[PATCH] add-mmc.c-and-other-file-but-can-not-boot-from-sd

xiangfu xiangfu at openmoko.org
Sat Aug 16 18:43:17 CEST 2008


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

this is just add some files we may use.
copy from u-boot

Signed-off-by: xiangfu <xiangfu at openmoko.org>
- ---
 src/calc_pclk.c |   78 +++++++
 src/common.h    |  681
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/fat.h       |  220 ++++++++++++++++++
 src/io.h        |  337 +++++++++++++++++++++++++++
 src/mmc.c       |  538 +++++++++++++++++++++++++++++++++++++++++++
 src/mmc.h       |   33 +++
 src/part.h      |  138 +++++++++++
 7 files changed, 2025 insertions(+), 0 deletions(-)
 create mode 100644 src/calc_pclk.c
 create mode 100644 src/common.h
 create mode 100644 src/fat.h
 create mode 100644 src/io.h
 create mode 100644 src/mmc.c
 create mode 100644 src/mmc.h
 create mode 100644 src/part.h

diff --git a/src/calc_pclk.c b/src/calc_pclk.c
new file mode 100644
index 0000000..777ad03
- --- /dev/null
+++ b/src/calc_pclk.c
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2007 OpenMoko, Inc.
+ * Author: xiangfu liu <xiangfu at openmoko.org>
+ *
+ *
+ * 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
+ */
+
+/* NOTE this code is not good, some define is
+ * is already show in other files
+ */
+
+# define CLKDIVN_val    (7)
+# define CAMDIVN_val    (0)
+# define CONFIG_SYS_CLK_FREQ  (12000000)/* the GTA02 has this input
clock */
+
+# define MPLL    ((142 << 12) + (7 << 4) + 1)
+# define BAUDRATE    	(115200)
+
+typedef unsigned long   ulong;
+
+static ulong get_PLLCLK(int pllreg)
+{
+  ulong r, m, p, s;
+
+  if (pllreg == MPLL){
+    r = MPLL;
+  }
+
+  m = ((r & 0xFF000) >> 12) + 8;
+  p = ((r & 0x003F0) >> 4) + 2;
+  s = r & 0x3;
+  /* To avoid integer overflow, changed the calc order */
+  if (pllreg == MPLL)
+    return ( 2 * m * (CONFIG_SYS_CLK_FREQ / (p << s )) );
+  else
+    return ( m * (CONFIG_SYS_CLK_FREQ / (p << s )) );
+}
+
+ulong get_FCLK(void)
+{
+  return(get_PLLCLK(MPLL));
+}
+
+
+ulong get_HCLK(void)
+{
+  switch (CLKDIVN_val & 0x6) {
+  case 0x0:
+    return get_FCLK();
+  case 0x2:
+    return get_FCLK()/2;
+  case 0x4:
+    return (CAMDIVN_val & 0x200) ? get_FCLK()/8 : get_FCLK()/4;
+  case 0x6:
+    return (CAMDIVN_val & 0x100) ? get_FCLK()/6 : get_FCLK()/3;
+  }
+  return 0;
+}
+
+ulong get_PCLK(void)
+{
+  return((CLKDIVN_val & 0x1) ? get_HCLK()/2 : get_HCLK());
+}
+
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..055dec2
- --- /dev/null
+++ b/src/common.h
@@ -0,0 +1,681 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.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
+ */
+
+#ifndef __COMMON_H_
+#define __COMMON_H_	1
+
+#undef	_LINUX_CONFIG_H
+#define _LINUX_CONFIG_H 1	/* avoid reading Linux autoconf.h file	*/
+
+typedef unsigned char		uchar;
+typedef volatile unsigned long	vu_long;
+typedef volatile unsigned short vu_short;
+typedef volatile unsigned char	vu_char;
+
+#include <config.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/ptrace.h>
+#include <stdarg.h>
+#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
+#include <pci.h>
+#endif
+#if defined(CONFIG_8xx)
+#include <asm/8xx_immap.h>
+#if defined(CONFIG_MPC852)	|| defined(CONFIG_MPC852T)	|| \
+    defined(CONFIG_MPC859)	|| defined(CONFIG_MPC859T)	|| \
+    defined(CONFIG_MPC859DSL)	|| \
+    defined(CONFIG_MPC866)	|| defined(CONFIG_MPC866T)	|| \
+    defined(CONFIG_MPC866P)
+# define CONFIG_MPC866_FAMILY 1
+#elif defined(CONFIG_MPC870) \
+   || defined(CONFIG_MPC875) \
+   || defined(CONFIG_MPC880) \
+   || defined(CONFIG_MPC885)
+# define CONFIG_MPC885_FAMILY   1
+#endif
+#if   defined(CONFIG_MPC860)	   \
+   || defined(CONFIG_MPC860T)	   \
+   || defined(CONFIG_MPC866_FAMILY) \
+   || defined(CONFIG_MPC885_FAMILY)
+# define CONFIG_MPC86x 1
+#endif
+#elif defined(CONFIG_5xx)
+#include <asm/5xx_immap.h>
+#elif defined(CONFIG_MPC5xxx)
+#include <mpc5xxx.h>
+#elif defined(CONFIG_MPC512X)
+#include <mpc512x.h>
+#include <asm/immap_512x.h>
+#elif defined(CONFIG_MPC8220)
+#include <asm/immap_8220.h>
+#elif defined(CONFIG_8260)
+#if   defined(CONFIG_MPC8247) \
+   || defined(CONFIG_MPC8248) \
+   || defined(CONFIG_MPC8271) \
+   || defined(CONFIG_MPC8272)
+#define CONFIG_MPC8272_FAMILY	1
+#endif
+#if defined(CONFIG_MPC8272_FAMILY)
+#define CONFIG_MPC8260	1
+#endif
+#include <asm/immap_8260.h>
+#endif
+#ifdef CONFIG_MPC86xx
+#include <mpc86xx.h>
+#include <asm/immap_86xx.h>
+#endif
+#ifdef CONFIG_MPC85xx
+#include <mpc85xx.h>
+#include <asm/immap_85xx.h>
+#endif
+#ifdef CONFIG_MPC83XX
+#include <mpc83xx.h>
+#include <asm/immap_83xx.h>
+#endif
+#ifdef	CONFIG_4xx
+#include <ppc4xx.h>
+#endif
+#ifdef CONFIG_HYMOD
+#include <board/hymod/hymod.h>
+#endif
+#ifdef CONFIG_ARM
+#define asmlinkage	/* nothing */
+#endif
+#ifdef CONFIG_BLACKFIN
+#include <asm/blackfin.h>
+#endif
+
+#include <part.h>
+#include <flash.h>
+#include <image.h>
+
+#ifdef	DEBUG
+#define debug(fmt,args...)	printf (fmt ,##args)
+#define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);
+#else
+#define debug(fmt,args...)
+#define debugX(level,fmt,args...)
+#endif	/* DEBUG */
+
+#define BUG() do { \
+	printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
__FUNCTION__); \
+	panic("BUG!"); \
+} while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); }
while(0)
+
+typedef void (interrupt_handler_t)(void *);
+
+#include <asm/u-boot.h> /* boot information for Linux kernel */
+#include <asm/global_data.h>	/* global data used for startup functions */
+
+/*
+ * enable common handling for all TQM8xxL/M boards:
+ * - CONFIG_TQM8xxM will be defined for all TQM8xxM boards
+ * - CONFIG_TQM8xxL will be defined for all TQM8xxL _and_ TQM8xxM boards
+ *                  and for the TQM885D board
+ */
+#if defined(CONFIG_TQM823M) || defined(CONFIG_TQM850M) || \
+    defined(CONFIG_TQM855M) || defined(CONFIG_TQM860M) || \
+    defined(CONFIG_TQM862M) || defined(CONFIG_TQM866M)
+# ifndef CONFIG_TQM8xxM
+#  define CONFIG_TQM8xxM
+# endif
+#endif
+#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \
+    defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L) || \
+    defined(CONFIG_TQM862L) || defined(CONFIG_TQM8xxM) || \
+    defined(CONFIG_TQM885D)
+# ifndef CONFIG_TQM8xxL
+#  define CONFIG_TQM8xxL
+# endif
+#endif
+
+#ifndef CONFIG_SERIAL_MULTI
+
+#if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2) \
+ || defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \
+ || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+
+#define CONFIG_SERIAL_MULTI	1
+
+#endif
+
+#endif /* CONFIG_SERIAL_MULTI */
+
+/*
+ * General Purpose Utilities
+ */
+#define min(X, Y)				\
+	({ typeof (X) __x = (X), __y = (Y);	\
+		(__x < __y) ? __x : __y; })
+
+#define max(X, Y)				\
+	({ typeof (X) __x = (X), __y = (Y);	\
+		(__x > __y) ? __x : __y; })
+
+
+/*
+ * Function Prototypes
+ */
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+void	serial_buffered_init (void);
+void	serial_buffered_putc (const char);
+void	serial_buffered_puts (const char *);
+int	serial_buffered_getc (void);
+int	serial_buffered_tstc (void);
+#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
+
+void	hang		(void) __attribute__ ((noreturn));
+
+/* */
+long int initdram (int);
+int	display_options (void);
+void	print_size (ulong, const char *);
+int	print_buffer (ulong addr, void* data, uint width, uint count, uint
linelen);
+
+/* common/main.c */
+void	main_loop	(void);
+int	run_command	(const char *cmd, int flag);
+int	readline	(const char *const prompt);
+int	readline_into_buffer	(const char *const prompt, char * buffer);
+int	parse_line (char *, char *[]);
+void	init_cmd_timeout(void);
+void	reset_cmd_timeout(void);
+
+/* lib_$(ARCH)/board.c */
+void	board_init_f  (ulong) __attribute__ ((noreturn));
+void	board_init_r  (gd_t *, ulong) __attribute__ ((noreturn));
+int	checkboard    (void);
+int	checkflash    (void);
+int	checkdram     (void);
+char *	strmhz(char *buf, long hz);
+int	last_stage_init(void);
+extern ulong monitor_flash_len;
+#ifdef CFG_ID_EEPROM
+int mac_read_from_eeprom(void);
+#endif
+
+/* common/flash.c */
+void flash_perror (int);
+
+/* common/cmd_autoscript.c */
+int	autoscript (ulong addr, const char *fit_uname);
+
+extern ulong load_addr;		/* Default Load Address */
+
+/* common/cmd_nvedit.c */
+int	env_init     (void);
+void	env_relocate (void);
+int	envmatch     (uchar *, int);
+char	*getenv	     (char *);
+int	getenv_r     (char *name, char *buf, unsigned len);
+int	saveenv	     (void);
+#ifdef CONFIG_PPC		/* ARM version to be fixed! */
+void inline setenv   (char *, char *);
+#else
+void	setenv	     (char *, char *);
+#ifdef CONFIG_HAS_UID
+void	forceenv     (char *, char *);
+#endif
+#endif /* CONFIG_PPC */
+#ifdef CONFIG_ARM
+# include <asm/mach-types.h>
+# include <asm/setup.h>
+# include <asm/u-boot-arm.h>	/* ARM version to be fixed! */
+#endif /* CONFIG_ARM */
+#ifdef CONFIG_I386		/* x86 version to be fixed! */
+# include <asm/u-boot-i386.h>
+#endif /* CONFIG_I386 */
+
+#ifdef CONFIG_AUTO_COMPLETE
+int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf);
+#endif
+
+void	pci_init      (void);
+void	pci_init_board(void);
+void	pciinfo	      (int, int);
+
+#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
+    int	   pci_pre_init	       (struct pci_controller * );
+#endif
+
+#if defined(CONFIG_PCI) && (defined(CONFIG_440) || defined(CONFIG_405EX))
+#   if defined(CFG_PCI_TARGET_INIT)
+	void	pci_target_init	     (struct pci_controller *);
+#   endif
+#   if defined(CFG_PCI_MASTER_INIT)
+	void	pci_master_init	     (struct pci_controller *);
+#   endif
+    int	    is_pci_host		(struct pci_controller *);
+#if defined(CONFIG_440SPE) || \
+    defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+    defined(CONFIG_405EX)
+   void pcie_setup_hoses(int busno);
+#endif
+#endif
+
+int	misc_init_f   (void);
+int	misc_init_r   (void);
+
+/* common/exports.c */
+void	jumptable_init(void);
+
+/* api/api.c */
+void	api_init (void);
+
+/* common/memsize.c */
+long	get_ram_size  (volatile long *, long);
+
+/* $(BOARD)/$(BOARD).c */
+void	reset_phy     (void);
+void	fdc_hw_init   (void);
+
+/* $(BOARD)/eeprom.c */
+void eeprom_init  (void);
+#ifndef CONFIG_SPI
+int  eeprom_probe (unsigned dev_addr, unsigned offset);
+#endif
+int  eeprom_read  (unsigned dev_addr, unsigned offset, uchar *buffer,
unsigned cnt);
+int  eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer,
unsigned cnt);
+#ifdef CONFIG_LWMON
+extern uchar pic_read  (uchar reg);
+extern void  pic_write (uchar reg, uchar val);
+#endif
+
+/*
+ * Set this up regardless of board
+ * type, to prevent errors.
+ */
+#if defined(CONFIG_SPI) || !defined(CFG_I2C_EEPROM_ADDR)
+# define CFG_DEF_EEPROM_ADDR 0
+#else
+# define CFG_DEF_EEPROM_ADDR CFG_I2C_EEPROM_ADDR
+#endif /* CONFIG_SPI || !defined(CFG_I2C_EEPROM_ADDR) */
+
+#if defined(CONFIG_SPI)
+extern void spi_init_f (void);
+extern void spi_init_r (void);
+extern ssize_t spi_read	 (uchar *, int, uchar *, int);
+extern ssize_t spi_write (uchar *, int, uchar *, int);
+#endif
+
+#ifdef CONFIG_RPXCLASSIC
+void rpxclassic_init (void);
+#endif
+
+void rpxlite_init (void);
+
+#ifdef CONFIG_MBX
+/* $(BOARD)/mbx8xx.c */
+void	mbx_init (void);
+void	board_serial_init (void);
+void	board_ether_init (void);
+#endif
+
+#if defined(CONFIG_RPXCLASSIC)	|| defined(CONFIG_MBX) || \
+    defined(CONFIG_IAD210)	|| defined(CONFIG_XPEDITE1K) || \
+    defined(CONFIG_METROBOX)    || defined(CONFIG_KAREF) || \
+    defined(CONFIG_V38B)
+void	board_get_enetaddr (uchar *addr);
+#endif
+
+#ifdef CONFIG_HERMES
+/* $(BOARD)/hermes.c */
+void hermes_start_lxt980 (int speed);
+#endif
+
+#ifdef CONFIG_EVB64260
+void  evb64260_init(void);
+void  debug_led(int, int);
+void  display_mem_map(void);
+void  perform_soft_reset(void);
+#endif
+
+void	load_sernum_ethaddr (void);
+
+/* $(BOARD)/$(BOARD).c */
+int board_early_init_f (void);
+int board_late_init (void);
+int board_postclk_init (void); /* after clocks/timebase, before
env/serial */
+int board_early_init_r (void);
+void board_poweroff (void);
+
+#if defined(CFG_DRAM_TEST)
+int testdram(void);
+#endif /* CFG_DRAM_TEST */
+
+/* $(CPU)/start.S */
+#if defined(CONFIG_5xx) || \
+    defined(CONFIG_8xx)
+uint	get_immr      (uint);
+#endif
+uint	get_pir	      (void);
+#if defined(CONFIG_MPC5xxx)
+uint	get_svr       (void);
+#endif
+uint	get_pvr	      (void);
+uint	get_svr	      (void);
+uint	rd_ic_cst     (void);
+void	wr_ic_cst     (uint);
+void	wr_ic_adr     (uint);
+uint	rd_dc_cst     (void);
+void	wr_dc_cst     (uint);
+void	wr_dc_adr     (uint);
+int	icache_status (void);
+void	icache_enable (void);
+void	icache_disable(void);
+int	dcache_status (void);
+void	dcache_enable (void);
+void	dcache_disable(void);
+void	relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn));
+ulong	get_endaddr   (void);
+void	trap_init     (ulong);
+#if defined (CONFIG_4xx)	|| \
+    defined (CONFIG_MPC5xxx)	|| \
+    defined (CONFIG_74xx_7xx)	|| \
+    defined (CONFIG_74x)	|| \
+    defined (CONFIG_75x)	|| \
+    defined (CONFIG_74xx)	|| \
+    defined (CONFIG_MPC8220)	|| \
+    defined (CONFIG_MPC85xx)	|| \
+    defined (CONFIG_MPC86xx)	|| \
+    defined (CONFIG_MPC83XX)
+unsigned char	in8(unsigned int);
+void		out8(unsigned int, unsigned char);
+unsigned short	in16(unsigned int);
+unsigned short	in16r(unsigned int);
+void		out16(unsigned int, unsigned short value);
+void		out16r(unsigned int, unsigned short value);
+unsigned long	in32(unsigned int);
+unsigned long	in32r(unsigned int);
+void		out32(unsigned int, unsigned long value);
+void		out32r(unsigned int, unsigned long value);
+void		ppcDcbf(unsigned long value);
+void		ppcDcbi(unsigned long value);
+void		ppcSync(void);
+void		ppcDcbz(unsigned long value);
+#endif
+#if defined (CONFIG_MICROBLAZE)
+unsigned short	in16(unsigned int);
+void		out16(unsigned int, unsigned short value);
+#endif
+
+#if defined (CONFIG_MPC83XX)
+void		ppcDWload(unsigned int *addr, unsigned int *ret);
+void		ppcDWstore(unsigned int *addr, unsigned int *value);
+#endif
+
+/* $(CPU)/cpu.c */
+int	checkcpu      (void);
+int	checkicache   (void);
+int	checkdcache   (void);
+void	upmconfig     (unsigned int, unsigned int *, unsigned int);
+ulong	get_tbclk     (void);
+void	reset_cpu     (ulong addr);
+#if defined (CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
+void ft_cpu_setup(void *blob, bd_t *bd);
+#ifdef CONFIG_PCI
+void ft_pci_setup(void *blob, bd_t *bd);
+#endif
+#endif
+
+
+/* $(CPU)/serial.c */
+int	serial_init   (void);
+void	serial_addr   (unsigned int);
+void	serial_setbrg (void);
+void	serial_putc   (const char);
+void	serial_putc_raw(const char);
+void	serial_puts   (const char *);
+int	serial_getc   (void);
+int	serial_tstc   (void);
+
+void	_serial_setbrg (const int);
+void	_serial_putc   (const char, const int);
+void	_serial_putc_raw(const char, const int);
+void	_serial_puts   (const char *, const int);
+int	_serial_getc   (const int);
+int	_serial_tstc   (const int);
+
+/* $(CPU)/speed.c */
+int	get_clocks (void);
+int	get_clocks_866 (void);
+int	sdram_adjust_866 (void);
+int	adjust_sdram_tbs_8xx (void);
+#if defined(CONFIG_8260)
+int	prt_8260_clks (void);
+#elif defined(CONFIG_MPC5xxx)
+int	prt_mpc5xxx_clks (void);
+#endif
+#if defined(CONFIG_MPC512X)
+int	prt_mpc512xxx_clks (void);
+#endif
+#if defined(CONFIG_MPC8220)
+int	prt_mpc8220_clks (void);
+#endif
+#ifdef CONFIG_4xx
+ulong	get_OPB_freq (void);
+ulong	get_PCI_freq (void);
+#endif
+#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || \
+    defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
+    defined(CONFIG_LH7A40X)
+void	s3c2410_irq(void);
+#define ARM920_IRQ_CALLBACK s3c2410_irq
+ulong	get_FCLK (void);
+ulong	get_HCLK (void);
+ulong	get_PCLK (void);
+ulong	get_UCLK (void);
+#endif
+#if defined(CONFIG_LH7A40X)
+ulong	get_PLLCLK (void);
+#endif
+#if defined CONFIG_INCA_IP
+uint	incaip_get_cpuclk (void);
+#endif
+#if defined(CONFIG_IMX)
+ulong get_systemPLLCLK(void);
+ulong get_FCLK(void);
+ulong get_HCLK(void);
+ulong get_BCLK(void);
+ulong get_PERCLK1(void);
+ulong get_PERCLK2(void);
+ulong get_PERCLK3(void);
+#endif
+ulong	get_bus_freq  (ulong);
+
+#if defined(CONFIG_MPC85xx)
+typedef MPC85xx_SYS_INFO sys_info_t;
+void	get_sys_info  ( sys_info_t * );
+ulong	get_ddr_freq  (ulong);
+#endif
+#if defined(CONFIG_MPC86xx)
+typedef MPC86xx_SYS_INFO sys_info_t;
+void   get_sys_info  ( sys_info_t * );
+#endif
+
+#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)
+#  if defined(CONFIG_440)
+#	if defined(CONFIG_440SPE)
+	 unsigned long determine_sysper(void);
+	 unsigned long determine_pci_clock_per(void);
+#	endif
+#  endif
+typedef PPC4xx_SYS_INFO sys_info_t;
+int	ppc440spe_revB(void);
+void	get_sys_info  ( sys_info_t * );
+#endif
+
+/* $(CPU)/cpu_init.c */
+#if defined(CONFIG_8xx) || defined(CONFIG_8260)
+void	cpu_init_f    (volatile immap_t *immr);
+#endif
+#if defined(CONFIG_4xx) || defined(CONFIG_MPC85xx) ||
defined(CONFIG_MCF52x2) ||defined(CONFIG_MPC86xx)
+void	cpu_init_f    (void);
+#endif
+
+int	cpu_init_r    (void);
+#if defined(CONFIG_8260)
+int	prt_8260_rsr  (void);
+#elif defined(CONFIG_MPC83XX)
+int	prt_83xx_rsr  (void);
+#endif
+
+/* $(CPU)/interrupts.c */
+int	interrupt_init	   (void);
+void	timer_interrupt	   (struct pt_regs *);
+void	external_interrupt (struct pt_regs *);
+void	irq_install_handler(int, interrupt_handler_t *, void *);
+void	irq_free_handler   (int);
+void	reset_timer	   (void);
+ulong	get_timer	   (ulong base);
+void	set_timer	   (ulong t);
+void	enable_interrupts  (void);
+int	disable_interrupts (void);
+
+/* $(CPU)/.../commproc.c */
+int	dpram_init (void);
+uint	dpram_base(void);
+uint	dpram_base_align(uint align);
+uint	dpram_alloc(uint size);
+uint	dpram_alloc_align(uint size,uint align);
+void	post_word_store (ulong);
+ulong	post_word_load (void);
+void	bootcount_store (ulong);
+ulong	bootcount_load (void);
+#define BOOTCOUNT_MAGIC		0xB001C041
+
+/* $(CPU)/.../<eth> */
+void mii_init (void);
+
+/* $(CPU)/.../lcd.c */
+ulong	lcd_setmem (ulong);
+
+/* $(CPU)/.../vfd.c */
+ulong	vfd_setmem (ulong);
+
+/* $(CPU)/.../video.c */
+ulong	video_setmem (ulong);
+
+/* lib_$(ARCH)/cache.c */
+void	flush_cache   (unsigned long, unsigned long);
+
+
+/* lib_$(ARCH)/ticks.S */
+unsigned long long get_ticks(void);
+void	wait_ticks    (unsigned long);
+
+/* lib_$(ARCH)/time.c */
+void	udelay	      (unsigned long);
+ulong	usec2ticks    (unsigned long usec);
+ulong	ticks2usec    (unsigned long ticks);
+int	init_timebase (void);
+
+/* lib_generic/vsprintf.c */
+ulong	simple_strtoul(const char *cp,char **endp,unsigned int base);
+#ifdef CFG_64BIT_VSPRINTF
+unsigned long long	simple_strtoull(const char *cp,char **endp,unsigned
int base);
+#endif
+long	simple_strtol(const char *cp,char **endp,unsigned int base);
+void	panic(const char *fmt, ...);
+int	sprintf(char * buf, const char *fmt, ...);
+int	vsprintf(char *buf, const char *fmt, va_list args);
+
+/* lib_generic/crc32.c */
+ulong crc32 (ulong, const unsigned char *, uint);
+ulong crc32_no_comp (ulong, const unsigned char *, uint);
+
+/* common/console.c */
+int	console_init_f(void);	/* Before relocation; uses the serial  stuff	*/
+int	console_init_r(void);	/* After  relocation; uses the console stuff	*/
+int	console_assign (int file, char *devname);	/* Assign the console	*/
+int	ctrlc (void);
+int	had_ctrlc (void);	/* have we had a Control-C since last clear? */
+void	clear_ctrlc (void);	/* clear the Control-C condition */
+int	disable_ctrlc (int);	/* 1 to disable, 0 to enable Control-C detect */
+
+/*
+ * STDIO based functions (can always be used)
+ */
+
+/* serial stuff */
+void	serial_printf (const char *fmt, ...);
+
+/* stdin */
+int	getc(void);
+int	tstc(void);
+
+/* stdout */
+void	putc(const char c);
+void	puts(const char *s);
+void	printf(const char *fmt, ...);
+void	vprintf(const char *fmt, va_list args);
+
+/* stderr */
+#define eputc(c)		fputc(stderr, c)
+#define eputs(s)		fputs(stderr, s)
+#define eprintf(fmt,args...)	fprintf(stderr,fmt ,##args)
+
+/*
+ * FILE based functions (can only be used AFTER relocation!)
+ */
+
+#define stdin		0
+#define stdout		1
+#define stderr		2
+#define MAX_FILES	3
+
+void	fprintf(int file, const char *fmt, ...);
+void	fputs(int file, const char *s);
+void	fputc(int file, const char c);
+int	ftstc(int file);
+int	fgetc(int file);
+
+int	pcmcia_init (void);
+
+#ifdef CONFIG_STATUS_LED
+# include <status_led.h>
+#endif
+/*
+ * Board-specific Platform code can reimplement show_boot_progress ()
if needed
+ */
+void inline show_boot_progress (int val);
+
+#ifdef CONFIG_INIT_CRITICAL
+#error CONFIG_INIT_CRITICAL is deprecated!
+#error Read section CONFIG_SKIP_LOWLEVEL_INIT in README.
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Multicore arch functions */
+#ifdef CONFIG_MP
+int cpu_status(int nr);
+int cpu_reset(int nr);
+int cpu_release(int nr, int argc, char *argv[]);
+#endif
+
+#endif	/* __COMMON_H_ */
diff --git a/src/fat.h b/src/fat.h
new file mode 100644
index 0000000..f993cca
- --- /dev/null
+++ b/src/fat.h
@@ -0,0 +1,220 @@
+/*
+ * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
+ *
+ * 2002-07-28 - rjones at nexus-tech.net - ported to ppcboot v1.1.6
+ * 2003-03-10 - kharris at nexus-tech.net - ported to u-boot
+ *
+ * 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 _FAT_H_
+#define _FAT_H_
+
+#include <asm/byteorder.h>
+
+#define CONFIG_SUPPORT_VFAT
+
+#define SECTOR_SIZE FS_BLOCK_SIZE
+
+#define FS_BLOCK_SIZE 512
+
+#if FS_BLOCK_SIZE != SECTOR_SIZE
+#error FS_BLOCK_SIZE != SECTOR_SIZE - This code needs to be fixed!
+#endif
+
+#define MAX_CLUSTSIZE	65536
+#define DIRENTSPERBLOCK	(FS_BLOCK_SIZE/sizeof(dir_entry))
+#define DIRENTSPERCLUST
((mydata->clust_size*SECTOR_SIZE)/sizeof(dir_entry))
+
+#define FATBUFBLOCKS	6
+#define FATBUFSIZE	(FS_BLOCK_SIZE*FATBUFBLOCKS)
+#define FAT12BUFSIZE	((FATBUFSIZE*2)/3)
+#define FAT16BUFSIZE	(FATBUFSIZE/2)
+#define FAT32BUFSIZE	(FATBUFSIZE/4)
+
+
+/* Filesystem identifiers */
+#define FAT12_SIGN	"FAT12   "
+#define FAT16_SIGN	"FAT16   "
+#define FAT32_SIGN	"FAT32   "
+#define SIGNLEN		8
+
+/* File attributes */
+#define ATTR_RO      1
+#define ATTR_HIDDEN  2
+#define ATTR_SYS     4
+#define ATTR_VOLUME  8
+#define ATTR_DIR     16
+#define ATTR_ARCH    32
+
+#define ATTR_VFAT     (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+
+#define DELETED_FLAG	((char)0xe5) /* Marks deleted files when in name[0] */
+#define aRING		0x05	     /* Used to represent 'å' in name[0] */
+
+/* Indicates that the entry is the last long entry in a set of long
+ * dir entries
+ */
+#define LAST_LONG_ENTRY_MASK	0x40
+
+/* Flags telling whether we should read a file or list a directory */
+#define LS_NO	0
+#define LS_YES	1
+#define LS_DIR	1
+#define LS_ROOT	2
+
+#ifdef DEBUG
+#define FAT_DPRINT(args...)	printf(args)
+#else
+#define FAT_DPRINT(args...)
+#endif
+#define FAT_ERROR(arg)		printf(arg)
+
+#define ISDIRDELIM(c)   ((c) == '/' || (c) == '\\')
+
+#define FSTYPE_NONE	(-1)
+
+#if defined(__linux__) && defined(__KERNEL__)
+#define FAT2CPU16	le16_to_cpu
+#define FAT2CPU32	le32_to_cpu
+#else
+#if __LITTLE_ENDIAN
+#define FAT2CPU16(x)	(x)
+#define FAT2CPU32(x)	(x)
+#else
+#define FAT2CPU16(x)	((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
+#define FAT2CPU32(x)	((((x) & 0x000000ff) << 24)  |	\
+	 		 (((x) & 0x0000ff00) << 8)  |	\
+			 (((x) & 0x00ff0000) >> 8)  |	\
+			 (((x) & 0xff000000) >> 24))
+#endif
+#endif
+
+#define TOLOWER(c)	if((c) >= 'A' && (c) <= 'Z'){(c)+=('a' - 'A');}
+#define START(dent)	(FAT2CPU16((dent)->start) \
+			+ (mydata->fatsize != 32 ? 0 : \
+			  (FAT2CPU16((dent)->starthi) << 16)))
+#define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
+				(x) >= ((fatsize) != 32 ? 0xfff0 : 0xffffff0))
+
+typedef struct boot_sector {
+	__u8	ignored[3];	/* Bootstrap code */
+	char	system_id[8];	/* Name of fs */
+	__u8	sector_size[2];	/* Bytes/sector */
+	__u8	cluster_size;	/* Sectors/cluster */
+	__u16	reserved;	/* Number of reserved sectors */
+	__u8	fats;		/* Number of FATs */
+	__u8	dir_entries[2];	/* Number of root directory entries */
+	__u8	sectors[2];	/* Number of sectors */
+	__u8	media;		/* Media code */
+	__u16	fat_length;	/* Sectors/FAT */
+	__u16	secs_track;	/* Sectors/track */
+	__u16	heads;		/* Number of heads */
+	__u32	hidden;		/* Number of hidden sectors */
+	__u32	total_sect;	/* Number of sectors (if sectors == 0) */
+
+	/* FAT32 only */
+	__u32	fat32_length;	/* Sectors/FAT */
+	__u16	flags;		/* Bit 8: fat mirroring, low 4: active fat */
+	__u8	version[2];	/* Filesystem version */
+	__u32	root_cluster;	/* First cluster in root directory */
+	__u16	info_sector;	/* Filesystem info sector */
+	__u16	backup_boot;	/* Backup boot sector */
+	__u16	reserved2[6];	/* Unused */
+} boot_sector;
+
+typedef struct volume_info
+{
+	__u8 drive_number;	/* BIOS drive number */
+	__u8 reserved;		/* Unused */
+	__u8 ext_boot_sign;	/* 0x29 if fields below exist (DOS 3.3+) */
+	__u8 volume_id[4];	/* Volume ID number */
+	char volume_label[11];	/* Volume label */
+	char fs_type[8];	/* Typically FAT12, FAT16, or FAT32 */
+	/* Boot code comes next, all but 2 bytes to fill up sector */
+	/* Boot sign comes last, 2 bytes */
+} volume_info;
+
+typedef struct dir_entry {
+	char	name[8],ext[3];	/* Name and extension */
+	__u8	attr;		/* Attribute bits */
+	__u8	lcase;		/* Case for base and extension */
+	__u8	ctime_ms;	/* Creation time, milliseconds */
+	__u16	ctime;		/* Creation time */
+	__u16	cdate;		/* Creation date */
+	__u16	adate;		/* Last access date */
+	__u16	starthi;	/* High 16 bits of cluster in FAT32 */
+	__u16	time,date,start;/* Time, date and first cluster */
+	__u32	size;		/* File size in bytes */
+} dir_entry;
+
+typedef struct dir_slot {
+	__u8    id;		/* Sequence number for slot */
+	__u8    name0_4[10];	/* First 5 characters in name */
+	__u8    attr;		/* Attribute byte */
+	__u8    reserved;	/* Unused */
+	__u8    alias_checksum;/* Checksum for 8.3 alias */
+	__u8    name5_10[12];	/* 6 more characters in name */
+	__u16   start;		/* Unused */
+	__u8    name11_12[4];	/* Last 2 characters in name */
+} dir_slot;
+
+/* Private filesystem parameters
+ *
+ * Note: FAT buffer has to be 32 bit aligned
+ * (see FAT32 accesses)
+ */
+typedef struct {
+	__u8	fatbuf[FATBUFSIZE]; /* Current FAT buffer */
+	int	fatsize;	/* Size of FAT in bits */
+	__u16	fatlength;	/* Length of FAT in sectors */
+	__u16	fat_sect;	/* Starting sector of the FAT */
+	__u16	rootdir_sect;	/* Start sector of root directory */
+	__u16	clust_size;	/* Size of clusters in sectors */
+	short	data_begin;	/* The sector of the first cluster, can be negative */
+	int	fatbufnum;	/* Used by get_fatent, init to -1 */
+} fsdata;
+
+typedef int	(file_detectfs_func)(void);
+typedef int	(file_ls_func)(const char *dir);
+typedef long	(file_read_func)(const char *filename, void *buffer,
+				 unsigned long maxsize);
+
+struct filesystem {
+	file_detectfs_func *detect;
+	file_ls_func	   *ls;
+	file_read_func	   *read;
+	const char	    name[12];
+};
+
+/* FAT tables */
+file_detectfs_func	file_fat_detectfs;
+file_ls_func		file_fat_ls;
+file_read_func		file_fat_read;
+
+/* Currently this doesn't check if the dir exists or is valid... */
+int file_cd(const char *path);
+int file_fat_detectfs(void);
+int file_fat_ls(const char *dir);
+long file_fat_read(const char *filename, void *buffer, unsigned long
maxsize);
+const char *file_getfsname(int idx);
+int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
+
+#endif /* _FAT_H_ */
diff --git a/src/io.h b/src/io.h
new file mode 100644
index 0000000..029b7f9
- --- /dev/null
+++ b/src/io.h
@@ -0,0 +1,337 @@
+/*
+ *  linux/include/asm-arm/io.h
+ *
+ *  Copyright (C) 1996-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *  16-Sep-1996	RMK	Inlined the inx/outx functions & optimised for both
+ *			constant addresses and variable addresses.
+ *  04-Dec-1997	RMK	Moved a lot of this stuff to the new architecture
+ *			specific IO header files.
+ *  27-Mar-1999	PJB	Second parameter of memcpy_toio is const..
+ *  04-Apr-1999	PJB	Added check_signature.
+ *  12-Dec-1999	RMK	More cleanups
+ *  18-Jun-2000 RMK	Removed virt_to_* and friends definitions
+ */
+#ifndef __ASM_ARM_IO_H
+#define __ASM_ARM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/memory.h>
+#if 0	/* XXX###XXX */
+#include <asm/arch/hardware.h>
+#endif	/* XXX###XXX */
+
+static inline void sync(void)
+{
+}
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
+ */
+typedef unsigned long phys_addr_t;
+
+#define MAP_NOCACHE	(0)
+#define MAP_WRCOMBINE	(0)
+#define MAP_WRBACK	(0)
+#define MAP_WRTHROUGH	(0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+	return (void *)paddr;
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+/*
+ * Generic virtual read/write.  Note that we don't support half-word
+ * read/writes.  We define __arch_*[bl] here, and leave __arch_*w
+ * to the architecture specific code.
+ */
+#define __arch_getb(a)			(*(volatile unsigned char *)(a))
+#define __arch_getw(a)			(*(volatile unsigned short *)(a))
+#define __arch_getl(a)			(*(volatile unsigned int *)(a))
+
+#define __arch_putb(v,a)		(*(volatile unsigned char *)(a) = (v))
+#define __arch_putw(v,a)		(*(volatile unsigned short *)(a) = (v))
+#define __arch_putl(v,a)		(*(volatile unsigned int *)(a) = (v))
+
+extern void __raw_writesb(unsigned int addr, const void *data, int
bytelen);
+extern void __raw_writesw(unsigned int addr, const void *data, int
wordlen);
+extern void __raw_writesl(unsigned int addr, const void *data, int
longlen);
+
+extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
+extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
+extern void __raw_readsl(unsigned int addr, void *data, int longlen);
+
+#define __raw_writeb(v,a)		__arch_putb(v,a)
+#define __raw_writew(v,a)		__arch_putw(v,a)
+#define __raw_writel(v,a)		__arch_putl(v,a)
+
+#define __raw_readb(a)			__arch_getb(a)
+#define __raw_readw(a)			__arch_getw(a)
+#define __raw_readl(a)			__arch_getl(a)
+
+#define writeb(v,a)			__arch_putb(v,a)
+#define writew(v,a)			__arch_putw(v,a)
+#define writel(v,a)			__arch_putl(v,a)
+
+#define readb(a)			__arch_getb(a)
+#define readw(a)			__arch_getw(a)
+#define readl(a)			__arch_getl(a)
+
+/*
+ * The compiler seems to be incapable of optimising constants
+ * properly.  Spell it out to the compiler in some cases.
+ * These are only valid for small values of "off" (< 1<<12)
+ */
+#define __raw_base_writeb(val,base,off)	__arch_base_putb(val,base,off)
+#define __raw_base_writew(val,base,off)	__arch_base_putw(val,base,off)
+#define __raw_base_writel(val,base,off)	__arch_base_putl(val,base,off)
+
+#define __raw_base_readb(base,off)	__arch_base_getb(base,off)
+#define __raw_base_readw(base,off)	__arch_base_getw(base,off)
+#define __raw_base_readl(base,off)	__arch_base_getl(base,off)
+
+/*
+ * Now, pick up the machine-defined IO definitions
+ */
+#if 0	/* XXX###XXX */
+#include <asm/arch/io.h>
+#endif	/* XXX###XXX */
+
+/*
+ *  IO port access primitives
+ *  -------------------------
+ *
+ * The ARM doesn't have special IO access instructions; all IO is memory
+ * mapped.  Note that these are defined to perform little endian accesses
+ * only.  Their primary purpose is to access PCI and ISA peripherals.
+ *
+ * Note that for a big endian machine, this implies that the following
+ * big endian mode connectivity is in place, as described by numerious
+ * ARM documents:
+ *
+ *    PCI:  D0-D7   D8-D15 D16-D23 D24-D31
+ *    ARM: D24-D31 D16-D23  D8-D15  D0-D7
+ *
+ * The machine specific io.h include defines __io to translate an "IO"
+ * address to a memory address.
+ *
+ * Note that we prevent GCC re-ordering or caching values in expressions
+ * by introducing sequence points into the in*() definitions.  Note that
+ * __raw_* do not guarantee this behaviour.
+ *
+ * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
+ */
+#ifdef __io
+#define outb(v,p)			__raw_writeb(v,__io(p))
+#define outw(v,p)			__raw_writew(cpu_to_le16(v),__io(p))
+#define outl(v,p)			__raw_writel(cpu_to_le32(v),__io(p))
+
+#define inb(p)	({ unsigned int __v = __raw_readb(__io(p)); __v; })
+#define inw(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p)));
__v; })
+#define inl(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p)));
__v; })
+
+#define outsb(p,d,l)			__raw_writesb(__io(p),d,l)
+#define outsw(p,d,l)			__raw_writesw(__io(p),d,l)
+#define outsl(p,d,l)			__raw_writesl(__io(p),d,l)
+
+#define insb(p,d,l)			__raw_readsb(__io(p),d,l)
+#define insw(p,d,l)			__raw_readsw(__io(p),d,l)
+#define insl(p,d,l)			__raw_readsl(__io(p),d,l)
+#endif
+
+#define outb_p(val,port)		outb((val),(port))
+#define outw_p(val,port)		outw((val),(port))
+#define outl_p(val,port)		outl((val),(port))
+#define inb_p(port)			inb((port))
+#define inw_p(port)			inw((port))
+#define inl_p(port)			inl((port))
+
+#define outsb_p(port,from,len)		outsb(port,from,len)
+#define outsw_p(port,from,len)		outsw(port,from,len)
+#define outsl_p(port,from,len)		outsl(port,from,len)
+#define insb_p(port,to,len)		insb(port,to,len)
+#define insw_p(port,to,len)		insw(port,to,len)
+#define insl_p(port,to,len)		insl(port,to,len)
+
+/*
+ * ioremap and friends.
+ *
+ * ioremap takes a PCI memory address, as specified in
+ * linux/Documentation/IO-mapping.txt.  If you want a
+ * physical address, use __ioremap instead.
+ */
+extern void * __ioremap(unsigned long offset, size_t size, unsigned
long flags);
+extern void __iounmap(void *addr);
+
+/*
+ * Generic ioremap support.
+ *
+ * Define:
+ *  iomem_valid_addr(off,size)
+ *  iomem_to_phys(off)
+ */
+#ifdef iomem_valid_addr
+#define __arch_ioremap(off,sz,nocache)				\
+ ({								\
+	unsigned long _off = (off), _size = (sz);		\
+	void *_ret = (void *)0;					\
+	if (iomem_valid_addr(_off, _size))			\
+		_ret = __ioremap(iomem_to_phys(_off),_size,0);	\
+	_ret;							\
+ })
+
+#define __arch_iounmap __iounmap
+#endif
+
+#define ioremap(off,sz)			__arch_ioremap((off),(sz),0)
+#define ioremap_nocache(off,sz)		__arch_ioremap((off),(sz),1)
+#define iounmap(_addr)			__arch_iounmap(_addr)
+
+/*
+ * DMA-consistent mapping functions.  These allocate/free a region of
+ * uncached, unwrite-buffered mapped memory space for use with DMA
+ * devices.  This is the "generic" version.  The PCI specific version
+ * is in pci.h
+ */
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
+extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
+extern void consistent_sync(void *vaddr, size_t size, int rw);
+
+/*
+ * String version of IO memory access ops:
+ */
+extern void _memcpy_fromio(void *, unsigned long, size_t);
+extern void _memcpy_toio(unsigned long, const void *, size_t);
+extern void _memset_io(unsigned long, int, size_t);
+
+extern void __readwrite_bug(const char *fn);
+
+/*
+ * If this architecture has PCI memory IO, then define the read/write
+ * macros.  These should only be used with the cookie passed from
+ * ioremap.
+ */
+#ifdef __mem_pci
+
+#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
+#define readw(c) ({ unsigned int __v =
le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
+#define readl(c) ({ unsigned int __v =
le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
+
+#define writeb(v,c)		__raw_writeb(v,__mem_pci(c))
+#define writew(v,c)		__raw_writew(cpu_to_le16(v),__mem_pci(c))
+#define writel(v,c)		__raw_writel(cpu_to_le32(v),__mem_pci(c))
+
+#define memset_io(c,v,l)		_memset_io(__mem_pci(c),(v),(l))
+#define memcpy_fromio(a,c,l)		_memcpy_fromio((a),__mem_pci(c),(l))
+#define memcpy_toio(c,a,l)		_memcpy_toio(__mem_pci(c),(a),(l))
+
+#define eth_io_copy_and_sum(s,c,l,b) \
+				eth_copy_and_sum((s),__mem_pci(c),(l),(b))
+
+static inline int
+check_signature(unsigned long io_addr, const unsigned char *signature,
+		int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+#elif !defined(readb)
+
+#define readb(addr)			(__readwrite_bug("readb"),0)
+#define readw(addr)			(__readwrite_bug("readw"),0)
+#define readl(addr)			(__readwrite_bug("readl"),0)
+#define writeb(v,addr)			__readwrite_bug("writeb")
+#define writew(v,addr)			__readwrite_bug("writew")
+#define writel(v,addr)			__readwrite_bug("writel")
+
+#define eth_io_copy_and_sum(a,b,c,d)	__readwrite_bug("eth_io_copy_and_sum")
+
+#define check_signature(io,sig,len)	(0)
+
+#endif	/* __mem_pci */
+
+/*
+ * If this architecture has ISA IO, then define the isa_read/isa_write
+ * macros.
+ */
+#ifdef __mem_isa
+
+#define isa_readb(addr)			__raw_readb(__mem_isa(addr))
+#define isa_readw(addr)			__raw_readw(__mem_isa(addr))
+#define isa_readl(addr)			__raw_readl(__mem_isa(addr))
+#define isa_writeb(val,addr)		__raw_writeb(val,__mem_isa(addr))
+#define isa_writew(val,addr)		__raw_writew(val,__mem_isa(addr))
+#define isa_writel(val,addr)		__raw_writel(val,__mem_isa(addr))
+#define isa_memset_io(a,b,c)		_memset_io(__mem_isa(a),(b),(c))
+#define isa_memcpy_fromio(a,b,c)	_memcpy_fromio((a),__mem_isa(b),(c))
+#define isa_memcpy_toio(a,b,c)		_memcpy_toio(__mem_isa((a)),(b),(c))
+
+#define isa_eth_io_copy_and_sum(a,b,c,d) \
+				eth_copy_and_sum((a),__mem_isa(b),(c),(d))
+
+static inline int
+isa_check_signature(unsigned long io_addr, const unsigned char *signature,
+		    int length)
+{
+	int retval = 0;
+	do {
+		if (isa_readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+#else	/* __mem_isa */
+
+#define isa_readb(addr)			(__readwrite_bug("isa_readb"),0)
+#define isa_readw(addr)			(__readwrite_bug("isa_readw"),0)
+#define isa_readl(addr)			(__readwrite_bug("isa_readl"),0)
+#define isa_writeb(val,addr)		__readwrite_bug("isa_writeb")
+#define isa_writew(val,addr)		__readwrite_bug("isa_writew")
+#define isa_writel(val,addr)		__readwrite_bug("isa_writel")
+#define isa_memset_io(a,b,c)		__readwrite_bug("isa_memset_io")
+#define isa_memcpy_fromio(a,b,c)	__readwrite_bug("isa_memcpy_fromio")
+#define isa_memcpy_toio(a,b,c)		__readwrite_bug("isa_memcpy_toio")
+
+#define isa_eth_io_copy_and_sum(a,b,c,d) \
+				__readwrite_bug("isa_eth_io_copy_and_sum")
+
+#define isa_check_signature(io,sig,len)	(0)
+
+#endif	/* __mem_isa */
+#endif	/* __KERNEL__ */
+#endif	/* __ASM_ARM_IO_H */
diff --git a/src/mmc.c b/src/mmc.c
new file mode 100644
index 0000000..39f1720
- --- /dev/null
+++ b/src/mmc.c
@@ -0,0 +1,538 @@
+/*
+ * u-boot S3C2410 MMC/SD card driver
+ * (C) Copyright 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge at openmoko.org>
+ *
+ * based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
+ * (C) 2005-2005 Thomas Kleffel
+ *
+ * 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 <common.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <s3c2410.h>
+#include <part.h>
+#include <fat.h>
+
+#if defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C)
+
+#define CONFIG_MMC_WIDE
+
+static S3C2410_SDI *sdi;
+
+static block_dev_desc_t mmc_dev;
+
+block_dev_desc_t * mmc_get_dev(int dev)
+{
+	return ((block_dev_desc_t *)&mmc_dev);
+}
+
+/*
+ * FIXME needs to read cid and csd info to determine block size
+ * and other parameters
+ */
+static uchar mmc_buf[MMC_BLOCK_SIZE];
+static mmc_csd_t mmc_csd;
+static int mmc_ready = 0;
+static int wide = 0;
+
+
+#define CMD_F_RESP	0x01
+#define CMD_F_RESP_LONG	0x02
+
+static u_int32_t *mmc_cmd(ushort cmd, ulong arg, ushort flags)
+{
+	static u_int32_t resp[5];
+
+	u_int32_t ccon, csta;
+	u_int32_t csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT;
+
+	memset(resp, 0, sizeof(resp));
+
+	debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags);
+
+	sdi->SDICSTA = 0xffffffff;
+	sdi->SDIDSTA = 0xffffffff;
+	sdi->SDIFSTA = 0xffffffff;
+
+	sdi->SDICARG = arg;
+
+	ccon = cmd & S3C2410_SDICMDCON_INDEX;
+	ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART;
+
+	if (flags & CMD_F_RESP) {
+		ccon |= S3C2410_SDICMDCON_WAITRSP;
+		csta_rdy_bit = S3C2410_SDICMDSTAT_RSPFIN; /* 1 << 9 */
+	}
+
+	if (flags & CMD_F_RESP_LONG)
+		ccon |= S3C2410_SDICMDCON_LONGRSP;
+
+	sdi->SDICCON = ccon;
+
+	while (1) {
+		csta = sdi->SDICSTA;
+		if (csta & csta_rdy_bit)
+			break;
+		if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
+			printf("===============> MMC CMD Timeout\n");
+			sdi->SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
+			break;
+		}
+	}
+
+	debug("final MMC CMD status 0x%x\n", csta);
+
+	sdi->SDICSTA |= csta_rdy_bit;
+
+	if (flags & CMD_F_RESP) {
+		resp[0] = sdi->SDIRSP0;
+		resp[1] = sdi->SDIRSP1;
+		resp[2] = sdi->SDIRSP2;
+		resp[3] = sdi->SDIRSP3;
+	}
+
+	return resp;
+}
+
+#define FIFO_FILL(host) ((host->SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
+
+static int mmc_block_read(uchar *dst, ulong src, ulong len)
+{
+	u_int32_t dcon, fifo;
+	u_int32_t *dst_u32 = (u_int32_t *)dst;
+	u_int32_t *resp;
+
+	if (len == 0)
+		return 0;
+
+	debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, len);
+
+	/* set block len */
+	resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP);
+	sdi->SDIBSIZE = len;
+
+	//sdi->SDIPRE = 0xff;
+
+	/* setup data */
+	dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM;
+	dcon |= S3C2410_SDIDCON_BLOCKMODE;
+	dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART;
+	if (wide)
+		dcon |= S3C2410_SDIDCON_WIDEBUS;
+#if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
+	dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART;
+#endif
+	sdi->SDIDCON = dcon;
+
+	/* send read command */
+	resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP);
+
+	while (len > 0) {
+		u_int32_t sdidsta = sdi->SDIDSTA;
+		fifo = FIFO_FILL(sdi);
+		if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL|
+				S3C2410_SDIDSTA_CRCFAIL|
+				S3C2410_SDIDSTA_RXCRCFAIL|
+				S3C2410_SDIDSTA_DATATIMEOUT)) {
+			printf("mmc_block_read: err SDIDSTA=0x%08x\n", sdidsta);
+			return -EIO;
+		}
+
+		while (fifo--) {
+			//debug("dst_u32 = 0x%08x\n", dst_u32);
+			*(dst_u32++) = sdi->SDIDAT;
+			if (len >= 4)
+				len -= 4;
+			else {
+				len = 0;
+				break;
+			}
+		}
+	}
+
+	debug("waiting for SDIDSTA  (currently 0x%08x\n", sdi->SDIDSTA);
+	while (!(sdi->SDIDSTA & (1 << 4))) {}
+	debug("done waiting for SDIDSTA (currently 0x%08x\n", sdi->SDIDSTA);
+
+	sdi->SDIDCON = 0;
+
+	if (!(sdi->SDIDSTA & S3C2410_SDIDSTA_XFERFINISH))
+		debug("mmc_block_read; transfer not finished!\n");
+
+	return 0;
+}
+
+static int mmc_block_write(ulong dst, uchar *src, int len)
+{
+	printf("MMC block write not yet supported on S3C2410!\n");
+	return -1;
+}
+
+
+int mmc_read(ulong src, uchar *dst, int size)
+{
+	ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
+	ulong mmc_block_size, mmc_block_address;
+
+	if (size == 0)
+		return 0;
+
+	if (!mmc_ready) {
+		printf("Please initialize the MMC first\n");
+		return -1;
+	}
+
+	mmc_block_size = MMC_BLOCK_SIZE;
+	mmc_block_address = ~(mmc_block_size - 1);
+
+	src -= CFG_MMC_BASE;
+	end = src + size;
+	part_start = ~mmc_block_address & src;
+	part_end = ~mmc_block_address & end;
+	aligned_start = mmc_block_address & src;
+	aligned_end = mmc_block_address & end;
+
+	/* all block aligned accesses */
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	if (part_start) {
+		part_len = mmc_block_size - part_start;
+		debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
+			return -1;
+
+		memcpy(dst, mmc_buf+part_start, part_len);
+		dst += part_len;
+		src += part_len;
+	}
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
+		debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_read((uchar *)(dst), src, mmc_block_size)) < 0)
+			return -1;
+	}
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	if (part_end && src < end) {
+		debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
+			return -1;
+
+		memcpy(dst, mmc_buf, part_end);
+	}
+	return 0;
+}
+
+int mmc_write(uchar *src, ulong dst, int size)
+{
+	ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
+	ulong mmc_block_size, mmc_block_address;
+
+	if (size == 0)
+		return 0;
+
+	if (!mmc_ready) {
+		printf("Please initialize the MMC first\n");
+		return -1;
+	}
+
+	mmc_block_size = MMC_BLOCK_SIZE;
+	mmc_block_address = ~(mmc_block_size - 1);
+
+	dst -= CFG_MMC_BASE;
+	end = dst + size;
+	part_start = ~mmc_block_address & dst;
+	part_end = ~mmc_block_address & end;
+	aligned_start = mmc_block_address & dst;
+	aligned_end = mmc_block_address & end;
+
+	/* all block aligned accesses */
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	if (part_start) {
+		part_len = mmc_block_size - part_start;
+		debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		(ulong)src, dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
+			return -1;
+
+		memcpy(mmc_buf+part_start, src, part_len);
+		if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0)
+			return -1;
+
+		dst += part_len;
+		src += part_len;
+	}
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
+		debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_write(dst, (uchar *)src, mmc_block_size)) < 0)
+			return -1;
+
+	}
+	debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
+	src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+	if (part_end && dst < end) {
+		debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend
%lx\n",
+		src, (ulong)dst, end, part_start, part_end, aligned_start, aligned_end);
+		if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
+			return -1;
+
+		memcpy(mmc_buf, src, part_end);
+		if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0)
+			return -1;
+
+	}
+	return 0;
+}
+
+ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst)
+{
+	int mmc_block_size = MMC_BLOCK_SIZE;
+	ulong src = blknr * mmc_block_size + CFG_MMC_BASE;
+
+	mmc_read(src, dst, blkcnt*mmc_block_size);
+	return blkcnt;
+}
+
+/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
+   that expects it to be shifted. */
+static u_int16_t rca = MMC_DEFAULT_RCA >> 16;
+
+static u_int32_t mmc_size(const struct mmc_csd *csd)
+{
+	u_int32_t block_len, mult, blocknr;
+
+	block_len = csd->read_bl_len << 12;
+	mult = csd->c_size_mult1 << 8;
+	blocknr = (csd->c_size+1) * mult;
+
+	return blocknr * block_len;
+}
+
+struct sd_cid {
+	char		pnm_0;	/* product name */
+	char		oid_1;	/* OEM/application ID */
+	char		oid_0;
+	uint8_t		mid;	/* manufacturer ID */
+	char		pnm_4;
+	char		pnm_3;
+	char		pnm_2;
+	char		pnm_1;
+	uint8_t		psn_2;	/* product serial number */
+	uint8_t		psn_1;
+	uint8_t		psn_0;	/* MSB */
+	uint8_t		prv;	/* product revision */
+	uint8_t		crc;	/* CRC7 checksum, b0 is unused and set to 1 */
+	uint8_t		mdt_1;	/* manufacturing date, LSB, RRRRyyyy yyyymmmm */
+	uint8_t		mdt_0;	/* MSB */
+	uint8_t		psn_3;	/* LSB */
+};
+
+static void print_mmc_cid(mmc_cid_t *cid)
+{
+	printf("MMC found. Card desciption is:\n");
+	printf("Manufacturer ID = %02x%02x%02x\n",
+		cid->id[0], cid->id[1], cid->id[2]);
+	printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev);
+	cid->hwrev = cid->fwrev = 0;	/* null terminate string */
+	printf("Product Name = %s\n",cid->name);
+	printf("Serial Number = %02x%02x%02x\n",
+		cid->sn[0], cid->sn[1], cid->sn[2]);
+	printf("Month = %d\n",cid->month);
+	printf("Year = %d\n",1997 + cid->year);
+}
+
+static void print_sd_cid(const struct sd_cid *cid)
+{
+	printf("Manufacturer:       0x%02x, OEM \"%c%c\"\n",
+	    cid->mid, cid->oid_0, cid->oid_1);
+	printf("Product name:       \"%c%c%c%c%c\", revision %d.%d\n",
+	    cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4,
+	    cid->prv >> 4, cid->prv & 15);
+	printf("Serial number:      %u\n",
+	    cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
+	    cid->psn_3);
+	printf("Manufacturing date: %d/%d\n",
+	    cid->mdt_1 & 15,
+	    2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
+	printf("CRC:                0x%02x, b0 = %d\n",
+	    cid->crc >> 1, cid->crc & 1);
+}
+
+int mmc_init(int verbose)
+{
+ 	int retries, rc = -ENODEV;
+	int is_sd = 0;
+	u_int32_t *resp;
+	S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+
+	sdi = S3C2410_GetBase_SDI();
+
+	debug("mmc_init(PCLK=%u)\n", get_PCLK());
+
+	clk_power->CLKCON |= (1 << 9);
+
+	sdi->SDIBSIZE = 512;
+#if defined(CONFIG_S3C2410)
+	/* S3C2410 has some bug that prevents reliable operation at higher
speed */
+	//sdi->SDIPRE = 0x3e;  /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
+	sdi->SDIPRE = 0x02;  /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
+	sdi->SDIDTIMER = 0xffff;
+#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
+	sdi->SDIPRE = 0x05;  /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
+	sdi->SDIDTIMER = 0x7fffff;
+#endif
+	sdi->SDIIMSK = 0x0;
+	sdi->SDICON = S3C2410_SDICON_FIFORESET|S3C2410_SDICON_CLOCKTYPE;
+	udelay(125000); /* FIXME: 74 SDCLK cycles */
+
+	mmc_csd.c_size = 0;
+
+	/* reset */
+	retries = 10;
+	resp = mmc_cmd(MMC_CMD_RESET, 0, 0);
+
+	printf("trying to detect SD Card...\n");
+	while (retries--) {
+		udelay(100000);
+		resp = mmc_cmd(55, 0x00000000, CMD_F_RESP);
+		resp = mmc_cmd(41, 0x00300000, CMD_F_RESP);
+
+		if (resp[0] & (1 << 31)) {
+			is_sd = 1;
+			break;
+		}
+	}
+
+	if (retries == 0 && !is_sd) {
+		retries = 10;
+		printf("failed to detect SD Card, trying MMC\n");
+		resp = mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ffc000, CMD_F_RESP);
+		while (retries-- && resp && !(resp[4] & 0x80)) {
+			debug("resp %x %x\n", resp[0], resp[1]);
+			udelay(50);
+			resp = mmc_cmd(1, 0x00ffff00, CMD_F_RESP);
+		}
+	}
+
+	/* try to get card id */
+	resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, CMD_F_RESP|CMD_F_RESP_LONG);
+	if (resp) {
+		if (!is_sd) {
+			/* TODO configure mmc driver depending on card
+			   attributes */
+			mmc_cid_t *cid = (mmc_cid_t *)resp;
+
+			if (verbose)
+				print_mmc_cid(cid);
+			sprintf((char *) mmc_dev.vendor,
+				"Man %02x%02x%02x Snr %02x%02x%02x",
+				cid->id[0], cid->id[1], cid->id[2],
+				cid->sn[0], cid->sn[1], cid->sn[2]);
+			sprintf((char *) mmc_dev.product,"%s",cid->name);
+			sprintf((char *) mmc_dev.revision,"%x %x",
+				cid->hwrev, cid->fwrev);
+		}
+		else {
+			struct sd_cid *cid = (struct sd_cid *) resp;
+
+			if (verbose)
+				print_sd_cid(cid);
+			sprintf((char *) mmc_dev.vendor,
+			    "Man %02 OEM %c%c \"%c%c%c%c%c\"",
+			    cid->mid, cid->oid_0, cid->oid_1,
+			    cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3,
+			    cid->pnm_4);
+			sprintf((char *) mmc_dev.product, "%d",
+			    cid->psn_0 << 24 | cid->psn_1 << 16 |
+			    cid->psn_2 << 8 | cid->psn_3);
+			sprintf((char *) mmc_dev.revision, "%d.%d",
+			    cid->prv >> 4, cid->prv & 15);
+		}
+
+		/* fill in device description */
+		mmc_dev.if_type = IF_TYPE_MMC;
+		mmc_dev.part_type = PART_TYPE_DOS;
+		mmc_dev.dev = 0;
+		mmc_dev.lun = 0;
+		mmc_dev.type = 0;
+		/* FIXME fill in the correct size (is set to 32MByte) */
+		mmc_dev.blksz = 512;
+		mmc_dev.lba = 0x10000;
+		mmc_dev.removable = 0;
+		mmc_dev.block_read = mmc_bread;
+
+		/* MMC exists, get CSD too */
+		resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP);
+		if (is_sd)
+			rca = resp[0] >> 16;
+
+		resp = mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, CMD_F_RESP|CMD_F_RESP_LONG);
+		if (resp) {
+			mmc_csd_t *csd = (mmc_csd_t *)resp;
+			memcpy(&mmc_csd, csd, sizeof(csd));
+			rc = 0;
+			mmc_ready = 1;
+			/* FIXME add verbose printout for csd */
+			printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
+				csd->read_bl_len, csd->c_size_mult1, csd->c_size);
+			printf("size = %u\n", mmc_size(csd));
+		}
+	}
+
+	resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, CMD_F_RESP);
+
+#ifdef CONFIG_MMC_WIDE
+	if (is_sd) {
+		resp = mmc_cmd(55, rca<<16, CMD_F_RESP);
+		resp = mmc_cmd(6, 0x02, CMD_F_RESP);
+		wide = 1;
+	}
+#endif
+
+	fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */
+
+	return rc;
+}
+
+int
+mmc_ident(block_dev_desc_t *dev)
+{
+	return 0;
+}
+
+int
+mmc2info(ulong addr)
+{
+	/* FIXME hard codes to 32 MB device */
+	if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0x02000000)
+		return 1;
+
+	return 0;
+}
+
+#endif	/* defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) */
diff --git a/src/mmc.h b/src/mmc.h
new file mode 100644
index 0000000..a271695
- --- /dev/null
+++ b/src/mmc.h
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.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
+ */
+
+#ifndef _MMC_H_
+#define _MMC_H_
+#include <asm/arch/mmc.h>
+
+int mmc_init(int verbose);
+int mmc_read(ulong src, uchar *dst, int size);
+int mmc_write(uchar *src, ulong dst, int size);
+int mmc2info(ulong addr);
+
+#endif /* _MMC_H_ */
diff --git a/src/part.h b/src/part.h
new file mode 100644
index 0000000..b22a637
- --- /dev/null
+++ b/src/part.h
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.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
+ */
+#ifndef _PART_H
+#define _PART_H
+
+#include <ide.h>
+
+typedef struct block_dev_desc {
+	int		if_type;	/* type of the interface */
+	int		dev;		/* device number */
+	unsigned char	part_type;	/* partition type */
+	unsigned char	target;		/* target SCSI ID */
+	unsigned char	lun;		/* target LUN */
+	unsigned char	type;		/* device type */
+	unsigned char	removable;	/* removable device */
+#ifdef CONFIG_LBA48
+	unsigned char	lba48;		/* device can use 48bit addr (ATA/ATAPI v7) */
+#endif
+	lbaint_t		lba;		/* number of blocks */
+	unsigned long	blksz;		/* block size */
+	char		vendor [40+1];	/* IDE model, SCSI Vendor */
+	char		product[20+1];	/* IDE Serial no, SCSI product */
+	char		revision[8+1];	/* firmware revision */
+	unsigned long	(*block_read)(int dev,
+				      unsigned long start,
+				      lbaint_t blkcnt,
+				      void *buffer);
+	unsigned long	(*block_write)(int dev,
+				       unsigned long start,
+				       lbaint_t blkcnt,
+				       const void *buffer);
+	void		*priv;		/* driver private struct pointer */
+}block_dev_desc_t;
+
+/* Interface types: */
+#define IF_TYPE_UNKNOWN		0
+#define IF_TYPE_IDE		1
+#define IF_TYPE_SCSI		2
+#define IF_TYPE_ATAPI		3
+#define IF_TYPE_USB		4
+#define IF_TYPE_DOC		5
+#define IF_TYPE_MMC		6
+#define IF_TYPE_SD		7
+#define IF_TYPE_SATA		8
+
+/* Part types */
+#define PART_TYPE_UNKNOWN	0x00
+#define PART_TYPE_MAC		0x01
+#define PART_TYPE_DOS		0x02
+#define PART_TYPE_ISO		0x03
+#define PART_TYPE_AMIGA		0x04
+
+/*
+ * Type string for U-Boot bootable partitions
+ */
+#define BOOT_PART_TYPE	"U-Boot"	/* primary boot partition type	*/
+#define BOOT_PART_COMP	"PPCBoot"	/* PPCBoot compatibility type	*/
+
+/* device types */
+#define DEV_TYPE_UNKNOWN	0xff	/* not connected */
+#define DEV_TYPE_HARDDISK	0x00	/* harddisk */
+#define DEV_TYPE_TAPE		0x01	/* Tape */
+#define DEV_TYPE_CDROM		0x05	/* CD-ROM */
+#define DEV_TYPE_OPDISK		0x07	/* optical disk */
+
+typedef struct disk_partition {
+	ulong	start;		/* # of first block in partition	*/
+	ulong	size;		/* number of blocks in partition	*/
+	ulong	blksz;		/* block size in bytes			*/
+	uchar	name[32];	/* partition name			*/
+	uchar	type[32];	/* string type description		*/
+} disk_partition_t;
+
+/* Misc _get_dev functions */
+block_dev_desc_t* get_dev(char* ifname, int dev);
+block_dev_desc_t* ide_get_dev(int dev);
+block_dev_desc_t* sata_get_dev(int dev);
+block_dev_desc_t* scsi_get_dev(int dev);
+block_dev_desc_t* usb_stor_get_dev(int dev);
+block_dev_desc_t* mmc_get_dev(int dev);
+block_dev_desc_t* systemace_get_dev(int dev);
+
+/* disk/part.c */
+int get_partition_info (block_dev_desc_t * dev_desc, int part,
disk_partition_t *info);
+void print_part (block_dev_desc_t *dev_desc);
+void  init_part (block_dev_desc_t *dev_desc);
+void dev_print(block_dev_desc_t *dev_desc);
+
+
+#ifdef CONFIG_MAC_PARTITION
+/* disk/part_mac.c */
+int get_partition_info_mac (block_dev_desc_t * dev_desc, int part,
disk_partition_t *info);
+void print_part_mac (block_dev_desc_t *dev_desc);
+int   test_part_mac (block_dev_desc_t *dev_desc);
+#endif
+
+#ifdef CONFIG_DOS_PARTITION
+/* disk/part_dos.c */
+int get_partition_info_dos (block_dev_desc_t * dev_desc, int part,
disk_partition_t *info);
+void print_part_dos (block_dev_desc_t *dev_desc);
+int   test_part_dos (block_dev_desc_t *dev_desc);
+#endif
+
+#ifdef CONFIG_ISO_PARTITION
+/* disk/part_iso.c */
+int get_partition_info_iso (block_dev_desc_t * dev_desc, int part,
disk_partition_t *info);
+void print_part_iso (block_dev_desc_t *dev_desc);
+int   test_part_iso (block_dev_desc_t *dev_desc);
+#endif
+
+#ifdef CONFIG_AMIGA_PARTITION
+/* disk/part_amiga.c */
+int get_partition_info_amiga (block_dev_desc_t * dev_desc, int part,
disk_partition_t *info);
+void print_part_amiga (block_dev_desc_t *dev_desc);
+int   test_part_amiga (block_dev_desc_t *dev_desc);
+#endif
+
+#endif /* _PART_H */
- -- 1.5.5
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQEVAwUBSKcDpBFuNemPXNFjAQKBeggAhqmul0i1lsY3X0p3AbaDa5nR1B+7FHEb
cRrlXmXVi3vNnYOvt8S5+3PcUjygj4908tbpAwPQvoyOkfGVzAmWqbqFnWRWbheV
HuVHD1M/TSul6sgU1sbP/EPcAfEGq1Tzv4oLz5r1yWLxoCW67utiwKHKcOVxFLFu
A+5GDAatvV0rrAUtFSBCQo4ARDal4mDOM7r8SHsMTE2YdJ4Z7bAAeufNHe0jQ3ty
ZW1Hk/plvCUXGIbTRonO6hrJgYTZ+gk7vF+kyVvk7F3ytrlxytb0e1HKnhzrDPFf
XHQIe/5SivEmPt1uJnKZCF+cKGqTOlBtEBUmZ1AZ857D35YJAYd7Og==
=fqOL
-----END PGP SIGNATURE-----




More information about the openmoko-kernel mailing list