summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ahci.c1
-rw-r--r--drivers/core/device.c13
-rw-r--r--drivers/ddr/marvell/a38x/ddr3_init.h2
-rw-r--r--drivers/dfu/dfu.c15
-rw-r--r--drivers/dfu/dfu_mmc.c27
-rw-r--r--drivers/gpio/lpc32xx_gpio.c41
-rw-r--r--drivers/gpio/s5p_gpio.c18
-rw-r--r--drivers/gpio/sh_pfc.c3
-rw-r--r--drivers/gpio/tegra_gpio.c58
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/mxc_i2c.c6
-rw-r--r--drivers/i2c/u8500_i2c.c601
-rw-r--r--drivers/i2c/u8500_i2c.h178
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/reset_sandbox.c2
-rw-r--r--drivers/mmc/dw_mmc.c3
-rw-r--r--drivers/mmc/mmc.c1
-rw-r--r--drivers/mmc/rpmb.c1
-rw-r--r--drivers/mmc/sunxi_mmc.c16
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/fsmc_nand.c49
-rw-r--r--drivers/mtd/nand/jz4740_nand.c1
-rw-r--r--drivers/mtd/nand/mxs_nand.c9
-rw-r--r--drivers/mtd/nand/nand_util.c1
-rw-r--r--drivers/mtd/nand/nomadik.c206
-rw-r--r--drivers/mtd/nand/omap_gpmc.c6
-rw-r--r--drivers/mtd/nand/sunxi_nand_spl.c27
-rw-r--r--drivers/mtd/nand/tegra_nand.c1
-rw-r--r--drivers/mtd/spi/sf_params.c1
-rw-r--r--drivers/net/designware.c42
-rw-r--r--drivers/net/e1000.c1
-rw-r--r--drivers/net/fec_mxc.c1
-rw-r--r--drivers/net/netconsole.c14
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/rtl8169.c1
-rw-r--r--drivers/net/smc91111.c51
-rw-r--r--drivers/net/smc91111.h22
-rw-r--r--drivers/net/vsc9953.c2232
-rw-r--r--drivers/pci/pci-uclass.c4
-rw-r--r--drivers/pci/pci_auto.c1
-rw-r--r--drivers/pci/pcie_imx.c6
-rw-r--r--drivers/pinctrl/Kconfig2
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/pinctrl-uclass.c15
-rw-r--r--drivers/pinctrl/rockchip/pinctrl_rk3288.c8
-rw-r--r--drivers/pinctrl/uniphier/Kconfig42
-rw-r--r--drivers/pinctrl/uniphier/Makefile8
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c133
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c133
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c130
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c144
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c141
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-proxstream2.c140
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c154
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier.h113
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/serial_pl01x.c22
-rw-r--r--drivers/serial/serial_sh.h43
-rw-r--r--drivers/spi/davinci_spi.c2
-rw-r--r--drivers/spi/ep93xx_spi.c2
-rw-r--r--drivers/spi/mxs_spi.c1
-rw-r--r--drivers/spi/tegra20_slink.c21
-rw-r--r--drivers/spi/xilinx_spi.c10
-rw-r--r--drivers/spi/zynq_spi.c7
-rw-r--r--drivers/thermal/Makefile2
-rw-r--r--drivers/thermal/imx_thermal.c90
-rw-r--r--drivers/usb/eth/asix.c1
-rw-r--r--drivers/usb/eth/asix88179.c1
-rw-r--r--drivers/usb/eth/mcs7830.c1
-rw-r--r--drivers/usb/eth/smsc95xx.c1
-rw-r--r--drivers/usb/gadget/ci_udc.c44
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/gadget/f_thor.c1
-rw-r--r--drivers/usb/gadget/g_dnl.c2
-rw-r--r--drivers/usb/host/dwc2.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c1
-rw-r--r--drivers/usb/host/ohci-hcd.c1
-rw-r--r--drivers/usb/host/usb-uclass.c1
-rw-r--r--drivers/usb/musb-new/musb_core.c2
-rwxr-xr-xdrivers/video/anx9804.c2
-rw-r--r--drivers/video/bcm2835.c1
-rw-r--r--drivers/video/mb862xx.c3
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/imx_watchdog.c17
85 files changed, 3649 insertions, 1470 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index 0d19dd25a3..82c68439f8 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -15,6 +15,7 @@
#include <asm/errno.h>
#include <asm/io.h>
#include <malloc.h>
+#include <memalign.h>
#include <scsi.h>
#include <libata.h>
#include <linux/ctype.h>
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 0ccd443f25..833a803696 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -289,8 +289,12 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
dev->flags |= DM_FLAG_ACTIVATED;
- /* continue regardless of the result of pinctrl */
- pinctrl_select_state(dev, "default");
+ /*
+ * Process pinctrl for everything except the root device, and
+ * continue regardless of the result of pinctrl.
+ */
+ if (dev->parent)
+ pinctrl_select_state(dev, "default");
ret = uclass_pre_probe_device(dev);
if (ret)
@@ -581,7 +585,10 @@ fdt_addr_t dev_get_addr(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_CONTROL)
fdt_addr_t addr;
- addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+ addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+ dev->parent->of_offset,
+ dev->of_offset, "reg",
+ 0, NULL);
if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
if (device_get_uclass_id(dev->parent) == UCLASS_SIMPLE_BUS)
addr = simple_bus_translate(dev->parent, addr);
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h
index e2ff040b00..cb3fb24416 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -32,8 +32,6 @@
*/
#define MV_DEBUG_INIT
-#define BIT(x) (1 << (x))
-
#ifdef MV_DEBUG_INIT
#define DEBUG_INIT_S(s) puts(s)
#define DEBUG_INIT_D(d, l) printf("%x", d)
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 6cf240de22..8f5915e49c 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -164,7 +164,6 @@ static int dfu_write_buffer_drain(struct dfu_entity *dfu)
void dfu_write_transaction_cleanup(struct dfu_entity *dfu)
{
/* clear everything */
- dfu_free_buf();
dfu->crc = 0;
dfu->offset = 0;
dfu->i_blk_seq_num = 0;
@@ -339,17 +338,6 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
dfu->r_left = dfu->get_medium_size(dfu);
if (dfu->r_left < 0)
return dfu->r_left;
- switch (dfu->layout) {
- case DFU_RAW_ADDR:
- case DFU_RAM_ADDR:
- break;
- default:
- if (dfu->r_left > dfu_buf_size) {
- printf("%s: File too big for buffer\n",
- __func__);
- return -EOVERFLOW;
- }
- }
debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left);
@@ -385,7 +373,6 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
dfu_hash_algo->name, dfu->crc);
puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
- dfu_free_buf();
dfu->i_blk_seq_num = 0;
dfu->crc = 0;
dfu->offset = 0;
@@ -433,6 +420,7 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
__func__, interface);
return -1;
}
+ dfu_get_buf(dfu);
return 0;
}
@@ -441,6 +429,7 @@ void dfu_free_entities(void)
{
struct dfu_entity *dfu, *p, *t = NULL;
+ dfu_free_buf();
list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
list_del(&dfu->list);
if (dfu->free_entity)
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 2a780f7b5d..5a9fb4a6e2 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -18,6 +18,7 @@
static unsigned char *dfu_file_buf;
static long dfu_file_buf_len;
+static long dfu_file_buf_filled;
static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
{
@@ -230,9 +231,12 @@ long dfu_get_medium_size_mmc(struct dfu_entity *dfu)
return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
case DFU_FS_FAT:
case DFU_FS_EXT4:
+ dfu_file_buf_filled = -1;
ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len);
if (ret < 0)
return ret;
+ if (len > CONFIG_SYS_DFU_MAX_FILE_SIZE)
+ return -1;
return len;
default:
printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -241,6 +245,27 @@ long dfu_get_medium_size_mmc(struct dfu_entity *dfu)
}
}
+static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf,
+ long *len)
+{
+ int ret;
+ long file_len;
+
+ if (dfu_file_buf_filled == -1) {
+ ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len);
+ if (ret < 0)
+ return ret;
+ dfu_file_buf_filled = file_len;
+ }
+ if (offset + *len > dfu_file_buf_filled)
+ return -EINVAL;
+
+ /* Add to the current buffer. */
+ memcpy(buf, dfu_file_buf + offset, *len);
+
+ return 0;
+}
+
int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
long *len)
{
@@ -252,7 +277,7 @@ int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
break;
case DFU_FS_FAT:
case DFU_FS_EXT4:
- ret = mmc_file_op(DFU_OP_READ, dfu, buf, len);
+ ret = mmc_file_unbuffer(dfu, offset, buf, len);
break;
default:
printf("%s: Layout (%s) not (yet) supported!\n", __func__,
diff --git a/drivers/gpio/lpc32xx_gpio.c b/drivers/gpio/lpc32xx_gpio.c
index 8a9826e6eb..9674ee75f0 100644
--- a/drivers/gpio/lpc32xx_gpio.c
+++ b/drivers/gpio/lpc32xx_gpio.c
@@ -22,7 +22,7 @@
* read on another one.
*
* In order to keep this code simple, GPIOS are considered here as
- * homogeneous and linear, from 0 to 127.
+ * homogeneous and linear, from 0 to 159.
*
* ** WARNING #1 **
*
@@ -35,7 +35,7 @@
* Please read NOTE in description of lpc32xx_gpio_get_function().
*/
-#define LPC32XX_GPIOS 128
+#define LPC32XX_GPIOS 160
struct lpc32xx_gpio_priv {
struct gpio_regs *regs;
@@ -45,11 +45,18 @@ struct lpc32xx_gpio_priv {
/**
* We have 4 GPIO ports of 32 bits each
+ *
+ * Port mapping offset (32 bits each):
+ * - Port 0: 0
+ * - Port 1: 32
+ * - Port 2: 64
+ * - Port 3: GPO / GPIO (output): 96
+ * - Port 3: GPI: 128
*/
-#define MAX_GPIO 128
+#define MAX_GPIO 160
-#define GPIO_TO_PORT(gpio) ((gpio / 32) & 3)
+#define GPIO_TO_PORT(gpio) ((gpio / 32) & 7)
#define GPIO_TO_RANK(gpio) (gpio % 32)
#define GPIO_TO_MASK(gpio) (1 << (gpio % 32))
@@ -75,9 +82,16 @@ static int lpc32xx_gpio_direction_input(struct udevice *dev, unsigned offset)
break;
case 2:
/* ports 2 and 3 share a common direction */
- case 3:
writel(mask, &regs->p2_p3_dir_clr);
break;
+ case 3:
+ /* Setup direction only for GPIO_xx. */
+ if ((mask >= 25) && (mask <= 30))
+ writel(mask, &regs->p2_p3_dir_clr);
+ break;
+ case 4:
+ /* GPI_xx; nothing to do. */
+ break;
default:
return -1;
}
@@ -111,6 +125,11 @@ static int lpc32xx_gpio_get_value(struct udevice *dev, unsigned offset)
value = readl(&regs->p2_inp_state);
break;
case 3:
+ /* Read GPO_xx and GPIO_xx (as output) using p3_outp_state. */
+ value = readl(&regs->p3_outp_state);
+ break;
+ case 4:
+ /* Read GPI_xx and GPIO_xx (as input) using p3_inp_state. */
value = readl(&regs->p3_inp_state);
break;
default:
@@ -149,6 +168,8 @@ static int gpio_set(struct udevice *dev, unsigned gpio)
case 3:
writel(mask, &regs->p3_outp_set);
break;
+ case 4:
+ /* GPI_xx; invalid. */
default:
return -1;
}
@@ -181,6 +202,8 @@ static int gpio_clr(struct udevice *dev, unsigned gpio)
case 3:
writel(mask, &regs->p3_outp_clr);
break;
+ case 4:
+ /* GPI_xx; invalid. */
default:
return -1;
}
@@ -223,9 +246,15 @@ static int lpc32xx_gpio_direction_output(struct udevice *dev, unsigned offset,
break;
case 2:
/* ports 2 and 3 share a common direction */
- case 3:
writel(mask, &regs->p2_p3_dir_set);
break;
+ case 3:
+ /* Setup direction only for GPIO_xx. */
+ if ((mask >= 25) && (mask <= 30))
+ writel(mask, &regs->p2_p3_dir_set);
+ break;
+ case 4:
+ /* GPI_xx; invalid. */
default:
return -1;
}
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 17fcfbf4d3..0f22b238ba 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -341,18 +341,22 @@ static int gpio_exynos_bind(struct udevice *parent)
plat = calloc(1, sizeof(*plat));
if (!plat)
return -ENOMEM;
- reg = fdtdec_get_addr(blob, node, "reg");
- if (reg != FDT_ADDR_T_NONE)
- bank = (struct s5p_gpio_bank *)((ulong)base + reg);
- plat->bank = bank;
- plat->bank_name = fdt_get_name(blob, node, NULL);
- debug("dev at %p: %s\n", bank, plat->bank_name);
+ plat->bank_name = fdt_get_name(blob, node, NULL);
ret = device_bind(parent, parent->driver,
- plat->bank_name, plat, -1, &dev);
+ plat->bank_name, plat, -1, &dev);
if (ret)
return ret;
+
dev->of_offset = node;
+
+ reg = dev_get_addr(dev);
+ if (reg != FDT_ADDR_T_NONE)
+ bank = (struct s5p_gpio_bank *)((ulong)base + reg);
+
+ plat->bank = bank;
+
+ debug("dev at %p: %s\n", bank, plat->bank_name);
}
return 0;
diff --git a/drivers/gpio/sh_pfc.c b/drivers/gpio/sh_pfc.c
index 7a5af20a2a..a0eac137c2 100644
--- a/drivers/gpio/sh_pfc.c
+++ b/drivers/gpio/sh_pfc.c
@@ -75,7 +75,8 @@ static int gpio_read_bit(struct pinmux_data_reg *dr,
debug("read_bit: addr = %lx, pos = %ld, "
"r_width = %ld\n", dr->reg, pos, dr->reg_width);
- return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+ return
+ (gpio_read_raw_reg(dr->mapped_reg + 0x4, dr->reg_width) >> pos) & 1;
}
static void gpio_write_bit(struct pinmux_data_reg *dr,
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 4921f0ff42..8e880e276f 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -1,6 +1,6 @@
/*
* NVIDIA Tegra20 GPIO handling.
- * (C) Copyright 2010-2012
+ * (C) Copyright 2010-2012,2015
* NVIDIA Corporation <www.nvidia.com>
*
* SPDX-License-Identifier: GPL-2.0+
@@ -25,12 +25,10 @@
DECLARE_GLOBAL_DATA_PTR;
-enum {
- TEGRA_CMD_INFO,
- TEGRA_CMD_PORT,
- TEGRA_CMD_OUTPUT,
- TEGRA_CMD_INPUT,
-};
+static const int CONFIG_SFIO = 0;
+static const int CONFIG_GPIO = 1;
+static const int DIRECTION_INPUT = 0;
+static const int DIRECTION_OUTPUT = 1;
struct tegra_gpio_platdata {
struct gpio_ctlr_bank *bank;
@@ -44,7 +42,7 @@ struct tegra_port_info {
int base_gpio; /* Port number for this port (0, 1,.., n-1) */
};
-/* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
+/* Return config of pin 'gpio' as GPIO (1) or SFIO (0) */
static int get_config(unsigned gpio)
{
struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
@@ -53,15 +51,15 @@ static int get_config(unsigned gpio)
int type;
u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
- type = (u >> GPIO_BIT(gpio)) & 1;
+ type = (u >> GPIO_BIT(gpio)) & 1;
debug("get_config: port = %d, bit = %d is %s\n",
GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
- return type;
+ return type ? CONFIG_GPIO : CONFIG_SFIO;
}
-/* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */
+/* Config pin 'gpio' as GPIO or SFIO, based on 'type' */
static void set_config(unsigned gpio, int type)
{
struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
@@ -72,7 +70,7 @@ static void set_config(unsigned gpio, int type)
GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
- if (type) /* GPIO */
+ if (type != CONFIG_SFIO)
u |= 1 << GPIO_BIT(gpio);
else
u &= ~(1 << GPIO_BIT(gpio));
@@ -93,7 +91,7 @@ static int get_direction(unsigned gpio)
debug("get_direction: port = %d, bit = %d, %s\n",
GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN");
- return dir;
+ return dir ? DIRECTION_OUTPUT : DIRECTION_INPUT;
}
/* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */
@@ -107,7 +105,7 @@ static void set_direction(unsigned gpio, int output)
GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN");
u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
- if (output)
+ if (output != DIRECTION_INPUT)
u |= 1 << GPIO_BIT(gpio);
else
u &= ~(1 << GPIO_BIT(gpio));
@@ -136,24 +134,16 @@ static void set_level(unsigned gpio, int high)
* Generic_GPIO primitives.
*/
-static int tegra_gpio_request(struct udevice *dev, unsigned offset,
- const char *label)
-{
- struct tegra_port_info *state = dev_get_priv(dev);
-
- /* Configure as a GPIO */
- set_config(state->base_gpio + offset, 1);
-
- return 0;
-}
-
/* set GPIO pin 'gpio' as an input */
static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
{
struct tegra_port_info *state = dev_get_priv(dev);
/* Configure GPIO direction as input. */
- set_direction(state->base_gpio + offset, 0);
+ set_direction(state->base_gpio + offset, DIRECTION_INPUT);
+
+ /* Enable the pin as a GPIO */
+ set_config(state->base_gpio + offset, 1);
return 0;
}
@@ -169,7 +159,10 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
set_level(gpio, value);
/* Configure GPIO direction as output. */
- set_direction(gpio, 1);
+ set_direction(gpio, DIRECTION_OUTPUT);
+
+ /* Enable the pin as a GPIO */
+ set_config(state->base_gpio + offset, 1);
return 0;
}
@@ -211,16 +204,18 @@ void gpio_config_table(const struct tegra_gpio_config *config, int len)
for (i = 0; i < len; i++) {
switch (config[i].init) {
case TEGRA_GPIO_INIT_IN:
- gpio_direction_input(config[i].gpio);
+ set_direction(config[i].gpio, DIRECTION_INPUT);
break;
case TEGRA_GPIO_INIT_OUT0:
- gpio_direction_output(config[i].gpio, 0);
+ set_level(config[i].gpio, 0);
+ set_direction(config[i].gpio, DIRECTION_OUTPUT);
break;
case TEGRA_GPIO_INIT_OUT1:
- gpio_direction_output(config[i].gpio, 1);
+ set_level(config[i].gpio, 1);
+ set_direction(config[i].gpio, DIRECTION_OUTPUT);
break;
}
- set_config(config[i].gpio, 1);
+ set_config(config[i].gpio, CONFIG_GPIO);
}
}
@@ -254,7 +249,6 @@ static int tegra_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
}
static const struct dm_gpio_ops gpio_tegra_ops = {
- .request = tegra_gpio_request,
.direction_input = tegra_gpio_direction_input,
.direction_output = tegra_gpio_direction_output,
.get_value = tegra_gpio_get_value,
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 8ce294b02a..32198bd5b2 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
obj-$(CONFIG_I2C_MV) += mv_i2c.o
obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
-obj-$(CONFIG_U8500_I2C) += u8500_i2c.o
obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
obj-$(CONFIG_SYS_I2C) += i2c_core.o
obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index f1056e21a2..0f977d706d 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -612,16 +612,22 @@ static u32 mxc_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed)
/*
* Register mxc i2c adapters
*/
+#ifdef CONFIG_SYS_I2C_MXC_I2C1
U_BOOT_I2C_ADAP_COMPLETE(mxc0, mxc_i2c_init, mxc_i2c_probe,
mxc_i2c_read, mxc_i2c_write,
mxc_i2c_set_bus_speed,
CONFIG_SYS_MXC_I2C1_SPEED,
CONFIG_SYS_MXC_I2C1_SLAVE, 0)
+#endif
+
+#ifdef CONFIG_SYS_I2C_MXC_I2C2
U_BOOT_I2C_ADAP_COMPLETE(mxc1, mxc_i2c_init, mxc_i2c_probe,
mxc_i2c_read, mxc_i2c_write,
mxc_i2c_set_bus_speed,
CONFIG_SYS_MXC_I2C2_SPEED,
CONFIG_SYS_MXC_I2C2_SLAVE, 1)
+#endif
+
#ifdef CONFIG_SYS_I2C_MXC_I2C3
U_BOOT_I2C_ADAP_COMPLETE(mxc2, mxc_i2c_init, mxc_i2c_probe,
mxc_i2c_read, mxc_i2c_write,
diff --git a/drivers/i2c/u8500_i2c.c b/drivers/i2c/u8500_i2c.c
deleted file mode 100644
index 81ffb8ed79..0000000000
--- a/drivers/i2c/u8500_i2c.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Basic U-Boot I2C interface for STn8500/DB8500
- * Author: Michael Brandt <Michael.Brandt@stericsson.com> for ST-Ericsson
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-/*
- * Only 7-bit I2C device addresses are supported.
- */
-
-#include <common.h>
-#include <i2c.h>
-
-#include "u8500_i2c.h"
-#include <asm/io.h>
-#include <asm/arch/clock.h>
-
-#define U8500_I2C_ENDAD_COUNTER (CONFIG_SYS_HZ/100) /* I2C bus timeout */
-#define U8500_I2C_FIFO_FLUSH_COUNTER 500000 /* flush "timeout" */
-#define U8500_I2C_SCL_FREQ 100000 /* I2C bus clock freq */
-#define U8500_I2C_INPUT_FREQ 48000000 /* Input clock freq */
-#define TX_FIFO_THRESHOLD 0x4
-#define RX_FIFO_THRESHOLD 0x4
-#define SLAVE_SETUP_TIME 14 /* Slave data setup time, 250ns for 48MHz i2c_clk */
-
-#define WRITE_FIELD(var, mask, shift, value) \
- (var = ((var & ~(mask)) | ((value) << (shift))))
-
-static unsigned int bus_initialized[CONFIG_SYS_U8500_I2C_BUS_MAX];
-static unsigned int i2c_bus_num;
-static unsigned int i2c_bus_speed[] = {
- CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SPEED,
- CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SPEED
-};
-static struct u8500_i2c_regs *i2c_dev[] = {
- (struct u8500_i2c_regs *)CONFIG_SYS_U8500_I2C0_BASE,
- (struct u8500_i2c_regs *)CONFIG_SYS_U8500_I2C1_BASE,
- (struct u8500_i2c_regs *)CONFIG_SYS_U8500_I2C2_BASE,
- (struct u8500_i2c_regs *)CONFIG_SYS_U8500_I2C3_BASE,
-};
-
-static struct {
- int periph;
- int pcken;
- int kcken;
-} i2c_clock_bits[] = {
- {3, 3, 3}, /* I2C0 */
- {1, 2, 2}, /* I2C1 */
- {1, 6, 6}, /* I2C2 */
- {2, 0, 0}, /* I2C3 */
-};
-
-static void i2c_set_bit(void *reg, u32 mask)
-{
- writel(readl(reg) | mask, reg);
-}
-
-static void i2c_clr_bit(void *reg, u32 mask)
-{
- writel(readl(reg) & ~mask, reg);
-}
-
-static void i2c_write_field(void *reg, u32 mask, uint shift, u32 value)
-{
- writel((readl(reg) & ~mask) | (value << shift), reg);
-}
-
-static int __i2c_set_bus_speed(unsigned int speed)
-{
- u32 value;
- struct u8500_i2c_regs *i2c_regs;
-
- i2c_regs = i2c_dev[i2c_bus_num];
-
- /* Select standard (100 kbps) speed mode */
- i2c_write_field(&i2c_regs->cr, U8500_I2C_CR_SM,
- U8500_I2C_CR_SHIFT_SM, 0x0);
-
- /*
- * Set the Baud Rate Counter 2 value
- * Baud rate (standard) = fi2cclk / ( (BRCNT2 x 2) + Foncycle )
- * Foncycle = 0 (no digital filtering)
- */
- value = (u32) (U8500_I2C_INPUT_FREQ / (speed * 2));
- i2c_write_field(&i2c_regs->brcr, U8500_I2C_BRCR_BRCNT2,
- U8500_I2C_BRCR_SHIFT_BRCNT2, value);
-
- /* ensure that BRCNT value is zero */
- i2c_write_field(&i2c_regs->brcr, U8500_I2C_BRCR_BRCNT1,
- U8500_I2C_BRCR_SHIFT_BRCNT1, 0);
-
- return U8500_I2C_INPUT_FREQ/(value * 2);
-}
-
-/*
- * i2c_init - initialize the i2c bus
- *
- * speed: bus speed (in HZ)
- * slaveaddr: address of device in slave mode
- *
- * Slave mode is not implemented.
- */
-void i2c_init(int speed, int slaveaddr)
-{
- struct u8500_i2c_regs *i2c_regs;
-
- debug("i2c_init bus %d, speed %d\n", i2c_bus_num, speed);
-
- u8500_clock_enable(i2c_clock_bits[i2c_bus_num].periph,
- i2c_clock_bits[i2c_bus_num].pcken,
- i2c_clock_bits[i2c_bus_num].kcken);
-
- i2c_regs = i2c_dev[i2c_bus_num];
-
- /* Disable the controller */
- i2c_clr_bit(&i2c_regs->cr, U8500_I2C_CR_PE);
-
- /* Clear registers */
- writel(0, &i2c_regs->cr);
- writel(0, &i2c_regs->scr);
- writel(0, &i2c_regs->hsmcr);
- writel(0, &i2c_regs->tftr);
- writel(0, &i2c_regs->rftr);
- writel(0, &i2c_regs->dmar);
-
- i2c_bus_speed[i2c_bus_num] = __i2c_set_bus_speed(speed);
-
- /*
- * Set our own address.
- * Set slave address mode to 7 bit addressing mode
- */
- i2c_clr_bit(&i2c_regs->cr, U8500_I2C_CR_SAM);
- i2c_write_field(&i2c_regs->scr, U8500_I2C_SCR_ADDR,
- U8500_I2C_SCR_SHIFT_ADDR, slaveaddr);
- /* Slave Data Set up Time */
- i2c_write_field(&i2c_regs->scr, U8500_I2C_SCR_DATA_SETUP_TIME,
- U8500_I2C_SCR_SHIFT_DATA_SETUP_TIME, SLAVE_SETUP_TIME);
-
- /* Disable the DMA sync logic */
- i2c_write_field(&i2c_regs->cr, U8500_I2C_CR_DMA_SLE,
- U8500_I2C_CR_SHIFT_DMA_SLE, 0);
-
- /* Disable interrupts */
- writel(0, &i2c_regs->imscr);
-
- /* Configure bus master mode */
- i2c_write_field(&i2c_regs->cr, U8500_I2C_CR_OM, U8500_I2C_CR_SHIFT_OM,
- U8500_I2C_BUS_MASTER_MODE);
- /* Set FIFO threshold values */
- writel(TX_FIFO_THRESHOLD, &i2c_regs->tftr);
- writel(RX_FIFO_THRESHOLD, &i2c_regs->rftr);
-
- /* Enable the I2C Controller */
- i2c_set_bit(&i2c_regs->cr, U8500_I2C_CR_PE);
-
- bus_initialized[i2c_bus_num] = 1;
-}
-
-
-/*
- * loop_till_bit_clear - polls on a bit till it clears
- * ioreg: register where you want to check status
- * mask: bit mask for the bit you wish to check
- * timeout: timeout in ticks/s
- */
-static int loop_till_bit_clear(void *io_reg, u32 mask, unsigned long timeout)
-{
- unsigned long timebase = get_timer(0);
-
- do {
- if ((readl(io_reg) & mask) == 0x0UL)
- return 0;
- } while (get_timer(timebase) < timeout);
-
- debug("loop_till_bit_clear timed out\n");
- return -1;
-}
-
-/*
- * loop_till_bit_set - polls on a bit till it is set.
- * ioreg: register where you want to check status
- * mask: bit mask for the bit you wish to check
- * timeout: timeout in ticks/s
- */
-static int loop_till_bit_set(void *io_reg, u32 mask, unsigned long timeout)
-{
- unsigned long timebase = get_timer(0);
-
- do {
- if ((readl(io_reg) & mask) != 0x0UL)
- return 0;
- } while (get_timer(timebase) < timeout);
-
- debug("loop_till_bit_set timed out\n");
- return -1;
-}
-
-/*
- * flush_fifo - flush the I2C TX and RX FIFOs
- */
-static void flush_fifo(struct u8500_i2c_regs *i2c_regs)
-{
- int counter = U8500_I2C_FIFO_FLUSH_COUNTER;
-
- /* Flush Tx FIFO */
- i2c_set_bit(&i2c_regs->cr, U8500_I2C_CR_FTX);
- /* Flush Rx FIFO */
- i2c_set_bit(&i2c_regs->cr, U8500_I2C_CR_FRX);
- while (counter--) {
- if (!(readl(&i2c_regs->cr) &
- (U8500_I2C_CR_FTX | U8500_I2C_CR_FRX)))
- break;
- }
- return;
-}
-
-#ifdef DEBUG
-static void print_abort_reason(struct u8500_i2c_regs *i2c_regs)
-{
- int cause;
-
- printf("abort: risr %08x, sr %08x\n", i2c_regs->risr, i2c_regs->sr);
- cause = (readl(&i2c_regs->sr) & U8500_I2C_SR_CAUSE) >>
- U8500_I2C_SR_SHIFT_CAUSE;
- switch (cause) {
- case U8500_I2C_NACK_ADDR:
- printf("No Ack received after Slave Address xmission\n");
- break;
- case U8500_I2C_NACK_DATA:
- printf("Valid for MASTER_WRITE: No Ack received "
- "during data phase\n");
- break;
- case U8500_I2C_ACK_MCODE:
- printf("Master recv ack after xmission of master code"
- "in hs mode\n");
- break;
- case U8500_I2C_ARB_LOST:
- printf("Master Lost arbitration\n");
- break;
- case U8500_I2C_BERR_START:
- printf("Slave restarts\n");
- break;
- case U8500_I2C_BERR_STOP:
- printf("Slave reset\n");
- break;
- case U8500_I2C_OVFL:
- printf("Overflow\n");
- break;
- default:
- printf("Unknown error type\n");
- }
-}
-#endif
-
-/*
- * i2c_abort - called when a I2C transaction failed
- */
-static void i2c_abort(struct u8500_i2c_regs *i2c_regs)
-{
-#ifdef DEBUG
- print_abort_reason(i2c_regs);
-#endif
- /* flush RX and TX fifos */
- flush_fifo(i2c_regs);
-
- /* Acknowledge the Master Transaction Done */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTD);
-
- /* Acknowledge the Master Transaction Done Without Stop */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTDWS);
-
- i2c_init(i2c_bus_speed[i2c_bus_num], CONFIG_SYS_I2C_SLAVE);
-}
-
-/*
- * write addr, alias index, to I2C bus.
- */
-static int i2c_write_addr(struct u8500_i2c_regs *i2c_regs, uint addr, int alen)
-{
- while (alen--) {
- /* Wait until the Tx Fifo is not full */
- if (loop_till_bit_clear((void *)&i2c_regs->risr,
- U8500_I2C_INT_TXFF,
- U8500_I2C_ENDAD_COUNTER)) {
- i2c_abort(i2c_regs);
- return -1;
- }
-
- /* MSB first */
- writeb((addr >> (alen * 8)) & 0xff, &i2c_regs->tfr);
- }
-
- return 0;
-}
-
-/*
- * Internal simplified read function:
- * i2c_regs: Pointer to I2C registers for current bus
- * chip: I2C chip address, range 0..127
- * addr: Memory (register) address within the chip
- * alen: Number of bytes to use for addr (typically 1, 2 for larger
- * memories, 0 for register type devices with only one register)
- * value: Where to put the data
- *
- * Returns: 0 on success, not 0 on failure
- */
-static int i2c_read_byte(struct u8500_i2c_regs *i2c_regs, uchar chip,
- uint addr, int alen, uchar *value)
-{
- u32 mcr = 0;
-
- /* Set the address mode to 7 bit */
- WRITE_FIELD(mcr, U8500_I2C_MCR_AM, U8500_I2C_MCR_SHIFT_AM, 1);
-
- /* Store the slave address in the master control register */
- WRITE_FIELD(mcr, U8500_I2C_MCR_A7, U8500_I2C_MCR_SHIFT_A7, chip);
-
- if (alen != 0) {
- /* Master write operation */
- mcr &= ~(U8500_I2C_MCR_OP);
-
- /* Configure the Frame length to one byte */
- WRITE_FIELD(mcr, U8500_I2C_MCR_LENGTH,
- U8500_I2C_MCR_SHIFT_LENGTH, 1);
-
- /* Repeated start, no stop */
- mcr &= ~(U8500_I2C_MCR_STOP);
-
- /* Write Master Control Register */
- writel(mcr, &i2c_regs->mcr);
-
- /* send addr/index */
- if (i2c_write_addr(i2c_regs, addr, alen) != 0)
- return -1;
-
- /* Check for the Master Transaction Done Without Stop */
- if (loop_till_bit_set((void *)&i2c_regs->risr,
- U8500_I2C_INT_MTDWS,
- U8500_I2C_ENDAD_COUNTER)) {
- return -1;
- }
-
- /* Acknowledge the Master Transaction Done Without Stop */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTDWS);
- }
-
- /* Master control configuration for read operation */
- mcr |= U8500_I2C_MCR_OP;
-
- /* Configure the STOP condition, we read only one byte */
- mcr |= U8500_I2C_MCR_STOP;
-
- /* Set the frame length to one byte, we support only 1 byte reads */
- WRITE_FIELD(mcr, U8500_I2C_MCR_LENGTH, U8500_I2C_MCR_SHIFT_LENGTH, 1);
-
- i2c_write_field(&i2c_regs->mcr, U8500_I2C_MCR_LENGTH_STOP_OP,
- U8500_I2C_MCR_SHIFT_LENGTH_STOP_OP, mcr);
-
- /*
- * receive_data_polling
- */
-
- /* Wait until the Rx FIFO is not empty */
- if (loop_till_bit_clear((void *)&i2c_regs->risr,
- U8500_I2C_INT_RXFE,
- U8500_I2C_ENDAD_COUNTER))
- return -1;
-
- /* Read the data byte from Rx FIFO */
- *value = readb(&i2c_regs->rfr);
-
- /* Wait until the work is done */
- if (loop_till_bit_set((void *)&i2c_regs->risr, U8500_I2C_INT_MTD,
- U8500_I2C_ENDAD_COUNTER))
- return -1;
-
- /* Acknowledge the Master Transaction Done */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTD);
-
- /* If MTD is set, Master Transaction Done Without Stop is set too */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTDWS);
-
- return 0;
-}
-
-/*
- * Internal simplified write function:
- * i2c_regs: Pointer to I2C registers for current bus
- * chip: I2C chip address, range 0..127
- * addr: Memory (register) address within the chip
- * alen: Number of bytes to use for addr (typically 1, 2 for larger
- * memories, 0 for register type devices with only one register)
- * data: Where to read the data
- * len: How many bytes to write
- *
- * Returns: 0 on success, not 0 on failure
- */
-static int __i2c_write(struct u8500_i2c_regs *i2c_regs, u8 chip, uint addr,
- int alen, u8 *data, int len)
-{
- int i;
- u32 mcr = 0;
-
- /* Set the address mode to 7 bit */
- WRITE_FIELD(mcr, U8500_I2C_MCR_AM, U8500_I2C_MCR_SHIFT_AM, 1);
-
- /* Store the slave address in the master control register */
- WRITE_FIELD(mcr, U8500_I2C_MCR_A7, U8500_I2C_MCR_SHIFT_A7, chip);
-
- /* Write operation */
- mcr &= ~(U8500_I2C_MCR_OP);
-
- /* Current transaction is terminated by STOP condition */
- mcr |= U8500_I2C_MCR_STOP;
-
- /* Frame length: addr byte + len */
- WRITE_FIELD(mcr, U8500_I2C_MCR_LENGTH, U8500_I2C_MCR_SHIFT_LENGTH,
- (alen + len));
-
- /* Write MCR register */
- writel(mcr, &i2c_regs->mcr);
-
- if (i2c_write_addr(i2c_regs, addr, alen) != 0)
- return -1;
-
- for (i = 0; i < len; i++) {
- /* Wait until the Tx FIFO is not full */
- if (loop_till_bit_clear((void *)&i2c_regs->risr,
- U8500_I2C_INT_TXFF,
- U8500_I2C_ENDAD_COUNTER))
- return -1;
-
- /* it is a 32 bit register with upper 24 reserved R/O */
- writeb(data[i], &i2c_regs->tfr);
- }
-
- /* Check for Master Transaction Done */
- if (loop_till_bit_set((void *)&i2c_regs->risr,
- U8500_I2C_INT_MTD,
- U8500_I2C_ENDAD_COUNTER)) {
- printf("i2c_write_byte error2: risr %08x\n",
- i2c_regs->risr);
- return -1;
- }
-
- /* Acknowledge Master Transaction Done */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTD);
-
- /* Acknowledge Master Transaction Done Without Stop */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTDWS);
-
- return 0;
-}
-
-/*
- * Probe the given I2C chip address. Returns 0 if a chip responded,
- * not 0 on failure.
- */
-int i2c_probe(uchar chip)
-{
- u32 mcr = 0;
- struct u8500_i2c_regs *i2c_regs;
-
- if (chip == CONFIG_SYS_I2C_SLAVE)
- return 1;
-
- i2c_regs = i2c_dev[i2c_bus_num];
-
- /* Set the address mode to 7 bit */
- WRITE_FIELD(mcr, U8500_I2C_MCR_AM, U8500_I2C_MCR_SHIFT_AM, 1);
-
- /* Store the slave address in the master control register */
- WRITE_FIELD(mcr, U8500_I2C_MCR_A10, U8500_I2C_MCR_SHIFT_A7, chip);
-
- /* Read operation */
- mcr |= U8500_I2C_MCR_OP;
-
- /* Set the frame length to one byte */
- WRITE_FIELD(mcr, U8500_I2C_MCR_LENGTH, U8500_I2C_MCR_SHIFT_LENGTH, 1);
-
- /* Current transaction is terminated by STOP condition */
- mcr |= U8500_I2C_MCR_STOP;
-
- /* Write MCR register */
- writel(mcr, &i2c_regs->mcr);
-
- /* Wait until the Rx Fifo is not empty */
- if (loop_till_bit_clear((void *)&i2c_regs->risr,
- U8500_I2C_INT_RXFE,
- U8500_I2C_ENDAD_COUNTER)) {
- i2c_abort(i2c_regs);
- return -1;
- }
-
- flush_fifo(i2c_regs);
-
- /* Acknowledge the Master Transaction Done */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTD);
-
- /* Acknowledge the Master Transaction Done Without Stop */
- i2c_set_bit(&i2c_regs->icr, U8500_I2C_INT_MTDWS);
-
- return 0;
-}
-
-/*
- * Read/Write interface:
- * chip: I2C chip address, range 0..127
- * addr: Memory (register) address within the chip
- * alen: Number of bytes to use for addr (typically 1, 2 for larger
- * memories, 0 for register type devices with only one
- * register)
- * buffer: Where to read/write the data
- * len: How many bytes to read/write
- *
- * Returns: 0 on success, not 0 on failure
- */
-int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- int i;
- int rc;
- struct u8500_i2c_regs *i2c_regs;
-
- if (alen > 2) {
- debug("I2C read: addr len %d not supported\n", alen);
- return 1;
- }
-
- i2c_regs = i2c_dev[i2c_bus_num];
-
- for (i = 0; i < len; i++) {
- rc = i2c_read_byte(i2c_regs, chip, addr + i, alen, &buffer[i]);
- if (rc != 0) {
- debug("I2C read: I/O error: %d\n", rc);
- i2c_abort(i2c_regs);
- return rc;
- }
- }
-
- return 0;
-}
-
-int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
-{
- int rc;
- struct u8500_i2c_regs *i2c_regs;
- i2c_regs = i2c_dev[i2c_bus_num];
-
- rc = __i2c_write(i2c_regs, chip, addr, alen, buffer,
- len);
- if (rc != 0) {
- debug("I2C write: I/O error\n");
- i2c_abort(i2c_regs);
- return rc;
- }
- return 0;
-}
-
-int i2c_set_bus_num(unsigned int bus)
-{
- if (bus > ARRAY_SIZE(i2c_dev) - 1) {
- debug("i2c_set_bus_num: only up to bus %d supported\n",
- ARRAY_SIZE(i2c_dev)-1);
- return -1;
- }
-
- i2c_bus_num = bus;
-
- if (!bus_initialized[i2c_bus_num])
- i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
-
- return 0;
-}
-
-int i2c_set_bus_speed(unsigned int speed)
-{
-
- if (speed > U8500_I2C_MAX_STANDARD_SCL) {
- debug("i2c_set_bus_speed: only up to %d supported\n",
- U8500_I2C_MAX_STANDARD_SCL);
- return -1;
- }
-
- /* sets as side effect i2c_bus_speed[i2c_bus_num] */
- i2c_init(speed, CONFIG_SYS_I2C_SLAVE);
-
- return 0;
-}
-
-unsigned int i2c_get_bus_num(void)
-{
- return i2c_bus_num;
-}
-
-unsigned int i2c_get_bus_speed(void)
-{
- return i2c_bus_speed[i2c_bus_num];
-}
diff --git a/drivers/i2c/u8500_i2c.h b/drivers/i2c/u8500_i2c.h
deleted file mode 100644
index ceecdeede0..0000000000
--- a/drivers/i2c/u8500_i2c.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2009
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef _U8500_I2C_H_
-#define _U8500_I2C_H_
-
-#include <asm/types.h>
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <asm/arch/u8500.h>
-
-struct u8500_i2c_regs {
- u32 cr; /* Control Register 0x00 */
- u32 scr; /* Slave Address Register 0x04 */
- u32 hsmcr; /* HS Master code Register 0x08 */
- u32 mcr; /* Master Control Register 0x0C */
- u32 tfr; /* Transmit Fifo Register 0x10 */
- u32 sr; /* Status Register 0x14 */
- u32 rfr; /* Receiver Fifo Register 0x18 */
- u32 tftr; /* Transmit Fifo Threshold Register 0x1C */
- u32 rftr; /* Receiver Fifo Threshold Register 0x20 */
- u32 dmar; /* DMA register 0x24 */
- u32 brcr; /* Baud Rate Counter Register 0x28 */
- u32 imscr; /* Interrupt Mask Set and Clear Register 0x2C */
- u32 risr; /* Raw interrupt status register 0x30 */
- u32 misr; /* Masked interrupt status register 0x34 */
- u32 icr; /* Interrupt Set and Clear Register 0x38 */
- u32 reserved_1[(0xFE0 - 0x3c) >> 2]; /* Reserved 0x03C to 0xFE0 */
- u32 periph_id_0; /* peripheral ID 0 0xFE0 */
- u32 periph_id_1; /* peripheral ID 1 0xFE4 */
- u32 periph_id_2; /* peripheral ID 2 0xFE8 */
- u32 periph_id_3; /* peripheral ID 3 0xFEC */
- u32 cell_id_0; /* I2C cell ID 0 0xFF0 */
- u32 cell_id_1; /* I2C cell ID 1 0xFF4 */
- u32 cell_id_2; /* I2C cell ID 2 0xFF8 */
- u32 cell_id_3; /* I2C cell ID 3 0xFFC */
-};
-
-
-/* Control Register */
-
-/* Mask values for control register mask */
-#define U8500_I2C_CR_PE 0x0001 /* Peripheral enable */
-#define U8500_I2C_CR_OM 0x0006 /* Operation mode */
-#define U8500_I2C_CR_SAM 0x0008 /* Slave Addressing mode */
-#define U8500_I2C_CR_SM 0x0030 /* Speed mode */
-#define U8500_I2C_CR_SGCM 0x0040 /* Slave General call mode */
-#define U8500_I2C_CR_FTX 0x0080 /* Flush Transmit */
-#define U8500_I2C_CR_FRX 0x0100 /* Flush Receive */
-#define U8500_I2C_CR_DMA_TX_EN 0x0200 /* DMA TX Enable */
-#define U8500_I2C_CR_DMA_RX_EN 0x0400 /* DMA Rx Enable */
-#define U8500_I2C_CR_DMA_SLE 0x0800 /* DMA Synchronization Logic enable */
-#define U8500_I2C_CR_LM 0x1000 /* Loop back mode */
-#define U8500_I2C_CR_FON 0x6000 /* Filtering On */
-
-/* shift valus for control register bit fields */
-#define U8500_I2C_CR_SHIFT_PE 0 /* Peripheral enable */
-#define U8500_I2C_CR_SHIFT_OM 1 /* Operation mode */
-#define U8500_I2C_CR_SHIFT_SAM 3 /* Slave Addressing mode */
-#define U8500_I2C_CR_SHIFT_SM 4 /* Speed mode */
-#define U8500_I2C_CR_SHIFT_SGCM 6 /* Slave General call mode */
-#define U8500_I2C_CR_SHIFT_FTX 7 /* Flush Transmit */
-#define U8500_I2C_CR_SHIFT_FRX 8 /* Flush Receive */
-#define U8500_I2C_CR_SHIFT_DMA_TX_EN 9 /* DMA TX Enable */
-#define U8500_I2C_CR_SHIFT_DMA_RX_EN 10 /* DMA Rx Enable */
-#define U8500_I2C_CR_SHIFT_DMA_SLE 11 /* DMA Synch Logic enable */
-#define U8500_I2C_CR_SHIFT_LM 12 /* Loop back mode */
-#define U8500_I2C_CR_SHIFT_FON 13 /* Filtering On */
-
-/* bus operation modes */
-#define U8500_I2C_BUS_SLAVE_MODE 0
-#define U8500_I2C_BUS_MASTER_MODE 1
-#define U8500_I2C_BUS_MASTER_SLAVE_MODE 2
-
-
-/* Slave control register*/
-
-/* Mask values slave control register */
-#define U8500_I2C_SCR_ADDR 0x3FF
-#define U8500_I2C_SCR_DATA_SETUP_TIME 0xFFFF0000
-
-/* Shift values for Slave control register */
-#define U8500_I2C_SCR_SHIFT_ADDR 0
-#define U8500_I2C_SCR_SHIFT_DATA_SETUP_TIME 16
-
-
-/* Master Control Register */
-
-/* Mask values for Master control register */
-#define U8500_I2C_MCR_OP 0x00000001 /* Operation */
-#define U8500_I2C_MCR_A7 0x000000FE /* LSB bits of Address */
-#define U8500_I2C_MCR_EA10 0x00000700 /* Extended Address */
-#define U8500_I2C_MCR_SB 0x00000800 /* Start byte procedure */
-#define U8500_I2C_MCR_AM 0x00003000 /* Address type */
-#define U8500_I2C_MCR_STOP 0x00004000 /* stop condition */
-#define U8500_I2C_MCR_LENGTH 0x03FF8000 /* Frame length */
-#define U8500_I2C_MCR_A10 0x000007FE /* Enable 10 bit address */
-/* mask for length field,stop and operation */
-#define U8500_I2C_MCR_LENGTH_STOP_OP 0x3FFC001
-
-/* Shift values for Master control values */
-#define U8500_I2C_MCR_SHIFT_OP 0 /* Operation */
-#define U8500_I2C_MCR_SHIFT_A7 1 /* LSB bits of Address */
-#define U8500_I2C_MCR_SHIFT_EA10 8 /* Extended Address */
-#define U8500_I2C_MCR_SHIFT_SB 11 /* Start byte procedure */
-#define U8500_I2C_MCR_SHIFT_AM 12 /* Address type */
-#define U8500_I2C_MCR_SHIFT_STOP 14 /* stop condition */
-#define U8500_I2C_MCR_SHIFT_LENGTH 15 /* Frame length */
-#define U8500_I2C_MCR_SHIFT_A10 1 /* Enable 10 bit address */
-
-#define U8500_I2C_MCR_SHIFT_LENGTH_STOP_OP 0
-
-
-/* Status Register */
-
-/* Mask values for Status register */
-#define U8500_I2C_SR_OP 0x00000003 /* Operation */
-#define U8500_I2C_SR_STATUS 0x0000000C /* Controller Status */
-#define U8500_I2C_SR_CAUSE 0x00000070 /* Abort Cause */
-#define U8500_I2C_SR_TYPE 0x00000180 /* Receive Type */
-#define U8500_I2C_SR_LENGTH 0x000FF700 /* Transfer length */
-
-/* Shift values for Status register */
-#define U8500_I2C_SR_SHIFT_OP 0 /* Operation */
-#define U8500_I2C_SR_SHIFT_STATUS 2 /* Controller Status */
-#define U8500_I2C_SR_SHIFT_CAUSE 4 /* Abort Cause */
-#define U8500_I2C_SR_SHIFT_TYPE 7 /* Receive Type */
-#define U8500_I2C_SR_SHIFT_LENGTH 9 /* Transfer length */
-
-/* abort cause */
-#define U8500_I2C_NACK_ADDR 0
-#define U8500_I2C_NACK_DATA 1
-#define U8500_I2C_ACK_MCODE 2
-#define U8500_I2C_ARB_LOST 3
-#define U8500_I2C_BERR_START 4
-#define U8500_I2C_BERR_STOP 5
-#define U8500_I2C_OVFL 6
-
-
-/* Baud rate counter registers */
-
-/* Mask values for Baud rate counter register */
-#define U8500_I2C_BRCR_BRCNT2 0xFFFF /* Baud Rate Cntr BRCR for HS */
-#define U8500_I2C_BRCR_BRCNT1 0xFFFF0000 /* BRCR for Standard and Fast */
-
-/* Shift values for the Baud rate counter register */
-#define U8500_I2C_BRCR_SHIFT_BRCNT2 0
-#define U8500_I2C_BRCR_SHIFT_BRCNT1 16
-
-
-/* Interrupt Register */
-
-/* Mask values for Interrupt registers */
-#define U8500_I2C_INT_TXFE 0x00000001 /* Tx fifo empty */
-#define U8500_I2C_INT_TXFNE 0x00000002 /* Tx Fifo nearly empty */
-#define U8500_I2C_INT_TXFF 0x00000004 /* Tx Fifo Full */
-#define U8500_I2C_INT_TXFOVR 0x00000008 /* Tx Fifo over run */
-#define U8500_I2C_INT_RXFE 0x00000010 /* Rx Fifo Empty */
-#define U8500_I2C_INT_RXFNF 0x00000020 /* Rx Fifo nearly empty */
-#define U8500_I2C_INT_RXFF 0x00000040 /* Rx Fifo Full */
-#define U8500_I2C_INT_RFSR 0x00010000 /* Read From slave request */
-#define U8500_I2C_INT_RFSE 0x00020000 /* Read from slave empty */
-#define U8500_I2C_INT_WTSR 0x00040000 /* Write to Slave request */
-#define U8500_I2C_INT_MTD 0x00080000 /* Master Transcation Done*/
-#define U8500_I2C_INT_STD 0x00100000 /* Slave Transaction Done */
-#define U8500_I2C_INT_MAL 0x01000000 /* Master Arbitation Lost */
-#define U8500_I2C_INT_BERR 0x02000000 /* Bus Error */
-#define U8500_I2C_INT_MTDWS 0x10000000 /* Master Tran Done wo/ Stop */
-
-/* Max clocks (Hz) */
-#define U8500_I2C_MAX_STANDARD_SCL 100000
-#define U8500_I2C_MAX_FAST_SCL 400000
-#define U8500_I2C_MAX_HIGH_SPEED_SCL 3400000
-
-#endif /* _U8500_I2C_H_ */
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f29a169774..8b38a84de6 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -59,7 +59,7 @@ config CROS_EC_SPI
provides a faster and more robust interface than I2C but the bugs
are less interesting.
-config CONFIG_FSL_SEC_MON
+config FSL_SEC_MON
bool "Enable FSL SEC_MON Driver"
help
Freescale Security Monitor block is responsible for monitoring
diff --git a/drivers/misc/reset_sandbox.c b/drivers/misc/reset_sandbox.c
index 917121bc5e..2691bb031a 100644
--- a/drivers/misc/reset_sandbox.c
+++ b/drivers/misc/reset_sandbox.c
@@ -40,7 +40,7 @@ static int sandbox_reset_request(struct udevice *dev, enum reset_t type)
* (see the U_BOOT_DEVICE() declaration below) should not do anything.
* If we are that device, return an error.
*/
- if (gd->fdt_blob && dev->of_offset == -1)
+ if (state->fdt_fname && dev->of_offset == -1)
return -ENODEV;
switch (type) {
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 1117fedefe..26d34ae5cc 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <errno.h>
#include <malloc.h>
+#include <memalign.h>
#include <mmc.h>
#include <dwmmc.h>
#include <asm-generic/errno.h>
@@ -213,7 +214,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
if (data) {
start = get_timer(0);
- timeout = 1000;
+ timeout = 240000;
for (;;) {
mask = dwmci_readl(host, DWMCI_RINTSTS);
/* Error during data transfer. */
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 371c1ec212..2a58702848 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -16,6 +16,7 @@
#include <mmc.h>
#include <part.h>
#include <malloc.h>
+#include <memalign.h>
#include <linux/list.h>
#include <div64.h>
#include "mmc_private.h"
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index 9d0b8bc0c8..1c6888fc48 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -10,6 +10,7 @@
#include <config.h>
#include <common.h>
+#include <memalign.h>
#include <mmc.h>
#include <u-boot/sha256.h>
#include "mmc_private.h"
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 25f18adb67..e717c44216 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -120,17 +120,27 @@ static int mmc_set_mod_clk(struct sunxi_mmc_host *mmchost, unsigned int hz)
/* determine delays */
if (hz <= 400000) {
oclk_dly = 0;
- sclk_dly = 7;
+ sclk_dly = 0;
} else if (hz <= 25000000) {
oclk_dly = 0;
sclk_dly = 5;
+#ifdef CONFIG_MACH_SUN9I
} else if (hz <= 50000000) {
- oclk_dly = 3;
- sclk_dly = 5;
+ oclk_dly = 5;
+ sclk_dly = 4;
} else {
/* hz > 50000000 */
oclk_dly = 2;
sclk_dly = 4;
+#else
+ } else if (hz <= 50000000) {
+ oclk_dly = 3;
+ sclk_dly = 4;
+ } else {
+ /* hz > 50000000 */
+ oclk_dly = 1;
+ sclk_dly = 4;
+#endif
}
writel(CCM_MMC_CTRL_ENABLE | pll | CCM_MMC_CTRL_SCLK_DLY(sclk_dly) |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 71c1a519e9..b4e5376176 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -60,7 +60,6 @@ obj-$(CONFIG_NAND_VF610_NFC) += vf610_nfc.o
obj-$(CONFIG_NAND_MXC) += mxc_nand.o
obj-$(CONFIG_NAND_MXS) += mxs_nand.o
obj-$(CONFIG_NAND_NDFC) += ndfc.o
-obj-$(CONFIG_NAND_NOMADIK) += nomadik.o
obj-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o
obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
obj-$(CONFIG_NAND_SPEAR) += spr_nand.o
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 567eff0914..e0e9e1ebd0 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -390,6 +390,55 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
+#ifndef CONFIG_SPL_BUILD
+/*
+ * fsmc_nand_switch_ecc - switch the ECC operation between different engines
+ *
+ * @eccstrength - the number of bits that could be corrected
+ * (1 - HW, 4 - SW BCH4)
+ */
+int fsmc_nand_switch_ecc(uint32_t eccstrength)
+{
+ struct nand_chip *nand;
+ struct mtd_info *mtd;
+ int err;
+
+ /*
+ * This functions is only called on SPEAr600 platforms, supporting
+ * 1 bit HW ECC. The BCH8 HW ECC (FSMC_VER8) from the ST-Ericsson
+ * Nomadik SoC is currently supporting this fsmc_nand_switch_ecc()
+ * function, as it doesn't need to switch to a different ECC layout.
+ */
+ mtd = &nand_info[nand_curr_device];
+ nand = mtd->priv;
+
+ /* Setup the ecc configurations again */
+ if (eccstrength == 1) {
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.bytes = 3;
+ nand->ecc.strength = 1;
+ nand->ecc.layout = &fsmc_ecc1_layout;
+ nand->ecc.calculate = fsmc_read_hwecc;
+ nand->ecc.correct = nand_correct_data;
+ } else if (eccstrength == 4) {
+ /*
+ * .calculate .correct and .bytes will be set in
+ * nand_scan_tail()
+ */
+ nand->ecc.mode = NAND_ECC_SOFT_BCH;
+ nand->ecc.strength = 4;
+ nand->ecc.layout = NULL;
+ } else {
+ printf("Error: ECC strength %d not supported!\n", eccstrength);
+ }
+
+ /* Update NAND handling after ECC mode switch */
+ err = nand_scan_tail(mtd);
+
+ return err;
+}
+#endif /* CONFIG_SPL_BUILD */
+
int fsmc_nand_init(struct nand_chip *nand)
{
static int chip_nr;
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 7a62cc3361..abcedc2102 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -16,7 +16,6 @@
#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
-#define BIT(x) (1 << (x))
#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
#define JZ_NAND_ECC_CTRL_RS BIT(2)
#define JZ_NAND_ECC_CTRL_RESET BIT(1)
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 1d689015a5..f15cf36c88 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -149,6 +149,13 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
uint32_t page_oob_size)
{
int ecc_strength;
+ int max_ecc_strength_supported;
+
+ /* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */
+ if (is_cpu_type(MXC_CPU_MX6SX))
+ max_ecc_strength_supported = 62;
+ else
+ max_ecc_strength_supported = 40;
/*
* Determine the ECC layout with the formula:
@@ -162,7 +169,7 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
/ (galois_field *
mxs_nand_ecc_chunk_cnt(page_data_size));
- return round_down(ecc_strength, 2);
+ return min(round_down(ecc_strength, 2), max_ecc_strength_supported);
}
static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 21b4a618ce..71285b6669 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -23,6 +23,7 @@
#include <command.h>
#include <watchdog.h>
#include <malloc.h>
+#include <memalign.h>
#include <div64.h>
#include <asm/errno.h>
diff --git a/drivers/mtd/nand/nomadik.c b/drivers/mtd/nand/nomadik.c
deleted file mode 100644
index a7cee5138d..0000000000
--- a/drivers/mtd/nand/nomadik.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * (C) Copyright 2007 STMicroelectronics, <www.st.com>
- * (C) Copyright 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <asm/io.h>
-
-static inline int parity(int b) /* b is really a byte; returns 0 or ~0 */
-{
- __asm__ __volatile__(
- "eor %0, %0, %0, lsr #4\n\t"
- "eor %0, %0, %0, lsr #2\n\t"
- "eor %0, %0, %0, lsr #1\n\t"
- "ands %0, %0, #1\n\t"
- "subne %0, %0, #2\t"
- : "=r" (b) : "0" (b));
- return b;
-}
-
-/*
- * This is the ECC routine used in hardware, according to the manual.
- * HW claims to make the calculation but not the correction; so we must
- * recalculate the bytes for a comparison.
- */
-static int ecc512(const unsigned char *data, unsigned char *ecc)
-{
- int gpar = 0;
- int i, val, par;
- int pbits = 0; /* P8, P16, ... P2048 */
- int pprime = 0; /* P8', P16', ... P2048' */
- int lowbits; /* P1, P2, P4 and primes */
-
- for (i = 0; i < 512; i++) {
- par = parity((val = data[i]));
- gpar ^= val;
- pbits ^= (i & par);
- }
- /*
- * Ok, now gpar is global parity (xor of all bytes)
- * pbits are all the parity bits (non-prime ones)
- */
- par = parity(gpar);
- pprime = pbits ^ par;
- /* Put low bits in the right position for ecc[2] (bits 7..2) */
- lowbits = 0
- | (parity(gpar & 0xf0) & 0x80) /* P4 */
- | (parity(gpar & 0x0f) & 0x40) /* P4' */
- | (parity(gpar & 0xcc) & 0x20) /* P2 */
- | (parity(gpar & 0x33) & 0x10) /* P2' */
- | (parity(gpar & 0xaa) & 0x08) /* P1 */
- | (parity(gpar & 0x55) & 0x04); /* P1' */
-
- ecc[2] = ~(lowbits | ((pbits & 0x100) >> 7) | ((pprime & 0x100) >> 8));
- /* now intermix bits for ecc[1] (P1024..P128') and ecc[0] (P64..P8') */
- ecc[1] = ~( (pbits & 0x80) >> 0 | ((pprime & 0x80) >> 1)
- | ((pbits & 0x40) >> 1) | ((pprime & 0x40) >> 2)
- | ((pbits & 0x20) >> 2) | ((pprime & 0x20) >> 3)
- | ((pbits & 0x10) >> 3) | ((pprime & 0x10) >> 4));
-
- ecc[0] = ~( (pbits & 0x8) << 4 | ((pprime & 0x8) << 3)
- | ((pbits & 0x4) << 3) | ((pprime & 0x4) << 2)
- | ((pbits & 0x2) << 2) | ((pprime & 0x2) << 1)
- | ((pbits & 0x1) << 1) | ((pprime & 0x1) << 0));
- return 0;
-}
-
-/* This is the method in the chip->ecc field */
-static int nomadik_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code)
-{
- return ecc512(dat, ecc_code);
-}
-
-static int nomadik_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
- uint8_t *r_ecc, uint8_t *c_ecc)
-{
- struct nand_chip *chip = mtd->priv;
- uint32_t r, c, d, diff; /*read, calculated, xor of them */
-
- if (!memcmp(r_ecc, c_ecc, chip->ecc.bytes))
- return 0;
-
- /* Reorder the bytes into ascending-order 24 bits -- see manual */
- r = r_ecc[2] << 22 | r_ecc[1] << 14 | r_ecc[0] << 6 | r_ecc[2] >> 2;
- c = c_ecc[2] << 22 | c_ecc[1] << 14 | c_ecc[0] << 6 | c_ecc[2] >> 2;
- diff = (r ^ c) & ((1<<24)-1); /* use 24 bits only */
-
- /* If 12 bits are different, one per pair, it's correctable */
- if (((diff | (diff>>1)) & 0x555555) == 0x555555) {
- int bit = ((diff & 2) >> 1)
- | ((diff & 0x8) >> 2) | ((diff & 0x20) >> 3);
- int byte;
-
- d = diff >> 6; /* remove bit-order info */
- byte = ((d & 2) >> 1)
- | ((d & 0x8) >> 2) | ((d & 0x20) >> 3)
- | ((d & 0x80) >> 4) | ((d & 0x200) >> 5)
- | ((d & 0x800) >> 6) | ((d & 0x2000) >> 7)
- | ((d & 0x8000) >> 8) | ((d & 0x20000) >> 9);
- /* correct the single bit */
- dat[byte] ^= 1<<bit;
- return 0;
- }
- /* If 1 bit only differs, it's one bit error in ECC, ignore */
- if ((diff ^ (1 << (ffs(diff) - 1))) == 0)
- return 0;
- /* Otherwise, uncorrectable */
- return -1;
-}
-
-static void nomadik_ecc_hwctl(struct mtd_info *mtd, int mode)
-{ /* mandatory in the structure but not used here */ }
-
-
-/* This is the layout used by older installations, we keep compatible */
-struct nand_ecclayout nomadik_ecc_layout = {
- .eccbytes = 3 * 4,
- .eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */
- 0x02, 0x03, 0x04,
- 0x12, 0x13, 0x14,
- 0x22, 0x23, 0x24,
- 0x32, 0x33, 0x34},
- .oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} },
-};
-
-#define MASK_ALE (1 << 24) /* our ALE is AD21 */
-#define MASK_CLE (1 << 23) /* our CLE is AD22 */
-
-/* This is copied from the AT91SAM9 devices (Stelian Pop, Lead Tech Design) */
-static void nomadik_nand_hwcontrol(struct mtd_info *mtd,
- int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- u32 pcr0 = readl(REG_FSMC_PCR0);
-
- if (ctrl & NAND_CTRL_CHANGE) {
- ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
- IO_ADDR_W &= ~(MASK_ALE | MASK_CLE);
-
- if (ctrl & NAND_CLE)
- IO_ADDR_W |= MASK_CLE;
- if (ctrl & NAND_ALE)
- IO_ADDR_W |= MASK_ALE;
-
- if (ctrl & NAND_NCE)
- writel(pcr0 | 0x4, REG_FSMC_PCR0);
- else
- writel(pcr0 & ~0x4, REG_FSMC_PCR0);
-
- this->IO_ADDR_W = (void *) IO_ADDR_W;
- this->IO_ADDR_R = (void *) IO_ADDR_W;
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-/* Returns 1 when ready; upper layers timeout at 20ms with timer routines */
-static int nomadik_nand_ready(struct mtd_info *mtd)
-{
- return 1; /* The ready bit is handled in hardware */
-}
-
-/* Copy a buffer 32bits at a time: faster than defualt method which is 8bit */
-static void nomadik_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *chip = mtd->priv;
- u32 *p = (u32 *) buf;
-
- len >>= 2;
- writel(0, REG_FSMC_ECCR0);
- for (i = 0; i < len; i++)
- p[i] = readl(chip->IO_ADDR_R);
-}
-
-int board_nand_init(struct nand_chip *chip)
-{
- /* Set up the FSMC_PCR0 for nand access*/
- writel(0x0000004a, REG_FSMC_PCR0);
- /* Set up FSMC_PMEM0, FSMC_PATT0 with timing data for access */
- writel(0x00020401, REG_FSMC_PMEM0);
- writel(0x00020404, REG_FSMC_PATT0);
-
- chip->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
- chip->cmd_ctrl = nomadik_nand_hwcontrol;
- chip->dev_ready = nomadik_nand_ready;
- /* The chip allows 32bit reads, so avoid the default 8bit copy */
- chip->read_buf = nomadik_nand_read_buf;
-
- /* ECC: follow the hardware-defined rulse, but do it in sw */
- chip->ecc.mode = NAND_ECC_HW;
- chip->ecc.bytes = 3;
- chip->ecc.size = 512;
- chip->ecc.strength = 1;
- chip->ecc.layout = &nomadik_ecc_layout;
- chip->ecc.calculate = nomadik_ecc_calculate;
- chip->ecc.hwctl = nomadik_ecc_hwctl;
- chip->ecc.correct = nomadik_ecc_correct;
-
- return 0;
-}
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 4372988ed2..4814fa202a 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -558,10 +558,10 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
bit_pos = error_loc[count] % 8;
if (byte_pos < SECTOR_BYTES) {
dat[byte_pos] ^= 1 << bit_pos;
- printf("nand: bit-flip corrected @data=%d\n", byte_pos);
+ debug("nand: bit-flip corrected @data=%d\n", byte_pos);
} else if (byte_pos < error_max) {
read_ecc[byte_pos - SECTOR_BYTES] ^= 1 << bit_pos;
- printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
+ debug("nand: bit-flip corrected @oob=%d\n", byte_pos -
SECTOR_BYTES);
} else {
err = -EBADMSG;
@@ -663,7 +663,7 @@ static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
/* correct data only, not ecc bytes */
if (errloc[i] < 8*512)
data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
- printf("corrected bitflip %u\n", errloc[i]);
+ debug("corrected bitflip %u\n", errloc[i]);
#ifdef DEBUG
puts("read_ecc: ");
/*
diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c
index bf9b1b1450..b0e07aa2d0 100644
--- a/drivers/mtd/nand/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/sunxi_nand_spl.c
@@ -321,6 +321,7 @@ static int nand_read_buffer(uint32_t offs, unsigned int size, void *dest,
{ 8192, 40, 1024, 5 },
{ 16384, 56, 1024, 5 },
{ 8192, 24, 1024, 5 },
+ { 4096, 24, 1024, 5 },
};
static int nand_config = -1;
int i;
@@ -355,18 +356,32 @@ static int nand_read_buffer(uint32_t offs, unsigned int size, void *dest,
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
{
+#if CONFIG_SYS_NAND_U_BOOT_OFFS == CONFIG_SPL_PAD_TO
+ /*
+ * u-boot-dtb.bin appended to SPL, use syndrome (like the BROM does)
+ * and try different erase block sizes to find the backup.
+ */
const uint32_t boot_offsets[] = {
0 * 1024 * 1024 + CONFIG_SYS_NAND_U_BOOT_OFFS,
1 * 1024 * 1024 + CONFIG_SYS_NAND_U_BOOT_OFFS,
2 * 1024 * 1024 + CONFIG_SYS_NAND_U_BOOT_OFFS,
4 * 1024 * 1024 + CONFIG_SYS_NAND_U_BOOT_OFFS,
};
- int i, syndrome;
-
- if (CONFIG_SYS_NAND_U_BOOT_OFFS == CONFIG_SPL_PAD_TO)
- syndrome = 1; /* u-boot-dtb.bin appended to SPL */
- else
- syndrome = 0; /* u-boot-dtb.bin on its own partition */
+ const int syndrome = 1;
+#else
+ /*
+ * u-boot-dtb.bin on its own partition, do not use syndrome, u-boot
+ * partition sits after 2 eraseblocks (spl, spl-backup), look for
+ * backup u-boot 1 erase block further.
+ */
+ const uint32_t eraseblock_size = CONFIG_SYS_NAND_U_BOOT_OFFS / 2;
+ const uint32_t boot_offsets[] = {
+ CONFIG_SYS_NAND_U_BOOT_OFFS,
+ CONFIG_SYS_NAND_U_BOOT_OFFS + eraseblock_size,
+ };
+ const int syndrome = 0;
+#endif
+ int i;
if (offs == CONFIG_SYS_NAND_U_BOOT_OFFS) {
for (i = 0; i < ARRAY_SIZE(boot_offsets); i++) {
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index debad4f791..a77db7b65d 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <asm/io.h>
+#include <memalign.h>
#include <nand.h>
#include <asm/arch/clock.h>
#include <asm/arch/funcmux.h>
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 4a4a3afc92..8f5bdda3d7 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -23,6 +23,7 @@ const struct spi_flash_params spi_flash_params_table[] = {
{"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K},
{"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K},
{"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K},
+ {"AT26DF081A", 0x1f4501, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K},
#endif
#ifdef CONFIG_SPI_FLASH_EON /* EON */
{"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, RD_NORM, 0},
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index ae78d21db6..6433896eec 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <miiphy.h>
#include <malloc.h>
+#include <pci.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <asm/io.h>
@@ -558,6 +559,22 @@ static int designware_eth_write_hwaddr(struct udevice *dev)
return _dw_write_hwaddr(priv, pdata->enetaddr);
}
+static int designware_eth_bind(struct udevice *dev)
+{
+#ifdef CONFIG_DM_PCI
+ static int num_cards;
+ char name[20];
+
+ /* Create a unique device name for PCI type devices */
+ if (device_is_on_pci_bus(dev)) {
+ sprintf(name, "eth_designware#%u", num_cards++);
+ device_set_name(dev, name);
+ }
+#endif
+
+ return 0;
+}
+
static int designware_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
@@ -565,6 +582,23 @@ static int designware_eth_probe(struct udevice *dev)
u32 iobase = pdata->iobase;
int ret;
+#ifdef CONFIG_DM_PCI
+ /*
+ * If we are on PCI bus, either directly attached to a PCI root port,
+ * or via a PCI bridge, fill in platdata before we probe the hardware.
+ */
+ if (device_is_on_pci_bus(dev)) {
+ pci_dev_t bdf = pci_get_bdf(dev);
+
+ dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
+ iobase &= PCI_BASE_ADDRESS_MEM_MASK;
+ iobase = pci_mem_to_phys(bdf, iobase);
+
+ pdata->iobase = iobase;
+ pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
+ }
+#endif
+
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
priv->mac_regs_p = (struct eth_mac_regs *)iobase;
priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@@ -617,10 +651,18 @@ U_BOOT_DRIVER(eth_designware) = {
.id = UCLASS_ETH,
.of_match = designware_eth_ids,
.ofdata_to_platdata = designware_eth_ofdata_to_platdata,
+ .bind = designware_eth_bind,
.probe = designware_eth_probe,
.ops = &designware_eth_ops,
.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
.platdata_auto_alloc_size = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
+
+static struct pci_device_id supported[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
+ { }
+};
+
+U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 7b830ff8c0..2ba03ed73e 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -32,6 +32,7 @@ tested on both gig copper and gig fiber boards
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <memalign.h>
#include <pci.h>
#include "e1000.h"
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index bff5fd1119..79f6737e8e 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <malloc.h>
+#include <memalign.h>
#include <net.h>
#include <netdev.h>
#include <miiphy.h>
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 31042a6b6b..bf972dc39b 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -170,7 +170,11 @@ int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
static void nc_send_packet(const char *buf, int len)
{
+#ifdef CONFIG_DM_ETH
+ struct udevice *eth;
+#else
struct eth_device *eth;
+#endif
int inited = 0;
uchar *pkt;
uchar *ether;
@@ -183,7 +187,7 @@ static void nc_send_packet(const char *buf, int len)
return;
if (!memcmp(nc_ether, net_null_ethaddr, 6)) {
- if (eth->state == ETH_STATE_ACTIVE)
+ if (eth_is_active(eth))
return; /* inside net loop */
output_packet = buf;
output_packet_len = len;
@@ -194,7 +198,7 @@ static void nc_send_packet(const char *buf, int len)
return;
}
- if (eth->state != ETH_STATE_ACTIVE) {
+ if (!eth_is_active(eth)) {
if (eth_is_on_demand_init()) {
if (eth_init() < 0)
return;
@@ -292,7 +296,11 @@ static int nc_stdio_getc(struct stdio_dev *dev)
static int nc_stdio_tstc(struct stdio_dev *dev)
{
+#ifdef CONFIG_DM_ETH
+ struct udevice *eth;
+#else
struct eth_device *eth;
+#endif
if (input_recursion)
return 0;
@@ -301,7 +309,7 @@ static int nc_stdio_tstc(struct stdio_dev *dev)
return 1;
eth = eth_get_dev();
- if (eth && eth->state == ETH_STATE_ACTIVE)
+ if (eth_is_active(eth))
return 0; /* inside net loop */
input_recursion = 1;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 65c731afb6..a6023f1033 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -571,7 +571,7 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
memset(dev, 0, sizeof(*dev));
dev->duplex = -1;
- dev->link = 1;
+ dev->link = 0;
dev->interface = interface;
dev->autoneg = AUTONEG_ENABLE;
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 7b6e20f30f..ebd46b27e5 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -44,6 +44,7 @@
#include <dm.h>
#include <errno.h>
#include <malloc.h>
+#include <memalign.h>
#include <net.h>
#ifndef CONFIG_DM_ETH
#include <netdev.h>
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index ade14cd475..f31216ffa6 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -499,15 +499,8 @@ again:
}
/* we have a packet address, so tell the card to use it */
-#ifndef CONFIG_XAENIAX
SMC_outb (dev, packet_no, PN_REG);
-#else
- /* On Xaeniax board, we can't use SMC_outb here because that way
- * the Allocate MMU command will end up written to the command register
- * as well, which will lead to a problem.
- */
- SMC_outl (dev, packet_no << 16, 0);
-#endif
+
/* do not write new ptr value if Write data fifo not empty */
while ( saved_ptr & PTR_NOTEMPTY )
printf ("Write data fifo not empty!\n");
@@ -542,39 +535,19 @@ again:
*/
#ifdef USE_32_BIT
SMC_outsl (dev, SMC91111_DATA_REG, buf, length >> 2);
-#ifndef CONFIG_XAENIAX
if (length & 0x2)
SMC_outw (dev, *((word *) (buf + (length & 0xFFFFFFFC))),
SMC91111_DATA_REG);
#else
- /* On XANEIAX, we can only use 32-bit writes, so we need to handle
- * unaligned tail part specially. The standard code doesn't work.
- */
- if ((length & 3) == 3) {
- u16 * ptr = (u16*) &buf[length-3];
- SMC_outl(dev, (*ptr) | ((0x2000 | buf[length-1]) << 16),
- SMC91111_DATA_REG);
- } else if ((length & 2) == 2) {
- u16 * ptr = (u16*) &buf[length-2];
- SMC_outl(dev, *ptr, SMC91111_DATA_REG);
- } else if (length & 1) {
- SMC_outl(dev, (0x2000 | buf[length-1]), SMC91111_DATA_REG);
- } else {
- SMC_outl(dev, 0, SMC91111_DATA_REG);
- }
-#endif
-#else
SMC_outsw (dev, SMC91111_DATA_REG, buf, (length) >> 1);
#endif /* USE_32_BIT */
-#ifndef CONFIG_XAENIAX
/* Send the last byte, if there is one. */
if ((length & 1) == 0) {
SMC_outw (dev, 0, SMC91111_DATA_REG);
} else {
SMC_outw (dev, buf[length - 1] | 0x2000, SMC91111_DATA_REG);
}
-#endif
/* and let the chipset deal with it */
SMC_outw (dev, MC_ENQUEUE, MMU_CMD_REG);
@@ -588,9 +561,6 @@ again:
/* release packet */
/* no need to release, MMU does that now */
-#ifdef CONFIG_XAENIAX
- SMC_outw (dev, MC_FREEPKT, MMU_CMD_REG);
-#endif
/* wait for MMU getting ready (low) */
while (SMC_inw (dev, MMU_CMD_REG) & MC_BUSY) {
@@ -610,9 +580,6 @@ again:
/* release packet */
/* no need to release, MMU does that now */
-#ifdef CONFIG_XAENIAX
- SMC_outw (dev, MC_FREEPKT, MMU_CMD_REG);
-#endif
/* wait for MMU getting ready (low) */
while (SMC_inw (dev, MMU_CMD_REG) & MC_BUSY) {
@@ -625,15 +592,7 @@ again:
}
/* restore previously saved registers */
-#ifndef CONFIG_XAENIAX
SMC_outb( dev, saved_pnr, PN_REG );
-#else
- /* On Xaeniax board, we can't use SMC_outb here because that way
- * the Allocate MMU command will end up written to the command register
- * as well, which will lead to a problem.
- */
- SMC_outl(dev, saved_pnr << 16, 0);
-#endif
SMC_outw( dev, saved_ptr, PTR_REG );
return length;
@@ -802,15 +761,7 @@ static int smc_rcv(struct eth_device *dev)
udelay(1); /* Wait until not busy */
/* restore saved registers */
-#ifndef CONFIG_XAENIAX
SMC_outb( dev, saved_pnr, PN_REG );
-#else
- /* On Xaeniax board, we can't use SMC_outb here because that way
- * the Allocate MMU command will end up written to the command register
- * as well, which will lead to a problem.
- */
- SMC_outl( dev, saved_pnr << 16, 0);
-#endif
SMC_outw( dev, saved_ptr, PTR_REG );
if (!is_error) {
diff --git a/drivers/net/smc91111.h b/drivers/net/smc91111.h
index e19c491cbc..5197f36039 100644
--- a/drivers/net/smc91111.h
+++ b/drivers/net/smc91111.h
@@ -77,19 +77,6 @@ struct smc91111_priv{
if (__p & 2) __v >>= 8; \
else __v &= 0xff; \
__v; })
-#elif defined(CONFIG_XAENIAX)
-#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r))))
-#define SMC_inw(a,z) ({ \
- unsigned int __p = (unsigned int)((a)->iobase + (z)); \
- unsigned int __v = *(volatile unsigned int *)((__p) & ~3); \
- if (__p & 3) __v >>= 16; \
- else __v &= 0xffff; \
- __v; })
-#define SMC_inb(a,p) ({ \
- unsigned int ___v = SMC_inw((a),(p) & ~1); \
- if ((p) & 1) ___v >>= 8; \
- else ___v &= 0xff; \
- ___v; })
#else
#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r))))
#define SMC_inw(a,r) (*((volatile word *)((a)->iobase+(r))))
@@ -104,15 +91,6 @@ struct smc91111_priv{
#ifdef CONFIG_XSENGINE
#define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r<<1))) = d)
#define SMC_outw(a,d,r) (*((volatile word *)((a)->iobase+(r<<1))) = d)
-#elif defined (CONFIG_XAENIAX)
-#define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r))) = d)
-#define SMC_outw(a,d,p) ({ \
- dword __dwo = SMC_inl((a),(p) & ~3); \
- dword __dwn = (word)(d); \
- __dwo &= ((p) & 3) ? 0x0000ffff : 0xffff0000; \
- __dwo |= ((p) & 3) ? __dwn << 16 : __dwn; \
- SMC_outl((a), __dwo, (p) & ~3); \
-})
#else
#define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r))) = d)
#define SMC_outw(a,d,r) (*((volatile word *)((a)->iobase+(r))) = d)
diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c
index fed7358448..7595db1acb 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*
@@ -10,7 +10,11 @@
#include <asm/fsl_serdes.h>
#include <fm_eth.h>
#include <fsl_memac.h>
+#include <bitfield.h>
+#include <errno.h>
+#include <malloc.h>
#include <vsc9953.h>
+#include <ethsw.h>
static struct vsc9953_info vsc9953_l2sw = {
.port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
@@ -25,50 +29,50 @@ static struct vsc9953_info vsc9953_l2sw = {
.port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
};
-void vsc9953_port_info_set_mdio(int port, struct mii_dev *bus)
+void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
{
- if (!VSC9953_PORT_CHECK(port))
+ if (!VSC9953_PORT_CHECK(port_no))
return;
- vsc9953_l2sw.port[port].bus = bus;
+ vsc9953_l2sw.port[port_no].bus = bus;
}
-void vsc9953_port_info_set_phy_address(int port, int address)
+void vsc9953_port_info_set_phy_address(int port_no, int address)
{
- if (!VSC9953_PORT_CHECK(port))
+ if (!VSC9953_PORT_CHECK(port_no))
return;
- vsc9953_l2sw.port[port].phyaddr = address;
+ vsc9953_l2sw.port[port_no].phyaddr = address;
}
-void vsc9953_port_info_set_phy_int(int port, phy_interface_t phy_int)
+void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
{
- if (!VSC9953_PORT_CHECK(port))
+ if (!VSC9953_PORT_CHECK(port_no))
return;
- vsc9953_l2sw.port[port].enet_if = phy_int;
+ vsc9953_l2sw.port[port_no].enet_if = phy_int;
}
-void vsc9953_port_enable(int port)
+void vsc9953_port_enable(int port_no)
{
- if (!VSC9953_PORT_CHECK(port))
+ if (!VSC9953_PORT_CHECK(port_no))
return;
- vsc9953_l2sw.port[port].enabled = 1;
+ vsc9953_l2sw.port[port_no].enabled = 1;
}
-void vsc9953_port_disable(int port)
+void vsc9953_port_disable(int port_no)
{
- if (!VSC9953_PORT_CHECK(port))
+ if (!VSC9953_PORT_CHECK(port_no))
return;
- vsc9953_l2sw.port[port].enabled = 0;
+ vsc9953_l2sw.port[port_no].enabled = 0;
}
static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
int regnum, int value)
{
- int timeout = 50000;
+ int timeout = 50000;
out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
@@ -85,8 +89,8 @@ static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
int regnum)
{
- int value = 0xFFFF;
- int timeout = 50000;
+ int value = 0xFFFF;
+ int timeout = 50000;
while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
udelay(1);
@@ -120,8 +124,8 @@ static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
static int init_phy(struct eth_device *dev)
{
- struct vsc9953_port_info *l2sw_port = dev->priv;
- struct phy_device *phydev = NULL;
+ struct vsc9953_port_info *l2sw_port = dev->priv;
+ struct phy_device *phydev = NULL;
#ifdef CONFIG_PHYLIB
if (!l2sw_port->bus)
@@ -148,21 +152,21 @@ static int init_phy(struct eth_device *dev)
return 0;
}
-static int vsc9953_port_init(int port)
+static int vsc9953_port_init(int port_no)
{
- struct eth_device *dev;
+ struct eth_device *dev;
/* Internal ports never have a PHY */
- if (VSC9953_INTERNAL_PORT_CHECK(port))
+ if (VSC9953_INTERNAL_PORT_CHECK(port_no))
return 0;
/* alloc eth device */
dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
if (!dev)
- return 1;
+ return -ENOMEM;
- sprintf(dev->name, "SW@PORT%d", port);
- dev->priv = &vsc9953_l2sw.port[port];
+ sprintf(dev->name, "SW@PORT%d", port_no);
+ dev->priv = &vsc9953_l2sw.port[port_no];
dev->init = NULL;
dev->halt = NULL;
dev->send = NULL;
@@ -170,225 +174,485 @@ static int vsc9953_port_init(int port)
if (init_phy(dev)) {
free(dev);
- return 1;
+ return -ENODEV;
}
return 0;
}
-void vsc9953_init(bd_t *bis)
+static int vsc9953_vlan_table_poll_idle(void)
{
- u32 i, hdx_cfg = 0, phy_addr = 0;
- int timeout;
- struct vsc9953_system_reg *l2sys_reg;
- struct vsc9953_qsys_reg *l2qsys_reg;
- struct vsc9953_dev_gmii *l2dev_gmii_reg;
- struct vsc9953_analyzer *l2ana_reg;
- struct vsc9953_devcpu_gcb *l2dev_gcb;
+ struct vsc9953_analyzer *l2ana_reg;
+ int timeout;
- l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
- VSC9953_DEV_GMII_OFFSET);
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ timeout = 50000;
+ while (((in_le32(&l2ana_reg->ana_tables.vlan_access) &
+ VSC9953_VLAN_CMD_MASK) != VSC9953_VLAN_CMD_IDLE) && --timeout)
+ udelay(1);
+
+ return timeout ? 0 : -EBUSY;
+}
+
+#ifdef CONFIG_CMD_ETHSW
+/* Add/remove a port to/from a VLAN */
+static void vsc9953_vlan_table_membership_set(int vid, u32 port_no, u8 add)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
VSC9953_ANA_OFFSET);
- l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
- VSC9953_SYS_OFFSET);
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
+ }
- l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
- VSC9953_QSYS_OFFSET);
+ val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
+ val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
+ out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
- l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
- VSC9953_DEVCPU_GCB);
+ clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
+ VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
- out_le32(&l2dev_gcb->chip_regs.soft_rst,
- CONFIG_VSC9953_SOFT_SWC_RST_ENA);
- timeout = 50000;
- while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
- CONFIG_VSC9953_SOFT_SWC_RST_ENA) && --timeout)
- udelay(1); /* busy wait for vsc9953 soft reset */
- if (timeout == 0)
- debug("Timeout waiting for VSC9953 to reset\n");
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
+ }
- out_le32(&l2sys_reg->sys.reset_cfg, CONFIG_VSC9953_MEM_ENABLE |
- CONFIG_VSC9953_MEM_INIT);
+ val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
+ val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid);
+ out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
+
+ val = in_le32(&l2ana_reg->ana_tables.vlan_access);
+ if (!add) {
+ val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
+ VSC9953_VLAN_CMD_WRITE) &
+ ~(bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
+ (1 << port_no)));
+ ;
+ } else {
+ val = bitfield_replace_by_mask(val, VSC9953_VLAN_CMD_MASK,
+ VSC9953_VLAN_CMD_WRITE) |
+ bitfield_replace_by_mask(0, VSC9953_VLAN_PORT_MASK,
+ (1 << port_no));
+ }
+ out_le32(&l2ana_reg->ana_tables.vlan_access, val);
- timeout = 50000;
- while ((in_le32(&l2sys_reg->sys.reset_cfg) &
- CONFIG_VSC9953_MEM_INIT) && --timeout)
- udelay(1); /* busy wait for vsc9953 memory init */
- if (timeout == 0)
- debug("Timeout waiting for VSC9953 memory to initialize\n");
+ /* wait for VLAN table command to flush */
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
+ }
+}
- out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
- | CONFIG_VSC9953_CORE_ENABLE));
+/* show VLAN membership for a port */
+static void vsc9953_vlan_membership_show(int port_no)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+ u32 vid;
- /* VSC9953 Setting to be done once only */
- out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
- for (i = 0; i < VSC9953_MAX_PORTS; i++) {
- if (vsc9953_port_init(i))
- printf("Failed to initialize l2switch port %d\n", i);
+ printf("Port %d VLAN membership: ", port_no);
- /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
- if (VSC9953_INTERNAL_PORT_CHECK(i)) {
- out_le32(&l2ana_reg->pfc[i].pfc_cfg,
- CONFIG_VSC9953_PFC_FC_QSGMII);
- out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
- CONFIG_VSC9953_MAC_FC_CFG_QSGMII);
- } else {
- out_le32(&l2ana_reg->pfc[i].pfc_cfg,
- CONFIG_VSC9953_PFC_FC);
- out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
- CONFIG_VSC9953_MAC_FC_CFG);
+ for (vid = 0; vid < VSC9953_MAX_VLAN; vid++) {
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
}
- out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
- CONFIG_VSC9953_CLOCK_CFG);
- out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
- CONFIG_VSC9953_MAC_ENA_CFG);
- out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
- CONFIG_VSC9953_MAC_MODE_CFG);
- out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
- CONFIG_VSC9953_MAC_IFG_CFG);
- /* mac_hdx_cfg varies with port id*/
- hdx_cfg = (CONFIG_VSC9953_MAC_HDX_CFG | (i << 16));
- out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
- out_le32(&l2sys_reg->sys.front_port_mode[i],
- CONFIG_VSC9953_FRONT_PORT_MODE);
- out_le32(&l2qsys_reg->sys.switch_port_mode[i],
- CONFIG_VSC9953_PORT_ENA);
- out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
- CONFIG_VSC9953_MAC_MAX_LEN);
- out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
- CONFIG_VSC9953_PAUSE_CFG);
- /* WAIT FOR 2 us*/
- udelay(2);
- l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(
- (char *)l2dev_gmii_reg
- + T1040_SWITCH_GMII_DEV_OFFSET);
+ val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
+ val = bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK,
+ vid);
+ out_le32(&l2ana_reg->ana_tables.vlan_tidx, val);
- /* Initialize Lynx PHY Wrappers */
- phy_addr = 0;
- if (vsc9953_l2sw.port[i].enet_if ==
- PHY_INTERFACE_MODE_QSGMII)
- phy_addr = (i + 0x4) & 0x1F;
- else if (vsc9953_l2sw.port[i].enet_if ==
- PHY_INTERFACE_MODE_SGMII)
- phy_addr = (i + 1) & 0x1F;
-
- if (phy_addr) {
- /* SGMII IF mode + AN enable */
- vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
- 0x14, PHY_SGMII_IF_MODE_AN |
- PHY_SGMII_IF_MODE_SGMII);
- /* Dev ability according to SGMII specification */
- vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
- 0x4, PHY_SGMII_DEV_ABILITY_SGMII);
- /* Adjust link timer for SGMII
- * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
- */
- vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
- 0x13, 0x0003);
- vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
- 0x12, 0x0d40);
- /* Restart AN */
- vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
- 0x0, PHY_SGMII_CR_DEF_VAL |
- PHY_SGMII_CR_RESET_AN);
+ clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
+ VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
- timeout = 50000;
- while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
- phy_addr, 0x01) & 0x0020) && --timeout)
- udelay(1); /* wait for AN to complete */
- if (timeout == 0)
- debug("Timeout waiting for AN to complete\n");
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
}
+
+ val = in_le32(&l2ana_reg->ana_tables.vlan_access);
+
+ if (bitfield_extract_by_mask(val, VSC9953_VLAN_PORT_MASK) &
+ (1 << port_no))
+ printf("%d ", vid);
}
+ printf("\n");
+}
+#endif
- printf("VSC9953 L2 switch initialized\n");
- return;
+/* vlan table set/clear all membership of vid */
+static void vsc9953_vlan_table_membership_all_set(int vid, int set_member)
+{
+ uint val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
+ }
+
+ /* read current vlan configuration */
+ val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
+ out_le32(&l2ana_reg->ana_tables.vlan_tidx,
+ bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
+
+ clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
+ VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
+
+ if (vsc9953_vlan_table_poll_idle() < 0) {
+ debug("VLAN table timeout\n");
+ return;
+ }
+
+ val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
+ out_le32(&l2ana_reg->ana_tables.vlan_tidx,
+ bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
+
+ clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
+ VSC9953_VLAN_PORT_MASK | VSC9953_VLAN_CMD_MASK,
+ VSC9953_VLAN_CMD_WRITE |
+ (set_member ? VSC9953_VLAN_PORT_MASK : 0));
}
-#ifdef CONFIG_VSC9953_CMD
-/* Enable/disable status of a VSC9953 port */
-static void vsc9953_port_status_set(int port_nr, u8 enabled)
+#ifdef CONFIG_CMD_ETHSW
+/* Get PVID of a VSC9953 port */
+static int vsc9953_port_vlan_pvid_get(int port_nr, int *pvid)
{
- u32 val;
- struct vsc9953_qsys_reg *l2qsys_reg;
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
/* Administrative down */
- if (vsc9953_l2sw.port[port_nr].enabled == 0)
+ if (vsc9953_l2sw.port[port_nr].enabled) {
+ printf("Port %d is administrative down\n", port_nr);
+ return -1;
+ }
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ /* Get ingress PVID */
+ val = in_le32(&l2ana_reg->port[port_nr].vlan_cfg);
+ *pvid = bitfield_extract_by_mask(val, VSC9953_VLAN_CFG_VID_MASK);
+
+ return 0;
+}
+#endif
+
+/* Set PVID for a VSC9953 port */
+static void vsc9953_port_vlan_pvid_set(int port_no, int pvid)
+{
+ uint val;
+ struct vsc9953_analyzer *l2ana_reg;
+ struct vsc9953_rew_reg *l2rew_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
return;
+ }
- l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
- VSC9953_QSYS_OFFSET);
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+ l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
+ VSC9953_REW_OFFSET);
+
+ /* Set PVID on ingress */
+ val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
+ val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_VID_MASK, pvid);
+ out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
+
+ /* Set PVID on egress */
+ val = in_le32(&l2rew_reg->port[port_no].port_vlan_cfg);
+ val = bitfield_replace_by_mask(val, VSC9953_PORT_VLAN_CFG_VID_MASK,
+ pvid);
+ out_le32(&l2rew_reg->port[port_no].port_vlan_cfg, val);
+}
+
+static void vsc9953_port_all_vlan_pvid_set(int pvid)
+{
+ int i;
+
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_vlan_pvid_set(i, pvid);
+}
+
+/* Enable/disable vlan aware of a VSC9953 port */
+static void vsc9953_port_vlan_aware_set(int port_no, int enabled)
+{
+ struct vsc9953_analyzer *l2ana_reg;
- val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_nr]);
- if (enabled == 1)
- val |= (1 << 13);
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ if (enabled)
+ setbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
+ VSC9953_VLAN_CFG_AWARE_ENA);
else
- val &= ~(1 << 13);
+ clrbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
+ VSC9953_VLAN_CFG_AWARE_ENA);
+}
+
+/* Set all VSC9953 ports' vlan aware */
+static void vsc9953_port_all_vlan_aware_set(int enabled)
+{
+ int i;
- out_le32(&l2qsys_reg->sys.switch_port_mode[port_nr], val);
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_vlan_aware_set(i, enabled);
}
-/* Set all VSC9953 ports' status */
-static void vsc9953_port_all_status_set(u8 enabled)
+/* Enable/disable vlan pop count of a VSC9953 port */
+static void vsc9953_port_vlan_popcnt_set(int port_no, int popcnt)
{
- int i;
+ uint val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ if (popcnt > 3 || popcnt < 0) {
+ printf("Invalid pop count value: %d\n", port_no);
+ return;
+ }
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
+ val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_POP_CNT_MASK,
+ popcnt);
+ out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
+}
+
+/* Set all VSC9953 ports' pop count */
+static void vsc9953_port_all_vlan_poncnt_set(int popcnt)
+{
+ int i;
for (i = 0; i < VSC9953_MAX_PORTS; i++)
- vsc9953_port_status_set(i, enabled);
+ vsc9953_port_vlan_popcnt_set(i, popcnt);
}
-/* Start autonegotiation for a VSC9953 PHY */
-static void vsc9953_phy_autoneg(int port_nr)
+/* Enable/disable learning for frames dropped due to ingress filtering */
+static void vsc9953_vlan_ingr_fltr_learn_drop(int enable)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ if (enable)
+ setbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
+ else
+ clrbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
+}
+
+/* Egress untag modes of a VSC9953 port */
+enum egress_untag_mode {
+ EGRESS_UNTAG_ALL = 0,
+ EGRESS_UNTAG_PVID_AND_ZERO,
+ EGRESS_UNTAG_ZERO,
+ EGRESS_UNTAG_NONE,
+};
+
+#ifdef CONFIG_CMD_ETHSW
+/* Get egress tagging configuration for a VSC9953 port */
+static int vsc9953_port_vlan_egr_untag_get(int port_no,
+ enum egress_untag_mode *mode)
{
- if (!vsc9953_l2sw.port[port_nr].phydev)
+ u32 val;
+ struct vsc9953_rew_reg *l2rew_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return -1;
+ }
+
+ l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
+ VSC9953_REW_OFFSET);
+
+ val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
+
+ switch (val & VSC9953_TAG_CFG_MASK) {
+ case VSC9953_TAG_CFG_NONE:
+ *mode = EGRESS_UNTAG_ALL;
+ return 0;
+ case VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO:
+ *mode = EGRESS_UNTAG_PVID_AND_ZERO;
+ return 0;
+ case VSC9953_TAG_CFG_ALL_BUT_ZERO:
+ *mode = EGRESS_UNTAG_ZERO;
+ return 0;
+ case VSC9953_TAG_CFG_ALL:
+ *mode = EGRESS_UNTAG_NONE;
+ return 0;
+ default:
+ printf("Unknown egress tagging configuration for port %d\n",
+ port_no);
+ return -1;
+ }
+}
+
+/* Show egress tagging configuration for a VSC9953 port */
+static void vsc9953_port_vlan_egr_untag_show(int port_no)
+{
+ enum egress_untag_mode mode;
+
+ if (vsc9953_port_vlan_egr_untag_get(port_no, &mode)) {
+ printf("%7d\t%17s\n", port_no, "-");
return;
+ }
- if (vsc9953_l2sw.port[port_nr].phydev->drv->startup(
- vsc9953_l2sw.port[port_nr].phydev))
- printf("Failed to start PHY for port %d\n", port_nr);
+ printf("%7d\t", port_no);
+ switch (mode) {
+ case EGRESS_UNTAG_ALL:
+ printf("%17s\n", "all");
+ break;
+ case EGRESS_UNTAG_NONE:
+ printf("%17s\n", "none");
+ break;
+ case EGRESS_UNTAG_PVID_AND_ZERO:
+ printf("%17s\n", "PVID and 0");
+ break;
+ case EGRESS_UNTAG_ZERO:
+ printf("%17s\n", "0");
+ break;
+ default:
+ printf("%17s\n", "-");
+ }
}
+#endif
-/* Start autonegotiation for all VSC9953 PHYs */
-static void vsc9953_phy_all_autoneg(void)
+static void vsc9953_port_vlan_egr_untag_set(int port_no,
+ enum egress_untag_mode mode)
{
- int i;
+ struct vsc9953_rew_reg *l2rew_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
+ VSC9953_REW_OFFSET);
+
+ switch (mode) {
+ case EGRESS_UNTAG_ALL:
+ clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_NONE);
+ break;
+ case EGRESS_UNTAG_PVID_AND_ZERO:
+ clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_CFG_MASK,
+ VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO);
+ break;
+ case EGRESS_UNTAG_ZERO:
+ clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_CFG_MASK,
+ VSC9953_TAG_CFG_ALL_BUT_ZERO);
+ break;
+ case EGRESS_UNTAG_NONE:
+ clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_ALL);
+ break;
+ default:
+ printf("Unknown untag mode for port %d\n", port_no);
+ }
+}
+
+static void vsc9953_port_all_vlan_egress_untagged_set(
+ enum egress_untag_mode mode)
+{
+ int i;
for (i = 0; i < VSC9953_MAX_PORTS; i++)
- vsc9953_phy_autoneg(i);
+ vsc9953_port_vlan_egr_untag_set(i, mode);
+}
+
+#ifdef CONFIG_CMD_ETHSW
+
+/* Enable/disable status of a VSC9953 port */
+static void vsc9953_port_status_set(int port_no, u8 enabled)
+{
+ struct vsc9953_qsys_reg *l2qsys_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled)
+ return;
+
+ l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
+ VSC9953_QSYS_OFFSET);
+
+ if (enabled)
+ setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
+ VSC9953_PORT_ENA);
+ else
+ clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
+ VSC9953_PORT_ENA);
+}
+
+/* Start autonegotiation for a VSC9953 PHY */
+static void vsc9953_phy_autoneg(int port_no)
+{
+ if (!vsc9953_l2sw.port[port_no].phydev)
+ return;
+
+ if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
+ vsc9953_l2sw.port[port_no].phydev))
+ printf("Failed to start PHY for port %d\n", port_no);
}
/* Print a VSC9953 port's configuration */
-static void vsc9953_port_config_show(int port)
+static void vsc9953_port_config_show(int port_no)
{
- int speed;
- int duplex;
- int link;
- u8 enabled;
- u32 val;
- struct vsc9953_qsys_reg *l2qsys_reg;
+ int speed;
+ int duplex;
+ int link;
+ u8 enabled;
+ u32 val;
+ struct vsc9953_qsys_reg *l2qsys_reg;
l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
VSC9953_QSYS_OFFSET);
- val = in_le32(&l2qsys_reg->sys.switch_port_mode[port]);
- enabled = vsc9953_l2sw.port[port].enabled &
- ((val & 0x00002000) >> 13);
+ val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
+ enabled = vsc9953_l2sw.port[port_no].enabled &&
+ (val & VSC9953_PORT_ENA);
/* internal ports (8 and 9) are fixed */
- if (VSC9953_INTERNAL_PORT_CHECK(port)) {
+ if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
link = 1;
speed = SPEED_2500;
duplex = DUPLEX_FULL;
} else {
- if (vsc9953_l2sw.port[port].phydev) {
- link = vsc9953_l2sw.port[port].phydev->link;
- speed = vsc9953_l2sw.port[port].phydev->speed;
- duplex = vsc9953_l2sw.port[port].phydev->duplex;
+ if (vsc9953_l2sw.port[port_no].phydev) {
+ link = vsc9953_l2sw.port[port_no].phydev->link;
+ speed = vsc9953_l2sw.port[port_no].phydev->speed;
+ duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
} else {
link = -1;
speed = -1;
@@ -396,7 +660,7 @@ static void vsc9953_port_config_show(int port)
}
}
- printf("%8d ", port);
+ printf("%8d ", port_no);
printf("%8s ", enabled == 1 ? "enabled" : "disabled");
printf("%8s ", link == 1 ? "up" : "down");
@@ -423,75 +687,1575 @@ static void vsc9953_port_config_show(int port)
printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
}
-/* Print VSC9953 ports' configuration */
-static void vsc9953_port_all_config_show(void)
+/* Show VSC9953 ports' statistics */
+static void vsc9953_port_statistics_show(int port_no)
{
- int i;
+ u32 rx_val;
+ u32 tx_val;
+ struct vsc9953_system_reg *l2sys_reg;
- for (i = 0; i < VSC9953_MAX_PORTS; i++)
- vsc9953_port_config_show(i);
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
+ VSC9953_SYS_OFFSET);
+
+ printf("Statistics for L2 Switch port %d:\n", port_no);
+
+ /* Set counter view for our port */
+ out_le32(&l2sys_reg->sys.stat_cfg, port_no);
+
+#define VSC9953_STATS_PRINTF "%-15s %10u"
+
+ /* Get number of Rx and Tx frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx frames:", rx_val, "Tx frames:", tx_val);
+
+ /* Get number of Rx and Tx bytes */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_oct);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_oct);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx bytes:", rx_val, "Tx bytes:", tx_val);
+
+ /* Get number of Rx frames received ok and Tx frames sent ok */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_0) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_1) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_2) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_3) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_4) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_5) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_6) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_yellow_prio_7) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_0) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_1) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_2) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_3) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_4) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_5) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_6) +
+ in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_green_prio_7);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx frames ok:", rx_val, "Tx frames ok:", tx_val);
+
+ /* Get number of Rx and Tx unicast frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_uc);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_uc);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx unicast:", rx_val, "Tx unicast:", tx_val);
+
+ /* Get number of Rx and Tx broadcast frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_bc);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_bc);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx broadcast:", rx_val, "Tx broadcast:", tx_val);
+
+ /* Get number of Rx and Tx frames of 64B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_64);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_64);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 64B:", rx_val, "Tx 64B:", tx_val);
+
+ /* Get number of Rx and Tx frames with sizes between 65B and 127B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_65_127);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_65_127);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 65B-127B:", rx_val, "Tx 65B-127B:", tx_val);
+
+ /* Get number of Rx and Tx frames with sizes between 128B and 255B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_128_255);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_128_255);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 128B-255B:", rx_val, "Tx 128B-255B:", tx_val);
+
+ /* Get number of Rx and Tx frames with sizes between 256B and 511B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_256_511);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_256_511);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 256B-511B:", rx_val, "Tx 256B-511B:", tx_val);
+
+ /* Get number of Rx and Tx frames with sizes between 512B and 1023B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_512_1023);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_512_1023);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 512B-1023B:", rx_val, "Tx 512B-1023B:", tx_val);
+
+ /* Get number of Rx and Tx frames with sizes between 1024B and 1526B */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_1024_1526);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_1024_1526);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx 1024B-1526B:", rx_val, "Tx 1024B-1526B:", tx_val);
+
+ /* Get number of Rx and Tx jumbo frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_sz_jumbo);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_sz_jumbo);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx jumbo:", rx_val, "Tx jumbo:", tx_val);
+
+ /* Get number of Rx and Tx dropped frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_tail) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_0) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_1) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_2) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_3) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_4) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_5) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_6) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_yellow_prio_7) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_0) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_1) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_2) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_3) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_4) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_5) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_6) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_green_prio_7);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_drop) +
+ in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx drops:", rx_val, "Tx drops:", tx_val);
+
+ /*
+ * Get number of Rx frames with CRC or alignment errors
+ * and number of detected Tx collisions
+ */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_crc);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_col);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx CRC&align:", rx_val, "Tx coll:", tx_val);
+
+ /*
+ * Get number of Rx undersized frames and
+ * number of Tx aged frames
+ */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_short);
+ tx_val = in_le32(&l2sys_reg->stat.tx_cntrs.c_tx_aged);
+ printf(VSC9953_STATS_PRINTF"\t\t"VSC9953_STATS_PRINTF"\n",
+ "Rx undersize:", rx_val, "Tx aged:", tx_val);
+
+ /* Get number of Rx oversized frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_long);
+ printf(VSC9953_STATS_PRINTF"\n", "Rx oversized:", rx_val);
+
+ /* Get number of Rx fragmented frames */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_frag);
+ printf(VSC9953_STATS_PRINTF"\n", "Rx fragments:", rx_val);
+
+ /* Get number of Rx jabber errors */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_jabber);
+ printf(VSC9953_STATS_PRINTF"\n", "Rx jabbers:", rx_val);
+
+ /*
+ * Get number of Rx frames filtered due to classification rules or
+ * no destination ports
+ */
+ rx_val = in_le32(&l2sys_reg->stat.rx_cntrs.c_rx_cat_drop) +
+ in_le32(&l2sys_reg->stat.drop_cntrs.c_dr_local);
+ printf(VSC9953_STATS_PRINTF"\n", "Rx filtered:", rx_val);
+
+ printf("\n");
}
-/* function to interpret commands starting with "ethsw " */
-static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+/* Clear statistics for a VSC9953 port */
+static void vsc9953_port_statistics_clear(int port_no)
{
- u8 enable;
- u32 port;
+ struct vsc9953_system_reg *l2sys_reg;
- if (argc < 4)
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
+ VSC9953_SYS_OFFSET);
+
+ /* Clear all counter groups for our ports */
+ out_le32(&l2sys_reg->sys.stat_cfg, port_no |
+ VSC9953_STAT_CLEAR_RX | VSC9953_STAT_CLEAR_TX |
+ VSC9953_STAT_CLEAR_DR);
+}
+
+enum port_learn_mode {
+ PORT_LEARN_NONE,
+ PORT_LEARN_AUTO
+};
+
+/* Set learning configuration for a VSC9953 port */
+static void vsc9953_port_learn_mode_set(int port_no, enum port_learn_mode mode)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
+ return;
+ }
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ switch (mode) {
+ case PORT_LEARN_NONE:
+ clrbits_le32(&l2ana_reg->port[port_no].port_cfg,
+ VSC9953_PORT_CFG_LEARN_DROP |
+ VSC9953_PORT_CFG_LEARN_CPU |
+ VSC9953_PORT_CFG_LEARN_AUTO |
+ VSC9953_PORT_CFG_LEARN_ENA);
+ break;
+ case PORT_LEARN_AUTO:
+ clrsetbits_le32(&l2ana_reg->port[port_no].port_cfg,
+ VSC9953_PORT_CFG_LEARN_DROP |
+ VSC9953_PORT_CFG_LEARN_CPU,
+ VSC9953_PORT_CFG_LEARN_ENA |
+ VSC9953_PORT_CFG_LEARN_AUTO);
+ break;
+ default:
+ printf("Unknown learn mode for port %d\n", port_no);
+ }
+}
+
+/* Get learning configuration for a VSC9953 port */
+static int vsc9953_port_learn_mode_get(int port_no, enum port_learn_mode *mode)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ /* Administrative down */
+ if (!vsc9953_l2sw.port[port_no].enabled) {
+ printf("Port %d is administrative down\n", port_no);
return -1;
+ }
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ /* For now we only support HW learning (auto) and no learning */
+ val = in_le32(&l2ana_reg->port[port_no].port_cfg);
+ if ((val & (VSC9953_PORT_CFG_LEARN_ENA |
+ VSC9953_PORT_CFG_LEARN_AUTO)) ==
+ (VSC9953_PORT_CFG_LEARN_ENA | VSC9953_PORT_CFG_LEARN_AUTO))
+ *mode = PORT_LEARN_AUTO;
+ else
+ *mode = PORT_LEARN_NONE;
+
+ return 0;
+}
- if (strcmp(argv[1], "port"))
+/* wait for FDB to become available */
+static int vsc9953_mac_table_poll_idle(void)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+ u32 timeout;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ timeout = 50000;
+ while (((in_le32(&l2ana_reg->ana_tables.mac_access) &
+ VSC9953_MAC_CMD_MASK) !=
+ VSC9953_MAC_CMD_IDLE) && --timeout)
+ udelay(1);
+
+ return timeout ? 0 : -EBUSY;
+}
+
+/* enum describing available commands for the MAC table */
+enum mac_table_cmd {
+ MAC_TABLE_READ,
+ MAC_TABLE_LOOKUP,
+ MAC_TABLE_WRITE,
+ MAC_TABLE_LEARN,
+ MAC_TABLE_FORGET,
+ MAC_TABLE_GET_NEXT,
+ MAC_TABLE_AGE,
+};
+
+/* Issues a command to the FDB table */
+static int vsc9953_mac_table_cmd(enum mac_table_cmd cmd)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ switch (cmd) {
+ case MAC_TABLE_READ:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK | VSC9953_MAC_CMD_VALID,
+ VSC9953_MAC_CMD_READ);
+ break;
+ case MAC_TABLE_LOOKUP:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK, VSC9953_MAC_CMD_READ |
+ VSC9953_MAC_CMD_VALID);
+ break;
+ case MAC_TABLE_WRITE:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK |
+ VSC9953_MAC_ENTRYTYPE_MASK,
+ VSC9953_MAC_CMD_WRITE |
+ VSC9953_MAC_ENTRYTYPE_LOCKED);
+ break;
+ case MAC_TABLE_LEARN:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK |
+ VSC9953_MAC_ENTRYTYPE_MASK,
+ VSC9953_MAC_CMD_LEARN |
+ VSC9953_MAC_ENTRYTYPE_LOCKED |
+ VSC9953_MAC_CMD_VALID);
+ break;
+ case MAC_TABLE_FORGET:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK |
+ VSC9953_MAC_ENTRYTYPE_MASK,
+ VSC9953_MAC_CMD_FORGET);
+ break;
+ case MAC_TABLE_GET_NEXT:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK |
+ VSC9953_MAC_ENTRYTYPE_MASK,
+ VSC9953_MAC_CMD_NEXT);
+ break;
+ case MAC_TABLE_AGE:
+ clrsetbits_le32(&l2ana_reg->ana_tables.mac_access,
+ VSC9953_MAC_CMD_MASK |
+ VSC9953_MAC_ENTRYTYPE_MASK,
+ VSC9953_MAC_CMD_AGE);
+ break;
+ default:
+ printf("Unknown MAC table command\n");
+ }
+
+ if (vsc9953_mac_table_poll_idle() < 0) {
+ debug("MAC table timeout\n");
return -1;
+ }
- if (!strcmp(argv[3], "show")) {
- if (!strcmp(argv[2], "all")) {
- vsc9953_phy_all_autoneg();
- printf("%8s %8s %8s %8s %8s\n",
- "Port", "Status", "Link", "Speed",
- "Duplex");
- vsc9953_port_all_config_show();
- return 0;
- } else {
- port = simple_strtoul(argv[2], NULL, 10);
- if (!VSC9953_PORT_CHECK(port))
- return -1;
- vsc9953_phy_autoneg(port);
- printf("%8s %8s %8s %8s %8s\n",
- "Port", "Status", "Link", "Speed",
- "Duplex");
- vsc9953_port_config_show(port);
- return 0;
- }
- } else if (!strcmp(argv[3], "enable")) {
- enable = 1;
- } else if (!strcmp(argv[3], "disable")) {
- enable = 0;
+ return 0;
+}
+
+/* show the FDB entries that correspond to a port and a VLAN */
+static void vsc9953_mac_table_show(int port_no, int vid)
+{
+ int rc[VSC9953_MAX_PORTS];
+ enum port_learn_mode mode[VSC9953_MAX_PORTS];
+ int i;
+ u32 val;
+ u32 vlan;
+ u32 mach;
+ u32 macl;
+ u32 dest_indx;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ /* disable auto learning */
+ if (port_no == ETHSW_CMD_PORT_ALL) {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
+ if (!rc[i] && mode[i] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
+ }
+ } else {
+ rc[port_no] = vsc9953_port_learn_mode_get(port_no,
+ &mode[port_no]);
+ if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
+ }
+
+ /* write port and vid to get selected FDB entries */
+ val = in_le32(&l2ana_reg->ana.anag_efil);
+ if (port_no != ETHSW_CMD_PORT_ALL) {
+ val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
+ port_no) | VSC9953_AGE_PORT_EN;
+ }
+ if (vid != ETHSW_CMD_VLAN_ALL) {
+ val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK,
+ vid) | VSC9953_AGE_VID_EN;
+ }
+ out_le32(&l2ana_reg->ana.anag_efil, val);
+
+ /* set MAC and VLAN to 0 to look from beginning */
+ clrbits_le32(&l2ana_reg->ana_tables.mach_data,
+ VSC9953_MAC_VID_MASK | VSC9953_MAC_MACH_MASK);
+ out_le32(&l2ana_reg->ana_tables.macl_data, 0);
+
+ /* get entries */
+ printf("%10s %17s %5s %4s\n", "EntryType", "MAC", "PORT", "VID");
+ do {
+ if (vsc9953_mac_table_cmd(MAC_TABLE_GET_NEXT) < 0) {
+ debug("GET NEXT MAC table command failed\n");
+ break;
+ }
+
+ val = in_le32(&l2ana_reg->ana_tables.mac_access);
+
+ /* get out when an invalid entry is found */
+ if (!(val & VSC9953_MAC_CMD_VALID))
+ break;
+
+ switch (val & VSC9953_MAC_ENTRYTYPE_MASK) {
+ case VSC9953_MAC_ENTRYTYPE_NORMAL:
+ printf("%10s ", "Dynamic");
+ break;
+ case VSC9953_MAC_ENTRYTYPE_LOCKED:
+ printf("%10s ", "Static");
+ break;
+ case VSC9953_MAC_ENTRYTYPE_IPV4MCAST:
+ printf("%10s ", "IPv4 Mcast");
+ break;
+ case VSC9953_MAC_ENTRYTYPE_IPV6MCAST:
+ printf("%10s ", "IPv6 Mcast");
+ break;
+ default:
+ printf("%10s ", "Unknown");
+ }
+
+ dest_indx = bitfield_extract_by_mask(val,
+ VSC9953_MAC_DESTIDX_MASK);
+
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ vlan = bitfield_extract_by_mask(val, VSC9953_MAC_VID_MASK);
+ mach = bitfield_extract_by_mask(val, VSC9953_MAC_MACH_MASK);
+ macl = in_le32(&l2ana_reg->ana_tables.macl_data);
+
+ printf("%02x:%02x:%02x:%02x:%02x:%02x ", (mach >> 8) & 0xff,
+ mach & 0xff, (macl >> 24) & 0xff, (macl >> 16) & 0xff,
+ (macl >> 8) & 0xff, macl & 0xff);
+ printf("%5d ", dest_indx);
+ printf("%4d\n", vlan);
+ } while (1);
+
+ /* set learning mode to previous value */
+ if (port_no == ETHSW_CMD_PORT_ALL) {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ if (!rc[i] && mode[i] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(i, mode[i]);
+ }
} else {
+ /* If administrative down, skip */
+ if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(port_no, mode[port_no]);
+ }
+
+ /* reset FDB port and VLAN FDB selection */
+ clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
+ VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
+ VSC9953_AGE_VID_MASK);
+}
+
+/* Add a static FDB entry */
+static int vsc9953_mac_table_add(u8 port_no, uchar mac[6], int vid)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
+ (mac[0] << 8) | (mac[1] << 0);
+ out_le32(&l2ana_reg->ana_tables.mach_data, val);
+
+ out_le32(&l2ana_reg->ana_tables.macl_data,
+ (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
+ (mac[5] << 0));
+
+ /* set on which port is the MAC address added */
+ val = in_le32(&l2ana_reg->ana_tables.mac_access);
+ val = bitfield_replace_by_mask(val, VSC9953_MAC_DESTIDX_MASK, port_no);
+ out_le32(&l2ana_reg->ana_tables.mac_access, val);
+
+ if (vsc9953_mac_table_cmd(MAC_TABLE_LEARN) < 0)
+ return -1;
+
+ /* check if the MAC address was indeed added */
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
+ (mac[0] << 8) | (mac[1] << 0);
+ out_le32(&l2ana_reg->ana_tables.mach_data, val);
+
+ out_le32(&l2ana_reg->ana_tables.macl_data,
+ (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
+ (mac[5] << 0));
+
+ if (vsc9953_mac_table_cmd(MAC_TABLE_READ) < 0)
+ return -1;
+
+ val = in_le32(&l2ana_reg->ana_tables.mac_access);
+
+ if ((port_no != bitfield_extract_by_mask(val,
+ VSC9953_MAC_DESTIDX_MASK))) {
+ printf("Failed to add MAC address\n");
return -1;
}
+ return 0;
+}
- if (!strcmp(argv[2], "all")) {
- vsc9953_port_all_status_set(enable);
- return 0;
+/* Delete a FDB entry */
+static int vsc9953_mac_table_del(uchar mac[6], u16 vid)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ /* check first if MAC entry is present */
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
+ (mac[0] << 8) | (mac[1] << 0);
+ out_le32(&l2ana_reg->ana_tables.mach_data, val);
+
+ out_le32(&l2ana_reg->ana_tables.macl_data,
+ (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) |
+ (mac[5] << 0));
+
+ if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
+ debug("Lookup in the MAC table failed\n");
+ return -1;
+ }
+
+ if (!(in_le32(&l2ana_reg->ana_tables.mac_access) &
+ VSC9953_MAC_CMD_VALID)) {
+ printf("The MAC address: %02x:%02x:%02x:%02x:%02x:%02x ",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ printf("VLAN: %d does not exist.\n", vid);
+ return -1;
+ }
+
+ /* FDB entry found, proceed to delete */
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
+ (mac[0] << 8) | (mac[1] << 0);
+ out_le32(&l2ana_reg->ana_tables.mach_data, val);
+
+ out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
+ (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
+
+ if (vsc9953_mac_table_cmd(MAC_TABLE_FORGET) < 0)
+ return -1;
+
+ /* check if the MAC entry is still in FDB */
+ val = in_le32(&l2ana_reg->ana_tables.mach_data);
+ val = bitfield_replace_by_mask(val, VSC9953_MACHDATA_VID_MASK, vid) |
+ (mac[0] << 8) | (mac[1] << 0);
+ out_le32(&l2ana_reg->ana_tables.mach_data, val);
+
+ out_le32(&l2ana_reg->ana_tables.macl_data, (mac[2] << 24) |
+ (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0));
+
+ if (vsc9953_mac_table_cmd(MAC_TABLE_LOOKUP) < 0) {
+ debug("Lookup in the MAC table failed\n");
+ return -1;
+ }
+ if (in_le32(&l2ana_reg->ana_tables.mac_access) &
+ VSC9953_MAC_CMD_VALID) {
+ printf("Failed to delete MAC address\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* age the unlocked entries in FDB */
+static void vsc9953_mac_table_age(int port_no, int vid)
+{
+ int rc[VSC9953_MAX_PORTS];
+ enum port_learn_mode mode[VSC9953_MAX_PORTS];
+ u32 val;
+ int i;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ /* set port and VID for selective aging */
+ val = in_le32(&l2ana_reg->ana.anag_efil);
+ if (port_no != ETHSW_CMD_PORT_ALL) {
+ /* disable auto learning */
+ rc[port_no] = vsc9953_port_learn_mode_get(port_no,
+ &mode[port_no]);
+ if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(port_no, PORT_LEARN_NONE);
+
+ val = bitfield_replace_by_mask(val, VSC9953_AGE_PORT_MASK,
+ port_no) | VSC9953_AGE_PORT_EN;
} else {
- port = simple_strtoul(argv[2], NULL, 10);
- if (!VSC9953_PORT_CHECK(port))
- return -1;
- vsc9953_port_status_set(port, enable);
- return 0;
+ /* disable auto learning on all ports */
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ rc[i] = vsc9953_port_learn_mode_get(i, &mode[i]);
+ if (!rc[i] && mode[i] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(i, PORT_LEARN_NONE);
+ }
+ }
+
+ if (vid != ETHSW_CMD_VLAN_ALL) {
+ val = bitfield_replace_by_mask(val, VSC9953_AGE_VID_MASK, vid) |
+ VSC9953_AGE_VID_EN;
+ }
+ out_le32(&l2ana_reg->ana.anag_efil, val);
+
+ /* age the dynamic FDB entries */
+ vsc9953_mac_table_cmd(MAC_TABLE_AGE);
+
+ /* clear previously set port and VID */
+ clrbits_le32(&l2ana_reg->ana.anag_efil, VSC9953_AGE_PORT_EN |
+ VSC9953_AGE_PORT_MASK | VSC9953_AGE_VID_EN |
+ VSC9953_AGE_VID_MASK);
+
+ if (port_no != ETHSW_CMD_PORT_ALL) {
+ if (!rc[port_no] && mode[port_no] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(port_no, mode[port_no]);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ if (!rc[i] && mode[i] != PORT_LEARN_NONE)
+ vsc9953_port_learn_mode_set(i, mode[i]);
+ }
+ }
+}
+
+/* Delete all the dynamic FDB entries */
+static void vsc9953_mac_table_flush(int port, int vid)
+{
+ vsc9953_mac_table_age(port, vid);
+ vsc9953_mac_table_age(port, vid);
+}
+
+enum egress_vlan_tag {
+ EGR_TAG_CLASS = 0,
+ EGR_TAG_PVID,
+};
+
+/* Set egress tag mode for a VSC9953 port */
+static void vsc9953_port_vlan_egress_tag_set(int port_no,
+ enum egress_vlan_tag mode)
+{
+ struct vsc9953_rew_reg *l2rew_reg;
+
+ l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
+ VSC9953_REW_OFFSET);
+
+ switch (mode) {
+ case EGR_TAG_CLASS:
+ clrbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_VID_PVID);
+ break;
+ case EGR_TAG_PVID:
+ setbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
+ VSC9953_TAG_VID_PVID);
+ break;
+ default:
+ printf("Unknown egress VLAN tag mode for port %d\n", port_no);
}
+}
- return -1;
+/* Get egress tag mode for a VSC9953 port */
+static void vsc9953_port_vlan_egress_tag_get(int port_no,
+ enum egress_vlan_tag *mode)
+{
+ u32 val;
+ struct vsc9953_rew_reg *l2rew_reg;
+
+ l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
+ VSC9953_REW_OFFSET);
+
+ val = in_le32(&l2rew_reg->port[port_no].port_tag_cfg);
+ if (val & VSC9953_TAG_VID_PVID)
+ *mode = EGR_TAG_PVID;
+ else
+ *mode = EGR_TAG_CLASS;
}
-U_BOOT_CMD(ethsw, 5, 0, do_ethsw,
- "vsc9953 l2 switch commands",
- "port <port_nr> enable|disable\n"
- " - enable/disable an l2 switch port\n"
- " port_nr=0..9; use \"all\" for all ports\n"
- "ethsw port <port_nr> show\n"
- " - show an l2 switch port's configuration\n"
- " port_nr=0..9; use \"all\" for all ports\n"
-);
-#endif /* CONFIG_VSC9953_CMD */
+/* VSC9953 VLAN learning modes */
+enum vlan_learning_mode {
+ SHARED_VLAN_LEARNING,
+ PRIVATE_VLAN_LEARNING,
+};
+
+/* Set VLAN learning mode for VSC9953 */
+static void vsc9953_vlan_learning_set(enum vlan_learning_mode lrn_mode)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ switch (lrn_mode) {
+ case SHARED_VLAN_LEARNING:
+ setbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
+ break;
+ case PRIVATE_VLAN_LEARNING:
+ clrbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
+ break;
+ default:
+ printf("Unknown VLAN learn mode\n");
+ }
+}
+
+/* Get VLAN learning mode for VSC9953 */
+static int vsc9953_vlan_learning_get(enum vlan_learning_mode *lrn_mode)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ val = in_le32(&l2ana_reg->ana.agen_ctrl);
+
+ if (!(val & VSC9953_FID_MASK_ALL)) {
+ *lrn_mode = PRIVATE_VLAN_LEARNING;
+ } else if ((val & VSC9953_FID_MASK_ALL) == VSC9953_FID_MASK_ALL) {
+ *lrn_mode = SHARED_VLAN_LEARNING;
+ } else {
+ printf("Unknown VLAN learning mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Enable/disable VLAN ingress filtering on a VSC9953 port */
+static void vsc9953_port_ingress_filtering_set(int port_no, int enabled)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ if (enabled)
+ setbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
+ else
+ clrbits_le32(&l2ana_reg->ana.vlan_mask, 1 << port_no);
+}
+
+/* Return VLAN ingress filtering on a VSC9953 port */
+static int vsc9953_port_ingress_filtering_get(int port_no)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ val = in_le32(&l2ana_reg->ana.vlan_mask);
+ return !!(val & (1 << port_no));
+}
+
+static int vsc9953_port_status_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ u8 enabled;
+
+ /* Last keyword should tell us if we should enable/disable the port */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_enable)
+ enabled = 1;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_disable)
+ enabled = 0;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_status_set(parsed_cmd->port, enabled);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_status_set(i, enabled);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_port_config_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_phy_autoneg(parsed_cmd->port);
+ printf("%8s %8s %8s %8s %8s\n",
+ "Port", "Status", "Link", "Speed",
+ "Duplex");
+ vsc9953_port_config_show(parsed_cmd->port);
+
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_phy_autoneg(i);
+ printf("%8s %8s %8s %8s %8s\n",
+ "Port", "Status", "Link", "Speed", "Duplex");
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_config_show(i);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_port_stats_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_statistics_show(parsed_cmd->port);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_statistics_show(i);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_port_stats_clear_key_func(struct ethsw_command_def
+ *parsed_cmd)
+{
+ int i;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_statistics_clear(parsed_cmd->port);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_statistics_clear(i);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_learn_show_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ enum port_learn_mode mode;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ if (vsc9953_port_learn_mode_get(parsed_cmd->port, &mode))
+ return CMD_RET_FAILURE;
+ printf("%7s %11s\n", "Port", "Learn mode");
+ switch (mode) {
+ case PORT_LEARN_NONE:
+ printf("%7d %11s\n", parsed_cmd->port, "disable");
+ break;
+ case PORT_LEARN_AUTO:
+ printf("%7d %11s\n", parsed_cmd->port, "auto");
+ break;
+ default:
+ printf("%7d %11s\n", parsed_cmd->port, "-");
+ }
+ } else {
+ printf("%7s %11s\n", "Port", "Learn mode");
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ if (vsc9953_port_learn_mode_get(i, &mode))
+ continue;
+ switch (mode) {
+ case PORT_LEARN_NONE:
+ printf("%7d %11s\n", i, "disable");
+ break;
+ case PORT_LEARN_AUTO:
+ printf("%7d %11s\n", i, "auto");
+ break;
+ default:
+ printf("%7d %11s\n", i, "-");
+ }
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ enum port_learn_mode mode;
+
+ /* Last keyword should tell us the learn mode */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_auto)
+ mode = PORT_LEARN_AUTO;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_disable)
+ mode = PORT_LEARN_NONE;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_learn_mode_set(parsed_cmd->port, mode);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_learn_mode_set(i, mode);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_fdb_show_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
+ !VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+
+ if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
+ !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
+ printf("Invalid VID number: %d\n", parsed_cmd->vid);
+ return CMD_RET_FAILURE;
+ }
+
+ vsc9953_mac_table_show(parsed_cmd->port, parsed_cmd->vid);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_fdb_flush_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL &&
+ !VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+
+ if (parsed_cmd->vid != ETHSW_CMD_VLAN_ALL &&
+ !VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
+ printf("Invalid VID number: %d\n", parsed_cmd->vid);
+ return CMD_RET_FAILURE;
+ }
+
+ vsc9953_mac_table_flush(parsed_cmd->port, parsed_cmd->vid);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_fdb_entry_add_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int vid;
+
+ /* a port number must be present */
+ if (parsed_cmd->port == ETHSW_CMD_PORT_ALL) {
+ printf("Please specify a port\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+
+ /* Use VLAN 1 if VID is not set */
+ vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
+
+ if (!VSC9953_VLAN_CHECK(vid)) {
+ printf("Invalid VID number: %d\n", vid);
+ return CMD_RET_FAILURE;
+ }
+
+ if (vsc9953_mac_table_add(parsed_cmd->port, parsed_cmd->ethaddr, vid))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_fdb_entry_del_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int vid;
+
+ /* Use VLAN 1 if VID is not set */
+ vid = (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL ? 1 : parsed_cmd->vid);
+
+ if (!VSC9953_VLAN_CHECK(vid)) {
+ printf("Invalid VID number: %d\n", vid);
+ return CMD_RET_FAILURE;
+ }
+
+ if (vsc9953_mac_table_del(parsed_cmd->ethaddr, vid))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_pvid_show_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ int pvid;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+
+ if (vsc9953_port_vlan_pvid_get(parsed_cmd->port, &pvid))
+ return CMD_RET_FAILURE;
+ printf("%7s %7s\n", "Port", "PVID");
+ printf("%7d %7d\n", parsed_cmd->port, pvid);
+ } else {
+ printf("%7s %7s\n", "Port", "PVID");
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ if (vsc9953_port_vlan_pvid_get(i, &pvid))
+ continue;
+ printf("%7d %7d\n", i, pvid);
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_pvid_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ /* PVID number should be set in parsed_cmd->vid */
+ if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
+ printf("Please set a pvid value\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
+ printf("Invalid VID number: %d\n", parsed_cmd->vid);
+ return CMD_RET_FAILURE;
+ }
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_vlan_pvid_set(parsed_cmd->port, parsed_cmd->vid);
+ } else {
+ vsc9953_port_all_vlan_pvid_set(parsed_cmd->vid);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_vlan_show_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_vlan_membership_show(parsed_cmd->port);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_vlan_membership_show(i);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_vlan_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ int add;
+
+ /* VLAN should be set in parsed_cmd->vid */
+ if (parsed_cmd->vid == ETHSW_CMD_VLAN_ALL) {
+ printf("Please set a vlan value\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!VSC9953_VLAN_CHECK(parsed_cmd->vid)) {
+ printf("Invalid VID number: %d\n", parsed_cmd->vid);
+ return CMD_RET_FAILURE;
+ }
+
+ /* keywords add/delete should be the last but one in array */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
+ ethsw_id_add)
+ add = 1;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 2] ==
+ ethsw_id_del)
+ add = 0;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_vlan_table_membership_set(parsed_cmd->vid,
+ parsed_cmd->port, add);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_vlan_table_membership_set(parsed_cmd->vid, i,
+ add);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+static int vsc9953_port_untag_show_key_func(
+ struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+
+ printf("%7s\t%17s\n", "Port", "Untag");
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_vlan_egr_untag_show(parsed_cmd->port);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_vlan_egr_untag_show(i);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_port_untag_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ enum egress_untag_mode mode;
+
+ /* keywords for the untagged mode are the last in the array */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_all)
+ mode = EGRESS_UNTAG_ALL;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_none)
+ mode = EGRESS_UNTAG_NONE;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_pvid)
+ mode = EGRESS_UNTAG_PVID_AND_ZERO;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_vlan_egr_untag_set(parsed_cmd->port, mode);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_vlan_egr_untag_set(i, mode);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_egr_vlan_tag_show_key_func(
+ struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ enum egress_vlan_tag mode;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_vlan_egress_tag_get(parsed_cmd->port, &mode);
+ printf("%7s\t%12s\n", "Port", "Egress VID");
+ printf("%7d\t", parsed_cmd->port);
+ switch (mode) {
+ case EGR_TAG_CLASS:
+ printf("%12s\n", "classified");
+ break;
+ case EGR_TAG_PVID:
+ printf("%12s\n", "pvid");
+ break;
+ default:
+ printf("%12s\n", "-");
+ }
+ } else {
+ printf("%7s\t%12s\n", "Port", "Egress VID");
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ vsc9953_port_vlan_egress_tag_get(i, &mode);
+ switch (mode) {
+ case EGR_TAG_CLASS:
+ printf("%7d\t%12s\n", i, "classified");
+ break;
+ case EGR_TAG_PVID:
+ printf("%7d\t%12s\n", i, "pvid");
+ break;
+ default:
+ printf("%7d\t%12s\n", i, "-");
+ }
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_egr_vlan_tag_set_key_func(
+ struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ enum egress_vlan_tag mode;
+
+ /* keywords for the egress vlan tag mode are the last in the array */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_pvid)
+ mode = EGR_TAG_PVID;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_classified)
+ mode = EGR_TAG_CLASS;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_vlan_egress_tag_set(parsed_cmd->port, mode);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_vlan_egress_tag_set(i, mode);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_vlan_learn_show_key_func(
+ struct ethsw_command_def *parsed_cmd)
+{
+ int rc;
+ enum vlan_learning_mode mode;
+
+ rc = vsc9953_vlan_learning_get(&mode);
+ if (rc)
+ return CMD_RET_FAILURE;
+
+ switch (mode) {
+ case SHARED_VLAN_LEARNING:
+ printf("VLAN learning mode: shared\n");
+ break;
+ case PRIVATE_VLAN_LEARNING:
+ printf("VLAN learning mode: private\n");
+ break;
+ default:
+ printf("Unknown VLAN learning mode\n");
+ rc = CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_vlan_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ enum vlan_learning_mode mode;
+
+ /* keywords for shared/private are the last in the array */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_shared)
+ mode = SHARED_VLAN_LEARNING;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_private)
+ mode = PRIVATE_VLAN_LEARNING;
+ else
+ return CMD_RET_USAGE;
+
+ vsc9953_vlan_learning_set(mode);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_ingr_fltr_show_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ int enabled;
+
+ printf("%7s\t%18s\n", "Port", "Ingress filtering");
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ enabled = vsc9953_port_ingress_filtering_get(parsed_cmd->port);
+ printf("%7d\t%18s\n", parsed_cmd->port, enabled ? "enable" :
+ "disable");
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ enabled = vsc9953_port_ingress_filtering_get(i);
+ printf("%7d\t%18s\n", parsed_cmd->port, enabled ?
+ "enable" :
+ "disable");
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_ingr_fltr_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ int enable;
+
+ /* keywords for enabling/disabling ingress filtering
+ * are the last in the array
+ */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_enable)
+ enable = 1;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_disable)
+ enable = 0;
+ else
+ return CMD_RET_USAGE;
+
+ if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) {
+ if (!VSC9953_PORT_CHECK(parsed_cmd->port)) {
+ printf("Invalid port number: %d\n", parsed_cmd->port);
+ return CMD_RET_FAILURE;
+ }
+ vsc9953_port_ingress_filtering_set(parsed_cmd->port, enable);
+ } else {
+ for (i = 0; i < VSC9953_MAX_PORTS; i++)
+ vsc9953_port_ingress_filtering_set(i, enable);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct ethsw_command_func vsc9953_cmd_func = {
+ .ethsw_name = "L2 Switch VSC9953",
+ .port_enable = &vsc9953_port_status_key_func,
+ .port_disable = &vsc9953_port_status_key_func,
+ .port_show = &vsc9953_port_config_key_func,
+ .port_stats = &vsc9953_port_stats_key_func,
+ .port_stats_clear = &vsc9953_port_stats_clear_key_func,
+ .port_learn = &vsc9953_learn_set_key_func,
+ .port_learn_show = &vsc9953_learn_show_key_func,
+ .fdb_show = &vsc9953_fdb_show_key_func,
+ .fdb_flush = &vsc9953_fdb_flush_key_func,
+ .fdb_entry_add = &vsc9953_fdb_entry_add_key_func,
+ .fdb_entry_del = &vsc9953_fdb_entry_del_key_func,
+ .pvid_show = &vsc9953_pvid_show_key_func,
+ .pvid_set = &vsc9953_pvid_set_key_func,
+ .vlan_show = &vsc9953_vlan_show_key_func,
+ .vlan_set = &vsc9953_vlan_set_key_func,
+ .port_untag_show = &vsc9953_port_untag_show_key_func,
+ .port_untag_set = &vsc9953_port_untag_set_key_func,
+ .port_egr_vlan_show = &vsc9953_egr_vlan_tag_show_key_func,
+ .port_egr_vlan_set = &vsc9953_egr_vlan_tag_set_key_func,
+ .vlan_learn_show = &vsc9953_vlan_learn_show_key_func,
+ .vlan_learn_set = &vsc9953_vlan_learn_set_key_func,
+ .port_ingr_filt_show = &vsc9953_ingr_fltr_show_key_func,
+ .port_ingr_filt_set = &vsc9953_ingr_fltr_set_key_func
+};
+
+#endif /* CONFIG_CMD_ETHSW */
+
+/*****************************************************************************
+At startup, the default configuration would be:
+ - HW learning enabled on all ports; (HW default)
+ - All ports are in VLAN 1;
+ - All ports are VLAN aware;
+ - All ports have POP_COUNT 1;
+ - All ports have PVID 1;
+ - All ports have TPID 0x8100; (HW default)
+ - All ports tag frames classified to all VLANs that are not PVID;
+*****************************************************************************/
+void vsc9953_default_configuration(void)
+{
+ int i;
+
+ for (i = 0; i < VSC9953_MAX_VLAN; i++)
+ vsc9953_vlan_table_membership_all_set(i, 0);
+ vsc9953_port_all_vlan_aware_set(1);
+ vsc9953_port_all_vlan_pvid_set(1);
+ vsc9953_port_all_vlan_poncnt_set(1);
+ vsc9953_vlan_table_membership_all_set(1, 1);
+ vsc9953_vlan_ingr_fltr_learn_drop(1);
+ vsc9953_port_all_vlan_egress_untagged_set(EGRESS_UNTAG_PVID_AND_ZERO);
+}
+
+void vsc9953_init(bd_t *bis)
+{
+ u32 i;
+ u32 hdx_cfg = 0;
+ u32 phy_addr = 0;
+ int timeout;
+ struct vsc9953_system_reg *l2sys_reg;
+ struct vsc9953_qsys_reg *l2qsys_reg;
+ struct vsc9953_dev_gmii *l2dev_gmii_reg;
+ struct vsc9953_analyzer *l2ana_reg;
+ struct vsc9953_devcpu_gcb *l2dev_gcb;
+
+ l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
+ VSC9953_DEV_GMII_OFFSET);
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
+ VSC9953_SYS_OFFSET);
+
+ l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
+ VSC9953_QSYS_OFFSET);
+
+ l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
+ VSC9953_DEVCPU_GCB);
+
+ out_le32(&l2dev_gcb->chip_regs.soft_rst,
+ VSC9953_SOFT_SWC_RST_ENA);
+ timeout = 50000;
+ while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
+ VSC9953_SOFT_SWC_RST_ENA) && --timeout)
+ udelay(1); /* busy wait for vsc9953 soft reset */
+ if (timeout == 0)
+ debug("Timeout waiting for VSC9953 to reset\n");
+
+ out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
+ VSC9953_MEM_INIT);
+
+ timeout = 50000;
+ while ((in_le32(&l2sys_reg->sys.reset_cfg) &
+ VSC9953_MEM_INIT) && --timeout)
+ udelay(1); /* busy wait for vsc9953 memory init */
+ if (timeout == 0)
+ debug("Timeout waiting for VSC9953 memory to initialize\n");
+
+ out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
+ | VSC9953_CORE_ENABLE));
+
+ /* VSC9953 Setting to be done once only */
+ out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
+
+ for (i = 0; i < VSC9953_MAX_PORTS; i++) {
+ if (vsc9953_port_init(i))
+ printf("Failed to initialize l2switch port %d\n", i);
+
+ /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
+ if (VSC9953_INTERNAL_PORT_CHECK(i)) {
+ out_le32(&l2ana_reg->pfc[i].pfc_cfg,
+ VSC9953_PFC_FC_QSGMII);
+ out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
+ VSC9953_MAC_FC_CFG_QSGMII);
+ } else {
+ out_le32(&l2ana_reg->pfc[i].pfc_cfg,
+ VSC9953_PFC_FC);
+ out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
+ VSC9953_MAC_FC_CFG);
+ }
+ out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
+ VSC9953_CLOCK_CFG);
+ out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
+ VSC9953_MAC_ENA_CFG);
+ out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
+ VSC9953_MAC_MODE_CFG);
+ out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
+ VSC9953_MAC_IFG_CFG);
+ /* mac_hdx_cfg varies with port id*/
+ hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
+ out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
+ out_le32(&l2sys_reg->sys.front_port_mode[i],
+ VSC9953_FRONT_PORT_MODE);
+ setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
+ VSC9953_PORT_ENA);
+ out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
+ VSC9953_MAC_MAX_LEN);
+ out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
+ VSC9953_PAUSE_CFG);
+ /* WAIT FOR 2 us*/
+ udelay(2);
+
+ l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(
+ (char *)l2dev_gmii_reg
+ + T1040_SWITCH_GMII_DEV_OFFSET);
+
+ /* Initialize Lynx PHY Wrappers */
+ phy_addr = 0;
+ if (vsc9953_l2sw.port[i].enet_if ==
+ PHY_INTERFACE_MODE_QSGMII)
+ phy_addr = (i + 0x4) & 0x1F;
+ else if (vsc9953_l2sw.port[i].enet_if ==
+ PHY_INTERFACE_MODE_SGMII)
+ phy_addr = (i + 1) & 0x1F;
+
+ if (phy_addr) {
+ /* SGMII IF mode + AN enable */
+ vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
+ 0x14, PHY_SGMII_IF_MODE_AN |
+ PHY_SGMII_IF_MODE_SGMII);
+ /* Dev ability according to SGMII specification */
+ vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
+ 0x4, PHY_SGMII_DEV_ABILITY_SGMII);
+ /* Adjust link timer for SGMII
+ * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
+ */
+ vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
+ 0x13, 0x0003);
+ vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
+ 0x12, 0x0d40);
+ /* Restart AN */
+ vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
+ 0x0, PHY_SGMII_CR_DEF_VAL |
+ PHY_SGMII_CR_RESET_AN);
+
+ timeout = 50000;
+ while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
+ phy_addr, 0x01) & 0x0020) && --timeout)
+ udelay(1); /* wait for AN to complete */
+ if (timeout == 0)
+ debug("Timeout waiting for AN to complete\n");
+ }
+ }
+
+ vsc9953_default_configuration();
+
+#ifdef CONFIG_CMD_ETHSW
+ if (ethsw_define_functions(&vsc9953_cmd_func) < 0)
+ debug("Unable to use \"ethsw\" commands\n");
+#endif
+
+ printf("VSC9953 L2 switch initialized\n");
+ return;
+}
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index ea70853da2..0756bbe8f1 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -238,7 +238,7 @@ int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
{
struct udevice *bus;
- for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
+ for (bus = dev; device_is_on_pci_bus(bus);)
bus = bus->parent;
return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size);
}
@@ -303,7 +303,7 @@ int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
{
struct udevice *bus;
- for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
+ for (bus = dev; device_is_on_pci_bus(bus);)
bus = bus->parent;
return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep,
size);
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index 41d5447f12..79f27c744b 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -185,6 +185,7 @@ void pciauto_setup_device(struct pci_controller *hose,
#ifndef CONFIG_PCI_ENUM_ONLY
/* Configure the expansion ROM address */
pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
+ header_type &= 0x7f;
if (header_type != PCI_HEADER_TYPE_CARDBUS) {
rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c
index ca485ba90c..1568f20c1a 100644
--- a/drivers/pci/pcie_imx.c
+++ b/drivers/pci/pcie_imx.c
@@ -495,7 +495,7 @@ __weak int imx6_pcie_toggle_reset(void)
*
* The PCIe #PERST reset line _MUST_ be connected, otherwise your
* design does not conform to the specification. You must wait at
- * least 20 mS after de-asserting the #PERST so the EP device can
+ * least 20 ms after de-asserting the #PERST so the EP device can
* do self-initialisation.
*
* In case your #PERST pin is connected to a plain GPIO pin of the
@@ -506,7 +506,7 @@ __weak int imx6_pcie_toggle_reset(void)
* In case your #PERST toggling logic is more complex, for example
* connected via CPLD or somesuch, you can override this function
* in your board file and implement reset logic as needed. You must
- * not forget to wait at least 20 mS after de-asserting #PERST in
+ * not forget to wait at least 20 ms after de-asserting #PERST in
* this case either though.
*
* In case your #PERST line of the PCIe EP device is not connected
@@ -538,7 +538,7 @@ static int imx6_pcie_deassert_core_reset(void)
/*
* Wait for the clock to settle a bit, when the clock are sourced
- * from the CPU, we need about 30mS to settle.
+ * from the CPU, we need about 30 ms to settle.
*/
mdelay(50);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b8146df99b..3b6e3b7060 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -124,4 +124,6 @@ config PINCTRL_SANDBOX
endif
+source "drivers/pinctrl/uniphier/Kconfig"
+
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f537df4e88..e56a17f966 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
+
+obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 58001ef572..b5fdcd12a8 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -11,7 +11,6 @@
#include <dm/device.h>
#include <dm/lists.h>
#include <dm/pinctrl.h>
-#include <dm/root.h>
#include <dm/uclass.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -160,8 +159,7 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
static int pinconfig_post_bind(struct udevice *dev)
{
- /* Scan the bus for devices */
- return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+ return 0;
}
#endif
@@ -249,10 +247,15 @@ static int pinctrl_post_bind(struct udevice *dev)
}
/*
- * The pinctrl driver child nodes should be bound so that peripheral
- * devices can easily search in parent devices during later DT-parsing.
+ * If set_state callback is set, we assume this pinctrl driver is the
+ * full implementation. In this case, its child nodes should be bound
+ * so that peripheral devices can easily search in parent devices
+ * during later DT-parsing.
*/
- return pinconfig_post_bind(dev);
+ if (ops->set_state)
+ return pinconfig_post_bind(dev);
+
+ return 0;
}
UCLASS_DRIVER(pinctrl) = {
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
index 5205498b36..c432a008e7 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
@@ -17,6 +17,7 @@
#include <asm/arch/periph.h>
#include <asm/arch/pmu_rk3288.h>
#include <dm/pinctrl.h>
+#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -415,6 +416,12 @@ static struct pinctrl_ops rk3288_pinctrl_ops = {
.get_periph_id = rk3288_pinctrl_get_periph_id,
};
+static int rk3288_pinctrl_bind(struct udevice *dev)
+{
+ /* scan child GPIO banks */
+ return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
static int rk3288_pinctrl_probe(struct udevice *dev)
{
struct rk3288_pinctrl_priv *priv = dev_get_priv(dev);
@@ -437,5 +444,6 @@ U_BOOT_DRIVER(pinctrl_rk3288) = {
.of_match = rk3288_pinctrl_ids,
.priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
.ops = &rk3288_pinctrl_ops,
+ .bind = rk3288_pinctrl_bind,
.probe = rk3288_pinctrl_probe,
};
diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
new file mode 100644
index 0000000000..2ff616e946
--- /dev/null
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -0,0 +1,42 @@
+if ARCH_UNIPHIER
+
+config PINCTRL_UNIPHIER_CORE
+ bool
+
+config PINCTRL_UNIPHIER_PH1_LD4
+ bool "UniPhier PH1-LD4 SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PH1_LD4
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+config PINCTRL_UNIPHIER_PH1_PRO4
+ bool "UniPhier PH1-Pro4 SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PH1_PRO4
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+config PINCTRL_UNIPHIER_PH1_SLD8
+ bool "UniPhier PH1-sLD8 SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PH1_SLD8
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+config PINCTRL_UNIPHIER_PH1_PRO5
+ bool "UniPhier PH1-Pro5 SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PH1_PRO5
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+config PINCTRL_UNIPHIER_PROXSTREAM2
+ bool "UniPhier ProXstream2 SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PROXSTREAM2
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+config PINCTRL_UNIPHIER_PH1_LD6B
+ bool "UniPhier PH1-LD6b SoC pinctrl driver"
+ depends on ARCH_UNIPHIER_PH1_LD6B
+ default y
+ select PINCTRL_UNIPHIER_CORE
+
+endif
diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile
new file mode 100644
index 0000000000..e215b10972
--- /dev/null
+++ b/drivers/pinctrl/uniphier/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_PINCTRL_UNIPHIER_CORE) += pinctrl-uniphier-core.o
+
+obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD4) += pinctrl-ph1-ld4.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO4) += pinctrl-ph1-pro4.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_SLD8) += pinctrl-ph1-sld8.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO5) += pinctrl-ph1-pro5.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PROXSTREAM2) += pinctrl-proxstream2.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD6B) += pinctrl-ph1-ld6b.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
new file mode 100644
index 0000000000..b3d47f0915
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin ph1_ld4_pins[] = {
+ UNIPHIER_PINCTRL_PIN(53, 0),
+ UNIPHIER_PINCTRL_PIN(54, 0),
+ UNIPHIER_PINCTRL_PIN(55, 0),
+ UNIPHIER_PINCTRL_PIN(56, 0),
+ UNIPHIER_PINCTRL_PIN(67, 0),
+ UNIPHIER_PINCTRL_PIN(68, 0),
+ UNIPHIER_PINCTRL_PIN(69, 0),
+ UNIPHIER_PINCTRL_PIN(70, 0),
+ UNIPHIER_PINCTRL_PIN(85, 0),
+ UNIPHIER_PINCTRL_PIN(88, 0),
+ UNIPHIER_PINCTRL_PIN(156, 0),
+};
+
+static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
+static const unsigned emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {102, 103};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {104, 105};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {108, 109};
+static const unsigned i2c2_muxvals[] = {2, 2};
+static const unsigned i2c3_pins[] = {108, 109};
+static const unsigned i2c3_muxvals[] = {3, 3};
+static const unsigned nand_pins[] = {24, 25, 26, 27, 28, 29, 30, 31, 158, 159,
+ 160, 161, 162, 163, 164};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+static const unsigned nand_cs1_pins[] = {22, 23};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {85, 88};
+static const unsigned uart0_muxvals[] = {1, 1};
+static const unsigned uart1_pins[] = {155, 156};
+static const unsigned uart1_muxvals[] = {13, 13};
+static const unsigned uart1b_pins[] = {69, 70};
+static const unsigned uart1b_muxvals[] = {23, 23};
+static const unsigned uart2_pins[] = {128, 129};
+static const unsigned uart2_muxvals[] = {13, 13};
+static const unsigned uart3_pins[] = {110, 111};
+static const unsigned uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {53, 54};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {55, 56};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {155, 156};
+static const unsigned usb2_muxvals[] = {4, 4};
+static const unsigned usb2b_pins[] = {67, 68};
+static const unsigned usb2b_muxvals[] = {23, 23};
+
+static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart1b),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart3),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+ UNIPHIER_PINCTRL_GROUP(usb2b),
+};
+
+static const char * const ph1_ld4_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "nand",
+ "sd",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "usb0",
+ "usb1",
+ "usb2",
+};
+
+static struct uniphier_pinctrl_socdata ph1_ld4_pinctrl_socdata = {
+ .pins = ph1_ld4_pins,
+ .pins_count = ARRAY_SIZE(ph1_ld4_pins),
+ .groups = ph1_ld4_groups,
+ .groups_count = ARRAY_SIZE(ph1_ld4_groups),
+ .functions = ph1_ld4_functions,
+ .functions_count = ARRAY_SIZE(ph1_ld4_functions),
+ .mux_bits = 8,
+ .reg_stride = 4,
+ .load_pinctrl = false,
+};
+
+static int ph1_ld4_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &ph1_ld4_pinctrl_socdata);
+}
+
+static const struct udevice_id ph1_ld4_pinctrl_match[] = {
+ { .compatible = "socionext,ph1-ld4-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(ph1_ld4_pinctrl) = {
+ .name = "ph1-ld4-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ph1_ld4_pinctrl_match),
+ .probe = ph1_ld4_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
new file mode 100644
index 0000000000..8703a215e4
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin ph1_ld6b_pins[] = {
+ UNIPHIER_PINCTRL_PIN(113, 0),
+ UNIPHIER_PINCTRL_PIN(114, 0),
+ UNIPHIER_PINCTRL_PIN(115, 0),
+ UNIPHIER_PINCTRL_PIN(116, 0),
+ UNIPHIER_PINCTRL_PIN(217, 0),
+ UNIPHIER_PINCTRL_PIN(218, 0),
+ UNIPHIER_PINCTRL_PIN(219, 0),
+ UNIPHIER_PINCTRL_PIN(220, 0),
+};
+
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {109, 110};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {111, 112};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {115, 116};
+static const unsigned i2c2_muxvals[] = {1, 1};
+static const unsigned i2c3_pins[] = {118, 119};
+static const unsigned i2c3_muxvals[] = {1, 1};
+static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
+ 42, 43, 44, 45, 46};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+static const unsigned nand_cs1_pins[] = {37, 38};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {135, 136};
+static const unsigned uart0_muxvals[] = {3, 3};
+static const unsigned uart0b_pins[] = {11, 12};
+static const unsigned uart0b_muxvals[] = {2, 2};
+static const unsigned uart1_pins[] = {115, 116};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart1b_pins[] = {113, 114};
+static const unsigned uart1b_muxvals[] = {1, 1};
+static const unsigned uart2_pins[] = {113, 114};
+static const unsigned uart2_muxvals[] = {2, 2};
+static const unsigned uart2b_pins[] = {86, 87};
+static const unsigned uart2b_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {56, 57};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {58, 59};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {60, 61};
+static const unsigned usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {62, 63};
+static const unsigned usb3_muxvals[] = {0, 0};
+
+static const struct uniphier_pinctrl_group ph1_ld6b_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart0b),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart1b),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart2b),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+ UNIPHIER_PINCTRL_GROUP(usb3),
+};
+
+static const char * const ph1_ld6b_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "nand",
+ "sd",
+ "uart0",
+ "uart1",
+ "uart2",
+ "usb0",
+ "usb1",
+ "usb2",
+ "usb3",
+};
+
+static struct uniphier_pinctrl_socdata ph1_ld6b_pinctrl_socdata = {
+ .pins = ph1_ld6b_pins,
+ .pins_count = ARRAY_SIZE(ph1_ld6b_pins),
+ .groups = ph1_ld6b_groups,
+ .groups_count = ARRAY_SIZE(ph1_ld6b_groups),
+ .functions = ph1_ld6b_functions,
+ .functions_count = ARRAY_SIZE(ph1_ld6b_functions),
+ .mux_bits = 8,
+ .reg_stride = 4,
+ .load_pinctrl = false,
+};
+
+static int ph1_ld6b_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &ph1_ld6b_pinctrl_socdata);
+}
+
+static const struct udevice_id ph1_ld6b_pinctrl_match[] = {
+ { .compatible = "socionext,ph1-ld6b-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(ph1_ld6b_pinctrl) = {
+ .name = "ph1-ld6b-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ph1_ld6b_pinctrl_match),
+ .probe = ph1_ld6b_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
new file mode 100644
index 0000000000..b3eaf138f7
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin ph1_pro4_pins[] = {
+};
+
+static const unsigned emmc_pins[] = {40, 41, 42, 43, 51, 52, 53};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {44, 45, 46, 47};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {142, 143};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {144, 145};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {146, 147};
+static const unsigned i2c2_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {148, 149};
+static const unsigned i2c3_muxvals[] = {0, 0};
+static const unsigned i2c6_pins[] = {308, 309};
+static const unsigned i2c6_muxvals[] = {6, 6};
+static const unsigned nand_pins[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+static const unsigned nand_cs1_pins[] = {131, 132};
+static const unsigned nand_cs1_muxvals[] = {1, 1};
+static const unsigned sd_pins[] = {150, 151, 152, 153, 154, 155, 156, 157, 158};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
+ 327};
+static const unsigned sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {127, 128};
+static const unsigned uart0_muxvals[] = {0, 0};
+static const unsigned uart1_pins[] = {129, 130};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {131, 132};
+static const unsigned uart2_muxvals[] = {0, 0};
+static const unsigned uart3_pins[] = {88, 89};
+static const unsigned uart3_muxvals[] = {2, 2};
+static const unsigned usb0_pins[] = {180, 181};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {182, 183};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {184, 185};
+static const unsigned usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {186, 187};
+static const unsigned usb3_muxvals[] = {0, 0};
+
+static const struct uniphier_pinctrl_group ph1_pro4_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(i2c6),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(sd1),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart3),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+ UNIPHIER_PINCTRL_GROUP(usb3),
+};
+
+static const char * const ph1_pro4_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "i2c6",
+ "nand",
+ "sd",
+ "sd1",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "usb0",
+ "usb1",
+ "usb2",
+ "usb3",
+};
+
+static struct uniphier_pinctrl_socdata ph1_pro4_pinctrl_socdata = {
+ .pins = ph1_pro4_pins,
+ .pins_count = ARRAY_SIZE(ph1_pro4_pins),
+ .groups = ph1_pro4_groups,
+ .groups_count = ARRAY_SIZE(ph1_pro4_groups),
+ .functions = ph1_pro4_functions,
+ .functions_count = ARRAY_SIZE(ph1_pro4_functions),
+ .mux_bits = 4,
+ .reg_stride = 8,
+ .load_pinctrl = true,
+};
+
+static int ph1_pro4_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &ph1_pro4_pinctrl_socdata);
+}
+
+static const struct udevice_id ph1_pro4_pinctrl_match[] = {
+ { .compatible = "socionext,ph1-pro4-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(ph1_pro4_pinctrl) = {
+ .name = "ph1-pro4-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ph1_pro4_pinctrl_match),
+ .probe = ph1_pro4_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
new file mode 100644
index 0000000000..3749250066
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin ph1_pro5_pins[] = {
+ UNIPHIER_PINCTRL_PIN(47, 0),
+ UNIPHIER_PINCTRL_PIN(48, 0),
+ UNIPHIER_PINCTRL_PIN(49, 0),
+ UNIPHIER_PINCTRL_PIN(50, 0),
+ UNIPHIER_PINCTRL_PIN(53, 0),
+ UNIPHIER_PINCTRL_PIN(54, 0),
+ UNIPHIER_PINCTRL_PIN(87, 0),
+ UNIPHIER_PINCTRL_PIN(88, 0),
+ UNIPHIER_PINCTRL_PIN(101, 0),
+ UNIPHIER_PINCTRL_PIN(102, 0),
+};
+
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {0, 0, 0, 0};
+static const unsigned i2c0_pins[] = {112, 113};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {114, 115};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {116, 117};
+static const unsigned i2c2_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {118, 119};
+static const unsigned i2c3_muxvals[] = {0, 0};
+static const unsigned i2c5_pins[] = {87, 88};
+static const unsigned i2c5_muxvals[] = {2, 2};
+static const unsigned i2c5b_pins[] = {196, 197};
+static const unsigned i2c5b_muxvals[] = {2, 2};
+static const unsigned i2c5c_pins[] = {215, 216};
+static const unsigned i2c5c_muxvals[] = {2, 2};
+static const unsigned i2c6_pins[] = {101, 102};
+static const unsigned i2c6_muxvals[] = {2, 2};
+static const unsigned nand_pins[] = {19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
+ 31, 32, 33, 34, 35};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+static const unsigned nand_cs1_pins[] = {26, 27};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {47, 48};
+static const unsigned uart0_muxvals[] = {0, 0};
+static const unsigned uart0b_pins[] = {227, 228};
+static const unsigned uart0b_muxvals[] = {3, 3};
+static const unsigned uart1_pins[] = {49, 50};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {51, 52};
+static const unsigned uart2_muxvals[] = {0, 0};
+static const unsigned uart3_pins[] = {53, 54};
+static const unsigned uart3_muxvals[] = {0, 0};
+static const unsigned usb0_pins[] = {124, 125};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {126, 127};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {128, 129};
+static const unsigned usb2_muxvals[] = {0, 0};
+
+static const struct uniphier_pinctrl_group ph1_pro5_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(i2c5),
+ UNIPHIER_PINCTRL_GROUP(i2c5b),
+ UNIPHIER_PINCTRL_GROUP(i2c5c),
+ UNIPHIER_PINCTRL_GROUP(i2c6),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart0b),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart3),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+};
+
+static const char * const ph1_pro5_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "i2c5",
+ "i2c6",
+ "nand",
+ "sd",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "usb0",
+ "usb1",
+ "usb2",
+};
+
+static struct uniphier_pinctrl_socdata ph1_pro5_pinctrl_socdata = {
+ .pins = ph1_pro5_pins,
+ .pins_count = ARRAY_SIZE(ph1_pro5_pins),
+ .groups = ph1_pro5_groups,
+ .groups_count = ARRAY_SIZE(ph1_pro5_groups),
+ .functions = ph1_pro5_functions,
+ .functions_count = ARRAY_SIZE(ph1_pro5_functions),
+ .mux_bits = 4,
+ .reg_stride = 8,
+ .load_pinctrl = true,
+};
+
+static int ph1_pro5_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &ph1_pro5_pinctrl_socdata);
+}
+
+static const struct udevice_id ph1_pro5_pinctrl_match[] = {
+ { .compatible = "socionext,ph1-pro5-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(ph1_pro5_pinctrl) = {
+ .name = "ph1-pro5-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ph1_pro5_pinctrl_match),
+ .probe = ph1_pro5_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
new file mode 100644
index 0000000000..5fafdb6100
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin ph1_sld8_pins[] = {
+ UNIPHIER_PINCTRL_PIN(32, 8),
+ UNIPHIER_PINCTRL_PIN(33, 8),
+ UNIPHIER_PINCTRL_PIN(34, 8),
+ UNIPHIER_PINCTRL_PIN(35, 8),
+ UNIPHIER_PINCTRL_PIN(36, 8),
+ UNIPHIER_PINCTRL_PIN(37, 8),
+ UNIPHIER_PINCTRL_PIN(38, 8),
+ UNIPHIER_PINCTRL_PIN(39, 8),
+ UNIPHIER_PINCTRL_PIN(40, 9),
+ UNIPHIER_PINCTRL_PIN(41, 0),
+ UNIPHIER_PINCTRL_PIN(42, 0),
+ UNIPHIER_PINCTRL_PIN(43, 0),
+ UNIPHIER_PINCTRL_PIN(44, 0),
+ UNIPHIER_PINCTRL_PIN(70, 0),
+ UNIPHIER_PINCTRL_PIN(71, 0),
+ UNIPHIER_PINCTRL_PIN(102, 10),
+ UNIPHIER_PINCTRL_PIN(103, 10),
+ UNIPHIER_PINCTRL_PIN(104, 11),
+ UNIPHIER_PINCTRL_PIN(105, 11),
+ UNIPHIER_PINCTRL_PIN(108, 13),
+ UNIPHIER_PINCTRL_PIN(109, 13),
+ UNIPHIER_PINCTRL_PIN(112, 0),
+ UNIPHIER_PINCTRL_PIN(113, 0),
+ UNIPHIER_PINCTRL_PIN(114, 0),
+ UNIPHIER_PINCTRL_PIN(115, 0),
+};
+
+static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {102, 103};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {104, 105};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {108, 109};
+static const unsigned i2c2_muxvals[] = {2, 2};
+static const unsigned i2c3_pins[] = {108, 109};
+static const unsigned i2c3_muxvals[] = {3, 3};
+static const unsigned nand_pins[] = {15, 16, 17, 18, 19, 20, 21, 24, 25, 26,
+ 27, 28, 29, 30, 31};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+static const unsigned nand_cs1_pins[] = {22, 23};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {70, 71};
+static const unsigned uart0_muxvals[] = {3, 3};
+static const unsigned uart1_pins[] = {114, 115};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {112, 113};
+static const unsigned uart2_muxvals[] = {1, 1};
+static const unsigned uart3_pins[] = {110, 111};
+static const unsigned uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {41, 42};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {43, 44};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {114, 115};
+static const unsigned usb2_muxvals[] = {1, 1};
+
+static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart3),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+};
+
+static const char * const ph1_sld8_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "nand",
+ "sd",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "usb0",
+ "usb1",
+ "usb2",
+};
+
+static struct uniphier_pinctrl_socdata ph1_sld8_pinctrl_socdata = {
+ .pins = ph1_sld8_pins,
+ .pins_count = ARRAY_SIZE(ph1_sld8_pins),
+ .groups = ph1_sld8_groups,
+ .groups_count = ARRAY_SIZE(ph1_sld8_groups),
+ .functions = ph1_sld8_functions,
+ .functions_count = ARRAY_SIZE(ph1_sld8_functions),
+ .mux_bits = 8,
+ .reg_stride = 4,
+ .load_pinctrl = false,
+};
+
+static int ph1_sld8_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &ph1_sld8_pinctrl_socdata);
+}
+
+static const struct udevice_id ph1_sld8_pinctrl_match[] = {
+ { .compatible = "socionext,ph1-sld8-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(ph1_sld8_pinctrl) = {
+ .name = "ph1-sld8-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ph1_sld8_pinctrl_match),
+ .probe = ph1_sld8_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-proxstream2.c b/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
new file mode 100644
index 0000000000..2cca69d514
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct uniphier_pinctrl_pin proxstream2_pins[] = {
+ UNIPHIER_PINCTRL_PIN(113, 0),
+ UNIPHIER_PINCTRL_PIN(114, 0),
+ UNIPHIER_PINCTRL_PIN(115, 0),
+ UNIPHIER_PINCTRL_PIN(116, 0),
+};
+
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {9, 9, 9, 9, 9, 9, 9};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {9, 9, 9, 9};
+static const unsigned i2c0_pins[] = {109, 110};
+static const unsigned i2c0_muxvals[] = {8, 8};
+static const unsigned i2c1_pins[] = {111, 112};
+static const unsigned i2c1_muxvals[] = {8, 8};
+static const unsigned i2c2_pins[] = {171, 172};
+static const unsigned i2c2_muxvals[] = {8, 8};
+static const unsigned i2c3_pins[] = {159, 160};
+static const unsigned i2c3_muxvals[] = {8, 8};
+static const unsigned i2c5_pins[] = {183, 184};
+static const unsigned i2c5_muxvals[] = {11, 11};
+static const unsigned i2c6_pins[] = {185, 186};
+static const unsigned i2c6_muxvals[] = {11, 11};
+static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
+ 42, 43, 44, 45, 46};
+static const unsigned nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8};
+static const unsigned nand_cs1_pins[] = {37, 38};
+static const unsigned nand_cs1_muxvals[] = {8, 8};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
+static const unsigned uart0_pins[] = {217, 218};
+static const unsigned uart0_muxvals[] = {8, 8};
+static const unsigned uart0b_pins[] = {179, 180};
+static const unsigned uart0b_muxvals[] = {10, 10};
+static const unsigned uart1_pins[] = {115, 116};
+static const unsigned uart1_muxvals[] = {8, 8};
+static const unsigned uart2_pins[] = {113, 114};
+static const unsigned uart2_muxvals[] = {8, 8};
+static const unsigned uart3_pins[] = {219, 220};
+static const unsigned uart3_muxvals[] = {8, 8};
+static const unsigned uart3b_pins[] = {181, 182};
+static const unsigned uart3b_muxvals[] = {10, 10};
+static const unsigned usb0_pins[] = {56, 57};
+static const unsigned usb0_muxvals[] = {8, 8};
+static const unsigned usb1_pins[] = {58, 59};
+static const unsigned usb1_muxvals[] = {8, 8};
+static const unsigned usb2_pins[] = {60, 61};
+static const unsigned usb2_muxvals[] = {8, 8};
+static const unsigned usb3_pins[] = {62, 63};
+static const unsigned usb3_muxvals[] = {8, 8};
+
+static const struct uniphier_pinctrl_group proxstream2_groups[] = {
+ UNIPHIER_PINCTRL_GROUP(emmc),
+ UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+ UNIPHIER_PINCTRL_GROUP(i2c0),
+ UNIPHIER_PINCTRL_GROUP(i2c1),
+ UNIPHIER_PINCTRL_GROUP(i2c2),
+ UNIPHIER_PINCTRL_GROUP(i2c3),
+ UNIPHIER_PINCTRL_GROUP(i2c5),
+ UNIPHIER_PINCTRL_GROUP(i2c6),
+ UNIPHIER_PINCTRL_GROUP(nand),
+ UNIPHIER_PINCTRL_GROUP(nand_cs1),
+ UNIPHIER_PINCTRL_GROUP(sd),
+ UNIPHIER_PINCTRL_GROUP(uart0),
+ UNIPHIER_PINCTRL_GROUP(uart0b),
+ UNIPHIER_PINCTRL_GROUP(uart1),
+ UNIPHIER_PINCTRL_GROUP(uart2),
+ UNIPHIER_PINCTRL_GROUP(uart3),
+ UNIPHIER_PINCTRL_GROUP(uart3b),
+ UNIPHIER_PINCTRL_GROUP(usb0),
+ UNIPHIER_PINCTRL_GROUP(usb1),
+ UNIPHIER_PINCTRL_GROUP(usb2),
+ UNIPHIER_PINCTRL_GROUP(usb3),
+};
+
+static const char * const proxstream2_functions[] = {
+ "emmc",
+ "i2c0",
+ "i2c1",
+ "i2c2",
+ "i2c3",
+ "i2c5",
+ "i2c6",
+ "nand",
+ "sd",
+ "uart0",
+ "uart0b",
+ "uart1",
+ "uart2",
+ "uart3",
+ "uart3b",
+ "usb0",
+ "usb1",
+ "usb2",
+ "usb3",
+};
+
+static struct uniphier_pinctrl_socdata proxstream2_pinctrl_socdata = {
+ .pins = proxstream2_pins,
+ .pins_count = ARRAY_SIZE(proxstream2_pins),
+ .groups = proxstream2_groups,
+ .groups_count = ARRAY_SIZE(proxstream2_groups),
+ .functions = proxstream2_functions,
+ .functions_count = ARRAY_SIZE(proxstream2_functions),
+ .mux_bits = 8,
+ .reg_stride = 4,
+ .load_pinctrl = false,
+};
+
+static int proxstream2_pinctrl_probe(struct udevice *dev)
+{
+ return uniphier_pinctrl_probe(dev, &proxstream2_pinctrl_socdata);
+}
+
+static const struct udevice_id proxstream2_pinctrl_match[] = {
+ { .compatible = "socionext,proxstream2-pinctrl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(proxstream2_pinctrl) = {
+ .name = "proxstream2-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(proxstream2_pinctrl_match),
+ .probe = proxstream2_pinctrl_probe,
+ .remove = uniphier_pinctrl_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
+ .ops = &uniphier_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
new file mode 100644
index 0000000000..37a920ca8b
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <dm/device.h>
+#include <dm/pinctrl.h>
+
+#include "pinctrl-uniphier.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->socdata->groups_count;
+}
+
+static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
+ unsigned selector)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->socdata->groups[selector].name;
+}
+
+static int uniphier_pinmux_get_functions_count(struct udevice *dev)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->socdata->functions_count;
+}
+
+static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
+ unsigned selector)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+ return priv->socdata->functions[selector];
+}
+
+static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ int pins_count = priv->socdata->pins_count;
+ const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
+ int i;
+
+ for (i = 0; i < pins_count; i++) {
+ if (pins[i].number == pin) {
+ unsigned int iectrl;
+ u32 tmp;
+
+ iectrl = uniphier_pin_get_iectrl(pins[i].data);
+ tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
+ tmp |= 1 << iectrl;
+ writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
+ }
+ }
+}
+
+static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
+ unsigned muxval)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ unsigned mux_bits = priv->socdata->mux_bits;
+ unsigned reg_stride = priv->socdata->reg_stride;
+ unsigned reg, reg_end, shift, mask;
+ u32 tmp;
+
+ reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
+ reg_end = reg + reg_stride;
+ shift = pin * mux_bits % 32;
+ mask = (1U << mux_bits) - 1;
+
+ /*
+ * If reg_stride is greater than 4, the MSB of each pinsel shall be
+ * stored in the offset+4.
+ */
+ for (; reg < reg_end; reg += 4) {
+ tmp = readl(priv->base + reg);
+ tmp &= ~(mask << shift);
+ tmp |= (mask & muxval) << shift;
+ writel(tmp, priv->base + reg);
+
+ muxval >>= mux_bits;
+ }
+
+ if (priv->socdata->load_pinctrl)
+ writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
+
+ /* some pins need input-enabling */
+ uniphier_pinconf_input_enable(dev, pin);
+}
+
+static int uniphier_pinmux_group_set(struct udevice *dev,
+ unsigned group_selector,
+ unsigned func_selector)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ const struct uniphier_pinctrl_group *grp =
+ &priv->socdata->groups[group_selector];
+ int i;
+
+ for (i = 0; i < grp->num_pins; i++)
+ uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
+
+ return 0;
+}
+
+const struct pinctrl_ops uniphier_pinctrl_ops = {
+ .get_groups_count = uniphier_pinctrl_get_groups_count,
+ .get_group_name = uniphier_pinctrl_get_group_name,
+ .get_functions_count = uniphier_pinmux_get_functions_count,
+ .get_function_name = uniphier_pinmux_get_function_name,
+ .pinmux_group_set = uniphier_pinmux_group_set,
+ .set_state = pinctrl_generic_set_state,
+};
+
+int uniphier_pinctrl_probe(struct udevice *dev,
+ struct uniphier_pinctrl_socdata *socdata)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ fdt_size_t size;
+
+ addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg",
+ &size);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = map_sysmem(addr, size);
+ if (!priv->base)
+ return -ENOMEM;
+
+ priv->socdata = socdata;
+
+ return 0;
+}
+
+int uniphier_pinctrl_remove(struct udevice *dev)
+{
+ struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+
+ unmap_sysmem(priv->base);
+
+ return 0;
+}
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
new file mode 100644
index 0000000000..7eaec6a702
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __PINCTRL_UNIPHIER_H__
+#define __PINCTRL_UNIPHIER_H__
+
+/* TODO: move this to include/linux/bug.h */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#define UNIPHIER_PINCTRL_PINMUX_BASE 0x0
+#define UNIPHIER_PINCTRL_LOAD_PINMUX 0x700
+#define UNIPHIER_PINCTRL_IECTRL 0xd00
+
+#define UNIPHIER_PIN_ATTR_PACKED(iectrl) (iectrl)
+
+static inline unsigned int uniphier_pin_get_iectrl(unsigned long data)
+{
+ return data;
+}
+
+/**
+ * struct uniphier_pinctrl_pin - pin data for UniPhier SoC
+ *
+ * @number: pin number
+ * @data: additional per-pin data
+ */
+struct uniphier_pinctrl_pin {
+ unsigned number;
+ unsigned long data;
+};
+
+/**
+ * struct uniphier_pinctrl_group - pin group data for UniPhier SoC
+ *
+ * @name: pin group name
+ * @pins: array of pins that belong to the group
+ * @num_pins: number of pins in the group
+ * @muxvals: array of values to be set to pinmux registers
+ */
+struct uniphier_pinctrl_group {
+ const char *name;
+ const unsigned *pins;
+ unsigned num_pins;
+ const unsigned *muxvals;
+};
+
+/**
+ * struct uniphier_pinctrl_socdata - SoC data for UniPhier pin controller
+ *
+ * @pins: array of pin data
+ * @pins_count: number of pin data
+ * @groups: array of pin group data
+ * @groups_count: number of pin group data
+ * @functions: array of pinmux function names
+ * @functions_count: number of pinmux functions
+ * @mux_bits: bit width of each pinmux register
+ * @reg_stride: stride of pinmux register address
+ * @load_pinctrl: if true, LOAD_PINMUX register must be set to one for new
+ * values in pinmux registers to become really effective
+ */
+struct uniphier_pinctrl_socdata {
+ const struct uniphier_pinctrl_pin *pins;
+ int pins_count;
+ const struct uniphier_pinctrl_group *groups;
+ int groups_count;
+ const char * const *functions;
+ int functions_count;
+ unsigned mux_bits;
+ unsigned reg_stride;
+ bool load_pinctrl;
+};
+
+#define UNIPHIER_PINCTRL_PIN(a, b) \
+{ \
+ .number = a, \
+ .data = UNIPHIER_PIN_ATTR_PACKED(b), \
+}
+
+#define UNIPHIER_PINCTRL_GROUP(grp) \
+ { \
+ .name = #grp, \
+ .pins = grp##_pins, \
+ .num_pins = ARRAY_SIZE(grp##_pins), \
+ .muxvals = grp##_muxvals + \
+ BUILD_BUG_ON_ZERO(ARRAY_SIZE(grp##_pins) != \
+ ARRAY_SIZE(grp##_muxvals)), \
+ }
+
+/**
+ * struct uniphier_pinctrl_priv - private data for UniPhier pinctrl driver
+ *
+ * @base: base address of the pinctrl device
+ * @socdata: SoC specific data
+ */
+struct uniphier_pinctrl_priv {
+ void __iomem *base;
+ struct uniphier_pinctrl_socdata *socdata;
+};
+
+extern const struct pinctrl_ops uniphier_pinctrl_ops;
+
+int uniphier_pinctrl_probe(struct udevice *dev,
+ struct uniphier_pinctrl_socdata *socdata);
+
+int uniphier_pinctrl_remove(struct udevice *dev);
+
+#endif /* __PINCTRL_UNIPHIER_H__ */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ccb80d2d1d..ddb725d326 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -111,7 +111,7 @@ config DEBUG_UART_SHIFT
config ROCKCHIP_SERIAL
bool "Rockchip on-chip UART support"
- depends on ARCH_UNIPHIER && DM_SERIAL
+ depends on ARCH_ROCKCHIP && DM_SERIAL
help
Select this to enable a debug UART for Rockchip devices. This uses
the ns16550 driver. You will need to #define CONFIG_SYS_NS16550 in
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index ecf3bc0240..3a5c1d0eaa 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -80,13 +80,6 @@ static int pl01x_generic_serial_init(struct pl01x_regs *regs,
writel(0, &regs->pl010_cr);
break;
case TYPE_PL011:
-#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
- /* Empty RX fifo if necessary */
- if (readl(&regs->pl011_cr) & UART_PL011_CR_UARTEN) {
- while (!(readl(&regs->fr) & UART_PL01x_FR_RXFE))
- readl(&regs->dr);
- }
-#endif
/* disable everything */
writel(0, &regs->pl011_cr);
break;
@@ -105,21 +98,6 @@ static int pl011_set_line_control(struct pl01x_regs *regs)
* control register write
*/
lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
-#ifdef CONFIG_PL011_SERIAL_RLCR
- {
- int i;
-
- /*
- * Program receive line control register after waiting
- * 10 bus cycles. Delay be writing to readonly register
- * 10 times
- */
- for (i = 0; i < 10; i++)
- writel(lcr, &regs->fr);
-
- writel(lcr, &regs->pl011_rlcr);
- }
-#endif
writel(lcr, &regs->pl011_lcrh);
return 0;
}
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index 941e6eda4c..cbc2929435 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -226,7 +226,11 @@ struct uart_port {
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
-# define SCIF_ORER 0x0001
+# if defined(CONFIG_SCIF_A)
+# define SCIF_ORER 0x0200
+# else
+# define SCIF_ORER 0x0001
+# endif
# define SCSCR_INIT(port) (port->clk_mode == EXT_CLK ? 0x32 : 0x30)
/* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */
#else
@@ -306,7 +310,11 @@ struct uart_port {
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-# define SCIF_RFDC_MASK 0x003f
+# if defined(CONFIG_SCIF_A)
+# define SCIF_RFDC_MASK 0x007f
+# else
+# define SCIF_RFDC_MASK 0x001f
+# endif
#else
# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
# define SCIF_RFDC_MASK 0x001f
@@ -557,6 +565,25 @@ SCIF_FNS(SCFCR, 0x18, 16)
SCIF_FNS(SCFDR, 0x1c, 16)
SCIF_FNS(SCLSR, 0x24, 16)
SCIF_FNS(DL, 0x00, 0) /* dummy */
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
+/* SCIFA and SCIF register offsets and size */
+SCIx_FNS(SCSMR, 0, 0, 0x00, 16, 0, 0, 0x00, 16, 0, 0)
+SCIx_FNS(SCBRR, 0, 0, 0x04, 8, 0, 0, 0x04, 8, 0, 0)
+SCIx_FNS(SCSCR, 0, 0, 0x08, 16, 0, 0, 0x08, 16, 0, 0)
+SCIx_FNS(SCxTDR, 0, 0, 0x20, 8, 0, 0, 0x0C, 8, 0, 0)
+SCIx_FNS(SCxSR, 0, 0, 0x14, 16, 0, 0, 0x10, 16, 0, 0)
+SCIx_FNS(SCxRDR, 0, 0, 0x24, 8, 0, 0, 0x14, 8, 0, 0)
+SCIF_FNS(SCFCR, 0, 0, 0x18, 16)
+SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
+SCIF_FNS(DL, 0, 0, 0x30, 16)
+SCIF_FNS(CKS, 0, 0, 0x34, 16)
+#if defined(CONFIG_SCIF_A)
+SCIF_FNS(SCLSR, 0, 0, 0x14, 16)
+#else
+SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
+#endif
#else
/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
/* name off sz off sz off sz off sz off sz*/
@@ -594,14 +621,8 @@ SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
#endif
SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
#endif
-#if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
- defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
-SCIF_FNS(DL, 0, 0, 0x30, 16)
-SCIF_FNS(CKS, 0, 0, 0x34, 16)
-#else
SCIF_FNS(DL, 0, 0, 0x0, 0) /* dummy */
#endif
-#endif
#define sci_in(port, reg) sci_##reg##_in(port)
#define sci_out(port, reg, value) sci_##reg##_out(port, value)
@@ -743,7 +764,11 @@ static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
#define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
-#define SCBRR_VALUE(bps, clk) (clk / bps / 32 - 1) /* Internal Clock */
+ #if defined(CONFIG_SCIF_A)
+ #define SCBRR_VALUE(bps, clk) (clk / bps / 16 - 1) /* Internal Clock */
+ #else
+ #define SCBRR_VALUE(bps, clk) (clk / bps / 32 - 1) /* Internal Clock */
+ #endif
#else /* Generic SH */
#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
#endif
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 0a036ccb00..0bd4f88926 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -15,8 +15,6 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
-#define BIT(x) (1 << (x))
-
/* SPIGCR0 */
#define SPIGCR0_SPIENA_MASK 0x1
#define SPIGCR0_SPIRST_MASK 0x0
diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c
index 235557ea3c..cb682ddda4 100644
--- a/drivers/spi/ep93xx_spi.c
+++ b/drivers/spi/ep93xx_spi.c
@@ -16,8 +16,6 @@
#include <asm/arch/ep93xx.h>
-
-#define BIT(x) (1<<(x))
#define SSPBASE SPI_BASE
#define SSPCR0 0x0000
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 2b9f395a97..627644b56b 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <malloc.h>
+#include <memalign.h>
#include <spi.h>
#include <asm/errno.h>
#include <asm/io.h>
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index fbb665b86f..144716fd91 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -36,6 +36,11 @@ DECLARE_GLOBAL_DATA_PTR;
#define SLINK_CMD_ENB (1 << 31)
#define SLINK_CMD_GO (1 << 30)
#define SLINK_CMD_M_S (1 << 28)
+#define SLINK_CMD_IDLE_SCLK_DRIVE_LOW (0 << 24)
+#define SLINK_CMD_IDLE_SCLK_DRIVE_HIGH (1 << 24)
+#define SLINK_CMD_IDLE_SCLK_PULL_LOW (2 << 24)
+#define SLINK_CMD_IDLE_SCLK_PULL_HIGH (3 << 24)
+#define SLINK_CMD_IDLE_SCLK_MASK (3 << 24)
#define SLINK_CMD_CK_SDA (1 << 21)
#define SLINK_CMD_CS_POL (1 << 13)
#define SLINK_CMD_CS_VAL (1 << 12)
@@ -331,6 +336,22 @@ static int tegra30_spi_set_speed(struct udevice *bus, uint speed)
static int tegra30_spi_set_mode(struct udevice *bus, uint mode)
{
struct tegra30_spi_priv *priv = dev_get_priv(bus);
+ struct spi_regs *regs = priv->regs;
+ u32 reg;
+
+ reg = readl(&regs->command);
+
+ /* Set CPOL and CPHA */
+ reg &= ~(SLINK_CMD_IDLE_SCLK_MASK | SLINK_CMD_CK_SDA);
+ if (mode & SPI_CPHA)
+ reg |= SLINK_CMD_CK_SDA;
+
+ if (mode & SPI_CPOL)
+ reg |= SLINK_CMD_IDLE_SCLK_DRIVE_HIGH;
+ else
+ reg |= SLINK_CMD_IDLE_SCLK_DRIVE_LOW;
+
+ writel(reg, &regs->command);
priv->mode = mode;
debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 6c21acda57..8ccc5780c9 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -247,7 +247,7 @@ static int xilinx_spi_set_speed(struct udevice *bus, uint speed)
priv->freq = speed;
- debug("xilinx_spi_set_speed: regs=%p, mode=%d\n", priv->regs,
+ debug("xilinx_spi_set_speed: regs=%p, speed=%d\n", priv->regs,
priv->freq);
return 0;
@@ -260,13 +260,13 @@ static int xilinx_spi_set_mode(struct udevice *bus, uint mode)
uint32_t spicr;
spicr = readl(&regs->spicr);
- if (priv->mode & SPI_LSB_FIRST)
+ if (mode & SPI_LSB_FIRST)
spicr |= SPICR_LSB_FIRST;
- if (priv->mode & SPI_CPHA)
+ if (mode & SPI_CPHA)
spicr |= SPICR_CPHA;
- if (priv->mode & SPI_CPOL)
+ if (mode & SPI_CPOL)
spicr |= SPICR_CPOL;
- if (priv->mode & SPI_LOOP)
+ if (mode & SPI_LOOP)
spicr |= SPICR_LOOP;
writel(spicr, &regs->spicr);
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 310fb69c8d..d370e495cd 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -272,7 +272,8 @@ static int zynq_spi_set_speed(struct udevice *bus, uint speed)
writel(confr, &regs->cr);
priv->freq = speed;
- debug("zynq_spi_set_speed: regs=%p, mode=%d\n", priv->regs, priv->freq);
+ debug("zynq_spi_set_speed: regs=%p, speed=%d\n",
+ priv->regs, priv->freq);
return 0;
}
@@ -287,9 +288,9 @@ static int zynq_spi_set_mode(struct udevice *bus, uint mode)
confr = readl(&regs->cr);
confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
- if (priv->mode & SPI_CPHA)
+ if (mode & SPI_CPHA)
confr |= ZYNQ_SPI_CR_CPHA_MASK;
- if (priv->mode & SPI_CPOL)
+ if (mode & SPI_CPOL)
confr |= ZYNQ_SPI_CR_CPOL_MASK;
writel(confr, &regs->cr);
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 6d4cacdcf7..d768f5ef80 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -6,4 +6,4 @@
#
obj-$(CONFIG_DM_THERMAL) += thermal-uclass.o
-obj-$(CONFIG_IMX6_THERMAL) += imx_thermal.o
+obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 3c6c9679f9..09a3c52680 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -25,6 +25,9 @@
#define FACTOR1 15976
#define FACTOR2 4297157
#define MEASURE_FREQ 327
+#define TEMPERATURE_MIN -40
+#define TEMPERATURE_HOT 85
+#define TEMPERATURE_MAX 125
#define TEMPSENSE0_TEMP_CNT_SHIFT 8
#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
@@ -41,6 +44,7 @@ struct thermal_data {
int maxc;
};
+#if defined(CONFIG_MX6)
static int read_cpu_temperature(struct udevice *dev)
{
int temperature;
@@ -123,6 +127,73 @@ static int read_cpu_temperature(struct udevice *dev)
return temperature;
}
+#elif defined(CONFIG_MX7)
+static int read_cpu_temperature(struct udevice *dev)
+{
+ unsigned int reg, tmp, start;
+ unsigned int raw_25c, te1;
+ int temperature;
+ unsigned int *priv = dev_get_priv(dev);
+ u32 fuse = *priv;
+ struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *)
+ ANATOP_BASE_ADDR;
+ /*
+ * fuse data layout:
+ * [31:21] sensor value @ 25C
+ * [20:18] hot temperature value
+ * [17:9] sensor value of room
+ * [8:0] sensor value of hot
+ */
+
+ raw_25c = fuse >> 21;
+ if (raw_25c == 0)
+ raw_25c = 25;
+
+ te1 = (fuse >> 9) & 0x1ff;
+
+ /*
+ * now we only use single measure, every time we read
+ * the temperature, we will power on/down anadig thermal
+ * module
+ */
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense1_clr);
+ writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_set);
+
+ /* write measure freq */
+ reg = readl(&ccm_anatop->tempsense1);
+ reg &= ~TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ_MASK;
+ reg |= TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ(MEASURE_FREQ);
+ writel(reg, &ccm_anatop->tempsense1);
+
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_clr);
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr);
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_set);
+
+ start = get_timer(0);
+ /* Wait max 100ms */
+ do {
+ /*
+ * Since we can not rely on finish bit, use 1ms delay to get
+ * temperature. From RM, 17us is enough to get data, but
+ * to gurantee to get the data, delay 100ms here.
+ */
+ reg = readl(&ccm_anatop->tempsense1);
+ tmp = (reg & TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_MASK)
+ >> TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_SHIFT;
+ } while (get_timer(0) < (start + 100));
+
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr);
+
+ /* power down anatop thermal sensor */
+ writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense1_set);
+ writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_clr);
+
+ /* Single point */
+ temperature = tmp - (te1 - raw_25c);
+
+ return temperature;
+}
+#endif
int imx_thermal_get_temp(struct udevice *dev, int *temp)
{
@@ -130,6 +201,7 @@ int imx_thermal_get_temp(struct udevice *dev, int *temp)
int cpu_tmp = 0;
cpu_tmp = read_cpu_temperature(dev);
+
while (cpu_tmp >= priv->critical) {
printf("CPU Temperature (%dC) too close to max (%dC)",
cpu_tmp, priv->maxc);
@@ -157,10 +229,20 @@ static int imx_thermal_probe(struct udevice *dev)
/* Read Temperature calibration data fuse */
fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse);
- /* Check for valid fuse */
- if (fuse == 0 || fuse == ~0) {
- printf("CPU: Thermal invalid data, fuse: 0x%x\n", fuse);
- return -EPERM;
+ if (is_soc_type(MXC_SOC_MX6)) {
+ /* Check for valid fuse */
+ if (fuse == 0 || fuse == ~0) {
+ debug("CPU: Thermal invalid data, fuse: 0x%x\n",
+ fuse);
+ return -EPERM;
+ }
+ } else if (is_soc_type(MXC_SOC_MX7)) {
+ /* No Calibration data in FUSE? */
+ if ((fuse & 0x3ffff) == 0)
+ return -EPERM;
+ /* We do not support 105C TE2 */
+ if (((fuse & 0x1c0000) >> 18) == 0x6)
+ return -EPERM;
}
/* set critical cooling temp */
diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
index 8a43e7c27d..ad083cf8ae 100644
--- a/drivers/usb/eth/asix.c
+++ b/drivers/usb/eth/asix.c
@@ -10,6 +10,7 @@
#include <dm.h>
#include <usb.h>
#include <malloc.h>
+#include <memalign.h>
#include <linux/mii.h>
#include "usb_ether.h"
diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c
index 94dfe85eff..cf4085d765 100644
--- a/drivers/usb/eth/asix88179.c
+++ b/drivers/usb/eth/asix88179.c
@@ -12,6 +12,7 @@
#include <linux/mii.h>
#include "usb_ether.h"
#include <malloc.h>
+#include <memalign.h>
#include <errno.h>
/* ASIX AX88179 based USB 3.0 Ethernet Devices */
diff --git a/drivers/usb/eth/mcs7830.c b/drivers/usb/eth/mcs7830.c
index c1b708600e..bbdad8b79a 100644
--- a/drivers/usb/eth/mcs7830.c
+++ b/drivers/usb/eth/mcs7830.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <linux/mii.h>
#include <malloc.h>
+#include <memalign.h>
#include <usb.h>
#include "usb_ether.h"
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 1dcd088b8d..dc8fa8891b 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -11,6 +11,7 @@
#include <dm.h>
#include <errno.h>
#include <malloc.h>
+#include <memalign.h>
#include <usb.h>
#include <asm/unaligned.h>
#include <linux/mii.h>
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 3e8eb8799f..1ba5054965 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -87,6 +87,7 @@ static int ci_ep_enable(struct usb_ep *ep,
static int ci_ep_disable(struct usb_ep *ep);
static int ci_ep_queue(struct usb_ep *ep,
struct usb_request *req, gfp_t gfp_flags);
+static int ci_ep_dequeue(struct usb_ep *ep, struct usb_request *req);
static struct usb_request *
ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req);
@@ -99,6 +100,7 @@ static struct usb_ep_ops ci_ep_ops = {
.enable = ci_ep_enable,
.disable = ci_ep_disable,
.queue = ci_ep_queue,
+ .dequeue = ci_ep_dequeue,
.alloc_request = ci_ep_alloc_request,
.free_request = ci_ep_free_request,
};
@@ -424,7 +426,7 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
int bit, num, len, in;
struct ci_req *ci_req;
u8 *buf;
- uint32_t length, actlen;
+ uint32_t len_left, len_this_dtd;
struct ept_queue_item *dtd, *qtd;
ci_ep->req_primed = true;
@@ -442,25 +444,23 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
ci_req->dtd_count = 0;
buf = ci_req->hw_buf;
- actlen = 0;
+ len_left = len;
dtd = item;
do {
- length = min(ci_req->req.length - actlen,
- (unsigned)EP_MAX_LENGTH_TRANSFER);
+ len_this_dtd = min(len_left, (unsigned)EP_MAX_LENGTH_TRANSFER);
- dtd->info = INFO_BYTES(length) | INFO_ACTIVE;
+ dtd->info = INFO_BYTES(len_this_dtd) | INFO_ACTIVE;
dtd->page0 = (unsigned long)buf;
dtd->page1 = ((unsigned long)buf & 0xfffff000) + 0x1000;
dtd->page2 = ((unsigned long)buf & 0xfffff000) + 0x2000;
dtd->page3 = ((unsigned long)buf & 0xfffff000) + 0x3000;
dtd->page4 = ((unsigned long)buf & 0xfffff000) + 0x4000;
- len -= length;
- actlen += length;
- buf += length;
+ len_left -= len_this_dtd;
+ buf += len_this_dtd;
- if (len) {
+ if (len_left) {
qtd = (struct ept_queue_item *)
memalign(ILIST_ALIGN, ILIST_ENT_SZ);
dtd->next = (unsigned long)qtd;
@@ -469,7 +469,7 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
}
ci_req->dtd_count++;
- } while (len);
+ } while (len_left);
item = dtd;
/*
@@ -525,6 +525,30 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
writel(bit, &udc->epprime);
}
+static int ci_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct ci_ep *ci_ep = container_of(_ep, struct ci_ep, ep);
+ struct ci_req *ci_req;
+
+ list_for_each_entry(ci_req, &ci_ep->queue, queue) {
+ if (&ci_req->req == _req)
+ break;
+ }
+
+ if (&ci_req->req != _req)
+ return -EINVAL;
+
+ list_del_init(&ci_req->queue);
+
+ if (ci_req->req.status == -EINPROGRESS) {
+ ci_req->req.status = -ECONNRESET;
+ if (ci_req->req.complete)
+ ci_req->req.complete(_ep, _req);
+ }
+
+ return 0;
+}
+
static int ci_ep_queue(struct usb_ep *ep,
struct usb_request *req, gfp_t gfp_flags)
{
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index d96296cd73..a13b21d0a0 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -948,6 +948,7 @@ static void composite_unbind(struct usb_gadget *gadget)
debug("unbind config '%s'/%p\n", c->label, c);
c->unbind(c);
}
+ free(c);
}
if (composite->unbind)
composite->unbind(cdev);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 53f4672291..c5e35ee350 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -17,6 +17,7 @@
#include <net.h>
#include <usb.h>
#include <malloc.h>
+#include <memalign.h>
#include <linux/ctype.h>
#include "gadget_chips.h"
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 06139ee04d..ff1481ba37 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <common.h>
#include <malloc.h>
+#include <memalign.h>
#include <version.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index ad89a0d2e6..2fa6da4091 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -93,8 +93,6 @@ static int g_dnl_unbind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
- free(cdev->config);
- cdev->config = NULL;
debug("%s: calling usb_gadget_disconnect for "
"controller '%s'\n", __func__, gadget->name);
usb_gadget_disconnect(gadget);
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 85236aeb2a..541c0f9687 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <usb.h>
#include <malloc.h>
+#include <memalign.h>
#include <phys2bus.h>
#include <usbroothubdes.h>
#include <asm/io.h>
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 88b670b7f8..135ef72622 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -15,6 +15,7 @@
#include <usb.h>
#include <asm/io.h>
#include <malloc.h>
+#include <memalign.h>
#include <watchdog.h>
#include <linux/compiler.h>
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 0ffd838db2..9bde2b252c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -41,6 +41,7 @@
#endif
#include <malloc.h>
+#include <memalign.h>
#include <usb.h>
#include "ohci.h"
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index b17a7d762e..c66ebb6678 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <memalign.h>
#include <usb.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index 411e5a0884..d1b6d15c8e 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -1550,7 +1550,7 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
- defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
+ defined(CONFIG_ARCH_OMAP4)
static irqreturn_t generic_interrupt(int irq, void *__hci)
{
diff --git a/drivers/video/anx9804.c b/drivers/video/anx9804.c
index 83d60d672d..37ad69a039 100755
--- a/drivers/video/anx9804.c
+++ b/drivers/video/anx9804.c
@@ -14,8 +14,6 @@
#include <i2c.h>
#include "anx9804.h"
-#define BIT(x) (1 << (x))
-
/* Registers at i2c address 0x38 */
#define ANX9804_HDCP_CONTROL_0_REG 0x01
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 61d054dd89..7867fe3895 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <lcd.h>
+#include <memalign.h>
#include <asm/arch/mbox.h>
#include <asm/global_data.h>
diff --git a/drivers/video/mb862xx.c b/drivers/video/mb862xx.c
index 868c51254d..1c74e97c5e 100644
--- a/drivers/video/mb862xx.c
+++ b/drivers/video/mb862xx.c
@@ -419,7 +419,8 @@ void *video_hw_init (void)
board_disp_init ();
#endif
-#if defined(CONFIG_SOCRATES) && !(CONFIG_POST & CONFIG_SYS_POST_SYSMON)
+#if (defined(CONFIG_LWMON5) || \
+ defined(CONFIG_SOCRATES)) && !(CONFIG_POST & CONFIG_SYS_POST_SYSMON)
/* Lamp on */
board_backlight_switch (1);
#endif
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 482a4bd5be..a007ae8234 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -7,7 +7,7 @@
obj-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o
obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
-ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 vf610 ls102xa))
+ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 mx7 vf610))
obj-y += imx_watchdog.o
endif
obj-$(CONFIG_S5P) += s5p_wdt.o
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c
index 1d18d4b269..0d775956bf 100644
--- a/drivers/watchdog/imx_watchdog.c
+++ b/drivers/watchdog/imx_watchdog.c
@@ -8,19 +8,7 @@
#include <asm/io.h>
#include <watchdog.h>
#include <asm/arch/imx-regs.h>
-
-struct watchdog_regs {
- u16 wcr; /* Control */
- u16 wsr; /* Service */
- u16 wrsr; /* Reset Status */
-};
-
-#define WCR_WDZST 0x01
-#define WCR_WDBG 0x02
-#define WCR_WDE 0x04 /* WDOG enable */
-#define WCR_WDT 0x08
-#define WCR_SRS 0x10
-#define SET_WCR_WT(x) (x << 8)
+#include <fsl_wdog.h>
#ifdef CONFIG_IMX_WATCHDOG
void hw_watchdog_reset(void)
@@ -55,7 +43,8 @@ void reset_cpu(ulong addr)
{
struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
- writew(WCR_WDE, &wdog->wcr);
+ clrsetbits_le16(&wdog->wcr, 0, WCR_WDE);
+
writew(0x5555, &wdog->wsr);
writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */
while (1) {