[U-Boot] [PATCH 6/6] S5PC100: Add onenand_ipl for SMDKC100 support

The SMDKC100 Board has 256MB onenand. So, It's bootable, if this patch is adapted thus the board use onenand_ipl.
Signed-off-by: HeungJun, Kim riverful.kim@samsung.com
---
This patch support onenand boot on SMDKC100 Board.
onenand_ipl/board/samsung/smdkc100/Makefile | 95 ++++++++++++++++++++ .../board/samsung/smdkc100/u-boot-onenand.lds | 53 +++++++++++ onenand_ipl/onenand_ipl.h | 11 +++ onenand_ipl/onenand_read.c | 18 ++++ 4 files changed, 177 insertions(+), 0 deletions(-) create mode 100644 onenand_ipl/board/samsung/smdkc100/Makefile create mode 100644 onenand_ipl/board/samsung/smdkc100/u-boot-onenand.lds
diff --git a/onenand_ipl/board/samsung/smdkc100/Makefile b/onenand_ipl/board/samsung/smdkc100/Makefile new file mode 100644 index 0000000..4301938 --- /dev/null +++ b/onenand_ipl/board/samsung/smdkc100/Makefile @@ -0,0 +1,95 @@ +# +# Samsung SMDKC100(S5PC100) board OneNAND IPL +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang mk7.kang@samsung.com +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# + +include $(TOPDIR)/config.mk +TEXT_BASE = 0xD0034000 +TEXT_BASE2K = 0xD0034800 +TEXT_BASE4K = 0xD0035000 + +LDSCRIPT= $(TOPDIR)/onenand_ipl/board/$(BOARDDIR)/u-boot-onenand.lds +LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) +AFLAGS += -DCONFIG_ONENAND_IPL -g +CFLAGS += -DCONFIG_ONENAND_IPL -g +OBJCFLAGS += --gap-fill=0x00 + +SOBJS := lowlevel_init.o mem_setup.o +SOBJS += start.o +COBJS += onenand_read.o +COBJS += onenand_boot.o + +SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c)) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +__OBJS := $(SOBJS) $(COBJS) +LNDIR := $(OBJTREE)/onenand_ipl/board/$(BOARDDIR) + +onenandobj := $(OBJTREE)/onenand_ipl/ + +ALL = $(onenandobj)onenand-ipl $(onenandobj)onenand-ipl.bin $(onenandobj)onenand-ipl-2k.bin $(onenandobj)onenand-ipl-4k.bin + +all: $(obj).depend $(ALL) + +$(onenandobj)onenand-ipl-2k.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(TEXT_BASE2K) -O binary $< $@ + +$(onenandobj)onenand-ipl-4k.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(TEXT_BASE4K) -O binary $< $@ + +$(onenandobj)onenand-ipl.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + +$(onenandobj)onenand-ipl: $(OBJS) + cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ + -Map $@.map -o $@ + +# create symbolic links from common files + +# from cpu directory +$(obj)start.S: + @rm -f $@ + ln -s $(SRCTREE)/cpu/$(CPU)/start.S $@ + +$(obj)mem_setup.S: + ln -sf $(SRCTREE)/board/$(BOARDDIR)/mem_setup.S $@ + +$(obj)lowlevel_init.S: + ln -sf $(SRCTREE)/board/$(BOARDDIR)/lowlevel_init.S $@ + +# from onenand_ipl directory +$(obj)onenand_ipl.h: + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_ipl.h $@ + +$(obj)onenand_boot.c: $(obj)onenand_ipl.h + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_boot.c $@ + +$(obj)onenand_read.c: $(obj)onenand_ipl.h + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_read.c $@ + +######################################################################### + +$(obj)%.o: $(obj)%.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)%.o: $(obj)$.c + $(CC) $(CFLAGS) -c -o $@ $< + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +clean: + rm onenand_boot.c onenand_read.c + +######################################################################### diff --git a/onenand_ipl/board/samsung/smdkc100/u-boot-onenand.lds b/onenand_ipl/board/samsung/smdkc100/u-boot-onenand.lds new file mode 100644 index 0000000..559f9f2 --- /dev/null +++ b/onenand_ipl/board/samsung/smdkc100/u-boot-onenand.lds @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2005-2008 Samsung Electronics + * Kyungmin Park kyungmin.park@samsung.com + * + * Derived from X-loader + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/onenand_ipl/onenand_ipl.h b/onenand_ipl/onenand_ipl.h index 412572a..9a1a214 100644 --- a/onenand_ipl/onenand_ipl.h +++ b/onenand_ipl/onenand_ipl.h @@ -23,7 +23,18 @@
#include <linux/mtd/onenand_regs.h>
+#ifdef CONFIG_S5PC1XX +#define AHB_ADDR 0xB0000000 +#define MEM_ADDR(fba, fpa, fsa) (((fba) << 13 | (fpa) << 7 | \ + (fsa) << 5) & 0x3ffffff) +#define CMD_MAP_01(mem_addr) (AHB_ADDR | (1 << 26) | (mem_addr)) +#define CMD_MAP_11(addr) (AHB_ADDR | (3 << 26) | ((addr) << 2)) + +#define onenand_readw(a) (readl(CMD_MAP_11((a) >> 1)) & 0xffff) +#else /* CONFIG_S5PC1XX */ #define onenand_readw(a) readw(THIS_ONENAND(a)) +#endif /* CONFIG_S5PC1XX */ + #define onenand_writew(v, a) writew(v, THIS_ONENAND(a))
#define THIS_ONENAND(a) (CONFIG_SYS_ONENAND_BASE + (a)) diff --git a/onenand_ipl/onenand_read.c b/onenand_ipl/onenand_read.c index d1a842d..df2740b 100644 --- a/onenand_ipl/onenand_read.c +++ b/onenand_ipl/onenand_read.c @@ -37,10 +37,24 @@ extern void *memcpy32(void *dest, void *src, int size); #endif
+ + /* read a page with ECC */ static inline int onenand_read_page(ulong block, ulong page, u_char * buf, int pagesize) { +#ifdef CONFIG_S5PC1XX + unsigned int *p = (unsigned int *) buf; + int mem_addr, i; + + mem_addr = MEM_ADDR(block, page, 0); + + pagesize >>= 2; + + for (i = 0; i < pagesize; i++) + *p++ = *(volatile unsigned int *)(CMD_MAP_01(mem_addr)); +#else /* CONFIG_S5PC1XX */ + unsigned long *base;
#ifndef __HAVE_ARCH_MEMCPY32 @@ -85,6 +99,7 @@ static inline int onenand_read_page(ulong block, ulong page, *p++ = value; } #endif +#endif /* CONFIG_S5PC1XX */
return 0; } @@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; +#ifdef CONFIG_S5PC1XX + nblocks = 1; +#endif
/* NOTE: you must read page from page 1 of block 0 */ /* read the block page by page*/

Dear HeungJun Kim,
In message 350d1ec30906250121q4e860812s35054aaee8c2016e@mail.gmail.com you wrote:
The SMDKC100 Board has 256MB onenand. So, It's bootable, if this patch is adapted thus the board use onenand_ipl.
Signed-off-by: HeungJun, Kim riverful.kim@samsung.com
This patch support onenand boot on SMDKC100 Board.
...
diff --git a/onenand_ipl/board/samsung/smdkc100/Makefile b/onenand_ipl/board/samsung/smdkc100/Makefile new file mode 100644 index 0000000..4301938 --- /dev/null +++ b/onenand_ipl/board/samsung/smdkc100/Makefile
...
+ALL = $(onenandobj)onenand-ipl $(onenandobj)onenand-ipl.bin $(onenandobj)onenand-ipl-2k.bin $(onenandobj)onenand-ipl-4k.bin
This patch is white-space corrupted. I gues this happened here because the line was way too long.
--- a/onenand_ipl/onenand_read.c +++ b/onenand_ipl/onenand_read.c @@ -37,10 +37,24 @@ extern void *memcpy32(void *dest, void *src, int size); #endif
Please do not arbitrary empty lines.
/* read a page with ECC */ static inline int onenand_read_page(ulong block, ulong page, u_char * buf, int pagesize) { +#ifdef CONFIG_S5PC1XX
- unsigned int *p = (unsigned int *) buf;
- int mem_addr, i;
- mem_addr = MEM_ADDR(block, page, 0);
- pagesize >>= 2;
- for (i = 0; i < pagesize; i++)
*p++ = *(volatile unsigned int *)(CMD_MAP_01(mem_addr));
+#else /* CONFIG_S5PC1XX */
- unsigned long *base;
I don't like to see such board specific code in global files.
Also, please use I/O accessor functions instead of register accesses.
@@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; +#ifdef CONFIG_S5PC1XX
- nblocks = 1;
+#endif
Again: why do we need such board specific code here?
Best regards,
Wolfgang Denk

Hi,
On Mon, Jul 20, 2009 at 5:04 AM, Wolfgang Denkwd@denx.de wrote:
Dear HeungJun Kim,
In message 350d1ec30906250121q4e860812s35054aaee8c2016e@mail.gmail.com you wrote:
The SMDKC100 Board has 256MB onenand. So, It's bootable, if this patch is adapted thus the board use onenand_ipl.
Signed-off-by: HeungJun, Kim riverful.kim@samsung.com
This patch support onenand boot on SMDKC100 Board.
...
diff --git a/onenand_ipl/board/samsung/smdkc100/Makefile b/onenand_ipl/board/samsung/smdkc100/Makefile new file mode 100644 index 0000000..4301938 --- /dev/null +++ b/onenand_ipl/board/samsung/smdkc100/Makefile
...
+ALL = $(onenandobj)onenand-ipl $(onenandobj)onenand-ipl.bin $(onenandobj)onenand-ipl-2k.bin $(onenandobj)onenand-ipl-4k.bin
This patch is white-space corrupted. I gues this happened here because the line was way too long.
--- a/onenand_ipl/onenand_read.c +++ b/onenand_ipl/onenand_read.c @@ -37,10 +37,24 @@ extern void *memcpy32(void *dest, void *src, int size); #endif
Please do not arbitrary empty lines.
/* read a page with ECC */ static inline int onenand_read_page(ulong block, ulong page, u_char * buf, int pagesize) { +#ifdef CONFIG_S5PC1XX
- unsigned int *p = (unsigned int *) buf;
- int mem_addr, i;
- mem_addr = MEM_ADDR(block, page, 0);
- pagesize >>= 2;
- for (i = 0; i < pagesize; i++)
- *p++ = *(volatile unsigned int *)(CMD_MAP_01(mem_addr));
+#else /* CONFIG_S5PC1XX */
unsigned long *base;
I don't like to see such board specific code in global files.
I think it's not board specific code. S3C64XX and S5PC1XX series have own OneNAND controller and to access the OneNAND, it should use the this controller.
If you don't like the ifdef. we can separate the function but I'm not sure it's really required.
Also, please use I/O accessor functions instead of register accesses.
readl(...)? If yes, I agree it.
@@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; +#ifdef CONFIG_S5PC1XX
- nblocks = 1;
+#endif
Again: why do we need such board specific code here?
It should be fixed.
Thank you, Kyungmin Park

Dear Kyungmin Park,
In message 9c9fda240907192016i32c7312dh490629f2f2bb31be@mail.gmail.com you wrote:
/* read a page with ECC */ static inline int onenand_read_page(ulong block, ulong page, u_char * buf> , int pagesize) { +#ifdef CONFIG_S5PC1XX
unsigned int *p = (unsigned int *) buf;
int mem_addr, i;
mem_addr = MEM_ADDR(block, page, 0);
pagesize >>= 2;
for (i = 0; i < pagesize; i++)
*p++ = *(volatile unsigned int *)(CMD_MAP_01> (mem_addr));
+#else /* CONFIG_S5PC1XX */
unsigned long *base;
I don't like to see such board specific code in global files.
I think it's not board specific code. S3C64XX and S5PC1XX series have own OneNAND controller and to access the OneNAND, it should use the this controller.
OK, so it is SoC specific code in a common file - that's just marginally better.
If you don't like the ifdef. we can separate the function but I'm not sure it's really required.
It would be great if we can get rid of the #ifdef.
Also, please use I/O accessor functions instead of register accesses.
readl(...)? If yes, I agree it.
Yes.
@@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> eras> e_shift;
+#ifdef CONFIG_S5PC1XX
nblocks = 1;
+#endif
Again: why do we need such board specific code here?
It should be fixed.
Thanks.
Best regards,
Wolfgang Denk

On Tue, Jul 21, 2009 at 6:18 AM, Wolfgang Denkwd@denx.de wrote:
Dear Kyungmin Park,
In message 9c9fda240907192016i32c7312dh490629f2f2bb31be@mail.gmail.com you wrote:
/* read a page with ECC */ static inline int onenand_read_page(ulong block, ulong page, u_char * buf> , int pagesize) { +#ifdef CONFIG_S5PC1XX
- unsigned int *p = (unsigned int *) buf;
- int mem_addr, i;
- mem_addr = MEM_ADDR(block, page, 0);
- pagesize >>= 2;
- for (i = 0; i < pagesize; i++)
- *p++ = *(volatile unsigned int *)(CMD_MAP_01> (mem_addr));
+#else /* CONFIG_S5PC1XX */
unsigned long *base;
I don't like to see such board specific code in global files.
I think it's not board specific code. S3C64XX and S5PC1XX series have own OneNAND controller and to access the OneNAND, it should use the this controller.
OK, so it is SoC specific code in a common file - that's just marginally better.
If you don't like the ifdef. we can separate the function but I'm not sure it's really required.
It would be great if we can get rid of the #ifdef.
As you know, OneNAND IPL has size limitation, 1KiB. So it's difficult to co-exist two different function.
Thank you, Kyungmin Park

On Thu, Jun 25, 2009 at 05:21:45PM +0900, HeungJun Kim wrote:
+#ifdef CONFIG_S5PC1XX
- unsigned int *p = (unsigned int *) buf;
- int mem_addr, i;
- mem_addr = MEM_ADDR(block, page, 0);
- pagesize >>= 2;
- for (i = 0; i < pagesize; i++)
*p++ = *(volatile unsigned int *)(CMD_MAP_01(mem_addr));
+#else /* CONFIG_S5PC1XX */
- unsigned long *base;
#ifndef __HAVE_ARCH_MEMCPY32 @@ -85,6 +99,7 @@ static inline int onenand_read_page(ulong block, ulong page, *p++ = value; } #endif +#endif /* CONFIG_S5PC1XX */
Please put each controller implementation in a separate file, with an appropriate name. Do not make anything which is SoC-specific look generic.
If onenand_read_block() is not controller-specific (looks like everything except the read of ONENAND_REG_TECHNOLOGY is generic), move it to onenand_boot.c.
@@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; +#ifdef CONFIG_S5PC1XX
- nblocks = 1;
+#endif
Why?
-Scott

hi
On Sat, Aug 1, 2009 at 7:19 AM, Scott Woodscottwood@freescale.com wrote:
On Thu, Jun 25, 2009 at 05:21:45PM +0900, HeungJun Kim wrote:
+#ifdef CONFIG_S5PC1XX
- unsigned int *p = (unsigned int *) buf;
- int mem_addr, i;
- mem_addr = MEM_ADDR(block, page, 0);
- pagesize >>= 2;
- for (i = 0; i < pagesize; i++)
- *p++ = *(volatile unsigned int *)(CMD_MAP_01(mem_addr));
+#else /* CONFIG_S5PC1XX */
unsigned long *base;
#ifndef __HAVE_ARCH_MEMCPY32 @@ -85,6 +99,7 @@ static inline int onenand_read_page(ulong block, ulong page, *p++ = value; } #endif +#endif /* CONFIG_S5PC1XX */
It should be S5PC100, not used at S5PC110. it uses generic interface with DMA support.
Please put each controller implementation in a separate file, with an appropriate name. Do not make anything which is SoC-specific look generic.
No problem, One question, how to use use generic & s5pc100 read function simultaneously. Since our test board use two cpu, s5pc100 & s5pc110. but each cpu has different read function. I want to use it both with only one u-boot image. In this case we have to distinguish and use it properly. Now I add the function pointer and assign it based on cpu id.
If onenand_read_block() is not controller-specific (looks like everything except the read of ONENAND_REG_TECHNOLOGY is generic), move it to onenand_boot.c.
@@ -114,6 +129,9 @@ int onenand_read_block(unsigned char *buf)
erasesize = ONENAND_PAGES_PER_BLOCK * pagesize; nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; +#ifdef CONFIG_S5PC1XX
- nblocks = 1;
+#endif
Why?
It's developer's mistake, no reason to use 1 block. actually internal ROM read 16KiB data to internal RAM in case of s5pc100.
Thank you, Kyungmin Park

Kyungmin Park wrote:
No problem, One question, how to use use generic & s5pc100 read function simultaneously. Since our test board use two cpu, s5pc100 & s5pc110. but each cpu has different read function. I want to use it both with only one u-boot image. In this case we have to distinguish and use it properly. Now I add the function pointer and assign it based on cpu id.
Using a function pointer is OK.
-Scott
participants (4)
-
HeungJun Kim
-
Kyungmin Park
-
Scott Wood
-
Wolfgang Denk