diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/s3c2440_gpio.c | 75 | ||||
-rw-r--r-- | drivers/i2c/s3c24x0_i2c.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 45 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_elbc_nand.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/mxs_nand.c | 35 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_util.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/vf610_nfc.c | 234 | ||||
-rw-r--r-- | drivers/net/bcm-sf2-eth.c | 6 | ||||
-rw-r--r-- | drivers/net/designware.c | 4 | ||||
-rw-r--r-- | drivers/net/dm9000x.c | 6 | ||||
-rw-r--r-- | drivers/net/ftmac110.c | 3 | ||||
-rw-r--r-- | drivers/net/greth.c | 10 | ||||
-rw-r--r-- | drivers/net/lan91c96.c | 7 | ||||
-rw-r--r-- | drivers/net/macb.c | 9 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 16 | ||||
-rw-r--r-- | drivers/net/phy/realtek.c | 102 | ||||
-rw-r--r-- | drivers/video/sunxi_display.c | 18 |
17 files changed, 370 insertions, 215 deletions
diff --git a/drivers/gpio/s3c2440_gpio.c b/drivers/gpio/s3c2440_gpio.c index e1e2d3f..d6c7eeb 100644 --- a/drivers/gpio/s3c2440_gpio.c +++ b/drivers/gpio/s3c2440_gpio.c @@ -8,53 +8,50 @@ #include <asm/arch/s3c2440.h> #include <asm/gpio.h> #include <asm/io.h> +#include <errno.h> #define GPIO_INPUT 0x0 #define GPIO_OUTPUT 0x1 -/* 0x4 means that we want DAT and not CON register */ -#define GPIO_PORT(x) ((((x) >> 5) & 0x3) + 0x4) -#define GPIO_BIT(x) ((x) & 0x3f) +#define S3C_GPIO_CON 0x0 +#define S3C_GPIO_DAT 0x4 -/* - * It's how we calculate the full port address - * We have to get the number of the port + 1 (Port A is at 0x56000001 ...) - * We move it at the second digit, and finally we add 0x4 because we want - * to modify GPIO DAT and not CON - */ -#define GPIO_FULLPORT(x) (S3C24X0_GPIO_BASE | ((GPIO_PORT(gpio) + 1) << 1)) +static uint32_t s3c_gpio_get_bank_addr(unsigned gpio) +{ + /* There is up to 16 pins per bank, one bank is 0x10 big. */ + uint32_t addr = gpio & ~0xf; + + if (addr >= 0x80 && addr != 0xd0) { /* Wrong GPIO bank. */ + printf("Invalid GPIO bank (bank %02x)\n", addr); + return 0xffffffff; + } + + return addr | S3C24X0_GPIO_BASE; +} int gpio_set_value(unsigned gpio, int value) { - unsigned l = readl(GPIO_FULLPORT(gpio)); - unsigned bit; - unsigned port = GPIO_FULLPORT(gpio); - - /* - * All GPIO Port have a configuration on - * 2 bits excepted the first GPIO (A) which - * have only 1 bit of configuration. - */ - if (!GPIO_PORT(gpio)) - bit = (0x1 << GPIO_BIT(gpio)); - else - bit = (0x3 << GPIO_BIT(gpio)); + uint32_t addr = s3c_gpio_get_bank_addr(gpio); + + if (addr == 0xffffffff) + return -EINVAL; if (value) - l |= bit; + setbits_le32(addr | S3C_GPIO_DAT, 1 << (gpio & 0xf)); else - l &= ~bit; + clrbits_le32(addr | S3C_GPIO_DAT, 1 << (gpio & 0xf)); - return writel(l, port); + return 0; } int gpio_get_value(unsigned gpio) { - unsigned l = readl(GPIO_FULLPORT(gpio)); + uint32_t addr = s3c_gpio_get_bank_addr(gpio); + + if (addr == 0xffffffff) + return -EINVAL; - if (GPIO_PORT(gpio) == 0) /* PORT A */ - return (l >> GPIO_BIT(gpio)) & 0x1; - return (l >> GPIO_BIT(gpio)) & 0x3; + return !!(readl(addr | S3C_GPIO_DAT) & (1 << (gpio & 0xf))); } int gpio_request(unsigned gpio, const char *label) @@ -67,13 +64,25 @@ int gpio_free(unsigned gpio) return 0; } +static int s3c_gpio_direction(unsigned gpio, uint8_t dir) +{ + uint32_t addr = s3c_gpio_get_bank_addr(gpio); + const uint32_t mask = 0x3 << ((gpio & 0xf) << 1); + const uint32_t dirm = dir << ((gpio & 0xf) << 1); + + if (addr == 0xffffffff) + return -EINVAL; + + clrsetbits_le32(addr | S3C_GPIO_CON, mask, dirm); + return 0; +} + int gpio_direction_input(unsigned gpio) { - return writel(GPIO_INPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio)); + return s3c_gpio_direction(gpio, GPIO_INPUT); } int gpio_direction_output(unsigned gpio, int value) { - writel(GPIO_OUTPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio)); - return gpio_set_value(gpio, value); + return s3c_gpio_direction(gpio, GPIO_OUTPUT); } diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 27ff587..c053e84 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -165,7 +165,7 @@ static int GetI2CSDA(void) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); -#ifdef CONFIG_S3C2410 +#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) return (readl(&gpio->gpedat) & 0x8000) >> 15; #endif #ifdef CONFIG_S3C2400 @@ -177,7 +177,7 @@ static void SetI2CSCL(int x) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); -#ifdef CONFIG_S3C2410 +#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat); #endif @@ -443,7 +443,7 @@ static void s3c24x0_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) int i; if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) { -#ifdef CONFIG_S3C2410 +#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) ulong old_gpecon = readl(&gpio->gpecon); #endif #ifdef CONFIG_S3C2400 @@ -452,7 +452,7 @@ static void s3c24x0_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) /* bus still busy probably by (most) previously interrupted transfer */ -#ifdef CONFIG_S3C2410 +#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */ writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000, &gpio->gpecon); @@ -478,7 +478,7 @@ static void s3c24x0_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) udelay(1000); /* restore pin functions */ -#ifdef CONFIG_S3C2410 +#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440) writel(old_gpecon, &gpio->gpecon); #endif #ifdef CONFIG_S3C2400 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 72825c3..3024357 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -32,6 +32,51 @@ config NAND_DENALI_SPARE_AREA_SKIP_BYTES of OOB area before last ECC sector data starts. This is potentially used to preserve the bad block marker in the OOB area. +config NAND_VF610_NFC + bool "Support for Freescale NFC for VF610/MPC5125" + select SYS_NAND_SELF_INIT + help + Enables support for NAND Flash Controller on some Freescale + processors like the VF610, MPC5125, MCF54418 or Kinetis K70. + The driver supports a maximum 2k page size. The driver + currently does not support hardware ECC. + +choice + prompt "Hardware ECC strength" + depends on NAND_VF610_NFC + default SYS_NAND_VF610_NFC_45_ECC_BYTES + help + Select the ECC strength used in the hardware BCH ECC block. + +config SYS_NAND_VF610_NFC_45_ECC_BYTES + bool "24-error correction (45 ECC bytes)" + +config SYS_NAND_VF610_NFC_60_ECC_BYTES + bool "32-error correction (60 ECC bytes)" + +endchoice + +comment "Generic NAND options" + +# Enhance depends when converting drivers to Kconfig which use this config +# option (mxc_nand, ndfc, omap_gpmc). +config SYS_NAND_BUSWIDTH_16BIT + bool "Use 16-bit NAND interface" + depends on NAND_VF610_NFC + help + Indicates that NAND device has 16-bit wide data-bus. In absence of this + config, bus-width of NAND device is assumed to be either 8-bit and later + determined by reading ONFI params. + Above config is useful when NAND device's bus-width information cannot + be determined from on-chip ONFI params, like in following scenarios: + - SPL boot does not support reading of ONFI parameters. This is done to + keep SPL code foot-print small. + - In current U-Boot flow using nand_init(), driver initialization + happens in board_nand_init() which is called before any device probe + (nand_scan_ident + nand_scan_tail), thus device's ONFI parameters are + not available while configuring controller. So a static CONFIG_NAND_xx + is needed to know the device's bus-width in advance. + if SPL config SPL_NAND_DENALI diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index e85832d..b3a0edb 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -679,6 +679,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr) if (priv->bank >= MAX_BANKS) { printf("fsl_elbc_nand: address did not match any " "chip selects\n"); + kfree(priv); return -ENODEV; } diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 2d2b938..9c144a2 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -36,7 +36,7 @@ #define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 0 #endif #define MXS_NAND_METADATA_SIZE 10 - +#define MXS_NAND_BITS_PER_ECC_LEVEL 13 #define MXS_NAND_COMMAND_BUFFER_SIZE 32 #define MXS_NAND_BCH_TIMEOUT 10000 @@ -135,7 +135,7 @@ static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size) static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength) { - return ecc_strength * 13; + return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL; } static uint32_t mxs_nand_aux_status_offset(void) @@ -146,26 +146,21 @@ static uint32_t mxs_nand_aux_status_offset(void) static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, uint32_t page_oob_size) { - if (page_data_size == 2048) { - if (page_oob_size == 64) - return 8; - - if (page_oob_size == 112) - return 14; - } - - if (page_data_size == 4096) { - if (page_oob_size == 128) - return 8; - - if (page_oob_size == 218) - return 16; + int ecc_strength; - if (page_oob_size == 224) - return 16; - } + /* + * Determine the ECC layout with the formula: + * ECC bits per chunk = (total page spare data bits) / + * (bits per ECC level) / (chunks per page) + * where: + * total page spare data bits = + * (page oob size - meta data size) * (bits per byte) + */ + ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) + / (MXS_NAND_BITS_PER_ECC_LEVEL * + mxs_nand_ecc_chunk_cnt(page_data_size)); - return 0; + return round_down(ecc_strength, 2); } static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 12dd26a..ee2c24d 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -483,7 +483,7 @@ int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs) memcpy(&vops, ops, sizeof(vops)); - vops.datbuf = malloc(verlen); + vops.datbuf = memalign(ARCH_DMA_MINALIGN, verlen); if (!vops.datbuf) return -ENOMEM; @@ -520,7 +520,7 @@ int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf) int rval = 0; size_t verofs; size_t verlen = nand->writesize; - uint8_t *verbuf = malloc(verlen); + uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen); if (!verbuf) return -ENOMEM; diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index d98dd28..5c11ac9 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -62,6 +62,7 @@ * Briefly these are bitmasks of controller cycles. */ #define READ_PAGE_CMD_CODE 0x7EE0 +#define READ_ONFI_PARAM_CMD_CODE 0x4860 #define PROGRAM_PAGE_CMD_CODE 0x7FC0 #define ERASE_CMD_CODE 0x4EC0 #define READ_ID_CMD_CODE 0x4804 @@ -71,6 +72,7 @@ /* NFC ECC mode define */ #define ECC_BYPASS 0 #define ECC_45_BYTE 6 +#define ECC_60_BYTE 7 /*** Register Mask and bit definitions */ @@ -145,43 +147,21 @@ struct vf610_nfc { struct nand_chip chip; void __iomem *regs; uint column; - int spareonly; - int page_sz; - int page; /* Status and ID are in alternate locations. */ int alt_buf; #define ALT_BUF_ID 1 #define ALT_BUF_STAT 2 +#define ALT_BUF_ONFI 3 struct clk *clk; }; #define mtd_to_nfc(_mtd) \ (struct vf610_nfc *)((struct nand_chip *)_mtd->priv)->priv -static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; -static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; - -static struct nand_bbt_descr bbt_main_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | - NAND_BBT_2BIT | NAND_BBT_VERSION, - .offs = 11, - .len = 4, - .veroffs = 15, - .maxblocks = 4, - .pattern = bbt_pattern, -}; - -static struct nand_bbt_descr bbt_mirror_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | - NAND_BBT_2BIT | NAND_BBT_VERSION, - .offs = 11, - .len = 4, - .veroffs = 15, - .maxblocks = 4, - .pattern = mirror_pattern, -}; +#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES) +#define ECC_HW_MODE ECC_45_BYTE -static struct nand_ecclayout vf610_nfc_ecc45 = { +static struct nand_ecclayout vf610_nfc_ecc = { .eccbytes = 45, .eccpos = {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -193,6 +173,24 @@ static struct nand_ecclayout vf610_nfc_ecc45 = { {.offset = 8, .length = 11} } }; +#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES) +#define ECC_HW_MODE ECC_60_BYTE + +static struct nand_ecclayout vf610_nfc_ecc = { + .eccbytes = 60, + .eccpos = { 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63 }, + .oobfree = { + {.offset = 2, + .length = 2} } +}; +#endif static inline u32 vf610_nfc_read(struct mtd_info *mtd, uint reg) { @@ -320,8 +318,8 @@ static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) { if (column != -1) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); - if (nfc->chip.options | NAND_BUSWIDTH_16) - column = column/2; + if (nfc->chip.options & NAND_BUSWIDTH_16) + column = column / 2; vf610_nfc_set_field(mtd, NFC_COL_ADDR, COL_ADDR_MASK, COL_ADDR_SHIFT, column); } @@ -330,6 +328,13 @@ static void vf610_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) ROW_ADDR_SHIFT, page); } +static inline void vf610_nfc_ecc_mode(struct mtd_info *mtd, int ecc_mode) +{ + vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, + CONFIG_ECC_MODE_MASK, + CONFIG_ECC_MODE_SHIFT, ecc_mode); +} + static inline void vf610_nfc_transfer_size(void __iomem *regbase, int size) { __raw_writel(size, regbase + NFC_SECTOR_SIZE); @@ -340,45 +345,64 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, int column, int page) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); + int page_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0; - nfc->column = max(column, 0); - nfc->spareonly = 0; - nfc->alt_buf = 0; + nfc->column = max(column, 0); + nfc->alt_buf = 0; switch (command) { + case NAND_CMD_SEQIN: + /* Use valid column/page from preread... */ + vf610_nfc_addr_cycle(mtd, column, page); + /* + * SEQIN => data => PAGEPROG sequence is done by the controller + * hence we do not need to issue the command here... + */ + return; case NAND_CMD_PAGEPROG: - nfc->page = -1; - vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); + page_sz += mtd->writesize + mtd->oobsize; + vf610_nfc_transfer_size(nfc->regs, page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_SEQIN, command, PROGRAM_PAGE_CMD_CODE); - vf610_nfc_addr_cycle(mtd, column, page); + vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); break; case NAND_CMD_RESET: vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, RESET_CMD_CODE); break; - /* - * NFC does not support sub-page reads and writes, - * so emulate them using full page transfers. - */ + case NAND_CMD_READOOB: - nfc->spareonly = 1; - case NAND_CMD_SEQIN: /* Pre-read for partial writes. */ + page_sz += mtd->oobsize; + column = mtd->writesize; + vf610_nfc_transfer_size(nfc->regs, page_sz); + vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, + NAND_CMD_READSTART, READ_PAGE_CMD_CODE); + vf610_nfc_addr_cycle(mtd, column, page); + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); + break; + case NAND_CMD_READ0: + page_sz += mtd->writesize + mtd->oobsize; column = 0; - /* Already read? */ - if (nfc->page == page) - return; - nfc->page = page; - vf610_nfc_transfer_size(nfc->regs, nfc->page_sz); + vf610_nfc_transfer_size(nfc->regs, page_sz); vf610_nfc_send_commands(nfc->regs, NAND_CMD_READ0, NAND_CMD_READSTART, READ_PAGE_CMD_CODE); vf610_nfc_addr_cycle(mtd, column, page); + vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); + break; + + case NAND_CMD_PARAM: + nfc->alt_buf = ALT_BUF_ONFI; + vf610_nfc_transfer_size(nfc->regs, 768); + vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM, + READ_ONFI_PARAM_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); break; case NAND_CMD_ERASE1: - nfc->page = -1; vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_commands(nfc->regs, command, NAND_CMD_ERASE2, ERASE_CMD_CODE); @@ -387,8 +411,11 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_READID: nfc->alt_buf = ALT_BUF_ID; + nfc->column = 0; vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); break; case NAND_CMD_STATUS: @@ -404,46 +431,19 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_done(mtd); } -static inline void vf610_nfc_read_spare(struct mtd_info *mtd, void *buf, - int len) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - - len = min(mtd->oobsize, (uint)len); - if (len > 0) - vf610_nfc_memcpy(buf, nfc->regs + mtd->writesize, len); -} - /* Read data from NFC buffers */ static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); uint c = nfc->column; - uint l; - /* Handle main area */ - if (!nfc->spareonly) { - l = min((uint)len, mtd->writesize - c); - nfc->column += l; - - if (!nfc->alt_buf) - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, - l); - else - if (nfc->alt_buf & ALT_BUF_ID) - *buf = vf610_nfc_get_id(mtd, c); - else - *buf = vf610_nfc_get_status(mtd); - - buf += l; - len -= l; - } + /* Alternate buffers are only supported through read_byte */ + if (nfc->alt_buf) + return; - /* Handle spare area access */ - if (len) { - nfc->column += len; - vf610_nfc_read_spare(mtd, buf, len); - } + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); + + nfc->column += len; } /* Write data to NFC buffers */ @@ -462,8 +462,29 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const u_char *buf, /* Read byte from NFC buffers */ static u8 vf610_nfc_read_byte(struct mtd_info *mtd) { + struct vf610_nfc *nfc = mtd_to_nfc(mtd); u8 tmp; - vf610_nfc_read_buf(mtd, &tmp, sizeof(tmp)); + uint c = nfc->column; + + switch (nfc->alt_buf) { + case ALT_BUF_ID: + tmp = vf610_nfc_get_id(mtd, c); + break; + case ALT_BUF_STAT: + tmp = vf610_nfc_get_status(mtd); + break; + case ALT_BUF_ONFI: +#ifdef __LITTLE_ENDIAN + /* Reverse byte since the controller uses big endianness */ + c = nfc->column ^ 0x3; + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; +#endif + default: + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; + } + nfc->column++; return tmp; } @@ -532,10 +553,8 @@ static inline int vf610_nfc_correct_data(struct mtd_info *mtd, u_char *dat) flip = count_written_bits(dat, nfc->chip.ecc.size, ecc_count); /* ECC failed. */ - if (flip > ecc_count) { - nfc->page = -1; + if (flip > ecc_count && flip > (nfc->chip.ecc.strength / 2)) return -1; - } /* Erased page. */ memset(dat, 0xff, nfc->chip.ecc.size); @@ -613,13 +632,11 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) mtd->priv = chip; chip->priv = nfc; - if (cfg.width == 16) { + if (cfg.width == 16) chip->options |= NAND_BUSWIDTH_16; - vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } else { - chip->options &= ~NAND_BUSWIDTH_16; - vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } + + /* Use 8-bit mode during initialization */ + vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); /* Disable subpage writes as we do not provide ecc->hwctl */ chip->options |= NAND_NO_SUBPAGE_WRITE; @@ -634,18 +651,8 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) /* Bad block options. */ if (cfg.flash_bbt) - chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_CREATE; - - /* Default to software ECC until flash ID. */ - vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, - CONFIG_ECC_MODE_MASK, - CONFIG_ECC_MODE_SHIFT, ECC_BYPASS); - - chip->bbt_td = &bbt_main_descr; - chip->bbt_md = &bbt_mirror_descr; - - nfc->page_sz = PAGE_2K + OOB_64; - nfc->page_sz += cfg.width == 16 ? 1 : 0; + chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB | + NAND_BBT_CREATE; /* Set configuration register. */ vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT); @@ -672,17 +679,17 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) goto error; } - chip->ecc.mode = NAND_ECC_SOFT; /* default */ + if (cfg.width == 16) + vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - nfc->page_sz = mtd->writesize + mtd->oobsize; + chip->ecc.mode = NAND_ECC_SOFT; /* default */ /* Single buffer only, max 256 OOB minus ECC status */ - if (nfc->page_sz > PAGE_2K + 256 - 8) { + if (mtd->writesize + mtd->oobsize > PAGE_2K + 256 - 8) { dev_err(nfc->dev, "Unsupported flash size\n"); err = -ENXIO; goto error; } - nfc->page_sz += cfg.width == 16 ? 1 : 0; if (cfg.hardware_ecc) { if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) { @@ -691,7 +698,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) goto error; } - chip->ecc.layout = &vf610_nfc_ecc45; + /* Current HW ECC layouts only use 64 bytes of OOB */ + if (mtd->oobsize > 64) + mtd->oobsize = 64; /* propagate ecc.layout to mtd_info */ mtd->ecclayout = chip->ecc.layout; @@ -699,14 +708,15 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) chip->ecc.write_page = vf610_nfc_write_page; chip->ecc.mode = NAND_ECC_HW; - chip->ecc.bytes = 45; chip->ecc.size = PAGE_2K; + chip->ecc.layout = &vf610_nfc_ecc; +#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES) chip->ecc.strength = 24; - - /* set ECC mode to 45 bytes OOB with 24 bits correction */ - vf610_nfc_set_field(mtd, NFC_FLASH_CONFIG, - CONFIG_ECC_MODE_MASK, - CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE); + chip->ecc.bytes = 45; +#elif defined(CONFIG_SYS_NAND_VF610_NFC_60_ECC_BYTES) + chip->ecc.strength = 32; + chip->ecc.bytes = 60; +#endif /* Enable ECC_STATUS */ vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT); diff --git a/drivers/net/bcm-sf2-eth.c b/drivers/net/bcm-sf2-eth.c index 51d5146..eab4c1f 100644 --- a/drivers/net/bcm-sf2-eth.c +++ b/drivers/net/bcm-sf2-eth.c @@ -154,12 +154,6 @@ static int bcm_sf2_eth_open(struct eth_device *dev, bd_t *bt) debug("Enabling BCM SF2 Ethernet.\n"); - /* Set MAC address from env */ - if (bcm_sf2_eth_write_hwaddr(dev) != 0) { - error("%s: MAC set error when opening !\n", __func__); - return -1; - } - eth->enable_mac(); /* enable tx and rx DMA */ diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 07281a6..ae51cf3 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -243,10 +243,6 @@ static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr) mdelay(100); }; - /* Soft reset above clears HW address registers. - * So we have to set it here once again */ - _dw_write_hwaddr(priv, enetaddr); - rx_descs_init(priv); tx_descs_init(priv); diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index ccd2131..3c41cec 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -343,13 +343,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) printf("MAC: %pM\n", dev->enetaddr); if (!is_valid_ethaddr(dev->enetaddr)) { -#ifdef CONFIG_RANDOM_MACADDR - printf("Bad MAC address (uninitialized EEPROM?), randomizing\n"); - net_random_ethaddr(dev->enetaddr); - printf("MAC: %pM\n", dev->enetaddr); -#else printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n"); -#endif } /* fill device MAC address registers */ diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c index 4bae9ad..4f17015 100644 --- a/drivers/net/ftmac110.c +++ b/drivers/net/ftmac110.c @@ -424,9 +424,6 @@ int ftmac110_initialize(bd_t *bis) dev->send = ftmac110_send; dev->recv = ftmac110_recv; - if (!eth_getenv_enetaddr_by_index("eth", card_nr, dev->enetaddr)) - net_random_ethaddr(dev->enetaddr); - /* allocate tx descriptors (it must be 16 bytes aligned) */ chip->txd = dma_alloc_coherent( sizeof(struct ftmac110_desc) * CFG_TXDES_NUM, &chip->txd_dma); diff --git a/drivers/net/greth.c b/drivers/net/greth.c index a93b37a..9bc8a8d 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -12,6 +12,7 @@ #include <common.h> #include <command.h> +#include <errno.h> #include <net.h> #include <netdev.h> #include <malloc.h> @@ -653,13 +654,8 @@ int greth_initialize(bd_t * bis) } } } else { - /* HW Address not found in environment, Set default HW address */ - addr[0] = GRETH_HWADDR_0; /* MSB */ - addr[1] = GRETH_HWADDR_1; - addr[2] = GRETH_HWADDR_2; - addr[3] = GRETH_HWADDR_3; - addr[4] = GRETH_HWADDR_4; - addr[5] = GRETH_HWADDR_5; /* LSB */ + /* No ethaddr set */ + return -EINVAL; } /* set and remember MAC address */ diff --git a/drivers/net/lan91c96.c b/drivers/net/lan91c96.c index 495c088..c4dd01e 100644 --- a/drivers/net/lan91c96.c +++ b/drivers/net/lan91c96.c @@ -725,12 +725,6 @@ static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev) static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac) { -#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ - char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; - - memcpy (v_rom_mac, hw_mac_addr, 6); - return (1); -#else int i; SMC_SELECT_BANK(dev, 1); for (i=0; i<6; i++) @@ -738,7 +732,6 @@ static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac) v_rom_mac[i] = SMC_inb(dev, LAN91C96_IA0 + i); } return (1); -#endif } /* Structure to detect the device IDs */ diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 4e1a7fe..f949161 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -525,7 +525,6 @@ static int macb_phy_init(struct macb_device *macb) return 1; } -static int macb_write_hwaddr(struct eth_device *dev); static int macb_init(struct eth_device *netdev, bd_t *bd) { struct macb_device *macb = to_macb(netdev); @@ -594,14 +593,6 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) #endif /* CONFIG_RMII */ } - /* update the ethaddr */ - if (is_valid_ethaddr(netdev->enetaddr)) { - macb_write_hwaddr(netdev); - } else { - printf("%s: mac address is not valid\n", netdev->name); - return -1; - } - if (!macb_phy_init(macb)) return -1; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f5221a3..c8d08e8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -21,6 +21,8 @@ #include <linux/err.h> #include <linux/compiler.h> +DECLARE_GLOBAL_DATA_PTR; + /* Generic PHY support and helper functions */ /** @@ -494,6 +496,20 @@ int phy_register(struct phy_driver *drv) INIT_LIST_HEAD(&drv->list); list_add_tail(&drv->list, &phy_drivers); +#ifdef CONFIG_NEEDS_MANUAL_RELOC + if (drv->probe) + drv->probe += gd->reloc_off; + if (drv->config) + drv->config += gd->reloc_off; + if (drv->startup) + drv->startup += gd->reloc_off; + if (drv->shutdown) + drv->shutdown += gd->reloc_off; + if (drv->readext) + drv->readext += gd->reloc_off; + if (drv->writeext) + drv->writeext += gd->reloc_off; +#endif return 0; } diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index ee97079..79452a8 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -29,6 +29,19 @@ /* RTL8211x PHY Interrupt Status Register */ #define MIIM_RTL8211x_PHY_INSR 0x13 +/* RTL8211F PHY Status Register */ +#define MIIM_RTL8211F_PHY_STATUS 0x1a +#define MIIM_RTL8211F_AUTONEG_ENABLE 0x1000 +#define MIIM_RTL8211F_PHYSTAT_SPEED 0x0030 +#define MIIM_RTL8211F_PHYSTAT_GBIT 0x0020 +#define MIIM_RTL8211F_PHYSTAT_100 0x0010 +#define MIIM_RTL8211F_PHYSTAT_DUPLEX 0x0008 +#define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800 +#define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 + +#define MIIM_RTL8211F_PAGE_SELECT 0x1f +#define MIIM_RTL8211F_TX_DELAY 0x100 + /* RealTek RTL8211x */ static int rtl8211x_config(struct phy_device *phydev) { @@ -48,6 +61,29 @@ static int rtl8211x_config(struct phy_device *phydev) return 0; } +static int rtl8211f_config(struct phy_device *phydev) +{ + u16 reg; + + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { + /* enable TXDLY */ + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0xd08); + reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); + reg |= MIIM_RTL8211F_TX_DELAY; + phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); + /* restore to default page 0 */ + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0x0); + } + + genphy_config_aneg(phydev); + + return 0; +} + static int rtl8211x_parse_status(struct phy_device *phydev) { unsigned int speed; @@ -105,6 +141,51 @@ static int rtl8211x_parse_status(struct phy_device *phydev) return 0; } +static int rtl8211f_parse_status(struct phy_device *phydev) +{ + unsigned int speed; + unsigned int mii_reg; + int i = 0; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43); + mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS); + + phydev->link = 1; + while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) { + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + phydev->link = 0; + break; + } + + if ((i++ % 1000) == 0) + putc('.'); + udelay(1000); + mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PHY_STATUS); + } + + if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED); + + switch (speed) { + case MIIM_RTL8211F_PHYSTAT_GBIT: + phydev->speed = SPEED_1000; + break; + case MIIM_RTL8211F_PHYSTAT_100: + phydev->speed = SPEED_100; + break; + default: + phydev->speed = SPEED_10; + } + + return 0; +} + static int rtl8211x_startup(struct phy_device *phydev) { /* Read the Status (2x to make sure link is right) */ @@ -114,6 +195,15 @@ static int rtl8211x_startup(struct phy_device *phydev) return 0; } +static int rtl8211f_startup(struct phy_device *phydev) +{ + /* Read the Status (2x to make sure link is right) */ + genphy_update_link(phydev); + rtl8211f_parse_status(phydev); + + return 0; +} + /* Support for RTL8211B PHY */ static struct phy_driver RTL8211B_driver = { .name = "RealTek RTL8211B", @@ -147,10 +237,22 @@ static struct phy_driver RTL8211DN_driver = { .shutdown = &genphy_shutdown, }; +/* Support for RTL8211F PHY */ +static struct phy_driver RTL8211F_driver = { + .name = "RealTek RTL8211F", + .uid = 0x1cc916, + .mask = 0xffffff, + .features = PHY_GBIT_FEATURES, + .config = &rtl8211f_config, + .startup = &rtl8211f_startup, + .shutdown = &genphy_shutdown, +}; + int phy_realtek_init(void) { phy_register(&RTL8211B_driver); phy_register(&RTL8211E_driver); + phy_register(&RTL8211F_driver); phy_register(&RTL8211DN_driver); return 0; diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 48dbdf5..269083b 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -558,8 +558,12 @@ static void sunxi_lcdc_init(void) /* Clock on */ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0); #ifdef CONFIG_VIDEO_LCD_IF_LVDS +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS); +#else setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST); #endif +#endif /* Init lcdc */ writel(0, &lcdc->ctrl); /* Disable tcon */ @@ -582,6 +586,16 @@ static void sunxi_lcdc_enable(void) #ifdef CONFIG_VIDEO_LCD_IF_LVDS setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE); setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + udelay(2); /* delay at least 1200 ns */ + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB); + udelay(2); /* delay at least 1200 ns */ + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC); + if (sunxi_display.depth == 18) + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7)); + else + setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf)); +#else setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE); udelay(2); /* delay at least 1200 ns */ setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1); @@ -589,6 +603,7 @@ static void sunxi_lcdc_enable(void) setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2); setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE); #endif +#endif } static void sunxi_lcdc_panel_enable(void) @@ -706,7 +721,8 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, #endif #ifdef CONFIG_VIDEO_LCD_IF_LVDS val = (sunxi_display.depth == 18) ? 1 : 0; - writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val), &lcdc->tcon0_lvds_intf); + writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) | + SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf); #endif if (sunxi_display.depth == 18 || sunxi_display.depth == 16) { |