summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/s3c2440_gpio.c75
-rw-r--r--drivers/i2c/s3c24x0_i2c.c10
-rw-r--r--drivers/mtd/nand/Kconfig45
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c1
-rw-r--r--drivers/mtd/nand/mxs_nand.c35
-rw-r--r--drivers/mtd/nand/nand_util.c4
-rw-r--r--drivers/mtd/nand/vf610_nfc.c234
-rw-r--r--drivers/net/bcm-sf2-eth.c6
-rw-r--r--drivers/net/designware.c4
-rw-r--r--drivers/net/dm9000x.c6
-rw-r--r--drivers/net/ftmac110.c3
-rw-r--r--drivers/net/greth.c10
-rw-r--r--drivers/net/lan91c96.c7
-rw-r--r--drivers/net/macb.c9
-rw-r--r--drivers/net/phy/phy.c16
-rw-r--r--drivers/net/phy/realtek.c102
-rw-r--r--drivers/video/sunxi_display.c18
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) {