diff options
263 files changed, 6004 insertions, 3113 deletions
@@ -1209,7 +1209,23 @@ The following options need to be configured: If this option is set, the driver enables cache flush. - TPM Support: - CONFIG_GENERIC_LPC_TPM + CONFIG_TPM + Support TPM devices. + + CONFIG_TPM_TIS_I2C + Support for i2c bus TPM devices. Only one device + per system is supported at this time. + + CONFIG_TPM_TIS_I2C_BUS_NUMBER + Define the the i2c bus number for the TPM device + + CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS + Define the TPM's address on the i2c bus + + CONFIG_TPM_TIS_I2C_BURST_LIMITATION + Define the burst count bytes upper limit + + CONFIG_TPM_TIS_LPC Support for generic parallel port TPM devices. Only one device per system is supported at this time. @@ -1245,6 +1261,9 @@ The following options need to be configured: CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the txfilltuning field in the EHCI controller on reset. + CONFIG_USB_HUB_MIN_POWER_ON_DELAY defines the minimum + interval for usb hub power-on delay.(minimum 100msec) + - USB Device: Define the below if you wish to use the USB console. Once firmware is rebuilt from a serial console issue the @@ -2916,12 +2935,30 @@ FIT uImage format: Address, size and partition on the MMC to load U-Boot from when the MMC is being used in raw mode. + CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR + Sector to load kernel uImage from when MMC is being + used in raw mode (for Falcon mode) + + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS + Sector and number of sectors to load kernel argument + parameters from when MMC is being used in raw mode + (for falcon mode) + CONFIG_SPL_FAT_SUPPORT Support for fs/fat/libfat.o in SPL binary CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME Filename to read to load U-Boot when reading from FAT + CONFIG_SPL_FAT_LOAD_KERNEL_NAME + Filename to read to load kernel uImage when reading + from FAT (for Falcon mode) + + CONFIG_SPL_FAT_LOAD_ARGS_NAME + Filename to read to load kernel argument parameters + when reading from FAT (for Falcon mode) + CONFIG_SPL_MPC83XX_WAIT_FOR_NAND Set this for NAND SPL on PPC mpc83xx targets, so that start.S waits for the rest of the SPL to load before @@ -3864,6 +3901,9 @@ Low Level (hardware related) configuration options: a second time. Useful for platforms that are pre-booted by coreboot or similar. +- CONFIG_PCI_INDIRECT_BRIDGE: + Enable support for indirect PCI bridges. + - CONFIG_SYS_SRIO: Chip has SRIO or not diff --git a/arch/arm/include/asm/arch-am33xx/omap.h b/arch/arm/include/asm/arch-am33xx/omap.h index db15159643..e7576c1106 100644 --- a/arch/arm/include/asm/arch-am33xx/omap.h +++ b/arch/arm/include/asm/arch-am33xx/omap.h @@ -31,8 +31,10 @@ #ifdef CONFIG_AM33XX #define NON_SECURE_SRAM_START 0x402F0400 #define NON_SECURE_SRAM_END 0x40310000 +#define SRAM_SCRATCH_SPACE_ADDR 0x4030C000 #elif defined(CONFIG_TI814X) #define NON_SECURE_SRAM_START 0x40300000 #define NON_SECURE_SRAM_END 0x40320000 +#define SRAM_SCRATCH_SPACE_ADDR 0x4031B800 #endif #endif diff --git a/arch/arm/include/asm/arch-omap4/omap.h b/arch/arm/include/asm/arch-omap4/omap.h index 66afd92492..9fd00ff2aa 100644 --- a/arch/arm/include/asm/arch-omap4/omap.h +++ b/arch/arm/include/asm/arch-omap4/omap.h @@ -127,6 +127,7 @@ struct s32ktimer { */ #define NON_SECURE_SRAM_START 0x40304000 #define NON_SECURE_SRAM_END 0x4030E000 /* Not inclusive */ +#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START /* base address for indirect vectors (internal boot mode) */ #define SRAM_ROM_VECT_BASE 0x4030D000 diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h index 817c1ff27f..5e6d82e51f 100644 --- a/arch/arm/include/asm/arch-omap5/omap.h +++ b/arch/arm/include/asm/arch-omap5/omap.h @@ -176,6 +176,7 @@ struct s32ktimer { #define NON_SECURE_SRAM_START 0x40300000 #define NON_SECURE_SRAM_END 0x40320000 /* Not inclusive */ #endif +#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START /* base address for indirect vectors (internal boot mode) */ #define SRAM_ROM_VECT_BASE 0x4031F000 diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 787e614ecb..0dbe81b59c 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -642,7 +642,6 @@ static inline u8 is_omap54xx(void) /* * SRAM scratch space entries */ -#define SRAM_SCRATCH_SPACE_ADDR NON_SECURE_SRAM_START #define OMAP_SRAM_SCRATCH_OMAP_REV SRAM_SCRATCH_SPACE_ADDR #define OMAP_SRAM_SCRATCH_EMIF_SIZE (SRAM_SCRATCH_SPACE_ADDR + 0x4) #define OMAP_SRAM_SCRATCH_EMIF_T_NUM (SRAM_SCRATCH_SPACE_ADDR + 0xC) diff --git a/arch/mips/include/asm/errno.h b/arch/mips/include/asm/errno.h index 1665a63a81..4c82b503d9 100644 --- a/arch/mips/include/asm/errno.h +++ b/arch/mips/include/asm/errno.h @@ -1,143 +1 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995, 1999, 2001, 2002 by Ralf Baechle - */ -#ifndef _ASM_MIPS_ERRNO_H -#define _ASM_MIPS_ERRNO_H - -/* - * These first 34 error codes are from Linux 2.6, <asm-generic/errno-base.h> - */ -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ - -/* - * These error numbers are intended to be MIPS ABI compatible - */ -#define ENOMSG 35 /* No message of desired type */ -#define EIDRM 36 /* Identifier removed */ -#define ECHRNG 37 /* Channel number out of range */ -#define EL2NSYNC 38 /* Level 2 not synchronized */ -#define EL3HLT 39 /* Level 3 halted */ -#define EL3RST 40 /* Level 3 reset */ -#define ELNRNG 41 /* Link number out of range */ -#define EUNATCH 42 /* Protocol driver not attached */ -#define ENOCSI 43 /* No CSI structure available */ -#define EL2HLT 44 /* Level 2 halted */ -#define EDEADLK 45 /* Resource deadlock would occur */ -#define ENOLCK 46 /* No record locks available */ -#define EBADE 50 /* Invalid exchange */ -#define EBADR 51 /* Invalid request descriptor */ -#define EXFULL 52 /* Exchange full */ -#define ENOANO 53 /* No anode */ -#define EBADRQC 54 /* Invalid request code */ -#define EBADSLT 55 /* Invalid slot */ -#define EDEADLOCK 56 /* File locking deadlock error */ -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EDOTDOT 73 /* RFS specific error */ -#define EMULTIHOP 74 /* Multihop attempted */ -#define EBADMSG 77 /* Not a data message */ -#define ENAMETOOLONG 78 /* File name too long */ -#define EOVERFLOW 79 /* Value too large for defined data type */ -#define ENOTUNIQ 80 /* Name not unique on network */ -#define EBADFD 81 /* File descriptor in bad state */ -#define EREMCHG 82 /* Remote address changed */ -#define ELIBACC 83 /* Can not access a needed shared library */ -#define ELIBBAD 84 /* Accessing a corrupted shared library */ -#define ELIBSCN 85 /* .lib section in a.out corrupted */ -#define ELIBMAX 86 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 87 /* Cannot exec a shared library directly */ -#define EILSEQ 88 /* Illegal byte sequence */ -#define ENOSYS 89 /* Function not implemented */ -#define ELOOP 90 /* Too many symbolic links encountered */ -#define ERESTART 91 /* Interrupted system call should be restarted */ -#define ESTRPIPE 92 /* Streams pipe error */ -#define ENOTEMPTY 93 /* Directory not empty */ -#define EUSERS 94 /* Too many users */ -#define ENOTSOCK 95 /* Socket operation on non-socket */ -#define EDESTADDRREQ 96 /* Destination address required */ -#define EMSGSIZE 97 /* Message too long */ -#define EPROTOTYPE 98 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 99 /* Protocol not available */ -#define EPROTONOSUPPORT 120 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 121 /* Socket type not supported */ -#define EOPNOTSUPP 122 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 123 /* Protocol family not supported */ -#define EAFNOSUPPORT 124 /* Address family not supported by protocol */ -#define EADDRINUSE 125 /* Address already in use */ -#define EADDRNOTAVAIL 126 /* Cannot assign requested address */ -#define ENETDOWN 127 /* Network is down */ -#define ENETUNREACH 128 /* Network is unreachable */ -#define ENETRESET 129 /* Network dropped connection because of reset */ -#define ECONNABORTED 130 /* Software caused connection abort */ -#define ECONNRESET 131 /* Connection reset by peer */ -#define ENOBUFS 132 /* No buffer space available */ -#define EISCONN 133 /* Transport endpoint is already connected */ -#define ENOTCONN 134 /* Transport endpoint is not connected */ -#define EUCLEAN 135 /* Structure needs cleaning */ -#define ENOTNAM 137 /* Not a XENIX named type file */ -#define ENAVAIL 138 /* No XENIX semaphores available */ -#define EISNAM 139 /* Is a named type file */ -#define EREMOTEIO 140 /* Remote I/O error */ -#define EINIT 141 /* Reserved */ -#define EREMDEV 142 /* Error 142 */ -#define ESHUTDOWN 143 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 144 /* Too many references: cannot splice */ -#define ETIMEDOUT 145 /* Connection timed out */ -#define ECONNREFUSED 146 /* Connection refused */ -#define EHOSTDOWN 147 /* Host is down */ -#define EHOSTUNREACH 148 /* No route to host */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define EALREADY 149 /* Operation already in progress */ -#define EINPROGRESS 150 /* Operation now in progress */ -#define ESTALE 151 /* Stale NFS file handle */ -#define ECANCELED 158 /* AIO operation canceled */ - -#endif /* _ASM_MIPS_ERRNO_H */ +#include <asm-generic/errno.h> diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 3864c804c0..50a882ca5a 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -184,19 +184,19 @@ extern void iounmap(void *addr); * 24-31 on SNI. * XXX more SNI hacks. */ -#define readb(addr) (*(volatile unsigned char *)(addr)) -#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr))) -#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr))) -#define __raw_readb readb -#define __raw_readw readw -#define __raw_readl readl - -#define writeb(b,addr) (*(volatile unsigned char *)(addr)) = (b) -#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (__ioswab16(b)) -#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (__ioswab32(b)) -#define __raw_writeb writeb -#define __raw_writew writew -#define __raw_writel writel +#define __raw_readb(addr) (*(volatile unsigned char *)(addr)) +#define __raw_readw(addr) (*(volatile unsigned short *)(addr)) +#define __raw_readl(addr) (*(volatile unsigned int *)(addr)) +#define readb(addr) __raw_readb((addr)) +#define readw(addr) __ioswab16(__raw_readw((addr))) +#define readl(addr) __ioswab32(__raw_readl((addr))) + +#define __raw_writeb(b, addr) (*(volatile unsigned char *)(addr)) = (b) +#define __raw_writew(b, addr) (*(volatile unsigned short *)(addr)) = (b) +#define __raw_writel(b, addr) (*(volatile unsigned int *)(addr)) = (b) +#define writeb(b, addr) __raw_writeb((b), (addr)) +#define writew(b, addr) __raw_writew(__ioswab16(b), (addr)) +#define writel(b, addr) __raw_writel(__ioswab32(b), (addr)) #define memset_io(a,b,c) memset((void *)(a),(b),(c)) #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) diff --git a/arch/powerpc/cpu/mpc8260/commproc.c b/arch/powerpc/cpu/mpc8260/commproc.c index 22cef3e983..484bd17745 100644 --- a/arch/powerpc/cpu/mpc8260/commproc.c +++ b/arch/powerpc/cpu/mpc8260/commproc.c @@ -43,7 +43,7 @@ m8260_cpm_reset(void) } while ((immr->im_cpm.cp_cpcr & CPM_CR_FLG) && ++count < 1000000); #ifdef CONFIG_HARD_I2C - *((unsigned short*)(&immr->im_dprambase[PROFF_I2C_BASE])) = 0; + immr->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)] = 0; #endif } diff --git a/arch/powerpc/cpu/mpc8260/cpu.c b/arch/powerpc/cpu/mpc8260/cpu.c index f8bc5a9834..22e1a23a2a 100644 --- a/arch/powerpc/cpu/mpc8260/cpu.c +++ b/arch/powerpc/cpu/mpc8260/cpu.c @@ -106,7 +106,7 @@ int checkcpu (void) * in the mask. */ m = immr & (IMMR_PARTNUM_MSK | IMMR_MASKNUM_MSK); - k = *((ushort *) & immap->im_dprambase[PROFF_REVNUM]); + k = immap->im_dprambase16[PROFF_REVNUM / sizeof(u16)]; switch (m) { case 0x0000: diff --git a/arch/powerpc/cpu/mpc8260/i2c.c b/arch/powerpc/cpu/mpc8260/i2c.c index b720b1fb88..e2341e9c39 100644 --- a/arch/powerpc/cpu/mpc8260/i2c.c +++ b/arch/powerpc/cpu/mpc8260/i2c.c @@ -221,14 +221,14 @@ void i2c_init(int speed, int slaveadd) i2c_init_board(); #endif - dpaddr = *((unsigned short *) (&immap->im_dprambase[PROFF_I2C_BASE])); + dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; if (dpaddr == 0) { /* need to allocate dual port ram */ dpaddr = m8260_cpm_dpalloc(64 + (NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) + MAX_TX_SPACE, 64); - *((unsigned short *)(&immap->im_dprambase[PROFF_I2C_BASE])) = + immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)] = dpaddr; } @@ -305,7 +305,7 @@ void i2c_newio(i2c_state_t *state) debug("[I2C] i2c_newio\n"); - dpaddr = *((unsigned short *)(&immap->im_dprambase[PROFF_I2C_BASE])); + dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; iip = (iic_t *)&immap->im_dprambase[dpaddr]; state->rx_idx = 0; state->tx_idx = 0; @@ -480,7 +480,7 @@ int i2c_doio(i2c_state_t *state) return I2CERR_QUEUE_EMPTY; } - dpaddr = *((unsigned short *)(&immap->im_dprambase[PROFF_I2C_BASE])); + dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; iip = (iic_t *)&immap->im_dprambase[dpaddr]; iip->iic_rbptr = iip->iic_rbase; iip->iic_tbptr = iip->iic_tbase; diff --git a/arch/powerpc/cpu/mpc8260/serial_smc.c b/arch/powerpc/cpu/mpc8260/serial_smc.c index feba1f63d2..9410e4c3b2 100644 --- a/arch/powerpc/cpu/mpc8260/serial_smc.c +++ b/arch/powerpc/cpu/mpc8260/serial_smc.c @@ -105,7 +105,7 @@ static int mpc8260_smc_serial_init(void) /* initialize pointers to SMC */ sp = (smc_t *) &(im->im_smc[SMC_INDEX]); - *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC; + im->im_dprambase16[PROFF_SMC_BASE / sizeof(u16)] = PROFF_SMC; up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC]; /* Disable transmitter/receiver. */ @@ -331,7 +331,7 @@ kgdb_serial_init (void) /* initialize pointers to SMC */ sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]); - *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC; + im->im_dprambase16[KGDB_PROFF_SMC_BASE / sizeof(u16)] = KGDB_PROFF_SMC; up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC]; /* Disable transmitter/receiver. */ diff --git a/arch/powerpc/cpu/mpc8260/spi.c b/arch/powerpc/cpu/mpc8260/spi.c index dc98ea73f2..01b492e8e4 100644 --- a/arch/powerpc/cpu/mpc8260/spi.c +++ b/arch/powerpc/cpu/mpc8260/spi.c @@ -146,7 +146,7 @@ void spi_init_f (void) immr = (immap_t *) CONFIG_SYS_IMMR; cp = (cpm8260_t *) &immr->im_cpm; - *(ushort *)(&immr->im_dprambase[PROFF_SPI_BASE]) = PROFF_SPI; + immr->im_dprambase16[PROFF_SPI_BASE / sizeof(u16)] = PROFF_SPI; spi = (spi_t *)&immr->im_dprambase[PROFF_SPI]; /* 1 */ diff --git a/arch/powerpc/cpu/mpc8xx/cpu.c b/arch/powerpc/cpu/mpc8xx/cpu.c index b6b733d77f..dc33eb3d10 100644 --- a/arch/powerpc/cpu/mpc8xx/cpu.c +++ b/arch/powerpc/cpu/mpc8xx/cpu.c @@ -78,7 +78,8 @@ static int check_CPU (long clock, uint pvr, uint immr) if ((pvr >> 16) != 0x0050) return -1; - k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + k = (immr << 16) | + immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]; m = 0; suf = ""; @@ -194,7 +195,8 @@ static int check_CPU (long clock, uint pvr, uint immr) if ((pvr >> 16) != 0x0050) return -1; - k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + k = (immr << 16) | + immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]; m = 0; switch (k) { @@ -253,7 +255,8 @@ static int check_CPU (long clock, uint pvr, uint immr) if ((pvr >> 16) != 0x0050) return -1; - k = (immr << 16) | in_be16((ushort *)&immap->im_cpm.cp_dparam[0xB0]); + k = (immr << 16) | + in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]); m = 0; switch (k) { @@ -312,7 +315,8 @@ static int check_CPU (long clock, uint pvr, uint immr) if ((pvr >> 16) != 0x0050) return -1; - k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + k = (immr << 16) | + immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]; m = 0; switch (k) { diff --git a/arch/powerpc/include/asm/8xx_immap.h b/arch/powerpc/include/asm/8xx_immap.h index 40679cb2b0..01129ed4f0 100644 --- a/arch/powerpc/include/asm/8xx_immap.h +++ b/arch/powerpc/include/asm/8xx_immap.h @@ -485,7 +485,12 @@ typedef struct comm_proc { * Some processors don't have all of it populated. */ u_char cp_dpmem[0x1C00]; /* BD / Data / ucode */ - u_char cp_dparam[0x400]; /* Parameter RAM */ + + /* Parameter RAM */ + union { + u_char cp_dparam[0x400]; + u16 cp_dparam16[0x200]; + }; } cpm8xx_t; /* Internal memory map. diff --git a/arch/powerpc/include/asm/immap_8260.h b/arch/powerpc/include/asm/immap_8260.h index 4974ae56fc..c7021a7095 100644 --- a/arch/powerpc/include/asm/immap_8260.h +++ b/arch/powerpc/include/asm/immap_8260.h @@ -526,13 +526,18 @@ typedef struct immap { /* Some references are into the unique and known dpram spaces, * others are from the generic base. */ -#define im_dprambase im_dpram1 - u_char im_dpram1[16*1024]; - char res1[16*1024]; - u_char im_dpram2[4*1024]; - char res2[8*1024]; - u_char im_dpram3[4*1024]; - char res3[16*1024]; + union { + struct { + u_char im_dpram1[16 * 1024]; + char res1[16 * 1024]; + u_char im_dpram2[4 * 1024]; + char res2[8 * 1024]; + u_char im_dpram3[4 * 1024]; + char res3[16 * 1024]; + }; + u8 im_dprambase[64 * 1024]; + u16 im_dprambase16[32 * 1024]; + }; sysconf8260_t im_siu_conf; /* SIU Configuration */ memctl8260_t im_memctl; /* Memory Controller */ diff --git a/board/ait/cam_enc_4xx/cam_enc_4xx.c b/board/ait/cam_enc_4xx/cam_enc_4xx.c index 644c445693..80a78221b1 100644 --- a/board/ait/cam_enc_4xx/cam_enc_4xx.c +++ b/board/ait/cam_enc_4xx/cam_enc_4xx.c @@ -120,7 +120,7 @@ int board_eth_init(bd_t *bis) #ifdef CONFIG_NAND_DAVINCI static int davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { struct nand_chip *this = mtd->priv; int i, eccsize = chip->ecc.size; @@ -167,8 +167,9 @@ davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static void davinci_std_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) +static int davinci_std_write_page_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required) { unsigned char davinci_ecc_buf[NAND_MAX_OOBSIZE]; struct nand_chip *this = mtd->priv; @@ -218,6 +219,7 @@ static void davinci_std_write_page_syndrome(struct mtd_info *mtd, i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->write_buf(mtd, oob, i); + return 0; } static int davinci_std_write_oob_syndrome(struct mtd_info *mtd, @@ -239,7 +241,7 @@ static int davinci_std_write_oob_syndrome(struct mtd_info *mtd, } static int davinci_std_read_oob_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, int page, int sndcmd) + struct nand_chip *chip, int page) { struct nand_chip *this = mtd->priv; uint8_t *buf = chip->oob_poi; @@ -249,7 +251,7 @@ static int davinci_std_read_oob_syndrome(struct mtd_info *mtd, chip->read_buf(mtd, bufpoi, mtd->oobsize); - return 1; + return 0; } static void nand_dm365evm_select_chip(struct mtd_info *mtd, int chip) diff --git a/board/raspberrypi/rpi_b/rpi_b.c b/board/raspberrypi/rpi_b/rpi_b.c index 6b3e095ba8..16d442aa62 100644 --- a/board/raspberrypi/rpi_b/rpi_b.c +++ b/board/raspberrypi/rpi_b/rpi_b.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2012 Stephen Warren + * (C) Copyright 2012-2013 Stephen Warren * * See file CREDITS for list of people who contributed to this * project. @@ -15,6 +15,8 @@ */ #include <common.h> +#include <config.h> +#include <lcd.h> #include <asm/arch/mbox.h> #include <asm/arch/sdhci.h> #include <asm/global_data.h> @@ -77,3 +79,13 @@ int board_mmc_init(void) return bcm2835_sdhci_init(BCM2835_SDHCI_BASE, msg_clk->get_clock_rate.body.resp.rate_hz); } + +void ft_board_setup(void *blob, bd_t *bd) +{ + /* + * For now, we simply always add the simplefb DT node. Later, we + * should be more intelligent, and e.g. only do this if no enabled DT + * node exists for the "real" graphics driver. + */ + lcd_dt_simplefb_add_node(blob); +} diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 06e8f07c4e..638cc4d68b 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -297,6 +297,15 @@ static struct emif_regs ddr3_evm_emif_reg_data = { .emif_ddr_phy_ctlr_1 = MT41J512M8RH125_EMIF_READ_LATENCY | PHY_EN_DYN_PWRDN, }; + +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + /* break into full u-boot on 'c' */ + return (serial_tstc() && serial_getc() == 'c'); +} +#endif + #endif /* diff --git a/common/board_f.c b/common/board_f.c index 81edbdf8e4..8efdb63655 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -421,19 +421,18 @@ static int setup_dest_addr(void) #endif gd->ram_top += get_effective_memsize(); gd->ram_top = board_get_usable_ram_top(gd->mon_len); - gd->dest_addr = gd->ram_top; + gd->relocaddr = gd->ram_top; debug("Ram top: %08lX\n", (ulong)gd->ram_top); #if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) /* * We need to make sure the location we intend to put secondary core * boot code is reserved and not used by any part of u-boot */ - if (gd->dest_addr > determine_mp_bootpg(NULL)) { - gd->dest_addr = determine_mp_bootpg(NULL); - debug("Reserving MP boot page to %08lx\n", gd->dest_addr); + if (gd->relocaddr > determine_mp_bootpg(NULL)) { + gd->relocaddr = determine_mp_bootpg(NULL); + debug("Reserving MP boot page to %08lx\n", gd->relocaddr); } #endif - gd->dest_addr_sp = gd->dest_addr; return 0; } @@ -441,9 +440,9 @@ static int setup_dest_addr(void) static int reserve_logbuffer(void) { /* reserve kernel log buffer */ - gd->dest_addr -= LOGBUFF_RESERVE; + gd->relocaddr -= LOGBUFF_RESERVE; debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, - gd->dest_addr); + gd->relocaddr); return 0; } #endif @@ -455,9 +454,9 @@ static int reserve_pram(void) ulong reg; reg = getenv_ulong("pram", 10, CONFIG_PRAM); - gd->dest_addr -= (reg << 10); /* size is in kB */ + gd->relocaddr -= (reg << 10); /* size is in kB */ debug("Reserving %ldk for protected RAM at %08lx\n", reg, - gd->dest_addr); + gd->relocaddr); return 0; } #endif /* CONFIG_PRAM */ @@ -465,7 +464,7 @@ static int reserve_pram(void) /* Round memory pointer down to next 4 kB limit */ static int reserve_round_4k(void) { - gd->dest_addr &= ~(4096 - 1); + gd->relocaddr &= ~(4096 - 1); return 0; } @@ -475,12 +474,12 @@ static int reserve_mmu(void) { /* reserve TLB table */ gd->arch.tlb_size = 4096 * 4; - gd->dest_addr -= gd->arch.tlb_size; + gd->relocaddr -= gd->arch.tlb_size; /* round down to next 64 kB limit */ - gd->dest_addr &= ~(0x10000 - 1); + gd->relocaddr &= ~(0x10000 - 1); - gd->arch.tlb_addr = gd->dest_addr; + gd->arch.tlb_addr = gd->relocaddr; debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr, gd->arch.tlb_addr + gd->arch.tlb_size); return 0; @@ -494,8 +493,8 @@ static int reserve_lcd(void) gd->fb_base = CONFIG_FB_ADDR; #else /* reserve memory for LCD display (always full pages) */ - gd->dest_addr = lcd_setmem(gd->dest_addr); - gd->fb_base = gd->dest_addr; + gd->relocaddr = lcd_setmem(gd->relocaddr); + gd->fb_base = gd->relocaddr; #endif /* CONFIG_FB_ADDR */ return 0; } @@ -506,8 +505,8 @@ static int reserve_lcd(void) static int reserve_video(void) { /* reserve memory for video display (always full pages) */ - gd->dest_addr = video_setmem(gd->dest_addr); - gd->fb_base = gd->dest_addr; + gd->relocaddr = video_setmem(gd->relocaddr); + gd->fb_base = gd->relocaddr; return 0; } @@ -519,15 +518,18 @@ static int reserve_uboot(void) * reserve memory for U-Boot code, data & bss * round down to next 4 kB limit */ - gd->dest_addr -= gd->mon_len; - gd->dest_addr &= ~(4096 - 1); + gd->relocaddr -= gd->mon_len; + gd->relocaddr &= ~(4096 - 1); #ifdef CONFIG_E500 /* round down to next 64 kB limit so that IVPR stays aligned */ - gd->dest_addr &= ~(65536 - 1); + gd->relocaddr &= ~(65536 - 1); #endif debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, - gd->dest_addr); + gd->relocaddr); + + gd->start_addr_sp = gd->relocaddr; + return 0; } @@ -535,20 +537,20 @@ static int reserve_uboot(void) /* reserve memory for malloc() area */ static int reserve_malloc(void) { - gd->dest_addr_sp = gd->dest_addr - TOTAL_MALLOC_LEN; + gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN; debug("Reserving %dk for malloc() at: %08lx\n", - TOTAL_MALLOC_LEN >> 10, gd->dest_addr_sp); + TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); return 0; } /* (permanently) allocate a Board Info struct */ static int reserve_board(void) { - gd->dest_addr_sp -= sizeof(bd_t); - gd->bd = (bd_t *)map_sysmem(gd->dest_addr_sp, sizeof(bd_t)); + gd->start_addr_sp -= sizeof(bd_t); + gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); memset(gd->bd, '\0', sizeof(bd_t)); debug("Reserving %zu Bytes for Board Info at: %08lx\n", - sizeof(bd_t), gd->dest_addr_sp); + sizeof(bd_t), gd->start_addr_sp); return 0; } #endif @@ -563,10 +565,10 @@ static int setup_machine(void) static int reserve_global_data(void) { - gd->dest_addr_sp -= sizeof(gd_t); - gd->new_gd = (gd_t *)map_sysmem(gd->dest_addr_sp, sizeof(gd_t)); + gd->start_addr_sp -= sizeof(gd_t); + gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); debug("Reserving %zu Bytes for Global Data at: %08lx\n", - sizeof(gd_t), gd->dest_addr_sp); + sizeof(gd_t), gd->start_addr_sp); return 0; } @@ -580,10 +582,10 @@ static int reserve_fdt(void) if (gd->fdt_blob) { gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); - gd->dest_addr_sp -= gd->fdt_size; - gd->new_fdt = map_sysmem(gd->dest_addr_sp, gd->fdt_size); + gd->start_addr_sp -= gd->fdt_size; + gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size); debug("Reserving %lu Bytes for FDT at: %08lx\n", - gd->fdt_size, gd->dest_addr_sp); + gd->fdt_size, gd->start_addr_sp); } return 0; @@ -593,8 +595,8 @@ static int reserve_stacks(void) { #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_ARM - gd->dest_addr_sp -= 128; /* leave 32 words for abort-stack */ - gd->irq_sp = gd->dest_addr_sp; + gd->start_addr_sp -= 128; /* leave 32 words for abort-stack */ + gd->irq_sp = gd->start_addr_sp; # endif #else # ifdef CONFIG_PPC @@ -602,9 +604,9 @@ static int reserve_stacks(void) # endif /* setup stack pointer for exceptions */ - gd->dest_addr_sp -= 16; - gd->dest_addr_sp &= ~0xf; - gd->irq_sp = gd->dest_addr_sp; + gd->start_addr_sp -= 16; + gd->start_addr_sp &= ~0xf; + gd->irq_sp = gd->start_addr_sp; /* * Handle architecture-specific things here @@ -613,18 +615,18 @@ static int reserve_stacks(void) */ # ifdef CONFIG_ARM # ifdef CONFIG_USE_IRQ - gd->dest_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ); + gd->start_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ); debug("Reserving %zu Bytes for IRQ stack at: %08lx\n", - CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ, gd->dest_addr_sp); + CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ, gd->start_addr_sp); /* 8-byte alignment for ARM ABI compliance */ - gd->dest_addr_sp &= ~0x07; + gd->start_addr_sp &= ~0x07; # endif /* leave 3 words for abort-stack, plus 1 for alignment */ - gd->dest_addr_sp -= 16; + gd->start_addr_sp -= 16; # elif defined(CONFIG_PPC) /* Clear initial stack frame */ - s = (ulong *) gd->dest_addr_sp; + s = (ulong *) gd->start_addr_sp; *s = 0; /* Terminate back chain */ *++s = 0; /* NULL return address */ # endif /* Architecture specific code */ @@ -635,7 +637,7 @@ static int reserve_stacks(void) static int display_new_sp(void) { - debug("New Stack Pointer is: %08lx\n", gd->dest_addr_sp); + debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp); return 0; } @@ -757,15 +759,13 @@ static int reloc_fdt(void) static int setup_reloc(void) { - gd->relocaddr = gd->dest_addr; - gd->start_addr_sp = gd->dest_addr_sp; - gd->reloc_off = gd->dest_addr - CONFIG_SYS_TEXT_BASE; + gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); debug("Relocation Offset is: %08lx\n", gd->reloc_off); debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n", - gd->dest_addr, (ulong)map_to_sysmem(gd->new_gd), - gd->dest_addr_sp); + gd->relocaddr, (ulong)map_to_sysmem(gd->new_gd), + gd->start_addr_sp); return 0; } @@ -794,7 +794,7 @@ static int jump_to_copy(void) #elif defined(CONFIG_SANDBOX) board_init_r(gd->new_gd, 0); #else - relocate_code(gd->dest_addr_sp, gd->new_gd, gd->dest_addr); + relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr); #endif return 0; @@ -851,12 +851,6 @@ static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_ARM timer_init, /* initialize timer */ #endif -#ifdef CONFIG_BOARD_POSTCLK_INIT - board_postclk_init, -#endif -#ifdef CONFIG_FSL_ESDHC - get_clocks, -#endif #ifdef CONFIG_SYS_ALLOC_DPRAM #if !defined(CONFIG_CPM2) dpram_init, @@ -865,6 +859,9 @@ static init_fnc_t init_sequence_f[] = { #if defined(CONFIG_BOARD_POSTCLK_INIT) board_postclk_init, #endif +#ifdef CONFIG_FSL_ESDHC + get_clocks, +#endif env_init, /* initialize environment */ #if defined(CONFIG_8xx_CPUCLK_DEFAULT) /* get CPU and bus clocks according to the environment variable */ diff --git a/common/board_r.c b/common/board_r.c index fd1fd319b6..f5649c95f1 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -137,7 +137,7 @@ static int initr_reloc_global_data(void) #ifdef CONFIG_SYS_SYM_OFFSETS monitor_flash_len = _end_ofs; #elif !defined(CONFIG_SANDBOX) - monitor_flash_len = (ulong)&__init_end - gd->dest_addr; + monitor_flash_len = (ulong)&__init_end - gd->relocaddr; #endif #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* @@ -145,7 +145,7 @@ static int initr_reloc_global_data(void) * We need to update it to point to the same CPU entry in RAM. * TODO: why not just add gd->reloc_ofs? */ - gd->arch.cpu += gd->dest_addr - CONFIG_SYS_MONITOR_BASE; + gd->arch.cpu += gd->relocaddr - CONFIG_SYS_MONITOR_BASE; /* * If we didn't know the cpu mask & # cores, we can save them of @@ -161,7 +161,7 @@ static int initr_reloc_global_data(void) * in SRAM mode and initialize that cache from SRAM mode back to being * a cache in cpu_init_r. */ - gd->env_addr += gd->dest_addr - CONFIG_SYS_MONITOR_BASE; + gd->env_addr += gd->relocaddr - CONFIG_SYS_MONITOR_BASE; #endif return 0; } @@ -178,7 +178,7 @@ static int initr_trap(void) /* * Setup trap handlers */ - trap_init(gd->dest_addr); + trap_init(gd->relocaddr); return 0; } @@ -263,7 +263,7 @@ static int initr_malloc(void) ulong malloc_start; /* The malloc area is immediately below the monitor copy in DRAM */ - malloc_start = gd->dest_addr - TOTAL_MALLOC_LEN; + malloc_start = gd->relocaddr - TOTAL_MALLOC_LEN; mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN), TOTAL_MALLOC_LEN); return 0; @@ -276,7 +276,7 @@ __weak int power_init_board(void) static int initr_announce(void) { - debug("Now running in RAM - U-Boot at: %08lx\n", gd->dest_addr); + debug("Now running in RAM - U-Boot at: %08lx\n", gd->relocaddr); return 0; } diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 15f4599d45..05130b6936 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -93,11 +93,6 @@ static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); static void fixup_silent_linux(void); #endif -static image_header_t *image_get_kernel(ulong img_addr, int verify); -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify); -#endif - static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); @@ -306,7 +301,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, &images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); if (ret) { puts("Could not find a valid device tree\n"); @@ -336,12 +331,15 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) ulong image_len = os.image_len; __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; int no_overlap = 0; + void *load_buf, *image_buf; #if defined(CONFIG_LZMA) || defined(CONFIG_LZO) int ret; #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ const char *type_name = genimg_get_type_name(os.type); + load_buf = map_sysmem(load, image_len); + image_buf = map_sysmem(image_start, image_len); switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) { @@ -349,8 +347,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) no_overlap = 1; } else { printf(" Loading %s ... ", type_name); - memmove_wd((void *)load, (void *)image_start, - image_len, CHUNKSZ); + memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); @@ -358,8 +355,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing %s ... ", type_name); - if (gunzip((void *)load, unc_len, - (uchar *)image_start, &image_len) != 0) { + if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) { puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) @@ -378,9 +374,9 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - int i = BZ2_bzBuffToBuffDecompress((char *)load, - &unc_len, (char *)image_start, image_len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len, + image_buf, image_len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); @@ -397,9 +393,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) SizeT lzma_len = unc_len; printf(" Uncompressing %s ... ", type_name); - ret = lzmaBuffToBuffDecompress( - (unsigned char *)load, &lzma_len, - (unsigned char *)image_start, image_len); + ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, + image_buf, image_len); unc_len = lzma_len; if (ret != SZ_OK) { printf("LZMA: uncompress or overwrite error %d " @@ -415,9 +410,8 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) case IH_COMP_LZO: printf(" Uncompressing %s ... ", type_name); - ret = lzop_decompress((const unsigned char *)image_start, - image_len, (unsigned char *)load, - &unc_len); + ret = lzop_decompress(image_buf, image_len, load_buf, + &unc_len); if (ret != LZO_E_OK) { printf("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); @@ -797,54 +791,6 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) } /** - * fit_check_kernel - verify FIT format kernel subimage - * @fit_hdr: pointer to the FIT image header - * os_noffset: kernel subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_kernel() verifies integrity of the kernel subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -#if defined(CONFIG_FIT) -static int fit_check_kernel(const void *fit, int os_noffset, int verify) -{ - fit_image_print(fit, os_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, os_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH); - return 0; - } - puts("OK\n"); - } - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH); - - if (!fit_image_check_target_arch(fit, os_noffset)) { - puts("Unsupported Architecture\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) && - !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) { - puts("Not a kernel image\n"); - bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL); - return 0; - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED); - return 1; -} -#endif /* CONFIG_FIT */ - -/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length @@ -864,12 +810,8 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, ulong img_addr; const void *buf; #if defined(CONFIG_FIT) - const void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; - const void *data; - size_t len; - int cfg_noffset; int os_noffset; #endif @@ -946,84 +888,16 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Booting kernel from FIT Image at %08lx ...\n", - img_addr); - - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT kernel image format!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); + os_noffset = fit_image_load(images, FIT_KERNEL_PROP, + img_addr, + &fit_uname_kernel, fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_KERNEL, + BOOTSTAGE_ID_FIT_KERNEL_START, + FIT_LOAD_IGNORED, os_data, os_len); + if (os_noffset < 0) return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); - - if (!fit_uname_kernel) { - /* - * no kernel image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config - * node - */ - bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); -#ifdef CONFIG_FIT_BEST_MATCH - if (fit_uname_config) - cfg_noffset = - fit_conf_get_node(fit_hdr, - fit_uname_config); - else - cfg_noffset = - fit_conf_find_compat(fit_hdr, - gd->fdt_blob); -#else - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); -#endif - if (cfg_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); - return NULL; - } - /* save configuration uname provided in the first - * bootm argument - */ - images->fit_uname_cfg = fdt_get_name(fit_hdr, - cfg_noffset, - NULL); - printf(" Using '%s' configuration\n", - images->fit_uname_cfg); - bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); - - os_noffset = fit_conf_get_kernel_node(fit_hdr, - cfg_noffset); - fit_uname_kernel = fit_get_name(fit_hdr, os_noffset, - NULL); - } else { - /* get kernel component image node offset */ - bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME); - os_noffset = fit_image_get_node(fit_hdr, - fit_uname_kernel); - } - if (os_noffset < 0) { - bootstage_error(BOOTSTAGE_ID_FIT_CONFIG); - return NULL; - } - - printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); - - bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE); - if (!fit_check_kernel(fit_hdr, os_noffset, images->verify)) - return NULL; - - /* get kernel image data address and length */ - if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { - puts("Could not find kernel subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR); - return NULL; - } - bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO); - *os_len = len; - *os_data = (ulong)data; - images->fit_hdr_os = (void *)fit_hdr; + images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; @@ -1820,7 +1694,7 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc, #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, images, + ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images, &images->ft_addr, &images->ft_len); if (ret) { puts("Could not find a valid device tree\n"); diff --git a/common/cmd_fitupd.c b/common/cmd_fitupd.c index 7a3789e3ed..618ff7c8d6 100644 --- a/common/cmd_fitupd.c +++ b/common/cmd_fitupd.c @@ -8,13 +8,12 @@ #include <common.h> #include <command.h> +#include <net.h> #if !defined(CONFIG_UPDATE_TFTP) #error "CONFIG_UPDATE_TFTP required" #endif -extern int update_tftp(ulong addr); - static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr = 0UL; diff --git a/common/cmd_immap.c b/common/cmd_immap.c index fdf9489b2e..bb15795e22 100644 --- a/common/cmd_immap.c +++ b/common/cmd_immap.c @@ -535,7 +535,7 @@ do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) volatile iic_t *iip; uint dpaddr; - dpaddr = *((unsigned short *) (&immap->im_dprambase[PROFF_I2C_BASE])); + dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; if (dpaddr == 0) iip = NULL; else diff --git a/common/cmd_nand.c b/common/cmd_nand.c index e9d3d3c1bf..8b1e01ae80 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -62,8 +62,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) ops.oobbuf = oobbuf; ops.len = nand->writesize; ops.ooblen = nand->oobsize; - ops.mode = MTD_OOB_RAW; - i = nand->read_oob(nand, addr, &ops); + ops.mode = MTD_OPS_RAW; + i = mtd_read_oob(nand, addr, &ops); if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); free(datbuf); @@ -404,13 +404,13 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, .oobbuf = ((u8 *)addr) + nand->writesize, .len = nand->writesize, .ooblen = nand->oobsize, - .mode = MTD_OOB_RAW + .mode = MTD_OPS_RAW }; if (read) - ret = nand->read_oob(nand, off, &ops); + ret = mtd_read_oob(nand, off, &ops); else - ret = nand->write_oob(nand, off, &ops); + ret = mtd_write_oob(nand, off, &ops); if (ret) { printf("%s: error at offset %llx, ret %d\n", @@ -425,6 +425,31 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, return ret; } +/* Adjust a chip/partition size down for bad blocks so we don't + * read/write/erase past the end of a chip/partition by accident. + */ +static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev) +{ + /* We grab the nand info object here fresh because this is usually + * called after arg_off_size() which can change the value of dev. + */ + nand_info_t *nand = &nand_info[dev]; + loff_t maxoffset = offset + *size; + int badblocks = 0; + + /* count badblocks in NAND from offset to offset + size */ + for (; offset < maxoffset; offset += nand->erasesize) { + if (nand_block_isbad(nand, offset)) + badblocks++; + } + /* adjust size if any bad blocks found */ + if (badblocks) { + *size -= badblocks * nand->erasesize; + printf("size adjusted to 0x%llx (%d bad blocks)\n", + (unsigned long long)*size, badblocks); + } +} + static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int i, ret = 0; @@ -521,6 +546,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int scrub = !strncmp(cmd, "scrub", 5); int spread = 0; int args = 2; + int adjust_size = 0; const char *scrub_warn = "Warning: " "scrub option will erase all factory set bad blocks!\n" @@ -537,8 +563,10 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) spread = 1; } else if (!strcmp(&cmd[5], ".part")) { args = 1; + adjust_size = 1; } else if (!strcmp(&cmd[5], ".chip")) { args = 0; + adjust_size = 1; } else { goto usage; } @@ -558,6 +586,10 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) &maxsize) != 0) return 1; + /* size is unspecified */ + if (adjust_size && !scrub) + adjust_size_for_badblocks(&size, off, dev); + nand = &nand_info[dev]; memset(&opts, 0, sizeof(opts)); @@ -642,6 +674,9 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) &off, &size, &maxsize) != 0) return 1; + /* size is unspecified */ + if (argc < 5) + adjust_size_for_badblocks(&size, off, dev); rwsize = size; } @@ -680,13 +715,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) mtd_oob_ops_t ops = { .oobbuf = (u8 *)addr, .ooblen = rwsize, - .mode = MTD_OOB_RAW + .mode = MTD_OPS_RAW }; if (read) - ret = nand->read_oob(nand, off, &ops); + ret = mtd_read_oob(nand, off, &ops); else - ret = nand->write_oob(nand, off, &ops); + ret = mtd_write_oob(nand, off, &ops); } else if (raw) { ret = raw_access(nand, addr, off, pagecount, read); } else { @@ -729,7 +764,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) while (argc > 0) { addr = simple_strtoul(*argv, NULL, 16); - if (nand->block_markbad(nand, addr)) { + if (mtd_block_markbad(nand, addr)) { printf("block 0x%08lx NOT marked " "as bad! ERROR %d\n", addr, ret); diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index a0d25e5521..06cc140567 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -83,7 +83,7 @@ static int onenand_block_read(loff_t from, size_t len, ops.len = blocksize; while (blocks) { - ret = mtd->block_isbad(mtd, ofs); + ret = mtd_block_isbad(mtd, ofs); if (ret) { printk("Bad blocks %d at 0x%x\n", (u32)(ofs >> this->erase_shift), (u32)ofs); @@ -97,7 +97,7 @@ static int onenand_block_read(loff_t from, size_t len, ops.datbuf = buf; ops.retlen = 0; - ret = mtd->read_oob(mtd, ofs, &ops); + ret = mtd_read_oob(mtd, ofs, &ops); if (ret) { printk("Read failed 0x%x, %d\n", (u32)ofs, ret); ofs += blocksize; @@ -118,7 +118,7 @@ static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf, struct mtd_oob_ops ops = { .len = mtd->writesize, .ooblen = mtd->oobsize, - .mode = MTD_OOB_AUTO, + .mode = MTD_OPS_AUTO_OOB, }; int page, ret = 0; for (page = 0; page < (mtd->erasesize / mtd->writesize); page ++) { @@ -126,7 +126,7 @@ static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf, buf += mtd->writesize; ops.oobbuf = (u_char *)buf; buf += mtd->oobsize; - ret = mtd->write_oob(mtd, to, &ops); + ret = mtd_write_oob(mtd, to, &ops); if (ret) break; to += mtd->writesize; @@ -156,7 +156,7 @@ static int onenand_block_write(loff_t to, size_t len, ofs = to; while (blocks) { - ret = mtd->block_isbad(mtd, ofs); + ret = mtd_block_isbad(mtd, ofs); if (ret) { printk("Bad blocks %d at 0x%x\n", (u32)(ofs >> this->erase_shift), (u32)ofs); @@ -165,7 +165,7 @@ static int onenand_block_write(loff_t to, size_t len, } if (!withoob) - ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf); + ret = mtd_write(mtd, ofs, blocksize, &_retlen, buf); else ret = onenand_write_oneblock_withoob(ofs, buf, &_retlen); if (ret) { @@ -195,7 +195,7 @@ static int onenand_block_erase(u32 start, u32 size, int force) int blocksize = 1 << this->erase_shift; for (ofs = start; ofs < (start + size); ofs += blocksize) { - ret = mtd->block_isbad(mtd, ofs); + ret = mtd_block_isbad(mtd, ofs); if (ret && !force) { printf("Skip erase bad block %d at 0x%x\n", (u32)(ofs >> this->erase_shift), (u32)ofs); @@ -206,7 +206,7 @@ static int onenand_block_erase(u32 start, u32 size, int force) instr.len = blocksize; instr.priv = force; instr.mtd = mtd; - ret = mtd->erase(mtd, &instr); + ret = mtd_erase(mtd, &instr); if (ret) { printf("erase failed block %d at 0x%x\n", (u32)(ofs >> this->erase_shift), (u32)ofs); @@ -261,7 +261,7 @@ static int onenand_block_test(u32 start, u32 size) while (blocks < end_block) { printf("\rTesting block %d at 0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs); - ret = mtd->block_isbad(mtd, ofs); + ret = mtd_block_isbad(mtd, ofs); if (ret) { printf("Skip erase bad block %d at 0x%x\n", (u32)(ofs >> this->erase_shift), (u32)ofs); @@ -270,19 +270,19 @@ static int onenand_block_test(u32 start, u32 size) instr.addr = ofs; instr.len = blocksize; - ret = mtd->erase(mtd, &instr); + ret = mtd_erase(mtd, &instr); if (ret) { printk("Erase failed 0x%x, %d\n", (u32)ofs, ret); goto next; } - ret = mtd->write(mtd, ofs, blocksize, &retlen, buf); + ret = mtd_write(mtd, ofs, blocksize, &retlen, buf); if (ret) { printk("Write failed 0x%x, %d\n", (u32)ofs, ret); goto next; } - ret = mtd->read(mtd, ofs, blocksize, &retlen, verify_buf); + ret = mtd_read(mtd, ofs, blocksize, &retlen, verify_buf); if (ret) { printk("Read failed 0x%x, %d\n", (u32)ofs, ret); goto next; @@ -324,7 +324,7 @@ static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob) ops.len = mtd->writesize; ops.ooblen = mtd->oobsize; ops.retlen = 0; - i = mtd->read_oob(mtd, addr, &ops); + i = mtd_read_oob(mtd, addr, &ops); if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); free(datbuf); @@ -373,7 +373,7 @@ static int do_onenand_bad(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar /* Currently only one OneNAND device is supported */ printf("\nDevice %d bad blocks:\n", 0); for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) { - if (mtd->block_isbad(mtd, ofs)) + if (mtd_block_isbad(mtd, ofs)) printf(" %08x\n", (u32)ofs); } @@ -530,7 +530,7 @@ static int do_onenand_markbad(cmd_tbl_t * cmdtp, int flag, int argc, char * cons while (argc > 0) { addr = simple_strtoul(*argv, NULL, 16); - if (mtd->block_markbad(mtd, addr)) { + if (mtd_block_markbad(mtd, addr)) { printf("block 0x%08lx NOT marked " "as bad! ERROR %d\n", addr, ret); diff --git a/common/env_onenand.c b/common/env_onenand.c index faa903d2f0..e8bde37266 100644 --- a/common/env_onenand.c +++ b/common/env_onenand.c @@ -68,7 +68,7 @@ void env_relocate_spec(void) /* Check OneNAND exist */ if (mtd->writesize) /* Ignore read fail */ - mtd->read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, + mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, (u_char *)buf); else mtd->writesize = MAX_ONENAND_PAGESIZE; @@ -113,12 +113,12 @@ int saveenv(void) #endif instr.addr = env_addr; instr.mtd = mtd; - if (mtd->erase(mtd, &instr)) { + if (mtd_erase(mtd, &instr)) { printf("OneNAND: erase failed at 0x%08llx\n", env_addr); return 1; } - if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, + if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, (u_char *)&env_new)) { printf("OneNAND: write failed at 0x%llx\n", instr.addr); return 2; diff --git a/common/fdt_support.c b/common/fdt_support.c index 416100e394..9a6f6b7d8b 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -458,7 +458,7 @@ void fdt_fixup_ethernet(void *fdt) { int node, i, j; char enet[16], *tmp, *end; - char mac[16] = "ethaddr"; + char mac[16]; const char *path; unsigned char mac_addr[6]; @@ -467,6 +467,7 @@ void fdt_fixup_ethernet(void *fdt) return; i = 0; + strcpy(mac, "ethaddr"); while ((tmp = getenv(mac)) != NULL) { sprintf(enet, "ethernet%d", i); path = fdt_getprop(fdt, node, enet, NULL); diff --git a/common/image-fdt.c b/common/image-fdt.c index 158c9cfbf5..0d421d92fb 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -211,51 +211,11 @@ error: return 1; } -#if defined(CONFIG_FIT) -/** - * fit_check_fdt - verify FIT format FDT subimage - * @fit_hdr: pointer to the FIT header - * fdt_noffset: FDT subimage node offset within FIT image - * @verify: data CRC verification flag - * - * fit_check_fdt() verifies integrity of the FDT subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) -{ - fit_image_print(fit, fdt_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, fdt_noffset)) { - fdt_error("Bad Data Hash"); - return 0; - } - puts("OK\n"); - } - - if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) { - fdt_error("Not a FDT image"); - return 0; - } - - if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) { - fdt_error("FDT image is compressed"); - return 0; - } - - return 1; -} -#endif - /** * boot_get_fdt - main fdt handling routine * @argc: command argument count * @argv: command argument list + * @arch: architecture (IH_ARCH_...) * @images: pointer to the bootm images structure * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length @@ -273,24 +233,20 @@ static int fit_check_fdt(const void *fit, int fdt_noffset, int verify) * 1, if fdt image is found but corrupted * of_flat_tree and of_size are set to 0 if no fdt exists */ -int boot_get_fdt(int flag, int argc, char * const argv[], +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, bootm_headers_t *images, char **of_flat_tree, ulong *of_size) { const image_header_t *fdt_hdr; ulong fdt_addr; char *fdt_blob = NULL; ulong image_start, image_data, image_end; - ulong load_start, load_end; + ulong load, load_end; void *buf; #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_fdt = NULL; ulong default_addr; - int cfg_noffset; int fdt_noffset; - const void *data; - size_t size; #endif *of_flat_tree = NULL; @@ -333,31 +289,15 @@ int boot_get_fdt(int flag, int argc, char * const argv[], * command argument */ fdt_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* fdt: using config '%s' from image at 0x%08lx\n", - fit_uname_config, fdt_addr); - - /* - * Check whether configuration has FDT blob defined, - * if not quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* fdt: no such config\n"); + fdt_noffset = fit_get_node_from_config(images, + FIT_FDT_PROP, + fdt_addr); + if (fdt_noffset == -ENOLINK) return 0; - } - - fdt_noffset = fit_conf_get_fdt_node(fit_hdr, - cfg_noffset); - if (fdt_noffset < 0) { - debug("* fdt: no fdt in config\n"); - return 0; - } + else if (fdt_noffset < 0) + return 1; } #endif - debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", fdt_addr); @@ -387,29 +327,28 @@ int boot_get_fdt(int flag, int argc, char * const argv[], image_data = (ulong)image_get_data(fdt_hdr); image_end = image_get_image_end(fdt_hdr); - load_start = image_get_load(fdt_hdr); - load_end = load_start + image_get_data_size(fdt_hdr); + load = image_get_load(fdt_hdr); + load_end = load + image_get_data_size(fdt_hdr); - if (load_start == image_start || - load_start == image_data) { + if (load == image_start || + load == image_data) { fdt_blob = (char *)image_data; break; } - if ((load_start < image_end) && - (load_end > image_start)) { + if ((load < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); goto error; } debug(" Loading FDT from 0x%08lx to 0x%08lx\n", - image_data, load_start); + image_data, load); - memmove((void *)load_start, + memmove((void *)load, (void *)image_data, image_get_data_size(fdt_hdr)); - fdt_blob = (char *)load_start; + fdt_addr = load; break; case IMAGE_FORMAT_FIT: /* @@ -420,107 +359,20 @@ int boot_get_fdt(int flag, int argc, char * const argv[], #if defined(CONFIG_FIT) /* check FDT blob vs FIT blob */ if (fit_check_format(buf)) { - /* - * FIT image - */ - fit_hdr = buf; - printf("## Flattened Device Tree from FIT Image at %08lx\n", - fdt_addr); - - if (!fit_uname_fdt) { - /* - * no FDT blob image node unit name, - * try to get config node first. If - * config unit node name is NULL - * fit_conf_get_node() will try to - * find default config node - */ - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - - if (cfg_noffset < 0) { - fdt_error("Could not find configuration node\n"); - goto error; - } - - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - fdt_noffset = fit_conf_get_fdt_node( - fit_hdr, - cfg_noffset); - fit_uname_fdt = fit_get_name(fit_hdr, - fdt_noffset, NULL); - } else { - /* - * get FDT component image node - * offset - */ - fdt_noffset = fit_image_get_node( - fit_hdr, - fit_uname_fdt); - } - if (fdt_noffset < 0) { - fdt_error("Could not find subimage node\n"); - goto error; - } - - printf(" Trying '%s' FDT blob subimage\n", - fit_uname_fdt); - - if (!fit_check_fdt(fit_hdr, fdt_noffset, - images->verify)) - goto error; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, fdt_noffset, - &data, &size)) { - fdt_error("Could not find FDT subimage data"); - goto error; - } + ulong load, len; - /* - * verify that image data is a proper FDT - * blob - */ - if (fdt_check_header((char *)data) != 0) { - fdt_error("Subimage data is not a FTD"); - goto error; - } - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = (ulong)fit_hdr; - image_end = fit_get_end(fit_hdr); - - if (fit_image_get_load(fit_hdr, fdt_noffset, - &load_start) == 0) { - load_end = load_start + size; + fdt_noffset = fit_image_load(images, + FIT_FDT_PROP, + fdt_addr, &fit_uname_fdt, + fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); - if ((load_start < image_end) && - (load_end > image_start)) { - fdt_error("FDT overwritten"); - goto error; - } - - printf(" Loading FDT from 0x%08lx to 0x%08lx\n", - (ulong)data, load_start); - - memmove((void *)load_start, - (void *)data, size); - - fdt_blob = (char *)load_start; - } else { - fdt_blob = (char *)data; - } - - images->fit_hdr_fdt = fit_hdr; + images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; + fdt_addr = load; break; } else #endif @@ -528,7 +380,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], /* * FDT blob */ - fdt_blob = buf; debug("* fdt: raw FDT blob\n"); printf("## Flattened Device Tree blob at %08lx\n", (long)fdt_addr); @@ -539,8 +390,8 @@ int boot_get_fdt(int flag, int argc, char * const argv[], goto error; } - printf(" Booting using the fdt blob at 0x%p\n", fdt_blob); - + printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); + fdt_blob = map_sysmem(fdt_addr, 0); } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { diff --git a/common/image-fit.c b/common/image-fit.c index 254feecaad..7bf82d33cf 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -31,6 +31,9 @@ #include <time.h> #else #include <common.h> +#include <errno.h> +#include <asm/io.h> +DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <bootstage.h> @@ -348,10 +351,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) #ifndef USE_HOSTCC printf("%s Data Start: ", p); - if (ret) + if (ret) { printf("unavailable\n"); - else - printf("0x%08lx\n", (ulong)data); + } else { + void *vdata = (void *)data; + + printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); + } #endif printf("%s Data Size: ", p); @@ -1349,63 +1355,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset, } /** - * fit_conf_get_kernel_node - get kernel image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_kernel_node() retrives kernel image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_kernel_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP); -} - -/** - * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_ramdisk_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP); -} - -/** - * fit_conf_get_fdt_node - get fdt image node offset that corresponds to - * a given configuration - * @fit: pointer to the FIT format image header - * @noffset: configuration node offset - * - * fit_conf_get_fdt_node() retrives fdt image node unit name from - * configuration FIT_KERNEL_PROP property and translates it to the node - * offset. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_conf_get_fdt_node(const void *fit, int noffset) -{ - return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP); -} - -/** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header * @noffset: offset of the configuration node @@ -1448,22 +1397,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) printf("%s FDT: %s\n", p, uname); } -/** - * fit_check_ramdisk - verify FIT format ramdisk subimage - * @fit_hdr: pointer to the FIT ramdisk header - * @rd_noffset: ramdisk subimage node offset within FIT image - * @arch: requested ramdisk image architecture type - * @verify: data CRC verification flag - * - * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from - * specified FIT image. - * - * returns: - * 1, on success - * 0, on failure - */ -int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, - int verify) +int fit_image_select(const void *fit, int rd_noffset, int verify) { fit_image_print(fit, rd_noffset, " "); @@ -1471,22 +1405,222 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, puts(" Verifying Hash Integrity ... "); if (!fit_image_verify(fit, rd_noffset)) { puts("Bad Data Hash\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH); - return 0; + return -EACCES; } puts("OK\n"); } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) || - !fit_image_check_arch(fit, rd_noffset, arch) || - !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) { - printf("No Linux %s Ramdisk Image\n", - genimg_get_arch_name(arch)); - bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); - return 0; + return 0; +} + +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr) +{ + int cfg_noffset; + void *fit_hdr; + int noffset; + + debug("* %s: using config '%s' from image at 0x%08lx\n", + prop_name, images->fit_uname_cfg, addr); + + /* Check whether configuration has this property defined */ + fit_hdr = map_sysmem(addr, 0); + cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); + if (cfg_noffset < 0) { + debug("* %s: no such config\n", prop_name); + return -ENOENT; } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK); - return 1; + noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); + if (noffset < 0) { + debug("* %s: no '%s' in config\n", prop_name, prop_name); + return -ENOLINK; + } + + return noffset; +} + +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp) +{ + int cfg_noffset, noffset; + const char *fit_uname; + const void *fit; + const void *buf; + size_t size; + int type_ok, os_ok; + ulong load, data, len; + int ret; + + fit = map_sysmem(addr, 0); + fit_uname = fit_unamep ? *fit_unamep : NULL; + printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); + if (!fit_check_format(fit)) { + printf("Bad FIT %s image format!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); + return -ENOEXEC; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); + if (fit_uname) { + /* get ramdisk component image node offset */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); + noffset = fit_image_get_node(fit, fit_uname); + } else { + /* + * no image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); + if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { + cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); + } else { + cfg_noffset = fit_conf_get_node(fit, + fit_uname_config); + } + if (cfg_noffset < 0) { + puts("Could not find configuration node\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_NO_UNIT_NAME); + return -ENOENT; + } + fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); + printf(" Using '%s' configuration\n", fit_uname_config); + if (image_type == IH_TYPE_KERNEL) { + /* Remember (and possibly verify) this config */ + images->fit_uname_cfg = fit_uname_config; + if (IMAGE_ENABLE_VERIFY && images->verify) { + puts(" Verifying Hash Integrity ... "); + if (!fit_config_verify(fit, cfg_noffset)) { + puts("Bad Data Hash\n"); + bootstage_error(bootstage_id + + BOOTSTAGE_SUB_HASH); + return -EACCES; + } + puts("OK\n"); + } + bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + } + + noffset = fit_conf_get_prop_node(fit, cfg_noffset, + prop_name); + fit_uname = fit_get_name(fit, noffset, NULL); + } + if (noffset < 0) { + puts("Could not find subimage node\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); + return -ENOENT; + } + + printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); + + ret = fit_image_select(fit, noffset, images->verify); + if (ret) { + bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); + return ret; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + if (!fit_image_check_target_arch(fit, noffset)) { + puts("Unsupported Architecture\n"); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); + return -ENOEXEC; + } + + if (image_type == IH_TYPE_FLATDT && + !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { + puts("FDT image is compressed"); + return -EPROTONOSUPPORT; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); + type_ok = fit_image_check_type(fit, noffset, image_type) || + (image_type == IH_TYPE_KERNEL && + fit_image_check_type(fit, noffset, + IH_TYPE_KERNEL_NOLOAD)); + os_ok = image_type == IH_TYPE_FLATDT || + fit_image_check_os(fit, noffset, IH_OS_LINUX); + if (!type_ok || !os_ok) { + printf("No Linux %s %s Image\n", genimg_get_arch_name(arch), + genimg_get_type_name(image_type)); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); + return -EIO; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); + + /* get image data address and length */ + if (fit_image_get_data(fit, noffset, &buf, &size)) { + printf("Could not find %s subimage data!\n", prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); + return -ENOMEDIUM; + } + len = (ulong)size; + + /* verify that image data is a proper FDT blob */ + if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) { + puts("Subimage data is not a FDT"); + return -ENOEXEC; + } + + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); + + /* + * Work-around for eldk-4.2 which gives this warning if we try to + * case in the unmap_sysmem() call: + * warning: initialization discards qualifiers from pointer target type + */ + { + void *vbuf = (void *)buf; + + data = map_to_sysmem(vbuf); + } + + if (load_op == FIT_LOAD_IGNORED) { + /* Don't load */ + } else if (fit_image_get_load(fit, noffset, &load)) { + if (load_op == FIT_LOAD_REQUIRED) { + printf("Can't get %s subimage load address!\n", + prop_name); + bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); + return -EBADF; + } + } else { + ulong image_start, image_end; + ulong load_end; + void *dst; + + /* + * move image data to the load address, + * make sure we don't overwrite initial image + */ + image_start = addr; + image_end = addr + fit_get_size(fit); + + load_end = load + len; + if (image_type != IH_TYPE_KERNEL && + load < image_end && load_end > image_start) { + printf("Error: %s overwritten\n", prop_name); + return -EXDEV; + } + + printf(" Loading %s from 0x%08lx to 0x%08lx\n", + prop_name, data, load); + + dst = map_sysmem(load, len); + memmove(dst, buf, len); + data = load; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); + + *datap = data; + *lenp = len; + if (fit_unamep) + *fit_unamep = (char *)fit_uname; + + return noffset; } diff --git a/common/image.c b/common/image.c index e91c89e1c5..f863502ab1 100644 --- a/common/image.c +++ b/common/image.c @@ -51,6 +51,7 @@ #include <u-boot/md5.h> #include <sha1.h> +#include <asm/errno.h> #include <asm/io.h> #ifdef CONFIG_CMD_BDI @@ -810,14 +811,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, char *end; #endif #if defined(CONFIG_FIT) - void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_ramdisk = NULL; ulong default_addr; int rd_noffset; - int cfg_noffset; - const void *data; - size_t size; #endif *rd_start = 0; @@ -865,32 +862,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, #if defined(CONFIG_FIT) } else { /* use FIT configuration provided in first bootm - * command argument + * command argument. If the property is not defined, + * quit silently. */ rd_addr = map_to_sysmem(images->fit_hdr_os); - fit_uname_config = images->fit_uname_cfg; - debug("* ramdisk: using config '%s' from image " - "at 0x%08lx\n", - fit_uname_config, rd_addr); - - /* - * Check whether configuration has ramdisk defined, - * if not, don't try to use it, quit silently. - */ - fit_hdr = images->fit_hdr_os; - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - debug("* ramdisk: no such config\n"); - return 1; - } - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - if (rd_noffset < 0) { - debug("* ramdisk: no ramdisk in config\n"); + rd_noffset = fit_get_node_from_config(images, + FIT_RAMDISK_PROP, rd_addr); + if (rd_noffset == -ENOLINK) return 0; - } + else if (rd_noffset < 0) + return 1; } #endif @@ -921,87 +902,16 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_hdr = buf; - printf("## Loading init Ramdisk from FIT " - "Image at %08lx ...\n", rd_addr); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT); - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT ramdisk image format!\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_FORMAT); + rd_noffset = fit_image_load(images, FIT_RAMDISK_PROP, + rd_addr, &fit_uname_ramdisk, + fit_uname_config, arch, + IH_TYPE_RAMDISK, + BOOTSTAGE_ID_FIT_RD_START, + FIT_LOAD_REQUIRED, &rd_data, &rd_len); + if (rd_noffset < 0) return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT_OK); - - if (!fit_uname_ramdisk) { - /* - * no ramdisk image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config node - */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - cfg_noffset = fit_conf_get_node(fit_hdr, - fit_uname_config); - if (cfg_noffset < 0) { - puts("Could not find configuration " - "node\n"); - bootstage_error( - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); - return 1; - } - fit_uname_config = fdt_get_name(fit_hdr, - cfg_noffset, NULL); - printf(" Using '%s' configuration\n", - fit_uname_config); - - rd_noffset = fit_conf_get_ramdisk_node(fit_hdr, - cfg_noffset); - fit_uname_ramdisk = fit_get_name(fit_hdr, - rd_noffset, NULL); - } else { - /* get ramdisk component image node offset */ - bootstage_mark( - BOOTSTAGE_ID_FIT_RD_UNIT_NAME); - rd_noffset = fit_image_get_node(fit_hdr, - fit_uname_ramdisk); - } - if (rd_noffset < 0) { - puts("Could not find subimage node\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_SUBNODE); - return 1; - } - - printf(" Trying '%s' ramdisk subimage\n", - fit_uname_ramdisk); - - bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK); - if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch, - images->verify)) - return 1; - - /* get ramdisk image data address and length */ - if (fit_image_get_data(fit_hdr, rd_noffset, &data, - &size)) { - puts("Could not find ramdisk subimage data!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_GET_DATA); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_GET_DATA_OK); - - rd_data = (ulong)data; - rd_len = size; - - if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) { - puts("Can't get ramdisk subimage load " - "address!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_RD_LOAD); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_FIT_RD_LOAD); - images->fit_hdr_rd = fit_hdr; + images->fit_hdr_rd = map_sysmem(rd_addr, 0); images->fit_uname_rd = fit_uname_ramdisk; images->fit_noffset_rd = rd_noffset; break; diff --git a/common/lcd.c b/common/lcd.c index edae835fb0..3a60484eea 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -57,6 +57,10 @@ #include <atmel_lcdc.h> #endif +#if defined(CONFIG_LCD_DT_SIMPLEFB) +#include <libfdt.h> +#endif + /************************************************************************/ /* ** FONT DATA */ /************************************************************************/ @@ -1182,3 +1186,86 @@ int lcd_get_screen_columns(void) { return CONSOLE_COLS; } + +#if defined(CONFIG_LCD_DT_SIMPLEFB) +static int lcd_dt_simplefb_configure_node(void *blob, int off) +{ + u32 stride; + fdt32_t cells[2]; + int ret; + const char format[] = +#if LCD_BPP == LCD_COLOR16 + "r5g6b5"; +#else + ""; +#endif + + if (!format[0]) + return -1; + + stride = panel_info.vl_col * 2; + + cells[0] = cpu_to_fdt32(gd->fb_base); + cells[1] = cpu_to_fdt32(stride * panel_info.vl_row); + ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(panel_info.vl_col); + ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(panel_info.vl_row); + ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(stride); + ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1); + if (ret < 0) + return -1; + + ret = fdt_delprop(blob, off, "status"); + if (ret < 0) + return -1; + + return 0; +} + +int lcd_dt_simplefb_add_node(void *blob) +{ + const char compat[] = "simple-framebuffer"; + const char disabled[] = "disabled"; + int off, ret; + + off = fdt_add_subnode(blob, 0, "framebuffer"); + if (off < 0) + return -1; + + ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled)); + if (ret < 0) + return -1; + + ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat)); + if (ret < 0) + return -1; + + return lcd_dt_simplefb_configure_node(blob, off); +} + +int lcd_dt_simplefb_enable_existing_node(void *blob) +{ + int off; + + off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer"); + if (off < 0) + return -1; + + return lcd_dt_simplefb_configure_node(blob, off); +} +#endif diff --git a/common/main.c b/common/main.c index 953ef296b1..56da214b26 100644 --- a/common/main.c +++ b/common/main.c @@ -28,26 +28,15 @@ /* #define DEBUG */ #include <common.h> -#include <watchdog.h> #include <command.h> #include <fdtdec.h> -#include <malloc.h> -#include <version.h> -#ifdef CONFIG_MODEM_SUPPORT -#include <malloc.h> /* for free() prototype */ -#endif - -#ifdef CONFIG_SYS_HUSH_PARSER #include <hush.h> -#endif - -#ifdef CONFIG_OF_CONTROL -#include <fdtdec.h> -#endif - +#include <malloc.h> +#include <menu.h> #include <post.h> +#include <version.h> +#include <watchdog.h> #include <linux/ctype.h> -#include <menu.h> DECLARE_GLOBAL_DATA_PTR; @@ -57,13 +46,18 @@ DECLARE_GLOBAL_DATA_PTR; void inline __show_boot_progress (int val) {} void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); -#if defined(CONFIG_UPDATE_TFTP) -int update_tftp (ulong addr); -#endif /* CONFIG_UPDATE_TFTP */ - #define MAX_DELAY_STOP_STR 32 -#undef DEBUG_PARSER +#define DEBUG_PARSER 0 /* set to 1 to debug */ + +#define debug_parser(fmt, args...) \ + debug_cond(DEBUG_PARSER, fmt, ##args) + +#ifndef DEBUG_BOOTKEYS +#define DEBUG_BOOTKEYS 0 +#endif +#define debug_bootkeys(fmt, args...) \ + debug_cond(DEBUG_BOOTKEYS, fmt, ##args) char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ @@ -93,10 +87,7 @@ extern void mdm_init(void); /* defined in board.c */ */ #if defined(CONFIG_BOOTDELAY) # if defined(CONFIG_AUTOBOOT_KEYED) -#ifndef CONFIG_MENU -static inline -#endif -int abortboot(int bootdelay) +static int abortboot_keyed(int bootdelay) { int abort = 0; uint64_t etime = endtick(bootdelay); @@ -152,11 +143,9 @@ int abortboot(int bootdelay) presskey_max = presskey_max > delaykey[i].len ? presskey_max : delaykey[i].len; -# if DEBUG_BOOTKEYS - printf("%s key:<%s>\n", - delaykey[i].retry ? "delay" : "stop", - delaykey[i].str ? delaykey[i].str : "NULL"); -# endif + debug_bootkeys("%s key:<%s>\n", + delaykey[i].retry ? "delay" : "stop", + delaykey[i].str ? delaykey[i].str : "NULL"); } /* In order to keep up with incoming data, check timeout only @@ -181,10 +170,9 @@ int abortboot(int bootdelay) memcmp (presskey + presskey_len - delaykey[i].len, delaykey[i].str, delaykey[i].len) == 0) { -# if DEBUG_BOOTKEYS - printf("got %skey\n", - delaykey[i].retry ? "delay" : "stop"); -# endif + debug_bootkeys("got %skey\n", + delaykey[i].retry ? "delay" : + "stop"); # ifdef CONFIG_BOOT_RETRY_TIME /* don't retry auto boot */ @@ -196,10 +184,8 @@ int abortboot(int bootdelay) } } while (!abort && get_ticks() <= etime); -# if DEBUG_BOOTKEYS if (!abort) - puts("key timeout\n"); -# endif + debug_bootkeys("key timeout\n"); #ifdef CONFIG_SILENT_CONSOLE if (abort) @@ -215,10 +201,7 @@ int abortboot(int bootdelay) static int menukey = 0; #endif -#ifndef CONFIG_MENU -static inline -#endif -int abortboot(int bootdelay) +static int abortboot_normal(int bootdelay) { int abort = 0; unsigned long ts; @@ -275,6 +258,15 @@ int abortboot(int bootdelay) return abort; } # endif /* CONFIG_AUTOBOOT_KEYED */ + +static int abortboot(int bootdelay) +{ +#ifdef CONFIG_AUTOBOOT_KEYED + return abortboot_keyed(bootdelay); +#else + return abortboot_normal(bootdelay); +#endif +} #endif /* CONFIG_BOOTDELAY */ /* @@ -342,93 +334,35 @@ static void process_fdt_options(const void *blob) } #endif /* CONFIG_OF_CONTROL */ - -/****************************************************************************/ - -void main_loop (void) +#ifdef CONFIG_BOOTDELAY +static void process_boot_delay(void) { -#ifndef CONFIG_SYS_HUSH_PARSER - static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; - int len; - int rc = 1; - int flag; -#endif -#if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL) +#ifdef CONFIG_OF_CONTROL char *env; #endif -#if defined(CONFIG_BOOTDELAY) char *s; int bootdelay; -#endif -#ifdef CONFIG_PREBOOT - char *p; -#endif #ifdef CONFIG_BOOTCOUNT_LIMIT unsigned long bootcount = 0; unsigned long bootlimit = 0; - char *bcs; - char bcs_set[16]; #endif /* CONFIG_BOOTCOUNT_LIMIT */ - bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); - #ifdef CONFIG_BOOTCOUNT_LIMIT bootcount = bootcount_load(); bootcount++; bootcount_store (bootcount); - sprintf (bcs_set, "%lu", bootcount); - setenv ("bootcount", bcs_set); - bcs = getenv ("bootlimit"); - bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; + setenv_ulong("bootcount", bootcount); + bootlimit = getenv_ulong("bootlimit", 10, 0); #endif /* CONFIG_BOOTCOUNT_LIMIT */ -#ifdef CONFIG_MODEM_SUPPORT - debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); - if (do_mdm_init) { - char *str = strdup(getenv("mdm_cmd")); - setenv ("preboot", str); /* set or delete definition */ - if (str != NULL) - free (str); - mdm_init(); /* wait for modem connection */ - } -#endif /* CONFIG_MODEM_SUPPORT */ - -#ifdef CONFIG_VERSION_VARIABLE - { - setenv ("ver", version_string); /* set version variable */ - } -#endif /* CONFIG_VERSION_VARIABLE */ - -#ifdef CONFIG_SYS_HUSH_PARSER - u_boot_hush_start (); -#endif - -#if defined(CONFIG_HUSH_INIT_VAR) - hush_init_var (); -#endif - -#ifdef CONFIG_PREBOOT - if ((p = getenv ("preboot")) != NULL) { -# ifdef CONFIG_AUTOBOOT_KEYED - int prev = disable_ctrlc(1); /* disable Control C checking */ -# endif - - run_command_list(p, -1, 0); - -# ifdef CONFIG_AUTOBOOT_KEYED - disable_ctrlc(prev); /* restore Control C checking */ -# endif - } -#endif /* CONFIG_PREBOOT */ - -#if defined(CONFIG_UPDATE_TFTP) - update_tftp (0UL); -#endif /* CONFIG_UPDATE_TFTP */ - -#if defined(CONFIG_BOOTDELAY) s = getenv ("bootdelay"); bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; +#ifdef CONFIG_OF_CONTROL + bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", + bootdelay); +#endif + debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); #if defined(CONFIG_MENU_SHOW) @@ -474,26 +408,88 @@ void main_loop (void) debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); if (bootdelay != -1 && s && !abortboot(bootdelay)) { -# ifdef CONFIG_AUTOBOOT_KEYED +#ifdef CONFIG_AUTOBOOT_KEYED int prev = disable_ctrlc(1); /* disable Control C checking */ -# endif +#endif run_command_list(s, -1, 0); -# ifdef CONFIG_AUTOBOOT_KEYED +#ifdef CONFIG_AUTOBOOT_KEYED disable_ctrlc(prev); /* restore Control C checking */ -# endif +#endif } -# ifdef CONFIG_MENUKEY +#ifdef CONFIG_MENUKEY if (menukey == CONFIG_MENUKEY) { s = getenv("menucmd"); if (s) run_command_list(s, -1, 0); } #endif /* CONFIG_MENUKEY */ +} #endif /* CONFIG_BOOTDELAY */ +void main_loop(void) +{ +#ifndef CONFIG_SYS_HUSH_PARSER + static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; + int len; + int rc = 1; + int flag; +#endif +#ifdef CONFIG_PREBOOT + char *p; +#endif + + bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); + +#ifdef CONFIG_MODEM_SUPPORT + debug("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); + if (do_mdm_init) { + char *str = strdup(getenv("mdm_cmd")); + setenv("preboot", str); /* set or delete definition */ + if (str != NULL) + free(str); + mdm_init(); /* wait for modem connection */ + } +#endif /* CONFIG_MODEM_SUPPORT */ + +#ifdef CONFIG_VERSION_VARIABLE + { + setenv("ver", version_string); /* set version variable */ + } +#endif /* CONFIG_VERSION_VARIABLE */ + +#ifdef CONFIG_SYS_HUSH_PARSER + u_boot_hush_start(); +#endif + +#if defined(CONFIG_HUSH_INIT_VAR) + hush_init_var(); +#endif + +#ifdef CONFIG_PREBOOT + p = getenv("preboot"); + if (p != NULL) { +# ifdef CONFIG_AUTOBOOT_KEYED + int prev = disable_ctrlc(1); /* disable Control C checking */ +# endif + + run_command_list(p, -1, 0); + +# ifdef CONFIG_AUTOBOOT_KEYED + disable_ctrlc(prev); /* restore Control C checking */ +# endif + } +#endif /* CONFIG_PREBOOT */ + +#if defined(CONFIG_UPDATE_TFTP) + update_tftp(0UL); +#endif /* CONFIG_UPDATE_TFTP */ + +#ifdef CONFIG_BOOTDELAY + process_boot_delay(); +#endif /* * Main Loop for Monitor Command Processing */ @@ -1080,20 +1076,20 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) * Special character handling */ switch (c) { - case '\r': /* Enter */ + case '\r': /* Enter */ case '\n': *p = '\0'; puts ("\r\n"); - return (p - p_buf); + return p - p_buf; - case '\0': /* nul */ + case '\0': /* nul */ continue; - case 0x03: /* ^C - break */ + case 0x03: /* ^C - break */ p_buf[0] = '\0'; /* discard input */ - return (-1); + return -1; - case 0x15: /* ^U - erase line */ + case 0x15: /* ^U - erase line */ while (col > plen) { puts (erase_seq); --col; @@ -1102,15 +1098,15 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) n = 0; continue; - case 0x17: /* ^W - erase word */ + case 0x17: /* ^W - erase word */ p=delete_char(p_buf, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=delete_char(p_buf, p, &col, &n, plen); } continue; - case 0x08: /* ^H - backspace */ - case 0x7F: /* DEL - backspace */ + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ p=delete_char(p_buf, p, &col, &n, plen); continue; @@ -1119,7 +1115,7 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) * Must be a normal character then */ if (n < CONFIG_SYS_CBSIZE-2) { - if (c == '\t') { /* expand TABs */ + if (c == '\t') { /* expand TABs */ #ifdef CONFIG_AUTO_COMPLETE /* if auto completion triggered just continue */ *p = '\0'; @@ -1134,7 +1130,7 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout) char buf[2]; /* - * Echo input using puts() to force am + * Echo input using puts() to force an * LCD flush if we are using an LCD */ ++col; @@ -1192,9 +1188,7 @@ int parse_line (char *line, char *argv[]) { int nargs = 0; -#ifdef DEBUG_PARSER - printf ("parse_line: \"%s\"\n", line); -#endif + debug_parser("parse_line: \"%s\"\n", line); while (nargs < CONFIG_SYS_MAXARGS) { /* skip any white space */ @@ -1203,10 +1197,8 @@ int parse_line (char *line, char *argv[]) if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif - return (nargs); + debug_parser("parse_line: nargs=%d\n", nargs); + return nargs; } argv[nargs++] = line; /* begin of argument string */ @@ -1217,10 +1209,8 @@ int parse_line (char *line, char *argv[]) if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL; -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif - return (nargs); + debug_parser("parse_line: nargs=%d\n", nargs); + return nargs; } *line++ = '\0'; /* terminate current arg */ @@ -1228,9 +1218,7 @@ int parse_line (char *line, char *argv[]) printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS); -#ifdef DEBUG_PARSER - printf ("parse_line: nargs=%d\n", nargs); -#endif + debug_parser("parse_line: nargs=%d\n", nargs); return (nargs); } @@ -1248,12 +1236,10 @@ static void process_macros (const char *input, char *output) /* 1 = waiting for '(' or '{' */ /* 2 = waiting for ')' or '}' */ /* 3 = waiting for ''' */ -#ifdef DEBUG_PARSER char *output_start = output; - printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input), - input); -#endif + debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input), + input); prev = '\0'; /* previous character */ @@ -1341,10 +1327,8 @@ static void process_macros (const char *input, char *output) else *(output - 1) = 0; -#ifdef DEBUG_PARSER - printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", - strlen (output_start), output_start); -#endif + debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n", + strlen(output_start), output_start); } /**************************************************************************** @@ -1375,12 +1359,12 @@ static int builtin_run_command(const char *cmd, int flag) int repeatable = 1; int rc = 0; -#ifdef DEBUG_PARSER - printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); - puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ - puts ("\"\n"); -#endif - + debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd); + if (DEBUG_PARSER) { + /* use puts - string may be loooong */ + puts(cmd ? cmd : "NULL"); + puts("\"\n"); + } clear_ctrlc(); /* forget any previous Control C */ if (!cmd || !*cmd) { @@ -1398,9 +1382,7 @@ static int builtin_run_command(const char *cmd, int flag) * repeatable commands */ -#ifdef DEBUG_PARSER - printf ("[PROCESS_SEPARATORS] %s\n", cmd); -#endif + debug_parser("[PROCESS_SEPARATORS] %s\n", cmd); while (*str) { /* @@ -1429,9 +1411,7 @@ static int builtin_run_command(const char *cmd, int flag) } else str = sep; /* no more commands for next pass */ -#ifdef DEBUG_PARSER - printf ("token: \"%s\"\n", token); -#endif + debug_parser("token: \"%s\"\n", token); /* find macros in this token and replace them */ process_macros (token, finaltoken); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 7efdcb88b7..170fa3871a 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -32,7 +32,7 @@ DECLARE_GLOBAL_DATA_PTR; -static void mmc_load_image_raw(struct mmc *mmc) +static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector) { unsigned long err; u32 image_size_sectors; @@ -42,10 +42,7 @@ static void mmc_load_image_raw(struct mmc *mmc) sizeof(struct image_header)); /* read image header to find the image size & load address */ - err = mmc->block_dev.block_read(0, - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1, - header); - + err = mmc->block_dev.block_read(0, sector, 1, header); if (err == 0) goto end; @@ -56,19 +53,33 @@ static void mmc_load_image_raw(struct mmc *mmc) mmc->read_bl_len; /* Read the header too to avoid extra memcpy */ - err = mmc->block_dev.block_read(0, - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, - image_size_sectors, (void *)spl_image.load_addr); + err = mmc->block_dev.block_read(0, sector, image_size_sectors, + (void *)spl_image.load_addr); end: - if (err == 0) { + if (err == 0) printf("spl: mmc blk read err - %lu\n", err); - hang(); + + return (err == 0); +} + +#ifdef CONFIG_SPL_OS_BOOT +static int mmc_load_image_raw_os(struct mmc *mmc) +{ + if (!mmc->block_dev.block_read(0, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, + (void *)CONFIG_SYS_SPL_ARGS_ADDR)) { + printf("mmc args blk read error\n"); + return -1; } + + return mmc_load_image_raw(mmc, CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); } +#endif #ifdef CONFIG_SPL_FAT_SUPPORT -static void mmc_load_image_fat(struct mmc *mmc) +static int mmc_load_image_fat(struct mmc *mmc, const char *filename) { int err; struct image_header *header; @@ -76,32 +87,41 @@ static void mmc_load_image_fat(struct mmc *mmc) header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); - err = fat_register_device(&mmc->block_dev, - CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION); - if (err) { - printf("spl: fat register err - %d\n", err); - hang(); - } - - err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME, - header, sizeof(struct image_header)); + err = file_fat_read(filename, header, sizeof(struct image_header)); if (err <= 0) goto end; spl_parse_image_header(header); - err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME, - (u8 *)spl_image.load_addr, 0); + err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); end: + if (err <= 0) + printf("spl: error reading image %s, err - %d\n", + filename, err); + + return (err <= 0); +} + +#ifdef CONFIG_SPL_OS_BOOT +static int mmc_load_image_fat_os(struct mmc *mmc) +{ + int err; + + err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME, + (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); if (err <= 0) { printf("spl: error reading image %s, err - %d\n", - CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME, err); - hang(); + CONFIG_SPL_FAT_LOAD_ARGS_NAME, err); + return -1; } + + return mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_KERNEL_NAME); } #endif +#endif + void spl_mmc_load_image(void) { struct mmc *mmc; @@ -121,17 +141,36 @@ void spl_mmc_load_image(void) printf("spl: mmc init failed: err - %d\n", err); hang(); } + boot_mode = spl_boot_mode(); if (boot_mode == MMCSD_MODE_RAW) { debug("boot mode - RAW\n"); - mmc_load_image_raw(mmc); +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || mmc_load_image_raw_os(mmc)) +#endif + err = mmc_load_image_raw(mmc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); #ifdef CONFIG_SPL_FAT_SUPPORT } else if (boot_mode == MMCSD_MODE_FAT) { debug("boot mode - FAT\n"); - mmc_load_image_fat(mmc); + + err = fat_register_device(&mmc->block_dev, + CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION); + if (err) { + printf("spl: fat register err - %d\n", err); + hang(); + } + +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || mmc_load_image_fat_os(mmc)) +#endif + err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME); #endif } else { puts("spl: wrong MMC boot mode\n"); hang(); } + + if (err) + hang(); } diff --git a/common/usb_hub.c b/common/usb_hub.c index 0d79ec3ea8..774ba6387a 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -53,6 +53,10 @@ #include <asm/4xx_pci.h> #endif +#ifndef CONFIG_USB_HUB_MIN_POWER_ON_DELAY +#define CONFIG_USB_HUB_MIN_POWER_ON_DELAY 100 +#endif + #define USB_BUFSIZ 512 static struct usb_hub_device hub_dev[USB_MAX_HUB]; @@ -148,8 +152,8 @@ static void usb_hub_power_on(struct usb_hub_device *hub) debug("port %d returns %lX\n", i + 1, dev->status); } - /* Wait at least 100 msec for power to become stable */ - mdelay(max(pgood_delay, (unsigned)100)); + /* Wait for power to become stable */ + mdelay(max(pgood_delay, CONFIG_USB_HUB_MIN_POWER_ON_DELAY)); } void usb_hub_reset(void) @@ -485,7 +489,11 @@ static int usb_hub_configure(struct usb_device *dev) i + 1, portstatus); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); - + /* + * The following hack causes a ghost device problem + * to Faraday EHCI + */ +#ifndef CONFIG_USB_EHCI_FARADAY /* EM interference sometimes causes bad shielded USB * devices to be shutdown by the hub, this hack enables * them again. Works at least with mouse driver */ @@ -497,6 +505,7 @@ static int usb_hub_configure(struct usb_device *dev) "re-enabling...\n", i + 1); usb_hub_port_connect_change(dev, i); } +#endif } if (portstatus & USB_PORT_STAT_SUSPEND) { debug("port %d suspend change\n", i + 1); diff --git a/common/usb_kbd.c b/common/usb_kbd.c index b962849920..3174b5e1bf 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -461,8 +461,13 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); debug("USB KBD: enable interrupt pipe...\n"); - usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp, - ep->bInterval); + if (usb_submit_int_msg(dev, pipe, data->new, maxp > 8 ? 8 : maxp, + ep->bInterval) < 0) { + printf("Failed to get keyboard state from device %04x:%04x\n", + dev->descriptor.idVendor, dev->descriptor.idProduct); + /* Abort, we don't want to use that non-functional keyboard. */ + return 0; + } /* Success. */ return 1; @@ -496,6 +501,7 @@ int drv_usb_kbd_init(void) if (old_dev) { /* Already registered, just return ok. */ debug("USB KBD: is already registered.\n"); + usb_kbd_deregister(); return 1; } diff --git a/disk/part_efi.c b/disk/part_efi.c index 5986589708..fb5e9f0477 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -372,7 +372,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba); ulong start; int i, k; - size_t name_len; + size_t efiname_len, dosname_len; #ifdef CONFIG_PARTITION_UUIDS char *str_uuid; #endif @@ -420,9 +420,14 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, sizeof(gpt_entry_attributes)); /* partition name */ - name_len = sizeof(gpt_e[i].partition_name) + efiname_len = sizeof(gpt_e[i].partition_name) / sizeof(efi_char16_t); - for (k = 0; k < name_len; k++) + dosname_len = sizeof(partitions[i].name); + + memset(gpt_e[i].partition_name, 0, + sizeof(gpt_e[i].partition_name)); + + for (k = 0; k < min(dosname_len, efiname_len); k++) gpt_e[i].partition_name[k] = (efi_char16_t)(partitions[i].name[k]); diff --git a/doc/device-tree-bindings/video/simple-framebuffer.txt b/doc/device-tree-bindings/video/simple-framebuffer.txt new file mode 100644 index 0000000000..3ea4605831 --- /dev/null +++ b/doc/device-tree-bindings/video/simple-framebuffer.txt @@ -0,0 +1,25 @@ +Simple Framebuffer + +A simple frame-buffer describes a raw memory region that may be rendered to, +with the assumption that the display hardware has already been set up to scan +out from that buffer. + +Required properties: +- compatible: "simple-framebuffer" +- reg: Should contain the location and size of the framebuffer memory. +- width: The width of the framebuffer in pixels. +- height: The height of the framebuffer in pixels. +- stride: The number of bytes in each line of the framebuffer. +- format: The format of the framebuffer surface. Valid values are: + - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b). + +Example: + + framebuffer { + compatible = "simple-framebuffer"; + reg = <0x1d385000 (1600 * 1200 * 2)>; + width = <1600>; + height = <1200>; + stride = <(1600 * 2)>; + format = "r5g6b5"; + }; diff --git a/drivers/input/key_matrix.c b/drivers/input/key_matrix.c index 946a186a1f..c900e45d15 100644 --- a/drivers/input/key_matrix.c +++ b/drivers/input/key_matrix.c @@ -154,54 +154,42 @@ static uchar *create_keymap(struct key_matrix *config, u32 *data, int len, return map; } -int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, - int node) +int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, int node) { const struct fdt_property *prop; - const char prefix[] = "linux,"; - int plen = sizeof(prefix) - 1; - int offset; - - /* Check each property name for ones that we understand */ - for (offset = fdt_first_property_offset(blob, node); - offset > 0; - offset = fdt_next_property_offset(blob, offset)) { - const char *name; - int len; - - prop = fdt_get_property_by_offset(blob, offset, NULL); - name = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); - len = strlen(name); - - /* Name needs to match "1,<type>keymap" */ - debug("%s: property '%s'\n", __func__, name); - if (strncmp(name, prefix, plen) || - len < plen + 6 || - strcmp(name + len - 6, "keymap")) - continue; + int proplen; + uchar *plain_keycode; - len -= plen + 6; - if (len == 0) { - config->plain_keycode = create_keymap(config, - (u32 *)prop->data, fdt32_to_cpu(prop->len), - KEY_FN, &config->fn_pos); - } else if (0 == strncmp(name + plen, "fn-", len)) { - config->fn_keycode = create_keymap(config, - (u32 *)prop->data, fdt32_to_cpu(prop->len), - -1, NULL); - } else { - debug("%s: unrecognised property '%s'\n", __func__, - name); - } + prop = fdt_get_property(blob, node, "linux,keymap", &proplen); + /* Basic keymap is required */ + if (!prop) { + debug("%s: cannot find keycode-plain map\n", __func__); + return -1; } - debug("%s: Decoded key maps %p, %p from fdt\n", __func__, - config->plain_keycode, config->fn_keycode); - if (!config->plain_keycode) { - debug("%s: cannot find keycode-plain map\n", __func__); + plain_keycode = create_keymap(config, (u32 *)prop->data, + proplen, KEY_FN, &config->fn_pos); + config->plain_keycode = plain_keycode; + /* Conversion error -> fail */ + if (!config->plain_keycode) + return -1; + + prop = fdt_get_property(blob, node, "linux,fn-keymap", &proplen); + /* fn keymap is optional */ + if (!prop) + goto done; + + config->fn_keycode = create_keymap(config, (u32 *)prop->data, + proplen, -1, NULL); + /* Conversion error -> fail */ + if (!config->fn_keycode) { + free(plain_keycode); return -1; } +done: + debug("%s: Decoded key maps %p, %p from fdt\n", __func__, + config->plain_keycode, config->fn_keycode); return 0; } diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 543c845ff0..99f39fc752 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk LIB := $(obj)libmtd.o -COBJS-$(CONFIG_MTD_DEVICE) += mtdcore.o +ifneq (,$(findstring y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND))) +COBJS-y += mtdcore.o +endif COBJS-$(CONFIG_MTD_PARTITIONS) += mtdpart.o COBJS-$(CONFIG_MTD_CONCAT) += mtdconcat.o COBJS-$(CONFIG_HAS_DATAFLASH) += at45.o diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c index 8d74fa9412..bbb71a19e7 100644 --- a/drivers/mtd/cfi_mtd.c +++ b/drivers/mtd/cfi_mtd.c @@ -244,12 +244,12 @@ int cfi_mtd_init(void) mtd->size = fi->size; mtd->writesize = 1; - mtd->erase = cfi_mtd_erase; - mtd->read = cfi_mtd_read; - mtd->write = cfi_mtd_write; - mtd->sync = cfi_mtd_sync; - mtd->lock = cfi_mtd_lock; - mtd->unlock = cfi_mtd_unlock; + mtd->_erase = cfi_mtd_erase; + mtd->_read = cfi_mtd_read; + mtd->_write = cfi_mtd_write; + mtd->_sync = cfi_mtd_sync; + mtd->_lock = cfi_mtd_lock; + mtd->_unlock = cfi_mtd_unlock; mtd->priv = fi; if (add_mtd_device(mtd)) diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index e6d938417d..31e4289b16 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -70,14 +70,14 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len, /* Entire transaction goes into this subdev */ size = len; - err = subdev->read(subdev, from, size, &retsize, buf); + err = mtd_read(subdev, from, size, &retsize, buf); /* Save information about bitflips! */ if (unlikely(err)) { - if (err == -EBADMSG) { + if (mtd_is_eccerr(err)) { mtd->ecc_stats.failed++; ret = err; - } else if (err == -EUCLEAN) { + } else if (mtd_is_bitflip(err)) { mtd->ecc_stats.corrected++; /* Do not overwrite -EBADMSG !! */ if (!ret) @@ -105,9 +105,6 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len, int err = -EINVAL; int i; - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - *retlen = 0; for (i = 0; i < concat->num_subdev; i++) { @@ -124,11 +121,7 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len, else size = len; - if (!(subdev->flags & MTD_WRITEABLE)) - err = -EROFS; - else - err = subdev->write(subdev, to, size, &retsize, buf); - + err = mtd_write(subdev, to, size, &retsize, buf); if (err) break; @@ -165,16 +158,16 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) if (from + devops.len > subdev->size) devops.len = subdev->size - from; - err = subdev->read_oob(subdev, from, &devops); + err = mtd_read_oob(subdev, from, &devops); ops->retlen += devops.retlen; ops->oobretlen += devops.oobretlen; /* Save information about bitflips! */ if (unlikely(err)) { - if (err == -EBADMSG) { + if (mtd_is_eccerr(err)) { mtd->ecc_stats.failed++; ret = err; - } else if (err == -EUCLEAN) { + } else if (mtd_is_bitflip(err)) { mtd->ecc_stats.corrected++; /* Do not overwrite -EBADMSG !! */ if (!ret) @@ -225,7 +218,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) if (to + devops.len > subdev->size) devops.len = subdev->size - to; - err = subdev->write_oob(subdev, to, &devops); + err = mtd_write_oob(subdev, to, &devops); ops->retlen += devops.retlen; if (err) return err; @@ -271,7 +264,7 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) * FIXME: Allow INTERRUPTIBLE. Which means * not having the wait_queue head on the stack. */ - err = mtd->erase(mtd, erase); + err = mtd_erase(mtd, erase); if (!err) { set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&waitq, &wait); @@ -294,15 +287,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) uint64_t length, offset = 0; struct erase_info *erase; - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - - if (instr->addr > concat->mtd.size) - return -EINVAL; - - if (instr->len + instr->addr > concat->mtd.size) - return -EINVAL; - /* * Check for proper erase block alignment of the to-be-erased area. * It is easier to do this based on the super device's erase @@ -350,8 +334,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) return -EINVAL; } - instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; - /* make a local copy of instr to avoid modifying the caller's struct */ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); @@ -390,10 +372,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) else erase->len = length; - if (!(subdev->flags & MTD_WRITEABLE)) { - err = -EROFS; - break; - } length -= erase->len; if ((err = concat_dev_erase(subdev, erase))) { /* sanity check: should never happen since @@ -429,9 +407,6 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) struct mtd_concat *concat = CONCAT(mtd); int i, err = -EINVAL; - if ((len + ofs) > mtd->size) - return -EINVAL; - for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; uint64_t size; @@ -446,7 +421,7 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) else size = len; - err = subdev->lock(subdev, ofs, size); + err = mtd_lock(subdev, ofs, size); if (err) break; @@ -467,9 +442,6 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) struct mtd_concat *concat = CONCAT(mtd); int i, err = 0; - if ((len + ofs) > mtd->size) - return -EINVAL; - for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; uint64_t size; @@ -484,7 +456,7 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) else size = len; - err = subdev->unlock(subdev, ofs, size); + err = mtd_unlock(subdev, ofs, size); if (err) break; @@ -507,7 +479,7 @@ static void concat_sync(struct mtd_info *mtd) for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; - subdev->sync(subdev); + mtd_sync(subdev); } } @@ -516,12 +488,9 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs) struct mtd_concat *concat = CONCAT(mtd); int i, res = 0; - if (!concat->subdev[0]->block_isbad) + if (!mtd_can_have_bb(concat->subdev[0])) return res; - if (ofs > mtd->size) - return -EINVAL; - for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; @@ -530,7 +499,7 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs) continue; } - res = subdev->block_isbad(subdev, ofs); + res = mtd_block_isbad(subdev, ofs); break; } @@ -542,12 +511,9 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) struct mtd_concat *concat = CONCAT(mtd); int i, err = -EINVAL; - if (!concat->subdev[0]->block_markbad) + if (!mtd_can_have_bb(concat->subdev[0])) return 0; - if (ofs > mtd->size) - return -EINVAL; - for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; @@ -556,7 +522,7 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) continue; } - err = subdev->block_markbad(subdev, ofs); + err = mtd_block_markbad(subdev, ofs); if (!err) mtd->ecc_stats.badblocks++; break; @@ -609,14 +575,14 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.subpage_sft = subdev[0]->subpage_sft; concat->mtd.oobsize = subdev[0]->oobsize; concat->mtd.oobavail = subdev[0]->oobavail; - if (subdev[0]->read_oob) - concat->mtd.read_oob = concat_read_oob; - if (subdev[0]->write_oob) - concat->mtd.write_oob = concat_write_oob; - if (subdev[0]->block_isbad) - concat->mtd.block_isbad = concat_block_isbad; - if (subdev[0]->block_markbad) - concat->mtd.block_markbad = concat_block_markbad; + if (subdev[0]->_read_oob) + concat->mtd._read_oob = concat_read_oob; + if (subdev[0]->_write_oob) + concat->mtd._write_oob = concat_write_oob; + if (subdev[0]->_block_isbad) + concat->mtd._block_isbad = concat_block_isbad; + if (subdev[0]->_block_markbad) + concat->mtd._block_markbad = concat_block_markbad; concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; @@ -653,8 +619,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c if (concat->mtd.writesize != subdev[i]->writesize || concat->mtd.subpage_sft != subdev[i]->subpage_sft || concat->mtd.oobsize != subdev[i]->oobsize || - !concat->mtd.read_oob != !subdev[i]->read_oob || - !concat->mtd.write_oob != !subdev[i]->write_oob) { + !concat->mtd._read_oob != !subdev[i]->_read_oob || + !concat->mtd._write_oob != !subdev[i]->_write_oob) { kfree(concat); printk("Incompatible OOB or ECC data on \"%s\"\n", subdev[i]->name); @@ -669,12 +635,12 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->num_subdev = num_devs; concat->mtd.name = name; - concat->mtd.erase = concat_erase; - concat->mtd.read = concat_read; - concat->mtd.write = concat_write; - concat->mtd.sync = concat_sync; - concat->mtd.lock = concat_lock; - concat->mtd.unlock = concat_unlock; + concat->mtd._erase = concat_erase; + concat->mtd._read = concat_read; + concat->mtd._write = concat_write; + concat->mtd._sync = concat_sync; + concat->mtd._lock = concat_lock; + concat->mtd._unlock = concat_unlock; /* * Combine the erase block size info of the subdevices: diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 3a81adaf60..49c08145a7 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -25,6 +25,11 @@ int add_mtd_device(struct mtd_info *mtd) mtd->index = i; mtd->usecount = 0; + /* default value if not set by driver */ + if (mtd->bitflip_threshold == 0) + mtd->bitflip_threshold = mtd->ecc_strength; + + /* No need to get a refcount on the module containing the notifier, since we hold the mtd_table_mutex */ @@ -186,3 +191,189 @@ void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, } } #endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */ + + /* + * Erase is an asynchronous operation. Device drivers are supposed + * to call instr->callback() whenever the operation completes, even + * if it completes with a failure. + * Callers are supposed to pass a callback function and wait for it + * to be called before writing to the block. + */ +int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) + return -EINVAL; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; + if (!instr->len) { + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; + } + return mtd->_erase(mtd, instr); +} + +int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + u_char *buf) +{ + if (from < 0 || from > mtd->size || len > mtd->size - from) + return -EINVAL; + if (!len) + return 0; + return mtd->_read(mtd, from, len, retlen, buf); +} + +int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf) +{ + *retlen = 0; + if (to < 0 || to > mtd->size || len > mtd->size - to) + return -EINVAL; + if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + if (!len) + return 0; + return mtd->_write(mtd, to, len, retlen, buf); +} + +/* + * In blackbox flight recorder like scenarios we want to make successful writes + * in interrupt context. panic_write() is only intended to be called when its + * known the kernel is about to panic and we need the write to succeed. Since + * the kernel is not going to be running for much longer, this function can + * break locks and delay to ensure the write succeeds (but not sleep). + */ +int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf) +{ + *retlen = 0; + if (!mtd->_panic_write) + return -EOPNOTSUPP; + if (to < 0 || to > mtd->size || len > mtd->size - to) + return -EINVAL; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + if (!len) + return 0; + return mtd->_panic_write(mtd, to, len, retlen, buf); +} + +int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) +{ + ops->retlen = ops->oobretlen = 0; + if (!mtd->_read_oob) + return -EOPNOTSUPP; + return mtd->_read_oob(mtd, from, ops); +} + +/* + * Method to access the protection register area, present in some flash + * devices. The user data is one time programmable but the factory data is read + * only. + */ +int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len) +{ + if (!mtd->_get_fact_prot_info) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_get_fact_prot_info(mtd, buf, len); +} + +int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + *retlen = 0; + if (!mtd->_read_fact_prot_reg) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf); +} + +int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len) +{ + if (!mtd->_get_user_prot_info) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_get_user_prot_info(mtd, buf, len); +} + +int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + *retlen = 0; + if (!mtd->_read_user_prot_reg) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf); +} + +int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, u_char *buf) +{ + *retlen = 0; + if (!mtd->_write_user_prot_reg) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); +} + +int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) +{ + if (!mtd->_lock_user_prot_reg) + return -EOPNOTSUPP; + if (!len) + return 0; + return mtd->_lock_user_prot_reg(mtd, from, len); +} + +/* Chip-supported device locking */ +int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + if (!mtd->_lock) + return -EOPNOTSUPP; + if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) + return -EINVAL; + if (!len) + return 0; + return mtd->_lock(mtd, ofs, len); +} + +int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + if (!mtd->_unlock) + return -EOPNOTSUPP; + if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) + return -EINVAL; + if (!len) + return 0; + return mtd->_unlock(mtd, ofs, len); +} + +int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + if (!mtd->_block_isbad) + return 0; + if (ofs < 0 || ofs > mtd->size) + return -EINVAL; + return mtd->_block_isbad(mtd, ofs); +} + +int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + if (!mtd->_block_markbad) + return -EOPNOTSUPP; + if (ofs < 0 || ofs > mtd->size) + return -EINVAL; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + return mtd->_block_markbad(mtd, ofs); +} + diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index cbfc6796c7..9dfe7bbc9a 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -52,17 +52,11 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, int res; stats = part->master->ecc_stats; - - if (from >= mtd->size) - len = 0; - else if (from + len > mtd->size) - len = mtd->size - from; - res = part->master->read(part->master, from + part->offset, - len, retlen, buf); + res = mtd_read(part->master, from + part->offset, len, retlen, buf); if (unlikely(res)) { - if (res == -EUCLEAN) + if (mtd_is_bitflip(res)) mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; - if (res == -EBADMSG) + if (mtd_is_eccerr(res)) mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; } return res; @@ -78,12 +72,12 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from, return -EINVAL; if (ops->datbuf && from + ops->len > mtd->size) return -EINVAL; - res = part->master->read_oob(part->master, from + part->offset, ops); + res = mtd_read_oob(part->master, from + part->offset, ops); if (unlikely(res)) { - if (res == -EUCLEAN) + if (mtd_is_bitflip(res)) mtd->ecc_stats.corrected++; - if (res == -EBADMSG) + if (mtd_is_eccerr(res)) mtd->ecc_stats.failed++; } return res; @@ -93,58 +87,35 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->read_user_prot_reg(part->master, from, - len, retlen, buf); + return mtd_read_user_prot_reg(part->master, from, len, retlen, buf); } static int part_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, size_t len) { struct mtd_part *part = PART(mtd); - return part->master->get_user_prot_info(part->master, buf, len); + return mtd_get_user_prot_info(part->master, buf, len); } static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->read_fact_prot_reg(part->master, from, - len, retlen, buf); + return mtd_read_fact_prot_reg(part->master, from, len, retlen, buf); } static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, size_t len) { struct mtd_part *part = PART(mtd); - return part->master->get_fact_prot_info(part->master, buf, len); + return mtd_get_fact_prot_info(part->master, buf, len); } static int part_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; - return part->master->write(part->master, to + part->offset, - len, retlen, buf); -} - -static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; - return part->master->panic_write(part->master, to + part->offset, - len, retlen, buf); + return mtd_write(part->master, to + part->offset, len, retlen, buf); } static int part_write_oob(struct mtd_info *mtd, loff_t to, @@ -152,41 +123,34 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to, { struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (to >= mtd->size) return -EINVAL; if (ops->datbuf && to + ops->len > mtd->size) return -EINVAL; - return part->master->write_oob(part->master, to + part->offset, ops); + return mtd_write_oob(part->master, to + part->offset, ops); } static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->write_user_prot_reg(part->master, from, - len, retlen, buf); + return mtd_write_user_prot_reg(part->master, from, len, retlen, buf); } static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) { struct mtd_part *part = PART(mtd); - return part->master->lock_user_prot_reg(part->master, from, len); + return mtd_lock_user_prot_reg(part->master, from, len); } static int part_erase(struct mtd_info *mtd, struct erase_info *instr) { struct mtd_part *part = PART(mtd); int ret; - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (instr->addr >= mtd->size) - return -EINVAL; + instr->addr += part->offset; - ret = part->master->erase(part->master, instr); + ret = mtd_erase(part->master, instr); if (ret) { if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) instr->fail_addr -= part->offset; @@ -197,7 +161,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr) void mtd_erase_callback(struct erase_info *instr) { - if (instr->mtd->erase == part_erase) { + if (instr->mtd->_erase == part_erase) { struct mtd_part *part = PART(instr->mtd); if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) @@ -211,32 +175,26 @@ void mtd_erase_callback(struct erase_info *instr) static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) - return -EINVAL; - return part->master->lock(part->master, ofs + part->offset, len); + return mtd_lock(part->master, ofs + part->offset, len); } static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) - return -EINVAL; - return part->master->unlock(part->master, ofs + part->offset, len); + return mtd_unlock(part->master, ofs + part->offset, len); } static void part_sync(struct mtd_info *mtd) { struct mtd_part *part = PART(mtd); - part->master->sync(part->master); + mtd_sync(part->master); } static int part_block_isbad(struct mtd_info *mtd, loff_t ofs) { struct mtd_part *part = PART(mtd); - if (ofs >= mtd->size) - return -EINVAL; ofs += part->offset; - return part->master->block_isbad(part->master, ofs); + return mtd_block_isbad(part->master, ofs); } static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) @@ -244,12 +202,8 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) struct mtd_part *part = PART(mtd); int res; - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (ofs >= mtd->size) - return -EINVAL; ofs += part->offset; - res = part->master->block_markbad(part->master, ofs); + res = mtd_block_markbad(part->master, ofs); if (!res) mtd->ecc_stats.badblocks++; return res; @@ -303,39 +257,36 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, slave->mtd.name = part->name; slave->mtd.owner = master->owner; - slave->mtd.read = part_read; - slave->mtd.write = part_write; - - if (master->panic_write) - slave->mtd.panic_write = part_panic_write; - - if (master->read_oob) - slave->mtd.read_oob = part_read_oob; - if (master->write_oob) - slave->mtd.write_oob = part_write_oob; - if (master->read_user_prot_reg) - slave->mtd.read_user_prot_reg = part_read_user_prot_reg; - if (master->read_fact_prot_reg) - slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg; - if (master->write_user_prot_reg) - slave->mtd.write_user_prot_reg = part_write_user_prot_reg; - if (master->lock_user_prot_reg) - slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg; - if (master->get_user_prot_info) - slave->mtd.get_user_prot_info = part_get_user_prot_info; - if (master->get_fact_prot_info) - slave->mtd.get_fact_prot_info = part_get_fact_prot_info; - if (master->sync) - slave->mtd.sync = part_sync; - if (master->lock) - slave->mtd.lock = part_lock; - if (master->unlock) - slave->mtd.unlock = part_unlock; - if (master->block_isbad) - slave->mtd.block_isbad = part_block_isbad; - if (master->block_markbad) - slave->mtd.block_markbad = part_block_markbad; - slave->mtd.erase = part_erase; + slave->mtd._read = part_read; + slave->mtd._write = part_write; + + if (master->_read_oob) + slave->mtd._read_oob = part_read_oob; + if (master->_write_oob) + slave->mtd._write_oob = part_write_oob; + if (master->_read_user_prot_reg) + slave->mtd._read_user_prot_reg = part_read_user_prot_reg; + if (master->_read_fact_prot_reg) + slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg; + if (master->_write_user_prot_reg) + slave->mtd._write_user_prot_reg = part_write_user_prot_reg; + if (master->_lock_user_prot_reg) + slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg; + if (master->_get_user_prot_info) + slave->mtd._get_user_prot_info = part_get_user_prot_info; + if (master->_get_fact_prot_info) + slave->mtd._get_fact_prot_info = part_get_fact_prot_info; + if (master->_sync) + slave->mtd._sync = part_sync; + if (master->_lock) + slave->mtd._lock = part_lock; + if (master->_unlock) + slave->mtd._unlock = part_unlock; + if (master->_block_isbad) + slave->mtd._block_isbad = part_block_isbad; + if (master->_block_markbad) + slave->mtd._block_markbad = part_block_markbad; + slave->mtd._erase = part_erase; slave->master = master; slave->offset = part->offset; slave->index = partno; @@ -416,12 +367,11 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, } slave->mtd.ecclayout = master->ecclayout; - if (master->block_isbad) { + if (master->_block_isbad) { uint64_t offs = 0; while (offs < slave->mtd.size) { - if (master->block_isbad(master, - offs + slave->offset)) + if (mtd_block_isbad(master, offs + slave->offset)) slave->mtd.ecc_stats.badblocks++; offs += slave->mtd.erasesize; } diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 994dd9f095..3bfbaf8ac9 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -489,7 +489,7 @@ normal_check: } static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct atmel_nand_host *host = chip->priv; int eccsize = chip->ecc.size; @@ -529,8 +529,9 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, return 0; } -static void atmel_nand_pmecc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) +static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, + int oob_required) { struct atmel_nand_host *host = chip->priv; uint32_t *eccpos = chip->ecc.layout->eccpos; @@ -557,7 +558,7 @@ static void atmel_nand_pmecc_write_page(struct mtd_info *mtd, if (!timeout) { printk(KERN_ERR "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n"); - return; + goto out; } for (i = 0; i < host->pmecc_sector_number; i++) { @@ -570,6 +571,8 @@ static void atmel_nand_pmecc_write_page(struct mtd_info *mtd, } } chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +out: + return 0; } static void atmel_pmecc_core_init(struct mtd_info *mtd) @@ -706,6 +709,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand, nand->ecc.read_page = atmel_nand_pmecc_read_page; nand->ecc.write_page = atmel_nand_pmecc_write_page; + nand->ecc.strength = cap; atmel_pmecc_core_init(mtd); @@ -775,9 +779,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd, * mtd: mtd info structure * chip: nand chip info structure * buf: buffer to store read data + * oob_required: caller expects OOB data read to chip->oob_poi */ -static int atmel_nand_read_page(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) +static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; diff --git a/drivers/mtd/nand/bfin_nand.c b/drivers/mtd/nand/bfin_nand.c index c7ddbb21d8..7e755e8965 100644 --- a/drivers/mtd/nand/bfin_nand.c +++ b/drivers/mtd/nand/bfin_nand.c @@ -374,9 +374,11 @@ int board_nand_init(struct nand_chip *chip) if (!NAND_IS_512()) { chip->ecc.bytes = 3; chip->ecc.size = 256; + chip->ecc.strength = 1; } else { chip->ecc.bytes = 6; chip->ecc.size = 512; + chip->ecc.strength = 2; } chip->ecc.mode = NAND_ECC_HW; chip->ecc.calculate = bfin_nfc_calculate_ecc; diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index e8506ddd9b..90f59857fd 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -607,12 +607,13 @@ void davinci_nand_init(struct nand_chip *nand) { nand->chip_delay = 0; #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT - nand->options |= NAND_USE_FLASH_BBT; + nand->bbt_options |= NAND_BBT_USE_FLASH; #endif #ifdef CONFIG_SYS_NAND_HW_ECC nand->ecc.mode = NAND_ECC_HW; nand->ecc.size = 512; nand->ecc.bytes = 3; + nand->ecc.strength = 1; nand->ecc.calculate = nand_davinci_calculate_ecc; nand->ecc.correct = nand_davinci_correct_data; nand->ecc.hwctl = nand_davinci_enable_hwecc; @@ -623,6 +624,7 @@ void davinci_nand_init(struct nand_chip *nand) nand->ecc.mode = NAND_ECC_HW_OOB_FIRST; nand->ecc.size = 512; nand->ecc.bytes = 10; + nand->ecc.strength = 4; nand->ecc.calculate = nand_davinci_4bit_calculate_ecc; nand->ecc.correct = nand_davinci_4bit_correct_data; nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index edf3a099ba..4cd741ebbb 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -134,7 +134,7 @@ static struct rs_control *rs_decoder; /* * The HW decoder in the DoC ASIC's provides us a error syndrome, - * which we must convert to a standard syndrom usable by the generic + * which we must convert to a standard syndrome usable by the generic * Reed-Solomon library code. * * Fabrice Bellard figured this out in the old docecc code. I added @@ -154,7 +154,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); parity = ecc[1]; - /* Initialize the syndrom buffer */ + /* Initialize the syndrome buffer */ for (i = 0; i < NROOTS; i++) s[i] = ds[0]; /* @@ -1033,7 +1033,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); else WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - if (no_ecc_failures && (ret == -EBADMSG)) { + if (no_ecc_failures && mtd_is_eccerr(ret)) { printk(KERN_ERR "suppressing ECC failure\n"); ret = 0; } @@ -1073,7 +1073,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch size_t retlen; for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { - ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); if (retlen != mtd->writesize) continue; if (ret) { @@ -1098,7 +1098,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch /* Only one mediaheader was found. We want buf to contain a mediaheader on return, so we'll have to re-read the one we found. */ offs = doc->mh0_page << this->page_shift; - ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + ret = mtd_read(mtd, offs, mtd->writesize, &retlen, buf); if (retlen != mtd->writesize) { /* Insanity. Give up. */ printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); @@ -1658,7 +1658,8 @@ static int __init doc_probe(unsigned long physadr) nand->ecc.mode = NAND_ECC_HW_SYNDROME; nand->ecc.size = 512; nand->ecc.bytes = 6; - nand->options = NAND_USE_FLASH_BBT; + nand->ecc.strength = 2; + nand->bbt_options = NAND_BBT_USE_FLASH; doc->physadr = physadr; doc->virtadr = virtadr; diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 834a8a6498..0fa776ae91 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -640,9 +640,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) return fsl_elbc_read_byte(mtd); } -static int fsl_elbc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf, int page) +static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) { fsl_elbc_read_buf(mtd, buf, mtd->writesize); fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -656,12 +655,13 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_elbc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf) +static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } static struct fsl_elbc_ctrl *elbc_ctrl; @@ -747,8 +747,8 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) nand->bbt_md = &bbt_mirror_descr; /* set up nand options */ - nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | - NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE; + nand->options = NAND_NO_SUBPAGE_WRITE; + nand->bbt_options = NAND_BBT_USE_FLASH; nand->controller = &elbc_ctrl->controller; nand->priv = priv; @@ -756,20 +756,8 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) nand->ecc.read_page = fsl_elbc_read_page; nand->ecc.write_page = fsl_elbc_write_page; -#ifdef CONFIG_FSL_ELBC_FMR - priv->fmr = CONFIG_FSL_ELBC_FMR; -#else priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT); - /* - * Hardware expects small page has ECCM0, large page has ECCM1 - * when booting from NAND. Board config can override if not - * booting from NAND. - */ - if (or & OR_FCM_PGS) - priv->fmr |= FMR_ECCM; -#endif - /* If CS Base Register selects full hardware ECC then use it */ if ((br & BR_DECC) == BR_DECC_CHK_GEN) { nand->ecc.mode = NAND_ECC_HW; @@ -781,16 +769,32 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) nand->ecc.size = 512; nand->ecc.bytes = 3; nand->ecc.steps = 1; + nand->ecc.strength = 1; } else { /* otherwise fall back to default software ECC */ nand->ecc.mode = NAND_ECC_SOFT; } + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + /* Large-page-specific setup */ - if (or & OR_FCM_PGS) { + if (mtd->writesize == 2048) { + setbits_be32(&elbc_ctrl->regs->bank[priv->bank].or, + OR_FCM_PGS); + in_be32(&elbc_ctrl->regs->bank[priv->bank].or); + priv->page_size = 1; nand->badblock_pattern = &largepage_memorybased; + /* + * Hardware expects small page has ECCM0, large page has + * ECCM1 when booting from NAND, and we follow that even + * when not booting from NAND. + */ + priv->fmr |= FMR_ECCM; + /* adjust ecc setup if needed */ if ((br & BR_DECC) == BR_DECC_CHK_GEN) { nand->ecc.steps = 4; @@ -798,12 +802,14 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) &fsl_elbc_oob_lp_eccm1 : &fsl_elbc_oob_lp_eccm0; } + } else if (mtd->writesize == 512) { + clrbits_be32(&elbc_ctrl->regs->bank[priv->bank].or, + OR_FCM_PGS); + in_be32(&elbc_ctrl->regs->bank[priv->bank].or); + } else { + return -ENODEV; } - ret = nand_scan_ident(mtd, 1, NULL); - if (ret) - return ret; - ret = nand_scan_tail(mtd); if (ret) return ret; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index b13d8a9303..439822c5a2 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -21,6 +21,7 @@ #include <common.h> #include <malloc.h> +#include <nand.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -41,7 +42,6 @@ struct fsl_ifc_ctrl; /* mtd information per set */ struct fsl_ifc_mtd { - struct mtd_info mtd; struct nand_chip chip; struct fsl_ifc_ctrl *ctrl; @@ -686,9 +686,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return nand_fsr; } -static int fsl_ifc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf, int page) +static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; @@ -705,12 +704,13 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_ifc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf) +static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { fsl_ifc_write_buf(mtd, buf, mtd->writesize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } static void fsl_ifc_ctrl_init(void) @@ -794,11 +794,14 @@ static void fsl_ifc_sram_init(void) out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext); } -int board_nand_init(struct nand_chip *nand) +static int fsl_ifc_chip_init(int devnum, u8 *addr) { + struct mtd_info *mtd = &nand_info[devnum]; + struct nand_chip *nand; struct fsl_ifc_mtd *priv; struct nand_ecclayout *layout; uint32_t cspr = 0, csor = 0, ver = 0; + int ret; if (!ifc_ctrl) { fsl_ifc_ctrl_init(); @@ -811,18 +814,18 @@ int board_nand_init(struct nand_chip *nand) return -ENOMEM; priv->ctrl = ifc_ctrl; - priv->vbase = nand->IO_ADDR_R; + priv->vbase = addr; /* Find which chip select it is connected to. */ for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) { - phys_addr_t base_addr = virt_to_phys(nand->IO_ADDR_R); + phys_addr_t phys_addr = virt_to_phys(addr); cspr = in_be32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr); csor = in_be32(&ifc_ctrl->regs->csor_cs[priv->bank].csor); if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND && - (cspr & CSPR_BA) == CSPR_PHYS_ADDR(base_addr)) { + (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) { ifc_ctrl->cs_nand = priv->bank << IFC_NAND_CSEL_SHIFT; break; } @@ -835,6 +838,9 @@ int board_nand_init(struct nand_chip *nand) return -ENODEV; } + nand = &priv->chip; + mtd->priv = nand; + ifc_ctrl->chips[priv->bank] = priv; /* fill in nand_chip structure */ @@ -852,8 +858,8 @@ int board_nand_init(struct nand_chip *nand) nand->bbt_md = &bbt_mirror_descr; /* set up nand options */ - nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | - NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE; + nand->options = NAND_NO_SUBPAGE_WRITE; + nand->bbt_options = NAND_BBT_USE_FLASH; if (cspr & CSPR_PORT_SIZE_16) { nand->read_byte = fsl_ifc_read_byte16; @@ -884,11 +890,13 @@ int board_nand_init(struct nand_chip *nand) bbt_mirror_descr.offs = 0; } + nand->ecc.strength = 4; priv->bufnum_mask = 15; break; case CSOR_NAND_PGS_2K: layout = &oob_2048_ecc4; + nand->ecc.strength = 4; priv->bufnum_mask = 3; break; @@ -896,8 +904,10 @@ int board_nand_init(struct nand_chip *nand) if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) { layout = &oob_4096_ecc4; + nand->ecc.strength = 4; } else { layout = &oob_4096_ecc8; + nand->ecc.strength = 8; nand->ecc.bytes = 16; } @@ -921,5 +931,31 @@ int board_nand_init(struct nand_chip *nand) if (ver == FSL_IFC_V1_1_0) fsl_ifc_sram_init(); + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + return ret; + + ret = nand_scan_tail(mtd); + if (ret) + return ret; + + ret = nand_register(devnum); + if (ret) + return ret; return 0; } + +#ifndef CONFIG_SYS_NAND_BASE_LIST +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } +#endif + +static unsigned long base_address[CONFIG_SYS_MAX_NAND_DEVICE] = + CONFIG_SYS_NAND_BASE_LIST; + +void board_nand_init(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) + fsl_ifc_chip_init(i, (u8 *)base_address[i]); +} diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 7a61d88cc5..fab2aebc31 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -341,6 +341,7 @@ void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller expects OOB data read to chip->oob_poi * @page: page number to read * * This routine is needed for fsmc verison 8 as reading from NAND chip has to be @@ -350,7 +351,7 @@ void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) * max of 8 bits) */ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { struct fsmc_eccplace *fsmc_eccpl; int i, j, s, stat, eccsize = chip->ecc.size; @@ -452,6 +453,7 @@ int fsmc_nand_init(struct nand_chip *nand) switch (fsmc_version) { case FSMC_VER8: nand->ecc.bytes = 13; + nand->ecc.strength = 8; nand->ecc.correct = fsmc_bch8_correct_data; nand->ecc.read_page = fsmc_read_page_hwecc; if (mtd->writesize == 512) @@ -466,6 +468,7 @@ int fsmc_nand_init(struct nand_chip *nand) break; default: nand->ecc.bytes = 3; + nand->ecc.strength = 1; nand->ecc.layout = &fsmc_ecc1_layout; nand->ecc.correct = nand_correct_data; break; diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 3ec34f3c9b..a691fbc403 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -253,6 +253,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.mode = NAND_ECC_HW_OOB_FIRST; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; + nand->ecc.strength = 4; nand->ecc.layout = &qi_lb60_ecclayout_2gb; nand->chip_delay = 50; nand->options = NAND_USE_FLASH_BBT; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index e6b7a70661..e53f341dcf 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -621,7 +621,7 @@ int board_nand_init(struct nand_chip *chip) chip->write_buf = mpc5121_nfc_write_buf; chip->verify_buf = mpc5121_nfc_verify_buf; chip->select_chip = mpc5121_nfc_select_chip; - chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT; + chip->bbt_options = NAND_BBT_USE_FLASH; chip->ecc.mode = NAND_ECC_SOFT; /* Reset NAND Flash controller */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index eeba521942..ac435f2050 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -396,7 +396,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) #if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page, int sndcmd) + int page) { struct mxc_nand_host *host = chip->priv; uint8_t *buf = chip->oob_poi; @@ -450,6 +450,7 @@ static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct mxc_nand_host *host = chip->priv; @@ -494,6 +495,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct mxc_nand_host *host = chip->priv; @@ -583,9 +585,10 @@ static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd, return status & NAND_STATUS_FAIL ? -EIO : 0; } -static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, +static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, + int oob_required) { struct mxc_nand_host *host = chip->priv; int eccsize = chip->ecc.size; @@ -619,11 +622,13 @@ static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, size = mtd->oobsize - (oob - chip->oob_poi); if (size) chip->write_buf(mtd, oob, size); + return 0; } -static void mxc_nand_write_page_syndrome(struct mtd_info *mtd, +static int mxc_nand_write_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, + int oob_required) { struct mxc_nand_host *host = chip->priv; int i, n, eccsize = chip->ecc.size; @@ -662,6 +667,7 @@ static void mxc_nand_write_page_syndrome(struct mtd_info *mtd, i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->write_buf(mtd, oob, i); + return 0; } static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, @@ -1188,7 +1194,7 @@ int board_nand_init(struct nand_chip *this) #endif #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT - this->options |= NAND_USE_FLASH_BBT; + this->bbt_options |= NAND_BBT_USE_FLASH; this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; #endif @@ -1236,6 +1242,13 @@ int board_nand_init(struct nand_chip *this) this->ecc.mode = NAND_ECC_HW; } + if (this->ecc.mode == NAND_ECC_HW) { + if (is_mxc_nfc_1()) + this->ecc.strength = 1; + else + this->ecc.strength = 4; + } + host->pagesize_2k = 0; this->ecc.size = 512; diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 398e4ddc15..866cabd276 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -553,7 +553,8 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd) * Read a page from NAND. */ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, + int page) { struct mxs_nand_info *nand_info = nand->priv; struct mxs_dma_desc *d; @@ -698,8 +699,9 @@ rtn: /* * Write a page to NAND. */ -static void mxs_nand_ecc_write_page(struct mtd_info *mtd, - struct nand_chip *nand, const uint8_t *buf) +static int mxs_nand_ecc_write_page(struct mtd_info *mtd, + struct nand_chip *nand, const uint8_t *buf, + int oob_required) { struct mxs_nand_info *nand_info = nand->priv; struct mxs_dma_desc *d; @@ -755,6 +757,7 @@ static void mxs_nand_ecc_write_page(struct mtd_info *mtd, rtn: mxs_nand_return_dma_descs(nand_info); + return 0; } /* @@ -770,7 +773,7 @@ static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from, struct mxs_nand_info *nand_info = chip->priv; int ret; - if (ops->mode == MTD_OOB_RAW) + if (ops->mode == MTD_OPS_RAW) nand_info->raw_oob_mode = 1; else nand_info->raw_oob_mode = 0; @@ -795,7 +798,7 @@ static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to, struct mxs_nand_info *nand_info = chip->priv; int ret; - if (ops->mode == MTD_OOB_RAW) + if (ops->mode == MTD_OPS_RAW) nand_info->raw_oob_mode = 1; else nand_info->raw_oob_mode = 0; @@ -873,7 +876,7 @@ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs) * what to do. */ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand, - int page, int cmd) + int page) { struct mxs_nand_info *nand_info = nand->priv; @@ -1006,19 +1009,19 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set); /* Hook some operations at the MTD level. */ - if (mtd->read_oob != mxs_nand_hook_read_oob) { - nand_info->hooked_read_oob = mtd->read_oob; - mtd->read_oob = mxs_nand_hook_read_oob; + if (mtd->_read_oob != mxs_nand_hook_read_oob) { + nand_info->hooked_read_oob = mtd->_read_oob; + mtd->_read_oob = mxs_nand_hook_read_oob; } - if (mtd->write_oob != mxs_nand_hook_write_oob) { - nand_info->hooked_write_oob = mtd->write_oob; - mtd->write_oob = mxs_nand_hook_write_oob; + if (mtd->_write_oob != mxs_nand_hook_write_oob) { + nand_info->hooked_write_oob = mtd->_write_oob; + mtd->_write_oob = mxs_nand_hook_write_oob; } - if (mtd->block_markbad != mxs_nand_hook_block_markbad) { - nand_info->hooked_block_markbad = mtd->block_markbad; - mtd->block_markbad = mxs_nand_hook_block_markbad; + if (mtd->_block_markbad != mxs_nand_hook_block_markbad) { + nand_info->hooked_block_markbad = mtd->_block_markbad; + mtd->_block_markbad = mxs_nand_hook_block_markbad; } /* We use the reference implementation for bad block management. */ @@ -1172,6 +1175,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.mode = NAND_ECC_HW; nand->ecc.bytes = 9; nand->ecc.size = 512; + nand->ecc.strength = 8; return 0; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a2d06be99f..9e05cef417 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -21,7 +21,7 @@ * TODO: * Enable cached programming for 2k page size chips * Check, if mtd->ecctype should be set to MTD_ECC_HW - * if we have HW ecc support. + * if we have HW ECC support. * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * BBT table is not serialized, has to be fixed @@ -134,21 +134,14 @@ static int check_offs_len(struct mtd_info *mtd, ret = -EINVAL; } - /* Do not allow past end of device */ - if (ofs + len > mtd->size) { - MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n", - __func__); - ret = -EINVAL; - } - return ret; } /** * nand_release_device - [GENERIC] release chip - * @mtd: MTD device structure + * @mtd: MTD device structure * - * Deselect, release chip lock and wake up anyone waiting on the device + * Deselect, release chip lock and wake up anyone waiting on the device. */ static void nand_release_device(struct mtd_info *mtd) { @@ -160,9 +153,9 @@ static void nand_release_device(struct mtd_info *mtd) /** * nand_read_byte - [DEFAULT] read one byte from the chip - * @mtd: MTD device structure + * @mtd: MTD device structure * - * Default read function for 8bit buswith + * Default read function for 8bit buswidth. */ uint8_t nand_read_byte(struct mtd_info *mtd) { @@ -172,10 +165,11 @@ uint8_t nand_read_byte(struct mtd_info *mtd) /** * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip - * @mtd: MTD device structure + * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip + * @mtd: MTD device structure + * + * Default read function for 16bit buswidth with endianness conversion. * - * Default read function for 16bit buswith with - * endianess conversion */ static uint8_t nand_read_byte16(struct mtd_info *mtd) { @@ -185,10 +179,9 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd) /** * nand_read_word - [DEFAULT] read one word from the chip - * @mtd: MTD device structure + * @mtd: MTD device structure * - * Default read function for 16bit buswith without - * endianess conversion + * Default read function for 16bit buswidth without endianness conversion. */ static u16 nand_read_word(struct mtd_info *mtd) { @@ -198,8 +191,8 @@ static u16 nand_read_word(struct mtd_info *mtd) /** * nand_select_chip - [DEFAULT] control CE line - * @mtd: MTD device structure - * @chipnr: chipnumber to select, -1 for deselect + * @mtd: MTD device structure + * @chipnr: chipnumber to select, -1 for deselect * * Default select function for 1 chip devices. */ @@ -221,11 +214,11 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) /** * nand_write_buf - [DEFAULT] write buffer to chip - * @mtd: MTD device structure - * @buf: data buffer - * @len: number of bytes to write + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write * - * Default write function for 8bit buswith + * Default write function for 8bit buswidth. */ void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { @@ -238,11 +231,11 @@ void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_read_buf - [DEFAULT] read chip data into buffer - * @mtd: MTD device structure - * @buf: buffer to store date - * @len: number of bytes to read + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read * - * Default read function for 8bit buswith + * Default read function for 8bit buswidth. */ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { @@ -255,11 +248,11 @@ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) /** * nand_verify_buf - [DEFAULT] Verify chip data against buffer - * @mtd: MTD device structure - * @buf: buffer containing the data to compare - * @len: number of bytes to compare + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare * - * Default verify function for 8bit buswith + * Default verify function for 8bit buswidth. */ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { @@ -274,11 +267,11 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_write_buf16 - [DEFAULT] write buffer to chip - * @mtd: MTD device structure - * @buf: data buffer - * @len: number of bytes to write + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write * - * Default write function for 16bit buswith + * Default write function for 16bit buswidth. */ void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { @@ -294,11 +287,11 @@ void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_read_buf16 - [DEFAULT] read chip data into buffer - * @mtd: MTD device structure - * @buf: buffer to store date - * @len: number of bytes to read + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read * - * Default read function for 16bit buswith + * Default read function for 16bit buswidth. */ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) { @@ -313,11 +306,11 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) /** * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer - * @mtd: MTD device structure - * @buf: buffer containing the data to compare - * @len: number of bytes to compare + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare * - * Default verify function for 16bit buswith + * Default verify function for 16bit buswidth. */ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { @@ -335,19 +328,19 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_block_bad - [DEFAULT] Read bad block marker from the chip - * @mtd: MTD device structure - * @ofs: offset from device start - * @getchip: 0, if the chip is already selected + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected * * Check, if the block is bad. */ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) { - int page, chipnr, res = 0; + int page, chipnr, res = 0, i = 0; struct nand_chip *chip = mtd->priv; u16 bad; - if (chip->options & NAND_BBT_SCANLASTPAGE) + if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) ofs += mtd->erasesize - mtd->writesize; page = (int)(ofs >> chip->page_shift) & chip->pagemask; @@ -361,23 +354,29 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) chip->select_chip(mtd, chipnr); } - if (chip->options & NAND_BUSWIDTH_16) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, - page); - bad = cpu_to_le16(chip->read_word(mtd)); - if (chip->badblockpos & 0x1) - bad >>= 8; - else - bad &= 0xFF; - } else { - chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); - bad = chip->read_byte(mtd); - } + do { + if (chip->options & NAND_BUSWIDTH_16) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, + chip->badblockpos & 0xFE, page); + bad = cpu_to_le16(chip->read_word(mtd)); + if (chip->badblockpos & 0x1) + bad >>= 8; + else + bad &= 0xFF; + } else { + chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, + page); + bad = chip->read_byte(mtd); + } - if (likely(chip->badblockbits == 8)) - res = bad != 0xFF; - else - res = hweight8(bad) < chip->badblockbits; + if (likely(chip->badblockbits == 8)) + res = bad != 0xFF; + else + res = hweight8(bad) < chip->badblockbits; + ofs += mtd->writesize; + page = (int)(ofs >> chip->page_shift) & chip->pagemask; + i++; + } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); if (getchip) nand_release_device(mtd); @@ -387,57 +386,83 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) /** * nand_default_block_markbad - [DEFAULT] mark a block bad - * @mtd: MTD device structure - * @ofs: offset from device start + * @mtd: MTD device structure + * @ofs: offset from device start * - * This is the default implementation, which can be overridden by - * a hardware specific driver. + * This is the default implementation, which can be overridden by a hardware + * specific driver. We try operations in the following order, according to our + * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): + * (1) erase the affected block, to allow OOB marker to be written cleanly + * (2) update in-memory BBT + * (3) write bad block marker to OOB area of affected block + * (4) update flash-based BBT + * Note that we retain the first error encountered in (3) or (4), finish the + * procedures, and dump the error in the end. */ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd->priv; uint8_t buf[2] = { 0, 0 }; - int block, ret, i = 0; + int block, res, ret = 0, i = 0; + int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); - if (chip->options & NAND_BBT_SCANLASTPAGE) - ofs += mtd->erasesize - mtd->writesize; + if (write_oob) { + struct erase_info einfo; + + /* Attempt erase before marking OOB */ + memset(&einfo, 0, sizeof(einfo)); + einfo.mtd = mtd; + einfo.addr = ofs; + einfo.len = 1 << chip->phys_erase_shift; + nand_erase_nand(mtd, &einfo, 0); + } /* Get block number */ block = (int)(ofs >> chip->bbt_erase_shift); + /* Mark block bad in memory-based BBT */ if (chip->bbt) chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); - /* Do we have a flash based bad block table ? */ - if (chip->options & NAND_USE_FLASH_BBT) - ret = nand_update_bbt(mtd, ofs); - else { + /* Write bad block marker to OOB */ + if (write_oob) { + struct mtd_oob_ops ops; + loff_t wr_ofs = ofs; + nand_get_device(chip, mtd, FL_WRITING); - /* Write to first two pages and to byte 1 and 6 if necessary. - * If we write to more than one location, the first error - * encountered quits the procedure. We write two bytes per - * location, so we dont have to mess with 16 bit access. - */ - do { - chip->ops.len = chip->ops.ooblen = 2; - chip->ops.datbuf = NULL; - chip->ops.oobbuf = buf; - chip->ops.ooboffs = chip->badblockpos & ~0x01; + ops.datbuf = NULL; + ops.oobbuf = buf; + ops.ooboffs = chip->badblockpos; + if (chip->options & NAND_BUSWIDTH_16) { + ops.ooboffs &= ~0x01; + ops.len = ops.ooblen = 2; + } else { + ops.len = ops.ooblen = 1; + } + ops.mode = MTD_OPS_PLACE_OOB; - ret = nand_do_write_oob(mtd, ofs, &chip->ops); + /* Write to first/last page(s) if necessary */ + if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) + wr_ofs += mtd->erasesize - mtd->writesize; + do { + res = nand_do_write_oob(mtd, wr_ofs, &ops); + if (!ret) + ret = res; - if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) { - chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS - & ~0x01; - ret = nand_do_write_oob(mtd, ofs, &chip->ops); - } i++; - ofs += mtd->writesize; - } while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) && - i < 2); + wr_ofs += mtd->writesize; + } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); nand_release_device(mtd); } + + /* Update flash-based bad block table */ + if (chip->bbt_options & NAND_BBT_USE_FLASH) { + res = nand_update_bbt(mtd, ofs); + if (!ret) + ret = res; + } + if (!ret) mtd->ecc_stats.badblocks++; @@ -446,16 +471,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) /** * nand_check_wp - [GENERIC] check if the chip is write protected - * @mtd: MTD device structure - * Check, if the device is write protected + * @mtd: MTD device structure * - * The function expects, that the device is already selected + * Check, if the device is write protected. The function expects, that the + * device is already selected. */ static int nand_check_wp(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; - /* broken xD cards report WP despite being writable */ + /* Broken xD cards report WP despite being writable */ if (chip->options & NAND_BROKEN_XD) return 0; @@ -466,10 +491,10 @@ static int nand_check_wp(struct mtd_info *mtd) /** * nand_block_checkbad - [GENERIC] Check if a block is marked bad - * @mtd: MTD device structure - * @ofs: offset from device start - * @getchip: 0, if the chip is already selected - * @allowbbt: 1, if its allowed to access the bbt area + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected + * @allowbbt: 1, if its allowed to access the bbt area * * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. @@ -491,10 +516,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, return nand_isbad_bbt(mtd, ofs, allowbbt); } -/* - * Wait for the ready pin, after a command - * The timeout is catched later. - */ +/* Wait for the ready pin, after a command. The timeout is caught later. */ void nand_wait_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; @@ -503,7 +525,7 @@ void nand_wait_ready(struct mtd_info *mtd) time_start = get_timer(0); - /* wait until command is processed or timeout occures */ + /* Wait until command is processed or timeout occurs */ while (get_timer(time_start) < timeo) { if (chip->dev_ready) if (chip->dev_ready(mtd)) @@ -513,13 +535,13 @@ void nand_wait_ready(struct mtd_info *mtd) /** * nand_command - [DEFAULT] Send command to NAND device - * @mtd: MTD device structure - * @command: the command to be sent - * @column: the column address for this command, -1 if none - * @page_addr: the page address for this command, -1 if none + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none * - * Send command to NAND device. This function is used for small page - * devices (256/512 Bytes per page) + * Send command to NAND device. This function is used for small page devices + * (256/512 Bytes per page). */ static void nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr) @@ -528,9 +550,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT; - /* - * Write out the command to the device. - */ + /* Write out the command to the device */ if (command == NAND_CMD_SEQIN) { int readcmd; @@ -550,9 +570,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, } chip->cmd_ctrl(mtd, command, ctrl); - /* - * Address cycle, when necessary - */ + /* Address cycle, when necessary */ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; /* Serially input address */ if (column != -1) { @@ -573,8 +591,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* - * program and erase have their own busy handlers - * status and sequential in needs no delay + * Program and erase have their own busy handlers status and sequential + * in needs no delay */ switch (command) { @@ -608,8 +626,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, return; } } - /* Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. */ + /* + * Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. + */ ndelay(100); nand_wait_ready(mtd); @@ -617,14 +637,14 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, /** * nand_command_lp - [DEFAULT] Send command to NAND large page device - * @mtd: MTD device structure - * @command: the command to be sent - * @column: the column address for this command, -1 if none - * @page_addr: the page address for this command, -1 if none + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none * * Send command to NAND device. This is the version for the new large page - * devices We dont have the separate regions as we have in the small page - * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. + * devices. We don't have the separate regions as we have in the small page + * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. */ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) @@ -667,8 +687,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* - * program and erase have their own busy handlers - * status, sequential in, and deplete1 need no delay + * Program and erase have their own busy handlers status, sequential + * in, and deplete1 need no delay. */ switch (command) { @@ -682,14 +702,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, case NAND_CMD_DEPLETE1: return; - /* - * read error status commands require only a short delay - */ case NAND_CMD_STATUS_ERROR: case NAND_CMD_STATUS_ERROR0: case NAND_CMD_STATUS_ERROR1: case NAND_CMD_STATUS_ERROR2: case NAND_CMD_STATUS_ERROR3: + /* Read error status commands require only a short delay */ udelay(chip->chip_delay); return; @@ -723,7 +741,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, default: /* * If we don't have access to the busy pin, we apply the given - * command delay + * command delay. */ if (!chip->dev_ready) { udelay(chip->chip_delay); @@ -731,8 +749,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, } } - /* Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. */ + /* + * Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. + */ ndelay(100); nand_wait_ready(mtd); @@ -740,9 +760,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, /** * nand_get_device - [GENERIC] Get chip for selected access - * @chip: the nand chip descriptor - * @mtd: MTD device structure - * @new_state: the state which is requested + * @chip: the nand chip descriptor + * @mtd: MTD device structure + * @new_state: the state which is requested * * Get the device and lock it for exclusive access */ @@ -754,13 +774,13 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) } /** - * nand_wait - [DEFAULT] wait until the command is done - * @mtd: MTD device structure - * @chip: NAND chip structure + * nand_wait - [DEFAULT] wait until the command is done + * @mtd: MTD device structure + * @chip: NAND chip structure * - * Wait for command done. This applies to erase and program only - * Erase can take up to 400ms and program up to 20ms according to - * general NAND and SmartMedia specs + * Wait for command done. This applies to erase and program only. Erase can + * take up to 400ms and program up to 20ms according to general NAND and + * SmartMedia specs. */ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) { @@ -804,34 +824,37 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) } /** - * nand_read_page_raw - [Intern] read raw page data without ecc - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_raw - [INTERN] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read * - * Not for syndrome calculating ecc controllers, which use a special oob layout + * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { chip->read_buf(mtd, buf, mtd->writesize); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + if (oob_required) + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } /** - * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read * * We need a special oob layout and handling even when OOB isn't used. */ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -864,14 +887,15 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, } /** - * nand_read_page_swecc - [REPLACABLE] software ecc based page read function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read */ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -881,7 +905,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; - chip->ecc.read_page_raw(mtd, chip, buf, page); + chip->ecc.read_page_raw(mtd, chip, buf, 1, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); @@ -905,12 +929,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @data_offs: offset of requested data within the page - * @readlen: data length - * @bufpoi: buffer to store read data + * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @data_offs: offset of requested data within the page + * @readlen: data length + * @bufpoi: buffer to store read data */ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) @@ -923,12 +947,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; int index = 0; - /* Column address wihin the page aligned to ECC size (256bytes). */ + /* Column address within the page aligned to ECC size (256bytes) */ start_step = data_offs / chip->ecc.size; end_step = (data_offs + readlen - 1) / chip->ecc.size; num_steps = end_step - start_step + 1; - /* Data size aligned to ECC ecc.size*/ + /* Data size aligned to ECC ecc.size */ datafrag_len = num_steps * chip->ecc.size; eccfrag_len = num_steps * chip->ecc.bytes; @@ -940,13 +964,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, p = bufpoi + data_col_addr; chip->read_buf(mtd, p, datafrag_len); - /* Calculate ECC */ + /* Calculate ECC */ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]); - /* The performance is faster if to position offsets - according to ecc.pos. Let make sure here that - there are no gaps in ecc positions */ + /* + * The performance is faster if we position offsets according to + * ecc.pos. Let's make sure that there are no gaps in ECC positions. + */ for (i = 0; i < eccfrag_len - 1; i++) { if (eccpos[i + start_step * chip->ecc.bytes] + 1 != eccpos[i + start_step * chip->ecc.bytes + 1]) { @@ -958,8 +983,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); } else { - /* send the command to read the particular ecc bytes */ - /* take care about buswidth alignment in read_buf */ + /* + * Send the command to read the particular ECC bytes take care + * about buswidth alignment in read_buf. + */ index = start_step * chip->ecc.bytes; aligned_pos = eccpos[index] & ~(busw - 1); @@ -992,16 +1019,17 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read * - * Not for syndrome calculating ecc controllers which need a special oob layout + * Not for syndrome calculating ECC controllers which need a special oob layout. */ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1037,21 +1065,21 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read * - * Hardware ECC for large page chips, require OOB to be read first. - * For this ECC mode, the write_page method is re-used from ECC_HW. - * These methods read/write ECC from the OOB area, unlike the - * ECC_HW_SYNDROME support with multiple ECC steps, follows the - * "infix ECC" scheme and reads/writes ECC from the data area, by - * overwriting the NAND manufacturer bad block markings. + * Hardware ECC for large page chips, require OOB to be read first. For this + * ECC mode, the write_page method is re-used from ECC_HW. These methods + * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with + * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from + * the data area, by overwriting the NAND manufacturer bad block markings. */ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1086,17 +1114,18 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, } /** - * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: buffer to store read data - * @page: page number to read + * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read * - * The hw generator calculates the error syndrome automatically. Therefor - * we need a special oob layout and handling. + * The hw generator calculates the error syndrome automatically. Therefore we + * need a special oob layout and handling. */ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1141,29 +1170,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_transfer_oob - [Internal] Transfer oob to client buffer - * @chip: nand chip structure - * @oob: oob destination address - * @ops: oob ops structure - * @len: size of oob to transfer + * nand_transfer_oob - [INTERN] Transfer oob to client buffer + * @chip: nand chip structure + * @oob: oob destination address + * @ops: oob ops structure + * @len: size of oob to transfer */ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, struct mtd_oob_ops *ops, size_t len) { switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_RAW: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_RAW: memcpy(oob, chip->oob_poi + ops->ooboffs, len); return oob + len; - case MTD_OOB_AUTO: { + case MTD_OPS_AUTO_OOB: { struct nand_oobfree *free = chip->ecc.layout->oobfree; uint32_t boffs = 0, roffs = ops->ooboffs; size_t bytes = 0; for (; free->length && len; free++, len -= bytes) { - /* Read request not from offset 0 ? */ + /* Read request not from offset 0? */ if (unlikely(roffs)) { if (roffs >= free->length) { roffs -= free->length; @@ -1189,26 +1218,23 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, } /** - * nand_do_read_ops - [Internal] Read data with ECC - * - * @mtd: MTD device structure - * @from: offset to read from - * @ops: oob ops structure + * nand_do_read_ops - [INTERN] Read data with ECC + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob ops structure * * Internal function. Called with chip held. */ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int chipnr, page, realpage, col, bytes, aligned; + int chipnr, page, realpage, col, bytes, aligned, oob_required; struct nand_chip *chip = mtd->priv; struct mtd_ecc_stats stats; - int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; - int sndcmd = 1; int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; - uint32_t max_oobsize = ops->mode == MTD_OOB_AUTO ? + uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; @@ -1225,6 +1251,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, buf = ops->datbuf; oob = ops->oobbuf; + oob_required = oob ? 1 : 0; while (1) { WATCHDOG_RESET(); @@ -1232,41 +1259,46 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, bytes = min(mtd->writesize - col, readlen); aligned = (bytes == mtd->writesize); - /* Is the current page in the buffer ? */ + /* Is the current page in the buffer? */ if (realpage != chip->pagebuf || oob) { bufpoi = aligned ? buf : chip->buffers->databuf; - if (likely(sndcmd)) { - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); /* Now read the page into the buffer */ - if (unlikely(ops->mode == MTD_OOB_RAW)) - ret = chip->ecc.read_page_raw(mtd, chip, - bufpoi, page); + if (unlikely(ops->mode == MTD_OPS_RAW)) + ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, + oob_required, + page); else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && !oob) ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); else ret = chip->ecc.read_page(mtd, chip, bufpoi, - page); - if (ret < 0) + oob_required, page); + if (ret < 0) { + if (!aligned) + /* Invalidate page cache */ + chip->pagebuf = -1; break; + } /* Transfer not aligned data */ if (!aligned) { if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && - !(mtd->ecc_stats.failed - stats.failed)) + !(mtd->ecc_stats.failed - stats.failed) && + (ops->mode != MTD_OPS_RAW)) chip->pagebuf = realpage; + else + /* Invalidate page cache */ + chip->pagebuf = -1; memcpy(buf, chip->buffers->databuf + col, bytes); } buf += bytes; if (unlikely(oob)) { - int toread = min(oobreadlen, max_oobsize); if (toread) { @@ -1275,20 +1307,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, oobreadlen -= toread; } } - - if (!(chip->options & NAND_NO_READRDY)) { - /* - * Apply delay or wait for ready/busy pin. Do - * this before the AUTOINCR check, so no - * problems arise if a chip which does auto - * increment is marked as NOAUTOINCR by the - * board driver. - */ - if (!chip->dev_ready) - udelay(chip->chip_delay); - else - nand_wait_ready(mtd); - } } else { memcpy(buf, chip->buffers->databuf + col, bytes); buf += bytes; @@ -1299,7 +1317,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (!readlen) break; - /* For subsequent reads align to page boundary. */ + /* For subsequent reads align to page boundary */ col = 0; /* Increment page address */ realpage++; @@ -1311,12 +1329,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } - - /* Check, if the chip supports auto page increment - * or if we have hit a block boundary. - */ - if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) - sndcmd = 1; } ops->retlen = ops->len - (size_t) readlen; @@ -1334,69 +1346,55 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, /** * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc - * @mtd: MTD device structure - * @from: offset to read from - * @len: number of bytes to read - * @retlen: pointer to variable to store the number of read bytes - * @buf: the databuffer to put data + * @mtd: MTD device structure + * @from: offset to read from + * @len: number of bytes to read + * @retlen: pointer to variable to store the number of read bytes + * @buf: the databuffer to put data * - * Get hold of the chip and call nand_do_read + * Get hold of the chip and call nand_do_read. */ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, uint8_t *buf) { struct nand_chip *chip = mtd->priv; + struct mtd_oob_ops ops; int ret; - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) - return -EINVAL; - if (!len) - return 0; - nand_get_device(chip, mtd, FL_READING); - - chip->ops.len = len; - chip->ops.datbuf = buf; - chip->ops.oobbuf = NULL; - - ret = nand_do_read_ops(mtd, from, &chip->ops); - - *retlen = chip->ops.retlen; - + ops.len = len; + ops.datbuf = buf; + ops.oobbuf = NULL; + ops.mode = MTD_OPS_PLACE_OOB; + ret = nand_do_read_ops(mtd, from, &ops); + *retlen = ops.retlen; nand_release_device(mtd); - return ret; } /** - * nand_read_oob_std - [REPLACABLE] the most common OOB data read function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @page: page number to read - * @sndcmd: flag whether to issue read command or not + * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read */ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page, int sndcmd) + int page) { - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - sndcmd = 0; - } + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return sndcmd; + return 0; } /** - * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC + * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC * with syndromes - * @mtd: mtd info structure - * @chip: nand chip info structure - * @page: page number to read - * @sndcmd: flag whether to issue read command or not + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read */ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page, int sndcmd) + int page) { uint8_t *buf = chip->oob_poi; int length = mtd->oobsize; @@ -1423,14 +1421,14 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (length > 0) chip->read_buf(mtd, bufpoi, length); - return 1; + return 0; } /** - * nand_write_oob_std - [REPLACABLE] the most common OOB data write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @page: page number to write + * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write */ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) @@ -1450,11 +1448,11 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, } /** - * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC - * with syndrome - only for large page flash ! - * @mtd: mtd info structure - * @chip: nand chip info structure - * @page: page number to write + * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC + * with syndrome - only for large page flash + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write */ static int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page) @@ -1509,27 +1507,30 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, } /** - * nand_do_read_oob - [Intern] NAND read out-of-band - * @mtd: MTD device structure - * @from: offset to read from - * @ops: oob operations description structure + * nand_do_read_oob - [INTERN] NAND read out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operations description structure * - * NAND read out-of-band data from the spare area + * NAND read out-of-band data from the spare area. */ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int page, realpage, chipnr, sndcmd = 1; + int page, realpage, chipnr; struct nand_chip *chip = mtd->priv; - int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; + struct mtd_ecc_stats stats; int readlen = ops->ooblen; int len; uint8_t *buf = ops->oobbuf; + int ret = 0; MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n", __func__, (unsigned long long)from, readlen); - if (ops->mode == MTD_OOB_AUTO) + stats = mtd->ecc_stats; + + if (ops->mode == MTD_OPS_AUTO_OOB) len = chip->ecc.layout->oobavail; else len = mtd->oobsize; @@ -1558,24 +1559,17 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, while (1) { WATCHDOG_RESET(); - sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); + if (ops->mode == MTD_OPS_RAW) + ret = chip->ecc.read_oob_raw(mtd, chip, page); + else + ret = chip->ecc.read_oob(mtd, chip, page); + + if (ret < 0) + break; len = min(len, readlen); buf = nand_transfer_oob(chip, buf, ops, len); - if (!(chip->options & NAND_NO_READRDY)) { - /* - * Apply delay or wait for ready/busy pin. Do this - * before the AUTOINCR check, so no problems arise if a - * chip which does auto increment is marked as - * NOAUTOINCR by the board driver. - */ - if (!chip->dev_ready) - udelay(chip->chip_delay); - else - nand_wait_ready(mtd); - } - readlen -= len; if (!readlen) break; @@ -1590,25 +1584,26 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } - - /* Check, if the chip supports auto page increment - * or if we have hit a block boundary. - */ - if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) - sndcmd = 1; } - ops->oobretlen = ops->ooblen; - return 0; + ops->oobretlen = ops->ooblen - readlen; + + if (ret < 0) + return ret; + + if (mtd->ecc_stats.failed - stats.failed) + return -EBADMSG; + + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band - * @mtd: MTD device structure - * @from: offset to read from - * @ops: oob operation description structure + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operation description structure * - * NAND read data and/or out-of-band data + * NAND read data and/or out-of-band data. */ static int nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) @@ -1628,9 +1623,9 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, nand_get_device(chip, mtd, FL_READING); switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_AUTO: - case MTD_OOB_RAW: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_AUTO_OOB: + case MTD_OPS_RAW: break; default: @@ -1649,31 +1644,36 @@ out: /** - * nand_write_page_raw - [Intern] raw page write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer + * nand_write_page_raw - [INTERN] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * - * Not for syndrome calculating ecc controllers, which use a special oob layout + * Not for syndrome calculating ECC controllers, which use a special oob layout. */ -static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) +static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { chip->write_buf(mtd, buf, mtd->writesize); - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + if (oob_required) + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } /** - * nand_write_page_raw_syndrome - [Intern] raw page write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer + * nand_write_page_raw_syndrome - [INTERN] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * * We need a special oob layout and handling even when ECC isn't checked. */ -static void nand_write_page_raw_syndrome(struct mtd_info *mtd, +static int nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, int oob_required) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1701,15 +1701,18 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, size = mtd->oobsize - (oob - chip->oob_poi); if (size) chip->write_buf(mtd, oob, size); + + return 0; } /** - * nand_write_page_swecc - [REPLACABLE] software ecc based page write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer + * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB */ -static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) +static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1718,24 +1721,25 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *p = buf; uint32_t *eccpos = chip->ecc.layout->eccpos; - /* Software ecc calculation */ + /* Software ECC calculation */ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->ecc.write_page_raw(mtd, chip, buf); + return chip->ecc.write_page_raw(mtd, chip, buf, 1); } /** - * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer + * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB */ -static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) +static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1754,19 +1758,23 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; } /** - * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write - * @mtd: mtd info structure - * @chip: nand chip info structure - * @buf: data buffer + * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * - * The hw generator calculates the error syndrome automatically. Therefor - * we need a special oob layout and handling. + * The hw generator calculates the error syndrome automatically. Therefore we + * need a special oob layout and handling. */ -static void nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) +static int nand_write_page_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1798,32 +1806,39 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, i = mtd->oobsize - (oob - chip->oob_poi); if (i) chip->write_buf(mtd, oob, i); + + return 0; } /** * nand_write_page - [REPLACEABLE] write one page - * @mtd: MTD device structure - * @chip: NAND chip descriptor - * @buf: the data to write - * @page: page number to write - * @cached: cached programming - * @raw: use _raw version of write_page + * @mtd: MTD device structure + * @chip: NAND chip descriptor + * @buf: the data to write + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to write + * @cached: cached programming + * @raw: use _raw version of write_page */ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int page, int cached, int raw) + const uint8_t *buf, int oob_required, int page, + int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf); + status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); else - chip->ecc.write_page(mtd, chip, buf); + status = chip->ecc.write_page(mtd, chip, buf, oob_required); + + if (status < 0) + return status; /* - * Cached progamming disabled for now, Not sure if its worth the - * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) + * Cached progamming disabled for now. Not sure if it's worth the + * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s). */ cached = 0; @@ -1833,7 +1848,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, status = chip->waitfunc(mtd, chip); /* * See if operation failed and additional status checks are - * available + * available. */ if ((status & NAND_STATUS_FAIL) && (chip->errstat)) status = chip->errstat(mtd, chip, FL_WRITING, status, @@ -1852,34 +1867,45 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, if (chip->verify_buf(mtd, buf, mtd->writesize)) return -EIO; + + /* Make sure the next page prog is preceded by a status read */ + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); #endif return 0; } /** - * nand_fill_oob - [Internal] Transfer client buffer to oob - * @chip: nand chip structure - * @oob: oob data buffer - * @len: oob data write length - * @ops: oob ops structure + * nand_fill_oob - [INTERN] Transfer client buffer to oob + * @mtd: MTD device structure + * @oob: oob data buffer + * @len: oob data write length + * @ops: oob ops structure */ -static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, - struct mtd_oob_ops *ops) +static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, + struct mtd_oob_ops *ops) { + struct nand_chip *chip = mtd->priv; + + /* + * Initialise to all 0xFF, to avoid the possibility of left over OOB + * data from a previous OOB read. + */ + memset(chip->oob_poi, 0xff, mtd->oobsize); + switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_RAW: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_RAW: memcpy(chip->oob_poi + ops->ooboffs, oob, len); return oob + len; - case MTD_OOB_AUTO: { + case MTD_OPS_AUTO_OOB: { struct nand_oobfree *free = chip->ecc.layout->oobfree; uint32_t boffs = 0, woffs = ops->ooboffs; size_t bytes = 0; for (; free->length && len; free++, len -= bytes) { - /* Write request not from offset 0 ? */ + /* Write request not from offset 0? */ if (unlikely(woffs)) { if (woffs >= free->length) { woffs -= free->length; @@ -1907,12 +1933,12 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0) /** - * nand_do_write_ops - [Internal] NAND write with ECC - * @mtd: MTD device structure - * @to: offset to write to - * @ops: oob operations description structure + * nand_do_write_ops - [INTERN] NAND write with ECC + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operations description structure * - * NAND write with ECC + * NAND write with ECC. */ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) @@ -1922,12 +1948,13 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, uint32_t writelen = ops->len; uint32_t oobwritelen = ops->ooblen; - uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ? + uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int ret, subpage; + int oob_required = oob ? 1 : 0; ops->retlen = 0; if (!writelen) @@ -1957,10 +1984,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, (chip->pagebuf << chip->page_shift) < (to + ops->len)) chip->pagebuf = -1; - /* If we're not given explicit OOB data, let it be 0xFF */ - if (likely(!oob)) - memset(chip->oob_poi, 0xff, mtd->oobsize); - /* Don't allow multipage oob writes with offset */ if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) return -EINVAL; @@ -1972,8 +1995,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; - /* Partial page write ? */ - if (unlikely(column || writelen < (mtd->writesize - 1))) { + /* Partial page write? */ + if (unlikely(column || writelen < mtd->writesize)) { cached = 0; bytes = min_t(int, bytes - column, (int) writelen); chip->pagebuf = -1; @@ -1984,12 +2007,15 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, if (unlikely(oob)) { size_t len = min(oobwritelen, oobmaxlen); - oob = nand_fill_oob(chip, oob, len, ops); + oob = nand_fill_oob(mtd, oob, len, ops); oobwritelen -= len; + } else { + /* We still need to erase leftover OOB data */ + memset(chip->oob_poi, 0xff, mtd->oobsize); } - ret = chip->write_page(mtd, chip, wbuf, page, cached, - (ops->mode == MTD_OOB_RAW)); + ret = chip->write_page(mtd, chip, wbuf, oob_required, page, + cached, (ops->mode == MTD_OPS_RAW)); if (ret) break; @@ -2018,48 +2044,39 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, /** * nand_write - [MTD Interface] NAND write with ECC - * @mtd: MTD device structure - * @to: offset to write to - * @len: number of bytes to write - * @retlen: pointer to variable to store the number of written bytes - * @buf: the data to write + * @mtd: MTD device structure + * @to: offset to write to + * @len: number of bytes to write + * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write * - * NAND write with ECC + * NAND write with ECC. */ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { struct nand_chip *chip = mtd->priv; + struct mtd_oob_ops ops; int ret; - /* Do not allow writes past end of device */ - if ((to + len) > mtd->size) - return -EINVAL; - if (!len) - return 0; - nand_get_device(chip, mtd, FL_WRITING); - - chip->ops.len = len; - chip->ops.datbuf = (uint8_t *)buf; - chip->ops.oobbuf = NULL; - - ret = nand_do_write_ops(mtd, to, &chip->ops); - - *retlen = chip->ops.retlen; - + ops.len = len; + ops.datbuf = (uint8_t *)buf; + ops.oobbuf = NULL; + ops.mode = MTD_OPS_PLACE_OOB; + ret = nand_do_write_ops(mtd, to, &ops); + *retlen = ops.retlen; nand_release_device(mtd); - return ret; } /** * nand_do_write_oob - [MTD Interface] NAND write out-of-band - * @mtd: MTD device structure - * @to: offset to write to - * @ops: oob operation description structure + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operation description structure * - * NAND write out-of-band + * NAND write out-of-band. */ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) @@ -2070,7 +2087,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n", __func__, (unsigned int)to, (int)ops->ooblen); - if (ops->mode == MTD_OOB_AUTO) + if (ops->mode == MTD_OPS_AUTO_OOB) len = chip->ecc.layout->oobavail; else len = mtd->oobsize; @@ -2120,10 +2137,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, if (page == chip->pagebuf) chip->pagebuf = -1; - memset(chip->oob_poi, 0xff, mtd->oobsize); - nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops); - status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); - memset(chip->oob_poi, 0xff, mtd->oobsize); + nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops); + + if (ops->mode == MTD_OPS_RAW) + status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask); + else + status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); if (status) return status; @@ -2135,9 +2154,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, /** * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band - * @mtd: MTD device structure - * @to: offset to write to - * @ops: oob operation description structure + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operation description structure */ static int nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) @@ -2157,9 +2176,9 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, nand_get_device(chip, mtd, FL_WRITING); switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_AUTO: - case MTD_OOB_RAW: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_AUTO_OOB: + case MTD_OPS_RAW: break; default: @@ -2177,11 +2196,11 @@ out: } /** - * single_erease_cmd - [GENERIC] NAND standard block erase command function - * @mtd: MTD device structure - * @page: the page address of the block which will be erased + * single_erase_cmd - [GENERIC] NAND standard block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased * - * Standard erase command for NAND chips + * Standard erase command for NAND chips. */ static void single_erase_cmd(struct mtd_info *mtd, int page) { @@ -2192,12 +2211,11 @@ static void single_erase_cmd(struct mtd_info *mtd, int page) } /** - * multi_erease_cmd - [GENERIC] AND specific block erase command function - * @mtd: MTD device structure - * @page: the page address of the block which will be erased + * multi_erase_cmd - [GENERIC] AND specific block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased * - * AND multi block erase command function - * Erase 4 consecutive blocks + * AND multi block erase command function. Erase 4 consecutive blocks. */ static void multi_erase_cmd(struct mtd_info *mtd, int page) { @@ -2212,10 +2230,10 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page) /** * nand_erase - [MTD Interface] erase block(s) - * @mtd: MTD device structure - * @instr: erase instruction + * @mtd: MTD device structure + * @instr: erase instruction * - * Erase one ore more blocks + * Erase one ore more blocks. */ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) { @@ -2224,12 +2242,12 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) #define BBT_PAGE_MASK 0xffffff3f /** - * nand_erase_nand - [Internal] erase block(s) - * @mtd: MTD device structure - * @instr: erase instruction - * @allowbbt: allow erasing the bbt area + * nand_erase_nand - [INTERN] erase block(s) + * @mtd: MTD device structure + * @instr: erase instruction + * @allowbbt: allow erasing the bbt area * - * Erase one ore more blocks + * Erase one ore more blocks. */ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt) @@ -2247,8 +2265,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, if (check_offs_len(mtd, instr->addr, instr->len)) return -EINVAL; - instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; - /* Grab the lock and see if the device is available */ nand_get_device(chip, mtd, FL_ERASING); @@ -2274,7 +2290,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, * If BBT requires refresh, set the BBT page mask to see if the BBT * should be rewritten. Otherwise the mask is set to 0xffffffff which * can not be matched. This is also done when the bbt is actually - * erased to avoid recusrsive updates + * erased to avoid recursive updates. */ if (chip->options & BBT_AUTO_REFRESH && !allowbbt) bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK; @@ -2286,20 +2302,18 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, while (len) { WATCHDOG_RESET(); - /* - * heck if we have a bad block, we do not erase bad blocks ! - */ + /* Check if we have a bad block, we do not erase bad blocks! */ if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { - printk(KERN_WARNING "%s: attempt to erase a bad block " - "at page 0x%08x\n", __func__, page); + pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", + __func__, page); instr->state = MTD_ERASE_FAILED; goto erase_exit; } /* * Invalidate the page cache, if we erase the block which - * contains the current cached page + * contains the current cached page. */ if (page <= chip->pagebuf && chip->pagebuf < (page + pages_per_block)) @@ -2329,7 +2343,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, /* * If BBT requires refresh, set the BBT rewrite flag to the - * page being erased + * page being erased. */ if (bbt_masked_page != 0xffffffff && (page & BBT_PAGE_MASK) == bbt_masked_page) @@ -2348,7 +2362,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, /* * If BBT requires refresh and BBT-PERCHIP, set the BBT - * page mask to see if this BBT should be rewritten + * page mask to see if this BBT should be rewritten. */ if (bbt_masked_page != 0xffffffff && (chip->bbt_td->options & NAND_BBT_PERCHIP)) @@ -2371,7 +2385,7 @@ erase_exit: /* * If BBT requires refresh and erase was successful, rewrite any - * selected bad block tables + * selected bad block tables. */ if (bbt_masked_page == 0xffffffff || ret) return ret; @@ -2379,7 +2393,7 @@ erase_exit: for (chipnr = 0; chipnr < chip->numchips; chipnr++) { if (!rewrite_bbt[chipnr]) continue; - /* update the BBT for chip */ + /* Update the BBT for chip */ MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt " "(%d:0x%0llx 0x%0x)\n", __func__, chipnr, rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]); @@ -2392,9 +2406,9 @@ erase_exit: /** * nand_sync - [MTD Interface] sync - * @mtd: MTD device structure + * @mtd: MTD device structure * - * Sync is actually a wait for chip ready function + * Sync is actually a wait for chip ready function. */ static void nand_sync(struct mtd_info *mtd) { @@ -2410,22 +2424,18 @@ static void nand_sync(struct mtd_info *mtd) /** * nand_block_isbad - [MTD Interface] Check if block at offset is bad - * @mtd: MTD device structure - * @offs: offset relative to mtd start + * @mtd: MTD device structure + * @offs: offset relative to mtd start */ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) { - /* Check for invalid offset */ - if (offs > mtd->size) - return -EINVAL; - return nand_block_checkbad(mtd, offs, 1, 0); } /** * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad - * @mtd: MTD device structure - * @ofs: offset relative to mtd start + * @mtd: MTD device structure + * @ofs: offset relative to mtd start */ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { @@ -2434,7 +2444,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) ret = nand_block_isbad(mtd, ofs); if (ret) { - /* If it was bad already, return success and do nothing. */ + /* If it was bad already, return success and do nothing */ if (ret > 0) return 0; return ret; @@ -2443,9 +2453,51 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) return chip->block_markbad(mtd, ofs); } -/* - * Set default functions + /** + * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand + * @mtd: MTD device structure + * @chip: nand chip info structure + * @addr: feature address. + * @subfeature_param: the subfeature parameters, a four bytes array. */ +static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, + int addr, uint8_t *subfeature_param) +{ + int status; + + if (!chip->onfi_version) + return -EINVAL; + + chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); + chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + status = chip->waitfunc(mtd, chip); + if (status & NAND_STATUS_FAIL) + return -EIO; + return 0; +} + +/** + * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand + * @mtd: MTD device structure + * @chip: nand chip info structure + * @addr: feature address. + * @subfeature_param: the subfeature parameters, a four bytes array. + */ +static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, + int addr, uint8_t *subfeature_param) +{ + if (!chip->onfi_version) + return -EINVAL; + + /* clear the sub feature parameters */ + memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); + + chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); + chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + return 0; +} + +/* Set default functions */ static void nand_set_defaults(struct nand_chip *chip, int busw) { /* check for proper chip_delay setup, set 20us if not */ @@ -2483,23 +2535,21 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) } #ifdef CONFIG_SYS_NAND_ONFI_DETECTION -/* - * sanitize ONFI strings so we can safely print them - */ +/* Sanitize ONFI strings so we can safely print them */ static void sanitize_string(char *s, size_t len) { ssize_t i; - /* null terminate */ + /* Null terminate */ s[len - 1] = 0; - /* remove non printable chars */ + /* Remove non printable chars */ for (i = 0; i < len - 1; i++) { if (s[i] < ' ' || s[i] > 127) s[i] = '?'; } - /* remove trailing spaces */ + /* Remove trailing spaces */ strim(s); } @@ -2516,7 +2566,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) } /* - * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise + * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. */ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, int *busw) @@ -2525,20 +2575,18 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, int i; int val; - /* try ONFI for unknow chip or LP */ + /* Try ONFI for unknown chip or LP */ chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') return 0; - MTDDEBUG(MTD_DEBUG_LEVEL0, "ONFI flash detected\n"); chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); for (i = 0; i < 3; i++) { chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == le16_to_cpu(p->crc)) { - MTDDEBUG(MTD_DEBUG_LEVEL0, - "ONFI param page %d valid\n", i); + pr_info("ONFI param page %d valid\n", i); break; } } @@ -2546,7 +2594,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (i == 3) return 0; - /* check version */ + /* Check version */ val = le16_to_cpu(p->revision); if (val & (1 << 5)) chip->onfi_version = 23; @@ -2562,8 +2610,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, chip->onfi_version = 0; if (!chip->onfi_version) { - printk(KERN_INFO "%s: unsupported ONFI version: %d\n", - __func__, val); + pr_info("%s: unsupported ONFI version: %d\n", __func__, val); return 0; } @@ -2580,8 +2627,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; - chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR; - + pr_info("ONFI flash detected\n"); return 1; } #else @@ -2594,7 +2640,248 @@ static inline int nand_flash_detect_onfi(struct mtd_info *mtd, #endif /* - * Get the flash and manufacturer id and lookup if the type is supported + * nand_id_has_period - Check if an ID string has a given wraparound period + * @id_data: the ID string + * @arrlen: the length of the @id_data array + * @period: the period of repitition + * + * Check if an ID string is repeated within a given sequence of bytes at + * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a + * period of 2). This is a helper function for nand_id_len(). Returns non-zero + * if the repetition has a period of @period; otherwise, returns zero. + */ +static int nand_id_has_period(u8 *id_data, int arrlen, int period) +{ + int i, j; + for (i = 0; i < period; i++) + for (j = i + period; j < arrlen; j += period) + if (id_data[i] != id_data[j]) + return 0; + return 1; +} + +/* + * nand_id_len - Get the length of an ID string returned by CMD_READID + * @id_data: the ID string + * @arrlen: the length of the @id_data array + + * Returns the length of the ID string, according to known wraparound/trailing + * zero patterns. If no pattern exists, returns the length of the array. + */ +static int nand_id_len(u8 *id_data, int arrlen) +{ + int last_nonzero, period; + + /* Find last non-zero byte */ + for (last_nonzero = arrlen - 1; last_nonzero >= 0; last_nonzero--) + if (id_data[last_nonzero]) + break; + + /* All zeros */ + if (last_nonzero < 0) + return 0; + + /* Calculate wraparound period */ + for (period = 1; period < arrlen; period++) + if (nand_id_has_period(id_data, arrlen, period)) + break; + + /* There's a repeated pattern */ + if (period < arrlen) + return period; + + /* There are trailing zeros */ + if (last_nonzero < arrlen - 1) + return last_nonzero + 1; + + /* No pattern detected */ + return arrlen; +} + +/* + * Many new NAND share similar device ID codes, which represent the size of the + * chip. The rest of the parameters must be decoded according to generic or + * manufacturer-specific "extended ID" decoding patterns. + */ +static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, + u8 id_data[8], int *busw) +{ + int extid, id_len; + /* The 3rd id byte holds MLC / multichip data */ + chip->cellinfo = id_data[2]; + /* The 4th id byte is the important one */ + extid = id_data[3]; + + id_len = nand_id_len(id_data, 8); + + /* + * Field definitions are in the following datasheets: + * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) + * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) + * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) + * + * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung + * ID to decide what to do. + */ + if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + id_data[5] != 0x00) { + /* Calc pagesize */ + mtd->writesize = 2048 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + switch (((extid >> 2) & 0x04) | (extid & 0x03)) { + case 1: + mtd->oobsize = 128; + break; + case 2: + mtd->oobsize = 218; + break; + case 3: + mtd->oobsize = 400; + break; + case 4: + mtd->oobsize = 436; + break; + case 5: + mtd->oobsize = 512; + break; + case 6: + default: /* Other cases are "reserved" (unknown) */ + mtd->oobsize = 640; + break; + } + extid >>= 2; + /* Calc blocksize */ + mtd->erasesize = (128 * 1024) << + (((extid >> 1) & 0x04) | (extid & 0x03)); + *busw = 0; + } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { + unsigned int tmp; + + /* Calc pagesize */ + mtd->writesize = 2048 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + switch (((extid >> 2) & 0x04) | (extid & 0x03)) { + case 0: + mtd->oobsize = 128; + break; + case 1: + mtd->oobsize = 224; + break; + case 2: + mtd->oobsize = 448; + break; + case 3: + mtd->oobsize = 64; + break; + case 4: + mtd->oobsize = 32; + break; + case 5: + mtd->oobsize = 16; + break; + default: + mtd->oobsize = 640; + break; + } + extid >>= 2; + /* Calc blocksize */ + tmp = ((extid >> 1) & 0x04) | (extid & 0x03); + if (tmp < 0x03) + mtd->erasesize = (128 * 1024) << tmp; + else if (tmp == 0x03) + mtd->erasesize = 768 * 1024; + else + mtd->erasesize = (64 * 1024) << tmp; + *busw = 0; + } else { + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * + (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + } +} + + /* + * Old devices have chip data hardcoded in the device ID table. nand_decode_id + * decodes a matching ID table entry and assigns the MTD size parameters for + * the chip. + */ +static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, + const struct nand_flash_dev *type, u8 id_data[8], + int *busw) +{ + int maf_id = id_data[0]; + + mtd->erasesize = type->erasesize; + mtd->writesize = type->pagesize; + mtd->oobsize = mtd->writesize / 32; + *busw = type->options & NAND_BUSWIDTH_16; + + /* + * Check for Spansion/AMD ID + repeating 5th, 6th byte since + * some Spansion chips have erasesize that conflicts with size + * listed in nand_ids table. + * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) + */ + if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00 + && id_data[6] == 0x00 && id_data[7] == 0x00 + && mtd->writesize == 512) { + mtd->erasesize = 128 * 1024; + mtd->erasesize <<= ((id_data[3] & 0x03) << 1); + } +} + + /* + * Set the bad block marker/indicator (BBM/BBI) patterns according to some + * heuristic patterns using various detected parameters (e.g., manufacturer, + * page size, cell-type information). + */ +static void nand_decode_bbm_options(struct mtd_info *mtd, + struct nand_chip *chip, u8 id_data[8]) +{ + int maf_id = id_data[0]; + + /* Set the bad block position */ + if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) + chip->badblockpos = NAND_LARGE_BADBLOCK_POS; + else + chip->badblockpos = NAND_SMALL_BADBLOCK_POS; + + /* + * Bad block marker is stored in the last page of each block on Samsung + * and Hynix MLC devices; stored in first two pages of each block on + * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, + * AMD/Spansion, and Macronix. All others scan only the first page. + */ + if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + (maf_id == NAND_MFR_SAMSUNG || + maf_id == NAND_MFR_HYNIX)) + chip->bbt_options |= NAND_BBT_SCANLASTPAGE; + else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + (maf_id == NAND_MFR_SAMSUNG || + maf_id == NAND_MFR_HYNIX || + maf_id == NAND_MFR_TOSHIBA || + maf_id == NAND_MFR_AMD || + maf_id == NAND_MFR_MACRONIX)) || + (mtd->writesize == 2048 && + maf_id == NAND_MFR_MICRON)) + chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; +} + +/* + * Get the flash and manufacturer id and lookup if the type is supported. */ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip, @@ -2605,14 +2892,13 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, const char *name; int i, maf_idx; u8 id_data[8]; - int ret; /* Select the device */ chip->select_chip(mtd, 0); /* * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) - * after power-up + * after power-up. */ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); @@ -2623,7 +2909,8 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, *maf_id = chip->read_byte(mtd); *dev_id = chip->read_byte(mtd); - /* Try again to make sure, as some systems the bus-hold or other + /* + * Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a * possibly credible NAND flash to appear. If the two results do * not match, ignore the device completely. @@ -2631,13 +2918,14 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - for (i = 0; i < 2; i++) + /* Read entire ID string */ + for (i = 0; i < 8; i++) id_data[i] = chip->read_byte(mtd); if (id_data[0] != *maf_id || id_data[1] != *dev_id) { - printk(KERN_INFO "%s: second ID read did not match " - "%02x,%02x against %02x,%02x\n", __func__, - *maf_id, *dev_id, id_data[0], id_data[1]); + pr_info("%s: second ID read did not match " + "%02x,%02x against %02x,%02x\n", __func__, + *maf_id, *dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } @@ -2651,18 +2939,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->onfi_version = 0; if (!type->name || !type->pagesize) { /* Check is chip is ONFI compliant */ - ret = nand_flash_detect_onfi(mtd, chip, &busw); - if (ret) + if (nand_flash_detect_onfi(mtd, chip, &busw)) goto ident_done; } - chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - - /* Read entire ID string */ - - for (i = 0; i < 8; i++) - id_data[i] = chip->read_byte(mtd); - if (!type->name) return ERR_PTR(-ENODEV); @@ -2672,101 +2952,25 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->chipsize = (uint64_t)type->chipsize << 20; if (!type->pagesize && chip->init_size) { - /* set the pagesize, oobsize, erasesize by the driver*/ + /* Set the pagesize, oobsize, erasesize by the driver */ busw = chip->init_size(mtd, chip, id_data); } else if (!type->pagesize) { - int extid; - /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = id_data[2]; - /* The 4th id byte is the important one */ - extid = id_data[3]; - - /* - * Field definitions are in the following datasheets: - * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) - * New style (6 byte ID): Samsung K9GBG08U0M (p.40) - * - * Check for wraparound + Samsung ID + nonzero 6th byte - * to decide what to do. - */ - if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && - id_data[0] == NAND_MFR_SAMSUNG && - (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && - id_data[5] != 0x00) { - /* Calc pagesize */ - mtd->writesize = 2048 << (extid & 0x03); - extid >>= 2; - /* Calc oobsize */ - switch (extid & 0x03) { - case 1: - mtd->oobsize = 128; - break; - case 2: - mtd->oobsize = 218; - break; - case 3: - mtd->oobsize = 400; - break; - default: - mtd->oobsize = 436; - break; - } - extid >>= 2; - /* Calc blocksize */ - mtd->erasesize = (128 * 1024) << - (((extid >> 1) & 0x04) | (extid & 0x03)); - busw = 0; - } else { - /* Calc pagesize */ - mtd->writesize = 1024 << (extid & 0x03); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * - (mtd->writesize >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; - } + /* Decode parameters from extended ID */ + nand_decode_ext_id(mtd, chip, id_data, &busw); } else { - /* - * Old devices have chip data hardcoded in the device id table - */ - mtd->erasesize = type->erasesize; - mtd->writesize = type->pagesize; - mtd->oobsize = mtd->writesize / 32; - busw = type->options & NAND_BUSWIDTH_16; - - /* - * Check for Spansion/AMD ID + repeating 5th, 6th byte since - * some Spansion chips have erasesize that conflicts with size - * listed in nand_ids table - * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) - */ - if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && - id_data[5] == 0x00 && id_data[6] == 0x00 && - id_data[7] == 0x00 && mtd->writesize == 512) { - mtd->erasesize = 128 * 1024; - mtd->erasesize <<= ((id_data[3] & 0x03) << 1); - } + nand_decode_id(mtd, chip, type, id_data, &busw); } /* Get chip options, preserve non chip based options */ chip->options |= type->options; - /* Check if chip is a not a samsung device. Do not clear the - * options for chips which are not having an extended id. + /* + * Check if chip is not a Samsung device. Do not clear the + * options for chips which do not have an extended id. */ if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; ident_done: - /* - * Set chip as a default. Board drivers can override it, if necessary - */ - chip->options |= NAND_NO_AUTOINCR; - /* Try to identify manufacturer */ for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { if (nand_manuf_ids[maf_idx].id == *maf_id) @@ -2775,21 +2979,23 @@ ident_done: /* * Check, if buswidth is correct. Hardware drivers should set - * chip correct ! + * chip correct! */ if (busw != (chip->options & NAND_BUSWIDTH_16)) { - printk(KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, - *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); - printk(KERN_WARNING "NAND bus width %d instead %d bit\n", - (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, - busw ? 16 : 8); + pr_info("NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, + *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); + pr_warn("NAND bus width %d instead %d bit\n", + (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, + busw ? 16 : 8); return ERR_PTR(-EINVAL); } + nand_decode_bbm_options(mtd, chip, id_data); + /* Calculate the address shift from the page size */ chip->page_shift = ffs(mtd->writesize) - 1; - /* Convert chipsize to number of pages per chip -1. */ + /* Convert chipsize to number of pages per chip -1 */ chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; chip->bbt_erase_shift = chip->phys_erase_shift = @@ -2803,73 +3009,38 @@ ident_done: chip->badblockbits = 8; - /* Set the bad block position */ - if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) - chip->badblockpos = NAND_LARGE_BADBLOCK_POS; - else - chip->badblockpos = NAND_SMALL_BADBLOCK_POS; - - /* - * Bad block marker is stored in the last page of each block - * on Samsung and Hynix MLC devices; stored in first two pages - * of each block on Micron devices with 2KiB pages and on - * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan - * only the first page. - */ - if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && - (*maf_id == NAND_MFR_SAMSUNG || - *maf_id == NAND_MFR_HYNIX)) - chip->options |= NAND_BBT_SCANLASTPAGE; - else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && - (*maf_id == NAND_MFR_SAMSUNG || - *maf_id == NAND_MFR_HYNIX || - *maf_id == NAND_MFR_TOSHIBA || - *maf_id == NAND_MFR_AMD)) || - (mtd->writesize == 2048 && - *maf_id == NAND_MFR_MICRON)) - chip->options |= NAND_BBT_SCAN2NDPAGE; - - /* - * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6 - */ - if (!(busw & NAND_BUSWIDTH_16) && - *maf_id == NAND_MFR_STMICRO && - mtd->writesize == 2048) { - chip->options |= NAND_BBT_SCANBYTE1AND6; - chip->badblockpos = 0; - } - /* Check for AND chips with 4 page planes */ if (chip->options & NAND_4PAGE_ARRAY) chip->erase_cmd = multi_erase_cmd; else chip->erase_cmd = single_erase_cmd; - /* Do not replace user supplied command function ! */ + /* Do not replace user supplied command function! */ if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; - /* TODO onfi flash name */ name = type->name; #ifdef CONFIG_SYS_NAND_ONFI_DETECTION if (chip->onfi_version) name = chip->onfi_params.model; #endif - MTDDEBUG(MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, - nand_manuf_ids[maf_idx].name, name); + pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," + " page size: %d, OOB size: %d\n", + *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, + name, + mtd->writesize, mtd->oobsize); return type; } /** * nand_scan_ident - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure - * @maxchips: Number of chips to scan for - * @table: Alternative NAND ID table + * @mtd: MTD device structure + * @maxchips: number of chips to scan for + * @table: alternative NAND ID table * - * This is the first phase of the normal nand_scan() function. It - * reads the flash ID and sets up MTD fields accordingly. + * This is the first phase of the normal nand_scan() function. It reads the + * flash ID and sets up MTD fields accordingly. * * The mtd->owner field must be set to the module of the caller. */ @@ -2891,7 +3062,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, if (IS_ERR(type)) { #ifndef CONFIG_SYS_NAND_QUIET_TEST - printk(KERN_WARNING "No NAND device found!!!\n"); + pr_warn("No NAND device found\n"); #endif chip->select_chip(mtd, -1); return PTR_ERR(type); @@ -2911,7 +3082,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, } #ifdef DEBUG if (i > 1) - printk(KERN_INFO "%d NAND chips detected\n", i); + pr_info("%d NAND chips detected\n", i); #endif /* Store the number of chips and calc total size for mtd */ @@ -2924,17 +3095,21 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, /** * nand_scan_tail - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure + * @mtd: MTD device structure * - * This is the second phase of the normal nand_scan() function. It - * fills out all the uninitialized function pointers with the defaults - * and scans for a bad block table if appropriate. + * This is the second phase of the normal nand_scan() function. It fills out + * all the uninitialized function pointers with the defaults and scans for a + * bad block table if appropriate. */ int nand_scan_tail(struct mtd_info *mtd) { int i; struct nand_chip *chip = mtd->priv; + /* New bad blocks should be marked in OOB, flash-based BBT, or both */ + BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && + !(chip->bbt_options & NAND_BBT_USE_FLASH)); + if (!(chip->options & NAND_OWN_BUFFERS)) chip->buffers = memalign(ARCH_DMA_MINALIGN, sizeof(*chip->buffers)); @@ -2945,7 +3120,7 @@ int nand_scan_tail(struct mtd_info *mtd) chip->oob_poi = chip->buffers->databuf + mtd->writesize; /* - * If no default placement scheme is given, select an appropriate one + * If no default placement scheme is given, select an appropriate one. */ if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { @@ -2962,16 +3137,22 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.layout = &nand_oob_128; break; default: - printk(KERN_WARNING "No oob scheme defined for " - "oobsize %d\n", mtd->oobsize); + pr_warn("No oob scheme defined for oobsize %d\n", + mtd->oobsize); } } if (!chip->write_page) chip->write_page = nand_write_page; + /* set for ONFI nand */ + if (!chip->onfi_set_features) + chip->onfi_set_features = nand_onfi_set_features; + if (!chip->onfi_get_features) + chip->onfi_get_features = nand_onfi_get_features; + /* - * check ECC mode, default to software if 3byte/512byte hardware ECC is + * Check ECC mode, default to software if 3byte/512byte hardware ECC is * selected and we have 256 byte pagesize fallback to software ECC */ @@ -2980,15 +3161,15 @@ int nand_scan_tail(struct mtd_info *mtd) /* Similar to NAND_ECC_HW, but a separate read_page handle */ if (!chip->ecc.calculate || !chip->ecc.correct || !chip->ecc.hwctl) { - printk(KERN_WARNING "No ECC functions supplied; " - "Hardware ECC not possible\n"); + pr_warn("No ECC functions supplied; " + "hardware ECC not possible\n"); BUG(); } if (!chip->ecc.read_page) chip->ecc.read_page = nand_read_page_hwecc_oob_first; case NAND_ECC_HW: - /* Use standard hwecc read page function ? */ + /* Use standard hwecc read page function? */ if (!chip->ecc.read_page) chip->ecc.read_page = nand_read_page_hwecc; if (!chip->ecc.write_page) @@ -3009,11 +3190,11 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.read_page == nand_read_page_hwecc || !chip->ecc.write_page || chip->ecc.write_page == nand_write_page_hwecc)) { - printk(KERN_WARNING "No ECC functions supplied; " - "Hardware ECC not possible\n"); + pr_warn("No ECC functions supplied; " + "hardware ECC not possible\n"); BUG(); } - /* Use standard syndrome read/write page function ? */ + /* Use standard syndrome read/write page function? */ if (!chip->ecc.read_page) chip->ecc.read_page = nand_read_page_syndrome; if (!chip->ecc.write_page) @@ -3027,11 +3208,16 @@ int nand_scan_tail(struct mtd_info *mtd) if (!chip->ecc.write_oob) chip->ecc.write_oob = nand_write_oob_syndrome; - if (mtd->writesize >= chip->ecc.size) + if (mtd->writesize >= chip->ecc.size) { + if (!chip->ecc.strength) { + pr_warn("Driver must set ecc.strength when using hardware ECC\n"); + BUG(); + } break; - printk(KERN_WARNING "%d byte HW ECC not possible on " - "%d byte page size, fallback to SW ECC\n", - chip->ecc.size, mtd->writesize); + } + pr_warn("%d byte HW ECC not possible on " + "%d byte page size, fallback to SW ECC\n", + chip->ecc.size, mtd->writesize); chip->ecc.mode = NAND_ECC_SOFT; case NAND_ECC_SOFT: @@ -3047,11 +3233,12 @@ int nand_scan_tail(struct mtd_info *mtd) if (!chip->ecc.size) chip->ecc.size = 256; chip->ecc.bytes = 3; + chip->ecc.strength = 1; break; case NAND_ECC_SOFT_BCH: if (!mtd_nand_has_bch()) { - printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n"); + pr_warn("CONFIG_MTD_ECC_BCH not enabled\n"); return -EINVAL; } chip->ecc.calculate = nand_bch_calculate_ecc; @@ -3066,8 +3253,8 @@ int nand_scan_tail(struct mtd_info *mtd) /* * Board driver should supply ecc.size and ecc.bytes values to * select how many bits are correctable; see nand_bch_init() - * for details. - * Otherwise, default to 4 bits for large page devices + * for details. Otherwise, default to 4 bits for large page + * devices. */ if (!chip->ecc.size && (mtd->oobsize >= 64)) { chip->ecc.size = 512; @@ -3078,13 +3265,14 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.bytes, &chip->ecc.layout); if (!chip->ecc.priv) - printk(KERN_WARNING "BCH ECC initialization failed!\n"); - + pr_warn("BCH ECC initialization failed!\n"); + chip->ecc.strength = + chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); break; case NAND_ECC_NONE: - printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " - "This is not recommended !!\n"); + pr_warn("NAND_ECC_NONE selected by board driver. " + "This is not recommended !!\n"); chip->ecc.read_page = nand_read_page_raw; chip->ecc.write_page = nand_write_page_raw; chip->ecc.read_oob = nand_read_oob_std; @@ -3096,14 +3284,19 @@ int nand_scan_tail(struct mtd_info *mtd) break; default: - printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", - chip->ecc.mode); + pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode); BUG(); } + /* For many systems, the standard OOB write also works for raw */ + if (!chip->ecc.read_oob_raw) + chip->ecc.read_oob_raw = chip->ecc.read_oob; + if (!chip->ecc.write_oob_raw) + chip->ecc.write_oob_raw = chip->ecc.write_oob; + /* * The number of bytes available for a client to place data into - * the out of band area + * the out of band area. */ chip->ecc.layout->oobavail = 0; for (i = 0; chip->ecc.layout->oobfree[i].length @@ -3114,19 +3307,16 @@ int nand_scan_tail(struct mtd_info *mtd) /* * Set the number of read / write steps for one page depending on ECC - * mode + * mode. */ chip->ecc.steps = mtd->writesize / chip->ecc.size; if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { - printk(KERN_WARNING "Invalid ecc parameters\n"); + pr_warn("Invalid ECC parameters\n"); BUG(); } chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; - /* - * Allow subpage writes up to ecc.steps. Not possible for MLC - * FLASH. - */ + /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { switch (chip->ecc.steps) { @@ -3159,21 +3349,29 @@ int nand_scan_tail(struct mtd_info *mtd) mtd->type = MTD_NANDFLASH; mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM : MTD_CAP_NANDFLASH; - mtd->erase = nand_erase; - mtd->point = NULL; - mtd->unpoint = NULL; - mtd->read = nand_read; - mtd->write = nand_write; - mtd->read_oob = nand_read_oob; - mtd->write_oob = nand_write_oob; - mtd->sync = nand_sync; - mtd->lock = NULL; - mtd->unlock = NULL; - mtd->block_isbad = nand_block_isbad; - mtd->block_markbad = nand_block_markbad; - - /* propagate ecc.layout to mtd_info */ + mtd->_erase = nand_erase; + mtd->_point = NULL; + mtd->_unpoint = NULL; + mtd->_read = nand_read; + mtd->_write = nand_write; + mtd->_read_oob = nand_read_oob; + mtd->_write_oob = nand_write_oob; + mtd->_sync = nand_sync; + mtd->_lock = NULL; + mtd->_unlock = NULL; + mtd->_block_isbad = nand_block_isbad; + mtd->_block_markbad = nand_block_markbad; + + /* propagate ecc info to mtd_info */ mtd->ecclayout = chip->ecc.layout; + mtd->ecc_strength = chip->ecc.strength; + /* + * Initialize bitflip_threshold to its default prior scan_bbt() call. + * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be + * properly set. + */ + if (!mtd->bitflip_threshold) + mtd->bitflip_threshold = mtd->ecc_strength; /* Check, if we should skip the bad block table scan */ if (chip->options & NAND_SKIP_BBTSCAN) @@ -3184,15 +3382,13 @@ int nand_scan_tail(struct mtd_info *mtd) /** * nand_scan - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure - * @maxchips: Number of chips to scan for - * - * This fills out all the uninitialized function pointers - * with the defaults. - * The flash ID is read and the mtd/chip structures are - * filled with the appropriate values. - * The mtd->owner field must be set to the module of the caller + * @mtd: MTD device structure + * @maxchips: number of chips to scan for * + * This fills out all the uninitialized function pointers with the defaults. + * The flash ID is read and the mtd/chip structures are filled with the + * appropriate values. The mtd->owner field must be set to the module of the + * caller. */ int nand_scan(struct mtd_info *mtd, int maxchips) { @@ -3206,8 +3402,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips) /** * nand_release - [NAND Interface] Free resources held by the NAND device - * @mtd: MTD device structure -*/ + * @mtd: MTD device structure + */ void nand_release(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 74a7061b05..8ef58451d5 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -4,7 +4,7 @@ * Overview: * Bad block table support for the NAND driver * - * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) + * Copyright © 2004 Thomas Gleixner (tglx@linutronix.de) * * 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 @@ -14,7 +14,7 @@ * * When nand_scan_bbt is called, then it tries to find the bad block table * depending on the options in the BBT descriptor(s). If no flash based BBT - * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory + * (NAND_BBT_USE_FLASH) is specified then the device is scanned for factory * marked good / bad blocks. This information is used to create a memory BBT. * Once a new bad block is discovered then the "factory" information is updated * on the device. @@ -22,7 +22,7 @@ * BBT on flash. If a BBT is found then the contents are read and the memory * based BBT is created. If a mirrored BBT is selected then the mirror is * searched too and the versions are compared. If the mirror has a greater - * version number than the mirror BBT is used to build the memory based BBT. + * version number, then the mirror BBT is used to build the memory based BBT. * If the tables are not versioned, then we "or" the bad block information. * If one of the BBTs is out of date or does not exist it is (re)created. * If no BBT exists at all then the device is scanned for factory marked @@ -36,9 +36,9 @@ * The table is marked in the OOB area with an ident pattern and a version * number which indicates which of both tables is more up to date. If the NAND * controller needs the complete OOB area for the ECC information then the - * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern - * and the version byte into the data area and the OOB area will remain - * untouched. + * option NAND_BBT_NO_OOB should be used (along with NAND_BBT_USE_FLASH, of + * course): it moves the ident pattern and the version byte into the data area + * and the OOB area will remain untouched. * * The table uses 2 bits per block * 11b: block is good @@ -63,126 +63,81 @@ #include <malloc.h> #include <linux/compat.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/bbm.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> #include <linux/bitops.h> +#include <linux/string.h> #include <asm/errno.h> static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) { - int ret; - - ret = memcmp(buf, td->pattern, td->len); - if (!ret) - return ret; - return -1; + if (memcmp(buf, td->pattern, td->len)) + return -1; + return 0; } /** * check_pattern - [GENERIC] check if a pattern is in the buffer - * @buf: the buffer to search - * @len: the length of buffer to search - * @paglen: the pagelength - * @td: search pattern descriptor - * - * Check for a pattern at the given place. Used to search bad block - * tables and good / bad block identifiers. - * If the SCAN_EMPTY option is set then check, if all bytes except the - * pattern area contain 0xff + * @buf: the buffer to search + * @len: the length of buffer to search + * @paglen: the pagelength + * @td: search pattern descriptor * -*/ + * Check for a pattern at the given place. Used to search bad block tables and + * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if + * all bytes except the pattern area contain 0xff. + */ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) { - int i, end = 0; + int end = 0; uint8_t *p = buf; if (td->options & NAND_BBT_NO_OOB) return check_pattern_no_oob(buf, td); end = paglen + td->offs; - if (td->options & NAND_BBT_SCANEMPTY) { - for (i = 0; i < end; i++) { - if (p[i] != 0xff) - return -1; - } - } + if (td->options & NAND_BBT_SCANEMPTY) + if (memchr_inv(p, 0xff, end)) + return -1; p += end; /* Compare the pattern */ - for (i = 0; i < td->len; i++) { - if (p[i] != td->pattern[i]) - return -1; - } - - /* Check both positions 1 and 6 for pattern? */ - if (td->options & NAND_BBT_SCANBYTE1AND6) { - if (td->options & NAND_BBT_SCANEMPTY) { - p += td->len; - end += NAND_SMALL_BADBLOCK_POS - td->offs; - /* Check region between positions 1 and 6 */ - for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len; - i++) { - if (*p++ != 0xff) - return -1; - } - } - else { - p += NAND_SMALL_BADBLOCK_POS - td->offs; - } - /* Compare the pattern */ - for (i = 0; i < td->len; i++) { - if (p[i] != td->pattern[i]) - return -1; - } - } + if (memcmp(p, td->pattern, td->len)) + return -1; if (td->options & NAND_BBT_SCANEMPTY) { p += td->len; end += td->len; - for (i = end; i < len; i++) { - if (*p++ != 0xff) - return -1; - } + if (memchr_inv(p, 0xff, len - end)) + return -1; } return 0; } /** * check_short_pattern - [GENERIC] check if a pattern is in the buffer - * @buf: the buffer to search - * @td: search pattern descriptor + * @buf: the buffer to search + * @td: search pattern descriptor * - * Check for a pattern at the given place. Used to search bad block - * tables and good / bad block identifiers. Same as check_pattern, but - * no optional empty check - * -*/ + * Check for a pattern at the given place. Used to search bad block tables and + * good / bad block identifiers. Same as check_pattern, but no optional empty + * check. + */ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) { - int i; - uint8_t *p = buf; - /* Compare the pattern */ - for (i = 0; i < td->len; i++) { - if (p[td->offs + i] != td->pattern[i]) - return -1; - } - /* Need to check location 1 AND 6? */ - if (td->options & NAND_BBT_SCANBYTE1AND6) { - for (i = 0; i < td->len; i++) { - if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i]) - return -1; - } - } + if (memcmp(buf + td->offs, td->pattern, td->len)) + return -1; return 0; } /** * add_marker_len - compute the length of the marker in data area - * @td: BBT descriptor used for computation + * @td: BBT descriptor used for computation * - * The length will be 0 if the markeris located in OOB area. + * The length will be 0 if the marker is located in OOB area. */ static u32 add_marker_len(struct nand_bbt_descr *td) { @@ -199,34 +154,33 @@ static u32 add_marker_len(struct nand_bbt_descr *td) /** * read_bbt - [GENERIC] Read the bad block table starting from page - * @mtd: MTD device structure - * @buf: temporary buffer - * @page: the starting page - * @num: the number of bbt descriptors to read - * @td: the bbt describtion table - * @offs: offset in the memory table + * @mtd: MTD device structure + * @buf: temporary buffer + * @page: the starting page + * @num: the number of bbt descriptors to read + * @td: the bbt describtion table + * @offs: offset in the memory table * * Read the bad block table starting from page. - * */ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, struct nand_bbt_descr *td, int offs) { - int res, i, j, act = 0; + int res, ret = 0, i, j, act = 0; struct nand_chip *this = mtd->priv; size_t retlen, len, totlen; loff_t from; int bits = td->options & NAND_BBT_NRBITS_MSK; - uint8_t msk = (uint8_t) ((1 << bits) - 1); + uint8_t msk = (uint8_t)((1 << bits) - 1); u32 marker_len; int reserved_block_code = td->reserved_block_code; totlen = (num * bits) >> 3; marker_len = add_marker_len(td); - from = ((loff_t) page) << this->page_shift; + from = ((loff_t)page) << this->page_shift; while (totlen) { - len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); + len = min(totlen, (size_t)(1 << this->bbt_erase_shift)); if (marker_len) { /* * In case the BBT marker is not in the OOB area it @@ -236,13 +190,20 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, from += marker_len; marker_len = 0; } - res = mtd->read(mtd, from, len, &retlen, buf); + res = mtd_read(mtd, from, len, &retlen, buf); if (res < 0) { - if (retlen != len) { - printk(KERN_INFO "nand_bbt: Error reading bad block table\n"); + if (mtd_is_eccerr(res)) { + pr_info("nand_bbt: ECC error in BBT at " + "0x%012llx\n", from & ~mtd->writesize); + return res; + } else if (mtd_is_bitflip(res)) { + pr_info("nand_bbt: corrected error in BBT at " + "0x%012llx\n", from & ~mtd->writesize); + ret = res; + } else { + pr_info("nand_bbt: error reading BBT\n"); return res; } - printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); } /* Analyse data */ @@ -253,17 +214,16 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, if (tmp == msk) continue; if (reserved_block_code && (tmp == reserved_block_code)) { - printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n", - (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + pr_info("nand_read_bbt: reserved block at 0x%012llx\n", + (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); mtd->ecc_stats.bbtblocks++; continue; } - MTDDEBUG(MTD_DEBUG_LEVEL0, "nand_read_bbt: " \ - "Bad block at 0x%012llx\n", + pr_info("nand_read_bbt: Bad block at 0x%012llx\n", (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); - /* Factory marked bad or worn out ? */ + /* Factory marked bad or worn out? */ if (tmp == 0) this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); else @@ -274,20 +234,20 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, totlen -= len; from += len; } - return 0; + return ret; } /** * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page - * @mtd: MTD device structure - * @buf: temporary buffer - * @td: descriptor for the bad block table - * @chip: read the table for a specific chip, -1 read all chips. - * Applies only if NAND_BBT_PERCHIP option is set + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @chip: read the table for a specific chip, -1 read all chips; applies only if + * NAND_BBT_PERCHIP option is set * - * Read the bad block table for all chips starting at a given page - * We assume that the bbt bits are in consecutive order. -*/ + * Read the bad block table for all chips starting at a given page. We assume + * that the bbt bits are in consecutive order. + */ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) { struct nand_chip *this = mtd->priv; @@ -313,10 +273,8 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc return 0; } -/* - * BBT marker is in the first page, no OOB. - */ -static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, +/* BBT marker is in the first page, no OOB */ +static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, struct nand_bbt_descr *td) { size_t retlen; @@ -326,70 +284,73 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, if (td->options & NAND_BBT_VERSION) len++; - return mtd->read(mtd, offs, len, &retlen, buf); + return mtd_read(mtd, offs, len, &retlen, buf); } -/* - * Scan read raw data from flash +/** + * scan_read_oob - [GENERIC] Scan data+OOB region to buffer + * @mtd: MTD device structure + * @buf: temporary buffer + * @offs: offset at which to scan + * @len: length of data region to read + * + * Scan read data from data+OOB. May traverse multiple pages, interleaving + * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest" + * ECC condition (error or bitflip). May quit on the first (non-ECC) error. */ -static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, +static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, size_t len) { struct mtd_oob_ops ops; - int res; + int res, ret = 0; - ops.mode = MTD_OOB_RAW; + ops.mode = MTD_OPS_PLACE_OOB; ops.ooboffs = 0; ops.ooblen = mtd->oobsize; - while (len > 0) { - if (len <= mtd->writesize) { - ops.oobbuf = buf + len; - ops.datbuf = buf; - ops.len = len; - return mtd->read_oob(mtd, offs, &ops); - } else { - ops.oobbuf = buf + mtd->writesize; - ops.datbuf = buf; - ops.len = mtd->writesize; - res = mtd->read_oob(mtd, offs, &ops); + ops.datbuf = buf; + ops.len = min(len, (size_t)mtd->writesize); + ops.oobbuf = buf + ops.len; - if (res) + res = mtd_read_oob(mtd, offs, &ops); + if (res) { + if (!mtd_is_bitflip_or_eccerr(res)) return res; + else if (mtd_is_eccerr(res) || !ret) + ret = res; } buf += mtd->oobsize + mtd->writesize; len -= mtd->writesize; + offs += mtd->writesize; } - return 0; + return ret; } -static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, +static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs, size_t len, struct nand_bbt_descr *td) { if (td->options & NAND_BBT_NO_OOB) - return scan_read_raw_data(mtd, buf, offs, td); + return scan_read_data(mtd, buf, offs, td); else - return scan_read_raw_oob(mtd, buf, offs, len); + return scan_read_oob(mtd, buf, offs, len); } -/* - * Scan write data with oob to flash - */ +/* Scan write data with oob to flash */ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, uint8_t *buf, uint8_t *oob) { struct mtd_oob_ops ops; - ops.mode = MTD_OOB_PLACE; + ops.mode = MTD_OPS_PLACE_OOB; ops.ooboffs = 0; ops.ooblen = mtd->oobsize; ops.datbuf = buf; ops.oobbuf = oob; ops.len = len; - return mtd->write_oob(mtd, offs, &ops); + return mtd_write_oob(mtd, offs, &ops); } static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) @@ -403,65 +364,60 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) /** * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page - * @mtd: MTD device structure - * @buf: temporary buffer - * @td: descriptor for the bad block table - * @md: descriptor for the bad block table mirror - * - * Read the bad block table(s) for all chips starting at a given page - * We assume that the bbt bits are in consecutive order. + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror * -*/ -static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, - struct nand_bbt_descr *td, struct nand_bbt_descr *md) + * Read the bad block table(s) for all chips starting at a given page. We + * assume that the bbt bits are in consecutive order. + */ +static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, struct nand_bbt_descr *md) { struct nand_chip *this = mtd->priv; /* Read the primary version, if available */ if (td->options & NAND_BBT_VERSION) { - scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, + scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift, mtd->writesize, td); td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; - printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", - td->pages[0], td->version[0]); + pr_info("Bad block table at page %d, version 0x%02X\n", + td->pages[0], td->version[0]); } /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { - scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, - mtd->writesize, td); + scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift, + mtd->writesize, md); md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; - printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", - md->pages[0], md->version[0]); + pr_info("Bad block table at page %d, version 0x%02X\n", + md->pages[0], md->version[0]); } - return 1; } -/* - * Scan a given block full - */ +/* Scan a given block full */ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, loff_t offs, uint8_t *buf, size_t readlen, - int scanlen, int len) + int scanlen, int numpages) { int ret, j; - ret = scan_read_raw_oob(mtd, buf, offs, readlen); - if (ret) + ret = scan_read_oob(mtd, buf, offs, readlen); + /* Ignore ECC errors when checking for BBM */ + if (ret && !mtd_is_bitflip_or_eccerr(ret)) return ret; - for (j = 0; j < len; j++, buf += scanlen) { + for (j = 0; j < numpages; j++, buf += scanlen) { if (check_pattern(buf, scanlen, mtd->writesize, bd)) return 1; } return 0; } -/* - * Scan a given block partially - */ +/* Scan a given block partially */ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, - loff_t offs, uint8_t *buf, int len) + loff_t offs, uint8_t *buf, int numpages) { struct mtd_oob_ops ops; int j, ret; @@ -470,16 +426,16 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, ops.oobbuf = buf; ops.ooboffs = 0; ops.datbuf = NULL; - ops.mode = MTD_OOB_PLACE; + ops.mode = MTD_OPS_PLACE_OOB; - for (j = 0; j < len; j++) { + for (j = 0; j < numpages; j++) { /* - * Read the full oob until read_oob is fixed to - * handle single byte reads for 16 bit - * buswidth + * Read the full oob until read_oob is fixed to handle single + * byte reads for 16 bit buswidth. */ - ret = mtd->read_oob(mtd, offs, &ops); - if (ret) + ret = mtd_read_oob(mtd, offs, &ops); + /* Ignore ECC errors when checking for BBM */ + if (ret && !mtd_is_bitflip_or_eccerr(ret)) return ret; if (check_short_pattern(buf, bd)) @@ -492,32 +448,32 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, /** * create_bbt - [GENERIC] Create a bad block table by scanning the device - * @mtd: MTD device structure - * @buf: temporary buffer - * @bd: descriptor for the good/bad block search pattern - * @chip: create the table for a specific chip, -1 read all chips. - * Applies only if NAND_BBT_PERCHIP option is set + * @mtd: MTD device structure + * @buf: temporary buffer + * @bd: descriptor for the good/bad block search pattern + * @chip: create the table for a specific chip, -1 read all chips; applies only + * if NAND_BBT_PERCHIP option is set * - * Create a bad block table by scanning the device - * for the given good/bad block identify pattern + * Create a bad block table by scanning the device for the given good/bad block + * identify pattern. */ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) { struct nand_chip *this = mtd->priv; - int i, numblocks, len, scanlen; + int i, numblocks, numpages, scanlen; int startblock; loff_t from; size_t readlen; - MTDDEBUG(MTD_DEBUG_LEVEL0, "Scanning device for bad blocks\n"); + pr_info("Scanning device for bad blocks\n"); if (bd->options & NAND_BBT_SCANALLPAGES) - len = 1 << (this->bbt_erase_shift - this->page_shift); + numpages = 1 << (this->bbt_erase_shift - this->page_shift); else if (bd->options & NAND_BBT_SCAN2NDPAGE) - len = 2; + numpages = 2; else - len = 1; + numpages = 1; if (!(bd->options & NAND_BBT_SCANEMPTY)) { /* We need only read few bytes from the OOB area */ @@ -526,18 +482,20 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, } else { /* Full page content should be read */ scanlen = mtd->writesize + mtd->oobsize; - readlen = len * mtd->writesize; + readlen = numpages * mtd->writesize; } if (chip == -1) { - /* Note that numblocks is 2 * (real numblocks) here, see i+=2 - * below as it makes shifting and masking less painful */ + /* + * Note that numblocks is 2 * (real numblocks) here, see i+=2 + * below as it makes shifting and masking less painful + */ numblocks = mtd->size >> (this->bbt_erase_shift - 1); startblock = 0; from = 0; } else { if (chip >= this->numchips) { - printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", + pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n", chip + 1, this->numchips); return -EINVAL; } @@ -547,8 +505,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, from = (loff_t)startblock << (this->bbt_erase_shift - 1); } - if (this->options & NAND_BBT_SCANLASTPAGE) - from += mtd->erasesize - (mtd->writesize * len); + if (this->bbt_options & NAND_BBT_SCANLASTPAGE) + from += mtd->erasesize - (mtd->writesize * numpages); for (i = startblock; i < numblocks;) { int ret; @@ -557,17 +515,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, if (bd->options & NAND_BBT_SCANALLPAGES) ret = scan_block_full(mtd, bd, from, buf, readlen, - scanlen, len); + scanlen, numpages); else - ret = scan_block_fast(mtd, bd, from, buf, len); + ret = scan_block_fast(mtd, bd, from, buf, numpages); if (ret < 0) return ret; if (ret) { this->bbt[i >> 3] |= 0x03 << (i & 0x6); - MTDDEBUG(MTD_DEBUG_LEVEL0, - "Bad eraseblock %d at 0x%012llx\n", + pr_warn("Bad eraseblock %d at 0x%012llx\n", i >> 1, (unsigned long long)from); mtd->ecc_stats.badblocks++; } @@ -580,20 +537,18 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, /** * search_bbt - [GENERIC] scan the device for a specific bad block table - * @mtd: MTD device structure - * @buf: temporary buffer - * @td: descriptor for the bad block table + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table * - * Read the bad block table by searching for a given ident pattern. - * Search is preformed either from the beginning up or from the end of - * the device downwards. The search starts always at the start of a - * block. - * If the option NAND_BBT_PERCHIP is given, each chip is searched - * for a bbt, which contains the bad block information of this chip. - * This is necessary to provide support for certain DOC devices. + * Read the bad block table by searching for a given ident pattern. Search is + * preformed either from the beginning up or from the end of the device + * downwards. The search starts always at the start of a block. If the option + * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains + * the bad block information of this chip. This is necessary to provide support + * for certain DOC devices. * - * The bbt ident pattern resides in the oob area of the first page - * in a block. + * The bbt ident pattern resides in the oob area of the first page in a block. */ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) { @@ -604,7 +559,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr int bbtblocks; int blocktopage = this->bbt_erase_shift - this->page_shift; - /* Search direction top -> down ? */ + /* Search direction top -> down? */ if (td->options & NAND_BBT_LASTBLOCK) { startblock = (mtd->size >> this->bbt_erase_shift) - 1; dir = -1; @@ -613,7 +568,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr dir = 1; } - /* Do we have a bbt per chip ? */ + /* Do we have a bbt per chip? */ if (td->options & NAND_BBT_PERCHIP) { chips = this->numchips; bbtblocks = this->chipsize >> this->bbt_erase_shift; @@ -634,7 +589,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr loff_t offs = (loff_t)actblock << this->bbt_erase_shift; /* Read first page */ - scan_read_raw(mtd, buf, offs, mtd->writesize, td); + scan_read(mtd, buf, offs, mtd->writesize, td); if (!check_pattern(buf, scanlen, mtd->writesize, td)) { td->pages[i] = actblock << blocktopage; if (td->options & NAND_BBT_VERSION) { @@ -649,10 +604,9 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr /* Check, if we found a bbt for each requested chip */ for (i = 0; i < chips; i++) { if (td->pages[i] == -1) - printk(KERN_WARNING "Bad block table not found for chip %d\n", i); + pr_warn("Bad block table not found for chip %d\n", i); else - MTDDEBUG(MTD_DEBUG_LEVEL0, "Bad block table found " \ - "at page %d, version 0x%02X\n", td->pages[i], + pr_info("Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); } return 0; @@ -660,14 +614,16 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr /** * search_read_bbts - [GENERIC] scan the device for bad block table(s) - * @mtd: MTD device structure - * @buf: temporary buffer - * @td: descriptor for the bad block table - * @md: descriptor for the bad block table mirror + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror * - * Search and read the bad block table(s) -*/ -static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) + * Search and read the bad block table(s). + */ +static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, + struct nand_bbt_descr *md) { /* Search the primary table */ search_bbt(mtd, buf, td); @@ -675,23 +631,18 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt /* Search the mirror table */ if (md) search_bbt(mtd, buf, md); - - /* Force result check */ - return 1; } /** * write_bbt - [GENERIC] (Re)write the bad block table + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror + * @chipsel: selector for a specific chip, -1 for all * - * @mtd: MTD device structure - * @buf: temporary buffer - * @td: descriptor for the bad block table - * @md: descriptor for the bad block table mirror - * @chipsel: selector for a specific chip, -1 for all - * - * (Re)write the bad block table - * -*/ + * (Re)write the bad block table. + */ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) @@ -710,14 +661,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ops.ooblen = mtd->oobsize; ops.ooboffs = 0; ops.datbuf = NULL; - ops.mode = MTD_OOB_PLACE; + ops.mode = MTD_OPS_PLACE_OOB; if (!rcode) rcode = 0xff; - /* Write bad block table per chip rather than per device ? */ + /* Write bad block table per chip rather than per device? */ if (td->options & NAND_BBT_PERCHIP) { numblocks = (int)(this->chipsize >> this->bbt_erase_shift); - /* Full device write or specific chip ? */ + /* Full device write or specific chip? */ if (chipsel == -1) { nrchips = this->numchips; } else { @@ -731,8 +682,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, /* Loop through the chips */ for (; chip < nrchips; chip++) { - - /* There was already a version of the table, reuse the page + /* + * There was already a version of the table, reuse the page * This applies for absolute placement too, as we have the * page nr. in td->pages. */ @@ -741,8 +692,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, goto write; } - /* Automatic placement of the bad block table */ - /* Search direction top -> down ? */ + /* + * Automatic placement of the bad block table. Search direction + * top -> down? + */ if (td->options & NAND_BBT_LASTBLOCK) { startblock = numblocks * (chip + 1) - 1; dir = -1; @@ -766,7 +719,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, if (!md || md->pages[chip] != page) goto write; } - printk(KERN_ERR "No space left to write bad block table\n"); + pr_err("No space left to write bad block table\n"); return -ENOSPC; write: @@ -791,29 +744,27 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, bbtoffs = chip * (numblocks >> 2); - to = ((loff_t) page) << this->page_shift; + to = ((loff_t)page) << this->page_shift; - /* Must we save the block contents ? */ + /* Must we save the block contents? */ if (td->options & NAND_BBT_SAVECONTENT) { /* Make it block aligned */ - to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); + to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); len = 1 << this->bbt_erase_shift; - res = mtd->read(mtd, to, len, &retlen, buf); + res = mtd_read(mtd, to, len, &retlen, buf); if (res < 0) { if (retlen != len) { - printk(KERN_INFO "nand_bbt: Error " - "reading block for writing " - "the bad block table\n"); + pr_info("nand_bbt: error reading block " + "for writing the bad block table\n"); return res; } - printk(KERN_WARNING "nand_bbt: ECC error " - "while reading block for writing " - "bad block table\n"); + pr_warn("nand_bbt: ECC error while reading " + "block for writing bad block table\n"); } /* Read oob data */ ops.ooblen = (len >> this->page_shift) * mtd->oobsize; ops.oobbuf = &buf[len]; - res = mtd->read_oob(mtd, to + mtd->writesize, &ops); + res = mtd_read_oob(mtd, to + mtd->writesize, &ops); if (res < 0 || ops.oobretlen != ops.ooblen) goto outerr; @@ -821,19 +772,19 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, pageoffs = page - (int)(to >> this->page_shift); offs = pageoffs << this->page_shift; /* Preset the bbt area with 0xff */ - memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); + memset(&buf[offs], 0xff, (size_t)(numblocks >> sft)); ooboffs = len + (pageoffs * mtd->oobsize); } else if (td->options & NAND_BBT_NO_OOB) { ooboffs = 0; offs = td->len; - /* the version byte */ + /* The version byte */ if (td->options & NAND_BBT_VERSION) offs++; /* Calc length */ - len = (size_t) (numblocks >> sft); + len = (size_t)(numblocks >> sft); len += offs; - /* Make it page aligned ! */ + /* Make it page aligned! */ len = ALIGN(len, mtd->writesize); /* Preset the buffer with 0xff */ memset(buf, 0xff, len); @@ -841,8 +792,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, memcpy(buf, td->pattern, td->len); } else { /* Calc length */ - len = (size_t) (numblocks >> sft); - /* Make it page aligned ! */ + len = (size_t)(numblocks >> sft); + /* Make it page aligned! */ len = ALIGN(len, mtd->writesize); /* Preset the buffer with 0xff */ memset(buf, 0xff, len + @@ -856,13 +807,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, if (td->options & NAND_BBT_VERSION) buf[ooboffs + td->veroffs] = td->version[chip]; - /* walk through the memory table */ + /* Walk through the memory table */ for (i = 0; i < numblocks;) { uint8_t dat; dat = this->bbt[bbtoffs + (i >> 2)]; for (j = 0; j < 4; j++, i++) { int sftcnt = (i << (3 - sft)) & sftmsk; - /* Do not store the reserved bbt blocks ! */ + /* Do not store the reserved bbt blocks! */ buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); dat >>= 2; @@ -883,8 +834,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, if (res < 0) goto outerr; - printk(KERN_DEBUG "Bad block table written to 0x%012llx, version " - "0x%02X\n", (unsigned long long)to, td->version[chip]); + pr_info("Bad block table written to 0x%012llx, version 0x%02X\n", + (unsigned long long)to, td->version[chip]); /* Mark it as used */ td->pages[chip] = page; @@ -892,19 +843,18 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, return 0; outerr: - printk(KERN_WARNING - "nand_bbt: Error while writing bad block table %d\n", res); + pr_warn("nand_bbt: error while writing bad block table %d\n", res); return res; } /** * nand_memory_bbt - [GENERIC] create a memory based bad block table - * @mtd: MTD device structure - * @bd: descriptor for the good/bad block search pattern + * @mtd: MTD device structure + * @bd: descriptor for the good/bad block search pattern * - * The function creates a memory based bbt by scanning the device - * for manufacturer / software marked good / bad blocks -*/ + * The function creates a memory based bbt by scanning the device for + * manufacturer / software marked good / bad blocks. + */ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; @@ -915,25 +865,24 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b /** * check_create - [GENERIC] create and write bbt(s) if necessary - * @mtd: MTD device structure - * @buf: temporary buffer - * @bd: descriptor for the good/bad block search pattern + * @mtd: MTD device structure + * @buf: temporary buffer + * @bd: descriptor for the good/bad block search pattern * - * The function checks the results of the previous call to read_bbt - * and creates / updates the bbt(s) if necessary - * Creation is necessary if no bbt was found for the chip/device - * Update is necessary if one of the tables is missing or the - * version nr. of one table is less than the other -*/ + * The function checks the results of the previous call to read_bbt and creates + * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found + * for the chip/device. Update is necessary if one of the tables is missing or + * the version nr. of one table is less than the other. + */ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) { - int i, chips, writeops, chipsel, res; + int i, chips, writeops, create, chipsel, res, res2; struct nand_chip *this = mtd->priv; struct nand_bbt_descr *td = this->bbt_td; struct nand_bbt_descr *md = this->bbt_md; struct nand_bbt_descr *rd, *rd2; - /* Do we have a bbt per chip ? */ + /* Do we have a bbt per chip? */ if (td->options & NAND_BBT_PERCHIP) chips = this->numchips; else @@ -941,86 +890,98 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc for (i = 0; i < chips; i++) { writeops = 0; + create = 0; rd = NULL; rd2 = NULL; - /* Per chip or per device ? */ + res = res2 = 0; + /* Per chip or per device? */ chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; - /* Mirrored table available ? */ + /* Mirrored table available? */ if (md) { if (td->pages[i] == -1 && md->pages[i] == -1) { + create = 1; writeops = 0x03; - goto create; - } - - if (td->pages[i] == -1) { + } else if (td->pages[i] == -1) { rd = md; - td->version[i] = md->version[i]; - writeops = 1; - goto writecheck; - } - - if (md->pages[i] == -1) { + writeops = 0x01; + } else if (md->pages[i] == -1) { rd = td; - md->version[i] = td->version[i]; - writeops = 2; - goto writecheck; - } - - if (td->version[i] == md->version[i]) { + writeops = 0x02; + } else if (td->version[i] == md->version[i]) { rd = td; if (!(td->options & NAND_BBT_VERSION)) rd2 = md; - goto writecheck; - } - - if (((int8_t) (td->version[i] - md->version[i])) > 0) { + } else if (((int8_t)(td->version[i] - md->version[i])) > 0) { rd = td; - md->version[i] = td->version[i]; - writeops = 2; + writeops = 0x02; } else { rd = md; - td->version[i] = md->version[i]; - writeops = 1; + writeops = 0x01; } - - goto writecheck; - } else { if (td->pages[i] == -1) { + create = 1; writeops = 0x01; - goto create; + } else { + rd = td; } - rd = td; - goto writecheck; } - create: - /* Create the bad block table by scanning the device ? */ - if (!(td->options & NAND_BBT_CREATE)) - continue; - /* Create the table in memory by scanning the chip(s) */ - if (!(this->options & NAND_CREATE_EMPTY_BBT)) - create_bbt(mtd, buf, bd, chipsel); - - td->version[i] = 1; - if (md) - md->version[i] = 1; - writecheck: - /* read back first ? */ - if (rd) - read_abs_bbt(mtd, buf, rd, chipsel); - /* If they weren't versioned, read both. */ - if (rd2) - read_abs_bbt(mtd, buf, rd2, chipsel); - - /* Write the bad block table to the device ? */ + if (create) { + /* Create the bad block table by scanning the device? */ + if (!(td->options & NAND_BBT_CREATE)) + continue; + + /* Create the table in memory by scanning the chip(s) */ + if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY)) + create_bbt(mtd, buf, bd, chipsel); + + td->version[i] = 1; + if (md) + md->version[i] = 1; + } + + /* Read back first? */ + if (rd) { + res = read_abs_bbt(mtd, buf, rd, chipsel); + if (mtd_is_eccerr(res)) { + /* Mark table as invalid */ + rd->pages[i] = -1; + rd->version[i] = 0; + i--; + continue; + } + } + /* If they weren't versioned, read both */ + if (rd2) { + res2 = read_abs_bbt(mtd, buf, rd2, chipsel); + if (mtd_is_eccerr(res2)) { + /* Mark table as invalid */ + rd2->pages[i] = -1; + rd2->version[i] = 0; + i--; + continue; + } + } + + /* Scrub the flash table(s)? */ + if (mtd_is_bitflip(res) || mtd_is_bitflip(res2)) + writeops = 0x03; + + /* Update version numbers before writing */ + if (md) { + td->version[i] = max(td->version[i], md->version[i]); + md->version[i] = td->version[i]; + } + + /* Write the bad block table to the device? */ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { res = write_bbt(mtd, buf, td, md, chipsel); if (res < 0) return res; } - /* Write the mirror bad block table to the device ? */ + /* Write the mirror bad block table to the device? */ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { res = write_bbt(mtd, buf, md, td, chipsel); if (res < 0) @@ -1032,20 +993,19 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc /** * mark_bbt_regions - [GENERIC] mark the bad block table regions - * @mtd: MTD device structure - * @td: bad block table descriptor + * @mtd: MTD device structure + * @td: bad block table descriptor * - * The bad block table regions are marked as "bad" to prevent - * accidental erasures / writes. The regions are identified by - * the mark 0x02. -*/ + * The bad block table regions are marked as "bad" to prevent accidental + * erasures / writes. The regions are identified by the mark 0x02. + */ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) { struct nand_chip *this = mtd->priv; int i, j, chips, block, nrblocks, update; uint8_t oldval, newval; - /* Do we have a bbt per chip ? */ + /* Do we have a bbt per chip? */ if (td->options & NAND_BBT_PERCHIP) { chips = this->numchips; nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); @@ -1082,9 +1042,11 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) update = 1; block += 2; } - /* If we want reserved blocks to be recorded to flash, and some - new ones have been marked, then we need to update the stored - bbts. This should only happen once. */ + /* + * If we want reserved blocks to be recorded to flash, and some + * new ones have been marked, then we need to update the stored + * bbts. This should only happen once. + */ if (update && td->reserved_block_code) nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); } @@ -1092,8 +1054,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) /** * verify_bbt_descr - verify the bad block description - * @mtd: MTD device structure - * @bd: the table to verify + * @mtd: MTD device structure + * @bd: the table to verify * * This functions performs a few sanity checks on the bad block description * table. @@ -1111,16 +1073,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) pattern_len = bd->len; bits = bd->options & NAND_BBT_NRBITS_MSK; - BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) && - !(this->options & NAND_USE_FLASH_BBT)); + BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) && + !(this->bbt_options & NAND_BBT_USE_FLASH)); BUG_ON(!bits); if (bd->options & NAND_BBT_VERSION) pattern_len++; if (bd->options & NAND_BBT_NO_OOB) { - BUG_ON(!(this->options & NAND_USE_FLASH_BBT)); - BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB)); + BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH)); + BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB)); BUG_ON(bd->offs); if (bd->options & NAND_BBT_VERSION) BUG_ON(bd->veroffs != bd->len); @@ -1140,18 +1102,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) /** * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) - * @mtd: MTD device structure - * @bd: descriptor for the good/bad block search pattern - * - * The function checks, if a bad block table(s) is/are already - * available. If not it scans the device for manufacturer - * marked good / bad blocks and writes the bad block table(s) to - * the selected place. + * @mtd: MTD device structure + * @bd: descriptor for the good/bad block search pattern * - * The bad block table memory is allocated here. It must be freed - * by calling the nand_free_bbt function. + * The function checks, if a bad block table(s) is/are already available. If + * not it scans the device for manufacturer marked good / bad blocks and writes + * the bad block table(s) to the selected place. * -*/ + * The bad block table memory is allocated here. It must be freed by calling + * the nand_free_bbt function. + */ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; @@ -1161,19 +1121,21 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) struct nand_bbt_descr *md = this->bbt_md; len = mtd->size >> (this->bbt_erase_shift + 2); - /* Allocate memory (2bit per block) and clear the memory bad block table */ + /* + * Allocate memory (2bit per block) and clear the memory bad block + * table. + */ this->bbt = kzalloc(len, GFP_KERNEL); - if (!this->bbt) { - printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); + if (!this->bbt) return -ENOMEM; - } - /* If no primary table decriptor is given, scan the device - * to build a memory based bad block table + /* + * If no primary table decriptor is given, scan the device to build a + * memory based bad block table. */ if (!td) { if ((res = nand_memory_bbt(mtd, bd))) { - printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n"); + pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); kfree(this->bbt); this->bbt = NULL; } @@ -1187,22 +1149,20 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) len += (len >> this->page_shift) * mtd->oobsize; buf = vmalloc(len); if (!buf) { - printk(KERN_ERR "nand_bbt: Out of memory\n"); kfree(this->bbt); this->bbt = NULL; return -ENOMEM; } - /* Is the bbt at a given page ? */ + /* Is the bbt at a given page? */ if (td->options & NAND_BBT_ABSPAGE) { - res = read_abs_bbts(mtd, buf, td, md); + read_abs_bbts(mtd, buf, td, md); } else { /* Search the bad block table using a pattern in oob */ - res = search_read_bbts(mtd, buf, td, md); + search_read_bbts(mtd, buf, td, md); } - if (res) - res = check_create(mtd, buf, bd); + res = check_create(mtd, buf, bd); /* Prevent the bbt regions from erasing / writing */ mark_bbt_region(mtd, td); @@ -1215,15 +1175,15 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) /** * nand_update_bbt - [NAND Interface] update bad block table(s) - * @mtd: MTD device structure - * @offs: the offset of the newly marked block + * @mtd: MTD device structure + * @offs: the offset of the newly marked block * - * The function updates the bad block table(s) -*/ + * The function updates the bad block table(s). + */ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) { struct nand_chip *this = mtd->priv; - int len, res = 0, writeops = 0; + int len, res = 0; int chip, chipsel; uint8_t *buf; struct nand_bbt_descr *td = this->bbt_td; @@ -1236,14 +1196,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) len = (1 << this->bbt_erase_shift); len += (len >> this->page_shift) * mtd->oobsize; buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "nand_update_bbt: Out of memory\n"); + if (!buf) return -ENOMEM; - } - writeops = md != NULL ? 0x03 : 0x01; - - /* Do we have a bbt per chip ? */ + /* Do we have a bbt per chip? */ if (td->options & NAND_BBT_PERCHIP) { chip = (int)(offs >> this->chip_shift); chipsel = chip; @@ -1256,14 +1212,14 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) if (md) md->version[chip]++; - /* Write the bad block table to the device ? */ - if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { + /* Write the bad block table to the device? */ + if (td->options & NAND_BBT_WRITE) { res = write_bbt(mtd, buf, td, md, chipsel); if (res < 0) goto out; } - /* Write the mirror bad block table to the device ? */ - if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { + /* Write the mirror bad block table to the device? */ + if (md && (md->options & NAND_BBT_WRITE)) { res = write_bbt(mtd, buf, md, td, chipsel); } @@ -1272,8 +1228,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs) return res; } -/* Define some generic bad / good block scan pattern which are used - * while scanning a device for factory marked good / bad blocks. */ +/* + * Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. + */ static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; @@ -1285,8 +1243,7 @@ static struct nand_bbt_descr agand_flashbased = { .pattern = scan_agand_pattern }; -/* Generic flash bbt decriptors -*/ +/* Generic flash bbt descriptors */ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; @@ -1296,7 +1253,7 @@ static struct nand_bbt_descr bbt_main_descr = { .offs = 8, .len = 4, .veroffs = 12, - .maxblocks = 4, + .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, .pattern = bbt_pattern }; @@ -1306,55 +1263,51 @@ static struct nand_bbt_descr bbt_mirror_descr = { .offs = 8, .len = 4, .veroffs = 12, - .maxblocks = 4, + .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, .pattern = mirror_pattern }; -static struct nand_bbt_descr bbt_main_no_bbt_descr = { +static struct nand_bbt_descr bbt_main_no_oob_descr = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | NAND_BBT_NO_OOB, .len = 4, .veroffs = 4, - .maxblocks = 4, + .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, .pattern = bbt_pattern }; -static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { +static struct nand_bbt_descr bbt_mirror_no_oob_descr = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | NAND_BBT_NO_OOB, .len = 4, .veroffs = 4, - .maxblocks = 4, + .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, .pattern = mirror_pattern }; -#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ - NAND_BBT_SCANBYTE1AND6) +#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB) /** - * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure - * @this: NAND chip to create descriptor for + * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure + * @this: NAND chip to create descriptor for * * This function allocates and initializes a nand_bbt_descr for BBM detection - * based on the properties of "this". The new descriptor is stored in + * based on the properties of @this. The new descriptor is stored in * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when * passed to this function. - * */ -static int nand_create_default_bbt_descr(struct nand_chip *this) +static int nand_create_badblock_pattern(struct nand_chip *this) { struct nand_bbt_descr *bd; if (this->badblock_pattern) { - printk(KERN_WARNING "BBT descr already allocated; not replacing.\n"); + pr_warn("Bad block pattern already allocated; not replacing\n"); return -EINVAL; } bd = kzalloc(sizeof(*bd), GFP_KERNEL); - if (!bd) { - printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n"); + if (!bd) return -ENOMEM; - } - bd->options = this->options & BBT_SCAN_OPTIONS; + bd->options = this->bbt_options & BADBLOCK_SCAN_MASK; bd->offs = this->badblockpos; bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1; bd->pattern = scan_ff_pattern; @@ -1365,22 +1318,20 @@ static int nand_create_default_bbt_descr(struct nand_chip *this) /** * nand_default_bbt - [NAND Interface] Select a default bad block table for the device - * @mtd: MTD device structure - * - * This function selects the default bad block table - * support for the device and calls the nand_scan_bbt function + * @mtd: MTD device structure * -*/ + * This function selects the default bad block table support for the device and + * calls the nand_scan_bbt function. + */ int nand_default_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; - /* Default for AG-AND. We must use a flash based - * bad block table as the devices have factory marked - * _good_ blocks. Erasing those blocks leads to loss - * of the good / bad information, so we _must_ store - * this information in a good / bad table during - * startup + /* + * Default for AG-AND. We must use a flash based bad block table as the + * devices have factory marked _good_ blocks. Erasing those blocks + * leads to loss of the good / bad information, so we _must_ store this + * information in a good / bad table during startup. */ if (this->options & NAND_IS_AND) { /* Use the default pattern descriptors */ @@ -1388,17 +1339,17 @@ int nand_default_bbt(struct mtd_info *mtd) this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; } - this->options |= NAND_USE_FLASH_BBT; + this->bbt_options |= NAND_BBT_USE_FLASH; return nand_scan_bbt(mtd, &agand_flashbased); } - /* Is a flash based bad block table requested ? */ - if (this->options & NAND_USE_FLASH_BBT) { + /* Is a flash based bad block table requested? */ + if (this->bbt_options & NAND_BBT_USE_FLASH) { /* Use the default pattern descriptors */ if (!this->bbt_td) { - if (this->options & NAND_USE_FLASH_BBT_NO_OOB) { - this->bbt_td = &bbt_main_no_bbt_descr; - this->bbt_md = &bbt_mirror_no_bbt_descr; + if (this->bbt_options & NAND_BBT_NO_OOB) { + this->bbt_td = &bbt_main_no_oob_descr; + this->bbt_md = &bbt_mirror_no_oob_descr; } else { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; @@ -1410,18 +1361,17 @@ int nand_default_bbt(struct mtd_info *mtd) } if (!this->badblock_pattern) - nand_create_default_bbt_descr(this); + nand_create_badblock_pattern(this); return nand_scan_bbt(mtd, this->badblock_pattern); } /** * nand_isbad_bbt - [NAND Interface] Check if a block is bad - * @mtd: MTD device structure - * @offs: offset in the device - * @allowbbt: allow access to bad block table region - * -*/ + * @mtd: MTD device structure + * @offs: offset in the device + * @allowbbt: allow access to bad block table region + */ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) { struct nand_chip *this = mtd->priv; diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 39535497f8..f856778b5e 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -71,14 +71,15 @@ const struct nand_flash_dev nand_flash_ids[] = { * These are the new chips with large page size. The pagesize and the * erasesize is determined from the extended id bytes */ -#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) +#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) - /*512 Megabit */ + /* 512 Megabit */ {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS}, + {"NAND 64MiB 3,3V 8-bit", 0xF0, 0, 64, 0, LP_OPTIONS}, {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16}, {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, @@ -157,9 +158,7 @@ const struct nand_flash_dev nand_flash_ids[] = { * writes possible, but not implemented now */ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, - NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | - BBT_AUTO_REFRESH - }, + NAND_IS_AND | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, {NULL,} }; @@ -176,6 +175,9 @@ const struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_MICRON, "Micron"}, - {NAND_MFR_AMD, "AMD"}, + {NAND_MFR_AMD, "AMD/Spansion"}, + {NAND_MFR_MACRONIX, "Macronix"}, + {NAND_MFR_EON, "Eon"}, {0x0, "Unknown"} }; + diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 4727f9c989..d81972ca27 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -121,7 +121,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) WATCHDOG_RESET(); if (!opts->scrub && bbtest) { - int ret = meminfo->block_isbad(meminfo, erase.addr); + int ret = mtd_block_isbad(meminfo, erase.addr); if (ret > 0) { if (!opts->quiet) printf("\rSkipping bad block at " @@ -144,7 +144,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) erased_length++; - result = meminfo->erase(meminfo, &erase); + result = mtd_erase(meminfo, &erase); if (result != 0) { printf("\n%s: MTD Erase failure: %d\n", mtd_device, result); @@ -153,15 +153,16 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) /* format for JFFS2 ? */ if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) { - chip->ops.ooblen = 8; - chip->ops.datbuf = NULL; - chip->ops.oobbuf = (uint8_t *)&cleanmarker; - chip->ops.ooboffs = 0; - chip->ops.mode = MTD_OOB_AUTO; + struct mtd_oob_ops ops; + ops.ooblen = 8; + ops.datbuf = NULL; + ops.oobbuf = (uint8_t *)&cleanmarker; + ops.ooboffs = 0; + ops.mode = MTD_OPS_AUTO_OOB; - result = meminfo->write_oob(meminfo, + result = mtd_write_oob(meminfo, erase.addr, - &chip->ops); + &ops); if (result != 0) { printf("\n%s: MTD writeoob failure: %d\n", mtd_device, result); @@ -458,7 +459,8 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length, static size_t drop_ffs(const nand_info_t *nand, const u_char *buf, const size_t *len) { - size_t i, l = *len; + size_t l = *len; + ssize_t i; for (i = l - 1; i >= 0; i--) if (buf[i] != 0xFF) @@ -604,7 +606,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ops.len = pagesize; ops.ooblen = nand->oobsize; - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooboffs = 0; pages = write_size / pagesize_oob; @@ -614,7 +616,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, ops.datbuf = p_buffer; ops.oobbuf = ops.datbuf + pagesize; - rval = nand->write_oob(nand, offset, &ops); + rval = mtd_write_oob(nand, offset, &ops); if (rval != 0) break; diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 213d2c945a..94b90332d6 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -216,6 +216,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.mode = NAND_ECC_HW; nand->ecc.size = 256; nand->ecc.bytes = 3; + nand->ecc.strength = 1; nand->select_chip = ndfc_select_chip; #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT diff --git a/drivers/mtd/nand/nomadik.c b/drivers/mtd/nand/nomadik.c index b76f4cbb5e..dc8e513739 100644 --- a/drivers/mtd/nand/nomadik.c +++ b/drivers/mtd/nand/nomadik.c @@ -212,6 +212,7 @@ int board_nand_init(struct nand_chip *chip) chip->ecc.mode = NAND_ECC_HW; chip->ecc.bytes = 3; chip->ecc.size = 512; + chip->ecc.strength = 1; chip->ecc.layout = &nomadik_ecc_layout; chip->ecc.calculate = nomadik_ecc_calculate; chip->ecc.hwctl = nomadik_ecc_hwctl; diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index bc1bcad3ba..5d088227ea 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -590,11 +590,12 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller expects OOB data read to chip->oob_poi * @page: page number to read * */ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -804,6 +805,7 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) nand->ecc.hwctl = NULL; nand->ecc.correct = NULL; nand->ecc.calculate = NULL; + nand->ecc.strength = eccstrength; /* Setup the ecc configurations again */ if (hardware) { @@ -901,7 +903,7 @@ int board_nand_init(struct nand_chip *nand) nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd; nand->cmd_ctrl = omap_nand_hwcontrol; - nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_AUTOINCR; + nand->options = NAND_NO_PADDING | NAND_CACHEPRG; /* If we are 16 bit dev, our gpmc config tells us that */ if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000) nand->options |= NAND_BUSWIDTH_16; @@ -934,6 +936,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.layout = &hw_bch8_nand_oob; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; + nand->ecc.strength = 8; nand->ecc.hwctl = omap_enable_ecc_bch; nand->ecc.correct = omap_correct_data_bch; nand->ecc.calculate = omap_calculate_ecc_bch; @@ -952,6 +955,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.hwctl = omap_enable_hwecc; nand->ecc.correct = omap_correct_data; nand->ecc.calculate = omap_calculate_ecc; + nand->ecc.strength = 1; omap_hwecc_init(nand); #endif #endif diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c index e1a459b009..43d8213e04 100644 --- a/drivers/mtd/nand/s3c2410_nand.c +++ b/drivers/mtd/nand/s3c2410_nand.c @@ -173,6 +173,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.mode = NAND_ECC_HW; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; + nand->ecc.strength = 1; #else nand->ecc.mode = NAND_ECC_SOFT; #endif diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c index 4d94cc6f56..6afbec61ee 100644 --- a/drivers/mtd/nand/tegra_nand.c +++ b/drivers/mtd/nand/tegra_nand.c @@ -707,7 +707,7 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip, * -EIO when command timeout */ static int nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { return nand_rw_page(mtd, chip, buf, page, 1, 0); } @@ -719,8 +719,8 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, * @param chip nand chip info structure * @param buf data buffer */ -static void nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) +static int nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, int oob_required) { int page; struct nand_drv *info; @@ -731,6 +731,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, (readl(&info->reg->addr_reg2) << 16); nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1); + return 0; } @@ -746,7 +747,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, * -EIO when command timeout */ static int nand_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { return nand_rw_page(mtd, chip, buf, page, 0, 0); } @@ -758,8 +759,8 @@ static int nand_read_page_raw(struct mtd_info *mtd, * @param chip nand chip info structure * @param buf data buffer */ -static void nand_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) +static int nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf, int oob_required) { int page; struct nand_drv *info; @@ -769,6 +770,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, (readl(&info->reg->addr_reg2) << 16); nand_rw_page(mtd, chip, (uint8_t *)buf, page, 0, 1); + return 0; } /** @@ -873,19 +875,13 @@ static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip, * @param mtd mtd info structure * @param chip nand chip info structure * @param page page number to read - * @param sndcmd flag whether to issue read command or not - * @return 1 - issue read command next time - * 0 - not to issue */ static int nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page, int sndcmd) + int page) { - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); - sndcmd = 0; - } + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); nand_rw_oob(mtd, chip, page, 0, 0); - return sndcmd; + return 0; } /** @@ -1018,6 +1014,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum) nand->ecc.write_page_raw = nand_write_page_raw; nand->ecc.read_oob = nand_read_oob; nand->ecc.write_oob = nand_write_oob; + nand->ecc.strength = 1; nand->select_chip = nand_select_chip; nand->dev_ready = nand_dev_ready; nand->priv = &nand_ctrl; diff --git a/drivers/mtd/nand/tegra_nand.h b/drivers/mtd/nand/tegra_nand.h index 7e74be75f8..622b869808 100644 --- a/drivers/mtd/nand/tegra_nand.h +++ b/drivers/mtd/nand/tegra_nand.h @@ -224,7 +224,7 @@ enum { #define BCH_DEC_STATUS_MAX_CORR_CNT_MASK (0x1f << 8) #define BCH_DEC_STATUS_PAGE_NUMBER_MASK 0xFF -#define LP_OPTIONS (NAND_NO_READRDY | NAND_NO_AUTOINCR) +#define LP_OPTIONS 0 struct nand_ctlr { u32 command; /* offset 00h */ diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 858e322743..ddfe7e7c75 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -743,7 +743,7 @@ static void onenand_release_device(struct mtd_info *mtd) } /** - * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer + * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer * @param mtd MTD device structure * @param buf destination address * @param column oob offset to read from @@ -807,7 +807,7 @@ static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status) return status; /* check if we failed due to uncorrectable error */ - if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR) + if (!mtd_is_eccerr(status) && status != ONENAND_BBT_READ_ECC_ERROR) return status; /* check if address lies in MLC region */ @@ -847,7 +847,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); - if (ops->mode == MTD_OOB_AUTO) + if (ops->mode == MTD_OPS_AUTO_OOB) oobsize = this->ecclayout->oobavail; else oobsize = mtd->oobsize; @@ -914,7 +914,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, thisooblen = oobsize - oobcolumn; thisooblen = min_t(int, thisooblen, ooblen - oobread); - if (ops->mode == MTD_OOB_AUTO) + if (ops->mode == MTD_OPS_AUTO_OOB) onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); else this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); @@ -929,7 +929,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (unlikely(ret)) ret = onenand_recover_lsb(mtd, from, ret); onenand_update_bufferram(mtd, from, !ret); - if (ret == -EBADMSG) + if (mtd_is_eccerr(ret)) ret = 0; } @@ -950,7 +950,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, /* Now wait for load */ ret = this->wait(mtd, FL_READING); onenand_update_bufferram(mtd, from, !ret); - if (ret == -EBADMSG) + if (mtd_is_eccerr(ret)) ret = 0; } } @@ -987,7 +987,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, struct mtd_ecc_stats stats; int read = 0, thislen, column, oobsize; size_t len = ops->ooblen; - mtd_oob_mode_t mode = ops->mode; + unsigned int mode = ops->mode; u_char *buf = ops->oobbuf; int ret = 0, readcmd; @@ -998,7 +998,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, /* Initialize return length value */ ops->oobretlen = 0; - if (mode == MTD_OOB_AUTO) + if (mode == MTD_OPS_AUTO_OOB) oobsize = this->ecclayout->oobavail; else oobsize = mtd->oobsize; @@ -1041,7 +1041,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from, break; } - if (mode == MTD_OOB_AUTO) + if (mode == MTD_OPS_AUTO_OOB) onenand_transfer_auto_oob(mtd, buf, column, thislen); else this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen); @@ -1115,10 +1115,10 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, int ret; switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_AUTO: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_AUTO_OOB: break; - case MTD_OOB_RAW: + case MTD_OPS_RAW: /* Not implemented yet */ default: return -EINVAL; @@ -1337,7 +1337,7 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, #define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0) /** - * onenand_fill_auto_oob - [Internal] oob auto-placement transfer + * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer * @param mtd MTD device structure * @param oob_buf oob buffer * @param buf source address @@ -1404,19 +1404,13 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, ops->retlen = 0; ops->oobretlen = 0; - /* Do not allow writes past end of device */ - if (unlikely((to + len) > mtd->size)) { - printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n"); - return -EINVAL; - } - /* Reject writes, which are not page aligned */ if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) { printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n"); return -EINVAL; } - if (ops->mode == MTD_OOB_AUTO) + if (ops->mode == MTD_OPS_AUTO_OOB) oobsize = this->ecclayout->oobavail; else oobsize = mtd->oobsize; @@ -1450,7 +1444,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, /* We send data to spare ram with oobsize * * to prevent byte access */ memset(oobbuf, 0xff, mtd->oobsize); - if (ops->mode == MTD_OOB_AUTO) + if (ops->mode == MTD_OPS_AUTO_OOB) onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen); else memcpy(oobbuf + oobcolumn, oob, thisooblen); @@ -1502,7 +1496,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, } /** - * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band + * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band * @param mtd MTD device structure * @param to offset to write to * @param len number of bytes to write @@ -1521,7 +1515,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, u_char *oobbuf; size_t len = ops->ooblen; const u_char *buf = ops->oobbuf; - mtd_oob_mode_t mode = ops->mode; + unsigned int mode = ops->mode; to += ops->ooboffs; @@ -1530,7 +1524,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, /* Initialize retlen, in case of early exit */ ops->oobretlen = 0; - if (mode == MTD_OOB_AUTO) + if (mode == MTD_OPS_AUTO_OOB) oobsize = this->ecclayout->oobavail; else oobsize = mtd->oobsize; @@ -1571,7 +1565,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to, /* We send data to spare ram with oobsize * to prevent byte access */ memset(oobbuf, 0xff, mtd->oobsize); - if (mode == MTD_OOB_AUTO) + if (mode == MTD_OPS_AUTO_OOB) onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen); else memcpy(oobbuf + column, buf, thislen); @@ -1661,10 +1655,10 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, int ret; switch (ops->mode) { - case MTD_OOB_PLACE: - case MTD_OOB_AUTO: + case MTD_OPS_PLACE_OOB: + case MTD_OPS_AUTO_OOB: break; - case MTD_OOB_RAW: + case MTD_OPS_RAW: /* Not implemented yet */ default: return -EINVAL; @@ -1720,13 +1714,6 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) addr, len); - /* Do not allow erase past end of device */ - if (unlikely((len + addr) > mtd->size)) { - MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:" - "Erase past end of device\n"); - return -EINVAL; - } - if (FLEXONENAND(this)) { /* Find the eraseregion of this address */ i = flexonenand_region(mtd, addr); @@ -1762,8 +1749,6 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) return -EINVAL; } - instr->fail_addr = 0xffffffff; - /* Grab the lock and see if the device is available */ onenand_get_device(mtd, FL_ERASING); @@ -1889,7 +1874,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) struct bbm_info *bbm = this->bbm; u_char buf[2] = {0, 0}; struct mtd_oob_ops ops = { - .mode = MTD_OOB_PLACE, + .mode = MTD_OPS_PLACE_OOB, .ooblen = 2, .oobbuf = buf, .ooboffs = 0, @@ -1915,7 +1900,6 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) */ int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct onenand_chip *this = mtd->priv; int ret; ret = onenand_block_isbad(mtd, ofs); @@ -1926,7 +1910,7 @@ int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) return ret; } - ret = this->block_markbad(mtd, ofs); + ret = mtd_block_markbad(mtd, ofs); return ret; } @@ -2386,7 +2370,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int i, ret; int block; struct mtd_oob_ops ops = { - .mode = MTD_OOB_PLACE, + .mode = MTD_OPS_PLACE_OOB, .ooboffs = 0, .ooblen = mtd->oobsize, .datbuf = NULL, @@ -2645,14 +2629,14 @@ int onenand_probe(struct mtd_info *mtd) mtd->size = this->chipsize; mtd->flags = MTD_CAP_NANDFLASH; - mtd->erase = onenand_erase; - mtd->read = onenand_read; - mtd->write = onenand_write; - mtd->read_oob = onenand_read_oob; - mtd->write_oob = onenand_write_oob; - mtd->sync = onenand_sync; - mtd->block_isbad = onenand_block_isbad; - mtd->block_markbad = onenand_block_markbad; + mtd->_erase = onenand_erase; + mtd->_read = onenand_read; + mtd->_write = onenand_write; + mtd->_read_oob = onenand_read_oob; + mtd->_write_oob = onenand_write_oob; + mtd->_sync = onenand_sync; + mtd->_block_isbad = onenand_block_isbad; + mtd->_block_markbad = onenand_block_markbad; return 0; } diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 9d5da54708..0267c2c5c9 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -87,7 +87,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf, startblock = 0; from = 0; - ops.mode = MTD_OOB_PLACE; + ops.mode = MTD_OPS_PLACE_OOB; ops.ooblen = readlen; ops.oobbuf = buf; ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; @@ -200,10 +200,8 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) len = this->chipsize >> (this->erase_shift + 2); /* Allocate memory (2bit per block) */ bbm->bbt = malloc(len); - if (!bbm->bbt) { - printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); + if (!bbm->bbt) return -ENOMEM; - } /* Clear the memory bad block table */ memset(bbm->bbt, 0x00, len); diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index a708162e43..25888220df 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -539,7 +539,7 @@ static int io_init(struct ubi_device *ubi) ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd); ubi->flash_size = ubi->mtd->size; - if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) + if (mtd_can_have_bb(ubi->mtd)) ubi->bad_allowed = 1; ubi->min_io_size = ubi->mtd->writesize; diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index d523c94b12..d2d3c9c580 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -460,7 +460,7 @@ retry: if (err == UBI_IO_BITFLIPS) { scrub = 1; err = 0; - } else if (err == -EBADMSG) { + } else if (mtd_is_eccerr(err)) { if (vol->vol_type == UBI_DYNAMIC_VOLUME) goto out_unlock; scrub = 1; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 8423894000..05de9aeb6e 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -154,7 +154,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, addr = (loff_t)pnum * ubi->peb_size + offset; retry: - err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); + err = mtd_read(ubi->mtd, addr, len, &read, buf); if (err) { if (err == -EUCLEAN) { /* @@ -268,7 +268,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, } addr = (loff_t)pnum * ubi->peb_size + offset; - err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); + err = mtd_write(ubi->mtd, addr, len, &written, buf); if (err) { ubi_err("error %d while writing %d bytes to PEB %d:%d, written" " %zd bytes", err, len, pnum, offset, written); @@ -318,7 +318,7 @@ retry: ei.callback = erase_callback; ei.priv = (unsigned long)&wq; - err = ubi->mtd->erase(ubi->mtd, &ei); + err = mtd_erase(ubi->mtd, &ei); if (err) { if (retries++ < UBI_IO_RETRIES) { dbg_io("error %d while erasing PEB %d, retry", @@ -516,7 +516,7 @@ int ubi_io_is_bad(const struct ubi_device *ubi, int pnum) if (ubi->bad_allowed) { int ret; - ret = mtd->block_isbad(mtd, (loff_t)pnum * ubi->peb_size); + ret = mtd_block_isbad(mtd, (loff_t)pnum * ubi->peb_size); if (ret < 0) ubi_err("error %d while checking if PEB %d is bad", ret, pnum); @@ -551,7 +551,7 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum) if (!ubi->bad_allowed) return 0; - err = mtd->block_markbad(mtd, (loff_t)pnum * ubi->peb_size); + err = mtd_block_markbad(mtd, (loff_t)pnum * ubi->peb_size); if (err) ubi_err("cannot mark PEB %d bad, error %d", pnum, err); return err; @@ -1242,7 +1242,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, loff_t addr = (loff_t)pnum * ubi->peb_size + offset; mutex_lock(&ubi->dbg_buf_mutex); - err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); + err = mtd_read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); if (err && err != -EUCLEAN) { ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 423d479152..e553188797 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -349,7 +349,7 @@ int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, return 0; err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); - if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) { + if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { ubi_warn("mark volume %d as corrupted", vol_id); vol->corrupted = 1; } diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index a6410bfb6b..e8660d9970 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c @@ -82,7 +82,7 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) err = ubi_eba_read_leb(ubi, vol, i, buf, 0, size, 1); if (err) { - if (err == -EBADMSG) + if (mtd_is_eccerr(err)) err = 1; break; } diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index f679f06494..29d2320010 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -388,7 +388,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, ubi->vtbl_size); - if (err == UBI_IO_BITFLIPS || err == -EBADMSG) + if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) /* * Scrub the PEB later. Note, -EBADMSG indicates an * uncorrectable ECC error, but we have our own CRC and diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 1ae35d360b..14999447b1 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -26,7 +26,8 @@ include $(TOPDIR)/config.mk LIB := $(obj)libpci.o COBJS-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o -COBJS-$(CONFIG_PCI) += pci.o pci_auto.o pci_indirect.o +COBJS-$(CONFIG_PCI) += pci.o pci_auto.o +COBJS-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o COBJS-$(CONFIG_FTPCI100) += pci_ftpci100.o COBJS-$(CONFIG_IXP_PCI) += pci_ixp.o COBJS-$(CONFIG_SH4_PCI) += pci_sh4.o diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index e8c159c0f3..913dd9c862 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -25,9 +25,10 @@ LIB := $(obj)libtpm.o $(shell mkdir -p $(obj)slb9635_i2c) -COBJS-$(CONFIG_GENERIC_LPC_TPM) = generic_lpc_tpm.o -COBJS-$(CONFIG_INFINEON_TPM_I2C) += tis_i2c.o slb9635_i2c/tpm.o -COBJS-$(CONFIG_INFINEON_TPM_I2C) += slb9635_i2c/tpm_tis_i2c.o +# TODO: Merge tpm_tis_lpc.c with tpm.c +COBJS-$(CONFIG_TPM_TIS_I2C) += tpm.o +COBJS-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o +COBJS-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/tpm/slb9635_i2c/compatibility.h b/drivers/tpm/slb9635_i2c/compatibility.h deleted file mode 100644 index 62dc9fa964..0000000000 --- a/drivers/tpm/slb9635_i2c/compatibility.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 Infineon Technologies - * - * Authors: - * Peter Huewe <huewe.external@infineon.com> - * - * Version: 2.1.1 - * - * 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 _COMPATIBILITY_H_ -#define _COMPATIBILITY_H_ - -/* all includes from U-Boot */ -#include <linux/types.h> -#include <linux/unaligned/be_byteshift.h> -#include <asm-generic/errno.h> -#include <compiler.h> -#include <common.h> - -/* extended error numbers from linux (see errno.h) */ -#define ECANCELED 125 /* Operation Canceled */ - -#define msleep(t) udelay((t)*1000) - -/* Timer frequency. Corresponds to msec timer resolution*/ -#define HZ 1000 - -#define dev_dbg(dev, format, arg...) debug(format, ##arg) -#define dev_err(dev, format, arg...) printf(format, ##arg) -#define dev_info(dev, format, arg...) debug(format, ##arg) -#define dbg_printf debug - -#endif diff --git a/drivers/tpm/tis_i2c.c b/drivers/tpm/tis_i2c.c index e818fbaf54..22554e1456 100644 --- a/drivers/tpm/tis_i2c.c +++ b/drivers/tpm/tis_i2c.c @@ -68,6 +68,10 @@ static int tpm_decode_config(struct tpm *dev) node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); if (node < 0) { + node = fdtdec_next_compatible(blob, 0, + COMPAT_INFINEON_SLB9645_TPM); + } + if (node < 0) { debug("%s: Node not found\n", __func__); return -1; } diff --git a/drivers/tpm/slb9635_i2c/tpm.c b/drivers/tpm/tpm.c index 496c48e8cf..b657334195 100644 --- a/drivers/tpm/slb9635_i2c/tpm.c +++ b/drivers/tpm/tpm.c @@ -32,11 +32,30 @@ * MA 02111-1307 USA */ -#include <malloc.h> -#include "tpm.h" +#include <config.h> +#include <common.h> +#include <compiler.h> +#include <fdtdec.h> +#include <i2c.h> +#include <tpm.h> +#include <asm-generic/errno.h> +#include <linux/types.h> +#include <linux/unaligned/be_byteshift.h> -/* global structure for tpm chip data */ -struct tpm_chip g_chip; +#include "tpm_private.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* TPM configuration */ +struct tpm { + int i2c_bus; + int slave_addr; + char inited; + int old_bus; +} tpm; + +/* Global structure for tpm chip data */ +static struct tpm_chip g_chip; enum tpm_duration { TPM_SHORT = 0, @@ -45,9 +64,18 @@ enum tpm_duration { TPM_UNDEFINED, }; -#define TPM_MAX_ORDINAL 243 -#define TPM_MAX_PROTECTED_ORDINAL 12 -#define TPM_PROTECTED_ORDINAL_MASK 0xFF +/* Extended error numbers from linux (see errno.h) */ +#define ECANCELED 125 /* Operation Canceled */ + +/* Timer frequency. Corresponds to msec timer resolution*/ +#define HZ 1000 + +#define TPM_MAX_ORDINAL 243 +#define TPM_MAX_PROTECTED_ORDINAL 12 +#define TPM_PROTECTED_ORDINAL_MASK 0xFF + +#define TPM_CMD_COUNT_BYTE 2 +#define TPM_CMD_ORDINAL_BYTE 6 /* * Array with one entry per ordinal defining the maximum amount @@ -318,34 +346,31 @@ static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { TPM_MEDIUM, }; -/* - * Returns max number of milliseconds to wait - */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +/* Returns max number of milliseconds to wait */ +static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, + u32 ordinal) { int duration_idx = TPM_UNDEFINED; int duration = 0; - if (ordinal < TPM_MAX_ORDINAL) + if (ordinal < TPM_MAX_ORDINAL) { duration_idx = tpm_ordinal_duration[ordinal]; - else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < - TPM_MAX_PROTECTED_ORDINAL) - duration_idx = - tpm_protected_ordinal_duration[ordinal & - TPM_PROTECTED_ORDINAL_MASK]; + } else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < + TPM_MAX_PROTECTED_ORDINAL) { + duration_idx = tpm_protected_ordinal_duration[ + ordinal & TPM_PROTECTED_ORDINAL_MASK]; + } if (duration_idx != TPM_UNDEFINED) duration = chip->vendor.duration[duration_idx]; + if (duration <= 0) - return 2 * 60 * HZ; /*two minutes timeout*/ + return 2 * 60 * HZ; /* Two minutes timeout */ else return duration; } -#define TPM_CMD_COUNT_BYTE 2 -#define TPM_CMD_ORDINAL_BYTE 6 - -ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) +static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) { ssize_t rc; u32 count, ordinal; @@ -358,18 +383,17 @@ ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE); if (count == 0) { - dev_err(chip->dev, "no data\n"); + error("no data\n"); return -ENODATA; } if (count > bufsiz) { - dev_err(chip->dev, - "invalid count value %x %zx\n", count, bufsiz); + error("invalid count value %x %zx\n", count, bufsiz); return -E2BIG; } rc = chip->vendor.send(chip, (u8 *)buf, count); if (rc < 0) { - dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); + error("tpm_transmit: tpm_send: error %zd\n", rc); goto out; } @@ -379,47 +403,126 @@ ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz) start = get_timer(0); stop = tpm_calc_ordinal_duration(chip, ordinal); do { - dbg_printf("waiting for status...\n"); + debug("waiting for status...\n"); u8 status = chip->vendor.status(chip); if ((status & chip->vendor.req_complete_mask) == chip->vendor.req_complete_val) { - dbg_printf("...got it;\n"); + debug("...got it;\n"); goto out_recv; } if ((status == chip->vendor.req_canceled)) { - dev_err(chip->dev, "Operation Canceled\n"); + error("Operation Canceled\n"); rc = -ECANCELED; goto out; } - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); chip->vendor.cancel(chip); - dev_err(chip->dev, "Operation Timed out\n"); + error("Operation Timed out\n"); rc = -ETIME; goto out; out_recv: - - dbg_printf("out_recv: reading response...\n"); + debug("out_recv: reading response...\n"); rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE); if (rc < 0) - dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); + error("tpm_transmit: tpm_recv: error %zd\n", rc); + out: return rc; } -#define TPM_ERROR_SIZE 10 +static int tpm_open(uint32_t dev_addr) +{ + int rc; + if (g_chip.is_open) + return -EBUSY; + rc = tpm_vendor_init(dev_addr); + if (rc < 0) + g_chip.is_open = 0; + return rc; +} -enum tpm_capabilities { - TPM_CAP_PROP = cpu_to_be32(5), -}; +static void tpm_close(void) +{ + if (g_chip.is_open) { + tpm_vendor_cleanup(&g_chip); + g_chip.is_open = 0; + } +} -enum tpm_sub_capabilities { - TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), - TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), -}; +static int tpm_select(void) +{ + int ret; + + tpm.old_bus = i2c_get_bus_num(); + if (tpm.old_bus != tpm.i2c_bus) { + ret = i2c_set_bus_num(tpm.i2c_bus); + if (ret) { + debug("%s: Fail to set i2c bus %d\n", __func__, + tpm.i2c_bus); + return -1; + } + } + return 0; +} + +static int tpm_deselect(void) +{ + int ret; + + if (tpm.old_bus != i2c_get_bus_num()) { + ret = i2c_set_bus_num(tpm.old_bus); + if (ret) { + debug("%s: Fail to restore i2c bus %d\n", + __func__, tpm.old_bus); + return -1; + } + } + tpm.old_bus = -1; + return 0; +} + +/** + * Decode TPM configuration. + * + * @param dev Returns a configuration of TPM device + * @return 0 if ok, -1 on error + */ +static int tpm_decode_config(struct tpm *dev) +{ +#ifdef CONFIG_OF_CONTROL + const void *blob = gd->fdt_blob; + int node, parent; + int i2c_bus; + + node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM); + if (node < 0) { + node = fdtdec_next_compatible(blob, 0, + COMPAT_INFINEON_SLB9645_TPM); + } + if (node < 0) { + debug("%s: Node not found\n", __func__); + return -1; + } + parent = fdt_parent_offset(blob, node); + if (parent < 0) { + debug("%s: Cannot find node parent\n", __func__); + return -1; + } + i2c_bus = i2c_get_bus_num_fdt(parent); + if (i2c_bus < 0) + return -1; + dev->i2c_bus = i2c_bus; + dev->slave_addr = fdtdec_get_addr(blob, node, "reg"); +#else + dev->i2c_bus = CONFIG_TPM_TIS_I2C_BUS_NUMBER; + dev->slave_addr = CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS; +#endif + return 0; +} struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) { @@ -433,21 +536,94 @@ struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry) return chip; } -int tpm_open(uint32_t dev_addr) +int tis_init(void) +{ + if (tpm.inited) + return 0; + + if (tpm_decode_config(&tpm)) + return -1; + + if (tpm_select()) + return -1; + + /* + * Probe TPM twice; the first probing might fail because TPM is asleep, + * and the probing can wake up TPM. + */ + if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) { + debug("%s: fail to probe i2c addr 0x%x\n", __func__, + tpm.slave_addr); + return -1; + } + + tpm_deselect(); + + tpm.inited = 1; + + return 0; +} + +int tis_open(void) { int rc; - if (g_chip.is_open) - return -EBUSY; - rc = tpm_vendor_init(dev_addr); - if (rc < 0) - g_chip.is_open = 0; + + if (!tpm.inited) + return -1; + + if (tpm_select()) + return -1; + + rc = tpm_open(tpm.slave_addr); + + tpm_deselect(); + return rc; } -void tpm_close(void) +int tis_close(void) { - if (g_chip.is_open) { - tpm_vendor_cleanup(&g_chip); - g_chip.is_open = 0; + if (!tpm.inited) + return -1; + + if (tpm_select()) + return -1; + + tpm_close(); + + tpm_deselect(); + + return 0; +} + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + int len; + uint8_t buf[4096]; + + if (!tpm.inited) + return -1; + + if (sizeof(buf) < sbuf_size) + return -1; + + memcpy(buf, sendbuf, sbuf_size); + + if (tpm_select()) + return -1; + + len = tpm_transmit(buf, sbuf_size); + + tpm_deselect(); + + if (len < 10) { + *rbuf_len = 0; + return -1; } + + memcpy(recvbuf, buf, len); + *rbuf_len = len; + + return 0; } diff --git a/drivers/tpm/slb9635_i2c/tpm.h b/drivers/tpm/tpm_private.h index 9ddee865df..888a074d35 100644 --- a/drivers/tpm/slb9635_i2c/tpm.h +++ b/drivers/tpm/tpm_private.h @@ -33,12 +33,11 @@ * MA 02111-1307 USA */ -#ifndef _TPM_H_ -#define _TPM_H_ +#ifndef _TPM_PRIVATE_H_ +#define _TPM_PRIVATE_H_ #include <linux/compiler.h> - -#include "compatibility.h" +#include <linux/types.h> enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -47,13 +46,9 @@ enum tpm_timeout { /* Size of external transmit buffer (used in tpm_transmit)*/ #define TPM_BUFSIZE 4096 -/* Index of fields in TPM command buffer */ -#define TPM_CMD_SIZE_BYTE 2 -#define TPM_CMD_ORDINAL_BYTE 6 - /* Index of Count field in TPM response buffer */ -#define TPM_RSP_SIZE_BYTE 2 -#define TPM_RSP_RC_BYTE 6 +#define TPM_RSP_SIZE_BYTE 2 +#define TPM_RSP_RC_BYTE 6 struct tpm_chip; @@ -65,10 +60,10 @@ struct tpm_vendor_specific { int (*recv) (struct tpm_chip *, u8 *, size_t); int (*send) (struct tpm_chip *, u8 *, size_t); void (*cancel) (struct tpm_chip *); - u8(*status) (struct tpm_chip *); + u8(*status) (struct tpm_chip *); int locality; - unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ - unsigned long duration[3]; /* msec */ + unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ + unsigned long duration[3]; /* msec */ }; struct tpm_chip { @@ -132,30 +127,11 @@ struct tpm_cmd_t { union tpm_cmd_params params; } __packed; +struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *); -/* ---------- Interface for TPM vendor ------------ */ - -extern struct tpm_chip *tpm_register_hardware( - const struct tpm_vendor_specific *); +int tpm_vendor_init(uint32_t dev_addr); -extern int tpm_vendor_init(uint32_t dev_addr); +void tpm_vendor_cleanup(struct tpm_chip *chip); -extern void tpm_vendor_cleanup(struct tpm_chip *chip); - -/* ---------- Interface for TDDL ------------------- */ - -/* - * if dev_addr != 0 - redefines TPM device address - * Returns < 0 on error, 0 on success. - */ -extern int tpm_open(uint32_t dev_addr); - -extern void tpm_close(void); - -/* - * Transmit bufsiz bytes out of buf to TPM and get results back in buf, too. - * Returns < 0 on error, 0 on success. - */ -extern ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz); #endif diff --git a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 82a41bf5b2..2dd8501f92 100644 --- a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -37,46 +37,102 @@ */ #include <common.h> +#include <fdtdec.h> +#include <compiler.h> #include <i2c.h> +#include <tpm.h> +#include <asm-generic/errno.h> #include <linux/types.h> +#include <linux/unaligned/be_byteshift.h> -#include "compatibility.h" -#include "tpm.h" +#include "tpm_private.h" + +DECLARE_GLOBAL_DATA_PTR; -/* max. buffer size supported by our tpm */ -#ifdef TPM_BUFSIZE -#undef TPM_BUFSIZE -#endif -#define TPM_BUFSIZE 1260 /* Address of the TPM on the I2C bus */ -#define TPM_I2C_ADDR 0x20 -/* max. number of iterations after i2c NAK */ -#define MAX_COUNT 3 +#define TPM_I2C_ADDR 0x20 + +/* Max buffer size supported by our tpm */ +#define TPM_DEV_BUFSIZE 1260 -#define SLEEP_DURATION 60 /*in usec*/ +/* Max number of iterations after i2c NAK */ +#define MAX_COUNT 3 -/* max. number of iterations after i2c NAK for 'long' commands - * we need this especially for sending TPM_READY, since the cleanup after the +/* + * Max number of iterations after i2c NAK for 'long' commands + * + * We need this especially for sending TPM_READY, since the cleanup after the * transtion to the ready state may take some time, but it is unpredictable * how long it will take. */ -#define MAX_COUNT_LONG 50 +#define MAX_COUNT_LONG 50 + +#define SLEEP_DURATION 60 /* in usec */ +#define SLEEP_DURATION_LONG 210 /* in usec */ -#define SLEEP_DURATION_LONG 210 /* in usec */ +#define TPM_HEADER_SIZE 10 + +/* + * Expected value for DIDVID register + * + * The only device the system knows about at this moment is Infineon slb9635. + */ +#define TPM_TIS_I2C_DID_VID 0x000b15d1L + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +enum tis_defaults { + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* ms */ +}; /* expected value for DIDVID register */ -#define TPM_TIS_I2C_DID_VID 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L + +enum i2c_chip_type { + SLB9635, + SLB9645, + UNKNOWN, +}; + +static const char * const chip_name[] = { + [SLB9635] = "slb9635tt", + [SLB9645] = "slb9645tt", + [UNKNOWN] = "unknown/fallback to slb9635", +}; + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) +#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) /* Structure to store I2C TPM specific stuff */ -struct tpm_inf_dev { +struct tpm_dev { uint addr; - u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ + u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ + enum i2c_chip_type chip_type; }; -static struct tpm_inf_dev tpm_dev = { +static struct tpm_dev tpm_dev = { .addr = TPM_I2C_ADDR }; +static struct tpm_dev tpm_dev; + /* * iic_tpm_read() - read from TPM register * @addr: register address to read from @@ -91,34 +147,52 @@ static struct tpm_inf_dev tpm_dev = { * * Return -EIO on error, 0 on success. */ -int iic_tpm_read(u8 addr, u8 *buffer, size_t len) +static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) { int rc; int count; - uint myaddr = addr; - /* we have to use uint here, uchar hangs the board */ - - for (count = 0; count < MAX_COUNT; count++) { - rc = i2c_write(tpm_dev.addr, 0, 0, (uchar *)&myaddr, 1); - if (rc == 0) - break; /*success, break to skip sleep*/ - - udelay(SLEEP_DURATION); - } - - if (rc) - return -rc; - - /* After the TPM has successfully received the register address it needs - * some time, thus we're sleeping here again, before retrieving the data - */ - for (count = 0; count < MAX_COUNT; count++) { - udelay(SLEEP_DURATION); - rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); - if (rc == 0) - break; /*success, break to skip sleep*/ + uint32_t addrbuf = addr; + + if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { + /* slb9635 protocol should work in both cases */ + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_write(tpm_dev.addr, 0, 0, + (uchar *)&addrbuf, 1); + if (rc == 0) + break; /* Success, break to skip sleep */ + udelay(SLEEP_DURATION); + } + if (rc) + return -rc; + + /* After the TPM has successfully received the register address + * it needs some time, thus we're sleeping here again, before + * retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + udelay(SLEEP_DURATION); + rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); + if (rc == 0) + break; /* success, break to skip sleep */ + } + } else { + /* + * Use a combined read for newer chips. + * Unfortunately the smbus functions are not suitable due to + * the 32 byte limit of the smbus. + * Retries should usually not be needed, but are kept just to + * be safe on the safe side. + */ + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len); + if (rc == 0) + break; /* break here to skip sleep */ + udelay(SLEEP_DURATION); + } } + /* Take care of 'guard time' */ + udelay(SLEEP_DURATION); if (rc) return -rc; @@ -126,24 +200,24 @@ int iic_tpm_read(u8 addr, u8 *buffer, size_t len) } static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, - unsigned int sleep_time, - u8 max_count) + unsigned int sleep_time, u8 max_count) { int rc = 0; int count; - /* prepare send buffer */ + /* Prepare send buffer */ tpm_dev.buf[0] = addr; memcpy(&(tpm_dev.buf[1]), buffer, len); for (count = 0; count < max_count; count++) { rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1); if (rc == 0) - break; /*success, break to skip sleep*/ - + break; /* Success, break to skip sleep */ udelay(sleep_time); } + /* take care of 'guard time' */ + udelay(SLEEP_DURATION); if (rc) return -rc; @@ -175,42 +249,16 @@ static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) /* * This function is needed especially for the cleanup situation after * sending TPM_READY - * */ + */ static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) { return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, MAX_COUNT_LONG); } -#define TPM_HEADER_SIZE 10 - -enum tis_access { - TPM_ACCESS_VALID = 0x80, - TPM_ACCESS_ACTIVE_LOCALITY = 0x20, - TPM_ACCESS_REQUEST_PENDING = 0x04, - TPM_ACCESS_REQUEST_USE = 0x02, -}; - -enum tis_status { - TPM_STS_VALID = 0x80, - TPM_STS_COMMAND_READY = 0x40, - TPM_STS_GO = 0x20, - TPM_STS_DATA_AVAIL = 0x10, - TPM_STS_DATA_EXPECT = 0x08, -}; - -enum tis_defaults { - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 2000, /* 2 sec */ -}; - -#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) -#define TPM_STS(l) (0x0001 | ((l) << 4)) -#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) -#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) - static int check_locality(struct tpm_chip *chip, int loc) { + const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; u8 buf; int rc; @@ -218,8 +266,7 @@ static int check_locality(struct tpm_chip *chip, int loc) if (rc < 0) return rc; - if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == - (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { + if ((buf & mask) == mask) { chip->vendor.locality = loc; return loc; } @@ -229,12 +276,13 @@ static int check_locality(struct tpm_chip *chip, int loc) static void release_locality(struct tpm_chip *chip, int loc, int force) { + const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; u8 buf; + if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) return; - if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == - (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { + if (force || (buf & mask) == mask) { buf = TPM_ACCESS_ACTIVE_LOCALITY; iic_tpm_write(TPM_ACCESS(loc), &buf, 1); } @@ -246,17 +294,17 @@ static int request_locality(struct tpm_chip *chip, int loc) u8 buf = TPM_ACCESS_REQUEST_USE; if (check_locality(chip, loc) >= 0) - return loc; /* we already have the locality */ + return loc; /* We already have the locality */ iic_tpm_write(TPM_ACCESS(loc), &buf, 1); - /* wait for burstcount */ + /* Wait for burstcount */ start = get_timer(0); stop = chip->vendor.timeout_a; do { if (check_locality(chip, loc) >= 0) return loc; - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); return -1; @@ -264,8 +312,9 @@ static int request_locality(struct tpm_chip *chip, int loc) static u8 tpm_tis_i2c_status(struct tpm_chip *chip) { - /* NOTE: since i2c read may fail, return 0 in this case --> time-out */ + /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ u8 buf; + if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) return 0; else @@ -274,8 +323,9 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) static void tpm_tis_i2c_ready(struct tpm_chip *chip) { - /* this causes the current command to be aborted */ + /* This causes the current command to be aborted */ u8 buf = TPM_STS_COMMAND_READY; + iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); } @@ -283,34 +333,34 @@ static ssize_t get_burstcount(struct tpm_chip *chip) { unsigned long start, stop; ssize_t burstcnt; - u8 buf[3]; + u8 addr, buf[3]; - /* wait for burstcount */ - /* which timeout value, spec has 2 answers (c & d) */ + /* Wait for burstcount */ + /* XXX: Which timeout value? Spec has 2 answers (c & d) */ start = get_timer(0); stop = chip->vendor.timeout_d; do { /* Note: STS is little endian */ - if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) - < 0) + addr = TPM_STS(chip->vendor.locality) + 1; + if (iic_tpm_read(addr, buf, 3) < 0) burstcnt = 0; else burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; if (burstcnt) return burstcnt; - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); } while (get_timer(start) < stop); return -EBUSY; } static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - int *status) + int *status) { unsigned long start, stop; - /* check current status */ + /* Check current status */ *status = tpm_tis_i2c_status(chip); if ((*status & mask) == mask) return 0; @@ -318,11 +368,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, start = get_timer(0); stop = timeout; do { - msleep(TPM_TIMEOUT); + udelay(TPM_TIMEOUT * 1000); *status = tpm_tis_i2c_status(chip); if ((*status & mask) == mask) return 0; - } while (get_timer(start) < stop); return -ETIME; @@ -337,17 +386,16 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) while (size < count) { burstcnt = get_burstcount(chip); - /* burstcount < 0 = tpm is busy */ + /* burstcount < 0 -> tpm is busy */ if (burstcnt < 0) return burstcnt; - /* limit received data to max. left */ + /* Limit received data to max left */ if (burstcnt > (count - size)) burstcnt = count - size; rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), - &(buf[size]), - burstcnt); + &(buf[size]), burstcnt); if (rc == 0) size += burstcnt; } @@ -365,10 +413,10 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - /* read first 10 bytes, including tag, paramsize, and result */ + /* Read first 10 bytes, including tag, paramsize, and result */ size = recv_data(chip, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) { - dev_err(chip->dev, "Unable to read header\n"); + error("Unable to read header\n"); goto out; } @@ -379,23 +427,24 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) } size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); + expected - TPM_HEADER_SIZE); if (size < expected) { - dev_err(chip->dev, "Unable to read remainder of result\n"); + error("Unable to read remainder of result\n"); size = -ETIME; goto out; } wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ - dev_err(chip->dev, "Error left over data\n"); + if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ + error("Error left over data\n"); size = -EIO; goto out; } out: tpm_tis_i2c_ready(chip); - /* The TPM needs some time to clean up here, + /* + * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ udelay(2000); @@ -409,10 +458,11 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) int rc, status; ssize_t burstcnt; size_t count = 0; + int retry = 0; u8 sts = TPM_STS_GO; - if (len > TPM_BUFSIZE) - return -E2BIG; /* command is too long for our tpm, sorry */ + if (len > TPM_DEV_BUFSIZE) + return -E2BIG; /* Command is too long for our tpm, sorry */ if (request_locality(chip, 0) < 0) return -EBUSY; @@ -420,44 +470,45 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) status = tpm_tis_i2c_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_i2c_ready(chip); - if (wait_for_stat - (chip, TPM_STS_COMMAND_READY, - chip->vendor.timeout_b, &status) < 0) { + if (wait_for_stat(chip, TPM_STS_COMMAND_READY, + chip->vendor.timeout_b, &status) < 0) { rc = -ETIME; goto out_err; } } - while (count < len - 1) { - burstcnt = get_burstcount(chip); + burstcnt = get_burstcount(chip); - /* burstcount < 0 = tpm is busy */ - if (burstcnt < 0) - return burstcnt; + /* burstcount < 0 -> tpm is busy */ + if (burstcnt < 0) + return burstcnt; - if (burstcnt > (len-1-count)) - burstcnt = len-1-count; + while (count < len - 1) { + if (burstcnt > len - 1 - count) + burstcnt = len - 1 - count; -#ifdef CONFIG_TPM_I2C_BURST_LIMITATION - if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION) - burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION; -#endif /* CONFIG_TPM_I2C_BURST_LIMITATION */ +#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION + if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION) + burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION; +#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */ rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), - &(buf[count]), burstcnt); + &(buf[count]), burstcnt); if (rc == 0) count += burstcnt; - - wait_for_stat(chip, TPM_STS_VALID, - chip->vendor.timeout_c, &status); - - if ((status & TPM_STS_DATA_EXPECT) == 0) { - rc = -EIO; - goto out_err; + else { + retry++; + wait_for_stat(chip, TPM_STS_VALID, + chip->vendor.timeout_c, &status); + + if ((status & TPM_STS_DATA_EXPECT) == 0) { + rc = -EIO; + goto out_err; + } } } - /* write last byte */ + /* Write last byte */ iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); if ((status & TPM_STS_DATA_EXPECT) != 0) { @@ -465,13 +516,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) goto out_err; } - /* go and do it */ + /* Go and do it */ iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); return len; + out_err: tpm_tis_i2c_ready(chip); - /* The TPM needs some time to clean up here, + /* + * The TPM needs some time to clean up here, * so we sleep rather than keeping the bus busy */ udelay(2000); @@ -490,12 +543,26 @@ static struct tpm_vendor_specific tpm_tis_i2c = { .req_canceled = TPM_STS_COMMAND_READY, }; -/* initialisation of i2c tpm */ +static enum i2c_chip_type tpm_vendor_chip_type(void) +{ +#ifdef CONFIG_OF_CONTROL + const void *blob = gd->fdt_blob; + + if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0) + return SLB9645; + + if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0) + return SLB9635; +#endif + return UNKNOWN; +} +/* Initialisation of i2c tpm */ int tpm_vendor_init(uint32_t dev_addr) { u32 vendor; + u32 expected_did_vid; uint old_addr; int rc = 0; struct tpm_chip *chip; @@ -504,6 +571,8 @@ int tpm_vendor_init(uint32_t dev_addr) if (dev_addr != 0) tpm_dev.addr = dev_addr; + tpm_dev.chip_type = tpm_vendor_chip_type(); + chip = tpm_register_hardware(&tpm_tis_i2c); if (chip < 0) { rc = -ENODEV; @@ -519,26 +588,33 @@ int tpm_vendor_init(uint32_t dev_addr) chip->vendor.timeout_c = TIS_SHORT_TIMEOUT; chip->vendor.timeout_d = TIS_SHORT_TIMEOUT; - if (request_locality(chip, 0) != 0) { + if (request_locality(chip, 0) < 0) { rc = -ENODEV; goto out_err; } - /* read four bytes from DID_VID register */ + /* Read four bytes from DID_VID register */ if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { rc = -EIO; goto out_release; } - /* create DID_VID register value, after swapping to little-endian */ - vendor = be32_to_cpu(vendor); + if (tpm_dev.chip_type == SLB9635) { + vendor = be32_to_cpu(vendor); + expected_did_vid = TPM_TIS_I2C_DID_VID_9635; + } else { + /* device id and byte order has changed for newer i2c tpms */ + expected_did_vid = TPM_TIS_I2C_DID_VID_9645; + } - if (vendor != TPM_TIS_I2C_DID_VID) { + if (tpm_dev.chip_type != UNKNOWN && vendor != expected_did_vid) { + error("Vendor id did not match! ID was %08x\n", vendor); rc = -ENODEV; goto out_release; } - dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); + debug("1.2 TPM (chip type %s device-id 0x%X)\n", + chip_name[tpm_dev.chip_type], vendor >> 16); /* * A timeout query to TPM can be placed here. diff --git a/drivers/tpm/generic_lpc_tpm.c b/drivers/tpm/tpm_tis_lpc.c index 04ad418973..04ad418973 100644 --- a/drivers/tpm/generic_lpc_tpm.c +++ b/drivers/tpm/tpm_tis_lpc.c diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c index 75ec8f7881..76624b9256 100644 --- a/drivers/usb/eth/asix.c +++ b/drivers/usb/eth/asix.c @@ -407,46 +407,40 @@ static int asix_basic_reset(struct ueth_data *dev) rx_ctl = asix_read_rx_ctl(dev); debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); - return 0; -} - -/* - * Asix callbacks - */ -static int asix_init(struct eth_device *eth, bd_t *bd) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int timeout = 0; -#define TIMEOUT_RESOLUTION 50 /* ms */ - int link_detected; - - debug("** %s()\n", __func__); - dev->phy_id = asix_get_phy_addr(dev); if (dev->phy_id < 0) debug("Failed to read phy id\n"); - if (asix_sw_reset(dev, AX_SWRESET_PRL) < 0) - goto out_err; - - if (asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL) < 0) - goto out_err; - asix_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET); asix_mdio_write(dev, dev->phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA); mii_nway_restart(dev); if (asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT) < 0) - goto out_err; + return -1; if (asix_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, AX88772_IPG2_DEFAULT, 0, NULL) < 0) { debug("Write IPG,IPG1,IPG2 failed\n"); - goto out_err; + return -1; } + return 0; +} + +/* + * Asix callbacks + */ +static int asix_init(struct eth_device *eth, bd_t *bd) +{ + struct ueth_data *dev = (struct ueth_data *)eth->priv; + int timeout = 0; +#define TIMEOUT_RESOLUTION 50 /* ms */ + int link_detected; + + debug("** %s()\n", __func__); + if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0) goto out_err; diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index e545b6be6b..432cf178cf 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -35,6 +35,7 @@ endif # new USB gadget layer dependencies ifdef CONFIG_USB_GADGET COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o +COBJS-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o endif diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2c5600ed52..f30778a163 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1098,4 +1098,5 @@ void usb_composite_unregister(struct usb_composite_driver *driver) if (composite != driver) return; usb_gadget_unregister_driver(&composite_driver); + composite = NULL; } diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index c28866f7d3..45bc132aef 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2261,7 +2261,8 @@ reset: if (rc) goto reset; fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + common->bulk_out_maxpacket = + le16_to_cpu(get_unaligned(&d->wMaxPacketSize)); clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); /* Allocate the requests */ diff --git a/drivers/usb/gadget/fotg210.c b/drivers/usb/gadget/fotg210.c new file mode 100644 index 0000000000..d003331bae --- /dev/null +++ b/drivers/usb/gadget/fotg210.c @@ -0,0 +1,948 @@ +/* + * Faraday USB 2.0 OTG Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#include <common.h> +#include <command.h> +#include <config.h> +#include <net.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> + +#include <usb/fotg210.h> + +#define CFG_NUM_ENDPOINTS 4 +#define CFG_EP0_MAX_PACKET_SIZE 64 +#define CFG_EPX_MAX_PACKET_SIZE 512 + +#define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 2) /* 250 ms */ + +struct fotg210_chip; + +struct fotg210_ep { + struct usb_ep ep; + + uint maxpacket; + uint id; + uint stopped; + + struct list_head queue; + struct fotg210_chip *chip; + const struct usb_endpoint_descriptor *desc; +}; + +struct fotg210_request { + struct usb_request req; + struct list_head queue; + struct fotg210_ep *ep; +}; + +struct fotg210_chip { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + struct fotg210_regs *regs; + uint8_t irq; + uint16_t addr; + int pullup; + enum usb_device_state state; + struct fotg210_ep ep[1 + CFG_NUM_ENDPOINTS]; +}; + +static struct usb_endpoint_descriptor ep0_desc = { + .bLength = sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, +}; + +static inline int fifo_to_ep(struct fotg210_chip *chip, int id, int in) +{ + return (id < 0) ? 0 : ((id & 0x03) + 1); +} + +static inline int ep_to_fifo(struct fotg210_chip *chip, int id) +{ + return (id <= 0) ? -1 : ((id - 1) & 0x03); +} + +static inline int ep_reset(struct fotg210_chip *chip, uint8_t ep_addr) +{ + int ep = ep_addr & USB_ENDPOINT_NUMBER_MASK; + struct fotg210_regs *regs = chip->regs; + + if (ep_addr & USB_DIR_IN) { + /* reset endpoint */ + setbits_le32(®s->iep[ep - 1], IEP_RESET); + mdelay(1); + clrbits_le32(®s->iep[ep - 1], IEP_RESET); + /* clear endpoint stall */ + clrbits_le32(®s->iep[ep - 1], IEP_STALL); + } else { + /* reset endpoint */ + setbits_le32(®s->oep[ep - 1], OEP_RESET); + mdelay(1); + clrbits_le32(®s->oep[ep - 1], OEP_RESET); + /* clear endpoint stall */ + clrbits_le32(®s->oep[ep - 1], OEP_STALL); + } + + return 0; +} + +static int fotg210_reset(struct fotg210_chip *chip) +{ + struct fotg210_regs *regs = chip->regs; + uint32_t i; + + chip->state = USB_STATE_POWERED; + + /* chip enable */ + writel(DEVCTRL_EN, ®s->dev_ctrl); + + /* device address reset */ + chip->addr = 0; + writel(0, ®s->dev_addr); + + /* set idle counter to 7ms */ + writel(7, ®s->idle); + + /* disable all interrupts */ + writel(IMR_MASK, ®s->imr); + writel(GIMR_MASK, ®s->gimr); + writel(GIMR0_MASK, ®s->gimr0); + writel(GIMR1_MASK, ®s->gimr1); + writel(GIMR2_MASK, ®s->gimr2); + + /* clear interrupts */ + writel(ISR_MASK, ®s->isr); + writel(0, ®s->gisr); + writel(0, ®s->gisr0); + writel(0, ®s->gisr1); + writel(0, ®s->gisr2); + + /* chip reset */ + setbits_le32(®s->dev_ctrl, DEVCTRL_RESET); + mdelay(10); + if (readl(®s->dev_ctrl) & DEVCTRL_RESET) { + printf("fotg210: chip reset failed\n"); + return -1; + } + + /* CX FIFO reset */ + setbits_le32(®s->cxfifo, CXFIFO_CXFIFOCLR); + mdelay(10); + if (readl(®s->cxfifo) & CXFIFO_CXFIFOCLR) { + printf("fotg210: ep0 fifo reset failed\n"); + return -1; + } + + /* create static ep-fifo map (EP1 <-> FIFO0, EP2 <-> FIFO1 ...) */ + writel(EPMAP14_DEFAULT, ®s->epmap14); + writel(EPMAP58_DEFAULT, ®s->epmap58); + writel(FIFOMAP_DEFAULT, ®s->fifomap); + writel(0, ®s->fifocfg); + for (i = 0; i < 8; ++i) { + writel(CFG_EPX_MAX_PACKET_SIZE, ®s->iep[i]); + writel(CFG_EPX_MAX_PACKET_SIZE, ®s->oep[i]); + } + + /* FIFO reset */ + for (i = 0; i < 4; ++i) { + writel(FIFOCSR_RESET, ®s->fifocsr[i]); + mdelay(10); + if (readl(®s->fifocsr[i]) & FIFOCSR_RESET) { + printf("fotg210: fifo%d reset failed\n", i); + return -1; + } + } + + /* enable only device interrupt and triggered at level-high */ + writel(IMR_IRQLH | IMR_HOST | IMR_OTG, ®s->imr); + writel(ISR_MASK, ®s->isr); + /* disable EP0 IN/OUT interrupt */ + writel(GIMR0_CXOUT | GIMR0_CXIN, ®s->gimr0); + /* disable EPX IN+SPK+OUT interrupts */ + writel(GIMR1_MASK, ®s->gimr1); + /* disable wakeup+idle+dma+zlp interrupts */ + writel(GIMR2_WAKEUP | GIMR2_IDLE | GIMR2_DMAERR | GIMR2_DMAFIN + | GIMR2_ZLPRX | GIMR2_ZLPTX, ®s->gimr2); + /* enable all group interrupt */ + writel(0, ®s->gimr); + + /* suspend delay = 3 ms */ + writel(3, ®s->idle); + + /* turn-on device interrupts */ + setbits_le32(®s->dev_ctrl, DEVCTRL_GIRQ_EN); + + return 0; +} + +static inline int fotg210_cxwait(struct fotg210_chip *chip, uint32_t mask) +{ + struct fotg210_regs *regs = chip->regs; + int ret = -1; + ulong ts; + + for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { + if ((readl(®s->cxfifo) & mask) != mask) + continue; + ret = 0; + break; + } + + if (ret) + printf("fotg210: cx/ep0 timeout\n"); + + return ret; +} + +static int fotg210_dma(struct fotg210_ep *ep, struct fotg210_request *req) +{ + struct fotg210_chip *chip = ep->chip; + struct fotg210_regs *regs = chip->regs; + uint32_t tmp, ts; + uint8_t *buf = req->req.buf + req->req.actual; + uint32_t len = req->req.length - req->req.actual; + int fifo = ep_to_fifo(chip, ep->id); + int ret = -EBUSY; + + /* 1. init dma buffer */ + if (len > ep->maxpacket) + len = ep->maxpacket; + + /* 2. wait for dma ready (hardware) */ + for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { + if (!(readl(®s->dma_ctrl) & DMACTRL_START)) { + ret = 0; + break; + } + } + if (ret) { + printf("fotg210: dma busy\n"); + req->req.status = ret; + return ret; + } + + /* 3. DMA target setup */ + if (ep->desc->bEndpointAddress & USB_DIR_IN) + flush_dcache_range((ulong)buf, (ulong)buf + len); + else + invalidate_dcache_range((ulong)buf, (ulong)buf + len); + + writel(virt_to_phys(buf), ®s->dma_addr); + + if (ep->desc->bEndpointAddress & USB_DIR_IN) { + if (ep->id == 0) { + /* Wait until cx/ep0 fifo empty */ + fotg210_cxwait(chip, CXFIFO_CXFIFOE); + writel(DMAFIFO_CX, ®s->dma_fifo); + } else { + /* Wait until epx fifo empty */ + fotg210_cxwait(chip, CXFIFO_FIFOE(fifo)); + writel(DMAFIFO_FIFO(fifo), ®s->dma_fifo); + } + writel(DMACTRL_LEN(len) | DMACTRL_MEM2FIFO, ®s->dma_ctrl); + } else { + uint32_t blen; + + if (ep->id == 0) { + writel(DMAFIFO_CX, ®s->dma_fifo); + do { + blen = CXFIFO_BYTES(readl(®s->cxfifo)); + } while (blen < len); + } else { + writel(DMAFIFO_FIFO(fifo), ®s->dma_fifo); + blen = FIFOCSR_BYTES(readl(®s->fifocsr[fifo])); + } + len = (len < blen) ? len : blen; + writel(DMACTRL_LEN(len) | DMACTRL_FIFO2MEM, ®s->dma_ctrl); + } + + /* 4. DMA start */ + setbits_le32(®s->dma_ctrl, DMACTRL_START); + + /* 5. DMA wait */ + ret = -EBUSY; + for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) { + tmp = readl(®s->gisr2); + /* DMA complete */ + if (tmp & GISR2_DMAFIN) { + ret = 0; + break; + } + /* DMA error */ + if (tmp & GISR2_DMAERR) { + printf("fotg210: dma error\n"); + break; + } + /* resume, suspend, reset */ + if (tmp & (GISR2_RESUME | GISR2_SUSPEND | GISR2_RESET)) { + printf("fotg210: dma reset by host\n"); + break; + } + } + + /* 7. DMA target reset */ + if (ret) + writel(DMACTRL_ABORT | DMACTRL_CLRFF, ®s->dma_ctrl); + + writel(0, ®s->gisr2); + writel(0, ®s->dma_fifo); + + req->req.status = ret; + if (!ret) + req->req.actual += len; + else + printf("fotg210: ep%d dma error(code=%d)\n", ep->id, ret); + + return len; +} + +/* + * result of setup packet + */ +#define CX_IDLE 0 +#define CX_FINISH 1 +#define CX_STALL 2 + +static void fotg210_setup(struct fotg210_chip *chip) +{ + int id, ret = CX_IDLE; + uint32_t tmp[2]; + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)tmp; + struct fotg210_regs *regs = chip->regs; + + /* + * If this is the first Cx 8 byte command, + * we can now query USB mode (high/full speed; USB 2.0/USB 1.0) + */ + if (chip->state == USB_STATE_POWERED) { + chip->state = USB_STATE_DEFAULT; + if (readl(®s->otgcsr) & OTGCSR_DEV_B) { + /* Mini-B */ + if (readl(®s->dev_ctrl) & DEVCTRL_HS) { + puts("fotg210: HS\n"); + chip->gadget.speed = USB_SPEED_HIGH; + /* SOF mask timer = 1100 ticks */ + writel(SOFMTR_TMR(1100), ®s->sof_mtr); + } else { + puts("fotg210: FS\n"); + chip->gadget.speed = USB_SPEED_FULL; + /* SOF mask timer = 10000 ticks */ + writel(SOFMTR_TMR(10000), ®s->sof_mtr); + } + } else { + printf("fotg210: mini-A?\n"); + } + } + + /* switch data port to ep0 */ + writel(DMAFIFO_CX, ®s->dma_fifo); + /* fetch 8 bytes setup packet */ + tmp[0] = readl(®s->ep0_data); + tmp[1] = readl(®s->ep0_data); + /* release data port */ + writel(0, ®s->dma_fifo); + + if (req->bRequestType & USB_DIR_IN) + ep0_desc.bEndpointAddress = USB_DIR_IN; + else + ep0_desc.bEndpointAddress = USB_DIR_OUT; + + ret = CX_IDLE; + + if ((req->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { + switch (req->bRequest) { + case USB_REQ_SET_CONFIGURATION: + debug("fotg210: set_cfg(%d)\n", req->wValue & 0x00FF); + if (!(req->wValue & 0x00FF)) { + chip->state = USB_STATE_ADDRESS; + writel(chip->addr, ®s->dev_addr); + } else { + chip->state = USB_STATE_CONFIGURED; + writel(chip->addr | DEVADDR_CONF, + ®s->dev_addr); + } + ret = CX_IDLE; + break; + + case USB_REQ_SET_ADDRESS: + debug("fotg210: set_addr(0x%04X)\n", req->wValue); + chip->state = USB_STATE_ADDRESS; + chip->addr = req->wValue & DEVADDR_ADDR_MASK; + ret = CX_FINISH; + writel(chip->addr, ®s->dev_addr); + break; + + case USB_REQ_CLEAR_FEATURE: + debug("fotg210: clr_feature(%d, %d)\n", + req->bRequestType & 0x03, req->wValue); + switch (req->wValue) { + case 0: /* [Endpoint] halt */ + ep_reset(chip, req->wIndex); + ret = CX_FINISH; + break; + case 1: /* [Device] remote wake-up */ + case 2: /* [Device] test mode */ + default: + ret = CX_STALL; + break; + } + break; + + case USB_REQ_SET_FEATURE: + debug("fotg210: set_feature(%d, %d)\n", + req->wValue, req->wIndex & 0xf); + switch (req->wValue) { + case 0: /* Endpoint Halt */ + id = req->wIndex & 0xf; + setbits_le32(®s->iep[id - 1], IEP_STALL); + setbits_le32(®s->oep[id - 1], OEP_STALL); + ret = CX_FINISH; + break; + case 1: /* Remote Wakeup */ + case 2: /* Test Mode */ + default: + ret = CX_STALL; + break; + } + break; + + case USB_REQ_GET_STATUS: + debug("fotg210: get_status\n"); + ret = CX_STALL; + break; + + case USB_REQ_SET_DESCRIPTOR: + debug("fotg210: set_descriptor\n"); + ret = CX_STALL; + break; + + case USB_REQ_SYNCH_FRAME: + debug("fotg210: sync frame\n"); + ret = CX_STALL; + break; + } + } /* if ((req->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) */ + + if (ret == CX_IDLE && chip->driver->setup) { + if (chip->driver->setup(&chip->gadget, req) < 0) + ret = CX_STALL; + else + ret = CX_FINISH; + } + + switch (ret) { + case CX_FINISH: + setbits_le32(®s->cxfifo, CXFIFO_CXFIN); + break; + + case CX_STALL: + setbits_le32(®s->cxfifo, CXFIFO_CXSTALL | CXFIFO_CXFIN); + printf("fotg210: cx_stall!\n"); + break; + + case CX_IDLE: + debug("fotg210: cx_idle?\n"); + default: + break; + } +} + +/* + * fifo - FIFO id + * zlp - zero length packet + */ +static void fotg210_recv(struct fotg210_chip *chip, int ep_id) +{ + struct fotg210_regs *regs = chip->regs; + struct fotg210_ep *ep = chip->ep + ep_id; + struct fotg210_request *req; + int len; + + if (ep->stopped || (ep->desc->bEndpointAddress & USB_DIR_IN)) { + printf("fotg210: ep%d recv, invalid!\n", ep->id); + return; + } + + if (list_empty(&ep->queue)) { + printf("fotg210: ep%d recv, drop!\n", ep->id); + return; + } + + req = list_first_entry(&ep->queue, struct fotg210_request, queue); + len = fotg210_dma(ep, req); + if (len < ep->ep.maxpacket || req->req.length <= req->req.actual) { + list_del_init(&req->queue); + if (req->req.complete) + req->req.complete(&ep->ep, &req->req); + } + + if (ep->id > 0 && list_empty(&ep->queue)) { + setbits_le32(®s->gimr1, + GIMR1_FIFO_RX(ep_to_fifo(chip, ep->id))); + } +} + +/* + * USB Gadget Layer + */ +static int fotg210_ep_enable( + struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +{ + struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); + struct fotg210_chip *chip = ep->chip; + struct fotg210_regs *regs = chip->regs; + int id = ep_to_fifo(chip, ep->id); + int in = (desc->bEndpointAddress & USB_DIR_IN) ? 1 : 0; + + if (!_ep || !desc + || desc->bDescriptorType != USB_DT_ENDPOINT + || le16_to_cpu(desc->wMaxPacketSize) == 0) { + printf("fotg210: bad ep or descriptor\n"); + return -EINVAL; + } + + ep->desc = desc; + ep->stopped = 0; + + if (in) + setbits_le32(®s->fifomap, FIFOMAP(id, FIFOMAP_IN)); + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + return -EINVAL; + + case USB_ENDPOINT_XFER_ISOC: + setbits_le32(®s->fifocfg, + FIFOCFG(id, FIFOCFG_EN | FIFOCFG_ISOC)); + break; + + case USB_ENDPOINT_XFER_BULK: + setbits_le32(®s->fifocfg, + FIFOCFG(id, FIFOCFG_EN | FIFOCFG_BULK)); + break; + + case USB_ENDPOINT_XFER_INT: + setbits_le32(®s->fifocfg, + FIFOCFG(id, FIFOCFG_EN | FIFOCFG_INTR)); + break; + } + + return 0; +} + +static int fotg210_ep_disable(struct usb_ep *_ep) +{ + struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); + struct fotg210_chip *chip = ep->chip; + struct fotg210_regs *regs = chip->regs; + int id = ep_to_fifo(chip, ep->id); + + ep->desc = NULL; + ep->stopped = 1; + + clrbits_le32(®s->fifocfg, FIFOCFG(id, FIFOCFG_CFG_MASK)); + clrbits_le32(®s->fifomap, FIFOMAP(id, FIFOMAP_DIR_MASK)); + + return 0; +} + +static struct usb_request *fotg210_ep_alloc_request( + struct usb_ep *_ep, gfp_t gfp_flags) +{ + struct fotg210_request *req = malloc(sizeof(*req)); + + if (req) { + memset(req, 0, sizeof(*req)); + INIT_LIST_HEAD(&req->queue); + } + return &req->req; +} + +static void fotg210_ep_free_request( + struct usb_ep *_ep, struct usb_request *_req) +{ + struct fotg210_request *req; + + req = container_of(_req, struct fotg210_request, req); + free(req); +} + +static int fotg210_ep_queue( + struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) +{ + struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); + struct fotg210_chip *chip = ep->chip; + struct fotg210_regs *regs = chip->regs; + struct fotg210_request *req; + + req = container_of(_req, struct fotg210_request, req); + if (!_req || !_req->complete || !_req->buf + || !list_empty(&req->queue)) { + printf("fotg210: invalid request to ep%d\n", ep->id); + return -EINVAL; + } + + if (!chip || chip->state == USB_STATE_SUSPENDED) { + printf("fotg210: request while chip suspended\n"); + return -EINVAL; + } + + req->req.actual = 0; + req->req.status = -EINPROGRESS; + + if (req->req.length == 0) { + req->req.status = 0; + if (req->req.complete) + req->req.complete(&ep->ep, &req->req); + return 0; + } + + if (ep->id == 0) { + do { + int len = fotg210_dma(ep, req); + if (len < ep->ep.maxpacket) + break; + if (ep->desc->bEndpointAddress & USB_DIR_IN) + udelay(100); + } while (req->req.length > req->req.actual); + } else { + if (ep->desc->bEndpointAddress & USB_DIR_IN) { + do { + int len = fotg210_dma(ep, req); + if (len < ep->ep.maxpacket) + break; + } while (req->req.length > req->req.actual); + } else { + list_add_tail(&req->queue, &ep->queue); + clrbits_le32(®s->gimr1, + GIMR1_FIFO_RX(ep_to_fifo(chip, ep->id))); + } + } + + if (ep->id == 0 || (ep->desc->bEndpointAddress & USB_DIR_IN)) { + if (req->req.complete) + req->req.complete(&ep->ep, &req->req); + } + + return 0; +} + +static int fotg210_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); + struct fotg210_request *req; + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) + return -EINVAL; + + /* remove the request */ + list_del_init(&req->queue); + + /* update status & invoke complete callback */ + if (req->req.status == -EINPROGRESS) { + req->req.status = -ECONNRESET; + if (req->req.complete) + req->req.complete(_ep, &req->req); + } + + return 0; +} + +static int fotg210_ep_halt(struct usb_ep *_ep, int halt) +{ + struct fotg210_ep *ep = container_of(_ep, struct fotg210_ep, ep); + struct fotg210_chip *chip = ep->chip; + struct fotg210_regs *regs = chip->regs; + int ret = -1; + + debug("fotg210: ep%d halt=%d\n", ep->id, halt); + + /* Endpoint STALL */ + if (ep->id > 0 && ep->id <= CFG_NUM_ENDPOINTS) { + if (halt) { + /* wait until all ep fifo empty */ + fotg210_cxwait(chip, 0xf00); + /* stall */ + if (ep->desc->bEndpointAddress & USB_DIR_IN) { + setbits_le32(®s->iep[ep->id - 1], + IEP_STALL); + } else { + setbits_le32(®s->oep[ep->id - 1], + OEP_STALL); + } + } else { + if (ep->desc->bEndpointAddress & USB_DIR_IN) { + clrbits_le32(®s->iep[ep->id - 1], + IEP_STALL); + } else { + clrbits_le32(®s->oep[ep->id - 1], + OEP_STALL); + } + } + ret = 0; + } + + return ret; +} + +/* + * activate/deactivate link with host. + */ +static void pullup(struct fotg210_chip *chip, int is_on) +{ + struct fotg210_regs *regs = chip->regs; + + if (is_on) { + if (!chip->pullup) { + chip->state = USB_STATE_POWERED; + chip->pullup = 1; + /* enable the chip */ + setbits_le32(®s->dev_ctrl, DEVCTRL_EN); + /* clear unplug bit (BIT0) */ + clrbits_le32(®s->phy_tmsr, PHYTMSR_UNPLUG); + } + } else { + chip->state = USB_STATE_NOTATTACHED; + chip->pullup = 0; + chip->addr = 0; + writel(chip->addr, ®s->dev_addr); + /* set unplug bit (BIT0) */ + setbits_le32(®s->phy_tmsr, PHYTMSR_UNPLUG); + /* disable the chip */ + clrbits_le32(®s->dev_ctrl, DEVCTRL_EN); + } +} + +static int fotg210_pullup(struct usb_gadget *_gadget, int is_on) +{ + struct fotg210_chip *chip; + + chip = container_of(_gadget, struct fotg210_chip, gadget); + + debug("fotg210: pullup=%d\n", is_on); + + pullup(chip, is_on); + + return 0; +} + +static int fotg210_get_frame(struct usb_gadget *_gadget) +{ + struct fotg210_chip *chip; + struct fotg210_regs *regs; + + chip = container_of(_gadget, struct fotg210_chip, gadget); + regs = chip->regs; + + return SOFFNR_FNR(readl(®s->sof_fnr)); +} + +static struct usb_gadget_ops fotg210_gadget_ops = { + .get_frame = fotg210_get_frame, + .pullup = fotg210_pullup, +}; + +static struct usb_ep_ops fotg210_ep_ops = { + .enable = fotg210_ep_enable, + .disable = fotg210_ep_disable, + .queue = fotg210_ep_queue, + .dequeue = fotg210_ep_dequeue, + .set_halt = fotg210_ep_halt, + .alloc_request = fotg210_ep_alloc_request, + .free_request = fotg210_ep_free_request, +}; + +static struct fotg210_chip controller = { + .regs = (void __iomem *)CONFIG_FOTG210_BASE, + .gadget = { + .name = "fotg210_udc", + .ops = &fotg210_gadget_ops, + .ep0 = &controller.ep[0].ep, + .speed = USB_SPEED_UNKNOWN, + .is_dualspeed = 1, + .is_otg = 0, + .is_a_peripheral = 0, + .b_hnp_enable = 0, + .a_hnp_support = 0, + .a_alt_hnp_support = 0, + }, + .ep[0] = { + .id = 0, + .ep = { + .name = "ep0", + .ops = &fotg210_ep_ops, + }, + .desc = &ep0_desc, + .chip = &controller, + .maxpacket = CFG_EP0_MAX_PACKET_SIZE, + }, + .ep[1] = { + .id = 1, + .ep = { + .name = "ep1", + .ops = &fotg210_ep_ops, + }, + .chip = &controller, + .maxpacket = CFG_EPX_MAX_PACKET_SIZE, + }, + .ep[2] = { + .id = 2, + .ep = { + .name = "ep2", + .ops = &fotg210_ep_ops, + }, + .chip = &controller, + .maxpacket = CFG_EPX_MAX_PACKET_SIZE, + }, + .ep[3] = { + .id = 3, + .ep = { + .name = "ep3", + .ops = &fotg210_ep_ops, + }, + .chip = &controller, + .maxpacket = CFG_EPX_MAX_PACKET_SIZE, + }, + .ep[4] = { + .id = 4, + .ep = { + .name = "ep4", + .ops = &fotg210_ep_ops, + }, + .chip = &controller, + .maxpacket = CFG_EPX_MAX_PACKET_SIZE, + }, +}; + +int usb_gadget_handle_interrupts(void) +{ + struct fotg210_chip *chip = &controller; + struct fotg210_regs *regs = chip->regs; + uint32_t id, st, isr, gisr; + + isr = readl(®s->isr) & (~readl(®s->imr)); + gisr = readl(®s->gisr) & (~readl(®s->gimr)); + if (!(isr & ISR_DEV) || !gisr) + return 0; + + writel(ISR_DEV, ®s->isr); + + /* CX interrupts */ + if (gisr & GISR_GRP0) { + st = readl(®s->gisr0); + writel(0, ®s->gisr0); + + if (st & GISR0_CXERR) + printf("fotg210: cmd error\n"); + + if (st & GISR0_CXABORT) + printf("fotg210: cmd abort\n"); + + if (st & GISR0_CXSETUP) /* setup */ + fotg210_setup(chip); + else if (st & GISR0_CXEND) /* command finish */ + setbits_le32(®s->cxfifo, CXFIFO_CXFIN); + } + + /* FIFO interrupts */ + if (gisr & GISR_GRP1) { + st = readl(®s->gisr1); + for (id = 0; id < 4; ++id) { + if (st & GISR1_RX_FIFO(id)) + fotg210_recv(chip, fifo_to_ep(chip, id, 0)); + } + } + + /* Device Status Interrupts */ + if (gisr & GISR_GRP2) { + st = readl(®s->gisr2); + writel(0, ®s->gisr2); + + if (st & GISR2_RESET) + printf("fotg210: reset by host\n"); + else if (st & GISR2_SUSPEND) + printf("fotg210: suspend/removed\n"); + else if (st & GISR2_RESUME) + printf("fotg210: resume\n"); + + /* Errors */ + if (st & GISR2_ISOCERR) + printf("fotg210: iso error\n"); + if (st & GISR2_ISOCABT) + printf("fotg210: iso abort\n"); + if (st & GISR2_DMAERR) + printf("fotg210: dma error\n"); + } + + return 0; +} + +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + int i, ret = 0; + struct fotg210_chip *chip = &controller; + + if (!driver || !driver->bind || !driver->setup) { + puts("fotg210: bad parameter.\n"); + return -EINVAL; + } + + INIT_LIST_HEAD(&chip->gadget.ep_list); + for (i = 0; i < CFG_NUM_ENDPOINTS + 1; ++i) { + struct fotg210_ep *ep = chip->ep + i; + + ep->ep.maxpacket = ep->maxpacket; + INIT_LIST_HEAD(&ep->queue); + + if (ep->id == 0) { + ep->stopped = 0; + } else { + ep->stopped = 1; + list_add_tail(&ep->ep.ep_list, &chip->gadget.ep_list); + } + } + + if (fotg210_reset(chip)) { + puts("fotg210: reset failed.\n"); + return -EINVAL; + } + + ret = driver->bind(&chip->gadget); + if (ret) { + debug("fotg210: driver->bind() returned %d\n", ret); + return ret; + } + chip->driver = driver; + + return ret; +} + +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct fotg210_chip *chip = &controller; + + driver->unbind(&chip->gadget); + chip->driver = NULL; + + pullup(chip, 0); + + return 0; +} diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index e5701422fa..f038747e63 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -150,6 +150,12 @@ #define gadget_is_mv(g) 0 #endif +#ifdef CONFIG_USB_GADGET_FOTG210 +#define gadget_is_fotg210(g) (!strcmp("fotg210_udc", (g)->name)) +#else +#define gadget_is_fotg210(g) 0 +#endif + /* * CONFIG_USB_GADGET_SX2 * CONFIG_USB_GADGET_AU1X00 @@ -215,5 +221,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x20; else if (gadget_is_mv(gadget)) return 0x21; + else if (gadget_is_fotg210(gadget)) + return 0x22; return -ENOENT; } diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 9ce98f0768..085503dbe8 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -314,7 +314,8 @@ static int pxa25x_ep_enable(struct usb_ep *_ep, if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress - || ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { + || ep->fifo_size < + le16_to_cpu(get_unaligned(&desc->wMaxPacketSize))) { printf("%s, bad ep or descriptor\n", __func__); return -EINVAL; } @@ -329,9 +330,9 @@ static int pxa25x_ep_enable(struct usb_ep *_ep, /* hardware _could_ do smaller, but driver doesn't */ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(desc->wMaxPacketSize) + && le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) != BULK_FIFO_SIZE) - || !desc->wMaxPacketSize) { + || !get_unaligned(&desc->wMaxPacketSize)) { printf("%s, bad %s maxpacket\n", __func__, _ep->name); return -ERANGE; } @@ -345,7 +346,7 @@ static int pxa25x_ep_enable(struct usb_ep *_ep, ep->desc = desc; ep->stopped = 0; ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + ep->ep.maxpacket = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)); /* flush fifo (mostly for OUT buffers) */ pxa25x_ep_fifo_flush(_ep); @@ -485,7 +486,7 @@ write_fifo(struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned max; - max = le16_to_cpu(ep->desc->wMaxPacketSize); + max = le16_to_cpu(get_unaligned(&ep->desc->wMaxPacketSize)); do { unsigned count; int is_last, is_short; @@ -766,7 +767,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) */ if (unlikely(ep->bmAttributes == USB_ENDPOINT_XFER_ISOC && req->req.length > - le16_to_cpu(ep->desc->wMaxPacketSize))) + le16_to_cpu(get_unaligned(&ep->desc->wMaxPacketSize)))) return -EMSGSIZE; debug_cond(NOISY, "%s queue req %p, len %d buf %p\n", diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 87a59704db..98f2a104b7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -43,6 +43,7 @@ COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o else COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o endif +COBJS-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o COBJS-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o diff --git a/drivers/usb/host/ehci-faraday.c b/drivers/usb/host/ehci-faraday.c new file mode 100644 index 0000000000..86add36ce1 --- /dev/null +++ b/drivers/usb/host/ehci-faraday.c @@ -0,0 +1,148 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#include <common.h> +#include <asm/io.h> +#include <usb.h> +#include <usb/fusbh200.h> +#include <usb/fotg210.h> + +#include "ehci.h" + +#ifndef CONFIG_USB_EHCI_BASE_LIST +#define CONFIG_USB_EHCI_BASE_LIST { CONFIG_USB_EHCI_BASE } +#endif + +union ehci_faraday_regs { + struct fusbh200_regs usb; + struct fotg210_regs otg; +}; + +static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs) +{ + return !readl(®s->usb.easstr); +} + +/* + * Create the appropriate control structures to manage + * a new EHCI host controller. + */ +int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr, + struct ehci_hcor **ret_hcor) +{ + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; + union ehci_faraday_regs *regs; + uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST; + + if (index < 0 || index >= ARRAY_SIZE(base_list)) + return -1; + regs = (void __iomem *)base_list[index]; + hccr = (struct ehci_hccr *)®s->usb.hccr; + hcor = (struct ehci_hcor *)®s->usb.hcor; + + if (ehci_is_fotg2xx(regs)) { + /* A-device bus reset */ + /* ... Power off A-device */ + setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); + /* ... Drop vbus and bus traffic */ + clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); + mdelay(1); + /* ... Power on A-device */ + clrbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSDROP); + /* ... Drive vbus and bus traffic */ + setbits_le32(®s->otg.otgcsr, OTGCSR_A_BUSREQ); + mdelay(1); + /* Disable OTG & DEV interrupts, triggered at level-high */ + writel(IMR_IRQLH | IMR_OTG | IMR_DEV, ®s->otg.imr); + /* Clear all interrupt status */ + writel(ISR_HOST | ISR_OTG | ISR_DEV, ®s->otg.isr); + } else { + /* Interrupt=level-high */ + setbits_le32(®s->usb.bmcsr, BMCSR_IRQLH); + /* VBUS on */ + clrbits_le32(®s->usb.bmcsr, BMCSR_VBUS_OFF); + /* Disable all interrupts */ + writel(0x00, ®s->usb.bmier); + writel(0x1f, ®s->usb.bmisr); + } + + *ret_hccr = hccr; + *ret_hcor = hcor; + + return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(int index) +{ + return 0; +} + +/* + * This ehci_set_usbmode() overrides the weak function + * in "ehci-hcd.c". + */ +void ehci_set_usbmode(int index) +{ + /* nothing needs to be done */ +} + +/* + * This ehci_get_port_speed() overrides the weak function + * in "ehci-hcd.c". + */ +int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) +{ + int spd, ret = PORTSC_PSPD_HS; + union ehci_faraday_regs *regs = (void __iomem *)((ulong)hcor - 0x10); + + if (ehci_is_fotg2xx(regs)) + spd = OTGCSR_SPD(readl(®s->otg.otgcsr)); + else + spd = BMCSR_SPD(readl(®s->usb.bmcsr)); + + switch (spd) { + case 0: /* full speed */ + ret = PORTSC_PSPD_FS; + break; + case 1: /* low speed */ + ret = PORTSC_PSPD_LS; + break; + case 2: /* high speed */ + ret = PORTSC_PSPD_HS; + break; + default: + printf("ehci-faraday: invalid device speed\n"); + break; + } + + return ret; +} + +/* + * This ehci_get_portsc_register() overrides the weak function + * in "ehci-hcd.c". + */ +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ + /* Faraday EHCI has one and only one portsc register */ + if (port) { + /* Printing the message would cause a scan failure! */ + debug("The request port(%d) is not configured\n", port); + return NULL; + } + + /* Faraday EHCI PORTSC register offset is 0x20 from hcor */ + return (uint32_t *)((uint8_t *)hcor + 0x20); +} diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e0f3e4b6c7..706cf0cb7d 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -589,10 +589,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); } else { dev->act_len = 0; +#ifndef CONFIG_USB_EHCI_FARADAY debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), ehci_readl(&ctrl->hcor->or_portsc[0]), ehci_readl(&ctrl->hcor->or_portsc[1])); +#endif } free(qtd); @@ -603,6 +605,17 @@ fail: return -1; } +__weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ + if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + /* Printing the message would cause a scan failure! */ + debug("The request port(%u) is not configured\n", port); + return NULL; + } + + return (uint32_t *)&hcor->or_portsc[port]; +} + int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) @@ -616,11 +629,6 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int port = le16_to_cpu(req->index) & 0xff; struct ehci_ctrl *ctrl = dev->controller; - if (port > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", port - 1); - return -1; - } - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[port - 1]; srclen = 0; debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", @@ -631,6 +639,19 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, typeReq = req->request | req->requesttype << 8; switch (typeReq) { + case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): + case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): + case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): + status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); + if (!status_reg) + return -1; + break; + default: + status_reg = NULL; + break; + } + + switch (typeReq) { case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch (le16_to_cpu(req->value) >> 8) { case USB_DT_DEVICE: @@ -809,21 +830,23 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, break; case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): reg = ehci_readl(status_reg); + reg &= ~EHCI_PS_CLEAR; switch (le16_to_cpu(req->value)) { case USB_PORT_FEAT_ENABLE: reg &= ~EHCI_PS_PE; break; case USB_PORT_FEAT_C_ENABLE: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE; + reg |= EHCI_PS_PE; break; case USB_PORT_FEAT_POWER: if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) - reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP); + reg &= ~EHCI_PS_PP; + break; case USB_PORT_FEAT_C_CONNECTION: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC; + reg |= EHCI_PS_CSC; break; case USB_PORT_FEAT_OVER_CURRENT: - reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC; + reg |= EHCI_PS_OCC; break; case USB_PORT_FEAT_C_RESET: ctrl->portreset &= ~(1 << port); @@ -903,6 +926,9 @@ int usb_lowlevel_init(int index, void **controller) qh_list->qh_overlay.qt_token = cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); + flush_dcache_range((uint32_t)qh_list, + ALIGN_END_ADDR(struct QH, qh_list, 1)); + /* Set async. queue head pointer. */ ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); @@ -916,6 +942,9 @@ int usb_lowlevel_init(int index, void **controller) periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + flush_dcache_range((uint32_t)periodic, + ALIGN_END_ADDR(struct QH, periodic, 1)); + /* * Step 2: Setup frame-list: Every microframe, USB tries the same list. * In particular, device specifications on polling frequency @@ -933,6 +962,10 @@ int usb_lowlevel_init(int index, void **controller) | QH_LINK_TYPE_QH; } + flush_dcache_range((uint32_t)ehcic[index].periodic_list, + ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, + 1024)); + /* Set periodic list base address */ ehci_writel(&ehcic[index].hcor->or_periodiclistbase, (uint32_t)ehcic[index].periodic_list); @@ -959,10 +992,13 @@ int usb_lowlevel_init(int index, void **controller) cmd |= CMD_RUN; ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); +#ifndef CONFIG_USB_EHCI_FARADAY /* take control over the ports */ cmd = ehci_readl(&ehcic[index].hcor->or_configflag); cmd |= FLAG_CF; ehci_writel(&ehcic[index].hcor->or_configflag, cmd); +#endif + /* unblock posted write */ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); mdelay(5); @@ -1144,6 +1180,16 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, *buf = buffer + i * elementsize; } + flush_dcache_range((uint32_t)buffer, + ALIGN_END_ADDR(char, buffer, + queuesize * elementsize)); + flush_dcache_range((uint32_t)result->first, + ALIGN_END_ADDR(struct QH, result->first, + queuesize)); + flush_dcache_range((uint32_t)result->tds, + ALIGN_END_ADDR(struct qTD, result->tds, + queuesize)); + if (disable_periodic(ctrl) < 0) { debug("FATAL: periodic should never fail, but did"); goto fail3; @@ -1154,6 +1200,11 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, result->last->qh_link = list->qh_link; list->qh_link = (uint32_t)result->first | QH_LINK_TYPE_QH; + flush_dcache_range((uint32_t)result->last, + ALIGN_END_ADDR(struct QH, result->last, 1)); + flush_dcache_range((uint32_t)list, + ALIGN_END_ADDR(struct QH, list, 1)); + if (enable_periodic(ctrl) < 0) { debug("FATAL: periodic should never fail, but did"); goto fail3; @@ -1184,6 +1235,8 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) return NULL; } /* still active */ + invalidate_dcache_range((uint32_t)cur, + ALIGN_END_ADDR(struct QH, cur, 1)); if (cur->qh_overlay.qt_token & 0x80) { debug("Exit poll_int_queue with no completed intr transfer. " "token is %x\n", cur->qh_overlay.qt_token); @@ -1290,6 +1343,9 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return -EINVAL; } + invalidate_dcache_range((uint32_t)buffer, + ALIGN_END_ADDR(char, buffer, length)); + ret = destroy_int_queue(dev, queue); if (ret < 0) return ret; diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 0793f07f24..b10f1590ba 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -572,8 +572,6 @@ static void video_drawchars(int xx, int yy, unsigned char *s, int count) SWAP32((video_font_draw_table32 [bits & 15][3] & eorx) ^ bgx); } - if (cfb_do_flush_cache) - flush_cache((ulong)dest0, 32); dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; s++; } @@ -642,8 +640,6 @@ static void video_invertchar(int xx, int yy) for (x = firstx; x < lastx; x++) { u8 *dest = (u8 *)(video_fb_address) + x + y; *dest = ~*dest; - if (cfb_do_flush_cache) - flush_cache((ulong)dest, 4); } } } @@ -687,6 +683,8 @@ void console_cursor(int state) } cursor_state = state; } + if (cfb_do_flush_cache) + flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); } #endif @@ -739,8 +737,6 @@ static void console_clear_line(int line, int begin, int end) memsetl(offset + i * VIDEO_LINE_LEN, size, bgx); } #endif - if (cfb_do_flush_cache) - flush_cache((ulong)CONSOLE_ROW_FIRST, CONSOLE_SIZE); } static void console_scrollup(void) @@ -1146,6 +1142,8 @@ void video_putc(const char c) #else parse_putc(c); #endif + if (cfb_do_flush_cache) + flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); } void video_puts(const char *s) @@ -1799,6 +1797,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y) } #endif + if (cfb_do_flush_cache) + flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); return (0); } #endif @@ -2209,6 +2209,9 @@ static int video_init(void) console_col = 0; console_row = 0; + if (cfb_do_flush_cache) + flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); + return 0; } diff --git a/examples/standalone/mem_to_mem_idma2intr.c b/examples/standalone/mem_to_mem_idma2intr.c index e466c904a7..215dc22033 100644 --- a/examples/standalone/mem_to_mem_idma2intr.c +++ b/examples/standalone/mem_to_mem_idma2intr.c @@ -309,7 +309,8 @@ int idma_init (void) memaddr = dpalloc (sizeof (pram_idma_t), 64); - *(volatile ushort *) &immap->im_dprambase[PROFF_IDMA2_BASE] = memaddr; + *(volatile u16 *)&immap->im_dprambase16 + [PROFF_IDMA2_BASE / sizeof(u16)] = memaddr; piptr = (volatile pram_idma_t *) ((uint) (immap) + memaddr); piptr->pi_resv1 = 0; /* manual says: clear it */ diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c index db49052b38..6fcba047f9 100644 --- a/fs/yaffs2/yaffs_mtdif.c +++ b/fs/yaffs2/yaffs_mtdif.c @@ -70,22 +70,22 @@ int nandmtd_WriteChunkToNAND(struct yaffs_dev *dev, int chunkInNAND, u8 spareAsBytes[8]; /* OOB */ if (data && !spare) - retval = mtd->write(mtd, addr, dev->data_bytes_per_chunk, + retval = mtd_write(mtd, addr, dev->data_bytes_per_chunk, &dummy, data); else if (spare) { if (dev->param.use_nand_ecc) { translate_spare2oob(spare, spareAsBytes); - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = 8; /* temp hack */ } else { - ops.mode = MTD_OOB_RAW; + ops.mode = MTD_OPS_RAW; ops.ooblen = YAFFS_BYTES_PER_SPARE; } ops.len = data ? dev->data_bytes_per_chunk : ops.ooblen; ops.datbuf = (u8 *)data; ops.ooboffs = 0; ops.oobbuf = spareAsBytes; - retval = mtd->write_oob(mtd, addr, &ops); + retval = mtd_write_oob(mtd, addr, &ops); } if (retval == 0) @@ -106,21 +106,21 @@ int nandmtd_ReadChunkFromNAND(struct yaffs_dev *dev, int chunkInNAND, u8 *data, u8 spareAsBytes[8]; /* OOB */ if (data && !spare) - retval = mtd->read(mtd, addr, dev->data_bytes_per_chunk, + retval = mtd_read(mtd, addr, dev->data_bytes_per_chunk, &dummy, data); else if (spare) { if (dev->param.use_nand_ecc) { - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = 8; /* temp hack */ } else { - ops.mode = MTD_OOB_RAW; + ops.mode = MTD_OPS_RAW; ops.ooblen = YAFFS_BYTES_PER_SPARE; } ops.len = data ? dev->data_bytes_per_chunk : ops.ooblen; ops.datbuf = data; ops.ooboffs = 0; ops.oobbuf = spareAsBytes; - retval = mtd->read_oob(mtd, addr, &ops); + retval = mtd_read_oob(mtd, addr, &ops); if (dev->param.use_nand_ecc) translate_oob2spare(spare, spareAsBytes); } @@ -151,7 +151,7 @@ int nandmtd_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) /* Todo finish off the ei if required */ - retval = mtd->erase(mtd, &ei); + retval = mtd_erase(mtd, &ei); if (retval == 0) return YAFFS_OK; diff --git a/fs/yaffs2/yaffs_mtdif2.c b/fs/yaffs2/yaffs_mtdif2.c index 8135bcc0fe..234cb706df 100644 --- a/fs/yaffs2/yaffs_mtdif2.c +++ b/fs/yaffs2/yaffs_mtdif2.c @@ -77,13 +77,13 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); } - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; ops.len = dev->param.total_bytes_per_chunk; ops.ooboffs = 0; ops.datbuf = (u8 *) data; ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr; - retval = mtd->write_oob(mtd, addr, &ops); + retval = mtd_write_oob(mtd, addr, &ops); if (retval == 0) return YAFFS_OK; @@ -121,16 +121,16 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, } if (dev->param.inband_tags || (data && !tags)) - retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, + retval = mtd_read(mtd, addr, dev->param.total_bytes_per_chunk, &dummy, data); else if (tags) { - ops.mode = MTD_OOB_AUTO; + ops.mode = MTD_OPS_AUTO_OOB; ops.ooblen = packed_tags_size; ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; ops.ooboffs = 0; ops.datbuf = data; ops.oobbuf = local_spare; - retval = mtd->read_oob(mtd, addr, &ops); + retval = mtd_read_oob(mtd, addr, &ops); } if (dev->param.inband_tags) { @@ -179,7 +179,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_dev *dev, int blockNo) "nandmtd2_MarkNANDBlockBad %d", blockNo); retval = - mtd->block_markbad(mtd, + mtd_block_markbad(mtd, blockNo * dev->param.chunks_per_block * dev->data_bytes_per_chunk); @@ -198,7 +198,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_dev *dev, int blockNo, yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_QueryNANDBlock %d", blockNo); retval = - mtd->block_isbad(mtd, + mtd_block_isbad(mtd, blockNo * dev->param.chunks_per_block * dev->data_bytes_per_chunk); diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 5416f468b0..3e9ca1182d 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -68,9 +68,6 @@ typedef struct global_data { unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ - /* TODO: is this the same as relocaddr, or something else? */ - unsigned long dest_addr; /* Post-relocation address of U-Boot */ - unsigned long dest_addr_sp; unsigned long ram_top; /* Top address of RAM used by U-Boot */ unsigned long relocaddr; /* Start address of U-Boot in RAM */ diff --git a/include/bootstage.h b/include/bootstage.h index 6dc0422bac..ef07a87e8d 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -37,6 +37,24 @@ enum bootstage_flags { BOOTSTAGEF_ALLOC = 1 << 1, /* Allocate an id */ }; +/* bootstate sub-IDs used for kernel and ramdisk ranges */ +enum { + BOOTSTAGE_SUB_FORMAT, + BOOTSTAGE_SUB_FORMAT_OK, + BOOTSTAGE_SUB_NO_UNIT_NAME, + BOOTSTAGE_SUB_UNIT_NAME, + BOOTSTAGE_SUB_SUBNODE, + + BOOTSTAGE_SUB_CHECK, + BOOTSTAGE_SUB_HASH = 5, + BOOTSTAGE_SUB_CHECK_ARCH = 5, + BOOTSTAGE_SUB_CHECK_ALL, + BOOTSTAGE_SUB_GET_DATA, + BOOTSTAGE_SUB_CHECK_ALL_OK = 7, + BOOTSTAGE_SUB_GET_DATA_OK, + BOOTSTAGE_SUB_LOAD, +}; + /* * A list of boot stages that we know about. Each of these indicates the * state that we are at, and the action that we are about to perform. For @@ -137,43 +155,24 @@ enum bootstage_id { BOOTSTAGE_ID_NET_DONE_ERR, BOOTSTAGE_ID_NET_DONE, + BOOTSTAGE_ID_FIT_FDT_START = 90, /* * Boot stages related to loading a FIT image. Some of these are a * bit wonky. */ - BOOTSTAGE_ID_FIT_FORMAT = 100, - BOOTSTAGE_ID_FIT_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_UNIT_NAME, - BOOTSTAGE_ID_FIT_CONFIG, - BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE, - BOOTSTAGE_ID_FIT_CHECK_HASH = 104, - - BOOTSTAGE_ID_FIT_CHECK_ARCH, - BOOTSTAGE_ID_FIT_CHECK_KERNEL, - BOOTSTAGE_ID_FIT_CHECKED, - - BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR = 107, - BOOTSTAGE_ID_FIT_KERNEL_INFO, + BOOTSTAGE_ID_FIT_KERNEL_START = 100, + + BOOTSTAGE_ID_FIT_CONFIG = 110, BOOTSTAGE_ID_FIT_TYPE, + BOOTSTAGE_ID_FIT_KERNEL_INFO, BOOTSTAGE_ID_FIT_COMPRESSION, BOOTSTAGE_ID_FIT_OS, BOOTSTAGE_ID_FIT_LOADADDR, BOOTSTAGE_ID_OVERWRITTEN, - BOOTSTAGE_ID_FIT_RD_FORMAT = 120, - BOOTSTAGE_ID_FIT_RD_FORMAT_OK, - BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_UNIT_NAME, - BOOTSTAGE_ID_FIT_RD_SUBNODE, - - BOOTSTAGE_ID_FIT_RD_CHECK, - BOOTSTAGE_ID_FIT_RD_HASH = 125, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL, - BOOTSTAGE_ID_FIT_RD_GET_DATA, - BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK = 127, - BOOTSTAGE_ID_FIT_RD_GET_DATA_OK, - BOOTSTAGE_ID_FIT_RD_LOAD, + /* Next 10 IDs used by BOOTSTAGE_SUB_... */ + BOOTSTAGE_ID_FIT_RD_START = 120, /* Ramdisk stages */ BOOTSTAGE_ID_IDE_FIT_READ = 140, BOOTSTAGE_ID_IDE_FIT_READ_OK, diff --git a/include/common.h b/include/common.h index e682bd8237..126891d658 100644 --- a/include/common.h +++ b/include/common.h @@ -310,9 +310,6 @@ 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); -#ifdef CONFIG_MENU -int abortboot(int bootdelay); -#endif extern char console_buffer[]; /* arch/$(ARCH)/lib/board.c */ diff --git a/include/commproc.h b/include/commproc.h index 7ca28c8369..6959905efe 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -127,6 +127,7 @@ typedef struct cpm_buf_desc { */ #define PROFF_SCC1 ((uint)0x0000) #define PROFF_IIC ((uint)0x0080) +#define PROFF_REVNUM ((uint)0x00b0) #define PROFF_SCC2 ((uint)0x0100) #define PROFF_SPI ((uint)0x0180) #define PROFF_SCC3 ((uint)0x0200) diff --git a/include/configs/A3000.h b/include/configs/A3000.h index b85244a89a..d506a558c0 100644 --- a/include/configs/A3000.h +++ b/include/configs/A3000.h @@ -96,6 +96,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ diff --git a/include/configs/APC405.h b/include/configs/APC405.h index 9a65cbced0..1e392290d7 100644 --- a/include/configs/APC405.h +++ b/include/configs/APC405.h @@ -218,6 +218,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/AR405.h b/include/configs/AR405.h index 99944766dd..7337f5374b 100644 --- a/include/configs/AR405.h +++ b/include/configs/AR405.h @@ -157,6 +157,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/ASH405.h b/include/configs/ASH405.h index 09aa763c11..35c37731cb 100644 --- a/include/configs/ASH405.h +++ b/include/configs/ASH405.h @@ -172,6 +172,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_HOST /* select pci host function */ #undef CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h index 1c9d08e256..c15bbd856c 100644 --- a/include/configs/B4860QDS.h +++ b/include/configs/B4860QDS.h @@ -620,6 +620,7 @@ unsigned long get_board_ddr_clk(void); #endif #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_NET_MULTI #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_E1000 diff --git a/include/configs/BSC9132QDS.h b/include/configs/BSC9132QDS.h index 431c686967..9d15d0eb88 100644 --- a/include/configs/BSC9132QDS.h +++ b/include/configs/BSC9132QDS.h @@ -73,6 +73,7 @@ #if defined(CONFIG_PCI) #define CONFIG_PCIE1 /* PCIE controler 1 (slot 1) */ #define CONFIG_FSL_PCI_INIT /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT /* enable 64-bit PCI resources */ diff --git a/include/configs/CATcenter.h b/include/configs/CATcenter.h index 1e3a5640eb..7017f8c19b 100644 --- a/include/configs/CATcenter.h +++ b/include/configs/CATcenter.h @@ -327,6 +327,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #undef CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPC45.h b/include/configs/CPC45.h index e102c365c4..c7904a1880 100644 --- a/include/configs/CPC45.h +++ b/include/configs/CPC45.h @@ -450,6 +450,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_SYS_EARLY_PCI_INIT #undef CONFIG_PCI_PNP #undef CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/CPCI2DP.h b/include/configs/CPCI2DP.h index 11cf58b146..bbd93ac502 100644 --- a/include/configs/CPCI2DP.h +++ b/include/configs/CPCI2DP.h @@ -146,6 +146,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPCI405.h b/include/configs/CPCI405.h index e3e5ebc53c..36476e0135 100644 --- a/include/configs/CPCI405.h +++ b/include/configs/CPCI405.h @@ -155,6 +155,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h index c4fff486d8..4c12c85c2b 100644 --- a/include/configs/CPCI4052.h +++ b/include/configs/CPCI4052.h @@ -176,6 +176,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPCI405AB.h b/include/configs/CPCI405AB.h index 9122cbd877..96b6c0ab66 100644 --- a/include/configs/CPCI405AB.h +++ b/include/configs/CPCI405AB.h @@ -173,6 +173,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPCI405DT.h b/include/configs/CPCI405DT.h index f778af7e36..c4cc5fd737 100644 --- a/include/configs/CPCI405DT.h +++ b/include/configs/CPCI405DT.h @@ -177,6 +177,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPCIISER4.h b/include/configs/CPCIISER4.h index 35daed05ef..78c66c76a7 100644 --- a/include/configs/CPCIISER4.h +++ b/include/configs/CPCIISER4.h @@ -140,6 +140,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/CPU87.h b/include/configs/CPU87.h index aa5ce29585..3e9c21cc9d 100644 --- a/include/configs/CPU87.h +++ b/include/configs/CPU87.h @@ -192,6 +192,7 @@ #define CONFIG_CMD_I2C #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_CMD_PCI #endif diff --git a/include/configs/CU824.h b/include/configs/CU824.h index a3ceed17f1..6632196ad9 100644 --- a/include/configs/CU824.h +++ b/include/configs/CU824.h @@ -288,6 +288,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/DU440.h b/include/configs/DU440.h index bbe271303a..4970ea657b 100644 --- a/include/configs/DU440.h +++ b/include/configs/DU440.h @@ -357,6 +357,7 @@ int du440_phy_addr(int devnum); * PCI stuff */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE*/ diff --git a/include/configs/ELPPC.h b/include/configs/ELPPC.h index 220372ccd8..d10f4c18a7 100644 --- a/include/configs/ELPPC.h +++ b/include/configs/ELPPC.h @@ -242,6 +242,7 @@ * PCI stuff */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* pci plug-and-play */ #define CONFIG_PCI_HOST PCI_HOST_AUTO #undef CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/G2000.h b/include/configs/G2000.h index 08ba8404bf..b6769ae68d 100644 --- a/include/configs/G2000.h +++ b/include/configs/G2000.h @@ -216,6 +216,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_HOST /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/HH405.h b/include/configs/HH405.h index 444413d8d6..d65377f580 100644 --- a/include/configs/HH405.h +++ b/include/configs/HH405.h @@ -231,6 +231,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_HOST /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/HIDDEN_DRAGON.h b/include/configs/HIDDEN_DRAGON.h index a62ef6364b..dbad1fd6af 100644 --- a/include/configs/HIDDEN_DRAGON.h +++ b/include/configs/HIDDEN_DRAGON.h @@ -93,6 +93,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/HWW1U1A.h b/include/configs/HWW1U1A.h index 791763aaaf..2b72a33487 100644 --- a/include/configs/HWW1U1A.h +++ b/include/configs/HWW1U1A.h @@ -188,6 +188,7 @@ #define CONFIG_PCI_PNP /* Scan PCI busses */ #define CONFIG_CMD_PCI /* Enable the "pci" command */ #define CONFIG_FSL_PCI_INIT /* Common FreeScale PCI initialization */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET /* We have PCI-E reset errata */ #define CONFIG_SYS_PCI_64BIT /* PCI resources are 64-bit */ #define CONFIG_PCI_SCAN_SHOW /* Display PCI scan during boot */ diff --git a/include/configs/JSE.h b/include/configs/JSE.h index e0a0d8e46b..6ce789d7fa 100644 --- a/include/configs/JSE.h +++ b/include/configs/JSE.h @@ -226,6 +226,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #undef CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/KAREF.h b/include/configs/KAREF.h index 546e28b8fa..8d5e8ff653 100644 --- a/include/configs/KAREF.h +++ b/include/configs/KAREF.h @@ -268,6 +268,7 @@ *----------------------------------------------------------------------*/ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices */ #define CONFIG_SYS_PCI_TARGBASE (CONFIG_SYS_PCI_MEMBASE) diff --git a/include/configs/MERGERBOX.h b/include/configs/MERGERBOX.h index 30fb6c2ffd..2496639512 100644 --- a/include/configs/MERGERBOX.h +++ b/include/configs/MERGERBOX.h @@ -36,6 +36,7 @@ #define CONFIG_SYS_TEXT_BASE 0xFC000000 #define CONFIG_PCI 1 +#define CONFIG_PCI_INDIRECT_BRIDGE 1 #define CONFIG_MASK_AER_AO #define CONFIG_DISPLAY_AER_FULL diff --git a/include/configs/METROBOX.h b/include/configs/METROBOX.h index 286f8690a8..d1ef559cf4 100644 --- a/include/configs/METROBOX.h +++ b/include/configs/METROBOX.h @@ -333,6 +333,7 @@ *----------------------------------------------------------------------*/ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices */ #define CONFIG_SYS_PCI_TARGBASE (CONFIG_SYS_PCI_MEMBASE) diff --git a/include/configs/MIP405.h b/include/configs/MIP405.h index 979495a72c..0d023ab9fb 100644 --- a/include/configs/MIP405.h +++ b/include/configs/MIP405.h @@ -206,6 +206,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* configure as pci-host */ #define CONFIG_PCI_PNP /* pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/MOUSSE.h b/include/configs/MOUSSE.h index 1391ce517d..b3dbd6fae5 100644 --- a/include/configs/MOUSSE.h +++ b/include/configs/MOUSSE.h @@ -330,6 +330,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/MPC8260ADS.h b/include/configs/MPC8260ADS.h index c4c41c77de..c312b7781d 100644 --- a/include/configs/MPC8260ADS.h +++ b/include/configs/MPC8260ADS.h @@ -195,6 +195,7 @@ /*PCI*/ #if CONFIG_ADSTYPE >= CONFIG_SYS_PQ2FADS #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #define CONFIG_PCI_BOOTDELAY 0 #define CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/MPC8266ADS.h b/include/configs/MPC8266ADS.h index 0474140fb3..c5aa58650e 100644 --- a/include/configs/MPC8266ADS.h +++ b/include/configs/MPC8266ADS.h @@ -137,6 +137,7 @@ /* PCI */ #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #define CONFIG_PCI_BOOTDELAY 0 #undef CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/MPC8308RDB.h b/include/configs/MPC8308RDB.h index 95a1885ace..f10555ce01 100644 --- a/include/configs/MPC8308RDB.h +++ b/include/configs/MPC8308RDB.h @@ -402,6 +402,7 @@ #define CONFIG_SYS_SCCR_PCIEXP1CM 1 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCIE #define CONFIG_PCI_PNP /* do pci plug-and-play */ diff --git a/include/configs/MPC8313ERDB.h b/include/configs/MPC8313ERDB.h index c28dfe0068..1d753e76b9 100644 --- a/include/configs/MPC8313ERDB.h +++ b/include/configs/MPC8313ERDB.h @@ -76,6 +76,7 @@ #endif #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_FSL_ELBC 1 #define CONFIG_MISC_INIT_R diff --git a/include/configs/MPC8315ERDB.h b/include/configs/MPC8315ERDB.h index 767b9763e4..ee806c4403 100644 --- a/include/configs/MPC8315ERDB.h +++ b/include/configs/MPC8315ERDB.h @@ -405,6 +405,7 @@ #define CONFIG_SYS_PCIE2_IO_SIZE 0x00800000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCIE #define CONFIG_PCI_PNP /* do pci plug-and-play */ diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h index 8d5ed0f7ab..ac4c253968 100644 --- a/include/configs/MPC8323ERDB.h +++ b/include/configs/MPC8323ERDB.h @@ -264,6 +264,7 @@ #define CONFIG_SYS_PCI1_IO_SIZE 0x04000000 /* 64M */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_SKIP_HOST_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ diff --git a/include/configs/MPC832XEMDS.h b/include/configs/MPC832XEMDS.h index f592d3a3a4..7c31f47953 100644 --- a/include/configs/MPC832XEMDS.h +++ b/include/configs/MPC832XEMDS.h @@ -360,6 +360,7 @@ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_83XX_PCI_STREAMING diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h index e5529c7007..212089c238 100644 --- a/include/configs/MPC8349EMDS.h +++ b/include/configs/MPC8349EMDS.h @@ -666,6 +666,7 @@ /* PCI @ 0x80000000 */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_IBAT1L (CONFIG_SYS_PCI1_MEM_BASE \ | BATL_PP_RW \ | BATL_MEMCOHERENCE) diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h index 2c3f1f62a6..1130b59a21 100644 --- a/include/configs/MPC8349ITX.h +++ b/include/configs/MPC8349ITX.h @@ -393,6 +393,7 @@ boards, we say we have two, but don't display a message if we find only one. */ * PCI */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_MPC83XX_PCI2 diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h index a1fbd5e4a4..a71ac2bd35 100644 --- a/include/configs/MPC8360EMDS.h +++ b/include/configs/MPC8360EMDS.h @@ -458,6 +458,7 @@ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_83XX_PCI_STREAMING diff --git a/include/configs/MPC8360ERDK.h b/include/configs/MPC8360ERDK.h index fc0095281a..fcca5424e3 100644 --- a/include/configs/MPC8360ERDK.h +++ b/include/configs/MPC8360ERDK.h @@ -314,6 +314,7 @@ #define CONFIG_SYS_PCI1_IO_SIZE 0x100000 /* 1M */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h index 82436618be..480468f2d7 100644 --- a/include/configs/MPC837XEMDS.h +++ b/include/configs/MPC837XEMDS.h @@ -395,6 +395,7 @@ #define CONFIG_SYS_PCIE2_IO_SIZE 0x00800000 #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #ifndef __ASSEMBLY__ extern int board_pci_host_broken(void); #endif diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h index 9ad7e3a90f..d5c9d059eb 100644 --- a/include/configs/MPC837XERDB.h +++ b/include/configs/MPC837XERDB.h @@ -421,6 +421,7 @@ #define CONFIG_SYS_PCIE2_IO_SIZE 0x00800000 #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #undef CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/MPC8536DS.h b/include/configs/MPC8536DS.h index bcd77b608f..cc2b7c332b 100644 --- a/include/configs/MPC8536DS.h +++ b/include/configs/MPC8536DS.h @@ -84,6 +84,7 @@ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCIE3 1 /* PCIE controler 3 (ULI bridge) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ diff --git a/include/configs/MPC8540ADS.h b/include/configs/MPC8540ADS.h index a0fe15e86e..6cb00ee664 100644 --- a/include/configs/MPC8540ADS.h +++ b/include/configs/MPC8540ADS.h @@ -52,6 +52,7 @@ #endif #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ #define CONFIG_ENV_OVERWRITE diff --git a/include/configs/MPC8541CDS.h b/include/configs/MPC8541CDS.h index a6bea153d7..d0e6ca65bf 100644 --- a/include/configs/MPC8541CDS.h +++ b/include/configs/MPC8541CDS.h @@ -40,6 +40,7 @@ #define CONFIG_SYS_TEXT_BASE 0xfff80000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ #define CONFIG_ENV_OVERWRITE diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h index d5f3c5f56f..09d0835c61 100644 --- a/include/configs/MPC8544DS.h +++ b/include/configs/MPC8544DS.h @@ -44,6 +44,7 @@ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCIE3 1 /* PCIE controler 3 (ULI bridge) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h index 0e22cc7e14..d070f6adc3 100644 --- a/include/configs/MPC8548CDS.h +++ b/include/configs/MPC8548CDS.h @@ -52,6 +52,7 @@ #define CONFIG_PCIE1 /* PCIE controler 1 (slot 1) */ #undef CONFIG_PCI2 #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ diff --git a/include/configs/MPC8555CDS.h b/include/configs/MPC8555CDS.h index 266cb54c92..483556b31b 100644 --- a/include/configs/MPC8555CDS.h +++ b/include/configs/MPC8555CDS.h @@ -40,6 +40,7 @@ #define CONFIG_SYS_TEXT_BASE 0xfff80000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ #define CONFIG_ENV_OVERWRITE diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h index 35d15f4271..525e88fa1b 100644 --- a/include/configs/MPC8560ADS.h +++ b/include/configs/MPC8560ADS.h @@ -49,6 +49,7 @@ #define CONFIG_SYS_TEXT_BASE 0xfff80000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ #undef CONFIG_ETHER_ON_FCC /* cpm FCC ethernet support */ diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h index 5d69fb66d9..f1bfdcbd2c 100644 --- a/include/configs/MPC8568MDS.h +++ b/include/configs/MPC8568MDS.h @@ -42,6 +42,7 @@ #define CONFIG_PCI1 1 /* PCI controller */ #define CONFIG_PCIE1 1 /* PCIE controller */ #define CONFIG_FSL_PCI_INIT 1 /* use common fsl pci init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ diff --git a/include/configs/MPC8569MDS.h b/include/configs/MPC8569MDS.h index acd3276e98..c54755fab8 100644 --- a/include/configs/MPC8569MDS.h +++ b/include/configs/MPC8569MDS.h @@ -41,6 +41,7 @@ #define CONFIG_PCI 1 /* Disable PCI/PCIE */ #define CONFIG_PCIE1 1 /* PCIE controller */ #define CONFIG_FSL_PCI_INIT 1 /* use common fsl pci init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_QE /* Enable QE */ diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index d233365b7d..25303c4f65 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -71,6 +71,7 @@ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCIE3 1 /* PCIE controler 3 (ULI bridge) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index c61982745f..f791e7682e 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -51,6 +51,7 @@ #define CONFIG_PCIE1 1 /* PCIe 1 connected to ULI bridge */ #define CONFIG_PCIE2 1 /* PCIe 2 connected to slot */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 264309772a..4a3ca017e8 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -510,6 +510,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); * BAT2 Rapidio Memory */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_DBAT2L (BAT_PHYS_ADDR(CONFIG_SYS_PCIE1_MEM_PHYS_LOW, \ CONFIG_SYS_PCIE1_MEM_PHYS_HIGH) \ | BATL_PP_RW | BATL_CACHEINHIBIT \ diff --git a/include/configs/MUSENKI.h b/include/configs/MUSENKI.h index 84a167d2a7..8b0415158a 100644 --- a/include/configs/MUSENKI.h +++ b/include/configs/MUSENKI.h @@ -87,6 +87,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/MVBLM7.h b/include/configs/MVBLM7.h index a9c00acc9a..afd4c0356d 100644 --- a/include/configs/MVBLM7.h +++ b/include/configs/MVBLM7.h @@ -42,6 +42,7 @@ #define CONFIG_SYS_IMMR 0xE0000000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_SKIP_HOST_BRIDGE #define CONFIG_HARD_I2C #define CONFIG_TSEC_ENET diff --git a/include/configs/MVBLUE.h b/include/configs/MVBLUE.h index 52d172925b..21f286e0fb 100644 --- a/include/configs/MVBLUE.h +++ b/include/configs/MVBLUE.h @@ -154,6 +154,7 @@ */ #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/OCRTC.h b/include/configs/OCRTC.h index 47110aff24..4a93417655 100644 --- a/include/configs/OCRTC.h +++ b/include/configs/OCRTC.h @@ -136,6 +136,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/ORSG.h b/include/configs/ORSG.h index 9f754c2a81..cd1f4254ad 100644 --- a/include/configs/ORSG.h +++ b/include/configs/ORSG.h @@ -134,6 +134,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_ADAPTER /* select pci adapter */ #undef CONFIG_PCI_PNP /* no pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h index 437ee6ee6b..5185597905 100644 --- a/include/configs/P1010RDB.h +++ b/include/configs/P1010RDB.h @@ -90,6 +90,7 @@ #define CONFIG_PCIE1 /* PCIE controler 1 (slot 1) */ #define CONFIG_PCIE2 /* PCIE controler 2 (slot 2) */ #define CONFIG_FSL_PCI_INIT /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT /* enable 64-bit PCI resources */ diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h index 8b13b107e2..9c27182dc7 100644 --- a/include/configs/P1022DS.h +++ b/include/configs/P1022DS.h @@ -316,7 +316,6 @@ #define CONFIG_SYS_HUSH_PARSER /* Video */ -#define CONFIG_FSL_DIU_FB #ifdef CONFIG_FSL_DIU_FB #define CONFIG_SYS_DIU_ADDR (CONFIG_SYS_CCSRBAR + 0x10000) @@ -336,7 +335,6 @@ #endif #ifndef CONFIG_FSL_DIU_FB -#define CONFIG_ATI #endif #ifdef CONFIG_ATI @@ -458,6 +456,7 @@ #define CONFIG_SYS_PCIE3_IO_SIZE 0x00010000 /* 64k */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_E1000 /* Define e1000 pci Ethernet card */ diff --git a/include/configs/P1023RDS.h b/include/configs/P1023RDS.h index 878bd5fa5e..4943d7c8fe 100644 --- a/include/configs/P1023RDS.h +++ b/include/configs/P1023RDS.h @@ -73,6 +73,7 @@ #define CONFIG_PCIE2 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCIE3 /* PCIE controler 3 (slot 3) */ #define CONFIG_FSL_PCI_INIT /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT /* enable 64-bit PCI resources */ #define CONFIG_FSL_LAW /* Use common FSL init code */ diff --git a/include/configs/P1_P2_RDB.h b/include/configs/P1_P2_RDB.h index a57d9dd26e..6ce4cbef9c 100644 --- a/include/configs/P1_P2_RDB.h +++ b/include/configs/P1_P2_RDB.h @@ -94,6 +94,7 @@ #define CONFIG_PCIE1 1 /* PCIE controler 1 (slot 1) */ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #endif /* #if defined(CONFIG_PCI) */ diff --git a/include/configs/P2020COME.h b/include/configs/P2020COME.h index c75f86cb84..05a75d8a76 100644 --- a/include/configs/P2020COME.h +++ b/include/configs/P2020COME.h @@ -58,6 +58,7 @@ #define CONFIG_PCIE3 1 /* PCIE controller 3 (slot 3) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #endif /* #if defined(CONFIG_PCI) */ diff --git a/include/configs/P2020DS.h b/include/configs/P2020DS.h index a975ee10ed..229117c18d 100644 --- a/include/configs/P2020DS.h +++ b/include/configs/P2020DS.h @@ -73,6 +73,7 @@ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_PCIE3 1 /* PCIE controler 3 (ULI bridge) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h index bbc53ceafd..9cd3a7cb34 100644 --- a/include/configs/P2041RDB.h +++ b/include/configs/P2041RDB.h @@ -560,6 +560,7 @@ unsigned long get_board_sys_clk(unsigned long dummy); #endif #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_E1000 diff --git a/include/configs/PCI405.h b/include/configs/PCI405.h index 119819e371..c3cacefed8 100644 --- a/include/configs/PCI405.h +++ b/include/configs/PCI405.h @@ -141,6 +141,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_ADAPTER /* select pci host function */ #undef CONFIG_PCI_PNP /* no pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h index 713ea12ee5..3757af07a0 100644 --- a/include/configs/PIP405.h +++ b/include/configs/PIP405.h @@ -199,6 +199,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* configure as pci-host */ #define CONFIG_PCI_PNP /* pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/PLU405.h b/include/configs/PLU405.h index 1ee0c48fa1..1745eb39fc 100644 --- a/include/configs/PLU405.h +++ b/include/configs/PLU405.h @@ -192,6 +192,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/PM826.h b/include/configs/PM826.h index fbcf8e5e22..faadfe43c1 100644 --- a/include/configs/PM826.h +++ b/include/configs/PM826.h @@ -176,6 +176,7 @@ #define CONFIG_CMD_SNTP #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_CMD_PCI #endif diff --git a/include/configs/PM828.h b/include/configs/PM828.h index c37aafdd47..f563fbe335 100644 --- a/include/configs/PM828.h +++ b/include/configs/PM828.h @@ -176,6 +176,7 @@ #define CONFIG_CMD_SNTP #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_CMD_PCI #endif diff --git a/include/configs/PMC405.h b/include/configs/PMC405.h index 8235b857d3..d97acecc44 100644 --- a/include/configs/PMC405.h +++ b/include/configs/PMC405.h @@ -163,6 +163,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/PMC405DE.h b/include/configs/PMC405DE.h index 992443a8e2..a427551281 100644 --- a/include/configs/PMC405DE.h +++ b/include/configs/PMC405DE.h @@ -142,6 +142,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* do (not) pci plug-and-play */ diff --git a/include/configs/PMC440.h b/include/configs/PMC440.h index 3837b8f139..40c18274f9 100644 --- a/include/configs/PMC440.h +++ b/include/configs/PMC440.h @@ -419,6 +419,7 @@ *----------------------------------------------------------------------*/ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 0 /* to avoid problems with PNP */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/PN62.h b/include/configs/PN62.h index 93876b1317..e2f96aa4ac 100644 --- a/include/configs/PN62.h +++ b/include/configs/PN62.h @@ -122,6 +122,7 @@ * PCI stuff */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* we need Plug 'n Play */ #if 0 #define CONFIG_PCI_SCAN_SHOW /* show PCI auto-scan at boot */ diff --git a/include/configs/PPChameleonEVB.h b/include/configs/PPChameleonEVB.h index 27a12b310b..210bc30ca8 100644 --- a/include/configs/PPChameleonEVB.h +++ b/include/configs/PPChameleonEVB.h @@ -324,6 +324,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #undef CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/SIMPC8313.h b/include/configs/SIMPC8313.h index c0ffb33129..318c4c5d51 100644 --- a/include/configs/SIMPC8313.h +++ b/include/configs/SIMPC8313.h @@ -52,6 +52,7 @@ #endif #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_FSL_ELBC 1 #define CONFIG_MISC_INIT_R diff --git a/include/configs/Sandpoint8240.h b/include/configs/Sandpoint8240.h index f54fcb33e5..fa456ed79f 100644 --- a/include/configs/Sandpoint8240.h +++ b/include/configs/Sandpoint8240.h @@ -127,6 +127,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/Sandpoint8245.h b/include/configs/Sandpoint8245.h index 84e4891dc9..cdc51a5016 100644 --- a/include/configs/Sandpoint8245.h +++ b/include/configs/Sandpoint8245.h @@ -95,6 +95,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/TQM8272.h b/include/configs/TQM8272.h index be977f1d76..3b3f9e6302 100644 --- a/include/configs/TQM8272.h +++ b/include/configs/TQM8272.h @@ -443,6 +443,7 @@ #define CONFIG_PCI #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */ #define CONFIG_PCI_PNP #define CONFIG_EEPRO100 diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h index 07384234c9..966a6e3da9 100644 --- a/include/configs/TQM834x.h +++ b/include/configs/TQM834x.h @@ -442,6 +442,7 @@ /* PCI */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_IBAT3L (CONFIG_SYS_PCI1_MEM_BASE \ | BATL_PP_RW \ | BATL_MEMCOHERENCE) diff --git a/include/configs/VOH405.h b/include/configs/VOH405.h index f1032f0f3f..8f0c4b6241 100644 --- a/include/configs/VOH405.h +++ b/include/configs/VOH405.h @@ -181,6 +181,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_HOST /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/W7OLMC.h b/include/configs/W7OLMC.h index 462b155a30..710812fc9f 100644 --- a/include/configs/W7OLMC.h +++ b/include/configs/W7OLMC.h @@ -154,6 +154,7 @@ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/W7OLMG.h b/include/configs/W7OLMG.h index f28f3e4f9a..f88dfe4cde 100644 --- a/include/configs/W7OLMG.h +++ b/include/configs/W7OLMG.h @@ -161,6 +161,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_AUTO /* select pci host function */ #define CONFIG_PCI_PNP /* pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/WUH405.h b/include/configs/WUH405.h index 5def36ad0c..0c78acac80 100644 --- a/include/configs/WUH405.h +++ b/include/configs/WUH405.h @@ -169,6 +169,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_HOST /* select pci host function */ #undef CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/adp-ag102.h b/include/configs/adp-ag102.h index eea44db356..a6e184961f 100644 --- a/include/configs/adp-ag102.h +++ b/include/configs/adp-ag102.h @@ -143,6 +143,7 @@ */ #define CONFIG_PCI #define CONFIG_FTPCI100 +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_FTPCI100_MEM_BASE 0xa0000000 #define CONFIG_FTPCI100_IO_SIZE FTPCI100_BASE_IO_SIZE(256) /* 256M */ #define CONFIG_FTPCI100_MEM_SIZE FTPCI100_MEM_SIZE(128) /* 128M */ diff --git a/include/configs/alpr.h b/include/configs/alpr.h index 0d53e51b9d..d93d5e204f 100644 --- a/include/configs/alpr.h +++ b/include/configs/alpr.h @@ -287,6 +287,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */ diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index b286ffc8d4..737e19ee6f 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -306,22 +306,44 @@ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK /* - * Place the image at the start of the ROM defined image space and leave - * space for SRAM scratch entries (see arch/arm/include/omap_common.h). + * Place the image at the start of the ROM defined image space. * We limit our size to the ROM-defined downloaded image area, and use the * rest of the space for stack. */ -#define CONFIG_SPL_TEXT_BASE 0x402F0500 +#define CONFIG_SPL_TEXT_BASE 0x402F0400 #define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR -#define CONFIG_SPL_BSS_START_ADDR 0x80000000 +#define CONFIG_SPL_OS_BOOT + +#define CONFIG_SPL_BSS_START_ADDR 0x80a00000 #define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KB */ #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 0x200 /* 256 KB */ #define CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION 1 #define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME "u-boot.img" + +#ifdef CONFIG_SPL_OS_BOOT +/* fat */ +#define CONFIG_SPL_FAT_LOAD_KERNEL_NAME "uImage" +#define CONFIG_SPL_FAT_LOAD_ARGS_NAME "args" +#define CONFIG_SYS_SPL_ARGS_ADDR (PHYS_DRAM_1 + 0x100) + +/* raw mmc */ +#define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR 0x500 /* address 0xa0000 */ +#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR 0x8 /* address 0x1000 */ +#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS 8 /* 4KB */ + +/* nand */ +#define CONFIG_CMD_SPL_NAND_OFS 0x240000 /* end of u-boot */ +#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x280000 +#define CONFIG_CMD_SPL_WRITE_SIZE 0x1000 + +/* spl export command */ +#define CONFIG_CMD_SPL +#endif + #define CONFIG_SPL_MMC_SUPPORT #define CONFIG_SPL_FAT_SUPPORT #define CONFIG_SPL_I2C_SUPPORT @@ -379,7 +401,7 @@ * other needs. */ #define CONFIG_SYS_TEXT_BASE 0x80800000 -#define CONFIG_SYS_SPL_MALLOC_START 0x80208000 +#define CONFIG_SYS_SPL_MALLOC_START 0x80a08000 #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 /* Since SPL did pll and ddr initialization for us, @@ -475,7 +497,8 @@ #define MTDPARTS_DEFAULT "mtdparts=omap2-nand.0:128k(SPL)," \ "128k(SPL.backup1)," \ "128k(SPL.backup2)," \ - "128k(SPL.backup3),1920k(u-boot)," \ + "128k(SPL.backup3),1792k(u-boot)," \ + "128k(u-boot-spl-os)," \ "128k(u-boot-env),5m(kernel),-(rootfs)" #define CONFIG_NAND_OMAP_GPMC #define GPMC_NAND_ECC_LP_x16_LAYOUT 1 diff --git a/include/configs/aria.h b/include/configs/aria.h index 5318aaf99c..bd81053875 100644 --- a/include/configs/aria.h +++ b/include/configs/aria.h @@ -350,6 +350,7 @@ * PCI */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_PCI_MEM_BASE 0xA0000000 #define CONFIG_SYS_PCI_MEM_PHYS CONFIG_SYS_PCI_MEM_BASE diff --git a/include/configs/atc.h b/include/configs/atc.h index 538a167528..57c4b33f1c 100644 --- a/include/configs/atc.h +++ b/include/configs/atc.h @@ -263,6 +263,7 @@ #endif #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #define CONFIG_SYS_PCI_MSTR_IO_BUS 0x00000000 /* PCI base */ diff --git a/include/configs/bamboo.h b/include/configs/bamboo.h index 506a558f14..d36984df2d 100644 --- a/include/configs/bamboo.h +++ b/include/configs/bamboo.h @@ -293,6 +293,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE*/ diff --git a/include/configs/bubinga.h b/include/configs/bubinga.h index da67ae3b5a..35a473a429 100644 --- a/include/configs/bubinga.h +++ b/include/configs/bubinga.h @@ -153,6 +153,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/canyonlands.h b/include/configs/canyonlands.h index acb127c1d1..92106d762d 100644 --- a/include/configs/canyonlands.h +++ b/include/configs/canyonlands.h @@ -496,6 +496,7 @@ *----------------------------------------------------------------------*/ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index be04a7548a..2fefdc80db 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -90,7 +90,8 @@ #endif /* Generic TPM interfaced through LPC bus */ -#define CONFIG_GENERIC_LPC_TPM +#define CONFIG_TPM +#define CONFIG_TPM_TIS_LPC #define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000 /*----------------------------------------------------------------------- diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h index 2e2d439678..66c7b4f95f 100644 --- a/include/configs/corenet_ds.h +++ b/include/configs/corenet_ds.h @@ -564,6 +564,7 @@ #endif #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_E1000 diff --git a/include/configs/csb272.h b/include/configs/csb272.h index f21fa648b1..eec087c0dc 100644 --- a/include/configs/csb272.h +++ b/include/configs/csb272.h @@ -204,6 +204,7 @@ * */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ #define PCI_HOST_FORCE 1 /* configure as pci host */ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ diff --git a/include/configs/csb472.h b/include/configs/csb472.h index aed5fa6a45..f6a456c18f 100644 --- a/include/configs/csb472.h +++ b/include/configs/csb472.h @@ -203,6 +203,7 @@ * */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ #define PCI_HOST_FORCE 1 /* configure as pci host */ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ diff --git a/include/configs/debris.h b/include/configs/debris.h index 32aa4e5065..c40fbd9f8d 100644 --- a/include/configs/debris.h +++ b/include/configs/debris.h @@ -172,6 +172,7 @@ *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP #define CONFIG_EEPRO100 diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h index 788227d79d..3b74d7c31c 100644 --- a/include/configs/devkit8000.h +++ b/include/configs/devkit8000.h @@ -360,6 +360,14 @@ #define CONFIG_CMD_SPL_NAND_OFS (CONFIG_SYS_NAND_SPL_KERNEL_OFFS+\ 0x400000) #define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x280000 + +#define CONFIG_SPL_FAT_LOAD_KERNEL_NAME "uImage" +#define CONFIG_SPL_FAT_LOAD_ARGS_NAME "args" + +#define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR 0x500 /* address 0xa0000 */ +#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR 0x8 /* address 0x1000 */ +#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS 8 /* 4KB */ + #define CONFIG_SYS_SPL_ARGS_ADDR (PHYS_SDRAM_1 + 0x100) #endif /* __CONFIG_H */ diff --git a/include/configs/eXalion.h b/include/configs/eXalion.h index 3238ac7327..a6a0f8bb58 100644 --- a/include/configs/eXalion.h +++ b/include/configs/eXalion.h @@ -180,6 +180,7 @@ * PCI stuff */ #define CONFIG_PCI 1 /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP diff --git a/include/configs/ebony.h b/include/configs/ebony.h index d6b655122a..b05ba08afd 100644 --- a/include/configs/ebony.h +++ b/include/configs/ebony.h @@ -177,6 +177,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */ diff --git a/include/configs/ep82xxm.h b/include/configs/ep82xxm.h index 8d78921f6b..7393f289a7 100644 --- a/include/configs/ep82xxm.h +++ b/include/configs/ep82xxm.h @@ -254,6 +254,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_PCI_BOOTDELAY 0 diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 8a82892f4f..41d6cf9d15 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -142,9 +142,9 @@ /* TPM */ #define CONFIG_TPM #define CONFIG_CMD_TPM -#define CONFIG_INFINEON_TPM_I2C -#define CONFIG_INFINEON_TPM_I2C_BUS 3 -#define CONFIG_INFINEON_TPM_I2C_ADDR 0x20 +#define CONFIG_TPM_TIS_I2C +#define CONFIG_TPM_TIS_I2C_BUS_NUMBER 3 +#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR 0x20 /* MMC SPL */ #define CONFIG_SPL diff --git a/include/configs/gdppc440etx.h b/include/configs/gdppc440etx.h index 9efbb8e34c..7b8bac48ec 100644 --- a/include/configs/gdppc440etx.h +++ b/include/configs/gdppc440etx.h @@ -178,6 +178,7 @@ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup*/ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to \ diff --git a/include/configs/icon.h b/include/configs/icon.h index 2fac0efe13..c2da4cec9a 100644 --- a/include/configs/icon.h +++ b/include/configs/icon.h @@ -234,6 +234,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/igep0033.h b/include/configs/igep0033.h index afbd549997..12f28f82a8 100644 --- a/include/configs/igep0033.h +++ b/include/configs/igep0033.h @@ -215,12 +215,11 @@ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK /* - * Place the image at the start of the ROM defined image space and leave - * space for SRAM scratch entries (see arch/arm/include/omap_common.h). + * Place the image at the start of the ROM defined image space. * We limit our size to the ROM-defined downloaded image area, and use the * rest of the space for stack. */ -#define CONFIG_SPL_TEXT_BASE 0x402F0500 +#define CONFIG_SPL_TEXT_BASE 0x402F0400 #define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR diff --git a/include/configs/intip.h b/include/configs/intip.h index 33364a843e..ed96b1b3c4 100644 --- a/include/configs/intip.h +++ b/include/configs/intip.h @@ -316,6 +316,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/katmai.h b/include/configs/katmai.h index 3ed8dc7f3e..c6f712c937 100644 --- a/include/configs/katmai.h +++ b/include/configs/katmai.h @@ -238,6 +238,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP 1 /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index d505a41de4..aec4a584ef 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -483,6 +483,7 @@ * PCI stuff *----------------------------------------------------------------------*/ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP 1 /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/korat.h b/include/configs/korat.h index b919aec359..d7c1f8508b 100644 --- a/include/configs/korat.h +++ b/include/configs/korat.h @@ -355,6 +355,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 0 /* to avoid problems with PNP */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/kvme080.h b/include/configs/kvme080.h index e49dc28776..87a5056afd 100644 --- a/include/configs/kvme080.h +++ b/include/configs/kvme080.h @@ -169,6 +169,7 @@ #define CONFIG_SYS_NS16550_CLK 14745600 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #define CONFIG_EEPRO100 diff --git a/include/configs/linkstation.h b/include/configs/linkstation.h index eec79619c1..20f0a18f86 100644 --- a/include/configs/linkstation.h +++ b/include/configs/linkstation.h @@ -185,6 +185,7 @@ * PCI stuff */ #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE /* Verified: CONFIG_PCI_PNP doesn't work */ #undef CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW diff --git a/include/configs/luan.h b/include/configs/luan.h index 3b4761bd08..f0e568af83 100644 --- a/include/configs/luan.h +++ b/include/configs/luan.h @@ -178,6 +178,7 @@ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/makalu.h b/include/configs/makalu.h index 6c1b136659..f71f28bb87 100644 --- a/include/configs/makalu.h +++ b/include/configs/makalu.h @@ -276,6 +276,7 @@ * PCI stuff *----------------------------------------------------------------------*/ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP 1 /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/mpc5121ads.h b/include/configs/mpc5121ads.h index 64ce52dee7..6f003aa03f 100644 --- a/include/configs/mpc5121ads.h +++ b/include/configs/mpc5121ads.h @@ -336,6 +336,7 @@ * PCI */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE /* * General PCI diff --git a/include/configs/mpc8308_p1m.h b/include/configs/mpc8308_p1m.h index aa681f0628..3c7a85e359 100644 --- a/include/configs/mpc8308_p1m.h +++ b/include/configs/mpc8308_p1m.h @@ -353,6 +353,7 @@ #define CONFIG_SYS_SCCR_PCIEXP1CM 1 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCIE #define CONFIG_PCI_PNP /* do pci plug-and-play */ diff --git a/include/configs/ocotea.h b/include/configs/ocotea.h index d0fe9dadfb..3e64c7405b 100644 --- a/include/configs/ocotea.h +++ b/include/configs/ocotea.h @@ -197,6 +197,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */ diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h index 7ed634b701..2fa537291b 100644 --- a/include/configs/p1_p2_rdb_pc.h +++ b/include/configs/p1_p2_rdb_pc.h @@ -217,6 +217,7 @@ #define CONFIG_PCIE1 /* PCIE controler 1 (slot 1) */ #define CONFIG_PCIE2 /* PCIE controler 2 (slot 2) */ #define CONFIG_FSL_PCI_INIT /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_FSL_PCIE_RESET /* need PCIe reset errata */ #define CONFIG_SYS_PCI_64BIT /* enable 64-bit PCI resources */ diff --git a/include/configs/p3p440.h b/include/configs/p3p440.h index d7b1ca203a..a19de079b6 100644 --- a/include/configs/p3p440.h +++ b/include/configs/p3p440.h @@ -241,6 +241,7 @@ *----------------------------------------------------------------------*/ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */ diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h index 348030227d..2ecd1050cf 100644 --- a/include/configs/pcm051.h +++ b/include/configs/pcm051.h @@ -205,12 +205,11 @@ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK /* - * Place the image at the start of the ROM defined image space and leave - * space for SRAM scratch entries (see arch/arm/include/omap_common.h). + * Place the image at the start of the ROM defined image space. * We limit our size to the ROM-defined downloaded image area, and use the * rest of the space for stack. */ -#define CONFIG_SPL_TEXT_BASE 0x402F0500 +#define CONFIG_SPL_TEXT_BASE 0x402F0400 #define CONFIG_SPL_MAX_SIZE (0x4030C000 - CONFIG_SPL_TEXT_BASE) #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR diff --git a/include/configs/pcs440ep.h b/include/configs/pcs440ep.h index 351ff5a22b..1897619058 100644 --- a/include/configs/pcs440ep.h +++ b/include/configs/pcs440ep.h @@ -317,6 +317,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE*/ diff --git a/include/configs/pm9263.h b/include/configs/pm9263.h index b60a9ade15..6f6ddfa20e 100644 --- a/include/configs/pm9263.h +++ b/include/configs/pm9263.h @@ -355,7 +355,7 @@ #define CONFIG_BOOTCOMMAND "run flashboot" #define CONFIG_ROOTPATH "/ronetix/rootfs" -#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n" +#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n", bootdelay #define CONFIG_CON_ROT "fbcon=rotate:3 " #define CONFIG_BOOTARGS "root=/dev/mtdblock4 rootfstype=jffs2 "\ diff --git a/include/configs/ppmc7xx.h b/include/configs/ppmc7xx.h index 5cd660927a..3f9fdd444d 100644 --- a/include/configs/ppmc7xx.h +++ b/include/configs/ppmc7xx.h @@ -118,6 +118,7 @@ */ #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI_PNP #undef CONFIG_PCI_SCAN_SHOW @@ -233,7 +234,7 @@ #define CONFIG_SYS_FLASH_ERASE_TOUT 250000 #define CONFIG_SYS_FLASH_WRITE_TOUT 5000 #define CONFIG_SYS_MAX_FLASH_BANKS 1 -#define CONFIG_SYS_MAX_FLASH_SECT 19 +#define CONFIG_SYS_MAX_FLASH_SECT 128 /* diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h index c18b35b057..216c6cb70b 100644 --- a/include/configs/rpi_b.h +++ b/include/configs/rpi_b.h @@ -61,6 +61,7 @@ #define CONFIG_BCM2835_GPIO /* LCD */ #define CONFIG_LCD +#define CONFIG_LCD_DT_SIMPLEFB #define LCD_BPP LCD_COLOR16 /* * Prevent allocation of RAM for FB; the real FB address is queried @@ -175,6 +176,7 @@ /* Device tree support for bootm/bootz */ #define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP /* ATAGs support for bootm/bootz */ #define CONFIG_SETUP_MEMORY_TAGS #define CONFIG_CMDLINE_TAG diff --git a/include/configs/sbc405.h b/include/configs/sbc405.h index 5abcda3c36..6e53bc2ee2 100644 --- a/include/configs/sbc405.h +++ b/include/configs/sbc405.h @@ -183,6 +183,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/sbc8349.h b/include/configs/sbc8349.h index 478d0d8f9d..fdc1b95e23 100644 --- a/include/configs/sbc8349.h +++ b/include/configs/sbc8349.h @@ -573,6 +573,7 @@ /* PCI @ 0x80000000 */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_IBAT1L (CONFIG_SYS_PCI1_MEM_BASE \ | BATL_PP_RW \ | BATL_MEMCOHERENCE) diff --git a/include/configs/sbc8548.h b/include/configs/sbc8548.h index 2209ddf823..148ade3568 100644 --- a/include/configs/sbc8548.h +++ b/include/configs/sbc8548.h @@ -33,6 +33,7 @@ * Top level Makefile configuration choices */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_PCI1 #endif diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h index 9040ec6095..0e2d17deb5 100644 --- a/include/configs/sbc8641d.h +++ b/include/configs/sbc8641d.h @@ -64,6 +64,7 @@ #define CONFIG_PCIE1 1 /* PCIE controler 1 (slot 1) */ #define CONFIG_PCIE2 1 /* PCIE controler 2 (slot 2) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ #define CONFIG_TSEC_ENET /* tsec ethernet support */ diff --git a/include/configs/sc3.h b/include/configs/sc3.h index fb74608bb9..9dec21de6e 100644 --- a/include/configs/sc3.h +++ b/include/configs/sc3.h @@ -269,6 +269,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index dd5d7cd260..11fce53c02 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -363,6 +363,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 0 /* to avoid problems with PNP */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/socrates.h b/include/configs/socrates.h index 25f15f2c35..7a0b481931 100644 --- a/include/configs/socrates.h +++ b/include/configs/socrates.h @@ -48,6 +48,7 @@ #define CONFIG_SYS_TEXT_BASE 0xfff80000 #define CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_TSEC_ENET /* tsec ethernet support */ diff --git a/include/configs/stxssa.h b/include/configs/stxssa.h index c1a90a7047..96d7128d0a 100644 --- a/include/configs/stxssa.h +++ b/include/configs/stxssa.h @@ -46,6 +46,7 @@ #define CONFIG_SYS_TEXT_BASE 0xFFF80000 #define CONFIG_PCI /* PCI ethernet support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_TSEC_ENET /* tsec ethernet support*/ #undef CONFIG_ETHER_ON_FCC /* cpm FCC ethernet support */ #define CONFIG_ENV_OVERWRITE diff --git a/include/configs/t3corp.h b/include/configs/t3corp.h index 2a731a637b..ff2189c2fb 100644 --- a/include/configs/t3corp.h +++ b/include/configs/t3corp.h @@ -376,6 +376,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/configs/t4qds.h b/include/configs/t4qds.h index fa1dcc3528..aa90249f0f 100644 --- a/include/configs/t4qds.h +++ b/include/configs/t4qds.h @@ -657,6 +657,7 @@ unsigned long get_board_ddr_clk(void); #endif #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_NET_MULTI #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_E1000 diff --git a/include/configs/taihu.h b/include/configs/taihu.h index a3738b7b1d..a43c3da4a0 100644 --- a/include/configs/taihu.h +++ b/include/configs/taihu.h @@ -171,6 +171,7 @@ unsigned char spi_read(void); #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/taishan.h b/include/configs/taishan.h index 3046081c52..c9f1a9fa24 100644 --- a/include/configs/taishan.h +++ b/include/configs/taishan.h @@ -192,6 +192,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_EEPRO100 1 /* include PCI EEPRO100 */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ diff --git a/include/configs/utx8245.h b/include/configs/utx8245.h index 66568c8d00..60d1503bc3 100644 --- a/include/configs/utx8245.h +++ b/include/configs/utx8245.h @@ -139,6 +139,7 @@ protect on ${u-boot_startaddr} ${u-boot_endaddr}" *----------------------------------------------------------------------- */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP #define CONFIG_PCI_SCAN_SHOW #define CONFIG_EEPRO100 diff --git a/include/configs/ve8313.h b/include/configs/ve8313.h index d3b8379186..7b1130a48e 100644 --- a/include/configs/ve8313.h +++ b/include/configs/ve8313.h @@ -43,6 +43,7 @@ #endif #define CONFIG_PCI 1 +#define CONFIG_PCI_INDIRECT_BRIDGE 1 #define CONFIG_FSL_ELBC 1 #define CONFIG_BOARD_EARLY_INIT_F 1 diff --git a/include/configs/vme8349.h b/include/configs/vme8349.h index 61e02e6077..f97de5490b 100644 --- a/include/configs/vme8349.h +++ b/include/configs/vme8349.h @@ -489,6 +489,7 @@ /* PCI @ 0x80000000 */ #ifdef CONFIG_PCI +#define CONFIG_PCI_INDIRECT_BRIDGE #define CONFIG_SYS_IBAT1L (CONFIG_SYS_PCI1_MEM_BASE | BATL_PP_RW | \ BATL_MEMCOHERENCE) #define CONFIG_SYS_IBAT1U (CONFIG_SYS_PCI1_MEM_BASE | BATU_BL_256M | \ diff --git a/include/configs/walnut.h b/include/configs/walnut.h index d10f74843d..219f276a4c 100644 --- a/include/configs/walnut.h +++ b/include/configs/walnut.h @@ -112,6 +112,7 @@ #define PCI_HOST_AUTO 2 /* detected via arbiter enable */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ /* resource configuration */ diff --git a/include/configs/xpedite1000.h b/include/configs/xpedite1000.h index 506d646fec..1f48cc5772 100644 --- a/include/configs/xpedite1000.h +++ b/include/configs/xpedite1000.h @@ -167,6 +167,7 @@ extern void out32(unsigned int, unsigned long); */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */ diff --git a/include/configs/xpedite517x.h b/include/configs/xpedite517x.h index 1851a00c16..f28f443fe9 100644 --- a/include/configs/xpedite517x.h +++ b/include/configs/xpedite517x.h @@ -49,6 +49,7 @@ #define CONFIG_PCIE1 1 /* PCIE controler 1 */ #define CONFIG_PCIE2 1 /* PCIE controler 2 */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ diff --git a/include/configs/xpedite520x.h b/include/configs/xpedite520x.h index ff99481b2f..3034a3c9a9 100644 --- a/include/configs/xpedite520x.h +++ b/include/configs/xpedite520x.h @@ -48,6 +48,7 @@ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCI1 1 /* PCI controller 1 */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ diff --git a/include/configs/xpedite537x.h b/include/configs/xpedite537x.h index 46f1c903f1..43359a2eef 100644 --- a/include/configs/xpedite537x.h +++ b/include/configs/xpedite537x.h @@ -49,6 +49,7 @@ #define CONFIG_PCIE1 1 /* PCIE controler 1 */ #define CONFIG_PCIE2 1 /* PCIE controler 2 */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ diff --git a/include/configs/xpedite550x.h b/include/configs/xpedite550x.h index 2acf6c80a5..a171085354 100644 --- a/include/configs/xpedite550x.h +++ b/include/configs/xpedite550x.h @@ -48,6 +48,7 @@ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCIE1 1 /* PCIE controler 1 (PEX8112 or XMC) */ #define CONFIG_FSL_PCI_INIT 1 /* Use common FSL init code */ +#define CONFIG_PCI_INDIRECT_BRIDGE 1 /* indirect PCI bridge support */ #define CONFIG_SYS_PCI_64BIT 1 /* enable 64-bit PCI resources */ #define CONFIG_FSL_PCIE_RESET 1 /* need PCIe reset errata */ #define CONFIG_FSL_LAW 1 /* Use common FSL init code */ diff --git a/include/configs/yosemite.h b/include/configs/yosemite.h index 0cbef6f85f..cde0df1a08 100644 --- a/include/configs/yosemite.h +++ b/include/configs/yosemite.h @@ -222,6 +222,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #undef CONFIG_PCI_PNP /* do (not) pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ #define CONFIG_SYS_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE*/ diff --git a/include/configs/yucca.h b/include/configs/yucca.h index fb684b5e10..3282d378d7 100644 --- a/include/configs/yucca.h +++ b/include/configs/yucca.h @@ -199,6 +199,7 @@ */ /* General PCI */ #define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_INDIRECT_BRIDGE /* indirect PCI bridge support */ #define CONFIG_PCI_PNP 1 /* do pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW 1 /* show pci devices on startup */ #define CONFIG_PCI_CONFIG_HOST_BRIDGE diff --git a/include/fdtdec.h b/include/fdtdec.h index 4e8032ba6c..1ece6122f5 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -93,6 +93,7 @@ enum fdt_compat_id { COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */ COMPAT_INFINEON_SLB9635_TPM, /* Infineon SLB9635 TPM */ + COMPAT_INFINEON_SLB9645_TPM, /* Infineon SLB9645 TPM */ COMPAT_COUNT, }; diff --git a/include/image.h b/include/image.h index b8cc5236a8..8ccc00b76a 100644 --- a/include/image.h +++ b/include/image.h @@ -402,6 +402,13 @@ void genimg_print_size(uint32_t size); #endif void genimg_print_time(time_t timestamp); +/* What to do with a image load address ('load = <> 'in the FIT) */ +enum fit_load_op { + FIT_LOAD_IGNORED, /* Ignore load address */ + FIT_LOAD_OPTIONAL, /* Can be provided, but optional */ + FIT_LOAD_REQUIRED, /* Must be provided */ +}; + #ifndef USE_HOSTCC /* Image format types, returned by _get_format() routine */ #define IMAGE_FORMAT_INVALID 0x00 @@ -415,8 +422,71 @@ ulong genimg_get_image(ulong img_addr); int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end); -int boot_get_fdt(int flag, int argc, char * const argv[], - bootm_headers_t *images, char **of_flat_tree, ulong *of_size); +/** + * fit_image_load() - load an image from a FIT + * + * This deals with all aspects of loading an image from a FIT, including + * selecting the right image based on configuration, verifying it, printing + * out progress messages, checking the type/arch/os and optionally copying it + * to the right load address. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + * @param fit_unamep On entry this is the requested image name + * (e.g. "kernel@1") or NULL to use the default. On exit + * points to the selected image name + * @param fit_uname_config Requested configuration name, or NULL for the + * default + * @param arch Expected architecture (IH_ARCH_...) + * @param image_type Required image type (IH_TYPE_...). If this is + * IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD + * also. + * @param bootstage_id ID of starting bootstage to use for progress updates. + * This will be added to the BOOTSTAGE_SUB values when + * calling bootstage_mark() + * @param load_op Decribes what to do with the load address + * @param datap Returns address of loaded image + * @param lenp Returns length of loaded image + */ +int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, + const char **fit_unamep, const char *fit_uname_config, + int arch, int image_type, int bootstage_id, + enum fit_load_op load_op, ulong *datap, ulong *lenp); + +/** + * fit_get_node_from_config() - Look up an image a FIT by type + * + * This looks in the selected conf@ node (images->fit_uname_cfg) for a + * particular image type (e.g. "kernel") and then finds the image that is + * referred to. + * + * For example, for something like: + * + * images { + * kernel@1 { + * ... + * }; + * }; + * configurations { + * conf@1 { + * kernel = "kernel@1"; + * }; + * }; + * + * the function will return the node offset of the kernel@1 node, assuming + * that conf@1 is the chosen configuration. + * + * @param images Boot images structure + * @param prop_name Property name to look up (FIT_..._PROP) + * @param addr Address of FIT in memory + */ +int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr); + +int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, + bootm_headers_t *images, + char **of_flat_tree, ulong *of_size); void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size); @@ -697,6 +767,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp); int fit_add_verification_data(void *fit); int fit_image_verify(const void *fit, int noffset); +int fit_config_verify(const void *fit, int conf_noffset); int fit_all_image_verify(const void *fit); int fit_image_check_os(const void *fit, int noffset, uint8_t os); int fit_image_check_arch(const void *fit, int noffset, uint8_t arch); @@ -706,9 +777,6 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname); -int fit_conf_get_kernel_node(const void *fit, int noffset); -int fit_conf_get_ramdisk_node(const void *fit, int noffset); -int fit_conf_get_fdt_node(const void *fit, int noffset); /** * fit_conf_get_prop_node() - Get node refered to by a configuration @@ -732,12 +800,35 @@ int fit_check_ramdisk(const void *fit, int os_noffset, int calculate_hash(const void *data, int data_len, const char *algo, uint8_t *value, int *value_len); -#ifndef USE_HOSTCC +/* + * At present we only support verification on the device + */ +#if defined(CONFIG_FIT_SIGNATURE) +# ifdef USE_HOSTCC +# define IMAGE_ENABLE_VERIFY 0 +#else +# define IMAGE_ENABLE_VERIFY 1 +# endif +#else +# define IMAGE_ENABLE_VERIFY 0 +#endif + +#ifdef USE_HOSTCC +# define gd_fdt_blob() NULL +#else +# define gd_fdt_blob() (gd->fdt_blob) +#endif + +#ifdef CONFIG_FIT_BEST_MATCH +#define IMAGE_ENABLE_BEST_MATCH 1 +#else +#define IMAGE_ENABLE_BEST_MATCH 0 +#endif + static inline int fit_image_check_target_arch(const void *fdt, int node) { return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT); } -#endif /* USE_HOSTCC */ #ifdef CONFIG_FIT_VERBOSE #define fit_unsupported(msg) printf("! %s:%d " \ diff --git a/include/lcd.h b/include/lcd.h index c6e7fc5216..30225edf56 100644 --- a/include/lcd.h +++ b/include/lcd.h @@ -324,6 +324,9 @@ void lcd_show_board_info(void); /* Return the size of the LCD frame buffer, and the line length */ int lcd_get_size(int *line_length); +int lcd_dt_simplefb_add_node(void *blob); +int lcd_dt_simplefb_enable_existing_node(void *blob); + /************************************************************************/ /* ** BITMAP DISPLAY SUPPORT */ /************************************************************************/ diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 8cbcdae114..71292b1a86 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -81,32 +81,53 @@ struct nand_bbt_descr { #define NAND_BBT_LASTBLOCK 0x00000010 /* The bbt is at the given page, else we must scan for the bbt */ #define NAND_BBT_ABSPAGE 0x00000020 -/* The bbt is at the given page, else we must scan for the bbt */ -#define NAND_BBT_SEARCH 0x00000040 /* bbt is stored per chip on multichip devices */ #define NAND_BBT_PERCHIP 0x00000080 /* bbt has a version counter at offset veroffs */ #define NAND_BBT_VERSION 0x00000100 /* Create a bbt if none exists */ #define NAND_BBT_CREATE 0x00000200 +/* + * Create an empty BBT with no vendor information. Vendor's information may be + * unavailable, for example, if the NAND controller has a different data and OOB + * layout or if this information is already purged. Must be used in conjunction + * with NAND_BBT_CREATE. + */ +#define NAND_BBT_CREATE_EMPTY 0x00000400 /* Search good / bad pattern through all pages of a block */ -#define NAND_BBT_SCANALLPAGES 0x00000400 +#define NAND_BBT_SCANALLPAGES 0x00000800 /* Scan block empty during good / bad block scan */ -#define NAND_BBT_SCANEMPTY 0x00000800 +#define NAND_BBT_SCANEMPTY 0x00001000 /* Write bbt if neccecary */ -#define NAND_BBT_WRITE 0x00001000 +#define NAND_BBT_WRITE 0x00002000 /* Read and write back block contents when writing bbt */ -#define NAND_BBT_SAVECONTENT 0x00002000 +#define NAND_BBT_SAVECONTENT 0x00004000 /* Search good / bad pattern on the first and the second page */ -#define NAND_BBT_SCAN2NDPAGE 0x00004000 +#define NAND_BBT_SCAN2NDPAGE 0x00008000 /* Search good / bad pattern on the last page of the eraseblock */ -#define NAND_BBT_SCANLASTPAGE 0x00008000 -/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */ -#define NAND_BBT_SCANBYTE1AND6 0x00100000 -/* The nand_bbt_descr was created dynamicaly and must be freed */ -#define NAND_BBT_DYNAMICSTRUCT 0x00200000 -/* The bad block table does not OOB for marker */ -#define NAND_BBT_NO_OOB 0x00400000 +#define NAND_BBT_SCANLASTPAGE 0x00010000 +/* + * Use a flash based bad block table. By default, OOB identifier is saved in + * OOB area. This option is passed to the default bad block table function. + */ +#define NAND_BBT_USE_FLASH 0x00020000 +/* + * Do not store flash based bad block table marker in the OOB area; store it + * in-band. + */ +#define NAND_BBT_NO_OOB 0x00040000 +/* + * Do not write new bad block markers to OOB; useful, e.g., when ECC covers + * entire spare area. Must be used with NAND_BBT_USE_FLASH. + */ +#define NAND_BBT_NO_OOB_BBM 0x00080000 + +/* + * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr + * was allocated dynamicaly and must be freed in nand_release(). Has no meaning + * in nand_chip.bbt_options. + */ +#define NAND_BBT_DYNAMICSTRUCT 0x80000000 /* The maximum number of blocks to scan for a bbt */ #define NAND_BBT_SCAN_MAXBLOCKS 4 diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 141c96024c..6f44abdc16 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -9,7 +9,8 @@ #include <linux/types.h> #include <div64.h> -#include <linux/mtd/mtd-abi.h> +#include <mtd/mtd-abi.h> +#include <asm/errno.h> #define MTD_CHAR_MAJOR 90 #define MTD_BLOCK_MAJOR 31 @@ -65,22 +66,6 @@ struct mtd_erase_region_info { unsigned long *lockmap; /* If keeping bitmap of locks */ }; -/* - * oob operation modes - * - * MTD_OOB_PLACE: oob data are placed at the given offset - * MTD_OOB_AUTO: oob data are automatically placed at the free areas - * which are defined by the ecclayout - * MTD_OOB_RAW: mode to read raw data+oob in one chunk. The oob data - * is inserted into the data. Thats a raw image of the - * flash contents. - */ -typedef enum { - MTD_OOB_PLACE, - MTD_OOB_AUTO, - MTD_OOB_RAW, -} mtd_oob_mode_t; - /** * struct mtd_oob_ops - oob operation operands * @mode: operation mode @@ -92,7 +77,7 @@ typedef enum { * @ooblen: number of oob bytes to write/read * @oobretlen: number of oob bytes written/read * @ooboffs: offset of oob data in the oob area (only relevant when - * mode = MTD_OOB_PLACE) + * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) * @datbuf: data buffer - if NULL only oob data are read/written * @oobbuf: oob data buffer * @@ -101,7 +86,7 @@ typedef enum { * OOB area. */ struct mtd_oob_ops { - mtd_oob_mode_t mode; + unsigned int mode; size_t len; size_t retlen; size_t ooblen; @@ -133,13 +118,25 @@ struct mtd_info { u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ u_int32_t oobavail; /* Available OOB bytes per block */ + /* + * read ops return -EUCLEAN if max number of bitflips corrected on any + * one region comprising an ecc step equals or exceeds this value. + * Settable by driver, else defaults to ecc_strength. User can override + * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; + * see Documentation/ABI/testing/sysfs-class-mtd for more detail. + */ + unsigned int bitflip_threshold; + /* Kernel-only stuff starts here. */ const char *name; int index; - /* ecc layout structure pointer - read only ! */ + /* ECC layout structure pointer - read only! */ struct nand_ecclayout *ecclayout; + /* max number of correctible bit errors per ecc step */ + unsigned int ecc_strength; + /* Data for variable erase regions. If numeraseregions is zero, * it means that the whole device has erasesize as given above. */ @@ -147,25 +144,17 @@ struct mtd_info { struct mtd_erase_region_info *eraseregions; /* - * Erase is an asynchronous operation. Device drivers are supposed - * to call instr->callback() whenever the operation completes, even - * if it completes with a failure. - * Callers are supposed to pass a callback function and wait for it - * to be called before writing to the block. + * Do not call via these pointers, use corresponding mtd_*() + * wrappers instead. */ - int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - - /* This stuff for eXecute-In-Place */ - /* phys is optional and may be set to NULL */ - int (*point) (struct mtd_info *mtd, loff_t from, size_t len, + int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); + int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, void **virt, phys_addr_t *phys); - - /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ - void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); - - - int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); + void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); + int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); /* In blackbox flight recorder like scenarios we want to make successful writes in interrupt context. panic_write() is only intended to be @@ -174,24 +163,35 @@ struct mtd_info { longer, this function can break locks and delay to ensure the write succeeds (but not sleep). */ - int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); + int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - int (*read_oob) (struct mtd_info *mtd, loff_t from, + int (*_read_oob) (struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); - int (*write_oob) (struct mtd_info *mtd, loff_t to, + int (*_write_oob) (struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); - + int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, + size_t len); + int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, + size_t len); + int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf); + int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, u_char *buf); + int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, + size_t len); + void (*_sync) (struct mtd_info *mtd); + int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); + int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); /* - * Methods to access the protection register area, present in some - * flash devices. The user data is one time programmable but the - * factory data is read only. + * If the driver is something smart, like UBI, it may need to maintain + * its own reference counting. The below functions are only for driver. */ - int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); - int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); - int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); - int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); + int (*_get_device) (struct mtd_info *mtd); + void (*_put_device) (struct mtd_info *mtd); /* XXX U-BOOT XXX */ #if 0 @@ -201,18 +201,6 @@ struct mtd_info { */ int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); #endif - - /* Sync */ - void (*sync) (struct mtd_info *mtd); - - /* Chip-supported device locking */ - int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - - /* Bad block management functions */ - int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); - int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); - /* XXX U-BOOT XXX */ #if 0 struct notifier_block reboot_notifier; /* default mode before reboot */ @@ -227,15 +215,59 @@ struct mtd_info { struct module *owner; int usecount; - - /* If the driver is something smart, like UBI, it may need to maintain - * its own reference counting. The below functions are only for driver. - * The driver may register its callbacks. These callbacks are not - * supposed to be called by MTD users */ - int (*get_device) (struct mtd_info *mtd); - void (*put_device) (struct mtd_info *mtd); }; +int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); +int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, + u_char *buf); +int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); +int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, + const u_char *buf); + +int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); + +static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + ops->retlen = ops->oobretlen = 0; + if (!mtd->_write_oob) + return -EOPNOTSUPP; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + return mtd->_write_oob(mtd, to, ops); +} + +int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len); +int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, + size_t len); +int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, u_char *buf); +int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); + +/* XXX U-BOOT XXX */ +#if 0 +int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen); +#endif + +static inline void mtd_sync(struct mtd_info *mtd) +{ + if (mtd->_sync) + mtd->_sync(mtd); +} + +int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); +int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); + static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) { do_div(sz, mtd->erasesize); @@ -247,6 +279,16 @@ static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) return do_div(sz, mtd->erasesize); } +static inline int mtd_has_oob(const struct mtd_info *mtd) +{ + return mtd->_read_oob && mtd->_write_oob; +} + +static inline int mtd_can_have_bb(const struct mtd_info *mtd) +{ + return !!mtd->_block_isbad; +} + /* Kernel-side ioctl definitions */ extern int add_mtd_device(struct mtd_info *mtd); @@ -269,12 +311,6 @@ struct mtd_notifier { extern void register_mtd_user (struct mtd_notifier *new); extern int unregister_mtd_user (struct mtd_notifier *old); - -int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen); - -int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, - unsigned long count, loff_t from, size_t *retlen); #endif #ifdef CONFIG_MTD_PARTITIONS @@ -296,17 +332,34 @@ static inline void mtd_erase_callback(struct erase_info *instr) #define MTD_DEBUG_LEVEL3 (3) /* Noisy */ #ifdef CONFIG_MTD_DEBUG +#define pr_debug(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) #define MTDDEBUG(n, args...) \ do { \ if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ printk(KERN_INFO args); \ } while(0) #else /* CONFIG_MTD_DEBUG */ +#define pr_debug(args...) #define MTDDEBUG(n, args...) \ do { \ if (0) \ printk(KERN_INFO args); \ } while(0) #endif /* CONFIG_MTD_DEBUG */ +#define pr_info(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_warn(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_err(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) + +static inline int mtd_is_bitflip(int err) { + return err == -EUCLEAN; +} + +static inline int mtd_is_eccerr(int err) { + return err == -EBADMSG; +} + +static inline int mtd_is_bitflip_or_eccerr(int err) { + return mtd_is_bitflip(err) || mtd_is_eccerr(err); +} #endif /* __MTD_MTD_H__ */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 98bf255bb2..2055584374 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -46,7 +46,7 @@ extern void nand_wait_ready(struct mtd_info *mtd); * is supported now. If you add a chip with bigger oobsize/page * adjust this accordingly. */ -#define NAND_MAX_OOBSIZE 576 +#define NAND_MAX_OOBSIZE 640 #define NAND_MAX_PAGESIZE 8192 /* @@ -82,6 +82,8 @@ extern void nand_wait_ready(struct mtd_info *mtd); #define NAND_CMD_READID 0x90 #define NAND_CMD_ERASE2 0xd0 #define NAND_CMD_PARAM 0xec +#define NAND_CMD_GET_FEATURES 0xee +#define NAND_CMD_SET_FEATURES 0xef #define NAND_CMD_RESET 0xff #define NAND_CMD_LOCK 0x2a @@ -142,7 +144,7 @@ typedef enum { #define NAND_ECC_READ 0 /* Reset Hardware ECC for write */ #define NAND_ECC_WRITE 1 -/* Enable Hardware ECC before syndrom is read back from flash */ +/* Enable Hardware ECC before syndrome is read back from flash */ #define NAND_ECC_READSYN 2 /* Bit mask for flags passed to do_nand_read_ecc */ @@ -153,9 +155,7 @@ typedef enum { * Option constants for bizarre disfunctionality and real * features. */ -/* Chip can not auto increment pages */ -#define NAND_NO_AUTOINCR 0x00000001 -/* Buswitdh is 16 bit */ +/* Buswidth is 16 bit */ #define NAND_BUSWIDTH_16 0x00000002 /* Device supports partial programming without padding */ #define NAND_NO_PADDING 0x00000004 @@ -179,12 +179,6 @@ typedef enum { * This happens with the Renesas AG-AND chips, possibly others. */ #define BBT_AUTO_REFRESH 0x00000080 -/* - * Chip does not require ready check on read. true - * for all large page devices, as they do not support - * autoincrement. - */ -#define NAND_NO_READRDY 0x00000100 /* Chip does not allow subpage writes */ #define NAND_NO_SUBPAGE_WRITE 0x00000200 @@ -202,34 +196,21 @@ typedef enum { (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK) /* Macros to identify the above */ -#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR)) #define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING)) #define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) #define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK)) #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ)) /* Non chip related options */ -/* - * Use a flash based bad block table. OOB identifier is saved in OOB area. - * This option is passed to the default bad block table function. - */ -#define NAND_USE_FLASH_BBT 0x00010000 /* This option skips the bbt scan during initialization. */ -#define NAND_SKIP_BBTSCAN 0x00020000 +#define NAND_SKIP_BBTSCAN 0x00010000 /* * This option is defined if the board driver allocates its own buffers * (e.g. because it needs them DMA-coherent). */ -#define NAND_OWN_BUFFERS 0x00040000 +#define NAND_OWN_BUFFERS 0x00020000 /* Chip may not exist, so silence any errors in scan */ -#define NAND_SCAN_SILENT_NODEV 0x00080000 -/* - * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch - * the OOB area. - */ -#define NAND_USE_FLASH_BBT_NO_OOB 0x00800000 -/* Create an empty BBT with no vendor information if the BBT is available */ -#define NAND_CREATE_EMPTY_BBT 0x01000000 +#define NAND_SCAN_SILENT_NODEV 0x00040000 /* Options set by nand scan */ /* bbt has already been read */ @@ -244,6 +225,21 @@ typedef enum { /* Keep gcc happy */ struct nand_chip; +/* ONFI timing mode, used in both asynchronous and synchronous mode */ +#define ONFI_TIMING_MODE_0 (1 << 0) +#define ONFI_TIMING_MODE_1 (1 << 1) +#define ONFI_TIMING_MODE_2 (1 << 2) +#define ONFI_TIMING_MODE_3 (1 << 3) +#define ONFI_TIMING_MODE_4 (1 << 4) +#define ONFI_TIMING_MODE_5 (1 << 5) +#define ONFI_TIMING_MODE_UNKNOWN (1 << 6) + +/* ONFI feature address */ +#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1 + +/* ONFI subfeature parameters length */ +#define ONFI_SUBFEATURE_PARAM_LEN 4 + struct nand_onfi_params { /* rev info and features block */ /* 'O' 'N' 'F' 'I' */ @@ -326,27 +322,32 @@ struct nand_hw_control { }; /** - * struct nand_ecc_ctrl - Control structure for ecc - * @mode: ecc mode - * @steps: number of ecc steps per page - * @size: data bytes per ecc step - * @bytes: ecc bytes per step - * @total: total number of ecc bytes per page - * @prepad: padding information for syndrome based ecc generators - * @postpad: padding information for syndrome based ecc generators + * struct nand_ecc_ctrl - Control structure for ECC + * @mode: ECC mode + * @steps: number of ECC steps per page + * @size: data bytes per ECC step + * @bytes: ECC bytes per step + * @strength: max number of correctible bits per ECC step + * @total: total number of ECC bytes per page + * @prepad: padding information for syndrome based ECC generators + * @postpad: padding information for syndrome based ECC generators * @layout: ECC layout control struct pointer - * @priv: pointer to private ecc control data - * @hwctl: function to control hardware ecc generator. Must only + * @priv: pointer to private ECC control data + * @hwctl: function to control hardware ECC generator. Must only * be provided if an hardware ECC is available - * @calculate: function for ecc calculation or readback from ecc hardware - * @correct: function for ecc correction, matching to ecc generator (sw/hw) + * @calculate: function for ECC calculation or readback from ECC hardware + * @correct: function for ECC correction, matching to ECC generator (sw/hw) * @read_page_raw: function to read a raw page without ECC * @write_page_raw: function to write a raw page without ECC - * @read_page: function to read a page according to the ecc generator - * requirements. - * @read_subpage: function to read parts of the page covered by ECC. - * @write_page: function to write a page according to the ecc generator + * @read_page: function to read a page according to the ECC generator + * requirements; returns maximum number of bitflips corrected in + * any single ECC step, 0 if bitflips uncorrectable, -EIO hw error + * @read_subpage: function to read parts of the page covered by ECC; + * returns same as read_page() + * @write_page: function to write a page according to the ECC generator * requirements. + * @write_oob_raw: function to write chip OOB data without ECC + * @read_oob_raw: function to read chip OOB data without ECC * @read_oob: function to read chip OOB data * @write_oob: function to write chip OOB data */ @@ -356,6 +357,7 @@ struct nand_ecc_ctrl { int size; int bytes; int total; + int strength; int prepad; int postpad; struct nand_ecclayout *layout; @@ -366,25 +368,28 @@ struct nand_ecc_ctrl { int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page); - void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf); + uint8_t *buf, int oob_required, int page); + int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required); int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page); + uint8_t *buf, int oob_required, int page); int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf); - void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf); - int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page, - int sndcmd); + int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required); + int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, + int page); + int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, + int page); + int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page); int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page); }; /** * struct nand_buffers - buffer structure for read/write - * @ecccalc: buffer for calculated ecc - * @ecccode: buffer for ecc read from flash + * @ecccalc: buffer for calculated ECC + * @ecccode: buffer for ECC read from flash * @databuf: buffer for data - dynamically sized * * Do not change the order of buffers. databuf and oobrbuf must be in @@ -418,7 +423,7 @@ struct nand_buffers { * mtd->oobsize, mtd->writesize and so on. * @id_data contains the 8 bytes values of NAND_CMD_READID. * Return with the bus width. - * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing + * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accessing * device ready/busy line. If set to NULL no access to * ready/busy is available and the ready/busy information * is read from the chip status register. @@ -426,17 +431,17 @@ struct nand_buffers { * commands to the chip. * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on * ready. - * @ecc: [BOARDSPECIFIC] ecc control ctructure + * @ecc: [BOARDSPECIFIC] ECC control structure * @buffers: buffer structure for read/write * @hwcontrol: platform-specific hardware control structure - * @ops: oob operation operands * @erase_cmd: [INTERN] erase command write function, selectable due * to AND support. * @scan_bbt: [REPLACEABLE] function to scan bad block table * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transferring * data from array to read regs (tR). * @state: [INTERN] the current state of the NAND device - * @oob_poi: poison value buffer + * @oob_poi: "poison value buffer," used for laying out OOB data + * before writing * @page_shift: [INTERN] number of address bits in a page (column * address bits). * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock @@ -445,10 +450,14 @@ struct nand_buffers { * @options: [BOARDSPECIFIC] various chip options. They can partly * be set to inform nand_scan about special functionality. * See the defines for further explanation. + * @bbt_options: [INTERN] bad block specific options. All options used + * here must come from bbm.h. By default, these options + * will be copied to the appropriate nand_bbt_descr's. * @badblockpos: [INTERN] position of the bad block marker in the oob * area. - * @badblockbits: [INTERN] number of bits to left-shift the bad block - * number + * @badblockbits: [INTERN] minimum number of set bits in a good block's + * bad block marker position; i.e., BBM == 11110111b is + * not bad when badblockbits == 7 * @cellinfo: [INTERN] MLC/multichip data from chip ident * @numchips: [INTERN] number of physical chips * @chipsize: [INTERN] the size of one chip for multichip arrays @@ -460,7 +469,9 @@ struct nand_buffers { * non 0 if ONFI supported. * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is * supported, 0 otherwise. - * @ecclayout: [REPLACEABLE] the default ecc placement scheme + * @onfi_set_features [REPLACEABLE] set the features for ONFI nand + * @onfi_get_features [REPLACEABLE] get the features for ONFI nand + * @ecclayout: [REPLACEABLE] the default ECC placement scheme * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash * lookup. @@ -468,9 +479,9 @@ struct nand_buffers { * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial * bad block scan. * @controller: [REPLACEABLE] a pointer to a hardware controller - * structure which is shared among multiple independend + * structure which is shared among multiple independent * devices. - * @priv: [OPTIONAL] pointer to private chip date + * @priv: [OPTIONAL] pointer to private chip data * @errstat: [OPTIONAL] hardware specific function to perform * additional error status checks (determine if errors are * correctable). @@ -501,10 +512,16 @@ struct nand_chip { int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int page, int cached, int raw); + const uint8_t *buf, int oob_required, int page, + int cached, int raw); + int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip, + int feature_addr, uint8_t *subfeature_para); + int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip, + int feature_addr, uint8_t *subfeature_para); int chip_delay; unsigned int options; + unsigned int bbt_options; int page_shift; int phys_erase_shift; @@ -534,8 +551,6 @@ struct nand_chip { struct nand_buffers *buffers; struct nand_hw_control hwcontrol; - struct mtd_oob_ops ops; - uint8_t *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; @@ -557,6 +572,8 @@ struct nand_chip { #define NAND_MFR_HYNIX 0xad #define NAND_MFR_MICRON 0x2c #define NAND_MFR_AMD 0x01 +#define NAND_MFR_MACRONIX 0xc2 +#define NAND_MFR_EON 0x92 /** * struct nand_flash_dev - NAND Flash Device ID Structure @@ -615,9 +632,9 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, * @partitions: mtd partition list * @chip_delay: R/B delay value in us * @options: Option flags, e.g. 16bit buswidth - * @ecclayout: ecc layout info structure + * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH + * @ecclayout: ECC layout info structure * @part_probe_types: NULL-terminated array of probe types - * @priv: hardware controller specific settings */ struct platform_nand_chip { int nr_chips; @@ -627,8 +644,8 @@ struct platform_nand_chip { struct nand_ecclayout *ecclayout; int chip_delay; unsigned int options; + unsigned int bbt_options; const char **part_probe_types; - void *priv; }; /* Keep gcc happy */ @@ -650,6 +667,7 @@ struct platform_nand_ctrl { int (*dev_ready)(struct mtd_info *mtd); void (*select_chip)(struct mtd_info *mtd, int chip); void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); + unsigned char (*read_byte)(struct mtd_info *mtd); void *priv; }; @@ -679,4 +697,23 @@ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len); void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len); uint8_t nand_read_byte(struct mtd_info *mtd); +/* return the supported asynchronous timing mode. */ + +#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static inline int onfi_get_async_timing_mode(struct nand_chip *chip) +{ + if (!chip->onfi_version) + return ONFI_TIMING_MODE_UNKNOWN; + return le16_to_cpu(chip->onfi_params.async_timing_mode); +} + +/* return the supported synchronous timing mode. */ +static inline int onfi_get_sync_timing_mode(struct nand_chip *chip) +{ + if (!chip->onfi_version) + return ONFI_TIMING_MODE_UNKNOWN; + return le16_to_cpu(chip->onfi_params.src_sync_timing_mode); +} +#endif + #endif /* __LINUX_MTD_NAND_H */ diff --git a/include/linux/string.h b/include/linux/string.h index e9b134d142..8e44855712 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -85,6 +85,9 @@ extern int memcmp(const void *,const void *,__kernel_size_t); #ifndef __HAVE_ARCH_MEMCHR extern void * memchr(const void *,int,__kernel_size_t); #endif +#ifndef __HAVE_ARCH_MEMCHR_INV +void *memchr_inv(const void *, int, size_t); +#endif #ifdef __cplusplus } diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index d1d732c283..bd48704c87 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -35,6 +35,7 @@ #include <linux/types.h> /* __u8 etc */ #include <asm/byteorder.h> /* le16_to_cpu */ +#include <asm/unaligned.h> /* get_unaligned() */ /*-------------------------------------------------------------------------*/ @@ -596,7 +597,7 @@ static inline int usb_endpoint_is_isoc_out( */ static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) { - return __le16_to_cpu(epd->wMaxPacketSize); + return __le16_to_cpu(get_unaligned(&epd->wMaxPacketSize)); } static inline int usb_endpoint_interrupt_type( diff --git a/include/linux/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 8bdd23112b..d51c1abd18 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -24,6 +24,25 @@ struct mtd_oob_buf { unsigned char __user *ptr; }; +/* + * MTD operation modes + * + * @MTD_OPS_PLACE_OOB: OOB data are placed at the given offset (default) + * @MTD_OPS_AUTO_OOB: OOB data are automatically placed at the free areas + * which are defined by the internal ecclayout + * @MTD_OPS_RAW: data are transferred as-is, with no error correction; + * this mode implies %MTD_OPS_PLACE_OOB + * + * These modes can be passed to ioctl(MEMWRITE) and are also used internally. + * See notes on "MTD file modes" for discussion on %MTD_OPS_RAW vs. + * %MTD_FILE_MODE_RAW. + */ +enum { + MTD_OPS_PLACE_OOB = 0, + MTD_OPS_AUTO_OOB = 1, + MTD_OPS_RAW = 2, +}; + #define MTD_ABSENT 0 #define MTD_RAM 1 #define MTD_ROM 2 @@ -82,24 +101,42 @@ struct otp_info { uint32_t locked; }; +/* Get basic MTD characteristics info (better to use sysfs) */ #define MEMGETINFO _IOR('M', 1, struct mtd_info_user) +/* Erase segment of MTD */ #define MEMERASE _IOW('M', 2, struct erase_info_user) +/* Write out-of-band data from MTD */ #define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) +/* Read out-of-band data from MTD */ #define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) +/* Lock a chip (for MTD that supports it) */ #define MEMLOCK _IOW('M', 5, struct erase_info_user) +/* Unlock a chip (for MTD that supports it) */ #define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +/* Get the number of different erase regions */ #define MEMGETREGIONCOUNT _IOR('M', 7, int) +/* Get information about the erase region for a specific index */ #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) +/* Get info about OOB modes (e.g., RAW, PLACE, AUTO) - legacy interface */ #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) +/* Check if an eraseblock is bad */ #define MEMGETBADBLOCK _IOW('M', 11, loff_t) +/* Mark an eraseblock as bad */ #define MEMSETBADBLOCK _IOW('M', 12, loff_t) +/* Set OTP (One-Time Programmable) mode (factory vs. user) */ #define OTPSELECT _IOR('M', 13, int) +/* Get number of OTP (One-Time Programmable) regions */ #define OTPGETREGIONCOUNT _IOW('M', 14, int) +/* Get all OTP (One-Time Programmable) info about MTD */ #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) +/* Lock a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */ #define OTPLOCK _IOR('M', 16, struct otp_info) +/* Get ECC layout (deprecated) */ #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) +/* Get statistics about corrected/uncorrected errors */ #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) +/* Set MTD mode on a per-file-descriptor basis (see "MTD file modes") */ #define MTDFILEMODE _IO('M', 19) /* @@ -146,7 +183,21 @@ struct mtd_ecc_stats { }; /* - * Read/write file modes for access to MTD + * MTD file modes - for read/write access to MTD + * + * @MTD_FILE_MODE_NORMAL: OTP disabled, ECC enabled + * @MTD_FILE_MODE_OTP_FACTORY: OTP enabled in factory mode + * @MTD_FILE_MODE_OTP_USER: OTP enabled in user mode + * @MTD_FILE_MODE_RAW: OTP disabled, ECC disabled + * + * These modes can be set via ioctl(MTDFILEMODE). The mode mode will be retained + * separately for each open file descriptor. + * + * Note: %MTD_FILE_MODE_RAW provides the same functionality as %MTD_OPS_RAW - + * raw access to the flash, without error correction or autoplacement schemes. + * Wherever possible, the MTD_OPS_* mode will override the MTD_FILE_MODE_* mode + * (e.g., when using ioctl(MEMWRITE)), but in some cases, the MTD_FILE_MODE is + * used out of necessity (e.g., `write()', ioctl(MEMWRITEOOB64)). */ enum mtd_file_modes { MTD_MODE_NORMAL = MTD_OTP_OFF, diff --git a/include/nand.h b/include/nand.h index f0f3bf94b5..26190e4137 100644 --- a/include/nand.h +++ b/include/nand.h @@ -31,7 +31,8 @@ * at the same time, so do it here. When all drivers are * converted, this will go away. */ -#if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_ATMEL) +#if defined(CONFIG_NAND_FSL_ELBC) || defined(CONFIG_NAND_ATMEL)\ + || defined(CONFIG_NAND_FSL_IFC) #define CONFIG_SYS_NAND_SELF_INIT #endif @@ -55,17 +56,17 @@ extern nand_info_t nand_info[]; static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf) { - return info->read(info, ofs, *len, (size_t *)len, buf); + return mtd_read(info, ofs, *len, (size_t *)len, buf); } static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf) { - return info->write(info, ofs, *len, (size_t *)len, buf); + return mtd_write(info, ofs, *len, (size_t *)len, buf); } static inline int nand_block_isbad(nand_info_t *info, loff_t ofs) { - return info->block_isbad(info, ofs); + return mtd_block_isbad(info, ofs); } static inline int nand_erase(nand_info_t *info, loff_t off, size_t size) @@ -77,7 +78,7 @@ static inline int nand_erase(nand_info_t *info, loff_t off, size_t size) instr.len = size; instr.callback = 0; - return info->erase(info, &instr); + return mtd_erase(info, &instr); } diff --git a/include/net.h b/include/net.h index 970d4d1fab..23fb947292 100644 --- a/include/net.h +++ b/include/net.h @@ -695,6 +695,9 @@ extern void copy_filename(char *dst, const char *src, int size); /* get a random source port */ extern unsigned int random_port(void); +/* Update U-Boot over TFTP */ +extern int update_tftp(ulong addr); + /**********************************************************************/ #endif /* __NET_H__ */ diff --git a/include/pci.h b/include/pci.h index 15f583f069..f9c5148255 100644 --- a/include/pci.h +++ b/include/pci.h @@ -569,7 +569,9 @@ extern __inline__ void pci_set_ops(struct pci_controller *hose, hose->write_dword = write_dword; } +#ifdef CONFIG_PCI_INDIRECT_BRIDGE extern void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); +#endif extern phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, pci_addr_t addr, unsigned long flags); diff --git a/include/usb/fotg210.h b/include/usb/fotg210.h new file mode 100644 index 0000000000..2d2d2431ba --- /dev/null +++ b/include/usb/fotg210.h @@ -0,0 +1,364 @@ +/* + * Faraday USB 2.0 OTG Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef _FOTG210_H +#define _FOTG210_H + +struct fotg210_regs { + /* USB Host Controller */ + struct { + uint32_t data[4]; + } hccr; /* 0x00 - 0x0f: hccr */ + struct { + uint32_t data[9]; + } hcor; /* 0x10 - 0x33: hcor */ + uint32_t rsvd1[3]; + uint32_t miscr; /* 0x40: Miscellaneous Register */ + uint32_t rsvd2[15]; + /* USB OTG Controller */ + uint32_t otgcsr;/* 0x80: OTG Control Status Register */ + uint32_t otgisr;/* 0x84: OTG Interrupt Status Register */ + uint32_t otgier;/* 0x88: OTG Interrupt Enable Register */ + uint32_t rsvd3[13]; + uint32_t isr; /* 0xC0: Global Interrupt Status Register */ + uint32_t imr; /* 0xC4: Global Interrupt Mask Register */ + uint32_t rsvd4[14]; + /* USB Device Controller */ + uint32_t dev_ctrl;/* 0x100: Device Control Register */ + uint32_t dev_addr;/* 0x104: Device Address Register */ + uint32_t dev_test;/* 0x108: Device Test Register */ + uint32_t sof_fnr; /* 0x10c: SOF Frame Number Register */ + uint32_t sof_mtr; /* 0x110: SOF Mask Timer Register */ + uint32_t phy_tmsr;/* 0x114: PHY Test Mode Selector Register */ + uint32_t rsvd5[2]; + uint32_t cxfifo;/* 0x120: CX FIFO Register */ + uint32_t idle; /* 0x124: IDLE Counter Register */ + uint32_t rsvd6[2]; + uint32_t gimr; /* 0x130: Group Interrupt Mask Register */ + uint32_t gimr0; /* 0x134: Group Interrupt Mask Register 0 */ + uint32_t gimr1; /* 0x138: Group Interrupt Mask Register 1 */ + uint32_t gimr2; /* 0x13c: Group Interrupt Mask Register 2 */ + uint32_t gisr; /* 0x140: Group Interrupt Status Register */ + uint32_t gisr0; /* 0x144: Group Interrupt Status Register 0 */ + uint32_t gisr1; /* 0x148: Group Interrupt Status Register 1 */ + uint32_t gisr2; /* 0x14c: Group Interrupt Status Register 2 */ + uint32_t rxzlp; /* 0x150: Receive Zero-Length-Packet Register */ + uint32_t txzlp; /* 0x154: Transfer Zero-Length-Packet Register */ + uint32_t isoeasr;/* 0x158: ISOC Error/Abort Status Register */ + uint32_t rsvd7[1]; + uint32_t iep[8]; /* 0x160 - 0x17f: IN Endpoint Register */ + uint32_t oep[8]; /* 0x180 - 0x19f: OUT Endpoint Register */ + uint32_t epmap14;/* 0x1a0: Endpoint Map Register (EP1 ~ 4) */ + uint32_t epmap58;/* 0x1a4: Endpoint Map Register (EP5 ~ 8) */ + uint32_t fifomap;/* 0x1a8: FIFO Map Register */ + uint32_t fifocfg; /* 0x1ac: FIFO Configuration Register */ + uint32_t fifocsr[4];/* 0x1b0 - 0x1bf: FIFO Control Status Register */ + uint32_t dma_fifo; /* 0x1c0: DMA Target FIFO Register */ + uint32_t rsvd8[1]; + uint32_t dma_ctrl; /* 0x1c8: DMA Control Register */ + uint32_t dma_addr; /* 0x1cc: DMA Address Register */ + uint32_t ep0_data; /* 0x1d0: EP0 Setup Packet PIO Register */ +}; + +/* Miscellaneous Register */ +#define MISCR_SUSPEND (1 << 6) /* Put transceiver in suspend mode */ +#define MISCR_EOF2(x) (((x) & 0x3) << 4) /* EOF 2 Timing */ +#define MISCR_EOF1(x) (((x) & 0x3) << 2) /* EOF 1 Timing */ +#define MISCR_ASST(x) (((x) & 0x3) << 0) /* Async. Sched. Sleep Timer */ + +/* OTG Control Status Register */ +#define OTGCSR_SPD_HIGH (2 << 22) /* Speed of the attached device (host) */ +#define OTGCSR_SPD_LOW (1 << 22) +#define OTGCSR_SPD_FULL (0 << 22) +#define OTGCSR_SPD_MASK (3 << 22) +#define OTGCSR_SPD_SHIFT 22 +#define OTGCSR_SPD(x) (((x) >> 22) & 0x03) +#define OTGCSR_DEV_A (0 << 21) /* Acts as A-device */ +#define OTGCSR_DEV_B (1 << 21) /* Acts as B-device */ +#define OTGCSR_ROLE_H (0 << 20) /* Acts as Host */ +#define OTGCSR_ROLE_D (1 << 20) /* Acts as Device */ +#define OTGCSR_A_VBUS_VLD (1 << 19) /* A-device VBUS Valid */ +#define OTGCSR_A_SESS_VLD (1 << 18) /* A-device Session Valid */ +#define OTGCSR_B_SESS_VLD (1 << 17) /* B-device Session Valid */ +#define OTGCSR_B_SESS_END (1 << 16) /* B-device Session End */ +#define OTGCSR_HFT_LONG (1 << 11) /* HDISCON noise filter = 270 us*/ +#define OTGCSR_HFT (0 << 11) /* HDISCON noise filter = 135 us*/ +#define OTGCSR_VFT_LONG (1 << 10) /* VBUS noise filter = 472 us*/ +#define OTGCSR_VFT (0 << 10) /* VBUS noise filter = 135 us*/ +#define OTGCSR_IDFT_LONG (1 << 9) /* ID noise filter = 4 ms*/ +#define OTGCSR_IDFT (0 << 9) /* ID noise filter = 3 ms*/ +#define OTGCSR_A_SRPR_VBUS (0 << 8) /* A-device: SRP responds to VBUS */ +#define OTGCSR_A_SRPR_DATA (1 << 8) /* A-device: SRP responds to DATA-LINE */ +#define OTGCSR_A_SRP_EN (1 << 7) /* A-device SRP detection enabled */ +#define OTGCSR_A_HNP (1 << 6) /* Set role=A-device with HNP enabled */ +#define OTGCSR_A_BUSDROP (1 << 5) /* A-device drop bus (power-down) */ +#define OTGCSR_A_BUSREQ (1 << 4) /* A-device request bus */ +#define OTGCSR_B_VBUS_DISC (1 << 2) /* B-device discharges VBUS */ +#define OTGCSR_B_HNP (1 << 1) /* B-device enable HNP */ +#define OTGCSR_B_BUSREQ (1 << 0) /* B-device request bus */ + +/* OTG Interrupt Status Register */ +#define OTGISR_APRM (1 << 12) /* Mini-A plug removed */ +#define OTGISR_BPRM (1 << 11) /* Mini-B plug removed */ +#define OTGISR_OVD (1 << 10) /* over-current detected */ +#define OTGISR_IDCHG (1 << 9) /* ID(A/B) changed */ +#define OTGISR_RLCHG (1 << 8) /* Role(Host/Device) changed */ +#define OTGISR_BSESSEND (1 << 6) /* B-device Session End */ +#define OTGISR_AVBUSERR (1 << 5) /* A-device VBUS Error */ +#define OTGISR_ASRP (1 << 4) /* A-device SRP detected */ +#define OTGISR_BSRP (1 << 0) /* B-device SRP complete */ + +/* OTG Interrupt Enable Register */ +#define OTGIER_APRM (1 << 12) /* Mini-A plug removed */ +#define OTGIER_BPRM (1 << 11) /* Mini-B plug removed */ +#define OTGIER_OVD (1 << 10) /* over-current detected */ +#define OTGIER_IDCHG (1 << 9) /* ID(A/B) changed */ +#define OTGIER_RLCHG (1 << 8) /* Role(Host/Device) changed */ +#define OTGIER_BSESSEND (1 << 6) /* B-device Session End */ +#define OTGIER_AVBUSERR (1 << 5) /* A-device VBUS Error */ +#define OTGIER_ASRP (1 << 4) /* A-device SRP detected */ +#define OTGIER_BSRP (1 << 0) /* B-device SRP complete */ + +/* Global Interrupt Status Register (W1C) */ +#define ISR_HOST (1 << 2) /* USB Host interrupt */ +#define ISR_OTG (1 << 1) /* USB OTG interrupt */ +#define ISR_DEV (1 << 0) /* USB Device interrupt */ +#define ISR_MASK 0x07 + +/* Global Interrupt Mask Register */ +#define IMR_IRQLH (1 << 3) /* Interrupt triggered at level-high */ +#define IMR_IRQLL (0 << 3) /* Interrupt triggered at level-low */ +#define IMR_HOST (1 << 2) /* USB Host interrupt */ +#define IMR_OTG (1 << 1) /* USB OTG interrupt */ +#define IMR_DEV (1 << 0) /* USB Device interrupt */ +#define IMR_MASK 0x0f + +/* Device Control Register */ +#define DEVCTRL_FS_FORCED (1 << 9) /* Forced to be Full-Speed Mode */ +#define DEVCTRL_HS (1 << 6) /* High Speed Mode */ +#define DEVCTRL_FS (0 << 6) /* Full Speed Mode */ +#define DEVCTRL_EN (1 << 5) /* Chip Enable */ +#define DEVCTRL_RESET (1 << 4) /* Chip Software Reset */ +#define DEVCTRL_SUSPEND (1 << 3) /* Enter Suspend Mode */ +#define DEVCTRL_GIRQ_EN (1 << 2) /* Global Interrupt Enabled */ +#define DEVCTRL_HALFSPD (1 << 1) /* Half speed mode for FPGA test */ +#define DEVCTRL_RWAKEUP (1 << 0) /* Enable remote wake-up */ + +/* Device Address Register */ +#define DEVADDR_CONF (1 << 7) /* SET_CONFIGURATION has been executed */ +#define DEVADDR_ADDR(x) ((x) & 0x7f) +#define DEVADDR_ADDR_MASK 0x7f + +/* Device Test Register */ +#define DEVTEST_NOSOF (1 << 6) /* Do not generate SOF */ +#define DEVTEST_TST_MODE (1 << 5) /* Enter Test Mode */ +#define DEVTEST_TST_NOTS (1 << 4) /* Do not toggle sequence */ +#define DEVTEST_TST_NOCRC (1 << 3) /* Do not append CRC */ +#define DEVTEST_TST_CLREA (1 << 2) /* Clear External Side Address */ +#define DEVTEST_TST_CXLP (1 << 1) /* EP0 loopback test */ +#define DEVTEST_TST_CLRFF (1 << 0) /* Clear FIFO */ + +/* SOF Frame Number Register */ +#define SOFFNR_UFN(x) (((x) >> 11) & 0x7) /* SOF Micro-Frame Number */ +#define SOFFNR_FNR(x) ((x) & 0x7ff) /* SOF Frame Number */ + +/* SOF Mask Timer Register */ +#define SOFMTR_TMR(x) ((x) & 0xffff) + +/* PHY Test Mode Selector Register */ +#define PHYTMSR_TST_PKT (1 << 4) /* Packet send test */ +#define PHYTMSR_TST_SE0NAK (1 << 3) /* High-Speed quiescent state */ +#define PHYTMSR_TST_KSTA (1 << 2) /* High-Speed K state */ +#define PHYTMSR_TST_JSTA (1 << 1) /* High-Speed J state */ +#define PHYTMSR_UNPLUG (1 << 0) /* Enable soft-detachment */ + +/* CX FIFO Register */ +#define CXFIFO_BYTES(x) (((x) >> 24) & 0x7f) /* CX/EP0 FIFO byte count */ +#define CXFIFO_FIFOE(x) (1 << (((x) & 0x03) + 8)) /* EPx FIFO empty */ +#define CXFIFO_FIFOE_FIFO0 (1 << 8) +#define CXFIFO_FIFOE_FIFO1 (1 << 9) +#define CXFIFO_FIFOE_FIFO2 (1 << 10) +#define CXFIFO_FIFOE_FIFO3 (1 << 11) +#define CXFIFO_FIFOE_MASK (0x0f << 8) +#define CXFIFO_CXFIFOE (1 << 5) /* CX FIFO empty */ +#define CXFIFO_CXFIFOF (1 << 4) /* CX FIFO full */ +#define CXFIFO_CXFIFOCLR (1 << 3) /* CX FIFO clear */ +#define CXFIFO_CXSTALL (1 << 2) /* CX Stall */ +#define CXFIFO_TSTPKTFIN (1 << 1) /* Test packet data transfer finished */ +#define CXFIFO_CXFIN (1 << 0) /* CX data transfer finished */ + +/* IDLE Counter Register */ +#define IDLE_MS(x) ((x) & 0x07) /* PHY suspend delay = x ms */ + +/* Group Interrupt Mask(Disable) Register */ +#define GIMR_GRP2 (1 << 2) /* Disable interrupt group 2 */ +#define GIMR_GRP1 (1 << 1) /* Disable interrupt group 1 */ +#define GIMR_GRP0 (1 << 0) /* Disable interrupt group 0 */ +#define GIMR_MASK 0x07 + +/* Group Interrupt Mask(Disable) Register 0 (CX) */ +#define GIMR0_CXABORT (1 << 5) /* CX command abort interrupt */ +#define GIMR0_CXERR (1 << 4) /* CX command error interrupt */ +#define GIMR0_CXEND (1 << 3) /* CX command end interrupt */ +#define GIMR0_CXOUT (1 << 2) /* EP0-OUT packet interrupt */ +#define GIMR0_CXIN (1 << 1) /* EP0-IN packet interrupt */ +#define GIMR0_CXSETUP (1 << 0) /* EP0-SETUP packet interrupt */ +#define GIMR0_MASK 0x3f + +/* Group Interrupt Mask(Disable) Register 1 (FIFO) */ +#define GIMR1_FIFO_IN(x) (1 << (((x) & 3) + 16)) /* FIFOx IN */ +#define GIMR1_FIFO_TX(x) GIMR1_FIFO_IN(x) +#define GIMR1_FIFO_OUT(x) (1 << (((x) & 3) * 2)) /* FIFOx OUT */ +#define GIMR1_FIFO_SPK(x) (1 << (((x) & 3) * 2 + 1)) /* FIFOx SHORT PACKET */ +#define GIMR1_FIFO_RX(x) (GIMR1_FIFO_OUT(x) | GIMR1_FIFO_SPK(x)) +#define GIMR1_MASK 0xf00ff + +/* Group Interrupt Mask(Disable) Register 2 (Device) */ +#define GIMR2_WAKEUP (1 << 10) /* Device waked up */ +#define GIMR2_IDLE (1 << 9) /* Device idle */ +#define GIMR2_DMAERR (1 << 8) /* DMA error */ +#define GIMR2_DMAFIN (1 << 7) /* DMA finished */ +#define GIMR2_ZLPRX (1 << 6) /* Zero-Length-Packet Rx Interrupt */ +#define GIMR2_ZLPTX (1 << 5) /* Zero-Length-Packet Tx Interrupt */ +#define GIMR2_ISOCABT (1 << 4) /* ISOC Abort Interrupt */ +#define GIMR2_ISOCERR (1 << 3) /* ISOC Error Interrupt */ +#define GIMR2_RESUME (1 << 2) /* Resume state change Interrupt */ +#define GIMR2_SUSPEND (1 << 1) /* Suspend state change Interrupt */ +#define GIMR2_RESET (1 << 0) /* Reset Interrupt */ +#define GIMR2_MASK 0x7ff + +/* Group Interrupt Status Register */ +#define GISR_GRP2 (1 << 2) /* Interrupt group 2 */ +#define GISR_GRP1 (1 << 1) /* Interrupt group 1 */ +#define GISR_GRP0 (1 << 0) /* Interrupt group 0 */ + +/* Group Interrupt Status Register 0 (CX) */ +#define GISR0_CXABORT (1 << 5) /* CX command abort interrupt */ +#define GISR0_CXERR (1 << 4) /* CX command error interrupt */ +#define GISR0_CXEND (1 << 3) /* CX command end interrupt */ +#define GISR0_CXOUT (1 << 2) /* EP0-OUT packet interrupt */ +#define GISR0_CXIN (1 << 1) /* EP0-IN packet interrupt */ +#define GISR0_CXSETUP (1 << 0) /* EP0-SETUP packet interrupt */ + +/* Group Interrupt Status Register 1 (FIFO) */ +#define GISR1_IN_FIFO(x) (1 << (((x) & 0x03) + 16)) /* FIFOx IN */ +#define GISR1_OUT_FIFO(x) (1 << (((x) & 0x03) * 2)) /* FIFOx OUT */ +#define GISR1_SPK_FIFO(x) (1 << (((x) & 0x03) * 2 + 1)) /* FIFOx SPK */ +#define GISR1_RX_FIFO(x) (3 << (((x) & 0x03) * 2)) /* FIFOx OUT/SPK */ + +/* Group Interrupt Status Register 2 (Device) */ +#define GISR2_WAKEUP (1 << 10) /* Device waked up */ +#define GISR2_IDLE (1 << 9) /* Device idle */ +#define GISR2_DMAERR (1 << 8) /* DMA error */ +#define GISR2_DMAFIN (1 << 7) /* DMA finished */ +#define GISR2_ZLPRX (1 << 6) /* Zero-Length-Packet Rx Interrupt */ +#define GISR2_ZLPTX (1 << 5) /* Zero-Length-Packet Tx Interrupt */ +#define GISR2_ISOCABT (1 << 4) /* ISOC Abort Interrupt */ +#define GISR2_ISOCERR (1 << 3) /* ISOC Error Interrupt */ +#define GISR2_RESUME (1 << 2) /* Resume state change Interrupt */ +#define GISR2_SUSPEND (1 << 1) /* Suspend state change Interrupt */ +#define GISR2_RESET (1 << 0) /* Reset Interrupt */ + +/* Receive Zero-Length-Packet Register */ +#define RXZLP_EP(x) (1 << ((x) - 1)) /* EPx ZLP rx interrupt */ + +/* Transfer Zero-Length-Packet Register */ +#define TXZLP_EP(x) (1 << ((x) - 1)) /* EPx ZLP tx interrupt */ + +/* ISOC Error/Abort Status Register */ +#define ISOEASR_EP(x) (0x10001 << ((x) - 1)) /* EPx ISOC Error/Abort */ + +/* IN Endpoint Register */ +#define IEP_SENDZLP (1 << 15) /* Send Zero-Length-Packet */ +#define IEP_TNRHB(x) (((x) & 0x03) << 13) \ + /* Transaction Number for High-Bandwidth EP(ISOC) */ +#define IEP_RESET (1 << 12) /* Reset Toggle Sequence */ +#define IEP_STALL (1 << 11) /* Stall */ +#define IEP_MAXPS(x) ((x) & 0x7ff) /* Max. packet size */ + +/* OUT Endpoint Register */ +#define OEP_RESET (1 << 12) /* Reset Toggle Sequence */ +#define OEP_STALL (1 << 11) /* Stall */ +#define OEP_MAXPS(x) ((x) & 0x7ff) /* Max. packet size */ + +/* Endpoint Map Register (EP1 ~ EP4) */ +#define EPMAP14_SET_IN(ep, fifo) \ + ((fifo) & 3) << (((ep) - 1) << 3 + 0) +#define EPMAP14_SET_OUT(ep, fifo) \ + ((fifo) & 3) << (((ep) - 1) << 3 + 4) +#define EPMAP14_SET(ep, in, out) \ + do { \ + EPMAP14_SET_IN(ep, in); \ + EPMAP14_SET_OUT(ep, out); \ + } while (0) + +#define EPMAP14_DEFAULT 0x33221100 /* EP1->FIFO0, EP2->FIFO1... */ + +/* Endpoint Map Register (EP5 ~ EP8) */ +#define EPMAP58_SET_IN(ep, fifo) \ + ((fifo) & 3) << (((ep) - 5) << 3 + 0) +#define EPMAP58_SET_OUT(ep, fifo) \ + ((fifo) & 3) << (((ep) - 5) << 3 + 4) +#define EPMAP58_SET(ep, in, out) \ + do { \ + EPMAP58_SET_IN(ep, in); \ + EPMAP58_SET_OUT(ep, out); \ + } while (0) + +#define EPMAP58_DEFAULT 0x00000000 /* All EPx->FIFO0 */ + +/* FIFO Map Register */ +#define FIFOMAP_BIDIR (2 << 4) +#define FIFOMAP_IN (1 << 4) +#define FIFOMAP_OUT (0 << 4) +#define FIFOMAP_DIR_MASK 0x30 +#define FIFOMAP_EP(x) ((x) & 0x0f) +#define FIFOMAP_EP_MASK 0x0f +#define FIFOMAP_CFG_MASK 0x3f +#define FIFOMAP_DEFAULT 0x04030201 /* FIFO0->EP1, FIFO1->EP2... */ +#define FIFOMAP(fifo, cfg) (((cfg) & 0x3f) << (((fifo) & 3) << 3)) + +/* FIFO Configuration Register */ +#define FIFOCFG_EN (1 << 5) +#define FIFOCFG_BLKSZ_1024 (1 << 4) +#define FIFOCFG_BLKSZ_512 (0 << 4) +#define FIFOCFG_3BLK (2 << 2) +#define FIFOCFG_2BLK (1 << 2) +#define FIFOCFG_1BLK (0 << 2) +#define FIFOCFG_NBLK_MASK 3 +#define FIFOCFG_NBLK_SHIFT 2 +#define FIFOCFG_INTR (3 << 0) +#define FIFOCFG_BULK (2 << 0) +#define FIFOCFG_ISOC (1 << 0) +#define FIFOCFG_RSVD (0 << 0) /* Reserved */ +#define FIFOCFG_TYPE_MASK 3 +#define FIFOCFG_TYPE_SHIFT 0 +#define FIFOCFG_CFG_MASK 0x3f +#define FIFOCFG(fifo, cfg) (((cfg) & 0x3f) << (((fifo) & 3) << 3)) + +/* FIFO Control Status Register */ +#define FIFOCSR_RESET (1 << 12) /* FIFO Reset */ +#define FIFOCSR_BYTES(x) ((x) & 0x7ff) /* Length(bytes) for OUT-EP/FIFO */ + +/* DMA Target FIFO Register */ +#define DMAFIFO_CX (1 << 4) /* DMA FIFO = CX FIFO */ +#define DMAFIFO_FIFO(x) (1 << ((x) & 0x3)) /* DMA FIFO = FIFOx */ + +/* DMA Control Register */ +#define DMACTRL_LEN(x) (((x) & 0x1ffff) << 8) /* DMA length (Bytes) */ +#define DMACTRL_LEN_SHIFT 8 +#define DMACTRL_CLRFF (1 << 4) /* Clear FIFO upon DMA abort */ +#define DMACTRL_ABORT (1 << 3) /* DMA abort */ +#define DMACTRL_IO2IO (1 << 2) /* IO to IO */ +#define DMACTRL_FIFO2MEM (0 << 1) /* FIFO to Memory */ +#define DMACTRL_MEM2FIFO (1 << 1) /* Memory to FIFO */ +#define DMACTRL_START (1 << 0) /* DMA start */ + +#endif diff --git a/include/usb/fusbh200.h b/include/usb/fusbh200.h new file mode 100644 index 0000000000..8a9c488cb5 --- /dev/null +++ b/include/usb/fusbh200.h @@ -0,0 +1,61 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su <dantesu@faraday-tech.com> + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef _FUSBH200_H +#define _FUSBH200_H + +struct fusbh200_regs { + struct { + uint32_t data[4]; + } hccr; /* 0x00 - 0x0f: hccr */ + struct { + uint32_t data[9]; + } hcor; /* 0x10 - 0x33: hcor */ + uint32_t easstr;/* 0x34: EOF&Async. Sched. Sleep Timer Register */ + uint32_t rsvd[2]; + uint32_t bmcsr; /* 0x40: Bus Monitor Control Status Register */ + uint32_t bmisr; /* 0x44: Bus Monitor Interrupt Status Register */ + uint32_t bmier; /* 0x48: Bus Monitor Interrupt Enable Register */ +}; + +/* EOF & Async. Schedule Sleep Timer Register */ +#define EASSTR_RUNNING (1 << 6) /* Put transceiver in running/resume mode */ +#define EASSTR_SUSPEND (0 << 6) /* Put transceiver in suspend mode */ +#define EASSTR_EOF2(x) (((x) & 0x3) << 4) /* EOF 2 Timing */ +#define EASSTR_EOF1(x) (((x) & 0x3) << 2) /* EOF 1 Timing */ +#define EASSTR_ASST(x) (((x) & 0x3) << 0) /* Async. Sched. Sleep Timer */ + +/* Bus Monitor Control Status Register */ +#define BMCSR_SPD_HIGH (2 << 9) /* Speed of the attached device */ +#define BMCSR_SPD_LOW (1 << 9) +#define BMCSR_SPD_FULL (0 << 9) +#define BMCSR_SPD_MASK (3 << 9) +#define BMCSR_SPD_SHIFT 9 +#define BMCSR_SPD(x) ((x >> 9) & 0x03) +#define BMCSR_VBUS (1 << 8) /* VBUS Valid */ +#define BMCSR_VBUS_OFF (1 << 4) /* VBUS Off */ +#define BMCSR_VBUS_ON (0 << 4) /* VBUS On */ +#define BMCSR_IRQLH (1 << 3) /* IRQ triggered at level-high */ +#define BMCSR_IRQLL (0 << 3) /* IRQ triggered at level-low */ +#define BMCSR_HALFSPD (1 << 2) /* Half speed mode for FPGA test */ +#define BMCSR_HFT_LONG (1 << 1) /* HDISCON noise filter = 270 us*/ +#define BMCSR_HFT (0 << 1) /* HDISCON noise filter = 135 us*/ +#define BMCSR_VFT_LONG (1 << 1) /* VBUS noise filter = 472 us*/ +#define BMCSR_VFT (0 << 1) /* VBUS noise filter = 135 us*/ + +/* Bus Monitor Interrupt Status Register */ +/* Bus Monitor Interrupt Enable Register */ +#define BMISR_DMAERR (1 << 4) /* DMA error */ +#define BMISR_DMA (1 << 3) /* DMA complete */ +#define BMISR_DEVRM (1 << 2) /* device removed */ +#define BMISR_OVD (1 << 1) /* over-current detected */ +#define BMISR_VBUSERR (1 << 0) /* VBUS error */ + +#endif diff --git a/lib/fdtdec.c b/lib/fdtdec.c index ac1fe0be20..005ad3d535 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -66,6 +66,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(GENERIC_SPI_FLASH, "spi-flash"), COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), + COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) diff --git a/lib/string.c b/lib/string.c index 09dfae03c2..3a82efab61 100644 --- a/lib/string.c +++ b/lib/string.c @@ -617,3 +617,62 @@ void *memchr(const void *s, int c, size_t n) } #endif +#ifndef __HAVE_ARCH_MEMCHR_INV +static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes) +{ + while (bytes) { + if (*start != value) + return (void *)start; + start++; + bytes--; + } + return NULL; +} +/** + * memchr_inv - Find an unmatching character in an area of memory. + * @start: The memory area + * @c: Find a character other than c + * @bytes: The size of the area. + * + * returns the address of the first character other than @c, or %NULL + * if the whole buffer contains just @c. + */ +void *memchr_inv(const void *start, int c, size_t bytes) +{ + u8 value = c; + u64 value64; + unsigned int words, prefix; + + if (bytes <= 16) + return check_bytes8(start, value, bytes); + + value64 = value; + value64 |= value64 << 8; + value64 |= value64 << 16; + value64 |= value64 << 32; + + prefix = (unsigned long)start % 8; + if (prefix) { + u8 *r; + + prefix = 8 - prefix; + r = check_bytes8(start, value, prefix); + if (r) + return r; + start += prefix; + bytes -= prefix; + } + + words = bytes / 8; + + while (words) { + if (*(u64 *)start != value64) + return check_bytes8(start, value, 8); + start += 8; + words--; + } + + return check_bytes8(start, value, bytes % 8); +} +#endif + diff --git a/test/image/test-fit.py b/test/image/test-fit.py new file mode 100755 index 0000000000..c4e8211162 --- /dev/null +++ b/test/image/test-fit.py @@ -0,0 +1,422 @@ +#!/usr/bin/python +# +# Copyright (c) 2013, Google Inc. +# +# Sanity check of the FIT handling in U-Boot +# +# 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 +# +# To run this: +# +# make O=sandbox sandbox_config +# make O=sandbox +# ./test/image/test-fit.py -u sandbox/u-boot + +import doctest +from optparse import OptionParser +import os +import shutil +import struct +import sys +import tempfile + +# The 'command' library in patman is convenient for running commands +base_path = os.path.dirname(sys.argv[0]) +patman = os.path.join(base_path, '../../tools/patman') +sys.path.append(patman) + +import command + +# Define a base ITS which we can adjust using % and a dictionary +base_its = ''' +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + data = /incbin/("%(kernel)s"); + type = "kernel"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x40000>; + entry = <0x8>; + }; + fdt@1 { + description = "snow"; + data = /incbin/("u-boot.dtb"); + type = "flat_dt"; + arch = "sandbox"; + %(fdt_load)s + compression = "none"; + signature@1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + ramdisk@1 { + description = "snow"; + data = /incbin/("%(ramdisk)s"); + type = "ramdisk"; + arch = "sandbox"; + os = "linux"; + %(ramdisk_load)s + compression = "none"; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + %(ramdisk_config)s + }; + }; +}; +''' + +# Define a base FDT - currently we don't use anything in this +base_fdt = ''' +/dts-v1/; + +/ { + model = "Sandbox Verified Boot Test"; + compatible = "sandbox"; + +}; +''' + +# This is the U-Boot script that is run for each test. First load the fit, +# then do the 'bootm' command, then save out memory from the places where +# we expect 'bootm' to write things. Then quit. +base_script = ''' +sb load host 0 %(fit_addr)x %(fit)s +fdt addr %(fit_addr)x +bootm start %(fit_addr)x +bootm loados +sb save host 0 %(kernel_out)s %(kernel_addr)x %(kernel_size)x +sb save host 0 %(fdt_out)s %(fdt_addr)x %(fdt_size)x +sb save host 0 %(ramdisk_out)s %(ramdisk_addr)x %(ramdisk_size)x +reset +''' + +def make_fname(leaf): + """Make a temporary filename + + Args: + leaf: Leaf name of file to create (within temporary directory) + Return: + Temporary filename + """ + global base_dir + + return os.path.join(base_dir, leaf) + +def filesize(fname): + """Get the size of a file + + Args: + fname: Filename to check + Return: + Size of file in bytes + """ + return os.stat(fname).st_size + +def read_file(fname): + """Read the contents of a file + + Args: + fname: Filename to read + Returns: + Contents of file as a string + """ + with open(fname, 'r') as fd: + return fd.read() + +def make_dtb(): + """Make a sample .dts file and compile it to a .dtb + + Returns: + Filename of .dtb file created + """ + src = make_fname('u-boot.dts') + dtb = make_fname('u-boot.dtb') + with open(src, 'w') as fd: + print >>fd, base_fdt + command.Output('dtc', src, '-O', 'dtb', '-o', dtb) + return dtb + +def make_its(params): + """Make a sample .its file with parameters embedded + + Args: + params: Dictionary containing parameters to embed in the %() strings + Returns: + Filename of .its file created + """ + its = make_fname('test.its') + with open(its, 'w') as fd: + print >>fd, base_its % params + return its + +def make_fit(mkimage, params): + """Make a sample .fit file ready for loading + + This creates a .its script with the selected parameters and uses mkimage to + turn this into a .fit image. + + Args: + mkimage: Filename of 'mkimage' utility + params: Dictionary containing parameters to embed in the %() strings + Return: + Filename of .fit file created + """ + fit = make_fname('test.fit') + its = make_its(params) + command.Output(mkimage, '-f', its, fit) + with open(make_fname('u-boot.dts'), 'w') as fd: + print >>fd, base_fdt + return fit + +def make_kernel(): + """Make a sample kernel with test data + + Returns: + Filename of kernel created + """ + fname = make_fname('test-kernel.bin') + data = '' + for i in range(100): + data += 'this kernel %d is unlikely to boot\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def make_ramdisk(): + """Make a sample ramdisk with test data + + Returns: + Filename of ramdisk created + """ + fname = make_fname('test-ramdisk.bin') + data = '' + for i in range(100): + data += 'ramdisk %d was seldom used in the middle ages\n' % i + with open(fname, 'w') as fd: + print >>fd, data + return fname + +def find_matching(text, match): + """Find a match in a line of text, and return the unmatched line portion + + This is used to extract a part of a line from some text. The match string + is used to locate the line - we use the first line that contains that + match text. + + Once we find a match, we discard the match string itself from the line, + and return what remains. + + TODO: If this function becomes more generally useful, we could change it + to use regex and return groups. + + Args: + text: Text to check (each line separated by \n) + match: String to search for + Return: + String containing unmatched portion of line + Exceptions: + ValueError: If match is not found + + >>> find_matching('first line:10\\nsecond_line:20', 'first line:') + '10' + >>> find_matching('first line:10\\nsecond_line:20', 'second linex') + Traceback (most recent call last): + ... + ValueError: Test aborted + >>> find_matching('first line:10\\nsecond_line:20', 'second_line:') + '20' + """ + for line in text.splitlines(): + pos = line.find(match) + if pos != -1: + return line[:pos] + line[pos + len(match):] + + print "Expected '%s' but not found in output:" + print text + raise ValueError('Test aborted') + +def set_test(name): + """Set the name of the current test and print a message + + Args: + name: Name of test + """ + global test_name + + test_name = name + print name + +def fail(msg): + """Raise an error with a helpful failure message + + Args: + msg: Message to display + """ + raise ValueError("Test '%s' failed: %s" % (test_name, msg)) + +def run_fit_test(mkimage, u_boot): + """Basic sanity check of FIT loading in U-Boot + + TODO: Almost everything: + - hash algorithms - invalid hash/contents should be detected + - signature algorithms - invalid sig/contents should be detected + - compression + - checking that errors are detected like: + - image overwriting + - missing images + - invalid configurations + - incorrect os/arch/type fields + - empty data + - images too large/small + - invalid FDT (e.g. putting a random binary in instead) + - default configuration selection + - bootm command line parameters should have desired effect + - run code coverage to make sure we are testing all the code + """ + global test_name + + # Set up invariant files + control_dtb = make_dtb() + kernel = make_kernel() + ramdisk = make_ramdisk() + kernel_out = make_fname('kernel-out.bin') + fdt_out = make_fname('fdt-out.dtb') + ramdisk_out = make_fname('ramdisk-out.bin') + + # Set up basic parameters with default values + params = { + 'fit_addr' : 0x1000, + + 'kernel' : kernel, + 'kernel_out' : kernel_out, + 'kernel_addr' : 0x40000, + 'kernel_size' : filesize(kernel), + + 'fdt_out' : fdt_out, + 'fdt_addr' : 0x80000, + 'fdt_size' : filesize(control_dtb), + 'fdt_load' : '', + + 'ramdisk' : ramdisk, + 'ramdisk_out' : ramdisk_out, + 'ramdisk_addr' : 0xc0000, + 'ramdisk_size' : filesize(ramdisk), + 'ramdisk_load' : '', + 'ramdisk_config' : '', + } + + # Make a basic FIT and a script to load it + fit = make_fit(mkimage, params) + params['fit'] = fit + cmd = base_script % params + + # First check that we can load a kernel + # We could perhaps reduce duplication with some loss of readability + set_test('Kernel load') + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) == read_file(fdt_out): + fail('FDT loaded but should be ignored') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Find out the offset in the FIT where U-Boot has found the FDT + line = find_matching(stdout, 'Booting using the fdt blob at ') + fit_offset = int(line, 16) - params['fit_addr'] + fdt_magic = struct.pack('>L', 0xd00dfeed) + data = read_file(fit) + + # Now find where it actually is in the FIT (skip the first word) + real_fit_offset = data.find(fdt_magic, 4) + if fit_offset != real_fit_offset: + fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' % + (fit_offset, real_fit_offset)) + + # Now a kernel and an FDT + set_test('Kernel + FDT load') + params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(kernel) != read_file(kernel_out): + fail('Kernel not loaded') + if read_file(control_dtb) != read_file(fdt_out): + fail('FDT not loaded') + if read_file(ramdisk) == read_file(ramdisk_out): + fail('Ramdisk loaded but should not be') + + # Try a ramdisk + set_test('Kernel + FDT + Ramdisk load') + params['ramdisk_config'] = 'ramdisk = "ramdisk@1";' + params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] + fit = make_fit(mkimage, params) + stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd) + if read_file(ramdisk) != read_file(ramdisk_out): + fail('Ramdisk not loaded') + +def run_tests(): + """Parse options, run the FIT tests and print the result""" + global base_path, base_dir + + # Work in a temporary directory + base_dir = tempfile.mkdtemp() + parser = OptionParser() + parser.add_option('-u', '--u-boot', + default=os.path.join(base_path, 'u-boot'), + help='Select U-Boot sandbox binary') + parser.add_option('-k', '--keep', action='store_true', + help="Don't delete temporary directory even when tests pass") + parser.add_option('-t', '--selftest', action='store_true', + help='Run internal self tests') + (options, args) = parser.parse_args() + + # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir + base_path = os.path.dirname(options.u_boot) + mkimage = os.path.join(base_path, 'tools/mkimage') + + # There are a few doctests - handle these here + if options.selftest: + doctest.testmod() + return + + title = 'FIT Tests' + print title, '\n', '=' * len(title) + + run_fit_test(mkimage, options.u_boot) + + print '\nTests passed' + print 'Caveat: this is only a sanity check - test coverage is poor' + + # Remove the tempoerary directory unless we are asked to keep it + if options.keep: + print "Output files are in '%s'" % base_dir + else: + shutil.rmtree(base_dir) + +run_tests() diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index 9f23901872..896e2bc985 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -273,6 +273,7 @@ our $logFunctions = qr{(?x: WARN(?:_RATELIMIT|_ONCE|)| panic| debug| + printf| MODULE_[A-Z_]+ )}; diff --git a/tools/mkimage.h b/tools/mkimage.h index e07a6157eb..03c6c8f523 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -44,12 +44,24 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +static inline void *map_sysmem(ulong paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline ulong map_to_sysmem(void *ptr) +{ + return (ulong)(uintptr_t)ptr; +} + #define MKIMAGE_TMPFILE_SUFFIX ".tmp" #define MKIMAGE_MAX_TMPFILE_LEN 256 #define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" #define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 #define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */ +#define IH_ARCH_DEFAULT IH_ARCH_INVALID + /* * This structure defines all such variables those are initialized by * mkimage main core and need to be referred by image type specific |