Date:2012-10-26 19:51:31 (1 year 11 months ago)
Author:Xiangfu
Commit:cb2b6b51f85a5a58dca16ad70c87eab14b867535
Message:uboot-xburst: split spl and usbboot patch * fix typo * add new build rule u-boot-xburst.bin to main Makefile

Files: package/uboot-xburst/Makefile (1 diff)
package/uboot-xburst/patches/0001-add-qi_lb60-spl-code-and-usbboot-code.patch (1 diff)
package/uboot-xburst/patches/0001-qi_lb60-add-nand-spl-support.patch (1 diff)
package/uboot-xburst/patches/0002-add-mmc-support.patch (1 diff)
package/uboot-xburst/patches/0002-qi_lb60-add-software-usbboot-support.patch (1 diff)
package/uboot-xburst/patches/0003-add-mmc-support.patch (1 diff)
package/uboot-xburst/patches/0003-add-more-boot-options-F1-F2-F3-F4-M-S.patch (1 diff)
package/uboot-xburst/patches/0004-add-more-boot-options-F1-F2-F3-F4-M-S.patch (1 diff)
package/uboot-xburst/patches/0004-add-nanonote-lcd-support.patch (1 diff)
package/uboot-xburst/patches/0005-add-nanonote-lcd-support.patch (1 diff)
package/uboot-xburst/patches/0005-enable-silent-console.patch (1 diff)
package/uboot-xburst/patches/0006-enable-silent-console.patch (1 diff)

Change Details

package/uboot-xburst/Makefile
6464define Build/Compile
6565    $(MAKE) -C $(PKG_BUILD_DIR) \
6666        CROSS_COMPILE=$(TARGET_CROSS)
67    $(MAKE) -C $(PKG_BUILD_DIR) \
68        CROSS_COMPILE=$(TARGET_CROSS) spl/u-boot-spl.bin
69    dd if=$(PKG_BUILD_DIR)/spl/u-boot-spl.bin of=$(PKG_BUILD_DIR)/u-boot-spl-tmp.bin conv=sync bs=8192 count=1
70    dd if=$(PKG_BUILD_DIR)/spl/u-boot-spl.bin of=$(PKG_BUILD_DIR)/u-boot-spl-tmp.bin conv=sync,notrunc oflag=append bs=8192 count=1
71    tr '\0' '\377' < /dev/zero | dd of=$(PKG_BUILD_DIR)/u-boot-spl-tmp.bin conv=sync,notrunc oflag=append bs=16384 count=1
72    cat $(PKG_BUILD_DIR)/u-boot-spl-tmp.bin $(PKG_BUILD_DIR)/u-boot.bin > $(PKG_BUILD_DIR)/u-boot-nand.bin
7367endef
7468
7569define Package/uboot/install/template
7670define Package/uboot-xburst-$(1)/install
77    $(CP) $(PKG_BUILD_DIR)/u-boot-nand.bin $(BIN_DIR)/$(2)
71    $(CP) $(PKG_BUILD_DIR)/u-boot-xburst.bin $(BIN_DIR)/$(2)
7872    rmdir $$(1)
7973endef
8074endef
package/uboot-xburst/patches/0001-add-qi_lb60-spl-code-and-usbboot-code.patch
1From eb328666f9381a1bd2059484a4aef024285be045 Mon Sep 17 00:00:00 2001
2From: Xiangfu Liu <xiangfu@openmobilefree.net>
3Date: Fri, 6 Jan 2012 17:05:11 +0800
4Subject: [PATCH 1/5] add qi_lb60 spl code and usbboot code
5
6 arch/mips/cpu/xburst/Makefile | 7 +-
7 arch/mips/cpu/xburst/cpu.c | 4 +
8 arch/mips/cpu/xburst/jz4740.c | 84 ++--
9 arch/mips/cpu/xburst/spl/Makefile | 47 ++
10 arch/mips/cpu/xburst/spl/start.S | 65 +++
11 arch/mips/lib/Makefile | 4 +
12 arch/mips/lib/string.c | 32 ++
13 board/qi/qi_lb60/Makefile | 5 +
14 board/qi/qi_lb60/qi_lb60-spl.c | 56 +++
15 board/qi/qi_lb60/qi_lb60.c | 6 +-
16 board/qi/qi_lb60/u-boot-spl.lds | 62 +++
17 board/qi/qi_lb60/usbboot.S | 880 +++++++++++++++++++++++++++++++++++++
18 drivers/mtd/nand/jz4740_nand.c | 39 +-
19 include/configs/qi_lb60.h | 173 ++++----
20 14 files changed, 1319 insertions(+), 145 deletions(-)
21 create mode 100644 arch/mips/cpu/xburst/spl/Makefile
22 create mode 100644 arch/mips/cpu/xburst/spl/start.S
23 create mode 100644 arch/mips/lib/string.c
24 create mode 100644 board/qi/qi_lb60/qi_lb60-spl.c
25 create mode 100644 board/qi/qi_lb60/u-boot-spl.lds
26 create mode 100644 board/qi/qi_lb60/usbboot.S
27
28diff --git a/arch/mips/cpu/xburst/Makefile b/arch/mips/cpu/xburst/Makefile
29index b1f2ae4..ec35e55 100644
30+++ b/arch/mips/cpu/xburst/Makefile
31@@ -24,9 +24,12 @@ include $(TOPDIR)/config.mk
32
33 LIB = $(obj)lib$(CPU).o
34
35+COBJS-y = cpu.o jz_serial.o
36+
37+ifneq ($(CONFIG_SPL_BUILD),y)
38 START = start.o
39-SOBJS-y =
40-COBJS-y = cpu.o timer.o jz_serial.o
41+COBJS-y += timer.o
42+endif
43
44 COBJS-$(CONFIG_JZ4740) += jz4740.o
45
46diff --git a/arch/mips/cpu/xburst/cpu.c b/arch/mips/cpu/xburst/cpu.c
47index ddcbfaa..1432838 100644
48+++ b/arch/mips/cpu/xburst/cpu.c
49@@ -42,6 +42,8 @@
50         : \
51         : "i" (op), "R" (*(unsigned char *)(addr)))
52
53+#ifndef CONFIG_SPL_BUILD
54+
55 void __attribute__((weak)) _machine_restart(void)
56 {
57     struct jz4740_wdt *wdt = (struct jz4740_wdt *)JZ4740_WDT_BASE;
58@@ -109,6 +111,8 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
59         cache_op(Hit_Invalidate_D, addr);
60 }
61
62+#endif
63+
64 void flush_icache_all(void)
65 {
66     u32 addr, t = 0;
67diff --git a/arch/mips/cpu/xburst/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
68index c0b9817..40ef411 100644
69+++ b/arch/mips/cpu/xburst/jz4740.c
70@@ -32,31 +32,19 @@ int disable_interrupts(void)
71     return 0;
72 }
73
74-/*
75- * PLL output clock = EXTAL * NF / (NR * NO)
76- * NF = FD + 2, NR = RD + 2
77- * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
78- */
79 void pll_init(void)
80 {
81     struct jz4740_cpm *cpm = (struct jz4740_cpm *)JZ4740_CPM_BASE;
82
83- register unsigned int cfcr, plcr1;
84- int n2FR[33] = {
85- 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
86- 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
87- 9
88- };
89- int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
90- int nf, pllout2;
91+ register unsigned int cfcr, plcr;
92+ unsigned int nf, pllout2;
93
94     cfcr = CPM_CPCCR_CLKOEN |
95- CPM_CPCCR_PCS |
96- (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
97- (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
98- (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
99- (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
100- (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
101+ (0 << CPM_CPCCR_CDIV_BIT) |
102+ (2 << CPM_CPCCR_HDIV_BIT) |
103+ (2 << CPM_CPCCR_PDIV_BIT) |
104+ (2 << CPM_CPCCR_MDIV_BIT) |
105+ (2 << CPM_CPCCR_LDIV_BIT);
106
107     pllout2 = (cfcr & CPM_CPCCR_PCS) ?
108         CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);
109@@ -65,15 +53,18 @@ void pll_init(void)
110     writel(pllout2 / 48000000 - 1, &cpm->uhccdr);
111
112     nf = CONFIG_SYS_CPU_SPEED * 2 / CONFIG_SYS_EXTAL;
113- plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
114+ plcr = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
115         (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
116         (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
117- (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
118+ (0x32 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
119         CPM_CPPCR_PLLEN; /* enable PLL */
120
121     /* init PLL */
122     writel(cfcr, &cpm->cpccr);
123- writel(plcr1, &cpm->cppcr);
124+ writel(plcr, &cpm->cppcr);
125+
126+ while (!(readl(&cpm->cppcr) & CPM_CPPCR_PLLS))
127+ ;
128 }
129
130 void sdram_init(void)
131@@ -92,26 +83,14 @@ void sdram_init(void)
132         2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
133     };
134
135- int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
136+ unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
137
138     cpu_clk = CONFIG_SYS_CPU_SPEED;
139- mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
140+ mem_clk = 84000000;
141
142     writel(0, &emc->bcr); /* Disable bus release */
143     writew(0, &emc->rtcsr); /* Disable clock for counting */
144
145- /* Fault DMCR value for mode register setting*/
146-#define SDRAM_ROW0 11
147-#define SDRAM_COL0 8
148-#define SDRAM_BANK40 0
149-
150- dmcr0 = ((SDRAM_ROW0 - 11) << EMC_DMCR_RA_BIT) |
151- ((SDRAM_COL0 - 8) << EMC_DMCR_CA_BIT) |
152- (SDRAM_BANK40 << EMC_DMCR_BA_BIT) |
153- (SDRAM_BW16 << EMC_DMCR_BW_BIT) |
154- EMC_DMCR_EPIN |
155- cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
156-
157     /* Basic DMCR value */
158     dmcr = ((SDRAM_ROW - 11) << EMC_DMCR_RA_BIT) |
159         ((SDRAM_COL - 8) << EMC_DMCR_CA_BIT) |
160@@ -128,36 +107,36 @@ void sdram_init(void)
161     if (tmp > 11)
162         tmp = 11;
163     dmcr |= (tmp - 4) << EMC_DMCR_TRAS_BIT;
164- tmp = SDRAM_RCD / ns;
165
166+ tmp = SDRAM_RCD / ns;
167     if (tmp > 3)
168         tmp = 3;
169     dmcr |= tmp << EMC_DMCR_RCD_BIT;
170- tmp = SDRAM_TPC / ns;
171
172+ tmp = SDRAM_TPC / ns;
173     if (tmp > 7)
174         tmp = 7;
175     dmcr |= tmp << EMC_DMCR_TPC_BIT;
176- tmp = SDRAM_TRWL / ns;
177
178+ tmp = SDRAM_TRWL / ns;
179     if (tmp > 3)
180         tmp = 3;
181     dmcr |= tmp << EMC_DMCR_TRWL_BIT;
182- tmp = (SDRAM_TRAS + SDRAM_TPC) / ns;
183
184+ tmp = (SDRAM_TRAS + SDRAM_TPC) / ns;
185     if (tmp > 14)
186         tmp = 14;
187     dmcr |= ((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT;
188
189     /* SDRAM mode value */
190- sdmode = EMC_SDMR_BT_SEQ |
191- EMC_SDMR_OM_NORMAL |
192- EMC_SDMR_BL_4 |
193+ sdmode = EMC_SDMR_BT_SEQ |
194+ EMC_SDMR_OM_NORMAL |
195+ EMC_SDMR_BL_4 |
196          cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
197
198     /* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
199     writel(dmcr, &emc->dmcr);
200- writeb(0, JZ4740_EMC_SDMR0 | sdmode);
201+ writeb(0, JZ4740_EMC_SDMR0 + sdmode);
202
203     /* Wait for precharge, > 200us */
204     tmp = (cpu_clk / 1000000) * 1000;
205@@ -172,8 +151,8 @@ void sdram_init(void)
206     if (tmp > 0xff)
207         tmp = 0xff;
208     writew(tmp, &emc->rtcor);
209+
210     writew(0, &emc->rtcnt);
211- /* Divisor is 64, CKO/64 */
212     writew(EMC_RTCSR_CKS_64, &emc->rtcsr);
213
214     /* Wait for number of auto-refresh cycles */
215@@ -182,13 +161,17 @@ void sdram_init(void)
216         ;
217
218     /* Stage 3. Mode Register Set */
219+ dmcr0 = (11 << EMC_DMCR_RA_BIT) |
220+ (8 << EMC_DMCR_CA_BIT) |
221+ (0 << EMC_DMCR_BA_BIT) |
222+ EMC_DMCR_EPIN |
223+ (SDRAM_BW16 << EMC_DMCR_BW_BIT) |
224+ cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
225     writel(dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET, &emc->dmcr);
226     writeb(0, JZ4740_EMC_SDMR0 | sdmode);
227
228     /* Set back to basic DMCR value */
229     writel(dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET, &emc->dmcr);
230-
231- /* everything is ok now */
232 }
233
234 DECLARE_GLOBAL_DATA_PTR;
235@@ -232,9 +215,10 @@ void rtc_init(void)
236 phys_size_t initdram(int board_type)
237 {
238     struct jz4740_emc *emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
239- u32 dmcr;
240- u32 rows, cols, dw, banks;
241- ulong size;
242+
243+ unsigned int dmcr;
244+ unsigned int rows, cols, dw, banks;
245+ unsigned long size;
246
247     dmcr = readl(&emc->dmcr);
248     rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
249diff --git a/arch/mips/cpu/xburst/spl/Makefile b/arch/mips/cpu/xburst/spl/Makefile
250new file mode 100644
251index 0000000..f45e8c8
252+++ b/arch/mips/cpu/xburst/spl/Makefile
253@@ -0,0 +1,47 @@
254+#
255+# Copyright (C) 2011 Xiangfu Liu <xiangfu@openmobilefree.net>
256+#
257+# See file CREDITS for list of people who contributed to this
258+# project.
259+#
260+# This program is free software; you can redistribute it and/or
261+# modify it under the terms of the GNU General Public License as
262+# published by the Free Software Foundation; either version 2 of
263+# the License, or (at your option) any later version.
264+#
265+# This program is distributed in the hope that it will be useful,
266+# but WITHOUT ANY WARRANTY; without even the implied warranty of
267+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
268+# GNU General Public License for more details.
269+#
270+# You should have received a copy of the GNU General Public License
271+# along with this program; if not, write to the Free Software
272+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
273+# MA 02111-1307 USA
274+#
275+
276+include $(TOPDIR)/config.mk
277+
278+LIB = $(obj)lib$(CPU).o
279+
280+START = start.o
281+SOBJS-y =
282+COBJS-y =
283+
284+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
285+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
286+START := $(addprefix $(obj),$(START))
287+
288+all: $(obj).depend $(START) $(LIB)
289+
290+$(LIB): $(OBJS)
291+ $(call cmd_link_o_target, $(OBJS))
292+
293+#########################################################################
294+
295+# defines $(obj).depend target
296+include $(SRCTREE)/rules.mk
297+
298+sinclude $(obj).depend
299+
300+#########################################################################
301diff --git a/arch/mips/cpu/xburst/spl/start.S b/arch/mips/cpu/xburst/spl/start.S
302new file mode 100644
303index 0000000..44dd1e0
304+++ b/arch/mips/cpu/xburst/spl/start.S
305@@ -0,0 +1,65 @@
306+/*
307+ * Startup Code for MIPS32 XBURST CPU-core
308+ *
309+ * Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
310+ *
311+ * See file CREDITS for list of people who contributed to this
312+ * project.
313+ *
314+ * This program is free software; you can redistribute it and/or
315+ * modify it under the terms of the GNU General Public License as
316+ * published by the Free Software Foundation; either version 3 of
317+ * the License, or (at your option) any later version.
318+ *
319+ * This program is distributed in the hope that it will be useful,
320+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
321+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
322+ * GNU General Public License for more details.
323+ *
324+ * You should have received a copy of the GNU General Public License
325+ * along with this program; if not, write to the Free Software
326+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
327+ * MA 02111-1307 USA
328+ */
329+
330+#include <config.h>
331+#include <version.h>
332+#include <asm/regdef.h>
333+#include <asm/mipsregs.h>
334+#include <asm/addrspace.h>
335+#include <asm/cacheops.h>
336+
337+#include <asm/jz4740.h>
338+
339+ .set noreorder
340+
341+ .globl _start
342+ .text
343+_start:
344+ .word JZ4740_NANDBOOT_CFG /* fetched during NAND Boot */
345+reset:
346+ /*
347+ * STATUS register
348+ * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
349+ */
350+ li t0, 0x0040FC04
351+ mtc0 t0, CP0_STATUS
352+ /*
353+ * CAUSE register
354+ * IV=1, use the specical interrupt vector (0x200)
355+ */
356+ li t1, 0x00800000
357+ mtc0 t1, CP0_CAUSE
358+
359+ bal 1f
360+ nop
361+ .word _GLOBAL_OFFSET_TABLE_
362+1:
363+ move gp, ra
364+ lw t1, 0(ra)
365+ move gp, t1
366+
367+ la sp, 0x80004000
368+ la t9, nand_spl_boot
369+ j t9
370+ nop
371diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
372index 967e98a..c1452a2 100644
373+++ b/arch/mips/lib/Makefile
374@@ -34,12 +34,16 @@ LGOBJS := $(addprefix $(obj),$(GLSOBJS))
375
376 SOBJS-y +=
377
378+ifeq ($(CONFIG_SPL_BUILD),y)
379+COBJS-y += string.o
380+else
381 COBJS-y += board.o
382 ifeq ($(CONFIG_QEMU_MIPS),y)
383 COBJS-y += bootm_qemu_mips.o
384 else
385 COBJS-y += bootm.o
386 endif
387+endif
388
389 SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
390 OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
391diff --git a/arch/mips/lib/string.c b/arch/mips/lib/string.c
392new file mode 100644
393index 0000000..d59f44a
394+++ b/arch/mips/lib/string.c
395@@ -0,0 +1,32 @@
396+/*
397+ * Copyright (c) 2012 Xiangfu Liu <xiangfu@openmobilefree.net>
398+ *
399+ * See file CREDITS for list of people who contributed to this
400+ * project.
401+ *
402+ * This program is free software; you can redistribute it and/or
403+ * modify it under the terms of the GNU General Public License as
404+ * published by the Free Software Foundation; either version 2 of
405+ * the License, or (at your option) any later version.
406+ *
407+ * This program is distributed in the hope that it will be useful,
408+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
409+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
410+ * GNU General Public License for more details.
411+ *
412+ * You should have received a copy of the GNU General Public License
413+ * along with this program; if not, write to the Free Software
414+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
415+ * MA 02111-1307 USA
416+ */
417+
418+/* copy from lib/string bcopy */
419+char * memcpy(const char * src, char * dest, int count)
420+{
421+ char *tmp = dest;
422+
423+ while (count--)
424+ *tmp++ = *src++;
425+
426+ return dest;
427+}
428diff --git a/board/qi/qi_lb60/Makefile b/board/qi/qi_lb60/Makefile
429index 5dae11b..6dd8c6f 100644
430+++ b/board/qi/qi_lb60/Makefile
431@@ -22,7 +22,12 @@ include $(TOPDIR)/config.mk
432
433 LIB = $(obj)lib$(BOARD).o
434
435+ifeq ($(CONFIG_SPL_BUILD),y)
436+SOBJS := usbboot.o
437+COBJS := $(BOARD)-spl.o
438+else
439 COBJS := $(BOARD).o
440+endif
441
442 SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
443 OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
444diff --git a/board/qi/qi_lb60/qi_lb60-spl.c b/board/qi/qi_lb60/qi_lb60-spl.c
445new file mode 100644
446index 0000000..f5031aa
447+++ b/board/qi/qi_lb60/qi_lb60-spl.c
448@@ -0,0 +1,56 @@
449+/*
450+ * Authors: Xiangfu Liu <xiangfu@sharism.cc>
451+ *
452+ * This program is free software; you can redistribute it and/or
453+ * modify it under the terms of the GNU General Public License
454+ * as published by the Free Software Foundation; either version
455+ * 3 of the License, or (at your option) any later version.
456+ */
457+
458+#include <common.h>
459+#include <nand.h>
460+#include <asm/io.h>
461+#include <asm/jz4740.h>
462+
463+#define KEY_U_OUT (32 * 2 + 16)
464+#define KEY_U_IN (32 * 3 + 19)
465+
466+static int is_usb_boot()
467+{
468+ __gpio_as_input(KEY_U_IN);
469+ __gpio_enable_pull(KEY_U_IN);
470+ __gpio_as_output(KEY_U_OUT);
471+ __gpio_clear_pin(KEY_U_OUT);
472+
473+ if (__gpio_get_pin(KEY_U_IN) == 0)
474+ return 1;
475+
476+ return 0;
477+}
478+
479+static struct jz4740_emc * emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
480+
481+void nand_spl_boot(void)
482+{
483+ uint32_t reg;
484+
485+ __gpio_as_sdram_16bit_4720();
486+ __gpio_as_uart0();
487+ __gpio_jtag_to_uart0();
488+
489+ serial_init();
490+ serial_puts("\nQi lb60 SPL\n");
491+
492+ pll_init();
493+ sdram_init();
494+
495+ if (is_usb_boot()) {
496+ serial_puts("[U] pressed, goto USBBOOT mode\n");
497+ usb_boot();
498+ }
499+
500+ nand_init();
501+
502+ serial_puts("\nStarting U-Boot ...\n");
503+ nand_boot();
504+}
505diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
506index d975209..553e05d 100644
507+++ b/board/qi/qi_lb60/qi_lb60.c
508@@ -97,8 +97,10 @@ int board_early_init_f(void)
509 /* U-Boot common routines */
510 int checkboard(void)
511 {
512- printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC, Speed %ld MHz)\n",
513- gd->cpu_clk / 1000000);
514+ printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC)\n");
515+ printf(" CPU: %ld \n", gd->cpu_clk);
516+ printf(" MEM: %ld \n", gd->mem_clk);
517+ printf(" DEV: %ld \n", gd->dev_clk);
518
519     return 0;
520 }
521diff --git a/board/qi/qi_lb60/u-boot-spl.lds b/board/qi/qi_lb60/u-boot-spl.lds
522new file mode 100644
523index 0000000..cf80c35
524+++ b/board/qi/qi_lb60/u-boot-spl.lds
525@@ -0,0 +1,62 @@
526+/*
527+ * (C) Copyright 2005
528+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
529+ *
530+ * This program is free software; you can redistribute it and/or
531+ * modify it under the terms of the GNU General Public License as
532+ * published by the Free Software Foundation; either version 2 of
533+ * the License, or (at your option) any later version.
534+ *
535+ * This program is distributed in the hope that it will be useful,
536+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
537+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
538+ * GNU General Public License for more details.
539+ *
540+ * You should have received a copy of the GNU General Public License
541+ * along with this program; if not, write to the Free Software
542+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
543+ * MA 02111-1307 USA
544+ */
545+
546+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
547+
548+OUTPUT_ARCH(mips)
549+ENTRY(_start)
550+SECTIONS
551+{
552+ . = 0x80000000;
553+ . = ALIGN(4);
554+ .text :
555+ {
556+ *(.text)
557+ }
558+
559+ . = ALIGN(4);
560+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
561+
562+ . = ALIGN(4);
563+ .data : { *(.data) }
564+
565+ . = ALIGN(4);
566+ .sdata : { *(.sdata) }
567+
568+ _gp = ALIGN(16);
569+
570+ __got_start = .;
571+ .got : { *(.got) }
572+ __got_end = .;
573+
574+ . = .;
575+ __u_boot_cmd_start = .;
576+ .u_boot_cmd : { *(.u_boot_cmd) }
577+ __u_boot_cmd_end = .;
578+
579+ uboot_end_data = .;
580+ num_got_entries = (__got_end - __got_start) >> 2;
581+
582+ . = ALIGN(4);
583+ .sbss : { *(.sbss) }
584+ .bss : { *(.bss) }
585+ uboot_end = .;
586+}
587+ASSERT(uboot_end <= 0x80002000, "NAND bootstrap too big");
588diff --git a/board/qi/qi_lb60/usbboot.S b/board/qi/qi_lb60/usbboot.S
589new file mode 100644
590index 0000000..eb8faa6
591+++ b/board/qi/qi_lb60/usbboot.S
592@@ -0,0 +1,880 @@
593+/*
594+ * for jz4740 usb boot
595+ *
596+ * Copyright (c) 2009 Author: <jlwei@ingenic.cn>
597+ *
598+ * See file CREDITS for list of people who contributed to this
599+ * project.
600+ *
601+ * This program is free software; you can redistribute it and/or
602+ * modify it under the terms of the GNU General Public License as
603+ * published by the Free Software Foundation; either version 2 of
604+ * the License, or (at your option) any later version.
605+ *
606+ * This program is distributed in the hope that it will be useful,
607+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
608+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
609+ * GNU General Public License for more details.
610+ *
611+ * You should have received a copy of the GNU General Public License
612+ * along with this program; if not, write to the Free Software
613+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
614+ * MA 02111-1307 USA
615+ */
616+ .set noreorder
617+ .globl usb_boot
618+ .text
619+
620+//----------------------------------------------------------------------
621+// Both NAND and USB boot load data to D-Cache first, then transfer
622+// data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
623+// So init caches first and then dispatch to a proper boot routine.
624+//----------------------------------------------------------------------
625+
626+.macro load_addr reg addr
627+ li \reg, 0x80000000
628+ addiu \reg, \reg, \addr
629+ la $2, usbboot_begin
630+ subu \reg, \reg, $2
631+.endm
632+
633+usb_boot:
634+ //--------------------------------------------------------------
635+ // Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
636+ //--------------------------------------------------------------
637+ la $9, 0xB0000000 // CPCCR: Clock Control Register
638+ la $8, 0x42041110 // I:S:M:P=1:2:2:2
639+ sw $8, 0($9)
640+
641+ la $9, 0xB0000010 // CPPCR: PLL Control Register
642+ la $8, 0x06000120 // M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
643+ sw $8, 0($9)
644+
645+ mtc0 $0, $26 // CP0_ERRCTL, restore WST reset state
646+ nop
647+
648+ mtc0 $0, $16 // CP0_CONFIG
649+ nop
650+
651+ // Relocate code to beginning of the ram
652+
653+ la $2, usbboot_begin
654+ la $3, usbboot_end
655+ li $4, 0x80000000
656+
657+1:
658+ lw $5, 0($2)
659+ sw $5, 0($4)
660+ addiu $2, $2, 4
661+ bne $2, $3, 1b
662+ addiu $4, $4, 4
663+
664+ li $2, 0x80000000
665+ ori $3, $2, 0
666+ addiu $3, $3, usbboot_end
667+ la $4, usbboot_begin
668+ subu $3, $3, $4
669+
670+
671+2:
672+ cache 0x0, 0($2) // Index_Invalidate_I
673+ cache 0x1, 0($2) // Index_Writeback_Inv_D
674+ addiu $2, $2, 32
675+ subu $4, $3, $2
676+ bgtz $4, 2b
677+ nop
678+
679+ load_addr $3, usb_boot_return
680+
681+ jr $3
682+
683+usbboot_begin:
684+
685+init_caches:
686+ li $2, 3 // cacheable for kseg0 access
687+ mtc0 $2, $16 // CP0_CONFIG
688+ nop
689+
690+ li $2, 0x20000000 // enable idx-store-data cache insn
691+ mtc0 $2, $26 // CP0_ERRCTL
692+
693+ ori $2, $28, 0 // start address
694+ ori $3, $2, 0x3fe0 // end address, total 16KB
695+ mtc0 $0, $28, 0 // CP0_TAGLO
696+ mtc0 $0, $28, 1 // CP0_DATALO
697+cache_clear_a_line:
698+ cache 0x8, 0($2) // Index_Store_Tag_I
699+ cache 0x9, 0($2) // Index_Store_Tag_D
700+ bne $2, $3, cache_clear_a_line
701+ addiu $2, $2, 32 // increment CACHE_LINE_SIZE
702+
703+ ori $2, $28, 0 // start address
704+ ori $3, $2, 0x3fe0 // end address, total 16KB
705+ la $4, 0x1ffff000 // physical address and 4KB page mask
706+cache_alloc_a_line:
707+ and $5, $2, $4
708+ ori $5, $5, 1 // V bit of the physical tag
709+ mtc0 $5, $28, 0 // CP0_TAGLO
710+ cache 0x8, 0($2) // Index_Store_Tag_I
711+ cache 0x9, 0($2) // Index_Store_Tag_D
712+ bne $2, $3, cache_alloc_a_line
713+ addiu $2, $2, 32 // increment CACHE_LINE_SIZE
714+
715+ nop
716+ nop
717+ nop
718+ //--------------------------------------------------------------
719+ // Transfer data from dcache to icache, then jump to icache.
720+ //
721+ // Input parameters:
722+ //
723+ // $19: data length in bytes
724+ // $20: jump target address
725+ //--------------------------------------------------------------
726+xfer_d2i:
727+
728+ ori $8, $20, 0
729+ addu $9, $8, $19 // total 16KB
730+
731+1:
732+ cache 0x0, 0($8) // Index_Invalidate_I
733+ cache 0x1, 0($8) // Index_Writeback_Inv_D
734+ bne $8, $9, 1b
735+ addiu $8, $8, 32
736+
737+ // flush write-buffer
738+ sync
739+
740+ // Invalidate BTB
741+ mfc0 $8, $16, 7 // CP0_CONFIG
742+ nop
743+ ori $8, 2
744+ mtc0 $8, $16, 7
745+ nop
746+
747+ // Overwrite config to disable ram initalisation
748+ li $2, 0xff
749+ sb $2, 20($20)
750+
751+ jalr $20
752+ nop
753+
754+icache_return:
755+ //--------------------------------------------------------------
756+ // User code can return to here after executing itself in
757+ // icache, by jumping to $31.
758+ //--------------------------------------------------------------
759+ b usb_boot_return
760+ nop
761+
762+
763+usb_boot_return:
764+ //--------------------------------------------------------------
765+ // Enable the USB PHY
766+ //--------------------------------------------------------------
767+ la $9, 0xB0000024 // CPM_SCR
768+ lw $8, 0($9)
769+ ori $8, 0x40 // USBPHY_ENABLE
770+ sw $8, 0($9)
771+
772+ //--------------------------------------------------------------
773+ // Initialize USB registers
774+ //--------------------------------------------------------------
775+ la $27, 0xb3040000 // USB registers base address
776+
777+ sb $0, 0x0b($27) // INTRUSBE: disable common USB interrupts
778+ sh $0, 0x06($27) // INTRINE: disable EPIN interrutps
779+ sh $0, 0x08($27) // INTROUTE: disable EPOUT interrutps
780+
781+ li $9, 0x61
782+ sb $9, 0x01($27) // POWER: HSENAB | SUSPENDM | SOFTCONN
783+
784+ //--------------------------------------------------------------
785+ // Initialize USB states
786+ //--------------------------------------------------------------
787+ li $22, 0 // set EP0 to IDLE state
788+ li $23, 1 // no data stage
789+
790+ //--------------------------------------------------------------
791+ // Main loop of polling the usb commands
792+ //--------------------------------------------------------------
793+usb_command_loop:
794+ lbu $9, 0x0a($27) // read INTRUSB
795+ andi $9, 0x04 // check USB_INTR_RESET
796+ beqz $9, check_intr_ep0in
797+ nop
798+
799+ //--------------------------------------------------------------
800+ // 1. Handle USB reset interrupt
801+ //--------------------------------------------------------------
802+handle_reset_intr:
803+ lbu $9, 0x01($27) // read POWER
804+ andi $9, 0x10 // test HS_MODE
805+ bnez $9, _usb_set_maxpktsize
806+ li $9, 512 // max packet size of HS mode
807+ li $9, 64 // max packet size of FS mode
808+
809+_usb_set_maxpktsize:
810+ li $8, 1
811+ sb $8, 0x0e($27) // set INDEX 1
812+
813+ sh $9, 0x10($27) // INMAXP
814+ sb $0, 0x13($27) // INCSRH
815+ sh $9, 0x14($27) // OUTMAXP
816+ sb $0, 0x17($27) // OUTCSRH
817+
818+_usb_flush_fifo:
819+ li $8, 0x48 // INCSR_CDT && INCSR_FF
820+ sb $8, 0x12($27) // INCSR
821+ li $8, 0x90 // OUTCSR_CDT && OUTCSR_FF
822+ sb $8, 0x16($27) // OUTCSR
823+
824+ li $22, 0 // set EP0 to IDLE state
825+ li $23, 1 // no data stage
826+
827+ //--------------------------------------------------------------
828+ // 2. Check and handle EP0 interrupt
829+ //--------------------------------------------------------------
830+check_intr_ep0in:
831+ lhu $10, 0x02($27) // read INTRIN
832+ andi $9, $10, 0x1 // check EP0 interrupt
833+ beqz $9, check_intr_ep1in
834+ nop
835+
836+handle_ep0_intr:
837+ sb $0, 0x0e($27) // set INDEX 0
838+ lbu $11, 0x12($27) // read CSR0
839+
840+ andi $9, $11, 0x04 // check SENTSTALL
841+ beqz $9, _ep0_setupend
842+ nop
843+
844+_ep0_sentstall:
845+ andi $9, $11, 0xdb
846+ sb $9, 0x12($27) // clear SENDSTALL and SENTSTALL
847+ li $22, 0 // set EP0 to IDLE state
848+
849+_ep0_setupend:
850+ andi $9, $11, 0x10 // check SETUPEND
851+ beqz $9, ep0_idle_state
852+ nop
853+
854+ ori $9, $11, 0x80
855+ sb $9, 0x12($27) // set SVDSETUPEND
856+ li $22, 0 // set EP0 to IDLE state
857+
858+ep0_idle_state:
859+ bnez $22, ep0_tx_state
860+ nop
861+
862+ //--------------------------------------------------------------
863+ // 2.1 Handle EP0 IDLE state interrupt
864+ //--------------------------------------------------------------
865+ andi $9, $11, 0x01 // check OUTPKTRDY
866+ beqz $9, check_intr_ep1in
867+ nop
868+
869+ //--------------------------------------------------------------
870+ // Read 8-bytes setup packet from the FIFO
871+ //--------------------------------------------------------------
872+ lw $25, 0x20($27) // first word of setup packet
873+ lw $26, 0x20($27) // second word of setup packet
874+
875+ andi $9, $25, 0x60 // bRequestType & USB_TYPE_MASK
876+ beqz $9, _ep0_std_req
877+ nop
878+
879+ //--------------------------------------------------------------
880+ // 2.1.1 Vendor-specific setup request
881+ //--------------------------------------------------------------
882+_ep0_vend_req:
883+ li $22, 0 // set EP0 to IDLE state
884+ li $23, 1 // NoData = 1
885+
886+ andi $9, $25, 0xff00 // check bRequest
887+ srl $9, $9, 8
888+ beqz $9, __ep0_get_cpu_info
889+ sub $8, $9, 0x1
890+ beqz $8, __ep0_set_data_address
891+ sub $8, $9, 0x2
892+ beqz $8, __ep0_set_data_length
893+ sub $8, $9, 0x3
894+ beqz $8, __ep0_flush_caches
895+ sub $8, $9, 0x4
896+ beqz $8, __ep0_prog_start1
897+ sub $8, $9, 0x5
898+ beqz $8, __ep0_prog_start2
899+ nop
900+ b _ep0_idle_state_fini // invalid request
901+ nop
902+
903+__ep0_get_cpu_info:
904+ load_addr $20, cpu_info_data // data pointer to transfer
905+ li $21, 8 // bytes left to transfer
906+ li $22, 1 // set EP0 to TX state
907+ li $23, 0 // NoData = 0
908+
909+ b _ep0_idle_state_fini
910+ nop
911+
912+__ep0_set_data_address:
913+ li $9, 0xffff0000
914+ and $9, $25, $9
915+ andi $8, $26, 0xffff
916+ or $20, $9, $8 // data address of next transfer
917+
918+ b _ep0_idle_state_fini
919+ nop
920+
921+__ep0_set_data_length:
922+ li $9, 0xffff0000
923+ and $9, $25, $9
924+ andi $8, $26, 0xffff
925+ or $21, $9, $8 // data length of next transfer
926+
927+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
928+ sb $9, 0x12($27) // CSR0
929+
930+ // We must write packet to FIFO before EP1-IN interrupt here.
931+ b handle_epin1_intr
932+ nop
933+
934+__ep0_flush_caches:
935+ // Flush dcache and invalidate icache.
936+ li $8, 0x80000000
937+ addi $9, $8, 0x3fe0 // total 16KB
938+
939+1:
940+ cache 0x0, 0($8) // Index_Invalidate_I
941+ cache 0x1, 0($8) // Index_Writeback_Inv_D
942+ bne $8, $9, 1b
943+ addiu $8, $8, 32
944+
945+ // flush write-buffer
946+ sync
947+
948+ // Invalidate BTB
949+ mfc0 $8, $16, 7 // CP0_CONFIG
950+ nop
951+ ori $8, 2
952+ mtc0 $8, $16, 7
953+ nop
954+
955+ b _ep0_idle_state_fini
956+ nop
957+
958+__ep0_prog_start1:
959+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
960+ sb $9, 0x12($27) // CSR0
961+
962+ li $9, 0xffff0000
963+ and $9, $25, $9
964+ andi $8, $26, 0xffff
965+ or $20, $9, $8 // target address
966+
967+ b xfer_d2i
968+ li $19, 0x2000 // 16KB data length
969+
970+__ep0_prog_start2:
971+ li $9, 0x48 // SVDOUTPKTRDY and DATAEND
972+ sb $9, 0x12($27) // CSR0
973+
974+ li $9, 0xffff0000
975+ and $9, $25, $9
976+ andi $8, $26, 0xffff
977+ or $20, $9, $8 // target address
978+
979+ jalr $20 // jump, and place the return address in $31
980+ nop
981+
982+__ep0_prog_start2_return:
983+ // User code can return to here after executing itself, by jumping to $31.
984+ b usb_boot_return
985+ nop
986+
987+ //--------------------------------------------------------------
988+ // 2.1.2 Standard setup request
989+ //--------------------------------------------------------------
990+_ep0_std_req:
991+ andi $12, $25, 0xff00 // check bRequest
992+ srl $12, $12, 8
993+ sub $9, $12, 0x05 // check USB_REQ_SET_ADDRESS
994+ bnez $9, __ep0_req_set_config
995+ nop
996+
997+ //--------------------------------------------------------------
998+ // Handle USB_REQ_SET_ADDRESS
999+ //--------------------------------------------------------------
1000+__ep0_req_set_addr:
1001+ srl $9, $25, 16 // get wValue
1002+ sb $9, 0x0($27) // set FADDR
1003+ li $23, 1 // NoData = 1
1004+ b _ep0_idle_state_fini
1005+ nop
1006+
1007+__ep0_req_set_config:
1008+ sub $9, $12, 0x09 // check USB_REQ_SET_CONFIGURATION
1009+ bnez $9, __ep0_req_get_desc
1010+ nop
1011+
1012+ //--------------------------------------------------------------
1013+ // Handle USB_REQ_SET_CONFIGURATION
1014+ //--------------------------------------------------------------
1015+ li $23, 1 // NoData = 1
1016+ b _ep0_idle_state_fini
1017+ nop
1018+
1019+__ep0_req_get_desc:
1020+ sub $9, $12, 0x06 // check USB_REQ_GET_DESCRIPTOR
1021+ bnez $9, _ep0_idle_state_fini
1022+ li $23, 1 // NoData = 1
1023+
1024+ //--------------------------------------------------------------
1025+ // Handle USB_REQ_GET_DESCRIPTOR
1026+ //--------------------------------------------------------------
1027+ li $23, 0 // NoData = 0
1028+
1029+ srl $9, $25, 24 // wValue >> 8
1030+ sub $8, $9, 0x01 // check USB_DT_DEVICE
1031+ beqz $8, ___ep0_get_dev_desc
1032+ srl $21, $26, 16 // get wLength
1033+ sub $8, $9, 0x02 // check USB_DT_CONFIG
1034+ beqz $8, ___ep0_get_conf_desc
1035+ sub $8, $9, 0x03 // check USB_DT_STRING
1036+ beqz $8, ___ep0_get_string_desc
1037+ sub $8, $9, 0x06 // check USB_DT_DEVICE_QUALIFIER
1038+ beqz $8, ___ep0_get_dev_qualifier
1039+ nop
1040+ b _ep0_idle_state_fini
1041+ nop
1042+
1043+___ep0_get_dev_desc:
1044+ load_addr $20, device_desc // data pointer
1045+ li $22, 1 // set EP0 to TX state
1046+ sub $8, $21, 18
1047+ blez $8, _ep0_idle_state_fini // wLength <= 18
1048+ nop
1049+ li $21, 18 // max length of device_desc
1050+ b _ep0_idle_state_fini
1051+ nop
1052+
1053+___ep0_get_dev_qualifier:
1054+ load_addr $20, dev_qualifier // data pointer
1055+ li $22, 1 // set EP0 to TX state
1056+ sub $8, $21, 10
1057+ blez $8, _ep0_idle_state_fini // wLength <= 10
1058+ nop
1059+ li $21, 10 // max length of dev_qualifier
1060+ b _ep0_idle_state_fini
1061+ nop
1062+
1063+___ep0_get_conf_desc:
1064+ load_addr $20, config_desc_fs // data pointer of FS mode
1065+ lbu $8, 0x01($27) // read POWER
1066+ andi $8, 0x10 // test HS_MODE
1067+ beqz $8, ___ep0_get_conf_desc2
1068+ nop
1069+ load_addr $20, config_desc_hs // data pointer of HS mode
1070+
1071+___ep0_get_conf_desc2:
1072+ li $22, 1 // set EP0 to TX state
1073+ sub $8, $21, 32
1074+ blez $8, _ep0_idle_state_fini // wLength <= 32
1075+ nop
1076+ li $21, 32 // max length of config_desc
1077+ b _ep0_idle_state_fini
1078+ nop
1079+
1080+___ep0_get_string_desc:
1081+ li $22, 1 // set EP0 to TX state
1082+
1083+ srl $9, $25, 16 // wValue & 0xff
1084+ andi $9, 0xff
1085+
1086+ sub $8, $9, 1
1087+ beqz $8, ___ep0_get_string_manufacture
1088+ sub $8, $9, 2
1089+ beqz $8, ___ep0_get_string_product
1090+ nop
1091+
1092+___ep0_get_string_lang_ids:
1093+ load_addr $20, string_lang_ids // data pointer
1094+ b _ep0_idle_state_fini
1095+ li $21, 4 // data length
1096+
1097+___ep0_get_string_manufacture:
1098+ load_addr $20, string_manufacture // data pointer
1099+ b _ep0_idle_state_fini
1100+ li $21, 16 // data length
1101+
1102+___ep0_get_string_product:
1103+ load_addr $20, string_product // data pointer
1104+ b _ep0_idle_state_fini
1105+ li $21, 46 // data length
1106+
1107+_ep0_idle_state_fini:
1108+ li $9, 0x40 // SVDOUTPKTRDY
1109+ beqz $23, _ep0_idle_state_fini2
1110+ nop
1111+ ori $9, $9, 0x08 // DATAEND
1112+_ep0_idle_state_fini2:
1113+ sb $9, 0x12($27) // CSR0
1114+ beqz $22, check_intr_ep1in
1115+ nop
1116+
1117+ //--------------------------------------------------------------
1118+ // 2.2 Handle EP0 TX state interrupt
1119+ //--------------------------------------------------------------
1120+ep0_tx_state:
1121+ sub $9, $22, 1
1122+ bnez $9, check_intr_ep1in
1123+ nop
1124+
1125+ sub $9, $21, 64 // max packetsize
1126+ blez $9, _ep0_tx_state2 // data count <= 64
1127+ ori $19, $21, 0
1128+ li $19, 64
1129+
1130+_ep0_tx_state2:
1131+ beqz $19, _ep0_tx_state3 // send ZLP
1132+ ori $18, $19, 0 // record bytes to be transferred
1133+ sub $21, $21, $19 // decrement data count
1134+
1135+_ep0_fifo_write_loop:
1136+ lbu $9, 0($20) // read data
1137+ sb $9, 0x20($27) // load FIFO
1138+ sub $19, $19, 1 // decrement counter
1139+ bnez $19, _ep0_fifo_write_loop
1140+ addi $20, $20, 1 // increment data pointer
1141+
1142+ sub $9, $18, 64 // max packetsize
1143+ beqz $9, _ep0_tx_state4
1144+ nop
1145+
1146+_ep0_tx_state3:
1147+ // transferred bytes < max packetsize
1148+ li $9, 0x0a // set INPKTRDY and DATAEND
1149+ sb $9, 0x12($27) // CSR0
1150+ li $22, 0 // set EP0 to IDLE state
1151+ b check_intr_ep1in
1152+ nop
1153+
1154+_ep0_tx_state4:
1155+ // transferred bytes == max packetsize
1156+ li $9, 0x02 // set INPKTRDY
1157+ sb $9, 0x12($27) // CSR0
1158+ b check_intr_ep1in
1159+ nop
1160+
1161+ //--------------------------------------------------------------
1162+ // 3. Check and handle EP1 BULK-IN interrupt
1163+ //--------------------------------------------------------------
1164+check_intr_ep1in:
1165+ andi $9, $10, 0x2 // check EP1 IN interrupt
1166+ beqz $9, check_intr_ep1out
1167+ nop
1168+
1169+handle_epin1_intr:
1170+ li $9, 1
1171+ sb $9, 0x0e($27) // set INDEX 1
1172+ lbu $9, 0x12($27) // read INCSR
1173+
1174+ andi $8, $9, 0x2 // check INCSR_FFNOTEMPT
1175+ bnez $8, _epin1_tx_state4
1176+ nop
1177+
1178+_epin1_write_fifo:
1179+ lhu $9, 0x10($27) // get INMAXP
1180+ sub $8, $21, $9
1181+ blez $8, _epin1_tx_state1 // bytes left <= INMAXP
1182+ ori $19, $21, 0
1183+ ori $19, $9, 0
1184+
1185+_epin1_tx_state1:
1186+ beqz $19, _epin1_tx_state4 // No data
1187+ nop
1188+
1189+ sub $21, $21, $19 // decrement data count
1190+
1191+ srl $5, $19, 2 // # of word
1192+ andi $6, $19, 0x3 // # of byte
1193+ beqz $5, _epin1_tx_state2
1194+ nop
1195+
1196+_epin1_fifo_write_word:
1197+ lw $9, 0($20) // read data from source address
1198+ sw $9, 0x24($27) // write FIFO
1199+ sub $5, $5, 1 // decrement counter
1200+ bnez $5, _epin1_fifo_write_word
1201+ addiu $20, $20, 4 // increment dest address
1202+
1203+_epin1_tx_state2:
1204+ beqz $6, _epin1_tx_state3
1205+ nop
1206+
1207+_epin1_fifo_write_byte:
1208+ lbu $9, 0($20) // read data from source address
1209+ sb $9, 0x24($27) // write FIFO
1210+ sub $6, $6, 1 // decrement counter
1211+ bnez $6, _epin1_fifo_write_byte
1212+ addiu $20, $20, 1 // increment dest address
1213+
1214+_epin1_tx_state3:
1215+ li $9, 0x1
1216+ sb $9, 0x12($27) // INCSR, set INPKTRDY
1217+
1218+_epin1_tx_state4:
1219+ // nop
1220+
1221+ //--------------------------------------------------------------
1222+ // 4. Check and handle EP1 BULK-OUT interrupt
1223+ //--------------------------------------------------------------
1224+check_intr_ep1out:
1225+ lhu $9, 0x04($27) // read INTROUT
1226+ andi $9, 0x2
1227+ beqz $9, check_status_next
1228+ nop
1229+
1230+handle_epout1_intr:
1231+ li $9, 1
1232+ sb $9, 0x0e($27) // set INDEX 1
1233+
1234+ lbu $9, 0x16($27) // read OUTCSR
1235+ andi $9, 0x1 // check OUTPKTRDY
1236+ beqz $9, check_status_next
1237+ nop
1238+
1239+_epout1_read_fifo:
1240+ lhu $19, 0x18($27) // read OUTCOUNT
1241+ srl $5, $19, 2 // # of word
1242+ andi $6, $19, 0x3 // # of byte
1243+ beqz $5, _epout1_rx_state1
1244+ nop
1245+
1246+_epout1_fifo_read_word:
1247+ lw $9, 0x24($27) // read FIFO
1248+ sw $9, 0($20) // store to dest address
1249+ sub $5, $5, 1 // decrement counter
1250+ bnez $5, _epout1_fifo_read_word
1251+ addiu $20, $20, 4 // increment dest address
1252+
1253+_epout1_rx_state1:
1254+ beqz $6, _epout1_rx_state2
1255+ nop
1256+
1257+_epout1_fifo_read_byte:
1258+ lbu $9, 0x24($27) // read FIFO
1259+ sb $9, 0($20) // store to dest address
1260+ sub $6, $6, 1 // decrement counter
1261+ bnez $6, _epout1_fifo_read_byte
1262+ addiu $20, $20, 1 // increment dest address
1263+
1264+_epout1_rx_state2:
1265+ sb $0, 0x16($27) // clear OUTPKTRDY
1266+
1267+check_status_next:
1268+ b usb_command_loop
1269+ nop
1270+
1271+//--------------------------------------------------------------
1272+// Device/Configuration/Interface/Endpoint/String Descriptors
1273+//--------------------------------------------------------------
1274+
1275+ .align 2
1276+device_desc:
1277+ .byte 0x12 // bLength
1278+ .byte 0x01 // bDescriptorType
1279+ .byte 0x00 // bcdUSB
1280+ .byte 0x02 // bcdUSB
1281+ .byte 0x00 // bDeviceClass
1282+ .byte 0x00 // bDeviceSubClass
1283+ .byte 0x00 // bDeviceProtocol
1284+ .byte 0x40 // bMaxPacketSize0
1285+ .byte 0x1a // idVendor
1286+ .byte 0x60 // idVendor
1287+ .byte 0x40 // idProduct
1288+ .byte 0x47 // idProduct
1289+ .byte 0x00 // bcdDevice
1290+ .byte 0x01 // bcdDevice
1291+ .byte 0x01 // iManufacturer
1292+ .byte 0x02 // iProduct
1293+ .byte 0x00 // iSerialNumber
1294+ .byte 0x01 // bNumConfigurations
1295+
1296+ .align 2
1297+dev_qualifier:
1298+ .byte 0x0a // bLength
1299+ .byte 0x06 // bDescriptorType
1300+ .byte 0x00 // bcdUSB
1301+ .byte 0x02 // bcdUSB
1302+ .byte 0x00 // bDeviceClass
1303+ .byte 0x00 // bDeviceSubClass
1304+ .byte 0x00 // bDeviceProtocol
1305+ .byte 0x40 // bMaxPacketSize0
1306+ .byte 0x01 // bNumConfigurations
1307+ .byte 0x00 // bRESERVED
1308+
1309+ .align 2
1310+config_desc_hs:
1311+ .byte 0x09 // bLength
1312+ .byte 0x02 // bDescriptorType
1313+ .byte 0x20 // wTotalLength
1314+ .byte 0x00 // wTotalLength
1315+ .byte 0x01 // bNumInterfaces
1316+ .byte 0x01 // bConfigurationValue
1317+ .byte 0x00 // iConfiguration
1318+ .byte 0xc0 // bmAttributes
1319+ .byte 0x01 // MaxPower
1320+intf_desc_hs:
1321+ .byte 0x09 // bLength
1322+ .byte 0x04 // bDescriptorType
1323+ .byte 0x00 // bInterfaceNumber
1324+ .byte 0x00 // bAlternateSetting
1325+ .byte 0x02 // bNumEndpoints
1326+ .byte 0xff // bInterfaceClass
1327+ .byte 0x00 // bInterfaceSubClass
1328+ .byte 0x50 // bInterfaceProtocol
1329+ .byte 0x00 // iInterface
1330+ep1_desc_hs:
1331+ .byte 0x07 // bLength
1332+ .byte 0x05 // bDescriptorType
1333+ .byte 0x01 // bEndpointAddress
1334+ .byte 0x02 // bmAttributes
1335+ .byte 0x00 // wMaxPacketSize
1336+ .byte 0x02 // wMaxPacketSize
1337+ .byte 0x00 // bInterval
1338+ep2_desc_hs:
1339+ .byte 0x07 // bLength
1340+ .byte 0x05 // bDescriptorType
1341+ .byte 0x81 // bEndpointAddress
1342+ .byte 0x02 // bmAttributes
1343+ .byte 0x00 // wMaxPacketSize
1344+ .byte 0x02 // wMaxPacketSize
1345+ .byte 0x00 // bInterval
1346+
1347+ .align 2
1348+config_desc_fs:
1349+ .byte 0x09 // bLength
1350+ .byte 0x02 // bDescriptorType
1351+ .byte 0x20 // wTotalLength
1352+ .byte 0x00 // wTotalLength
1353+ .byte 0x01 // bNumInterfaces
1354+ .byte 0x01 // bConfigurationValue
1355+ .byte 0x00 // iConfiguration
1356+ .byte 0xc0 // bmAttributes
1357+ .byte 0x01 // MaxPower
1358+intf_desc_fs:
1359+ .byte 0x09 // bLength
1360+ .byte 0x04 // bDescriptorType
1361+ .byte 0x00 // bInterfaceNumber
1362+ .byte 0x00 // bAlternateSetting
1363+ .byte 0x02 // bNumEndpoints
1364+ .byte 0xff // bInterfaceClass
1365+ .byte 0x00 // bInterfaceSubClass
1366+ .byte 0x50 // bInterfaceProtocol
1367+ .byte 0x00 // iInterface
1368+ep1_desc_fs:
1369+ .byte 0x07 // bLength
1370+ .byte 0x05 // bDescriptorType
1371+ .byte 0x01 // bEndpointAddress
1372+ .byte 0x02 // bmAttributes
1373+ .byte 0x40 // wMaxPacketSize
1374+ .byte 0x00 // wMaxPacketSize
1375+ .byte 0x00 // bInterval
1376+ep2_desc_fs:
1377+ .byte 0x07 // bLength
1378+ .byte 0x05 // bDescriptorType
1379+ .byte 0x81 // bEndpointAddress
1380+ .byte 0x02 // bmAttributes
1381+ .byte 0x40 // wMaxPacketSize
1382+ .byte 0x00 // wMaxPacketSize
1383+ .byte 0x00 // bInterval
1384+
1385+ .align 2
1386+string_lang_ids:
1387+ .byte 0x04
1388+ .byte 0x03
1389+ .byte 0x09
1390+ .byte 0x04
1391+
1392+ .align 2
1393+string_manufacture:
1394+ .byte 0x10
1395+ .byte 0x03
1396+ .byte 0x49
1397+ .byte 0x00
1398+ .byte 0x6e
1399+ .byte 0x00
1400+ .byte 0x67
1401+ .byte 0x00
1402+ .byte 0x65
1403+ .byte 0x00
1404+ .byte 0x6e
1405+ .byte 0x00
1406+ .byte 0x69
1407+ .byte 0x00
1408+ .byte 0x63
1409+ .byte 0x00
1410+
1411+ .align 2
1412+string_product:
1413+ .byte 0x2e
1414+ .byte 0x03
1415+ .byte 0x4a
1416+ .byte 0x00
1417+ .byte 0x5a
1418+ .byte 0x00
1419+ .byte 0x34
1420+ .byte 0x00
1421+ .byte 0x37
1422+ .byte 0x00
1423+ .byte 0x34
1424+ .byte 0x00
1425+ .byte 0x30
1426+ .byte 0x00
1427+ .byte 0x20
1428+ .byte 0x00
1429+ .byte 0x55
1430+ .byte 0x00
1431+ .byte 0x53
1432+ .byte 0x00
1433+ .byte 0x42
1434+ .byte 0x00
1435+ .byte 0x20
1436+ .byte 0x00
1437+ .byte 0x42
1438+ .byte 0x00
1439+ .byte 0x6f
1440+ .byte 0x00
1441+ .byte 0x6f
1442+ .byte 0x00
1443+ .byte 0x74
1444+ .byte 0x00
1445+ .byte 0x20
1446+ .byte 0x00
1447+ .byte 0x44
1448+ .byte 0x00
1449+ .byte 0x65
1450+ .byte 0x00
1451+ .byte 0x76
1452+ .byte 0x00
1453+ .byte 0x69
1454+ .byte 0x00
1455+ .byte 0x63
1456+ .byte 0x00
1457+ .byte 0x65
1458+ .byte 0x00
1459+
1460+ .align 2
1461+cpu_info_data:
1462+ .byte 0x4a
1463+ .byte 0x5a
1464+ .byte 0x34
1465+ .byte 0x37
1466+ .byte 0x34
1467+ .byte 0x30
1468+ .byte 0x56
1469+ .byte 0x31
1470+usbboot_end:
1471+
1472+ .set reorder
1473diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
1474index 3ec34f3..4ab2229 100644
1475+++ b/drivers/mtd/nand/jz4740_nand.c
1476@@ -15,6 +15,9 @@
1477 #include <asm/io.h>
1478 #include <asm/jz4740.h>
1479
1480+#ifdef CONFIG_SPL_BUILD
1481+#define printf(arg...) do {} while (0)
1482+#endif
1483 #define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
1484 #define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
1485 #define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
1486@@ -176,7 +179,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
1487         for (k = 0; k < 9; k++)
1488             writeb(read_ecc[k], &emc->nfpar[k]);
1489     }
1490- /* Set PRDY */
1491+
1492     writel(readl(&emc->nfecr) | EMC_NFECR_PRDY, &emc->nfecr);
1493
1494     /* Wait for completion */
1495@@ -184,7 +187,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
1496         status = readl(&emc->nfints);
1497     } while (!(status & EMC_NFINTS_DECF));
1498
1499- /* disable ecc */
1500+ /* Disable ECC */
1501     writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
1502
1503     /* Check decoding */
1504@@ -192,7 +195,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
1505         return 0;
1506
1507     if (status & EMC_NFINTS_UNCOR) {
1508- printf("uncorrectable ecc\n");
1509+ printf("JZ4740 uncorrectable ECC\n");
1510         return -1;
1511     }
1512
1513@@ -230,6 +233,32 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
1514     return errcnt;
1515 }
1516
1517+#ifdef CONFIG_SPL_BUILD
1518+static void jz_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
1519+{
1520+ int i;
1521+ struct nand_chip *this = mtd->priv;
1522+
1523+#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3) || \
1524+ (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)
1525+ for (i = 0; i < len; i += 2)
1526+ buf[i] = readw(this->IO_ADDR_R);
1527+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3) || \
1528+ (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)
1529+ for (i = 0; i < len; i++)
1530+ buf[i] = readb(this->IO_ADDR_R);
1531+#else
1532+ #error JZ4740_NANDBOOT_CFG not defined or wrong
1533+#endif
1534+}
1535+
1536+static uint8_t jz_nand_read_byte(struct mtd_info *mtd)
1537+{
1538+ struct nand_chip *this = mtd->priv;
1539+ return readb(this->IO_ADDR_R);
1540+}
1541+#endif
1542+
1543 /*
1544  * Main initialization routine
1545  */
1546@@ -254,6 +283,10 @@ int board_nand_init(struct nand_chip *nand)
1547     nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
1548     nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
1549     nand->ecc.layout = &qi_lb60_ecclayout_2gb;
1550+#ifdef CONFIG_SPL_BUILD
1551+ nand->read_byte = jz_nand_read_byte;
1552+ nand->read_buf = jz_nand_read_buf;
1553+#endif
1554     nand->chip_delay = 50;
1555     nand->options = NAND_USE_FLASH_BBT;
1556
1557diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
1558index 4bb5bbc..d4449ac 100644
1559+++ b/include/configs/qi_lb60.h
1560@@ -1,5 +1,5 @@
1561 /*
1562- * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
1563+ * Authors: Xiangfu Liu <xiangfu@openmobilefree.net>
1564  *
1565  * This program is free software; you can redistribute it and/or
1566  * modify it under the terms of the GNU General Public License
1567@@ -14,7 +14,6 @@
1568 #define CONFIG_SYS_LITTLE_ENDIAN
1569 #define CONFIG_JZSOC /* Jz SoC */
1570 #define CONFIG_JZ4740 /* Jz4740 SoC */
1571-#define CONFIG_NAND_JZ4740
1572
1573 #define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
1574 #define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
1575@@ -24,24 +23,43 @@
1576 #define CONFIG_SYS_UART_BASE JZ4740_UART0_BASE /* Base of the UART channel */
1577 #define CONFIG_BAUDRATE 57600
1578
1579+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
1580+#define CONFIG_BOOTDELAY 0
1581+#define CONFIG_BOOTARGS "mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
1582+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x280000;bootm"
1583+
1584+/*
1585+ * Miscellaneous configurable options
1586+ */
1587+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
1588+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
1589+#define CONFIG_SYS_LOAD_ADDR 0x80600000
1590+#define CONFIG_SYS_MEMTEST_START 0x80100000
1591+#define CONFIG_SYS_MEMTEST_END 0x80A00000
1592+#define CONFIG_SYS_TEXT_BASE 0x80100000
1593+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
1594+
1595+#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
1596+#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
1597+
1598+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
1599+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
1600+
1601+#define CONFIG_SYS_LONGHELP
1602+#define CONFIG_SYS_MAXARGS 16
1603+#define CONFIG_SYS_PROMPT "NanoNote# "
1604+
1605 #define CONFIG_SKIP_LOWLEVEL_INIT
1606 #define CONFIG_BOARD_EARLY_INIT_F
1607 #define CONFIG_SYS_NO_FLASH
1608 #define CONFIG_SYS_FLASH_BASE 0 /* init flash_base as 0 */
1609-#define CONFIG_ENV_OVERWRITE
1610-
1611-#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
1612-#define CONFIG_BOOTDELAY 0
1613-#define CONFIG_BOOTARGS "mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
1614-#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
1615
1616 /*
1617- * Command line configuration.
1618+ * Command line configuration
1619  */
1620 #define CONFIG_CMD_BOOTD /* bootd */
1621 #define CONFIG_CMD_CONSOLE /* coninfo */
1622 #define CONFIG_CMD_ECHO /* echo arguments */
1623-
1624 #define CONFIG_CMD_LOADB /* loadb */
1625 #define CONFIG_CMD_LOADS /* loads */
1626 #define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
1627@@ -58,45 +76,16 @@
1628 #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
1629
1630 /*
1631- * Miscellaneous configurable options
1632- */
1633-#define CONFIG_SYS_MAXARGS 16
1634-#define CONFIG_SYS_LONGHELP
1635-#define CONFIG_SYS_PROMPT "NanoNote# "
1636-#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
1637-#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
1638-
1639-#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
1640-#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
1641-
1642-#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
1643-#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
1644-#define CONFIG_SYS_LOAD_ADDR 0x80600000
1645-#define CONFIG_SYS_MEMTEST_START 0x80100000
1646-#define CONFIG_SYS_MEMTEST_END 0x80800000
1647-
1648-/*
1649- * Environment
1650+ * NAND driver configuration
1651  */
1652-#define CONFIG_ENV_IS_IN_NAND /* use NAND for environment vars */
1653-
1654-#define CONFIG_SYS_NAND_5_ADDR_CYCLE
1655-/*
1656- * if board nand flash is 1GB, set to 1
1657- * if board nand flash is 2GB, set to 2
1658- * for change the PAGE_SIZE and BLOCK_SIZE
1659- * will delete when there is no 1GB flash
1660- */
1661-#define NANONOTE_NAND_SIZE 2
1662-
1663-#define CONFIG_SYS_NAND_PAGE_SIZE (2048 * NANONOTE_NAND_SIZE)
1664-#define CONFIG_SYS_NAND_BLOCK_SIZE (256 * NANONOTE_NAND_SIZE << 10)
1665-/* nand bad block was marked at this page in a block, start from 0 */
1666+#define CONFIG_NAND_JZ4740
1667+#define CONFIG_SYS_NAND_PAGE_SIZE 4096
1668+#define CONFIG_SYS_NAND_BLOCK_SIZE (512 << 10)
1669+/* NAND bad block was marked at this page in a block, start from 0 */
1670 #define CONFIG_SYS_NAND_BADBLOCK_PAGE 127
1671 #define CONFIG_SYS_NAND_PAGE_COUNT 128
1672 #define CONFIG_SYS_NAND_BAD_BLOCK_POS 0
1673-/* ECC offset position in oob area, default value is 6 if it isn't defined */
1674-#define CONFIG_SYS_NAND_ECC_POS (6 * NANONOTE_NAND_SIZE)
1675+#define CONFIG_SYS_NAND_ECC_POS 12
1676 #define CONFIG_SYS_NAND_ECCSIZE 512
1677 #define CONFIG_SYS_NAND_ECCBYTES 9
1678 #define CONFIG_SYS_NAND_ECCPOS \
1679@@ -115,10 +104,9 @@
1680 #define CONFIG_SYS_ONENAND_BASE CONFIG_SYS_NAND_BASE
1681 #define CONFIG_SYS_MAX_NAND_DEVICE 1
1682 #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl.*/
1683-#define CONFIG_NAND_SPL_TEXT_BASE 0x80000000
1684
1685 /*
1686- * IPL (Initial Program Loader, integrated inside CPU)
1687+ * IPL (Initial Program Loader, integrated inside Ingenic Xburst JZ4740 CPU)
1688  * Will load first 8k from NAND (SPL) into cache and execute it from there.
1689  *
1690  * SPL (Secondary Program Loader)
1691@@ -130,77 +118,86 @@
1692  * NUB (NAND U-Boot)
1693  * This NAND U-Boot (NUB) is a special U-Boot version which can be started
1694  * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
1695- *
1696  */
1697+
1698+/*
1699+ * NAND SPL configuration
1700+ */
1701+#define CONFIG_SPL
1702+#define CONFIG_SPL_NAND_LOAD
1703+#define CONFIG_SPL_NAND_SIMPLE
1704+#define CONFIG_SPL_NAND_SUPPORT
1705+#define CONFIG_SPL_TEXT_BASE 0x80000000
1706+#define CONFIG_SPL_START_S_PATH "arch/mips/cpu/xburst/spl"
1707+
1708+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
1709+#define CONFIG_SYS_NAND_HW_ECC_OOBFIRST
1710+#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3
1711+
1712 #define CONFIG_SYS_NAND_U_BOOT_DST 0x80100000 /* Load NUB to this addr */
1713 #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
1714-/* Start NUB from this addr*/
1715+ /* Start NUB from this addr */
1716+#define CONFIG_SYS_NAND_U_BOOT_OFFS (32 << 10) /* Offset of NUB */
1717+#define CONFIG_SYS_NAND_U_BOOT_SIZE (256 << 10) /* Size of NUB */
1718
1719 /*
1720- * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
1721+ * Environment configuration
1722  */
1723-#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 << 10) /* Offset to RAM U-Boot image */
1724-#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 << 10) /* Size of RAM U-Boot image */
1725-
1726+#define CONFIG_ENV_OVERWRITE
1727+#define CONFIG_ENV_IS_IN_NAND
1728 #define CONFIG_ENV_SIZE (4 << 10)
1729 #define CONFIG_ENV_OFFSET \
1730     (CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE)
1731 #define CONFIG_ENV_OFFSET_REDUND \
1732     (CONFIG_ENV_OFFSET + CONFIG_SYS_NAND_BLOCK_SIZE)
1733
1734-#define CONFIG_SYS_TEXT_BASE 0x80100000
1735-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
1736-
1737 /*
1738- * SDRAM Info.
1739+ * CPU cache configuration
1740  */
1741-#define CONFIG_NR_DRAM_BANKS 1
1742+#define CONFIG_SYS_DCACHE_SIZE 16384
1743+#define CONFIG_SYS_ICACHE_SIZE 16384
1744+#define CONFIG_SYS_CACHELINE_SIZE 32
1745
1746 /*
1747- * Cache Configuration
1748+ * SDRAM configuration
1749  */
1750-#define CONFIG_SYS_DCACHE_SIZE 16384
1751-#define CONFIG_SYS_ICACHE_SIZE 16384
1752-#define CONFIG_SYS_CACHELINE_SIZE 32
1753+#define CONFIG_NR_DRAM_BANKS 1
1754+
1755+#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
1756+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
1757+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
1758+#define SDRAM_COL 9 /* Column address: 8 to 12 */
1759+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
1760+#define SDRAM_TRAS 45 /* RAS# Active Time */
1761+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
1762+#define SDRAM_TPC 20 /* RAS# Precharge Time */
1763+#define SDRAM_TRWL 7 /* Write Latency Time */
1764+#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
1765
1766 /*
1767- * GPIO definition
1768+ * GPIO configuration
1769  */
1770-#define GPIO_LCD_CS (2 * 32 + 21)
1771-#define GPIO_AMP_EN (3 * 32 + 4)
1772+#define GPIO_LCD_CS (2 * 32 + 21)
1773+#define GPIO_AMP_EN (3 * 32 + 4)
1774
1775-#define GPIO_SDPW_EN (3 * 32 + 2)
1776-#define GPIO_SD_DETECT (3 * 32 + 0)
1777+#define GPIO_SDPW_EN (3 * 32 + 2)
1778+#define GPIO_SD_DETECT (3 * 32 + 0)
1779
1780-#define GPIO_BUZZ_PWM (3 * 32 + 27)
1781-#define GPIO_USB_DETECT (3 * 32 + 28)
1782+#define GPIO_BUZZ_PWM (3 * 32 + 27)
1783+#define GPIO_USB_DETECT (3 * 32 + 28)
1784
1785-#define GPIO_AUDIO_POP (1 * 32 + 29)
1786-#define GPIO_COB_TEST (1 * 32 + 30)
1787+#define GPIO_AUDIO_POP (1 * 32 + 29)
1788+#define GPIO_COB_TEST (1 * 32 + 30)
1789
1790 #define GPIO_KEYOUT_BASE (2 * 32 + 10)
1791-#define GPIO_KEYIN_BASE (3 * 32 + 18)
1792-#define GPIO_KEYIN_8 (3 * 32 + 26)
1793+#define GPIO_KEYIN_BASE (3 * 32 + 18)
1794+#define GPIO_KEYIN_8 (3 * 32 + 26)
1795
1796-#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
1797+#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
1798 #define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
1799
1800 #define SPEN GPIO_LCD_CS /* LCDCS :Serial command enable */
1801 #define SPDA (2 * 32 + 22) /* LCDSCL:Serial command clock input */
1802 #define SPCK (2 * 32 + 23) /* LCDSDA:Serial command data input */
1803
1804-/* SDRAM paramters */
1805-#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
1806-#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
1807-#define SDRAM_ROW 13 /* Row address: 11 to 13 */
1808-#define SDRAM_COL 9 /* Column address: 8 to 12 */
1809-#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
1810-
1811-/* SDRAM Timings, unit: ns */
1812-#define SDRAM_TRAS 45 /* RAS# Active Time */
1813-#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
1814-#define SDRAM_TPC 20 /* RAS# Precharge Time */
1815-#define SDRAM_TRWL 7 /* Write Latency Time */
1816-#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
1817-
1818 #endif
18191.7.9.5
1820
package/uboot-xburst/patches/0001-qi_lb60-add-nand-spl-support.patch
1From 0329cf7965956a5a7044827e0ce88ae8d5150e54 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Fri, 12 Oct 2012 09:46:58 +0800
4Subject: [PATCH 1/6] qi_lb60: add nand spl support
5
6  The JZ4740 CPU can load 8KB from two different addresses:
7   1. the normal area up to 8KB starting from NAND flash address 0x00000000
8   2. the backup area up to 8KB starting from NAND flash address 0x00002000
9
10Signed-off-by: Xiangfu <xiangfu@openmobilefree.net>
11---
12 Makefile | 12 +++
13 arch/mips/cpu/xburst/Makefile | 7 +-
14 arch/mips/cpu/xburst/cpu.c | 4 +
15 arch/mips/cpu/xburst/jz4740.c | 82 +++++++----------
16 arch/mips/cpu/xburst/spl/Makefile | 47 ++++++++++
17 arch/mips/cpu/xburst/spl/start.S | 63 +++++++++++++
18 board/qi/qi_lb60/Makefile | 4 +
19 board/qi/qi_lb60/qi_lb60-spl.c | 30 +++++++
20 board/qi/qi_lb60/qi_lb60.c | 8 +-
21 board/qi/qi_lb60/u-boot-spl.lds | 61 +++++++++++++
22 drivers/mtd/nand/jz4740_nand.c | 39 ++++++++-
23 include/configs/qi_lb60.h | 175 ++++++++++++++++++-------------------
24 12 files changed, 386 insertions(+), 146 deletions(-)
25 create mode 100644 arch/mips/cpu/xburst/spl/Makefile
26 create mode 100644 arch/mips/cpu/xburst/spl/start.S
27 create mode 100644 board/qi/qi_lb60/qi_lb60-spl.c
28 create mode 100644 board/qi/qi_lb60/u-boot-spl.lds
29
30diff --git a/Makefile b/Makefile
31index 34d9075..a22778e 100644
32--- a/Makefile
33@@ -393,6 +393,10 @@ ALL-y += $(obj)u-boot-nodtb-tegra.bin
34 endif
35 endif
36
37+ifeq ($(CPU),xburst)
38+ALL-y += $(obj)u-boot-xburst.bin
39+endif
40+
41 all: $(ALL-y) $(SUBDIR_EXAMPLES)
42
43 $(obj)u-boot.dtb: $(obj)u-boot
44@@ -506,6 +510,14 @@ $(obj)u-boot-nodtb-tegra.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
45 endif
46 endif
47
48+ifeq ($(CPU),xburst)
49+$(obj)u-boot-xburst.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
50+ dd if=$(obj)spl/u-boot-spl.bin of=$(obj)spl/u-boot-pad.bin conv=sync bs=8192 count=1
51+ dd if=$(obj)spl/u-boot-spl.bin of=$(obj)spl/u-boot-pad.bin conv=sync,notrunc oflag=append bs=8192 count=1
52+ tr '\0' '\377' < /dev/zero | dd of=$(obj)spl/u-boot-pad.bin conv=sync,notrunc oflag=append bs=16384 count=1
53+ cat $(obj)spl/u-boot-pad.bin u-boot.bin > $@
54+endif
55+
56 ifeq ($(CONFIG_SANDBOX),y)
57 GEN_UBOOT = \
58         cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
59diff --git a/arch/mips/cpu/xburst/Makefile b/arch/mips/cpu/xburst/Makefile
60index b1f2ae4..ec35e55 100644
61--- a/arch/mips/cpu/xburst/Makefile
62@@ -24,9 +24,12 @@ include $(TOPDIR)/config.mk
63
64 LIB = $(obj)lib$(CPU).o
65
66+COBJS-y = cpu.o jz_serial.o
67+
68+ifneq ($(CONFIG_SPL_BUILD),y)
69 START = start.o
70-SOBJS-y =
71-COBJS-y = cpu.o timer.o jz_serial.o
72+COBJS-y += timer.o
73+endif
74
75 COBJS-$(CONFIG_JZ4740) += jz4740.o
76
77diff --git a/arch/mips/cpu/xburst/cpu.c b/arch/mips/cpu/xburst/cpu.c
78index ddcbfaa..1432838 100644
79--- a/arch/mips/cpu/xburst/cpu.c
80@@ -42,6 +42,8 @@
81         : \
82         : "i" (op), "R" (*(unsigned char *)(addr)))
83
84+#ifndef CONFIG_SPL_BUILD
85+
86 void __attribute__((weak)) _machine_restart(void)
87 {
88     struct jz4740_wdt *wdt = (struct jz4740_wdt *)JZ4740_WDT_BASE;
89@@ -109,6 +111,8 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
90         cache_op(Hit_Invalidate_D, addr);
91 }
92
93+#endif
94+
95 void flush_icache_all(void)
96 {
97     u32 addr, t = 0;
98diff --git a/arch/mips/cpu/xburst/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
99index c0b9817..8816aa3 100644
100--- a/arch/mips/cpu/xburst/jz4740.c
101@@ -32,31 +32,19 @@ int disable_interrupts(void)
102     return 0;
103 }
104
105-/*
106- * PLL output clock = EXTAL * NF / (NR * NO)
107- * NF = FD + 2, NR = RD + 2
108- * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
109- */
110 void pll_init(void)
111 {
112     struct jz4740_cpm *cpm = (struct jz4740_cpm *)JZ4740_CPM_BASE;
113
114- register unsigned int cfcr, plcr1;
115- int n2FR[33] = {
116- 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
117- 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
118- 9
119- };
120- int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
121- int nf, pllout2;
122+ register unsigned int cfcr, plcr;
123+ unsigned int nf, pllout2;
124
125     cfcr = CPM_CPCCR_CLKOEN |
126- CPM_CPCCR_PCS |
127- (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
128- (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
129- (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
130- (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
131- (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
132+ (0 << CPM_CPCCR_CDIV_BIT) |
133+ (2 << CPM_CPCCR_HDIV_BIT) |
134+ (2 << CPM_CPCCR_PDIV_BIT) |
135+ (2 << CPM_CPCCR_MDIV_BIT) |
136+ (2 << CPM_CPCCR_LDIV_BIT);
137
138     pllout2 = (cfcr & CPM_CPCCR_PCS) ?
139         CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);
140@@ -65,15 +53,18 @@ void pll_init(void)
141     writel(pllout2 / 48000000 - 1, &cpm->uhccdr);
142
143     nf = CONFIG_SYS_CPU_SPEED * 2 / CONFIG_SYS_EXTAL;
144- plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
145+ plcr = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
146         (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
147         (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
148- (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
149+ (0x32 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
150         CPM_CPPCR_PLLEN; /* enable PLL */
151
152     /* init PLL */
153     writel(cfcr, &cpm->cpccr);
154- writel(plcr1, &cpm->cppcr);
155+ writel(plcr, &cpm->cppcr);
156+
157+ while (!(readl(&cpm->cppcr) & CPM_CPPCR_PLLS))
158+ ;
159 }
160
161 void sdram_init(void)
162@@ -92,26 +83,12 @@ void sdram_init(void)
163         2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
164     };
165
166- int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
167-
168     cpu_clk = CONFIG_SYS_CPU_SPEED;
169- mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
170+ mem_clk = 84000000;
171
172     writel(0, &emc->bcr); /* Disable bus release */
173     writew(0, &emc->rtcsr); /* Disable clock for counting */
174
175- /* Fault DMCR value for mode register setting*/
176-#define SDRAM_ROW0 11
177-#define SDRAM_COL0 8
178-#define SDRAM_BANK40 0
179-
180- dmcr0 = ((SDRAM_ROW0 - 11) << EMC_DMCR_RA_BIT) |
181- ((SDRAM_COL0 - 8) << EMC_DMCR_CA_BIT) |
182- (SDRAM_BANK40 << EMC_DMCR_BA_BIT) |
183- (SDRAM_BW16 << EMC_DMCR_BW_BIT) |
184- EMC_DMCR_EPIN |
185- cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
186-
187     /* Basic DMCR value */
188     dmcr = ((SDRAM_ROW - 11) << EMC_DMCR_RA_BIT) |
189         ((SDRAM_COL - 8) << EMC_DMCR_CA_BIT) |
190@@ -128,31 +105,31 @@ void sdram_init(void)
191     if (tmp > 11)
192         tmp = 11;
193     dmcr |= (tmp - 4) << EMC_DMCR_TRAS_BIT;
194- tmp = SDRAM_RCD / ns;
195
196+ tmp = SDRAM_RCD / ns;
197     if (tmp > 3)
198         tmp = 3;
199     dmcr |= tmp << EMC_DMCR_RCD_BIT;
200- tmp = SDRAM_TPC / ns;
201
202+ tmp = SDRAM_TPC / ns;
203     if (tmp > 7)
204         tmp = 7;
205     dmcr |= tmp << EMC_DMCR_TPC_BIT;
206- tmp = SDRAM_TRWL / ns;
207
208+ tmp = SDRAM_TRWL / ns;
209     if (tmp > 3)
210         tmp = 3;
211     dmcr |= tmp << EMC_DMCR_TRWL_BIT;
212- tmp = (SDRAM_TRAS + SDRAM_TPC) / ns;
213
214+ tmp = (SDRAM_TRAS + SDRAM_TPC) / ns;
215     if (tmp > 14)
216         tmp = 14;
217     dmcr |= ((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT;
218
219     /* SDRAM mode value */
220- sdmode = EMC_SDMR_BT_SEQ |
221- EMC_SDMR_OM_NORMAL |
222- EMC_SDMR_BL_4 |
223+ sdmode = EMC_SDMR_BT_SEQ |
224+ EMC_SDMR_OM_NORMAL |
225+ EMC_SDMR_BL_4 |
226          cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
227
228     /* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
229@@ -172,8 +149,8 @@ void sdram_init(void)
230     if (tmp > 0xff)
231         tmp = 0xff;
232     writew(tmp, &emc->rtcor);
233+
234     writew(0, &emc->rtcnt);
235- /* Divisor is 64, CKO/64 */
236     writew(EMC_RTCSR_CKS_64, &emc->rtcsr);
237
238     /* Wait for number of auto-refresh cycles */
239@@ -182,13 +159,17 @@ void sdram_init(void)
240         ;
241
242     /* Stage 3. Mode Register Set */
243+ dmcr0 = (11 << EMC_DMCR_RA_BIT) |
244+ (8 << EMC_DMCR_CA_BIT) |
245+ (0 << EMC_DMCR_BA_BIT) |
246+ EMC_DMCR_EPIN |
247+ (SDRAM_BW16 << EMC_DMCR_BW_BIT) |
248+ cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
249     writel(dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET, &emc->dmcr);
250     writeb(0, JZ4740_EMC_SDMR0 | sdmode);
251
252     /* Set back to basic DMCR value */
253     writel(dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET, &emc->dmcr);
254-
255- /* everything is ok now */
256 }
257
258 DECLARE_GLOBAL_DATA_PTR;
259@@ -232,9 +213,10 @@ void rtc_init(void)
260 phys_size_t initdram(int board_type)
261 {
262     struct jz4740_emc *emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
263- u32 dmcr;
264- u32 rows, cols, dw, banks;
265- ulong size;
266+
267+ unsigned int dmcr;
268+ unsigned int rows, cols, dw, banks;
269+ unsigned long size;
270
271     dmcr = readl(&emc->dmcr);
272     rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
273diff --git a/arch/mips/cpu/xburst/spl/Makefile b/arch/mips/cpu/xburst/spl/Makefile
274new file mode 100644
275index 0000000..f45e8c8
276--- /dev/null
277@@ -0,0 +1,47 @@
278+#
279+# Copyright (C) 2011 Xiangfu Liu <xiangfu@openmobilefree.net>
280+#
281+# See file CREDITS for list of people who contributed to this
282+# project.
283+#
284+# This program is free software; you can redistribute it and/or
285+# modify it under the terms of the GNU General Public License as
286+# published by the Free Software Foundation; either version 2 of
287+# the License, or (at your option) any later version.
288+#
289+# This program is distributed in the hope that it will be useful,
290+# but WITHOUT ANY WARRANTY; without even the implied warranty of
291+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
292+# GNU General Public License for more details.
293+#
294+# You should have received a copy of the GNU General Public License
295+# along with this program; if not, write to the Free Software
296+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
297+# MA 02111-1307 USA
298+#
299+
300+include $(TOPDIR)/config.mk
301+
302+LIB = $(obj)lib$(CPU).o
303+
304+START = start.o
305+SOBJS-y =
306+COBJS-y =
307+
308+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
309+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
310+START := $(addprefix $(obj),$(START))
311+
312+all: $(obj).depend $(START) $(LIB)
313+
314+$(LIB): $(OBJS)
315+ $(call cmd_link_o_target, $(OBJS))
316+
317+#########################################################################
318+
319+# defines $(obj).depend target
320+include $(SRCTREE)/rules.mk
321+
322+sinclude $(obj).depend
323+
324+#########################################################################
325diff --git a/arch/mips/cpu/xburst/spl/start.S b/arch/mips/cpu/xburst/spl/start.S
326new file mode 100644
327index 0000000..e31c4c8
328--- /dev/null
329@@ -0,0 +1,63 @@
330+/*
331+ * Copyright (c) 2010 Xiangfu Liu <xiangfu@openmobilefree.net>
332+ *
333+ * See file CREDITS for list of people who contributed to this
334+ * project.
335+ *
336+ * This program is free software; you can redistribute it and/or
337+ * modify it under the terms of the GNU General Public License as
338+ * published by the Free Software Foundation; either version 3 of
339+ * the License, or (at your option) any later version.
340+ *
341+ * This program is distributed in the hope that it will be useful,
342+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
343+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
344+ * GNU General Public License for more details.
345+ *
346+ * You should have received a copy of the GNU General Public License
347+ * along with this program; if not, write to the Free Software
348+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
349+ * MA 02111-1307 USA
350+ */
351+
352+#include <config.h>
353+#include <version.h>
354+#include <asm/regdef.h>
355+#include <asm/mipsregs.h>
356+#include <asm/addrspace.h>
357+#include <asm/cacheops.h>
358+
359+#include <asm/jz4740.h>
360+
361+ .set noreorder
362+
363+ .globl _start
364+ .text
365+_start:
366+ .word JZ4740_NANDBOOT_CFG /* fetched during NAND Boot */
367+reset:
368+ /*
369+ * STATUS register
370+ * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
371+ */
372+ li t0, 0x0040FC04
373+ mtc0 t0, CP0_STATUS
374+ /*
375+ * CAUSE register
376+ * IV=1, use the specical interrupt vector (0x200)
377+ */
378+ li t1, 0x00800000
379+ mtc0 t1, CP0_CAUSE
380+
381+ bal 1f
382+ nop
383+ .word _GLOBAL_OFFSET_TABLE_
384+1:
385+ move gp, ra
386+ lw t1, 0(ra)
387+ move gp, t1
388+
389+ la sp, 0x80004000
390+ la t9, nand_spl_boot
391+ j t9
392+ nop
393diff --git a/board/qi/qi_lb60/Makefile b/board/qi/qi_lb60/Makefile
394index 5dae11b..e399246 100644
395--- a/board/qi/qi_lb60/Makefile
396@@ -22,7 +22,11 @@ include $(TOPDIR)/config.mk
397
398 LIB = $(obj)lib$(BOARD).o
399
400+ifeq ($(CONFIG_SPL_BUILD),y)
401+COBJS := $(BOARD)-spl.o
402+else
403 COBJS := $(BOARD).o
404+endif
405
406 SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
407 OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
408diff --git a/board/qi/qi_lb60/qi_lb60-spl.c b/board/qi/qi_lb60/qi_lb60-spl.c
409new file mode 100644
410index 0000000..3fe3fa3
411--- /dev/null
412@@ -0,0 +1,30 @@
413+/*
414+ * Authors: Xiangfu Liu <xiangfu@openmobilefree.cc>
415+ *
416+ * This program is free software; you can redistribute it and/or
417+ * modify it under the terms of the GNU General Public License
418+ * as published by the Free Software Foundation; either version
419+ * 3 of the License, or (at your option) any later version.
420+ */
421+
422+#include <common.h>
423+#include <nand.h>
424+#include <asm/io.h>
425+#include <asm/jz4740.h>
426+
427+void nand_spl_boot(void)
428+{
429+ __gpio_as_sdram_16bit_4720();
430+ __gpio_as_uart0();
431+ __gpio_jtag_to_uart0();
432+
433+ serial_init();
434+
435+ pll_init();
436+ sdram_init();
437+
438+ nand_init();
439+
440+ puts("\nQi LB60 SPL: Starting U-Boot ...\n");
441+ nand_boot();
442+}
443diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
444index d975209..3bd4e2f 100644
445--- a/board/qi/qi_lb60/qi_lb60.c
446@@ -1,5 +1,5 @@
447 /*
448- * Authors: Xiangfu Liu <xiangfu@sharism.cc>
449+ * Authors: Xiangfu Liu <xiangfu@openmobilefree.net>
450  *
451  * This program is free software; you can redistribute it and/or
452  * modify it under the terms of the GNU General Public License
453@@ -97,8 +97,10 @@ int board_early_init_f(void)
454 /* U-Boot common routines */
455 int checkboard(void)
456 {
457- printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC, Speed %ld MHz)\n",
458- gd->cpu_clk / 1000000);
459+ printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC)\n");
460+ printf(" CPU: %ld\n", gd->cpu_clk);
461+ printf(" MEM: %ld\n", gd->mem_clk);
462+ printf(" DEV: %ld\n", gd->dev_clk);
463
464     return 0;
465 }
466diff --git a/board/qi/qi_lb60/u-boot-spl.lds b/board/qi/qi_lb60/u-boot-spl.lds
467new file mode 100644
468index 0000000..930537f
469--- /dev/null
470@@ -0,0 +1,61 @@
471+/*
472+ * (C) Copyright 2012 Xiangfu Liu <xiangfu@openmobilefree.net>
473+ *
474+ * This program is free software; you can redistribute it and/or
475+ * modify it under the terms of the GNU General Public License as
476+ * published by the Free Software Foundation; either version 2 of
477+ * the License, or (at your option) any later version.
478+ *
479+ * This program is distributed in the hope that it will be useful,
480+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
481+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
482+ * GNU General Public License for more details.
483+ *
484+ * You should have received a copy of the GNU General Public License
485+ * along with this program; if not, write to the Free Software
486+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
487+ * MA 02111-1307 USA
488+ */
489+
490+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
491+
492+OUTPUT_ARCH(mips)
493+ENTRY(_start)
494+SECTIONS
495+{
496+ . = 0x80000000;
497+ . = ALIGN(4);
498+ .text :
499+ {
500+ *(.text)
501+ }
502+
503+ . = ALIGN(4);
504+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
505+
506+ . = ALIGN(4);
507+ .data : { *(.data) }
508+
509+ . = ALIGN(4);
510+ .sdata : { *(.sdata) }
511+
512+ _gp = ALIGN(16);
513+
514+ __got_start = .;
515+ .got : { *(.got) }
516+ __got_end = .;
517+
518+ . = .;
519+ __u_boot_cmd_start = .;
520+ .u_boot_cmd : { *(.u_boot_cmd) }
521+ __u_boot_cmd_end = .;
522+
523+ uboot_end_data = .;
524+ num_got_entries = (__got_end - __got_start) >> 2;
525+
526+ . = ALIGN(4);
527+ .sbss : { *(.sbss) }
528+ .bss : { *(.bss) }
529+ uboot_end = .;
530+}
531+ASSERT(uboot_end <= 0x80002000, "NAND bootstrap too big");
532diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
533index 3ec34f3..24a4921 100644
534--- a/drivers/mtd/nand/jz4740_nand.c
535@@ -15,6 +15,9 @@
536 #include <asm/io.h>
537 #include <asm/jz4740.h>
538
539+#ifdef CONFIG_SPL_BUILD
540+#define printf(s) puts(s)
541+#endif
542 #define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
543 #define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
544 #define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
545@@ -176,7 +179,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
546         for (k = 0; k < 9; k++)
547             writeb(read_ecc[k], &emc->nfpar[k]);
548     }
549- /* Set PRDY */
550+
551     writel(readl(&emc->nfecr) | EMC_NFECR_PRDY, &emc->nfecr);
552
553     /* Wait for completion */
554@@ -184,7 +187,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
555         status = readl(&emc->nfints);
556     } while (!(status & EMC_NFINTS_DECF));
557
558- /* disable ecc */
559+ /* Disable ECC */
560     writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
561
562     /* Check decoding */
563@@ -192,7 +195,7 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
564         return 0;
565
566     if (status & EMC_NFINTS_UNCOR) {
567- printf("uncorrectable ecc\n");
568+ printf("JZ4740 uncorrectable ECC\n");
569         return -1;
570     }
571
572@@ -230,6 +233,32 @@ static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
573     return errcnt;
574 }
575
576+#ifdef CONFIG_SPL_BUILD
577+static void jz_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
578+{
579+ int i;
580+ struct nand_chip *this = mtd->priv;
581+
582+#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3) || \
583+ (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)
584+ for (i = 0; i < len; i += 2)
585+ buf[i] = readw(this->IO_ADDR_R);
586+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3) || \
587+ (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)
588+ for (i = 0; i < len; i++)
589+ buf[i] = readb(this->IO_ADDR_R);
590+#else
591+ #error JZ4740_NANDBOOT_CFG not defined or wrong
592+#endif
593+}
594+
595+static uint8_t jz_nand_read_byte(struct mtd_info *mtd)
596+{
597+ struct nand_chip *this = mtd->priv;
598+ return readb(this->IO_ADDR_R);
599+}
600+#endif
601+
602 /*
603  * Main initialization routine
604  */
605@@ -254,6 +283,10 @@ int board_nand_init(struct nand_chip *nand)
606     nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
607     nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
608     nand->ecc.layout = &qi_lb60_ecclayout_2gb;
609+#ifdef CONFIG_SPL_BUILD
610+ nand->read_byte = jz_nand_read_byte;
611+ nand->read_buf = jz_nand_read_buf;
612+#endif
613     nand->chip_delay = 50;
614     nand->options = NAND_USE_FLASH_BBT;
615
616diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
617index 4bb5bbc..7bff444 100644
618--- a/include/configs/qi_lb60.h
619@@ -1,5 +1,5 @@
620 /*
621- * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
622+ * Authors: Xiangfu Liu <xiangfu@openmobilefree.net>
623  *
624  * This program is free software; you can redistribute it and/or
625  * modify it under the terms of the GNU General Public License
626@@ -14,7 +14,6 @@
627 #define CONFIG_SYS_LITTLE_ENDIAN
628 #define CONFIG_JZSOC /* Jz SoC */
629 #define CONFIG_JZ4740 /* Jz4740 SoC */
630-#define CONFIG_NAND_JZ4740
631
632 #define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
633 #define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
634@@ -24,24 +23,43 @@
635 #define CONFIG_SYS_UART_BASE JZ4740_UART0_BASE /* Base of the UART channel */
636 #define CONFIG_BAUDRATE 57600
637
638+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
639+#define CONFIG_BOOTDELAY 0
640+#define CONFIG_BOOTARGS "mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
641+#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x280000;bootm"
642+
643+/*
644+ * Miscellaneous configurable options
645+ */
646+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
647+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
648+#define CONFIG_SYS_LOAD_ADDR 0x80600000
649+#define CONFIG_SYS_MEMTEST_START 0x80100000
650+#define CONFIG_SYS_MEMTEST_END 0x80A00000
651+#define CONFIG_SYS_TEXT_BASE 0x80100000
652+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
653+
654+#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
655+#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
656+
657+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
658+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
659+
660+#define CONFIG_SYS_LONGHELP
661+#define CONFIG_SYS_MAXARGS 16
662+#define CONFIG_SYS_PROMPT "NanoNote# "
663+
664 #define CONFIG_SKIP_LOWLEVEL_INIT
665 #define CONFIG_BOARD_EARLY_INIT_F
666 #define CONFIG_SYS_NO_FLASH
667 #define CONFIG_SYS_FLASH_BASE 0 /* init flash_base as 0 */
668-#define CONFIG_ENV_OVERWRITE
669-
670-#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAUL)
671-#define CONFIG_BOOTDELAY 0
672-#define CONFIG_BOOTARGS "mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
673-#define CONFIG_BOOTCOMMAND "nand read 0x80600000 0x400000 0x200000;bootm"
674
675 /*
676- * Command line configuration.
677+ * Command line configuration
678  */
679 #define CONFIG_CMD_BOOTD /* bootd */
680 #define CONFIG_CMD_CONSOLE /* coninfo */
681 #define CONFIG_CMD_ECHO /* echo arguments */
682-
683 #define CONFIG_CMD_LOADB /* loadb */
684 #define CONFIG_CMD_LOADS /* loads */
685 #define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop mtest */
686@@ -58,45 +76,16 @@
687 #define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
688
689 /*
690- * Miscellaneous configurable options
691- */
692-#define CONFIG_SYS_MAXARGS 16
693-#define CONFIG_SYS_LONGHELP
694-#define CONFIG_SYS_PROMPT "NanoNote# "
695-#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
696-#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
697-
698-#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
699-#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
700-
701-#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
702-#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
703-#define CONFIG_SYS_LOAD_ADDR 0x80600000
704-#define CONFIG_SYS_MEMTEST_START 0x80100000
705-#define CONFIG_SYS_MEMTEST_END 0x80800000
706-
707-/*
708- * Environment
709+ * NAND driver configuration
710  */
711-#define CONFIG_ENV_IS_IN_NAND /* use NAND for environment vars */
712-
713-#define CONFIG_SYS_NAND_5_ADDR_CYCLE
714-/*
715- * if board nand flash is 1GB, set to 1
716- * if board nand flash is 2GB, set to 2
717- * for change the PAGE_SIZE and BLOCK_SIZE
718- * will delete when there is no 1GB flash
719- */
720-#define NANONOTE_NAND_SIZE 2
721-
722-#define CONFIG_SYS_NAND_PAGE_SIZE (2048 * NANONOTE_NAND_SIZE)
723-#define CONFIG_SYS_NAND_BLOCK_SIZE (256 * NANONOTE_NAND_SIZE << 10)
724-/* nand bad block was marked at this page in a block, start from 0 */
725+#define CONFIG_NAND_JZ4740
726+#define CONFIG_SYS_NAND_PAGE_SIZE 4096
727+#define CONFIG_SYS_NAND_BLOCK_SIZE (512 << 10)
728+/* NAND bad block was marked at this page in a block, start from 0 */
729 #define CONFIG_SYS_NAND_BADBLOCK_PAGE 127
730 #define CONFIG_SYS_NAND_PAGE_COUNT 128
731 #define CONFIG_SYS_NAND_BAD_BLOCK_POS 0
732-/* ECC offset position in oob area, default value is 6 if it isn't defined */
733-#define CONFIG_SYS_NAND_ECC_POS (6 * NANONOTE_NAND_SIZE)
734+#define CONFIG_SYS_NAND_ECC_POS 12
735 #define CONFIG_SYS_NAND_ECCSIZE 512
736 #define CONFIG_SYS_NAND_ECCBYTES 9
737 #define CONFIG_SYS_NAND_ECCPOS \
738@@ -115,10 +104,9 @@
739 #define CONFIG_SYS_ONENAND_BASE CONFIG_SYS_NAND_BASE
740 #define CONFIG_SYS_MAX_NAND_DEVICE 1
741 #define CONFIG_SYS_NAND_SELECT_DEVICE 1 /* nand driver supports mutipl.*/
742-#define CONFIG_NAND_SPL_TEXT_BASE 0x80000000
743
744 /*
745- * IPL (Initial Program Loader, integrated inside CPU)
746+ * IPL (Initial Program Loader, integrated inside Ingenic Xburst JZ4740 CPU)
747  * Will load first 8k from NAND (SPL) into cache and execute it from there.
748  *
749  * SPL (Secondary Program Loader)
750@@ -130,77 +118,88 @@
751  * NUB (NAND U-Boot)
752  * This NAND U-Boot (NUB) is a special U-Boot version which can be started
753  * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
754- *
755  */
756+
757+/*
758+ * NAND SPL configuration
759+ */
760+#define CONFIG_SPL
761+#define CONFIG_SPL_LIBGENERIC_SUPPORT
762+#define CONFIG_SPL_LIBCOMMON_SUPPORT
763+#define CONFIG_SPL_NAND_LOAD
764+#define CONFIG_SPL_NAND_SIMPLE
765+#define CONFIG_SPL_NAND_SUPPORT
766+#define CONFIG_SPL_TEXT_BASE 0x80000000
767+#define CONFIG_SPL_START_S_PATH "arch/mips/cpu/xburst/spl"
768+
769+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
770+#define CONFIG_SYS_NAND_HW_ECC_OOBFIRST
771+#define JZ4740_NANDBOOT_CFG JZ4740_NANDBOOT_B8R3
772+
773 #define CONFIG_SYS_NAND_U_BOOT_DST 0x80100000 /* Load NUB to this addr */
774 #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST
775-/* Start NUB from this addr*/
776+ /* Start NUB from this addr */
777+#define CONFIG_SYS_NAND_U_BOOT_OFFS (32 << 10) /* Offset of NUB */
778+#define CONFIG_SYS_NAND_U_BOOT_SIZE (256 << 10) /* Size of NUB */
779
780 /*
781- * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
782+ * Environment configuration
783  */
784-#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 << 10) /* Offset to RAM U-Boot image */
785-#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 << 10) /* Size of RAM U-Boot image */
786-
787+#define CONFIG_ENV_OVERWRITE
788+#define CONFIG_ENV_IS_IN_NAND
789 #define CONFIG_ENV_SIZE (4 << 10)
790 #define CONFIG_ENV_OFFSET \
791     (CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE)
792 #define CONFIG_ENV_OFFSET_REDUND \
793     (CONFIG_ENV_OFFSET + CONFIG_SYS_NAND_BLOCK_SIZE)
794
795-#define CONFIG_SYS_TEXT_BASE 0x80100000
796-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
797-
798 /*
799- * SDRAM Info.
800+ * CPU cache configuration
801  */
802-#define CONFIG_NR_DRAM_BANKS 1
803+#define CONFIG_SYS_DCACHE_SIZE 16384
804+#define CONFIG_SYS_ICACHE_SIZE 16384
805+#define CONFIG_SYS_CACHELINE_SIZE 32
806
807 /*
808- * Cache Configuration
809+ * SDRAM configuration
810  */
811-#define CONFIG_SYS_DCACHE_SIZE 16384
812-#define CONFIG_SYS_ICACHE_SIZE 16384
813-#define CONFIG_SYS_CACHELINE_SIZE 32
814+#define CONFIG_NR_DRAM_BANKS 1
815+
816+#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
817+#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
818+#define SDRAM_ROW 13 /* Row address: 11 to 13 */
819+#define SDRAM_COL 9 /* Column address: 8 to 12 */
820+#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
821+#define SDRAM_TRAS 45 /* RAS# Active Time */
822+#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
823+#define SDRAM_TPC 20 /* RAS# Precharge Time */
824+#define SDRAM_TRWL 7 /* Write Latency Time */
825+#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
826
827 /*
828- * GPIO definition
829+ * GPIO configuration
830  */
831-#define GPIO_LCD_CS (2 * 32 + 21)
832-#define GPIO_AMP_EN (3 * 32 + 4)
833+#define GPIO_LCD_CS (2 * 32 + 21)
834+#define GPIO_AMP_EN (3 * 32 + 4)
835
836-#define GPIO_SDPW_EN (3 * 32 + 2)
837-#define GPIO_SD_DETECT (3 * 32 + 0)
838+#define GPIO_SDPW_EN (3 * 32 + 2)
839+#define GPIO_SD_DETECT (3 * 32 + 0)
840
841-#define GPIO_BUZZ_PWM (3 * 32 + 27)
842-#define GPIO_USB_DETECT (3 * 32 + 28)
843+#define GPIO_BUZZ_PWM (3 * 32 + 27)
844+#define GPIO_USB_DETECT (3 * 32 + 28)
845
846-#define GPIO_AUDIO_POP (1 * 32 + 29)
847-#define GPIO_COB_TEST (1 * 32 + 30)
848+#define GPIO_AUDIO_POP (1 * 32 + 29)
849+#define GPIO_COB_TEST (1 * 32 + 30)
850
851 #define GPIO_KEYOUT_BASE (2 * 32 + 10)
852-#define GPIO_KEYIN_BASE (3 * 32 + 18)
853-#define GPIO_KEYIN_8 (3 * 32 + 26)
854+#define GPIO_KEYIN_BASE (3 * 32 + 18)
855+#define GPIO_KEYIN_8 (3 * 32 + 26)
856
857-#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
858+#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
859 #define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
860
861 #define SPEN GPIO_LCD_CS /* LCDCS :Serial command enable */
862 #define SPDA (2 * 32 + 22) /* LCDSCL:Serial command clock input */
863 #define SPCK (2 * 32 + 23) /* LCDSDA:Serial command data input */
864
865-/* SDRAM paramters */
866-#define SDRAM_BW16 1 /* Data bus width: 0-32bit, 1-16bit */
867-#define SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */
868-#define SDRAM_ROW 13 /* Row address: 11 to 13 */
869-#define SDRAM_COL 9 /* Column address: 8 to 12 */
870-#define SDRAM_CASL 2 /* CAS latency: 2 or 3 */
871-
872-/* SDRAM Timings, unit: ns */
873-#define SDRAM_TRAS 45 /* RAS# Active Time */
874-#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
875-#define SDRAM_TPC 20 /* RAS# Precharge Time */
876-#define SDRAM_TRWL 7 /* Write Latency Time */
877-#define SDRAM_TREF 15625 /* Refresh period: 8192 cycles/64ms */
878-
879 #endif
880--
8811.7.9.5
882
package/uboot-xburst/patches/0002-add-mmc-support.patch
1From ae857e757e24058a78f95cd472024bb4f268899f Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Wed, 10 Oct 2012 18:19:41 +0800
4Subject: [PATCH 2/5] add mmc support
5
6 arch/mips/include/asm/jz4740.h | 166 ++++++
7 board/qi/qi_lb60/qi_lb60.c | 9 +-
8 drivers/mmc/Makefile | 1 +
9 drivers/mmc/jz_mmc.c | 1179 ++++++++++++++++++++++++++++++++++++++++
10 drivers/mmc/jz_mmc.h | 176 ++++++
11 include/configs/qi_lb60.h | 9 +
12 include/mmc.h | 40 ++
13 7 files changed, 1578 insertions(+), 2 deletions(-)
14 create mode 100644 drivers/mmc/jz_mmc.c
15 create mode 100644 drivers/mmc/jz_mmc.h
16
17diff --git a/arch/mips/include/asm/jz4740.h b/arch/mips/include/asm/jz4740.h
18index 7a7cfff..68287fb 100644
19+++ b/arch/mips/include/asm/jz4740.h
20@@ -1146,5 +1146,171 @@ extern void sdram_init(void);
21 extern void calc_clocks(void);
22 extern void rtc_init(void);
23
24+/*************************************************************************
25+ * MSC
26+ *************************************************************************/
27+#define REG8(addr) *((volatile u8 *)(addr))
28+#define REG16(addr) *((volatile u16 *)(addr))
29+#define REG32(addr) *((volatile u32 *)(addr))
30+
31+#define CPM_BASE 0xB0000000
32+#define CPM_CPCCR (CPM_BASE+0x00)
33+#define CPM_MSCCDR (CPM_BASE+0x68)
34+#define REG_CPM_MSCCDR REG32(CPM_MSCCDR)
35+#define REG_CPM_CPCCR REG32(CPM_CPCCR)
36+
37+#define MSC_BASE 0xB0021000
38+
39+#define MSC_STRPCL (MSC_BASE + 0x000)
40+#define MSC_STAT (MSC_BASE + 0x004)
41+#define MSC_CLKRT (MSC_BASE + 0x008)
42+#define MSC_CMDAT (MSC_BASE + 0x00C)
43+#define MSC_RESTO (MSC_BASE + 0x010)
44+#define MSC_RDTO (MSC_BASE + 0x014)
45+#define MSC_BLKLEN (MSC_BASE + 0x018)
46+#define MSC_NOB (MSC_BASE + 0x01C)
47+#define MSC_SNOB (MSC_BASE + 0x020)
48+#define MSC_IMASK (MSC_BASE + 0x024)
49+#define MSC_IREG (MSC_BASE + 0x028)
50+#define MSC_CMD (MSC_BASE + 0x02C)
51+#define MSC_ARG (MSC_BASE + 0x030)
52+#define MSC_RES (MSC_BASE + 0x034)
53+#define MSC_RXFIFO (MSC_BASE + 0x038)
54+#define MSC_TXFIFO (MSC_BASE + 0x03C)
55+
56+#define REG_MSC_STRPCL REG16(MSC_STRPCL)
57+#define REG_MSC_STAT REG32(MSC_STAT)
58+#define REG_MSC_CLKRT REG16(MSC_CLKRT)
59+#define REG_MSC_CMDAT REG32(MSC_CMDAT)
60+#define REG_MSC_RESTO REG16(MSC_RESTO)
61+#define REG_MSC_RDTO REG16(MSC_RDTO)
62+#define REG_MSC_BLKLEN REG16(MSC_BLKLEN)
63+#define REG_MSC_NOB REG16(MSC_NOB)
64+#define REG_MSC_SNOB REG16(MSC_SNOB)
65+#define REG_MSC_IMASK REG16(MSC_IMASK)
66+#define REG_MSC_IREG REG16(MSC_IREG)
67+#define REG_MSC_CMD REG8(MSC_CMD)
68+#define REG_MSC_ARG REG32(MSC_ARG)
69+#define REG_MSC_RES REG16(MSC_RES)
70+#define REG_MSC_RXFIFO REG32(MSC_RXFIFO)
71+#define REG_MSC_TXFIFO REG32(MSC_TXFIFO)
72+
73+/* MSC Clock and Control Register (MSC_STRPCL) */
74+
75+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7)
76+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6)
77+#define MSC_STRPCL_START_READWAIT (1 << 5)
78+#define MSC_STRPCL_STOP_READWAIT (1 << 4)
79+#define MSC_STRPCL_RESET (1 << 3)
80+#define MSC_STRPCL_START_OP (1 << 2)
81+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0
82+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT)
83+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */
84+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */
85+
86+/* MSC Status Register (MSC_STAT) */
87+
88+#define MSC_STAT_IS_RESETTING (1 << 15)
89+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14)
90+#define MSC_STAT_PRG_DONE (1 << 13)
91+#define MSC_STAT_DATA_TRAN_DONE (1 << 12)
92+#define MSC_STAT_END_CMD_RES (1 << 11)
93+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10)
94+#define MSC_STAT_IS_READWAIT (1 << 9)
95+#define MSC_STAT_CLK_EN (1 << 8)
96+#define MSC_STAT_DATA_FIFO_FULL (1 << 7)
97+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6)
98+#define MSC_STAT_CRC_RES_ERR (1 << 5)
99+#define MSC_STAT_CRC_READ_ERROR (1 << 4)
100+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2
101+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT)
102+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */
103+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */
104+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */
105+#define MSC_STAT_TIME_OUT_RES (1 << 1)
106+#define MSC_STAT_TIME_OUT_READ (1 << 0)
107+
108+/* MSC Bus Clock Control Register (MSC_CLKRT) */
109+
110+#define MSC_CLKRT_CLK_RATE_BIT 0
111+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT)
112+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */
113+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */
114+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */
115+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */
116+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */
117+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */
118+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */
119+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */
120+
121+/* MSC Command Sequence Control Register (MSC_CMDAT) */
122+
123+#define MSC_CMDAT_IO_ABORT (1 << 11)
124+#define MSC_CMDAT_BUS_WIDTH_BIT 9
125+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT)
126+#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT)
127+#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT)
128+#define MSC_CMDAT_DMA_EN (1 << 8)
129+#define MSC_CMDAT_INIT (1 << 7)
130+#define MSC_CMDAT_BUSY (1 << 6)
131+#define MSC_CMDAT_STREAM_BLOCK (1 << 5)
132+#define MSC_CMDAT_WRITE (1 << 4)
133+#define MSC_CMDAT_READ (0 << 4)
134+#define MSC_CMDAT_DATA_EN (1 << 3)
135+#define MSC_CMDAT_RESPONSE_BIT 0
136+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT)
137+#define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT)
138+#define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT)
139+#define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT)
140+#define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT)
141+#define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT)
142+#define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT)
143+#define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT)
144+
145+/* MSC Interrupts Mask Register (MSC_IMASK) */
146+#define MSC_IMASK_SDIO (1 << 7)
147+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6)
148+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5)
149+#define MSC_IMASK_END_CMD_RES (1 << 2)
150+#define MSC_IMASK_PRG_DONE (1 << 1)
151+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0)
152+
153+
154+/* MSC Interrupts Status Register (MSC_IREG) */
155+#define MSC_IREG_SDIO (1 << 7)
156+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6)
157+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5)
158+#define MSC_IREG_END_CMD_RES (1 << 2)
159+#define MSC_IREG_PRG_DONE (1 << 1)
160+#define MSC_IREG_DATA_TRAN_DONE (1 << 0)
161+
162+static __inline__ unsigned int __cpm_get_pllout2(void)
163+{
164+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS)
165+ return __cpm_get_pllout();
166+ else
167+ return __cpm_get_pllout()/2;
168+}
169+
170+static inline void __cpm_select_msc_clk(int sd)
171+{
172+ unsigned int pllout2 = __cpm_get_pllout2();
173+ unsigned int div = 0;
174+
175+ if (sd) {
176+ div = pllout2 / 24000000;
177+ }
178+ else {
179+ div = pllout2 / 16000000;
180+ }
181+
182+ REG_CPM_MSCCDR = div - 1;
183+}
184+#define __msc_reset() \
185+do { \
186+ REG_MSC_STRPCL = MSC_STRPCL_RESET; \
187+ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \
188+} while (0)
189+
190 #endif /* !__ASSEMBLY__ */
191 #endif /* __JZ4740_H__ */
192diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
193index 553e05d..68da069 100644
194+++ b/board/qi/qi_lb60/qi_lb60.c
195@@ -40,8 +40,13 @@ static void gpio_init(void)
196         __gpio_clear_pin(GPIO_KEYOUT_BASE + i);
197     }
198
199- __gpio_as_input(GPIO_KEYIN_8);
200- __gpio_enable_pull(GPIO_KEYIN_8);
201+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
202+ printf("[S] pressed, enable UART0\n");
203+ __gpio_as_uart0();
204+ } else {
205+ __gpio_as_input(GPIO_KEYIN_8);
206+ __gpio_enable_pull(GPIO_KEYIN_8);
207+ }
208
209     /* enable the TP4, TP5 as UART0 */
210     __gpio_jtag_to_uart0();
211diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
212index 565ba6a..3c717b1 100644
213+++ b/drivers/mmc/Makefile
214@@ -47,6 +47,7 @@ COBJS-$(CONFIG_SDHCI) += sdhci.o
215 COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
216 COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
217 COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
218+COBJS-$(CONFIG_JZ4740_MMC) += jz_mmc.o
219
220 COBJS := $(COBJS-y)
221 SRCS := $(COBJS:.o=.c)
222diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
223new file mode 100644
224index 0000000..642cecc
225+++ b/drivers/mmc/jz_mmc.c
226@@ -0,0 +1,1179 @@
227+/*
228+ * (C) Copyright 2003
229+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
230+ *
231+ * See file CREDITS for list of people who contributed to this
232+ * project.
233+ *
234+ * This program is free software; you can redistribute it and/or
235+ * modify it under the terms of the GNU General Public License as
236+ * published by the Free Software Foundation; either version 2 of
237+ * the License, or (at your option) any later version.
238+ *
239+ * This program is distributed in the hope that it will be useful,
240+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
241+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
242+ * GNU General Public License for more details.
243+ *
244+ * You should have received a copy of the GNU General Public License
245+ * along with this program; if not, write to the Free Software
246+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
247+ * MA 02111-1307 USA
248+ */
249+
250+#include <config.h>
251+#include <common.h>
252+#include <part.h>
253+#include <mmc.h>
254+
255+#include <asm/io.h>
256+#include <asm/jz4740.h>
257+#include "jz_mmc.h"
258+
259+static int sd2_0 = 0;
260+static int mmc_ready = 0;
261+static int use_4bit; /* Use 4-bit data bus */
262+/*
263+ * MMC Events
264+ */
265+#define MMC_EVENT_NONE 0x00 /* No events */
266+#define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */
267+#define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */
268+#define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */
269+
270+
271+#define MMC_IRQ_MASK() \
272+do { \
273+ REG_MSC_IMASK = 0xffff; \
274+ REG_MSC_IREG = 0xffff; \
275+} while (0)
276+
277+/*
278+ * GPIO definition
279+ */
280+#if defined(CONFIG_SAKC)
281+
282+#define __msc_init_io() \
283+do { \
284+ __gpio_as_input(GPIO_SD_CD_N); \
285+} while (0)
286+
287+#else
288+#define __msc_init_io() \
289+do { \
290+ __gpio_as_output(GPIO_SD_VCC_EN_N); \
291+ __gpio_as_input(GPIO_SD_CD_N); \
292+} while (0)
293+
294+#define __msc_enable_power() \
295+do { \
296+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \
297+} while (0)
298+
299+#define __msc_disable_power() \
300+do { \
301+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \
302+} while (0)
303+
304+#endif /* CONFIG_SAKE */
305+
306+#define __msc_card_detected() \
307+({ \
308+ int detected = 1; \
309+ __gpio_as_input(GPIO_SD_CD_N); \
310+ __gpio_disable_pull(GPIO_SD_CD_N); \
311+ if (!__gpio_get_pin(GPIO_SD_CD_N)) \
312+ detected = 0; \
313+ detected; \
314+})
315+
316+/*
317+ * Local functions
318+ */
319+
320+extern int
321+fat_register_device(block_dev_desc_t *dev_desc, int part_no);
322+
323+static block_dev_desc_t mmc_dev;
324+
325+block_dev_desc_t * mmc_get_dev(int dev)
326+{
327+ return ((block_dev_desc_t *)&mmc_dev);
328+}
329+
330+/* Stop the MMC clock and wait while it happens */
331+static inline int jz_mmc_stop_clock(void)
332+{
333+ int timeout = 1000;
334+
335+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP;
336+
337+ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) {
338+ timeout--;
339+ if (timeout == 0)
340+ return MMC_ERROR_TIMEOUT;
341+ udelay(1);
342+ }
343+ return MMC_NO_ERROR;
344+}
345+
346+/* Start the MMC clock and operation */
347+static inline int jz_mmc_start_clock(void)
348+{
349+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP;
350+ return MMC_NO_ERROR;
351+}
352+
353+static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate)
354+{
355+ u32 clkrt = 0;
356+ u32 clk_src = is_sd ? 24000000 : 16000000;
357+
358+ while (rate < clk_src) {
359+ clkrt ++;
360+ clk_src >>= 1;
361+ }
362+
363+ return clkrt;
364+}
365+
366+/* Set the MMC clock frequency */
367+void jz_mmc_set_clock(int sd, u32 rate)
368+{
369+ jz_mmc_stop_clock();
370+
371+ /* Select clock source of MSC */
372+ __cpm_select_msc_clk(sd);
373+
374+ /* Set clock dividor of MSC */
375+ REG_MSC_CLKRT = jz_mmc_calc_clkrt(sd, rate);
376+}
377+
378+static int jz_mmc_check_status(struct mmc_request *request)
379+{
380+ u32 status = REG_MSC_STAT;
381+
382+ /* Checking for response or data timeout */
383+ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) {
384+ printf("MMC/SD timeout, MMC_STAT 0x%x CMD %d\n", status, request->cmd);
385+ return MMC_ERROR_TIMEOUT;
386+ }
387+
388+ /* Checking for CRC error */
389+ if (status & (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) {
390+ printf("MMC/CD CRC error, MMC_STAT 0x%x\n", status);
391+ return MMC_ERROR_CRC;
392+ }
393+
394+ return MMC_NO_ERROR;
395+}
396+
397+/* Obtain response to the command and store it to response buffer */
398+static void jz_mmc_get_response(struct mmc_request *request)
399+{
400+ int i;
401+ u8 *buf;
402+ u32 data;
403+
404+ debug("fetch response for request %d, cmd %d\n",
405+ request->rtype, request->cmd);
406+
407+ buf = request->response;
408+ request->result = MMC_NO_ERROR;
409+
410+ switch (request->rtype) {
411+ case RESPONSE_R1: case RESPONSE_R1B: case RESPONSE_R6:
412+ case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5:
413+ {
414+ data = REG_MSC_RES;
415+ buf[0] = (data >> 8) & 0xff;
416+ buf[1] = data & 0xff;
417+ data = REG_MSC_RES;
418+ buf[2] = (data >> 8) & 0xff;
419+ buf[3] = data & 0xff;
420+ data = REG_MSC_RES;
421+ buf[4] = data & 0xff;
422+
423+ debug("request %d, response [%02x %02x %02x %02x %02x]\n",
424+ request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]);
425+ break;
426+ }
427+ case RESPONSE_R2_CID: case RESPONSE_R2_CSD:
428+ {
429+ for (i = 0; i < 16; i += 2) {
430+ data = REG_MSC_RES;
431+ buf[i] = (data >> 8) & 0xff;
432+ buf[i+1] = data & 0xff;
433+ }
434+ debug("request %d, response [", request->rtype);
435+#if CONFIG_MMC_DEBUG_VERBOSE > 2
436+ if (g_mmc_debug >= 3) {
437+ int n;
438+ for (n = 0; n < 17; n++)
439+ printk("%02x ", buf[n]);
440+ printk("]\n");
441+ }
442+#endif
443+ break;
444+ }
445+ case RESPONSE_NONE:
446+ debug("No response\n");
447+ break;
448+
449+ default:
450+ debug("unhandled response type for request %d\n", request->rtype);
451+ break;
452+ }
453+}
454+
455+static int jz_mmc_receive_data(struct mmc_request *req)
456+{
457+ u32 stat, timeout, data, cnt;
458+ u8 *buf = req->buffer;
459+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
460+
461+ timeout = 0x3ffffff;
462+
463+ while (timeout) {
464+ timeout--;
465+ stat = REG_MSC_STAT;
466+
467+ if (stat & MSC_STAT_TIME_OUT_READ)
468+ return MMC_ERROR_TIMEOUT;
469+ else if (stat & MSC_STAT_CRC_READ_ERROR)
470+ return MMC_ERROR_CRC;
471+ else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)
472+ || (stat & MSC_STAT_DATA_FIFO_AFULL)) {
473+ /* Ready to read data */
474+ break;
475+ }
476+ udelay(1);
477+ }
478+ if (!timeout)
479+ return MMC_ERROR_TIMEOUT;
480+
481+ /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
482+ cnt = wblocklen;
483+ while (cnt) {
484+ data = REG_MSC_RXFIFO;
485+ {
486+ *buf++ = (u8)(data >> 0);
487+ *buf++ = (u8)(data >> 8);
488+ *buf++ = (u8)(data >> 16);
489+ *buf++ = (u8)(data >> 24);
490+ }
491+ cnt --;
492+ while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY))
493+ ;
494+ }
495+ return MMC_NO_ERROR;
496+}
497+
498+static int jz_mmc_transmit_data(struct mmc_request *req)
499+{
500+#if 0
501+ u32 nob = req->nob;
502+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
503+ u8 *buf = req->buffer;
504+ u32 *wbuf = (u32 *)buf;
505+ u32 waligned = (((u32)buf & 0x3) == 0); /* word aligned ? */
506+ u32 stat, timeout, data, cnt;
507+
508+ for (nob; nob >= 1; nob--) {
509+ timeout = 0x3FFFFFF;
510+
511+ while (timeout) {
512+ timeout--;
513+ stat = REG_MSC_STAT;
514+
515+ if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS))
516+ return MMC_ERROR_CRC;
517+ else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) {
518+ /* Ready to write data */
519+ break;
520+ }
521+
522+ udelay(1);
523+ }
524+
525+ if (!timeout)
526+ return MMC_ERROR_TIMEOUT;
527+
528+ /* Write data to TXFIFO */
529+ cnt = wblocklen;
530+ while (cnt) {
531+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL)
532+ ;
533+
534+ if (waligned) {
535+ REG_MSC_TXFIFO = *wbuf++;
536+ }
537+ else {
538+ data = *buf++ | (*buf++ << 8) | (*buf++ << 16) | (*buf++ << 24);
539+ REG_MSC_TXFIFO = data;
540+ }
541+
542+ cnt--;
543+ }
544+ }
545+#endif
546+ return MMC_NO_ERROR;
547+}
548+
549+
550+/*
551+ * Name: int jz_mmc_exec_cmd()
552+ * Function: send command to the card, and get a response
553+ * Input: struct mmc_request *req : MMC/SD request
554+ * Output: 0: right >0: error code
555+ */
556+int jz_mmc_exec_cmd(struct mmc_request *request)
557+{
558+ u32 cmdat = 0, events = 0;
559+ int retval, timeout = 0x3fffff;
560+
561+ /* Indicate we have no result yet */
562+ request->result = MMC_NO_RESPONSE;
563+ if (request->cmd == MMC_CIM_RESET) {
564+ /* On reset, 1-bit bus width */
565+ use_4bit = 0;
566+
567+ /* Reset MMC/SD controller */
568+ __msc_reset();
569+
570+ /* On reset, drop MMC clock down */
571+ jz_mmc_set_clock(0, MMC_CLOCK_SLOW);
572+
573+ /* On reset, stop MMC clock */
574+ jz_mmc_stop_clock();
575+ }
576+ if (request->cmd == MMC_CMD_SEND_OP_COND) {
577+ debug("Have an MMC card\n");
578+ /* always use 1bit for MMC */
579+ use_4bit = 0;
580+ }
581+ if (request->cmd == SET_BUS_WIDTH) {
582+ if (request->arg == 0x2) {
583+ printf("Use 4-bit bus width\n");
584+ use_4bit = 1;
585+ } else {
586+ printf("Use 1-bit bus width\n");
587+ use_4bit = 0;
588+ }
589+ }
590+
591+ /* stop clock */
592+ jz_mmc_stop_clock();
593+
594+ /* mask all interrupts */
595+ REG_MSC_IMASK = 0xffff;
596+
597+ /* clear status */
598+ REG_MSC_IREG = 0xffff;
599+
600+ /* use 4-bit bus width when possible */
601+ if (use_4bit)
602+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT;
603+
604+ /* Set command type and events */
605+ switch (request->cmd) {
606+ /* MMC core extra command */
607+ case MMC_CIM_RESET:
608+ cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */
609+ break;
610+
611+ /* bc - broadcast - no response */
612+ case MMC_CMD_GO_IDLE_STATE:
613+ case MMC_CMD_SET_DSR:
614+ break;
615+
616+ /* bcr - broadcast with response */
617+ case MMC_CMD_SEND_OP_COND:
618+ case MMC_CMD_ALL_SEND_CID:
619+ case MMC_GO_IRQ_STATE:
620+ break;
621+
622+ /* adtc - addressed with data transfer */
623+ case MMC_READ_DAT_UNTIL_STOP:
624+ case MMC_CMD_READ_SINGLE_BLOCK:
625+ case MMC_CMD_READ_MULTIPLE_BLOCK:
626+ case SD_CMD_APP_SEND_SCR:
627+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ;
628+ events = MMC_EVENT_RX_DATA_DONE;
629+ break;
630+
631+ case MMC_WRITE_DAT_UNTIL_STOP:
632+ case MMC_CMD_WRITE_SINGLE_BLOCK:
633+ case MMC_CMD_WRITE_MULTIPLE_BLOCK:
634+ case MMC_PROGRAM_CID:
635+ case MMC_PROGRAM_CSD:
636+ case MMC_SEND_WRITE_PROT:
637+ case MMC_GEN_CMD:
638+ case MMC_LOCK_UNLOCK:
639+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE;
640+ events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE;
641+
642+ break;
643+
644+ case MMC_CMD_STOP_TRANSMISSION:
645+ events = MMC_EVENT_PROG_DONE;
646+ break;
647+
648+ /* ac - no data transfer */
649+ default:
650+ break;
651+ }
652+
653+ /* Set response type */
654+ switch (request->rtype) {
655+ case RESPONSE_NONE:
656+ break;
657+
658+ case RESPONSE_R1B:
659+ cmdat |= MSC_CMDAT_BUSY;
660+ /*FALLTHRU*/
661+ case RESPONSE_R1:
662+ cmdat |= MSC_CMDAT_RESPONSE_R1;
663+ break;
664+ case RESPONSE_R2_CID:
665+ case RESPONSE_R2_CSD:
666+ cmdat |= MSC_CMDAT_RESPONSE_R2;
667+ break;
668+ case RESPONSE_R3:
669+ cmdat |= MSC_CMDAT_RESPONSE_R3;
670+ break;
671+ case RESPONSE_R4:
672+ cmdat |= MSC_CMDAT_RESPONSE_R4;
673+ break;
674+ case RESPONSE_R5:
675+ cmdat |= MSC_CMDAT_RESPONSE_R5;
676+ break;
677+ case RESPONSE_R6:
678+ cmdat |= MSC_CMDAT_RESPONSE_R6;
679+ break;
680+ default:
681+ break;
682+ }
683+
684+ /* Set command index */
685+ if (request->cmd == MMC_CIM_RESET) {
686+ REG_MSC_CMD = MMC_CMD_GO_IDLE_STATE;
687+ } else {
688+ REG_MSC_CMD = request->cmd;
689+ }
690+
691+ /* Set argument */
692+ REG_MSC_ARG = request->arg;
693+
694+ /* Set block length and nob */
695+ if (request->cmd == SD_CMD_APP_SEND_SCR) { /* get SCR from DataFIFO */
696+ REG_MSC_BLKLEN = 8;
697+ REG_MSC_NOB = 1;
698+ } else {
699+ REG_MSC_BLKLEN = request->block_len;
700+ REG_MSC_NOB = request->nob;
701+ }
702+
703+ /* Set command */
704+ REG_MSC_CMDAT = cmdat;
705+
706+ debug("Send cmd %d cmdat: %x arg: %x resp %d\n", request->cmd,
707+ cmdat, request->arg, request->rtype);
708+
709+ /* Start MMC/SD clock and send command to card */
710+ jz_mmc_start_clock();
711+
712+ /* Wait for command completion */
713+ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES))
714+ ;
715+
716+ if (timeout == 0)
717+ return MMC_ERROR_TIMEOUT;
718+
719+ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */
720+
721+ /* Check for status */
722+ retval = jz_mmc_check_status(request);
723+ if (retval) {
724+ return retval;
725+ }
726+
727+ /* Complete command with no response */
728+ if (request->rtype == RESPONSE_NONE) {
729+ return MMC_NO_ERROR;
730+ }
731+
732+ /* Get response */
733+ jz_mmc_get_response(request);
734+
735+ /* Start data operation */
736+ if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) {
737+ if (events & MMC_EVENT_RX_DATA_DONE) {
738+ if (request->cmd == SD_CMD_APP_SEND_SCR) {
739+ /* SD card returns SCR register as data.
740+ MMC core expect it in the response buffer,
741+ after normal response. */
742+ request->buffer = (u8 *)((u32)request->response + 5);
743+ }
744+ jz_mmc_receive_data(request);
745+ }
746+
747+ if (events & MMC_EVENT_TX_DATA_DONE) {
748+ jz_mmc_transmit_data(request);
749+ }
750+
751+ /* Wait for Data Done */
752+ while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE))
753+ ;
754+ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */
755+ }
756+
757+ /* Wait for Prog Done event */
758+ if (events & MMC_EVENT_PROG_DONE) {
759+ while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE))
760+ ;
761+ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */
762+ }
763+
764+ /* Command completed */
765+
766+ return MMC_NO_ERROR; /* return successfully */
767+}
768+
769+int mmc_block_read(u8 *dst, ulong src, ulong len)
770+{
771+
772+ struct mmc_request request;
773+ struct mmc_response_r1 r1;
774+ int retval = 0;
775+
776+ if (len == 0)
777+ goto exit;
778+
779+ mmc_simple_cmd(&request, MMC_CMD_SEND_STATUS, mmcinfo.rca, RESPONSE_R1);
780+ retval = mmc_unpack_r1(&request, &r1, 0);
781+ if (retval && (retval != MMC_ERROR_STATE_MISMATCH))
782+ goto exit;
783+
784+ mmc_simple_cmd(&request, MMC_CMD_SET_BLOCKLEN, len, RESPONSE_R1);
785+ if (retval = mmc_unpack_r1(&request, &r1, 0))
786+ goto exit;
787+
788+ if (!sd2_0)
789+ src *= mmcinfo.block_len;
790+
791+ mmc_send_cmd(&request, MMC_CMD_READ_SINGLE_BLOCK, src, 1, len, RESPONSE_R1, dst);
792+ if (retval = mmc_unpack_r1(&request, &r1, 0))
793+ goto exit;
794+
795+exit:
796+ return retval;
797+}
798+
799+ulong mmc_bread(int dev_num, ulong blkstart, ulong blkcnt, ulong *dst)
800+{
801+ if (!mmc_ready) {
802+ printf("Please initial the MMC first\n");
803+ return -1;
804+ }
805+
806+ int i = 0;
807+ ulong dst_tmp = dst;
808+
809+ for (i = 0; i < blkcnt; i++) {
810+ if ((mmc_block_read((uchar *)(dst_tmp), blkstart, mmcinfo.block_len)) < 0)
811+ return -1;
812+
813+ dst_tmp += mmcinfo.block_len;
814+ blkstart++;
815+ }
816+
817+ return i;
818+}
819+
820+int mmc_select_card(void)
821+{
822+ struct mmc_request request;
823+ struct mmc_response_r1 r1;
824+ int retval;
825+
826+ mmc_simple_cmd(&request, MMC_CMD_SELECT_CARD, mmcinfo.rca, RESPONSE_R1B);
827+ retval = mmc_unpack_r1(&request, &r1, 0);
828+ if (retval) {
829+ return retval;
830+ }
831+
832+ if (mmcinfo.sd) {
833+ mmc_simple_cmd(&request, MMC_CMD_APP_CMD, mmcinfo.rca, RESPONSE_R1);
834+ retval = mmc_unpack_r1(&request,&r1,0);
835+ if (retval) {
836+ return retval;
837+ }
838+#if defined(MMC_BUS_WIDTH_1BIT)
839+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 1, RESPONSE_R1);
840+#else
841+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 2, RESPONSE_R1);
842+#endif
843+ retval = mmc_unpack_r1(&request,&r1,0);
844+ if (retval) {
845+ return retval;
846+ }
847+ }
848+ return 0;
849+}
850+
851+/*
852+ * Configure card
853+ */
854+static void mmc_configure_card(void)
855+{
856+ u32 rate;
857+
858+ /* Get card info */
859+ if (sd2_0)
860+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) << 10;
861+ else
862+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) * (1 << (mmcinfo.csd.c_size_mult + 2));
863+
864+ mmcinfo.block_len = 1 << mmcinfo.csd.read_bl_len;
865+
866+ mmc_dev.if_type = IF_TYPE_SD;
867+ mmc_dev.part_type = PART_TYPE_DOS;
868+ mmc_dev.dev = 0;
869+ mmc_dev.lun = 0;
870+ mmc_dev.type = 0;
871+ mmc_dev.blksz = mmcinfo.block_len;
872+ mmc_dev.lba = mmcinfo.block_num;
873+ mmc_dev.removable = 0;
874+
875+ printf("%s Detected: %lu blocks of %lu bytes\n",
876+ sd2_0 == 1 ? "SDHC" : "SD",
877+ mmc_dev.lba,
878+ mmc_dev.blksz);
879+
880+ /* Fix the clock rate */
881+ rate = mmc_tran_speed(mmcinfo.csd.tran_speed);
882+ if (rate < MMC_CLOCK_SLOW)
883+ rate = MMC_CLOCK_SLOW;
884+ if ((mmcinfo.sd == 0) && (rate > MMC_CLOCK_FAST))
885+ rate = MMC_CLOCK_FAST;
886+ if ((mmcinfo.sd) && (rate > SD_CLOCK_FAST))
887+ rate = SD_CLOCK_FAST;
888+
889+ debug("%s: block_len=%d block_num=%d rate=%d\n",
890+ __func__, mmcinfo.block_len, mmcinfo.block_num, rate);
891+
892+ jz_mmc_set_clock(mmcinfo.sd, rate);
893+}
894+
895+/*
896+ * State machine routines to initialize card(s)
897+ */
898+
899+/*
900+ CIM_SINGLE_CARD_ACQ (frequency at 400 kHz)
901+ --- Must enter from GO_IDLE_STATE ---
902+ 1. SD_SEND_OP_COND (SD Card) [CMD55] + [CMD41]
903+ 2. SEND_OP_COND (Full Range) [CMD1] {optional}
904+ 3. SEND_OP_COND (Set Range ) [CMD1]
905+ If busy, delay and repeat step 2
906+ 4. ALL_SEND_CID [CMD2]
907+ If timeout, set an error (no cards found)
908+ 5. SET_RELATIVE_ADDR [CMD3]
909+ 6. SEND_CSD [CMD9]
910+ 7. SET_DSR [CMD4] Only call this if (csd.dsr_imp).
911+ 8. Set clock frequency (check available in csd.tran_speed)
912+ */
913+
914+#define MMC_INIT_DOING 0
915+#define MMC_INIT_PASSED 1
916+#define MMC_INIT_FAILED 2
917+
918+static int mmc_init_card_state(struct mmc_request *request)
919+{
920+ struct mmc_response_r1 r1;
921+ struct mmc_response_r3 r3;
922+ int retval;
923+ int ocr = 0x40300000;
924+ int limit_41 = 0;
925+
926+ switch (request->cmd) {
927+ case MMC_CMD_GO_IDLE_STATE: /* No response to parse */
928+ if (mmcinfo.sd)
929+ mmc_simple_cmd(request, 8, 0x1aa, RESPONSE_R1);
930+ else
931+ mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
932+ break;
933+
934+ case 8:
935+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
936+ mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1);
937+ break;
938+
939+ case MMC_CMD_APP_CMD:
940+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
941+ if (retval & (limit_41 < 100)) {
942+ debug("%s: unable to MMC_APP_CMD error=%d (%s)\n",
943+ __func__, retval, mmc_result_to_string(retval));
944+ limit_41++;
945+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3);
946+ } else if (limit_41 < 100) {
947+ limit_41++;
948+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3);
949+ } else{
950+ /* reset the card to idle*/
951+ mmc_simple_cmd(request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE);
952+ mmcinfo.sd = 0;
953+ }
954+ break;
955+
956+ case SD_CMD_APP_SEND_OP_COND:
957+ retval = mmc_unpack_r3(request, &r3);
958+ if (retval) {
959+ debug("%s: try MMC card\n", __func__);
960+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
961+ break;
962+ }
963+
964+ debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr);
965+
966+ if(!(r3.ocr & MMC_CARD_BUSY || ocr == 0)){
967+ udelay(50000);
968+ mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1);
969+ } else {
970+ mmcinfo.sd = 1; /* SD Card ready */
971+ mmcinfo.state = CARD_STATE_READY;
972+ mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID);
973+ }
974+ break;
975+
976+ case MMC_CMD_SEND_OP_COND:
977+ retval = mmc_unpack_r3(request, &r3);
978+ if (retval) {
979+ debug("%s: failed SEND_OP_COND error=%d (%s)\n",
980+ __func__, retval, mmc_result_to_string(retval));
981+ return MMC_INIT_FAILED;
982+ }
983+
984+ debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr);
985+ if (!(r3.ocr & MMC_CARD_BUSY)) {
986+ mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
987+ } else {
988+ mmcinfo.sd = 0; /* MMC Card ready */
989+ mmcinfo.state = CARD_STATE_READY;
990+ mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID);
991+ }
992+ break;
993+
994+ case MMC_CMD_ALL_SEND_CID:
995+ retval = mmc_unpack_cid( request, &mmcinfo.cid );
996+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
997+ if ( retval && (retval != MMC_ERROR_CRC)) {
998+ debug("mmc_init_card_state: unable to ALL_SEND_CID error=%d (%s)\n",
999+ retval, mmc_result_to_string(retval));
1000+ return MMC_INIT_FAILED;
1001+ }
1002+ mmcinfo.state = CARD_STATE_IDENT;
1003+ if(mmcinfo.sd)
1004+ mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, 0, RESPONSE_R6);
1005+ else
1006+ mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, ID_TO_RCA(mmcinfo.id) << 16, RESPONSE_R1);
1007+ break;
1008+
1009+ case MMC_CMD_SET_RELATIVE_ADDR:
1010+ if (mmcinfo.sd) {
1011+ retval = mmc_unpack_r6(request, &r1, mmcinfo.state, &mmcinfo.rca);
1012+ mmcinfo.rca = mmcinfo.rca << 16;
1013+ debug("%s: Get RCA from SD: 0x%04x Status: %x\n",
1014+ __func__, mmcinfo.rca, r1.status);
1015+ } else {
1016+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
1017+ mmcinfo.rca = ID_TO_RCA(mmcinfo.id) << 16;
1018+ }
1019+ if (retval) {
1020+ debug("%s: unable to SET_RELATIVE_ADDR error=%d (%s)\n",
1021+ __func__, retval, mmc_result_to_string(retval));
1022+ return MMC_INIT_FAILED;
1023+ }
1024+
1025+ mmcinfo.state = CARD_STATE_STBY;
1026+ mmc_simple_cmd(request, MMC_CMD_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD);
1027+
1028+ break;
1029+
1030+ case MMC_CMD_SEND_CSD:
1031+ retval = mmc_unpack_csd(request, &mmcinfo.csd);
1032+ mmc_ready = 1;
1033+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
1034+ if (retval && (retval != MMC_ERROR_CRC)) {
1035+ debug("%s: unable to SEND_CSD error=%d (%s)\n",
1036+ __func__, retval, mmc_result_to_string(retval));
1037+ return MMC_INIT_FAILED;
1038+ }
1039+ if (mmcinfo.csd.dsr_imp) {
1040+ debug("%s: driver doesn't support setting DSR\n", __func__);
1041+ }
1042+ mmc_configure_card();
1043+ return MMC_INIT_PASSED;
1044+
1045+ default:
1046+ debug("%s: error! Illegal last cmd %d\n", __func__, request->cmd);
1047+ return MMC_INIT_FAILED;
1048+ }
1049+
1050+ return MMC_INIT_DOING;
1051+}
1052+
1053+int mmc_init_card(void)
1054+{
1055+ struct mmc_request request;
1056+ int retval;
1057+
1058+ mmc_simple_cmd(&request, MMC_CIM_RESET, 0, RESPONSE_NONE); /* reset card */
1059+ mmc_simple_cmd(&request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE);
1060+ mmcinfo.sd = 1; /* assuming a SD card */
1061+
1062+ while ((retval = mmc_init_card_state(&request)) == MMC_INIT_DOING)
1063+ ;
1064+
1065+ if (retval == MMC_INIT_PASSED)
1066+ return MMC_NO_ERROR;
1067+ else
1068+ return MMC_NO_RESPONSE;
1069+}
1070+
1071+int mmc_legacy_init(int verbose)
1072+{
1073+ if (!__msc_card_detected())
1074+ return 1;
1075+
1076+ /* Step-1: init GPIO */
1077+ __gpio_as_msc();
1078+ __msc_init_io();
1079+
1080+ /* Step-2: turn on power of card */
1081+#if !defined(CONFIG_SAKC)
1082+ __msc_enable_power();
1083+#endif
1084+
1085+ /* Step-3: Reset MSC Controller. */
1086+ __msc_reset();
1087+
1088+ /* Step-3: mask all IRQs. */
1089+ MMC_IRQ_MASK();
1090+
1091+ /* Step-4: stop MMC/SD clock */
1092+ jz_mmc_stop_clock();
1093+ mmc_init_card();
1094+ mmc_select_card();
1095+
1096+ mmc_dev.block_read = mmc_bread;
1097+ fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
1098+
1099+ return 0;
1100+}
1101+
1102+/*
1103+ * Debugging functions
1104+ */
1105+static char * mmc_result_strings[] = {
1106+ "NO_RESPONSE",
1107+ "NO_ERROR",
1108+ "ERROR_OUT_OF_RANGE",
1109+ "ERROR_ADDRESS",
1110+ "ERROR_BLOCK_LEN",
1111+ "ERROR_ERASE_SEQ",
1112+ "ERROR_ERASE_PARAM",
1113+ "ERROR_WP_VIOLATION",
1114+ "ERROR_CARD_IS_LOCKED",
1115+ "ERROR_LOCK_UNLOCK_FAILED",
1116+ "ERROR_COM_CRC",
1117+ "ERROR_ILLEGAL_COMMAND",
1118+ "ERROR_CARD_ECC_FAILED",
1119+ "ERROR_CC",
1120+ "ERROR_GENERAL",
1121+ "ERROR_UNDERRUN",
1122+ "ERROR_OVERRUN",
1123+ "ERROR_CID_CSD_OVERWRITE",
1124+ "ERROR_STATE_MISMATCH",
1125+ "ERROR_HEADER_MISMATCH",
1126+ "ERROR_TIMEOUT",
1127+ "ERROR_CRC",
1128+ "ERROR_DRIVER_FAILURE",
1129+};
1130+
1131+char * mmc_result_to_string(int i)
1132+{
1133+ return mmc_result_strings[i+1];
1134+}
1135+
1136+static char * card_state_strings[] = {
1137+ "empty",
1138+ "idle",
1139+ "ready",
1140+ "ident",
1141+ "stby",
1142+ "tran",
1143+ "data",
1144+ "rcv",
1145+ "prg",
1146+ "dis",
1147+};
1148+
1149+static inline char * card_state_to_string(int i)
1150+{
1151+ return card_state_strings[i+1];
1152+}
1153+
1154+/*
1155+ * Utility functions
1156+ */
1157+
1158+#define PARSE_U32(_buf,_index) \
1159+ (((u32)_buf[_index]) << 24) | (((u32)_buf[_index+1]) << 16) | \
1160+ (((u32)_buf[_index+2]) << 8) | ((u32)_buf[_index+3]);
1161+
1162+#define PARSE_U16(_buf,_index) \
1163+ (((u16)_buf[_index]) << 8) | ((u16)_buf[_index+1]);
1164+
1165+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd)
1166+{
1167+ u8 *buf = request->response;
1168+ int num = 0;
1169+
1170+ if (request->result)
1171+ return request->result;
1172+
1173+ if (buf[0] != 0x3f)
1174+ return MMC_ERROR_HEADER_MISMATCH;
1175+
1176+ csd->csd_structure = (buf[1] & 0xc0) >> 6;
1177+ if (csd->csd_structure)
1178+ sd2_0 = 1;
1179+ else
1180+ sd2_0 = 0;
1181+
1182+ switch (csd->csd_structure) {
1183+ case 0 :/* Version 1.01-1.10
1184+ * Version 2.00/Standard Capacity */
1185+ csd->taac = buf[2];
1186+ csd->nsac = buf[3];
1187+ csd->tran_speed = buf[4];
1188+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
1189+ csd->read_bl_len = buf[6] & 0x0f;
1190+ /* for support 2GB card*/
1191+ if (csd->read_bl_len >= 10)
1192+ {
1193+ num = csd->read_bl_len - 9;
1194+ csd->read_bl_len = 9;
1195+ }
1196+
1197+ csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0;
1198+ csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;
1199+ csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0;
1200+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
1201+ csd->c_size = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;
1202+
1203+ if (num)
1204+ csd->c_size = csd->c_size << num;
1205+
1206+
1207+ csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3;
1208+ csd->vdd_r_curr_max = buf[9] & 0x07;
1209+ csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5;
1210+ csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2;
1211+ csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);
1212+ csd->sector_size = (buf[11] & 0x7c) >> 2;
1213+ csd->erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
1214+ csd->wp_grp_size = buf[12] & 0x1f;
1215+ csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0;
1216+ csd->default_ecc = (buf[13] & 0x60) >> 5;
1217+ csd->r2w_factor = (buf[13] & 0x1c) >> 2;
1218+ csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);
1219+ if (csd->write_bl_len >= 10)
1220+ csd->write_bl_len = 9;
1221+
1222+ csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0;
1223+ csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0;
1224+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
1225+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
1226+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
1227+ csd->file_format = (buf[15] & 0x0c) >> 2;
1228+ csd->ecc = buf[15] & 0x03;
1229+ break;
1230+ case 1 : /* Version 2.00/High Capacity */
1231+ csd->taac = 0;
1232+ csd->nsac = 0;
1233+ csd->tran_speed = buf[4];
1234+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
1235+
1236+ csd->read_bl_len = 9;
1237+ csd->read_bl_partial = 0;
1238+ csd->write_blk_misalign = 0;
1239+ csd->read_blk_misalign = 0;
1240+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
1241+ csd->c_size = ((((u16)buf[8]) & 0x3f) << 16) | (((u16)buf[9]) << 8) | ((u16)buf[10]) ;
1242+ csd->sector_size = 0x7f;
1243+ csd->erase_grp_size = 0;
1244+ csd->wp_grp_size = 0;
1245+ csd->wp_grp_enable = 0;
1246+ csd->default_ecc = (buf[13] & 0x60) >> 5;
1247+ csd->r2w_factor = 4;/* Unused */
1248+ csd->write_bl_len = 9;
1249+
1250+ csd->write_bl_partial = 0;
1251+ csd->file_format_grp = 0;
1252+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
1253+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
1254+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
1255+ csd->file_format = 0;
1256+ csd->ecc = buf[15] & 0x03;
1257+ }
1258+
1259+ return 0;
1260+}
1261+
1262+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state)
1263+{
1264+ u8 *buf = request->response;
1265+
1266+ if (request->result)
1267+ return request->result;
1268+
1269+ r1->cmd = buf[0];
1270+ r1->status = PARSE_U32(buf,1);
1271+
1272+ debug("mmc_unpack_r1: cmd=%d status=%08x\n", r1->cmd, r1->status);
1273+
1274+ if (R1_STATUS(r1->status)) {
1275+ if (r1->status & R1_OUT_OF_RANGE) return MMC_ERROR_OUT_OF_RANGE;
1276+ if (r1->status & R1_ADDRESS_ERROR) return MMC_ERROR_ADDRESS;
1277+ if (r1->status & R1_BLOCK_LEN_ERROR) return MMC_ERROR_BLOCK_LEN;
1278+ if (r1->status & R1_ERASE_SEQ_ERROR) return MMC_ERROR_ERASE_SEQ;
1279+ if (r1->status & R1_ERASE_PARAM) return MMC_ERROR_ERASE_PARAM;
1280+ if (r1->status & R1_WP_VIOLATION) return MMC_ERROR_WP_VIOLATION;
1281+ /*if (r1->status & R1_CARD_IS_LOCKED) return MMC_ERROR_CARD_IS_LOCKED; */
1282+ if (r1->status & R1_LOCK_UNLOCK_FAILED) return MMC_ERROR_LOCK_UNLOCK_FAILED;
1283+ if (r1->status & R1_COM_CRC_ERROR) return MMC_ERROR_COM_CRC;
1284+ if (r1->status & R1_ILLEGAL_COMMAND) return MMC_ERROR_ILLEGAL_COMMAND;
1285+ if (r1->status & R1_CARD_ECC_FAILED) return MMC_ERROR_CARD_ECC_FAILED;
1286+ if (r1->status & R1_CC_ERROR) return MMC_ERROR_CC;
1287+ if (r1->status & R1_ERROR) return MMC_ERROR_GENERAL;
1288+ if (r1->status & R1_UNDERRUN) return MMC_ERROR_UNDERRUN;
1289+ if (r1->status & R1_OVERRUN) return MMC_ERROR_OVERRUN;
1290+ if (r1->status & R1_CID_CSD_OVERWRITE) return MMC_ERROR_CID_CSD_OVERWRITE;
1291+ }
1292+
1293+ if (buf[0] != request->cmd)
1294+ return MMC_ERROR_HEADER_MISMATCH;
1295+
1296+ /* This should be last - it's the least dangerous error */
1297+
1298+ return 0;
1299+}
1300+
1301+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr)
1302+{
1303+ u8 *buf = request->response;
1304+ if (request->result)
1305+ return request->result;
1306+
1307+ *scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */
1308+ return mmc_unpack_r1(request, r1, state);
1309+
1310+}
1311+
1312+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca)
1313+{
1314+ u8 *buf = request->response;
1315+
1316+ if (request->result)
1317+ return request->result;
1318+
1319+ *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */
1320+
1321+ *(buf+1) = 0;
1322+ *(buf+2) = 0;
1323+
1324+ return mmc_unpack_r1(request, r1, state);
1325+}
1326+
1327+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid)
1328+{
1329+ int i;
1330+ u8 *buf = request->response;
1331+
1332+ if (request->result)
1333+ return request->result;
1334+
1335+ cid->mid = buf[1];
1336+ cid->oid = PARSE_U16(buf,2);
1337+ for (i = 0 ; i < 5 ; i++)
1338+ cid->pnm[i] = buf[4+i];
1339+ cid->pnm[6] = 0;
1340+ cid->prv = buf[10];
1341+ cid->psn = PARSE_U32(buf,10);
1342+ cid->mdt = buf[15];
1343+
1344+ printf("Man %02x OEM 0x%04x \"%s\" %d.%d 0x%08x "
1345+ "Date %02u/%04u\n",
1346+ cid->mid,
1347+ cid->oid,
1348+ cid->pnm,
1349+ cid->prv >> 4,
1350+ cid->prv & 0xf,
1351+ cid->psn,
1352+ cid->mdt & 0xf,
1353+ (cid->mdt >> 4) + 2000);
1354+
1355+ if (buf[0] != 0x3f)
1356+ return MMC_ERROR_HEADER_MISMATCH;
1357+ return 0;
1358+}
1359+
1360+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3)
1361+{
1362+ u8 *buf = request->response;
1363+
1364+ if (request->result)
1365+ return request->result;
1366+
1367+ r3->ocr = PARSE_U32(buf,1);
1368+ debug("mmc_unpack_r3: ocr=%08x\n", r3->ocr);
1369+
1370+ if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH;
1371+ return 0;
1372+}
1373+
1374+#define KBPS 1
1375+#define MBPS 1000
1376+
1377+static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };
1378+static u32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000,
1379+ 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };
1380+
1381+u32 mmc_tran_speed(u8 ts)
1382+{
1383+ u32 rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];
1384+
1385+ if (rate <= 0) {
1386+ debug("%s: error - unrecognized speed 0x%02x\n", __func__, ts);
1387+ return 1;
1388+ }
1389+
1390+ return rate;
1391+}
1392+
1393+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
1394+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer)
1395+{
1396+ request->cmd = cmd;
1397+ request->arg = arg;
1398+ request->rtype = rtype;
1399+ request->nob = nob;
1400+ request->block_len = block_len;
1401+ request->buffer = buffer;
1402+ request->cnt = nob * block_len;
1403+
1404+ jz_mmc_exec_cmd(request);
1405+}
1406diff --git a/drivers/mmc/jz_mmc.h b/drivers/mmc/jz_mmc.h
1407new file mode 100644
1408index 0000000..936c514
1409+++ b/drivers/mmc/jz_mmc.h
1410@@ -0,0 +1,176 @@
1411+/*
1412+ * linux/drivers/mmc/jz_mmc.h
1413+ *
1414+ * Author: Vladimir Shebordaev, Igor Oblakov
1415+ * Copyright: MontaVista Software Inc.
1416+ *
1417+ * $Id: jz_mmc.h,v 1.3 2007-06-15 08:04:20 jlwei Exp $
1418+ *
1419+ * This program is free software; you can redistribute it and/or modify
1420+ * it under the terms of the GNU General Public License version 2 as
1421+ * published by the Free Software Foundation.
1422+ */
1423+#ifndef __MMC_JZMMC_H__
1424+#define __MMC_JZMMC_H__
1425+
1426+#define ID_TO_RCA(x) ((x)+1)
1427+#define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */
1428+
1429+/* Standard MMC/SD clock speeds */
1430+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */
1431+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */
1432+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */
1433+
1434+/* Use negative numbers to disambiguate */
1435+#define MMC_CIM_RESET -1
1436+#define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
1437+
1438+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
1439+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
1440+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
1441+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
1442+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
1443+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
1444+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
1445+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
1446+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
1447+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
1448+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
1449+#define R1_CC_ERROR (1 << 20) /* erx, c */
1450+#define R1_ERROR (1 << 19) /* erx, c */
1451+#define R1_UNDERRUN (1 << 18) /* ex, c */
1452+#define R1_OVERRUN (1 << 17) /* ex, c */
1453+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
1454+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
1455+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
1456+#define R1_ERASE_RESET (1 << 13) /* sr, c */
1457+#define R1_STATUS(x) (x & 0xFFFFE000)
1458+
1459+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
1460+
1461+#define MMC_PROGRAM_CID 26 /* adtc R1 */
1462+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
1463+
1464+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
1465+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
1466+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
1467+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
1468+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
1469+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
1470+
1471+
1472+enum mmc_result_t {
1473+ MMC_NO_RESPONSE = -1,
1474+ MMC_NO_ERROR = 0,
1475+ MMC_ERROR_OUT_OF_RANGE,
1476+ MMC_ERROR_ADDRESS,
1477+ MMC_ERROR_BLOCK_LEN,
1478+ MMC_ERROR_ERASE_SEQ,
1479+ MMC_ERROR_ERASE_PARAM,
1480+ MMC_ERROR_WP_VIOLATION,
1481+ MMC_ERROR_CARD_IS_LOCKED,
1482+ MMC_ERROR_LOCK_UNLOCK_FAILED,
1483+ MMC_ERROR_COM_CRC,
1484+ MMC_ERROR_ILLEGAL_COMMAND,
1485+ MMC_ERROR_CARD_ECC_FAILED,
1486+ MMC_ERROR_CC,
1487+ MMC_ERROR_GENERAL,
1488+ MMC_ERROR_UNDERRUN,
1489+ MMC_ERROR_OVERRUN,
1490+ MMC_ERROR_CID_CSD_OVERWRITE,
1491+ MMC_ERROR_STATE_MISMATCH,
1492+ MMC_ERROR_HEADER_MISMATCH,
1493+ MMC_ERROR_TIMEOUT,
1494+ MMC_ERROR_CRC,
1495+ MMC_ERROR_DRIVER_FAILURE,
1496+};
1497+
1498+enum card_state {
1499+ CARD_STATE_EMPTY = -1,
1500+ CARD_STATE_IDLE = 0,
1501+ CARD_STATE_READY = 1,
1502+ CARD_STATE_IDENT = 2,
1503+ CARD_STATE_STBY = 3,
1504+ CARD_STATE_TRAN = 4,
1505+ CARD_STATE_DATA = 5,
1506+ CARD_STATE_RCV = 6,
1507+ CARD_STATE_PRG = 7,
1508+ CARD_STATE_DIS = 8,
1509+};
1510+
1511+enum mmc_rsp_t {
1512+ RESPONSE_NONE = 0,
1513+ RESPONSE_R1 = 1,
1514+ RESPONSE_R1B = 2,
1515+ RESPONSE_R2_CID = 3,
1516+ RESPONSE_R2_CSD = 4,
1517+ RESPONSE_R3 = 5,
1518+ RESPONSE_R4 = 6,
1519+ RESPONSE_R5 = 7,
1520+ RESPONSE_R6 = 8,
1521+};
1522+
1523+struct mmc_response_r1 {
1524+ u8 cmd;
1525+ u32 status;
1526+};
1527+
1528+struct mmc_response_r3 {
1529+ u32 ocr;
1530+};
1531+
1532+/* the information structure of MMC/SD Card */
1533+struct mmc_info {
1534+ int id; /* Card index */
1535+ int sd; /* MMC or SD card */
1536+ int rca; /* RCA */
1537+ u32 scr; /* SCR 63:32*/
1538+ int flags; /* Ejected, inserted */
1539+ enum card_state state; /* empty, ident, ready, whatever */
1540+
1541+ /* Card specific information */
1542+ struct mmc_cid cid;
1543+ struct mmc_csd csd;
1544+ u32 block_num;
1545+ u32 block_len;
1546+ u32 erase_unit;
1547+};
1548+
1549+struct mmc_info mmcinfo;
1550+
1551+struct mmc_request {
1552+ int index; /* Slot index - used for CS lines */
1553+ int cmd; /* Command to send */
1554+ u32 arg; /* Argument to send */
1555+ enum mmc_rsp_t rtype; /* Response type expected */
1556+
1557+ /* Data transfer (these may be modified at the low level) */
1558+ u16 nob; /* Number of blocks to transfer*/
1559+ u16 block_len; /* Block length */
1560+ u8 *buffer; /* Data buffer */
1561+ u32 cnt; /* Data length, for PIO */
1562+
1563+ /* Results */
1564+ u8 response[18]; /* Buffer to store response - CRC is optional */
1565+ enum mmc_result_t result;
1566+};
1567+
1568+char * mmc_result_to_string(int);
1569+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd);
1570+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state);
1571+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca);
1572+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr);
1573+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid);
1574+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3);
1575+
1576+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
1577+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer);
1578+u32 mmc_tran_speed(u8 ts);
1579+void jz_mmc_set_clock(int sd, u32 rate);
1580+
1581+static inline void mmc_simple_cmd(struct mmc_request *request, int cmd, u32 arg, enum mmc_rsp_t rtype)
1582+{
1583+ mmc_send_cmd( request, cmd, arg, 0, 0, rtype, 0);
1584+}
1585+
1586+#endif /* __MMC_JZMMC_H__ */
1587diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
1588index d4449ac..2690e17 100644
1589+++ b/include/configs/qi_lb60.h
1590@@ -31,6 +31,15 @@
1591 /*
1592  * Miscellaneous configurable options
1593  */
1594+#define CONFIG_JZ4740_MMC
1595+#define CONFIG_MMC 1
1596+#define CONFIG_FAT 1
1597+#define CONFIG_DOS_PARTITION 1
1598+#define CONFIG_CMD_MMC
1599+#define CONFIG_CMD_FAT
1600+#define CONFIG_CMD_EXT2
1601+
1602+
1603 #define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
1604 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000
1605 #define CONFIG_SYS_LOAD_ADDR 0x80600000
1606diff --git a/include/mmc.h b/include/mmc.h
1607index a13e2bd..3c4761c 100644
1608+++ b/include/mmc.h
1609@@ -283,4 +283,44 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
1610 int mmc_legacy_init(int verbose);
1611 #endif
1612
1613+struct mmc_csd
1614+{
1615+ u8 csd_structure:2,
1616+ spec_vers:4,
1617+ rsvd1:2;
1618+ u8 taac;
1619+ u8 nsac;
1620+ u8 tran_speed;
1621+ u16 ccc:12,
1622+ read_bl_len:4;
1623+ u32 c_size:22;
1624+ u64 read_bl_partial:1,
1625+ write_blk_misalign:1,
1626+ read_blk_misalign:1,
1627+ dsr_imp:1,
1628+ rsvd2:2,
1629+ vdd_r_curr_min:3,
1630+ vdd_r_curr_max:3,
1631+ vdd_w_curr_min:3,
1632+ vdd_w_curr_max:3,
1633+ c_size_mult:3,
1634+ sector_size:5,
1635+ erase_grp_size:5,
1636+ wp_grp_size:5,
1637+ wp_grp_enable:1,
1638+ default_ecc:2,
1639+ r2w_factor:3,
1640+ write_bl_len:4,
1641+ write_bl_partial:1,
1642+ rsvd3:5;
1643+ u8 file_format_grp:1,
1644+ copy:1,
1645+ perm_write_protect:1,
1646+ tmp_write_protect:1,
1647+ file_format:2,
1648+ ecc:2;
1649+ u8 crc:7;
1650+ u8 one:1;
1651+};
1652+
1653 #endif /* _MMC_H_ */
16541.7.9.5
1655
package/uboot-xburst/patches/0002-qi_lb60-add-software-usbboot-support.patch
1From fa51192b912d296b8eec10f7d44c6c17eb1dd368 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Fri, 12 Oct 2012 09:47:39 +0800
4Subject: [PATCH 2/6] qi_lb60: add software usbboot support
5
6  JZ4740 CPU have a internal ROM have such kind of code, that make
7  JZ4740 can boot from USB
8
9  usbboot.S can downloads user program from the USB port to internal
10  SRAM and branches to the internal SRAM to execute the program
11
12Signed-off-by: Xiangfu <xiangfu@openmobilefree.net>
13---
14 board/qi/qi_lb60/Makefile | 1 +
15 board/qi/qi_lb60/qi_lb60-spl.c | 20 +
16 board/qi/qi_lb60/usbboot.S | 838 ++++++++++++++++++++++++++++++++++++++++
17 3 files changed, 859 insertions(+)
18 create mode 100644 board/qi/qi_lb60/usbboot.S
19
20diff --git a/board/qi/qi_lb60/Makefile b/board/qi/qi_lb60/Makefile
21index e399246..6dd8c6f 100644
22--- a/board/qi/qi_lb60/Makefile
23@@ -23,6 +23,7 @@ include $(TOPDIR)/config.mk
24 LIB = $(obj)lib$(BOARD).o
25
26 ifeq ($(CONFIG_SPL_BUILD),y)
27+SOBJS := usbboot.o
28 COBJS := $(BOARD)-spl.o
29 else
30 COBJS := $(BOARD).o
31diff --git a/board/qi/qi_lb60/qi_lb60-spl.c b/board/qi/qi_lb60/qi_lb60-spl.c
32index 3fe3fa3..aea459c 100644
33--- a/board/qi/qi_lb60/qi_lb60-spl.c
34@@ -12,6 +12,24 @@
35 #include <asm/io.h>
36 #include <asm/jz4740.h>
37
38+#define KEY_U_OUT (32 * 2 + 16)
39+#define KEY_U_IN (32 * 3 + 19)
40+
41+extern void usb_boot(void);
42+
43+static void check_usb_boot(void)
44+{
45+ __gpio_as_input(KEY_U_IN);
46+ __gpio_enable_pull(KEY_U_IN);
47+ __gpio_as_output(KEY_U_OUT);
48+ __gpio_clear_pin(KEY_U_OUT);
49+
50+ if (!__gpio_get_pin(KEY_U_IN)) {
51+ puts("[U] pressed, goto USBBOOT mode\n");
52+ usb_boot();
53+ }
54+}
55+
56 void nand_spl_boot(void)
57 {
58     __gpio_as_sdram_16bit_4720();
59@@ -23,6 +41,8 @@ void nand_spl_boot(void)
60     pll_init();
61     sdram_init();
62
63+ check_usb_boot();
64+
65     nand_init();
66
67     puts("\nQi LB60 SPL: Starting U-Boot ...\n");
68diff --git a/board/qi/qi_lb60/usbboot.S b/board/qi/qi_lb60/usbboot.S
69new file mode 100644
70index 0000000..c872266
71--- /dev/null
72@@ -0,0 +1,838 @@
73+/*
74+ * for jz4740 usb boot
75+ *
76+ * Copyright (c) 2009 Author: <jlwei@ingenic.cn>
77+ *
78+ * See file CREDITS for list of people who contributed to this
79+ * project.
80+ *
81+ * This program is free software; you can redistribute it and/or
82+ * modify it under the terms of the GNU General Public License as
83+ * published by the Free Software Foundation; either version 2 of
84+ * the License, or (at your option) any later version.
85+ *
86+ * This program is distributed in the hope that it will be useful,
87+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89+ * GNU General Public License for more details.
90+ *
91+ * You should have received a copy of the GNU General Public License
92+ * along with this program; if not, write to the Free Software
93+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
94+ * MA 02111-1307 USA
95+ */
96+ .set noreorder
97+ .globl usb_boot
98+ .text
99+
100+/*
101+ * Both NAND and USB boot load data to D-Cache first, then transfer
102+ * data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
103+ * So init caches first and then dispatch to a proper boot routine.
104+ */
105+
106+.macro load_addr reg addr
107+ li \reg, 0x80000000
108+ addiu \reg, \reg, \addr
109+ la $2, usbboot_begin
110+ subu \reg, \reg, $2
111+.endm
112+
113+usb_boot:
114+ /* Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz. */
115+ la $9, 0xB0000000 /* CPCCR: Clock Control Register */
116+ la $8, 0x42041110 /* I:S:M:P=1:2:2:2 */
117+ sw $8, 0($9)
118+
119+ la $9, 0xB0000010 /* CPPCR: PLL Control Register */
120+ la $8, 0x06000120 /* M=12 N=0 D=0 CLK=12*(M+2)/(N+2) */
121+ sw $8, 0($9)
122+
123+ mtc0 $0, $26 /* CP0_ERRCTL, restore WST reset state */
124+ nop
125+
126+ mtc0 $0, $16 /* CP0_CONFIG */
127+ nop
128+
129+ /* Relocate code to beginning of the ram */
130+
131+ la $2, usbboot_begin
132+ la $3, usbboot_end
133+ li $4, 0x80000000
134+
135+1:
136+ lw $5, 0($2)
137+ sw $5, 0($4)
138+ addiu $2, $2, 4
139+ bne $2, $3, 1b
140+ addiu $4, $4, 4
141+
142+ li $2, 0x80000000
143+ ori $3, $2, 0
144+ addiu $3, $3, usbboot_end
145+ la $4, usbboot_begin
146+ subu $3, $3, $4
147+
148+
149+2:
150+ cache 0x0, 0($2) /* Index_Invalidate_I */
151+ cache 0x1, 0($2) /* Index_Writeback_Inv_D */
152+ addiu $2, $2, 32
153+ subu $4, $3, $2
154+ bgtz $4, 2b
155+ nop
156+
157+ load_addr $3, usb_boot_return
158+
159+ jr $3
160+
161+usbboot_begin:
162+
163+init_caches:
164+ li $2, 3 /* cacheable for kseg0 access */
165+ mtc0 $2, $16 /* CP0_CONFIG */
166+ nop
167+
168+ li $2, 0x20000000 /* enable idx-store-data cache insn */
169+ mtc0 $2, $26 /* CP0_ERRCTL */
170+
171+ ori $2, $28, 0 /* start address */
172+ ori $3, $2, 0x3fe0 /* end address, total 16KB */
173+ mtc0 $0, $28, 0 /* CP0_TAGLO */
174+ mtc0 $0, $28, 1 /* CP0_DATALO */
175+cache_clear_a_line:
176+ cache 0x8, 0($2) /* Index_Store_Tag_I */
177+ cache 0x9, 0($2) /* Index_Store_Tag_D */
178+ bne $2, $3, cache_clear_a_line
179+ addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */
180+
181+ ori $2, $28, 0 /* start address */
182+ ori $3, $2, 0x3fe0 /* end address, total 16KB */
183+ la $4, 0x1ffff000 /* physical address and 4KB page mask */
184+cache_alloc_a_line:
185+ and $5, $2, $4
186+ ori $5, $5, 1 /* V bit of the physical tag */
187+ mtc0 $5, $28, 0 /* CP0_TAGLO */
188+ cache 0x8, 0($2) /* Index_Store_Tag_I */
189+ cache 0x9, 0($2) /* Index_Store_Tag_D */
190+ bne $2, $3, cache_alloc_a_line
191+ addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */
192+
193+ nop
194+ nop
195+ nop
196+ /*
197+ * Transfer data from dcache to icache, then jump to icache.
198+ * Input parameters:
199+ * $19: data length in bytes
200+ * $20: jump target address
201+ */
202+xfer_d2i:
203+
204+ ori $8, $20, 0
205+ addu $9, $8, $19 /* total 16KB */
206+
207+1:
208+ cache 0x0, 0($8) /* Index_Invalidate_I */
209+ cache 0x1, 0($8) /* Index_Writeback_Inv_D */
210+ bne $8, $9, 1b
211+ addiu $8, $8, 32
212+
213+ /* flush write-buffer */
214+ sync
215+
216+ /* Invalidate BTB */
217+ mfc0 $8, $16, 7 /* CP0_CONFIG */
218+ nop
219+ ori $8, 2
220+ mtc0 $8, $16, 7
221+ nop
222+
223+ /* Overwrite config to disable ram initalisation */
224+ li $2, 0xff
225+ sb $2, 20($20)
226+
227+ jalr $20
228+ nop
229+
230+icache_return:
231+ /* User code can return to here after executing itself in
232+ icache, by jumping to $31. */
233+ b usb_boot_return
234+ nop
235+
236+
237+usb_boot_return:
238+ /* Enable the USB PHY */
239+ la $9, 0xB0000024 /* CPM_SCR */
240+ lw $8, 0($9)
241+ ori $8, 0x40 /* USBPHY_ENABLE */
242+ sw $8, 0($9)
243+
244+ /* Initialize USB registers */
245+ la $27, 0xb3040000 /* USB registers base address */
246+
247+ sb $0, 0x0b($27) /* INTRUSBE: disable common USB interrupts */
248+ sh $0, 0x06($27) /* INTRINE: disable EPIN interrutps */
249+ sh $0, 0x08($27) /* INTROUTE: disable EPOUT interrutps */
250+
251+ li $9, 0x61
252+ sb $9, 0x01($27) /* POWER: HSENAB | SUSPENDM | SOFTCONN */
253+
254+ /* Initialize USB states */
255+ li $22, 0 /* set EP0 to IDLE state */
256+ li $23, 1 /* no data stage */
257+
258+ /* Main loop of polling the usb commands */
259+usb_command_loop:
260+ lbu $9, 0x0a($27) /* read INTRUSB */
261+ andi $9, 0x04 /* check USB_INTR_RESET */
262+ beqz $9, check_intr_ep0in
263+ nop
264+
265+ /* 1. Handle USB reset interrupt */
266+handle_reset_intr:
267+ lbu $9, 0x01($27) /* read POWER */
268+ andi $9, 0x10 /* test HS_MODE */
269+ bnez $9, _usb_set_maxpktsize
270+ li $9, 512 /* max packet size of HS mode */
271+ li $9, 64 /* max packet size of FS mode */
272+
273+_usb_set_maxpktsize:
274+ li $8, 1
275+ sb $8, 0x0e($27) /* set INDEX 1 */
276+
277+ sh $9, 0x10($27) /* INMAXP */
278+ sb $0, 0x13($27) /* INCSRH */
279+ sh $9, 0x14($27) /* OUTMAXP */
280+ sb $0, 0x17($27) /* OUTCSRH */
281+
282+_usb_flush_fifo:
283+ li $8, 0x48 /* INCSR_CDT && INCSR_FF */
284+ sb $8, 0x12($27) /* INCSR */
285+ li $8, 0x90 /* OUTCSR_CDT && OUTCSR_FF */
286+ sb $8, 0x16($27) /* OUTCSR */
287+
288+ li $22, 0 /* set EP0 to IDLE state */
289+ li $23, 1 /* no data stage */
290+
291+ /* 2. Check and handle EP0 interrupt */
292+check_intr_ep0in:
293+ lhu $10, 0x02($27) /* read INTRIN */
294+ andi $9, $10, 0x1 /* check EP0 interrupt */
295+ beqz $9, check_intr_ep1in
296+ nop
297+
298+handle_ep0_intr:
299+ sb $0, 0x0e($27) /* set INDEX 0 */
300+ lbu $11, 0x12($27) /* read CSR0 */
301+
302+ andi $9, $11, 0x04 /* check SENTSTALL */
303+ beqz $9, _ep0_setupend
304+ nop
305+
306+_ep0_sentstall:
307+ andi $9, $11, 0xdb
308+ sb $9, 0x12($27) /* clear SENDSTALL and SENTSTALL */
309+ li $22, 0 /* set EP0 to IDLE state */
310+
311+_ep0_setupend:
312+ andi $9, $11, 0x10 /* check SETUPEND */
313+ beqz $9, ep0_idle_state
314+ nop
315+
316+ ori $9, $11, 0x80
317+ sb $9, 0x12($27) /* set SVDSETUPEND */
318+ li $22, 0 /* set EP0 to IDLE state */
319+
320+ep0_idle_state:
321+ bnez $22, ep0_tx_state
322+ nop
323+
324+ /* 2.1 Handle EP0 IDLE state interrupt */
325+ andi $9, $11, 0x01 /* check OUTPKTRDY */
326+ beqz $9, check_intr_ep1in
327+ nop
328+
329+ /* Read 8-bytes setup packet from the FIFO */
330+ lw $25, 0x20($27) /* first word of setup packet */
331+ lw $26, 0x20($27) /* second word of setup packet */
332+
333+ andi $9, $25, 0x60 /* bRequestType & USB_TYPE_MASK */
334+ beqz $9, _ep0_std_req
335+ nop
336+
337+ /* 2.1.1 Vendor-specific setup request */
338+_ep0_vend_req:
339+ li $22, 0 /* set EP0 to IDLE state */
340+ li $23, 1 /* NoData = 1 */
341+
342+ andi $9, $25, 0xff00 /* check bRequest */
343+ srl $9, $9, 8
344+ beqz $9, __ep0_get_cpu_info
345+ sub $8, $9, 0x1
346+ beqz $8, __ep0_set_data_address
347+ sub $8, $9, 0x2
348+ beqz $8, __ep0_set_data_length
349+ sub $8, $9, 0x3
350+ beqz $8, __ep0_flush_caches
351+ sub $8, $9, 0x4
352+ beqz $8, __ep0_prog_start1
353+ sub $8, $9, 0x5
354+ beqz $8, __ep0_prog_start2
355+ nop
356+ b _ep0_idle_state_fini /* invalid request */
357+ nop
358+
359+__ep0_get_cpu_info:
360+ load_addr $20, cpu_info_data /* data pointer to transfer */
361+ li $21, 8 /* bytes left to transfer */
362+ li $22, 1 /* set EP0 to TX state */
363+ li $23, 0 /* NoData = 0 */
364+
365+ b _ep0_idle_state_fini
366+ nop
367+
368+__ep0_set_data_address:
369+ li $9, 0xffff0000
370+ and $9, $25, $9
371+ andi $8, $26, 0xffff
372+ or $20, $9, $8 /* data address of next transfer */
373+
374+ b _ep0_idle_state_fini
375+ nop
376+
377+__ep0_set_data_length:
378+ li $9, 0xffff0000
379+ and $9, $25, $9
380+ andi $8, $26, 0xffff
381+ or $21, $9, $8 /* data length of next transfer */
382+
383+ li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
384+ sb $9, 0x12($27) /* CSR0 */
385+
386+ /* We must write packet to FIFO before EP1-IN interrupt here. */
387+ b handle_epin1_intr
388+ nop
389+
390+__ep0_flush_caches:
391+ /* Flush dcache and invalidate icache. */
392+ li $8, 0x80000000
393+ addi $9, $8, 0x3fe0 /* total 16KB */
394+
395+1:
396+ cache 0x0, 0($8) /* Index_Invalidate_I */
397+ cache 0x1, 0($8) /* Index_Writeback_Inv_D */
398+ bne $8, $9, 1b
399+ addiu $8, $8, 32
400+
401+ /* flush write-buffer */
402+ sync
403+
404+ /* Invalidate BTB */
405+ mfc0 $8, $16, 7 /* CP0_CONFIG */
406+ nop
407+ ori $8, 2
408+ mtc0 $8, $16, 7
409+ nop
410+
411+ b _ep0_idle_state_fini
412+ nop
413+
414+__ep0_prog_start1:
415+ li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
416+ sb $9, 0x12($27) /* CSR0 */
417+
418+ li $9, 0xffff0000
419+ and $9, $25, $9
420+ andi $8, $26, 0xffff
421+ or $20, $9, $8 /* target address */
422+
423+ b xfer_d2i
424+ li $19, 0x2000 /* 16KB data length */
425+
426+__ep0_prog_start2:
427+ li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
428+ sb $9, 0x12($27) /* CSR0 */
429+
430+ li $9, 0xffff0000
431+ and $9, $25, $9
432+ andi $8, $26, 0xffff
433+ or $20, $9, $8 /* target address */
434+
435+ jalr $20 /* jump, and place the return address in $31 */
436+ nop
437+
438+__ep0_prog_start2_return:
439+/* User code can return to here after executing itself, by jumping to $31 */
440+ b usb_boot_return
441+ nop
442+
443+ /* 2.1.2 Standard setup request */
444+_ep0_std_req:
445+ andi $12, $25, 0xff00 /* check bRequest */
446+ srl $12, $12, 8
447+ sub $9, $12, 0x05 /* check USB_REQ_SET_ADDRESS */
448+ bnez $9, __ep0_req_set_config
449+ nop
450+
451+ /* Handle USB_REQ_SET_ADDRESS */
452+__ep0_req_set_addr:
453+ srl $9, $25, 16 /* get wValue */
454+ sb $9, 0x0($27) /* set FADDR */
455+ li $23, 1 /* NoData = 1 */
456+ b _ep0_idle_state_fini
457+ nop
458+
459+__ep0_req_set_config:
460+ sub $9, $12, 0x09 /* check USB_REQ_SET_CONFIGURATION */
461+ bnez $9, __ep0_req_get_desc
462+ nop
463+
464+ /* Handle USB_REQ_SET_CONFIGURATION */
465+ li $23, 1 /* NoData = 1 */
466+ b _ep0_idle_state_fini
467+ nop
468+
469+__ep0_req_get_desc:
470+ sub $9, $12, 0x06 /* check USB_REQ_GET_DESCRIPTOR */
471+ bnez $9, _ep0_idle_state_fini
472+ li $23, 1 /* NoData = 1 */
473+
474+ /* Handle USB_REQ_GET_DESCRIPTOR */
475+ li $23, 0 /* NoData = 0 */
476+
477+ srl $9, $25, 24 /* wValue >> 8 */
478+ sub $8, $9, 0x01 /* check USB_DT_DEVICE */
479+ beqz $8, ___ep0_get_dev_desc
480+ srl $21, $26, 16 /* get wLength */
481+ sub $8, $9, 0x02 /* check USB_DT_CONFIG */
482+ beqz $8, ___ep0_get_conf_desc
483+ sub $8, $9, 0x03 /* check USB_DT_STRING */
484+ beqz $8, ___ep0_get_string_desc
485+ sub $8, $9, 0x06 /* check USB_DT_DEVICE_QUALIFIER */
486+ beqz $8, ___ep0_get_dev_qualifier
487+ nop
488+ b _ep0_idle_state_fini
489+ nop
490+
491+___ep0_get_dev_desc:
492+ load_addr $20, device_desc /* data pointer */
493+ li $22, 1 /* set EP0 to TX state */
494+ sub $8, $21, 18
495+ blez $8, _ep0_idle_state_fini /* wLength <= 18 */
496+ nop
497+ li $21, 18 /* max length of device_desc */
498+ b _ep0_idle_state_fini
499+ nop
500+
501+___ep0_get_dev_qualifier:
502+ load_addr $20, dev_qualifier /* data pointer */
503+ li $22, 1 /* set EP0 to TX state */
504+ sub $8, $21, 10
505+ blez $8, _ep0_idle_state_fini /* wLength <= 10 */
506+ nop
507+ li $21, 10 /* max length of dev_qualifier */
508+ b _ep0_idle_state_fini
509+ nop
510+
511+___ep0_get_conf_desc:
512+ load_addr $20, config_desc_fs /* data pointer of FS mode */
513+ lbu $8, 0x01($27) /* read POWER */
514+ andi $8, 0x10 /* test HS_MODE */
515+ beqz $8, ___ep0_get_conf_desc2
516+ nop
517+ load_addr $20, config_desc_hs /* data pointer of HS mode */
518+
519+___ep0_get_conf_desc2:
520+ li $22, 1 /* set EP0 to TX state */
521+ sub $8, $21, 32
522+ blez $8, _ep0_idle_state_fini /* wLength <= 32 */
523+ nop
524+ li $21, 32 /* max length of config_desc */
525+ b _ep0_idle_state_fini
526+ nop
527+
528+___ep0_get_string_desc:
529+ li $22, 1 /* set EP0 to TX state */
530+
531+ srl $9, $25, 16 /* wValue & 0xff */
532+ andi $9, 0xff
533+
534+ sub $8, $9, 1
535+ beqz $8, ___ep0_get_string_manufacture
536+ sub $8, $9, 2
537+ beqz $8, ___ep0_get_string_product
538+ nop
539+
540+___ep0_get_string_lang_ids:
541+ load_addr $20, string_lang_ids /* data pointer */
542+ b _ep0_idle_state_fini
543+ li $21, 4 /* data length */
544+
545+___ep0_get_string_manufacture:
546+ load_addr $20, string_manufacture /* data pointer */
547+ b _ep0_idle_state_fini
548+ li $21, 16 /* data length */
549+
550+___ep0_get_string_product:
551+ load_addr $20, string_product /* data pointer */
552+ b _ep0_idle_state_fini
553+ li $21, 46 /* data length */
554+
555+_ep0_idle_state_fini:
556+ li $9, 0x40 /* SVDOUTPKTRDY */
557+ beqz $23, _ep0_idle_state_fini2
558+ nop
559+ ori $9, $9, 0x08 /* DATAEND */
560+_ep0_idle_state_fini2:
561+ sb $9, 0x12($27) /* CSR0 */
562+ beqz $22, check_intr_ep1in
563+ nop
564+
565+ /* 2.2 Handle EP0 TX state interrupt */
566+ep0_tx_state:
567+ sub $9, $22, 1
568+ bnez $9, check_intr_ep1in
569+ nop
570+
571+ sub $9, $21, 64 /* max packetsize */
572+ blez $9, _ep0_tx_state2 /* data count <= 64 */
573+ ori $19, $21, 0
574+ li $19, 64
575+
576+_ep0_tx_state2:
577+ beqz $19, _ep0_tx_state3 /* send ZLP */
578+ ori $18, $19, 0 /* record bytes to be transferred */
579+ sub $21, $21, $19 /* decrement data count */
580+
581+_ep0_fifo_write_loop:
582+ lbu $9, 0($20) /* read data */
583+ sb $9, 0x20($27) /* load FIFO */
584+ sub $19, $19, 1 /* decrement counter */
585+ bnez $19, _ep0_fifo_write_loop
586+ addi $20, $20, 1 /* increment data pointer */
587+
588+ sub $9, $18, 64 /* max packetsize */
589+ beqz $9, _ep0_tx_state4
590+ nop
591+
592+_ep0_tx_state3:
593+ /* transferred bytes < max packetsize */
594+ li $9, 0x0a /* set INPKTRDY and DATAEND */
595+ sb $9, 0x12($27) /* CSR0 */
596+ li $22, 0 /* set EP0 to IDLE state */
597+ b check_intr_ep1in
598+ nop
599+
600+_ep0_tx_state4:
601+ /* transferred bytes == max packetsize */
602+ li $9, 0x02 /* set INPKTRDY */
603+ sb $9, 0x12($27) /* CSR0 */
604+ b check_intr_ep1in
605+ nop
606+
607+ /* 3. Check and handle EP1 BULK-IN interrupt */
608+check_intr_ep1in:
609+ andi $9, $10, 0x2 /* check EP1 IN interrupt */
610+ beqz $9, check_intr_ep1out
611+ nop
612+
613+handle_epin1_intr:
614+ li $9, 1
615+ sb $9, 0x0e($27) /* set INDEX 1 */
616+ lbu $9, 0x12($27) /* read INCSR */
617+
618+ andi $8, $9, 0x2 /* check INCSR_FFNOTEMPT */
619+ bnez $8, _epin1_tx_state4
620+ nop
621+
622+_epin1_write_fifo:
623+ lhu $9, 0x10($27) /* get INMAXP */
624+ sub $8, $21, $9
625+ blez $8, _epin1_tx_state1 /* bytes left <= INMAXP */
626+ ori $19, $21, 0
627+ ori $19, $9, 0
628+
629+_epin1_tx_state1:
630+ beqz $19, _epin1_tx_state4 /* No data */
631+ nop
632+
633+ sub $21, $21, $19 /* decrement data count */
634+
635+ srl $5, $19, 2 /* # of word */
636+ andi $6, $19, 0x3 /* # of byte */
637+ beqz $5, _epin1_tx_state2
638+ nop
639+
640+_epin1_fifo_write_word:
641+ lw $9, 0($20) /* read data from source address */
642+ sw $9, 0x24($27) /* write FIFO */
643+ sub $5, $5, 1 /* decrement counter */
644+ bnez $5, _epin1_fifo_write_word
645+ addiu $20, $20, 4 /* increment dest address */
646+
647+_epin1_tx_state2:
648+ beqz $6, _epin1_tx_state3
649+ nop
650+
651+_epin1_fifo_write_byte:
652+ lbu $9, 0($20) /* read data from source address */
653+ sb $9, 0x24($27) /* write FIFO */
654+ sub $6, $6, 1 /* decrement counter */
655+ bnez $6, _epin1_fifo_write_byte
656+ addiu $20, $20, 1 /* increment dest address */
657+
658+_epin1_tx_state3:
659+ li $9, 0x1
660+ sb $9, 0x12($27) /* INCSR, set INPKTRDY */
661+
662+_epin1_tx_state4:
663+ /* 4. Check and handle EP1 BULK-OUT interrupt */
664+check_intr_ep1out:
665+ lhu $9, 0x04($27) /* read INTROUT */
666+ andi $9, 0x2
667+ beqz $9, check_status_next
668+ nop
669+
670+handle_epout1_intr:
671+ li $9, 1
672+ sb $9, 0x0e($27) /* set INDEX 1 */
673+
674+ lbu $9, 0x16($27) /* read OUTCSR */
675+ andi $9, 0x1 /* check OUTPKTRDY */
676+ beqz $9, check_status_next
677+ nop
678+
679+_epout1_read_fifo:
680+ lhu $19, 0x18($27) /* read OUTCOUNT */
681+ srl $5, $19, 2 /* # of word */
682+ andi $6, $19, 0x3 /* # of byte */
683+ beqz $5, _epout1_rx_state1
684+ nop
685+
686+_epout1_fifo_read_word:
687+ lw $9, 0x24($27) /* read FIFO */
688+ sw $9, 0($20) /* store to dest address */
689+ sub $5, $5, 1 /* decrement counter */
690+ bnez $5, _epout1_fifo_read_word
691+ addiu $20, $20, 4 /* increment dest address */
692+
693+_epout1_rx_state1:
694+ beqz $6, _epout1_rx_state2
695+ nop
696+
697+_epout1_fifo_read_byte:
698+ lbu $9, 0x24($27) /* read FIFO */
699+ sb $9, 0($20) /* store to dest address */
700+ sub $6, $6, 1 /* decrement counter */
701+ bnez $6, _epout1_fifo_read_byte
702+ addiu $20, $20, 1 /* increment dest address */
703+
704+_epout1_rx_state2:
705+ sb $0, 0x16($27) /* clear OUTPKTRDY */
706+
707+check_status_next:
708+ b usb_command_loop
709+ nop
710+
711+/* Device/Configuration/Interface/Endpoint/String Descriptors */
712+
713+ .align 2
714+device_desc:
715+ .byte 0x12 /* bLength */
716+ .byte 0x01 /* bDescriptorType */
717+ .byte 0x00 /* bcdUSB */
718+ .byte 0x02 /* bcdUSB */
719+ .byte 0x00 /* bDeviceClass */
720+ .byte 0x00 /* bDeviceSubClass */
721+ .byte 0x00 /* bDeviceProtocol */
722+ .byte 0x40 /* bMaxPacketSize0 */
723+ .byte 0x1a /* idVendor */
724+ .byte 0x60 /* idVendor */
725+ .byte 0x40 /* idProduct */
726+ .byte 0x47 /* idProduct */
727+ .byte 0x00 /* bcdDevice */
728+ .byte 0x01 /* bcdDevice */
729+ .byte 0x01 /* iManufacturer */
730+ .byte 0x02 /* iProduct */
731+ .byte 0x00 /* iSerialNumber */
732+ .byte 0x01 /* bNumConfigurations */
733+
734+ .align 2
735+dev_qualifier:
736+ .byte 0x0a /* bLength */
737+ .byte 0x06 /* bDescriptorType */
738+ .byte 0x00 /* bcdUSB */
739+ .byte 0x02 /* bcdUSB */
740+ .byte 0x00 /* bDeviceClass */
741+ .byte 0x00 /* bDeviceSubClass */
742+ .byte 0x00 /* bDeviceProtocol */
743+ .byte 0x40 /* bMaxPacketSize0 */
744+ .byte 0x01 /* bNumConfigurations */
745+ .byte 0x00 /* bRESERVED */
746+
747+ .align 2
748+config_desc_hs:
749+ .byte 0x09 /* bLength */
750+ .byte 0x02 /* bDescriptorType */
751+ .byte 0x20 /* wTotalLength */
752+ .byte 0x00 /* wTotalLength */
753+ .byte 0x01 /* bNumInterfaces */
754+ .byte 0x01 /* bConfigurationValue */
755+ .byte 0x00 /* iConfiguration */
756+ .byte 0xc0 /* bmAttributes */
757+ .byte 0x01 /* MaxPower */
758+intf_desc_hs:
759+ .byte 0x09 /* bLength */
760+ .byte 0x04 /* bDescriptorType */
761+ .byte 0x00 /* bInterfaceNumber */
762+ .byte 0x00 /* bAlternateSetting */
763+ .byte 0x02 /* bNumEndpoints */
764+ .byte 0xff /* bInterfaceClass */
765+ .byte 0x00 /* bInterfaceSubClass */
766+ .byte 0x50 /* bInterfaceProtocol */
767+ .byte 0x00 /* iInterface */
768+ep1_desc_hs:
769+ .byte 0x07 /* bLength */
770+ .byte 0x05 /* bDescriptorType */
771+ .byte 0x01 /* bEndpointAddress */
772+ .byte 0x02 /* bmAttributes */
773+ .byte 0x00 /* wMaxPacketSize */
774+ .byte 0x02 /* wMaxPacketSize */
775+ .byte 0x00 /* bInterval */
776+ep2_desc_hs:
777+ .byte 0x07 /* bLength */
778+ .byte 0x05 /* bDescriptorType */
779+ .byte 0x81 /* bEndpointAddress */
780+ .byte 0x02 /* bmAttributes */
781+ .byte 0x00 /* wMaxPacketSize */
782+ .byte 0x02 /* wMaxPacketSize */
783+ .byte 0x00 /* bInterval */
784+
785+ .align 2
786+config_desc_fs:
787+ .byte 0x09 /* bLength */
788+ .byte 0x02 /* bDescriptorType */
789+ .byte 0x20 /* wTotalLength */
790+ .byte 0x00 /* wTotalLength */
791+ .byte 0x01 /* bNumInterfaces */
792+ .byte 0x01 /* bConfigurationValue */
793+ .byte 0x00 /* iConfiguration */
794+ .byte 0xc0 /* bmAttributes */
795+ .byte 0x01 /* MaxPower */
796+intf_desc_fs:
797+ .byte 0x09 /* bLength */
798+ .byte 0x04 /* bDescriptorType */
799+ .byte 0x00 /* bInterfaceNumber */
800+ .byte 0x00 /* bAlternateSetting */
801+ .byte 0x02 /* bNumEndpoints */
802+ .byte 0xff /* bInterfaceClass */
803+ .byte 0x00 /* bInterfaceSubClass */
804+ .byte 0x50 /* bInterfaceProtocol */
805+ .byte 0x00 /* iInterface */
806+ep1_desc_fs:
807+ .byte 0x07 /* bLength */
808+ .byte 0x05 /* bDescriptorType */
809+ .byte 0x01 /* bEndpointAddress */
810+ .byte 0x02 /* bmAttributes */
811+ .byte 0x40 /* wMaxPacketSize */
812+ .byte 0x00 /* wMaxPacketSize */
813+ .byte 0x00 /* bInterval */
814+ep2_desc_fs:
815+ .byte 0x07 /* bLength */
816+ .byte 0x05 /* bDescriptorType */
817+ .byte 0x81 /* bEndpointAddress */
818+ .byte 0x02 /* bmAttributes */
819+ .byte 0x40 /* wMaxPacketSize */
820+ .byte 0x00 /* wMaxPacketSize */
821+ .byte 0x00 /* bInterval */
822+
823+ .align 2
824+string_lang_ids:
825+ .byte 0x04
826+ .byte 0x03
827+ .byte 0x09
828+ .byte 0x04
829+
830+ .align 2
831+string_manufacture:
832+ .byte 0x10
833+ .byte 0x03
834+ .byte 0x49
835+ .byte 0x00
836+ .byte 0x6e
837+ .byte 0x00
838+ .byte 0x67
839+ .byte 0x00
840+ .byte 0x65
841+ .byte 0x00
842+ .byte 0x6e
843+ .byte 0x00
844+ .byte 0x69
845+ .byte 0x00
846+ .byte 0x63
847+ .byte 0x00
848+
849+ .align 2
850+string_product:
851+ .byte 0x2e
852+ .byte 0x03
853+ .byte 0x4a
854+ .byte 0x00
855+ .byte 0x5a
856+ .byte 0x00
857+ .byte 0x34
858+ .byte 0x00
859+ .byte 0x37
860+ .byte 0x00
861+ .byte 0x34
862+ .byte 0x00
863+ .byte 0x30
864+ .byte 0x00
865+ .byte 0x20
866+ .byte 0x00
867+ .byte 0x55
868+ .byte 0x00
869+ .byte 0x53
870+ .byte 0x00
871+ .byte 0x42
872+ .byte 0x00
873+ .byte 0x20
874+ .byte 0x00
875+ .byte 0x42
876+ .byte 0x00
877+ .byte 0x6f
878+ .byte 0x00
879+ .byte 0x6f
880+ .byte 0x00
881+ .byte 0x74
882+ .byte 0x00
883+ .byte 0x20
884+ .byte 0x00
885+ .byte 0x44
886+ .byte 0x00
887+ .byte 0x65
888+ .byte 0x00
889+ .byte 0x76
890+ .byte 0x00
891+ .byte 0x69
892+ .byte 0x00
893+ .byte 0x63
894+ .byte 0x00
895+ .byte 0x65
896+ .byte 0x00
897+
898+ .align 2
899+cpu_info_data:
900+ .byte 0x4a
901+ .byte 0x5a
902+ .byte 0x34
903+ .byte 0x37
904+ .byte 0x34
905+ .byte 0x30
906+ .byte 0x56
907+ .byte 0x31
908+usbboot_end:
909+
910+ .set reorder
911--
9121.7.9.5
913
package/uboot-xburst/patches/0003-add-mmc-support.patch
1From bd36739e77669e8df45c38f6acfe2cea511534d9 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Wed, 10 Oct 2012 18:19:41 +0800
4Subject: [PATCH 3/6] add mmc support
5
6---
7 arch/mips/include/asm/jz4740.h | 166 ++++++
8 board/qi/qi_lb60/qi_lb60.c | 9 +-
9 drivers/mmc/Makefile | 1 +
10 drivers/mmc/jz_mmc.c | 1179 ++++++++++++++++++++++++++++++++++++++++
11 drivers/mmc/jz_mmc.h | 176 ++++++
12 include/configs/qi_lb60.h | 9 +
13 include/mmc.h | 40 ++
14 7 files changed, 1578 insertions(+), 2 deletions(-)
15 create mode 100644 drivers/mmc/jz_mmc.c
16 create mode 100644 drivers/mmc/jz_mmc.h
17
18diff --git a/arch/mips/include/asm/jz4740.h b/arch/mips/include/asm/jz4740.h
19index 7a7cfff..68287fb 100644
20--- a/arch/mips/include/asm/jz4740.h
21@@ -1146,5 +1146,171 @@ extern void sdram_init(void);
22 extern void calc_clocks(void);
23 extern void rtc_init(void);
24
25+/*************************************************************************
26+ * MSC
27+ *************************************************************************/
28+#define REG8(addr) *((volatile u8 *)(addr))
29+#define REG16(addr) *((volatile u16 *)(addr))
30+#define REG32(addr) *((volatile u32 *)(addr))
31+
32+#define CPM_BASE 0xB0000000
33+#define CPM_CPCCR (CPM_BASE+0x00)
34+#define CPM_MSCCDR (CPM_BASE+0x68)
35+#define REG_CPM_MSCCDR REG32(CPM_MSCCDR)
36+#define REG_CPM_CPCCR REG32(CPM_CPCCR)
37+
38+#define MSC_BASE 0xB0021000
39+
40+#define MSC_STRPCL (MSC_BASE + 0x000)
41+#define MSC_STAT (MSC_BASE + 0x004)
42+#define MSC_CLKRT (MSC_BASE + 0x008)
43+#define MSC_CMDAT (MSC_BASE + 0x00C)
44+#define MSC_RESTO (MSC_BASE + 0x010)
45+#define MSC_RDTO (MSC_BASE + 0x014)
46+#define MSC_BLKLEN (MSC_BASE + 0x018)
47+#define MSC_NOB (MSC_BASE + 0x01C)
48+#define MSC_SNOB (MSC_BASE + 0x020)
49+#define MSC_IMASK (MSC_BASE + 0x024)
50+#define MSC_IREG (MSC_BASE + 0x028)
51+#define MSC_CMD (MSC_BASE + 0x02C)
52+#define MSC_ARG (MSC_BASE + 0x030)
53+#define MSC_RES (MSC_BASE + 0x034)
54+#define MSC_RXFIFO (MSC_BASE + 0x038)
55+#define MSC_TXFIFO (MSC_BASE + 0x03C)
56+
57+#define REG_MSC_STRPCL REG16(MSC_STRPCL)
58+#define REG_MSC_STAT REG32(MSC_STAT)
59+#define REG_MSC_CLKRT REG16(MSC_CLKRT)
60+#define REG_MSC_CMDAT REG32(MSC_CMDAT)
61+#define REG_MSC_RESTO REG16(MSC_RESTO)
62+#define REG_MSC_RDTO REG16(MSC_RDTO)
63+#define REG_MSC_BLKLEN REG16(MSC_BLKLEN)
64+#define REG_MSC_NOB REG16(MSC_NOB)
65+#define REG_MSC_SNOB REG16(MSC_SNOB)
66+#define REG_MSC_IMASK REG16(MSC_IMASK)
67+#define REG_MSC_IREG REG16(MSC_IREG)
68+#define REG_MSC_CMD REG8(MSC_CMD)
69+#define REG_MSC_ARG REG32(MSC_ARG)
70+#define REG_MSC_RES REG16(MSC_RES)
71+#define REG_MSC_RXFIFO REG32(MSC_RXFIFO)
72+#define REG_MSC_TXFIFO REG32(MSC_TXFIFO)
73+
74+/* MSC Clock and Control Register (MSC_STRPCL) */
75+
76+#define MSC_STRPCL_EXIT_MULTIPLE (1 << 7)
77+#define MSC_STRPCL_EXIT_TRANSFER (1 << 6)
78+#define MSC_STRPCL_START_READWAIT (1 << 5)
79+#define MSC_STRPCL_STOP_READWAIT (1 << 4)
80+#define MSC_STRPCL_RESET (1 << 3)
81+#define MSC_STRPCL_START_OP (1 << 2)
82+#define MSC_STRPCL_CLOCK_CONTROL_BIT 0
83+#define MSC_STRPCL_CLOCK_CONTROL_MASK (0x3 << MSC_STRPCL_CLOCK_CONTROL_BIT)
84+ #define MSC_STRPCL_CLOCK_CONTROL_STOP (0x1 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Stop MMC/SD clock */
85+ #define MSC_STRPCL_CLOCK_CONTROL_START (0x2 << MSC_STRPCL_CLOCK_CONTROL_BIT) /* Start MMC/SD clock */
86+
87+/* MSC Status Register (MSC_STAT) */
88+
89+#define MSC_STAT_IS_RESETTING (1 << 15)
90+#define MSC_STAT_SDIO_INT_ACTIVE (1 << 14)
91+#define MSC_STAT_PRG_DONE (1 << 13)
92+#define MSC_STAT_DATA_TRAN_DONE (1 << 12)
93+#define MSC_STAT_END_CMD_RES (1 << 11)
94+#define MSC_STAT_DATA_FIFO_AFULL (1 << 10)
95+#define MSC_STAT_IS_READWAIT (1 << 9)
96+#define MSC_STAT_CLK_EN (1 << 8)
97+#define MSC_STAT_DATA_FIFO_FULL (1 << 7)
98+#define MSC_STAT_DATA_FIFO_EMPTY (1 << 6)
99+#define MSC_STAT_CRC_RES_ERR (1 << 5)
100+#define MSC_STAT_CRC_READ_ERROR (1 << 4)
101+#define MSC_STAT_CRC_WRITE_ERROR_BIT 2
102+#define MSC_STAT_CRC_WRITE_ERROR_MASK (0x3 << MSC_STAT_CRC_WRITE_ERROR_BIT)
103+ #define MSC_STAT_CRC_WRITE_ERROR_NO (0 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No error on transmission of data */
104+ #define MSC_STAT_CRC_WRITE_ERROR (1 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* Card observed erroneous transmission of data */
105+ #define MSC_STAT_CRC_WRITE_ERROR_NOSTS (2 << MSC_STAT_CRC_WRITE_ERROR_BIT) /* No CRC status is sent back */
106+#define MSC_STAT_TIME_OUT_RES (1 << 1)
107+#define MSC_STAT_TIME_OUT_READ (1 << 0)
108+
109+/* MSC Bus Clock Control Register (MSC_CLKRT) */
110+
111+#define MSC_CLKRT_CLK_RATE_BIT 0
112+#define MSC_CLKRT_CLK_RATE_MASK (0x7 << MSC_CLKRT_CLK_RATE_BIT)
113+ #define MSC_CLKRT_CLK_RATE_DIV_1 (0x0 << MSC_CLKRT_CLK_RATE_BIT) /* CLK_SRC */
114+ #define MSC_CLKRT_CLK_RATE_DIV_2 (0x1 << MSC_CLKRT_CLK_RATE_BIT) /* 1/2 of CLK_SRC */
115+ #define MSC_CLKRT_CLK_RATE_DIV_4 (0x2 << MSC_CLKRT_CLK_RATE_BIT) /* 1/4 of CLK_SRC */
116+ #define MSC_CLKRT_CLK_RATE_DIV_8 (0x3 << MSC_CLKRT_CLK_RATE_BIT) /* 1/8 of CLK_SRC */
117+ #define MSC_CLKRT_CLK_RATE_DIV_16 (0x4 << MSC_CLKRT_CLK_RATE_BIT) /* 1/16 of CLK_SRC */
118+ #define MSC_CLKRT_CLK_RATE_DIV_32 (0x5 << MSC_CLKRT_CLK_RATE_BIT) /* 1/32 of CLK_SRC */
119+ #define MSC_CLKRT_CLK_RATE_DIV_64 (0x6 << MSC_CLKRT_CLK_RATE_BIT) /* 1/64 of CLK_SRC */
120+ #define MSC_CLKRT_CLK_RATE_DIV_128 (0x7 << MSC_CLKRT_CLK_RATE_BIT) /* 1/128 of CLK_SRC */
121+
122+/* MSC Command Sequence Control Register (MSC_CMDAT) */
123+
124+#define MSC_CMDAT_IO_ABORT (1 << 11)
125+#define MSC_CMDAT_BUS_WIDTH_BIT 9
126+#define MSC_CMDAT_BUS_WIDTH_MASK (0x3 << MSC_CMDAT_BUS_WIDTH_BIT)
127+#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << MSC_CMDAT_BUS_WIDTH_BIT)
128+#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << MSC_CMDAT_BUS_WIDTH_BIT)
129+#define MSC_CMDAT_DMA_EN (1 << 8)
130+#define MSC_CMDAT_INIT (1 << 7)
131+#define MSC_CMDAT_BUSY (1 << 6)
132+#define MSC_CMDAT_STREAM_BLOCK (1 << 5)
133+#define MSC_CMDAT_WRITE (1 << 4)
134+#define MSC_CMDAT_READ (0 << 4)
135+#define MSC_CMDAT_DATA_EN (1 << 3)
136+#define MSC_CMDAT_RESPONSE_BIT 0
137+#define MSC_CMDAT_RESPONSE_MASK (0x7 << MSC_CMDAT_RESPONSE_BIT)
138+#define MSC_CMDAT_RESPONSE_NONE (0x0 << MSC_CMDAT_RESPONSE_BIT)
139+#define MSC_CMDAT_RESPONSE_R1 (0x1 << MSC_CMDAT_RESPONSE_BIT)
140+#define MSC_CMDAT_RESPONSE_R2 (0x2 << MSC_CMDAT_RESPONSE_BIT)
141+#define MSC_CMDAT_RESPONSE_R3 (0x3 << MSC_CMDAT_RESPONSE_BIT)
142+#define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT)
143+#define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT)
144+#define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT)
145+
146+/* MSC Interrupts Mask Register (MSC_IMASK) */
147+#define MSC_IMASK_SDIO (1 << 7)
148+#define MSC_IMASK_TXFIFO_WR_REQ (1 << 6)
149+#define MSC_IMASK_RXFIFO_RD_REQ (1 << 5)
150+#define MSC_IMASK_END_CMD_RES (1 << 2)
151+#define MSC_IMASK_PRG_DONE (1 << 1)
152+#define MSC_IMASK_DATA_TRAN_DONE (1 << 0)
153+
154+
155+/* MSC Interrupts Status Register (MSC_IREG) */
156+#define MSC_IREG_SDIO (1 << 7)
157+#define MSC_IREG_TXFIFO_WR_REQ (1 << 6)
158+#define MSC_IREG_RXFIFO_RD_REQ (1 << 5)
159+#define MSC_IREG_END_CMD_RES (1 << 2)
160+#define MSC_IREG_PRG_DONE (1 << 1)
161+#define MSC_IREG_DATA_TRAN_DONE (1 << 0)
162+
163+static __inline__ unsigned int __cpm_get_pllout2(void)
164+{
165+ if (REG_CPM_CPCCR & CPM_CPCCR_PCS)
166+ return __cpm_get_pllout();
167+ else
168+ return __cpm_get_pllout()/2;
169+}
170+
171+static inline void __cpm_select_msc_clk(int sd)
172+{
173+ unsigned int pllout2 = __cpm_get_pllout2();
174+ unsigned int div = 0;
175+
176+ if (sd) {
177+ div = pllout2 / 24000000;
178+ }
179+ else {
180+ div = pllout2 / 16000000;
181+ }
182+
183+ REG_CPM_MSCCDR = div - 1;
184+}
185+#define __msc_reset() \
186+do { \
187+ REG_MSC_STRPCL = MSC_STRPCL_RESET; \
188+ while (REG_MSC_STAT & MSC_STAT_IS_RESETTING); \
189+} while (0)
190+
191 #endif /* !__ASSEMBLY__ */
192 #endif /* __JZ4740_H__ */
193diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
194index 3bd4e2f..a2ba648 100644
195--- a/board/qi/qi_lb60/qi_lb60.c
196@@ -40,8 +40,13 @@ static void gpio_init(void)
197         __gpio_clear_pin(GPIO_KEYOUT_BASE + i);
198     }
199
200- __gpio_as_input(GPIO_KEYIN_8);
201- __gpio_enable_pull(GPIO_KEYIN_8);
202+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
203+ printf("[S] pressed, enable UART0\n");
204+ __gpio_as_uart0();
205+ } else {
206+ __gpio_as_input(GPIO_KEYIN_8);
207+ __gpio_enable_pull(GPIO_KEYIN_8);
208+ }
209
210     /* enable the TP4, TP5 as UART0 */
211     __gpio_jtag_to_uart0();
212diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
213index 565ba6a..3c717b1 100644
214--- a/drivers/mmc/Makefile
215@@ -47,6 +47,7 @@ COBJS-$(CONFIG_SDHCI) += sdhci.o
216 COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
217 COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
218 COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
219+COBJS-$(CONFIG_JZ4740_MMC) += jz_mmc.o
220
221 COBJS := $(COBJS-y)
222 SRCS := $(COBJS:.o=.c)
223diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
224new file mode 100644
225index 0000000..642cecc
226--- /dev/null
227@@ -0,0 +1,1179 @@
228+/*
229+ * (C) Copyright 2003
230+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
231+ *
232+ * See file CREDITS for list of people who contributed to this
233+ * project.
234+ *
235+ * This program is free software; you can redistribute it and/or
236+ * modify it under the terms of the GNU General Public License as
237+ * published by the Free Software Foundation; either version 2 of
238+ * the License, or (at your option) any later version.
239+ *
240+ * This program is distributed in the hope that it will be useful,
241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
243+ * GNU General Public License for more details.
244+ *
245+ * You should have received a copy of the GNU General Public License
246+ * along with this program; if not, write to the Free Software
247+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
248+ * MA 02111-1307 USA
249+ */
250+
251+#include <config.h>
252+#include <common.h>
253+#include <part.h>
254+#include <mmc.h>
255+
256+#include <asm/io.h>
257+#include <asm/jz4740.h>
258+#include "jz_mmc.h"
259+
260+static int sd2_0 = 0;
261+static int mmc_ready = 0;
262+static int use_4bit; /* Use 4-bit data bus */
263+/*
264+ * MMC Events
265+ */
266+#define MMC_EVENT_NONE 0x00 /* No events */
267+#define MMC_EVENT_RX_DATA_DONE 0x01 /* Rx data done */
268+#define MMC_EVENT_TX_DATA_DONE 0x02 /* Tx data done */
269+#define MMC_EVENT_PROG_DONE 0x04 /* Programming is done */
270+
271+
272+#define MMC_IRQ_MASK() \
273+do { \
274+ REG_MSC_IMASK = 0xffff; \
275+ REG_MSC_IREG = 0xffff; \
276+} while (0)
277+
278+/*
279+ * GPIO definition
280+ */
281+#if defined(CONFIG_SAKC)
282+
283+#define __msc_init_io() \
284+do { \
285+ __gpio_as_input(GPIO_SD_CD_N); \
286+} while (0)
287+
288+#else
289+#define __msc_init_io() \
290+do { \
291+ __gpio_as_output(GPIO_SD_VCC_EN_N); \
292+ __gpio_as_input(GPIO_SD_CD_N); \
293+} while (0)
294+
295+#define __msc_enable_power() \
296+do { \
297+ __gpio_clear_pin(GPIO_SD_VCC_EN_N); \
298+} while (0)
299+
300+#define __msc_disable_power() \
301+do { \
302+ __gpio_set_pin(GPIO_SD_VCC_EN_N); \
303+} while (0)
304+
305+#endif /* CONFIG_SAKE */
306+
307+#define __msc_card_detected() \
308+({ \
309+ int detected = 1; \
310+ __gpio_as_input(GPIO_SD_CD_N); \
311+ __gpio_disable_pull(GPIO_SD_CD_N); \
312+ if (!__gpio_get_pin(GPIO_SD_CD_N)) \
313+ detected = 0; \
314+ detected; \
315+})
316+
317+/*
318+ * Local functions
319+ */
320+
321+extern int
322+fat_register_device(block_dev_desc_t *dev_desc, int part_no);
323+
324+static block_dev_desc_t mmc_dev;
325+
326+block_dev_desc_t * mmc_get_dev(int dev)
327+{
328+ return ((block_dev_desc_t *)&mmc_dev);
329+}
330+
331+/* Stop the MMC clock and wait while it happens */
332+static inline int jz_mmc_stop_clock(void)
333+{
334+ int timeout = 1000;
335+
336+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_STOP;
337+
338+ while (timeout && (REG_MSC_STAT & MSC_STAT_CLK_EN)) {
339+ timeout--;
340+ if (timeout == 0)
341+ return MMC_ERROR_TIMEOUT;
342+ udelay(1);
343+ }
344+ return MMC_NO_ERROR;
345+}
346+
347+/* Start the MMC clock and operation */
348+static inline int jz_mmc_start_clock(void)
349+{
350+ REG_MSC_STRPCL = MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP;
351+ return MMC_NO_ERROR;
352+}
353+
354+static inline u32 jz_mmc_calc_clkrt(int is_sd, u32 rate)
355+{
356+ u32 clkrt = 0;
357+ u32 clk_src = is_sd ? 24000000 : 16000000;
358+
359+ while (rate < clk_src) {
360+ clkrt ++;
361+ clk_src >>= 1;
362+ }
363+
364+ return clkrt;
365+}
366+
367+/* Set the MMC clock frequency */
368+void jz_mmc_set_clock(int sd, u32 rate)
369+{
370+ jz_mmc_stop_clock();
371+
372+ /* Select clock source of MSC */
373+ __cpm_select_msc_clk(sd);
374+
375+ /* Set clock dividor of MSC */
376+ REG_MSC_CLKRT = jz_mmc_calc_clkrt(sd, rate);
377+}
378+
379+static int jz_mmc_check_status(struct mmc_request *request)
380+{
381+ u32 status = REG_MSC_STAT;
382+
383+ /* Checking for response or data timeout */
384+ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) {
385+ printf("MMC/SD timeout, MMC_STAT 0x%x CMD %d\n", status, request->cmd);
386+ return MMC_ERROR_TIMEOUT;
387+ }
388+
389+ /* Checking for CRC error */
390+ if (status & (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) {
391+ printf("MMC/CD CRC error, MMC_STAT 0x%x\n", status);
392+ return MMC_ERROR_CRC;
393+ }
394+
395+ return MMC_NO_ERROR;
396+}
397+
398+/* Obtain response to the command and store it to response buffer */
399+static void jz_mmc_get_response(struct mmc_request *request)
400+{
401+ int i;
402+ u8 *buf;
403+ u32 data;
404+
405+ debug("fetch response for request %d, cmd %d\n",
406+ request->rtype, request->cmd);
407+
408+ buf = request->response;
409+ request->result = MMC_NO_ERROR;
410+
411+ switch (request->rtype) {
412+ case RESPONSE_R1: case RESPONSE_R1B: case RESPONSE_R6:
413+ case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5:
414+ {
415+ data = REG_MSC_RES;
416+ buf[0] = (data >> 8) & 0xff;
417+ buf[1] = data & 0xff;
418+ data = REG_MSC_RES;
419+ buf[2] = (data >> 8) & 0xff;
420+ buf[3] = data & 0xff;
421+ data = REG_MSC_RES;
422+ buf[4] = data & 0xff;
423+
424+ debug("request %d, response [%02x %02x %02x %02x %02x]\n",
425+ request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]);
426+ break;
427+ }
428+ case RESPONSE_R2_CID: case RESPONSE_R2_CSD:
429+ {
430+ for (i = 0; i < 16; i += 2) {
431+ data = REG_MSC_RES;
432+ buf[i] = (data >> 8) & 0xff;
433+ buf[i+1] = data & 0xff;
434+ }
435+ debug("request %d, response [", request->rtype);
436+#if CONFIG_MMC_DEBUG_VERBOSE > 2
437+ if (g_mmc_debug >= 3) {
438+ int n;
439+ for (n = 0; n < 17; n++)
440+ printk("%02x ", buf[n]);
441+ printk("]\n");
442+ }
443+#endif
444+ break;
445+ }
446+ case RESPONSE_NONE:
447+ debug("No response\n");
448+ break;
449+
450+ default:
451+ debug("unhandled response type for request %d\n", request->rtype);
452+ break;
453+ }
454+}
455+
456+static int jz_mmc_receive_data(struct mmc_request *req)
457+{
458+ u32 stat, timeout, data, cnt;
459+ u8 *buf = req->buffer;
460+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
461+
462+ timeout = 0x3ffffff;
463+
464+ while (timeout) {
465+ timeout--;
466+ stat = REG_MSC_STAT;
467+
468+ if (stat & MSC_STAT_TIME_OUT_READ)
469+ return MMC_ERROR_TIMEOUT;
470+ else if (stat & MSC_STAT_CRC_READ_ERROR)
471+ return MMC_ERROR_CRC;
472+ else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY)
473+ || (stat & MSC_STAT_DATA_FIFO_AFULL)) {
474+ /* Ready to read data */
475+ break;
476+ }
477+ udelay(1);
478+ }
479+ if (!timeout)
480+ return MMC_ERROR_TIMEOUT;
481+
482+ /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */
483+ cnt = wblocklen;
484+ while (cnt) {
485+ data = REG_MSC_RXFIFO;
486+ {
487+ *buf++ = (u8)(data >> 0);
488+ *buf++ = (u8)(data >> 8);
489+ *buf++ = (u8)(data >> 16);
490+ *buf++ = (u8)(data >> 24);
491+ }
492+ cnt --;
493+ while (cnt && (REG_MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY))
494+ ;
495+ }
496+ return MMC_NO_ERROR;
497+}
498+
499+static int jz_mmc_transmit_data(struct mmc_request *req)
500+{
501+#if 0
502+ u32 nob = req->nob;
503+ u32 wblocklen = (u32)(req->block_len + 3) >> 2; /* length in word */
504+ u8 *buf = req->buffer;
505+ u32 *wbuf = (u32 *)buf;
506+ u32 waligned = (((u32)buf & 0x3) == 0); /* word aligned ? */
507+ u32 stat, timeout, data, cnt;
508+
509+ for (nob; nob >= 1; nob--) {
510+ timeout = 0x3FFFFFF;
511+
512+ while (timeout) {
513+ timeout--;
514+ stat = REG_MSC_STAT;
515+
516+ if (stat & (MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_WRITE_ERROR_NOSTS))
517+ return MMC_ERROR_CRC;
518+ else if (!(stat & MSC_STAT_DATA_FIFO_FULL)) {
519+ /* Ready to write data */
520+ break;
521+ }
522+
523+ udelay(1);
524+ }
525+
526+ if (!timeout)
527+ return MMC_ERROR_TIMEOUT;
528+
529+ /* Write data to TXFIFO */
530+ cnt = wblocklen;
531+ while (cnt) {
532+ while (REG_MSC_STAT & MSC_STAT_DATA_FIFO_FULL)
533+ ;
534+
535+ if (waligned) {
536+ REG_MSC_TXFIFO = *wbuf++;
537+ }
538+ else {
539+ data = *buf++ | (*buf++ << 8) | (*buf++ << 16) | (*buf++ << 24);
540+ REG_MSC_TXFIFO = data;
541+ }
542+
543+ cnt--;
544+ }
545+ }
546+#endif
547+ return MMC_NO_ERROR;
548+}
549+
550+
551+/*
552+ * Name: int jz_mmc_exec_cmd()
553+ * Function: send command to the card, and get a response
554+ * Input: struct mmc_request *req : MMC/SD request
555+ * Output: 0: right >0: error code
556+ */
557+int jz_mmc_exec_cmd(struct mmc_request *request)
558+{
559+ u32 cmdat = 0, events = 0;
560+ int retval, timeout = 0x3fffff;
561+
562+ /* Indicate we have no result yet */
563+ request->result = MMC_NO_RESPONSE;
564+ if (request->cmd == MMC_CIM_RESET) {
565+ /* On reset, 1-bit bus width */
566+ use_4bit = 0;
567+
568+ /* Reset MMC/SD controller */
569+ __msc_reset();
570+
571+ /* On reset, drop MMC clock down */
572+ jz_mmc_set_clock(0, MMC_CLOCK_SLOW);
573+
574+ /* On reset, stop MMC clock */
575+ jz_mmc_stop_clock();
576+ }
577+ if (request->cmd == MMC_CMD_SEND_OP_COND) {
578+ debug("Have an MMC card\n");
579+ /* always use 1bit for MMC */
580+ use_4bit = 0;
581+ }
582+ if (request->cmd == SET_BUS_WIDTH) {
583+ if (request->arg == 0x2) {
584+ printf("Use 4-bit bus width\n");
585+ use_4bit = 1;
586+ } else {
587+ printf("Use 1-bit bus width\n");
588+ use_4bit = 0;
589+ }
590+ }
591+
592+ /* stop clock */
593+ jz_mmc_stop_clock();
594+
595+ /* mask all interrupts */
596+ REG_MSC_IMASK = 0xffff;
597+
598+ /* clear status */
599+ REG_MSC_IREG = 0xffff;
600+
601+ /* use 4-bit bus width when possible */
602+ if (use_4bit)
603+ cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT;
604+
605+ /* Set command type and events */
606+ switch (request->cmd) {
607+ /* MMC core extra command */
608+ case MMC_CIM_RESET:
609+ cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */
610+ break;
611+
612+ /* bc - broadcast - no response */
613+ case MMC_CMD_GO_IDLE_STATE:
614+ case MMC_CMD_SET_DSR:
615+ break;
616+
617+ /* bcr - broadcast with response */
618+ case MMC_CMD_SEND_OP_COND:
619+ case MMC_CMD_ALL_SEND_CID:
620+ case MMC_GO_IRQ_STATE:
621+ break;
622+
623+ /* adtc - addressed with data transfer */
624+ case MMC_READ_DAT_UNTIL_STOP:
625+ case MMC_CMD_READ_SINGLE_BLOCK:
626+ case MMC_CMD_READ_MULTIPLE_BLOCK:
627+ case SD_CMD_APP_SEND_SCR:
628+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ;
629+ events = MMC_EVENT_RX_DATA_DONE;
630+ break;
631+
632+ case MMC_WRITE_DAT_UNTIL_STOP:
633+ case MMC_CMD_WRITE_SINGLE_BLOCK:
634+ case MMC_CMD_WRITE_MULTIPLE_BLOCK:
635+ case MMC_PROGRAM_CID:
636+ case MMC_PROGRAM_CSD:
637+ case MMC_SEND_WRITE_PROT:
638+ case MMC_GEN_CMD:
639+ case MMC_LOCK_UNLOCK:
640+ cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE;
641+ events = MMC_EVENT_TX_DATA_DONE | MMC_EVENT_PROG_DONE;
642+
643+ break;
644+
645+ case MMC_CMD_STOP_TRANSMISSION:
646+ events = MMC_EVENT_PROG_DONE;
647+ break;
648+
649+ /* ac - no data transfer */
650+ default:
651+ break;
652+ }
653+
654+ /* Set response type */
655+ switch (request->rtype) {
656+ case RESPONSE_NONE:
657+ break;
658+
659+ case RESPONSE_R1B:
660+ cmdat |= MSC_CMDAT_BUSY;
661+ /*FALLTHRU*/
662+ case RESPONSE_R1:
663+ cmdat |= MSC_CMDAT_RESPONSE_R1;
664+ break;
665+ case RESPONSE_R2_CID:
666+ case RESPONSE_R2_CSD:
667+ cmdat |= MSC_CMDAT_RESPONSE_R2;
668+ break;
669+ case RESPONSE_R3:
670+ cmdat |= MSC_CMDAT_RESPONSE_R3;
671+ break;
672+ case RESPONSE_R4:
673+ cmdat |= MSC_CMDAT_RESPONSE_R4;
674+ break;
675+ case RESPONSE_R5:
676+ cmdat |= MSC_CMDAT_RESPONSE_R5;
677+ break;
678+ case RESPONSE_R6:
679+ cmdat |= MSC_CMDAT_RESPONSE_R6;
680+ break;
681+ default:
682+ break;
683+ }
684+
685+ /* Set command index */
686+ if (request->cmd == MMC_CIM_RESET) {
687+ REG_MSC_CMD = MMC_CMD_GO_IDLE_STATE;
688+ } else {
689+ REG_MSC_CMD = request->cmd;
690+ }
691+
692+ /* Set argument */
693+ REG_MSC_ARG = request->arg;
694+
695+ /* Set block length and nob */
696+ if (request->cmd == SD_CMD_APP_SEND_SCR) { /* get SCR from DataFIFO */
697+ REG_MSC_BLKLEN = 8;
698+ REG_MSC_NOB = 1;
699+ } else {
700+ REG_MSC_BLKLEN = request->block_len;
701+ REG_MSC_NOB = request->nob;
702+ }
703+
704+ /* Set command */
705+ REG_MSC_CMDAT = cmdat;
706+
707+ debug("Send cmd %d cmdat: %x arg: %x resp %d\n", request->cmd,
708+ cmdat, request->arg, request->rtype);
709+
710+ /* Start MMC/SD clock and send command to card */
711+ jz_mmc_start_clock();
712+
713+ /* Wait for command completion */
714+ while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES))
715+ ;
716+
717+ if (timeout == 0)
718+ return MMC_ERROR_TIMEOUT;
719+
720+ REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */
721+
722+ /* Check for status */
723+ retval = jz_mmc_check_status(request);
724+ if (retval) {
725+ return retval;
726+ }
727+
728+ /* Complete command with no response */
729+ if (request->rtype == RESPONSE_NONE) {
730+ return MMC_NO_ERROR;
731+ }
732+
733+ /* Get response */
734+ jz_mmc_get_response(request);
735+
736+ /* Start data operation */
737+ if (events & (MMC_EVENT_RX_DATA_DONE | MMC_EVENT_TX_DATA_DONE)) {
738+ if (events & MMC_EVENT_RX_DATA_DONE) {
739+ if (request->cmd == SD_CMD_APP_SEND_SCR) {
740+ /* SD card returns SCR register as data.
741+ MMC core expect it in the response buffer,
742+ after normal response. */
743+ request->buffer = (u8 *)((u32)request->response + 5);
744+ }
745+ jz_mmc_receive_data(request);
746+ }
747+
748+ if (events & MMC_EVENT_TX_DATA_DONE) {
749+ jz_mmc_transmit_data(request);
750+ }
751+
752+ /* Wait for Data Done */
753+ while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE))
754+ ;
755+ REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */
756+ }
757+
758+ /* Wait for Prog Done event */
759+ if (events & MMC_EVENT_PROG_DONE) {
760+ while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE))
761+ ;
762+ REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */
763+ }
764+
765+ /* Command completed */
766+
767+ return MMC_NO_ERROR; /* return successfully */
768+}
769+
770+int mmc_block_read(u8 *dst, ulong src, ulong len)
771+{
772+
773+ struct mmc_request request;
774+ struct mmc_response_r1 r1;
775+ int retval = 0;
776+
777+ if (len == 0)
778+ goto exit;
779+
780+ mmc_simple_cmd(&request, MMC_CMD_SEND_STATUS, mmcinfo.rca, RESPONSE_R1);
781+ retval = mmc_unpack_r1(&request, &r1, 0);
782+ if (retval && (retval != MMC_ERROR_STATE_MISMATCH))
783+ goto exit;
784+
785+ mmc_simple_cmd(&request, MMC_CMD_SET_BLOCKLEN, len, RESPONSE_R1);
786+ if (retval = mmc_unpack_r1(&request, &r1, 0))
787+ goto exit;
788+
789+ if (!sd2_0)
790+ src *= mmcinfo.block_len;
791+
792+ mmc_send_cmd(&request, MMC_CMD_READ_SINGLE_BLOCK, src, 1, len, RESPONSE_R1, dst);
793+ if (retval = mmc_unpack_r1(&request, &r1, 0))
794+ goto exit;
795+
796+exit:
797+ return retval;
798+}
799+
800+ulong mmc_bread(int dev_num, ulong blkstart, ulong blkcnt, ulong *dst)
801+{
802+ if (!mmc_ready) {
803+ printf("Please initial the MMC first\n");
804+ return -1;
805+ }
806+
807+ int i = 0;
808+ ulong dst_tmp = dst;
809+
810+ for (i = 0; i < blkcnt; i++) {
811+ if ((mmc_block_read((uchar *)(dst_tmp), blkstart, mmcinfo.block_len)) < 0)
812+ return -1;
813+
814+ dst_tmp += mmcinfo.block_len;
815+ blkstart++;
816+ }
817+
818+ return i;
819+}
820+
821+int mmc_select_card(void)
822+{
823+ struct mmc_request request;
824+ struct mmc_response_r1 r1;
825+ int retval;
826+
827+ mmc_simple_cmd(&request, MMC_CMD_SELECT_CARD, mmcinfo.rca, RESPONSE_R1B);
828+ retval = mmc_unpack_r1(&request, &r1, 0);
829+ if (retval) {
830+ return retval;
831+ }
832+
833+ if (mmcinfo.sd) {
834+ mmc_simple_cmd(&request, MMC_CMD_APP_CMD, mmcinfo.rca, RESPONSE_R1);
835+ retval = mmc_unpack_r1(&request,&r1,0);
836+ if (retval) {
837+ return retval;
838+ }
839+#if defined(MMC_BUS_WIDTH_1BIT)
840+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 1, RESPONSE_R1);
841+#else
842+ mmc_simple_cmd(&request, SET_BUS_WIDTH, 2, RESPONSE_R1);
843+#endif
844+ retval = mmc_unpack_r1(&request,&r1,0);
845+ if (retval) {
846+ return retval;
847+ }
848+ }
849+ return 0;
850+}
851+
852+/*
853+ * Configure card
854+ */
855+static void mmc_configure_card(void)
856+{
857+ u32 rate;
858+
859+ /* Get card info */
860+ if (sd2_0)
861+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) << 10;
862+ else
863+ mmcinfo.block_num = (mmcinfo.csd.c_size + 1) * (1 << (mmcinfo.csd.c_size_mult + 2));
864+
865+ mmcinfo.block_len = 1 << mmcinfo.csd.read_bl_len;
866+
867+ mmc_dev.if_type = IF_TYPE_SD;
868+ mmc_dev.part_type = PART_TYPE_DOS;
869+ mmc_dev.dev = 0;
870+ mmc_dev.lun = 0;
871+ mmc_dev.type = 0;
872+ mmc_dev.blksz = mmcinfo.block_len;
873+ mmc_dev.lba = mmcinfo.block_num;
874+ mmc_dev.removable = 0;
875+
876+ printf("%s Detected: %lu blocks of %lu bytes\n",
877+ sd2_0 == 1 ? "SDHC" : "SD",
878+ mmc_dev.lba,
879+ mmc_dev.blksz);
880+
881+ /* Fix the clock rate */
882+ rate = mmc_tran_speed(mmcinfo.csd.tran_speed);
883+ if (rate < MMC_CLOCK_SLOW)
884+ rate = MMC_CLOCK_SLOW;
885+ if ((mmcinfo.sd == 0) && (rate > MMC_CLOCK_FAST))
886+ rate = MMC_CLOCK_FAST;
887+ if ((mmcinfo.sd) && (rate > SD_CLOCK_FAST))
888+ rate = SD_CLOCK_FAST;
889+
890+ debug("%s: block_len=%d block_num=%d rate=%d\n",
891+ __func__, mmcinfo.block_len, mmcinfo.block_num, rate);
892+
893+ jz_mmc_set_clock(mmcinfo.sd, rate);
894+}
895+
896+/*
897+ * State machine routines to initialize card(s)
898+ */
899+
900+/*
901+ CIM_SINGLE_CARD_ACQ (frequency at 400 kHz)
902+ --- Must enter from GO_IDLE_STATE ---
903+ 1. SD_SEND_OP_COND (SD Card) [CMD55] + [CMD41]
904+ 2. SEND_OP_COND (Full Range) [CMD1] {optional}
905+ 3. SEND_OP_COND (Set Range ) [CMD1]
906+ If busy, delay and repeat step 2
907+ 4. ALL_SEND_CID [CMD2]
908+ If timeout, set an error (no cards found)
909+ 5. SET_RELATIVE_ADDR [CMD3]
910+ 6. SEND_CSD [CMD9]
911+ 7. SET_DSR [CMD4] Only call this if (csd.dsr_imp).
912+ 8. Set clock frequency (check available in csd.tran_speed)
913+ */
914+
915+#define MMC_INIT_DOING 0
916+#define MMC_INIT_PASSED 1
917+#define MMC_INIT_FAILED 2
918+
919+static int mmc_init_card_state(struct mmc_request *request)
920+{
921+ struct mmc_response_r1 r1;
922+ struct mmc_response_r3 r3;
923+ int retval;
924+ int ocr = 0x40300000;
925+ int limit_41 = 0;
926+
927+ switch (request->cmd) {
928+ case MMC_CMD_GO_IDLE_STATE: /* No response to parse */
929+ if (mmcinfo.sd)
930+ mmc_simple_cmd(request, 8, 0x1aa, RESPONSE_R1);
931+ else
932+ mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
933+ break;
934+
935+ case 8:
936+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
937+ mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1);
938+ break;
939+
940+ case MMC_CMD_APP_CMD:
941+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
942+ if (retval & (limit_41 < 100)) {
943+ debug("%s: unable to MMC_APP_CMD error=%d (%s)\n",
944+ __func__, retval, mmc_result_to_string(retval));
945+ limit_41++;
946+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3);
947+ } else if (limit_41 < 100) {
948+ limit_41++;
949+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, ocr, RESPONSE_R3);
950+ } else{
951+ /* reset the card to idle*/
952+ mmc_simple_cmd(request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE);
953+ mmcinfo.sd = 0;
954+ }
955+ break;
956+
957+ case SD_CMD_APP_SEND_OP_COND:
958+ retval = mmc_unpack_r3(request, &r3);
959+ if (retval) {
960+ debug("%s: try MMC card\n", __func__);
961+ mmc_simple_cmd(request, SD_CMD_APP_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
962+ break;
963+ }
964+
965+ debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr);
966+
967+ if(!(r3.ocr & MMC_CARD_BUSY || ocr == 0)){
968+ udelay(50000);
969+ mmc_simple_cmd(request, MMC_CMD_APP_CMD, 0, RESPONSE_R1);
970+ } else {
971+ mmcinfo.sd = 1; /* SD Card ready */
972+ mmcinfo.state = CARD_STATE_READY;
973+ mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID);
974+ }
975+ break;
976+
977+ case MMC_CMD_SEND_OP_COND:
978+ retval = mmc_unpack_r3(request, &r3);
979+ if (retval) {
980+ debug("%s: failed SEND_OP_COND error=%d (%s)\n",
981+ __func__, retval, mmc_result_to_string(retval));
982+ return MMC_INIT_FAILED;
983+ }
984+
985+ debug("%s: read ocr value = 0x%08x\n", __func__, r3.ocr);
986+ if (!(r3.ocr & MMC_CARD_BUSY)) {
987+ mmc_simple_cmd(request, MMC_CMD_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3);
988+ } else {
989+ mmcinfo.sd = 0; /* MMC Card ready */
990+ mmcinfo.state = CARD_STATE_READY;
991+ mmc_simple_cmd(request, MMC_CMD_ALL_SEND_CID, 0, RESPONSE_R2_CID);
992+ }
993+ break;
994+
995+ case MMC_CMD_ALL_SEND_CID:
996+ retval = mmc_unpack_cid( request, &mmcinfo.cid );
997+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
998+ if ( retval && (retval != MMC_ERROR_CRC)) {
999+ debug("mmc_init_card_state: unable to ALL_SEND_CID error=%d (%s)\n",
1000+ retval, mmc_result_to_string(retval));
1001+ return MMC_INIT_FAILED;
1002+ }
1003+ mmcinfo.state = CARD_STATE_IDENT;
1004+ if(mmcinfo.sd)
1005+ mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, 0, RESPONSE_R6);
1006+ else
1007+ mmc_simple_cmd(request, MMC_CMD_SET_RELATIVE_ADDR, ID_TO_RCA(mmcinfo.id) << 16, RESPONSE_R1);
1008+ break;
1009+
1010+ case MMC_CMD_SET_RELATIVE_ADDR:
1011+ if (mmcinfo.sd) {
1012+ retval = mmc_unpack_r6(request, &r1, mmcinfo.state, &mmcinfo.rca);
1013+ mmcinfo.rca = mmcinfo.rca << 16;
1014+ debug("%s: Get RCA from SD: 0x%04x Status: %x\n",
1015+ __func__, mmcinfo.rca, r1.status);
1016+ } else {
1017+ retval = mmc_unpack_r1(request,&r1,mmcinfo.state);
1018+ mmcinfo.rca = ID_TO_RCA(mmcinfo.id) << 16;
1019+ }
1020+ if (retval) {
1021+ debug("%s: unable to SET_RELATIVE_ADDR error=%d (%s)\n",
1022+ __func__, retval, mmc_result_to_string(retval));
1023+ return MMC_INIT_FAILED;
1024+ }
1025+
1026+ mmcinfo.state = CARD_STATE_STBY;
1027+ mmc_simple_cmd(request, MMC_CMD_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD);
1028+
1029+ break;
1030+
1031+ case MMC_CMD_SEND_CSD:
1032+ retval = mmc_unpack_csd(request, &mmcinfo.csd);
1033+ mmc_ready = 1;
1034+ /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */
1035+ if (retval && (retval != MMC_ERROR_CRC)) {
1036+ debug("%s: unable to SEND_CSD error=%d (%s)\n",
1037+ __func__, retval, mmc_result_to_string(retval));
1038+ return MMC_INIT_FAILED;
1039+ }
1040+ if (mmcinfo.csd.dsr_imp) {
1041+ debug("%s: driver doesn't support setting DSR\n", __func__);
1042+ }
1043+ mmc_configure_card();
1044+ return MMC_INIT_PASSED;
1045+
1046+ default:
1047+ debug("%s: error! Illegal last cmd %d\n", __func__, request->cmd);
1048+ return MMC_INIT_FAILED;
1049+ }
1050+
1051+ return MMC_INIT_DOING;
1052+}
1053+
1054+int mmc_init_card(void)
1055+{
1056+ struct mmc_request request;
1057+ int retval;
1058+
1059+ mmc_simple_cmd(&request, MMC_CIM_RESET, 0, RESPONSE_NONE); /* reset card */
1060+ mmc_simple_cmd(&request, MMC_CMD_GO_IDLE_STATE, 0, RESPONSE_NONE);
1061+ mmcinfo.sd = 1; /* assuming a SD card */
1062+
1063+ while ((retval = mmc_init_card_state(&request)) == MMC_INIT_DOING)
1064+ ;
1065+
1066+ if (retval == MMC_INIT_PASSED)
1067+ return MMC_NO_ERROR;
1068+ else
1069+ return MMC_NO_RESPONSE;
1070+}
1071+
1072+int mmc_legacy_init(int verbose)
1073+{
1074+ if (!__msc_card_detected())
1075+ return 1;
1076+
1077+ /* Step-1: init GPIO */
1078+ __gpio_as_msc();
1079+ __msc_init_io();
1080+
1081+ /* Step-2: turn on power of card */
1082+#if !defined(CONFIG_SAKC)
1083+ __msc_enable_power();
1084+#endif
1085+
1086+ /* Step-3: Reset MSC Controller. */
1087+ __msc_reset();
1088+
1089+ /* Step-3: mask all IRQs. */
1090+ MMC_IRQ_MASK();
1091+
1092+ /* Step-4: stop MMC/SD clock */
1093+ jz_mmc_stop_clock();
1094+ mmc_init_card();
1095+ mmc_select_card();
1096+
1097+ mmc_dev.block_read = mmc_bread;
1098+ fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
1099+
1100+ return 0;
1101+}
1102+
1103+/*
1104+ * Debugging functions
1105+ */
1106+static char * mmc_result_strings[] = {
1107+ "NO_RESPONSE",
1108+ "NO_ERROR",
1109+ "ERROR_OUT_OF_RANGE",
1110+ "ERROR_ADDRESS",
1111+ "ERROR_BLOCK_LEN",
1112+ "ERROR_ERASE_SEQ",
1113+ "ERROR_ERASE_PARAM",
1114+ "ERROR_WP_VIOLATION",
1115+ "ERROR_CARD_IS_LOCKED",
1116+ "ERROR_LOCK_UNLOCK_FAILED",
1117+ "ERROR_COM_CRC",
1118+ "ERROR_ILLEGAL_COMMAND",
1119+ "ERROR_CARD_ECC_FAILED",
1120+ "ERROR_CC",
1121+ "ERROR_GENERAL",
1122+ "ERROR_UNDERRUN",
1123+ "ERROR_OVERRUN",
1124+ "ERROR_CID_CSD_OVERWRITE",
1125+ "ERROR_STATE_MISMATCH",
1126+ "ERROR_HEADER_MISMATCH",
1127+ "ERROR_TIMEOUT",
1128+ "ERROR_CRC",
1129+ "ERROR_DRIVER_FAILURE",
1130+};
1131+
1132+char * mmc_result_to_string(int i)
1133+{
1134+ return mmc_result_strings[i+1];
1135+}
1136+
1137+static char * card_state_strings[] = {
1138+ "empty",
1139+ "idle",
1140+ "ready",
1141+ "ident",
1142+ "stby",
1143+ "tran",
1144+ "data",
1145+ "rcv",
1146+ "prg",
1147+ "dis",
1148+};
1149+
1150+static inline char * card_state_to_string(int i)
1151+{
1152+ return card_state_strings[i+1];
1153+}
1154+
1155+/*
1156+ * Utility functions
1157+ */
1158+
1159+#define PARSE_U32(_buf,_index) \
1160+ (((u32)_buf[_index]) << 24) | (((u32)_buf[_index+1]) << 16) | \
1161+ (((u32)_buf[_index+2]) << 8) | ((u32)_buf[_index+3]);
1162+
1163+#define PARSE_U16(_buf,_index) \
1164+ (((u16)_buf[_index]) << 8) | ((u16)_buf[_index+1]);
1165+
1166+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd)
1167+{
1168+ u8 *buf = request->response;
1169+ int num = 0;
1170+
1171+ if (request->result)
1172+ return request->result;
1173+
1174+ if (buf[0] != 0x3f)
1175+ return MMC_ERROR_HEADER_MISMATCH;
1176+
1177+ csd->csd_structure = (buf[1] & 0xc0) >> 6;
1178+ if (csd->csd_structure)
1179+ sd2_0 = 1;
1180+ else
1181+ sd2_0 = 0;
1182+
1183+ switch (csd->csd_structure) {
1184+ case 0 :/* Version 1.01-1.10
1185+ * Version 2.00/Standard Capacity */
1186+ csd->taac = buf[2];
1187+ csd->nsac = buf[3];
1188+ csd->tran_speed = buf[4];
1189+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
1190+ csd->read_bl_len = buf[6] & 0x0f;
1191+ /* for support 2GB card*/
1192+ if (csd->read_bl_len >= 10)
1193+ {
1194+ num = csd->read_bl_len - 9;
1195+ csd->read_bl_len = 9;
1196+ }
1197+
1198+ csd->read_bl_partial = (buf[7] & 0x80) ? 1 : 0;
1199+ csd->write_blk_misalign = (buf[7] & 0x40) ? 1 : 0;
1200+ csd->read_blk_misalign = (buf[7] & 0x20) ? 1 : 0;
1201+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
1202+ csd->c_size = ((((u16)buf[7]) & 0x03) << 10) | (((u16)buf[8]) << 2) | (((u16)buf[9]) & 0xc0) >> 6;
1203+
1204+ if (num)
1205+ csd->c_size = csd->c_size << num;
1206+
1207+
1208+ csd->vdd_r_curr_min = (buf[9] & 0x38) >> 3;
1209+ csd->vdd_r_curr_max = buf[9] & 0x07;
1210+ csd->vdd_w_curr_min = (buf[10] & 0xe0) >> 5;
1211+ csd->vdd_w_curr_max = (buf[10] & 0x1c) >> 2;
1212+ csd->c_size_mult = ((buf[10] & 0x03) << 1) | ((buf[11] & 0x80) >> 7);
1213+ csd->sector_size = (buf[11] & 0x7c) >> 2;
1214+ csd->erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
1215+ csd->wp_grp_size = buf[12] & 0x1f;
1216+ csd->wp_grp_enable = (buf[13] & 0x80) ? 1 : 0;
1217+ csd->default_ecc = (buf[13] & 0x60) >> 5;
1218+ csd->r2w_factor = (buf[13] & 0x1c) >> 2;
1219+ csd->write_bl_len = ((buf[13] & 0x03) << 2) | ((buf[14] & 0xc0) >> 6);
1220+ if (csd->write_bl_len >= 10)
1221+ csd->write_bl_len = 9;
1222+
1223+ csd->write_bl_partial = (buf[14] & 0x20) ? 1 : 0;
1224+ csd->file_format_grp = (buf[15] & 0x80) ? 1 : 0;
1225+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
1226+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
1227+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
1228+ csd->file_format = (buf[15] & 0x0c) >> 2;
1229+ csd->ecc = buf[15] & 0x03;
1230+ break;
1231+ case 1 : /* Version 2.00/High Capacity */
1232+ csd->taac = 0;
1233+ csd->nsac = 0;
1234+ csd->tran_speed = buf[4];
1235+ csd->ccc = (((u16)buf[5]) << 4) | ((buf[6] & 0xf0) >> 4);
1236+
1237+ csd->read_bl_len = 9;
1238+ csd->read_bl_partial = 0;
1239+ csd->write_blk_misalign = 0;
1240+ csd->read_blk_misalign = 0;
1241+ csd->dsr_imp = (buf[7] & 0x10) ? 1 : 0;
1242+ csd->c_size = ((((u16)buf[8]) & 0x3f) << 16) | (((u16)buf[9]) << 8) | ((u16)buf[10]) ;
1243+ csd->sector_size = 0x7f;
1244+ csd->erase_grp_size = 0;
1245+ csd->wp_grp_size = 0;
1246+ csd->wp_grp_enable = 0;
1247+ csd->default_ecc = (buf[13] & 0x60) >> 5;
1248+ csd->r2w_factor = 4;/* Unused */
1249+ csd->write_bl_len = 9;
1250+
1251+ csd->write_bl_partial = 0;
1252+ csd->file_format_grp = 0;
1253+ csd->copy = (buf[15] & 0x40) ? 1 : 0;
1254+ csd->perm_write_protect = (buf[15] & 0x20) ? 1 : 0;
1255+ csd->tmp_write_protect = (buf[15] & 0x10) ? 1 : 0;
1256+ csd->file_format = 0;
1257+ csd->ecc = buf[15] & 0x03;
1258+ }
1259+
1260+ return 0;
1261+}
1262+
1263+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state)
1264+{
1265+ u8 *buf = request->response;
1266+
1267+ if (request->result)
1268+ return request->result;
1269+
1270+ r1->cmd = buf[0];
1271+ r1->status = PARSE_U32(buf,1);
1272+
1273+ debug("mmc_unpack_r1: cmd=%d status=%08x\n", r1->cmd, r1->status);
1274+
1275+ if (R1_STATUS(r1->status)) {
1276+ if (r1->status & R1_OUT_OF_RANGE) return MMC_ERROR_OUT_OF_RANGE;
1277+ if (r1->status & R1_ADDRESS_ERROR) return MMC_ERROR_ADDRESS;
1278+ if (r1->status & R1_BLOCK_LEN_ERROR) return MMC_ERROR_BLOCK_LEN;
1279+ if (r1->status & R1_ERASE_SEQ_ERROR) return MMC_ERROR_ERASE_SEQ;
1280+ if (r1->status & R1_ERASE_PARAM) return MMC_ERROR_ERASE_PARAM;
1281+ if (r1->status & R1_WP_VIOLATION) return MMC_ERROR_WP_VIOLATION;
1282+ /*if (r1->status & R1_CARD_IS_LOCKED) return MMC_ERROR_CARD_IS_LOCKED; */
1283+ if (r1->status & R1_LOCK_UNLOCK_FAILED) return MMC_ERROR_LOCK_UNLOCK_FAILED;
1284+ if (r1->status & R1_COM_CRC_ERROR) return MMC_ERROR_COM_CRC;
1285+ if (r1->status & R1_ILLEGAL_COMMAND) return MMC_ERROR_ILLEGAL_COMMAND;
1286+ if (r1->status & R1_CARD_ECC_FAILED) return MMC_ERROR_CARD_ECC_FAILED;
1287+ if (r1->status & R1_CC_ERROR) return MMC_ERROR_CC;
1288+ if (r1->status & R1_ERROR) return MMC_ERROR_GENERAL;
1289+ if (r1->status & R1_UNDERRUN) return MMC_ERROR_UNDERRUN;
1290+ if (r1->status & R1_OVERRUN) return MMC_ERROR_OVERRUN;
1291+ if (r1->status & R1_CID_CSD_OVERWRITE) return MMC_ERROR_CID_CSD_OVERWRITE;
1292+ }
1293+
1294+ if (buf[0] != request->cmd)
1295+ return MMC_ERROR_HEADER_MISMATCH;
1296+
1297+ /* This should be last - it's the least dangerous error */
1298+
1299+ return 0;
1300+}
1301+
1302+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr)
1303+{
1304+ u8 *buf = request->response;
1305+ if (request->result)
1306+ return request->result;
1307+
1308+ *scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */
1309+ return mmc_unpack_r1(request, r1, state);
1310+
1311+}
1312+
1313+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca)
1314+{
1315+ u8 *buf = request->response;
1316+
1317+ if (request->result)
1318+ return request->result;
1319+
1320+ *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */
1321+
1322+ *(buf+1) = 0;
1323+ *(buf+2) = 0;
1324+
1325+ return mmc_unpack_r1(request, r1, state);
1326+}
1327+
1328+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid)
1329+{
1330+ int i;
1331+ u8 *buf = request->response;
1332+
1333+ if (request->result)
1334+ return request->result;
1335+
1336+ cid->mid = buf[1];
1337+ cid->oid = PARSE_U16(buf,2);
1338+ for (i = 0 ; i < 5 ; i++)
1339+ cid->pnm[i] = buf[4+i];
1340+ cid->pnm[6] = 0;
1341+ cid->prv = buf[10];
1342+ cid->psn = PARSE_U32(buf,10);
1343+ cid->mdt = buf[15];
1344+
1345+ printf("Man %02x OEM 0x%04x \"%s\" %d.%d 0x%08x "
1346+ "Date %02u/%04u\n",
1347+ cid->mid,
1348+ cid->oid,
1349+ cid->pnm,
1350+ cid->prv >> 4,
1351+ cid->prv & 0xf,
1352+ cid->psn,
1353+ cid->mdt & 0xf,
1354+ (cid->mdt >> 4) + 2000);
1355+
1356+ if (buf[0] != 0x3f)
1357+ return MMC_ERROR_HEADER_MISMATCH;
1358+ return 0;
1359+}
1360+
1361+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3)
1362+{
1363+ u8 *buf = request->response;
1364+
1365+ if (request->result)
1366+ return request->result;
1367+
1368+ r3->ocr = PARSE_U32(buf,1);
1369+ debug("mmc_unpack_r3: ocr=%08x\n", r3->ocr);
1370+
1371+ if (buf[0] != 0x3f) return MMC_ERROR_HEADER_MISMATCH;
1372+ return 0;
1373+}
1374+
1375+#define KBPS 1
1376+#define MBPS 1000
1377+
1378+static u32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };
1379+static u32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000,
1380+ 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };
1381+
1382+u32 mmc_tran_speed(u8 ts)
1383+{
1384+ u32 rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];
1385+
1386+ if (rate <= 0) {
1387+ debug("%s: error - unrecognized speed 0x%02x\n", __func__, ts);
1388+ return 1;
1389+ }
1390+
1391+ return rate;
1392+}
1393+
1394+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
1395+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer)
1396+{
1397+ request->cmd = cmd;
1398+ request->arg = arg;
1399+ request->rtype = rtype;
1400+ request->nob = nob;
1401+ request->block_len = block_len;
1402+ request->buffer = buffer;
1403+ request->cnt = nob * block_len;
1404+
1405+ jz_mmc_exec_cmd(request);
1406+}
1407diff --git a/drivers/mmc/jz_mmc.h b/drivers/mmc/jz_mmc.h
1408new file mode 100644
1409index 0000000..936c514
1410--- /dev/null
1411@@ -0,0 +1,176 @@
1412+/*
1413+ * linux/drivers/mmc/jz_mmc.h
1414+ *
1415+ * Author: Vladimir Shebordaev, Igor Oblakov
1416+ * Copyright: MontaVista Software Inc.
1417+ *
1418+ * $Id: jz_mmc.h,v 1.3 2007-06-15 08:04:20 jlwei Exp $
1419+ *
1420+ * This program is free software; you can redistribute it and/or modify
1421+ * it under the terms of the GNU General Public License version 2 as
1422+ * published by the Free Software Foundation.
1423+ */
1424+#ifndef __MMC_JZMMC_H__
1425+#define __MMC_JZMMC_H__
1426+
1427+#define ID_TO_RCA(x) ((x)+1)
1428+#define MMC_OCR_ARG 0x00ff8000 /* Argument of OCR */
1429+
1430+/* Standard MMC/SD clock speeds */
1431+#define MMC_CLOCK_SLOW 400000 /* 400 kHz for initial setup */
1432+#define MMC_CLOCK_FAST 20000000 /* 20 MHz for maximum for normal operation */
1433+#define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */
1434+
1435+/* Use negative numbers to disambiguate */
1436+#define MMC_CIM_RESET -1
1437+#define SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
1438+
1439+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
1440+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
1441+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
1442+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
1443+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
1444+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
1445+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
1446+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
1447+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
1448+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
1449+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
1450+#define R1_CC_ERROR (1 << 20) /* erx, c */
1451+#define R1_ERROR (1 << 19) /* erx, c */
1452+#define R1_UNDERRUN (1 << 18) /* ex, c */
1453+#define R1_OVERRUN (1 << 17) /* ex, c */
1454+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
1455+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
1456+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
1457+#define R1_ERASE_RESET (1 << 13) /* sr, c */
1458+#define R1_STATUS(x) (x & 0xFFFFE000)
1459+
1460+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
1461+
1462+#define MMC_PROGRAM_CID 26 /* adtc R1 */
1463+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
1464+
1465+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
1466+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
1467+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
1468+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
1469+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
1470+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
1471+
1472+
1473+enum mmc_result_t {
1474+ MMC_NO_RESPONSE = -1,
1475+ MMC_NO_ERROR = 0,
1476+ MMC_ERROR_OUT_OF_RANGE,
1477+ MMC_ERROR_ADDRESS,
1478+ MMC_ERROR_BLOCK_LEN,
1479+ MMC_ERROR_ERASE_SEQ,
1480+ MMC_ERROR_ERASE_PARAM,
1481+ MMC_ERROR_WP_VIOLATION,
1482+ MMC_ERROR_CARD_IS_LOCKED,
1483+ MMC_ERROR_LOCK_UNLOCK_FAILED,
1484+ MMC_ERROR_COM_CRC,
1485+ MMC_ERROR_ILLEGAL_COMMAND,
1486+ MMC_ERROR_CARD_ECC_FAILED,
1487+ MMC_ERROR_CC,
1488+ MMC_ERROR_GENERAL,
1489+ MMC_ERROR_UNDERRUN,
1490+ MMC_ERROR_OVERRUN,
1491+ MMC_ERROR_CID_CSD_OVERWRITE,
1492+ MMC_ERROR_STATE_MISMATCH,
1493+ MMC_ERROR_HEADER_MISMATCH,
1494+ MMC_ERROR_TIMEOUT,
1495+ MMC_ERROR_CRC,
1496+ MMC_ERROR_DRIVER_FAILURE,
1497+};
1498+
1499+enum card_state {
1500+ CARD_STATE_EMPTY = -1,
1501+ CARD_STATE_IDLE = 0,
1502+ CARD_STATE_READY = 1,
1503+ CARD_STATE_IDENT = 2,
1504+ CARD_STATE_STBY = 3,
1505+ CARD_STATE_TRAN = 4,
1506+ CARD_STATE_DATA = 5,
1507+ CARD_STATE_RCV = 6,
1508+ CARD_STATE_PRG = 7,
1509+ CARD_STATE_DIS = 8,
1510+};
1511+
1512+enum mmc_rsp_t {
1513+ RESPONSE_NONE = 0,
1514+ RESPONSE_R1 = 1,
1515+ RESPONSE_R1B = 2,
1516+ RESPONSE_R2_CID = 3,
1517+ RESPONSE_R2_CSD = 4,
1518+ RESPONSE_R3 = 5,
1519+ RESPONSE_R4 = 6,
1520+ RESPONSE_R5 = 7,
1521+ RESPONSE_R6 = 8,
1522+};
1523+
1524+struct mmc_response_r1 {
1525+ u8 cmd;
1526+ u32 status;
1527+};
1528+
1529+struct mmc_response_r3 {
1530+ u32 ocr;
1531+};
1532+
1533+/* the information structure of MMC/SD Card */
1534+struct mmc_info {
1535+ int id; /* Card index */
1536+ int sd; /* MMC or SD card */
1537+ int rca; /* RCA */
1538+ u32 scr; /* SCR 63:32*/
1539+ int flags; /* Ejected, inserted */
1540+ enum card_state state; /* empty, ident, ready, whatever */
1541+
1542+ /* Card specific information */
1543+ struct mmc_cid cid;
1544+ struct mmc_csd csd;
1545+ u32 block_num;
1546+ u32 block_len;
1547+ u32 erase_unit;
1548+};
1549+
1550+struct mmc_info mmcinfo;
1551+
1552+struct mmc_request {
1553+ int index; /* Slot index - used for CS lines */
1554+ int cmd; /* Command to send */
1555+ u32 arg; /* Argument to send */
1556+ enum mmc_rsp_t rtype; /* Response type expected */
1557+
1558+ /* Data transfer (these may be modified at the low level) */
1559+ u16 nob; /* Number of blocks to transfer*/
1560+ u16 block_len; /* Block length */
1561+ u8 *buffer; /* Data buffer */
1562+ u32 cnt; /* Data length, for PIO */
1563+
1564+ /* Results */
1565+ u8 response[18]; /* Buffer to store response - CRC is optional */
1566+ enum mmc_result_t result;
1567+};
1568+
1569+char * mmc_result_to_string(int);
1570+int mmc_unpack_csd(struct mmc_request *request, struct mmc_csd *csd);
1571+int mmc_unpack_r1(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state);
1572+int mmc_unpack_r6(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, int *rca);
1573+int mmc_unpack_scr(struct mmc_request *request, struct mmc_response_r1 *r1, enum card_state state, u32 *scr);
1574+int mmc_unpack_cid(struct mmc_request *request, struct mmc_cid *cid);
1575+int mmc_unpack_r3(struct mmc_request *request, struct mmc_response_r3 *r3);
1576+
1577+void mmc_send_cmd(struct mmc_request *request, int cmd, u32 arg,
1578+ u16 nob, u16 block_len, enum mmc_rsp_t rtype, u8 *buffer);
1579+u32 mmc_tran_speed(u8 ts);
1580+void jz_mmc_set_clock(int sd, u32 rate);
1581+
1582+static inline void mmc_simple_cmd(struct mmc_request *request, int cmd, u32 arg, enum mmc_rsp_t rtype)
1583+{
1584+ mmc_send_cmd( request, cmd, arg, 0, 0, rtype, 0);
1585+}
1586+
1587+#endif /* __MMC_JZMMC_H__ */
1588diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
1589index 7bff444..7b33be0 100644
1590--- a/include/configs/qi_lb60.h
1591@@ -31,6 +31,15 @@
1592 /*
1593  * Miscellaneous configurable options
1594  */
1595+#define CONFIG_JZ4740_MMC
1596+#define CONFIG_MMC 1
1597+#define CONFIG_FAT 1
1598+#define CONFIG_DOS_PARTITION 1
1599+#define CONFIG_CMD_MMC
1600+#define CONFIG_CMD_FAT
1601+#define CONFIG_CMD_EXT2
1602+
1603+
1604 #define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
1605 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000
1606 #define CONFIG_SYS_LOAD_ADDR 0x80600000
1607diff --git a/include/mmc.h b/include/mmc.h
1608index a13e2bd..3c4761c 100644
1609--- a/include/mmc.h
1610@@ -283,4 +283,44 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
1611 int mmc_legacy_init(int verbose);
1612 #endif
1613
1614+struct mmc_csd
1615+{
1616+ u8 csd_structure:2,
1617+ spec_vers:4,
1618+ rsvd1:2;
1619+ u8 taac;
1620+ u8 nsac;
1621+ u8 tran_speed;
1622+ u16 ccc:12,
1623+ read_bl_len:4;
1624+ u32 c_size:22;
1625+ u64 read_bl_partial:1,
1626+ write_blk_misalign:1,
1627+ read_blk_misalign:1,
1628+ dsr_imp:1,
1629+ rsvd2:2,
1630+ vdd_r_curr_min:3,
1631+ vdd_r_curr_max:3,
1632+ vdd_w_curr_min:3,
1633+ vdd_w_curr_max:3,
1634+ c_size_mult:3,
1635+ sector_size:5,
1636+ erase_grp_size:5,
1637+ wp_grp_size:5,
1638+ wp_grp_enable:1,
1639+ default_ecc:2,
1640+ r2w_factor:3,
1641+ write_bl_len:4,
1642+ write_bl_partial:1,
1643+ rsvd3:5;
1644+ u8 file_format_grp:1,
1645+ copy:1,
1646+ perm_write_protect:1,
1647+ tmp_write_protect:1,
1648+ file_format:2,
1649+ ecc:2;
1650+ u8 crc:7;
1651+ u8 one:1;
1652+};
1653+
1654 #endif /* _MMC_H_ */
1655--
16561.7.9.5
1657
package/uboot-xburst/patches/0003-add-more-boot-options-F1-F2-F3-F4-M-S.patch
1From 4662aa16d93f7ffd933125db6231868be544ebd5 Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Wed, 10 Oct 2012 18:39:55 +0800
4Subject: [PATCH 3/5] add more boot options(F1/F2/F3/F4/M/S)
5
6 arch/mips/include/asm/global_data.h | 3 +++
7 arch/mips/lib/bootm.c | 17 ++++++++++++++++-
8 board/qi/qi_lb60/qi_lb60.c | 26 +++++++++++++++++++++++---
9 common/main.c | 21 +++++++++++++++++++--
10 include/configs/qi_lb60.h | 32 ++++++++++++++++++++++++++++++++
11 5 files changed, 93 insertions(+), 6 deletions(-)
12
13diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
14index 6e2cdc7..cd03d7e 100644
15+++ b/arch/mips/include/asm/global_data.h
16@@ -59,6 +59,9 @@ typedef struct global_data {
17     unsigned long env_valid; /* Checksum of Environment valid? */
18     void **jt; /* jump table */
19     char env_buf[32]; /* buffer for getenv() before reloc. */
20+#if defined(CONFIG_NANONOTE)
21+ unsigned long boot_option;
22+#endif
23 } gd_t;
24
25 #include <asm-generic/global_data_flags.h>
26diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
27index 608c1a7..e00416b 100644
28+++ b/arch/mips/lib/bootm.c
29@@ -47,10 +47,25 @@ int do_bootm_linux(int flag, int argc, char * const argv[],
30             bootm_headers_t *images)
31 {
32     void (*theKernel) (int, char **, char **, int *);
33- char *commandline = getenv("bootargs");
34+ char *commandline;
35     char env_buf[12];
36     char *cp;
37
38+#if defined(CONFIG_NANONOTE)
39+ if (gd->boot_option & BOOT_FROM_MEMCARD)
40+ commandline = getenv ("bootargsfromsd");
41+ else if (gd->boot_option & BOOT_WITH_F1)
42+ commandline = getenv ("bootargsf1");
43+ else if (gd->boot_option & BOOT_WITH_F2)
44+ commandline = getenv ("bootargsf2");
45+ else if (gd->boot_option & BOOT_WITH_F3)
46+ commandline = getenv ("bootargsf3");
47+ else if (gd->boot_option & BOOT_WITH_F4)
48+ commandline = getenv ("bootargsf4");
49+ else
50+#endif
51+ commandline = getenv ("bootargs");
52+
53     if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
54         return 1;
55
56diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
57index 68da069..14a928e 100644
58+++ b/board/qi/qi_lb60/qi_lb60.c
59@@ -15,7 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
60
61 static void gpio_init(void)
62 {
63- unsigned int i;
64+ unsigned int i, j;
65
66     /* Initialize NAND Flash Pins */
67     __gpio_as_nand();
68@@ -42,14 +42,34 @@ static void gpio_init(void)
69
70     if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
71         printf("[S] pressed, enable UART0\n");
72+ gd->boot_option |= BOOT_WITH_ENABLE_UART;
73         __gpio_as_uart0();
74     } else {
75         __gpio_as_input(GPIO_KEYIN_8);
76         __gpio_enable_pull(GPIO_KEYIN_8);
77     }
78
79- /* enable the TP4, TP5 as UART0 */
80- __gpio_jtag_to_uart0();
81+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 3) == 0) {
82+ printf("[M] pressed, boot from memory card\n");
83+ gd->boot_option |= BOOT_FROM_MEMCARD;
84+ __gpio_jtag_to_uart0();
85+ }
86+
87+ for (j = 0; j < 4; j++) {
88+ for (i = 0; i < 4; i++)
89+ __gpio_set_pin(GPIO_KEYOUT_BASE + i);
90+
91+ __gpio_clear_pin(GPIO_KEYOUT_BASE + j);
92+
93+ if (__gpio_get_pin(GPIO_KEYIN_BASE) == 0) {
94+ printf("[F%d] pressed", (j + 1));
95+ gd->boot_option |= (1 << (j + 2));
96+ /* BOOT_WITH_F1 (1 << 2) */
97+ /* BOOT_WITH_F2 (1 << 3) */
98+ /* BOOT_WITH_F3 (1 << 4) */
99+ /* BOOT_WITH_F4 (1 << 5) */
100+ }
101+ }
102
103     __gpio_as_output(GPIO_AUDIO_POP);
104     __gpio_set_pin(GPIO_AUDIO_POP);
105diff --git a/common/main.c b/common/main.c
106index 9507cec..dbfb7ca 100644
107+++ b/common/main.c
108@@ -355,7 +355,11 @@ void main_loop (void)
109 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
110     s = getenv ("bootdelay");
111     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
112-
113+#if defined(CONFIG_NANONOTE)
114+ DECLARE_GLOBAL_DATA_PTR;
115+ if (gd->boot_option & BOOT_WITH_ENABLE_UART)
116+ bootdelay = 3;
117+# endif
118     debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
119
120 #if defined(CONFIG_MENU_SHOW)
121@@ -379,7 +383,20 @@ void main_loop (void)
122     }
123     else
124 #endif /* CONFIG_BOOTCOUNT_LIMIT */
125- s = getenv ("bootcmd");
126+#if defined(CONFIG_NANONOTE)
127+ if (gd->boot_option & BOOT_FROM_MEMCARD)
128+ s = getenv ("bootcmdfromsd");
129+ else if (gd->boot_option & BOOT_WITH_F1)
130+ s = getenv ("bootcmdf1");
131+ else if (gd->boot_option & BOOT_WITH_F2)
132+ s = getenv ("bootcmdf2");
133+ else if (gd->boot_option & BOOT_WITH_F3)
134+ s = getenv ("bootcmdf3");
135+ else if (gd->boot_option & BOOT_WITH_F4)
136+ s = getenv ("bootcmdf4");
137+ else
138+#endif
139+ s = getenv ("bootcmd");
140
141     debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
142
143diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
144index 2690e17..e824d48 100644
145+++ b/include/configs/qi_lb60.h
146@@ -31,6 +31,7 @@
147 /*
148  * Miscellaneous configurable options
149  */
150+#define CONFIG_NANONOTE
151 #define CONFIG_JZ4740_MMC
152 #define CONFIG_MMC 1
153 #define CONFIG_FAT 1
154@@ -39,6 +40,37 @@
155 #define CONFIG_CMD_FAT
156 #define CONFIG_CMD_EXT2
157
158+#define CONFIG_CMD_UBIFS
159+#define CONFIG_CMD_UBI
160+#define CONFIG_MTD_PARTITIONS
161+#define CONFIG_MTD_DEVICE
162+#define CONFIG_CMD_MTDPARTS
163+#define CONFIG_CMD_UBI
164+#define CONFIG_CMD_UBIFS
165+#define CONFIG_LZO
166+#define CONFIG_RBTREE
167+
168+#define MTDIDS_DEFAULT "nand0=jz4740-nand"
169+#define MTDPARTS_DEFAULT "mtdparts=jz4740-nand:4M@0(uboot)ro,4M@4M(kernel)ro,512M@8M(rootfs)ro,-(data)ro"
170+
171+#define BOOT_FROM_MEMCARD 1
172+#define BOOT_WITH_ENABLE_UART (1 << 1) /* Vaule for global_data.h gd->boot_option */
173+#define BOOT_WITH_F1 (1 << 2)
174+#define BOOT_WITH_F2 (1 << 3)
175+#define BOOT_WITH_F3 (1 << 4)
176+#define BOOT_WITH_F4 (1 << 5)
177+
178+#define CONFIG_EXTRA_ENV_SETTINGS \
179+ "bootcmdfromsd=mmc init; ext2load mmc 0 0x80600000 /boot/uImage; bootm;\0" \
180+ "bootargsfromsd=mem=32M console=tty0 console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootwait\0" \
181+ "bootcmdf1=mmc init; ext2load mmc 0:1 0x80600000 /boot/uImage; bootm;\0" \
182+ "bootargsf1=mem=32M console=tty0 console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootwait\0" \
183+ "bootcmdf2=mmc init; ext2load mmc 0:2 0x80600000 /boot/uImage; bootm;\0" \
184+ "bootargsf2=mem=32M console=tty0 console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p2 rw rootwait\0" \
185+ "bootcmdf3=mmc init; ext2load mmc 0:3 0x80600000 /boot/uImage; bootm;\0" \
186+ "bootargsf3=mem=32M console=tty0 console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p3 rw rootwait\0" \
187+ "bootcmdf4=mtdparts default;ubi part rootfs;ubifsmount rootfs;ubifsload 0x80600000 /boot/uImage; bootm;\0" \
188+ "bootargsf4=mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
189
190 #define CONFIG_SYS_SDRAM_BASE 0x80000000 /* Cached addr */
191 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000
1921.7.9.5
193
package/uboot-xburst/patches/0004-add-more-boot-options-F1-F2-F3-F4-M-S.patch
1From c52b6168979d03fc31205444c3278c537787472a Mon Sep 17 00:00:00 2001
2From: Xiangfu <xiangfu@openmobilefree.net>
3Date: Wed, 10 Oct 2012 18:39:55 +0800
4Subject: [PATCH 4/6] add more boot options(F1/F2/F3/F4/M/S)
5
6---
7 arch/mips/include/asm/global_data.h | 3 +++
8 arch/mips/lib/bootm.c | 17 ++++++++++++++++-
9 board/qi/qi_lb60/qi_lb60.c | 26 +++++++++++++++++++++++---
10 common/main.c | 21 +++++++++++++++++++--
11 include/configs/qi_lb60.h | 32 ++++++++++++++++++++++++++++++++
12 5 files changed, 93 insertions(+), 6 deletions(-)
13
14diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
15index 6e2cdc7..cd03d7e 100644
16--- a/arch/mips/include/asm/global_data.h
17@@ -59,6 +59,9 @@ typedef struct global_data {
18     unsigned long env_valid; /* Checksum of Environment valid? */
19     void **jt; /* jump table */
20     char env_buf[32]; /* buffer for getenv() before reloc. */
21+#if defined(CONFIG_NANONOTE)
22+ unsigned long boot_option;
23+#endif
24 } gd_t;
25
26 #include <asm-generic/global_data_flags.h>
27diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
28index 608c1a7..e00416b 100644
29--- a/arch/mips/lib/bootm.c
30@@ -47,10 +47,25 @@ int do_bootm_linux(int flag, int argc, char * const argv[],
31             bootm_headers_t *images)
32 {
33     void (*theKernel) (int, char **, char **, int *);
34- char *commandline = getenv("bootargs");
35+ char *commandline;
36     char env_buf[12];
37     char *cp;
38
39+#if defined(CONFIG_NANONOTE)
40+ if (gd->boot_option & BOOT_FROM_MEMCARD)
41+ commandline = getenv ("bootargsfromsd");
42+ else if (gd->boot_option & BOOT_WITH_F1)
43+ commandline = getenv ("bootargsf1");
44+ else if (gd->boot_option & BOOT_WITH_F2)
45+ commandline = getenv ("bootargsf2");
46+ else if (gd->boot_option & BOOT_WITH_F3)
47+ commandline = getenv ("bootargsf3");
48+ else if (gd->boot_option & BOOT_WITH_F4)
49+ commandline = getenv ("bootargsf4");
50+ else
51+#endif
52+ commandline = getenv ("bootargs");
53+
54     if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
55         return 1;
56
57diff --git a/board/qi/qi_lb60/qi_lb60.c b/board/qi/qi_lb60/qi_lb60.c
58index a2ba648..d622219 100644
59--- a/board/qi/qi_lb60/qi_lb60.c
60@@ -15,7 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
61
62 static void gpio_init(void)
63 {
64- unsigned int i;
65+ unsigned int i, j;
66
67     /* Initialize NAND Flash Pins */
68     __gpio_as_nand();
69@@ -42,14 +42,34 @@ static void gpio_init(void)
70
71     if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
72         printf("[S] pressed, enable UART0\n");
73+ gd->boot_option |= BOOT_WITH_ENABLE_UART;
74         __gpio_as_uart0();
75     } else {
76         __gpio_as_input(GPIO_KEYIN_8);
77         __gpio_enable_pull(GPIO_KEYIN_8);
78     }
79
80- /* enable the TP4, TP5 as UART0 */
81- __gpio_jtag_to_uart0();
82+ if (__gpio_get_pin(GPIO_KEYIN_BASE + 3) == 0) {
83+ printf("[M] pressed, boot from memory card\n");
84+ gd->boot_option |= BOOT_FROM_MEMCARD;
85+ __gpio_jtag_to_uart0();
86+ }
87+
88+ for (j = 0; j < 4; j++) {
89+ for (i = 0; i < 4; i++)
90+ __gpio_set_pin(GPIO_KEYOUT_BASE + i);
91+
92+ __gpio_clear_pin(GPIO_KEYOUT_BASE + j);
93+
94+ if (__gpio_get_pin(GPIO_KEYIN_BASE) == 0) {
95+ printf("[F%d] pressed", (j + 1));
96+ gd->boot_option |= (1 << (j + 2));
97+ /* BOOT_WITH_F1 (1 << 2) */
98+ /* BOOT_WITH_F2 (1 << 3) */
99+ /* BOOT_WITH_F3 (1 << 4) */
100+ /* BOOT_WITH_F4 (1 << 5) */
101+ }
102+ }
103
104     __gpio_as_output(GPIO_AUDIO_POP);
105     __gpio_set_pin(GPIO_AUDIO_POP);
106diff --git a/common/main.c b/common/main.c
107index 9507cec..dbfb7ca 100644
108--- a/common/main.c
109@@ -355,7 +355,11 @@ void main_loop (void)
110 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
111     s = getenv ("bootdelay");
112     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
113-
114+#if defined(CONFIG_NANONOTE)
115+ DECLARE_GLOBAL_DATA_PTR;
116+ if (gd->boot_option & BOOT_WITH_ENABLE_UART)
117+ bootdelay = 3;
118+# endif
119   &nbs