diff --git a/qiboot/src/calc_pclk.c b/qiboot/src/calc_pclk.c new file mode 100644 index 0000000..777ad03 --- /dev/null +++ b/qiboot/src/calc_pclk.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2007 OpenMoko, Inc. + * Author: xiangfu liu + * + * + * 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/qiboot/src/common.h b/qiboot/src/common.h new file mode 100644 index 0000000..055dec2 --- /dev/null +++ b/qiboot/src/common.h @@ -0,0 +1,681 @@ +/* + * (C) Copyright 2000-2007 + * Wolfgang Denk, DENX Software Engineering, wd@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 +#include +#include +#include +#include +#include +#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) +#include +#endif +#if defined(CONFIG_8xx) +#include +#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 +#elif defined(CONFIG_MPC5xxx) +#include +#elif defined(CONFIG_MPC512X) +#include +#include +#elif defined(CONFIG_MPC8220) +#include +#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 +#endif +#ifdef CONFIG_MPC86xx +#include +#include +#endif +#ifdef CONFIG_MPC85xx +#include +#include +#endif +#ifdef CONFIG_MPC83XX +#include +#include +#endif +#ifdef CONFIG_4xx +#include +#endif +#ifdef CONFIG_HYMOD +#include +#endif +#ifdef CONFIG_ARM +#define asmlinkage /* nothing */ +#endif +#ifdef CONFIG_BLACKFIN +#include +#endif + +#include +#include +#include + +#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 /* boot information for Linux kernel */ +#include /* 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 +# include +# include /* ARM version to be fixed! */ +#endif /* CONFIG_ARM */ +#ifdef CONFIG_I386 /* x86 version to be fixed! */ +# include +#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)/.../ */ +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 +#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/qiboot/src/fat.h b/qiboot/src/fat.h new file mode 100644 index 0000000..f993cca --- /dev/null +++ b/qiboot/src/fat.h @@ -0,0 +1,220 @@ +/* + * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg + * + * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 + * 2003-03-10 - kharris@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 + +#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/qiboot/src/io.h b/qiboot/src/io.h new file mode 100644 index 0000000..029b7f9 --- /dev/null +++ b/qiboot/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 +#include +#include +#if 0 /* XXX###XXX */ +#include +#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 +#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/qiboot/src/mmc.c b/qiboot/src/mmc.c new file mode 100644 index 0000000..39f1720 --- /dev/null +++ b/qiboot/src/mmc.c @@ -0,0 +1,538 @@ +/* + * u-boot S3C2410 MMC/SD card driver + * (C) Copyright 2006 by OpenMoko, Inc. + * Author: Harald Welte + * + * 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 +#include +#include +#include +#include +#include +#include + +#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/qiboot/src/mmc.h b/qiboot/src/mmc.h new file mode 100644 index 0000000..a271695 --- /dev/null +++ b/qiboot/src/mmc.h @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@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 + +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/qiboot/src/part.h b/qiboot/src/part.h new file mode 100644 index 0000000..b22a637 --- /dev/null +++ b/qiboot/src/part.h @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@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 + +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 */