summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bios_emulator/Makefile3
-rw-r--r--drivers/misc/fsl_ifc.c24
-rw-r--r--drivers/misc/gpio_led.c33
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/atmel_nand.c40
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c99
-rw-r--r--drivers/mtd/nand/fsl_ifc_spl.c7
-rw-r--r--drivers/mtd/nand/omap_elm.c196
-rw-r--r--drivers/mtd/nand/omap_gpmc.c321
-rw-r--r--drivers/mtd/onenand/onenand_base.c15
-rw-r--r--drivers/net/designware.c2
-rw-r--r--drivers/net/designware.h7
-rw-r--r--drivers/net/dm9000x.c9
-rw-r--r--drivers/net/e1000.c34
-rw-r--r--drivers/net/e1000.h9
-rw-r--r--drivers/net/fsl_mdio.c17
-rw-r--r--drivers/net/mvgbe.c5
-rw-r--r--drivers/net/npe/Makefile1
-rw-r--r--drivers/net/phy/atheros.c8
-rw-r--r--drivers/net/phy/micrel.c34
-rw-r--r--drivers/net/phy/phy.c5
-rw-r--r--drivers/net/phy/realtek.c6
-rw-r--r--drivers/net/phy/smsc.c3
-rw-r--r--drivers/net/phy/vitesse.c69
-rw-r--r--drivers/net/rtl8139.c2
-rw-r--r--drivers/net/rtl8169.c90
-rw-r--r--drivers/net/sh_eth.c51
-rw-r--r--drivers/net/sh_eth.h34
-rw-r--r--drivers/net/tsec.c199
-rw-r--r--drivers/net/zynq_gem.c82
30 files changed, 1056 insertions, 350 deletions
diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile
index 6f74fdc..52a2ceb 100644
--- a/drivers/bios_emulator/Makefile
+++ b/drivers/bios_emulator/Makefile
@@ -8,9 +8,8 @@ obj-y = atibios.o biosemu.o besys.o bios.o \
$(X86DIR)/sys.o \
$(X86DIR)/debug.o
-EXTRA_CFLAGS += -I. -I./include -I$(TOPDIR)/include \
+EXTRA_CFLAGS += -I. -I./include \
-D__PPC__ -D__BIG_ENDIAN__
CFLAGS += $(EXTRA_CFLAGS)
-HOSTCFLAGS += $(EXTRA_CFLAGS)
CPPFLAGS += $(EXTRA_CFLAGS)
diff --git a/drivers/misc/fsl_ifc.c b/drivers/misc/fsl_ifc.c
index 507c4de..be61973 100644
--- a/drivers/misc/fsl_ifc.c
+++ b/drivers/misc/fsl_ifc.c
@@ -34,6 +34,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR0_EXT
set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR0_EXT
+ set_ifc_csor_ext(IFC_CS0, CONFIG_SYS_CSOR0_EXT);
+#endif
set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0);
set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0);
set_ifc_csor(IFC_CS0, CONFIG_SYS_CSOR0);
@@ -43,6 +46,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR1_EXT
set_ifc_cspr_ext(IFC_CS1, CONFIG_SYS_CSPR1_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR1_EXT
+ set_ifc_csor_ext(IFC_CS1, CONFIG_SYS_CSOR1_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR1) && defined(CONFIG_SYS_CSOR1)
set_ifc_ftim(IFC_CS1, IFC_FTIM0, CONFIG_SYS_CS1_FTIM0);
set_ifc_ftim(IFC_CS1, IFC_FTIM1, CONFIG_SYS_CS1_FTIM1);
@@ -57,6 +63,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR2_EXT
set_ifc_cspr_ext(IFC_CS2, CONFIG_SYS_CSPR2_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR2_EXT
+ set_ifc_csor_ext(IFC_CS2, CONFIG_SYS_CSOR2_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR2) && defined(CONFIG_SYS_CSOR2)
set_ifc_ftim(IFC_CS2, IFC_FTIM0, CONFIG_SYS_CS2_FTIM0);
set_ifc_ftim(IFC_CS2, IFC_FTIM1, CONFIG_SYS_CS2_FTIM1);
@@ -71,6 +80,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR3_EXT
set_ifc_cspr_ext(IFC_CS3, CONFIG_SYS_CSPR3_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR3_EXT
+ set_ifc_csor_ext(IFC_CS3, CONFIG_SYS_CSOR3_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR3) && defined(CONFIG_SYS_CSOR3)
set_ifc_ftim(IFC_CS3, IFC_FTIM0, CONFIG_SYS_CS3_FTIM0);
set_ifc_ftim(IFC_CS3, IFC_FTIM1, CONFIG_SYS_CS3_FTIM1);
@@ -85,6 +97,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR4_EXT
set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR4_EXT
+ set_ifc_csor_ext(IFC_CS4, CONFIG_SYS_CSOR4_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4)
set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0);
set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1);
@@ -99,6 +114,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR5_EXT
set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR5_EXT
+ set_ifc_csor_ext(IFC_CS5, CONFIG_SYS_CSOR5_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5)
set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0);
set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1);
@@ -113,6 +131,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR6_EXT
set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR6_EXT
+ set_ifc_csor_ext(IFC_CS6, CONFIG_SYS_CSOR6_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6)
set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0);
set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1);
@@ -127,6 +148,9 @@ void init_early_memctl_regs(void)
#ifdef CONFIG_SYS_CSPR7_EXT
set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT);
#endif
+#ifdef CONFIG_SYS_CSOR7_EXT
+ set_ifc_csor_ext(IFC_CS7, CONFIG_SYS_CSOR7_EXT);
+#endif
#if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7)
set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0);
set_ifc_ftim(IFC_CS7, IFC_FTIM1, CONFIG_SYS_CS7_FTIM1);
diff --git a/drivers/misc/gpio_led.c b/drivers/misc/gpio_led.c
index 3fedddc..3e95727 100644
--- a/drivers/misc/gpio_led.c
+++ b/drivers/misc/gpio_led.c
@@ -9,15 +9,42 @@
#include <status_led.h>
#include <asm/gpio.h>
+#ifndef CONFIG_GPIO_LED_INVERTED_TABLE
+#define CONFIG_GPIO_LED_INVERTED_TABLE {}
+#endif
+
+static led_id_t gpio_led_inv[] = CONFIG_GPIO_LED_INVERTED_TABLE;
+
+static int gpio_led_gpio_value(led_id_t mask, int state)
+{
+ int i, gpio_value = (state == STATUS_LED_ON);
+
+ for (i = 0; i < ARRAY_SIZE(gpio_led_inv); i++) {
+ if (gpio_led_inv[i] == mask)
+ gpio_value = !gpio_value;
+ }
+
+ return gpio_value;
+}
+
void __led_init(led_id_t mask, int state)
{
- gpio_request(mask, "gpio_led");
- gpio_direction_output(mask, state == STATUS_LED_ON);
+ int gpio_value;
+
+ if (gpio_request(mask, "gpio_led") != 0) {
+ printf("%s: failed requesting GPIO%lu!\n", __func__, mask);
+ return;
+ }
+
+ gpio_value = gpio_led_gpio_value(mask, state);
+ gpio_direction_output(mask, gpio_value);
}
void __led_set(led_id_t mask, int state)
{
- gpio_set_value(mask, state == STATUS_LED_ON);
+ int gpio_value = gpio_led_gpio_value(mask, state);
+
+ gpio_set_value(mask, gpio_value);
}
void __led_toggle(led_id_t mask)
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index eb1eafa..e145cd1 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
obj-$(CONFIG_NAND_SPEAR) += spr_nand.o
obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o
obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
+obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_PLAT) += nand_plat.o
obj-$(CONFIG_NAND_DOCG4) += docg4.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index da83f06..16b7df0 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -412,7 +412,7 @@ static int pmecc_err_location(struct mtd_info *mtd)
}
if (!timeout) {
- printk(KERN_ERR "atmel_nand : Timeout to calculate PMECC error location\n");
+ dev_err(host->dev, "atmel_nand : Timeout to calculate PMECC error location\n");
return -1;
}
@@ -452,7 +452,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
*(buf + byte_pos) ^= (1 << bit_pos);
pos = sector_num * host->pmecc_sector_size + byte_pos;
- printk(KERN_INFO "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+ dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
pos, bit_pos, err_byte, *(buf + byte_pos));
} else {
/* Bit flip in OOB area */
@@ -462,7 +462,7 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
ecc[tmp] ^= (1 << bit_pos);
pos = tmp + nand_chip->ecc.layout->eccpos[0];
- printk(KERN_INFO "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+ dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
pos, bit_pos, err_byte, ecc[tmp]);
}
@@ -500,7 +500,7 @@ normal_check:
err_nbr = pmecc_err_location(mtd);
if (err_nbr == -1) {
- printk(KERN_ERR "PMECC: Too many errors\n");
+ dev_err(host->dev, "PMECC: Too many errors\n");
mtd->ecc_stats.failed++;
return -EIO;
} else {
@@ -544,7 +544,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
}
if (!timeout) {
- printk(KERN_ERR "atmel_nand : Timeout to read PMECC page\n");
+ dev_err(host->dev, "atmel_nand : Timeout to read PMECC page\n");
return -1;
}
@@ -584,7 +584,7 @@ static int 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");
+ dev_err(host->dev, "atmel_nand : Timeout to read PMECC status, fail to write PMECC in oob\n");
goto out;
}
@@ -827,6 +827,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
switch (mtd->writesize) {
case 2048:
case 4096:
+ case 8192:
host->pmecc_degree = (sector_size == 512) ?
PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14;
host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
@@ -840,8 +841,15 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
nand->ecc.steps = 1;
nand->ecc.bytes = host->pmecc_bytes_per_sector *
host->pmecc_sector_number;
+
+ if (nand->ecc.bytes > MTD_MAX_ECCPOS_ENTRIES_LARGE) {
+ dev_err(host->dev, "too large eccpos entries. max support ecc.bytes is %d\n",
+ MTD_MAX_ECCPOS_ENTRIES_LARGE);
+ return -EINVAL;
+ }
+
if (nand->ecc.bytes > mtd->oobsize - 2) {
- printk(KERN_ERR "No room for ECC bytes\n");
+ dev_err(host->dev, "No room for ECC bytes\n");
return -EINVAL;
}
pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
@@ -852,7 +860,7 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
case 512:
case 1024:
/* TODO */
- printk(KERN_ERR "Unsupported page size for PMECC, use Software ECC\n");
+ dev_err(host->dev, "Unsupported page size for PMECC, use Software ECC\n");
default:
/* page size not handled by HW ECC */
/* switching back to soft ECC */
@@ -1035,7 +1043,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* it doesn't seems to be a freshly
* erased block.
* We can't correct so many errors */
- printk(KERN_WARNING "atmel_nand : multiple errors detected."
+ dev_warn(host->dev, "atmel_nand : multiple errors detected."
" Unable to correct.\n");
return -EIO;
}
@@ -1045,12 +1053,12 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* there's nothing much to do here.
* the bit error is on the ECC itself.
*/
- printk(KERN_WARNING "atmel_nand : one bit error on ECC code."
+ dev_warn(host->dev, "atmel_nand : one bit error on ECC code."
" Nothing to correct\n");
return 0;
}
- printk(KERN_WARNING "atmel_nand : one bit error on data."
+ dev_warn(host->dev, "atmel_nand : one bit error on data."
" (word offset in the page :"
" 0x%x bit offset : 0x%x)\n",
ecc_word, ecc_bit);
@@ -1062,7 +1070,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
/* 8 bits words */
dat[ecc_word] ^= (1 << ecc_bit);
}
- printk(KERN_WARNING "atmel_nand : error corrected\n");
+ dev_warn(host->dev, "atmel_nand : error corrected\n");
return 1;
}
@@ -1178,7 +1186,11 @@ int atmel_nand_chip_init(int devnum, ulong base_addr)
mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
+#ifdef CONFIG_NAND_ECC_BCH
+ nand->ecc.mode = NAND_ECC_SOFT_BCH;
+#else
nand->ecc.mode = NAND_ECC_SOFT;
+#endif
#ifdef CONFIG_SYS_NAND_DBW_16
nand->options = NAND_BUSWIDTH_16;
#endif
@@ -1186,7 +1198,7 @@ int atmel_nand_chip_init(int devnum, ulong base_addr)
#ifdef CONFIG_SYS_NAND_READY_PIN
nand->dev_ready = at91_nand_ready;
#endif
- nand->chip_delay = 20;
+ nand->chip_delay = 75;
ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
if (ret)
@@ -1214,6 +1226,6 @@ void board_nand_init(void)
int i;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
if (atmel_nand_chip_init(i, base_addr[i]))
- printk(KERN_ERR "atmel_nand: Fail to initialize #%d chip",
+ dev_err(host->dev, "atmel_nand: Fail to initialize #%d chip",
i);
}
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 3b845b9..1808a7f 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -125,6 +125,69 @@ static struct nand_ecclayout oob_4096_ecc8 = {
.oobfree = { {2, 6}, {136, 82} },
};
+/* 8192-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_8192_ecc4 = {
+ .eccbytes = 128,
+ .eccpos = {
+ 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,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ },
+ .oobfree = { {2, 6}, {136, 208} },
+};
+
+/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
+static struct nand_ecclayout oob_8192_ecc8 = {
+ .eccbytes = 256,
+ .eccpos = {
+ 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,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263,
+ },
+ .oobfree = { {2, 6}, {264, 80} },
+};
/*
* Generic flash bbt descriptors
@@ -428,20 +491,27 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (mtd->writesize > 512) {
nand_fcr0 =
(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
+ (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
+ (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
out_be32(&ifc->ifc_nand.nand_fir0,
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
(IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT));
- out_be32(&ifc->ifc_nand.nand_fir1, 0);
+ (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT));
+ out_be32(&ifc->ifc_nand.nand_fir1,
+ (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+ (IFC_FIR_OP_RDSTAT <<
+ IFC_NAND_FIR1_OP6_SHIFT) |
+ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT));
} else {
nand_fcr0 = ((NAND_CMD_PAGEPROG <<
IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_SEQIN <<
- IFC_NAND_FCR0_CMD2_SHIFT));
+ IFC_NAND_FCR0_CMD2_SHIFT) |
+ (NAND_CMD_STATUS <<
+ IFC_NAND_FCR0_CMD3_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir0,
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@@ -450,7 +520,11 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
out_be32(&ifc->ifc_nand.nand_fir1,
- (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
+ (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+ (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+ (IFC_FIR_OP_RDSTAT <<
+ IFC_NAND_FIR1_OP7_SHIFT) |
+ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT));
if (column >= mtd->writesize)
nand_fcr0 |=
@@ -902,6 +976,21 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
priv->bufnum_mask = 1;
break;
+ case CSOR_NAND_PGS_8K:
+ if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+ CSOR_NAND_ECC_MODE_4) {
+ layout = &oob_8192_ecc4;
+ nand->ecc.strength = 4;
+ } else {
+ layout = &oob_8192_ecc8;
+ nand->ecc.strength = 8;
+ nand->ecc.bytes = 16;
+ }
+
+ priv->bufnum_mask = 0;
+ break;
+
+
default:
printf("ifc nand: bad csor %#x: bad page size\n", csor);
return -ENODEV;
diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c
index 3c8278d..9de327b 100644
--- a/drivers/mtd/nand/fsl_ifc_spl.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -112,10 +112,13 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
- if (csor & CSOR_NAND_PGS_4K) {
+ if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) {
+ page_size = 8192;
+ bufnum_mask = 0x0;
+ } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) {
page_size = 4096;
bufnum_mask = 0x1;
- } else if (csor & CSOR_NAND_PGS_2K) {
+ } else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) {
page_size = 2048;
bufnum_mask = 0x3;
} else {
diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/omap_elm.c
new file mode 100644
index 0000000..2aa7807
--- /dev/null
+++ b/drivers/mtd/nand/omap_elm.c
@@ -0,0 +1,196 @@
+/*
+ * (C) Copyright 2010-2011 Texas Instruments, <www.ti.com>
+ * Mansoor Ahamed <mansoor.ahamed@ti.com>
+ *
+ * BCH Error Location Module (ELM) support.
+ *
+ * NOTE:
+ * 1. Supports only continuous mode. Dont see need for page mode in uboot
+ * 2. Supports only syndrome polynomial 0. i.e. poly local variable is
+ * always set to ELM_DEFAULT_POLY. Dont see need for other polynomial
+ * sets in uboot
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/cpu.h>
+#include <asm/omap_gpmc.h>
+#include <asm/omap_elm.h>
+
+#define ELM_DEFAULT_POLY (0)
+
+struct elm *elm_cfg;
+
+/**
+ * elm_load_syndromes - Load BCH syndromes based on nibble selection
+ * @syndrome: BCH syndrome
+ * @nibbles:
+ * @poly: Syndrome Polynomial set to use
+ *
+ * Load BCH syndromes based on nibble selection
+ */
+static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly)
+{
+ u32 *ptr;
+ u32 val;
+
+ /* reg 0 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0];
+ val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) |
+ (syndrome[3] << 24);
+ writel(val, ptr);
+ /* reg 1 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1];
+ val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) |
+ (syndrome[7] << 24);
+ writel(val, ptr);
+
+ /* BCH 8-bit with 26 nibbles (4*8=32) */
+ if (nibbles > 13) {
+ /* reg 2 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2];
+ val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) |
+ (syndrome[11] << 24);
+ writel(val, ptr);
+ /* reg 3 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[3];
+ val = syndrome[12] | (syndrome[13] << 8) |
+ (syndrome[14] << 16) | (syndrome[15] << 24);
+ writel(val, ptr);
+ }
+
+ /* BCH 16-bit with 52 nibbles (7*8=56) */
+ if (nibbles > 26) {
+ /* reg 4 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4];
+ val = syndrome[16] | (syndrome[17] << 8) |
+ (syndrome[18] << 16) | (syndrome[19] << 24);
+ writel(val, ptr);
+
+ /* reg 5 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[5];
+ val = syndrome[20] | (syndrome[21] << 8) |
+ (syndrome[22] << 16) | (syndrome[23] << 24);
+ writel(val, ptr);
+
+ /* reg 6 */
+ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6];
+ val = syndrome[24] | (syndrome[25] << 8) |
+ (syndrome[26] << 16) | (syndrome[27] << 24);
+ writel(val, ptr);
+ }
+}
+
+/**
+ * elm_check_errors - Check for BCH errors and return error locations
+ * @syndrome: BCH syndrome
+ * @nibbles:
+ * @error_count: Returns number of errrors in the syndrome
+ * @error_locations: Returns error locations (in decimal) in this array
+ *
+ * Check the provided syndrome for BCH errors and return error count
+ * and locations in the array passed. Returns -1 if error is not correctable,
+ * else returns 0
+ */
+int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count,
+ u32 *error_locations)
+{
+ u8 poly = ELM_DEFAULT_POLY;
+ s8 i;
+ u32 location_status;
+
+ elm_load_syndromes(syndrome, nibbles, poly);
+
+ /* start processing */
+ writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6])
+ | ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID),
+ &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]);
+
+ /* wait for processing to complete */
+ while ((readl(&elm_cfg->irqstatus) & (0x1 << poly)) != 0x1)
+ ;
+ /* clear status */
+ writel((readl(&elm_cfg->irqstatus) | (0x1 << poly)),
+ &elm_cfg->irqstatus);
+
+ /* check if correctable */
+ location_status = readl(&elm_cfg->error_location[poly].location_status);
+ if (!(location_status & ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK))
+ return -1;
+
+ /* get error count */
+ *error_count = readl(&elm_cfg->error_location[poly].location_status) &
+ ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK;
+
+ for (i = 0; i < *error_count; i++) {
+ error_locations[i] =
+ readl(&elm_cfg->error_location[poly].error_location_x[i]);
+ }
+
+ return 0;
+}
+
+
+/**
+ * elm_config - Configure ELM module
+ * @level: 4 / 8 / 16 bit BCH
+ *
+ * Configure ELM module based on BCH level.
+ * Set mode as continuous mode.
+ * Currently we are using only syndrome 0 and syndromes 1 to 6 are not used.
+ * Also, the mode is set only for syndrome 0
+ */
+int elm_config(enum bch_level level)
+{
+ u32 val;
+ u8 poly = ELM_DEFAULT_POLY;
+ u32 buffer_size = 0x7FF;
+
+ /* config size and level */
+ val = (u32)(level) & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK;
+ val |= ((buffer_size << ELM_LOCATION_CONFIG_ECC_SIZE_POS) &
+ ELM_LOCATION_CONFIG_ECC_SIZE_MASK);
+ writel(val, &elm_cfg->location_config);
+
+ /* config continous mode */
+ /* enable interrupt generation for syndrome polynomial set */
+ writel((readl(&elm_cfg->irqenable) | (0x1 << poly)),
+ &elm_cfg->irqenable);
+ /* set continuous mode for the syndrome polynomial set */
+ writel((readl(&elm_cfg->page_ctrl) & ~(0x1 << poly)),
+ &elm_cfg->page_ctrl);
+
+ return 0;
+}
+
+/**
+ * elm_reset - Do a soft reset of ELM
+ *
+ * Perform a soft reset of ELM and return after reset is done.
+ */
+void elm_reset(void)
+{
+ /* initiate reset */
+ writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET),
+ &elm_cfg->sysconfig);
+
+ /* wait for reset complete and normal operation */
+ while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) !=
+ ELM_SYSSTATUS_RESETDONE)
+ ;
+}
+
+/**
+ * elm_init - Initialize ELM module
+ *
+ * Initialize ELM support. Currently it does only base address init
+ * and ELM reset.
+ */
+void elm_init(void)
+{
+ elm_cfg = (struct elm *)ELM_BASE;
+ elm_reset();
+}
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index ec1787f..5e7e6b3 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -15,15 +15,13 @@
#include <linux/bch.h>
#include <linux/compiler.h>
#include <nand.h>
-#ifdef CONFIG_AM33XX
-#include <asm/arch/elm.h>
-#endif
+#include <asm/omap_elm.h>
+
+#define BADBLOCK_MARKER_LENGTH 2
+#define SECTOR_BYTES 512
static uint8_t cs;
-static __maybe_unused struct nand_ecclayout hw_nand_oob =
- GPMC_NAND_HW_ECC_LAYOUT;
-static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
- GPMC_NAND_HW_BCH8_ECC_LAYOUT;
+static __maybe_unused struct nand_ecclayout omap_ecclayout;
/*
* omap_nand_hwcontrol - Set the address pointers corretly for the
@@ -233,6 +231,7 @@ struct nand_bch_priv {
uint8_t type;
uint8_t nibbles;
struct bch_control *control;
+ enum omap_ecc ecc_scheme;
};
/* bch types */
@@ -274,17 +273,15 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
{
uint32_t val;
uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-#ifdef CONFIG_AM33XX
uint32_t unused_length = 0;
-#endif
uint32_t wr_mode = BCH_WRAPMODE_6;
struct nand_bch_priv *bch = chip->priv;
/* Clear the ecc result registers, select ecc reg as 1 */
writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-#ifdef CONFIG_AM33XX
- wr_mode = BCH_WRAPMODE_1;
+ if (bch->ecc_scheme == OMAP_ECC_BCH8_CODE_HW) {
+ wr_mode = BCH_WRAPMODE_1;
switch (bch->nibbles) {
case ECC_BCH4_NIBBLES:
@@ -320,7 +317,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
val |= (unused_length << 22);
break;
}
-#else
+ } else {
/*
* This ecc_size_config setting is for BCH sw library.
*
@@ -333,7 +330,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
* size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
*/
val = (32 << 22) | (0 << 12);
-#endif
+ }
/* ecc size configuration */
writel(val, &gpmc_cfg->ecc_size_config);
@@ -376,9 +373,9 @@ static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
}
/*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * BCH support using ELM module
*/
-#ifdef CONFIG_AM33XX
+#ifdef CONFIG_NAND_OMAP_ELM
/*
* omap_read_bch8_result - Read BCH result for BCH8 level
*
@@ -631,20 +628,20 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
return 0;
}
-#endif /* CONFIG_AM33XX */
+#endif /* CONFIG_NAND_OMAP_ELM */
/*
* OMAP3 BCH8 support (with BCH library)
*/
-#ifdef CONFIG_NAND_OMAP_BCH8
+#ifdef CONFIG_BCH
/*
- * omap_calculate_ecc_bch - Read BCH ECC result
+ * omap_calculate_ecc_bch_sw - Read BCH ECC result
*
* @mtd: MTD device structure
* @dat: The pointer to data on which ecc is computed (unused here)
* @ecc: The ECC output buffer
*/
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
+static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc)
{
int ret = 0;
@@ -689,13 +686,13 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
}
/**
- * omap_correct_data_bch - Decode received data and correct errors
+ * omap_correct_data_bch_sw - Decode received data and correct errors
* @mtd: MTD device structure
* @data: page data
* @read_ecc: ecc read from nand flash
* @calc_ecc: ecc read from HW ECC registers
*/
-static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
u_char *read_ecc, u_char *calc_ecc)
{
int i, count;
@@ -752,7 +749,150 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
chip_priv->control = NULL;
}
}
-#endif /* CONFIG_NAND_OMAP_BCH8 */
+#endif /* CONFIG_BCH */
+
+/**
+ * omap_select_ecc_scheme - configures driver for particular ecc-scheme
+ * @nand: NAND chip device structure
+ * @ecc_scheme: ecc scheme to configure
+ * @pagesize: number of main-area bytes per page of NAND device
+ * @oobsize: number of OOB/spare bytes per page of NAND device
+ */
+static int omap_select_ecc_scheme(struct nand_chip *nand,
+ enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
+ struct nand_bch_priv *bch = nand->priv;
+ struct nand_ecclayout *ecclayout = nand->ecc.layout;
+ int eccsteps = pagesize / SECTOR_BYTES;
+ int i;
+
+ switch (ecc_scheme) {
+ case OMAP_ECC_HAM1_CODE_SW:
+ debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
+ /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
+ * initialized in nand_scan_tail(), so just set ecc.mode */
+ bch_priv.control = NULL;
+ bch_priv.type = 0;
+ nand->ecc.mode = NAND_ECC_SOFT;
+ nand->ecc.layout = NULL;
+ nand->ecc.size = pagesize;
+ bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
+ break;
+
+ case OMAP_ECC_HAM1_CODE_HW:
+ debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ bch_priv.control = NULL;
+ bch_priv.type = 0;
+ /* populate ecc specific fields */
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 1;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 3;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data;
+ nand->ecc.calculate = omap_calculate_ecc;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++)
+ ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
+ break;
+
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+#ifdef CONFIG_BCH
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* check if BCH S/W library can be used for error detection */
+ bch_priv.control = init_bch(13, 8, 0x201b);
+ if (!bch_priv.control) {
+ printf("nand: error: could not init_bch()\n");
+ return -ENODEV;
+ }
+ bch_priv.type = ECC_BCH8;
+ /* populate ecc specific fields */
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 13;
+ nand->ecc.hwctl = omap_enable_ecc_bch;
+ nand->ecc.correct = omap_correct_data_bch_sw;
+ nand->ecc.calculate = omap_calculate_ecc_bch_sw;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
+ for (i = 1; i < ecclayout->eccbytes; i++) {
+ if (i % nand->ecc.bytes)
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 1;
+ else
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 2;
+ }
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ omap_hwecc_init_bch(nand, NAND_ECC_READ);
+ bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+ break;
+#else
+ printf("nand: error: CONFIG_BCH required for ECC\n");
+ return -EINVAL;
+#endif
+
+ case OMAP_ECC_BCH8_CODE_HW:
+#ifdef CONFIG_NAND_OMAP_ELM
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* intialize ELM for ECC error detection */
+ elm_init();
+ bch_priv.type = ECC_BCH8;
+ /* populate ecc specific fields */
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 14;
+ nand->ecc.hwctl = omap_enable_ecc_bch;
+ nand->ecc.correct = omap_correct_data_bch;
+ nand->ecc.calculate = omap_calculate_ecc_bch;
+ nand->ecc.read_page = omap_read_page_bch;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++)
+ ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+ ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+ BADBLOCK_MARKER_LENGTH;
+ bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
+ break;
+#else
+ printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
+ return -EINVAL;
+#endif
+
+ default:
+ debug("nand: error: ecc scheme not enabled or supported\n");
+ return -EINVAL;
+ }
+ return 0;
+}
#ifndef CONFIG_SPL_BUILD
/*
@@ -763,77 +903,45 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
* @eccstrength - the number of bits that could be corrected
* (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
*/
-void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
+int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
{
struct nand_chip *nand;
struct mtd_info *mtd;
+ int err = 0;
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[nand_curr_device].name) {
- printf("Error: Can't switch ecc, no devices available\n");
- return;
+ printf("nand: error: no NAND devices found\n");
+ return -ENODEV;
}
mtd = &nand_info[nand_curr_device];
nand = mtd->priv;
-
nand->options |= NAND_OWN_BUFFERS;
-
- /* Reset ecc interface */
- nand->ecc.mode = NAND_ECC_NONE;
- nand->ecc.read_page = NULL;
- nand->ecc.write_page = NULL;
- nand->ecc.read_oob = NULL;
- nand->ecc.write_oob = NULL;
- nand->ecc.hwctl = NULL;
- nand->ecc.correct = NULL;
- nand->ecc.calculate = NULL;
- nand->ecc.strength = eccstrength;
-
/* Setup the ecc configurations again */
if (hardware) {
if (eccstrength == 1) {
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_nand_oob;
- nand->ecc.size = 512;
- nand->ecc.bytes = 3;
- nand->ecc.hwctl = omap_enable_hwecc;
- nand->ecc.correct = omap_correct_data;
- nand->ecc.calculate = omap_calculate_ecc;
- omap_hwecc_init(nand);
- printf("1-bit hamming HW ECC selected\n");
- }
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
- else if (eccstrength == 8) {
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_bch8_nand_oob;
- nand->ecc.size = 512;
-#ifdef CONFIG_AM33XX
- nand->ecc.bytes = 14;
- nand->ecc.read_page = omap_read_page_bch;
-#else
- nand->ecc.bytes = 13;
-#endif
- nand->ecc.hwctl = omap_enable_ecc_bch;
- nand->ecc.correct = omap_correct_data_bch;
- nand->ecc.calculate = omap_calculate_ecc_bch;
- omap_hwecc_init_bch(nand, NAND_ECC_READ);
- printf("8-bit BCH HW ECC selected\n");
+ err = omap_select_ecc_scheme(nand,
+ OMAP_ECC_HAM1_CODE_HW,
+ mtd->writesize, mtd->oobsize);
+ } else if (eccstrength == 8) {
+ err = omap_select_ecc_scheme(nand,
+ OMAP_ECC_BCH8_CODE_HW,
+ mtd->writesize, mtd->oobsize);
+ } else {
+ printf("nand: error: unsupported ECC scheme\n");
+ return -EINVAL;
}
-#endif
} else {
- nand->ecc.mode = NAND_ECC_SOFT;
- /* Use mtd default settings */
- nand->ecc.layout = NULL;
- nand->ecc.size = 0;
- printf("SW ECC selected\n");
+ err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
+ mtd->writesize, mtd->oobsize);
}
/* Update NAND handling after ECC mode switch */
- nand_scan_tail(mtd);
-
- nand->options &= ~NAND_OWN_BUFFERS;
+ if (!err)
+ err = nand_scan_tail(mtd);
+ return err;
}
#endif /* CONFIG_SPL_BUILD */
@@ -856,7 +964,7 @@ int board_nand_init(struct nand_chip *nand)
{
int32_t gpmc_config = 0;
cs = 0;
-
+ int err = 0;
/*
* xloader/Uboot's gpmc configuration would have configured GPMC for
* nand type of memory. The following logic scans and latches on to the
@@ -873,7 +981,7 @@ int board_nand_init(struct nand_chip *nand)
cs++;
}
if (cs >= GPMC_MAX_CS) {
- printf("NAND: Unable to find NAND settings in "
+ printf("nand: error: Unable to find NAND settings in "
"GPMC Configuration - quitting\n");
return -ENODEV;
}
@@ -885,64 +993,27 @@ int board_nand_init(struct nand_chip *nand)
nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
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->priv = &bch_priv;
+ nand->cmd_ctrl = omap_nand_hwcontrol;
+ 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;
nand->chip_delay = 100;
+ nand->ecc.layout = &omap_ecclayout;
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
-#ifdef CONFIG_AM33XX
- /* AM33xx uses the ELM */
- /* required in case of BCH */
- elm_init();
-#else
- /*
- * Whereas other OMAP based SoC do not have the ELM, they use the BCH
- * SW library.
- */
- bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
- if (!bch_priv.control) {
- puts("Could not init_bch()\n");
- return -ENODEV;
- }
-#endif
- /* BCH info that will be correct for SPL or overridden otherwise. */
- nand->priv = &bch_priv;
-#endif
-
- /* Default ECC mode */
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
- nand->ecc.mode = NAND_ECC_HW;
- 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;
-#ifdef CONFIG_AM33XX
- nand->ecc.read_page = omap_read_page_bch;
-#endif
- omap_hwecc_init_bch(nand, NAND_ECC_READ);
-#else
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
- nand->ecc.mode = NAND_ECC_SOFT;
+ /* select ECC scheme */
+#if defined(CONFIG_NAND_OMAP_ECCSCHEME)
+ err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
+ CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
#else
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &hw_nand_oob;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
- 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
+ /* pagesize and oobsize are not required to configure sw ecc-scheme */
+ err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
+ 0, 0);
#endif
+ if (err)
+ return err;
#ifdef CONFIG_SPL_BUILD
if (nand->options & NAND_BUSWIDTH_16)
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 067f8ef..979e4af 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -761,7 +761,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
uint8_t *oob_buf = this->oob_buf;
free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+ i++, free++) {
if (readcol >= lastgap)
readcol += free->offset - lastgap;
if (readend >= lastgap)
@@ -770,7 +771,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
}
this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+ i++, free++) {
int free_end = free->offset + free->length;
if (free->offset < readend && free_end > readcol) {
int st = max_t(int,free->offset,readcol);
@@ -1356,7 +1358,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
unsigned int i;
free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+ i++, free++) {
if (writecol >= lastgap)
writecol += free->offset - lastgap;
if (writeend >= lastgap)
@@ -1364,7 +1367,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
lastgap = free->offset + free->length;
}
free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE && free->length;
+ i++, free++) {
int free_end = free->offset + free->length;
if (free->offset < writeend && free_end > writecol) {
int st = max_t(int,free->offset,writecol);
@@ -2750,7 +2754,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
* the out of band area
*/
this->ecclayout->oobavail = 0;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
+
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE &&
this->ecclayout->oobfree[i].length; i++)
this->ecclayout->oobavail +=
this->ecclayout->oobfree[i].length;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 8413d57..22155b4 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -96,7 +96,7 @@ static int mac_reset(struct eth_device *dev)
ulong start;
int timeout = CONFIG_MACRESET_TIMEOUT;
- writel(DMAMAC_SRST, &dma_p->busmode);
+ writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
if (priv->interface != PHY_INTERFACE_MODE_RGMII)
writel(MII_PORTSELECT, &mac_p->conf);
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index e80002a..5440c92 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -112,7 +112,7 @@ struct dmamacdescr {
u32 dmamac_cntl;
void *dmamac_addr;
struct dmamacdescr *dmamac_next;
-};
+} __aligned(16);
/*
* txrx_status definitions
@@ -224,8 +224,7 @@ struct dw_eth_dev {
u32 tx_currdescnum;
u32 rx_currdescnum;
u32 phy_configured;
- int link_printed;
- u32 padding;
+ u32 link_printed;
struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
@@ -237,7 +236,7 @@ struct dw_eth_dev {
struct eth_dma_regs *dma_regs_p;
struct eth_device *dev;
-} __attribute__ ((aligned(8)));
+};
/* Speed specific definitions */
#define SPEED_10M 1
diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c
index f7170e0..b68d808 100644
--- a/drivers/net/dm9000x.c
+++ b/drivers/net/dm9000x.c
@@ -342,6 +342,15 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)
DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
printf("MAC: %pM\n", dev->enetaddr);
+ if (!is_valid_ether_addr(dev->enetaddr)) {
+#ifdef CONFIG_RANDOM_MACADDR
+ printf("Bad MAC address (uninitialized EEPROM?), randomizing\n");
+ eth_random_enetaddr(dev->enetaddr);
+ printf("MAC: %pM\n", dev->enetaddr);
+#else
+ printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n");
+#endif
+ }
/* fill device MAC address registers */
for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 57aa53d..9a66e68 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -114,12 +114,13 @@ static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
static int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
static int e1000_phy_reset(struct e1000_hw *hw);
static int e1000_detect_gig_phy(struct e1000_hw *hw);
-static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
static void e1000_set_media_type(struct e1000_hw *hw);
static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
+#ifndef CONFIG_E1000_NO_NVM
+static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
uint16_t words,
uint16_t *data);
@@ -885,6 +886,7 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
}
+#endif /* CONFIG_E1000_NO_NVM */
/*****************************************************************************
* Set PHY to class A mode
@@ -897,6 +899,7 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
static int32_t
e1000_set_phy_mode(struct e1000_hw *hw)
{
+#ifndef CONFIG_E1000_NO_NVM
int32_t ret_val;
uint16_t eeprom_data;
@@ -923,10 +926,11 @@ e1000_set_phy_mode(struct e1000_hw *hw)
hw->phy_reset_disable = false;
}
}
-
+#endif
return E1000_SUCCESS;
}
+#ifndef CONFIG_E1000_NO_NVM
/***************************************************************************
*
* Obtaining software semaphore bit (SMBI) before resetting PHY.
@@ -965,6 +969,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
return E1000_SUCCESS;
}
+#endif
/***************************************************************************
* This function clears HW semaphore bits.
@@ -977,6 +982,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
static void
e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
{
+#ifndef CONFIG_E1000_NO_NVM
uint32_t swsm;
DEBUGFUNC();
@@ -991,6 +997,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
} else
swsm &= ~(E1000_SWSM_SWESMBI);
E1000_WRITE_REG(hw, SWSM, swsm);
+#endif
}
/***************************************************************************
@@ -1007,6 +1014,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
static int32_t
e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
{
+#ifndef CONFIG_E1000_NO_NVM
int32_t timeout;
uint32_t swsm;
@@ -1043,7 +1051,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
"SWESMBI bit is set.\n");
return -E1000_ERR_EEPROM;
}
-
+#endif
return E1000_SUCCESS;
}
@@ -1097,6 +1105,7 @@ static bool e1000_is_second_port(struct e1000_hw *hw)
}
}
+#ifndef CONFIG_E1000_NO_NVM
/******************************************************************************
* Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
* second function of dual function devices
@@ -1136,6 +1145,7 @@ e1000_read_mac_addr(struct eth_device *nic)
#endif
return 0;
}
+#endif
/******************************************************************************
* Initializes receive address filters.
@@ -1764,9 +1774,11 @@ static int
e1000_setup_link(struct eth_device *nic)
{
struct e1000_hw *hw = nic->priv;
- uint32_t ctrl_ext;
int32_t ret_val;
+#ifndef CONFIG_E1000_NO_NVM
+ uint32_t ctrl_ext;
uint16_t eeprom_data;
+#endif
DEBUGFUNC();
@@ -1775,6 +1787,7 @@ e1000_setup_link(struct eth_device *nic)
if (e1000_check_phy_reset_block(hw))
return E1000_SUCCESS;
+#ifndef CONFIG_E1000_NO_NVM
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -1788,7 +1801,7 @@ e1000_setup_link(struct eth_device *nic)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
-
+#endif
if (hw->fc == e1000_fc_default) {
switch (hw->mac_type) {
case e1000_ich8lan:
@@ -1797,6 +1810,7 @@ e1000_setup_link(struct eth_device *nic)
hw->fc = e1000_fc_full;
break;
default:
+#ifndef CONFIG_E1000_NO_NVM
ret_val = e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
if (ret_val) {
@@ -1809,6 +1823,7 @@ e1000_setup_link(struct eth_device *nic)
EEPROM_WORD0F_ASM_DIR)
hw->fc = e1000_fc_tx_pause;
else
+#endif
hw->fc = e1000_fc_full;
break;
}
@@ -1828,6 +1843,7 @@ e1000_setup_link(struct eth_device *nic)
DEBUGOUT("After fix-ups FlowControl is now = %x\n", hw->fc);
+#ifndef CONFIG_E1000_NO_NVM
/* Take the 4 bits from EEPROM word 0x0F that determine the initial
* polarity value for the SW controlled pins, and setup the
* Extended Device Control reg with that info.
@@ -1840,6 +1856,7 @@ e1000_setup_link(struct eth_device *nic)
SWDPIO__EXT_SHIFT);
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
}
+#endif
/* Call the necessary subroutine to configure the link. */
ret_val = (hw->media_type == e1000_media_type_fiber) ?
@@ -5196,6 +5213,7 @@ e1000_initialize(bd_t * bis)
e1000_reset_hw(hw);
list_add_tail(&hw->list_node, &e1000_hw_list);
+#ifndef CONFIG_E1000_NO_NVM
/* Validate the EEPROM and get chipset information */
#if !defined(CONFIG_MVBC_1G)
if (e1000_init_eeprom_params(hw)) {
@@ -5206,11 +5224,17 @@ e1000_initialize(bd_t * bis)
continue;
#endif
e1000_read_mac_addr(nic);
+#endif
e1000_get_bus_type(hw);
+#ifndef CONFIG_E1000_NO_NVM
printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n ",
nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2],
nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]);
+#else
+ memset(nic->enetaddr, 0, 6);
+ printf("e1000: no NVM\n");
+#endif
/* Set up the function pointers and register the device */
nic->init = e1000_init;
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index 25884f5..ff87af2 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -63,11 +63,14 @@ struct e1000_hw_stats;
/* Internal E1000 helper functions */
struct e1000_hw *e1000_find_card(unsigned int cardnum);
+
+#ifndef CONFIG_E1000_NO_NVM
int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
void e1000_standby_eeprom(struct e1000_hw *hw);
void e1000_release_eeprom(struct e1000_hw *hw);
void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+#endif
#ifdef CONFIG_E1000_SPI
int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
@@ -1019,6 +1022,7 @@ struct e1000_hw_stats {
uint64_t tsctfc;
};
+#ifndef CONFIG_E1000_NO_NVM
struct e1000_eeprom_info {
e1000_eeprom_type type;
uint16_t word_size;
@@ -1029,6 +1033,7 @@ e1000_eeprom_type type;
bool use_eerd;
bool use_eewr;
};
+#endif
typedef enum {
e1000_smart_speed_default = 0,
@@ -1081,10 +1086,14 @@ struct e1000_hw {
uint32_t io_base;
#endif
uint32_t asf_firmware_present;
+#ifndef CONFIG_E1000_NO_NVM
uint32_t eeprom_semaphore_present;
+#endif
uint32_t swfw_sync_present;
uint32_t swfwhw_semaphore_present;
+#ifndef CONFIG_E1000_NO_NVM
struct e1000_eeprom_info eeprom;
+#endif
e1000_ms_type master_slave;
e1000_ms_type original_master_slave;
e1000_ffe_config ffe_config_state;
diff --git a/drivers/net/fsl_mdio.c b/drivers/net/fsl_mdio.c
index ce36bd7..1d88e65 100644
--- a/drivers/net/fsl_mdio.c
+++ b/drivers/net/fsl_mdio.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ * Copyright 2009-2010, 2013 Freescale Semiconductor, Inc.
* Jun-jie Zhang <b18070@freescale.com>
* Mingkai Hu <Mingkai.hu@freescale.com>
*
@@ -13,7 +13,7 @@
#include <asm/errno.h>
#include <asm/fsl_enet.h>
-void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr,
+void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr,
int dev_addr, int regnum, int value)
{
int timeout = 1000000;
@@ -26,7 +26,7 @@ void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr,
;
}
-int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr,
+int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr,
int dev_addr, int regnum)
{
int value;
@@ -57,7 +57,8 @@ int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr,
static int fsl_pq_mdio_reset(struct mii_dev *bus)
{
- struct tsec_mii_mng *regs = bus->priv;
+ struct tsec_mii_mng __iomem *regs =
+ (struct tsec_mii_mng __iomem *)bus->priv;
/* Reset MII (due to new addresses) */
out_be32(&regs->miimcfg, MIIMCFG_RESET_MGMT);
@@ -72,7 +73,8 @@ static int fsl_pq_mdio_reset(struct mii_dev *bus)
int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
{
- struct tsec_mii_mng *phyregs = bus->priv;
+ struct tsec_mii_mng __iomem *phyregs =
+ (struct tsec_mii_mng __iomem *)bus->priv;
return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum);
}
@@ -80,7 +82,8 @@ int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
u16 value)
{
- struct tsec_mii_mng *phyregs = bus->priv;
+ struct tsec_mii_mng __iomem *phyregs =
+ (struct tsec_mii_mng __iomem *)bus->priv;
tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value);
@@ -101,7 +104,7 @@ int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info)
bus->reset = fsl_pq_mdio_reset;
sprintf(bus->name, info->name);
- bus->priv = info->regs;
+ bus->priv = (void *)info->regs;
return mdio_register(bus);
}
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index 6c901d1..0cd06b6 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -420,8 +420,9 @@ static int mvgbe_init(struct eth_device *dev)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
- && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+ !defined(CONFIG_PHYLIB) && \
+ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
int i;
#endif
/* setup RX rings */
diff --git a/drivers/net/npe/Makefile b/drivers/net/npe/Makefile
index e36c0bb..0779255 100644
--- a/drivers/net/npe/Makefile
+++ b/drivers/net/npe/Makefile
@@ -8,7 +8,6 @@
LOCAL_CFLAGS += -I$(TOPDIR)/drivers/net/npe/include -DCONFIG_IXP425_COMPONENT_ETHDB -D__linux
CFLAGS += $(LOCAL_CFLAGS)
CPPFLAGS += $(LOCAL_CFLAGS) # needed for depend
-HOSTCFLAGS += $(LOCAL_CFLAGS)
obj-y := npe.o \
miiphy.o \
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 0f2dfd6..b20b4df 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -40,7 +40,7 @@ static int ar8035_config(struct phy_device *phydev)
static struct phy_driver AR8021_driver = {
.name = "AR8021",
.uid = 0x4dd040,
- .mask = 0xfffff0,
+ .mask = 0x4fffff,
.features = PHY_GBIT_FEATURES,
.config = ar8021_config,
.startup = genphy_startup,
@@ -48,11 +48,11 @@ static struct phy_driver AR8021_driver = {
};
static struct phy_driver AR8031_driver = {
- .name = "AR8031",
+ .name = "AR8031/AR8033",
.uid = 0x4dd074,
- .mask = 0xfffff0,
+ .mask = 0x4fffff,
.features = PHY_GBIT_FEATURES,
- .config = genphy_config,
+ .config = ar8021_config,
.startup = genphy_startup,
.shutdown = genphy_shutdown,
};
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index a7450f8..5d7e3be 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -100,6 +100,19 @@ int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
}
+
+static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
+ int regnum)
+{
+ return ksz9021_phy_extended_read(phydev, regnum);
+}
+
+static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
+ int devaddr, int regnum, u16 val)
+{
+ return ksz9021_phy_extended_write(phydev, regnum, val);
+}
+
/* Micrel ksz9021 */
static int ksz9021_config(struct phy_device *phydev)
{
@@ -131,6 +144,8 @@ static struct phy_driver ksz9021_driver = {
.config = &ksz9021_config,
.startup = &ksz90xx_startup,
.shutdown = &genphy_shutdown,
+ .writeext = &ksz9021_phy_extwrite,
+ .readext = &ksz9021_phy_extread,
};
#endif
@@ -171,14 +186,31 @@ int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
}
+static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
+ int regnum)
+{
+ return ksz9031_phy_extended_read(phydev, devaddr, regnum,
+ MII_KSZ9031_MOD_DATA_NO_POST_INC);
+};
+
+static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
+ int devaddr, int regnum, u16 val)
+{
+ return ksz9031_phy_extended_write(phydev, devaddr, regnum,
+ MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
+};
+
+
static struct phy_driver ksz9031_driver = {
.name = "Micrel ksz9031",
.uid = 0x221620,
- .mask = 0xfffffe,
+ .mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &genphy_config,
.startup = &ksz90xx_startup,
.shutdown = &genphy_shutdown,
+ .writeext = &ksz9031_phy_extwrite,
+ .readext = &ksz9031_phy_extread,
};
int phy_micrel_init(void)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 62925bb..c691fbb 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -275,13 +275,14 @@ int genphy_parse_link(struct phy_device *phydev)
int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
/* We're using autonegotiation */
- if (mii_reg & BMSR_ANEGCAPABLE) {
+ if (phydev->supported & SUPPORTED_Autoneg) {
u32 lpa = 0;
int gblpa = 0;
u32 estatus = 0;
/* Check for gigabit capability */
- if (mii_reg & BMSR_ERCAP) {
+ if (phydev->supported & (SUPPORTED_1000baseT_Full |
+ SUPPORTED_1000baseT_Half)) {
/* We want a list of states supported by
* both PHYs in the link
*/
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index ddbbc35..a3ace68 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -102,7 +102,7 @@ static int rtl8211x_startup(struct phy_device *phydev)
static struct phy_driver RTL8211B_driver = {
.name = "RealTek RTL8211B",
.uid = 0x1cc910,
- .mask = 0xfffff0,
+ .mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
.config = &rtl8211x_config,
.startup = &rtl8211x_startup,
@@ -113,7 +113,7 @@ static struct phy_driver RTL8211B_driver = {
static struct phy_driver RTL8211E_driver = {
.name = "RealTek RTL8211E",
.uid = 0x1cc915,
- .mask = 0xfffff0,
+ .mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
.config = &rtl8211x_config,
.startup = &rtl8211x_startup,
@@ -124,7 +124,7 @@ static struct phy_driver RTL8211E_driver = {
static struct phy_driver RTL8211DN_driver = {
.name = "RealTek RTL8211DN",
.uid = 0x1cc914,
- .mask = 0xfffff0,
+ .mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
.config = &rtl8211x_config,
.startup = &rtl8211x_startup,
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 60ed92d..bfd9815 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -12,6 +12,7 @@
*/
#include <miiphy.h>
+/* This code does not check the partner abilities. */
static int smsc_parse_status(struct phy_device *phydev)
{
int mii_reg;
@@ -64,7 +65,7 @@ static struct phy_driver lan8710_driver = {
.mask = 0xffff0,
.features = PHY_BASIC_FEATURES,
.config = &genphy_config_aneg,
- .startup = &smsc_startup,
+ .startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 5cf103e..c555979 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -49,6 +49,15 @@
#define MIIM_VSC8574_18G_QSGMII 0x80e0
#define MIIM_VSC8574_18G_CMDSTAT 0x8000
+/* Vitesse VSC8514 control register */
+#define MIIM_VSC8514_GENERAL18 0x12
+#define MIIM_VSC8514_GENERAL19 0x13
+#define MIIM_VSC8514_GENERAL23 0x17
+
+/* Vitesse VSC8514 gerenal purpose register 18 */
+#define MIIM_VSC8514_18G_QSGMII 0x80e0
+#define MIIM_VSC8514_18G_CMDSTAT 0x8000
+
/* CIS8201 */
static int vitesse_config(struct phy_device *phydev)
{
@@ -148,7 +157,7 @@ static int vsc8601_config(struct phy_device *phydev)
static int vsc8574_config(struct phy_device *phydev)
{
u32 val;
- /* configure regiser 19G for MAC */
+ /* configure register 19G for MAC */
phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
PHY_EXT_PAGE_ACCESS_GENERAL);
@@ -188,6 +197,53 @@ static int vsc8574_config(struct phy_device *phydev)
return 0;
}
+static int vsc8514_config(struct phy_device *phydev)
+{
+ u32 val;
+ int timeout = 1000000;
+
+ /* configure register to access 19G */
+ phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
+ PHY_EXT_PAGE_ACCESS_GENERAL);
+
+ val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19);
+ if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
+ /* set bit 15:14 to '01' for QSGMII mode */
+ val = (val & 0x3fff) | (1 << 14);
+ phy_write(phydev, MDIO_DEVAD_NONE,
+ MIIM_VSC8514_GENERAL19, val);
+ /* Enable 4 ports MAC QSGMII */
+ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18,
+ MIIM_VSC8514_18G_QSGMII);
+ } else {
+ /*TODO Add SGMII functionality once spec sheet
+ * for VSC8514 defines complete functionality
+ */
+ }
+
+ val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
+ /* When bit 15 is cleared the command has completed */
+ while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--)
+ val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
+
+ if (0 == timeout) {
+ printf("PHY 8514 config failed\n");
+ return -1;
+ }
+
+ phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
+
+ /* configure register to access 23 */
+ val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23);
+ /* set bits 10:8 to '000' */
+ val = (val & 0xf8ff);
+ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val);
+
+ genphy_config_aneg(phydev);
+
+ return 0;
+}
+
static struct phy_driver VSC8211_driver = {
.name = "Vitesse VSC8211",
.uid = 0xfc4b0,
@@ -238,6 +294,16 @@ static struct phy_driver VSC8574_driver = {
.shutdown = &genphy_shutdown,
};
+static struct phy_driver VSC8514_driver = {
+ .name = "Vitesse VSC8514",
+ .uid = 0x70570,
+ .mask = 0xffff0,
+ .features = PHY_GBIT_FEATURES,
+ .config = &vsc8514_config,
+ .startup = &vitesse_startup,
+ .shutdown = &genphy_shutdown,
+};
+
static struct phy_driver VSC8601_driver = {
.name = "Vitesse VSC8601",
.uid = 0x70420,
@@ -298,6 +364,7 @@ int phy_vitesse_init(void)
phy_register(&VSC8211_driver);
phy_register(&VSC8221_driver);
phy_register(&VSC8574_driver);
+ phy_register(&VSC8514_driver);
phy_register(&VSC8662_driver);
phy_register(&cis8201_driver);
phy_register(&cis8204_driver);
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index 4186699..208ce5c 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -188,7 +188,7 @@ static int rtl_transmit(struct eth_device *dev, void *packet, int length);
static int rtl_poll(struct eth_device *dev);
static void rtl_disable(struct eth_device *dev);
#ifdef CONFIG_MCAST_TFTP/* This driver already accepts all b/mcast */
-static int rtl_bcast_addr (struct eth_device *dev, u8 bcast_mac, u8 set)
+static int rtl_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, u8 set)
{
return (0);
}
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 13fa9c0..d040ab1 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -246,6 +246,8 @@ static struct {
{"RTL-8169sc/8110sc", 0x18, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x30, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x38, 0xff7e1880,},
+ {"RTL-8168d/8111d", 0x28, 0xff7e1880,},
+ {"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,},
{"RTL-8101e", 0x34, 0xff7e1880,},
{"RTL-8100e", 0x32, 0xff7e1880,},
};
@@ -314,6 +316,7 @@ static const unsigned int rtl8169_rx_config =
static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_REALTEK, 0x8167},
+ {PCI_VENDOR_ID_REALTEK, 0x8168},
{PCI_VENDOR_ID_REALTEK, 0x8169},
{}
};
@@ -394,6 +397,50 @@ match:
return 0;
}
+/*
+ * Cache maintenance functions. These are simple wrappers around the more
+ * general purpose flush_cache() and invalidate_dcache_range() functions.
+ */
+
+static void rtl_inval_rx_desc(struct RxDesc *desc)
+{
+ unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_rx_desc(struct RxDesc *desc)
+{
+ flush_cache((unsigned long)desc, sizeof(*desc));
+}
+
+static void rtl_inval_tx_desc(struct TxDesc *desc)
+{
+ unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_tx_desc(struct TxDesc *desc)
+{
+ flush_cache((unsigned long)desc, sizeof(*desc));
+}
+
+static void rtl_inval_buffer(void *buf, size_t size)
+{
+ unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_buffer(void *buf, size_t size)
+{
+ flush_cache((unsigned long)buf, size);
+}
+
/**************************************************************************
RECV - Receive a frame
***************************************************************************/
@@ -411,14 +458,16 @@ static int rtl_recv(struct eth_device *dev)
ioaddr = dev->iobase;
cur_rx = tpc->cur_rx;
- flush_cache((unsigned long)&tpc->RxDescArray[cur_rx],
- sizeof(struct RxDesc));
+
+ rtl_inval_rx_desc(&tpc->RxDescArray[cur_rx]);
+
if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
unsigned char rxdata[RX_BUF_LEN];
length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
status) & 0x00001FFF) - 4;
+ rtl_inval_buffer(tpc->RxBufferRing[cur_rx], length);
memcpy(rxdata, tpc->RxBufferRing[cur_rx], length);
NetReceive(rxdata, length);
@@ -430,8 +479,7 @@ static int rtl_recv(struct eth_device *dev)
cpu_to_le32(OWNbit + RX_BUF_SIZE);
tpc->RxDescArray[cur_rx].buf_addr =
cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx]));
- flush_cache((unsigned long)tpc->RxBufferRing[cur_rx],
- RX_BUF_SIZE);
+ rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]);
} else {
puts("Error Rx");
}
@@ -473,7 +521,7 @@ static int rtl_send(struct eth_device *dev, void *packet, int length)
/* point to the current txb incase multiple tx_rings are used */
ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
memcpy(ptxb, (char *)packet, (int)length);
- flush_cache((unsigned long)ptxb, length);
+ rtl_flush_buffer(ptxb, length);
while (len < ETH_ZLEN)
ptxb[len++] = '\0';
@@ -489,20 +537,20 @@ static int rtl_send(struct eth_device *dev, void *packet, int length)
cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) |
((len > ETH_ZLEN) ? len : ETH_ZLEN));
}
+ rtl_flush_tx_desc(&tpc->TxDescArray[entry]);
RTL_W8(TxPoll, 0x40); /* set polling bit */
tpc->cur_tx++;
to = currticks() + TX_TIMEOUT;
do {
- flush_cache((unsigned long)&tpc->TxDescArray[entry],
- sizeof(struct TxDesc));
+ rtl_inval_tx_desc(&tpc->TxDescArray[entry]);
} while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit)
&& (currticks() < to)); /* wait */
if (currticks() >= to) {
#ifdef DEBUG_RTL8169_TX
- puts ("tx timeout/error\n");
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ puts("tx timeout/error\n");
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
ret = 0;
} else {
@@ -604,7 +652,7 @@ static void rtl8169_hw_start(struct eth_device *dev)
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
}
@@ -638,11 +686,11 @@ static void rtl8169_init_ring(struct eth_device *dev)
tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
tpc->RxDescArray[i].buf_addr =
cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i]));
- flush_cache((unsigned long)tpc->RxBufferRing[i], RX_BUF_SIZE);
+ rtl_flush_rx_desc(&tpc->RxDescArray[i]);
}
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
}
@@ -683,7 +731,7 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
txb[5] = dev->enetaddr[5];
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
return 0;
}
@@ -869,11 +917,25 @@ int rtl8169_initialize(bd_t *bis)
int idx=0;
while(1){
+ unsigned int region;
+ u16 device;
+
/* Find RTL8169 */
if ((devno = pci_find_devices(supported, idx++)) < 0)
break;
- pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
+ pci_read_config_word(devno, PCI_DEVICE_ID, &device);
+ switch (device) {
+ case 0x8168:
+ region = 2;
+ break;
+
+ default:
+ region = 1;
+ break;
+ }
+
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_0 + (region * 4), &iobase);
iobase &= ~0xf;
debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index d5a83e0..5e132f2 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -4,6 +4,7 @@
* Copyright (C) 2008, 2011 Renesas Solutions Corp.
* Copyright (c) 2008, 2011 Nobuhiro Iwamatsu
* Copyright (c) 2007 Carlos Munoz <carlos@kenati.com>
+ * Copyright (C) 2013 Renesas Electronics Corporation
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -25,13 +26,31 @@
#ifndef CONFIG_SH_ETHER_PHY_ADDR
# error "Please define CONFIG_SH_ETHER_PHY_ADDR"
#endif
-#ifdef CONFIG_SH_ETHER_CACHE_WRITEBACK
-#define flush_cache_wback(addr, len) \
- dcache_wback_range((u32)addr, (u32)(addr + len - 1))
+
+#if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF)
+#define flush_cache_wback(addr, len) \
+ flush_dcache_range((u32)addr, (u32)(addr + len - 1))
#else
#define flush_cache_wback(...)
#endif
+#if defined(CONFIG_SH_ETHER_CACHE_INVALIDATE) && defined(CONFIG_ARM)
+#define invalidate_cache(addr, len) \
+ { \
+ u32 line_size = CONFIG_SH_ETHER_ALIGNE_SIZE; \
+ u32 start, end; \
+ \
+ start = (u32)addr; \
+ end = start + len; \
+ start &= ~(line_size - 1); \
+ end = ((end + line_size - 1) & ~(line_size - 1)); \
+ \
+ invalidate_dcache_range(start, end); \
+ }
+#else
+#define invalidate_cache(...)
+#endif
+
#define TIMEOUT_CNT 1000
int sh_eth_send(struct eth_device *dev, void *packet, int len)
@@ -69,8 +88,11 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len)
/* Wait until packet is transmitted */
timeout = TIMEOUT_CNT;
- while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--)
+ do {
+ invalidate_cache(port_info->tx_desc_cur,
+ sizeof(struct tx_desc_s));
udelay(100);
+ } while (port_info->tx_desc_cur->td0 & TD_TACT && timeout--);
if (timeout < 0) {
printf(SHETHER_NAME ": transmit timeout\n");
@@ -94,12 +116,14 @@ int sh_eth_recv(struct eth_device *dev)
uchar *packet;
/* Check if the rx descriptor is ready */
+ invalidate_cache(port_info->rx_desc_cur, sizeof(struct rx_desc_s));
if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) {
/* Check for errors */
if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) {
len = port_info->rx_desc_cur->rd1 & 0xffff;
packet = (uchar *)
ADDR_TO_P2(port_info->rx_desc_cur->rd2);
+ invalidate_cache(packet, len);
NetReceive(packet, len);
}
@@ -108,7 +132,6 @@ int sh_eth_recv(struct eth_device *dev)
port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
else
port_info->rx_desc_cur->rd0 = RD_RACT;
-
/* Point to the next descriptor */
port_info->rx_desc_cur++;
if (port_info->rx_desc_cur >=
@@ -237,15 +260,17 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
* Allocate rx data buffers. They must be 32 bytes aligned and in
* P2 area
*/
- port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31);
+ port_info->rx_buf_malloc = malloc(
+ NUM_RX_DESC * MAX_BUF_SIZE + RX_BUF_ALIGNE_SIZE - 1);
if (!port_info->rx_buf_malloc) {
printf(SHETHER_NAME ": malloc failed\n");
ret = -ENOMEM;
goto err_buf_malloc;
}
- tmp_addr = (u32)(((int)port_info->rx_buf_malloc + (32 - 1)) &
- ~(32 - 1));
+ tmp_addr = (u32)(((int)port_info->rx_buf_malloc
+ + (RX_BUF_ALIGNE_SIZE - 1)) &
+ ~(RX_BUF_ALIGNE_SIZE - 1));
port_info->rx_buf_base = (u8 *)ADDR_TO_P2(tmp_addr);
/* Initialize all descriptors */
@@ -351,8 +376,9 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
struct phy_device *phy;
/* Configure e-dmac registers */
- sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | EDMR_EL,
- EDMR);
+ sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) |
+ (EMDR_DESC | EDMR_EL), EDMR);
+
sh_eth_write(eth, 0, EESIPR);
sh_eth_write(eth, 0, TRSCER);
sh_eth_write(eth, 0, TFTR);
@@ -384,6 +410,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
#if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+ sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR);
#endif
/* Configure phy */
ret = sh_eth_phy_config(eth);
@@ -407,7 +435,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
sh_eth_write(eth, GECMR_100B, GECMR);
#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
sh_eth_write(eth, 1, RTRATE);
-#elif defined(CONFIG_CPU_SH7724)
+#elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \
+ defined(CONFIG_R8A7791)
val = ECMR_RTM;
#endif
} else if (phy->speed == 10) {
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index 9ad800e..8aa7109 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -31,6 +31,11 @@
#define ADDR_TO_P2(addr) (addr)
#endif /* defined(CONFIG_SH) */
+/* base padding size is 16 */
+#ifndef CONFIG_SH_ETHER_ALIGNE_SIZE
+#define CONFIG_SH_ETHER_ALIGNE_SIZE 16
+#endif
+
/* Number of supported ports */
#define MAX_PORT_NUM 2
@@ -45,15 +50,16 @@
/* The size of the tx descriptor is determined by how much padding is used.
4, 20, or 52 bytes of padding can be used */
-#define TX_DESC_PADDING 4
-#define TX_DESC_SIZE (12 + TX_DESC_PADDING)
+#define TX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12)
+/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */
+#define TX_DESC_SIZE (12 + TX_DESC_PADDING)
/* Tx descriptor. We always use 3 bytes of padding */
struct tx_desc_s {
volatile u32 td0;
u32 td1;
u32 td2; /* Buffer start */
- u32 padding;
+ u8 padding[TX_DESC_PADDING]; /* aligned cache line size */
};
/* There is no limitation in the number of rx descriptors */
@@ -61,15 +67,18 @@ struct tx_desc_s {
/* The size of the rx descriptor is determined by how much padding is used.
4, 20, or 52 bytes of padding can be used */
-#define RX_DESC_PADDING 4
+#define RX_DESC_PADDING (CONFIG_SH_ETHER_ALIGNE_SIZE - 12)
+/* same as CONFIG_SH_ETHER_ALIGNE_SIZE */
#define RX_DESC_SIZE (12 + RX_DESC_PADDING)
+/* aligned cache line size */
+#define RX_BUF_ALIGNE_SIZE (CONFIG_SH_ETHER_ALIGNE_SIZE > 32 ? 64 : 32)
/* Rx descriptor. We always use 4 bytes of padding */
struct rx_desc_s {
volatile u32 rd0;
volatile u32 rd1;
u32 rd2; /* Buffer start */
- u32 padding;
+ u8 padding[TX_DESC_PADDING]; /* aligned cache line size */
};
struct sh_eth_info {
@@ -157,6 +166,7 @@ enum {
TLFRCR,
CERCR,
CEECR,
+ RMIIMR, /* R8A7790 */
MAFCR,
RTRATE,
CSMR,
@@ -263,6 +273,7 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
[RMCR] = 0x0058,
[TFUCR] = 0x0064,
[RFOCR] = 0x0068,
+ [RMIIMR] = 0x006C,
[FCFTR] = 0x0070,
[RPADIR] = 0x0078,
[TRIMD] = 0x007c,
@@ -290,6 +301,9 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
#elif defined(CONFIG_R8A7740)
#define SH_ETH_TYPE_GETHER
#define BASE_IO_ADDR 0xE9A00000
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+#define SH_ETH_TYPE_ETHER
+#define BASE_IO_ADDR 0xEE700200
#endif
/*
@@ -320,6 +334,14 @@ enum DMAC_M_BIT {
#endif
};
+#if CONFIG_SH_ETHER_ALIGNE_SIZE == 64
+# define EMDR_DESC EDMR_DL1
+#elif CONFIG_SH_ETHER_ALIGNE_SIZE == 32
+# define EMDR_DESC EDMR_DL0
+#elif CONFIG_SH_ETHER_ALIGNE_SIZE == 16 /* Default */
+# define EMDR_DESC 0
+#endif
+
/* RFLR */
#define RFLR_RFL_MIN 0x05EE /* Recv Frame length 1518 byte */
@@ -485,6 +507,8 @@ enum FELIC_MODE_BIT {
ECMR_PRM = 0x00000001,
#ifdef CONFIG_CPU_SH7724
ECMR_RTM = 0x00000010,
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+ ECMR_RTM = 0x00000004,
#endif
};
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index f5e314b..e9138f0 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -5,7 +5,7 @@
* terms of the GNU Public License, Version 2, incorporated
* herein by reference.
*
- * Copyright 2004-2011 Freescale Semiconductor, Inc.
+ * Copyright 2004-2011, 2013 Freescale Semiconductor, Inc.
* (C) Copyright 2003, Motorola, Inc.
* author Andy Fleming
*
@@ -25,21 +25,13 @@ DECLARE_GLOBAL_DATA_PTR;
#define TX_BUF_CNT 2
-static uint rxIdx; /* index of the current RX buffer */
-static uint txIdx; /* index of the current TX buffer */
-
-typedef volatile struct rtxbd {
- txbd8_t txbd[TX_BUF_CNT];
- rxbd8_t rxbd[PKTBUFSRX];
-} RTXBD;
-
-#define MAXCONTROLLERS (8)
-
-static struct tsec_private *privlist[MAXCONTROLLERS];
-static int num_tsecs = 0;
+static uint rx_idx; /* index of the current RX buffer */
+static uint tx_idx; /* index of the current TX buffer */
#ifdef __GNUC__
-static RTXBD rtx __attribute__ ((aligned(8)));
+static struct txbd8 __iomem txbd[TX_BUF_CNT] __aligned(8);
+static struct rxbd8 __iomem rxbd[PKTBUFSRX] __aligned(8);
+
#else
#error "rtx must be 64-bit aligned"
#endif
@@ -57,7 +49,7 @@ static struct tsec_info_struct tsec_info[] = {
#endif
#ifdef CONFIG_MPC85XX_FEC
{
- .regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
+ .regs = TSEC_GET_REGS(2, 0x2000),
.devname = CONFIG_MPC85XX_FEC_NAME,
.phyaddr = FEC_PHY_ADDR,
.flags = FEC_FLAGS,
@@ -113,32 +105,31 @@ static void tsec_configure_serdes(struct tsec_private *priv)
* result.
* 2) Use the 8 most significant bits as a hash into a 256-entry
* table. The table is controlled through 8 32-bit registers:
- * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is
- * gaddr7. This means that the 3 most significant bits in the
+ * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is entry
+ * 255. This means that the 3 most significant bits in the
* hash index which gaddr register to use, and the 5 other bits
* indicate which bit (assuming an IBM numbering scheme, which
- * for PowerPC (tm) is usually the case) in the tregister holds
+ * for PowerPC (tm) is usually the case) in the register holds
* the entry. */
static int
-tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
+tsec_mcast_addr(struct eth_device *dev, const u8 *mcast_mac, u8 set)
{
- struct tsec_private *priv = privlist[1];
- volatile tsec_t *regs = priv->regs;
- volatile u32 *reg_array, value;
- u8 result, whichbit, whichreg;
-
- result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
- whichbit = result & 0x1f; /* the 5 LSB = which bit to set */
- whichreg = result >> 5; /* the 3 MSB = which reg to set it in */
- value = (1 << (31-whichbit));
-
- reg_array = &(regs->hash.gaddr0);
-
- if (set) {
- reg_array[whichreg] |= value;
- } else {
- reg_array[whichreg] &= ~value;
- }
+ struct tsec_private *priv = (struct tsec_private *)dev->priv;
+ struct tsec __iomem *regs = priv->regs;
+ u32 result, value;
+ u8 whichbit, whichreg;
+
+ result = ether_crc(MAC_ADDR_LEN, mcast_mac);
+ whichbit = (result >> 24) & 0x1f; /* the 5 LSB = which bit to set */
+ whichreg = result >> 29; /* the 3 MSB = which reg to set it in */
+
+ value = 1 << (31-whichbit);
+
+ if (set)
+ setbits_be32(&regs->hash.gaddr0 + whichreg, value);
+ else
+ clrbits_be32(&regs->hash.gaddr0 + whichreg, value);
+
return 0;
}
#endif /* Multicast TFTP ? */
@@ -147,7 +138,7 @@ tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
* those we don't care about (unless zero is bad, in which case,
* choose a more appropriate value)
*/
-static void init_registers(tsec_t *regs)
+static void init_registers(struct tsec __iomem *regs)
{
/* Clear IEVENT */
out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
@@ -175,7 +166,7 @@ static void init_registers(tsec_t *regs)
out_be32(&regs->rctrl, 0x00000000);
/* Init RMON mib registers */
- memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
+ memset((void *)&regs->rmon, 0, sizeof(regs->rmon));
out_be32(&regs->rmon.cam1, 0xffffffff);
out_be32(&regs->rmon.cam2, 0xffffffff);
@@ -194,7 +185,7 @@ static void init_registers(tsec_t *regs)
*/
static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
{
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
u32 ecntrl, maccfg2;
if (!phydev->link) {
@@ -248,7 +239,7 @@ static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
void redundant_init(struct eth_device *dev)
{
struct tsec_private *priv = dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
uint t, count = 0;
int fail = 1;
static const u8 pkt[] = {
@@ -281,23 +272,26 @@ void redundant_init(struct eth_device *dev)
clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
do {
+ uint16_t status;
tsec_send(dev, (void *)pkt, sizeof(pkt));
/* Wait for buffer to be received */
- for (t = 0; rtx.rxbd[rxIdx].status & RXBD_EMPTY; t++) {
+ for (t = 0; in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY; t++) {
if (t >= 10 * TOUT_LOOP) {
printf("%s: tsec: rx error\n", dev->name);
break;
}
}
- if (!memcmp(pkt, (void *)NetRxPackets[rxIdx], sizeof(pkt)))
+ if (!memcmp(pkt, (void *)NetRxPackets[rx_idx], sizeof(pkt)))
fail = 0;
- rtx.rxbd[rxIdx].length = 0;
- rtx.rxbd[rxIdx].status =
- RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
- rxIdx = (rxIdx + 1) % PKTBUFSRX;
+ out_be16(&rxbd[rx_idx].length, 0);
+ status = RXBD_EMPTY;
+ if ((rx_idx + 1) == PKTBUFSRX)
+ status |= RXBD_WRAP;
+ out_be16(&rxbd[rx_idx].status, status);
+ rx_idx = (rx_idx + 1) % PKTBUFSRX;
if (in_be32(&regs->ievent) & IEVENT_BSY) {
out_be32(&regs->ievent, IEVENT_BSY);
@@ -325,36 +319,39 @@ void redundant_init(struct eth_device *dev)
*/
static void startup_tsec(struct eth_device *dev)
{
- int i;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
+ uint16_t status;
+ int i;
/* reset the indices to zero */
- rxIdx = 0;
- txIdx = 0;
+ rx_idx = 0;
+ tx_idx = 0;
#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
uint svr;
#endif
/* Point to the buffer descriptors */
- out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
- out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
+ out_be32(&regs->tbase, (u32)&txbd[0]);
+ out_be32(&regs->rbase, (u32)&rxbd[0]);
/* Initialize the Rx Buffer descriptors */
for (i = 0; i < PKTBUFSRX; i++) {
- rtx.rxbd[i].status = RXBD_EMPTY;
- rtx.rxbd[i].length = 0;
- rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
+ out_be16(&rxbd[i].status, RXBD_EMPTY);
+ out_be16(&rxbd[i].length, 0);
+ out_be32(&rxbd[i].bufptr, (u32)NetRxPackets[i]);
}
- rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
+ status = in_be16(&rxbd[PKTBUFSRX - 1].status);
+ out_be16(&rxbd[PKTBUFSRX - 1].status, status | RXBD_WRAP);
/* Initialize the TX Buffer Descriptors */
for (i = 0; i < TX_BUF_CNT; i++) {
- rtx.txbd[i].status = 0;
- rtx.txbd[i].length = 0;
- rtx.txbd[i].bufPtr = 0;
+ out_be16(&txbd[i].status, 0);
+ out_be16(&txbd[i].length, 0);
+ out_be32(&txbd[i].bufptr, 0);
}
- rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
+ status = in_be16(&txbd[TX_BUF_CNT - 1].status);
+ out_be16(&txbd[TX_BUF_CNT - 1].status, status | TXBD_WRAP);
#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
svr = get_svr();
@@ -378,66 +375,67 @@ static void startup_tsec(struct eth_device *dev)
*/
static int tsec_send(struct eth_device *dev, void *packet, int length)
{
- int i;
- int result = 0;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
+ uint16_t status;
+ int result = 0;
+ int i;
/* Find an empty buffer descriptor */
- for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+ for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
debug("%s: tsec: tx buffers full\n", dev->name);
return result;
}
}
- rtx.txbd[txIdx].bufPtr = (uint) packet;
- rtx.txbd[txIdx].length = length;
- rtx.txbd[txIdx].status |=
- (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+ out_be32(&txbd[tx_idx].bufptr, (u32)packet);
+ out_be16(&txbd[tx_idx].length, length);
+ status = in_be16(&txbd[tx_idx].status);
+ out_be16(&txbd[tx_idx].status, status |
+ (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));
/* Tell the DMA to go */
out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
/* Wait for buffer to be transmitted */
- for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+ for (i = 0; in_be16(&txbd[tx_idx].status) & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
debug("%s: tsec: tx error\n", dev->name);
return result;
}
}
- txIdx = (txIdx + 1) % TX_BUF_CNT;
- result = rtx.txbd[txIdx].status & TXBD_STATS;
+ tx_idx = (tx_idx + 1) % TX_BUF_CNT;
+ result = in_be16(&txbd[tx_idx].status) & TXBD_STATS;
return result;
}
static int tsec_recv(struct eth_device *dev)
{
- int length;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
- while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
-
- length = rtx.rxbd[rxIdx].length;
+ while (!(in_be16(&rxbd[rx_idx].status) & RXBD_EMPTY)) {
+ int length = in_be16(&rxbd[rx_idx].length);
+ uint16_t status = in_be16(&rxbd[rx_idx].status);
/* Send the packet up if there were no errors */
- if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
- NetReceive(NetRxPackets[rxIdx], length - 4);
- } else {
- printf("Got error %x\n",
- (rtx.rxbd[rxIdx].status & RXBD_STATS));
- }
+ if (!(status & RXBD_STATS))
+ NetReceive(NetRxPackets[rx_idx], length - 4);
+ else
+ printf("Got error %x\n", (status & RXBD_STATS));
- rtx.rxbd[rxIdx].length = 0;
+ out_be16(&rxbd[rx_idx].length, 0);
+ status = RXBD_EMPTY;
/* Set the wrap bit if this is the last element in the list */
- rtx.rxbd[rxIdx].status =
- RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+ if ((rx_idx + 1) == PKTBUFSRX)
+ status |= RXBD_WRAP;
+ out_be16(&rxbd[rx_idx].status, status);
- rxIdx = (rxIdx + 1) % PKTBUFSRX;
+ rx_idx = (rx_idx + 1) % PKTBUFSRX;
}
if (in_be32(&regs->ievent) & IEVENT_BSY) {
@@ -453,7 +451,7 @@ static int tsec_recv(struct eth_device *dev)
static void tsec_halt(struct eth_device *dev)
{
struct tsec_private *priv = (struct tsec_private *)dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
@@ -475,11 +473,9 @@ static void tsec_halt(struct eth_device *dev)
*/
static int tsec_init(struct eth_device *dev, bd_t * bd)
{
- uint tempval;
- char tmpbuf[MAC_ADDR_LEN];
- int i;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
+ u32 tempval;
int ret;
/* Make sure the controller is stopped */
@@ -492,16 +488,16 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
/* Copy the station address into the address registers.
- * Backwards, because little endian MACS are dumb */
- for (i = 0; i < MAC_ADDR_LEN; i++)
- tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
-
- tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
- tmpbuf[3];
+ * For a station address of 0x12345678ABCD in transmission
+ * order (BE), MACnADDR1 is set to 0xCDAB7856 and
+ * MACnADDR2 is set to 0x34120000.
+ */
+ tempval = (dev->enetaddr[5] << 24) | (dev->enetaddr[4] << 16) |
+ (dev->enetaddr[3] << 8) | dev->enetaddr[2];
out_be32(&regs->macstnaddr1, tempval);
- tempval = *((uint *) (tmpbuf + 4));
+ tempval = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16);
out_be32(&regs->macstnaddr2, tempval);
@@ -527,7 +523,7 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
static phy_interface_t tsec_get_interface(struct tsec_private *priv)
{
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
u32 ecntrl;
ecntrl = in_be32(&regs->ecntrl);
@@ -576,7 +572,7 @@ static int init_phy(struct eth_device *dev)
{
struct tsec_private *priv = (struct tsec_private *)dev->priv;
struct phy_device *phydev;
- tsec_t *regs = priv->regs;
+ struct tsec __iomem *regs = priv->regs;
u32 supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
@@ -626,7 +622,6 @@ static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
if (NULL == priv)
return 0;
- privlist[num_tsecs++] = priv;
priv->regs = tsec_info->regs;
priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
@@ -684,7 +679,7 @@ int tsec_standard_init(bd_t *bis)
{
struct fsl_pq_mdio_info info;
- info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
+ info.regs = TSEC_GET_MDIO_REGS_BASE(1);
info.name = DEFAULT_MII_NAME;
fsl_pq_mdio_init(bis, &info);
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 236a753..6a017a8 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -43,11 +43,6 @@
#define ZYNQ_GEM_TXBUF_WRAP_MASK 0x40000000
#define ZYNQ_GEM_TXBUF_LAST_MASK 0x00008000 /* Last buffer */
-#define ZYNQ_GEM_TXSR_HRESPNOK_MASK 0x00000100 /* Transmit hresp not OK */
-#define ZYNQ_GEM_TXSR_URUN_MASK 0x00000040 /* Transmit underrun */
-/* Transmit buffs exhausted mid frame */
-#define ZYNQ_GEM_TXSR_BUFEXH_MASK 0x00000010
-
#define ZYNQ_GEM_NWCTRL_TXEN_MASK 0x00000008 /* Enable transmit */
#define ZYNQ_GEM_NWCTRL_RXEN_MASK 0x00000004 /* Enable receive */
#define ZYNQ_GEM_NWCTRL_MDEN_MASK 0x00000010 /* Enable MDIO port */
@@ -90,6 +85,11 @@
*/
#define PHY_DETECT_MASK 0x1808
+/* TX BD status masks */
+#define ZYNQ_GEM_TXBUF_FRMLEN_MASK 0x000007ff
+#define ZYNQ_GEM_TXBUF_EXHAUSTED 0x08000000
+#define ZYNQ_GEM_TXBUF_UNDERRUN 0x10000000
+
/* Device registers */
struct zynq_gem_regs {
u32 nwctrl; /* Network Control reg */
@@ -123,12 +123,18 @@ struct emac_bd {
};
#define RX_BUF 3
+/* Page table entries are set to 1MB, or multiples of 1MB
+ * (not < 1MB). driver uses less bd's so use 1MB bdspace.
+ */
+#define BD_SPACE 0x100000
+/* BD separation space */
+#define BD_SEPRN_SPACE 64
/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
struct zynq_gem_priv {
- struct emac_bd tx_bd;
- struct emac_bd rx_bd[RX_BUF];
- char rxbuffers[RX_BUF * PKTSIZE_ALIGN];
+ struct emac_bd *tx_bd;
+ struct emac_bd *rx_bd;
+ char *rxbuffers;
u32 rxbd_current;
u32 rx_first_buf;
int phyaddr;
@@ -299,20 +305,18 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
readl(&regs->stat[i]);
/* Setup RxBD space */
- memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd));
- /* Create the RxBD ring */
- memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers));
+ memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));
for (i = 0; i < RX_BUF; i++) {
priv->rx_bd[i].status = 0xF0000000;
priv->rx_bd[i].addr =
- (u32)((char *)&(priv->rxbuffers) +
+ ((u32)(priv->rxbuffers) +
(i * PKTSIZE_ALIGN));
}
/* WRAP bit to last BD */
priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;
/* Write RxBDs to IP */
- writel((u32)&(priv->rx_bd), &regs->rxqbase);
+ writel((u32)priv->rx_bd, &regs->rxqbase);
/* Setup for DMA Configuration register */
writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);
@@ -368,32 +372,35 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)
{
- u32 status;
+ u32 addr, size;
struct zynq_gem_priv *priv = dev->priv;
struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
- const u32 mask = ZYNQ_GEM_TXSR_HRESPNOK_MASK | \
- ZYNQ_GEM_TXSR_URUN_MASK | ZYNQ_GEM_TXSR_BUFEXH_MASK;
/* setup BD */
- writel((u32)&(priv->tx_bd), &regs->txqbase);
+ writel((u32)priv->tx_bd, &regs->txqbase);
/* Setup Tx BD */
- memset((void *)&(priv->tx_bd), 0, sizeof(struct emac_bd));
+ memset(priv->tx_bd, 0, sizeof(struct emac_bd));
+
+ priv->tx_bd->addr = (u32)ptr;
+ priv->tx_bd->status = (len & ZYNQ_GEM_TXBUF_FRMLEN_MASK) |
+ ZYNQ_GEM_TXBUF_LAST_MASK;
- priv->tx_bd.addr = (u32)ptr;
- priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK;
+ addr = (u32) ptr;
+ addr &= ~(ARCH_DMA_MINALIGN - 1);
+ size = roundup(len, ARCH_DMA_MINALIGN);
+ flush_dcache_range(addr, addr + size);
+ barrier();
/* Start transmit */
setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK);
- /* Read the stat register to know if the packet has been transmitted */
- status = readl(&regs->txsr);
- if (status & mask)
- printf("Something has gone wrong here!? Status is 0x%x.\n",
- status);
+ /* Read TX BD status */
+ if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_UNDERRUN)
+ printf("TX underrun\n");
+ if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
+ printf("TX buffers exhausted in mid frame\n");
- /* Clear Tx status register before leaving . */
- writel(status, &regs->txsr);
return 0;
}
@@ -416,8 +423,12 @@ static int zynq_gem_recv(struct eth_device *dev)
frame_len = current_bd->status & ZYNQ_GEM_RXBUF_LEN_MASK;
if (frame_len) {
- NetReceive((u8 *) (current_bd->addr &
- ZYNQ_GEM_RXBUF_ADD_MASK), frame_len);
+ u32 addr = current_bd->addr & ZYNQ_GEM_RXBUF_ADD_MASK;
+ addr &= ~(ARCH_DMA_MINALIGN - 1);
+ u32 size = roundup(frame_len, ARCH_DMA_MINALIGN);
+ invalidate_dcache_range(addr, addr + size);
+
+ NetReceive((u8 *)addr, frame_len);
if (current_bd->status & ZYNQ_GEM_RXBUF_SOF_MASK)
priv->rx_first_buf = priv->rxbd_current;
@@ -471,6 +482,7 @@ int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio)
{
struct eth_device *dev;
struct zynq_gem_priv *priv;
+ void *bd_space;
dev = calloc(1, sizeof(*dev));
if (dev == NULL)
@@ -483,6 +495,18 @@ int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio)
}
priv = dev->priv;
+ /* Align rxbuffers to ARCH_DMA_MINALIGN */
+ priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN);
+ memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN);
+
+ /* Align bd_space to 1MB */
+ bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
+ mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE, DCACHE_OFF);
+
+ /* Initialize the bd spaces for tx and rx bd's */
+ priv->tx_bd = (struct emac_bd *)bd_space;
+ priv->rx_bd = (struct emac_bd *)((u32)bd_space + BD_SEPRN_SPACE);
+
priv->phyaddr = phy_addr;
priv->emio = emio;