summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-02-01 16:16:12 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2010-02-01 16:16:12 +0100
commit7ca411ecd2dc1c6bc47caad4b1e25a118bd7441b (patch)
tree716f34c98b8e9a1535a9dc42605644d0793f5161
parentdc6550ed3be2c47476ccaefdee2277b9360a8ed6 (diff)
parent976b4be6021569e9808cf83ab7600231d1315307 (diff)
downloadbarebox-7ca411ecd2dc1c6bc47caad4b1e25a118bd7441b.tar.gz
barebox-7ca411ecd2dc1c6bc47caad4b1e25a118bd7441b.tar.xz
Merge branch 'next'
-rw-r--r--Documentation/boards.dox10
-rw-r--r--Documentation/commands.dox2
-rw-r--r--Documentation/developers_manual.dox1
-rw-r--r--Documentation/users_manual.dox1
-rw-r--r--Doxyfile3
-rw-r--r--Makefile23
-rw-r--r--arch/architecture.dox1
-rw-r--r--arch/arm/Kconfig6
-rw-r--r--arch/arm/Makefile9
-rw-r--r--arch/arm/configs/edb93xx_defconfig236
-rw-r--r--arch/arm/configs/freescale_mx35_3stack_defconfig67
-rw-r--r--arch/arm/lib/barebox.lds.S5
-rw-r--r--arch/arm/mach-ep93xx/Kconfig438
-rw-r--r--arch/arm/mach-ep93xx/Makefile3
-rw-r--r--arch/arm/mach-ep93xx/clocksource.c96
-rw-r--r--arch/arm/mach-ep93xx/gpio.c136
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h600
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio.h29
-rw-r--r--arch/arm/mach-ep93xx/led.c62
-rw-r--r--arch/arm/mach-ep93xx/led.h26
-rw-r--r--arch/arm/mach-ep93xx/lowlevel_init.S64
-rw-r--r--arch/arm/mach-imx/include/mach/imx27-regs.h1
-rw-r--r--arch/arm/mach-imx/speed-imx27.c5
-rw-r--r--arch/x86/Kconfig67
-rw-r--r--arch/x86/Makefile50
-rw-r--r--arch/x86/boot/Kconfig20
-rw-r--r--arch/x86/boot/Makefile13
-rw-r--r--arch/x86/boot/a20.c170
-rw-r--r--arch/x86/boot/bioscall.S99
-rw-r--r--arch/x86/boot/boot.h193
-rw-r--r--arch/x86/boot/boot_hdisk.S176
-rw-r--r--arch/x86/boot/boot_main.S58
-rw-r--r--arch/x86/boot/main_entry.c44
-rw-r--r--arch/x86/boot/pmjump.S89
-rw-r--r--arch/x86/boot/prepare_uboot.c86
-rw-r--r--arch/x86/boot/regs.c34
-rw-r--r--arch/x86/boot/tty.c45
-rw-r--r--arch/x86/configs/generic_defconfig186
-rw-r--r--arch/x86/include/asm/barebox.h21
-rw-r--r--arch/x86/include/asm/barebox.lds.h113
-rw-r--r--arch/x86/include/asm/bitops.h32
-rw-r--r--arch/x86/include/asm/byteorder.h30
-rw-r--r--arch/x86/include/asm/common.h29
-rw-r--r--arch/x86/include/asm/elf.h30
-rw-r--r--arch/x86/include/asm/io.h73
-rw-r--r--arch/x86/include/asm/modes.h65
-rw-r--r--arch/x86/include/asm/module.h37
-rw-r--r--arch/x86/include/asm/posix_types.h49
-rw-r--r--arch/x86/include/asm/segment.h43
-rw-r--r--arch/x86/include/asm/string.h31
-rw-r--r--arch/x86/include/asm/syslib.h33
-rw-r--r--arch/x86/include/asm/types.h44
-rw-r--r--arch/x86/lib/Makefile9
-rw-r--r--arch/x86/lib/barebox.lds.S194
-rw-r--r--arch/x86/lib/bios_disk.S77
-rw-r--r--arch/x86/lib/gdt.c55
-rw-r--r--arch/x86/lib/linux_start.S75
-rw-r--r--arch/x86/lib/memory.c67
-rw-r--r--arch/x86/lib/memory16.S73
-rw-r--r--arch/x86/lib/traveler.S183
-rw-r--r--arch/x86/mach-i386/Kconfig29
-rw-r--r--arch/x86/mach-i386/Makefile5
-rw-r--r--arch/x86/mach-i386/generic.c38
-rw-r--r--arch/x86/mach-i386/pit_timer.c71
-rw-r--r--arch/x86/mach-i386/reset.c34
-rw-r--r--arch/x86/mach-x86.dox128
-rw-r--r--board/edb93xx/Makefile2
-rw-r--r--board/edb93xx/config.h4
-rw-r--r--board/edb93xx/early_udelay.h34
-rw-r--r--board/edb93xx/edb93xx.c172
-rw-r--r--board/edb93xx/edb93xx.dox108
-rw-r--r--board/edb93xx/edb93xx.h48
-rw-r--r--board/edb93xx/env/bin/boot48
-rw-r--r--board/edb93xx/env/bin/flash_partition22
-rw-r--r--board/edb93xx/env/bin/init19
-rw-r--r--board/edb93xx/env/bin/set_nor_parts3
-rw-r--r--board/edb93xx/env/bin/update_kernel16
-rw-r--r--board/edb93xx/env/bin/update_rootfs16
-rw-r--r--board/edb93xx/env/config16
-rw-r--r--board/edb93xx/flash_cfg.c38
-rw-r--r--board/edb93xx/pll_cfg.c58
-rw-r--r--board/edb93xx/pll_cfg.h72
-rw-r--r--board/edb93xx/sdram_cfg.c127
-rw-r--r--board/edb93xx/sdram_cfg.h144
-rw-r--r--board/eukrea_cpuimx27/eukrea_cpuimx27.c41
-rw-r--r--board/eukrea_cpuimx27/lowlevel_init.S4
-rw-r--r--board/freescale-mx35-3-stack/3stack.c113
-rw-r--r--board/freescale-mx35-3-stack/env/bin/_update5
-rw-r--r--board/freescale-mx35-3-stack/env/bin/boot50
-rw-r--r--board/freescale-mx35-3-stack/env/bin/init15
-rw-r--r--board/freescale-mx35-3-stack/env/bin/update_kernel2
-rw-r--r--board/freescale-mx35-3-stack/env/bin/update_rootfs (renamed from board/freescale-mx35-3-stack/env/bin/update_root)8
-rw-r--r--board/freescale-mx35-3-stack/env/config41
-rw-r--r--board/freescale-mx35-3-stack/lowlevel_init.S340
-rw-r--r--board/x86_generic/Makefile1
-rw-r--r--board/x86_generic/config.h21
-rw-r--r--board/x86_generic/env/bin/boot37
-rw-r--r--board/x86_generic/env/bin/init15
-rw-r--r--board/x86_generic/env/config31
-rw-r--r--board/x86_generic/generic_pc.c140
-rw-r--r--commands/Kconfig8
-rw-r--r--commands/Makefile1
-rw-r--r--commands/linux16.c363
-rwxr-xr-xcommands/partition.c37
-rw-r--r--drivers/Kconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/Kconfig26
-rw-r--r--drivers/ata/Makefile7
-rw-r--r--drivers/ata/bios.c291
-rw-r--r--drivers/ata/disk_drive.c346
-rw-r--r--drivers/i2c/Kconfig3
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/lp3972.c110
-rw-r--r--drivers/i2c/mc13892.c91
-rw-r--r--drivers/i2c/mc9sdz60.c84
-rw-r--r--drivers/net/Kconfig5
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ep93xx.c676
-rw-r--r--drivers/net/ep93xx.h147
-rw-r--r--drivers/serial/Kconfig7
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/serial_pl010.c172
-rw-r--r--drivers/serial/serial_pl010.h100
-rw-r--r--include/ata.h39
-rw-r--r--include/common.h1
-rw-r--r--include/i2c/lp3972.h7
-rw-r--r--include/i2c/mc13892.h90
-rw-r--r--include/i2c/mc9sdz60.h61
-rw-r--r--scripts/Makefile4
-rw-r--r--scripts/setupmbr/Makefile4
-rw-r--r--scripts/setupmbr/arch.h55
-rw-r--r--scripts/setupmbr/setupmbr.c705
132 files changed, 9708 insertions, 371 deletions
diff --git a/Documentation/boards.dox b/Documentation/boards.dox
index dba547f3..3eb79b27 100644
--- a/Documentation/boards.dox
+++ b/Documentation/boards.dox
@@ -20,6 +20,14 @@ ARM type:
@li @subpage a9m2440
@li @subpage a9m2410
@li @subpage eukrea_cpuimx27
+@li @subpage edb9301
+@li @subpage edb9302
+@li @subpage edb9302a
+@li @subpage edb9307
+@li @subpage edb9307a
+@li @subpage edb9312
+@li @subpage edb9315
+@li @subpage edb9315a
Blackfin type:
@@ -27,7 +35,7 @@ Blackfin type:
x86 type:
-@li nothing yet
+@li @subpage generic_pc
coldfire/m68k type:
diff --git a/Documentation/commands.dox b/Documentation/commands.dox
index 4c14a885..a8850b1b 100644
--- a/Documentation/commands.dox
+++ b/Documentation/commands.dox
@@ -20,5 +20,5 @@
@li @subpage setenv_command
@li @subpage sh_command
@li @subpage unprotect_command
-
+@li @subpage linux16_command
*/
diff --git a/Documentation/developers_manual.dox b/Documentation/developers_manual.dox
index 2f7d3605..620905ea 100644
--- a/Documentation/developers_manual.dox
+++ b/Documentation/developers_manual.dox
@@ -20,5 +20,6 @@ This part of the documentation is intended for developers of @a barebox.
@li @subpage barebox_simul
@li @subpage io_access_functions
@li @subpage mcfv4e_MCDlib
+@li @subpage x86_runtime
*/
diff --git a/Documentation/users_manual.dox b/Documentation/users_manual.dox
index e4ba9d00..5467bee4 100644
--- a/Documentation/users_manual.dox
+++ b/Documentation/users_manual.dox
@@ -10,5 +10,6 @@ work easier.
@li @subpage readline_parser
@li @subpage command_reference
@li @subpage partitions
+@li @subpage x86_bootloader
*/
diff --git a/Doxyfile b/Doxyfile
index c9b04b6d..94dd6ae0 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -484,7 +484,8 @@ INPUT = Documentation \
commands \
common \
board \
- lib
+ lib \
+ scripts/setupmbr
# This tag can be used to specify the character encoding of the source files that
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
diff --git a/Makefile b/Makefile
index 5d4f634b..5826368e 100644
--- a/Makefile
+++ b/Makefile
@@ -643,7 +643,30 @@ endef
barebox.bin: barebox
$(Q)$(OBJCOPY) -O binary barebox barebox.bin
+ifdef CONFIG_X86
+ifdef CONFIG_X86_HDBOOT
+ @echo "-------------------------------------------------" > barebox.S
+ @echo " * MBR content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .bootsector -mi8086 -d barebox >> barebox.S
+ @echo "-------------------------------------------------" >> barebox.S
+ @echo " * Boot loader content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .bootstrapping -mi8086 -d barebox >> barebox.S
+endif
+ @echo "-------------------------------------------------" >> barebox.S
+ @echo " * Regular Text content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .text -d barebox >> barebox.S
+ @echo "-------------------------------------------------" >> barebox.S
+ @echo " * Regular Data content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .data -d barebox >> barebox.S
+ @echo "-------------------------------------------------" >> barebox.S
+ @echo " * Commands content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .barebox_cmd -d barebox >> barebox.S
+ @echo "-------------------------------------------------" >> barebox.S
+ @echo " * Init Calls content" >> barebox.S
+ $(Q)$(OBJDUMP) -j .barebox_initcalls -d barebox >> barebox.S
+else
$(Q)$(OBJDUMP) -d barebox > barebox.S
+endif
# barebox image
barebox: $(barebox-lds) $(barebox-head) $(barebox-common) $(kallsyms.o) FORCE
diff --git a/arch/architecture.dox b/arch/architecture.dox
index 669c0284..ea00dcdc 100644
--- a/arch/architecture.dox
+++ b/arch/architecture.dox
@@ -88,6 +88,7 @@ TODO
@li @subpage dev_bf_mach
@li @subpage dev_ppc_mach
@li @subpage dev_m68k_mach
+@li @subpage dev_x86_mach
*/
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c091a996..9cad224c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -31,6 +31,11 @@ config ARCH_AT91RM9200
bool "Atmel AT91RM9200"
select CPU_ARM920T
+config ARCH_EP93XX
+ bool "Cirrus Logic EP93xx"
+ select CPU_ARM920T
+ select GENERIC_GPIO
+
config ARCH_IMX
bool "Freescale iMX-based"
select GENERIC_GPIO
@@ -51,6 +56,7 @@ endchoice
source arch/arm/cpu/Kconfig
source arch/arm/mach-at91/Kconfig
source arch/arm/mach-at91rm9200/Kconfig
+source arch/arm/mach-ep93xx/Kconfig
source arch/arm/mach-imx/Kconfig
source arch/arm/mach-netx/Kconfig
source arch/arm/mach-omap/Kconfig
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 47b002f9..ede20854 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -39,6 +39,7 @@ CPPFLAGS += $(CFLAGS_ABI) $(arch-y) $(tune-y)
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AT91) := at91
machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
+machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_IMX) := imx
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_OMAP) := omap
@@ -51,6 +52,14 @@ board-$(CONFIG_MACH_A9M2440) := a9m2440
board-$(CONFIG_MACH_AT91SAM9260EK) := at91sam9260ek
board-$(CONFIG_MACH_AT91SAM9263EK) := at91sam9263ek
board-$(CONFIG_MACH_ECO920) := eco920
+board-$(CONFIG_MACH_EDB9301) := edb93xx
+board-$(CONFIG_MACH_EDB9302) := edb93xx
+board-$(CONFIG_MACH_EDB9302A) := edb93xx
+board-$(CONFIG_MACH_EDB9307) := edb93xx
+board-$(CONFIG_MACH_EDB9307A) := edb93xx
+board-$(CONFIG_MACH_EDB93012) := edb93xx
+board-$(CONFIG_MACH_EDB9315) := edb93xx
+board-$(CONFIG_MACH_EDB9315A) := edb93xx
board-$(CONFIG_MACH_EUKREA_CPUIMX27) := eukrea_cpuimx27
board-$(CONFIG_MACH_FREESCALE_MX35_3STACK) := freescale-mx35-3-stack
board-$(CONFIG_MACH_FREESCALE_MX25_3STACK) := freescale-mx25-3-stack
diff --git a/arch/arm/configs/edb93xx_defconfig b/arch/arm/configs/edb93xx_defconfig
new file mode 100644
index 00000000..d6b4b19f
--- /dev/null
+++ b/arch/arm/configs/edb93xx_defconfig
@@ -0,0 +1,236 @@
+#
+# Automatically generated make config: don't edit
+# barebox version: 2009.12.0
+# Fri Jan 8 17:27:15 2010
+#
+CONFIG_ARM=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_S3C24xx is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+
+#
+# processor features
+#
+CONFIG_ARCH_TEXT_BASE=0x05700000
+CONFIG_BOARDINFO="Cirrus Logic EDB9301"
+CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET=y
+
+#
+# Cirrus EP93xx System-on-Chip
+#
+CONFIG_ARCH_EP9301=y
+# CONFIG_ARCH_EP9302 is not set
+# CONFIG_ARCH_EP9307 is not set
+# CONFIG_ARCH_EP9312 is not set
+# CONFIG_ARCH_EP9315 is not set
+CONFIG_MACH_EDB9301=y
+CONFIG_EP93XX_SDRAM_NUM_BANKS=4
+CONFIG_EP93XX_SDRAM_BANK0_BASE=0x00000000
+CONFIG_EP93XX_SDRAM_BANK0_SIZE=0x00800000
+CONFIG_EP93XX_SDRAM_BANK1_BASE=0x01000000
+CONFIG_EP93XX_SDRAM_BANK1_SIZE=0x00800000
+CONFIG_EP93XX_SDRAM_BANK2_BASE=0x04000000
+CONFIG_EP93XX_SDRAM_BANK2_SIZE=0x00800000
+CONFIG_EP93XX_SDRAM_BANK3_BASE=0x05000000
+CONFIG_EP93XX_SDRAM_BANK3_SIZE=0x00800000
+CONFIG_AEABI=y
+
+#
+# Arm specific settings
+#
+CONFIG_CMD_ARM_CPUINFO=y
+CONFIG_CMDLINE_TAG=y
+CONFIG_SETUP_MEMORY_TAGS=y
+# CONFIG_INITRD_TAG is not set
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_GREGORIAN_CALENDER=y
+CONFIG_HAS_KALLSYMS=y
+CONFIG_HAS_MODULES=y
+CONFIG_CMD_MEMORY=y
+CONFIG_ENV_HANDLING=y
+CONFIG_GENERIC_GPIO=y
+
+#
+# General Settings
+#
+CONFIG_LOCALVERSION_AUTO=y
+
+#
+# memory layout
+#
+CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
+CONFIG_TEXT_BASE=0x05700000
+CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
+CONFIG_MEMORY_LAYOUT_DEFAULT=y
+# CONFIG_MEMORY_LAYOUT_FIXED is not set
+CONFIG_STACK_SIZE=0x8000
+CONFIG_MALLOC_SIZE=0x400000
+# CONFIG_BROKEN is not set
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_MACH_HAS_LOWLEVEL_INIT=y
+CONFIG_MACH_DO_LOWLEVEL_INIT=y
+CONFIG_PROMPT="barebox:"
+CONFIG_BAUDRATE=115200
+CONFIG_LONGHELP=y
+CONFIG_CBSIZE=1024
+CONFIG_MAXARGS=16
+CONFIG_SHELL_HUSH=y
+# CONFIG_SHELL_SIMPLE is not set
+CONFIG_GLOB=y
+CONFIG_PROMPT_HUSH_PS2="> "
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_DYNAMIC_CRC_TABLE=y
+CONFIG_ERRNO_MESSAGES=y
+CONFIG_TIMESTAMP=y
+CONFIG_CONSOLE_FULL=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+# CONFIG_OF_FLAT_TREE is not set
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="board/edb93xx/env"
+
+#
+# Debugging
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_FLASH_NOISE is not set
+# CONFIG_ENABLE_PARTITION_NOISE is not set
+# CONFIG_ENABLE_DEVICE_NOISE is not set
+
+#
+# Commands
+#
+
+#
+# scripting
+#
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TRUE=y
+CONFIG_CMD_FALSE=y
+
+#
+# file commands
+#
+CONFIG_CMD_LS=y
+CONFIG_CMD_RM=y
+CONFIG_CMD_CAT=y
+CONFIG_CMD_MKDIR=y
+CONFIG_CMD_RMDIR=y
+CONFIG_CMD_CP=y
+CONFIG_CMD_PWD=y
+CONFIG_CMD_CD=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UMOUNT=y
+
+#
+# console
+#
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO=y
+
+#
+# memory
+#
+# CONFIG_CMD_LOADB is not set
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_MTEST=y
+# CONFIG_CMD_MTEST_ALTERNATIVE is not set
+
+#
+# flash
+#
+CONFIG_CMD_FLASH=y
+
+#
+# booting
+#
+CONFIG_CMD_BOOTM=y
+# CONFIG_CMD_BOOTM_ZLIB is not set
+# CONFIG_CMD_BOOTM_BZLIB is not set
+# CONFIG_CMD_BOOTM_SHOW_TYPE is not set
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTU=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_TEST=y
+CONFIG_CMD_VERSION=y
+CONFIG_CMD_HELP=y
+CONFIG_CMD_DEVINFO=y
+CONFIG_CMD_GPIO=y
+CONFIG_NET=y
+CONFIG_NET_DHCP=y
+# CONFIG_NET_RARP is not set
+# CONFIG_NET_NFS is not set
+CONFIG_NET_PING=y
+CONFIG_NET_TFTP=y
+
+#
+# Drivers
+#
+
+#
+# serial drivers
+#
+# CONFIG_DRIVER_SERIAL_ARM_DCC is not set
+# CONFIG_DRIVER_SERIAL_NS16550 is not set
+CONFIG_DRIVER_SERIAL_PL010=y
+CONFIG_MIIPHY=y
+
+#
+# Network drivers
+#
+# CONFIG_DRIVER_NET_SMC911X is not set
+# CONFIG_DRIVER_NET_SMC91111 is not set
+CONFIG_DRIVER_NET_EP93XX=y
+
+#
+# SPI drivers
+#
+# CONFIG_SPI is not set
+# CONFIG_I2C is not set
+
+#
+# flash drivers
+#
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_NEW is not set
+CONFIG_DRIVER_CFI_OLD=y
+# CONFIG_CFI_BUFFER_WRITE is not set
+# CONFIG_NAND is not set
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_VIDEO is not set
+
+#
+# Filesystem support
+#
+# CONFIG_FS_CRAMFS is not set
+CONFIG_FS_RAMFS=y
+CONFIG_FS_DEVFS=y
+CONFIG_CRC32=y
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
diff --git a/arch/arm/configs/freescale_mx35_3stack_defconfig b/arch/arm/configs/freescale_mx35_3stack_defconfig
index 1319a695..17a2fdc6 100644
--- a/arch/arm/configs/freescale_mx35_3stack_defconfig
+++ b/arch/arm/configs/freescale_mx35_3stack_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# barebox version: 2.0.0-rc10
-# Fri Dec 18 11:47:45 2009
+# barebox version: 2009.12.0-pre
+# Tue Dec 22 17:43:43 2009
#
# CONFIG_BOARD_LINKER_SCRIPT is not set
CONFIG_GENERIC_LINKER_SCRIPT=y
@@ -43,17 +43,17 @@ CONFIG_MACH_FREESCALE_MX35_3STACK=y
# CONFIG_MACH_PCM043 is not set
#
-# Board specific settings
+# Board specific settings
#
#
-# i.MX specific settings
+# i.MX specific settings
#
# CONFIG_IMX_CLKO is not set
-# CONFIG_AEABI is not set
+CONFIG_AEABI=y
#
-# Arm specific settings
+# Arm specific settings
#
CONFIG_CMD_ARM_CPUINFO=y
CONFIG_CMDLINE_TAG=y
@@ -68,12 +68,12 @@ CONFIG_ENV_HANDLING=y
CONFIG_GENERIC_GPIO=y
#
-# General Settings
+# General Settings
#
CONFIG_LOCALVERSION_AUTO=y
#
-# memory layout
+# memory layout
#
CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
CONFIG_TEXT_BASE=0x87F00000
@@ -81,7 +81,7 @@ CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
CONFIG_MEMORY_LAYOUT_DEFAULT=y
# CONFIG_MEMORY_LAYOUT_FIXED is not set
CONFIG_STACK_SIZE=0x8000
-CONFIG_MALLOC_SIZE=0x400000
+CONFIG_MALLOC_SIZE=0x1000000
# CONFIG_BROKEN is not set
# CONFIG_EXPERIMENTAL is not set
CONFIG_MACH_HAS_LOWLEVEL_INIT=y
@@ -105,10 +105,10 @@ CONFIG_CONSOLE_ACTIVATE_FIRST=y
# CONFIG_OF_FLAT_TREE is not set
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="board/pcm043/env/"
+CONFIG_DEFAULT_ENVIRONMENT_PATH="board/freescale-mx35-3-stack/env/"
#
-# Debugging
+# Debugging
#
# CONFIG_DEBUG_INFO is not set
# CONFIG_ENABLE_FLASH_NOISE is not set
@@ -116,11 +116,11 @@ CONFIG_DEFAULT_ENVIRONMENT_PATH="board/pcm043/env/"
# CONFIG_ENABLE_DEVICE_NOISE is not set
#
-# Commands
+# Commands
#
#
-# scripting
+# scripting
#
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
@@ -133,7 +133,7 @@ CONFIG_CMD_TRUE=y
CONFIG_CMD_FALSE=y
#
-# file commands
+# file commands
#
CONFIG_CMD_LS=y
CONFIG_CMD_RM=y
@@ -147,13 +147,13 @@ CONFIG_CMD_MOUNT=y
CONFIG_CMD_UMOUNT=y
#
-# console
+# console
#
CONFIG_CMD_CLEAR=y
CONFIG_CMD_ECHO=y
#
-# memory
+# memory
#
# CONFIG_CMD_LOADB is not set
CONFIG_CMD_MEMINFO=y
@@ -161,12 +161,12 @@ CONFIG_CMD_CRC=y
# CONFIG_CMD_MTEST is not set
#
-# flash
+# flash
#
CONFIG_CMD_FLASH=y
#
-# booting
+# booting
#
CONFIG_CMD_BOOTM=y
# CONFIG_CMD_BOOTM_ZLIB is not set
@@ -182,7 +182,8 @@ CONFIG_CMD_TEST=y
CONFIG_CMD_VERSION=y
CONFIG_CMD_HELP=y
CONFIG_CMD_DEVINFO=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_BMP=y
+# CONFIG_CMD_GPIO is not set
CONFIG_NET=y
CONFIG_NET_DHCP=y
# CONFIG_NET_RARP is not set
@@ -191,11 +192,11 @@ CONFIG_NET_PING=y
CONFIG_NET_TFTP=y
#
-# Drivers
+# Drivers
#
#
-# serial drivers
+# serial drivers
#
# CONFIG_DRIVER_SERIAL_ARM_DCC is not set
CONFIG_DRIVER_SERIAL_IMX=y
@@ -203,39 +204,43 @@ CONFIG_DRIVER_SERIAL_IMX=y
CONFIG_MIIPHY=y
#
-# Network drivers
+# Network drivers
#
CONFIG_DRIVER_NET_SMC911X=y
CONFIG_DRIVER_NET_SMC911X_ADDRESS_SHIFT=0
# CONFIG_DRIVER_NET_SMC91111 is not set
-# CONFIG_DRIVER_NET_FEC_IMX is not set
+CONFIG_DRIVER_NET_FEC_IMX=y
#
-# SPI drivers
+# SPI drivers
#
-CONFIG_SPI=y
-# CONFIG_DRIVER_SPI_IMX is not set
-# CONFIG_DRIVER_SPI_MC13783 is not set
+# CONFIG_SPI is not set
CONFIG_I2C=y
CONFIG_DRIVER_I2C_IMX=y
CONFIG_DRIVER_I2C_MC13892=y
CONFIG_DRIVER_I2C_MC9SDZ60=y
#
-# flash drivers
+# flash drivers
#
CONFIG_HAS_CFI=y
CONFIG_DRIVER_CFI=y
# CONFIG_DRIVER_CFI_NEW is not set
CONFIG_DRIVER_CFI_OLD=y
CONFIG_CFI_BUFFER_WRITE=y
-# CONFIG_NAND is not set
+CONFIG_NAND=y
+CONFIG_NAND_IMX=y
+CONFIG_NAND_IMX_BOOT=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
# CONFIG_USB is not set
# CONFIG_USB_GADGET is not set
-# CONFIG_VIDEO is not set
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_IMX_IPU=y
#
-# Filesystem support
+# Filesystem support
#
# CONFIG_FS_CRAMFS is not set
CONFIG_FS_RAMFS=y
diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S
index c8d1bb9d..a5eaefa2 100644
--- a/arch/arm/lib/barebox.lds.S
+++ b/arch/arm/lib/barebox.lds.S
@@ -39,6 +39,11 @@ SECTIONS
_stext = .;
_text = .;
*(.text_entry*)
+#ifdef CONFIG_ARCH_EP93XX
+ /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */
+ . = 0x1000;
+ LONG(0x53555243) /* 'CRUS' */
+#endif
*(.text_bare_init*)
*(.text*)
}
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
new file mode 100644
index 00000000..ed6e9864
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -0,0 +1,438 @@
+if ARCH_EP93XX
+
+config EP93XX_SDCE0_PHYS_OFFSET
+ bool
+
+config EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ bool
+
+comment "Cirrus EP93xx System-on-Chip"
+
+choice
+ prompt "Cirrus Logic EP93XX Processor"
+
+config ARCH_EP9301
+ bool "EP9301"
+
+config ARCH_EP9302
+ bool "EP9302"
+
+config ARCH_EP9307
+ bool "EP9307"
+
+config ARCH_EP9312
+ bool "EP9312"
+
+config ARCH_EP9315
+ bool "EP9315"
+
+endchoice
+
+# ----------------------------------------------------------
+
+if ARCH_EP9301
+
+choice
+ prompt "EP9301 Board Type"
+
+config MACH_EDB9301
+ bool "Cirrus Logic EDB9301"
+ select EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9301 Evaluation board
+
+endchoice
+
+if MACH_EDB9301
+
+config BOARDINFO
+ default "Cirrus Logic EDB9301"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x05700000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 4
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0x00000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0x01000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK2_BASE
+ hex
+ default 0x04000000
+
+config EP93XX_SDRAM_BANK2_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK3_BASE
+ hex
+ default 0x05000000
+
+config EP93XX_SDRAM_BANK3_SIZE
+ hex
+ default 0x00800000
+
+endif
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_EP9302
+
+choice
+ prompt "EP9302 Board Type"
+
+config MACH_EDB9302
+ bool "Cirrus Logic EDB9302"
+ select EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9302 Evaluation board
+
+config MACH_EDB9302A
+ bool "Cirrus Logic EDB9302A"
+ select EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9302A Evaluation board
+
+endchoice
+
+if MACH_EDB9302
+
+config BOARDINFO
+ default "Cirrus Logic EDB9302"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x05700000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 4
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0x00000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0x01000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK2_BASE
+ hex
+ default 0x04000000
+
+config EP93XX_SDRAM_BANK2_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK3_BASE
+ hex
+ default 0x05000000
+
+config EP93XX_SDRAM_BANK3_SIZE
+ hex
+ default 0x00800000
+
+endif
+
+if MACH_EDB9302A
+
+config BOARDINFO
+ default "Cirrus Logic EDB9302A"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0xc5700000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 4
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0xc0000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0xc1000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK2_BASE
+ hex
+ default 0xc4000000
+
+config EP93XX_SDRAM_BANK2_SIZE
+ hex
+ default 0x00800000
+
+config EP93XX_SDRAM_BANK3_BASE
+ hex
+ default 0xc5000000
+
+config EP93XX_SDRAM_BANK3_SIZE
+ hex
+ default 0x00800000
+
+endif
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_EP9307
+
+choice
+ prompt "EP9307 Board Type"
+
+config MACH_EDB9307
+ bool "Cirrus Logic EDB9307"
+ select EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9307 Evaluation board
+
+config MACH_EDB9307A
+ bool "Cirrus Logic EDB9307A"
+ select EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9307A Evaluation board
+
+endchoice
+
+if MACH_EDB9307
+
+config BOARDINFO
+ default "Cirrus Logic EDB9307"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x01f00000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 2
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0x00000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x02000000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0x04000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x02000000
+
+endif
+
+if MACH_EDB9307A
+
+config BOARDINFO
+ default "Cirrus Logic EDB9307A"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0xc1f00000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 2
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0xc0000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x02000000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0xc4000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x02000000
+
+endif
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_EP9312
+
+choice
+ prompt "EP9312 Board Type"
+
+config MACH_EDB9312
+ bool "Cirrus Logic EDB9312"
+ select EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9312 Evaluation board
+
+endchoice
+
+if MACH_EDB9312
+
+config BOARDINFO
+ default "Cirrus Logic EDB9312"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x01f00000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 2
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0x00000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x02000000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0x04000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x02000000
+
+endif
+
+endif
+
+# ----------------------------------------------------------
+
+if ARCH_EP9315
+
+choice
+ prompt "EP9315 Board Type"
+
+config MACH_EDB9315
+ bool "Cirrus Logic EDB9315"
+ select EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9315 Evaluation board
+
+config MACH_EDB9315A
+ bool "Cirrus Logic EDB9315A"
+ select EP93XX_SDCE0_PHYS_OFFSET
+ select MACH_HAS_LOWLEVEL_INIT
+ help
+ Say y here if you are using Cirrus Logic's EDB9315A Evaluation board
+
+endchoice
+
+if MACH_EDB9315
+
+config BOARDINFO
+ default "Cirrus Logic EDB9315"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x01f00000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 2
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0x00000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x02000000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0x04000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x02000000
+
+endif
+
+if MACH_EDB9315A
+
+config BOARDINFO
+ default "Cirrus Logic EDB9315A"
+
+config ARCH_TEXT_BASE
+ hex
+ default 0xc1f00000
+
+config EP93XX_SDRAM_NUM_BANKS
+ int
+ default 2
+
+config EP93XX_SDRAM_BANK0_BASE
+ hex
+ default 0xc0000000
+
+config EP93XX_SDRAM_BANK0_SIZE
+ hex
+ default 0x02000000
+
+config EP93XX_SDRAM_BANK1_BASE
+ hex
+ default 0xc4000000
+
+config EP93XX_SDRAM_BANK1_SIZE
+ hex
+ default 0x02000000
+
+endif
+
+endif
+
+endif
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
new file mode 100644
index 00000000..dac65717
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -0,0 +1,3 @@
+obj-y += clocksource.o gpio.o led.o
+
+obj-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += lowlevel_init.o
diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c
new file mode 100644
index 00000000..2a7d90e4
--- /dev/null
+++ b/arch/arm/mach-ep93xx/clocksource.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <asm/io.h>
+#include <mach/ep93xx-regs.h>
+
+#define TIMER_CLKSEL (1 << 3)
+#define TIMER_MODE (1 << 6)
+#define TIMER_ENABLE (1 << 7)
+
+#define TIMER_FREQ 508469
+
+static uint64_t ep93xx_clocksource_read(void)
+{
+ struct timer_regs *timer = (struct timer_regs *)TIMER_BASE;
+
+ return 0xffffffff - readl(&timer->timer3.value);
+}
+
+static struct clocksource cs = {
+ .read = ep93xx_clocksource_read,
+ .mask = 0xffffffff,
+ .shift = 10,
+};
+
+static int clocksource_init(void)
+{
+ struct timer_regs *timer = (struct timer_regs *)TIMER_BASE;
+
+ /* use timer 3 with 508KHz and free running */
+ writel(TIMER_CLKSEL,
+ &timer->timer3.control);
+
+ /* load timer 3 with max value */
+ writel(0xffffffff, &timer->timer3.load);
+
+ /* enable timer 3 with 508KHz and periodic mode */
+ writel(TIMER_ENABLE | TIMER_MODE | TIMER_CLKSEL,
+ &timer->timer3.control);
+
+ cs.mult = clocksource_hz2mult(TIMER_FREQ, cs.shift);
+
+ init_clock(&cs);
+
+ return 0;
+}
+
+core_initcall(clocksource_init);
+
+/*
+ * Reset the cpu
+ */
+void reset_cpu(ulong ignored)
+{
+ struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+ uint32_t value;
+
+ /* Unlock DeviceCfg and set SWRST */
+ writel(0xAA, &syscon->sysswlock);
+ value = readl(&syscon->devicecfg);
+ value |= SYSCON_DEVICECFG_SWRST;
+ writel(value, &syscon->devicecfg);
+
+ /* Unlock DeviceCfg and clear SWRST */
+ writel(0xAA, &syscon->sysswlock);
+ value = readl(&syscon->devicecfg);
+ value &= ~SYSCON_DEVICECFG_SWRST;
+ writel(value, &syscon->devicecfg);
+
+ /* Dying... */
+ while (1)
+ ; /* noop */
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
new file mode 100644
index 00000000..5d574340
--- /dev/null
+++ b/arch/arm/mach-ep93xx/gpio.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ *
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <init.h>
+#include <asm/io.h>
+#include <mach/ep93xx-regs.h>
+
+#define EP93XX_GPIO_NUM_PORTS 8
+#define EP93XX_GPIO_NUM_GPIOS (EP93XX_GPIO_NUM_PORTS * 8)
+
+struct gpio_port {
+ uint32_t *dr;
+ uint32_t *ddr;
+};
+
+struct gpio_port gpio_ports[EP93XX_GPIO_NUM_PORTS];
+
+static int ep93xx_gpio_init(void)
+{
+ struct gpio_regs *gpio_regs = (struct gpio_regs *)GPIO_BASE;
+
+ gpio_ports[0].dr = &gpio_regs->padr;
+ gpio_ports[0].ddr = &gpio_regs->paddr;
+ gpio_ports[1].dr = &gpio_regs->pbdr;
+ gpio_ports[1].ddr = &gpio_regs->pbddr;
+ gpio_ports[2].dr = &gpio_regs->pcdr;
+ gpio_ports[2].ddr = &gpio_regs->pcddr;
+ gpio_ports[3].dr = &gpio_regs->pddr;
+ gpio_ports[3].ddr = &gpio_regs->pdddr;
+ gpio_ports[4].dr = &gpio_regs->pedr;
+ gpio_ports[4].ddr = &gpio_regs->peddr;
+ gpio_ports[5].dr = &gpio_regs->pfdr;
+ gpio_ports[5].ddr = &gpio_regs->pfddr;
+ gpio_ports[6].dr = &gpio_regs->pgdr;
+ gpio_ports[6].ddr = &gpio_regs->pgddr;
+ gpio_ports[7].dr = &gpio_regs->phdr;
+ gpio_ports[7].ddr = &gpio_regs->phddr;
+
+ return 0;
+}
+
+postcore_initcall(ep93xx_gpio_init);
+
+static struct gpio_port *gpio_get_port(unsigned gpio)
+{
+ if (gpio >= EP93XX_GPIO_NUM_GPIOS)
+ return 0;
+
+ return &gpio_ports[gpio / 8];
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ struct gpio_port *port = gpio_get_port(gpio);
+ const int shift = gpio % 8;
+ u32 val;
+
+ if (!port)
+ return;
+
+ val = readl(port->dr);
+
+ if (value)
+ val |= 1 << shift;
+ else
+ val &= ~(1 << shift);
+
+ writel(val, port->dr);
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ struct gpio_port *port = gpio_get_port(gpio);
+ const int shift = gpio % 8;
+ u32 val;
+
+ if (!port)
+ return -EINVAL;
+
+ val = readl(port->ddr);
+ val &= ~(1 << shift);
+ writel(val, port->ddr);
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ struct gpio_port *port = gpio_get_port(gpio);
+ const int shift = gpio % 8;
+ u32 val;
+
+ if (!port)
+ return -EINVAL;
+
+ gpio_set_value(gpio, value);
+
+ val = readl(port->ddr);
+ val |= 1 << shift;
+ writel(val, port->ddr);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct gpio_port *port = gpio_get_port(gpio);
+ const int shift = gpio % 8;
+ u32 val;
+
+ if (!port)
+ return -EINVAL;
+
+ val = readl(port->dr);
+
+ return val & (1 << shift) ? 1 : 0;
+}
+
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
new file mode 100644
index 00000000..50bb0eb4
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -0,0 +1,600 @@
+/* -----------------------------------------------------------------------------
+ * Cirrus Logic EP93xx register definitions.
+ *
+ * Copyright (C) 2009
+ * Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2006
+ * Dominic Rath <Dominic.Rath@gmx.de>
+ *
+ * Copyright (C) 2004, 2005
+ * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+ *
+ * Based in large part on linux/include/asm-arm/arch-ep93xx/regmap.h, which is
+ *
+ * Copyright (C) 2004 Ray Lehtiniemi
+ * Copyright (C) 2003 Cirrus Logic, Inc
+ * Copyright (C) 1999 ARM Limited.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+
+#define EP93XX_AHB_BASE 0x80000000
+#define EP93XX_APB_BASE 0x80800000
+
+/* -----------------------------------------------------------------------------
+ * 0x80000000 - 0x8000FFFF: DMA
+ */
+#define DMA_OFFSET 0x000000
+#define DMA_BASE (EP93XX_AHB_BASE | DMA_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct dma_channel {
+ uint32_t control;
+ uint32_t interrupt;
+ uint32_t ppalloc;
+ uint32_t status;
+ uint32_t reserved0;
+ uint32_t remain;
+ uint32_t reserved1[2];
+ uint32_t maxcnt0;
+ uint32_t base0;
+ uint32_t current0;
+ uint32_t reserved2;
+ uint32_t maxcnt1;
+ uint32_t base1;
+ uint32_t current1;
+ uint32_t reserved3;
+};
+
+struct dma_regs {
+ struct dma_channel m2p_channel_0;
+ struct dma_channel m2p_channel_1;
+ struct dma_channel m2p_channel_2;
+ struct dma_channel m2p_channel_3;
+ struct dma_channel m2m_channel_0;
+ struct dma_channel m2m_channel_1;
+ struct dma_channel reserved0[2];
+ struct dma_channel m2p_channel_5;
+ struct dma_channel m2p_channel_4;
+ struct dma_channel m2p_channel_7;
+ struct dma_channel m2p_channel_6;
+ struct dma_channel m2p_channel_9;
+ struct dma_channel m2p_channel_8;
+ uint32_t channel_arbitration;
+ uint32_t reserved[15];
+ uint32_t global_interrupt;
+};
+#endif
+
+/* -----------------------------------------------------------------------------
+ * 0x80010000 - 0x8001FFFF: Ethernet MAC
+ */
+#define MAC_OFFSET 0x010000
+#define MAC_BASE (EP93XX_AHB_BASE | MAC_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct mac_queue {
+ uint32_t badd;
+ union { /* deal with half-word aligned registers */
+ uint32_t blen;
+ union {
+ uint16_t filler;
+ uint16_t curlen;
+ };
+ };
+ uint32_t curadd;
+};
+
+struct mac_regs {
+ uint32_t rxctl;
+ uint32_t txctl;
+ uint32_t testctl;
+ uint32_t reserved0;
+ uint32_t miicmd;
+ uint32_t miidata;
+ uint32_t miists;
+ uint32_t reserved1;
+ uint32_t selfctl;
+ uint32_t inten;
+ uint32_t intstsp;
+ uint32_t intstsc;
+ uint32_t reserved2[2];
+ uint32_t diagad;
+ uint32_t diagdata;
+ uint32_t gt;
+ uint32_t fct;
+ uint32_t fcf;
+ uint32_t afp;
+ union {
+ struct {
+ uint32_t indad;
+ uint32_t indad_upper;
+ };
+ uint32_t hashtbl;
+ };
+ uint32_t reserved3[2];
+ uint32_t giintsts;
+ uint32_t giintmsk;
+ uint32_t giintrosts;
+ uint32_t giintfrc;
+ uint32_t txcollcnt;
+ uint32_t rxmissnct;
+ uint32_t rxruntcnt;
+ uint32_t reserved4;
+ uint32_t bmctl;
+ uint32_t bmsts;
+ uint32_t rxbca;
+ uint32_t reserved5;
+ struct mac_queue rxdq;
+ uint32_t rxdqenq;
+ struct mac_queue rxstsq;
+ uint32_t rxstsqenq;
+ struct mac_queue txdq;
+ uint32_t txdqenq;
+ struct mac_queue txstsq;
+ uint32_t reserved6;
+ uint32_t rxbufthrshld;
+ uint32_t txbufthrshld;
+ uint32_t rxststhrshld;
+ uint32_t txststhrshld;
+ uint32_t rxdthrshld;
+ uint32_t txdthrshld;
+ uint32_t maxfrmlen;
+ uint32_t maxhdrlen;
+};
+#endif
+
+#define SELFCTL_RWP (1 << 7)
+#define SELFCTL_GPO0 (1 << 5)
+#define SELFCTL_PUWE (1 << 4)
+#define SELFCTL_PDWE (1 << 3)
+#define SELFCTL_MIIL (1 << 2)
+#define SELFCTL_RESET (1 << 0)
+
+#define INTSTS_RWI (1 << 30)
+#define INTSTS_RXMI (1 << 29)
+#define INTSTS_RXBI (1 << 28)
+#define INTSTS_RXSQI (1 << 27)
+#define INTSTS_TXLEI (1 << 26)
+#define INTSTS_ECIE (1 << 25)
+#define INTSTS_TXUHI (1 << 24)
+#define INTSTS_MOI (1 << 18)
+#define INTSTS_TXCOI (1 << 17)
+#define INTSTS_RXROI (1 << 16)
+#define INTSTS_MIII (1 << 12)
+#define INTSTS_PHYI (1 << 11)
+#define INTSTS_TI (1 << 10)
+#define INTSTS_AHBE (1 << 8)
+#define INTSTS_OTHER (1 << 4)
+#define INTSTS_TXSQ (1 << 3)
+#define INTSTS_RXSQ (1 << 2)
+
+#define BMCTL_MT (1 << 13)
+#define BMCTL_TT (1 << 12)
+#define BMCTL_UNH (1 << 11)
+#define BMCTL_TXCHR (1 << 10)
+#define BMCTL_TXDIS (1 << 9)
+#define BMCTL_TXEN (1 << 8)
+#define BMCTL_EH2 (1 << 6)
+#define BMCTL_EH1 (1 << 5)
+#define BMCTL_EEOB (1 << 4)
+#define BMCTL_RXCHR (1 << 2)
+#define BMCTL_RXDIS (1 << 1)
+#define BMCTL_RXEN (1 << 0)
+
+#define BMSTS_TXACT (1 << 7)
+#define BMSTS_TP (1 << 4)
+#define BMSTS_RXACT (1 << 3)
+#define BMSTS_QID_MASK 0x07
+#define BMSTS_QID_RXDATA 0x00
+#define BMSTS_QID_TXDATA 0x01
+#define BMSTS_QID_RXSTS 0x02
+#define BMSTS_QID_TXSTS 0x03
+#define BMSTS_QID_RXDESC 0x04
+#define BMSTS_QID_TXDESC 0x05
+
+#define AFP_MASK 0x07
+#define AFP_IAPRIMARY 0x00
+#define AFP_IASECONDARY1 0x01
+#define AFP_IASECONDARY2 0x02
+#define AFP_IASECONDARY3 0x03
+#define AFP_TX 0x06
+#define AFP_HASH 0x07
+
+#define RXCTL_PAUSEA (1 << 20)
+#define RXCTL_RXFCE1 (1 << 19)
+#define RXCTL_RXFCE0 (1 << 18)
+#define RXCTL_BCRC (1 << 17)
+#define RXCTL_SRXON (1 << 16)
+#define RXCTL_RCRCA (1 << 13)
+#define RXCTL_RA (1 << 12)
+#define RXCTL_PA (1 << 11)
+#define RXCTL_BA (1 << 10)
+#define RXCTL_MA (1 << 9)
+#define RXCTL_IAHA (1 << 8)
+#define RXCTL_IA3 (1 << 3)
+#define RXCTL_IA2 (1 << 2)
+#define RXCTL_IA1 (1 << 1)
+#define RXCTL_IA0 (1 << 0)
+
+#define TXCTL_DEFDIS (1 << 7)
+#define TXCTL_MBE (1 << 6)
+#define TXCTL_ICRC (1 << 5)
+#define TXCTL_TPD (1 << 4)
+#define TXCTL_OCOLL (1 << 3)
+#define TXCTL_SP (1 << 2)
+#define TXCTL_PB (1 << 1)
+#define TXCTL_STXON (1 << 0)
+
+#define MIICMD_REGAD_MASK (0x001F)
+#define MIICMD_PHYAD_MASK (0x03E0)
+#define MIICMD_OPCODE_MASK (0xC000)
+#define MIICMD_PHYAD_8950 (0x0000)
+#define MIICMD_OPCODE_READ (0x8000)
+#define MIICMD_OPCODE_WRITE (0x4000)
+
+#define MIISTS_BUSY (1 << 0)
+
+/* -----------------------------------------------------------------------------
+ * 0x80020000 - 0x8002FFFF: USB OHCI
+ */
+#define USB_OFFSET 0x020000
+#define USB_BASE (EP93XX_AHB_BASE | USB_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80030000 - 0x8003FFFF: Raster engine
+ */
+#if (defined(CONFIG_EP9307) || defined(CONFIG_EP9312) || defined(CONFIG_EP9315))
+#define RASTER_OFFSET 0x030000
+#define RASTER_BASE (EP93XX_AHB_BASE | RASTER_OFFSET)
+#endif
+
+/* -----------------------------------------------------------------------------
+ * 0x80040000 - 0x8004FFFF: Graphics accelerator
+ */
+#if defined(CONFIG_EP9315)
+#define GFX_OFFSET 0x040000
+#define GFX_BASE (EP93XX_AHB_BASE | GFX_OFFSET)
+#endif
+
+/* -----------------------------------------------------------------------------
+ * 0x80050000 - 0x8005FFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x80060000 - 0x8006FFFF: SDRAM controller
+ */
+#define SDRAM_OFFSET 0x060000
+#define SDRAM_BASE (EP93XX_AHB_BASE | SDRAM_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct sdram_regs {
+ uint32_t reserved;
+ uint32_t glconfig;
+ uint32_t refrshtimr;
+ uint32_t bootsts;
+ uint32_t devcfg0;
+ uint32_t devcfg1;
+ uint32_t devcfg2;
+ uint32_t devcfg3;
+};
+#endif
+
+#define SDRAM_DEVCFG_EXTBUSWIDTH (1 << 2)
+#define SDRAM_DEVCFG_BANKCOUNT (1 << 3)
+#define SDRAM_DEVCFG_SROMLL (1 << 5)
+#define SDRAM_DEVCFG_CASLAT_2 0x00010000
+#define SDRAM_DEVCFG_RASTOCAS_2 0x00200000
+
+#define GLCONFIG_INIT (1 << 0)
+#define GLCONFIG_MRS (1 << 1)
+#define GLCONFIG_SMEMBUSY (1 << 5)
+#define GLCONFIG_LCR (1 << 6)
+#define GLCONFIG_REARBEN (1 << 7)
+#define GLCONFIG_CLKSHUTDOWN (1 << 30)
+#define GLCONFIG_CKE (1 << 31)
+
+/* -----------------------------------------------------------------------------
+ * 0x80070000 - 0x8007FFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x80080000 - 0x8008FFFF: SRAM controller & PCMCIA
+ */
+#define SMC_OFFSET 0x080000
+#define SMC_BASE (EP93XX_AHB_BASE | SMC_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct smc_regs {
+ uint32_t bcr0;
+ uint32_t bcr1;
+ uint32_t bcr2;
+ uint32_t bcr3;
+ uint32_t reserved0[2];
+ uint32_t bcr6;
+ uint32_t bcr7;
+#if defined(CONFIG_EP9315)
+ uint32_t pcattribute;
+ uint32_t pccommon;
+ uint32_t pcio;
+ uint32_t reserved1[5];
+ uint32_t pcmciactrl;
+#endif
+};
+#endif
+
+#define SMC_BCR_IDCY_SHIFT 0
+#define SMC_BCR_WST1_SHIFT 5
+#define SMC_BCR_BLE (1 << 10)
+#define SMC_BCR_WST2_SHIFT 11
+#define SMC_BCR_MW_SHIFT 28
+
+/* -----------------------------------------------------------------------------
+ * 0x80090000 - 0x8009FFFF: Boot ROM
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x800A0000 - 0x800AFFFF: IDE interface
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x800B0000 - 0x800BFFFF: VIC1
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x800C0000 - 0x800CFFFF: VIC2
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x800D0000 - 0x800FFFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x80800000 - 0x8080FFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x80810000 - 0x8081FFFF: Timers
+ */
+#define TIMER_OFFSET 0x010000
+#define TIMER_BASE (EP93XX_APB_BASE | TIMER_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct timer {
+ uint32_t load;
+ uint32_t value;
+ uint32_t control;
+ uint32_t clear;
+};
+
+struct timer4 {
+ uint32_t value_low;
+ uint32_t value_high;
+};
+
+struct timer_regs {
+ struct timer timer1;
+ uint32_t reserved0[4];
+ struct timer timer2;
+ uint32_t reserved1[12];
+ struct timer4 timer4;
+ uint32_t reserved2[6];
+ struct timer timer3;
+};
+#endif
+
+/* -----------------------------------------------------------------------------
+ * 0x80820000 - 0x8082FFFF: I2S
+ */
+#define I2S_OFFSET 0x020000
+#define I2S_BASE (EP93XX_APB_BASE | I2S_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80830000 - 0x8083FFFF: Security
+ */
+#define SECURITY_OFFSET 0x030000
+#define SECURITY_BASE (EP93XX_APB_BASE | SECURITY_OFFSET)
+
+#define EXTENSIONID (SECURITY_BASE + 0x2714)
+
+/* -----------------------------------------------------------------------------
+ * 0x80840000 - 0x8084FFFF: GPIO
+ */
+#define GPIO_OFFSET 0x040000
+#define GPIO_BASE (EP93XX_APB_BASE | GPIO_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct gpio_int {
+ uint32_t inttype1;
+ uint32_t inttype2;
+ uint32_t eoi;
+ uint32_t inten;
+ uint32_t intsts;
+ uint32_t rawintsts;
+ uint32_t db;
+};
+
+struct gpio_regs {
+ uint32_t padr;
+ uint32_t pbdr;
+ uint32_t pcdr;
+ uint32_t pddr;
+ uint32_t paddr;
+ uint32_t pbddr;
+ uint32_t pcddr;
+ uint32_t pdddr;
+ uint32_t pedr;
+ uint32_t peddr;
+ uint32_t reserved0[2];
+ uint32_t pfdr;
+ uint32_t pfddr;
+ uint32_t pgdr;
+ uint32_t pgddr;
+ uint32_t phdr;
+ uint32_t phddr;
+ uint32_t reserved1;
+ uint32_t finttype1;
+ uint32_t finttype2;
+ uint32_t reserved2;
+ struct gpio_int pfint;
+ uint32_t reserved3[10];
+ struct gpio_int paint;
+ struct gpio_int pbint;
+ uint32_t eedrive;
+};
+#endif
+
+/* -----------------------------------------------------------------------------
+ * 0x80850000 - 0x8087FFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x80880000 - 0x8088FFFF: AAC
+ */
+#define AAC_OFFSET 0x080000
+#define AAC_BASE (EP93XX_APB_BASE | AAC_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80890000 - 0x8089FFFF: Reserved
+ */
+
+/* -----------------------------------------------------------------------------
+ * 0x808A0000 - 0x808AFFFF: SPI
+ */
+#define SPI_OFFSET 0x0A0000
+#define SPI_BASE (EP93XX_APB_BASE | SPI_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x808B0000 - 0x808BFFFF: IrDA
+ */
+#define IRDA_OFFSET 0x0B0000
+#define IRDA_BASE (EP93XX_APB_BASE | IRDA_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x808C0000 - 0x808CFFFF: UART1
+ */
+#define UART1_OFFSET 0x0C0000
+#define UART1_BASE (EP93XX_APB_BASE | UART1_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x808D0000 - 0x808DFFFF: UART2
+ */
+#define UART2_OFFSET 0x0D0000
+#define UART2_BASE (EP93XX_APB_BASE | UART2_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x808E0000 - 0x808EFFFF: UART3
+ */
+#define UART3_OFFSET 0x0E0000
+#define UART3_BASE (EP93XX_APB_BASE | UART3_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x808F0000 - 0x808FFFFF: Key Matrix
+ */
+#define KEY_OFFSET 0x0F0000
+#define KEY_BASE (EP93XX_APB_BASE | KEY_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80900000 - 0x8090FFFF: Touchscreen
+ */
+#define TOUCH_OFFSET 0x900000
+#define TOUCH_BASE (EP93XX_APB_BASE | TOUCH_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80910000 - 0x8091FFFF: Pulse Width Modulation
+ */
+#define PWM_OFFSET 0x910000
+#define PWM_BASE (EP93XX_APB_BASE | PWM_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80920000 - 0x8092FFFF: Real time clock
+ */
+#define RTC_OFFSET 0x920000
+#define RTC_BASE (EP93XX_APB_BASE | RTC_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80930000 - 0x8093FFFF: Syscon
+ */
+#define SYSCON_OFFSET 0x930000
+#define SYSCON_BASE (EP93XX_APB_BASE | SYSCON_OFFSET)
+
+#ifndef __ASSEMBLY__
+struct syscon_regs {
+ uint32_t pwrsts;
+ uint32_t pwrcnt;
+ uint32_t halt;
+ uint32_t stby;
+ uint32_t reserved0[2];
+ uint32_t teoi;
+ uint32_t stfclr;
+ uint32_t clkset1;
+ uint32_t clkset2;
+ uint32_t reserved1[6];
+ uint32_t scratch0;
+ uint32_t scratch1;
+ uint32_t reserved2[2];
+ uint32_t apbwait;
+ uint32_t bustmstrarb;
+ uint32_t bootmodeclr;
+ uint32_t reserved3[9];
+ uint32_t devicecfg;
+ uint32_t vidclkdiv;
+ uint32_t mirclkdiv;
+ uint32_t i2sclkdiv;
+ uint32_t keytchclkdiv;
+ uint32_t chipid;
+ uint32_t syscfg;
+ uint32_t reserved4[8];
+ uint32_t sysswlock;
+};
+#else
+#define SYSCON_SCRATCH0 (SYSCON_BASE + 0x0040)
+#endif
+
+#define SYSCON_PWRCNT_UART_BAUD (1 << 29)
+
+#define SYSCON_CLKSET_PLL_X2IPD_SHIFT 0
+#define SYSCON_CLKSET_PLL_X2FBD2_SHIFT 5
+#define SYSCON_CLKSET_PLL_X1FBD1_SHIFT 11
+#define SYSCON_CLKSET_PLL_PS_SHIFT 16
+#define SYSCON_CLKSET1_PCLK_DIV_SHIFT 18
+#define SYSCON_CLKSET1_HCLK_DIV_SHIFT 20
+#define SYSCON_CLKSET1_NBYP1 (1 << 23)
+#define SYSCON_CLKSET1_FCLK_DIV_SHIFT 25
+
+#define SYSCON_CLKSET2_PLL2_EN (1 << 18)
+#define SYSCON_CLKSET2_NBYP2 (1 << 19)
+#define SYSCON_CLKSET2_USB_DIV_SHIFT 28
+
+#define SYSCON_CHIPID_REV_MASK 0xF0000000
+#define SYSCON_DEVICECFG_SWRST (1 << 31)
+
+/* -----------------------------------------------------------------------------
+ * 0x80930000 - 0x8093FFFF: Watchdog Timer
+ */
+#define WATCHDOG_OFFSET 0x940000
+#define WATCHDOG_BASE (EP93XX_APB_BASE | WATCHDOG_OFFSET)
+
+/* -----------------------------------------------------------------------------
+ * 0x80950000 - 0x9000FFFF: Reserved
+ */
+
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
new file mode 100644
index 00000000..a305f274
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/gpio.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ *
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+void gpio_set_value(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_direction_input(unsigned gpio);
+
+#endif /* __ASM_ARCH_GPIO_H */
+
diff --git a/arch/arm/mach-ep93xx/led.c b/arch/arm/mach-ep93xx/led.c
new file mode 100644
index 00000000..6d6b9023
--- /dev/null
+++ b/arch/arm/mach-ep93xx/led.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/ep93xx-regs.h>
+
+#define GREEN_LED_POS 0x01
+#define RED_LED_POS 0x02
+
+inline void switch_LED_on(uint32_t bit_pos)
+{
+ register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE;
+
+ writel(readl(&gpio->pedr) | bit_pos, &gpio->pedr);
+}
+
+inline void switch_LED_off(uint32_t bit_pos)
+{
+ register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE;
+
+ writel(readl(&gpio->pedr) & ~bit_pos, &gpio->pedr);
+}
+
+void red_LED_on(void)
+{
+ switch_LED_on(RED_LED_POS);
+}
+
+void red_LED_off(void)
+{
+ switch_LED_off(RED_LED_POS);
+}
+
+void green_LED_on(void)
+{
+ switch_LED_on(GREEN_LED_POS);
+}
+
+void green_LED_off(void)
+{
+ switch_LED_off(GREEN_LED_POS);
+}
diff --git a/arch/arm/mach-ep93xx/led.h b/arch/arm/mach-ep93xx/led.h
new file mode 100644
index 00000000..db9512fc
--- /dev/null
+++ b/arch/arm/mach-ep93xx/led.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+extern void red_LED_on(void);
+extern void red_LED_off(void);
+extern void green_LED_on(void);
+extern void green_LED_off(void);
diff --git a/arch/arm/mach-ep93xx/lowlevel_init.S b/arch/arm/mach-ep93xx/lowlevel_init.S
new file mode 100644
index 00000000..27c2c90b
--- /dev/null
+++ b/arch/arm/mach-ep93xx/lowlevel_init.S
@@ -0,0 +1,64 @@
+/*
+ * Low-level initialization for EP93xx
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ *
+ * 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
+ */
+
+#include <mach/ep93xx-regs.h>
+
+.globl board_init_lowlevel
+board_init_lowlevel:
+ /* backup return address */
+ ldr r1, =SYSCON_SCRATCH0
+ str lr, [r1]
+
+ /* Turn on both LEDs */
+ bl red_LED_on
+ bl green_LED_on
+
+ /* Configure flash wait states before we switch to the PLL */
+ bl flash_cfg
+
+ /* Set up PLL */
+ bl pll_cfg
+
+ /* Turn off the Green LED and leave the Red LED on */
+ bl green_LED_off
+
+ /* Setup SDRAM */
+ bl sdram_cfg
+
+ /* Turn on Green LED, Turn off the Red LED */
+ bl green_LED_on
+ bl red_LED_off
+
+ /* switch to async mode */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #0xc0000000
+ mcr p15, 0, r0, c1, c0, 0
+
+ /* restore return address */
+ ldr r1, =SYSCON_SCRATCH0
+ ldr lr, [r1]
+
+ mov pc, lr
diff --git a/arch/arm/mach-imx/include/mach/imx27-regs.h b/arch/arm/mach-imx/include/mach/imx27-regs.h
index 33d67d6f..6c31ccd9 100644
--- a/arch/arm/mach-imx/include/mach/imx27-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx27-regs.h
@@ -16,6 +16,7 @@
#define IMX_UART2_BASE (0x0b000 + IMX_IO_BASE)
#define IMX_UART3_BASE (0x0c000 + IMX_IO_BASE)
#define IMX_UART4_BASE (0x0d000 + IMX_IO_BASE)
+#define IMX_I2C1_BASE (0x12000 + IMX_IO_BASE)
#define IMX_GPIO_BASE (0x15000 + IMX_IO_BASE)
#define IMX_TIM4_BASE (0x19000 + IMX_IO_BASE)
#define IMX_TIM5_BASE (0x1a000 + IMX_IO_BASE)
diff --git a/arch/arm/mach-imx/speed-imx27.c b/arch/arm/mach-imx/speed-imx27.c
index deaca1eb..cdcd4191 100644
--- a/arch/arm/mach-imx/speed-imx27.c
+++ b/arch/arm/mach-imx/speed-imx27.c
@@ -154,6 +154,11 @@ ulong imx_get_lcdclk(void)
return imx_get_perclk3();
}
+ulong imx_get_i2cclk(void)
+{
+ return imx_get_ipgclk();
+}
+
void imx_dump_clocks(void)
{
uint32_t cid = CID;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
new file mode 100644
index 00000000..6e70760f
--- /dev/null
+++ b/arch/x86/Kconfig
@@ -0,0 +1,67 @@
+#
+#
+#
+config ARCH_TEXT_BASE
+ hex
+ default 0x00007c00 if MACH_X86_GENERIC
+
+config BOARDINFO
+ default "Generic x86 bootloader" if MACH_X86_GENERIC
+
+config BOARD_LINKER_SCRIPT
+ bool
+ default n
+
+config GENERIC_LINKER_SCRIPT
+ bool
+ default y
+ depends on !BOARD_LINKER_SCRIPT
+
+config X86
+ bool
+ select HAS_KALLSYMS
+ select HAS_MODULES
+ select HAVE_CONFIGURABLE_MEMORY_LAYOUT
+ select HAVE_CONFIGURABLE_TEXT_BASE
+ default y
+
+choice
+ prompt "Select your board"
+
+config MACH_X86_GENERIC
+ bool "Generic x86"
+ select X86_BOOTLOADER
+ help
+ Say Y here if you want barebox to be your BIOS based bootloader
+
+endchoice
+
+choice
+ prompt "Bring up type"
+
+ config X86_BIOS_BRINGUP
+ prompt "16 bit BIOS"
+ bool
+ help
+ Barebox will act as a BIOS based bootloader. This includes
+ some 16 bit real mode code and some restrictions everyone knows
+ from BIOS based systems.
+
+ config X86_NATIVE_BRINGUP
+ bool "native"
+ help
+ Barebox will act as a native bootloader. This includes all the
+ required initialization needed to bring up a piece of hardware.
+ Note: Not implemented yet
+
+endchoice
+
+source arch/x86/boot/Kconfig
+source arch/x86/mach-i386/Kconfig
+
+source common/Kconfig
+source commands/Kconfig
+source net/Kconfig
+source drivers/Kconfig
+source fs/Kconfig
+source lib/Kconfig
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
new file mode 100644
index 00000000..2e2cb810
--- /dev/null
+++ b/arch/x86/Makefile
@@ -0,0 +1,50 @@
+CPPFLAGS += -D__X86__ -fno-strict-aliasing
+
+board-y := x86_generic
+machine-y := i386
+
+TEXT_BASE = $(CONFIG_TEXT_BASE)
+
+CPPFLAGS += -march=i386 -DTEXT_BASE=$(TEXT_BASE) -P
+
+ifndef CONFIG_MODULES
+# Add cleanup flags
+CPPFLAGS += -fdata-sections -ffunction-sections
+LDFLAGS_uboot += -static --gc-sections
+endif
+
+ifeq ($(incdir-y),)
+incdir-y := $(machine-y)
+endif
+INCDIR := arch-$(incdir-y)
+
+all: $(KBUILD_IMAGE)
+
+
+
+
+
+
+ifneq ($(board-y),)
+BOARD := board/$(board-y)/
+else
+BOARD :=
+endif
+
+ifneq ($(machine-y),)
+MACH := arch/x86/mach-$(machine-y)/
+else
+MACH :=
+endif
+
+common-y += $(BOARD) $(MACH)
+common-y += arch/x86/lib/
+common-y += arch/x86/boot/
+
+# arch/x86/cpu/
+
+lds-$(CONFIG_GENERIC_LINKER_SCRIPT) := arch/x86/lib/barebox.lds
+lds-$(CONFIG_BOARD_LINKER_SCRIPT) := $(BOARD)/barebox.lds
+
+CLEAN_FILES += arch/x86/lib/barebox.lds barebox.map barebox.S
+
diff --git a/arch/x86/boot/Kconfig b/arch/x86/boot/Kconfig
new file mode 100644
index 00000000..cdb82e46
--- /dev/null
+++ b/arch/x86/boot/Kconfig
@@ -0,0 +1,20 @@
+if X86_BIOS_BRINGUP
+
+menu "BIOS boot source "
+
+config X86_HDBOOT
+ bool "HD boot"
+ help
+ Add code to boot from harddisk
+
+config X86_VESA
+ bool
+ default y if X86_GENERIC_HAS_VIDEO
+
+config X86_VGA
+ bool
+ default y if X86_GENERIC_HAS_VIDEO
+
+endmenu
+
+endif
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
new file mode 100644
index 00000000..b92b4750
--- /dev/null
+++ b/arch/x86/boot/Makefile
@@ -0,0 +1,13 @@
+
+CPPFLAGS += -D__I386__ -fno-strict-aliasing -m32 -g -Os -march=i386 \
+ -mregparm=3 -fno-strict-aliasing -fomit-frame-pointer -ffreestanding \
+ -fno-toplevel-reorder -fno-unit-at-a-time -fno-stack-protector \
+ -mpreferred-stack-boundary=2
+
+obj-$(CONFIG_X86_HDBOOT) += boot_main.o boot_hdisk.o
+
+obj-$(CONFIG_X86_BIOS_BRINGUP) += prepare_uboot.o a20.o bioscall.o regs.o tty.o pmjump.o main_entry.o
+
+obj-$(CONFIG_X86_VESA) += console_vesa.o
+obj-$(CONFIG_X86_VGA) += console_vga.o
+obj-$(CONFIG_X86_SERIAL) += console_serial.o
diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c
new file mode 100644
index 00000000..4b61d919
--- /dev/null
+++ b/arch/x86/boot/a20.c
@@ -0,0 +1,170 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007-2008 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Enable A20 gate (return -1 on failure)
+ */
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include "boot.h"
+
+#define MAX_8042_LOOPS 100000
+#define MAX_8042_FF 32
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+static int __bootcode empty_8042(void)
+{
+ u8 status;
+ int loops = MAX_8042_LOOPS;
+ int ffs = MAX_8042_FF;
+
+ while (loops--) {
+ io_delay();
+
+ status = inb(0x64);
+ if (status == 0xff) {
+ /* FF is a plausible, but very unlikely status */
+ if (!--ffs)
+ return -1; /* Assume no KBC present */
+ }
+ if (status & 1) {
+ /* Read and discard input data */
+ io_delay();
+ (void)inb(0x60);
+ } else if (!(status & 2)) {
+ /* Buffers empty, finished! */
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled. The memory address
+ used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR (4*0x80)
+#define A20_TEST_SHORT 32
+#define A20_TEST_LONG 2097152 /* 2^21 */
+
+static int __bootcode a20_test(int loops)
+{
+ int ok = 0;
+ int saved, ctr;
+
+ set_fs(0x0000);
+ set_gs(0xffff);
+
+ saved = ctr = rdfs32(A20_TEST_ADDR);
+
+ while (loops--) {
+ wrfs32(++ctr, A20_TEST_ADDR);
+ io_delay(); /* Serialize and make delay constant */
+ ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
+ if (ok)
+ break;
+ }
+
+ wrfs32(saved, A20_TEST_ADDR);
+ return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int __bootcode a20_test_short(void)
+{
+ return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+ is useful when dealing with the KBC or other slow external circuitry. */
+static int __bootcode a20_test_long(void)
+{
+ return a20_test(A20_TEST_LONG);
+}
+
+static void __bootcode enable_a20_bios(void)
+{
+ struct biosregs ireg;
+
+ initregs(&ireg);
+ ireg.ax = 0x2401;
+ intcall(0x15, &ireg, NULL);
+}
+
+static void __bootcode enable_a20_kbc(void)
+{
+ empty_8042();
+
+ outb(0xd1, 0x64); /* Command write */
+ empty_8042();
+
+ outb(0xdf, 0x60); /* A20 on */
+ empty_8042();
+
+ outb(0xff, 0x64); /* Null command, but UHCI wants it */
+ empty_8042();
+}
+
+static void __bootcode enable_a20_fast(void)
+{
+ u8 port_a;
+
+ port_a = inb(0x92); /* Configuration port A */
+ port_a |= 0x02; /* Enable A20 */
+ port_a &= ~0x01; /* Do not reset machine */
+ outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255 /* Number of times to try */
+
+int __bootcode enable_a20(void)
+{
+ int loops = A20_ENABLE_LOOPS;
+ int kbc_err;
+
+ while (loops--) {
+ /* First, check to see if A20 is already enabled
+ (legacy free, etc.) */
+ if (a20_test_short())
+ return 0;
+
+ /* Next, try the BIOS (INT 0x15, AX=0x2401) */
+ enable_a20_bios();
+ if (a20_test_short())
+ return 0;
+
+ /* Try enabling A20 through the keyboard controller */
+ kbc_err = empty_8042();
+
+ if (a20_test_short())
+ return 0; /* BIOS worked, but with delayed reaction */
+
+ if (!kbc_err) {
+ enable_a20_kbc();
+ if (a20_test_long())
+ return 0;
+ }
+
+ /* Finally, try enabling the "fast A20 gate" */
+ enable_a20_fast();
+ if (a20_test_long())
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S
new file mode 100644
index 00000000..84d2577e
--- /dev/null
+++ b/arch/x86/boot/bioscall.S
@@ -0,0 +1,99 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2 or (at your
+ * option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes
+ * touching registers they shouldn't be.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .file "bioscall.S"
+ .code16
+ .section .boot.text.intcall, "ax"
+
+ .globl intcall
+ .type intcall, @function
+intcall:
+ /* Self-modify the INT instruction. Ugly, but works. */
+ cmpb %al, 3f
+ je 1f
+ movb %al, 3f
+ jmp 1f /* Synchronize pipeline */
+1:
+ /* Save state */
+ pushfl
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Copy input state to stack frame */
+ subw $44, %sp
+ movw %dx, %si
+ movw %sp, %di
+ movw $11, %cx
+ rep; movsd
+
+ /* Pop full state from the stack */
+ popal
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popfl
+
+ /* Actual INT */
+ .byte 0xcd /* INT opcode */
+3: .byte 0
+
+ /* Push full state to the stack */
+ pushfl
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+ pushal
+
+ /* Re-establish C environment invariants */
+ cld
+ movzwl %sp, %esp
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+
+ /* Copy output state from stack frame */
+ movw 68(%esp), %di /* Original %cx == 3rd argument */
+ andw %di, %di
+ jz 4f
+ movw %sp, %si
+ movw $11, %cx
+ rep; movsd
+4: addw $44, %sp
+
+ /* Restore state and return */
+ popal
+ popw %gs
+ popw %fs
+ popfl
+ retl
+ .size intcall, .-intcall
+
+/* ------------------------------------------------------------------------ */
+ .code16
+ .section .boot.text.die, "ax"
+
+ .globl die
+ .type die, @function
+die:
+ hlt
+ jmp die
+ .size die, .-die
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
new file mode 100644
index 00000000..d98b0661
--- /dev/null
+++ b/arch/x86/boot/boot.h
@@ -0,0 +1,193 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Main declarations for the real mode code
+ */
+
+#ifndef BOOT_BOOT_H
+#define BOOT_BOOT_H
+
+#define STACK_SIZE 512 /* Minimum number of bytes for stack */
+
+/** Carry flag */
+#define X86_EFLAGS_CF 0x00000001
+
+/** PE flag */
+#define X86_CR0_PE 0x00000001
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+/* we are still in real mode here! */
+#define THIS_IS_REALMODE_CODE asm(".code16gcc");
+
+struct biosregs {
+ union {
+ struct {
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t _esp;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t _fsgs;
+ uint32_t _dses;
+ uint32_t eflags;
+ };
+ struct {
+ uint16_t di, hdi;
+ uint16_t si, hsi;
+ uint16_t bp, hbp;
+ uint16_t _sp, _hsp;
+ uint16_t bx, hbx;
+ uint16_t dx, hdx;
+ uint16_t cx, hcx;
+ uint16_t ax, hax;
+ uint16_t gs, fs;
+ uint16_t es, ds;
+ uint16_t flags, hflags;
+ };
+ struct {
+ uint8_t dil, dih, edi2, edi3;
+ uint8_t sil, sih, esi2, esi3;
+ uint8_t bpl, bph, ebp2, ebp3;
+ uint8_t _spl, _sph, _esp2, _esp3;
+ uint8_t bl, bh, ebx2, ebx3;
+ uint8_t dl, dh, edx2, edx3;
+ uint8_t cl, ch, ecx2, ecx3;
+ uint8_t al, ah, eax2, eax3;
+ };
+ };
+};
+
+/* functions in the realmode part */
+extern int enable_a20(void);
+extern void initregs(struct biosregs *regs);
+extern void intcall(uint8_t int_no, const struct biosregs *ireg, struct biosregs *oreg);
+extern void boot_puts(char*);
+extern void __attribute__((noreturn)) die(void);
+extern void __attribute__((noreturn)) protected_mode_jump(void);
+
+struct gdt_ptr {
+ uint16_t len;
+ uint32_t ptr;
+} __attribute__((packed));
+
+/* These functions are used to reference data in other segments. */
+
+static inline uint16_t ds(void)
+{
+ uint16_t seg;
+ asm("movw %%ds,%0" : "=rm" (seg));
+ return seg;
+}
+
+static inline void set_fs(uint16_t seg)
+{
+ asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+
+static inline uint16_t fs(void)
+{
+ uint16_t seg;
+ asm volatile("movw %%fs,%0" : "=rm" (seg));
+ return seg;
+}
+
+static inline void set_gs(uint16_t seg)
+{
+ asm volatile("movw %0,%%gs" : : "rm" (seg));
+}
+
+static inline uint16_t gs(void)
+{
+ uint16_t seg;
+ asm volatile("movw %%gs,%0" : "=rm" (seg));
+ return seg;
+}
+
+typedef unsigned int addr_t;
+
+static inline uint8_t rdfs8(addr_t addr)
+{
+ uint8_t v;
+ asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr));
+ return v;
+}
+static inline uint16_t rdfs16(addr_t addr)
+{
+ uint16_t v;
+ asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(uint16_t *)addr));
+ return v;
+}
+static inline uint32_t rdfs32(addr_t addr)
+{
+ uint32_t v;
+ asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
+ return v;
+}
+
+static inline void wrfs8(uint8_t v, addr_t addr)
+{
+ asm volatile("movb %1,%%fs:%0" : "+m" (*(uint8_t *)addr) : "qi" (v));
+}
+static inline void wrfs16(uint16_t v, addr_t addr)
+{
+ asm volatile("movw %1,%%fs:%0" : "+m" (*(uint16_t *)addr) : "ri" (v));
+}
+static inline void wrfs32(uint32_t v, addr_t addr)
+{
+ asm volatile("movl %1,%%fs:%0" : "+m" (*(uint32_t *)addr) : "ri" (v));
+}
+
+static inline uint8_t rdgs8(addr_t addr)
+{
+ uint8_t v;
+ asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr));
+ return v;
+}
+static inline uint16_t rdgs16(addr_t addr)
+{
+ uint16_t v;
+ asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(uint16_t *)addr));
+ return v;
+}
+static inline uint32_t rdgs32(addr_t addr)
+{
+ uint32_t v;
+ asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
+ return v;
+}
+
+static inline void wrgs8(uint8_t v, addr_t addr)
+{
+ asm volatile("movb %1,%%gs:%0" : "+m" (*(uint8_t *)addr) : "qi" (v));
+}
+static inline void wrgs16(uint16_t v, addr_t addr)
+{
+ asm volatile("movw %1,%%gs:%0" : "+m" (*(uint16_t *)addr) : "ri" (v));
+}
+static inline void wrgs32(uint32_t v, addr_t addr)
+{
+ asm volatile("movl %1,%%gs:%0" : "+m" (*(uint32_t *)addr) : "ri" (v));
+}
+
+/** use the built in memset function for the real mode code */
+#define memset(d,c,l) __builtin_memset(d,c,l)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* BOOT_BOOT_H */
diff --git a/arch/x86/boot/boot_hdisk.S b/arch/x86/boot/boot_hdisk.S
new file mode 100644
index 00000000..40388e99
--- /dev/null
+++ b/arch/x86/boot/boot_hdisk.S
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Loading the barebox image from a disk drive in LBA mode
+ */
+
+/**
+ * @fn void real_start(void)
+ * @brief A very simple and small loader to fetch all required sectors
+ * from the boot media.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .file "boot_hdisk.S"
+ .code16
+
+ /*
+ * These symbols are generated by the linker, because they need a
+ * special layout. This layout is needed to be able to setup this
+ * bootloader by patching the binary when it gets stored into the
+ * master boot record.
+ */
+ .extern indirect_sector_lba
+ .extern boot_stack
+ .extern start_pre_uboot
+ .extern boot_disk
+ .section .boot_code, "ax"
+
+ .globl real_start
+ .type real_start, @function
+
+real_start:
+
+ xorw %ax, %ax /* set up %ds and %ss as offset from 0 */
+ movw %ax, %ds
+ movw %ax, %ss
+
+ /* set up the REAL stack */
+ movw $boot_stack, %sp
+
+ sti /* we're safe again */
+
+ /* save drive reference first thing! */
+ movb %dl, boot_disk
+ pushw %dx
+
+ movw $notification_string, %si
+ call output_message
+
+ /*
+ * This boot code only supports LBA. We fail here, if the BIOS
+ * does not support LBA for the harddisk
+ */
+
+ /* check if LBA is supported */
+ movb $0x41, %ah
+ movw $0x55aa, %bx
+ int $0x13
+
+ /*
+ * %dl may have been clobbered by INT 13, AH=41H.
+ * This happens, for example, with AST BIOS 1.04.
+ */
+ popw %dx
+ pushw %dx
+
+ /* stop if no LBA support */
+ jc no_lba
+ cmpw $0xaa55, %bx
+ jne no_lba
+ andw $1, %cx
+ jz no_lba
+
+lba_mode:
+ /*
+ * Load the indirect sector. Its content is ready for use,
+ * provided by the installer
+ */
+ movw $indirect_sector_lba, %si
+ movb $0x42, %ah
+ int $0x13
+ jc no_lba /* error? Then die */
+
+ /*
+ * Now loop through all valid entries in the indirect sector
+ */
+ movw $indirect_area, %si
+
+load_loop:
+ /*
+ * Stop if this "Disk Address Packet Structure" is invalid
+ * We call it invalid, if the size member is zero. If it is invalid
+ * we are optimistic and calling the loaded image
+ */
+ movw (%si), %ax
+ cmpw $0x0000, %ax
+ je start_main
+
+ /*
+ * Load this entry
+ */
+ movb $0x42, %ah
+ int $0x13
+ jc no_lba
+
+ addw (%si), %si /* next entry */
+ cmpw $indirect_area + 512, %si
+ jne load_loop
+ /*
+ * fall through to start u-boot.
+ */
+start_main:
+ movw $jmp_string, %si
+ call output_message
+ jmp start_pre_uboot
+/*
+ * die if there is no LBA support
+ */
+no_lba: movw $chs_string, %si
+ call output_message
+ hlt
+
+/*
+ * message: write the string pointed to by %si
+ *
+ * WARNING: trashes %si, %ax, and %bx
+ */
+
+/*
+ * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+ * %ah = 0xe %al = character
+ * %bh = page %bl = foreground color (graphics modes)
+ */
+
+1:
+ movw $0x0001, %bx
+ movb $0xe, %ah
+ int $0x10 /* display this char */
+
+output_message:
+ lodsb
+ cmpb $0, %al
+ jne 1b /* if not end of string, next char */
+ ret
+
+/* ---------------------------------------------------------------------- */
+
+ .section .boot_data
+
+notification_string: .asciz "UBOOT2 "
+chs_string: .asciz "CHS "
+jmp_string: .asciz "JMP "
+
+#endif
diff --git a/arch/x86/boot/boot_main.S b/arch/x86/boot/boot_main.S
new file mode 100644
index 00000000..f3d248ae
--- /dev/null
+++ b/arch/x86/boot/boot_main.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Common boot sector main routine to be entered by the BIOS
+ */
+/**
+ * @fn void _start(void)
+ *
+ * @brief Fix segment:offset settings of some buggy BIOSs
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .file "boot_main.S"
+ .code16
+
+ .extern real_start
+
+ .section .boot_start, "ax"
+ .type _start, @function
+
+ /*
+ * The BIOS loads this code to address 0x00007c00.
+ * The code should be called with CS:IP 0:0x7c00 (hopefully).
+ */
+ .globl _start
+_start:
+ cli /* we're not safe here! */
+ /*
+ * It seems there are implementations in the wild which call this
+ * code with CS:IP 0x07C0:0000 instead. We fix it immediately.
+ */
+ ljmp $0, $real_start
+
+ .size _start, .-_start
+
+#endif
diff --git a/arch/x86/boot/main_entry.c b/arch/x86/boot/main_entry.c
new file mode 100644
index 00000000..5f199e98
--- /dev/null
+++ b/arch/x86/boot/main_entry.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Start of the 32 bit flat mode
+ */
+
+#include <string.h>
+
+/* These symbols are generated by the linker */
+extern char __bss_start;
+extern char __bss_end;
+
+extern void start_barebox(void);
+
+/**
+ * Called plainly from assembler that switches from real to flat mode
+ *
+ * @note The C environment isn't initialized yet
+ */
+void uboot_entry(void)
+{
+ /* clear the BSS first */
+ memset(&__bss_start, 0x00, &__bss_end - &__bss_start);
+ start_barebox();
+}
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
new file mode 100644
index 00000000..d48e1983
--- /dev/null
+++ b/arch/x86/boot/pmjump.S
@@ -0,0 +1,89 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief The actual transition into protected mode
+ *
+ * Note: This function is running in flat and real mode. Due to some
+ * other restrictions it must running from an address space below 0x10000
+ */
+
+/**
+ * @fn void protected_mode_jump(void)
+ * @brief Switches the first time from real mode to flat mode
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <asm/modes.h>
+#include "boot.h"
+
+ .file "pmjump.S"
+ .code16
+ .section .boot.text.protected_mode_jump, "ax"
+
+ .globl protected_mode_jump
+ .type protected_mode_jump, @function
+
+protected_mode_jump:
+ jmp 1f /* Short jump to serialize on 386/486 */
+1:
+
+ movw $__BOOT_DS, %cx
+ movw $__BOOT_TSS, %di
+
+ movl %cr0, %edx
+ orb $X86_CR0_PE, %dl /* enable protected mode */
+ movl %edx, %cr0
+
+ /* Transition to 32-bit flat mode */
+ data32 ljmp $__BOOT_CS, $in_pm32
+
+/* ------------------------------------------------------------------------ */
+
+ .section ".text.in_pm32","ax"
+ .code32
+
+ .extern uboot_entry
+ .extern __bss_end
+
+ .type in_pm32, @function
+in_pm32:
+ # Set up data segments for flat 32-bit mode
+ movl %ecx, %ds
+ movl %ecx, %es
+ movl %ecx, %fs
+ movl %ecx, %gs
+ movl %ecx, %ss
+/*
+ * Our flat mode code uses its own stack area behind the bss. With this we
+ * are still able to return to real mode temporarely
+ */
+ movl $__bss_end + 32768, %esp
+
+ # Set up TR to make Intel VT happy
+ ltr %di
+
+ # Clear registers to allow for future extensions to the
+ # 32-bit boot protocol
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ xorl %ebx, %ebx
+ xorl %ebp, %ebp
+ xorl %edi, %edi
+
+ # Set up LDTR to make Intel VT happy
+ lldt %cx
+
+ jmp uboot_entry
+
+ .size protected_mode_jump, .-protected_mode_jump
+
+#endif
diff --git a/arch/x86/boot/prepare_uboot.c b/arch/x86/boot/prepare_uboot.c
new file mode 100644
index 00000000..a68acedd
--- /dev/null
+++ b/arch/x86/boot/prepare_uboot.c
@@ -0,0 +1,86 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Prepare the machine for transition to protected mode.
+ */
+#include <asm/segment.h>
+#include <asm/modes.h>
+#include <asm/io.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+/*
+ * While we are in flat mode, we can't handle interrupts. But we can't
+ * switch them off for ever in the PIC, because we need them again while
+ * entering real mode code again and again....
+ */
+static void __bootcode realmode_switch_hook(void)
+{
+ asm volatile("cli");
+ outb(0x80, 0x70); /* Disable NMI */
+ io_delay();
+}
+
+/*
+ * Reset IGNNE# if asserted in the FPU.
+ */
+static void __bootcode reset_coprocessor(void)
+{
+ outb(0, 0xf0);
+ io_delay();
+ outb(0, 0xf1);
+ io_delay();
+}
+
+/**
+ * Setup and register the global descriptor table (GDT)
+ *
+ * @note This is for the first time only
+ */
+static void __bootcode setup_gdt(void)
+{
+ /* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
+ of the gdt_ptr contents. Thus, make it static so it will
+ stay in memory, at least long enough that we switch to the
+ proper kernel GDT. */
+ static struct gdt_ptr __bootdata gdt_ptr;
+
+ gdt_ptr.len = gdt_size - 1;
+ gdt_ptr.ptr = (uint32_t)&gdt + (ds() << 4);
+
+ asm volatile("lgdtl %0" : : "m" (gdt_ptr));
+}
+
+static char a20_message[] __bootdata = "A20 gate not responding, unable to boot...\n";
+
+/*
+ * Actual invocation sequence
+ */
+void __bootcode start_pre_uboot(void)
+{
+ /* Hook before leaving real mode, also disables interrupts */
+ realmode_switch_hook();
+
+ /* Enable the A20 gate */
+ if (enable_a20()) {
+ boot_puts(a20_message);
+ die();
+ }
+
+ /* Reset coprocessor (IGNNE#) */
+ reset_coprocessor();
+
+ setup_gdt();
+ /* Actual transition to protected mode... */
+ protected_mode_jump();
+}
diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c
new file mode 100644
index 00000000..ddc51551
--- /dev/null
+++ b/arch/x86/boot/regs.c
@@ -0,0 +1,34 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2 or (at your
+ * option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Simple helper function for initializing a register set.
+ *
+ * Note that this sets EFLAGS_CF in the input register set; this
+ * makes it easier to catch functions which do nothing but don't
+ * explicitly set CF.
+ */
+
+#include <asm/segment.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+void __bootcode initregs(struct biosregs *reg)
+{
+ memset(reg, 0, sizeof *reg);
+ reg->eflags |= X86_EFLAGS_CF;
+ reg->ds = ds();
+ reg->es = ds();
+ reg->fs = fs();
+ reg->gs = gs();
+}
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
new file mode 100644
index 00000000..a81671be
--- /dev/null
+++ b/arch/x86/boot/tty.c
@@ -0,0 +1,45 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Very simple screen I/O for the initialization stage
+ *
+ * @todo Probably should add very simple serial I/O?
+ * @attention This is real mode code!
+ */
+
+#include <asm/segment.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+static void __bootcode putchar(int ch)
+{
+ struct biosregs ireg;
+
+ if (ch == '\n')
+ putchar('\r'); /* \n -> \r\n */
+
+ initregs(&ireg);
+ ireg.bx = 0x0007;
+ ireg.cx = 0x0001;
+ ireg.ah = 0x0e;
+ ireg.al = ch;
+ intcall(0x10, &ireg, NULL);
+}
+
+void __bootcode boot_puts(char *str)
+{
+ while (*str)
+ putchar(*str++);
+}
diff --git a/arch/x86/configs/generic_defconfig b/arch/x86/configs/generic_defconfig
new file mode 100644
index 00000000..091f696e
--- /dev/null
+++ b/arch/x86/configs/generic_defconfig
@@ -0,0 +1,186 @@
+#
+# Automatically generated make config: don't edit
+# barebox version: 2009.12.0-x86-trunk
+#
+CONFIG_ARCH_TEXT_BASE=0x00007c00
+CONFIG_BOARDINFO="Generic x86 bootloader"
+# CONFIG_BOARD_LINKER_SCRIPT is not set
+CONFIG_GENERIC_LINKER_SCRIPT=y
+CONFIG_X86=y
+CONFIG_MACH_X86_GENERIC=y
+CONFIG_X86_BIOS_BRINGUP=y
+# CONFIG_X86_NATIVE_BRINGUP is not set
+
+#
+# BIOS boot source
+#
+CONFIG_X86_HDBOOT=y
+
+#
+# Board specific settings
+#
+CONFIG_GREGORIAN_CALENDER=y
+CONFIG_HAS_KALLSYMS=y
+CONFIG_HAS_MODULES=y
+CONFIG_CMD_MEMORY=y
+CONFIG_ENV_HANDLING=y
+
+#
+# General Settings
+#
+CONFIG_LOCALVERSION_AUTO=y
+
+#
+# memory layout
+#
+CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
+CONFIG_TEXT_BASE=0x00007c00
+CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
+CONFIG_MEMORY_LAYOUT_DEFAULT=y
+# CONFIG_MEMORY_LAYOUT_FIXED is not set
+CONFIG_STACK_SIZE=0x7000
+CONFIG_MALLOC_SIZE=0x400000
+CONFIG_BROKEN=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_MODULES is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_PROMPT="uboot:"
+CONFIG_BAUDRATE=115200
+CONFIG_LONGHELP=y
+CONFIG_CBSIZE=1024
+CONFIG_MAXARGS=16
+CONFIG_SHELL_HUSH=y
+# CONFIG_SHELL_SIMPLE is not set
+CONFIG_GLOB=y
+CONFIG_PROMPT_HUSH_PS2="> "
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_DYNAMIC_CRC_TABLE=y
+CONFIG_ERRNO_MESSAGES=y
+CONFIG_TIMESTAMP=y
+CONFIG_CONSOLE_FULL=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+# CONFIG_OF_FLAT_TREE is not set
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="board/x86_generic/env"
+
+#
+# Debugging
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_FLASH_NOISE is not set
+# CONFIG_ENABLE_PARTITION_NOISE is not set
+# CONFIG_ENABLE_DEVICE_NOISE is not set
+
+#
+# Commands
+#
+
+#
+# scripting
+#
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+# CONFIG_CMD_TRUE is not set
+# CONFIG_CMD_FALSE is not set
+
+#
+# file commands
+#
+CONFIG_CMD_LS=y
+CONFIG_CMD_RM=y
+CONFIG_CMD_CAT=y
+CONFIG_CMD_MKDIR=y
+CONFIG_CMD_RMDIR=y
+CONFIG_CMD_CP=y
+CONFIG_CMD_PWD=y
+CONFIG_CMD_CD=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UMOUNT=y
+
+#
+# console
+#
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO=y
+
+#
+# memory
+#
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADY is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_CRC is not set
+# CONFIG_CMD_MTEST is not set
+
+#
+# flash
+#
+# CONFIG_CMD_FLASH is not set
+
+#
+# booting
+#
+# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_LINUX16=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+# CONFIG_CMD_PARTITION is not set
+CONFIG_CMD_TEST=y
+CONFIG_CMD_VERSION=y
+CONFIG_CMD_HELP=y
+CONFIG_CMD_DEVINFO=y
+# CONFIG_NET is not set
+
+#
+# Drivers
+#
+
+#
+# serial drivers
+#
+CONFIG_DRIVER_SERIAL_NS16550=y
+
+#
+# SPI drivers
+#
+# CONFIG_SPI is not set
+# CONFIG_I2C is not set
+
+#
+# flash drivers
+#
+# CONFIG_DRIVER_CFI is not set
+# CONFIG_DRIVER_CFI_OLD is not set
+# CONFIG_NAND is not set
+CONFIG_ATA=y
+
+#
+# drive types
+#
+CONFIG_ATA_DISK=y
+
+#
+# interface types
+#
+CONFIG_ATA_BIOS=y
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_VIDEO is not set
+
+#
+# Filesystem support
+#
+# CONFIG_FS_CRAMFS is not set
+CONFIG_FS_RAMFS=y
+CONFIG_FS_DEVFS=y
+CONFIG_CRC32=y
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
diff --git a/arch/x86/include/asm/barebox.h b/arch/x86/include/asm/barebox.h
new file mode 100644
index 00000000..39bea184
--- /dev/null
+++ b/arch/x86/include/asm/barebox.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/* nothing special yet */
diff --git a/arch/x86/include/asm/barebox.lds.h b/arch/x86/include/asm/barebox.lds.h
new file mode 100644
index 00000000..6cbf15f5
--- /dev/null
+++ b/arch/x86/include/asm/barebox.lds.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Adapt linker script content in accordance to Kconfig settings
+ */
+
+#define INITCALLS \
+ KEEP(*(.initcall.0)) \
+ KEEP(*(.initcall.1)) \
+ KEEP(*(.initcall.2)) \
+ KEEP(*(.initcall.3)) \
+ KEEP(*(.initcall.4)) \
+ KEEP(*(.initcall.5)) \
+ KEEP(*(.initcall.6)) \
+ KEEP(*(.initcall.7))
+
+#define BAREBOX_CMDS KEEP(*(SORT_BY_NAME(.barebox_cmd*)))
+
+#define BAREBOX_SYMS KEEP(*(__usymtab))
+
+/**
+ * Area in the MBR of the barebox basic boot code. This offset must be in
+ * accordance to the 'indirect_sector_lba' label.
+ */
+#define PATCH_AREA 400
+
+/**
+ * Offset where to store the boot drive number (BIOS number, 1 byte)
+ */
+#define PATCH_AREA_BOOT_DEV 16
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * It points to an LBA number (8 bytes) and defines the first sector of this
+ * storage on disk.
+ */
+#define PATCH_AREA_PERS_START 20
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * It points to a short number (2 bytes) and defines the sector count of this
+ * storage on disk.
+ */
+#define PATCH_AREA_PERS_SIZE 28
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * drive number (BIOS number, 1 byte)
+ */
+#define PATCH_AREA_PERS_DRIVE 30
+
+/**
+ * Mark the persistant environment as not used
+ */
+#define PATCH_AREA_PERS_SIZE_UNUSED 0x000
+
+/**
+ * Mark a DAPS as unused/invalid
+ */
+#define MARK_DAPS_INVALID 0x0000
+
+/**
+ * Offset of the partition table in an MBR
+ */
+#define OFFSET_OF_PARTITION_TABLE 446
+
+/**
+ * Offset of the signature in an MBR
+ */
+#define OFFSET_OF_SIGNATURE 510
+
+/**
+ * Area where to store indirect sector to loop through. Keep this value
+ * in accordance to the 'indirect_area' label. Note: .
+ *
+ * @attention These addresses are real mode ones (seg:offset)
+ */
+#define INDIRECT_AREA 0x7A00
+#define INDIRECT_SEGMENT 0x0000
+
+/**
+ * Area where to load sectors from disk to. They should start after the
+ * MBR area and must be in accordance to the offset of the '.bootstrapping'
+ * section in the linker file.
+ *
+ * @attention The address must be a multiple of 512.
+ */
+#define LOAD_AREA 0x7e00
+#define LOAD_SEGMENT 0x0000
+
+/**
+ * Size of one sector.
+ */
+#define SECTOR_SIZE 512
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
new file mode 100644
index 00000000..b43afa3f
--- /dev/null
+++ b/arch/x86/include/asm/bitops.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 bit operations
+ *
+ * This file is required only to make all sources happy including
+ * 'linux/bitops.h'
+ */
+
+#ifndef _ASM_X86_BITOPS_H_
+#define _ASM_X86_BITOPS_H_
+
+/* nothing special yet */
+
+#endif /* _ASM_X86_BITOPS_H_ */
diff --git a/arch/x86/include/asm/byteorder.h b/arch/x86/include/asm/byteorder.h
new file mode 100644
index 00000000..51ce8e1d
--- /dev/null
+++ b/arch/x86/include/asm/byteorder.h
@@ -0,0 +1,30 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 endianess declaration
+ */
+
+#ifndef __ASM_X86_BYTEORDER_H
+#define __ASM_X86_BYTEORDER_H
+
+#include <asm/types.h>
+#include <linux/byteorder/little_endian.h>
+
+#endif
diff --git a/arch/x86/include/asm/common.h b/arch/x86/include/asm/common.h
new file mode 100644
index 00000000..4862680e
--- /dev/null
+++ b/arch/x86/include/asm/common.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 common declarations
+ */
+
+#ifndef _ASM_X86_COMMON_H_
+#define _ASM_X86_COMMON_H_
+
+/* Nothing exiting yet */
+
+#endif /* _ASM_X86_COMMON_H_ */
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
new file mode 100644
index 00000000..01342d6a
--- /dev/null
+++ b/arch/x86/include/asm/elf.h
@@ -0,0 +1,30 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 specific elf information
+ *
+ */
+
+#ifndef _ASM_X86_ELF_H
+#define _ASM_X86_ELF_H
+
+#define ELF_CLASS ELFCLASS32
+
+#endif /* _ASM_X86_ELF_H */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
new file mode 100644
index 00000000..27ea6425
--- /dev/null
+++ b/arch/x86/include/asm/io.h
@@ -0,0 +1,73 @@
+/*
+ * Mostly stolen from the linux kernel
+ */
+
+/**
+ * @file
+ * @brief x86 IO access functions
+ */
+
+#ifndef __ASM_X86_IO_H
+#define __ASM_X86_IO_H
+
+static inline void outb(unsigned char value, int port)
+{
+ asm volatile("outb %b0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outw(unsigned short value, int port)
+{
+ asm volatile("outw %w0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outl(unsigned long value, int port)
+{
+ asm volatile("outl %0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline unsigned char inb(int port)
+{
+ unsigned char value;
+ asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+static inline unsigned short inw(int port)
+{
+ unsigned short value;
+ asm volatile("inw %w1, %w0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+static inline unsigned long inl(int port)
+{
+ unsigned long value;
+ asm volatile("inl %w1, %0" : "=a"(value) : "Nd"(port));
+ return value;
+}
+
+#define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void *addr) \
+ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+ :"m" (*(volatile type*)addr) barrier); return ret; }
+
+build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
+build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
+build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
+
+#define build_mmio_write(name, size, type, reg, barrier) \
+ static inline void name(type val, volatile void *addr) \
+ { asm volatile("mov" size " %0,%1": :reg (val), \
+ "m" (*(volatile type*)addr) barrier); }
+
+build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
+build_mmio_write(writew, "w", unsigned short, "r", :"memory")
+build_mmio_write(writel, "l", unsigned int, "r", :"memory")
+
+/* do a tiny io delay */
+static inline void io_delay(void)
+{
+ inb(0x80);
+}
+
+#endif /* __ASM_X86_IO_H */
diff --git a/arch/x86/include/asm/modes.h b/arch/x86/include/asm/modes.h
new file mode 100644
index 00000000..8417ddc4
--- /dev/null
+++ b/arch/x86/include/asm/modes.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Declarations to bring some light in the real/protected/flat mode darkness
+ */
+#ifndef _ASM_X86_MODES_H
+#define _ASM_X86_MODES_H
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+extern uint64_t gdt[];
+extern unsigned gdt_size;
+
+#endif
+
+/** to simplify GDT entry generation */
+#define GDT_ENTRY(flags, base, limit) \
+ ((((base) & 0xff000000ULL) << (56-24)) | \
+ (((flags) & 0x0000f0ffULL) << 40) | \
+ (((limit) & 0x000f0000ULL) << (48-16)) | \
+ (((base) & 0x00ffffffULL) << 16) | \
+ (((limit) & 0x0000ffffULL)))
+
+/** 32 bit barebox text */
+#define GDT_ENTRY_BOOT_CS 2
+#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
+
+/** 32 bit barebox data */
+#define GDT_ENTRY_BOOT_DS 3
+#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+
+/** 16 bit barebox text */
+#define GDT_ENTRY_REAL_CS 4
+#define __REAL_CS (GDT_ENTRY_REAL_CS * 8)
+
+/** 16 bit barebox data */
+#define GDT_ENTRY_REAL_DS 5
+#define __REAL_DS (GDT_ENTRY_REAL_DS * 8)
+
+/** Something to make others happy */
+#define GDT_ENTRY_BOOT_TSS 6
+#define __BOOT_TSS (GDT_ENTRY_BOOT_TSS * 8)
+
+#endif /* _ASM_X86_MODES_H */
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
new file mode 100644
index 00000000..168e91df
--- /dev/null
+++ b/arch/x86/include/asm/module.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 module support
+ *
+ */
+
+#ifndef _ASM_X86_MODULE_H_
+#define _ASM_X86_MODULE_H_
+
+/** currently nothing special */
+struct mod_arch_specific
+{
+ int foo;
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif /* _ASM_X86_MODULE_H_ */
diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h
new file mode 100644
index 00000000..a22f301a
--- /dev/null
+++ b/arch/x86/include/asm/posix_types.h
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 posix types
+ *
+ * Minimal set to make all the other header files copied from the Linxu kernel happy
+ */
+
+#ifndef _ASM_X86_POSIX_TYPES_H
+#define _ASM_X86_POSIX_TYPES_H
+
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_dev_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+typedef long long __kernel_loff_t;
+
+#endif /* _ASM_X86_POSIX_TYPES_H */
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
new file mode 100644
index 00000000..cb9b3d0c
--- /dev/null
+++ b/arch/x86/include/asm/segment.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+#ifndef _ASM_X86_SEGMENT_H
+#define _ASM_X86_SEGMENT_H
+
+#include <linux/compiler.h>
+
+/**
+ * @file
+ * @brief To be able to mark functions running in real _and_ flat mode
+ */
+
+/**
+ * Section for every program code needed to bring barebox from real mode
+ * to flat mode
+ */
+#define __bootcode __section(.boot.text)
+
+/**
+ * Section for every data needed to bring barebox from real mode
+ * to flat mode
+ */
+#define __bootdata __section(.boot.data)
+
+#endif /* _ASM_X86_SEGMENT_H */
diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h
new file mode 100644
index 00000000..5ca2ff1a
--- /dev/null
+++ b/arch/x86/include/asm/string.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 specific string optimizations
+ *
+ * Thanks to the Linux kernel here we can add many micro optimized string
+ * functions. But currently it makes no sense, to do so.
+ */
+#ifndef __ASM_X86_STRING_H
+#define __ASM_X86_STRING_H
+
+/* nothing special yet */
+
+#endif
diff --git a/arch/x86/include/asm/syslib.h b/arch/x86/include/asm/syslib.h
new file mode 100644
index 00000000..eebe1a99
--- /dev/null
+++ b/arch/x86/include/asm/syslib.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+extern unsigned int x86_uart_read(unsigned long, unsigned char);
+extern void x86_uart_write(unsigned int, unsigned long, unsigned char);
+
+#ifdef CONFIG_X86_BIOS_BRINGUP
+
+extern int bios_disk_rw_int13_extensions(int, int, void*) __attribute__((regparm(3)));
+extern uint16_t bios_get_memsize(void);
+
+#endif
+
+#ifdef CONFIG_CMD_LINUX16
+extern void bios_start_linux(unsigned) __attribute__((regparm(1)));
+#endif
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
new file mode 100644
index 00000000..17c5fd7b
--- /dev/null
+++ b/arch/x86/include/asm/types.h
@@ -0,0 +1,44 @@
+/*
+ * 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
+ *
+ */
+
+#ifndef __ASM_X86_TYPES_H
+#define __ASM_X86_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+
+typedef unsigned char u8;
+
+typedef unsigned short u16;
+
+typedef unsigned int u32;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_X86_TYPES_H */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
new file mode 100644
index 00000000..b67629f1
--- /dev/null
+++ b/arch/x86/lib/Makefile
@@ -0,0 +1,9 @@
+extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += barebox.lds
+obj-y += memory.o
+obj-y += gdt.o
+
+# needed, when running via a 16 bit BIOS
+obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o
+obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o
+obj-$(CONFIG_X86_BIOS_BRINGUP) += bios_disk.o
+obj-$(CONFIG_CMD_LINUX16) += linux_start.o
diff --git a/arch/x86/lib/barebox.lds.S b/arch/x86/lib/barebox.lds.S
new file mode 100644
index 00000000..2917d2fa
--- /dev/null
+++ b/arch/x86/lib/barebox.lds.S
@@ -0,0 +1,194 @@
+/*
+ * 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
+ *
+ */
+
+#undef i386
+#include <asm/barebox.lds.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+MEMORY
+{
+ mbr(rwx): ORIGIN = TEXT_BASE, LENGTH = 2 * SECTOR_SIZE
+ barebox (rwx) : ORIGIN = TEXT_BASE + SECTOR_SIZE, LENGTH = (256 * 1024 * 1024)
+}
+
+SECTIONS
+{
+#ifdef CONFIG_X86_HDBOOT
+
+ .ramlayout : {
+ boot_stack = INDIRECT_AREA;
+ indirect_area = INDIRECT_AREA;
+ }
+ /* describing the main boot sector */
+ .bootsector : AT (0) {
+ *(.boot_start)
+
+ . = 0x00b;
+ /*
+ * Maybe later on occupied by a "BIOS parameter block". So,
+ * keep it free from code.
+ * - BytesPerSector dw@0x000B
+ * - SectorsPerCluster db@0x000D
+ * - ReservedSectors dw@0x000E
+ * - FatCopies db@0x0010
+ * - RootDirEntries dw@0x0011
+ * - NumSectors dw@0x0013
+ * - MediaType db@0x0015
+ * - SectorsPerFAT dw@0x0016
+ * - SectorsPerTrack dw@0x0018
+ * - NumberOfHeads dw@0x001A
+ * - HiddenSectors dd@0x001C
+ * - SectorsBig dd@0x0020
+ */
+ LONG(0);
+
+ . = 0x024;
+ *(.boot_code)
+ *(.boot_data)
+
+ /*
+ * embed one "Disk Address Packet Structure" into the boot sector
+ * This DAPS points to the 'indirect' sector to give the boot code
+ * an idea what and where to load. Its content must be adapted
+ * to the system it should run on, so, this structure must be
+ * located at a well known offset.
+ */
+ . = PATCH_AREA;
+ indirect_sector_lba = .;
+ SHORT(0x0010); /* size of this structure */
+ SHORT(0x0001); /* one sector */
+ SHORT(indirect_area); /* where to store: offset */
+ SHORT(0x0000); /* where to store: segment */
+ /* the following values are filled by the installer */
+ LONG(0x00000000); /* LBA start lower */
+ LONG(0x00000000); /* LBA start upper */
+
+ /* boot disk number used by upper layers */
+ . = PATCH_AREA + PATCH_AREA_BOOT_DEV;
+ boot_disk = .;
+ BYTE(0x00); /* boot disk number (provided by the BIOS)
+
+ /* information about the persistant environment storage */
+ . = PATCH_AREA + PATCH_AREA_PERS_START;
+ pers_env_storage = .;
+ LONG(0x00000000); /* LBA start lower */
+ LONG(0x00000000); /* LBA start upper */
+
+ . = PATCH_AREA + PATCH_AREA_PERS_SIZE;
+ pers_env_size = .;
+ SHORT(PATCH_AREA_PERS_SIZE_UNUSED); /* size of this area in sectors */
+
+ . = PATCH_AREA + PATCH_AREA_PERS_DRIVE;
+ pers_env_drive = .;
+ BYTE(0x00); /* used drive */
+
+ /* partition table area (fixed location) */
+ . = OFFSET_OF_PARTITION_TABLE;
+ /* create an empty one */
+ LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+ LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+ LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+ LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+
+ /* boot sector signature */
+ . = OFFSET_OF_SIGNATURE;
+ BYTE(0x55);
+ BYTE(0xAA);
+ /* end of the first sector */
+
+ /*
+ * The indirect sector starts here
+ */
+ . = SECTOR_SIZE;
+ BYTE(MARK_DAPS_INVALID); /* mark the first entry invalid */
+ BYTE(0x00);
+ . = SECTOR_SIZE + 496;
+ BYTE(MARK_DAPS_INVALID); /* mark the last entry invalid */
+ BYTE(0x00);
+ . = SECTOR_SIZE + 508;
+ LONG(0x00000000); /* LBA start upper */
+ } > mbr
+
+ /* some real mode bootstrapping */
+ .bootstrapping : AT ( LOADADDR(.bootsector) + SIZEOF(.bootsector) ) {
+ *(.boot.head)
+ *(.boot.text*)
+ *(.boot.rodata*)
+ *(.boot.data*)
+ . = ALIGN(4);
+ } > barebox
+#endif
+
+ /* the main barebox part (32 bit) */
+ .text : AT ( LOADADDR(.bootstrapping) + SIZEOF(.bootstrapping) ) {
+ /* do not align here! It may fails with the LOADADDR! */
+ _stext = .;
+ *(.text_entry*)
+ *(.text_bare_init*)
+ *(.text*)
+ . = ALIGN(4);
+ *(.rodata*)
+ . = ALIGN(4);
+ _etext = .; /* End of text and rodata section */
+ } > barebox
+
+ .data : AT ( LOADADDR(.text) + SIZEOF(.text) ) {
+ *(.data*)
+ . = ALIGN(4);
+ } > barebox
+
+ .got : AT ( LOADADDR(.data) + SIZEOF (.data) ) {
+ *(.got*)
+ . = ALIGN(4);
+ } > barebox
+
+ .barebox_cmd : AT ( LOADADDR(.got) + SIZEOF (.got) ) {
+ __barebox_cmd_start = .;
+ BAREBOX_CMDS
+ __barebox_cmd_end = .;
+ . = ALIGN(4);
+ } > barebox
+
+ .barebox_initcalls : AT ( LOADADDR(.barebox_cmd) + SIZEOF (.barebox_cmd) ) {
+ __barebox_initcalls_start = .;
+ INITCALLS
+ __barebox_initcalls_end = .;
+ . = ALIGN(4);
+ } > barebox
+
+ .__usymtab : AT ( LOADADDR(.barebox_initcalls) + SIZEOF (.barebox_initcalls) ) {
+ __usymtab_start = .;
+ BAREBOX_SYMS
+ __usymtab_end = .;
+ . = ALIGN(4);
+ } > barebox
+
+ .bss : {
+ __bss_start = .;
+ *(.bss*);
+ *( COMMON )
+ __bss_end = .;
+ _end = .;
+ } > barebox
+}
diff --git a/arch/x86/lib/bios_disk.S b/arch/x86/lib/bios_disk.S
new file mode 100644
index 00000000..3acd6604
--- /dev/null
+++ b/arch/x86/lib/bios_disk.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Do BIOS calls to load or save data from disks
+ *
+ * @note These functions are running in flat and real mode. Due to some
+ * other restrictions these routines must running from an address
+ * space below 0x10000
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+/*
+ * int bios_disk_rw_int13_extensions (int ah, int drive, void *dap)
+ *
+ * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
+ * is passed for disk address packet. If an error occurs, return
+ * non-zero, otherwise zero.
+ */
+ .section .boot.text.bios_disk_rw_int13_extensions, "ax"
+ .code32
+ .globl bios_disk_rw_int13_extensions
+ .type bios_disk_rw_int13_extensions, @function
+
+ .extern prot_to_real
+ .extern real_to_prot
+
+bios_disk_rw_int13_extensions:
+ pushl %ebp
+ pushl %esi
+
+ /* compute the address of disk_address_packet */
+ movw %cx, %si
+ xorw %cx, %cx
+ shrl $4, %ecx /* save the segment to cx */
+
+ movb %al, %dh
+ call prot_to_real /* enter real mode right now */
+
+ .code16
+ movb %dh, %ah
+ movw %cx, %ds
+ int $0x13 /* do the operation */
+ movb %ah, %dl /* save return value */
+ /* back to protected mode */
+ DATA32 call real_to_prot
+
+ .code32
+ movb %dl, %al /* return value in %eax */
+
+ popl %esi
+ popl %ebp
+
+ ret
+
+#endif
diff --git a/arch/x86/lib/gdt.c b/arch/x86/lib/gdt.c
new file mode 100644
index 00000000..a9c4d0e9
--- /dev/null
+++ b/arch/x86/lib/gdt.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Definition of the Global Descriptor Table
+ */
+
+#include <types.h>
+#include <asm/modes.h>
+#include <asm/segment.h>
+
+/**
+ * The 'Global Descriptor Table' used in barebox
+ *
+ * Note: This table must reachable by real and flat mode code
+ */
+uint64_t gdt[] __attribute__((aligned(16))) __bootdata = {
+ /* CS: code, read/execute, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+ /* DS: data, read/write, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+ /* CS: for real mode calls */
+ [GDT_ENTRY_REAL_CS] = GDT_ENTRY(0x009E, 0, 0x0ffff),
+ /* DS: for real mode calls */
+ [GDT_ENTRY_REAL_DS] = GDT_ENTRY(0x0092, 0, 0x0ffff),
+ /* TSS: 32-bit tss, 104 bytes, base 4096 */
+ /* We only have a TSS here to keep Intel VT happy;
+ we don't actually use it for anything. */
+ [GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
+};
+
+/**
+ * Size of the GDT must be known to load it
+ *
+ * Note: This varibale must reachable by real and flat mode code
+ */
+unsigned gdt_size __bootdata = sizeof(gdt);
diff --git a/arch/x86/lib/linux_start.S b/arch/x86/lib/linux_start.S
new file mode 100644
index 00000000..fac2510d
--- /dev/null
+++ b/arch/x86/lib/linux_start.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Start the Linux real mode setup code
+ *
+ * Note: These functions are running in flat and real mode. Due to some
+ * other restrictions these routines must running from an address
+ * space below 0x10000
+ */
+
+/*
+ * void bios_start_linux(unsigned segment)
+ *
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .section .boot.text.bios_start_linux, "ax"
+ .code32
+ .globl bios_start_linux
+ .type bios_start_linux, @function
+
+ .extern prot_to_real
+
+bios_start_linux:
+ /* 'prot_to_real' eats our eax content */
+ movl %eax, %ebx
+ addl $0x20, %eax
+ movw %ax, setup_seg
+
+ call prot_to_real
+
+ .code16
+
+ cli
+ /* all segment registers are using the same segment */
+ movw %bx, %ss
+ movw %bx, %ds
+ movw %bx, %es
+ movw %bx, %fs
+ movw %bx, %gs
+
+ /* stack for the setup code (end of heap) */
+ movw $0x9000, %sp
+
+ /* do an 'ljmp' and never return */
+ .byte 0xea
+ .word 0
+setup_seg:
+ .word 0
+
+ .code32
+
+#endif
diff --git a/arch/x86/lib/memory.c b/arch/x86/lib/memory.c
new file mode 100644
index 00000000..9496d227
--- /dev/null
+++ b/arch/x86/lib/memory.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Memory management
+ */
+
+#include <init.h>
+#include <stdio.h>
+#include <mem_malloc.h>
+#include <asm/syslib.h>
+#include <asm-generic/memory_layout.h>
+
+/**
+ * Handling of free memory
+ *
+ * Topics:
+ * - areas used by BIOS code
+ * - The 0xa0000... 0xfffff hole
+ * - memory above 0x100000
+ */
+
+static int x86_mem_malloc_init(void)
+{
+#ifdef CONFIG_MEMORY_LAYOUT_DEFAULT
+ unsigned long memory_size;
+
+ memory_size = bios_get_memsize();
+ memory_size <<= 10; /* BIOS reports in kiB */
+
+ /*
+ * We do not want to conflict with the kernel. So, we keep the
+ * area from 0x100000 ... 0xFFFFFF free from usage
+ */
+ if (memory_size >= (15 * 1024 * 1024 + MALLOC_SIZE))
+ mem_malloc_init((void*)(16 * 1024 * 1024),
+ (void*)(16 * 1024 * 1024) + MALLOC_SIZE);
+ else
+ return -1;
+#else
+ mem_malloc_init((void *)MALLOC_BASE,
+ (void *)(MALLOC_BASE + MALLOC_SIZE));
+#endif
+ return 0;
+}
+
+core_initcall(x86_mem_malloc_init);
diff --git a/arch/x86/lib/memory16.S b/arch/x86/lib/memory16.S
new file mode 100644
index 00000000..01450fa5
--- /dev/null
+++ b/arch/x86/lib/memory16.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Query the memory layout information from the BIOS
+ *
+ * Note: This function is running in flat and real mode. Due to some
+ * other restrictions it must running from an address space below 0x10000
+ */
+
+/**
+ * @fn unsigned short bios_get_memsize(void)
+ * @brief Does a BIOS call "INT 15H, AH=88H" to get extended memory size
+ * @return Extended memory size in KB
+ *
+ * @note This call is limited to 64 MiB. So, if the system provides more than
+ * 64 MiB of memory, still 64 MiB are reported.
+ *
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ .section .boot.text.bios_get_memsize, "ax"
+ .code32
+ .globl bios_get_memsize
+ .type bios_get_memsize, @function
+
+ .extern prot_to_real
+
+bios_get_memsize:
+
+ pushl %ebp
+
+ call prot_to_real /* enter real mode */
+ .code16
+
+ movb $0x88, %ah
+ int $0x15
+
+ movw %ax, %dx
+
+ DATA32 call real_to_prot
+
+ .code32
+
+ movw %dx, %ax
+
+ popl %ebp
+ ret
+
+ .size bios_get_memsize, .-bios_get_memsize
+
+#endif
diff --git a/arch/x86/lib/traveler.S b/arch/x86/lib/traveler.S
new file mode 100644
index 00000000..2b6dc85e
--- /dev/null
+++ b/arch/x86/lib/traveler.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Switch from the flat mode world into the real mode world and vice versa
+ *
+ * Note: These functions are *called* and return in a different operating mode
+ */
+
+/**
+ * @fn void real_to_prot(void)
+ * @brief Switch from temp. real mode back to flat mode
+ *
+ * Called from a 32 bit flat mode segment and returns into a 16 bit segment
+ */
+
+/**
+ * @fn void prot_to_real(void)
+ * @brief Switch from flat mode to real mode
+ *
+ * Called from a 16 bit real mode segment and returns into a 32 bit segment
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <asm/modes.h>
+
+ .file "walkyrie.S"
+
+/* keep the current flat mode stack pointer, while playing in real mode */
+ .section .boot.data.protstack
+ .code32
+protstack: .long 4
+/* temp. store */
+return_addr: .long 4
+
+
+ .section .boot.text.real_to_prot, "ax"
+ .code16
+ .globl real_to_prot
+ .type real_to_prot, @function
+
+/* Note: This routine should not change any other standard registers than eax */
+real_to_prot:
+ /*
+ * Always disable the interrupts, when returning to flat mode
+ */
+ cli
+
+ /* turn on protected mode */
+ movl %cr0, %eax
+ orl $0x00000001, %eax
+ movl %eax, %cr0
+
+ /* jump to relocation, flush prefetch queue, and reload %cs */
+ DATA32 ljmp $__BOOT_CS, $return_to_flatmode
+
+/* ----------------------------------------------------------------------- */
+ .section .boot.text.return_to_flatmode, "ax"
+ .type return_to_flatmode, @function
+ .code32
+
+return_to_flatmode:
+ /* reload other segment registers */
+ movw $__BOOT_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* move the return address from the real mode to the flat mode stack */
+ movl (%esp), %eax
+ movl %eax, return_addr
+
+ /* setup again the flat mode stack */
+ movl protstack, %eax
+ movl %eax, %esp
+ movl %eax, %ebp
+
+ movl return_addr, %eax
+ movl %eax, (%esp)
+
+ /* flag we returned happy here */
+ xorl %eax, %eax
+ ret
+
+ .size real_to_prot, .-real_to_prot
+
+/* ------------------------------------------------------------------------ */
+
+/* Note: This routine should not change any other standard registers than eax */
+
+ .section .boot.text.prot_to_real, "ax"
+ .globl prot_to_real
+ .type prot_to_real, @function
+ .extern boot_stack
+ .code32
+
+prot_to_real:
+ /* save the protected mode stack */
+ movl %esp, %eax
+ movl %eax, protstack
+
+ /* prepare the real mode stack */
+ /* - address to call to the top of this stack */
+ movl (%esp), %eax
+ movl %eax, boot_stack - 4
+
+ /* - the stack itself */
+ movl $boot_stack - 4, %eax
+ movl %eax, %esp
+ movl %eax, %ebp
+
+ /* prepare segments limits to 16 bit */
+ movw $__REAL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* at last, also limit the code segment to 16 bit */
+ ljmp $__REAL_CS, $return_to_realmode
+
+/* ----------------------------------------------------------------------- */
+
+ .section .boot.text.return_to_realmode, "ax"
+return_to_realmode:
+ .code16
+
+ /* disable protected mode */
+ movl %cr0, %eax
+ andl $(~0x00000001), %eax
+ movl %eax, %cr0
+
+ /*
+ * all the protected mode settings are still cached in the CPU.
+ * Refresh them by re-loading all registers in realmode
+ * Start with the CS, continue with the data registers
+ */
+ ljmp $0, $enter_realmode
+
+enter_realmode:
+ xorl %eax, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ /*
+ * back in plain real mode now, we can play again with the BIOS
+ */
+
+ /* restore interrupts */
+ sti
+
+ /* return on realmode stack! */
+ DATA32 ret
+
+ .size prot_to_real, .-prot_to_real
+
+#endif
diff --git a/arch/x86/mach-i386/Kconfig b/arch/x86/mach-i386/Kconfig
new file mode 100644
index 00000000..11f6aa67
--- /dev/null
+++ b/arch/x86/mach-i386/Kconfig
@@ -0,0 +1,29 @@
+
+menu "Board specific settings "
+
+if X86_BOOTLOADER
+
+config X86_GENERIC_HAS_ISA
+ bool "ISA support"
+ help
+ Say Y here if the target supports a ISA bus
+
+config X86_GENERIC_HAS_PCI
+ bool "PCI support"
+ select HAS_PCI
+ help
+ Say Y here if the target supports a PCI bus
+
+config X86_GENERIC_HAS_VIDEO
+ bool "video support"
+ help
+ Say Y here if the target supports a video output
+
+config X86_GENERIC_HAS_USB
+ bool "USB support"
+ help
+ Say Y here if the target supports a USB interface
+
+endif
+
+endmenu
diff --git a/arch/x86/mach-i386/Makefile b/arch/x86/mach-i386/Makefile
new file mode 100644
index 00000000..10712e6a
--- /dev/null
+++ b/arch/x86/mach-i386/Makefile
@@ -0,0 +1,5 @@
+obj-y += generic.o
+obj-y += reset.o
+
+# reference clocksource
+obj-y += pit_timer.o
diff --git a/arch/x86/mach-i386/generic.c b/arch/x86/mach-i386/generic.c
new file mode 100644
index 00000000..edeacc42
--- /dev/null
+++ b/arch/x86/mach-i386/generic.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 Architecture Initialization routines
+ */
+
+#include <asm/io.h>
+
+/** to work with the 8250 UART driver implementation we need this function */
+unsigned int x86_uart_read(unsigned long base, unsigned char reg_idx)
+{
+ return inb(base + reg_idx);
+}
+
+/** to work with the 8250 UART driver implementation we need this function */
+void x86_uart_write(unsigned int val, unsigned long base, unsigned char reg_idx)
+{
+ outb(val, base + reg_idx);
+}
diff --git a/arch/x86/mach-i386/pit_timer.c b/arch/x86/mach-i386/pit_timer.c
new file mode 100644
index 00000000..b9f805e6
--- /dev/null
+++ b/arch/x86/mach-i386/pit_timer.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Clocksource based on the 'Programmable Interval Timer' PIT (8253)
+ *
+ * This timer should be available on almost all PCs. It also should be run
+ * at a fixed frequency (1193181.8181 Hz) and not modified to use another
+ * reload value than 0xFFFF. So, it always counts from 0xffff down to 0.
+ *
+ * @note: We can't reprogram the PIT, it will be still used by the BIOS. This
+ * clocksource driver does not touch any PIT settings.
+ */
+
+#include <init.h>
+#include <clock.h>
+#include <asm/io.h>
+
+/** base address of the PIT in a standard PC */
+#define PIT 0x40
+
+static uint64_t pit_clocksource_read(void)
+{
+ uint16_t val1, val2;
+
+ outb(0x00, PIT + 3); /* latch counter 0 */
+ outb(0x00, 0x80);
+
+ val1 = inb(PIT);
+ outb(0x00, 0x80);
+
+ val2 = inb(PIT);
+ val2 <<= 8;
+
+ /* note: its a down counter */
+ return 0xFFFFU - (val1 | val2);
+}
+
+static struct clocksource cs = {
+ .read = pit_clocksource_read,
+ .mask = 0x0000ffff,
+ .shift = 10,
+};
+
+static int clocksource_init (void)
+{
+ cs.mult = clocksource_hz2mult(1193182, cs.shift);
+ init_clock(&cs);
+
+ return 0;
+}
+
+core_initcall(clocksource_init);
diff --git a/arch/x86/mach-i386/reset.c b/arch/x86/mach-i386/reset.c
new file mode 100644
index 00000000..a4eb3648
--- /dev/null
+++ b/arch/x86/mach-i386/reset.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Resetting an x86 CPU
+ */
+
+#include <common.h>
+
+void reset_cpu(ulong addr)
+{
+ /** How to reset the machine? */
+ while(1)
+ ;
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/x86/mach-x86.dox b/arch/x86/mach-x86.dox
new file mode 100644
index 00000000..fc5b85a0
--- /dev/null
+++ b/arch/x86/mach-x86.dox
@@ -0,0 +1,128 @@
+/* This document is intended to provide the developer with information
+ * how to integrate a new CPU (MACH) into this part of the barebox tree
+ */
+
+/** @page x86_runtime barebox on x86 at runtime
+
+@section mach_x86_memory_layout barebox's memory layout (BIOS based)
+
+@a barebox uses the following memory layout at runtime when it still depends
+on some kind of BIOS function:
+
+@verbatim
+ Addresses
+------------------------
+
+ seg:off flat
+
+xxxx:xxxx 0x01xxxxxx end of barebox's malloc area
+ . .
+xxxx:xxxx 0x01000000 start of barebox's malloc area
+ . .
+ . . (used while loading a Linux kernel of type 'bzImage')
+ . .
+xxxx:xxxx 0x00100000 start of extended memory and malloc area
+ . .
+ . . (the big hole)
+ . .
+9000:ffff 0x0009ffff end of expected real mode memory
+ . .
+ . . (used while loading a Linux kernel of type 'bzImage')
+ . .
+9000:0000 0x00090000 end of used lower real mode memory
+ . .
+ . .
+ . . Flat mode stack (about 32 kiB)
+ . . bss
+ . . Data
+ . . Text
+0000:7e00 0x00007e00 Real and flat mode barebox code
+0000:7c00 0x00007c00 MBR initial boot loader code
+0000:7a00 0x00007a00 location of the indirect sector (while booting only)
+ below: real mode stack
+@endverbatim
+
+@note The start address of 0x0000:7c000 is a fixed one, defined by the BIOS.
+So, for a BIOS based @a barebox this address can't be changed.
+
+While the @a barebox code is runnung in flat mode, all interrupts are disabled.
+But in the CPU only. All other interrupt settings are still valid. This is
+required to be able to call real mode code from inside @a barebox flat mode
+code. Thats why not the PIC is touched nor the IDT.
+
+@todo Add some notes about drive numbers used by the BIOS. They may change
+if one change orders in the BIOS setup. Drive orders and numbers may be
+different at BIOS runtime and Linux runtime! But these numbers are required
+at BIOS runtime for booting and the persistant environment storage.
+
+@attention Currently there is a 4 GiB limit for the disk sizes!
+
+@section mach_x86_image_layout barebox's image layout
+
+@a barebox's binary image layout
+
+@verbatim
+ Offset Content
+
+ 0x?????
+ . 32 bit barebox code
+ .
+ . 16 bit bootstrap code, BIOS calling code
+ 0x00400
+ 0x003ff
+ . indirect sector
+ 0x00200
+ 0x001ff
+ . MBR
+ 0x00000
+@endverbatim
+
+The "indirect sector" is a free area in the image where the sector information
+gets stored when this image will be written to a boot media. This information
+is required to load all parts of the image from the boot media at runtime.
+
+The image gets installed in two ways onto the boot media, depending on the
+need for a persistant storage.
+
+@subsection mach_x86_drive_layout_wops barebox's boot media layout without persistant storage
+
+In this case @a barebox's persistant storage is anywhere:
+
+@verbatim
+ Sector Content
+---------------------------
+ X start of first partition
+ .
+ ? end of the binary image
+ . 32 bit barebox code
+ 2 16 bit bootstrap code, BIOS calling code
+ 1 indirect sector
+ 0 MBR, Partition table, boot code
+@endverbatim
+
+@subsection mach_x86_drive_layout_wps barebox's boot media layout with persistant storage
+
+@a barebox's persistant storage is part of the boot media (more
+space required in front of the first partition) and interferes with the
+boot loader image itself:
+
+@verbatim
+ Sector Content
+---------------------------
+ X start of first partition
+ .
+ n+? end of the binary image
+ . 32 bit barebox code
+ n+2 16 bit bootstrap code, BIOS calling code
+ n+1 indirect sector
+ n end of persistant environment storage
+ .
+ 1 start of persistant environment storage
+ 0 MBR, Partition table, boot code
+@endverbatim
+
+The information where the persistant storage is located is also stored into
+the MBR at specific locations by @p setupmbr. The @a barebox runtime will use
+it to load and store all environment relevant data.
+
+*/
diff --git a/board/edb93xx/Makefile b/board/edb93xx/Makefile
new file mode 100644
index 00000000..e19cd7b4
--- /dev/null
+++ b/board/edb93xx/Makefile
@@ -0,0 +1,2 @@
+
+obj-y += edb93xx.o flash_cfg.o pll_cfg.o sdram_cfg.o
diff --git a/board/edb93xx/config.h b/board/edb93xx/config.h
new file mode 100644
index 00000000..6ae9a40e
--- /dev/null
+++ b/board/edb93xx/config.h
@@ -0,0 +1,4 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#endif /* __CONFIG_H */
diff --git a/board/edb93xx/early_udelay.h b/board/edb93xx/early_udelay.h
new file mode 100644
index 00000000..3b26b3f1
--- /dev/null
+++ b/board/edb93xx/early_udelay.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <common.h>
+
+/* delay execution before timers are initialized */
+static inline void early_udelay(uint32_t usecs)
+{
+ /* loop takes 4 cycles at 5.0ns (fastest case, running at 200MHz) */
+ register uint32_t loops = (usecs * 1000) / 20;
+
+ __asm__ volatile ("1:\n"
+ "subs %0, %1, #1\n"
+ "bne 1b":"=r" (loops):"0" (loops));
+}
diff --git a/board/edb93xx/edb93xx.c b/board/edb93xx/edb93xx.c
new file mode 100644
index 00000000..add88e1d
--- /dev/null
+++ b/board/edb93xx/edb93xx.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <environment.h>
+#include <fs.h>
+#include <init.h>
+#include <partition.h>
+#include <asm/armlinux.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <mach/ep93xx-regs.h>
+#include "edb93xx.h"
+
+/*
+ * Up to 32MiB NOR type flash, connected to
+ * CS line 6, data width is 16 bit
+ */
+static struct device_d cfi_dev = {
+ .name = "cfi_flash",
+ .map_base = 0x60000000,
+ .size = EDB93XX_CFI_FLASH_SIZE,
+};
+
+static struct memory_platform_data ram_dev_pdata0 = {
+ .name = "ram0",
+ .flags = DEVFS_RDWR,
+};
+
+static struct device_d sdram0_dev = {
+ .name = "mem",
+ .map_base = CONFIG_EP93XX_SDRAM_BANK0_BASE,
+ .size = CONFIG_EP93XX_SDRAM_BANK0_SIZE,
+ .platform_data = &ram_dev_pdata0,
+};
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 2)
+static struct memory_platform_data ram_dev_pdata1 = {
+ .name = "ram1",
+ .flags = DEVFS_RDWR,
+};
+
+static struct device_d sdram1_dev = {
+ .name = "mem",
+ .map_base = CONFIG_EP93XX_SDRAM_BANK1_BASE,
+ .size = CONFIG_EP93XX_SDRAM_BANK1_SIZE,
+ .platform_data = &ram_dev_pdata1,
+};
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 3)
+static struct memory_platform_data ram_dev_pdata2 = {
+ .name = "ram2",
+ .flags = DEVFS_RDWR,
+};
+
+static struct device_d sdram2_dev = {
+ .name = "mem",
+ .map_base = CONFIG_EP93XX_SDRAM_BANK2_BASE,
+ .size = CONFIG_EP93XX_SDRAM_BANK2_SIZE,
+ .platform_data = &ram_dev_pdata2,
+};
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS == 4)
+static struct memory_platform_data ram_dev_pdata3 = {
+ .name = "ram3",
+ .flags = DEVFS_RDWR,
+};
+
+static struct device_d sdram3_dev = {
+ .name = "mem",
+ .map_base = CONFIG_EP93XX_SDRAM_BANK3_BASE,
+ .size = CONFIG_EP93XX_SDRAM_BANK3_SIZE,
+ .platform_data = &ram_dev_pdata3,
+};
+#endif
+
+static struct device_d eth_dev = {
+ .name = "ep93xx_eth",
+};
+
+static int ep93xx_devices_init(void)
+{
+ register_device(&cfi_dev);
+
+ /*
+ * Create partitions that should be
+ * not touched by any regular user
+ */
+ devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
+ devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0");
+
+ protect_file("/dev/env0", 1);
+
+ register_device(&sdram0_dev);
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 2)
+ register_device(&sdram1_dev);
+#endif
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 3)
+ register_device(&sdram2_dev);
+#endif
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS == 4)
+ register_device(&sdram3_dev);
+#endif
+
+ armlinux_add_dram(&sdram0_dev);
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 2)
+ armlinux_add_dram(&sdram1_dev);
+#endif
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 3)
+ armlinux_add_dram(&sdram2_dev);
+#endif
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS == 4)
+ armlinux_add_dram(&sdram3_dev);
+#endif
+
+ register_device(&eth_dev);
+
+ armlinux_set_bootparams((void *)CONFIG_EP93XX_SDRAM_BANK0_BASE + 0x100);
+
+ armlinux_set_architecture(MACH_TYPE);
+
+ return 0;
+}
+
+device_initcall(ep93xx_devices_init);
+
+static struct device_d edb93xx_serial_device = {
+ .name = "pl010_serial",
+ .map_base = UART1_BASE,
+ .size = 4096,
+};
+
+static int edb93xx_console_init(void)
+{
+ struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+
+ /*
+ * set UARTBAUD bit to drive UARTs with 14.7456MHz instead of
+ * 14.7456/2 MHz
+ */
+ uint32_t value = readl(&syscon->pwrcnt);
+ value |= SYSCON_PWRCNT_UART_BAUD;
+ writel(value, &syscon->pwrcnt);
+
+ register_device(&edb93xx_serial_device);
+
+ return 0;
+}
+
+console_initcall(edb93xx_console_init);
diff --git a/board/edb93xx/edb93xx.dox b/board/edb93xx/edb93xx.dox
new file mode 100644
index 00000000..3964d553
--- /dev/null
+++ b/board/edb93xx/edb93xx.dox
@@ -0,0 +1,108 @@
+/** @page edb9301 Cirrus Logic EDB9301
+
+This boards is based on a Cirrus Logic EP9301 CPU. The board is shipped with:
+
+- 16MiB NOR type Flash Memory
+- 32MiB synchronous dynamic RAM on CS3
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+
+*/
+
+/** @page edb9302 Cirrus Logic EDB9302
+
+This board is based on a Cirrus Logic EP9302 CPU. The board is shipped with:
+
+- 16MiB NOR type Flash Memory
+- 32MiB synchronous dynamic RAM on CS3
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+
+*/
+
+/** @page edb9302a Cirrus Logic EDB9302A
+
+This board is based on a Cirrus Logic EP9302 CPU. The board is shipped with:
+
+- 16MiB NOR type Flash Memory
+- 32MiB synchronous dynamic RAM on CS0
+- 512kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+
+*/
+
+/** @page edb9307 Cirrus Logic EDB9307
+
+This board is based on a Cirrus Logic EP9307 CPU. The board is shipped with:
+
+- 32MiB NOR type Flash Memory
+- 64MiB synchronous dynamic RAM on CS3
+- 512kiB asynchronous SRAM
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+- Real-Time Clock
+- IR receiver
+
+*/
+
+/** @page edb9307a Cirrus Logic EDB9307A
+
+This board is based on a Cirrus Logic EP9307 CPU. The board is shipped with:
+
+- 32MiB NOR type Flash Memory
+- 64MiB synchronous dynamic RAM on CS0
+- 512kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+- Real-Time Clock
+- IR receiver
+
+*/
+
+/** @page edb9312 Cirrus Logic EDB9312
+
+This board is based on a Cirrus Logic EP9312 CPU. The board is shipped with:
+
+- 32MiB NOR type Flash Memory
+- 64MiB synchronous dynamic RAM on CS3
+- 512kiB asynchronous SRAM
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+- Real-Time Clock
+- IR receiver
+
+*/
+
+/** @page edb9315 Cirrus Logic EDB9315
+
+This board is based on a Cirrus Logic EP9315 CPU. The board is shipped with:
+
+- 32MiB NOR type Flash Memory
+- 64MiB synchronous dynamic RAM on CS3
+- 512kiB asynchronous SRAM
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+- Real-Time Clock
+- IR receiver
+
+*/
+
+/** @page edb9315a Cirrus Logic EDB9315A
+
+This board is based on a Cirrus Logic EP9315 CPU. The board is shipped with:
+
+- 32MiB NOR type Flash Memory
+- 64MiB synchronous dynamic RAM on CS0
+- 128kiB serial EEPROM
+- MII 10/100 Ethernet PHY
+- Stereo audio codec
+- Real-Time Clock
+- IR receiver
+
+*/ \ No newline at end of file
diff --git a/board/edb93xx/edb93xx.h b/board/edb93xx/edb93xx.h
new file mode 100644
index 00000000..5e5c6f51
--- /dev/null
+++ b/board/edb93xx/edb93xx.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#if defined(CONFIG_MACH_EDB9301)
+#define MACH_TYPE MACH_TYPE_EDB9301
+#elif defined(CONFIG_MACH_EDB9302)
+#define MACH_TYPE MACH_TYPE_EDB9302
+#elif defined(CONFIG_MACH_EDB9302A)
+#define MACH_TYPE MACH_TYPE_EDB9302A
+#elif defined(CONFIG_MACH_EDB9307)
+#define MACH_TYPE MACH_TYPE_EDB9307
+#elif defined(CONFIG_MACH_EDB9307A)
+#define MACH_TYPE MACH_TYPE_EDB9307A
+#elif defined(CONFIG_MACH_EDB9312)
+#define MACH_TYPE MACH_TYPE_EDB9312
+#elif defined(CONFIG_MACH_EDB9315)
+#define MACH_TYPE MACH_TYPE_EDB9315
+#elif defined(CONFIG_MACH_EDB9315A)
+#define MACH_TYPE MACH_TYPE_EDB9315A
+#endif
+
+#if defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302) || \
+ defined(CONFIG_MACH_EDB9302A)
+#define EDB93XX_CFI_FLASH_SIZE (16 * 1024 * 1024)
+#elif defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9307A) || \
+ defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || \
+ defined(CONFIG_MACH_EDB9315A)
+#define EDB93XX_CFI_FLASH_SIZE (32 * 1024 * 1024)
+#endif
diff --git a/board/edb93xx/env/bin/boot b/board/edb93xx/env/bin/boot
new file mode 100644
index 00000000..143f3d01
--- /dev/null
+++ b/board/edb93xx/env/bin/boot
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+. /env/config
+
+if [ x${rootfs_boot_media} = xflash ];
+then
+ rootfs_img=/dev/nor0.rootfs_${active_cfg}
+
+ if [ x${active_cfg} = x1 ];
+ then
+ rootfs_blkdev=/dev/mtdblock4
+ cfg_1_ro="ro"
+ cfg_2_ro=""
+ else
+ rootfs_blkdev=/dev/mtdblock6
+ cfg_1_ro=""
+ cfg_2_ro="ro"
+ fi
+
+ bootargs_rootfs="root=${rootfs_blkdev} rootfstype=squashfs ro"
+elif [ x${rootfs_boot_media} = xnet ];
+then
+ bootargs_rootfs="root=/dev/nfs nfsroot=${eth0.serverip}:/srv/nfs/${board},v3,nolock,tcp ip=${eth0.ipaddr}"
+else
+ echo "ERROR: \$rootfs_boot_media invalid: ${rootfs_boot_media}"
+ exit 1
+fi
+
+if [ x${kernel_boot_media} = xflash ];
+then
+ kernel_img=/dev/nor0.kernel_${active_cfg}
+elif [ x${kernel_boot_media} = xnet ];
+then
+ cd /
+ tftp ${board}/kernel.img || exit 1
+ kernel_img=/kernel.img
+else
+ echo "ERROR: \$kernel_boot_media invalid: ${kernel_boot_media}"
+ exit 1
+fi
+
+source /env/bin/set_nor_parts
+
+bootargs_mtd="mtdparts=physmap-flash.0:${nor_parts}"
+
+bootargs="${bootargs_common} ${bootargs_mtd} ${bootargs_rootfs}"
+
+bootm ${kernel_img} \ No newline at end of file
diff --git a/board/edb93xx/env/bin/flash_partition b/board/edb93xx/env/bin/flash_partition
new file mode 100644
index 00000000..ded40aa8
--- /dev/null
+++ b/board/edb93xx/env/bin/flash_partition
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ $# != 2 ];
+then
+ echo "Usage: $0 <image> <partition>"
+ exit 1
+fi
+
+image=$1
+partition=$2
+
+echo "Unlocking ${partition}"
+unprotect ${partition}
+
+echo "Erasing ${partition}"
+erase ${partition}
+
+echo "Flashing ${image} to ${partition}"
+cp ${image} ${partition}
+
+echo "Locking ${partition}"
+protect ${partition}
diff --git a/board/edb93xx/env/bin/init b/board/edb93xx/env/bin/init
new file mode 100644
index 00000000..c6b5aed2
--- /dev/null
+++ b/board/edb93xx/env/bin/init
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+PATH=/env/bin
+export PATH
+
+. /env/config
+
+# add partitions to barebox
+. /env/bin/set_nor_parts
+addpart /dev/nor0 ${nor_parts}
+
+echo
+echo -n "Hit any key to stop autoboot: "
+timeout -a $autoboot_timeout
+if [ $? != 0 ]; then
+ exit
+fi
+
+boot \ No newline at end of file
diff --git a/board/edb93xx/env/bin/set_nor_parts b/board/edb93xx/env/bin/set_nor_parts
new file mode 100644
index 00000000..38321fa8
--- /dev/null
+++ b/board/edb93xx/env/bin/set_nor_parts
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+nor_parts="256k(barebox)ro,128k(env_boot),128k(env_boot.bak),1664k(kernel_1)${cfg_1_ro},6144k(rootfs_1)${cfg_1_ro},1664k(kernel_2)${cfg_2_ro},6144k(rootfs_2)${cfg_2_ro},128k(cfg_app),128k(cfg_app.bak)" \ No newline at end of file
diff --git a/board/edb93xx/env/bin/update_kernel b/board/edb93xx/env/bin/update_kernel
new file mode 100644
index 00000000..3e4b9b0b
--- /dev/null
+++ b/board/edb93xx/env/bin/update_kernel
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. /env/config
+
+if [ $# != 1 ];
+then
+ echo "Usage: $0 <1/2>"
+ exit 1
+fi
+
+partition=/dev/nor0.kernel_$1
+
+cd /
+tftp ${board}/kernel.img || exit 1
+
+flash_partition kernel.img ${partition}
diff --git a/board/edb93xx/env/bin/update_rootfs b/board/edb93xx/env/bin/update_rootfs
new file mode 100644
index 00000000..52a3699f
--- /dev/null
+++ b/board/edb93xx/env/bin/update_rootfs
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. /env/config
+
+if [ $# != 1 ];
+then
+ echo "Usage: $0 <1/2>"
+ exit 1
+fi
+
+partition=/dev/nor0.rootfs_$1
+
+cd /
+tftp ${board}/rootfs.img || exit 1
+
+flash_partition rootfs.img ${partition}
diff --git a/board/edb93xx/env/config b/board/edb93xx/env/config
new file mode 100644
index 00000000..47ab209d
--- /dev/null
+++ b/board/edb93xx/env/config
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+eth0.ipaddr=192.168.0.50
+eth0.netmask=255.255.0.0
+eth0.serverip=192.168.0.8
+eth0.ethaddr=80:81:82:83:84:85
+
+board=edb9301
+autoboot_timeout=3
+active_cfg=1
+bootargs_common="console=ttyAM0,115200"
+
+# valid media: flash/net
+kernel_boot_media=flash
+rootfs_boot_media=flash
+
diff --git a/board/edb93xx/flash_cfg.c b/board/edb93xx/flash_cfg.c
new file mode 100644
index 00000000..91a6a4ea
--- /dev/null
+++ b/board/edb93xx/flash_cfg.c
@@ -0,0 +1,38 @@
+/*
+ * Flash setup for Cirrus edb93xx boards
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <mach/ep93xx-regs.h>
+#include <asm/io.h>
+
+#define SMC_BCR6_VALUE (2 << SMC_BCR_IDCY_SHIFT | 5 << SMC_BCR_WST1_SHIFT | \
+ SMC_BCR_BLE | 2 << SMC_BCR_WST2_SHIFT | \
+ 1 << SMC_BCR_MW_SHIFT)
+
+void flash_cfg(void)
+{
+ struct smc_regs *smc = (struct smc_regs *)SMC_BASE;
+
+ writel(SMC_BCR6_VALUE, &smc->bcr6);
+}
diff --git a/board/edb93xx/pll_cfg.c b/board/edb93xx/pll_cfg.c
new file mode 100644
index 00000000..a687af0a
--- /dev/null
+++ b/board/edb93xx/pll_cfg.c
@@ -0,0 +1,58 @@
+/*
+ * PLL setup for Cirrus edb93xx boards
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "pll_cfg.h"
+#include "early_udelay.h"
+
+void pll_cfg(void)
+{
+ struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
+
+ /* setup PLL1 */
+ writel(CLKSET1_VAL, &syscon->clkset1);
+
+ /*
+ * flush the pipeline
+ * writing to CLKSET1 causes the EP93xx to enter standby for between
+ * 8 ms to 16 ms, until PLL1 stabilizes
+ */
+ asm("nop");
+ asm("nop");
+ asm("nop");
+ asm("nop");
+ asm("nop");
+
+ /* setup PLL2 */
+ writel(CLKSET2_VAL, &syscon->clkset2);
+
+ /*
+ * the user's guide recommends to wait at least 1 ms for PLL2 to
+ * stabilize
+ */
+ early_udelay(1000);
+}
diff --git a/board/edb93xx/pll_cfg.h b/board/edb93xx/pll_cfg.h
new file mode 100644
index 00000000..9691339e
--- /dev/null
+++ b/board/edb93xx/pll_cfg.h
@@ -0,0 +1,72 @@
+/*
+ * PLL register values for Cirrus edb93xx boards
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <mach/ep93xx-regs.h>
+
+#if defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302) || \
+ defined(CONFIG_MACH_EDB9302A)
+/*
+ * fclk_div: 2, nbyp1: 1, hclk_div: 5, pclk_div: 2
+ * pll1_x1: 294912000.000000, pll1_x2ip: 36864000.000000,
+ * pll1_x2: 331776000.000000, pll1_out: 331776000.000000
+ */
+#define CLKSET1_VAL (7 << SYSCON_CLKSET_PLL_X2IPD_SHIFT | \
+ 8 << SYSCON_CLKSET_PLL_X2FBD2_SHIFT | \
+ 19 << SYSCON_CLKSET_PLL_X1FBD1_SHIFT | \
+ 1 << SYSCON_CLKSET1_PCLK_DIV_SHIFT | \
+ 3 << SYSCON_CLKSET1_HCLK_DIV_SHIFT | \
+ SYSCON_CLKSET1_NBYP1 | \
+ 1 << SYSCON_CLKSET1_FCLK_DIV_SHIFT)
+#elif defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9307A) ||\
+ defined CONFIG_MACH_EDB9312 || defined(CONFIG_MACH_EDB9315) ||\
+ defined(CONFIG_MACH_EDB9315A)
+/*
+ * fclk_div: 2, nbyp1: 1, hclk_div: 4, pclk_div: 2
+ * pll1_x1: 3096576000.000000, pll1_x2ip: 129024000.000000,
+ * pll1_x2: 3999744000.000000, pll1_out: 1999872000.000000
+ */
+#define CLKSET1_VAL (23 << SYSCON_CLKSET_PLL_X2IPD_SHIFT | \
+ 30 << SYSCON_CLKSET_PLL_X2FBD2_SHIFT | \
+ 20 << SYSCON_CLKSET_PLL_X1FBD1_SHIFT | \
+ 1 << SYSCON_CLKSET1_PCLK_DIV_SHIFT | \
+ 2 << SYSCON_CLKSET1_HCLK_DIV_SHIFT | \
+ SYSCON_CLKSET1_NBYP1 | \
+ 1 << SYSCON_CLKSET1_FCLK_DIV_SHIFT)
+#else
+#error "Undefined board"
+#endif
+
+/*
+ * usb_div: 4, nbyp2: 1, pll2_en: 1
+ * pll2_x1: 368640000.000000, pll2_x2ip: 15360000.000000,
+ * pll2_x2: 384000000.000000, pll2_out: 192000000.000000
+ */
+#define CLKSET2_VAL (23 << SYSCON_CLKSET_PLL_X2IPD_SHIFT | \
+ 24 << SYSCON_CLKSET_PLL_X2FBD2_SHIFT | \
+ 24 << SYSCON_CLKSET_PLL_X1FBD1_SHIFT | \
+ 1 << SYSCON_CLKSET_PLL_PS_SHIFT | \
+ SYSCON_CLKSET2_PLL2_EN | \
+ SYSCON_CLKSET2_NBYP2 | \
+ 3 << SYSCON_CLKSET2_USB_DIV_SHIFT)
diff --git a/board/edb93xx/sdram_cfg.c b/board/edb93xx/sdram_cfg.c
new file mode 100644
index 00000000..9f56f727
--- /dev/null
+++ b/board/edb93xx/sdram_cfg.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include "sdram_cfg.h"
+#include "early_udelay.h"
+
+#define PROGRAM_MODE_REG(bank) (*(volatile uint32_t *) \
+ (SDRAM_BASE_ADDR | SDRAM_BANK_SEL_##bank | SDRAM_MODE_REG_VAL))
+
+#define PRECHARGE_BANK(bank) (*(volatile uint32_t *) \
+ (SDRAM_BASE_ADDR | SDRAM_BANK_SEL_##bank))
+
+static void force_precharge(void);
+static void setup_refresh_timer(void);
+static void program_mode_registers(void);
+
+void sdram_cfg(void)
+{
+ struct sdram_regs *sdram = (struct sdram_regs *)SDRAM_BASE;
+
+ writel(SDRAM_DEVCFG_VAL, &sdram->SDRAM_DEVCFG_REG);
+
+ /* Issue continous NOP commands */
+ writel(GLCONFIG_INIT | GLCONFIG_MRS | GLCONFIG_CKE, &sdram->glconfig);
+
+ early_udelay(200);
+
+ force_precharge();
+
+ setup_refresh_timer();
+
+ program_mode_registers();
+
+ /* Select normal operation mode */
+ writel(GLCONFIG_CKE, &sdram->glconfig);
+}
+
+static void force_precharge(void)
+{
+ /*
+ * Errata most EP93xx revisions say that PRECHARGE ALL isn't always
+ * issued.
+ *
+ * Do a read from each bank to make sure they're precharged
+ */
+
+ PRECHARGE_BANK(0);
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 2)
+ PRECHARGE_BANK(1);
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 3)
+ PRECHARGE_BANK(2);
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS == 4)
+ PRECHARGE_BANK(3);
+#endif
+}
+
+static void setup_refresh_timer(void)
+{
+ struct sdram_regs *sdram = (struct sdram_regs *)SDRAM_BASE;
+
+ /* Load refresh timer with 10 to issue refresh every 10 cycles */
+ writel(0x0a, &sdram->refrshtimr);
+
+ /*
+ * Wait at least 80 clock cycles to provide 8 refresh cycles
+ * to all SDRAMs
+ */
+ early_udelay(1);
+
+ /*
+ * Program refresh timer with normal value
+ * We need 8192 refresh cycles every 64ms
+ * at 15ns (HCLK >= 66MHz) per cycle:
+ * 64ms / 8192 = 7.8125us
+ * 7.8125us / 15ns = 520 (0x208)
+ */
+ /*
+ * TODO: redboot uses 0x1e0 for the slowest possible device
+ * but i don't understand how this value is calculated
+ */
+ writel(0x208, &sdram->refrshtimr);
+}
+
+static void program_mode_registers(void)
+{
+ PROGRAM_MODE_REG(0);
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 2)
+ PROGRAM_MODE_REG(1);
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS >= 3)
+ PROGRAM_MODE_REG(2);
+#endif
+
+#if (CONFIG_EP93XX_SDRAM_NUM_BANKS == 4)
+ PROGRAM_MODE_REG(3);
+#endif
+}
diff --git a/board/edb93xx/sdram_cfg.h b/board/edb93xx/sdram_cfg.h
new file mode 100644
index 00000000..7babee8d
--- /dev/null
+++ b/board/edb93xx/sdram_cfg.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <mach/ep93xx-regs.h>
+
+#define SDRAM_BASE_ADDR CONFIG_EP93XX_SDRAM_BANK0_BASE
+
+#ifdef CONFIG_EP93XX_SDCE0_PHYS_OFFSET
+#define SDRAM_DEVCFG_REG devcfg0
+#elif defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
+#define SDRAM_DEVCFG_REG devcfg3
+#else
+#error "SDRAM bank configuration"
+#endif
+
+#if defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302) ||\
+ defined(CONFIG_MACH_EDB9302A)
+/*
+ * 1x Samsung K4S561632C-TC/L75 4M x 16bit x 4 banks SDRAM
+ *
+ * CLK cycle time min:
+ * @ CAS latency = 3: 7.5ns
+ * @ CAS latency = 2: 10ns
+ * We're running at 66MHz (15ns cycle time) external bus speed (HCLK),
+ * so it's safe to use CAS latency = 2
+ *
+ * RAS-to-CAS delay min:
+ * 20ns
+ * At 15ns cycle time, we use RAS-to-CAS delay = 2
+ *
+ * SROMLL = 1: Swap BA[1:0] with A[13:12], making the SDRAM appear
+ * as four blocks of 8MB size, instead of eight blocks of 4MB size:
+ *
+ * EDB9301/EDB9302:
+ *
+ * 0x00000000 - 0x007fffff
+ * 0x01000000 - 0x017fffff
+ * 0x04000000 - 0x047fffff
+ * 0x05000000 - 0x057fffff
+ *
+ *
+ * EDB9302a:
+ *
+ * 0xc0000000 - 0xc07fffff
+ * 0xc1000000 - 0xc17fffff
+ * 0xc4000000 - 0xc47fffff
+ * 0xc5000000 - 0xc57fffff
+ *
+ * BANKCOUNT = 1: This is a device with four banks
+ */
+
+#define SDRAM_DEVCFG_VAL (SDRAM_DEVCFG_BANKCOUNT | \
+ SDRAM_DEVCFG_SROMLL | \
+ SDRAM_DEVCFG_CASLAT_2 | \
+ SDRAM_DEVCFG_RASTOCAS_2 | \
+ SDRAM_DEVCFG_EXTBUSWIDTH)
+
+/*
+ * 16 bit ext. bus
+ *
+ * A[22:09] is output as SYA[13:0]
+ * CAS latency: 2
+ * Burst type: sequential
+ * Burst length: 8 (required for 16 bit ext. bus)
+ * SYA[13:0] = 0x0023
+ */
+#define SDRAM_MODE_REG_VAL 0x4600
+
+#define SDRAM_BANK_SEL_0 0x00000000 /* A[22:21] = b00 */
+#define SDRAM_BANK_SEL_1 0x00200000 /* A[22:21] = b01 */
+#define SDRAM_BANK_SEL_2 0x00400000 /* A[22:21] = b10 */
+#define SDRAM_BANK_SEL_3 0x00600000 /* A[22:21] = b11 */
+
+#elif defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9307A) ||\
+ defined CONFIG_MACH_EDB9312 || defined(CONFIG_MACH_EDB9315) ||\
+ defined(CONFIG_MACH_EDB9315A)
+/*
+ * 2x Samsung K4S561632C-TC/L75 4M x 16bit x 4 banks SDRAM
+ *
+ * CLK cycle time min:
+ * @ CAS latency = 3: 7.5ns
+ * @ CAS latency = 2: 10ns
+ * We're running at 100MHz (10ns cycle time) external bus speed (HCLK),
+ * so it's safe to use CAS latency = 2
+ *
+ * RAS-to-CAS delay min:
+ * 20ns
+ * At 10ns cycle time, we use RAS-to-CAS delay = 2
+ *
+ * EDB9307, EDB9312, EDB9315:
+ *
+ * 0x00000000 - 0x01ffffff
+ * 0x04000000 - 0x05ffffff
+ *
+ *
+ * EDB9307a, EDB9315a:
+ *
+ * 0xc0000000 - 0xc1ffffff
+ * 0xc4000000 - 0xc5ffffff
+ */
+
+#define SDRAM_DEVCFG_VAL (SDRAM_DEVCFG_BANKCOUNT | \
+ SDRAM_DEVCFG_SROMLL | \
+ SDRAM_DEVCFG_CASLAT_2 | \
+ SDRAM_DEVCFG_RASTOCAS_2)
+
+/*
+ * 32 bit ext. bus
+ *
+ * A[23:10] is output as SYA[13:0]
+ * CAS latency: 2
+ * Burst type: sequential
+ * Burst length: 4
+ * SYA[13:0] = 0x0022
+ */
+#define SDRAM_MODE_REG_VAL 0x8800
+
+#define SDRAM_BANK_SEL_0 0x00000000 /* A[23:22] = b00 */
+#define SDRAM_BANK_SEL_1 0x00400000 /* A[23:22] = b01 */
+#define SDRAM_BANK_SEL_2 0x00800000 /* A[23:22] = b10 */
+#define SDRAM_BANK_SEL_3 0x00c00000 /* A[23:22] = b11 */
+#endif
diff --git a/board/eukrea_cpuimx27/eukrea_cpuimx27.c b/board/eukrea_cpuimx27/eukrea_cpuimx27.c
index 68780449..0908dca7 100644
--- a/board/eukrea_cpuimx27/eukrea_cpuimx27.c
+++ b/board/eukrea_cpuimx27/eukrea_cpuimx27.c
@@ -21,6 +21,7 @@
*/
#include <common.h>
+#include <errno.h>
#include <net.h>
#include <cfi_flash.h>
#include <init.h>
@@ -42,6 +43,8 @@
#include <mach/imx-pll.h>
#include <ns16550.h>
#include <asm/mmu.h>
+#include <i2c/i2c.h>
+#include <i2c/lp3972.h>
static struct device_d cfi_dev = {
.name = "cfi_flash",
@@ -140,6 +143,17 @@ static struct device_d quad_uart_serial_device = {
};
#endif
+static struct i2c_board_info i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("lp3972", 0x34),
+ },
+};
+
+static struct device_d i2c_dev = {
+ .name = "i2c-imx",
+ .map_base = IMX_I2C1_BASE,
+};
+
#ifdef CONFIG_MMU
static void eukrea_cpuimx27_mmu_init(void)
{
@@ -187,6 +201,8 @@ static int eukrea_cpuimx27_devices_init(void)
PD15_AOUT_FEC_COL,
PD16_AIN_FEC_TX_ER,
PF23_AIN_FEC_TX_EN,
+ PD17_PF_I2C_DATA,
+ PD18_PF_I2C_CLK,
#ifdef CONFIG_DRIVER_SERIAL_IMX
PE12_PF_UART1_TXD,
PE13_PF_UART1_RXD,
@@ -198,9 +214,9 @@ static int eukrea_cpuimx27_devices_init(void)
eukrea_cpuimx27_mmu_init();
/* configure 16 bit nor flash on cs0 */
- CS0U = 0x0000CC03;
- CS0L = 0xa0330D01;
- CS0A = 0x00220800;
+ CS0U = 0x00008F03;
+ CS0L = 0xA0330D01;
+ CS0A = 0x002208C0;
/* initizalize gpios */
for (i = 0; i < ARRAY_SIZE(mode); i++)
@@ -213,6 +229,10 @@ static int eukrea_cpuimx27_devices_init(void)
register_device(&nand_dev);
register_device(&sdram_dev);
+ PCCR0 |= PCCR0_I2C1_EN;
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+ register_device(&i2c_dev);
+
devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0");
protect_file("/dev/env0", 1);
@@ -244,9 +264,9 @@ static int eukrea_cpuimx27_console_init(void)
#endif
/* configure 8 bit UART on cs3 */
FMCR &= ~0x2;
- CS3U = 0x0000DCF6;
- CS3L = 0x444A4541;
- CS3A = 0x44443302;
+ CS3U = 0x0000D603;
+ CS3L = 0x0D1D0D01;
+ CS3A = 0x00D20000;
#ifdef CONFIG_DRIVER_SERIAL_NS16550
register_device(&quad_uart_serial_device);
#endif
@@ -257,9 +277,18 @@ console_initcall(eukrea_cpuimx27_console_init);
static int eukrea_cpuimx27_late_init(void)
{
+ struct i2c_client *client;
+ u8 reg[1];
+
console_flush();
register_device(&fec_dev);
+ client = lp3972_get_client();
+ if (!client)
+ return -ENODEV;
+ reg[0] = 0xa0;
+ i2c_write_reg(client, 0x39, reg, sizeof(reg));
+
return 0;
}
diff --git a/board/eukrea_cpuimx27/lowlevel_init.S b/board/eukrea_cpuimx27/lowlevel_init.S
index 4622af88..5295a8a2 100644
--- a/board/eukrea_cpuimx27/lowlevel_init.S
+++ b/board/eukrea_cpuimx27/lowlevel_init.S
@@ -8,10 +8,10 @@
#if defined CONFIG_EUKREA_CPUIMX27_SDRAM_256MB
#define ROWS0 ESDCTL_ROW14
-#define CFG0 0x00695729
+#define CFG0 0x0029572D
#elif defined CONFIG_EUKREA_CPUIMX27_SDRAM_128MB
#define ROWS0 ESDCTL_ROW13
-#define CFG0 0x00395B28
+#define CFG0 0x00095728
#endif
#define ESDCTL0_VAL (ESDCTL0_SDE | ROWS0 | ESDCTL0_COL10)
diff --git a/board/freescale-mx35-3-stack/3stack.c b/board/freescale-mx35-3-stack/3stack.c
index e5419661..e6fa0f04 100644
--- a/board/freescale-mx35-3-stack/3stack.c
+++ b/board/freescale-mx35-3-stack/3stack.c
@@ -60,8 +60,8 @@ static struct device_d cfi_dev = {
};
static struct fec_platform_data fec_info = {
- .xcv_type = MII100,
- .phy_addr = 0x1F,
+ .xcv_type = MII100,
+ .phy_addr = 0x1F,
};
static struct device_d fec_dev = {
@@ -71,8 +71,8 @@ static struct device_d fec_dev = {
};
static struct memory_platform_data sdram_pdata = {
- .name = "ram0",
- .flags = DEVFS_RDWR,
+ .name = "ram0",
+ .flags = DEVFS_RDWR,
};
static struct device_d sdram_dev = {
@@ -157,7 +157,7 @@ static int f3s_devices_init(void)
reg = readl(IMX_CCM_BASE + CCM_RCSR);
/* some fuses provide us vital information about connected hardware */
if (reg & 0x20000000)
- nand_info.width = 2; /* bit */
+ nand_info.width = 2; /* 16 bit */
else
nand_info.width = 1; /* 8 bit */
@@ -167,17 +167,17 @@ static int f3s_devices_init(void)
register_device(&nand_dev);
register_device(&cfi_dev);
- switch ( (reg >> 25) & 0x3) {
+ switch ((reg >> 25) & 0x3) {
case 0x01: /* NAND is the source */
devfs_add_partition("nand0", 0x00000, 0x40000, PARTITION_FIXED, "self_raw");
dev_add_bb_dev("self_raw", "self0");
- devfs_add_partition("nand0", 0x40000, 0x20000, PARTITION_FIXED, "env_raw");
+ devfs_add_partition("nand0", 0x40000, 0x80000, PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
break;
case 0x00: /* NOR is the source */
devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
- devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0");
+ devfs_add_partition("nor0", 0x40000, 0x80000, PARTITION_FIXED, "env0");
protect_file("/dev/env0", 1);
break;
}
@@ -332,7 +332,7 @@ static int f3s_core_init(void)
/* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */
#define MAX_PARAM1 0x00302154
- writel(MAX_PARAM1, IMX_MAX_BASE + 0x0); /* for S0 */
+ writel(MAX_PARAM1, IMX_MAX_BASE + 0x000); /* for S0 */
writel(MAX_PARAM1, IMX_MAX_BASE + 0x100); /* for S1 */
writel(MAX_PARAM1, IMX_MAX_BASE + 0x200); /* for S2 */
writel(MAX_PARAM1, IMX_MAX_BASE + 0x300); /* for S3 */
@@ -358,74 +358,84 @@ static int f3s_core_init(void)
core_initcall(f3s_core_init);
-static int f3s_get_rev(struct i2c_client *client)
+static int f3s_get_rev(struct mc13892 *mc13892)
{
- u8 reg[3];
- int rev;
+ u32 rev;
+ int err;
- i2c_read_reg(client, 0x7, reg, sizeof(reg));
+ err = mc13892_reg_read(mc13892, MC13892_REG_IDENTIFICATION, &rev);
+ if (err)
+ return err;
- rev = reg[0] << 16 | reg [1] << 8 | reg[2];
- dev_info(&client->dev, "revision: 0x%x\n", rev);
+ dev_info(&mc13892->client->dev, "revision: 0x%x\n", rev);
+ if (rev == 0x00ffffff)
+ return -ENODEV;
- /* just return '0' or '1' */
- return !!((rev >> 6) & 0x7);
+ return ((rev >> 6) & 0x7) ? 20 : 10;
}
-static void f3s_pmic_init_v2(struct i2c_client *client)
+static int f3s_pmic_init_v2(struct mc13892 *mc13892)
{
- u8 reg[3];
+ int err = 0;
- i2c_read_reg(client, 0x1e, reg, sizeof(reg));
- reg[2] |= 0x03;
- i2c_write_reg(client, 0x1e, reg, sizeof(reg));
+ err |= mc13892_set_bits(mc13892, MC13892_REG_SETTING_0, 0x03, 0x03);
+ err |= mc13892_set_bits(mc13892, MC13892_REG_MODE_0, 0x01, 0x01);
+ if (err)
+ dev_err(&mc13892->client->dev,
+ "Init sequence failed, the system might not be working!\n");
- i2c_read_reg(client, 0x20, reg, sizeof(reg));
- reg[2] |= 0x01;
- i2c_write_reg(client, 0x20, reg, sizeof(reg));
+ return err;
}
-static void f3s_pmic_init_all(struct i2c_client *client)
+static int f3s_pmic_init_all(struct mc9sdz60 *mc9sdz60)
{
- u8 reg[1];
+ int err = 0;
- i2c_read_reg(client, 0x20, reg, sizeof(reg));
- reg[0] |= 0x04;
- i2c_write_reg(client, 0x20, reg, sizeof(reg));
+ err |= mc9sdz60_set_bits(mc9sdz60, MC9SDZ60_REG_INT_FLAG_1, 0x04, 0x04);
+ err |= mc9sdz60_set_bits(mc9sdz60, MC9SDZ60_REG_GPIO_2, 0x80, 0x00);
mdelay(200);
+ err |= mc9sdz60_set_bits(mc9sdz60, MC9SDZ60_REG_GPIO_2, 0x80, 0x80);
- i2c_read_reg(client, 0x1a, reg, sizeof(reg));
- reg[0] &= 0x7f;
- i2c_write_reg(client, 0x1a, reg, sizeof(reg));
-
- mdelay(200);
+ if (err)
+ dev_err(&mc9sdz60->client->dev,
+ "Init sequence failed, the system might not be working!\n");
- reg[0] |= 0x80;
- i2c_write_reg(client, 0x1a, reg, sizeof(reg));
+ return err;
}
static int f3s_pmic_init(void)
{
- struct i2c_client *client;
+ struct mc13892 *mc13892;
+ struct mc9sdz60 *mc9sdz60;
int rev;
- client = mc13892_get_client();
- if (!client)
- return -ENODEV;
+ mc13892 = mc13892_get();
+ if (!mc13892) {
+ printf("FAILED to get mc13892 handle!\n");
+ return 0;
+ }
- rev = f3s_get_rev(client);
- if (rev) {
- printf("i.MX35 CPU board version 2.0\n");
- f3s_pmic_init_v2(client);
- } else {
- printf("i.MX35 CPU board version 1.0\n");
+ rev = f3s_get_rev(mc13892);
+ switch (rev) {
+ case 10:
+ break;
+ case 20:
+ f3s_pmic_init_v2(mc13892);
+ break;
+ default:
+ printf("FAILED to identify board revision!\n");
+ return 0;
}
+ printf("i.MX35 PDK CPU board version %d.%d\n", rev / 10, rev % 10);
- client = mc9sdz60_get_client();
- if (!client)
- return -ENODEV;
- f3s_pmic_init_all(client);
+ mc9sdz60 = mc9sdz60_get();
+ if (!mc9sdz60) {
+ printf("FAILED to get mc9sdz60 handle!\n");
+ return 0;
+ }
+
+ f3s_pmic_init_all(mc9sdz60);
return 0;
}
@@ -442,4 +452,3 @@ void __bare_init nand_boot(void)
imx_nand_load_image((void *)TEXT_BASE, 256 * 1024);
}
#endif
-
diff --git a/board/freescale-mx35-3-stack/env/bin/_update b/board/freescale-mx35-3-stack/env/bin/_update
index fb7cbe86..4f0839f8 100644
--- a/board/freescale-mx35-3-stack/env/bin/_update
+++ b/board/freescale-mx35-3-stack/env/bin/_update
@@ -20,7 +20,7 @@ fi
ping $eth0.serverip
if [ $? -ne 0 ] ; then
- echo "update aborted"
+ echo "Server did not reply! Update aborted."
exit 1
fi
@@ -28,9 +28,12 @@ unprotect $part
echo
echo "erasing partition $part"
+echo
erase $part
echo
echo "flashing $image to $part"
echo
tftp $image $part
+
+protect $part
diff --git a/board/freescale-mx35-3-stack/env/bin/boot b/board/freescale-mx35-3-stack/env/bin/boot
index dfb59aa6..fb2fe614 100644
--- a/board/freescale-mx35-3-stack/env/bin/boot
+++ b/board/freescale-mx35-3-stack/env/bin/boot
@@ -3,43 +3,53 @@
. /env/config
if [ x$1 = xnand ]; then
- root=nand
- kernel=nand
+ rootfs_loc=nand
+ kernel_loc=nand
+elif [ x$1 = xnor ]; then
+ rootfs_loc=nor
+ kernel_loc=nor
+elif [ x$1 = xnet ]; then
+ rootfs_loc=net
+ kernel_loc=net
fi
-if [ x$1 = xnet ]; then
- root=net
- kernel=net
-fi
-
-if [ x$1 = xnor ]; then
- root=nor
- kernel=nor
-fi
if [ x$ip = xdhcp ]; then
bootargs="$bootargs ip=dhcp"
-else
+elif [ x$ip != xno ]; then
bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask:::"
fi
-if [ x$root = xnand ]; then
- bootargs="$bootargs root=$rootpart_nand rootfstype=jffs2"
-elif [ x$root = xnor ]; then
- bootargs="$bootargs root=$rootpart_nor rootfstype=jffs2"
+
+if [ $rootfs_loc != net ]; then
+ if [ x$rootfs_loc = xnand ]; then
+ rootfs_mtdblock=$rootfs_mtdblock_nand
+ else
+ rootfs_mtdblock=$rootfs_mtdblock_nor
+ fi
+
+
+ if [ $rootfs_type = ubifs ]; then
+ bootargs="$bootargs root=ubi0:root ubi.mtd=$rootfs_mtdblock"
+ else
+ bootargs="$bootargs root=/dev/mtdblock$rootfs_mtdblock"
+ fi
+
+ bootargs="$bootargs rootfstype=$rootfs_type"
else
bootargs="$bootargs root=/dev/nfs nfsroot=$eth0.serverip:$nfsroot,v3,tcp"
fi
-bootargs="$bootargs mtdparts=physmap-flash.0:$nor_parts;imx_nand:$nand_parts"
-if [ $kernel = net ]; then
+bootargs="$bootargs mtdparts=\"physmap-flash.0:$nor_parts;mxc_nand:$nand_parts\""
+
+if [ $kernel_loc = net ]; then
if [ x$ip = xdhcp ]; then
dhcp
fi
- tftp $uimage uImage || exit 1
+ tftp $kernel uImage || exit 1
bootm uImage
-elif [ $kernel = nor ]; then
+elif [ $kernel_loc = nor ]; then
bootm /dev/nor0.kernel
else
bootm /dev/nand0.kernel.bb
diff --git a/board/freescale-mx35-3-stack/env/bin/init b/board/freescale-mx35-3-stack/env/bin/init
index cdf0f6b8..c982f22a 100644
--- a/board/freescale-mx35-3-stack/env/bin/init
+++ b/board/freescale-mx35-3-stack/env/bin/init
@@ -16,12 +16,13 @@ if [ -e /dev/nand0 ]; then
source /env/bin/hush_hack
fi
-#if [ -z $eth0.ethaddr ]; then
-# while [ -z $eth0.ethaddr ]; do
-# readline "no MAC address set for eth0. please enter the one found on your board: " eth0.ethaddr
-# done
-# echo -a /env/config "eth0.ethaddr=$eth0.ethaddr"
-#fi
+if [ -z $eth0.ethaddr ]; then
+ while [ -z $eth0.ethaddr ]; do
+ readline "no MAC address set for eth0. please enter the one found on your board: " eth0.ethaddr
+ done
+ echo -a /env/config "eth0.ethaddr=$eth0.ethaddr"
+ saveenv
+fi
echo
echo -n "Hit any key to stop autoboot: "
@@ -29,7 +30,7 @@ timeout -a $autoboot_timeout
if [ $? != 0 ]; then
echo
echo "type update_kernel nand|nor [<imagename>] to update kernel into flash"
- echo "type update_root nand|nor [<imagename>] to update rootfs into flash"
+ echo "type update_rootfs nand|nor [<imagename>] to update rootfs into flash"
echo
exit
fi
diff --git a/board/freescale-mx35-3-stack/env/bin/update_kernel b/board/freescale-mx35-3-stack/env/bin/update_kernel
index 05c822d8..63ad11aa 100644
--- a/board/freescale-mx35-3-stack/env/bin/update_kernel
+++ b/board/freescale-mx35-3-stack/env/bin/update_kernel
@@ -1,8 +1,8 @@
#!/bin/sh
. /env/config
+image=$kernel
-image=$uimage
if [ x$1 = xnand ]; then
part=/dev/nand0.kernel.bb
elif [ x$1 = xnor ]; then
diff --git a/board/freescale-mx35-3-stack/env/bin/update_root b/board/freescale-mx35-3-stack/env/bin/update_rootfs
index eaf36ebc..53dd2ca5 100644
--- a/board/freescale-mx35-3-stack/env/bin/update_root
+++ b/board/freescale-mx35-3-stack/env/bin/update_rootfs
@@ -2,7 +2,12 @@
. /env/config
-image=$uimage
+if [ $rootfs_type = ubifs ]; then
+ image=${rootfs}.ubi
+else
+ image=${rootfs}.$rootfs_type
+fi
+
if [ x$1 = xnand ]; then
part=/dev/nand0.root.bb
elif [ x$1 = xnor ]; then
@@ -13,4 +18,3 @@ else
fi
. /env/bin/_update $2
-
diff --git a/board/freescale-mx35-3-stack/env/config b/board/freescale-mx35-3-stack/env/config
index 9fcb3dc7..51195f74 100644
--- a/board/freescale-mx35-3-stack/env/config
+++ b/board/freescale-mx35-3-stack/env/config
@@ -1,28 +1,35 @@
#!/bin/sh
+# use 'dhcp' to do dhcp in barebox and in kernel
+# use 'no' if you don't want to pass the ip from barebox to the kernel
+#ip=dhcp
+
+# or set your networking parameters here
+#eth0.ipaddr=a.b.c.d
+#eth0.netmask=a.b.c.d
+#eth0.gateway=a.b.c.d
+#eth0.serverip=a.b.c.d
+
# can be either 'net', 'nor' or 'nand''
-kernel=net
-root=net
+kernel_loc=nand
+rootfs_loc=nand
-uimage=uImage-pcm038
-jffs2=root-pcm038.jffs2
+# can be either 'jffs2', or 'ubifs'
+rootfs_type=ubifs
+
+kernel=uImage-mx35-3-stack
+rootfs=root-mx35-3-stack
+envimage=u-boot-v2-environment-mx35-3-stack
autoboot_timeout=3
-nfsroot="/ptx/work/octopus/rsc/svn/oselas/bsp/phytec/phyCORE-i.MX27/OSELAS.BSP-Phytec-phyCORE-i.MX27-trunk/root"
+nfsroot="/path/to/nfs/root"
bootargs="console=ttymxc0,115200"
-nor_parts="256k(barebox)ro,128k(bareboxenv),1536k(kernel),-(root)"
-rootpart_nor="/dev/mtdblock3"
-
-nand_parts="256k(barebox)ro,128k(bareboxenv),1536k(kernel),-(root)"
-rootpart_nand="/dev/mtdblock7"
+bootargs="$bootargs video=mx3fb:CTP-CLAA070LC0ACW"
-# use 'dhcp' to do dhcp in barebox and in kernel
-ip=dhcp
+nor_parts="256k(barebox)ro,512k(bareboxenv),2M(kernel),-(root)"
+rootfs_mtdblock_nor=3
-# or set your networking parameters here
-#eth0.ipaddr=a.b.c.d
-#eth0.netmask=a.b.c.d
-#eth0.gateway=a.b.c.d
-#eth0.serverip=a.b.c.d
+nand_parts="256k(barebox)ro,512k(bareboxenv),2M(kernel),-(root)"
+rootfs_mtdblock_nand=7
diff --git a/board/freescale-mx35-3-stack/lowlevel_init.S b/board/freescale-mx35-3-stack/lowlevel_init.S
index 4e0a1029..1680579b 100644
--- a/board/freescale-mx35-3-stack/lowlevel_init.S
+++ b/board/freescale-mx35-3-stack/lowlevel_init.S
@@ -27,9 +27,9 @@
#include <asm/cache-l2x0.h>
#include "board-mx35_3stack.h"
-#define CSD0_BASE_ADDR 0x80000000
-#define ESDCTL_BASE_ADDR 0xB8001000
-#define CSD1_BASE_ADDR 0x90000000
+#define CSD0_BASE_ADDR 0x80000000
+#define ESDCTL_BASE_ADDR 0xB8001000
+#define CSD1_BASE_ADDR 0x90000000
#define writel(val, reg) \
ldr r0, =reg; \
@@ -42,84 +42,84 @@
strb r1, [r0];
/* Assuming 24MHz input clock */
-#define MPCTL_PARAM_399 (IMX_PLL_PD(0) | IMX_PLL_MFD(15) | IMX_PLL_MFI(8) | IMX_PLL_MFN(5))
-#define MPCTL_PARAM_532 ((1 << 31) | IMX_PLL_PD(0) | IMX_PLL_MFD(11) | IMX_PLL_MFI(11) | IMX_PLL_MFN(1))
-#define PPCTL_PARAM_300 (IMX_PLL_PD(0) | IMX_PLL_MFD(3) | IMX_PLL_MFI(6) | IMX_PLL_MFN(1))
+#define MPCTL_PARAM_399 (IMX_PLL_PD(0) | IMX_PLL_MFD(15) | IMX_PLL_MFI(8) | IMX_PLL_MFN(5))
+#define MPCTL_PARAM_532 ((1 << 31) | IMX_PLL_PD(0) | IMX_PLL_MFD(11) | IMX_PLL_MFI(11) | IMX_PLL_MFN(1))
+#define PPCTL_PARAM_300 (IMX_PLL_PD(0) | IMX_PLL_MFD(3) | IMX_PLL_MFI(6) | IMX_PLL_MFN(1))
.section ".text_bare_init","ax"
-ARM_PPMRR: .word 0x40000015
-L2CACHE_PARAM: .word 0x00030024
-CCM_CCMR_W: .word 0x003F4208
-CCM_PDR0_W: .word 0x00001000
-MPCTL_PARAM_399_W: .word MPCTL_PARAM_399
-MPCTL_PARAM_532_W: .word MPCTL_PARAM_532
-PPCTL_PARAM_W: .word PPCTL_PARAM_300
-CCM_BASE_ADDR_W: .word IMX_CCM_BASE
+ARM_PPMRR: .word 0x40000015
+L2CACHE_PARAM: .word 0x00030024
+CCM_CCMR_W: .word 0x003F4208
+CCM_PDR0_W: .word 0x00001000
+MPCTL_PARAM_399_W: .word MPCTL_PARAM_399
+MPCTL_PARAM_532_W: .word MPCTL_PARAM_532
+PPCTL_PARAM_W: .word PPCTL_PARAM_300
+CCM_BASE_ADDR_W: .word IMX_CCM_BASE
.globl board_init_lowlevel
board_init_lowlevel:
- mov r10, lr
+ mov r10, lr
- mrc 15, 0, r1, c1, c0, 0
+ mrc 15, 0, r1, c1, c0, 0
- mrc 15, 0, r0, c1, c0, 1
- orr r0, r0, #7
- mcr 15, 0, r0, c1, c0, 1
+ mrc 15, 0, r0, c1, c0, 1
+ orr r0, r0, #7
+ mcr 15, 0, r0, c1, c0, 1
- orr r1, r1, #(1<<11) /* Flow prediction (Z) */
- orr r1, r1, #(1<<22) /* unaligned accesses */
- orr r1, r1, #(1<<21) /* Low Int Latency */
+ orr r1, r1, #(1 << 11) /* Flow prediction (Z) */
+ orr r1, r1, #(1 << 22) /* unaligned accesses */
+ orr r1, r1, #(1 << 21) /* Low Int Latency */
- mcr 15, 0, r1, c1, c0, 0
+ mcr 15, 0, r1, c1, c0, 0
- mov r0, #0
- mcr 15, 0, r0, c15, c2, 4
+ mov r0, #0
+ mcr 15, 0, r0, c15, c2, 4
/*
- * Branch predicition is now enabled. Flush the BTAC to ensure a valid
- * starting point. Don't flush BTAC while it is disabled to avoid
+ * Branch predicition is now enabled. Flush the BTAC to ensure a valid
+ * starting point. Don't flush BTAC while it is disabled to avoid
* ARM1136 erratum 408023.
*/
- mov r0, #0
- mcr p15, 0, r0, c7, c5, 6 /* flush entire BTAC */
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 6 /* flush entire BTAC */
- mov r0, #0
- mcr 15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */
- mcr 15, 0, r0, c8, c7, 0 /* invalidate TLBs */
- mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */
+ mov r0, #0
+ mcr 15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */
+ mcr 15, 0, r0, c8, c7, 0 /* invalidate TLBs */
+ mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */
/* Also setup the Peripheral Port Remap register inside the core */
- ldr r0, ARM_PPMRR /* start from AIPS 2GB region */
- mcr p15, 0, r0, c15, c2, 4
+ ldr r0, ARM_PPMRR /* start from AIPS 2GB region */
+ mcr p15, 0, r0, c15, c2, 4
/*
* End of ARM1136 init
*/
- ldr r0, CCM_BASE_ADDR_W
+ ldr r0, CCM_BASE_ADDR_W
- ldr r2, CCM_CCMR_W
- str r2, [r0, #CCM_CCMR]
+ ldr r2, CCM_CCMR_W
+ str r2, [r0, #CCM_CCMR]
- ldr r3, MPCTL_PARAM_532_W /* consumer path*/
+ ldr r3, MPCTL_PARAM_532_W /* consumer path*/
- /* Set MPLL , arm clock and ahb clock*/
- str r3, [r0, #CCM_MPCTL]
+ /* Set MPLL, arm clock and ahb clock */
+ str r3, [r0, #CCM_MPCTL]
- ldr r1, PPCTL_PARAM_W
- str r1, [r0, #CCM_PPCTL]
+ ldr r1, PPCTL_PARAM_W
+ str r1, [r0, #CCM_PPCTL]
- ldr r1, CCM_PDR0_W
- str r1, [r0, #CCM_PDR0]
+ ldr r1, CCM_PDR0_W
+ str r1, [r0, #CCM_PDR0]
- ldr r1, [r0, #CCM_CGR0]
- orr r1, r1, #0x00300000
- str r1, [r0, #CCM_CGR0]
+ ldr r1, [r0, #CCM_CGR0]
+ orr r1, r1, #0x00300000
+ str r1, [r0, #CCM_CGR0]
- ldr r1, [r0, #CCM_CGR1]
- orr r1, r1, #0x00000C00
- orr r1, r1, #0x00000003
- str r1, [r0, #CCM_CGR1]
+ ldr r1, [r0, #CCM_CGR1]
+ orr r1, r1, #0x00000C00
+ orr r1, r1, #0x00000003
+ str r1, [r0, #CCM_CGR1]
/* Skip SDRAM initialization if we run from RAM */
cmp pc, #0x80000000
@@ -130,33 +130,33 @@ board_init_lowlevel:
mov pc, r10
1:
- ldr r0, =ESDCTL_BASE_ADDR
- mov r3, #0x2000
- str r3, [r0, #0x0]
- str r3, [r0, #0x8]
+ ldr r0, =ESDCTL_BASE_ADDR
+ mov r3, #0x2000
+ str r3, [r0, #0x0]
+ str r3, [r0, #0x8]
- /* ip(r12) has used to save lr register in upper calling*/
- mov fp, lr
+ /* ip(r12) has used to save lr register in upper calling */
+ mov fp, lr
- mov r5, #0x00
- mov r2, #0x00
- mov r1, #CSD0_BASE_ADDR
- bl setup_sdram_bank
- cmp r3, #0x0
- orreq r5, r5, #1
- eorne r2, r2, #0x1
- blne setup_sdram_bank
+ mov r5, #0x00
+ mov r2, #0x00
+ mov r1, #CSD0_BASE_ADDR
+ bl setup_sdram_bank
+ cmp r3, #0x0
+ orreq r5, r5, #1
+ eorne r2, r2, #0x1
+ blne setup_sdram_bank
- mov lr, fp
+ mov lr, fp
- ldr r3, =ESDCTL_DELAY_LINE5
- str r3, [r0, #0x30]
+ ldr r3, =ESDCTL_DELAY_LINE5
+ str r3, [r0, #0x30]
#ifdef CONFIG_NAND_IMX_BOOT
- ldr sp, =TEXT_BASE - 4 /* Setup a temporary stack in SDRAM */
+ ldr sp, =TEXT_BASE - 4 /* Setup a temporary stack in SDRAM */
- ldr r0, =IMX_NFC_BASE /* start of NFC SRAM */
- ldr r2, =IMX_NFC_BASE + 0x800 /* end of NFC SRAM */
+ ldr r0, =IMX_NFC_BASE /* start of NFC SRAM */
+ ldr r2, =IMX_NFC_BASE + 0x800 /* end of NFC SRAM */
/* skip NAND boot if not running from NFC space */
cmp pc, r0
@@ -165,119 +165,119 @@ board_init_lowlevel:
bhs ret
/* Move ourselves out of NFC SRAM */
- ldr r1, =TEXT_BASE
+ ldr r1, =TEXT_BASE
copy_loop:
- ldmia r0!, {r3-r9} /* copy from source address [r0] */
- stmia r1!, {r3-r9} /* copy to target address [r1] */
- cmp r0, r2 /* until source end addreee [r2] */
+ ldmia r0!, {r3-r9} /* copy from source address [r0] */
+ stmia r1!, {r3-r9} /* copy to target address [r1] */
+ cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
- ldr pc, =1f /* Jump to SDRAM */
+ ldr pc, =1f /* Jump to SDRAM */
1:
- bl nand_boot /* Load barebox from NAND Flash */
+ bl nand_boot /* Load barebox from NAND Flash */
/* rebase the return address */
ldr r1, =IMX_NFC_BASE - TEXT_BASE
- sub r10, r10, r1 /* adjust return address from NFC SRAM */
+ sub r10, r10, r1 /* adjust return address from NFC SRAM */
ret:
#endif /* CONFIG_NAND_IMX_BOOT */
- mov pc, r10
+ mov pc, r10
/*
* r0: ESDCTL control base, r1: sdram slot base
- * r2: DDR type(0:DDR2, 1:MDDR) r3, r4:working base
+ * r2: DDR type (0: DDR2, 1: MDDR) r3, r4: working base
*/
setup_sdram_bank:
- mov r3, #0xE /*0xA + 0x4*/
- tst r2, #0x1
- orreq r3, r3, #0x300 /*DDR2*/
- str r3, [r0, #0x10]
- bic r3, r3, #0x00A
- str r3, [r0, #0x10]
- beq 2f
-
- mov r3, #0x20000
-1: subs r3, r3, #1
- bne 1b
-
-2: tst r2, #0x1
- ldreq r3, =ESDCTL_DDR2_CONFIG
- ldrne r3, =ESDCTL_MDDR_CONFIG
- cmp r1, #CSD1_BASE_ADDR
- strlo r3, [r0, #0x4]
- strhs r3, [r0, #0xC]
-
- ldr r3, =ESDCTL_0x92220000
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
- mov r3, #0xDA
- ldr r4, =ESDCTL_PRECHARGE
- strb r3, [r1, r4]
-
- tst r2, #0x1
- bne skip_set_mode
-
- cmp r1, #CSD1_BASE_ADDR
- ldr r3, =ESDCTL_0xB2220000
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
- mov r3, #0xDA
- ldr r4, =ESDCTL_DDR2_EMR2
- strb r3, [r1, r4]
- ldr r4, =ESDCTL_DDR2_EMR3
- strb r3, [r1, r4]
- ldr r4, =ESDCTL_DDR2_EN_DLL
- strb r3, [r1, r4]
- ldr r4, =ESDCTL_DDR2_RESET_DLL
- strb r3, [r1, r4]
-
- ldr r3, =ESDCTL_0x92220000
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
- mov r3, #0xDA
- ldr r4, =ESDCTL_PRECHARGE
- strb r3, [r1, r4]
+ mov r3, #0xE /* 0xA + 0x4 */
+ tst r2, #0x1
+ orreq r3, r3, #0x300 /* DDR2 */
+ str r3, [r0, #0x10]
+ bic r3, r3, #0x00A
+ str r3, [r0, #0x10]
+ beq 2f
+
+ mov r3, #0x20000
+1: subs r3, r3, #1
+ bne 1b
+
+2: tst r2, #0x1
+ ldreq r3, =ESDCTL_DDR2_CONFIG
+ ldrne r3, =ESDCTL_MDDR_CONFIG
+ cmp r1, #CSD1_BASE_ADDR
+ strlo r3, [r0, #0x4]
+ strhs r3, [r0, #0xC]
+
+ ldr r3, =ESDCTL_0x92220000
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+ mov r3, #0xDA
+ ldr r4, =ESDCTL_PRECHARGE
+ strb r3, [r1, r4]
+
+ tst r2, #0x1
+ bne skip_set_mode
+
+ cmp r1, #CSD1_BASE_ADDR
+ ldr r3, =ESDCTL_0xB2220000
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+ mov r3, #0xDA
+ ldr r4, =ESDCTL_DDR2_EMR2
+ strb r3, [r1, r4]
+ ldr r4, =ESDCTL_DDR2_EMR3
+ strb r3, [r1, r4]
+ ldr r4, =ESDCTL_DDR2_EN_DLL
+ strb r3, [r1, r4]
+ ldr r4, =ESDCTL_DDR2_RESET_DLL
+ strb r3, [r1, r4]
+
+ ldr r3, =ESDCTL_0x92220000
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+ mov r3, #0xDA
+ ldr r4, =ESDCTL_PRECHARGE
+ strb r3, [r1, r4]
skip_set_mode:
- cmp r1, #CSD1_BASE_ADDR
- ldr r3, =ESDCTL_0xA2220000
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
- mov r3, #0xDA
- strb r3, [r1]
- strb r3, [r1]
-
- ldr r3, =ESDCTL_0xB2220000
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
- tst r2, #0x1
- ldreq r4, =ESDCTL_DDR2_MR
- ldrne r4, =ESDCTL_MDDR_MR
- mov r3, #0xDA
- strb r3, [r1, r4]
- ldreq r4, =ESDCTL_DDR2_OCD_DEFAULT
- streqb r3, [r1, r4]
- ldreq r4, =ESDCTL_DDR2_EN_DLL
- ldrne r4, =ESDCTL_MDDR_EMR
- strb r3, [r1, r4]
-
- cmp r1, #CSD1_BASE_ADDR
- ldr r3, =ESDCTL_0x82228080
- strlo r3, [r0, #0x0]
- strhs r3, [r0, #0x8]
-
- tst r2, #0x1
- moveq r4, #0x20000
- movne r4, #0x200
-1: subs r4, r4, #1
- bne 1b
-
- str r3, [r1, #0x100]
- ldr r4, [r1, #0x100]
- cmp r3, r4
- movne r3, #1
- moveq r3, #0
-
- mov pc, lr
+ cmp r1, #CSD1_BASE_ADDR
+ ldr r3, =ESDCTL_0xA2220000
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+ mov r3, #0xDA
+ strb r3, [r1]
+ strb r3, [r1]
+
+ ldr r3, =ESDCTL_0xB2220000
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+ tst r2, #0x1
+ ldreq r4, =ESDCTL_DDR2_MR
+ ldrne r4, =ESDCTL_MDDR_MR
+ mov r3, #0xDA
+ strb r3, [r1, r4]
+ ldreq r4, =ESDCTL_DDR2_OCD_DEFAULT
+ streqb r3, [r1, r4]
+ ldreq r4, =ESDCTL_DDR2_EN_DLL
+ ldrne r4, =ESDCTL_MDDR_EMR
+ strb r3, [r1, r4]
+
+ cmp r1, #CSD1_BASE_ADDR
+ ldr r3, =ESDCTL_0x82228080
+ strlo r3, [r0, #0x0]
+ strhs r3, [r0, #0x8]
+
+ tst r2, #0x1
+ moveq r4, #0x20000
+ movne r4, #0x200
+1: subs r4, r4, #1
+ bne 1b
+
+ str r3, [r1, #0x100]
+ ldr r4, [r1, #0x100]
+ cmp r3, r4
+ movne r3, #1
+ moveq r3, #0
+
+ mov pc, lr
diff --git a/board/x86_generic/Makefile b/board/x86_generic/Makefile
new file mode 100644
index 00000000..248240da
--- /dev/null
+++ b/board/x86_generic/Makefile
@@ -0,0 +1 @@
+obj-y += generic_pc.o
diff --git a/board/x86_generic/config.h b/board/x86_generic/config.h
new file mode 100644
index 00000000..39bea184
--- /dev/null
+++ b/board/x86_generic/config.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/* nothing special yet */
diff --git a/board/x86_generic/env/bin/boot b/board/x86_generic/env/bin/boot
new file mode 100644
index 00000000..fcfffe31
--- /dev/null
+++ b/board/x86_generic/env/bin/boot
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+. /env/config
+
+if [ x$1 = xdisk ]; then
+ root=disk
+ kernel=disk
+fi
+
+if [ x$1 = xnet ]; then
+ root=net
+ kernel=net
+fi
+
+if [ x$ip = xdhcp ]; then
+ bootargs="$bootargs ip=dhcp"
+else
+ bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask:::"
+fi
+
+if [ x$root = xdisk ]; then
+ bootargs="$bootargs root=$rootpart_disk rootfstype=$rootpart_fs rw"
+else
+ bootargs="$bootargs root=/dev/nfs nfsroot=$eth0.serverip:$nfsroot,v3,tcp rw"
+fi
+
+if [ $kernel = net ]; then
+ if [ x$ip = xdhcp ]; then
+ dhcp
+ fi
+ tftp $uimage uImage || exit 1
+ bootm uImage
+else
+ bootargs="BOOT_IMAGE=$kernel_device auto $bootargs"
+ linux16 $kernel_device
+fi
+
diff --git a/board/x86_generic/env/bin/init b/board/x86_generic/env/bin/init
new file mode 100644
index 00000000..2924a444
--- /dev/null
+++ b/board/x86_generic/env/bin/init
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+PATH=/env/bin
+export PATH
+
+. /env/config
+
+echo
+echo -n "Hit any key to stop autoboot: "
+timeout -a $autoboot_timeout
+if [ $? != 0 ]; then
+ exit
+fi
+
+boot
diff --git a/board/x86_generic/env/config b/board/x86_generic/env/config
new file mode 100644
index 00000000..dd57aad7
--- /dev/null
+++ b/board/x86_generic/env/config
@@ -0,0 +1,31 @@
+#
+# basic config
+#
+# boot source: 'disk' or 'net'
+kernel=disk
+root=disk
+
+# data for the NFS case
+nfsroot="/path/to/nfs_root"
+
+# data for the disk case
+kernel_device=/dev/biosdisk0.1
+rootpart_disk=/dev/sda1
+rootpart_fs=ext2
+
+baudrate=115200
+serial=ttyS0
+
+# use UART for console
+bootargs="console=$serial,$baudrate"
+
+autoboot_timeout=3
+
+# use 'dhcp' to do dhcp in uboot and in kernel
+# ip=dhcp
+# or set your networking parameters here
+# eth0.ipaddr=192.168.3.11
+# eth0.netmask=255.255.255.0
+# eth0.gateway=a.b.c.d
+# eth0.serverip=192.168.3.10
+# eth0.ethaddr=aa.bb.cc.dd.ee.ff
diff --git a/board/x86_generic/generic_pc.c b/board/x86_generic/generic_pc.c
new file mode 100644
index 00000000..bd93bc16
--- /dev/null
+++ b/board/x86_generic/generic_pc.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Generic PC support to let barebox acting as a boot loader
+ */
+
+#include <common.h>
+#include <types.h>
+#include <driver.h>
+#include <init.h>
+#include <asm/syslib.h>
+#include <ns16550.h>
+
+static struct memory_platform_data ram_pdata = {
+ .name = "ram0",
+ .flags = DEVFS_RDWR,
+};
+
+static struct device_d sdram_dev = {
+ .name = "mem",
+ .size = 16 * 1024 * 1024,
+ .map_base = 0,
+ .platform_data = &ram_pdata,
+};
+
+static struct device_d bios_disk_dev = {
+ .name = "biosdrive",
+ .size = 1,
+};
+
+/*
+ * These datas are from the MBR, created by the linker and filled by the
+ * setup tool while installing barebox on the disk drive
+ */
+extern uint64_t pers_env_storage;
+extern uint16_t pers_env_size;
+extern uint8_t pers_env_drive;
+
+/**
+ * Persistant environment "not used" marker.
+ * Note: Must be in accordance to the value the tool "setup_mbr" writes.
+ */
+#define PATCH_AREA_PERS_SIZE_UNUSED 0x000
+
+static int devices_init(void)
+{
+ int rc;
+
+ sdram_dev.size = bios_get_memsize(); /* extended memory only */
+ sdram_dev.size <<= 10;
+
+ register_device(&sdram_dev);
+ register_device(&bios_disk_dev);
+
+ if (pers_env_size != PATCH_AREA_PERS_SIZE_UNUSED) {
+ rc = devfs_add_partition("disk0", /* FIXME */
+ pers_env_storage * 512,
+ (unsigned)pers_env_size * 512,
+ DEVFS_PARTITION_FIXED, "env0");
+ printf("Partition: %d\n", rc);
+ } else
+ printf("No persistant storage defined\n");
+
+ return 0;
+}
+device_initcall(devices_init);
+
+#ifdef CONFIG_DRIVER_SERIAL_NS16550
+
+static struct NS16550_plat serial_plat = {
+ .clock = 1843200,
+ .f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR,
+ .reg_read = x86_uart_read,
+ .reg_write = x86_uart_write,
+};
+
+/* we are expecting always one serial interface */
+static struct device_d generic_pc_serial_device = {
+ .name = "serial_ns16550",
+ .map_base = 0x3f8,
+ .size = 8,
+ .platform_data = (void *)&serial_plat,
+};
+
+static int pc_console_init(void)
+{
+ /* Register the serial port */
+ return register_device(&generic_pc_serial_device);
+}
+console_initcall(pc_console_init);
+
+#endif
+
+/** @page generic_pc Generic PC based bootloader
+
+This platform acts as a generic PC based bootloader. It depends on at least
+one boot media that is connected locally (no network boot) and can be
+handled by the regular BIOS (any kind of hard disks for example).
+
+The created @a barebox image can be used to boot a standard x86 bzImage
+Linux kernel.
+
+Refer section @ref x86_bootloader_preparations how to do so.
+
+How to get the binary image:
+
+Using the default configuration:
+
+@code
+make ARCH=x86 generic_defconfig
+@endcode
+
+Build the binary image:
+
+@code
+make ARCH=x86 CROSS_COMPILE=x86compiler
+@endcode
+
+@note replace the 'x86compiler' with your x86 (cross) compiler.
+
+*/
diff --git a/commands/Kconfig b/commands/Kconfig
index 28896cb9..bb264fc1 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -219,6 +219,14 @@ config CMD_BOOTU
compile in the 'bootu' command to start raw (uncompressed)
Linux images
+config CMD_LINUX16
+ tristate
+ default y if X86
+ prompt "linux16"
+ help
+ Compile the linux16 command to be able to boot bzImages
+ via real mode.
+
config CMD_RESET
tristate
prompt "reset"
diff --git a/commands/Makefile b/commands/Makefile
index 1c657dd6..b32fa05d 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_LINUX16) += linux16.o
obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o
obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o
obj-$(CONFIG_CMD_LOADS) += loads.o
diff --git a/commands/linux16.c b/commands/linux16.c
new file mode 100644
index 00000000..b15812f1
--- /dev/null
+++ b/commands/linux16.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * In parts from the GRUB2 project:
+ *
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
+ *
+ * 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
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <fs.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/syslib.h>
+
+/** FIXME */
+#define LINUX_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */
+
+/** FIXME */
+#define LINUX_FLAG_BIG_KERNEL 0x1
+
+/** FIXME */
+#define LINUX_BOOT_LOADER_TYPE 0x72
+
+/** FIXME */
+#define LINUX_DEFAULT_SETUP_SECTS 4
+
+/** FIXME */
+#define LINUX_MAX_SETUP_SECTS 64
+
+/** FIXME */
+#define LINUX_OLD_REAL_MODE_SEGMT 0x9000
+
+/** FIXME */
+#define LINUX_OLD_REAL_MODE_ADDR (LINUX_OLD_REAL_MODE_SEGMT << 4)
+
+/** FIXME */
+#define LINUX_HEAP_END_OFFSET (LINUX_OLD_REAL_MODE_SEGMT - 0x200)
+
+/** FIXME */
+#define LINUX_FLAG_CAN_USE_HEAP 0x80
+
+/** Define kernel command lines's start offset in the setup segment */
+#define LINUX_CL_OFFSET 0x9000
+
+/** Define kernel command lines's end offset */
+#define LINUX_CL_END_OFFSET 0x90FF
+
+/** FIXME */
+#define LINUX_CL_MAGIC 0xA33F
+
+/** FIXME */
+#define LINUX_SETUP_MOVE_SIZE 0x9100
+
+/** Sector size */
+#define DISK_SECTOR_BITS 9
+#define DISK_SECTOR_SIZE 0x200
+
+/** Where to load a bzImage */
+#define LINUX_BZIMAGE_ADDR 0x100000
+
+struct linux_kernel_header {
+ /* first sector of the image */
+ uint8_t code1[0x0020];
+ uint16_t cl_magic; /**< Magic number 0xA33F */
+ uint16_t cl_offset; /**< The offset of command line */
+ uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
+ uint8_t setup_sects; /**< The size of the setup in sectors */
+ uint16_t root_flags; /**< If the root is mounted readonly */
+ uint16_t syssize; /**< obsolete */
+ uint16_t swap_dev; /**< obsolete */
+ uint16_t ram_size; /**< obsolete */
+ uint16_t vid_mode; /**< Video mode control */
+ uint16_t root_dev; /**< Default root device number */
+ uint16_t boot_flag; /**< 0xAA55 magic number */
+
+ /* second sector of the image */
+ uint16_t jump; /**< Jump instruction (this is code!) */
+ uint32_t header; /**< Magic signature "HdrS" */
+ uint16_t version; /**< Boot protocol version supported */
+ uint32_t realmode_swtch; /**< Boot loader hook */
+ uint16_t start_sys; /**< The load-low segment (obsolete) */
+ uint16_t kernel_version; /**< Points to kernel version string */
+ uint8_t type_of_loader; /**< Boot loader identifier */
+#define LINUX_LOADER_ID_LILO 0x0
+#define LINUX_LOADER_ID_LOADLIN 0x1
+#define LINUX_LOADER_ID_BOOTSECT 0x2
+#define LINUX_LOADER_ID_SYSLINUX 0x3
+#define LINUX_LOADER_ID_ETHERBOOT 0x4
+#define LINUX_LOADER_ID_ELILO 0x5
+#define LINUX_LOADER_ID_GRUB 0x7
+#define LINUX_LOADER_ID_UBOOT 0x8
+#define LINUX_LOADER_ID_XEN 0x9
+#define LINUX_LOADER_ID_GUJIN 0xa
+#define LINUX_LOADER_ID_QEMU 0xb
+ uint8_t loadflags; /**< Boot protocol option flags */
+ uint16_t setup_move_size; /**< Move to high memory size */
+ uint32_t code32_start; /**< Boot loader hook */
+ uint32_t ramdisk_image; /**< initrd load address */
+ uint32_t ramdisk_size; /**< initrd size */
+ uint32_t bootsect_kludge; /**< obsolete */
+ uint16_t heap_end_ptr; /**< Free memory after setup end */
+ uint8_t ext_loader_ver; /**< boot loader's extension of the version number */
+ uint8_t ext_loader_type; /**< boot loader's extension of its type */
+ char *cmd_line_ptr; /**< Points to the kernel command line */
+ uint32_t initrd_addr_max; /**< Highest address for initrd */
+#if 0
+ /* for the records only. These members are defined in
+ * more recent Linux kernels
+ */
+ uint32_t kernel_alignment; /**< Alignment unit required by the kernel */
+ uint8_t relocatable_kernel; /** */
+ uint8_t min_alignment; /** */
+ uint32_t cmdline_size; /** */
+ uint32_t hardware_subarch; /** */
+ uint64_t hardware_subarch_data; /** */
+ uint32_t payload_offset; /** */
+ uint32_t payload_length; /** */
+ uint64_t setup_data; /** */
+ uint64_t pref_address; /** */
+ uint32_t init_size; /** */
+#endif
+} __attribute__ ((packed));
+
+/**
+ * Load an x86 Linux kernel bzImage and start it
+ * @param cmdtp FIXME
+ * @param argc parameter count
+ * @param argv list of parameter
+ *
+ * Loads an x86 bzImage, checks for its integrity, stores the two parts
+ * (setup = 'real mode code' and kernel = 'protected mode code') to their
+ * default locations, switches back to real mode and runs the setup code.
+ */
+static int do_linux16(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+ struct linux_kernel_header *lh = NULL;
+ int rc;
+ unsigned setup_sects;
+ unsigned real_mode_size;
+ size_t image_size;
+ const char *cmdline = getenv("bootargs");
+
+ if (argc < 2) {
+ perror("linux16");
+ return 1;
+ }
+
+ lh = read_file(argv[1], &image_size);
+ if (lh == NULL) {
+ printf("Cannot read file '%s'\n", argv[1]);
+ return 1;
+ }
+
+ if (lh->boot_flag != 0xaa55) {
+ printf("File '%s' has invalid magic number\n", argv[1]);
+ rc = 1;
+ goto on_error;
+ }
+
+ if (lh->setup_sects > LINUX_MAX_SETUP_SECTS) {
+ printf("File '%s' contains too many setup sectors\n", argv[1]);
+ rc = 1;
+ goto on_error;
+ }
+
+ setup_sects = lh->setup_sects;
+
+ printf("Found a %d.%d image header\n", lh->version >> 8, lh->version & 0xFF);
+
+ if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200) {
+ /* kernel is recent enough */
+ ;
+ if (!(lh->loadflags & LINUX_FLAG_BIG_KERNEL)) {
+ printf("Cannot load a classic zImage. Use a bzImage instead\n");
+ goto on_error;
+ }
+ lh->type_of_loader = LINUX_BOOT_LOADER_TYPE; /* TODO */
+
+ if (lh->version >= 0x0201) {
+ lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
+ lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
+ }
+
+ if (lh->version >= 0x0202)
+ lh->cmd_line_ptr = (void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET); /* FIXME */
+ else {
+ lh->cl_magic = LINUX_CL_MAGIC;
+ lh->cl_offset = LINUX_CL_OFFSET;
+ lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
+ }
+ } else {
+ printf("Kernel too old to handle\n");
+ rc = 1;
+ goto on_error;
+ }
+
+ if (strlen(cmdline) >= (LINUX_CL_END_OFFSET - LINUX_CL_OFFSET)) {
+ printf("Kernel command line exceeds the available space\n");
+ rc = 1;
+ goto on_error;
+ }
+
+ /* If SETUP_SECTS is not set, set it to the default. */
+ if (setup_sects == 0) {
+ printf("Fixing setup sector count\n");
+ setup_sects = LINUX_DEFAULT_SETUP_SECTS;
+ }
+
+ if (setup_sects >= 15) {
+ void *src = lh;
+ if (lh->kernel_version != 0)
+ printf("Kernel version: '%s'\n", src + lh->kernel_version + DISK_SECTOR_SIZE);
+ }
+
+ /*
+ * Size of the real mode part to handle in a separate way
+ */
+ real_mode_size = (setup_sects << DISK_SECTOR_BITS) + DISK_SECTOR_SIZE;
+
+ /*
+ * real mode space hole extended memory
+ * |---------------------------------------------->|----------->|------------------------------>
+ * 0 0xa0000 0x100000
+ * <-1-|----------2-----------><-3- |
+ * 0x7e00 0x90000
+ * <-4--|-5--> |---------6------------->
+ *
+ * 1) real mode stack
+ * 2) barebox code
+ * 3) flat mode stack
+ * 4) realmode stack when starting a Linux kernel
+ * 5) Kernel's real mode setup code
+ * 6) compressed kernel image
+ */
+ /*
+ * Parts of the image we know:
+ * - real mode part
+ * - kernel payload
+ */
+ /*
+ * NOTE: This part is dangerous, as it copies some image content to
+ * various locations in the main memory. This could overwrite important
+ * data of the running barebox (hopefully not)
+ */
+ /* copy the real mode part of the image to the 9th segment */
+ memcpy((void*)LINUX_OLD_REAL_MODE_ADDR, lh, LINUX_SETUP_MOVE_SIZE);
+
+ /* TODO add 'BOOT_IMAGE=<file>' and 'auto' if no user intervention was done (in front of all other params) */
+ /* copy also the command line into this area */
+ memcpy((void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET), cmdline, strlen(cmdline) + 1);
+ printf("Using kernel command line: '%s'\n", cmdline);
+
+ /* copy the compressed image part to its final address the setup code expects it
+ * Note: The protected mode part starts at offset (setup_sects + 1) * 512
+ */
+ memcpy((void*)LINUX_BZIMAGE_ADDR, ((void*)lh) + real_mode_size, image_size - real_mode_size);
+
+ /*
+ * switch back to real mode now and start the real mode part of the
+ * image at address "(LINUX_OLD_REAL_MODE_ADDR >> 4) + 0x20:0x0000"
+ * which means "0x9020:0x000" -> 0x90200
+ */
+ bios_start_linux(LINUX_OLD_REAL_MODE_SEGMT); /* does not return */
+
+on_error:
+ if (lh != NULL)
+ free(lh);
+
+ return rc;
+}
+
+static const __maybe_unused char cmd_linux16_help[] =
+"Usage: linux16 <file>\n"
+"Boot a linux kernel via real mode code\n";
+
+
+BAREBOX_CMD_START(linux16)
+ .cmd = do_linux16,
+ .usage = "boot linux kernel",
+ BAREBOX_CMD_HELP(cmd_linux16_help)
+BAREBOX_CMD_END
+
+/**
+ * @file
+ * @brief Boot support for Linux on x86
+ */
+
+/**
+ * @page linux16_command linux16: Boot a bzImage kernel on x86
+ *
+ * Usage is: linux16 \<file\>
+ *
+ * Boot a linux kernel via real mode code. Only kernel images in the
+ * @p bzImage format are supported.
+ */
+
+/**
+ * @page x86_boot_preparation Linux Preparation on x86
+ *
+ * Due to some real mode constraints, starting Linux is somehow tricky.
+ * Currently only @p bzImages are supported, because @p zImages would
+ * interfere with the @a barebox runtime.
+ * Also older load header versions than 2.00 aren't supported.
+ *
+ * The memory layout immediately before starting the Linux kernel:
+ *
+@verbatim
+ real mode space hole extended memory
+ |---------------------------------------------->|----------->|------------------------------>
+ 0 0x7e00 0x90000 0xa0000 0x100000
+ <-1-|----------2-----------><-3- |
+ <-4--|-5--> |---------6------------->
+@endverbatim
+ *
+ * @li 1 = @a barebox's real mode stack
+ * @li 2 = @a barebox's code
+ * @li 3 = @a barebox's flat mode stack
+ * @li 4 = real mode stack, when starting the Linux kernel
+ * @li 5 = Kernel's real mode setup code
+ * @li 6 = compressed kernel image
+ *
+ * A more detailed memory layout for kernel's real mode setup code
+ *
+@verbatim
+
+ 0x90000 0x97fff 0x99000 0x990ff
+ ---|------------------------------------------|----------------|--------------------|
+ |<-------- max setup code size ----------->|<--heap/stack-->|<-- command line -->|
+
+@endverbatim
+ *
+ * The regular entry point into the setup code is 0x90200 (2nd sector)
+ *
+ * To start the kernel, it's own setup code will be called. To do so, it
+ * must be called in real mode. So, @a barebox switches back to real mode
+ * a last time and does a jump to the setup code entry point. Now its up to
+ * the setup code to deflate the kernel, switching to its own protected mode
+ * setup and starting the kernel itself.
+ *
+ * @note This scenario only works, if a BIOS is still present. In this case
+ * there is no need for @a barebox to forward any system related information
+ * to the kernel. Everything is detected by kernel's setup code.
+ *
+ */
diff --git a/commands/partition.c b/commands/partition.c
index 3cb7b612..bc0bbf96 100755
--- a/commands/partition.c
+++ b/commands/partition.c
@@ -41,8 +41,10 @@
#include <linux/stat.h>
#include <libgen.h>
+#define SIZE_REMAINING ((ulong)-1)
+
static int mtd_part_do_parse_one(char *devname, const char *partstr,
- char **endp, unsigned long offset,
+ char **endp, unsigned long *offset,
off_t devsize, size_t *retsize)
{
ulong size;
@@ -54,12 +56,18 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
memset(buf, 0, PATH_MAX);
if (*partstr == '-') {
- size = devsize - offset;
+ size = SIZE_REMAINING;
end = (char *)partstr + 1;
} else {
size = strtoul_suffix(partstr, &end, 0);
}
+ if (*end == '@')
+ *offset = strtoul_suffix(end+1, &end, 0);
+
+ if (size == SIZE_REMAINING)
+ size = devsize - *offset;
+
partstr = end;
if (*partstr == '(') {
@@ -76,7 +84,7 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
end++;
}
- if (size + offset > devsize) {
+ if (size + *offset > devsize) {
printf("%s: partition end is beyond device\n", buf);
return -EINVAL;
}
@@ -93,7 +101,7 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
*retsize = size;
- ret = devfs_add_partition(devname, offset, size, flags, buf);
+ ret = devfs_add_partition(devname, *offset, size, flags, buf);
if (ret)
printf("cannot create %s: %s\n", buf, strerror(-ret));
return ret;
@@ -123,7 +131,7 @@ static int do_addpart(cmd_tbl_t * cmdtp, int argc, char *argv[])
while (1) {
size_t size = 0;
- if (mtd_part_do_parse_one(devname, endp, &endp, offset, devsize, &size))
+ if (mtd_part_do_parse_one(devname, endp, &endp, &offset, devsize, &size))
return 1;
offset += size;
@@ -146,10 +154,11 @@ static const __maybe_unused char cmd_addpart_help[] =
"\n"
"addpart adds a partition description to a device. The partition description\n"
"has the form\n"
-"size1(name1)[ro],size2(name2)[ro],...\n"
-"<device> is the device name under. Size can be given in decimal or if prefixed\n"
-"with 0x in hex. Sizes can have an optional suffix K,M,G. The size of the last\n"
-"partition can be specified as '-' for the remaining space of the device.\n"
+"size1[@offset1](name1)[ro],size2[@offset2](name2)[ro],...\n"
+"<device> is the device name under. Size and offset can be given in decimal\n"
+"or - if prefixed with 0x in hex. Both can have an optional suffix K,M,G.\n"
+"The size of the last partition can be specified as '-' for the remaining\n"
+"space of the device.\n"
"This format is the same as used in the Linux kernel for cmdline mtd partitions.\n"
"\n"
"Note: That this command has to be reworked and will probably change it's API.";
@@ -167,12 +176,12 @@ BAREBOX_CMD_END
* Adds a partition description to a device. The partition description has the
* form
*
- * size1(name1)[ro],size2(name2)[ro],...
+ * size1[@offset1](name1)[ro],size2[@offset2](name2)[ro],...
*
- * \<device> is the device name under. Sizes can be given in decimal or - if
- * prefixed with 0x - in hex. Sizes can have an optional suffix K,M,G. The
- * size of the last partition can be specified as '-' for the remaining space
- * of the device.
+ * \<device> is the device name under. Size and offset can be given in decimal
+ * or - if prefixed with 0x - in hex. Both can have an optional suffix K,M,G.
+ * The size of the last partition can be specified as '-' for the remaining
+ * space of the device.
*
* @note The format is the same as used in the Linux kernel for cmdline mtd
* partitions.
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8bab7ac0..bf559c40 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,7 @@ source "drivers/spi/Kconfig"
source "drivers/i2c/Kconfig"
source "drivers/nor/Kconfig"
source "drivers/nand/Kconfig"
+source "drivers/ata/Kconfig"
source "drivers/usb/Kconfig"
source "drivers/video/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5dc7756a..7bae6ffc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -3,6 +3,7 @@ obj-y += serial/
obj-y += nand/
obj-y += nor/
obj-y += usb/
+obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_VIDEO) += video/
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
new file mode 100644
index 00000000..b43c975d
--- /dev/null
+++ b/drivers/ata/Kconfig
@@ -0,0 +1,26 @@
+menuconfig ATA
+ bool "ATA "
+ help
+ Add support for ATA types of drives like harddisks and CDROMs.
+
+if ATA
+
+comment "drive types"
+
+config ATA_DISK
+ bool "disk drives"
+ help
+ Add support for regular disk drives
+
+comment "interface types"
+
+config ATA_BIOS
+ bool "BIOS based"
+ depends on X86_BIOS_BRINGUP
+ help
+ Gain disk drive access via int13 calls to the standard PC-BIOS.
+ The advantage of this driver is, it still uses user's defined boot
+ media to work on. Disadvantage is: Due to its 16 bit nature it is
+ slow.
+
+endif
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
new file mode 100644
index 00000000..30d15ccb
--- /dev/null
+++ b/drivers/ata/Makefile
@@ -0,0 +1,7 @@
+# drive types
+
+obj-$(CONFIG_ATA_DISK) += disk_drive.o
+
+# interface types
+
+obj-$(CONFIG_ATA_BIOS) += bios.o
diff --git a/drivers/ata/bios.c b/drivers/ata/bios.c
new file mode 100644
index 00000000..51e2425a
--- /dev/null
+++ b/drivers/ata/bios.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Media communication layer through the standard 16 bit PC-BIOS
+ *
+ * This communication driver does all accesses to the boot medium via 16 bit
+ * real mode calls into the standard BIOS. Due to this method, its possible
+ * to use all the medias to boot from that are supported by the BIOS. This
+ * also includes emulated only medias.
+ *
+ * To be able to call the real mode BIOS, this driver must switch back to
+ * real mode for each access. This will slow down the access a little bit, but
+ * we are a boot loader here, not an operating system...
+ *
+ * Note: We need scratch memory for the BIOS communication, because the BIOS
+ * can only handle memory below 0xA0000. So we must copy all data between
+ * the flat mode buffers and realmode buffers.
+ *
+ * Note: This driver makes no sense on other architectures than x86.
+ *
+ * Note: This driver does only support LBA addressing. Currently no CHS!
+ */
+
+#include <stdio.h>
+#include <linux/types.h>
+#include <init.h>
+#include <driver.h>
+#include <string.h>
+#include <xfuncs.h>
+#include <asm/syslib.h>
+#include <ata.h>
+#include <errno.h>
+
+/**
+ * Sector count handled in one count
+ *
+ * @todo 127 are always possible, some BIOS manufacturer supports up to 255.
+ * Is it's worth to detect Phoenic's restriction?
+ */
+#define SECTORS_AT_ONCE 64
+
+/** Size of one sector in bytes */
+#define SECTOR_SIZE 512
+
+/** Command to read sectors from media */
+#define BIOS_READ_CMD 0
+
+/** Command to write sectors to media */
+#define BIOS_WRT_CMD 1
+
+/**
+ * "Disk Address Packet Structure" to be used when calling
+ * BIOS's int13, function 0x42/0x43
+ */
+struct DAPS
+{
+ uint8_t size; /**< always '16' */
+ uint8_t res1; /**< always '0' */
+ int8_t count; /**< number of sectors 0...127 */
+ uint8_t res2; /**< always '0' */
+ uint16_t offset; /**< buffer address: offset */
+ uint16_t segment; /**< buffer address: segment */
+ uint64_t lba; /**< LBA of the start sector */
+} __attribute__ ((packed));
+
+/**
+ * Collection of data we need to know about the connected drive
+ */
+struct media_access {
+ int drive_no; /**< drive number used by the BIOS */
+ int is_cdrom; /**< drive is a CDROM e.g. no write support */
+};
+
+/**
+ * Scratch memory for BIOS communication to handle data in chunks of 32 kiB
+ *
+ * Note: This variable is located in the .bss segment, assuming it is located
+ * below 0xA0000. If not, the BIOS is not able to read or store any data
+ * from/to it. The variable must also aligned to a 16 byte boundary to easify
+ * linear to segment:offset address conversion.
+ */
+static uint8_t scratch_buffer[SECTORS_AT_ONCE * SECTOR_SIZE] __attribute__((aligned(16)));
+
+/**
+ * Communication buffer for the 16 bit int13 BIOS call
+ *
+ * Note: This variable is located in the .bss segment, assuming it is located
+ * below 0xA0000. If not, the BIOS is not able to read or store any data
+ * from/to it. The variable must also aligned to a 16 byte boundary to easify
+ * linear to segment:offset conversion.
+ */
+static struct DAPS bios_daps __attribute__((aligned(16)));
+
+/**
+ * @param media our data we need to do the access
+ * @param cmd Command to forward to the BIOS
+ * @param sector_start LBA of the start sector
+ * @param sector_count Sector count
+ * @param buffer Buffer to read from or write to (in the low memory area)
+ * @return 0 on success, anything else on failure
+ */
+static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sector_start, unsigned sector_count, void *buffer)
+{
+ int rc;
+
+ /* prepare the DAPS for the int13 call */
+ bios_daps.size = sizeof(struct DAPS);
+ bios_daps.res1 = 0;
+ bios_daps.count = sector_count; /* always less than 128! */
+ bios_daps.res2 = 0;
+ bios_daps.segment = (unsigned long)buffer >> 4;
+ bios_daps.offset = (unsigned long)buffer - (unsigned long)(bios_daps.segment << 4);
+ bios_daps.lba = sector_start;
+
+ if (cmd == BIOS_READ_CMD)
+ rc = bios_disk_rw_int13_extensions(0x42, media->drive_no, &bios_daps);
+ else if (cmd == BIOS_WRT_CMD)
+ rc = bios_disk_rw_int13_extensions(0x43, media->drive_no, &bios_daps);
+ else
+ return -1;
+
+ return rc;
+}
+
+/**
+ * Read a chunk of sectors from media
+ * @param dev our data we need to do the access
+ * @param sector_start Sector's LBA number to start read from
+ * @param sector_count Sectors to read
+ * @param buffer Buffer to read into
+ * @return 0 on success, anything else on failure
+ *
+ * This routine expects the buffer has the correct size to store all data!
+ */
+static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer)
+{
+ int rc;
+ struct ata_interface *intf = dev->platform_data;
+ struct media_access *media = intf->priv;
+
+ while (sector_count >= SECTORS_AT_ONCE) {
+ rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer);
+ if (rc != 0)
+ return rc;
+ __builtin_memcpy(buffer, scratch_buffer, sizeof(scratch_buffer));
+ buffer += sizeof(scratch_buffer);
+ sector_start += SECTORS_AT_ONCE;
+ sector_count -= SECTORS_AT_ONCE;
+ };
+
+ /* Are sectors still remaining? */
+ if (sector_count) {
+ rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, sector_count, scratch_buffer);
+ __builtin_memcpy(buffer, scratch_buffer, sector_count * SECTOR_SIZE);
+ } else
+ rc = 0;
+
+ return rc;
+}
+
+/**
+ * Write a chunk of sectors to media
+ * @param dev our data we need to do the access
+ * @param sector_start Sector's LBA number to start write to
+ * @param sector_count Sectors to write
+ * @param buffer Buffer to write from
+ * @return 0 on success, anything else on failure
+ *
+ * This routine expects the buffer has the correct size to read all data!
+ */
+static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer)
+{
+ int rc;
+ struct ata_interface *intf = dev->platform_data;
+ struct media_access *media = intf->priv;
+
+ while (sector_count >= SECTORS_AT_ONCE) {
+ __builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer));
+ rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer);
+ if (rc != 0)
+ return rc;
+ buffer += sizeof(scratch_buffer);
+ sector_start += SECTORS_AT_ONCE;
+ sector_count -= SECTORS_AT_ONCE;
+ };
+
+ /* Are sectors still remaining? */
+ if (sector_count) {
+ __builtin_memcpy(scratch_buffer, buffer, sector_count * SECTOR_SIZE);
+ rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, sector_count, scratch_buffer);
+ } else
+ rc = 0;
+
+ return rc;
+}
+
+/**
+ * Probe for connected drives and register them
+ *
+ * Detecting if a drive is present is done by simply reading its MBR.
+ *
+ * FIXME: Relation between BIOS disk numbering scheme and our representation
+ * here in barebox (and later on in the linux kernel)
+ */
+static int biosdisk_probe(struct device_d *dev)
+{
+ int drive, rc;
+ struct media_access media, *m;
+ struct device_d *drive_dev;
+ struct ata_interface *p;
+
+ for (drive = 0x80; drive < 0x90; drive++) {
+ media.drive_no = drive;
+ media.is_cdrom = 0; /* don't know yet */
+ rc = biosdisk_bios_call(&media, BIOS_READ_CMD, 0, 1, scratch_buffer);
+ if (rc != 0)
+ continue;
+
+ printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no);
+
+ drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface));
+ if (drive_dev == NULL) {
+ dev_err(dev, "Out of memory\n");
+ return -1;
+ }
+ m = (struct media_access*)&drive_dev[1];
+ p = (struct ata_interface*)&m[1];
+
+ m->drive_no = drive;
+ m->is_cdrom = 0;
+
+ p->write = biosdisk_write;
+ p->read = biosdisk_read;
+ p->priv = m;
+
+ strcpy(drive_dev->name, "biosdisk");
+ drive_dev->id = drive - 0x80;
+ drive_dev->size = 1;
+ drive_dev->map_base = 0;
+ drive_dev->platform_data = p;
+
+ register_device(drive_dev);
+ }
+
+ return 0;
+}
+
+static struct driver_d biosdisk_driver = {
+ .name = "biosdrive",
+ .probe = biosdisk_probe,
+};
+
+static int biosdisk_init(void)
+{
+ /* sanity */
+ if (scratch_buffer > (uint8_t*)0x9FFFF) {
+ printf("BIOS driver: Scratch memory not in real mode area. Cannot continue!\n");
+ return -EIO;
+ }
+ if (&bios_daps > (struct DAPS*)0x9FFFF) {
+ printf("BIOS driver: DAPS memory not in real mode area. Cannot continue!\n");
+ return -EIO;
+ }
+
+ register_driver(&biosdisk_driver);
+ return 0;
+}
+
+device_initcall(biosdisk_init);
diff --git a/drivers/ata/disk_drive.c b/drivers/ata/disk_drive.c
new file mode 100644
index 00000000..250dadaa
--- /dev/null
+++ b/drivers/ata/disk_drive.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Generic disk drive support
+ *
+ * @todo Support for disks larger than 4 GiB
+ */
+
+#include <stdio.h>
+#include <init.h>
+#include <driver.h>
+#include <types.h>
+#include <ata.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <string.h>
+#include <linux/kernel.h>
+
+/**
+ * Description of one partition table entry (D*S type)
+ */
+struct partition_entry {
+ uint8_t boot_indicator;
+ uint8_t chs_begin[3];
+ uint8_t type;
+ uint8_t chs_end[3];
+ uint32_t partition_start;
+ uint32_t partition_size;
+} __attribute__ ((packed));
+
+/** one for all */
+#define SECTOR_SIZE 512
+
+/**
+ * Guess the size of the disk, based on the partition table entries
+ * @param dev device to create partitions for
+ * @param table partition table
+ * @return size in sectors
+ */
+static unsigned long disk_guess_size(struct device_d *dev, struct partition_entry *table)
+{
+ int part_order[4] = {0, 1, 2, 3};
+ unsigned long size = 0;
+ int i;
+
+ /* TODO order the partitions */
+
+ for (i = 0; i < 4; i++) {
+ if (table[part_order[i]].partition_start != 0) {
+ size += table[part_order[i]].partition_start - size; /* the gap */
+ size += table[part_order[i]].partition_size;
+ }
+ }
+#if 1
+/* limit disk sizes we can't handle due to 32 bit limits */
+ if (size > 0x7fffff) {
+ dev_warn(dev, "Warning: Size limited due to 32 bit contraints\n");
+ size = 0x7fffff;
+ }
+#endif
+ return size;
+}
+
+/**
+ * Register partitions found on the drive
+ * @param dev device to create partitions for
+ * @param table partition table
+ * @return 0 on success
+ */
+static int disk_register_partitions(struct device_d *dev, struct partition_entry *table)
+{
+ int part_order[4] = {0, 1, 2, 3};
+ int i, rc;
+ char drive_name[16], partition_name[19];
+
+ /* TODO order the partitions */
+
+ for (i = 0; i < 4; i++) {
+ sprintf(drive_name, "%s%d", dev->name, dev->id);
+ sprintf(partition_name, "%s%d.%d", dev->name, dev->id, i);
+ if (table[part_order[i]].partition_start != 0) {
+#if 1
+/* ignore partitions we can't handle due to 32 bit limits */
+ if (table[part_order[i]].partition_start > 0x7fffff)
+ continue;
+ if (table[part_order[i]].partition_size > 0x7fffff)
+ continue;
+#endif
+ dev_info(dev, "Registering partition %s to drive %s\n", partition_name, drive_name);
+ rc = devfs_add_partition(drive_name,
+ table[part_order[i]].partition_start * SECTOR_SIZE,
+ table[part_order[i]].partition_size * SECTOR_SIZE,
+ DEVFS_PARTITION_FIXED, partition_name);
+ if (rc != 0)
+ dev_err(dev, "Failed to register partition %s (%d)\n", partition_name, rc);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Write some data to a disk
+ * @param cdev the device to write to
+ * @param _buf source of data
+ * @param count byte count to write
+ * @param offset where to write to disk
+ * @param flags Ignored
+ * @return Written bytes or negative value in case of failure
+ */
+static ssize_t disk_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct device_d *dev = cdev->dev;
+ struct ata_interface *intf = dev->platform_data;
+ int rc;
+ unsigned sep_count = offset & (SECTOR_SIZE - 1);
+ ssize_t written = 0;
+
+ /* starting at no sector boundary? */
+ if (sep_count != 0) {
+ uint8_t tmp_buf[SECTOR_SIZE];
+ unsigned to_write = min(SECTOR_SIZE - sep_count, count);
+
+ rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read data\n");
+ return -1;
+ }
+ memcpy(&tmp_buf[sep_count], _buf, to_write);
+ rc = intf->write(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot write data\n");
+ return -1;
+ }
+
+ _buf += to_write;
+ offset += to_write;
+ count -= to_write;
+ written += to_write;
+ }
+
+ /* full sector part */
+ sep_count = count / SECTOR_SIZE;
+ if (sep_count) {
+ rc = intf->write(dev, offset / SECTOR_SIZE, sep_count, _buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot write data\n");
+ return -1;
+ }
+ _buf += sep_count * SECTOR_SIZE;
+ offset += sep_count * SECTOR_SIZE;
+ count -= sep_count * SECTOR_SIZE;
+ written += sep_count * SECTOR_SIZE;
+ }
+
+ /* ending at no sector boundary? */
+ if (count) {
+ uint8_t tmp_buf[SECTOR_SIZE];
+
+ rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read data\n");
+ return -1;
+ }
+ memcpy(tmp_buf, _buf, count);
+ rc = intf->write(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot write data\n");
+ return -1;
+ }
+ written += count;
+ }
+
+ return written;
+}
+
+/**
+ * Read some data from a disk
+ * @param cdev the device to read from
+ * @param _buf destination of the data
+ * @param count byte count to read
+ * @param offset where to read from
+ * @param flags Ignored
+ * @return Read bytes or negative value in case of failure
+ */
+static ssize_t disk_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct device_d *dev = cdev->dev;
+ struct ata_interface *intf = dev->platform_data;
+ int rc;
+ unsigned sep_count = offset & (SECTOR_SIZE - 1);
+ ssize_t read = 0;
+
+ /* starting at no sector boundary? */
+ if (sep_count != 0) {
+ uint8_t tmp_buf[SECTOR_SIZE];
+ unsigned to_read = min(SECTOR_SIZE - sep_count, count);
+
+ rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read data\n");
+ return -1;
+ }
+ memcpy(_buf, &tmp_buf[sep_count], to_read);
+ _buf += to_read;
+ offset += to_read;
+ count -= to_read;
+ read += to_read;
+ }
+
+ /* full sector part */
+ sep_count = count / SECTOR_SIZE;
+ if (sep_count) {
+ rc = intf->read(dev, offset / SECTOR_SIZE, sep_count, _buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read data\n");
+ return -1;
+ }
+ _buf += sep_count * SECTOR_SIZE;
+ offset += sep_count * SECTOR_SIZE;
+ count -= sep_count * SECTOR_SIZE;
+ read += sep_count * SECTOR_SIZE;
+ }
+
+ /* ending at no sector boundary? */
+ if (count) {
+ uint8_t tmp_buf[SECTOR_SIZE];
+
+ rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read data\n");
+ return -1;
+ }
+ memcpy(_buf, tmp_buf, count);
+ read += count;
+ }
+
+ return read;
+}
+
+static struct file_operations disk_ops = {
+ .read = disk_read,
+ .write = disk_write,
+ .lseek = dev_lseek_default,
+};
+
+/**
+ * Probe the connected disk drive
+ */
+static int disk_probe(struct device_d *dev)
+{
+ uint8_t sector[512];
+ int rc;
+ struct ata_interface *intf = dev->platform_data;
+ struct cdev *disk_cdev;
+
+ rc = intf->read(dev, 0, 1, sector);
+ if (rc != 0) {
+ dev_err(dev, "Cannot read MBR of this device\n");
+ return -1;
+ }
+
+ /* It seems a valuable disk. Register it */
+ disk_cdev = xzalloc(sizeof(struct cdev));
+ if (disk_cdev == NULL) {
+ dev_err(dev, "Out of memory\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * BIOS based disks needs special handling. Not the driver can
+ * enumerate the hardware, the BIOS did it already. To show the user
+ * the drive ordering must not correspond to the Linux drive order,
+ * use the 'biosdisk' name instead.
+ */
+#ifdef CONFIG_ATA_BIOS
+ if (strcmp(dev->driver->name, "biosdisk") == 0)
+ disk_cdev->name = asprintf("biosdisk%d", dev->id);
+ else
+#endif
+ disk_cdev->name = asprintf("disk%d", dev->id);
+ /**
+ * @todo we need the size of the drive, else its nearly impossible
+ * to do anything with it (at least with the generic routines)
+ */
+ disk_cdev->size = 32; /* FIXME */
+ disk_cdev->ops = &disk_ops;
+ disk_cdev->dev = dev;
+ devfs_create(disk_cdev);
+
+ if ((sector[510] != 0x55) || (sector[511] != 0xAA)) {
+ dev_info(dev, "No partition table found\n");
+ return 0;
+ }
+
+ /* guess the size of this drive */
+ dev->size = disk_guess_size(dev, (struct partition_entry*)&sector[446]) * SECTOR_SIZE;
+ dev_info(dev, "Drive size guessed to %u kiB\n", dev->size / 1024);
+ disk_cdev->size = dev->size;
+
+ disk_register_partitions(dev, (struct partition_entry*)&sector[446]);
+
+ return 0;
+}
+
+#ifdef CONFIG_ATA_BIOS
+static struct driver_d biosdisk_driver = {
+ .name = "biosdisk",
+ .probe = disk_probe,
+};
+#endif
+
+static struct driver_d disk_driver = {
+ .name = "disk",
+ .probe = disk_probe,
+};
+
+static int disk_init(void)
+{
+#ifdef CONFIG_ATA_BIOS
+ register_driver(&biosdisk_driver);
+#endif
+ register_driver(&disk_driver);
+ return 0;
+}
+
+device_initcall(disk_init);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 46723ed8..f1b2949f 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -13,4 +13,7 @@ config DRIVER_I2C_MC13892
config DRIVER_I2C_MC9SDZ60
bool "MC9SDZ60 driver"
+config DRIVER_I2C_LP3972
+ bool "LP3972 driver"
+
endif
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 5dd642fd..62d030bf 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DRIVER_I2C_IMX) += i2c-imx.o
obj-$(CONFIG_DRIVER_I2C_MC13892) += mc13892.o
obj-$(CONFIG_DRIVER_I2C_MC9SDZ60) += mc9sdz60.o
+obj-$(CONFIG_DRIVER_I2C_LP3972) += lp3972.o
diff --git a/drivers/i2c/lp3972.c b/drivers/i2c/lp3972.c
new file mode 100644
index 00000000..98266990
--- /dev/null
+++ b/drivers/i2c/lp3972.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * 2009 Marc Kleine-Budde <mkl@pengutronix.de>
+ * 2009 Eric Benard <eric@eukrea.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.
+ *
+ * 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
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+
+#include <i2c/i2c.h>
+
+#include <asm/byteorder.h>
+
+#define DRIVERNAME "lp3972"
+
+struct lp_priv {
+ struct cdev cdev;
+ struct i2c_client *client;
+};
+
+#define to_lp_priv(a) container_of(a, struct lp_priv, cdev)
+
+static struct lp_priv *lp_dev;
+
+struct i2c_client *lp3972_get_client(void)
+{
+ if (!lp_dev)
+ return NULL;
+
+ return lp_dev->client;
+}
+
+static u32 lp_read_reg(struct lp_priv *lp, int reg)
+{
+ u8 buf;
+
+ i2c_read_reg(lp->client, reg, &buf, sizeof(buf));
+
+ return buf;
+}
+
+static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct lp_priv *priv = to_lp_priv(cdev);
+ int i = count;
+ u8 *buf = _buf;
+
+ while (i) {
+ *buf = lp_read_reg(priv, offset);
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static struct file_operations lp_fops = {
+ .lseek = dev_lseek_default,
+ .read = lp_read,
+};
+
+static int lp_probe(struct device_d *dev)
+{
+ if (lp_dev)
+ return -EBUSY;
+
+ lp_dev = xzalloc(sizeof(struct lp_priv));
+ lp_dev->cdev.name = DRIVERNAME;
+ lp_dev->client = to_i2c_client(dev);
+ lp_dev->cdev.size = 256;
+ lp_dev->cdev.dev = dev;
+ lp_dev->cdev.ops = &lp_fops;
+
+ devfs_create(&lp_dev->cdev);
+
+ return 0;
+}
+
+static struct driver_d lp_driver = {
+ .name = DRIVERNAME,
+ .probe = lp_probe,
+};
+
+static int lp_init(void)
+{
+ register_driver(&lp_driver);
+ return 0;
+}
+
+device_initcall(lp_init);
diff --git a/drivers/i2c/mc13892.c b/drivers/i2c/mc13892.c
index 54661d4f..67d4232a 100644
--- a/drivers/i2c/mc13892.c
+++ b/drivers/i2c/mc13892.c
@@ -26,47 +26,99 @@
#include <errno.h>
#include <i2c/i2c.h>
-
-#include <asm/byteorder.h>
+#include <i2c/mc13892.h>
#define DRIVERNAME "mc13892"
-struct mc_priv {
- struct cdev cdev;
- struct i2c_client *client;
-};
-
-#define to_mc_priv(a) container_of(a, struct mc_priv, cdev)
+#define to_mc13892(a) container_of(a, struct mc13892, cdev)
-static struct mc_priv *mc_dev;
+static struct mc13892 *mc_dev;
-struct i2c_client *mc13892_get_client(void)
+struct mc13892 *mc13892_get(void)
{
if (!mc_dev)
return NULL;
- return mc_dev->client;
+ return mc_dev;
+}
+EXPORT_SYMBOL(mc13892_get);
+
+int mc13892_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val)
+{
+ u8 buf[3];
+ int ret;
+
+ ret = i2c_read_reg(mc13892->client, reg, buf, 3);
+ *val = buf[0] << 16 | buf[1] << 8 | buf[2] << 0;
+
+ return ret == 3 ? 0 : ret;
}
+EXPORT_SYMBOL(mc13892_reg_read)
-static u32 mc_read_reg(struct mc_priv *mc, int reg)
+int mc13892_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val)
{
- u32 buf;
+ u8 buf[] = {
+ val >> 16,
+ val >> 8,
+ val >> 0,
+ };
+ int ret;
+
+ ret = i2c_write_reg(mc13892->client, reg, buf, 3);
+
+ return ret == 3 ? 0 : ret;
+}
+EXPORT_SYMBOL(mc13892_reg_write)
+
+int mc13892_set_bits(struct mc13892 *mc13892, enum mc13892_reg reg, u32 mask, u32 val)
+{
+ u32 tmp;
+ int err;
+
+ err = mc13892_reg_read(mc13892, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
- i2c_read_reg(mc->client, reg, (u8 *)&buf, sizeof(buf));
+ if (!err)
+ err = mc13892_reg_write(mc13892, reg, tmp);
- return buf;
+ return err;
}
+EXPORT_SYMBOL(mc13892_set_bits);
static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
{
- struct mc_priv *priv = to_mc_priv(cdev);
- int i = count >> 2;
+ struct mc13892 *priv = to_mc13892(cdev);
u32 *buf = _buf;
+ size_t i = count >> 2;
+ int err;
+
+ offset >>= 2;
+
+ while (i) {
+ err = mc13892_reg_read(priv, offset, buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct mc13892 *mc13892 = to_mc13892(cdev);
+ const u32 *buf = _buf;
+ size_t i = count >> 2;
+ int err;
offset >>= 2;
while (i) {
- *buf = mc_read_reg(priv, offset);
+ err = mc13892_reg_write(mc13892, offset, *buf);
+ if (err)
+ return (ssize_t)err;
buf++;
i--;
offset++;
@@ -78,6 +130,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset
static struct file_operations mc_fops = {
.lseek = dev_lseek_default,
.read = mc_read,
+ .write = mc_write,
};
static int mc_probe(struct device_d *dev)
@@ -85,7 +138,7 @@ static int mc_probe(struct device_d *dev)
if (mc_dev)
return -EBUSY;
- mc_dev = xzalloc(sizeof(struct mc_priv));
+ mc_dev = xzalloc(sizeof(struct mc13892));
mc_dev->cdev.name = DRIVERNAME;
mc_dev->client = to_i2c_client(dev);
mc_dev->cdev.size = 256;
diff --git a/drivers/i2c/mc9sdz60.c b/drivers/i2c/mc9sdz60.c
index 4b1068d1..3580af88 100644
--- a/drivers/i2c/mc9sdz60.c
+++ b/drivers/i2c/mc9sdz60.c
@@ -26,45 +26,88 @@
#include <errno.h>
#include <i2c/i2c.h>
-
-#include <asm/byteorder.h>
+#include <i2c/mc9sdz60.h>
#define DRIVERNAME "mc9sdz60"
-struct mc_priv {
- struct cdev cdev;
- struct i2c_client *client;
-};
-
-#define to_mc_priv(a) container_of(a, struct mc_priv, cdev)
+#define to_mc9sdz60(a) container_of(a, struct mc9sdz60, cdev)
-static struct mc_priv *mc_dev;
+static struct mc9sdz60 *mc_dev;
-struct i2c_client *mc9sdz60_get_client(void)
+struct mc9sdz60 *mc9sdz60_get(void)
{
if (!mc_dev)
return NULL;
- return mc_dev->client;
+ return mc_dev;
}
+EXPORT_SYMBOL(mc9sdz60_get);
-static u32 mc_read_reg(struct mc_priv *mc, int reg)
+int mc9sdz60_reg_read(struct mc9sdz60 *mc9sdz60, enum mc9sdz60_reg reg, u8 *val)
{
- u8 buf;
+ int ret;
- i2c_read_reg(mc->client, reg, &buf, sizeof(buf));
+ ret = i2c_read_reg(mc9sdz60->client, reg, val, 1);
- return buf;
+ return ret == 1 ? 0 : ret;
}
+EXPORT_SYMBOL(mc9sdz60_reg_read)
+
+int mc9sdz60_reg_write(struct mc9sdz60 *mc9sdz60, enum mc9sdz60_reg reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_write_reg(mc9sdz60->client, reg, &val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+EXPORT_SYMBOL(mc9sdz60_reg_write)
+
+int mc9sdz60_set_bits(struct mc9sdz60 *mc9sdz60, enum mc9sdz60_reg reg, u8 mask, u8 val)
+{
+ u8 tmp;
+ int err;
+
+ err = mc9sdz60_reg_read(mc9sdz60, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+
+ if (!err)
+ err = mc9sdz60_reg_write(mc9sdz60, reg, tmp);
+
+ return err;
+}
+EXPORT_SYMBOL(mc9sdz60_set_bits);
static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
{
- struct mc_priv *priv = to_mc_priv(cdev);
- int i = count;
+ struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev);
u8 *buf = _buf;
+ size_t i = count;
+ int err;
+
+ while (i) {
+ err = mc9sdz60_reg_read(mc9sdz60, offset, buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev);
+ const u8 *buf = _buf;
+ size_t i = count;
+ int err;
while (i) {
- *buf = mc_read_reg(priv, offset);
+ err = mc9sdz60_reg_write(mc9sdz60, offset, *buf);
+ if (err)
+ return (ssize_t)err;
buf++;
i--;
offset++;
@@ -76,6 +119,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset
static struct file_operations mc_fops = {
.lseek = dev_lseek_default,
.read = mc_read,
+ .write = mc_write,
};
static int mc_probe(struct device_d *dev)
@@ -83,10 +127,10 @@ static int mc_probe(struct device_d *dev)
if (mc_dev)
return -EBUSY;
- mc_dev = xzalloc(sizeof(struct mc_priv));
+ mc_dev = xzalloc(sizeof(struct mc9sdz60));
mc_dev->cdev.name = DRIVERNAME;
mc_dev->client = to_i2c_client(dev);
- mc_dev->cdev.size = 256;
+ mc_dev->cdev.size = 64; /* 35 known registers */
mc_dev->cdev.dev = dev;
mc_dev->cdev.ops = &mc_fops;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ed7656ee..09555622 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -64,6 +64,11 @@ config DRIVER_NET_FEC_IMX
depends on ARCH_HAS_FEC_IMX
select MIIPHY
+config DRIVER_NET_EP93XX
+ bool "EP93xx Ethernet driver"
+ depends on ARCH_EP93XX
+ select MIIPHY
+
config DRIVER_NET_MACB
bool "macb Ethernet driver"
depends on ARCH_AT91
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 67519204..1b6f1046 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
obj-$(CONFIG_DRIVER_NET_AT91_ETHER) += at91_ether.o
obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
obj-$(CONFIG_DRIVER_NET_FEC_IMX) += fec_imx.o
+obj-$(CONFIG_DRIVER_NET_EP93XX) += ep93xx.o
obj-$(CONFIG_DRIVER_NET_MACB) += macb.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
obj-$(CONFIG_MIIPHY) += miiphy.o
diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c
new file mode 100644
index 00000000..aa1a0053
--- /dev/null
+++ b/drivers/net/ep93xx.c
@@ -0,0 +1,676 @@
+/*
+ * Cirrus Logic EP93xx ethernet MAC / MII driver.
+ *
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2004, 2005
+ * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+ *
+ * Based on the original eth.[ch] Cirrus Logic EP93xx Rev D. Ethernet Driver,
+ * which is
+ *
+ * (C) Copyright 2002 2003
+ * Adam Bezanson, Network Audio Technologies, Inc.
+ * <bezanson@netaudiotech.com>
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <init.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <mach/ep93xx-regs.h>
+#include "ep93xx.h"
+
+static int ep93xx_eth_send_packet(struct eth_device *edev,
+ void *packet, int length);
+static int ep93xx_eth_rcv_packet(struct eth_device *edev);
+
+static int ep93xx_phy_read(struct miiphy_device *mdev, uint8_t phy_addr,
+ uint8_t phy_reg, uint16_t *value);
+static int ep93xx_phy_write(struct miiphy_device *mdev, uint8_t phy_addr,
+ uint8_t phy_reg, uint16_t value);
+
+static inline struct ep93xx_eth_priv *ep93xx_get_priv(struct eth_device *edev)
+{
+ return (struct ep93xx_eth_priv *)edev->priv;
+}
+
+static inline struct mac_regs *ep93xx_get_regs(struct eth_device *edev)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+
+ return priv->regs;
+}
+
+#if defined(EP93XX_MAC_DEBUG)
+/**
+ * Dump ep93xx_mac values to the terminal.
+ */
+inline void dump_dev(struct eth_device *edev)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ int i;
+
+ printf("\ndump_dev()\n");
+ printf(" rx_dq.base %08X\n", priv->rx_dq.base);
+ printf(" rx_dq.current %08X\n", priv->rx_dq.current);
+ printf(" rx_dq.end %08X\n", priv->rx_dq.end);
+ printf(" rx_sq.base %08X\n", priv->rx_sq.base);
+ printf(" rx_sq.current %08X\n", priv->rx_sq.current);
+ printf(" rx_sq.end %08X\n", priv->rx_sq.end);
+
+ for (i = 0; i < NUMRXDESC; i++)
+ printf(" rx_buffer[%2.d] %08X\n", i, NetRxPackets[i]);
+
+ printf(" tx_dq.base %08X\n", priv->tx_dq.base);
+ printf(" tx_dq.current %08X\n", priv->tx_dq.current);
+ printf(" tx_dq.end %08X\n", priv->tx_dq.end);
+ printf(" tx_sq.base %08X\n", priv->tx_sq.base);
+ printf(" tx_sq.current %08X\n", priv->tx_sq.current);
+ printf(" tx_sq.end %08X\n", priv->tx_sq.end);
+}
+
+/**
+ * Dump all RX descriptor queue entries to the terminal.
+ */
+inline void dump_rx_descriptor_queue(struct eth_device *edev)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ int i;
+
+ printf("\ndump_rx_descriptor_queue()\n");
+ printf(" descriptor address word1 word2\n");
+ for (i = 0; i < NUMRXDESC; i++) {
+ printf(" [ %08X ] %08X %08X\n",
+ (priv->rx_dq.base + i),
+ (priv->rx_dq.base + i)->word1,
+ (priv->rx_dq.base + i)->word2);
+ }
+}
+
+/**
+ * Dump all RX status queue entries to the terminal.
+ */
+inline void dump_rx_status_queue(void)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ int i;
+
+ printf("\ndump_rx_status_queue()\n");
+ printf(" descriptor address word1 word2\n");
+ for (i = 0; i < NUMRXDESC; i++) {
+ printf(" [ %08X ] %08X %08X\n",
+ (priv->rx_sq.base + i),
+ (priv->rx_sq.base + i)->word1,
+ (priv->rx_sq.base + i)->word2);
+ }
+}
+
+/**
+ * Dump all TX descriptor queue entries to the terminal.
+ */
+inline void dump_tx_descriptor_queue(void)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ int i;
+
+ printf("\ndump_tx_descriptor_queue()\n");
+ printf(" descriptor address word1 word2\n");
+ for (i = 0; i < NUMTXDESC; i++) {
+ printf(" [ %08X ] %08X %08X\n",
+ (priv->tx_dq.base + i),
+ (priv->tx_dq.base + i)->word1,
+ (priv->tx_dq.base + i)->word2);
+ }
+}
+
+/**
+ * Dump all TX status queue entries to the terminal.
+ */
+inline void dump_tx_status_queue(void)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ int i;
+
+ printf("\ndump_tx_status_queue()\n");
+ printf(" descriptor address word1\n");
+ for (i = 0; i < NUMTXDESC; i++) {
+ printf(" [ %08X ] %08X\n",
+ (priv->rx_sq.base + i),
+ (priv->rx_sq.base + i)->word1);
+ }
+}
+#else
+#define dump_dev(x)
+#define dump_rx_descriptor_queue()
+#define dump_rx_status_queue()
+#define dump_tx_descriptor_queue()
+#define dump_tx_status_queue()
+#endif /* defined(EP93XX_MAC_DEBUG) */
+
+/**
+ * Reset the EP93xx MAC by twiddling the soft reset bit and spinning until
+ * it's cleared.
+ */
+static void ep93xx_eth_reset(struct eth_device *edev)
+{
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+ uint32_t value;
+
+ pr_debug("+ep93xx_eth_reset\n");
+
+ value = readl(&regs->selfctl);
+ value |= SELFCTL_RESET;
+ writel(value, &regs->selfctl);
+
+ while (readl(&regs->selfctl) & SELFCTL_RESET)
+ ; /* noop */
+
+ pr_debug("-ep93xx_eth_reset\n");
+}
+
+static int ep93xx_eth_init_dev(struct eth_device *edev)
+{
+ pr_debug("+ep93xx_eth_init_dev\n");
+
+ pr_debug("-ep93xx_eth_init_dev\n");
+
+ return 0;
+}
+
+static int ep93xx_eth_open(struct eth_device *edev)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+ int i;
+
+ pr_debug("+ep93xx_eth_open\n");
+
+ ep93xx_eth_reset(edev);
+
+ /* Reset the descriptor queues' current and end address values */
+ priv->tx_dq.current = priv->tx_dq.base;
+ priv->tx_dq.end = (priv->tx_dq.base + NUMTXDESC);
+
+ priv->tx_sq.current = priv->tx_sq.base;
+ priv->tx_sq.end = (priv->tx_sq.base + NUMTXDESC);
+
+ priv->rx_dq.current = priv->rx_dq.base;
+ priv->rx_dq.end = (priv->rx_dq.base + NUMRXDESC);
+
+ priv->rx_sq.current = priv->rx_sq.base;
+ priv->rx_sq.end = (priv->rx_sq.base + NUMRXDESC);
+
+ /*
+ * Set the transmit descriptor and status queues' base address,
+ * current address, and length registers. Set the maximum frame
+ * length and threshold. Enable the transmit descriptor processor.
+ */
+ writel((uint32_t)priv->tx_dq.base, &regs->txdq.badd);
+ writel((uint32_t)priv->tx_dq.base, &regs->txdq.curadd);
+ writel(sizeof(struct tx_descriptor) * NUMTXDESC, &regs->txdq.blen);
+
+ writel((uint32_t)priv->tx_sq.base, &regs->txstsq.badd);
+ writel((uint32_t)priv->tx_sq.base, &regs->txstsq.curadd);
+ writel(sizeof(struct tx_status) * NUMTXDESC, &regs->txstsq.blen);
+
+ writel(0x00040000, &regs->txdthrshld);
+ writel(0x00040000, &regs->txststhrshld);
+
+ writel((TXSTARTMAX << 0) | (PKTSIZE_ALIGN << 16), &regs->maxfrmlen);
+ writel(BMCTL_TXEN, &regs->bmctl);
+
+ /*
+ * Set the receive descriptor and status queues' base address,
+ * current address, and length registers. Enable the receive
+ * descriptor processor.
+ */
+ writel((uint32_t)priv->rx_dq.base, &regs->rxdq.badd);
+ writel((uint32_t)priv->rx_dq.base, &regs->rxdq.curadd);
+ writel(sizeof(struct rx_descriptor) * NUMRXDESC, &regs->rxdq.blen);
+
+ writel((uint32_t)priv->rx_sq.base, &regs->rxstsq.badd);
+ writel((uint32_t)priv->rx_sq.base, &regs->rxstsq.curadd);
+ writel(sizeof(struct rx_status) * NUMRXDESC, &regs->rxstsq.blen);
+
+ writel(0x00040000, &regs->rxdthrshld);
+
+ writel(BMCTL_RXEN, &regs->bmctl);
+
+ writel(0x00040000, &regs->rxststhrshld);
+
+ /* Wait until the receive descriptor processor is active */
+ while (!(readl(&regs->bmsts) & BMSTS_RXACT))
+ ; /* noop */
+
+ /*
+ * Initialize the RX descriptor queue. Clear the TX descriptor queue.
+ * Clear the RX and TX status queues. Enqueue the RX descriptor and
+ * status entries to the MAC.
+ */
+ for (i = 0; i < NUMRXDESC; i++) {
+ /* set buffer address */
+ (priv->rx_dq.base + i)->word1 = (uint32_t)NetRxPackets[i];
+
+ /* set buffer length, clear buffer index and NSOF */
+ (priv->rx_dq.base + i)->word2 = PKTSIZE_ALIGN;
+ }
+
+ memset(priv->tx_dq.base, 0,
+ (sizeof(struct tx_descriptor) * NUMTXDESC));
+ memset(priv->rx_sq.base, 0,
+ (sizeof(struct rx_status) * NUMRXDESC));
+ memset(priv->tx_sq.base, 0,
+ (sizeof(struct tx_status) * NUMTXDESC));
+
+ writel(NUMRXDESC, &regs->rxdqenq);
+ writel(NUMRXDESC, &regs->rxstsqenq);
+
+ /* Turn on RX and TX */
+ writel(RXCTL_IA0 | RXCTL_BA | RXCTL_SRXON |
+ RXCTL_RCRCA | RXCTL_MA, &regs->rxctl);
+ writel(TXCTL_STXON, &regs->txctl);
+
+ /* Dump data structures if we're debugging */
+ dump_dev();
+ dump_rx_descriptor_queue();
+ dump_rx_status_queue();
+ dump_tx_descriptor_queue();
+ dump_tx_status_queue();
+
+ pr_debug("-ep93xx_eth_open\n");
+
+ return 0;
+}
+
+/**
+ * Halt EP93xx MAC transmit and receive by clearing the TxCTL and RxCTL
+ * registers.
+ */
+static void ep93xx_eth_halt(struct eth_device *edev)
+{
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+
+ pr_debug("+ep93xx_eth_halt\n");
+
+ writel(0x00000000, &regs->rxctl);
+ writel(0x00000000, &regs->txctl);
+
+ pr_debug("-ep93xx_eth_halt\n");
+}
+
+static int ep93xx_eth_get_ethaddr(struct eth_device *edev,
+ unsigned char *mac_addr)
+{
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+ uint32_t value;
+
+ value = readl(&regs->indad);
+ mac_addr[0] = value & 0xFF;
+ mac_addr[1] = (value >> 8) & 0xFF;
+ mac_addr[2] = (value >> 16) & 0xFF;
+ mac_addr[3] = (value >> 24) & 0xFF;
+
+ value = readl(&regs->indad_upper);
+ mac_addr[4] = value & 0xFF;
+ mac_addr[5] = (value >> 8) & 0xFF;
+
+ return 0;
+}
+
+static int ep93xx_eth_set_ethaddr(struct eth_device *edev,
+ unsigned char *mac_addr)
+{
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+
+ writel(AFP_IAPRIMARY, &regs->afp);
+
+ writel(mac_addr[0] | (mac_addr[1] << 8) |
+ (mac_addr[2] << 16) | (mac_addr[3] << 24),
+ &regs->indad);
+ writel(mac_addr[4] | (mac_addr[5] << 8), &regs->indad_upper);
+
+ return 0;
+}
+
+static int ep93xx_eth_probe(struct device_d *dev)
+{
+ struct eth_device *edev;
+ struct ep93xx_eth_priv *priv;
+ int ret = -1;
+
+ pr_debug("ep93xx_eth_probe()\n");
+
+ edev = xzalloc(sizeof(struct eth_device) +
+ sizeof(struct ep93xx_eth_priv));
+ dev->type_data = edev;
+ edev->priv = (struct ep93xx_eth_priv *)(edev + 1);
+
+ priv = edev->priv;
+ priv->regs = (struct mac_regs *)MAC_BASE;
+
+ edev->init = ep93xx_eth_init_dev;
+ edev->open = ep93xx_eth_open;
+ edev->send = ep93xx_eth_send_packet;
+ edev->recv = ep93xx_eth_rcv_packet;
+ edev->halt = ep93xx_eth_halt;
+ edev->get_ethaddr = ep93xx_eth_get_ethaddr;
+ edev->set_ethaddr = ep93xx_eth_set_ethaddr;
+
+ priv->miiphy.read = ep93xx_phy_read;
+ priv->miiphy.write = ep93xx_phy_write;
+ priv->miiphy.address = 0;
+ priv->miiphy.flags = 0;
+
+ priv->tx_dq.base = calloc(NUMTXDESC,
+ sizeof(struct tx_descriptor));
+ if (priv->tx_dq.base == NULL) {
+ pr_err("calloc() failed: tx_dq.base");
+ goto eth_probe_failed_0;
+ }
+
+ priv->tx_sq.base = calloc(NUMTXDESC,
+ sizeof(struct tx_status));
+ if (priv->tx_sq.base == NULL) {
+ pr_err("calloc() failed: tx_sq.base");
+ goto eth_probe_failed_1;
+ }
+
+ priv->rx_dq.base = calloc(NUMRXDESC,
+ sizeof(struct rx_descriptor));
+ if (priv->rx_dq.base == NULL) {
+ pr_err("calloc() failed: rx_dq.base");
+ goto eth_probe_failed_2;
+ }
+
+ priv->rx_sq.base = calloc(NUMRXDESC,
+ sizeof(struct rx_status));
+ if (priv->rx_sq.base == NULL) {
+ pr_err("calloc() failed: rx_sq.base");
+ goto eth_probe_failed_3;
+ }
+
+ miiphy_register(&priv->miiphy);
+ eth_register(edev);
+
+ ret = 0;
+
+ goto eth_probe_done;
+
+eth_probe_failed_3:
+ free(priv->rx_dq.base);
+ /* Fall through */
+
+eth_probe_failed_2:
+ free(priv->tx_sq.base);
+ /* Fall through */
+
+eth_probe_failed_1:
+ free(priv->tx_dq.base);
+ /* Fall through */
+
+eth_probe_failed_0:
+ /* Fall through */
+
+eth_probe_done:
+ return ret;
+}
+
+/**
+ * Copy a frame of data from the MAC into the protocol layer for further
+ * processing.
+ */
+static int ep93xx_eth_rcv_packet(struct eth_device *edev)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+ int ret = -1;
+
+ pr_debug("+ep93xx_eth_rcv_packet\n");
+
+ if (RX_STATUS_RFP(priv->rx_sq.current)) {
+ if (RX_STATUS_RWE(priv->rx_sq.current)) {
+ /*
+ * We have a good frame. Extract the frame's length
+ * from the current rx_status_queue entry, and copy
+ * the frame's data into NetRxPackets[] of the
+ * protocol stack. We track the total number of
+ * bytes in the frame (nbytes_frame) which will be
+ * used when we pass the data off to the protocol
+ * layer via NetReceive().
+ */
+ NetReceive((uchar *)priv->rx_dq.current->word1,
+ RX_STATUS_FRAME_LEN(priv->rx_sq.current));
+ pr_debug("reporting %d bytes...\n",
+ RX_STATUS_FRAME_LEN(priv->rx_sq.current));
+
+ ret = 0;
+
+ } else {
+ /* Do we have an erroneous packet? */
+ pr_err("packet rx error, status %08X %08X\n",
+ priv->rx_sq.current->word1,
+ priv->rx_sq.current->word2);
+ dump_rx_descriptor_queue();
+ dump_rx_status_queue();
+ }
+
+ /*
+ * Clear the associated status queue entry, and
+ * increment our current pointers to the next RX
+ * descriptor and status queue entries (making sure
+ * we wrap properly).
+ */
+ memset((void *)priv->rx_sq.current, 0,
+ sizeof(struct rx_status));
+
+ priv->rx_sq.current++;
+ if (priv->rx_sq.current >= priv->rx_sq.end)
+ priv->rx_sq.current = priv->rx_sq.base;
+
+ priv->rx_dq.current++;
+ if (priv->rx_dq.current >= priv->rx_dq.end)
+ priv->rx_dq.current = priv->rx_dq.base;
+
+ /*
+ * Finally, return the RX descriptor and status entries
+ * back to the MAC engine, and loop again, checking for
+ * more descriptors to process.
+ */
+ writel(1, &regs->rxdqenq);
+ writel(1, &regs->rxstsqenq);
+ } else {
+ ret = 0;
+ }
+
+ pr_debug("-ep93xx_eth_rcv_packet %d\n", ret);
+
+ return ret;
+}
+
+/**
+ * Send a block of data via ethernet.
+ */
+static int ep93xx_eth_send_packet(struct eth_device *edev,
+ void *packet, int length)
+{
+ struct ep93xx_eth_priv *priv = ep93xx_get_priv(edev);
+ struct mac_regs *regs = ep93xx_get_regs(edev);
+ int ret = -1;
+
+ pr_debug("+ep93xx_eth_send_packet\n");
+
+ /*
+ * Initialize the TX descriptor queue with the new packet's info.
+ * Clear the associated status queue entry. Enqueue the packet
+ * to the MAC for transmission.
+ */
+
+ /* set buffer address */
+ priv->tx_dq.current->word1 = (uint32_t)packet;
+
+ /* set buffer length and EOF bit */
+ priv->tx_dq.current->word2 = length | TX_DESC_EOF;
+
+ /* clear tx status */
+ priv->tx_sq.current->word1 = 0;
+
+ /* enqueue the TX descriptor */
+ writel(1, &regs->txdqenq);
+
+ /* wait for the frame to become processed */
+ while (!TX_STATUS_TXFP(priv->tx_sq.current))
+ ; /* noop */
+
+ if (!TX_STATUS_TXWE(priv->tx_sq.current)) {
+ pr_err("packet tx error, status %08X\n",
+ priv->tx_sq.current->word1);
+ dump_tx_descriptor_queue();
+ dump_tx_status_queue();
+
+ /* TODO: Add better error handling? */
+ goto eth_send_failed_0;
+ }
+
+ ret = 0;
+ /* Fall through */
+
+eth_send_failed_0:
+ pr_debug("-ep93xx_eth_send_packet %d\n", ret);
+
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * EP93xx ethernet MII functionality.
+ */
+
+/**
+ * Maximum MII address we support
+ */
+#define MII_ADDRESS_MAX (31)
+
+/**
+ * Maximum MII register address we support
+ */
+#define MII_REGISTER_MAX (31)
+
+/**
+ * Read a 16-bit value from an MII register.
+ */
+static int ep93xx_phy_read(struct miiphy_device *mdev, uint8_t phy_addr,
+ uint8_t phy_reg, uint16_t *value)
+{
+ struct mac_regs *regs = ep93xx_get_regs(mdev->edev);
+ int ret = -1;
+ uint32_t self_ctl;
+
+ pr_debug("+ep93xx_phy_read\n");
+
+ /*
+ * Save the current SelfCTL register value. Set MAC to suppress
+ * preamble bits. Wait for any previous MII command to complete
+ * before issuing the new command.
+ */
+ self_ctl = readl(&regs->selfctl);
+#if defined(CONFIG_MII_SUPPRESS_PREAMBLE) /* TODO */
+ writel(self_ctl & ~(1 << 8), &regs->selfctl);
+#endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
+
+ while (readl(&regs->miists) & MIISTS_BUSY)
+ ; /* noop */
+
+ /*
+ * Issue the MII 'read' command. Wait for the command to complete.
+ * Read the MII data value.
+ */
+ writel(MIICMD_OPCODE_READ | ((uint32_t)phy_addr << 5) |
+ (uint32_t)phy_reg, &regs->miicmd);
+ while (readl(&regs->miists) & MIISTS_BUSY)
+ ; /* noop */
+
+ *value = (unsigned short)readl(&regs->miidata);
+
+ /* Restore the saved SelfCTL value and return. */
+ writel(self_ctl, &regs->selfctl);
+
+ ret = 0;
+
+ pr_debug("-ep93xx_phy_read\n");
+
+ return ret;
+}
+
+/**
+ * Write a 16-bit value to an MII register.
+ */
+static int ep93xx_phy_write(struct miiphy_device *mdev, uint8_t phy_addr,
+ uint8_t phy_reg, uint16_t value)
+{
+ struct mac_regs *regs = ep93xx_get_regs(mdev->edev);
+ int ret = -1;
+ uint32_t self_ctl;
+
+ pr_debug("+ep93xx_phy_write\n");
+
+ /*
+ * Save the current SelfCTL register value. Set MAC to suppress
+ * preamble bits. Wait for any previous MII command to complete
+ * before issuing the new command.
+ */
+ self_ctl = readl(&regs->selfctl);
+#if defined(CONFIG_MII_SUPPRESS_PREAMBLE) /* TODO */
+ writel(self_ctl & ~(1 << 8), &regs->selfctl);
+#endif /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
+
+ while (readl(&regs->miists) & MIISTS_BUSY)
+ ; /* noop */
+
+ /* Issue the MII 'write' command. Wait for the command to complete. */
+ writel((uint32_t)value, &regs->miidata);
+ writel(MIICMD_OPCODE_WRITE | ((uint32_t)phy_addr << 5) | phy_reg,
+ &regs->miicmd);
+ while (readl(&regs->miists) & MIISTS_BUSY)
+ ; /* noop */
+
+ /* Restore the saved SelfCTL value and return. */
+ writel(self_ctl, &regs->selfctl);
+
+ ret = 0;
+
+ pr_debug("-ep93xx_phy_write\n");
+
+ return ret;
+}
+
+static struct driver_d ep93xx_eth_driver = {
+ .name = "ep93xx_eth",
+ .probe = ep93xx_eth_probe,
+};
+
+static int ep93xx_eth_init(void)
+{
+ register_driver(&ep93xx_eth_driver);
+ return 0;
+}
+
+device_initcall(ep93xx_eth_init);
diff --git a/drivers/net/ep93xx.h b/drivers/net/ep93xx.h
new file mode 100644
index 00000000..ae45c54f
--- /dev/null
+++ b/drivers/net/ep93xx.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * Copyright (C) 2004, 2005
+ * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
+ *
+ * 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
+ *
+ */
+
+#ifndef _ETH_H
+#define _ETH_H
+
+#include <net.h>
+
+/**
+ * #define this to dump device status and queue info during initialization and
+ * following errors.
+ */
+#undef EP93XX_MAC_DEBUG
+
+/**
+ * Number of descriptor and status entries in our RX queues.
+ * It must be power of 2 !
+ */
+#define NUMRXDESC PKTBUFSRX
+
+/**
+ * Number of descriptor and status entries in our TX queues.
+ */
+#define NUMTXDESC 1
+
+/**
+ * 944 = (1024 - 64) - 16, Fifo size - Minframesize - 16 (Chip FACT)
+ */
+#define TXSTARTMAX 944
+
+/**
+ * Receive descriptor queue entry
+ */
+struct rx_descriptor {
+ uint32_t word1;
+ uint32_t word2;
+} __attribute__((packed));
+
+/**
+ * Receive status queue entry
+ */
+struct rx_status {
+ uint32_t word1;
+ uint32_t word2;
+} __attribute__((packed));
+
+#define RX_STATUS_RWE(rx_status) ((rx_status->word1 >> 30) & 0x01)
+#define RX_STATUS_RFP(rx_status) ((rx_status->word1 >> 31) & 0x01)
+#define RX_STATUS_FRAME_LEN(rx_status) (rx_status->word2 & 0xFFFF)
+
+
+/**
+ * Transmit descriptor queue entry
+ */
+struct tx_descriptor {
+ uint32_t word1;
+ uint32_t word2;
+} __attribute__((packed));
+
+#define TX_DESC_EOF (1 << 31)
+
+/**
+ * Transmit status queue entry
+ */
+struct tx_status {
+ uint32_t word1;
+} __attribute__((packed));
+
+#define TX_STATUS_TXWE(tx_status) (((tx_status)->word1 >> 30) & 0x01)
+#define TX_STATUS_TXFP(tx_status) (((tx_status)->word1 >> 31) & 0x01)
+
+/**
+ * Transmit descriptor queue
+ */
+struct tx_descriptor_queue {
+ struct tx_descriptor *base;
+ struct tx_descriptor *current;
+ struct tx_descriptor *end;
+};
+
+/**
+ * Transmit status queue
+ */
+struct tx_status_queue {
+ struct tx_status *base;
+ volatile struct tx_status *current;
+ struct tx_status *end;
+};
+
+/**
+ * Receive descriptor queue
+ */
+struct rx_descriptor_queue {
+ struct rx_descriptor *base;
+ struct rx_descriptor *current;
+ struct rx_descriptor *end;
+};
+
+/**
+ * Receive status queue
+ */
+struct rx_status_queue {
+ struct rx_status *base;
+ volatile struct rx_status *current;
+ struct rx_status *end;
+};
+
+/**
+ * EP93xx MAC private data structure
+ */
+struct ep93xx_eth_priv {
+ struct mac_regs *regs;
+
+ struct rx_descriptor_queue rx_dq;
+ struct rx_status_queue rx_sq;
+ void *rx_buffer[NUMRXDESC];
+
+ struct tx_descriptor_queue tx_dq;
+ struct tx_status_queue tx_sq;
+
+ struct miiphy_device miiphy;
+};
+
+#endif
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b0ff5fa1..8a5056bc 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -47,6 +47,13 @@ config DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
help
Say Y here if you are using OMAP extensions to NS16550
+config DRIVER_SERIAL_PL010
+ depends on ARCH_EP93XX
+ default y
+ bool "ARM AMBA PL010 support"
+ help
+ Enable this to get support for AMBA PL010 based serial devices
+
config DRIVER_SERIAL_S3C24X0
bool "Samsung S3C24X0 serial driver"
depends on ARCH_S3C24xx
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 8ab680de..9f203bbc 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -3,7 +3,6 @@
# s3c4510b_uart.o
# serial_max3100.o
# serial_pl010.o
-# serial_pl011.o
# serial_xuartlite.o
obj-$(CONFIG_DRIVER_SERIAL_ARM_DCC) += arm_dcc.o
obj-$(CONFIG_DRIVER_SERIAL_IMX) += serial_imx.o
@@ -13,4 +12,5 @@ obj-$(CONFIG_DRIVER_SERIAL_LINUX_COMSOLE) += linux_console.o
obj-$(CONFIG_DRIVER_SERIAL_MPC5XXX) += serial_mpc5xxx.o
obj-$(CONFIG_DRIVER_SERIAL_BLACKFIN) += serial_blackfin.o
obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial_ns16550.o
+obj-$(CONFIG_DRIVER_SERIAL_PL010) += serial_pl010.o
obj-$(CONFIG_DRIVER_SERIAL_S3C24X0) += serial_s3c24x0.o
diff --git a/drivers/serial/serial_pl010.c b/drivers/serial/serial_pl010.c
new file mode 100644
index 00000000..1a6366f6
--- /dev/null
+++ b/drivers/serial/serial_pl010.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * (C) Copyright 2004
+ * ARM Ltd.
+ * Philippe Robin, <philippe.robin@arm.com>
+ *
+ * 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
+ */
+
+/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include "serial_pl010.h"
+
+static int pl010_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ struct pl010_struct *pl010 = (struct pl010_struct *)cdev->dev->map_base;
+ unsigned int divisor;
+
+ switch (baudrate) {
+ case 9600:
+ divisor = UART_PL010_BAUD_9600;
+ break;
+
+ case 19200:
+ divisor = UART_PL010_BAUD_9600;
+ break;
+
+ case 38400:
+ divisor = UART_PL010_BAUD_38400;
+ break;
+
+ case 57600:
+ divisor = UART_PL010_BAUD_57600;
+ break;
+
+ case 115200:
+ divisor = UART_PL010_BAUD_115200;
+ break;
+
+ default:
+ divisor = UART_PL010_BAUD_38400;
+ }
+
+ writel((divisor & 0xf00) >> 8, &pl010->linctrlmid);
+ writel(divisor & 0xff, &pl010->linctrllow);
+
+ /* high register must always be written */
+ writel(readl(&pl010->linctrlhigh), &pl010->linctrlhigh);
+
+ return 0;
+}
+
+static int pl010_init_port(struct console_device *cdev)
+{
+ struct pl010_struct *pl010 = (struct pl010_struct *)cdev->dev->map_base;
+
+ /*
+ * First, disable everything.
+ */
+ writel(0x00, &pl010->ctrl);
+
+ /*
+ * Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
+ */
+ writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN,
+ &pl010->linctrlhigh);
+
+ /*
+ * Finally, enable the UART
+ */
+ writel(UART_PL010_CR_UARTEN, &pl010->ctrl);
+
+ return 0;
+}
+
+static void pl010_putc(struct console_device *cdev, char c)
+{
+ struct pl010_struct *pl010 = (struct pl010_struct *)cdev->dev->map_base;
+
+ /* Wait until there is space in the FIFO */
+ while (readl(&pl010->flag) & UART_PL010_FR_TXFF)
+ ; /* noop */
+
+ /* Send the character */
+ writel(c, &pl010->data);
+}
+
+static int pl010_getc(struct console_device *cdev)
+{
+ struct pl010_struct *pl010 = (struct pl010_struct *)cdev->dev->map_base;
+ unsigned int data;
+
+ /* Wait until there is data in the FIFO */
+ while (readl(&pl010->flag) & UART_PL010_FR_RXFE)
+ ; /* noop */
+
+ data = readl(&pl010->data);
+
+ /* Check for an error flag */
+ if (data & 0xFFFFFF00) {
+ /* Clear the error */
+ writel(0xFFFFFFFF, &pl010->errclr);
+ return -1;
+ }
+
+ return (int)data;
+}
+
+static int pl010_tstc(struct console_device *cdev)
+{
+ struct pl010_struct *pl010 = (struct pl010_struct *)cdev->dev->map_base;
+
+ return !(readl(&pl010->flag) & UART_PL010_FR_RXFE);
+}
+
+static int pl010_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+
+ cdev = malloc(sizeof(struct console_device));
+ dev->type_data = cdev;
+ cdev->dev = dev;
+ cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+ cdev->tstc = pl010_tstc;
+ cdev->putc = pl010_putc;
+ cdev->getc = pl010_getc;
+ cdev->setbrg = pl010_setbaudrate;
+
+ pl010_init_port(cdev);
+
+ console_register(cdev);
+
+ return 0;
+}
+
+static struct driver_d pl010_driver = {
+ .name = "pl010_serial",
+ .probe = pl010_probe,
+};
+
+static int pl010_init(void)
+{
+ register_driver(&pl010_driver);
+
+ return 0;
+}
+
+console_initcall(pl010_init);
diff --git a/drivers/serial/serial_pl010.h b/drivers/serial/serial_pl010.h
new file mode 100644
index 00000000..6124e0e0
--- /dev/null
+++ b/drivers/serial/serial_pl010.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
+ *
+ * (C) Copyright 2003, 2004
+ * ARM Ltd.
+ * Philippe Robin, <philippe.robin@arm.com>
+ *
+ * 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
+ */
+
+struct hldc_struct {
+ uint32_t ctrl;
+ uint32_t addmtchval;
+ uint32_t addmask;
+ uint32_t rxinfobuf;
+ uint32_t sts;
+};
+
+struct pl010_struct {
+ uint32_t data;
+ union {
+ uint32_t rxsts;
+ uint32_t errclr;
+ };
+ uint32_t linctrlhigh;
+ uint32_t linctrlmid;
+ uint32_t linctrllow;
+ uint32_t ctrl;
+ uint32_t flag;
+ union {
+ uint32_t intid;
+ uint32_t intclr;
+ };
+ uint32_t not_used0[2];
+ uint32_t dmactrl;
+ uint32_t not_used1[53];
+ uint32_t modemctrl;
+ uint32_t modemsts;
+ uint32_t not_used2[65];
+ struct hldc_struct hldc;
+};
+
+#define UART_PL010_RSR_OE (1 << 3)
+#define UART_PL010_RSR_BE (1 << 2)
+#define UART_PL010_RSR_PE (1 << 1)
+#define UART_PL010_RSR_FE (1 << 0)
+
+#define UART_PL010_FR_TXFE (1 << 7)
+#define UART_PL010_FR_RXFF (1 << 6)
+#define UART_PL010_FR_TXFF (1 << 5)
+#define UART_PL010_FR_RXFE (1 << 4)
+#define UART_PL010_FR_BUSY (1 << 3)
+#define UART_PL010_FR_TMSK (UART_PL010_FR_TXFF + UART_PL010_FR_BUSY)
+
+#define UART_PL010_CR_LPE (1 << 7)
+#define UART_PL010_CR_RTIE (1 << 6)
+#define UART_PL010_CR_TIE (1 << 5)
+#define UART_PL010_CR_RIE (1 << 4)
+#define UART_PL010_CR_MSIE (1 << 3)
+#define UART_PL010_CR_IIRLP (1 << 2)
+#define UART_PL010_CR_SIREN (1 << 1)
+#define UART_PL010_CR_UARTEN (1 << 0)
+
+#define UART_PL010_LCRH_WLEN_8 (3 << 5)
+#define UART_PL010_LCRH_WLEN_7 (2 << 5)
+#define UART_PL010_LCRH_WLEN_6 (1 << 5)
+#define UART_PL010_LCRH_WLEN_5 (0 << 5)
+#define UART_PL010_LCRH_FEN (1 << 4)
+#define UART_PL010_LCRH_STP2 (1 << 3)
+#define UART_PL010_LCRH_EPS (1 << 2)
+#define UART_PL010_LCRH_PEN (1 << 1)
+#define UART_PL010_LCRH_BRK (1 << 0)
+
+#define UART_PL010_BAUD_460800 1
+#define UART_PL010_BAUD_230400 3
+#define UART_PL010_BAUD_115200 7
+#define UART_PL010_BAUD_57600 15
+#define UART_PL010_BAUD_38400 23
+#define UART_PL010_BAUD_19200 47
+#define UART_PL010_BAUD_14400 63
+#define UART_PL010_BAUD_9600 95
+#define UART_PL010_BAUD_4800 191
+#define UART_PL010_BAUD_2400 383
+#define UART_PL010_BAUD_1200 767
diff --git a/include/ata.h b/include/ata.h
new file mode 100644
index 00000000..d56399ea
--- /dev/null
+++ b/include/ata.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Declarations to communicate with ATA types of drives
+ */
+
+#include <types.h>
+#include <driver.h>
+
+/**
+ * Access functions from drives through the specified interface
+ */
+struct ata_interface {
+ /** write a count of sectors from a buffer to the drive */
+ int (*write)(struct device_d*, uint64_t, unsigned, const void*);
+ /** read a count of sectors from the drive into the buffer */
+ int (*read)(struct device_d*, uint64_t, unsigned, void*);
+ /** private interface data */
+ void *priv;
+};
diff --git a/include/common.h b/include/common.h
index 0c49d950..2b40954a 100644
--- a/include/common.h
+++ b/include/common.h
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/stddef.h>
#include <asm/common.h>
#define pr_info(fmt, arg...) printf(fmt, ##arg)
diff --git a/include/i2c/lp3972.h b/include/i2c/lp3972.h
new file mode 100644
index 00000000..edb58011
--- /dev/null
+++ b/include/i2c/lp3972.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_ARCH_LP3972_H
+#define __ASM_ARCH_LP3972_H
+
+extern struct i2c_client *lp3972_get_client(void);
+
+#endif /* __ASM_ARCH_LP3972_H */
+
diff --git a/include/i2c/mc13892.h b/include/i2c/mc13892.h
index 2f44f6c8..112d05ba 100644
--- a/include/i2c/mc13892.h
+++ b/include/i2c/mc13892.h
@@ -1,7 +1,93 @@
+/*
+ * Copyright (C) 2009 Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ * Derived from:
+ * - arch-mxc/pmic_external.h -- contains interface of the PMIC protocol driver
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ */
+
#ifndef __ASM_ARCH_MC13892_H
#define __ASM_ARCH_MC13892_H
-extern struct i2c_client *mc13892_get_client(void);
+enum mc13892_reg {
+ MC13892_REG_INT_STATUS0 = 0x00,
+ MC13892_REG_INT_MASK0 = 0x01,
+ MC13892_REG_INT_SENSE0 = 0x02,
+ MC13892_REG_INT_STATUS1 = 0x03,
+ MC13892_REG_INT_MASK1 = 0x04,
+ MC13892_REG_INT_SENSE1 = 0x05,
+ MC13892_REG_PU_MODE_S = 0x06,
+ MC13892_REG_IDENTIFICATION = 0x07,
+ MC13892_REG_UNUSED0 = 0x08,
+ MC13892_REG_ACC0 = 0x09,
+ MC13892_REG_ACC1 = 0x0a,
+ MC13892_REG_UNUSED1 = 0x0b,
+ MC13892_REG_UNUSED2 = 0x0c,
+ MC13892_REG_POWER_CTL0 = 0x0d,
+ MC13892_REG_POWER_CTL1 = 0x0e,
+ MC13892_REG_POWER_CTL2 = 0x0f,
+ MC13892_REG_REGEN_ASSIGN = 0x10,
+ MC13892_REG_UNUSED3 = 0x11,
+ MC13892_REG_MEM_A = 0x12,
+ MC13892_REG_MEM_B = 0x13,
+ MC13892_REG_RTC_TIME = 0x14,
+ MC13892_REG_RTC_ALARM = 0x15,
+ MC13892_REG_RTC_DAY = 0x16,
+ MC13892_REG_RTC_DAY_ALARM = 0x17,
+ MC13892_REG_SW_0 = 0x18,
+ MC13892_REG_SW_1 = 0x19,
+ MC13892_REG_SW_2 = 0x1a,
+ MC13892_REG_SW_3 = 0x1b,
+ MC13892_REG_SW_4 = 0x1c,
+ MC13892_REG_SW_5 = 0x1d,
+ MC13892_REG_SETTING_0 = 0x1e,
+ MC13892_REG_SETTING_1 = 0x1f,
+ MC13892_REG_MODE_0 = 0x20,
+ MC13892_REG_MODE_1 = 0x21,
+ MC13892_REG_POWER_MISC = 0x22,
+ MC13892_REG_UNUSED4 = 0x23,
+ MC13892_REG_UNUSED5 = 0x24,
+ MC13892_REG_UNUSED6 = 0x25,
+ MC13892_REG_UNUSED7 = 0x26,
+ MC13892_REG_UNUSED8 = 0x27,
+ MC13892_REG_UNUSED9 = 0x28,
+ MC13892_REG_UNUSED10 = 0x29,
+ MC13892_REG_UNUSED11 = 0x2a,
+ MC13892_REG_ADC0 = 0x2b,
+ MC13892_REG_ADC1 = 0x2c,
+ MC13892_REG_ADC2 = 0x2d,
+ MC13892_REG_ADC3 = 0x2e,
+ MC13892_REG_ADC4 = 0x2f,
+ MC13892_REG_CHARGE = 0x30,
+ MC13892_REG_USB0 = 0x31,
+ MC13892_REG_USB1 = 0x32,
+ MC13892_REG_LED_CTL0 = 0x33,
+ MC13892_REG_LED_CTL1 = 0x34,
+ MC13892_REG_LED_CTL2 = 0x35,
+ MC13892_REG_LED_CTL3 = 0x36,
+ MC13892_REG_UNUSED12 = 0x37,
+ MC13892_REG_UNUSED13 = 0x38,
+ MC13892_REG_TRIM0 = 0x39,
+ MC13892_REG_TRIM1 = 0x3a,
+ MC13892_REG_TEST0 = 0x3b,
+ MC13892_REG_TEST1 = 0x3c,
+ MC13892_REG_TEST2 = 0x3d,
+ MC13892_REG_TEST3 = 0x3e,
+ MC13892_REG_TEST4 = 0x3f,
+};
-#endif /* __ASM_ARCH_MC13892_H */
+struct mc13892 {
+ struct cdev cdev;
+ struct i2c_client *client;
+};
+
+extern struct mc13892 *mc13892_get(void);
+extern int mc13892_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val);
+extern int mc13892_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val);
+extern int mc13892_set_bits(struct mc13892 *mc13892, enum mc13892_reg reg, u32 mask, u32 val);
+
+#endif /* __ASM_ARCH_MC13892_H */
diff --git a/include/i2c/mc9sdz60.h b/include/i2c/mc9sdz60.h
index 04cfca04..4cc233e0 100644
--- a/include/i2c/mc9sdz60.h
+++ b/include/i2c/mc9sdz60.h
@@ -1,7 +1,64 @@
+/*
+ * Copyright (C) 2009 Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ * Derived from:
+ * - mcu_max8660-bus.h -- contains interface of the mc9sdz60 and max8660
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ */
+
#ifndef __ASM_ARCH_MC9SDZ60_H
#define __ASM_ARCH_MC9SDZ60_H
-extern struct i2c_client *mc9sdz60_get_client(void);
+enum mc9sdz60_reg {
+ MC9SDZ60_REG_VERSION = 0x00,
+ MC9SDZ60_REG_SECS = 0x01,
+ MC9SDZ60_REG_MINS = 0x02,
+ MC9SDZ60_REG_HRS = 0x03,
+ MC9SDZ60_REG_DAY = 0x04,
+ MC9SDZ60_REG_DATE = 0x05,
+ MC9SDZ60_REG_MONTH = 0x06,
+ MC9SDZ60_REG_YEAR = 0x07,
+ MC9SDZ60_REG_ALARM_SECS = 0x08,
+ MC9SDZ60_REG_ALARM_MINS = 0x09,
+ MC9SDZ60_REG_ALARM_HRS = 0x0a,
+ MC9SDZ60_REG_TS_CONTROL = 0x0b,
+ MC9SDZ60_REG_X_LOW = 0x0c,
+ MC9SDZ60_REG_Y_LOW = 0x0d,
+ MC9SDZ60_REG_XY_HIGH = 0x0e,
+ MC9SDZ60_REG_X_LEFT_LOW = 0x0f,
+ MC9SDZ60_REG_X_LEFT_HIGH = 0x10,
+ MC9SDZ60_REG_X_RIGHT = 0x11,
+ MC9SDZ60_REG_Y_TOP_LOW = 0x12,
+ MC9SDZ60_REG_Y_TOP_HIGH = 0x13,
+ MC9SDZ60_REG_Y_BOTTOM = 0x14,
+ MC9SDZ60_REG_RESET_1 = 0x15,
+ MC9SDZ60_REG_RESET_2 = 0x16,
+ MC9SDZ60_REG_POWER_CTL = 0x17,
+ MC9SDZ60_REG_DELAY_CONFIG = 0x18,
+ MC9SDZ60_REG_GPIO_1 = 0x19,
+ MC9SDZ60_REG_GPIO_2 = 0x1a,
+ MC9SDZ60_REG_KPD_1 = 0x1b,
+ MC9SDZ60_REG_KPD_2 = 0x1c,
+ MC9SDZ60_REG_KPD_CONTROL = 0x1d,
+ MC9SDZ60_REG_INT_ENABLE_1 = 0x1e,
+ MC9SDZ60_REG_INT_ENABLE_2 = 0x1f,
+ MC9SDZ60_REG_INT_FLAG_1 = 0x20,
+ MC9SDZ60_REG_INT_FLAG_2 = 0x21,
+ MC9SDZ60_REG_DES_FLAG = 0x22,
+};
-#endif /* __ASM_ARCH_MC9SDZ60_H */
+struct mc9sdz60 {
+ struct cdev cdev;
+ struct i2c_client *client;
+};
+
+extern struct mc9sdz60 *mc9sdz60_get(void);
+extern int mc9sdz60_reg_read(struct mc9sdz60 *priv, enum mc9sdz60_reg reg, u8 *val);
+extern int mc9sdz60_reg_write(struct mc9sdz60 *priv, enum mc9sdz60_reg reg, u8 val);
+extern int mc9sdz60_set_bits(struct mc9sdz60 *priv, enum mc9sdz60_reg reg, u8 mask, u8 val);
+
+#endif /* __ASM_ARCH_MC9SDZ60_H */
diff --git a/scripts/Makefile b/scripts/Makefile
index c22a8b6e..be8e3e05 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -14,5 +14,7 @@ always := $(hostprogs-y) $(hostprogs-m)
subdir-y += mod
+subdir-$(CONFIG_X86) += setupmbr
+
# Let clean descend into subdirs
-subdir- += basic kconfig
+subdir- += basic kconfig setupmbr
diff --git a/scripts/setupmbr/Makefile b/scripts/setupmbr/Makefile
new file mode 100644
index 00000000..8680fedc
--- /dev/null
+++ b/scripts/setupmbr/Makefile
@@ -0,0 +1,4 @@
+HOST_EXTRACFLAGS=-I$(srctree)
+
+hostprogs-y := setupmbr
+always := $(hostprogs-y)
diff --git a/scripts/setupmbr/arch.h b/scripts/setupmbr/arch.h
new file mode 100644
index 00000000..a720dfe9
--- /dev/null
+++ b/scripts/setupmbr/arch.h
@@ -0,0 +1,55 @@
+
+/* we need the one from the host */
+#include <endian.h>
+#include <stdint.h>
+
+/* Byte-orders. */
+#define swap16(x) \
+({ \
+ uint16_t _x = (x); \
+ (uint16_t) ((_x << 8) | (_x >> 8)); \
+})
+
+#define swap32(x) \
+({ \
+ uint32_t _x = (x); \
+ (uint32_t) ((_x << 24) \
+ | ((_x & (uint32_t) 0xFF00UL) << 8) \
+ | ((_x & (uint32_t) 0xFF0000UL) >> 8) \
+ | (_x >> 24)); \
+})
+
+#define swap64(x) \
+({ \
+ uint64_t _x = (x); \
+ (uint64_t) ((_x << 56) \
+ | ((_x & (uint64_t) 0xFF00ULL) << 40) \
+ | ((_x & (uint64_t) 0xFF0000ULL) << 24) \
+ | ((_x & (uint64_t) 0xFF000000ULL) << 8) \
+ | ((_x & (uint64_t) 0xFF00000000ULL) >> 8) \
+ | ((_x & (uint64_t) 0xFF0000000000ULL) >> 24) \
+ | ((_x & (uint64_t) 0xFF000000000000ULL) >> 40) \
+ | (_x >> 56)); \
+})
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+/* Our target is a ia32 machine, always little endian */
+
+# define host2target_16(x) swap16(x)
+# define host2target_32(x) swap32(x)
+# define host2target_64(x) swap64(x)
+# define target2host_16(x) swap16(x)
+# define target2host_32(x) swap32(x)
+# define target2host_64(x) swap64(x)
+
+#else
+
+# define host2target_16(x) (x)
+# define host2target_32(x) (x)
+# define host2target_64(x) (x)
+# define target2host_16(x) (x)
+# define target2host_32(x) (x)
+# define target2host_64(x) (x)
+
+#endif
diff --git a/scripts/setupmbr/setupmbr.c b/scripts/setupmbr/setupmbr.c
new file mode 100644
index 00000000..01e8c645
--- /dev/null
+++ b/scripts/setupmbr/setupmbr.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/**
+ * @file
+ * @brief Write the barebox binary to the MBR and the following disk sectors
+ *
+ * Also patch dedicated locations in the image to make it work at runtime
+ *
+ * Current restrictions are:
+ * - only installs into MBR and the sectors after it
+ * - tested only with QEMU
+ * - and maybe some others
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+/* include the info from this barebox release */
+#include "include/linux/utsrelease.h"
+#include "arch/x86/include/asm/barebox.lds.h"
+
+/** define to disable integrity tests and debug messages */
+#define NDEBUG
+
+/* some infos about our target architecture */
+#include "arch.h"
+
+/**
+ * "Disk Address Packet Structure" to be used when calling int13,
+ * function 0x42
+ *
+ * @note All entries are in target endianess
+ */
+struct DAPS
+{
+ uint8_t size; /**< size of this data set, 0 marks it as invalid */
+ uint8_t res1; /**< always 0 */
+ int8_t count; /**< number of sectors 0...127 to handle */
+ uint8_t res2; /**< always 0 */
+ uint16_t offset; /**< store address: offset */
+ uint16_t segment; /**< store address: segment */
+ uint64_t lba; /**< start sector number in LBA */
+} __attribute__ ((packed));
+
+/**
+ * Description of one partition table entry (D*S type)
+ *
+ * @note All entries are in target endianess
+ */
+struct partition_entry {
+ uint8_t boot_indicator;
+ uint8_t chs_begin[3];
+ uint8_t type;
+ uint8_t chs_end[3];
+ uint32_t partition_start; /* LE */
+ uint32_t partition_size; /* LE */
+} __attribute__ ((packed));
+
+#ifndef NDEBUG
+static void debugout(const struct DAPS *entry, int supress_entry)
+{
+ if (supress_entry)
+ printf("DAPS entry: ");
+ else
+ printf("DAPS entry % 3u: ", ((unsigned)entry & ( SECTOR_SIZE - 1)) / sizeof(struct DAPS));
+
+ printf("Size: % 2u, Count: % 3d, Offset: 0x%04hX, Segment: 0x%04hX, LBA: %llu\n",
+ entry->size, entry->count,
+ target2host_16(entry->offset), target2host_16(entry->segment),
+ target2host_64(entry->lba));
+}
+#else
+# define debugout(x,y) (__ASSERT_VOID_CAST(0))
+#endif
+
+/**
+ * Fill *one* DAPS
+ * @param sector The DAPS to fill
+ * @param count Sector count
+ * @param offset Realmode offset in the segment
+ * @param segment Real mode segment
+ * @param lba LBA of the first sector to read
+ * @return 0 on success
+ */
+static int fill_daps(struct DAPS *sector, unsigned count, unsigned offset, unsigned segment, uint64_t lba)
+{
+ assert(sector != NULL);
+ assert(count < 128);
+ assert(offset < 0x10000);
+ assert(segment < 0x10000);
+
+ sector->size = sizeof(struct DAPS);
+ sector->res1 = 0;
+ sector->count = (int8_t)count;
+ sector->res2 = 0;
+ sector->offset = host2target_16(offset);
+ sector->segment = host2target_16(segment);
+ sector->lba = host2target_64(lba);
+
+ return 0;
+}
+
+/**
+ * Mark a DAPS invalid to let the boot loader code stop at this entry.
+ * @param sector The DAPS to be marked as invalid
+ *
+ * Marking as invalid must be done in accordance to the detection method
+ * the assembler routine in the boot loader uses:
+ * The current code tests for zero in the first two bytes of the DAPS.
+ */
+static void invalidate_daps(struct DAPS *sector)
+{
+ sector->size = MARK_DAPS_INVALID;
+ sector->res1 = 0;
+}
+
+/**
+ * Create the indirect sector with the DAPS entries
+ * @param daps_table Where to store the entries
+ * @param size Size of the whole image in bytes
+ * @param pers_sector_count Count of sectors to skip after MBR for the persistant environment storage
+ * @return 0 on success
+ *
+ * This routine calculates the DAPS entries for the case the whole
+ * barebox images fits into the MBR itself and the sectors after it.
+ * This means the start of the first partition must keep enough sectors
+ * unused.
+ * It also skips 'pers_sector_count' sectors after the MBR for special
+ * usage if given.
+ */
+static int barebox_linear_image(struct DAPS *daps_table, off_t size, long pers_sector_count)
+{
+ unsigned offset = LOAD_AREA, next_offset;
+ unsigned segment = LOAD_SEGMENT;
+ unsigned chunk_size, i = 0;
+ uint64_t lba = 2 + pers_sector_count;
+ int rc;
+
+ /*
+ * We can load up to 127 sectors in one chunk. What a bad number...
+ * So, we will load in chunks of 32 kiB.
+ */
+
+ /* at runtime two sectors from the image are already loaded: MBR and indirect */
+ size -= 2 * SECTOR_SIZE;
+ /* and now round up to multiple of sector size */
+ size = (size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
+
+ /*
+ * The largest image we can load with this method is:
+ * (SECTOR_SIZE / sizeof(DAPS) - 1) * 32 kiB
+ * For a 512 byte sector and a 16 byte DAPS:
+ * (512 / 16 - 1) * 32 kiB = 992 kiB
+ * Note: '- 1' to consider one entry is required to pad to a 32 kiB boundary
+ */
+
+ if (size >= (SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32 * 1024) {
+ fprintf(stderr, "Image too large to boot. Max size is %zu kiB, image size is %lu kiB\n",
+ (SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32, size / 1024);
+ return -1;
+ }
+
+ if (size > 32 * 1024) {
+ /* first fill up until the next 32 k boundary */
+ next_offset = (offset + 32 * 1024 -1) & ~0x7fff;
+ chunk_size = next_offset - offset;
+ if (chunk_size & (SECTOR_SIZE-1)) {
+ fprintf(stderr, "Unable to pad from %X to %X in multiple of sectors\n", offset, next_offset);
+ return -1;
+ }
+
+ rc = fill_daps(&daps_table[i], chunk_size / SECTOR_SIZE, offset, segment, lba);
+ if (rc != 0)
+ return -1;
+ debugout(&daps_table[i], 0);
+
+ /* calculate values to enter the loop for the other entries */
+ size -= chunk_size;
+ i++;
+ lba += chunk_size / SECTOR_SIZE;
+ offset += chunk_size;
+ if (offset >= 0x10000) {
+ segment += 4096;
+ offset = 0;
+ }
+
+ /*
+ * Now load the remaining image part in 32 kiB chunks
+ */
+ while (size) {
+ if (size >= 32 * 1024 ) {
+ if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) {
+ fprintf(stderr, "Internal tool error: Too many DAPS entries!\n");
+ return -1;
+ }
+ rc = fill_daps(&daps_table[i], 64, offset, segment, lba);
+ if (rc != 0)
+ return -1;
+ debugout(&daps_table[i], 0);
+
+ size -= 32 * 1024;
+ lba += 64;
+ offset += 32 * 1024;
+ if (offset >= 0x10000) {
+ segment += 4096;
+ offset = 0;
+ }
+ i++;
+ } else {
+ if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) {
+ fprintf(stderr, "Internal tool error: Too many DAPS entries!\n");
+ return -1;
+ }
+ rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba);
+ if (rc != 0)
+ return -1;
+ debugout(&daps_table[i], 0);
+ size = 0; /* finished */
+ i++;
+ }
+ };
+ } else {
+ /* less than 32 kiB. Very small image... */
+ rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba);
+ if (rc != 0)
+ return -1;
+ debugout(&daps_table[i], 0);
+ i++;
+ }
+
+ /*
+ * Do not mark an entry as invalid if the buffer is full. The
+ * boot code stops if all entries of a buffer are read.
+ */
+ if (i >= (SECTOR_SIZE / sizeof(struct DAPS)))
+ return 0;
+
+ /* mark the last DAPS invalid */
+ invalidate_daps(&daps_table[i]);
+ debugout(&daps_table[i], 0);
+
+ return 0;
+}
+
+/**
+ * Do some simple sanity checks if this sector could be an MBR
+ * @param sector Sector with data to check
+ * @param size Size of the buffer
+ * @return 0 if successfull
+ */
+static int check_for_valid_mbr(const uint8_t *sector, off_t size)
+{
+ if (size < SECTOR_SIZE) {
+ fprintf(stderr, "MBR too small to be valid\n");
+ return -1;
+ }
+
+ if ((sector[OFFSET_OF_SIGNATURE] != 0x55) ||
+ (sector[OFFSET_OF_SIGNATURE + 1] != 0xAA)) {
+ fprintf(stderr, "No MBR signature found\n");
+ return -1;
+ }
+
+ /* FIXME: try to check if there is a valid partition table */
+ return 0;
+}
+
+/**
+ * Check space between start of the image and the start of the first partition
+ * @param hd_image HD image to examine
+ * @param size Size of the barebox image
+ * @return 0 on success, -1 if the barebox image is too large
+ */
+static int check_for_space(const void *hd_image, off_t size)
+{
+ struct partition_entry *partition;
+ uint8_t *mbr_disk_sector = (uint8_t*)hd_image;
+ off_t spare_sector_count;
+
+ assert(hd_image != NULL);
+ assert(size > 0);
+
+ if (check_for_valid_mbr(hd_image, size) != 0)
+ return -1;
+
+ /* where to read */
+ partition = (struct partition_entry*) &mbr_disk_sector[OFFSET_OF_PARTITION_TABLE];
+
+ /* TODO describes the first entry always the first partition? */
+ spare_sector_count = target2host_32(partition->partition_start);
+
+#ifdef DEBUG
+ printf("Debug: Required free sectors for barebox prior first partition: %lu, hd image provides: %lu\n",
+ (size + SECTOR_SIZE - 1) / SECTOR_SIZE, spare_sector_count);
+#endif
+ spare_sector_count *= SECTOR_SIZE;
+ if (spare_sector_count < size) {
+ fprintf(stderr, "Not enough space after MBR to store barebox\n");
+ fprintf(stderr, "Move begin of the first partition beyond sector %lu\n", (size + SECTOR_SIZE - 1) / SECTOR_SIZE);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Setup the persistant environment storage information
+ * @param patch_area Where to patch
+ * @param pers_sector_start Start sector of the persistant environment storage
+ * @param pers_sector_count Count of sectors for the persistant environment storage
+ * @return 0 on success
+ */
+static int store_pers_env_info(void *patch_area, uint64_t pers_sector_start, long pers_sector_count)
+{
+ uint64_t *start_lba = (uint64_t*)(patch_area + PATCH_AREA_PERS_START);
+ uint16_t *count_lba = (uint16_t*)(patch_area + PATCH_AREA_PERS_SIZE);
+
+ assert(patch_area != NULL);
+ assert(pers_sector_count >= 0);
+
+ if (pers_sector_count == 0) {
+ *count_lba = host2target_16(PATCH_AREA_PERS_SIZE_UNUSED);
+ return 0;
+ }
+
+ *start_lba = host2target_64(pers_sector_start);
+ *count_lba = host2target_16(pers_sector_count);
+
+ return 0;
+}
+
+/**
+ * Prepare the MBR and indirect sector for runtime
+ * @param fd_barebox barebox image to use
+ * @param fd_hd Hard disk image to prepare
+ * @param pers_sector_count Count of sectors to skip after MBR for the persistant environment storage
+ * @return 0 on success
+ *
+ * This routine expects a prepared hard disk image file with a partition table
+ * in its first sector. This method only is currently supported.
+ */
+static int barebox_overlay_mbr(int fd_barebox, int fd_hd, long pers_sector_count)
+{
+ const void *barebox_image;
+ void *hd_image;
+ int rc;
+ struct stat sb;
+ struct DAPS *embed; /* part of the MBR */
+ struct DAPS *indirect; /* sector with indirect DAPS */
+ off_t required_size;
+
+ if (fstat(fd_barebox, &sb) == -1) {
+ perror("fstat");
+ return -1;
+ }
+
+ /* the barebox image won't be touched */
+ barebox_image = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd_barebox, 0);
+ if (barebox_image == MAP_FAILED) {
+ perror("mmap");
+ return -1;
+ }
+
+ rc = check_for_valid_mbr(barebox_image, sb.st_size);
+ if (rc != 0) {
+ fprintf(stderr, "barebox image seems not valid: Bad MBR signature\n");
+ goto on_error_hd;
+ }
+
+ /*
+ * the persistant environment storage is in front of the main
+ * barebox image. To handle both, we need more space in front of the
+ * the first partition.
+ */
+ required_size = sb.st_size + pers_sector_count * SECTOR_SIZE;
+
+ /* the hd image will be modified */
+ hd_image = mmap(NULL, required_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd_hd, 0);
+ if (hd_image == MAP_FAILED) {
+ perror("mmap");
+ rc = -1;
+ goto on_error_hd;
+ }
+
+ /* check for space */
+ rc = check_for_space(hd_image, required_size);
+ if (rc != 0)
+ goto on_error_space;
+
+ /* embed barebox's boot code into the disk drive image */
+ memcpy(hd_image, barebox_image, OFFSET_OF_PARTITION_TABLE);
+
+ /*
+ * embed the barebox main image into the disk drive image,
+ * but keep the persistant environment storage untouched
+ * (if defined), e.g. store the main image behind this special area.
+ */
+ memcpy(hd_image + ((pers_sector_count + 1) * SECTOR_SIZE),
+ barebox_image + SECTOR_SIZE, sb.st_size - SECTOR_SIZE);
+
+ /* now, prepare this hard disk image for BIOS based booting */
+ embed = hd_image + PATCH_AREA;
+ indirect = hd_image + ((pers_sector_count + 1) * SECTOR_SIZE);
+
+ /*
+ * Fill the embedded DAPS to let the basic boot code find the
+ * indirect sector at runtime
+ */
+#ifdef DEBUG
+ printf("Debug: Fill in embedded DAPS\n");
+#endif
+ rc = fill_daps(embed, 1, INDIRECT_AREA, INDIRECT_SEGMENT,
+ 1 + pers_sector_count);
+ if (rc != 0)
+ goto on_error_space;
+ debugout(embed, 1);
+
+#ifdef DEBUG
+ printf("Debug: Fill in indirect sector\n");
+#endif
+ /*
+ * fill the indirect sector with the remaining DAPS to load the
+ * whole barebox image at runtime
+ */
+ rc = barebox_linear_image(indirect, sb.st_size, pers_sector_count);
+ if (rc != 0)
+ goto on_error_space;
+
+ /*
+ * TODO: Replace the fixed LBA starting number by a calculated one,
+ * to support barebox as a chained loader in a different start
+ * sector than the MBR
+ */
+ rc = store_pers_env_info(embed, 1, pers_sector_count);
+ if (rc != 0)
+ goto on_error_space;
+
+on_error_space:
+ munmap(hd_image, required_size);
+
+on_error_hd:
+ munmap((void*)barebox_image, sb.st_size);
+
+ return rc;
+}
+
+static void print_usage(const char *pname)
+{
+ printf("%s: Preparing a hard disk image for boot with barebox on x86.\n", pname);
+ printf("Usage is\n %s [options] -m <barebox image> -d <hd image>\n", pname);
+ printf(" [options] are:\n -s <count> sector count of the persistant environment storage\n");
+ printf(" <barebox image> barebox's boot image file\n");
+ printf(" <hd image> HD image to store the barebox image\n");
+ printf(" If no '-s <x>' was given, barebox occupies sectors 0 to n, else sector 0 and x+1 to n\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int rc = 0, c;
+ char *barebox_image_filename = NULL, *hd_image_filename = NULL;
+ int fd_barebox_image = 0, fd_hd_image = 0;
+ long barebox_pers_size = -1;
+
+ if (argc == 1) {
+ print_usage(argv[0]);
+ exit(0);
+ }
+
+ /* handle command line options first */
+ while (1) {
+ c = getopt(argc, argv, "m:d:s:hv");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 's':
+ barebox_pers_size = strtol(optarg, NULL, 0);
+ break;
+ case 'm':
+ barebox_image_filename = strdup(optarg);
+ break;
+ case 'd':
+ hd_image_filename = strdup(optarg);
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ rc = 0;
+ goto on_error;
+ case 'v':
+ printf("setupmbr for u-boot-v%s\n", UTS_RELEASE);
+ printf("Send bug reports to 'barebox@lists.infradead.org'\n");
+ rc = 0;
+ goto on_error;
+ }
+ }
+
+ if (barebox_image_filename == NULL) {
+ print_usage(argv[0]);
+ rc = -1;
+ goto on_error;
+ }
+
+ fd_barebox_image = open(barebox_image_filename, O_RDONLY);
+ if (fd_barebox_image == -1) {
+ fprintf(stderr, "Cannot open '%s' for reading\n",
+ barebox_image_filename);
+ rc = -1;
+ goto on_error;
+ }
+
+ fd_hd_image = open(hd_image_filename, O_RDWR);
+ if (fd_hd_image == -1) {
+ fprintf(stderr, "Cannot open '%s'\n", hd_image_filename);
+ rc = -1;
+ goto on_error;
+ }
+
+ if (barebox_pers_size < 0)
+ barebox_pers_size = 0;
+
+ rc = barebox_overlay_mbr(fd_barebox_image, fd_hd_image, barebox_pers_size);
+
+on_error:
+ if (fd_barebox_image != -1)
+ close(fd_barebox_image);
+ if (fd_hd_image != -1)
+ close(fd_hd_image);
+
+ if (barebox_image_filename != NULL)
+ free(barebox_image_filename);
+ if (hd_image_filename != NULL)
+ free(hd_image_filename);
+
+ return rc;
+}
+
+/** @page x86_bootloader barebox acting as PC bootloader
+
+@section x86_bootloader_features Features
+
+@a barebox can act as a bootloader for PC based systems. In this case a special
+binary layout will be created to be able to store it on some media the PC
+BIOS can boot from. It can boot Linux kernels stored also on the same boot
+media and be configured at runtime, with the possibility to store the changed
+configuration on the boot media.
+
+@section x86_bootloader_restrictions Restrictions
+
+Due to some BIOS and @a barebox restrictions the boot media must be
+prepared in some special way:
+
+@li @a barebox must be stored in the MBR (Master Boot Record) of the boot media.
+ Currently its not possible to store and boot it in one of the partition
+ sectors (to use it as a second stage loader). This is no eternal
+ restriction. It only needs further effort to add this feature.
+@li @a barebox currently cannot run a chained boot loader. Also, this is no
+ eternal restriction, only further effort needed.
+@li @a barebox comes with limited filesystem support. There is currently no
+ support for the most common and popular filesystems used in the *NIX world.
+ This restricts locations where to store a kernel and other runtime
+ information
+@li @a barebox must be stored to the first n sectors of the boot media. To ensure
+ this does not collide with partitions on the boot media, the first
+ partition must start at a sector behind the ones @a barebox occupies.
+@li @a barebox handles its runtime configuration in a special way: It stores it
+ in a binary way into some reserved sectors ("persistant storage").
+
+@section x86_bootloader_preparations Boot Preparations
+
+To store the @a barebox image to a boot media, it comes with the tool
+@p setupmbr in the directory @p scripts/setupmbr/ . To be able to use it on
+the boot media of your choice, some preparations are required:
+
+@subsection x86_bootloader_preparations_partition Keep Sectors free
+
+Build the @a barebox image and check its size. At least this amount of
+sectors must be kept free after the MBR prior the first partition. Do this
+simple calulation:
+
+ sectors = (\<size of barebox image\> + 511) / 512
+
+To be able to store the runtime configuration, further free sectors are
+required. Its up to you and your requirements, how large this persistant
+storage must be. If you need 16 kiB for this purpose, you need to keep
+additional 32 sectors free.
+
+For this example we are reserving 300 sectors for the @a barebox image and
+additionaly 32 sectors for the persistant storage. So, the first partition on
+the boot media must start at sector 333 or later.
+
+Run the @p fdisk tool to setup such a partition table:
+
+@verbatim
+[jb@host]~> fdisk /dev/sda
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders
+Units = cylinders of 1008 * 512 = 516096 bytes
+
+ Device Boot Start End Blocks Id System
+@endverbatim
+
+Change the used units to @p sectors for easier handling.
+
+@verbatim
+Command (m for help): u
+Changing display/entry units to sectors
+
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders, total 409248 sectors
+Units = sectors of 1 * 512 = 512 bytes
+
+ Device Boot Start End Blocks Id System
+@endverbatim
+
+Now its possible to create the first partition with the required offset:
+
+@verbatim
+Command (m for help): n
+Command action
+ e extended
+ p primary partition (1-4)
+p
+Partition number (1-4): 1
+First sector (63-409247, default 63): 333
+Last sector or +size or +sizeM or +sizeK (333-409247, default 409247): +18M
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders, total 409248 sectors
+Units = sectors of 1 * 512 = 512 bytes
+
+ Device Boot Start End Blocks Id System
+/dev/sda 333 35489 17578+ 83 Linux
+@endverbatim
+
+That's all. Do whatever is required now with the new partition (formatting
+and populating the root filesystem for example) to make it useful.
+
+In the next step, @a barebox gets installed to this boot media:
+
+@verbatim
+[jb@host]~> scripts/setupmbr/setupmbr -s 32 -m ./barebox -d /dev/sda
+@endverbatim
+
+This command writes the @a barebox image file './barebox' onto the device
+@p /dev/sda.
+
+The @p -s option will keep the persistant storage sectors free and untouched
+and set flags in the MBR to forward its existance, size and location to
+@a barebox at runtime. @p setupmbr also does not change the partition table.
+
+The @a barebox image gets stored on the boot media like this:
+
+@verbatim
+sector 0 1 33 333
+ |---|-------------|--------------- ~~~ ------------|--------------
+ MBR persistant barebox first
+ storage main image partition
+@endverbatim
+
+If the @p -s option is omitted, the "persistant storage" part simply does
+not exist:
+
+@verbatim
+sector 0 1 333
+ |---|--------------- ~~~ ------------|--------------
+ MBR barebox first
+ main image partition
+@endverbatim
+
+@note The @p setupmbr tool is also working on real image file than on device
+ nodes only. So, there is no restriction what kind of file will be
+ modified.
+*/