summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/sata_sil.c1
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/at91_gpio.c125
-rw-r--r--drivers/gpio/spear_gpio.c102
-rw-r--r--drivers/gpio/tegra_gpio.c (renamed from drivers/gpio/tegra2_gpio.c)2
-rw-r--r--drivers/i2c/designware_i2c.c16
-rw-r--r--drivers/i2c/mxc_i2c.c31
-rw-r--r--drivers/i2c/mxs_i2c.c2
-rw-r--r--drivers/i2c/omap24xx_i2c.c46
-rw-r--r--drivers/mmc/Makefile2
-rw-r--r--drivers/mmc/fsl_esdhc.c20
-rw-r--r--drivers/mmc/mmc.c23
-rw-r--r--drivers/mmc/tegra_mmc.c (renamed from drivers/mmc/tegra2_mmc.c)4
-rw-r--r--drivers/mmc/tegra_mmc.h (renamed from drivers/mmc/tegra2_mmc.h)8
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/fsmc_nand.c486
-rw-r--r--drivers/mtd/nand/spr_nand.c124
-rw-r--r--drivers/mtd/spi/eon.c44
-rw-r--r--drivers/mtd/spi/macronix.c91
-rw-r--r--drivers/mtd/spi/ramtron.c23
-rw-r--r--drivers/mtd/spi/spansion.c68
-rw-r--r--drivers/mtd/spi/spi_flash.c35
-rw-r--r--drivers/mtd/spi/spi_flash_internal.h12
-rw-r--r--drivers/mtd/spi/sst.c76
-rw-r--r--drivers/mtd/spi/stmicro.c36
-rw-r--r--drivers/mtd/spi/winbond.c66
-rw-r--r--drivers/mtd/st_smi.c (renamed from drivers/mtd/spr_smi.c)255
-rw-r--r--drivers/net/bfin_mac.c3
-rw-r--r--drivers/net/davinci_emac.c8
-rw-r--r--drivers/net/designware.c130
-rw-r--r--drivers/net/designware.h2
-rw-r--r--drivers/net/fec_mxc.c18
-rw-r--r--drivers/net/fm/eth.c9
-rw-r--r--drivers/net/phy/micrel.c15
-rw-r--r--drivers/net/phy/phy.c5
-rw-r--r--drivers/net/sh_eth.c145
-rw-r--r--drivers/net/sh_eth.h396
-rw-r--r--drivers/net/tsec.c8
-rw-r--r--drivers/net/xilinx_axi_emac.c6
-rw-r--r--drivers/net/xilinx_ll_temac.c8
-rw-r--r--drivers/rtc/m41t62.c10
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/kirkwood_spi.c64
-rw-r--r--drivers/spi/tegra_spi.c (renamed from drivers/spi/tegra2_spi.c)17
-rw-r--r--drivers/usb/eth/asix.c30
-rw-r--r--drivers/usb/eth/smsc95xx.c13
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-atmel.c89
-rw-r--r--drivers/usb/host/ehci-exynos.c (renamed from drivers/usb/host/ehci-s5p.c)26
-rw-r--r--drivers/usb/host/ehci-hcd.c96
-rw-r--r--drivers/usb/host/ehci-omap.c1
-rw-r--r--drivers/usb/host/ehci-tegra.c18
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/cfb_console.c2
-rw-r--r--drivers/video/da8xx-fb.c1
-rw-r--r--drivers/video/exynos_fb.c3
-rw-r--r--drivers/video/ipu_common.c23
-rw-r--r--drivers/video/ipu_disp.c3
-rw-r--r--drivers/video/ipu_regs.h12
61 files changed, 1806 insertions, 1067 deletions
diff --git a/drivers/block/sata_sil.c b/drivers/block/sata_sil.c
index 5e7ef5e..fb7cd2a 100644
--- a/drivers/block/sata_sil.c
+++ b/drivers/block/sata_sil.c
@@ -30,7 +30,6 @@
/* Convert sectorsize to wordsize */
#define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
-#define mdelay(n) udelay((n)*1000)
#define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v))
static struct sata_info sata_info;
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fb3b09a..32a2474 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,7 +35,8 @@ COBJS-$(CONFIG_PCA953X) += pca953x.o
COBJS-$(CONFIG_PCA9698) += pca9698.o
COBJS-$(CONFIG_S5P) += s5p_gpio.o
COBJS-$(CONFIG_SANDBOX_GPIO) += sandbox.o
-COBJS-$(CONFIG_TEGRA2_GPIO) += tegra2_gpio.o
+COBJS-$(CONFIG_SPEAR_GPIO) += spear_gpio.o
+COBJS-$(CONFIG_TEGRA_GPIO) += tegra_gpio.o
COBJS-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
COBJS-$(CONFIG_ALTERA_PIO) += altera_pio.o
COBJS-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c
index be2a026..ac3b322 100644
--- a/drivers/gpio/at91_gpio.c
+++ b/drivers/gpio/at91_gpio.c
@@ -86,7 +86,14 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
mask = 1 << pin;
writel(mask, &pio->port[port].idr);
at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+ writel(readl(&pio->port[port].abcdsr1) & ~mask,
+ &pio->port[port].abcdsr1);
+ writel(readl(&pio->port[port].abcdsr2) & ~mask,
+ &pio->port[port].abcdsr2);
+#else
writel(mask, &pio->port[port].asr);
+#endif
writel(mask, &pio->port[port].pdr);
}
return 0;
@@ -104,12 +111,63 @@ int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
mask = 1 << pin;
writel(mask, &pio->port[port].idr);
at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+ writel(readl(&pio->port[port].abcdsr1) | mask,
+ &pio->port[port].abcdsr1);
+ writel(readl(&pio->port[port].abcdsr2) & ~mask,
+ &pio->port[port].abcdsr2);
+#else
writel(mask, &pio->port[port].bsr);
+#endif
writel(mask, &pio->port[port].pdr);
}
return 0;
}
+#if defined(CPU_HAS_PIO3)
+/*
+ * mux the pin to the "C" internal peripheral role.
+ */
+int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &pio->port[port].idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(readl(&pio->port[port].abcdsr1) & ~mask,
+ &pio->port[port].abcdsr1);
+ writel(readl(&pio->port[port].abcdsr2) | mask,
+ &pio->port[port].abcdsr2);
+ writel(mask, &pio->port[port].pdr);
+ }
+ return 0;
+}
+
+/*
+ * mux the pin to the "D" internal peripheral role.
+ */
+int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &pio->port[port].idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(readl(&pio->port[port].abcdsr1) | mask,
+ &pio->port[port].abcdsr1);
+ writel(readl(&pio->port[port].abcdsr2) | mask,
+ &pio->port[port].abcdsr2);
+ writel(mask, &pio->port[port].pdr);
+ }
+ return 0;
+}
+#endif
+
/*
* mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
* configure it for an input.
@@ -162,13 +220,76 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
mask = 1 << pin;
- if (is_on)
+ if (is_on) {
+#if defined(CPU_HAS_PIO3)
+ writel(mask, &pio->port[port].ifscdr);
+#endif
writel(mask, &pio->port[port].ifer);
- else
+ } else {
writel(mask, &pio->port[port].ifdr);
+ }
+ }
+ return 0;
+}
+
+#if defined(CPU_HAS_PIO3)
+/*
+ * enable/disable the debounce filter.
+ */
+int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
+{
+ at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ if (is_on) {
+ writel(mask, &pio->port[port].ifscer);
+ writel(div & PIO_SCDR_DIV, &pio->port[port].scdr);
+ writel(mask, &pio->port[port].ifer);
+ } else {
+ writel(mask, &pio->port[port].ifdr);
+ }
+ }
+ return 0;
+}
+
+/*
+ * enable/disable the pull-down.
+ * If pull-up already enabled while calling the function, we disable it.
+ */
+int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
+{
+ at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &pio->port[port].pudr);
+ if (is_on)
+ writel(mask, &pio->port[port].ppder);
+ else
+ writel(mask, &pio->port[port].ppddr);
+ }
+ return 0;
+}
+
+/*
+ * disable Schmitt trigger
+ */
+int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
+{
+ at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ writel(readl(&pio->port[port].schmitt) | mask,
+ &pio->port[port].schmitt);
}
return 0;
}
+#endif
/*
* enable/disable the multi-driver. This is only valid for output and
diff --git a/drivers/gpio/spear_gpio.c b/drivers/gpio/spear_gpio.c
new file mode 100644
index 0000000..d3c728e
--- /dev/null
+++ b/drivers/gpio/spear_gpio.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Driver for SPEAr600 GPIO controller
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+static int gpio_direction(unsigned gpio,
+ enum gpio_direction direction)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+ u32 val;
+
+ val = readl(&regs->gpiodir);
+
+ if (direction == GPIO_DIRECTION_OUT)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+
+ writel(val, &regs->gpiodir);
+
+ return 0;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+
+ writel(1 << gpio, &regs->gpiodata[DATA_REG_ADDR(gpio)]);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+ u32 val;
+
+ val = readl(&regs->gpiodata[DATA_REG_ADDR(gpio)]);
+
+ return !!val;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= SPEAR_GPIO_COUNT)
+ return -EINVAL;
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+void gpio_toggle_value(unsigned gpio)
+{
+ gpio_set_value(gpio, !gpio_get_value(gpio));
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return gpio_direction(gpio, GPIO_DIRECTION_IN);
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ int ret = gpio_direction(gpio, GPIO_DIRECTION_OUT);
+
+ if (ret < 0)
+ return ret;
+
+ gpio_set_value(gpio, value);
+ return 0;
+}
diff --git a/drivers/gpio/tegra2_gpio.c b/drivers/gpio/tegra_gpio.c
index 70ca46f..60ec6e3 100644
--- a/drivers/gpio/tegra2_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -1,6 +1,6 @@
/*
* NVIDIA Tegra2 GPIO handling.
- * (C) Copyright 2010,2011
+ * (C) Copyright 2010-2012
* NVIDIA Corporation <www.nvidia.com>
*
* See file CREDITS for list of people who contributed to this
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 6d118ac..bf64a2a 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -90,7 +90,7 @@ static void set_speed(int i2c_spd)
*
* Set the i2c speed.
*/
-void i2c_set_bus_speed(int speed)
+int i2c_set_bus_speed(int speed)
{
if (speed >= I2C_MAX_SPEED)
set_speed(IC_SPEED_MODE_MAX);
@@ -98,6 +98,8 @@ void i2c_set_bus_speed(int speed)
set_speed(IC_SPEED_MODE_FAST);
else
set_speed(IC_SPEED_MODE_STANDARD);
+
+ return 0;
}
/*
@@ -215,10 +217,8 @@ static int check_params(uint addr, int alen, uchar *buffer, int len)
static int i2c_xfer_init(uchar chip, uint addr)
{
- if (i2c_wait_for_bb()) {
- printf("Timed out waiting for bus\n");
+ if (i2c_wait_for_bb())
return 1;
- }
i2c_setaddress(chip);
writel(addr, &i2c_regs_p->ic_cmd_data);
@@ -282,7 +282,6 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
start_time_rx = get_timer(0);
} else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
- printf("Timed out. i2c read Failed\n");
return 1;
}
}
@@ -334,9 +333,14 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
int i2c_probe(uchar chip)
{
u32 tmp;
+ int ret;
/*
* Try to read the first location of the chip.
*/
- return i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
+ ret = i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
+ if (ret)
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+ return ret;
}
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index c88ac7c..fc68062 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -59,27 +59,10 @@ struct mxc_i2c_regs {
#define I2SR_IIF (1 << 1)
#define I2SR_RX_NO_AK (1 << 0)
-#if defined(CONFIG_SYS_I2C_MX31_PORT1)
-#define I2C_BASE 0x43f80000
-#define I2C_CLK_OFFSET 26
-#elif defined (CONFIG_SYS_I2C_MX31_PORT2)
-#define I2C_BASE 0x43f98000
-#define I2C_CLK_OFFSET 28
-#elif defined (CONFIG_SYS_I2C_MX31_PORT3)
-#define I2C_BASE 0x43f84000
-#define I2C_CLK_OFFSET 30
-#elif defined(CONFIG_SYS_I2C_MX53_PORT1)
-#define I2C_BASE I2C1_BASE_ADDR
-#elif defined(CONFIG_SYS_I2C_MX53_PORT2)
-#define I2C_BASE I2C2_BASE_ADDR
-#elif defined(CONFIG_SYS_I2C_MX35_PORT1)
-#define I2C_BASE I2C_BASE_ADDR
-#elif defined(CONFIG_SYS_I2C_MX35_PORT2)
-#define I2C_BASE I2C2_BASE_ADDR
-#elif defined(CONFIG_SYS_I2C_MX35_PORT3)
-#define I2C_BASE I2C3_BASE_ADDR
+#ifdef CONFIG_SYS_I2C_BASE
+#define I2C_BASE CONFIG_SYS_I2C_BASE
#else
-#error "define CONFIG_SYS_I2C_MX<Processor>_PORTx to use the mx I2C driver"
+#error "define CONFIG_SYS_I2C_BASE to use the mxc_i2c driver"
#endif
#define I2C_MAX_TIMEOUT 10000
@@ -114,7 +97,7 @@ static uint8_t i2c_imx_get_clk(unsigned int rate)
(struct clock_control_regs *)CCM_BASE;
/* start the required I2C clock */
- writel(readl(&sc_regs->cgr0) | (3 << I2C_CLK_OFFSET),
+ writel(readl(&sc_regs->cgr0) | (3 << CONFIG_SYS_I2C_CLK_OFFSET),
&sc_regs->cgr0);
#endif
@@ -248,12 +231,6 @@ int i2c_imx_start(void)
struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE;
unsigned int temp = 0;
int result;
- int speed = i2c_get_bus_speed();
- u8 clk_idx = i2c_imx_get_clk(speed);
- u8 idx = i2c_clk_div[clk_idx][1];
-
- /* Store divider value */
- writeb(idx, &i2c_regs->ifdr);
/* Enable I2C controller */
writeb(0, &i2c_regs->i2sr);
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
index c8fea32..48aaaa6 100644
--- a/drivers/i2c/mxs_i2c.c
+++ b/drivers/i2c/mxs_i2c.c
@@ -97,7 +97,7 @@ void mxs_i2c_write(uchar chip, uint addr, int alen,
for (i = 0; i < alen; i++) {
data >>= 8;
- data |= ((char *)&addr)[i] << 24;
+ data |= ((char *)&addr)[alen - i - 1] << 24;
if ((i & 3) == 2)
writel(data, &i2c_regs->hw_i2c_data);
}
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index a7ffd95..81193b0 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -202,7 +202,7 @@ static int i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value)
}
if (status & I2C_STAT_RRDY) {
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
- defined(CONFIG_OMAP44XX)
+ defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
*value = readb(&i2c_base->data);
#else
*value = readw(&i2c_base->data);
@@ -232,7 +232,7 @@ static void flush_fifo(void)
stat = readw(&i2c_base->stat);
if (stat == I2C_STAT_RRDY) {
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
- defined(CONFIG_OMAP44XX)
+ defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
readb(&i2c_base->data);
#else
readw(&i2c_base->data);
@@ -255,23 +255,43 @@ int i2c_probe(uchar chip)
/* wait until bus not busy */
wait_for_bb();
- /* try to write one byte */
+ /* try to read one byte */
writew(1, &i2c_base->cnt);
/* set slave address */
writew(chip, &i2c_base->sa);
/* stop bit needed here */
- writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
- I2C_CON_STP, &i2c_base->con);
-
- status = wait_for_pin();
+ writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, &i2c_base->con);
- /* check for ACK (!NAK) */
- if (!(status & I2C_STAT_NACK))
- res = 0;
-
- /* abort transfer (force idle state) */
- writew(0, &i2c_base->con);
+ while (1) {
+ status = wait_for_pin();
+ if (status == 0 || status & I2C_STAT_AL) {
+ res = 1;
+ goto probe_exit;
+ }
+ if (status & I2C_STAT_NACK) {
+ res = 1;
+ writew(0xff, &i2c_base->stat);
+ writew (readw (&i2c_base->con) | I2C_CON_STP, &i2c_base->con);
+ wait_for_bb ();
+ break;
+ }
+ if (status & I2C_STAT_ARDY) {
+ writew(I2C_STAT_ARDY, &i2c_base->stat);
+ break;
+ }
+ if (status & I2C_STAT_RRDY) {
+ res = 0;
+#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
+ defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
+ readb(&i2c_base->data);
+#else
+ readw(&i2c_base->data);
+#endif
+ writew(I2C_STAT_RRDY, &i2c_base->stat);
+ }
+ }
+probe_exit:
flush_fifo();
/* don't allow any more data in... we don't want it. */
writew(0, &i2c_base->cnt);
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index a8e681c..c567737 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -42,7 +42,7 @@ COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
COBJS-$(CONFIG_SDHCI) += sdhci.o
COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
-COBJS-$(CONFIG_TEGRA2_MMC) += tegra2_mmc.o
+COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 07370b5..b6c969d 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -190,6 +190,10 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
esdhc_write32(&regs->dsaddr, (u32)data->dest);
} else {
+ flush_dcache_range((ulong)data->src,
+ (ulong)data->src+data->blocks
+ *data->blocksize);
+
if (wml_value > WML_WR_WML_MAX)
wml_value = WML_WR_WML_MAX_VAL;
if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
@@ -249,7 +253,15 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
return 0;
}
-
+static void check_and_invalidate_dcache_range
+ (struct mmc_cmd *cmd,
+ struct mmc_data *data) {
+ unsigned start = (unsigned)data->dest ;
+ unsigned size = roundup(ARCH_DMA_MINALIGN,
+ data->blocks*data->blocksize);
+ unsigned end = start+size ;
+ invalidate_dcache_range(start, end);
+}
/*
* Sends a command out on the bus. Takes the mmc pointer,
* a command pointer, and an optional data pointer.
@@ -315,6 +327,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
;
+ if (data && (data->flags & MMC_DATA_READ))
+ check_and_invalidate_dcache_range(cmd, data);
+
irqstat = esdhc_read32(&regs->irqstat);
esdhc_write32(&regs->irqstat, irqstat);
@@ -528,6 +543,9 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
/* First reset the eSDHC controller */
esdhc_reset(regs);
+ esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
+ | SYSCTL_IPGEN | SYSCTL_CKEN);
+
mmc->priv = cfg;
mmc->send_cmd = esdhc_send_cmd;
mmc->set_ios = esdhc_set_ios;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index aebe578..c1c2862 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -333,6 +333,7 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
int err = 0;
struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0;
+ int timeout = 1000;
if (!mmc)
return -1;
@@ -352,6 +353,10 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
break;
blk += blk_r;
+
+ /* Waiting for the ready status */
+ if (mmc_send_status(mmc, timeout))
+ return 0;
}
return blk;
@@ -1195,9 +1200,9 @@ int mmc_startup(struct mmc *mmc)
}
if (mmc->card_caps & MMC_MODE_HS)
- mmc_set_clock(mmc, 50000000);
+ mmc->tran_speed = 50000000;
else
- mmc_set_clock(mmc, 25000000);
+ mmc->tran_speed = 25000000;
} else {
width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >>
MMC_MODE_WIDTH_BITS_SHIFT);
@@ -1234,13 +1239,14 @@ int mmc_startup(struct mmc *mmc)
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
- mmc_set_clock(mmc, 52000000);
+ mmc->tran_speed = 52000000;
else
- mmc_set_clock(mmc, 26000000);
- } else
- mmc_set_clock(mmc, 20000000);
+ mmc->tran_speed = 26000000;
+ }
}
+ mmc_set_clock(mmc, mmc->tran_speed);
+
/* fill in device description */
mmc->block_dev.lun = 0;
mmc->block_dev.type = 0;
@@ -1305,8 +1311,11 @@ int mmc_register(struct mmc *mmc)
block_dev_desc_t *mmc_get_dev(int dev)
{
struct mmc *mmc = find_mmc_device(dev);
+ if (!mmc)
+ return NULL;
- return mmc ? &mmc->block_dev : NULL;
+ mmc_init(mmc);
+ return &mmc->block_dev;
}
#endif
diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra_mmc.c
index fb8a57d..29bf583 100644
--- a/drivers/mmc/tegra2_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -2,7 +2,7 @@
* (C) Copyright 2009 SAMSUNG Electronics
* Minkyu Kang <mk7.kang@samsung.com>
* Jaehoon Chung <jh80.chung@samsung.com>
- * Portions Copyright 2011 NVIDIA Corporation
+ * Portions Copyright 2011-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
#include <asm/io.h>
#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
-#include "tegra2_mmc.h"
+#include "tegra_mmc.h"
/* support 4 mmc hosts */
struct mmc mmc_dev[4];
diff --git a/drivers/mmc/tegra2_mmc.h b/drivers/mmc/tegra_mmc.h
index 67c00db..f9cdcaa 100644
--- a/drivers/mmc/tegra2_mmc.h
+++ b/drivers/mmc/tegra_mmc.h
@@ -1,7 +1,7 @@
/*
* (C) Copyright 2009 SAMSUNG Electronics
* Minkyu Kang <mk7.kang@samsung.com>
- * Portions Copyright (C) 2011 NVIDIA Corporation
+ * Portions Copyright (C) 2011-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,8 +19,8 @@
*
*/
-#ifndef __TEGRA2_MMC_H_
-#define __TEGRA2_MMC_H_
+#ifndef __TEGRA_MMC_H_
+#define __TEGRA_MMC_H_
#define TEGRA2_SDMMC1_BASE 0xC8000000
#define TEGRA2_SDMMC2_BASE 0xC8000200
@@ -128,4 +128,4 @@ struct mmc_host {
};
#endif /* __ASSEMBLY__ */
-#endif /* __TEGRA2_MMC_H_ */
+#endif /* __TEGRA_MMC_H_ */
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 5a5ecdf..543c845 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -35,7 +35,7 @@ COBJS-$(CONFIG_HAS_DATAFLASH) += dataflash.o
COBJS-$(CONFIG_FTSMC020) += ftsmc020.o
COBJS-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
COBJS-$(CONFIG_MW_EEPROM) += mw_eeprom.o
-COBJS-$(CONFIG_SPEARSMI) += spr_smi.o
+COBJS-$(CONFIG_ST_SMI) += st_smi.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1d1b628..29dc20e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
COBJS-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
+COBJS-$(CONFIG_NAND_FSMC) += fsmc_nand.o
COBJS-$(CONFIG_NAND_JZ4740) += jz4740_nand.o
COBJS-$(CONFIG_NAND_KB9202) += kb9202_nand.o
COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
new file mode 100644
index 0000000..7a61d88
--- /dev/null
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -0,0 +1,486 @@
+/*
+ * (C) Copyright 2010
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com.
+ *
+ * (C) Copyright 2012
+ * Amit Virdi, ST Microelectronics, amit.virdi@st.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/fsmc_nand.h>
+#include <asm/arch/hardware.h>
+
+static u32 fsmc_version;
+static struct fsmc_regs *const fsmc_regs_p = (struct fsmc_regs *)
+ CONFIG_SYS_FSMC_BASE;
+
+/*
+ * ECC4 and ECC1 have 13 bytes and 3 bytes of ecc respectively for 512 bytes of
+ * data. ECC4 can correct up to 8 bits in 512 bytes of data while ECC1 can
+ * correct 1 bit in 512 bytes
+ */
+
+static struct nand_ecclayout fsmc_ecc4_lp_layout = {
+ .eccbytes = 104,
+ .eccpos = { 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14,
+ 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30,
+ 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46,
+ 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62,
+ 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78,
+ 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94,
+ 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110,
+ 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126
+ },
+ .oobfree = {
+ {.offset = 15, .length = 3},
+ {.offset = 31, .length = 3},
+ {.offset = 47, .length = 3},
+ {.offset = 63, .length = 3},
+ {.offset = 79, .length = 3},
+ {.offset = 95, .length = 3},
+ {.offset = 111, .length = 3},
+ {.offset = 127, .length = 1}
+ }
+};
+
+/*
+ * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes
+ * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118
+ * bytes are free for use.
+ */
+static struct nand_ecclayout fsmc_ecc4_224_layout = {
+ .eccbytes = 104,
+ .eccpos = { 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14,
+ 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30,
+ 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46,
+ 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62,
+ 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78,
+ 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94,
+ 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110,
+ 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126
+ },
+ .oobfree = {
+ {.offset = 15, .length = 3},
+ {.offset = 31, .length = 3},
+ {.offset = 47, .length = 3},
+ {.offset = 63, .length = 3},
+ {.offset = 79, .length = 3},
+ {.offset = 95, .length = 3},
+ {.offset = 111, .length = 3},
+ {.offset = 127, .length = 97}
+ }
+};
+
+/*
+ * ECC placement definitions in oobfree type format
+ * There are 13 bytes of ecc for every 512 byte block and it has to be read
+ * consecutively and immediately after the 512 byte data block for hardware to
+ * generate the error bit offsets in 512 byte data
+ * Managing the ecc bytes in the following way makes it easier for software to
+ * read ecc bytes consecutive to data bytes. This way is similar to
+ * oobfree structure maintained already in u-boot nand driver
+ */
+static struct fsmc_eccplace fsmc_eccpl_lp = {
+ .eccplace = {
+ {.offset = 2, .length = 13},
+ {.offset = 18, .length = 13},
+ {.offset = 34, .length = 13},
+ {.offset = 50, .length = 13},
+ {.offset = 66, .length = 13},
+ {.offset = 82, .length = 13},
+ {.offset = 98, .length = 13},
+ {.offset = 114, .length = 13}
+ }
+};
+
+static struct nand_ecclayout fsmc_ecc4_sp_layout = {
+ .eccbytes = 13,
+ .eccpos = { 0, 1, 2, 3, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14
+ },
+ .oobfree = {
+ {.offset = 15, .length = 1},
+ }
+};
+
+static struct fsmc_eccplace fsmc_eccpl_sp = {
+ .eccplace = {
+ {.offset = 0, .length = 4},
+ {.offset = 6, .length = 9}
+ }
+};
+
+static struct nand_ecclayout fsmc_ecc1_layout = {
+ .eccbytes = 24,
+ .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
+ 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
+ .oobfree = {
+ {.offset = 8, .length = 8},
+ {.offset = 24, .length = 8},
+ {.offset = 40, .length = 8},
+ {.offset = 56, .length = 8},
+ {.offset = 72, .length = 8},
+ {.offset = 88, .length = 8},
+ {.offset = 104, .length = 8},
+ {.offset = 120, .length = 8}
+ }
+};
+
+/* Count the number of 0's in buff upto a max of max_bits */
+static int count_written_bits(uint8_t *buff, int size, int max_bits)
+{
+ int k, written_bits = 0;
+
+ for (k = 0; k < size; k++) {
+ written_bits += hweight8(~buff[k]);
+ if (written_bits > max_bits)
+ break;
+ }
+
+ return written_bits;
+}
+
+static void fsmc_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ ulong IO_ADDR_W;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ IO_ADDR_W = (ulong)this->IO_ADDR_W;
+
+ IO_ADDR_W &= ~(CONFIG_SYS_NAND_CLE | CONFIG_SYS_NAND_ALE);
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W |= CONFIG_SYS_NAND_CLE;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W |= CONFIG_SYS_NAND_ALE;
+
+ if (ctrl & NAND_NCE) {
+ writel(readl(&fsmc_regs_p->pc) |
+ FSMC_ENABLE, &fsmc_regs_p->pc);
+ } else {
+ writel(readl(&fsmc_regs_p->pc) &
+ ~FSMC_ENABLE, &fsmc_regs_p->pc);
+ }
+ this->IO_ADDR_W = (void *)IO_ADDR_W;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+}
+
+static int fsmc_bch8_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ /* The calculated ecc is actually the correction index in data */
+ u32 err_idx[8];
+ u32 num_err, i;
+ u32 ecc1, ecc2, ecc3, ecc4;
+
+ num_err = (readl(&fsmc_regs_p->sts) >> 10) & 0xF;
+
+ if (likely(num_err == 0))
+ return 0;
+
+ if (unlikely(num_err > 8)) {
+ /*
+ * This is a temporary erase check. A newly erased page read
+ * would result in an ecc error because the oob data is also
+ * erased to FF and the calculated ecc for an FF data is not
+ * FF..FF.
+ * This is a workaround to skip performing correction in case
+ * data is FF..FF
+ *
+ * Logic:
+ * For every page, each bit written as 0 is counted until these
+ * number of bits are greater than 8 (the maximum correction
+ * capability of FSMC for each 512 + 13 bytes)
+ */
+
+ int bits_ecc = count_written_bits(read_ecc, 13, 8);
+ int bits_data = count_written_bits(dat, 512, 8);
+
+ if ((bits_ecc + bits_data) <= 8) {
+ if (bits_data)
+ memset(dat, 0xff, 512);
+ return bits_data + bits_ecc;
+ }
+
+ return -EBADMSG;
+ }
+
+ ecc1 = readl(&fsmc_regs_p->ecc1);
+ ecc2 = readl(&fsmc_regs_p->ecc2);
+ ecc3 = readl(&fsmc_regs_p->ecc3);
+ ecc4 = readl(&fsmc_regs_p->sts);
+
+ err_idx[0] = (ecc1 >> 0) & 0x1FFF;
+ err_idx[1] = (ecc1 >> 13) & 0x1FFF;
+ err_idx[2] = (((ecc2 >> 0) & 0x7F) << 6) | ((ecc1 >> 26) & 0x3F);
+ err_idx[3] = (ecc2 >> 7) & 0x1FFF;
+ err_idx[4] = (((ecc3 >> 0) & 0x1) << 12) | ((ecc2 >> 20) & 0xFFF);
+ err_idx[5] = (ecc3 >> 1) & 0x1FFF;
+ err_idx[6] = (ecc3 >> 14) & 0x1FFF;
+ err_idx[7] = (((ecc4 >> 16) & 0xFF) << 5) | ((ecc3 >> 27) & 0x1F);
+
+ i = 0;
+ while (i < num_err) {
+ err_idx[i] ^= 3;
+
+ if (err_idx[i] < 512 * 8)
+ __change_bit(err_idx[i], dat);
+
+ i++;
+ }
+
+ return num_err;
+}
+
+static int fsmc_read_hwecc(struct mtd_info *mtd,
+ const u_char *data, u_char *ecc)
+{
+ u_int ecc_tmp;
+ int timeout = CONFIG_SYS_HZ;
+ ulong start;
+
+ switch (fsmc_version) {
+ case FSMC_VER8:
+ start = get_timer(0);
+ while (get_timer(start) < timeout) {
+ /*
+ * Busy waiting for ecc computation
+ * to finish for 512 bytes
+ */
+ if (readl(&fsmc_regs_p->sts) & FSMC_CODE_RDY)
+ break;
+ }
+
+ ecc_tmp = readl(&fsmc_regs_p->ecc1);
+ ecc[0] = (u_char) (ecc_tmp >> 0);
+ ecc[1] = (u_char) (ecc_tmp >> 8);
+ ecc[2] = (u_char) (ecc_tmp >> 16);
+ ecc[3] = (u_char) (ecc_tmp >> 24);
+
+ ecc_tmp = readl(&fsmc_regs_p->ecc2);
+ ecc[4] = (u_char) (ecc_tmp >> 0);
+ ecc[5] = (u_char) (ecc_tmp >> 8);
+ ecc[6] = (u_char) (ecc_tmp >> 16);
+ ecc[7] = (u_char) (ecc_tmp >> 24);
+
+ ecc_tmp = readl(&fsmc_regs_p->ecc3);
+ ecc[8] = (u_char) (ecc_tmp >> 0);
+ ecc[9] = (u_char) (ecc_tmp >> 8);
+ ecc[10] = (u_char) (ecc_tmp >> 16);
+ ecc[11] = (u_char) (ecc_tmp >> 24);
+
+ ecc_tmp = readl(&fsmc_regs_p->sts);
+ ecc[12] = (u_char) (ecc_tmp >> 16);
+ break;
+
+ default:
+ ecc_tmp = readl(&fsmc_regs_p->ecc1);
+ ecc[0] = (u_char) (ecc_tmp >> 0);
+ ecc[1] = (u_char) (ecc_tmp >> 8);
+ ecc[2] = (u_char) (ecc_tmp >> 16);
+ break;
+ }
+
+ return 0;
+}
+
+void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+ writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCPLEN_256,
+ &fsmc_regs_p->pc);
+ writel(readl(&fsmc_regs_p->pc) & ~FSMC_ECCEN,
+ &fsmc_regs_p->pc);
+ writel(readl(&fsmc_regs_p->pc) | FSMC_ECCEN,
+ &fsmc_regs_p->pc);
+}
+
+/*
+ * fsmc_read_page_hwecc
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @page: page number to read
+ *
+ * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
+ * performed in a strict sequence as follows:
+ * data(512 byte) -> ecc(13 byte)
+ * After this read, fsmc hardware generates and reports error data bits(upto a
+ * max of 8 bits)
+ */
+static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int page)
+{
+ struct fsmc_eccplace *fsmc_eccpl;
+ int i, j, s, stat, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ uint8_t *ecc_calc = chip->buffers->ecccalc;
+ uint8_t *ecc_code = chip->buffers->ecccode;
+ int off, len, group = 0;
+ uint8_t oob[13] __attribute__ ((aligned (2)));
+
+ /* Differentiate between small and large page ecc place definitions */
+ if (mtd->writesize == 512)
+ fsmc_eccpl = &fsmc_eccpl_sp;
+ else
+ fsmc_eccpl = &fsmc_eccpl_lp;
+
+ for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
+
+ chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+
+ for (j = 0; j < eccbytes;) {
+ off = fsmc_eccpl->eccplace[group].offset;
+ len = fsmc_eccpl->eccplace[group].length;
+ group++;
+
+ /*
+ * length is intentionally kept a higher multiple of 2
+ * to read at least 13 bytes even in case of 16 bit NAND
+ * devices
+ */
+ if (chip->options & NAND_BUSWIDTH_16)
+ len = roundup(len, 2);
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
+ chip->read_buf(mtd, oob + j, len);
+ j += len;
+ }
+
+ memcpy(&ecc_code[i], oob, 13);
+ chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+
+ stat = chip->ecc.correct(mtd, p, &ecc_code[i],
+ &ecc_calc[i]);
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+
+ return 0;
+}
+
+int fsmc_nand_init(struct nand_chip *nand)
+{
+ static int chip_nr;
+ struct mtd_info *mtd;
+ int i;
+ u32 peripid2 = readl(&fsmc_regs_p->peripid2);
+
+ fsmc_version = (peripid2 >> FSMC_REVISION_SHFT) &
+ FSMC_REVISION_MSK;
+
+ writel(readl(&fsmc_regs_p->ctrl) | FSMC_WP, &fsmc_regs_p->ctrl);
+
+#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
+ writel(FSMC_DEVWID_16 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
+ &fsmc_regs_p->pc);
+#elif defined(CONFIG_SYS_FSMC_NAND_8BIT)
+ writel(FSMC_DEVWID_8 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
+ &fsmc_regs_p->pc);
+#else
+#error Please define CONFIG_SYS_FSMC_NAND_16BIT or CONFIG_SYS_FSMC_NAND_8BIT
+#endif
+ writel(readl(&fsmc_regs_p->pc) | FSMC_TCLR_1 | FSMC_TAR_1,
+ &fsmc_regs_p->pc);
+ writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
+ &fsmc_regs_p->comm);
+ writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
+ &fsmc_regs_p->attrib);
+
+ nand->options = 0;
+#if defined(CONFIG_SYS_FSMC_NAND_16BIT)
+ nand->options |= NAND_BUSWIDTH_16;
+#endif
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.size = 512;
+ nand->ecc.calculate = fsmc_read_hwecc;
+ nand->ecc.hwctl = fsmc_enable_hwecc;
+ nand->cmd_ctrl = fsmc_nand_hwcontrol;
+ nand->IO_ADDR_R = nand->IO_ADDR_W =
+ (void __iomem *)CONFIG_SYS_NAND_BASE;
+ nand->badblockbits = 7;
+
+ mtd = &nand_info[chip_nr++];
+ mtd->priv = nand;
+
+ switch (fsmc_version) {
+ case FSMC_VER8:
+ nand->ecc.bytes = 13;
+ nand->ecc.correct = fsmc_bch8_correct_data;
+ nand->ecc.read_page = fsmc_read_page_hwecc;
+ if (mtd->writesize == 512)
+ nand->ecc.layout = &fsmc_ecc4_sp_layout;
+ else {
+ if (mtd->oobsize == 224)
+ nand->ecc.layout = &fsmc_ecc4_224_layout;
+ else
+ nand->ecc.layout = &fsmc_ecc4_lp_layout;
+ }
+
+ break;
+ default:
+ nand->ecc.bytes = 3;
+ nand->ecc.layout = &fsmc_ecc1_layout;
+ nand->ecc.correct = nand_correct_data;
+ break;
+ }
+
+ /* Detect NAND chips */
+ if (nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_DEVICE, NULL))
+ return -ENXIO;
+
+ if (nand_scan_tail(mtd))
+ return -ENXIO;
+
+ for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+ if (nand_register(i))
+ return -ENXIO;
+
+ return 0;
+}
diff --git a/drivers/mtd/nand/spr_nand.c b/drivers/mtd/nand/spr_nand.c
deleted file mode 100644
index 097d0c6..0000000
--- a/drivers/mtd/nand/spr_nand.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * (C) Copyright 2009
- * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <common.h>
-#include <nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/spr_nand.h>
-
-static struct fsmc_regs *const fsmc_regs_p =
- (struct fsmc_regs *)CONFIG_SPEAR_FSMCBASE;
-
-static struct nand_ecclayout spear_nand_ecclayout = {
- .eccbytes = 24,
- .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
- 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
- .oobfree = {
- {.offset = 8, .length = 8},
- {.offset = 24, .length = 8},
- {.offset = 40, .length = 8},
- {.offset = 56, .length = 8},
- {.offset = 72, .length = 8},
- {.offset = 88, .length = 8},
- {.offset = 104, .length = 8},
- {.offset = 120, .length = 8}
- }
-};
-
-static void spear_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
-{
- struct nand_chip *this = mtd->priv;
- ulong IO_ADDR_W;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- IO_ADDR_W = (ulong)this->IO_ADDR_W;
-
- IO_ADDR_W &= ~(CONFIG_SYS_NAND_CLE | CONFIG_SYS_NAND_ALE);
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= CONFIG_SYS_NAND_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= CONFIG_SYS_NAND_ALE;
-
- if (ctrl & NAND_NCE) {
- writel(readl(&fsmc_regs_p->genmemctrl_pc) |
- FSMC_ENABLE, &fsmc_regs_p->genmemctrl_pc);
- } else {
- writel(readl(&fsmc_regs_p->genmemctrl_pc) &
- ~FSMC_ENABLE, &fsmc_regs_p->genmemctrl_pc);
- }
- this->IO_ADDR_W = (void *)IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-static int spear_read_hwecc(struct mtd_info *mtd,
- const u_char *data, u_char ecc[3])
-{
- u_int ecc_tmp;
-
- /* read the h/w ECC */
- ecc_tmp = readl(&fsmc_regs_p->genmemctrl_ecc);
-
- ecc[0] = (u_char) (ecc_tmp & 0xFF);
- ecc[1] = (u_char) ((ecc_tmp & 0xFF00) >> 8);
- ecc[2] = (u_char) ((ecc_tmp & 0xFF0000) >> 16);
-
- return 0;
-}
-
-void spear_enable_hwecc(struct mtd_info *mtd, int mode)
-{
- writel(readl(&fsmc_regs_p->genmemctrl_pc) & ~0x80,
- &fsmc_regs_p->genmemctrl_pc);
- writel(readl(&fsmc_regs_p->genmemctrl_pc) & ~FSMC_ECCEN,
- &fsmc_regs_p->genmemctrl_pc);
- writel(readl(&fsmc_regs_p->genmemctrl_pc) | FSMC_ECCEN,
- &fsmc_regs_p->genmemctrl_pc);
-}
-
-int spear_nand_init(struct nand_chip *nand)
-{
- writel(FSMC_DEVWID_8 | FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON,
- &fsmc_regs_p->genmemctrl_pc);
- writel(readl(&fsmc_regs_p->genmemctrl_pc) | FSMC_TCLR_1 | FSMC_TAR_1,
- &fsmc_regs_p->genmemctrl_pc);
- writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
- &fsmc_regs_p->genmemctrl_comm);
- writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
- &fsmc_regs_p->genmemctrl_attrib);
-
- nand->options = 0;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.layout = &spear_nand_ecclayout;
- nand->ecc.size = 512;
- nand->ecc.bytes = 3;
- nand->ecc.calculate = spear_read_hwecc;
- nand->ecc.hwctl = spear_enable_hwecc;
- nand->ecc.correct = nand_correct_data;
- nand->cmd_ctrl = spear_nand_hwcontrol;
- return 0;
-}
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
index f9352f9..691ed4e 100644
--- a/drivers/mtd/spi/eon.c
+++ b/drivers/mtd/spi/eon.c
@@ -10,24 +10,8 @@
#include "spi_flash_internal.h"
-/* EN25Q128-specific commands */
-#define CMD_EN25Q128_WREN 0x06 /* Write Enable */
-#define CMD_EN25Q128_WRDI 0x04 /* Write Disable */
-#define CMD_EN25Q128_RDSR 0x05 /* Read Status Register */
-#define CMD_EN25Q128_WRSR 0x01 /* Write Status Register */
-#define CMD_EN25Q128_READ 0x03 /* Read Data Bytes */
-#define CMD_EN25Q128_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
-#define CMD_EN25Q128_PP 0x02 /* Page Program */
-#define CMD_EN25Q128_SE 0x20 /* Sector Erase */
-#define CMD_EN25Q128_BE 0xd8 /* Block Erase */
-#define CMD_EN25Q128_DP 0xb9 /* Deep Power-down */
-#define CMD_EN25Q128_RES 0xab /* Release from DP, and Read Signature */
-
struct eon_spi_flash_params {
u8 idcode1;
- u16 page_size;
- u16 pages_per_sector;
- u16 sectors_per_block;
u16 nr_sectors;
const char *name;
};
@@ -35,35 +19,16 @@ struct eon_spi_flash_params {
static const struct eon_spi_flash_params eon_spi_flash_table[] = {
{
.idcode1 = 0x16,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_sectors = 1024,
.name = "EN25Q32B",
},
{
.idcode1 = 0x18,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_sectors = 4096,
.name = "EN25Q128",
},
- {
- .idcode1 = 0x16,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
- .nr_sectors = 1024,
- .name = "EN25Q32B",
- },
};
-static int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len);
-}
-
struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
{
const struct eon_spi_flash_params *params;
@@ -91,12 +56,11 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
- flash->erase = eon_erase;
+ flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
- flash->page_size = params->page_size;
- flash->sector_size = params->page_size * params->pages_per_sector
- * params->sectors_per_block;
- flash->size = params->page_size * params->pages_per_sector
+ flash->page_size = 256;
+ flash->sector_size = 256 * 16 * 16;
+ flash->size = 256 * 16
* params->nr_sectors;
return flash;
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
index dacbc28..c97a39d 100644
--- a/drivers/mtd/spi/macronix.c
+++ b/drivers/mtd/spi/macronix.c
@@ -35,25 +35,8 @@
#include "spi_flash_internal.h"
-/* MX25xx-specific commands */
-#define CMD_MX25XX_WREN 0x06 /* Write Enable */
-#define CMD_MX25XX_WRDI 0x04 /* Write Disable */
-#define CMD_MX25XX_RDSR 0x05 /* Read Status Register */
-#define CMD_MX25XX_WRSR 0x01 /* Write Status Register */
-#define CMD_MX25XX_READ 0x03 /* Read Data Bytes */
-#define CMD_MX25XX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
-#define CMD_MX25XX_PP 0x02 /* Page Program */
-#define CMD_MX25XX_SE 0x20 /* Sector Erase */
-#define CMD_MX25XX_BE 0xD8 /* Block Erase */
-#define CMD_MX25XX_CE 0xc7 /* Chip Erase */
-#define CMD_MX25XX_DP 0xb9 /* Deep Power-down */
-#define CMD_MX25XX_RES 0xab /* Release from DP, and Read Signature */
-
struct macronix_spi_flash_params {
u16 idcode;
- u16 page_size;
- u16 pages_per_sector;
- u16 sectors_per_block;
u16 nr_blocks;
const char *name;
};
@@ -61,106 +44,41 @@ struct macronix_spi_flash_params {
static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
{
.idcode = 0x2013,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 8,
.name = "MX25L4005",
},
{
.idcode = 0x2014,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 16,
.name = "MX25L8005",
},
{
.idcode = 0x2015,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 32,
.name = "MX25L1605D",
},
{
.idcode = 0x2016,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 64,
.name = "MX25L3205D",
},
{
.idcode = 0x2017,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 128,
.name = "MX25L6405D",
},
{
.idcode = 0x2018,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 256,
.name = "MX25L12805D",
},
{
.idcode = 0x2618,
- .page_size = 256,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 256,
.name = "MX25L12855E",
},
};
-static int macronix_write_status(struct spi_flash *flash, u8 sr)
-{
- u8 cmd;
- int ret;
-
- ret = spi_flash_cmd_write_enable(flash);
- if (ret < 0) {
- debug("SF: enabling write failed\n");
- return ret;
- }
-
- cmd = CMD_MX25XX_WRSR;
- ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1);
- if (ret) {
- debug("SF: fail to write status register\n");
- return ret;
- }
-
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
- if (ret < 0) {
- debug("SF: write status register timed out\n");
- return ret;
- }
-
- return 0;
-}
-
-static int macronix_unlock(struct spi_flash *flash)
-{
- int ret;
-
- /* Enable status register writing and clear BP# bits */
- ret = macronix_write_status(flash, 0);
- if (ret)
- debug("SF: fail to disable write protection\n");
-
- return ret;
-}
-
-static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, offset, len);
-}
-
struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
{
const struct macronix_spi_flash_params *params;
@@ -189,15 +107,14 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
- flash->erase = macronix_erase;
+ flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
- flash->page_size = params->page_size;
- flash->sector_size = params->page_size * params->pages_per_sector
- * params->sectors_per_block;
+ flash->page_size = 256;
+ flash->sector_size = 256 * 16 * 16;
flash->size = flash->sector_size * params->nr_blocks;
/* Clear BP# bits for read-only flash */
- macronix_unlock(flash);
+ spi_flash_cmd_write_status(flash, 0);
return flash;
}
diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c
index 27d4039..0999781 100644
--- a/drivers/mtd/spi/ramtron.c
+++ b/drivers/mtd/spi/ramtron.c
@@ -54,19 +54,6 @@
#include <spi_flash.h>
#include "spi_flash_internal.h"
-/* RAMTRON commands common to all devices */
-#define CMD_RAMTRON_WREN 0x06 /* Write Enable */
-#define CMD_RAMTRON_WRDI 0x04 /* Write Disable */
-#define CMD_RAMTRON_RDSR 0x05 /* Read Status Register */
-#define CMD_RAMTRON_WRSR 0x01 /* Write Status Register */
-#define CMD_RAMTRON_READ 0x03 /* Read Data Bytes */
-#define CMD_RAMTRON_WRITE 0x02 /* Write Data Bytes */
-/* not all have those: */
-#define CMD_RAMTRON_FSTRD 0x0b /* Fast Read (for compatibility - not used here) */
-#define CMD_RAMTRON_SLEEP 0xb9 /* Enter Sleep Mode */
-#define CMD_RAMTRON_RDID 0x9f /* Read ID */
-#define CMD_RAMTRON_SNR 0xc3 /* Read Serial Number */
-
/*
* Properties of supported FRAMs
* Note: speed is currently not used because we have no method to deliver that
@@ -196,7 +183,7 @@ static int ramtron_common(struct spi_flash *flash,
return ret;
}
- if (command == CMD_RAMTRON_WRITE) {
+ if (command == CMD_PAGE_PROGRAM) {
/* send WREN */
ret = spi_flash_cmd_write_enable(flash);
if (ret < 0) {
@@ -206,7 +193,7 @@ static int ramtron_common(struct spi_flash *flash,
}
/* do the transaction */
- if (command == CMD_RAMTRON_WRITE)
+ if (command == CMD_PAGE_PROGRAM)
ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, buf, len);
else
ret = spi_flash_cmd_read(flash->spi, cmd, cmd_len, buf, len);
@@ -223,14 +210,14 @@ static int ramtron_read(struct spi_flash *flash,
u32 offset, size_t len, void *buf)
{
return ramtron_common(flash, offset, len, buf,
- CMD_RAMTRON_READ);
+ CMD_READ_ARRAY_SLOW);
}
static int ramtron_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
return ramtron_common(flash, offset, len, (void *)buf,
- CMD_RAMTRON_WRITE);
+ CMD_PAGE_PROGRAM);
}
static int ramtron_erase(struct spi_flash *flash, u32 offset, size_t len)
@@ -270,7 +257,7 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
* We COULD have a non JEDEC conformant FRAM here,
* read the status register to verify
*/
- ret = spi_flash_cmd(spi, CMD_RAMTRON_RDSR, &sr, 1);
+ ret = spi_flash_cmd(spi, CMD_READ_STATUS, &sr, 1);
if (ret)
return NULL;
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index 6301d87..9a114ac 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -31,34 +31,9 @@
#include "spi_flash_internal.h"
-/* S25FLxx-specific commands */
-#define CMD_S25FLXX_READ 0x03 /* Read Data Bytes */
-#define CMD_S25FLXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
-#define CMD_S25FLXX_READID 0x90 /* Read Manufacture ID and Device ID */
-#define CMD_S25FLXX_WREN 0x06 /* Write Enable */
-#define CMD_S25FLXX_WRDI 0x04 /* Write Disable */
-#define CMD_S25FLXX_RDSR 0x05 /* Read Status Register */
-#define CMD_S25FLXX_WRSR 0x01 /* Write Status Register */
-#define CMD_S25FLXX_PP 0x02 /* Page Program */
-#define CMD_S25FLXX_SE 0xd8 /* Sector Erase */
-#define CMD_S25FLXX_BE 0xc7 /* Bulk Erase */
-#define CMD_S25FLXX_DP 0xb9 /* Deep Power-down */
-#define CMD_S25FLXX_RES 0xab /* Release from DP, and Read Signature */
-
-#define SPSN_ID_S25FL008A 0x0213
-#define SPSN_ID_S25FL016A 0x0214
-#define SPSN_ID_S25FL032A 0x0215
-#define SPSN_ID_S25FL064A 0x0216
-#define SPSN_ID_S25FL128P 0x2018
-#define SPSN_EXT_ID_S25FL128P_256KB 0x0300
-#define SPSN_EXT_ID_S25FL128P_64KB 0x0301
-#define SPSN_EXT_ID_S25FL032P 0x4d00
-#define SPSN_EXT_ID_S25FL129P 0x4d01
-
struct spansion_spi_flash_params {
u16 idcode1;
u16 idcode2;
- u16 page_size;
u16 pages_per_sector;
u16 nr_sectors;
const char *name;
@@ -66,76 +41,63 @@ struct spansion_spi_flash_params {
static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
{
- .idcode1 = SPSN_ID_S25FL008A,
+ .idcode1 = 0x0213,
.idcode2 = 0,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
.name = "S25FL008A",
},
{
- .idcode1 = SPSN_ID_S25FL016A,
+ .idcode1 = 0x0214,
.idcode2 = 0,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "S25FL016A",
},
{
- .idcode1 = SPSN_ID_S25FL032A,
+ .idcode1 = 0x0215,
.idcode2 = 0,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "S25FL032A",
},
{
- .idcode1 = SPSN_ID_S25FL064A,
+ .idcode1 = 0x0216,
.idcode2 = 0,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
.name = "S25FL064A",
},
{
- .idcode1 = SPSN_ID_S25FL128P,
- .idcode2 = SPSN_EXT_ID_S25FL128P_64KB,
- .page_size = 256,
+ .idcode1 = 0x2018,
+ .idcode2 = 0x0301,
.pages_per_sector = 256,
.nr_sectors = 256,
.name = "S25FL128P_64K",
},
{
- .idcode1 = SPSN_ID_S25FL128P,
- .idcode2 = SPSN_EXT_ID_S25FL128P_256KB,
- .page_size = 256,
+ .idcode1 = 0x2018,
+ .idcode2 = 0x0300,
.pages_per_sector = 1024,
.nr_sectors = 64,
.name = "S25FL128P_256K",
},
{
- .idcode1 = SPSN_ID_S25FL032A,
- .idcode2 = SPSN_EXT_ID_S25FL032P,
- .page_size = 256,
+ .idcode1 = 0x0215,
+ .idcode2 = 0x4d00,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "S25FL032P",
},
{
- .idcode1 = SPSN_ID_S25FL128P,
- .idcode2 = SPSN_EXT_ID_S25FL129P,
- .page_size = 256,
+ .idcode1 = 0x2018,
+ .idcode2 = 0x4d01,
.pages_per_sector = 256,
.nr_sectors = 256,
.name = "S25FL129P_64K",
},
};
-static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len);
-}
-
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
{
const struct spansion_spi_flash_params *params;
@@ -169,10 +131,10 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
- flash->erase = spansion_erase;
+ flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
- flash->page_size = params->page_size;
- flash->sector_size = params->page_size * params->pages_per_sector;
+ flash->page_size = 256;
+ flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
return flash;
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index f689cc4..00aece9 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -190,8 +190,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
CMD_READ_STATUS, STATUS_WIP);
}
-int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
- u32 offset, size_t len)
+int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
{
u32 start, end, erase_size;
int ret;
@@ -209,7 +208,10 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
return ret;
}
- cmd[0] = erase_cmd;
+ if (erase_size == 4096)
+ cmd[0] = CMD_ERASE_4K;
+ else
+ cmd[0] = CMD_ERASE_64K;
start = offset;
end = start + len;
@@ -240,6 +242,33 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
return ret;
}
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
+{
+ u8 cmd;
+ int ret;
+
+ ret = spi_flash_cmd_write_enable(flash);
+ if (ret < 0) {
+ debug("SF: enabling write failed\n");
+ return ret;
+ }
+
+ cmd = CMD_WRITE_STATUS;
+ ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1);
+ if (ret) {
+ debug("SF: fail to write status register\n");
+ return ret;
+ }
+
+ ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ if (ret < 0) {
+ debug("SF: write status register timed out\n");
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* The following table holds all device probe functions
*
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index 91e036a..141cfa8 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -17,12 +17,16 @@
#define CMD_READ_ARRAY_SLOW 0x03
#define CMD_READ_ARRAY_FAST 0x0b
-#define CMD_READ_ARRAY_LEGACY 0xe8
+#define CMD_WRITE_STATUS 0x01
#define CMD_PAGE_PROGRAM 0x02
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS 0x05
#define CMD_WRITE_ENABLE 0x06
+#define CMD_ERASE_4K 0x20
+#define CMD_ERASE_32K 0x52
+#define CMD_ERASE_64K 0xd8
+#define CMD_ERASE_CHIP 0xc7
/* Common status */
#define STATUS_WIP 0x01
@@ -70,6 +74,9 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
}
+/* Program the status register. */
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
+
/*
* Same as spi_flash_cmd_read() except it also claims/releases the SPI
* bus. Used as common part of the ->read() operation.
@@ -88,8 +95,7 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
/* Erase sectors. */
-int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
- u32 offset, size_t len);
+int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
index 9559c80..ced4f24 100644
--- a/drivers/mtd/spi/sst.c
+++ b/drivers/mtd/spi/sst.c
@@ -18,15 +18,8 @@
#include "spi_flash_internal.h"
-#define CMD_SST_WREN 0x06 /* Write Enable */
-#define CMD_SST_WRDI 0x04 /* Write Disable */
-#define CMD_SST_RDSR 0x05 /* Read Status Register */
-#define CMD_SST_WRSR 0x01 /* Write Status Register */
-#define CMD_SST_READ 0x03 /* Read Data Bytes */
-#define CMD_SST_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
#define CMD_SST_BP 0x02 /* Byte Program */
#define CMD_SST_AAI_WP 0xAD /* Auto Address Increment Word Program */
-#define CMD_SST_SE 0x20 /* Sector Erase */
#define SST_SR_WIP (1 << 0) /* Write-in-Progress */
#define SST_SR_WEL (1 << 1) /* Write enable */
@@ -51,13 +44,6 @@ struct sst_spi_flash {
const struct sst_spi_flash_params *params;
};
-static inline struct sst_spi_flash *to_sst_spi_flash(struct spi_flash *flash)
-{
- return container_of(flash, struct sst_spi_flash, flash);
-}
-
-#define SST_SECTOR_SIZE (4 * 1024)
-#define SST_PAGE_SIZE 256
static const struct sst_spi_flash_params sst_spi_flash_table[] = {
{
.idcode1 = 0x8d,
@@ -108,24 +94,6 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = {
};
static int
-sst_enable_writing(struct spi_flash *flash)
-{
- int ret = spi_flash_cmd_write_enable(flash);
- if (ret)
- debug("SF: Enabling Write failed\n");
- return ret;
-}
-
-static int
-sst_disable_writing(struct spi_flash *flash)
-{
- int ret = spi_flash_cmd_write_disable(flash);
- if (ret)
- debug("SF: Disabling Write failed\n");
- return ret;
-}
-
-static int
sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
{
int ret;
@@ -137,9 +105,9 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
};
debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
- spi_w8r8(flash->spi, CMD_SST_RDSR), buf, cmd[0], offset);
+ spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
- ret = sst_enable_writing(flash);
+ ret = spi_flash_cmd_write_enable(flash);
if (ret)
return ret;
@@ -172,7 +140,7 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
}
offset += actual;
- ret = sst_enable_writing(flash);
+ ret = spi_flash_cmd_write_enable(flash);
if (ret)
goto done;
@@ -184,7 +152,7 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
for (; actual < len - 1; actual += 2) {
debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
- spi_w8r8(flash->spi, CMD_SST_RDSR), buf + actual, cmd[0],
+ spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, cmd[0],
offset);
ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
@@ -203,7 +171,7 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
}
if (!ret)
- ret = sst_disable_writing(flash);
+ ret = spi_flash_cmd_write_disable(flash);
/* If there is a single trailing byte, write it out */
if (!ret && actual != len)
@@ -217,32 +185,6 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
return ret;
}
-static int sst_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len);
-}
-
-static int
-sst_unlock(struct spi_flash *flash)
-{
- int ret;
- u8 cmd, status;
-
- ret = sst_enable_writing(flash);
- if (ret)
- return ret;
-
- cmd = CMD_SST_WRSR;
- status = 0;
- ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &status, 1);
- if (ret)
- debug("SF: Unable to set status byte\n");
-
- debug("SF: sst: status = %x\n", spi_w8r8(flash->spi, CMD_SST_RDSR));
-
- return ret;
-}
-
struct spi_flash *
spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
{
@@ -275,14 +217,14 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.write = sst_write_wp;
else
stm->flash.write = spi_flash_cmd_write_multi;
- stm->flash.erase = sst_erase;
+ stm->flash.erase = spi_flash_cmd_erase;
stm->flash.read = spi_flash_cmd_read_fast;
- stm->flash.page_size = SST_PAGE_SIZE;
- stm->flash.sector_size = SST_SECTOR_SIZE;
+ stm->flash.page_size = 256;
+ stm->flash.sector_size = 4096;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
/* Flash powers up read-only, so clear BP# bits */
- sst_unlock(&stm->flash);
+ spi_flash_cmd_write_status(&stm->flash, 0);
return &stm->flash;
}
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index a9b33cf..dbd1fc1 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -34,21 +34,10 @@
#include "spi_flash_internal.h"
/* M25Pxx-specific commands */
-#define CMD_M25PXX_WREN 0x06 /* Write Enable */
-#define CMD_M25PXX_WRDI 0x04 /* Write Disable */
-#define CMD_M25PXX_RDSR 0x05 /* Read Status Register */
-#define CMD_M25PXX_WRSR 0x01 /* Write Status Register */
-#define CMD_M25PXX_READ 0x03 /* Read Data Bytes */
-#define CMD_M25PXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
-#define CMD_M25PXX_PP 0x02 /* Page Program */
-#define CMD_M25PXX_SE 0xd8 /* Sector Erase */
-#define CMD_M25PXX_BE 0xc7 /* Bulk Erase */
-#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
#define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */
struct stmicro_spi_flash_params {
u8 idcode1;
- u16 page_size;
u16 pages_per_sector;
u16 nr_sectors;
const char *name;
@@ -57,67 +46,60 @@ struct stmicro_spi_flash_params {
static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
{
.idcode1 = 0x11,
- .page_size = 256,
.pages_per_sector = 128,
.nr_sectors = 4,
.name = "M25P10",
},
{
.idcode1 = 0x15,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "M25P16",
},
{
.idcode1 = 0x12,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 4,
.name = "M25P20",
},
{
.idcode1 = 0x16,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "M25P32",
},
{
.idcode1 = 0x13,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 8,
.name = "M25P40",
},
{
.idcode1 = 0x17,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
.name = "M25P64",
},
{
.idcode1 = 0x14,
- .page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
.name = "M25P80",
},
{
.idcode1 = 0x18,
- .page_size = 256,
.pages_per_sector = 1024,
.nr_sectors = 64,
.name = "M25P128",
},
+ {
+ .idcode1 = 0x19,
+ .pages_per_sector = 256,
+ .nr_sectors = 512,
+ .name = "N25Q256",
+ },
};
-static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, len);
-}
-
struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
{
const struct stmicro_spi_flash_params *params;
@@ -159,10 +141,10 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
- flash->erase = stmicro_erase;
+ flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
- flash->page_size = params->page_size;
- flash->sector_size = params->page_size * params->pages_per_sector;
+ flash->page_size = 256;
+ flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
return flash;
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index a6a6653..427b71f 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -10,26 +10,8 @@
#include "spi_flash_internal.h"
-/* M25Pxx-specific commands */
-#define CMD_W25_WREN 0x06 /* Write Enable */
-#define CMD_W25_WRDI 0x04 /* Write Disable */
-#define CMD_W25_RDSR 0x05 /* Read Status Register */
-#define CMD_W25_WRSR 0x01 /* Write Status Register */
-#define CMD_W25_READ 0x03 /* Read Data Bytes */
-#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
-#define CMD_W25_PP 0x02 /* Page Program */
-#define CMD_W25_SE 0x20 /* Sector (4K) Erase */
-#define CMD_W25_BE 0xd8 /* Block (64K) Erase */
-#define CMD_W25_CE 0xc7 /* Chip Erase */
-#define CMD_W25_DP 0xb9 /* Deep Power-down */
-#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */
-
struct winbond_spi_flash_params {
uint16_t id;
- /* Log2 of page size in power-of-two mode */
- uint8_t l2_page_size;
- uint16_t pages_per_sector;
- uint16_t sectors_per_block;
uint16_t nr_blocks;
const char *name;
};
@@ -37,81 +19,56 @@ struct winbond_spi_flash_params {
static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
{
.id = 0x3013,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 8,
.name = "W25X40",
},
{
.id = 0x3015,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 32,
.name = "W25X16",
},
{
.id = 0x3016,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 64,
.name = "W25X32",
},
{
.id = 0x3017,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 128,
.name = "W25X64",
},
{
+ .id = 0x4014,
+ .nr_blocks = 16,
+ .name = "W25Q80BL",
+ },
+ {
.id = 0x4015,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 32,
.name = "W25Q16",
},
{
.id = 0x4016,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 64,
.name = "W25Q32",
},
{
.id = 0x4017,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 128,
.name = "W25Q64",
},
{
.id = 0x4018,
- .l2_page_size = 8,
- .pages_per_sector = 16,
- .sectors_per_block = 16,
.nr_blocks = 256,
.name = "W25Q128",
},
};
-static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
- return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len);
-}
-
struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
{
const struct winbond_spi_flash_params *params;
struct spi_flash *flash;
unsigned int i;
- unsigned page_size;
for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) {
params = &winbond_spi_flash_table[i];
@@ -134,17 +91,12 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
flash->spi = spi;
flash->name = params->name;
- /* Assuming power-of-two page size initially. */
- page_size = 1 << params->l2_page_size;
-
flash->write = spi_flash_cmd_write_multi;
- flash->erase = winbond_erase;
+ flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
- flash->page_size = page_size;
- flash->sector_size = page_size * params->pages_per_sector;
- flash->size = page_size * params->pages_per_sector
- * params->sectors_per_block
- * params->nr_blocks;
+ flash->page_size = 4096;
+ flash->sector_size = 4096;
+ flash->size = 4096 * 16 * params->nr_blocks;
return flash;
}
diff --git a/drivers/mtd/spr_smi.c b/drivers/mtd/st_smi.c
index 6d4257a..7507e5d 100644
--- a/drivers/mtd/spr_smi.c
+++ b/drivers/mtd/st_smi.c
@@ -1,6 +1,6 @@
/*
* (C) Copyright 2009
- * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com.
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -24,10 +24,10 @@
#include <common.h>
#include <flash.h>
#include <linux/err.h>
+#include <linux/mtd/st_smi.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
-#include <asm/arch/spr_smi.h>
#if !defined(CONFIG_SYS_NO_FLASH)
@@ -37,19 +37,61 @@ static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] =
CONFIG_SYS_FLASH_ADDR_BASE;
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
-#define ST_M25Pxx_ID 0x00002020
-
-static struct flash_dev flash_ids[] = {
- {0x10, 0x10000, 2}, /* 64K Byte */
- {0x11, 0x20000, 4}, /* 128K Byte */
- {0x12, 0x40000, 4}, /* 256K Byte */
- {0x13, 0x80000, 8}, /* 512K Byte */
- {0x14, 0x100000, 16}, /* 1M Byte */
- {0x15, 0x200000, 32}, /* 2M Byte */
- {0x16, 0x400000, 64}, /* 4M Byte */
- {0x17, 0x800000, 128}, /* 8M Byte */
- {0x18, 0x1000000, 64}, /* 16M Byte */
- {0x00,}
+/* data structure to maintain flash ids from different vendors */
+struct flash_device {
+ char *name;
+ u8 erase_cmd;
+ u32 device_id;
+ u32 pagesize;
+ unsigned long sectorsize;
+ unsigned long size_in_bytes;
+};
+
+#define FLASH_ID(n, es, id, psize, ssize, size) \
+{ \
+ .name = n, \
+ .erase_cmd = es, \
+ .device_id = id, \
+ .pagesize = psize, \
+ .sectorsize = ssize, \
+ .size_in_bytes = size \
+}
+
+/*
+ * List of supported flash devices.
+ * Currently the erase_cmd field is not used in this driver.
+ */
+static struct flash_device flash_devices[] = {
+ FLASH_ID("st m25p16" , 0xd8, 0x00152020, 0x100, 0x10000, 0x200000),
+ FLASH_ID("st m25p32" , 0xd8, 0x00162020, 0x100, 0x10000, 0x400000),
+ FLASH_ID("st m25p64" , 0xd8, 0x00172020, 0x100, 0x10000, 0x800000),
+ FLASH_ID("st m25p128" , 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000),
+ FLASH_ID("st m25p05" , 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000),
+ FLASH_ID("st m25p10" , 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000),
+ FLASH_ID("st m25p20" , 0xd8, 0x00122020, 0x100, 0x10000, 0x40000),
+ FLASH_ID("st m25p40" , 0xd8, 0x00132020, 0x100, 0x10000, 0x80000),
+ FLASH_ID("st m25p80" , 0xd8, 0x00142020, 0x100, 0x10000, 0x100000),
+ FLASH_ID("st m45pe10" , 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
+ FLASH_ID("st m45pe20" , 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
+ FLASH_ID("st m45pe40" , 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
+ FLASH_ID("st m45pe80" , 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
+ FLASH_ID("sp s25fl004" , 0xd8, 0x00120201, 0x100, 0x10000, 0x80000),
+ FLASH_ID("sp s25fl008" , 0xd8, 0x00130201, 0x100, 0x10000, 0x100000),
+ FLASH_ID("sp s25fl016" , 0xd8, 0x00140201, 0x100, 0x10000, 0x200000),
+ FLASH_ID("sp s25fl032" , 0xd8, 0x00150201, 0x100, 0x10000, 0x400000),
+ FLASH_ID("sp s25fl064" , 0xd8, 0x00160201, 0x100, 0x10000, 0x800000),
+ FLASH_ID("mac 25l512" , 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000),
+ FLASH_ID("mac 25l1005" , 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000),
+ FLASH_ID("mac 25l2005" , 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000),
+ FLASH_ID("mac 25l4005" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+ FLASH_ID("mac 25l4005a" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+ FLASH_ID("mac 25l8005" , 0xd8, 0x001420C2, 0x010, 0x10000, 0x100000),
+ FLASH_ID("mac 25l1605" , 0xd8, 0x001520C2, 0x100, 0x10000, 0x200000),
+ FLASH_ID("mac 25l1605a" , 0xd8, 0x001520C2, 0x010, 0x10000, 0x200000),
+ FLASH_ID("mac 25l3205" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+ FLASH_ID("mac 25l3205a" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+ FLASH_ID("mac 25l6405" , 0xd8, 0x001720C2, 0x100, 0x10000, 0x800000),
+ FLASH_ID("wbd w25q128" , 0xd8, 0x001840EF, 0x100, 0x10000, 0x1000000),
};
/*
@@ -58,13 +100,19 @@ static struct flash_dev flash_ids[] = {
*
* Wait until TFF is set in status register
*/
-static void smi_wait_xfer_finish(int timeout)
+static int smi_wait_xfer_finish(int timeout)
{
- while (timeout--) {
+ ulong start = get_timer(0);
+
+ while (get_timer(start) < timeout) {
if (readl(&smicntl->smi_sr) & TFF)
- break;
- udelay(1000);
- }
+ return 0;
+
+ /* Try after 10 ms */
+ udelay(10);
+ };
+
+ return -1;
}
/*
@@ -82,7 +130,9 @@ static unsigned int smi_read_id(flash_info_t *info, int banknum)
writel(READ_ID, &smicntl->smi_tr);
writel((banknum << BANKSEL_SHIFT) | SEND | TX_LEN_1 | RX_LEN_3,
&smicntl->smi_cr2);
- smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ if (smi_wait_xfer_finish(XFER_FINISH_TOUT))
+ return -EIO;
value = (readl(&smicntl->smi_rr) & 0x00FFFFFF);
@@ -103,30 +153,30 @@ static unsigned int smi_read_id(flash_info_t *info, int banknum)
static ulong flash_get_size(ulong base, int banknum)
{
flash_info_t *info = &flash_info[banknum];
- struct flash_dev *dev;
- unsigned int value;
- unsigned int density;
+ int value;
int i;
value = smi_read_id(info, banknum);
- density = (value >> 16) & 0xff;
-
- for (i = 0, dev = &flash_ids[0]; dev->density != 0x0;
- i++, dev = &flash_ids[i]) {
- if (dev->density == density) {
- info->size = dev->size;
- info->sector_count = dev->sector_count;
- break;
- }
- }
- if (dev->density == 0x0)
+ if (value < 0) {
+ printf("Flash id could not be read\n");
return 0;
+ }
- info->flash_id = value & 0xffff;
- info->start[0] = base;
+ /* Matches chip-id to entire list of 'serial-nor flash' ids */
+ for (i = 0; i < ARRAY_SIZE(flash_devices); i++) {
+ if (flash_devices[i].device_id == value) {
+ info->size = flash_devices[i].size_in_bytes;
+ info->flash_id = value;
+ info->start[0] = base;
+ info->sector_count =
+ info->size/flash_devices[i].sectorsize;
- return info->size;
+ return info->size;
+ }
+ }
+
+ return 0;
}
/*
@@ -136,9 +186,9 @@ static ulong flash_get_size(ulong base, int banknum)
* This routine will get the status register of the flash chip present at the
* given bank
*/
-static unsigned int smi_read_sr(int bank)
+static int smi_read_sr(int bank)
{
- u32 ctrlreg1;
+ u32 ctrlreg1, val;
/* store the CTRL REG1 state */
ctrlreg1 = readl(&smicntl->smi_cr1);
@@ -150,12 +200,15 @@ static unsigned int smi_read_sr(int bank)
/* Performing a RSR instruction in HW mode */
writel((bank << BANKSEL_SHIFT) | RD_STATUS_REG, &smicntl->smi_cr2);
- smi_wait_xfer_finish(XFER_FINISH_TOUT);
+ if (smi_wait_xfer_finish(XFER_FINISH_TOUT))
+ return -1;
+
+ val = readl(&smicntl->smi_sr);
/* Restore the CTRL REG1 state */
writel(ctrlreg1, &smicntl->smi_cr1);
- return readl(&smicntl->smi_sr);
+ return val;
}
/*
@@ -169,22 +222,20 @@ static unsigned int smi_read_sr(int bank)
*/
static int smi_wait_till_ready(int bank, int timeout)
{
- int count;
- unsigned int sr;
+ int sr;
+ ulong start = get_timer(0);
/* One chip guarantees max 5 msec wait here after page writes,
but potentially three seconds (!) after page erase. */
- for (count = 0; count < timeout; count++) {
-
+ while (get_timer(start) < timeout) {
sr = smi_read_sr(bank);
- if (sr < 0)
- break;
- else if (!(sr & WIP_BIT))
+ if ((sr >= 0) && (!(sr & WIP_BIT)))
return 0;
- /* Try again after 1m-sec */
- udelay(1000);
- }
+ /* Try again after 10 usec */
+ udelay(10);
+ } while (timeout--);
+
printf("SMI controller is still in wait, timeout=%d\n", timeout);
return -EIO;
}
@@ -199,7 +250,9 @@ static int smi_wait_till_ready(int bank, int timeout)
static int smi_write_enable(int bank)
{
u32 ctrlreg1;
+ u32 start;
int timeout = WMODE_TOUT;
+ int sr;
/* Store the CTRL REG1 state */
ctrlreg1 = readl(&smicntl->smi_cr1);
@@ -210,19 +263,21 @@ static int smi_write_enable(int bank)
/* Give the Flash, Write Enable command */
writel((bank << BANKSEL_SHIFT) | WE, &smicntl->smi_cr2);
- smi_wait_xfer_finish(XFER_FINISH_TOUT);
+ if (smi_wait_xfer_finish(XFER_FINISH_TOUT))
+ return -1;
/* Restore the CTRL REG1 state */
writel(ctrlreg1, &smicntl->smi_cr1);
- while (timeout--) {
- if (smi_read_sr(bank) & (1 << (bank + WM_SHIFT)))
- break;
- udelay(1000);
- }
+ start = get_timer(0);
+ while (get_timer(start) < timeout) {
+ sr = smi_read_sr(bank);
+ if ((sr >= 0) && (sr & (1 << (bank + WM_SHIFT))))
+ return 0;
- if (timeout)
- return 0;
+ /* Try again after 10 usec */
+ udelay(10);
+ };
return -1;
}
@@ -232,7 +287,7 @@ static int smi_write_enable(int bank)
*
* SMI initialization routine. Sets SMI control register1.
*/
-static void smi_init(void)
+void smi_init(void)
{
/* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */
writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4,
@@ -275,45 +330,39 @@ static int smi_sector_erase(flash_info_t *info, unsigned int sector)
writel(readl(&smicntl->smi_sr) & ~(ERF1 | ERF2), &smicntl->smi_sr);
- if (info->flash_id == ST_M25Pxx_ID) {
- /* Wait until finished previous write command. */
- if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
- return -EBUSY;
+ /* Wait until finished previous write command. */
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
- /* Send write enable, before erase commands. */
- if (smi_write_enable(bank))
- return -EIO;
+ /* Send write enable, before erase commands. */
+ if (smi_write_enable(bank))
+ return -EIO;
- /* Put SMI in SW mode */
- writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
+ /* Put SMI in SW mode */
+ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
- /* Send Sector Erase command in SW Mode */
- writel(instruction, &smicntl->smi_tr);
- writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4,
+ /* Send Sector Erase command in SW Mode */
+ writel(instruction, &smicntl->smi_tr);
+ writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4,
&smicntl->smi_cr2);
- smi_wait_xfer_finish(XFER_FINISH_TOUT);
+ if (smi_wait_xfer_finish(XFER_FINISH_TOUT))
+ return -EIO;
- if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
- return -EBUSY;
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
- /* Put SMI in HW mode */
- writel(readl(&smicntl->smi_cr1) & ~SW_MODE,
+ /* Put SMI in HW mode */
+ writel(readl(&smicntl->smi_cr1) & ~SW_MODE,
&smicntl->smi_cr1);
- return 0;
- } else {
- /* Put SMI in HW mode */
- writel(readl(&smicntl->smi_cr1) & ~SW_MODE,
- &smicntl->smi_cr1);
- return -EINVAL;
- }
+ return 0;
}
/*
* smi_write - Write to SMI flash
* @src_addr: source buffer
* @dst_addr: destination buffer
- * @length: length to write in words
+ * @length: length to write in bytes
* @bank: bank base address
*
* Write to SMI flash
@@ -321,7 +370,10 @@ static int smi_sector_erase(flash_info_t *info, unsigned int sector)
static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
unsigned int length, ulong bank_addr)
{
+ u8 *src_addr8 = (u8 *)src_addr;
+ u8 *dst_addr8 = (u8 *)dst_addr;
int banknum;
+ int i;
switch (bank_addr) {
case SMIBANK0_BASE:
@@ -350,7 +402,7 @@ static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
return -EIO;
/* Perform the write command */
- while (length--) {
+ for (i = 0; i < length; i += 4) {
if (((ulong) (dst_addr) % SFLASH_PAGE_SIZE) == 0) {
if (smi_wait_till_ready(banknum,
CONFIG_SYS_FLASH_WRITE_TOUT))
@@ -360,7 +412,18 @@ static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
return -EIO;
}
- *dst_addr++ = *src_addr++;
+ if (length < 4) {
+ int k;
+
+ /*
+ * Handle special case, where length < 4 (redundant env)
+ */
+ for (k = 0; k < length; k++)
+ *dst_addr8++ = *src_addr8++;
+ } else {
+ /* Normal 32bit write */
+ *dst_addr++ = *src_addr++;
+ }
if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2)))
return -EIO;
@@ -386,7 +449,7 @@ static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length)
{
return smi_write((unsigned int *)src, (unsigned int *)dest_addr,
- (length + 3) / 4, info->start[0]);
+ length, info->start[0]);
}
/*
@@ -429,8 +492,13 @@ void flash_print_info(flash_info_t *info)
puts("missing or unknown FLASH type\n");
return;
}
- printf(" Size: %ld MB in %d Sectors\n",
- info->size >> 20, info->sector_count);
+
+ if (info->size >= 0x100000)
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+ else
+ printf(" Size: %ld KB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
puts(" Sector Start Addresses:");
for (i = 0; i < info->sector_count; ++i) {
@@ -483,11 +551,6 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
int prot = 0;
flash_sect_t sect;
- if (info->flash_id != ST_M25Pxx_ID) {
- puts("Can't erase unknown flash type - aborted\n");
- return 1;
- }
-
if ((s_first < 0) || (s_first > s_last)) {
puts("- no sectors to erase\n");
return 1;
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index e24ac4a..c63398e 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -190,8 +190,7 @@ static int bfin_EMAC_recv(struct eth_device *dev)
debug("%s: len = %d\n", __func__, length - 4);
- NetRxPackets[rxIdx] =
- (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest);
+ NetRxPackets[rxIdx] = rxbuf[rxIdx]->FrmData->Dest;
NetReceive(NetRxPackets[rxIdx], length - 4);
bfin_write_DMA1_IRQ_STATUS(DMA_DONE | DMA_ERR);
rxbuf[rxIdx]->StatusWord = 0x00000000;
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index e471d2c..b2516d1 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -895,5 +895,13 @@ int davinci_emac_initialize(void)
miiphy_register(phy[i].name, davinci_mii_phy_read,
davinci_mii_phy_write);
}
+
+#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
+ defined(CONFIG_MACH_DAVINCI_DA850_EVM)
+ for (i = 0; i < num_phy; i++) {
+ if (phy[i].is_phy_connected(i))
+ phy[i].auto_negotiate(i);
+ }
+#endif
return(1);
}
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 9b17db4..bf21a08 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -28,6 +28,7 @@
#include <common.h>
#include <miiphy.h>
#include <malloc.h>
+#include <linux/compiler.h>
#include <linux/err.h>
#include <asm/io.h>
#include "designware.h"
@@ -153,6 +154,13 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
if (priv->phy_configured != 1)
configure_phy(dev);
+ /* Print link status only once */
+ if (!priv->link_printed) {
+ printf("ENET Speed is %d Mbps - %s duplex connection\n",
+ priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+ priv->link_printed = 1;
+ }
+
/* Reset ethernet hardware */
if (mac_reset(dev) < 0)
return -1;
@@ -163,15 +171,22 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
writel(FIXEDBURST | PRIORXTX_41 | BURST_16,
&dma_p->busmode);
- writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode);
- writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode);
+ writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD |
+ TXSECONDFRAME, &dma_p->opmode);
conf = FRAMEBURSTENABLE | DISABLERXOWN;
- if (priv->speed != SPEED_1000M)
+ if (priv->speed != 1000)
conf |= MII_PORTSELECT;
- if (priv->duplex == FULL_DUPLEX)
+ if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
+ (priv->interface != PHY_INTERFACE_MODE_GMII)) {
+
+ if (priv->speed == 100)
+ conf |= FES_100;
+ }
+
+ if (priv->duplex == FULL)
conf |= FULLDPLXMODE;
writel(conf, &mac_p->conf);
@@ -389,6 +404,16 @@ static int dw_reset_phy(struct eth_device *dev)
return 0;
}
+/*
+ * Add weak default function for board specific PHY configuration
+ */
+int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr,
+ int (*mii_write)(struct eth_device *, u8, u8, u16),
+ int dw_reset_phy(struct eth_device *))
+{
+ return 0;
+}
+
static int configure_phy(struct eth_device *dev)
{
struct dw_eth_dev *priv = dev->priv;
@@ -398,9 +423,6 @@ static int configure_phy(struct eth_device *dev)
u16 bmsr;
u32 timeout;
ulong start;
- u16 anlpar, btsr;
-#else
- u16 ctrl;
#endif
#if defined(CONFIG_DW_SEARCH_PHY)
@@ -412,6 +434,16 @@ static int configure_phy(struct eth_device *dev)
#else
phy_addr = priv->address;
#endif
+
+ /*
+ * Some boards need board specific PHY initialization. This is
+ * after the main driver init code but before the auto negotiation
+ * is run.
+ */
+ if (designware_board_phy_init(dev, phy_addr,
+ eth_mdio_write, dw_reset_phy) < 0)
+ return -1;
+
if (dw_reset_phy(dev) < 0)
return -1;
@@ -437,72 +469,32 @@ static int configure_phy(struct eth_device *dev)
#if defined(CONFIG_DW_AUTONEG)
timeout = CONFIG_AUTONEG_TIMEOUT;
start = get_timer(0);
-
+ puts("Waiting for PHY auto negotiation to complete");
while (get_timer(start) < timeout) {
eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
- if (bmsr & BMSR_ANEGCOMPLETE)
+ if (bmsr & BMSR_ANEGCOMPLETE) {
+ priv->phy_configured = 1;
break;
-
- /* Try again after 10usec */
- udelay(10);
- };
-
- eth_mdio_read(dev, phy_addr, MII_LPA, &anlpar);
- eth_mdio_read(dev, phy_addr, MII_STAT1000, &btsr);
-
- if (bmsr & BMSR_ANEGCOMPLETE) {
- if (btsr & PHY_1000BTSR_1000FD) {
- priv->speed = SPEED_1000M;
- bmcr |= BMCR_SPEED1000;
- priv->duplex = FULL_DUPLEX;
- bmcr |= BMCR_FULLDPLX;
- } else if (btsr & PHY_1000BTSR_1000HD) {
- priv->speed = SPEED_1000M;
- bmcr |= BMCR_SPEED1000;
- priv->duplex = HALF_DUPLEX;
- bmcr &= ~BMCR_FULLDPLX;
- } else if (anlpar & LPA_100FULL) {
- priv->speed = SPEED_100M;
- bmcr |= BMCR_SPEED100;
- priv->duplex = FULL_DUPLEX;
- bmcr |= BMCR_FULLDPLX;
- } else if (anlpar & LPA_100HALF) {
- priv->speed = SPEED_100M;
- bmcr |= BMCR_SPEED100;
- priv->duplex = HALF_DUPLEX;
- bmcr &= ~BMCR_FULLDPLX;
- } else if (anlpar & LPA_10FULL) {
- priv->speed = SPEED_10M;
- bmcr &= ~BMCR_SPEED100;
- priv->duplex = FULL_DUPLEX;
- bmcr |= BMCR_FULLDPLX;
- } else {
- priv->speed = SPEED_10M;
- bmcr &= ~BMCR_SPEED100;
- priv->duplex = HALF_DUPLEX;
- bmcr &= ~BMCR_FULLDPLX;
}
- if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0)
- return -1;
- } else
- return -1;
-#else
- if (eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl) < 0)
- return -1;
- if (ctrl & BMCR_FULLDPLX)
- priv->duplex = FULL_DUPLEX;
- else
- priv->duplex = HALF_DUPLEX;
+ /* Print dot all 1s to show progress */
+ if ((get_timer(start) % 1000) == 0)
+ putc('.');
- if (ctrl & BMCR_SPEED1000)
- priv->speed = SPEED_1000M;
- else if (ctrl & BMCR_SPEED100)
- priv->speed = SPEED_100M;
+ /* Try again after 1msec */
+ udelay(1000);
+ };
+
+ if (!(bmsr & BMSR_ANEGCOMPLETE))
+ puts(" TIMEOUT!\n");
else
- priv->speed = SPEED_10M;
-#endif
+ puts(" done\n");
+#else
priv->phy_configured = 1;
+#endif
+
+ priv->speed = miiphy_speed(dev->name, phy_addr);
+ priv->duplex = miiphy_duplex(dev->name, phy_addr);
return 0;
}
@@ -531,7 +523,7 @@ static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val)
}
#endif
-int designware_initialize(u32 id, ulong base_addr, u32 phy_addr)
+int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
{
struct eth_device *dev;
struct dw_eth_dev *priv;
@@ -565,11 +557,7 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr)
DW_DMA_BASE_OFFSET);
priv->address = phy_addr;
priv->phy_configured = 0;
-
- if (mac_reset(dev) < 0)
- return -1;
-
- configure_phy(dev);
+ priv->interface = interface;
dev->init = dw_eth_init;
dev->send = dw_eth_send;
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index abf729d..d668f8f 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -234,11 +234,13 @@ struct dmamacdescr {
struct dw_eth_dev {
u32 address;
+ u32 interface;
u32 speed;
u32 duplex;
u32 tx_currdescnum;
u32 rx_currdescnum;
u32 phy_configured;
+ int link_printed;
u32 padding;
struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index eee41d7..fbfc842 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -424,14 +424,12 @@ static void fec_reg_setup(struct fec_priv *fec)
/* Start with frame length = 1518, common for all modes. */
rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT;
- if (fec->xcv_type == SEVENWIRE)
- rcntrl |= FEC_RCNTRL_FCE;
- else if (fec->xcv_type == RGMII)
+ if (fec->xcv_type != SEVENWIRE) /* xMII modes */
+ rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
+ if (fec->xcv_type == RGMII)
rcntrl |= FEC_RCNTRL_RGMII;
else if (fec->xcv_type == RMII)
rcntrl |= FEC_RCNTRL_RMII;
- else /* MII mode */
- rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
writel(rcntrl, &fec->eth->r_cntrl);
}
@@ -510,7 +508,13 @@ static int fec_open(struct eth_device *edev)
fec_eth_phy_config(edev);
if (fec->phydev) {
/* Start up the PHY */
- phy_startup(fec->phydev);
+ int ret = phy_startup(fec->phydev);
+
+ if (ret) {
+ printf("Could not initialize PHY %s\n",
+ fec->phydev->dev->name);
+ return ret;
+ }
speed = fec->phydev->speed;
} else {
speed = _100BASET;
@@ -599,7 +603,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
fec_reg_setup(fec);
- if (fec->xcv_type == MII10 || fec->xcv_type == MII100)
+ if (fec->xcv_type != SEVENWIRE)
fec_mii_setspeed(fec);
/*
diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c
index f34f4db..2b616ad 100644
--- a/drivers/net/fm/eth.c
+++ b/drivers/net/fm/eth.c
@@ -363,6 +363,9 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
{
struct fm_eth *fm_eth;
struct fsl_enet_mac *mac;
+#ifdef CONFIG_PHYLIB
+ int ret;
+#endif
fm_eth = (struct fm_eth *)dev->priv;
mac = fm_eth->mac;
@@ -384,7 +387,11 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
fmc_tx_port_graceful_stop_disable(fm_eth);
#ifdef CONFIG_PHYLIB
- phy_startup(fm_eth->phydev);
+ ret = phy_startup(fm_eth->phydev);
+ if (ret) {
+ printf("%s: Could not initialize\n", fm_eth->phydev->dev->name);
+ return ret;
+ }
#else
fm_eth->phydev->speed = SPEED_1000;
fm_eth->phydev->link = 1;
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index e3043df..30f3264 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -35,6 +35,12 @@ static struct phy_driver KSZ804_driver = {
.shutdown = &genphy_shutdown,
};
+#ifndef CONFIG_PHY_MICREL_KSZ9021
+/*
+ * I can't believe Micrel used the exact same part number
+ * for the KSZ9021
+ * Shame Micrel, Shame!!!!!
+ */
static struct phy_driver KS8721_driver = {
.name = "Micrel KS8721BL",
.uid = 0x221610,
@@ -44,7 +50,9 @@ static struct phy_driver KS8721_driver = {
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
+#endif
+#ifdef CONFIG_PHY_MICREL_KSZ9021
/* ksz9021 PHY Registers */
#define MII_KSZ9021_EXTENDED_CTRL 0x0b
#define MII_KSZ9021_EXTENDED_DATAW 0x0c
@@ -127,12 +135,15 @@ static struct phy_driver ksz9021_driver = {
.startup = &ksz9021_startup,
.shutdown = &genphy_shutdown,
};
+#endif
int phy_micrel_init(void)
{
phy_register(&KSZ804_driver);
- phy_register(&KS8721_driver);
+#ifdef CONFIG_PHY_MICREL_KSZ9021
phy_register(&ksz9021_driver);
-
+#else
+ phy_register(&KS8721_driver);
+#endif
return 0;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7d327f7..baef60f 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -723,10 +723,13 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
return phydev;
}
+/*
+ * Start the PHY. Returns 0 on success, or a negative error code.
+ */
int phy_startup(struct phy_device *phydev)
{
if (phydev->drv->startup)
- phydev->drv->startup(phydev);
+ return phydev->drv->startup(phydev);
return 0;
}
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index bb57e4d..09af860 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1,5 +1,5 @@
/*
- * sh_eth.c - Driver for Renesas SH7763's ethernet controler.
+ * sh_eth.c - Driver for Renesas ethernet controler.
*
* Copyright (C) 2008, 2011 Renesas Solutions Corp.
* Copyright (c) 2008, 2011 Nobuhiro Iwamatsu
@@ -76,8 +76,8 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len)
port_info->tx_desc_cur->td0 = TD_TACT | TD_TFP;
/* Restart the transmitter if disabled */
- if (!(inl(EDTRR(port)) & EDTRR_TRNS))
- outl(EDTRR_TRNS, EDTRR(port));
+ if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
+ sh_eth_write(eth, EDTRR_TRNS, EDTRR);
/* Wait until packet is transmitted */
timeout = TIMEOUT_CNT;
@@ -129,25 +129,24 @@ int sh_eth_recv(struct eth_device *dev)
}
/* Restart the receiver if disabled */
- if (!(inl(EDRRR(port)) & EDRRR_R))
- outl(EDRRR_R, EDRRR(port));
+ if (!(sh_eth_read(eth, EDRRR) & EDRRR_R))
+ sh_eth_write(eth, EDRRR_R, EDRRR);
return len;
}
static int sh_eth_reset(struct sh_eth_dev *eth)
{
- int port = eth->port;
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
int ret = 0, i;
/* Start e-dmac transmitter and receiver */
- outl(EDSR_ENALL, EDSR(port));
+ sh_eth_write(eth, EDSR_ENALL, EDSR);
/* Perform a software reset and wait for it to complete */
- outl(EDMR_SRST, EDMR(port));
+ sh_eth_write(eth, EDMR_SRST, EDMR);
for (i = 0; i < TIMEOUT_CNT ; i++) {
- if (!(inl(EDMR(port)) & EDMR_SRST))
+ if (!(sh_eth_read(eth, EDMR) & EDMR_SRST))
break;
udelay(1000);
}
@@ -159,9 +158,9 @@ static int sh_eth_reset(struct sh_eth_dev *eth)
return ret;
#else
- outl(inl(EDMR(port)) | EDMR_SRST, EDMR(port));
+ sh_eth_write(eth, sh_eth_read(eth, EDMR) | EDMR_SRST, EDMR);
udelay(3000);
- outl(inl(EDMR(port)) & ~EDMR_SRST, EDMR(port));
+ sh_eth_write(eth, sh_eth_read(eth, EDMR) & ~EDMR_SRST, EDMR);
return 0;
#endif
@@ -207,11 +206,11 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
/* Point the controller to the tx descriptor list. Must use physical
addresses */
- outl(ADDR_TO_PHY(port_info->tx_desc_base), TDLAR(port));
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
- outl(ADDR_TO_PHY(port_info->tx_desc_base), TDFAR(port));
- outl(ADDR_TO_PHY(cur_tx_desc), TDFXR(port));
- outl(0x01, TDFFR(port));/* Last discriptor bit */
+ sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
+ sh_eth_write(eth, ADDR_TO_PHY(cur_tx_desc), TDFXR);
+ sh_eth_write(eth, 0x01, TDFFR);/* Last discriptor bit */
#endif
err:
@@ -275,11 +274,11 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
cur_rx_desc->rd0 |= RD_RDLE;
/* Point the controller to the rx descriptor list */
- outl(ADDR_TO_PHY(port_info->rx_desc_base), RDLAR(port));
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
- outl(ADDR_TO_PHY(port_info->rx_desc_base), RDFAR(port));
- outl(ADDR_TO_PHY(cur_rx_desc), RDFXR(port));
- outl(RDFFR_RDLF, RDFFR(port));
+ sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
+ sh_eth_write(eth, ADDR_TO_PHY(cur_rx_desc), RDFXR);
+ sh_eth_write(eth, RDFFR_RDLF, RDFFR);
#endif
return ret;
@@ -364,49 +363,39 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
struct phy_device *phy;
/* Configure e-dmac registers */
- outl((inl(EDMR(port)) & ~EMDR_DESC_R) | EDMR_EL, EDMR(port));
- outl(0, EESIPR(port));
- outl(0, TRSCER(port));
- outl(0, TFTR(port));
- outl((FIFO_SIZE_T | FIFO_SIZE_R), FDR(port));
- outl(RMCR_RST, RMCR(port));
-#if !defined(CONFIG_CPU_SH7757) && !defined(CONFIG_CPU_SH7724)
- outl(0, RPADIR(port));
+ sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | EDMR_EL,
+ EDMR);
+ sh_eth_write(eth, 0, EESIPR);
+ sh_eth_write(eth, 0, TRSCER);
+ sh_eth_write(eth, 0, TFTR);
+ sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
+ sh_eth_write(eth, RMCR_RST, RMCR);
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, 0, RPADIR);
#endif
- outl((FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR(port));
+ sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
/* Configure e-mac registers */
-#if defined(CONFIG_CPU_SH7757)
- outl(ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP |
- ECSIPR_MPDIP | ECSIPR_ICDIP, ECSIPR(port));
-#else
- outl(0, ECSIPR(port));
-#endif
+ sh_eth_write(eth, 0, ECSIPR);
/* Set Mac address */
val = dev->enetaddr[0] << 24 | dev->enetaddr[1] << 16 |
dev->enetaddr[2] << 8 | dev->enetaddr[3];
- outl(val, MAHR(port));
+ sh_eth_write(eth, val, MAHR);
val = dev->enetaddr[4] << 8 | dev->enetaddr[5];
- outl(val, MALR(port));
-
- outl(RFLR_RFL_MIN, RFLR(port));
-#if !defined(CONFIG_CPU_SH7757) && !defined(CONFIG_CPU_SH7724)
- outl(0, PIPR(port));
-#endif
-#if !defined(CONFIG_CPU_SH7724)
- outl(APR_AP, APR(port));
- outl(MPR_MP, MPR(port));
-#endif
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
- outl(TPAUSER_TPAUSE, TPAUSER(port));
-#elif defined(CONFIG_CPU_SH7757)
- outl(TPAUSER_UNLIMITED, TPAUSER(port));
+ sh_eth_write(eth, val, MALR);
+
+ sh_eth_write(eth, RFLR_RFL_MIN, RFLR);
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, 0, PIPR);
+ sh_eth_write(eth, APR_AP, APR);
+ sh_eth_write(eth, MPR_MP, MPR);
+ sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER);
#endif
#if defined(CONFIG_CPU_SH7734)
- outl(CONFIG_SH_ETHER_SH7734_MII, RMII_MII(port));
+ sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
#endif
/* Configure phy */
ret = sh_eth_phy_config(eth);
@@ -415,42 +404,47 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
goto err_phy_cfg;
}
phy = port_info->phydev;
- phy_startup(phy);
+ ret = phy_startup(phy);
+ if (ret) {
+ printf(SHETHER_NAME ": phy startup failure\n");
+ return ret;
+ }
val = 0;
/* Set the transfer speed */
if (phy->speed == 100) {
printf(SHETHER_NAME ": 100Base/");
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
- outl(GECMR_100B, GECMR(port));
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, GECMR_100B, GECMR);
#elif defined(CONFIG_CPU_SH7757)
- outl(1, RTRATE(port));
+ sh_eth_write(eth, 1, RTRATE);
#elif defined(CONFIG_CPU_SH7724)
val = ECMR_RTM;
#endif
} else if (phy->speed == 10) {
printf(SHETHER_NAME ": 10Base/");
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
- outl(GECMR_10B, GECMR(port));
+#if defined(SH_ETH_TYPE_GETHER)
+ sh_eth_write(eth, GECMR_10B, GECMR);
#elif defined(CONFIG_CPU_SH7757)
- outl(0, RTRATE(port));
+ sh_eth_write(eth, 0, RTRATE);
#endif
}
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
else if (phy->speed == 1000) {
printf(SHETHER_NAME ": 1000Base/");
- outl(GECMR_1000B, GECMR(port));
+ sh_eth_write(eth, GECMR_1000B, GECMR);
}
#endif
/* Check if full duplex mode is supported by the phy */
if (phy->duplex) {
printf("Full\n");
- outl(val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE|ECMR_DM), ECMR(port));
+ sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE|ECMR_DM),
+ ECMR);
} else {
printf("Half\n");
- outl(val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR(port));
+ sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR);
}
return ret;
@@ -465,12 +459,12 @@ static void sh_eth_start(struct sh_eth_dev *eth)
* Enable the e-dmac receiver only. The transmitter will be enabled when
* we have something to transmit
*/
- outl(EDRRR_R, EDRRR(eth->port));
+ sh_eth_write(eth, EDRRR_R, EDRRR);
}
static void sh_eth_stop(struct sh_eth_dev *eth)
{
- outl(~EDRRR_R, EDRRR(eth->port));
+ sh_eth_write(eth, ~EDRRR_R, EDRRR);
}
int sh_eth_init(struct eth_device *dev, bd_t *bd)
@@ -574,9 +568,8 @@ static int sh_eth_bb_init(struct bb_miiphy_bus *bus)
static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus)
{
struct sh_eth_dev *eth = bus->priv;
- int port = eth->port;
- outl(inl(PIR(port)) | PIR_MMD, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MMD, PIR);
return 0;
}
@@ -584,9 +577,8 @@ static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus)
static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus)
{
struct sh_eth_dev *eth = bus->priv;
- int port = eth->port;
- outl(inl(PIR(port)) & ~PIR_MMD, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MMD, PIR);
return 0;
}
@@ -594,12 +586,11 @@ static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus)
static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v)
{
struct sh_eth_dev *eth = bus->priv;
- int port = eth->port;
if (v)
- outl(inl(PIR(port)) | PIR_MDO, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDO, PIR);
else
- outl(inl(PIR(port)) & ~PIR_MDO, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDO, PIR);
return 0;
}
@@ -607,9 +598,8 @@ static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v)
static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v)
{
struct sh_eth_dev *eth = bus->priv;
- int port = eth->port;
- *v = (inl(PIR(port)) & PIR_MDI) >> 3;
+ *v = (sh_eth_read(eth, PIR) & PIR_MDI) >> 3;
return 0;
}
@@ -617,12 +607,11 @@ static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v)
static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v)
{
struct sh_eth_dev *eth = bus->priv;
- int port = eth->port;
if (v)
- outl(inl(PIR(port)) | PIR_MDC, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDC, PIR);
else
- outl(inl(PIR(port)) & ~PIR_MDC, PIR(port));
+ sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDC, PIR);
return 0;
}
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index a1ba68b..3703c55 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -97,143 +97,208 @@ struct sh_eth_dev {
struct sh_eth_info port_info[MAX_PORT_NUM];
};
-/* Register Address */
-#ifdef CONFIG_CPU_SH7763
-#define BASE_IO_ADDR 0xfee00000
+/* from linux/drivers/net/ethernet/renesas/sh_eth.h */
+enum {
+ /* E-DMAC registers */
+ EDSR = 0,
+ EDMR,
+ EDTRR,
+ EDRRR,
+ EESR,
+ EESIPR,
+ TDLAR,
+ TDFAR,
+ TDFXR,
+ TDFFR,
+ RDLAR,
+ RDFAR,
+ RDFXR,
+ RDFFR,
+ TRSCER,
+ RMFCR,
+ TFTR,
+ FDR,
+ RMCR,
+ EDOCR,
+ TFUCR,
+ RFOCR,
+ FCFTR,
+ RPADIR,
+ TRIMD,
+ RBWAR,
+ TBRAR,
+
+ /* Ether registers */
+ ECMR,
+ ECSR,
+ ECSIPR,
+ PIR,
+ PSR,
+ RDMLR,
+ PIPR,
+ RFLR,
+ IPGR,
+ APR,
+ MPR,
+ PFTCR,
+ PFRCR,
+ RFCR,
+ RFCF,
+ TPAUSER,
+ TPAUSECR,
+ BCFR,
+ BCFRR,
+ GECMR,
+ BCULR,
+ MAHR,
+ MALR,
+ TROCR,
+ CDCR,
+ LCCR,
+ CNDCR,
+ CEFCR,
+ FRECR,
+ TSFRCR,
+ TLFRCR,
+ CERCR,
+ CEECR,
+ MAFCR,
+ RTRATE,
+ CSMR,
+ RMII_MII,
+
+ /* This value must be written at last. */
+ SH_ETH_MAX_REGISTER_OFFSET,
+};
+
+static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+ [EDSR] = 0x0000,
+ [EDMR] = 0x0400,
+ [EDTRR] = 0x0408,
+ [EDRRR] = 0x0410,
+ [EESR] = 0x0428,
+ [EESIPR] = 0x0430,
+ [TDLAR] = 0x0010,
+ [TDFAR] = 0x0014,
+ [TDFXR] = 0x0018,
+ [TDFFR] = 0x001c,
+ [RDLAR] = 0x0030,
+ [RDFAR] = 0x0034,
+ [RDFXR] = 0x0038,
+ [RDFFR] = 0x003c,
+ [TRSCER] = 0x0438,
+ [RMFCR] = 0x0440,
+ [TFTR] = 0x0448,
+ [FDR] = 0x0450,
+ [RMCR] = 0x0458,
+ [RPADIR] = 0x0460,
+ [FCFTR] = 0x0468,
+ [CSMR] = 0x04E4,
+
+ [ECMR] = 0x0500,
+ [ECSR] = 0x0510,
+ [ECSIPR] = 0x0518,
+ [PIR] = 0x0520,
+ [PSR] = 0x0528,
+ [PIPR] = 0x052c,
+ [RFLR] = 0x0508,
+ [APR] = 0x0554,
+ [MPR] = 0x0558,
+ [PFTCR] = 0x055c,
+ [PFRCR] = 0x0560,
+ [TPAUSER] = 0x0564,
+ [GECMR] = 0x05b0,
+ [BCULR] = 0x05b4,
+ [MAHR] = 0x05c0,
+ [MALR] = 0x05c8,
+ [TROCR] = 0x0700,
+ [CDCR] = 0x0708,
+ [LCCR] = 0x0710,
+ [CEFCR] = 0x0740,
+ [FRECR] = 0x0748,
+ [TSFRCR] = 0x0750,
+ [TLFRCR] = 0x0758,
+ [RFCR] = 0x0760,
+ [CERCR] = 0x0768,
+ [CEECR] = 0x0770,
+ [MAFCR] = 0x0778,
+ [RMII_MII] = 0x0790,
+};
-#define EDSR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0000)
-
-#define TDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0010)
-#define TDFAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0014)
-#define TDFXR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0018)
-#define TDFFR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x001c)
-
-#define RDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0030)
-#define RDFAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0034)
-#define RDFXR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0038)
-#define RDFFR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x003c)
-
-#define EDMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0400)
-#define EDTRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0408)
-#define EDRRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0410)
-#define EESR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0428)
-#define EESIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0430)
-#define TRSCER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0438)
-#define TFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0448)
-#define FDR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0450)
-#define RMCR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0458)
-#define RPADIR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0460)
-#define FCFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0468)
-#define ECMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0500)
-#define RFLR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0508)
-#define ECSIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0518)
-#define PIR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0520)
-#define PIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x052c)
-#define APR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0554)
-#define MPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0558)
-#define TPAUSER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0564)
-#define GECMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05b0)
-#define MALR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05c8)
-#define MAHR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x05c0)
+static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
+ [ECMR] = 0x0100,
+ [RFLR] = 0x0108,
+ [ECSR] = 0x0110,
+ [ECSIPR] = 0x0118,
+ [PIR] = 0x0120,
+ [PSR] = 0x0128,
+ [RDMLR] = 0x0140,
+ [IPGR] = 0x0150,
+ [APR] = 0x0154,
+ [MPR] = 0x0158,
+ [TPAUSER] = 0x0164,
+ [RFCF] = 0x0160,
+ [TPAUSECR] = 0x0168,
+ [BCFRR] = 0x016c,
+ [MAHR] = 0x01c0,
+ [MALR] = 0x01c8,
+ [TROCR] = 0x01d0,
+ [CDCR] = 0x01d4,
+ [LCCR] = 0x01d8,
+ [CNDCR] = 0x01dc,
+ [CEFCR] = 0x01e4,
+ [FRECR] = 0x01e8,
+ [TSFRCR] = 0x01ec,
+ [TLFRCR] = 0x01f0,
+ [RFCR] = 0x01f4,
+ [MAFCR] = 0x01f8,
+ [RTRATE] = 0x01fc,
+
+ [EDMR] = 0x0000,
+ [EDTRR] = 0x0008,
+ [EDRRR] = 0x0010,
+ [TDLAR] = 0x0018,
+ [RDLAR] = 0x0020,
+ [EESR] = 0x0028,
+ [EESIPR] = 0x0030,
+ [TRSCER] = 0x0038,
+ [RMFCR] = 0x0040,
+ [TFTR] = 0x0048,
+ [FDR] = 0x0050,
+ [RMCR] = 0x0058,
+ [TFUCR] = 0x0064,
+ [RFOCR] = 0x0068,
+ [FCFTR] = 0x0070,
+ [RPADIR] = 0x0078,
+ [TRIMD] = 0x007c,
+ [RBWAR] = 0x00c8,
+ [RDFAR] = 0x00cc,
+ [TBRAR] = 0x00d4,
+ [TDFAR] = 0x00d8,
+};
+/* Register Address */
+#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#define SH_ETH_TYPE_GETHER
+#define BASE_IO_ADDR 0xfee00000
#elif defined(CONFIG_CPU_SH7757)
+#if defined(CONFIG_SH_ETHER_USE_GETHER)
+#define SH_ETH_TYPE_GETHER
+#define BASE_IO_ADDR 0xfee00000
+#else
+#define SH_ETH_TYPE_ETHER
#define BASE_IO_ADDR 0xfef00000
-
-#define TDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0018)
-#define RDLAR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0020)
-
-#define EDMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0000)
-#define EDTRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0008)
-#define EDRRR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0010)
-#define EESR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0028)
-#define EESIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0030)
-#define TRSCER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0038)
-#define TFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0048)
-#define FDR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0050)
-#define RMCR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0058)
-#define FCFTR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0070)
-#define ECMR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0100)
-#define RFLR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0108)
-#define ECSIPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0118)
-#define PIR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0120)
-#define APR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0154)
-#define MPR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0158)
-#define TPAUSER(port) (BASE_IO_ADDR + 0x800 * (port) + 0x0164)
-#define MAHR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x01c0)
-#define MALR(port) (BASE_IO_ADDR + 0x800 * (port) + 0x01c8)
-#define RTRATE(port) (BASE_IO_ADDR + 0x800 * (port) + 0x01fc)
-
+#endif
#elif defined(CONFIG_CPU_SH7724)
+#define SH_ETH_TYPE_ETHER
#define BASE_IO_ADDR 0xA4600000
-
-#define TDLAR(port) (BASE_IO_ADDR + 0x0018)
-#define RDLAR(port) (BASE_IO_ADDR + 0x0020)
-
-#define EDMR(port) (BASE_IO_ADDR + 0x0000)
-#define EDTRR(port) (BASE_IO_ADDR + 0x0008)
-#define EDRRR(port) (BASE_IO_ADDR + 0x0010)
-#define EESR(port) (BASE_IO_ADDR + 0x0028)
-#define EESIPR(port) (BASE_IO_ADDR + 0x0030)
-#define TRSCER(port) (BASE_IO_ADDR + 0x0038)
-#define TFTR(port) (BASE_IO_ADDR + 0x0048)
-#define FDR(port) (BASE_IO_ADDR + 0x0050)
-#define RMCR(port) (BASE_IO_ADDR + 0x0058)
-#define FCFTR(port) (BASE_IO_ADDR + 0x0070)
-#define ECMR(port) (BASE_IO_ADDR + 0x0100)
-#define RFLR(port) (BASE_IO_ADDR + 0x0108)
-#define ECSIPR(port) (BASE_IO_ADDR + 0x0118)
-#define PIR(port) (BASE_IO_ADDR + 0x0120)
-#define APR(port) (BASE_IO_ADDR + 0x0154)
-#define MPR(port) (BASE_IO_ADDR + 0x0158)
-#define TPAUSER(port) (BASE_IO_ADDR + 0x0164)
-#define MAHR(port) (BASE_IO_ADDR + 0x01c0)
-#define MALR(port) (BASE_IO_ADDR + 0x01c8)
-
-#elif defined(CONFIG_CPU_SH7734)
-#define BASE_IO_ADDR 0xFEE00000
-
-#define EDSR(port) (BASE_IO_ADDR)
-
-#define TDLAR(port) (BASE_IO_ADDR + 0x0010)
-#define TDFAR(port) (BASE_IO_ADDR + 0x0014)
-#define TDFXR(port) (BASE_IO_ADDR + 0x0018)
-#define TDFFR(port) (BASE_IO_ADDR + 0x001c)
-#define RDLAR(port) (BASE_IO_ADDR + 0x0030)
-#define RDFAR(port) (BASE_IO_ADDR + 0x0034)
-#define RDFXR(port) (BASE_IO_ADDR + 0x0038)
-#define RDFFR(port) (BASE_IO_ADDR + 0x003c)
-
-#define EDMR(port) (BASE_IO_ADDR + 0x0400)
-#define EDTRR(port) (BASE_IO_ADDR + 0x0408)
-#define EDRRR(port) (BASE_IO_ADDR + 0x0410)
-#define EESR(port) (BASE_IO_ADDR + 0x0428)
-#define EESIPR(port) (BASE_IO_ADDR + 0x0430)
-#define TRSCER(port) (BASE_IO_ADDR + 0x0438)
-#define TFTR(port) (BASE_IO_ADDR + 0x0448)
-#define FDR(port) (BASE_IO_ADDR + 0x0450)
-#define RMCR(port) (BASE_IO_ADDR + 0x0458)
-#define RPADIR(port) (BASE_IO_ADDR + 0x0460)
-#define FCFTR(port) (BASE_IO_ADDR + 0x0468)
-#define ECMR(port) (BASE_IO_ADDR + 0x0500)
-#define RFLR(port) (BASE_IO_ADDR + 0x0508)
-#define ECSIPR(port) (BASE_IO_ADDR + 0x0518)
-#define PIR(port) (BASE_IO_ADDR + 0x0520)
-#define PIPR(port) (BASE_IO_ADDR + 0x052c)
-#define APR(port) (BASE_IO_ADDR + 0x0554)
-#define MPR(port) (BASE_IO_ADDR + 0x0558)
-#define TPAUSER(port) (BASE_IO_ADDR + 0x0564)
-#define GECMR(port) (BASE_IO_ADDR + 0x05b0)
-#define MAHR(port) (BASE_IO_ADDR + 0x05C0)
-#define MALR(port) (BASE_IO_ADDR + 0x05C8)
-#define RMII_MII(port) (BASE_IO_ADDR + 0x0790)
-
#endif
/*
* Register's bits
* Copy from Linux driver source code
*/
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
/* EDSR */
enum EDSR_BIT {
EDSR_ENT = 0x01, EDSR_ENR = 0x02,
@@ -244,15 +309,15 @@ enum EDSR_BIT {
/* EDMR */
enum DMAC_M_BIT {
EDMR_DL1 = 0x20, EDMR_DL0 = 0x10,
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
EDMR_SRST = 0x03, /* Receive/Send reset */
EMDR_DESC_R = 0x30, /* Descriptor reserve size */
EDMR_EL = 0x40, /* Litte endian */
-#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7724)
+#elif defined(SH_ETH_TYPE_ETHER)
EDMR_SRST = 0x01,
EMDR_DESC_R = 0x30, /* Descriptor reserve size */
EDMR_EL = 0x40, /* Litte endian */
-#else /* CONFIG_CPU_SH7763 */
+#else
EDMR_SRST = 0x01,
#endif
};
@@ -262,7 +327,7 @@ enum DMAC_M_BIT {
/* EDTRR */
enum DMAC_T_BIT {
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
EDTRR_TRNS = 0x03,
#else
EDTRR_TRNS = 0x01,
@@ -271,7 +336,11 @@ enum DMAC_T_BIT {
/* GECMR */
enum GECMR_BIT {
+#if defined(CONFIG_CPU_SH7757)
+ GECMR_1000B = 0x20, GECMR_100B = 0x01, GECMR_10B = 0x00,
+#else
GECMR_1000B = 0x01, GECMR_100B = 0x04, GECMR_10B = 0x00,
+#endif
};
/* EDRRR*/
@@ -302,7 +371,7 @@ enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, };
/* EESR */
enum EESR_BIT {
-#if defined(CONFIG_CPU_SH7724) || defined(CONFIG_CPU_SH7757)
+#if defined(SH_ETH_TYPE_ETHER)
EESR_TWB = 0x40000000,
#else
EESR_TWB = 0xC0000000,
@@ -312,14 +381,14 @@ enum EESR_BIT {
#endif
EESR_TABT = 0x04000000,
EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000,
-#if defined(CONFIG_CPU_SH7724) || defined(CONFIG_CPU_SH7757)
+#if defined(SH_ETH_TYPE_ETHER)
EESR_ADE = 0x00800000,
#endif
EESR_ECI = 0x00400000,
EESR_FTC = 0x00200000, EESR_TDE = 0x00100000,
EESR_TFE = 0x00080000, EESR_FRC = 0x00040000,
EESR_RDE = 0x00020000, EESR_RFE = 0x00010000,
-#if defined(CONFIG_CPU_SH7724) && !defined(CONFIG_CPU_SH7757)
+#if defined(SH_ETH_TYPE_ETHER)
EESR_CND = 0x00000800,
#endif
EESR_DLC = 0x00000400,
@@ -331,7 +400,7 @@ enum EESR_BIT {
};
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
# define TX_CHECK (EESR_TC1 | EESR_FTC)
# define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
| EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI)
@@ -391,8 +460,7 @@ enum FCFTR_BIT {
/* Transfer descriptor bit */
enum TD_STS_BIT {
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7757) \
- || defined(CONFIG_CPU_SH7724) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_ETHER)
TD_TACT = 0x80000000,
#else
TD_TACT = 0x7fffffff,
@@ -408,7 +476,7 @@ enum TD_STS_BIT {
enum RECV_RST_BIT { RMCR_RST = 0x01, };
/* ECMR */
enum FELIC_MODE_BIT {
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
ECMR_TRCCM=0x04000000, ECMR_RCSC= 0x00800000, ECMR_DPAD= 0x00200000,
ECMR_RZPF = 0x00100000,
#endif
@@ -423,12 +491,10 @@ enum FELIC_MODE_BIT {
};
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF | ECMR_PFR | ECMR_RXF | \
ECMR_TXF | ECMR_MCT)
-#elif CONFIG_CPU_SH7757
-#define ECMR_CHG_DM (ECMR_ZPF)
-#elif CONFIG_CPU_SH7724
+#elif defined(SH_ETH_TYPE_ETHER)
#define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF)
#else
#define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF | ECMR_MCT)
@@ -436,14 +502,14 @@ enum FELIC_MODE_BIT {
/* ECSR */
enum ECSR_STATUS_BIT {
-#if defined(CONFIG_CPU_SH7724) || defined(CONFIG_CPU_SH7757)
+#if defined(SH_ETH_TYPE_ETHER)
ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10,
#endif
ECSR_LCHNG = 0x04,
ECSR_MPD = 0x02, ECSR_ICD = 0x01,
};
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
# define ECSR_INIT (ECSR_ICD | ECSIPR_MPDIP)
#else
# define ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | \
@@ -452,20 +518,19 @@ enum ECSR_STATUS_BIT {
/* ECSIPR */
enum ECSIPR_STATUS_MASK_BIT {
-#if defined(CONFIG_CPU_SH7724)
+#if defined(SH_ETH_TYPE_ETHER)
+ ECSIPR_BRCRXIP = 0x20,
ECSIPR_PSRTOIP = 0x10,
- ECSIPR_LCHNGIP = 0x04,
- ECSIPR_ICDIP = 0x01,
-#elif defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#elif defined(SH_ETY_TYPE_GETHER)
ECSIPR_PSRTOIP = 0x10,
ECSIPR_PHYIP = 0x08,
+#endif
ECSIPR_LCHNGIP = 0x04,
ECSIPR_MPDIP = 0x02,
ECSIPR_ICDIP = 0x01,
-#endif
};
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
# define ECSIPR_INIT (ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP)
#else
# define ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | \
@@ -474,20 +539,12 @@ enum ECSIPR_STATUS_MASK_BIT {
/* APR */
enum APR_BIT {
-#ifdef CONFIG_CPU_SH7757
- APR_AP = 0x00000001,
-#else
APR_AP = 0x00000004,
-#endif
};
/* MPR */
enum MPR_BIT {
-#ifdef CONFIG_CPU_SH7757
- MPR_MP = 0x00000001,
-#else
MPR_MP = 0x00000006,
-#endif
};
/* TRSCER */
@@ -504,7 +561,7 @@ enum RPADIR_BIT {
RPADIR_PADR = 0x0003f,
};
-#if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
+#if defined(SH_ETH_TYPE_GETHER)
# define RPADIR_INIT (0x00)
#else
# define RPADIR_INIT (RPADIR_PADS1)
@@ -514,3 +571,28 @@ enum RPADIR_BIT {
enum FIFO_SIZE_BIT {
FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
};
+
+static inline unsigned long sh_eth_reg_addr(struct sh_eth_dev *eth,
+ int enum_index)
+{
+#if defined(SH_ETH_TYPE_GETHER)
+ const u16 *reg_offset = sh_eth_offset_gigabit;
+#elif defined(SH_ETH_TYPE_ETHER)
+ const u16 *reg_offset = sh_eth_offset_fast_sh4;
+#else
+#error
+#endif
+ return BASE_IO_ADDR + reg_offset[enum_index] + 0x800 * eth->port;
+}
+
+static inline void sh_eth_write(struct sh_eth_dev *eth, unsigned long data,
+ int enum_index)
+{
+ outl(data, sh_eth_reg_addr(eth, enum_index));
+}
+
+static inline unsigned long sh_eth_read(struct sh_eth_dev *eth,
+ int enum_index)
+{
+ return inl(sh_eth_reg_addr(eth, enum_index));
+}
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 3c1c8f0..f5e314b 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -480,6 +480,7 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
int i;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
tsec_t *regs = priv->regs;
+ int ret;
/* Make sure the controller is stopped */
tsec_halt(dev);
@@ -511,7 +512,12 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
startup_tsec(dev);
/* Start up the PHY */
- phy_startup(priv->phydev);
+ ret = phy_startup(priv->phydev);
+ if (ret) {
+ printf("Could not initialize PHY %s\n",
+ priv->phydev->dev->name);
+ return ret;
+ }
adjust_link(priv, priv->phydev);
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 7854a04..d777144 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -272,7 +272,11 @@ static int setup_phy(struct eth_device *dev)
phydev->advertising = phydev->supported;
priv->phydev = phydev;
phy_config(phydev);
- phy_startup(phydev);
+ if (phy_startup(phydev)) {
+ printf("axiemac: could not initialize PHY %s\n",
+ phydev->dev->name);
+ return 0;
+ }
switch (phydev->speed) {
case 1000:
diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
index 27dafc1..b67153b 100644
--- a/drivers/net/xilinx_ll_temac.c
+++ b/drivers/net/xilinx_ll_temac.c
@@ -232,6 +232,7 @@ static void ll_temac_halt(struct eth_device *dev)
static int ll_temac_init(struct eth_device *dev, bd_t *bis)
{
struct ll_temac *ll_temac = dev->priv;
+ int ret;
printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
dev->name, dev->index, dev->iobase);
@@ -240,7 +241,12 @@ static int ll_temac_init(struct eth_device *dev, bd_t *bis)
return -1;
/* Start up the PHY */
- phy_startup(ll_temac->phydev);
+ ret = phy_startup(ll_temac->phydev);
+ if (ret) {
+ printf("%s: Could not initialize PHY %s\n",
+ dev->name, ll_temac->phydev->dev->name);
+ return ret;
+ }
if (!ll_temac_adjust_link(dev)) {
ll_temac_halt(dev);
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index 62c2446..8721e74 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -63,6 +63,8 @@
#define M41T62_FEATURE_HT (1 << 0)
#define M41T62_FEATURE_BL (1 << 1)
+#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
+
int rtc_get(struct rtc_time *tm)
{
u8 buf[M41T62_DATETIME_REG_SIZE];
@@ -132,9 +134,15 @@ int rtc_set(struct rtc_time *tm)
void rtc_reset(void)
{
+ u8 val;
+
/*
- * Nothing to do
+ * M41T82: Make sure HT (Halt Update) bit is cleared.
+ * This bit is 0 in M41T62 so its save to clear it always.
*/
+ i2c_read(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
+ val &= ~M41T80_ALHOUR_HT;
+ i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
}
#endif
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3ae38e5..cd3f9fa 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
COBJS-$(CONFIG_SH_SPI) += sh_spi.o
COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
+COBJS-$(CONFIG_TEGRA_SPI) += tegra_spi.o
COBJS-$(CONFIG_TEGRA2_SPI) += tegra2_spi.o
COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index db8ba8b..f4523a3 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -34,16 +34,14 @@
static struct kwspi_registers *spireg = (struct kwspi_registers *)KW_SPI_BASE;
+u32 cs_spi_mpp_back[2];
+
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
struct spi_slave *slave;
u32 data;
- u32 kwspi_mpp_config[] = {
- MPP0_GPIO,
- MPP7_SPI_SCn,
- 0
- };
+ u32 kwspi_mpp_config[] = { 0, 0 };
if (!spi_cs_is_valid(bus, cs))
return NULL;
@@ -70,29 +68,75 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
/* program mpp registers to select SPI_CSn */
if (cs) {
- kwspi_mpp_config[0] = MPP0_GPIO;
- kwspi_mpp_config[1] = MPP7_SPI_SCn;
+ kwspi_mpp_config[0] = MPP7_SPI_SCn;
} else {
kwspi_mpp_config[0] = MPP0_SPI_SCn;
- kwspi_mpp_config[1] = MPP7_GPO;
}
- kirkwood_mpp_conf(kwspi_mpp_config);
+ kirkwood_mpp_conf(kwspi_mpp_config, cs_spi_mpp_back);
return slave;
}
void spi_free_slave(struct spi_slave *slave)
{
+ kirkwood_mpp_conf(cs_spi_mpp_back, NULL);
free(slave);
}
-int spi_claim_bus(struct spi_slave *slave)
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+u32 spi_mpp_backup[4];
+#endif
+
+__attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave)
{
return 0;
}
+int spi_claim_bus(struct spi_slave *slave)
+{
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+ u32 config;
+ u32 spi_mpp_config[4];
+
+ config = CONFIG_SYS_KW_SPI_MPP;
+
+ if (config & MOSI_MPP6)
+ spi_mpp_config[0] = MPP6_SPI_MOSI;
+ else
+ spi_mpp_config[0] = MPP1_SPI_MOSI;
+
+ if (config & SCK_MPP10)
+ spi_mpp_config[1] = MPP10_SPI_SCK;
+ else
+ spi_mpp_config[1] = MPP2_SPI_SCK;
+
+ if (config & MISO_MPP11)
+ spi_mpp_config[2] = MPP11_SPI_MISO;
+ else
+ spi_mpp_config[2] = MPP3_SPI_MISO;
+
+ spi_mpp_config[3] = 0;
+ spi_mpp_backup[3] = 0;
+
+ /* set new spi mpp and save current mpp config */
+ kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup);
+
+#endif
+
+ return board_spi_claim_bus(slave);
+}
+
+__attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave)
+{
+}
+
void spi_release_bus(struct spi_slave *slave)
{
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+ kirkwood_mpp_conf(spi_mpp_backup, NULL);
+#endif
+
+ board_spi_release_bus(slave);
}
#ifndef CONFIG_SPI_CS_IS_VALID
diff --git a/drivers/spi/tegra2_spi.c b/drivers/spi/tegra_spi.c
index 56cb229..4a3e799 100644
--- a/drivers/spi/tegra2_spi.c
+++ b/drivers/spi/tegra_spi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012 NVIDIA Corporation
* With help from the mpc8xxx SPI driver
* With more help from omap3_spi SPI driver
*
@@ -28,12 +28,17 @@
#include <spi.h>
#include <asm/io.h>
#include <asm/gpio.h>
-#include <ns16550.h>
#include <asm/arch/clk_rst.h>
#include <asm/arch/clock.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/uart-spi-switch.h>
-#include <asm/arch/tegra2_spi.h>
+#include <asm/arch/tegra_spi.h>
+
+#if defined(CONFIG_SPI_CORRUPTS_UART)
+ #define corrupt_delay() udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
+#else
+ #define corrupt_delay()
+#endif
struct tegra_spi_slave {
struct spi_slave slave;
@@ -161,14 +166,20 @@ void spi_cs_activate(struct spi_slave *slave)
/* CS is negated on Tegra, so drive a 1 to get a 0 */
setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+
+ corrupt_delay(); /* Let UART settle */
}
void spi_cs_deactivate(struct spi_slave *slave)
{
struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ pinmux_select_uart();
+
/* CS is negated on Tegra, so drive a 0 to get a 1 */
clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
+
+ corrupt_delay(); /* Let SPI settle */
}
int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
index a3bf51a..8fb7fc8 100644
--- a/drivers/usb/eth/asix.c
+++ b/drivers/usb/eth/asix.c
@@ -168,27 +168,28 @@ static inline int asix_set_hw_mii(struct ueth_data *dev)
static int asix_mdio_read(struct ueth_data *dev, int phy_id, int loc)
{
- __le16 res;
+ ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
asix_set_sw_mii(dev);
- asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res);
+ asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
asix_set_hw_mii(dev);
debug("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
- phy_id, loc, le16_to_cpu(res));
+ phy_id, loc, le16_to_cpu(*res));
- return le16_to_cpu(res);
+ return le16_to_cpu(*res);
}
static void
asix_mdio_write(struct ueth_data *dev, int phy_id, int loc, int val)
{
- __le16 res = cpu_to_le16(val);
+ ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
+ *res = cpu_to_le16(val);
debug("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
phy_id, loc, val);
asix_set_sw_mii(dev);
- asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
+ asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, res);
asix_set_hw_mii(dev);
}
@@ -210,7 +211,8 @@ static int asix_sw_reset(struct ueth_data *dev, u8 flags)
static inline int asix_get_phy_addr(struct ueth_data *dev)
{
- u8 buf[2];
+ ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 2);
+
int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
debug("asix_get_phy_addr()\n");
@@ -242,13 +244,14 @@ static int asix_write_medium_mode(struct ueth_data *dev, u16 mode)
static u16 asix_read_rx_ctl(struct ueth_data *dev)
{
- __le16 v;
- int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
+ ALLOC_CACHE_ALIGN_BUFFER(__le16, v, 1);
+
+ int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, v);
if (ret < 0)
debug("Error reading RX_CTL register: %02x\n", ret);
else
- ret = le16_to_cpu(v);
+ ret = le16_to_cpu(*v);
return ret;
}
@@ -313,7 +316,7 @@ static int mii_nway_restart(struct ueth_data *dev)
static int asix_init(struct eth_device *eth, bd_t *bd)
{
int embd_phy;
- unsigned char buf[ETH_ALEN];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
u16 rx_ctl;
struct ueth_data *dev = (struct ueth_data *)eth->priv;
int timeout = 0;
@@ -425,7 +428,8 @@ static int asix_send(struct eth_device *eth, void *packet, int length)
int err;
u32 packet_len;
int actual_len;
- unsigned char msg[PKTSIZE + sizeof(packet_len)];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
+ PKTSIZE + sizeof(packet_len));
debug("** %s(), len %d\n", __func__, length);
@@ -452,7 +456,7 @@ static int asix_send(struct eth_device *eth, void *packet, int length)
static int asix_recv(struct eth_device *eth)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
- static unsigned char recv_buf[AX_RX_URB_SIZE];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
unsigned char *buf_ptr;
int err;
int actual_len;
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index c7aebea..c62a8c1 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -153,13 +153,15 @@ static int curr_eth_dev; /* index for name of next device detected */
static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
{
int len;
+ ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
cpu_to_le32s(&data);
+ tmpbuf[0] = data;
len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0),
USB_VENDOR_REQUEST_WRITE_REGISTER,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, &data, sizeof(data), USB_CTRL_SET_TIMEOUT);
+ 00, index, tmpbuf, sizeof(data), USB_CTRL_SET_TIMEOUT);
if (len != sizeof(data)) {
debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d",
index, data, len);
@@ -171,11 +173,13 @@ static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
{
int len;
+ ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0),
USB_VENDOR_REQUEST_READ_REGISTER,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, data, sizeof(data), USB_CTRL_GET_TIMEOUT);
+ 00, index, tmpbuf, sizeof(data), USB_CTRL_GET_TIMEOUT);
+ *data = tmpbuf[0];
if (len != sizeof(data)) {
debug("smsc95xx_read_reg failed: index=%d, len=%d",
index, len);
@@ -664,7 +668,8 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
int actual_len;
u32 tx_cmd_a;
u32 tx_cmd_b;
- unsigned char msg[PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
+ PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg);
if (length > PKTSIZE)
@@ -695,7 +700,7 @@ static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
static int smsc95xx_recv(struct eth_device *eth)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
- static unsigned char recv_buf[AX_RX_URB_SIZE];
+ DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
unsigned char *buf_ptr;
int err;
int actual_len;
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 59c3e57..6de9164 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -36,11 +36,13 @@ COBJS-$(CONFIG_USB_SL811HS) += sl811-hcd.o
# echi
COBJS-$(CONFIG_USB_EHCI) += ehci-hcd.o
COBJS-$(CONFIG_USB_EHCI_ARMADA100) += ehci-armada100.o utmi-armada100.o
+COBJS-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o
ifdef CONFIG_MPC512X
COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o
else
COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
endif
+COBJS-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
COBJS-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o
@@ -50,7 +52,6 @@ COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o
COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
COBJS-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
-COBJS-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
COBJS-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
new file mode 100644
index 0000000..15b9b60
--- /dev/null
+++ b/drivers/usb/host/ehci-atmel.c
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2012
+ * Atmel Semiconductor <www.atmel.com>
+ * Written-by: Bo Shen <voice.shen@atmel.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <usb.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/clk.h>
+
+#include "ehci.h"
+#include "ehci-core.h"
+
+/* Enable UTMI PLL time out 500us
+ * 10 times as datasheet specified
+ */
+#define EN_UPLL_TIMEOUT 500UL
+
+int ehci_hcd_init(void)
+{
+ at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
+ ulong start_time, tmp_time;
+
+ start_time = get_timer(0);
+ /* Enable UTMI PLL */
+ writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+ while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) {
+ WATCHDOG_RESET();
+ tmp_time = get_timer(0);
+ if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
+ printf("ERROR: failed to enable UPLL\n");
+ return -1;
+ }
+ }
+
+ /* Enable USB Host clock */
+ writel(1 << ATMEL_ID_UHPHS, &pmc->pcer);
+
+ hccr = (struct ehci_hccr *)ATMEL_BASE_EHCI;
+ hcor = (struct ehci_hcor *)((uint32_t)hccr +
+ HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+ return 0;
+}
+
+int ehci_hcd_stop(void)
+{
+ at91_pmc_t *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
+ ulong start_time, tmp_time;
+
+ /* Disable USB Host Clock */
+ writel(1 << ATMEL_ID_UHPHS, &pmc->pcdr);
+
+ start_time = get_timer(0);
+ /* Disable UTMI PLL */
+ writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr);
+ while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) {
+ WATCHDOG_RESET();
+ tmp_time = get_timer(0);
+ if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
+ printf("ERROR: failed to stop UPLL\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-exynos.c
index 4dd4ec1..a71b397 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -1,5 +1,5 @@
/*
- * SAMSUNG S5P USB HOST EHCI Controller
+ * SAMSUNG EXYNOS USB HOST EHCI Controller
*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
* Vivek Gautam <gautam.vivek@samsung.com>
@@ -23,13 +23,19 @@
#include <common.h>
#include <usb.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/ehci-s5p.h>
+#include <asm/arch/ehci.h>
+#include <asm/arch/system.h>
+#include <asm/arch/power.h>
#include "ehci.h"
#include "ehci-core.h"
/* Setup the EHCI host controller. */
-static void setup_usb_phy(struct s5p_usb_phy *usb)
+static void setup_usb_phy(struct exynos_usb_phy *usb)
{
+ set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
+
+ set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
+
clrbits_le32(&usb->usbphyctrl0,
HOST_CTRL0_FSEL_MASK |
HOST_CTRL0_COMMONON_N |
@@ -61,7 +67,7 @@ static void setup_usb_phy(struct s5p_usb_phy *usb)
}
/* Reset the EHCI host controller. */
-static void reset_usb_phy(struct s5p_usb_phy *usb)
+static void reset_usb_phy(struct exynos_usb_phy *usb)
{
/* HOST_PHY reset */
setbits_le32(&usb->usbphyctrl0,
@@ -70,6 +76,8 @@ static void reset_usb_phy(struct s5p_usb_phy *usb)
HOST_CTRL0_SIDDQ |
HOST_CTRL0_FORCESUSPEND |
HOST_CTRL0_FORCESLEEP);
+
+ set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
}
/*
@@ -79,12 +87,12 @@ static void reset_usb_phy(struct s5p_usb_phy *usb)
*/
int ehci_hcd_init(void)
{
- struct s5p_usb_phy *usb;
+ struct exynos_usb_phy *usb;
- usb = (struct s5p_usb_phy *)samsung_get_base_usb_phy();
+ usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
setup_usb_phy(usb);
- hccr = (struct ehci_hccr *)(EXYNOS5_USB_HOST_EHCI_BASE);
+ hccr = (struct ehci_hccr *)samsung_get_base_usb_ehci();
hcor = (struct ehci_hcor *)((uint32_t) hccr
+ HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
@@ -101,9 +109,9 @@ int ehci_hcd_init(void)
*/
int ehci_hcd_stop()
{
- struct s5p_usb_phy *usb;
+ struct exynos_usb_phy *usb;
- usb = (struct s5p_usb_phy *)samsung_get_base_usb_phy();
+ usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
reset_usb_phy(usb);
return 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 04300be..2a82a29 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
volatile struct ehci_hcor *hcor;
static uint16_t portreset;
-static struct QH qh_list __attribute__((aligned(32)));
+DEFINE_ALIGN_BUFFER(struct QH, qh_list, 1, USB_DMA_MINALIGN);
+
+#define ALIGN_END_ADDR(type, ptr, size) \
+ ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
static struct descriptor {
struct usb_hub_descriptor hub;
@@ -172,18 +175,15 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
{
uint32_t delta, next;
uint32_t addr = (uint32_t)buf;
- size_t rsz = roundup(sz, 32);
int idx;
- if (sz != rsz)
- debug("EHCI-HCD: Misaligned buffer size (%08x)\n", sz);
-
- if (addr & 31)
+ if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))
debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf);
+ flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN));
+
idx = 0;
while (idx < 5) {
- flush_dcache_range(addr, addr + rsz);
td->qt_buffer[idx] = cpu_to_hc32(addr);
td->qt_buffer_hi[idx] = 0;
next = (addr + 4096) & ~4095;
@@ -196,7 +196,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
}
if (idx == 5) {
- debug("out of buffer pointers (%u bytes left)\n", sz);
+ printf("out of buffer pointers (%u bytes left)\n", sz);
return -1;
}
@@ -207,8 +207,8 @@ static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *req)
{
- static struct QH qh __attribute__((aligned(32)));
- static struct qTD qtd[3] __attribute__((aligned (32)));
+ ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
+ ALLOC_ALIGN_BUFFER(struct qTD, qtd, 3, USB_DMA_MINALIGN);
int qtd_counter = 0;
volatile struct qTD *vtd;
@@ -229,8 +229,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
le16_to_cpu(req->value), le16_to_cpu(req->value),
le16_to_cpu(req->index));
- memset(&qh, 0, sizeof(struct QH));
- memset(qtd, 0, sizeof(qtd));
+ memset(qh, 0, sizeof(struct QH));
+ memset(qtd, 0, 3 * sizeof(*qtd));
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
@@ -244,7 +244,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
* qh_overlay.qt_next ...... 13-10 H
* - qh_overlay.qt_altnext
*/
- qh.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
+ qh->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
usb_pipeendpoint(pipe) == 0) ? 1 : 0;
endpt = (8 << 28) |
@@ -255,14 +255,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
(usb_pipespeed(pipe) << 12) |
(usb_pipeendpoint(pipe) << 8) |
(0 << 7) | (usb_pipedevice(pipe) << 0);
- qh.qh_endpt1 = cpu_to_hc32(endpt);
+ qh->qh_endpt1 = cpu_to_hc32(endpt);
endpt = (1 << 30) |
(dev->portnr << 23) |
(dev->parent->devnum << 16) | (0 << 8) | (0 << 0);
- qh.qh_endpt2 = cpu_to_hc32(endpt);
- qh.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+ qh->qh_endpt2 = cpu_to_hc32(endpt);
+ qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
- tdp = &qh.qh_overlay.qt_next;
+ tdp = &qh->qh_overlay.qt_next;
if (req != NULL) {
/*
@@ -281,7 +281,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
(0 << 15) | (0 << 12) | (3 << 10) | (2 << 8) | (0x80 << 0);
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req)) != 0) {
- debug("unable construct SETUP td\n");
+ printf("unable construct SETUP td\n");
goto fail;
}
/* Update previous qTD! */
@@ -310,7 +310,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
qtd[qtd_counter].qt_token = cpu_to_hc32(token);
if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) {
- debug("unable construct DATA td\n");
+ printf("unable construct DATA td\n");
goto fail;
}
/* Update previous qTD! */
@@ -340,13 +340,16 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
tdp = &qtd[qtd_counter++].qt_next;
}
- qh_list.qh_link = cpu_to_hc32((uint32_t)&qh | QH_LINK_TYPE_QH);
+ qh_list->qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH);
/* Flush dcache */
- flush_dcache_range((uint32_t)&qh_list,
- (uint32_t)&qh_list + sizeof(struct QH));
- flush_dcache_range((uint32_t)&qh, (uint32_t)&qh + sizeof(struct QH));
- flush_dcache_range((uint32_t)qtd, (uint32_t)qtd + sizeof(qtd));
+ flush_dcache_range((uint32_t)qh_list,
+ ALIGN_END_ADDR(struct QH, qh_list, 1));
+ flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
+ flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, 3));
+
+ /* Set async. queue head pointer. */
+ ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
usbsts = ehci_readl(&hcor->or_usbsts);
ehci_writel(&hcor->or_usbsts, (usbsts & 0x3f));
@@ -369,12 +372,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
timeout = USB_TIMEOUT_MS(pipe);
do {
/* Invalidate dcache */
- invalidate_dcache_range((uint32_t)&qh_list,
- (uint32_t)&qh_list + sizeof(struct QH));
- invalidate_dcache_range((uint32_t)&qh,
- (uint32_t)&qh + sizeof(struct QH));
+ invalidate_dcache_range((uint32_t)qh_list,
+ ALIGN_END_ADDR(struct QH, qh_list, 1));
+ invalidate_dcache_range((uint32_t)qh,
+ ALIGN_END_ADDR(struct QH, qh, 1));
invalidate_dcache_range((uint32_t)qtd,
- (uint32_t)qtd + sizeof(qtd));
+ ALIGN_END_ADDR(struct qTD, qtd, 3));
token = hc32_to_cpu(vtd->qt_token);
if (!(token & 0x80))
@@ -382,9 +385,17 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
WATCHDOG_RESET();
} while (get_timer(ts) < timeout);
- /* Invalidate the memory area occupied by buffer */
- invalidate_dcache_range(((uint32_t)buffer & ~31),
- ((uint32_t)buffer & ~31) + roundup(length, 32));
+ /*
+ * Invalidate the memory area occupied by buffer
+ * Don't try to fix the buffer alignment, if it isn't properly
+ * aligned it's upper layer's fault so let invalidate_dcache_range()
+ * vow about it. But we have to fix the length as it's actual
+ * transfer length and can be unaligned. This is potentially
+ * dangerous operation, it's responsibility of the calling
+ * code to make sure enough space is reserved.
+ */
+ invalidate_dcache_range((uint32_t)buffer,
+ ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN));
/* Check that the TD processing happened */
if (token & 0x80) {
@@ -403,9 +414,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
goto fail;
}
- qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
-
- token = hc32_to_cpu(qh.qh_overlay.qt_token);
+ token = hc32_to_cpu(qh->qh_overlay.qt_token);
if (!(token & 0x80)) {
debug("TOKEN=%#x\n", token);
switch (token & 0xfc) {
@@ -733,16 +742,13 @@ int usb_lowlevel_init(void)
#endif
/* Set head of reclaim list */
- memset(&qh_list, 0, sizeof(qh_list));
- qh_list.qh_link = cpu_to_hc32((uint32_t)&qh_list | QH_LINK_TYPE_QH);
- qh_list.qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
- qh_list.qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
- qh_list.qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
- qh_list.qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
- qh_list.qh_overlay.qt_token = cpu_to_hc32(0x40);
-
- /* Set async. queue head pointer. */
- ehci_writel(&hcor->or_asynclistaddr, (uint32_t)&qh_list);
+ memset(qh_list, 0, sizeof(*qh_list));
+ qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH);
+ qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
+ qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
+ qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
+ qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
+ qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40);
reg = ehci_readl(&hccr->cr_hcsparams);
descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 1ed7710..292673b 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -246,7 +246,6 @@ int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
omap_ehci_soft_phy_reset(i);
- dcache_disable();
hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a7e105b..4646b29 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009 NVIDIA Corporation
+ * Copyright (c) 2009-2012 NVIDIA Corporation
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -29,6 +29,22 @@
#include <asm/errno.h>
#include <asm/arch/usb.h>
+/*
+ * A known hardware issue where Connect Status Change bit of PORTSC register
+ * of USB1 controller will be set after Port Reset.
+ * We have to clear it in order for later device enumeration to proceed.
+ * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup
+ * in "ehci-hcd.c".
+ */
+void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
+{
+ mdelay(50);
+ if (((u32) status_reg & TEGRA_USB_ADDR_MASK) != TEGRA_USB1_BASE)
+ return;
+ /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */
+ if (ehci_readl(status_reg) & EHCI_PS_CSC)
+ *reg |= EHCI_PS_CSC;
+}
/*
* Create the appropriate control structures to manage
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index a8adcce..e914369 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -145,7 +145,7 @@ struct musb_regs {
struct musb_epN_regs epN;
} ep[16];
-} __attribute__((packed, aligned(32)));
+} __attribute__((packed, aligned(USB_DMA_MINALIGN)));
#endif
/*
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 44b7feb..2f8e2b5 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -42,7 +42,7 @@ COBJS-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
COBJS-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o
COBJS-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
-COBJS-$(CONFIG_VIDEO_MX5) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
+COBJS-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o
COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o
COBJS-$(CONFIG_VIDEO_SM501) += sm501.o
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 92fa77d..19d061f 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -164,7 +164,7 @@
/*
* Defines for the i.MX31 driver (mx3fb.c)
*/
-#if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_MX5)
+#if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
#define VIDEO_FB_16BPP_WORD_SWAP
#endif
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index a2981b1..30c19b3 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -121,7 +121,6 @@ struct da8xx_lcd_regs {
#define LOWER_MARGIN 32
#define calc_fbsize() (panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP)
-#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); })
static struct da8xx_lcd_regs *da8xx_fb_reg_base;
diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c
index 92be4ea..49fdfec 100644
--- a/drivers/video/exynos_fb.c
+++ b/drivers/video/exynos_fb.c
@@ -44,9 +44,6 @@ short console_row;
static unsigned int panel_width, panel_height;
-/* LCD Panel data */
-vidinfo_t panel_info;
-
static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
{
unsigned long palette_size;
diff --git a/drivers/video/ipu_common.c b/drivers/video/ipu_common.c
index 9d20c86..2020da9 100644
--- a/drivers/video/ipu_common.c
+++ b/drivers/video/ipu_common.c
@@ -163,6 +163,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
static int clk_ipu_enable(struct clk *clk)
{
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
u32 reg;
reg = __raw_readl(clk->enable_reg);
@@ -178,12 +179,13 @@ static int clk_ipu_enable(struct clk *clk)
reg = __raw_readl(&mxc_ccm->clpcr);
reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
__raw_writel(reg, &mxc_ccm->clpcr);
-
+#endif
return 0;
}
static void clk_ipu_disable(struct clk *clk)
{
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
u32 reg;
reg = __raw_readl(clk->enable_reg);
@@ -202,13 +204,14 @@ static void clk_ipu_disable(struct clk *clk)
reg = __raw_readl(&mxc_ccm->clpcr);
reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
__raw_writel(reg, &mxc_ccm->clpcr);
+#endif
}
static struct clk ipu_clk = {
.name = "ipu_clk",
- .rate = 133000000,
- .enable_reg = (u32 *)(MXC_CCM_BASE +
+ .rate = CONFIG_IPUV3_CLK,
+ .enable_reg = (u32 *)(CCM_BASE_ADDR +
offsetof(struct mxc_ccm_reg, CCGR5)),
.enable_shift = MXC_CCM_CCGR5_CG5_OFFSET,
.enable = clk_ipu_enable,
@@ -216,8 +219,15 @@ static struct clk ipu_clk = {
.usecount = 0,
};
+static struct clk ldb_clk = {
+ .name = "ldb_clk",
+ .rate = 65000000,
+ .usecount = 0,
+};
+
/* Globals */
struct clk *g_ipu_clk;
+struct clk *g_ldb_clk;
unsigned char g_ipu_clk_enabled;
struct clk *g_di_clk[2];
struct clk *g_pixel_clk[2];
@@ -340,7 +350,7 @@ static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
if (parent == g_ipu_clk)
di_gen &= ~DI_GEN_DI_CLK_EXT;
- else if (!IS_ERR(g_di_clk[clk->id]) && parent == g_di_clk[clk->id])
+ else if (!IS_ERR(g_di_clk[clk->id]) && parent == g_ldb_clk)
di_gen |= DI_GEN_DI_CLK_EXT;
else
return -EINVAL;
@@ -401,6 +411,7 @@ void ipu_reset(void)
int ipu_probe(void)
{
unsigned long ipu_base;
+#if defined CONFIG_MX51
u32 temp;
u32 *reg_hsc_mcd = (u32 *)MIPI_HSC_BASE_ADDR;
@@ -414,6 +425,7 @@ int ipu_probe(void)
temp = __raw_readl(reg_hsc_mxt_conf);
__raw_writel(temp | 0x10000, reg_hsc_mxt_conf);
+#endif
ipu_base = IPU_CTRL_BASE_ADDR;
ipu_cpmem_base = (u32 *)(ipu_base + IPU_CPMEM_REG_BASE);
@@ -424,7 +436,8 @@ int ipu_probe(void)
g_ipu_clk = &ipu_clk;
debug("ipu_clk = %u\n", clk_get_rate(g_ipu_clk));
-
+ g_ldb_clk = &ldb_clk;
+ debug("ldb_clk = %u\n", clk_get_rate(g_ldb_clk));
ipu_reset();
clk_set_parent(g_pixel_clk[0], g_ipu_clk);
diff --git a/drivers/video/ipu_disp.c b/drivers/video/ipu_disp.c
index fa8fb2c..b4116df 100644
--- a/drivers/video/ipu_disp.c
+++ b/drivers/video/ipu_disp.c
@@ -64,6 +64,7 @@ static int dmfc_size_28, dmfc_size_29, dmfc_size_24, dmfc_size_27, dmfc_size_23;
int g_di1_tvout;
extern struct clk *g_ipu_clk;
+extern struct clk *g_ldb_clk;
extern struct clk *g_di_clk[2];
extern struct clk *g_pixel_clk[2];
@@ -941,7 +942,7 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
udelay(10000);
}
}
- clk_set_parent(g_pixel_clk[disp], g_di_clk[disp]);
+ clk_set_parent(g_pixel_clk[disp], g_ldb_clk);
} else {
if (clk_get_usecount(g_pixel_clk[disp]) != 0)
clk_set_parent(g_pixel_clk[disp], g_ipu_clk);
diff --git a/drivers/video/ipu_regs.h b/drivers/video/ipu_regs.h
index 93b195f..a43aa03 100644
--- a/drivers/video/ipu_regs.h
+++ b/drivers/video/ipu_regs.h
@@ -47,14 +47,24 @@
#define IPU_SMFC_REG_BASE 0x00050000
#define IPU_DC_REG_BASE 0x00058000
#define IPU_DMFC_REG_BASE 0x00060000
+#define IPU_VDI_REG_BASE 0x00680000
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
#define IPU_CPMEM_REG_BASE 0x01000000
#define IPU_LUT_REG_BASE 0x01020000
#define IPU_SRM_REG_BASE 0x01040000
#define IPU_TPM_REG_BASE 0x01060000
#define IPU_DC_TMPL_REG_BASE 0x01080000
#define IPU_ISP_TBPR_REG_BASE 0x010C0000
-#define IPU_VDI_REG_BASE 0x00680000
+#elif defined(CONFIG_MX6Q)
+#define IPU_CPMEM_REG_BASE 0x00100000
+#define IPU_LUT_REG_BASE 0x00120000
+#define IPU_SRM_REG_BASE 0x00140000
+#define IPU_TPM_REG_BASE 0x00160000
+#define IPU_DC_TMPL_REG_BASE 0x00180000
+#define IPU_ISP_TBPR_REG_BASE 0x001C0000
+#endif
+#define IPU_CTRL_BASE_ADDR (IPU_SOC_BASE_ADDR + IPU_SOC_OFFSET)
extern u32 *ipu_dc_tmpl_reg;