summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile4
-rw-r--r--drivers/bootcount/bootcount_ram.c3
-rw-r--r--drivers/clk/rockchip/clk_rk3288.c7
-rw-r--r--drivers/gpio/bcm2835_gpio.c24
-rw-r--r--drivers/gpio/dwapb_gpio.c20
-rw-r--r--drivers/mtd/nand/nand_ids.c3
-rw-r--r--drivers/mtd/spi/Makefile2
-rw-r--r--drivers/mtd/spi/sandbox.c11
-rw-r--r--drivers/mtd/spi/sf.c4
-rw-r--r--drivers/mtd/spi/sf_dataflash.c178
-rw-r--r--drivers/mtd/spi/sf_internal.h72
-rw-r--r--drivers/mtd/spi/sf_params.c149
-rw-r--r--drivers/mtd/spi/spi_flash.c236
-rw-r--r--drivers/mtd/spi/spi_flash_ids.c184
-rw-r--r--drivers/mtd/spi/sunxi_spi_spl.c3
-rw-r--r--drivers/net/keystone_net.c23
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c3
-rw-r--r--drivers/net/sun8i_emac.c2
-rw-r--r--drivers/power/regulator/regulator-uclass.c28
-rw-r--r--drivers/serial/Kconfig6
-rw-r--r--drivers/serial/serial_bcm283x_mu.c46
-rw-r--r--drivers/serial/serial_lpuart.c7
-rw-r--r--drivers/serial/serial_pl01x.c2
-rw-r--r--drivers/serial/serial_pxa.c183
-rw-r--r--drivers/spi/kirkwood_spi.c15
-rw-r--r--drivers/spi/rk_spi.c44
-rw-r--r--drivers/spi/spi-uclass.c18
-rw-r--r--drivers/usb/gadget/Makefile9
-rw-r--r--drivers/video/bcm2835.c6
-rw-r--r--drivers/video/display-uclass.c18
-rw-r--r--drivers/video/rockchip/rk_hdmi.c33
-rw-r--r--drivers/video/rockchip/rk_vop.c16
-rw-r--r--drivers/video/video-uclass.c3
33 files changed, 781 insertions, 581 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 761d0b3..c19fa14 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -33,7 +33,9 @@ obj-$(CONFIG_SPL_ETH_SUPPORT) += net/
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
obj-$(CONFIG_SPL_USBETH_SUPPORT) += net/phy/
obj-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += usb/musb-new/
-obj-$(CONFIG_SPL_USBETH_SUPPORT) += usb/gadget/
+obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
+obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
+obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu/
obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/
obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/
obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
diff --git a/drivers/bootcount/bootcount_ram.c b/drivers/bootcount/bootcount_ram.c
index e0d2669..ad4cc56 100644
--- a/drivers/bootcount/bootcount_ram.c
+++ b/drivers/bootcount/bootcount_ram.c
@@ -37,7 +37,8 @@ void bootcount_store(ulong a)
/* Make sure the data is written to RAM */
flush_dcache_range((ulong)&save_addr[0],
- (ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN]);
+ (((ulong)&save_addr[REPEAT_PATTERN + OFFS_PATTERN] &
+ ~(ARCH_DMA_MINALIGN - 1)) + ARCH_DMA_MINALIGN));
}
ulong bootcount_load(void)
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index ed97e87..d15504c 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -691,6 +691,13 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
switch (clk->id) {
+ case PLL_APLL:
+ /* We only support a fixed rate here */
+ if (rate != 1800000000)
+ return -EINVAL;
+ rk3288_clk_configure_cpu(priv->cru, priv->grf);
+ new_rate = rate;
+ break;
case CLK_DDR:
new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate);
break;
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index 8dd7a28..cd5480e 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#include <fdtdec.h>
struct bcm2835_gpios {
struct bcm2835_gpio_regs *reg;
@@ -118,9 +119,32 @@ static int bcm2835_gpio_probe(struct udevice *dev)
return 0;
}
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id bcm2835_gpio_id[] = {
+ {.compatible = "brcm,bcm2835-gpio"},
+ {}
+};
+
+static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+ struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
+ fdt_addr_t addr;
+
+ addr = dev_get_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = addr;
+ return 0;
+}
+#endif
+
U_BOOT_DRIVER(gpio_bcm2835) = {
.name = "gpio_bcm2835",
.id = UCLASS_GPIO,
+ .of_match = of_match_ptr(bcm2835_gpio_id),
+ .ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata),
+ .platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata),
.ops = &gpio_bcm2835_ops,
.probe = bcm2835_gpio_probe,
.flags = DM_FLAG_PRE_RELOC,
diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c
index 471e18a..85e0a86 100644
--- a/drivers/gpio/dwapb_gpio.c
+++ b/drivers/gpio/dwapb_gpio.c
@@ -19,8 +19,8 @@
DECLARE_GLOBAL_DATA_PTR;
-#define GPIO_SWPORTA_DR 0x00
-#define GPIO_SWPORTA_DDR 0x04
+#define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc)
+#define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc)
#define GPIO_INTEN 0x30
#define GPIO_INTMASK 0x34
#define GPIO_INTTYPE_LEVEL 0x38
@@ -28,7 +28,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define GPIO_INTSTATUS 0x40
#define GPIO_PORTA_DEBOUNCE 0x48
#define GPIO_PORTA_EOI 0x4c
-#define GPIO_EXT_PORTA 0x50
+#define GPIO_EXT_PORT(p) (0x50 + (p) * 4)
struct gpio_dwapb_platdata {
const char *name;
@@ -41,7 +41,7 @@ static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin)
{
struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
- clrbits_le32(plat->base + GPIO_SWPORTA_DDR, 1 << pin);
+ clrbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
return 0;
}
@@ -50,12 +50,12 @@ static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin,
{
struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
- setbits_le32(plat->base + GPIO_SWPORTA_DDR, 1 << pin);
+ setbits_le32(plat->base + GPIO_SWPORT_DDR(plat->bank), 1 << pin);
if (val)
- setbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin);
+ setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
else
- clrbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin);
+ clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
return 0;
}
@@ -63,7 +63,7 @@ static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin,
static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin)
{
struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
- return !!(readl(plat->base + GPIO_EXT_PORTA) & (1 << pin));
+ return !!(readl(plat->base + GPIO_EXT_PORT(plat->bank)) & (1 << pin));
}
@@ -72,9 +72,9 @@ static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val)
struct gpio_dwapb_platdata *plat = dev_get_platdata(dev);
if (val)
- setbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin);
+ setbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
else
- clrbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin);
+ clrbits_le32(plat->base + GPIO_SWPORT_DR(plat->bank), 1 << pin);
return 0;
}
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index ce0a14e..d36f900 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -46,6 +46,9 @@ struct nand_flash_dev nand_flash_ids[] = {
{"TC58NVG2S0F 4G 3.3V 8-bit",
{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
+ {"TC58NVG2S0H 4G 3.3V 8-bit",
+ { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00} },
+ SZ_4K, SZ_512, SZ_256K, 0, 8, 256, NAND_ECC_INFO(8, SZ_512) },
{"TC58NVG3S0F 8G 3.3V 8-bit",
{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },
SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) },
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index f3dc409..fcda023 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o
obj-$(CONFIG_SPL_SPI_SUNXI) += sunxi_spi_spl.o
endif
-obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o
+obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index f59134f..4944059 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -88,7 +88,7 @@ struct sandbox_spi_flash {
/* The current flash status (see STAT_XXX defines above) */
u16 status;
/* Data describing the flash we're emulating */
- const struct spi_flash_params *data;
+ const struct spi_flash_info *data;
/* The file on disk to serv up data from */
int fd;
};
@@ -112,7 +112,7 @@ static int sandbox_sf_probe(struct udevice *dev)
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
const char *file;
size_t len, idname_len;
- const struct spi_flash_params *data;
+ const struct spi_flash_info *data;
struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
struct sandbox_state *state = state_get_current();
struct udevice *bus = dev->parent;
@@ -168,7 +168,7 @@ static int sandbox_sf_probe(struct udevice *dev)
}
debug("%s: device='%s'\n", __func__, spec);
- for (data = spi_flash_params_table; data->name; data++) {
+ for (data = spi_flash_ids; data->name; data++) {
len = strlen(data->name);
if (idname_len != len)
continue;
@@ -289,7 +289,7 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
/* we only support erase here */
if (sbsf->cmd == CMD_ERASE_CHIP) {
sbsf->erase_size = sbsf->data->sector_size *
- sbsf->data->nr_sectors;
+ sbsf->data->n_sectors;
} else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) {
sbsf->erase_size = 4 << 10;
} else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) {
@@ -359,7 +359,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
debug(" id: off:%u tx:", sbsf->off);
if (sbsf->off < IDCODE_LEN) {
/* Extract correct byte from ID 0x00aabbcc */
- id = sbsf->data->jedec >>
+ id = ((JEDEC_MFR(sbsf->data) << 16) |
+ JEDEC_ID(sbsf->data)) >>
(8 * (IDCODE_LEN - 1 - sbsf->off));
} else {
id = 0;
diff --git a/drivers/mtd/spi/sf.c b/drivers/mtd/spi/sf.c
index 664e860..d5e175c 100644
--- a/drivers/mtd/spi/sf.c
+++ b/drivers/mtd/spi/sf.c
@@ -18,10 +18,6 @@ static int spi_flash_read_write(struct spi_slave *spi,
unsigned long flags = SPI_XFER_BEGIN;
int ret;
-#ifdef CONFIG_SF_DUAL_FLASH
- if (spi->flags & SPI_XFER_U_PAGE)
- flags |= SPI_XFER_U_PAGE;
-#endif
if (data_len == 0)
flags |= SPI_XFER_END;
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c
index b2a56da..bcddfa0 100644
--- a/drivers/mtd/spi/sf_dataflash.c
+++ b/drivers/mtd/spi/sf_dataflash.c
@@ -1,12 +1,12 @@
/*
- *
* Atmel DataFlash probing
*
* Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc.
* Haikun Wang (haikun.wang@freescale.com)
*
* SPDX-License-Identifier: GPL-2.0+
-*/
+ */
+
#include <common.h>
#include <dm.h>
#include <errno.h>
@@ -67,15 +67,12 @@
#define OP_WRITE_SECURITY_REVC 0x9A
#define OP_WRITE_SECURITY 0x9B /* revision D */
-
struct dataflash {
uint8_t command[16];
unsigned short page_offset; /* offset in flash address */
};
-/*
- * Return the status of the DataFlash device.
- */
+/* Return the status of the DataFlash device */
static inline int dataflash_status(struct spi_slave *spi)
{
int ret;
@@ -114,9 +111,7 @@ static int dataflash_waitready(struct spi_slave *spi)
return -ETIME;
}
-/*
- * Erase pages of flash.
- */
+/* Erase pages of flash */
static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len)
{
struct dataflash *dataflash;
@@ -147,7 +142,7 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len)
status = spi_claim_bus(spi);
if (status) {
- debug("SPI DATAFLASH: unable to claim SPI bus\n");
+ debug("dataflash: unable to claim SPI bus\n");
return status;
}
@@ -232,7 +227,7 @@ static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len,
status = spi_claim_bus(spi);
if (status) {
- debug("SPI DATAFLASH: unable to claim SPI bus\n");
+ debug("dataflash: unable to claim SPI bus\n");
return status;
}
@@ -290,7 +285,7 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len,
status = spi_claim_bus(spi);
if (status) {
- debug("SPI DATAFLASH: unable to claim SPI bus\n");
+ debug("dataflash: unable to claim SPI bus\n");
return status;
}
@@ -387,7 +382,7 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len,
/* Check result of the compare operation */
if (status & (1 << 6)) {
- printf("SPI DataFlash: write compare page %u, err %d\n",
+ printf("dataflash: write compare page %u, err %d\n",
pageaddr, status);
remaining = 0;
status = -EIO;
@@ -501,9 +496,10 @@ static struct flash_info dataflash_data[] = {
{ "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
};
-static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id)
+static struct flash_info *jedec_probe(struct spi_slave *spi)
{
int tmp;
+ uint8_t id[5];
uint32_t jedec;
struct flash_info *info;
int status;
@@ -517,6 +513,11 @@ static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id)
* That's not an error; only rev C and newer chips handle it, and
* only Atmel sells these chips.
*/
+ tmp = spi_flash_cmd(spi, CMD_READ_ID, id, sizeof(id));
+ if (tmp < 0) {
+ printf("dataflash: error %d reading JEDEC ID\n", tmp);
+ return ERR_PTR(tmp);
+ }
if (id[0] != 0x1f)
return NULL;
@@ -533,7 +534,7 @@ static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id)
if (info->flags & SUP_POW2PS) {
status = dataflash_status(spi);
if (status < 0) {
- debug("SPI DataFlash: status error %d\n",
+ debug("dataflash: status error %d\n",
status);
return NULL;
}
@@ -555,10 +556,8 @@ static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id)
* size (it might be binary) even when we can tell which density
* class is involved (legacy chip id scheme).
*/
- printf("SPI DataFlash: Unsupported flash IDs: ");
- printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
- id[0], jedec, id[3] << 8 | id[4]);
- return NULL;
+ printf("dataflash: JEDEC id %06x not handled\n", jedec);
+ return ERR_PTR(-ENODEV);
}
/*
@@ -580,21 +579,15 @@ static int spi_dataflash_probe(struct udevice *dev)
struct spi_slave *spi = dev_get_parent_priv(dev);
struct spi_flash *spi_flash;
struct flash_info *info;
- u8 idcode[5];
- int ret, status = 0;
+ int status;
spi_flash = dev_get_uclass_priv(dev);
+ spi_flash->spi = spi;
spi_flash->dev = dev;
- ret = spi_claim_bus(spi);
- if (ret)
- return ret;
-
- ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
- if (ret) {
- printf("SPI DataFlash: Failed to get idcodes\n");
- goto err_read_cmd;
- }
+ status = spi_claim_bus(spi);
+ if (status)
+ return status;
/*
* Try to detect dataflash by JEDEC ID.
@@ -603,79 +596,70 @@ static int spi_dataflash_probe(struct udevice *dev)
* Both support the security register, though with different
* write procedures.
*/
- info = jedec_probe(spi, idcode);
- if (info != NULL)
- add_dataflash(dev, info->name, info->nr_pages,
- info->pagesize, info->pageoffset,
- (info->flags & SUP_POW2PS) ? 'd' : 'c');
- else {
- /*
- * Older chips support only legacy commands, identifing
- * capacity using bits in the status byte.
- */
- status = dataflash_status(spi);
- if (status <= 0 || status == 0xff) {
- printf("SPI DataFlash: read status error %d\n", status);
- if (status == 0 || status == 0xff)
- status = -ENODEV;
- goto err_read_cmd;
- }
- /*
- * if there's a device there, assume it's dataflash.
- * board setup should have set spi->max_speed_max to
- * match f(car) for continuous reads, mode 0 or 3.
- */
- switch (status & 0x3c) {
- case 0x0c: /* 0 0 1 1 x x */
- status = add_dataflash(dev, "AT45DB011B",
- 512, 264, 9, 0);
- break;
- case 0x14: /* 0 1 0 1 x x */
- status = add_dataflash(dev, "AT45DB021B",
- 1024, 264, 9, 0);
- break;
- case 0x1c: /* 0 1 1 1 x x */
- status = add_dataflash(dev, "AT45DB041x",
- 2048, 264, 9, 0);
- break;
- case 0x24: /* 1 0 0 1 x x */
- status = add_dataflash(dev, "AT45DB081B",
- 4096, 264, 9, 0);
- break;
- case 0x2c: /* 1 0 1 1 x x */
- status = add_dataflash(dev, "AT45DB161x",
- 4096, 528, 10, 0);
- break;
- case 0x34: /* 1 1 0 1 x x */
- status = add_dataflash(dev, "AT45DB321x",
- 8192, 528, 10, 0);
- break;
- case 0x38: /* 1 1 1 x x x */
- case 0x3c:
- status = add_dataflash(dev, "AT45DB642x",
- 8192, 1056, 11, 0);
- break;
- /* obsolete AT45DB1282 not (yet?) supported */
- default:
- dev_info(&spi->dev, "unsupported device (%x)\n",
- status & 0x3c);
- status = -ENODEV;
- goto err_read_cmd;
- }
+ info = jedec_probe(spi);
+ if (IS_ERR(info))
+ goto err_jedec_probe;
+ if (info != NULL) {
+ status = add_dataflash(dev, info->name, info->nr_pages,
+ info->pagesize, info->pageoffset,
+ (info->flags & SUP_POW2PS) ? 'd' : 'c');
+ if (status < 0)
+ goto err_status;
}
- /* Assign spi data */
- spi_flash->spi = spi;
- spi_flash->memory_map = spi->memory_map;
- spi_flash->dual_flash = spi->option;
+ /*
+ * Older chips support only legacy commands, identifing
+ * capacity using bits in the status byte.
+ */
+ status = dataflash_status(spi);
+ if (status <= 0 || status == 0xff) {
+ printf("dataflash: read status error %d\n", status);
+ if (status == 0 || status == 0xff)
+ status = -ENODEV;
+ goto err_jedec_probe;
+ }
- spi_release_bus(spi);
+ /*
+ * if there's a device there, assume it's dataflash.
+ * board setup should have set spi->max_speed_max to
+ * match f(car) for continuous reads, mode 0 or 3.
+ */
+ switch (status & 0x3c) {
+ case 0x0c: /* 0 0 1 1 x x */
+ status = add_dataflash(dev, "AT45DB011B", 512, 264, 9, 0);
+ break;
+ case 0x14: /* 0 1 0 1 x x */
+ status = add_dataflash(dev, "AT45DB021B", 1024, 264, 9, 0);
+ break;
+ case 0x1c: /* 0 1 1 1 x x */
+ status = add_dataflash(dev, "AT45DB041x", 2048, 264, 9, 0);
+ break;
+ case 0x24: /* 1 0 0 1 x x */
+ status = add_dataflash(dev, "AT45DB081B", 4096, 264, 9, 0);
+ break;
+ case 0x2c: /* 1 0 1 1 x x */
+ status = add_dataflash(dev, "AT45DB161x", 4096, 528, 10, 0);
+ break;
+ case 0x34: /* 1 1 0 1 x x */
+ status = add_dataflash(dev, "AT45DB321x", 8192, 528, 10, 0);
+ break;
+ case 0x38: /* 1 1 1 x x x */
+ case 0x3c:
+ status = add_dataflash(dev, "AT45DB642x", 8192, 1056, 11, 0);
+ break;
+ /* obsolete AT45DB1282 not (yet?) supported */
+ default:
+ printf("dataflash: unsupported device (%x)\n", status & 0x3c);
+ status = -ENODEV;
+ goto err_status;
+ }
- return 0;
+ return status;
-err_read_cmd:
+err_status:
+ spi_free_slave(spi);
+err_jedec_probe:
spi_release_bus(spi);
-
return status;
}
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index cde4cfb..2463686 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -23,6 +23,7 @@ enum spi_dual_flash {
enum spi_nor_option_flags {
SNOR_F_SST_WR = BIT(0),
SNOR_F_USE_FSR = BIT(1),
+ SNOR_F_USE_UPAGE = BIT(3),
};
#define SPI_FLASH_3B_ADDR_LEN 3
@@ -98,42 +99,45 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
const void *buf);
#endif
-#ifdef CONFIG_SPI_FLASH_SPANSION
-/* Used for Spansion S25FS-S family flash only. */
-#define CMD_SPANSION_RDAR 0x65 /* Read any device register */
-#define CMD_SPANSION_WRAR 0x71 /* Write any device register */
-#endif
-/**
- * struct spi_flash_params - SPI/QSPI flash device params structure
- *
- * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
- * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
- * @ext_jedec: Device ext_jedec ID
- * @sector_size: Isn't necessarily a sector size from vendor,
- * the size listed here is what works with CMD_ERASE_64K
- * @nr_sectors: No.of sectors on this device
- * @flags: Important param, for flash specific behaviour
- */
-struct spi_flash_params {
- const char *name;
- u32 jedec;
- u16 ext_jedec;
- u32 sector_size;
- u32 nr_sectors;
-
- u16 flags;
-#define SECT_4K BIT(0)
-#define E_FSR BIT(1)
-#define SST_WR BIT(2)
-#define WR_QPP BIT(3)
-#define RD_QUAD BIT(4)
-#define RD_DUAL BIT(5)
-#define RD_QUADIO BIT(6)
-#define RD_DUALIO BIT(7)
+#define JEDEC_MFR(info) ((info)->id[0])
+#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2]))
+#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4]))
+#define SPI_FLASH_MAX_ID_LEN 6
+
+struct spi_flash_info {
+ /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */
+ const char *name;
+
+ /*
+ * This array stores the ID bytes.
+ * The first three bytes are the JEDIC ID.
+ * JEDEC ID zero means "no ID" (mostly older chips).
+ */
+ u8 id[SPI_FLASH_MAX_ID_LEN];
+ u8 id_len;
+
+ /*
+ * The size listed here is what works with SPINOR_OP_SE, which isn't
+ * necessarily called a "sector" by the vendor.
+ */
+ u32 sector_size;
+ u32 n_sectors;
+
+ u16 page_size;
+
+ u16 flags;
+#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */
+#define E_FSR BIT(1) /* use flag status register for */
+#define SST_WR BIT(2) /* use SST byte/word programming */
+#define WR_QPP BIT(3) /* use Quad Page Program */
+#define RD_QUAD BIT(4) /* use Quad Read */
+#define RD_DUAL BIT(5) /* use Dual Read */
+#define RD_QUADIO BIT(6) /* use Quad IO Read */
+#define RD_DUALIO BIT(7) /* use Dual IO Read */
#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO)
};
-extern const struct spi_flash_params spi_flash_params_table[];
+extern const struct spi_flash_info spi_flash_ids[];
/* Send a single-byte command to the device and read the response */
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
@@ -182,7 +186,7 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
* - SPI claim
* - spi_flash_cmd_write_enable
* - spi_flash_cmd_write
- * - spi_flash_cmd_wait_ready
+ * - spi_flash_wait_till_ready
* - SPI release
*/
int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
deleted file mode 100644
index 5b50114..0000000
--- a/drivers/mtd/spi/sf_params.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * SPI flash Params table
- *
- * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <spi.h>
-#include <spi_flash.h>
-
-#include "sf_internal.h"
-
-/* SPI/QSPI flash device params structure */
-const struct spi_flash_params spi_flash_params_table[] = {
-#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
- {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, SECT_4K},
- {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, SECT_4K},
- {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, SECT_4K},
- {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, SECT_4K},
- {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, SECT_4K},
- {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, SECT_4K},
- {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, SECT_4K},
- {"AT25DF321A", 0x1f4701, 0x0, 64 * 1024, 64, SECT_4K},
- {"AT25DF321", 0x1f4700, 0x0, 64 * 1024, 64, SECT_4K},
- {"AT26DF081A", 0x1f4501, 0x0, 64 * 1024, 16, SECT_4K},
-#endif
-#ifdef CONFIG_SPI_FLASH_EON /* EON */
- {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0},
- {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, SECT_4K},
- {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0},
- {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0},
-#endif
-#ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */
- {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, SECT_4K},
- {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, SECT_4K},
-#endif
-#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
- {"IS25LP032", 0x9d6016, 0x0, 64 * 1024, 64, 0},
- {"IS25LP064", 0x9d6017, 0x0, 64 * 1024, 128, 0},
- {"IS25LP128", 0x9d6018, 0x0, 64 * 1024, 256, 0},
-#endif
-#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
- {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0},
- {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0},
- {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0},
- {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0},
- {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0},
- {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0},
- {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP},
- {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP},
- {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP},
- {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP},
-#endif
-#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
- {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0},
- {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0},
- {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0},
- {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0},
- {"S25FL116K", 0x014015, 0x0, 64 * 1024, 128, 0},
- {"S25FL164K", 0x014017, 0x0140, 64 * 1024, 128, 0},
- {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, RD_FULL | WR_QPP},
- {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP},
- {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP},
- {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP},
- {"S25FL128S_256K", 0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP},
- {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP},
- {"S25FL256S_256K", 0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP},
- {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP},
- {"S25FS512S", 0x010220, 0x4D00, 128 * 1024, 512, RD_FULL | WR_QPP},
- {"S25FL512S_256K", 0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP},
- {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP},
- {"S25FL512S_512K", 0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP},
-#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
- {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0},
- {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0},
- {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0},
- {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0},
- {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0},
- {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, 0},
- {"M25PX16", 0x207115, 0x1000, 64 * 1024, 32, RD_QUAD | RD_DUAL},
- {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0},
- {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0},
- {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0},
- {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, SECT_4K},
- {"N25Q016A", 0x20bb15, 0x0, 64 * 1024, 32, SECT_4K},
- {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP},
- {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP},
- {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K},
- {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K},
- {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K},
- {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K},
- {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K},
-#endif
-#ifdef CONFIG_SPI_FLASH_SST /* SST */
- {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WR},
- {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WR},
- {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WR},
- {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WR},
- {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, SECT_4K},
- {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WR},
- {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WR},
- {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WR},
- {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR},
- {"SST25WF040B", 0x621613, 0x0, 64 * 1024, 8, SECT_4K},
- {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR},
-#endif
-#ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */
- {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0},
- {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0},
- {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0},
- {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, SECT_4K},
- {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, SECT_4K},
- {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, SECT_4K},
- {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, SECT_4K},
- {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K},
- {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K},
-#endif
- {}, /* Empty entry to terminate the list */
- /*
- * Note:
- * Below paired flash devices has similar spi_flash params.
- * (S25FL129P_64K, S25FL128S_64K)
- * (W25Q80BL, W25Q80BV)
- * (W25Q16CL, W25Q16DV)
- * (W25Q32BV, W25Q32FV_SPI)
- * (W25Q64CV, W25Q64FV_SPI)
- * (W25Q128BV, W25Q128FV_SPI)
- * (W25Q32DW, W25Q32FV_QPI)
- * (W25Q64DW, W25Q64FV_QPI)
- * (W25Q128FW, W25Q128FV_QPI)
- */
-};
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 7f6e9ae..94c0b00 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -144,7 +144,7 @@ static int write_evcr(struct spi_flash *flash, u8 evcr)
#endif
#ifdef CONFIG_SPI_FLASH_BAR
-static int spi_flash_write_bar(struct spi_flash *flash, u32 offset)
+static int write_bar(struct spi_flash *flash, u32 offset)
{
u8 cmd, bank_sel;
int ret;
@@ -165,7 +165,7 @@ bar_end:
return flash->bank_curr;
}
-static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
+static int read_bar(struct spi_flash *flash, const struct spi_flash_info *info)
{
u8 curr_bank = 0;
int ret;
@@ -173,7 +173,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0)
if (flash->size <= SPI_FLASH_16MB_BOUN)
goto bar_end;
- switch (idcode0) {
+ switch (JEDEC_MFR(info)) {
case SPI_FLASH_CFI_MFR_SPANSION:
flash->bank_read_cmd = CMD_BANKADDR_BRRD;
flash->bank_write_cmd = CMD_BANKADDR_BRWR;
@@ -199,15 +199,13 @@ bar_end:
#ifdef CONFIG_SF_DUAL_FLASH
static void spi_flash_dual(struct spi_flash *flash, u32 *addr)
{
- struct spi_slave *spi = flash->spi;
-
switch (flash->dual_flash) {
case SF_DUAL_STACKED_FLASH:
if (*addr >= (flash->size >> 1)) {
*addr -= flash->size >> 1;
- spi->flags |= SPI_XFER_U_PAGE;
+ flash->flags |= SNOR_F_USE_UPAGE;
} else {
- spi->flags &= ~SPI_XFER_U_PAGE;
+ flash->flags &= ~SNOR_F_USE_UPAGE;
}
break;
case SF_DUAL_PARALLEL_FLASH:
@@ -262,8 +260,8 @@ static int spi_flash_ready(struct spi_flash *flash)
return sr && fsr;
}
-static int spi_flash_cmd_wait_ready(struct spi_flash *flash,
- unsigned long timeout)
+static int spi_flash_wait_till_ready(struct spi_flash *flash,
+ unsigned long timeout)
{
unsigned long timebase;
int ret;
@@ -311,7 +309,7 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
return ret;
}
- ret = spi_flash_cmd_wait_ready(flash, timeout);
+ ret = spi_flash_wait_till_ready(flash, timeout);
if (ret < 0) {
debug("SF: write %s timed out\n",
timeout == SPI_FLASH_PROG_TIMEOUT ?
@@ -353,7 +351,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
spi_flash_dual(flash, &erase_addr);
#endif
#ifdef CONFIG_SPI_FLASH_BAR
- ret = spi_flash_write_bar(flash, erase_addr);
+ ret = write_bar(flash, erase_addr);
if (ret < 0)
return ret;
#endif
@@ -404,7 +402,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
spi_flash_dual(flash, &write_addr);
#endif
#ifdef CONFIG_SPI_FLASH_BAR
- ret = spi_flash_write_bar(flash, write_addr);
+ ret = write_bar(flash, write_addr);
if (ret < 0)
return ret;
#endif
@@ -508,7 +506,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
spi_flash_dual(flash, &read_addr);
#endif
#ifdef CONFIG_SPI_FLASH_BAR
- ret = spi_flash_write_bar(flash, read_addr);
+ ret = write_bar(flash, read_addr);
if (ret < 0)
return ret;
bank_sel = flash->bank_curr;
@@ -560,7 +558,7 @@ static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
if (ret)
return ret;
- return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ return spi_flash_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT);
}
int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
@@ -608,7 +606,7 @@ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
break;
}
- ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+ ret = spi_flash_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT);
if (ret)
break;
@@ -924,9 +922,35 @@ static int micron_quad_enable(struct spi_flash *flash)
}
#endif
-static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
+static const struct spi_flash_info *spi_flash_read_id(struct spi_flash *flash)
{
- switch (idcode0) {
+ int tmp;
+ u8 id[SPI_FLASH_MAX_ID_LEN];
+ const struct spi_flash_info *info;
+
+ tmp = spi_flash_cmd(flash->spi, CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN);
+ if (tmp < 0) {
+ printf("SF: error %d reading JEDEC ID\n", tmp);
+ return ERR_PTR(tmp);
+ }
+
+ info = spi_flash_ids;
+ for (; info->name != NULL; info++) {
+ if (info->id_len) {
+ if (!memcmp(info->id, id, info->id_len))
+ return info;
+ }
+ }
+
+ printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
+ id[0], id[1], id[2]);
+ return ERR_PTR(-ENODEV);
+}
+
+static int set_quad_mode(struct spi_flash *flash,
+ const struct spi_flash_info *info)
+{
+ switch (JEDEC_MFR(info)) {
#ifdef CONFIG_SPI_FLASH_MACRONIX
case SPI_FLASH_CFI_MFR_MACRONIX:
return macronix_quad_enable(flash);
@@ -941,7 +965,8 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
return micron_quad_enable(flash);
#endif
default:
- printf("SF: Need set QEB func for %02x flash\n", idcode0);
+ printf("SF: Need set QEB func for %02x flash\n",
+ JEDEC_MFR(info));
return -1;
}
}
@@ -971,138 +996,28 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
}
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
-#ifdef CONFIG_SPI_FLASH_SPANSION
-static int spansion_s25fss_disable_4KB_erase(struct spi_slave *spi)
-{
- u8 cmd[4];
- u32 offset = 0x800004; /* CR3V register offset */
- u8 cr3v;
- int ret;
-
- cmd[0] = CMD_SPANSION_RDAR;
- cmd[1] = offset >> 16;
- cmd[2] = offset >> 8;
- cmd[3] = offset >> 0;
-
- ret = spi_flash_cmd_read(spi, cmd, 4, &cr3v, 1);
- if (ret)
- return -EIO;
- /* CR3V bit3: 4-KB Erase */
- if (cr3v & 0x8)
- return 0;
-
- cmd[0] = CMD_SPANSION_WRAR;
- cr3v |= 0x8;
- ret = spi_flash_cmd_write(spi, cmd, 4, &cr3v, 1);
- if (ret)
- return -EIO;
-
- cmd[0] = CMD_SPANSION_RDAR;
- ret = spi_flash_cmd_read(spi, cmd, 4, &cr3v, 1);
- if (ret)
- return -EIO;
- if (!(cr3v & 0x8))
- return -EFAULT;
-
- return 0;
-}
-#endif
-
int spi_flash_scan(struct spi_flash *flash)
{
struct spi_slave *spi = flash->spi;
- const struct spi_flash_params *params;
- u16 jedec, ext_jedec;
- u8 idcode[5];
- int ret;
-
- /* Read the ID codes */
- ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
- if (ret) {
- printf("SF: Failed to get idcodes\n");
- return ret;
- }
-
-#ifdef DEBUG
- printf("SF: Got idcodes\n");
- print_buffer(0, idcode, 1, sizeof(idcode), 0);
-#endif
-
- jedec = idcode[1] << 8 | idcode[2];
- ext_jedec = idcode[3] << 8 | idcode[4];
-
- /* Validate params from spi_flash_params table */
- params = spi_flash_params_table;
- for (; params->name != NULL; params++) {
- if ((params->jedec >> 16) == idcode[0]) {
- if ((params->jedec & 0xFFFF) == jedec) {
- if (params->ext_jedec == 0)
- break;
- else if (params->ext_jedec == ext_jedec)
- break;
- }
- }
- }
-
- if (!params->name) {
- printf("SF: Unsupported flash IDs: ");
- printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
- idcode[0], jedec, ext_jedec);
- return -EPROTONOSUPPORT;
- }
-
-#ifdef CONFIG_SPI_FLASH_SPANSION
- /*
- * The S25FS-S family physical sectors may be configured as a
- * hybrid combination of eight 4-kB parameter sectors
- * at the top or bottom of the address space with all
- * but one of the remaining sectors being uniform size.
- * The Parameter Sector Erase commands (20h or 21h) must
- * be used to erase the 4-kB parameter sectors individually.
- * The Sector (uniform sector) Erase commands (D8h or DCh)
- * must be used to erase any of the remaining
- * sectors, including the portion of highest or lowest address
- * sector that is not overlaid by the parameter sectors.
- * The uniform sector erase command has no effect on parameter sectors.
- */
- if ((jedec == 0x0219 || (jedec == 0x0220)) &&
- (ext_jedec & 0xff00) == 0x4d00) {
- int ret;
- u8 id[6];
-
- /* Read the ID codes again, 6 bytes */
- ret = spi_flash_cmd(flash->spi, CMD_READ_ID, id, sizeof(id));
- if (ret)
- return -EIO;
+ const struct spi_flash_info *info = NULL;
+ int ret = -1;
- ret = memcmp(id, idcode, 5);
- if (ret)
- return -EIO;
+ info = spi_flash_read_id(flash);
+ if (IS_ERR_OR_NULL(info))
+ return -ENOENT;
- /* 0x81: S25FS-S family 0x80: S25FL-S family */
- if (id[5] == 0x81) {
- ret = spansion_s25fss_disable_4KB_erase(spi);
- if (ret)
- return ret;
- }
- }
-#endif
/* Flash powers up read-only, so clear BP# bits */
- if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL ||
- idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX ||
- idcode[0] == SPI_FLASH_CFI_MFR_SST)
+ if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_ATMEL ||
+ JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX ||
+ JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST)
write_sr(flash, 0);
- /* Assign spi data */
- flash->name = params->name;
+ flash->name = info->name;
flash->memory_map = spi->memory_map;
- flash->dual_flash = spi->option;
- /* Assign spi flash flags */
- if (params->flags & SST_WR)
+ if (info->flags & SST_WR)
flash->flags |= SNOR_F_SST_WR;
- /* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
flash->write = spi_flash_cmd_write_ops;
#if defined(CONFIG_SPI_FLASH_SST)
@@ -1117,39 +1032,33 @@ int spi_flash_scan(struct spi_flash *flash)
flash->read = spi_flash_cmd_read_ops;
#endif
- /* lock hooks are flash specific - assign them based on idcode0 */
- switch (idcode[0]) {
#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
- case SPI_FLASH_CFI_MFR_STMICRO:
- case SPI_FLASH_CFI_MFR_SST:
+ /* NOR protection support for STmicro/Micron chips and similar */
+ if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_STMICRO ||
+ JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) {
flash->flash_lock = stm_lock;
flash->flash_unlock = stm_unlock;
flash->flash_is_locked = stm_is_locked;
-#endif
- break;
- default:
- debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
}
+#endif
/* Compute the flash size */
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
+ flash->page_size = info->page_size;
/*
* The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
* 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
* the 0x4d00 Extended JEDEC code have 512b pages. All of the others
* have 256b pages.
*/
- if (ext_jedec == 0x4d00) {
- if ((jedec == 0x0215) || (jedec == 0x216) || (jedec == 0x220))
- flash->page_size = 256;
- else
+ if (JEDEC_EXT(info) == 0x4d00) {
+ if ((JEDEC_ID(info) != 0x0215) &&
+ (JEDEC_ID(info) != 0x0216))
flash->page_size = 512;
- } else {
- flash->page_size = 256;
}
flash->page_size <<= flash->shift;
- flash->sector_size = params->sector_size << flash->shift;
- flash->size = flash->sector_size * params->nr_sectors << flash->shift;
+ flash->sector_size = info->sector_size << flash->shift;
+ flash->size = flash->sector_size * info->n_sectors << flash->shift;
#ifdef CONFIG_SF_DUAL_FLASH
if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
flash->size <<= 1;
@@ -1157,7 +1066,7 @@ int spi_flash_scan(struct spi_flash *flash)
#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS
/* Compute erase sector and command */
- if (params->flags & SECT_4K) {
+ if (info->flags & SECT_4K) {
flash->erase_cmd = CMD_ERASE_4K;
flash->erase_size = 4096 << flash->shift;
} else
@@ -1174,13 +1083,13 @@ int spi_flash_scan(struct spi_flash *flash)
flash->read_cmd = CMD_READ_ARRAY_FAST;
if (spi->mode & SPI_RX_SLOW)
flash->read_cmd = CMD_READ_ARRAY_SLOW;
- else if (spi->mode & SPI_RX_QUAD && params->flags & RD_QUAD)
+ else if (spi->mode & SPI_RX_QUAD && info->flags & RD_QUAD)
flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST;
- else if (spi->mode & SPI_RX_DUAL && params->flags & RD_DUAL)
+ else if (spi->mode & SPI_RX_DUAL && info->flags & RD_DUAL)
flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST;
/* Look for write commands */
- if (params->flags & WR_QPP && spi->mode & SPI_TX_QUAD)
+ if (info->flags & WR_QPP && spi->mode & SPI_TX_QUAD)
flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
else
/* Go for default supported write cmd */
@@ -1190,9 +1099,10 @@ int spi_flash_scan(struct spi_flash *flash)
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
(flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
(flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
- ret = set_quad_mode(flash, idcode[0]);
+ ret = set_quad_mode(flash, info);
if (ret) {
- debug("SF: Fail to set QEB for %02x\n", idcode[0]);
+ debug("SF: Fail to set QEB for %02x\n",
+ JEDEC_MFR(info));
return -EINVAL;
}
}
@@ -1217,18 +1127,18 @@ int spi_flash_scan(struct spi_flash *flash)
}
#ifdef CONFIG_SPI_FLASH_STMICRO
- if (params->flags & E_FSR)
+ if (info->flags & E_FSR)
flash->flags |= SNOR_F_USE_FSR;
#endif
/* Configure the BAR - discover bank cmds and read current bank */
#ifdef CONFIG_SPI_FLASH_BAR
- ret = spi_flash_read_bar(flash, idcode[0]);
+ ret = read_bar(flash, info);
if (ret < 0)
return ret;
#endif
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
ret = spi_flash_decode_fdt(gd->fdt_blob, flash);
if (ret) {
debug("SF: FDT decode error\n");
diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c
new file mode 100644
index 0000000..edca94e
--- /dev/null
+++ b/drivers/mtd/spi/spi_flash_ids.c
@@ -0,0 +1,184 @@
+/*
+ * SPI Flash ID's.
+ *
+ * Copyright (C) 2016 Jagan Teki <jagan@openedev.com>
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <spi_flash.h>
+
+#include "sf_internal.h"
+
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+ .id = { \
+ ((_jedec_id) >> 16) & 0xff, \
+ ((_jedec_id) >> 8) & 0xff, \
+ (_jedec_id) & 0xff, \
+ ((_ext_id) >> 8) & 0xff, \
+ (_ext_id) & 0xff, \
+ }, \
+ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \
+ .sector_size = (_sector_size), \
+ .n_sectors = (_n_sectors), \
+ .page_size = 256, \
+ .flags = (_flags),
+
+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+ .id = { \
+ ((_jedec_id) >> 16) & 0xff, \
+ ((_jedec_id) >> 8) & 0xff, \
+ (_jedec_id) & 0xff, \
+ ((_ext_id) >> 16) & 0xff, \
+ ((_ext_id) >> 8) & 0xff, \
+ (_ext_id) & 0xff, \
+ }, \
+ .id_len = 6, \
+ .sector_size = (_sector_size), \
+ .n_sectors = (_n_sectors), \
+ .page_size = 256, \
+ .flags = (_flags),
+
+const struct spi_flash_info spi_flash_ids[] = {
+#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
+ {"at45db011d", INFO(0x1f2200, 0x0, 64 * 1024, 4, SECT_4K) },
+ {"at45db021d", INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K) },
+ {"at45db041d", INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K) },
+ {"at45db081d", INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K) },
+ {"at45db161d", INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K) },
+ {"at45db321d", INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K) },
+ {"at45db641d", INFO(0x1f2800, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"at25df321a", INFO(0x1f4701, 0x0, 64 * 1024, 64, SECT_4K) },
+ {"at25df321", INFO(0x1f4700, 0x0, 64 * 1024, 64, SECT_4K) },
+ {"at26df081a", INFO(0x1f4501, 0x0, 64 * 1024, 16, SECT_4K) },
+#endif
+#ifdef CONFIG_SPI_FLASH_EON /* EON */
+ {"en25q32b", INFO(0x1c3016, 0x0, 64 * 1024, 64, 0) },
+ {"en25q64", INFO(0x1c3017, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"en25q128b", INFO(0x1c3018, 0x0, 64 * 1024, 256, 0) },
+ {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) },
+#endif
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */
+ {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"gd25lq32", INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K) },
+#endif
+#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
+ {"is25lp032", INFO(0x9d6016, 0x0, 64 * 1024, 64, 0) },
+ {"is25lp064", INFO(0x9d6017, 0x0, 64 * 1024, 128, 0) },
+ {"is25lp128", INFO(0x9d6018, 0x0, 64 * 1024, 256, 0) },
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
+ {"mx25l2006e", INFO(0xc22012, 0x0, 64 * 1024, 4, 0) },
+ {"mx25l4005", INFO(0xc22013, 0x0, 64 * 1024, 8, 0) },
+ {"mx25l8005", INFO(0xc22014, 0x0, 64 * 1024, 16, 0) },
+ {"mx25l1605d", INFO(0xc22015, 0x0, 64 * 1024, 32, 0) },
+ {"mx25l3205d", INFO(0xc22016, 0x0, 64 * 1024, 64, 0) },
+ {"mx25l6405d", INFO(0xc22017, 0x0, 64 * 1024, 128, 0) },
+ {"mx25l12805", INFO(0xc22018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"mx25l25635f", INFO(0xc22019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP) },
+ {"mx25l51235f", INFO(0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) },
+ {"mx25l12855e", INFO(0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) },
+ {"mx66l1g45g", INFO(0xc2201b, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP) },
+#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
+ {"s25fl008a", INFO(0x010213, 0x0, 64 * 1024, 16, 0) },
+ {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) },
+ {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) },
+ {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) },
+ {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 128, 0) },
+ {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) },
+ {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64, RD_FULL | WR_QPP) },
+ {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) },
+ {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) },
+ {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) },
+ {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) },
+ {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) },
+ {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+ {"s25fs512s", INFO6(0x010220, 0x4d0081, 128 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+ {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) },
+ {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) },
+ {"s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP) },
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
+ {"m25p10", INFO(0x202011, 0x0, 32 * 1024, 4, 0) },
+ {"m25p20", INFO(0x202012, 0x0, 64 * 1024, 4, 0) },
+ {"m25p40", INFO(0x202013, 0x0, 64 * 1024, 8, 0) },
+ {"m25p80", INFO(0x202014, 0x0, 64 * 1024, 16, 0) },
+ {"m25p16", INFO(0x202015, 0x0, 64 * 1024, 32, 0) },
+ {"m25pE16", INFO(0x208015, 0x1000, 64 * 1024, 32, 0) },
+ {"m25pX16", INFO(0x207115, 0x1000, 64 * 1024, 32, RD_QUAD | RD_DUAL) },
+ {"m25p32", INFO(0x202016, 0x0, 64 * 1024, 64, 0) },
+ {"m25p64", INFO(0x202017, 0x0, 64 * 1024, 128, 0) },
+ {"m25p128", INFO(0x202018, 0x0, 256 * 1024, 64, 0) },
+ {"m25pX64", INFO(0x207117, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"n25q016a", INFO(0x20bb15, 0x0, 64 * 1024, 32, SECT_4K) },
+ {"n25q32", INFO(0x20ba16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q32a", INFO(0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q64", INFO(0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q64a", INFO(0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q128", INFO(0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"n25q128a", INFO(0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"n25q256", INFO(0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q256a", INFO(0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+ {"n25q512", INFO(0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+ {"n25q512a", INFO(0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+ {"n25q1024", INFO(0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+ {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+ {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+ {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+#endif
+#ifdef CONFIG_SPI_FLASH_SST /* SST */
+ {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) },
+ {"sst25vf080b", INFO(0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) },
+ {"sst25vf016b", INFO(0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WR) },
+ {"sst25vf032b", INFO(0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WR) },
+ {"sst25vf064c", INFO(0xbf254b, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"sst25wf512", INFO(0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WR) },
+ {"sst25wf010", INFO(0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WR) },
+ {"sst25wf020", INFO(0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WR) },
+ {"sst25wf040", INFO(0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) },
+ {"sst25wf040b", INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K) },
+ {"sst25wf080", INFO(0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) },
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */
+ {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) },
+ {"w25p16", INFO(0xef2015, 0x0, 64 * 1024, 32, 0) },
+ {"w25p32", INFO(0xef2016, 0x0, 64 * 1024, 64, 0) },
+ {"w25x40", INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K) },
+ {"w25x16", INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K) },
+ {"w25x32", INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K) },
+ {"w25x64", INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K) },
+ {"w25q80bl", INFO(0xef4014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q16cl", INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q32bv", INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q64cv", INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q128bv", INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q256", INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q80bw", INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q16dw", INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q32dw", INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q64dw", INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) },
+ {"w25q128fw", INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) },
+#endif
+ {}, /* Empty entry to terminate the list */
+ /*
+ * Note:
+ * Below paired flash devices has similar spi_flash params.
+ * (s25fl129p_64k, s25fl128s_64k)
+ * (w25q80bl, w25q80bv)
+ * (w25q16cl, w25q16dv)
+ * (w25q32bv, w25q32fv_spi)
+ * (w25q64cv, w25q64fv_spi)
+ * (w25q128bv, w25q128fv_spi)
+ * (w25q32dw, w25q32fv_qpi)
+ * (w25q64dw, w25q64fv_qpi)
+ * (w25q128fw, w25q128fv_qpi)
+ */
+};
diff --git a/drivers/mtd/spi/sunxi_spi_spl.c b/drivers/mtd/spi/sunxi_spi_spl.c
index 67c7edd..7502314 100644
--- a/drivers/mtd/spi/sunxi_spi_spl.c
+++ b/drivers/mtd/spi/sunxi_spi_spl.c
@@ -158,9 +158,10 @@ static void spi0_disable_clock(void)
(1 << AHB_RESET_SPI0_SHIFT));
}
-static int spi0_init(void)
+static void spi0_init(void)
{
unsigned int pin_function = SUNXI_GPC_SPI0;
+
if (IS_ENABLED(CONFIG_MACH_SUN50I))
pin_function = SUN50I_GPC_SPI0;
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index f88d83e..a5120e0 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -56,13 +56,16 @@ struct rx_buff_desc net_rx_buffs = {
#ifdef CONFIG_DM_ETH
enum link_type {
- LINK_TYPE_MAC_TO_MAC_AUTO = 0,
- LINK_TYPE_MAC_TO_PHY_MODE = 1,
- LINK_TYPE_MAC_TO_MAC_FORCED_MODE = 2,
- LINK_TYPE_MAC_TO_FIBRE_MODE = 3,
- LINK_TYPE_MAC_TO_PHY_NO_MDIO_MODE = 4,
- LINK_TYPE_10G_MAC_TO_PHY_MODE = 10,
- LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11,
+ LINK_TYPE_SGMII_MAC_TO_MAC_AUTO = 0,
+ LINK_TYPE_SGMII_MAC_TO_PHY_MODE = 1,
+ LINK_TYPE_SGMII_MAC_TO_MAC_FORCED_MODE = 2,
+ LINK_TYPE_SGMII_MAC_TO_FIBRE_MODE = 3,
+ LINK_TYPE_SGMII_MAC_TO_PHY_NO_MDIO_MODE = 4,
+ LINK_TYPE_RGMII_LINK_MAC_PHY = 5,
+ LINK_TYPE_RGMII_LINK_MAC_MAC_FORCED = 6,
+ LINK_TYPE_RGMII_LINK_MAC_PHY_NO_MDIO = 7,
+ LINK_TYPE_10G_MAC_TO_PHY_MODE = 10,
+ LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11,
};
#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
@@ -1077,11 +1080,15 @@ static int ks2_eth_parse_slave_interface(int netcp, int slave,
priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
}
- if (priv->link_type == LINK_TYPE_MAC_TO_PHY_MODE) {
+ if (priv->link_type == LINK_TYPE_SGMII_MAC_TO_PHY_MODE) {
priv->phy_if = PHY_INTERFACE_MODE_SGMII;
pdata->phy_interface = priv->phy_if;
priv->sgmii_link_type = SGMII_LINK_MAC_PHY;
priv->has_mdio = true;
+ } else if (priv->link_type == LINK_TYPE_RGMII_LINK_MAC_PHY) {
+ priv->phy_if = PHY_INTERFACE_MODE_RGMII;
+ pdata->phy_interface = priv->phy_if;
+ priv->has_mdio = true;
}
return 0;
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index 75b2b6b..4e61700 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -420,13 +420,14 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
goto err_dpmac_setup;
#ifdef CONFIG_PHYLIB
- if (priv->phydev)
+ if (priv->phydev) {
err = phy_startup(priv->phydev);
if (err) {
printf("%s: Could not initialize\n",
priv->phydev->dev->name);
goto err_dpamc_bind;
}
+ }
#else
priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device));
memset(priv->phydev, 0, sizeof(struct phy_device));
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 6ac8ba3..abd9cc8 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -180,8 +180,8 @@ static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
miiaddr |= MDIO_CMD_MII_WRITE;
miiaddr |= MDIO_CMD_MII_BUSY;
- writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
writel(val, priv->mac_reg + EMAC_MII_DATA);
+ writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
start = get_timer(0);
while (get_timer(start) < timeout) {
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 4434e36..52a1070 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -41,6 +41,27 @@ int regulator_get_value(struct udevice *dev)
int regulator_set_value(struct udevice *dev, int uV)
{
const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
+ return -EINVAL;
+ if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
+ return -EINVAL;
+
+ if (!ops || !ops->set_value)
+ return -ENOSYS;
+
+ return ops->set_value(dev, uV);
+}
+
+/*
+ * To be called with at most caution as there is no check
+ * before setting the actual voltage value.
+ */
+int regulator_set_value_force(struct udevice *dev, int uV)
+{
+ const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_value)
return -ENOSYS;
@@ -61,6 +82,13 @@ int regulator_get_current(struct udevice *dev)
int regulator_set_current(struct udevice *dev, int uA)
{
const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA)
+ return -EINVAL;
+ if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA)
+ return -EINVAL;
if (!ops || !ops->set_current)
return -ENOSYS;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 56c024f..620dd82 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -407,4 +407,10 @@ config MSM_SERIAL
for example APQ8016 and MSM8916.
Single baudrate is supported in current implementation (115200).
+config PXA_SERIAL
+ bool "PXA serial port support"
+ help
+ If you have a machine based on a Marvell XScale PXA2xx CPU you
+ can enable its onboard serial ports by enabling this option.
+
endmenu
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c
index f4e062f..3884f74 100644
--- a/drivers/serial/serial_bcm283x_mu.c
+++ b/drivers/serial/serial_bcm283x_mu.c
@@ -25,6 +25,8 @@
#include <linux/compiler.h>
#include <fdtdec.h>
+DECLARE_GLOBAL_DATA_PTR;
+
struct bcm283x_mu_regs {
u32 io;
u32 iir;
@@ -57,7 +59,7 @@ static int bcm283x_mu_serial_setbrg(struct udevice *dev, int baudrate)
struct bcm283x_mu_regs *regs = priv->regs;
u32 divider;
- if (plat->skip_init)
+ if (plat->disabled || plat->skip_init)
return 0;
divider = plat->clock / (baudrate * 8);
@@ -83,10 +85,14 @@ static int bcm283x_mu_serial_probe(struct udevice *dev)
static int bcm283x_mu_serial_getc(struct udevice *dev)
{
+ struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
struct bcm283x_mu_priv *priv = dev_get_priv(dev);
struct bcm283x_mu_regs *regs = priv->regs;
u32 data;
+ if (plat->disabled)
+ return -EAGAIN;
+
/* Wait until there is data in the FIFO */
if (!(readl(&regs->lsr) & BCM283X_MU_LSR_RX_READY))
return -EAGAIN;
@@ -98,9 +104,13 @@ static int bcm283x_mu_serial_getc(struct udevice *dev)
static int bcm283x_mu_serial_putc(struct udevice *dev, const char data)
{
+ struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
struct bcm283x_mu_priv *priv = dev_get_priv(dev);
struct bcm283x_mu_regs *regs = priv->regs;
+ if (plat->disabled)
+ return 0;
+
/* Wait until there is space in the FIFO */
if (!(readl(&regs->lsr) & BCM283X_MU_LSR_TX_EMPTY))
return -EAGAIN;
@@ -113,9 +123,15 @@ static int bcm283x_mu_serial_putc(struct udevice *dev, const char data)
static int bcm283x_mu_serial_pending(struct udevice *dev, bool input)
{
+ struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
struct bcm283x_mu_priv *priv = dev_get_priv(dev);
struct bcm283x_mu_regs *regs = priv->regs;
- unsigned int lsr = readl(&regs->lsr);
+ unsigned int lsr;
+
+ if (plat->disabled)
+ return 0;
+
+ lsr = readl(&regs->lsr);
if (input) {
WATCHDOG_RESET();
@@ -132,9 +148,35 @@ static const struct dm_serial_ops bcm283x_mu_serial_ops = {
.setbrg = bcm283x_mu_serial_setbrg,
};
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id bcm283x_mu_serial_id[] = {
+ {.compatible = "brcm,bcm2835-aux-uart"},
+ {}
+};
+
+static int bcm283x_mu_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
+ fdt_addr_t addr;
+
+ addr = dev_get_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = addr;
+ plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock", 1);
+ plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "skip-init");
+ plat->disabled = false;
+ return 0;
+}
+#endif
+
U_BOOT_DRIVER(serial_bcm283x_mu) = {
.name = "serial_bcm283x_mu",
.id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(bcm283x_mu_serial_id),
+ .ofdata_to_platdata = of_match_ptr(bcm283x_mu_serial_ofdata_to_platdata),
.platdata_auto_alloc_size = sizeof(struct bcm283x_mu_serial_platdata),
.probe = bcm283x_mu_serial_probe,
.ops = &bcm283x_mu_serial_ops,
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 042e9a2..beb4243 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -170,9 +170,14 @@ static int lpuart_serial_probe(struct udevice *dev)
}
#else
+u32 __weak get_lpuart_clk(void)
+{
+ return CONFIG_SYS_CLK_FREQ;
+}
+
static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate)
{
- u32 clk = CONFIG_SYS_CLK_FREQ;
+ u32 clk = get_lpuart_clk();
u32 sbr;
sbr = (clk / (16 * baudrate));
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 6f83835..a8d3d67 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -356,6 +356,8 @@ static int pl01x_serial_ofdata_to_platdata(struct udevice *dev)
plat->base = addr;
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock", 1);
plat->type = dev_get_driver_data(dev);
+ plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "skip-init");
return 0;
}
#endif
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index 1eb19ec..ea5971b 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -14,6 +14,9 @@
*
* Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
*
+ * Modified to add driver model (DM) support
+ * (C) Copyright 2016 Marcel Ziswiler <marcel.ziswiler@toradex.com>
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -21,73 +24,17 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/regs-uart.h>
#include <asm/io.h>
+#include <dm.h>
+#include <dm/platform_data/serial_pxa.h>
#include <linux/compiler.h>
#include <serial.h>
#include <watchdog.h>
DECLARE_GLOBAL_DATA_PTR;
-/*
- * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can
- * easily handle enabling of clock.
- */
-#ifdef CONFIG_CPU_MONAHANS
-#define UART_CLK_BASE CKENA_21_BTUART
-#define UART_CLK_REG CKENA
-#define BTUART_INDEX 0
-#define FFUART_INDEX 1
-#define STUART_INDEX 2
-#elif CONFIG_CPU_PXA25X
-#define UART_CLK_BASE (1 << 4) /* HWUART */
-#define UART_CLK_REG CKEN
-#define HWUART_INDEX 0
-#define STUART_INDEX 1
-#define FFUART_INDEX 2
-#define BTUART_INDEX 3
-#else /* PXA27x */
-#define UART_CLK_BASE CKEN5_STUART
-#define UART_CLK_REG CKEN
-#define STUART_INDEX 0
-#define FFUART_INDEX 1
-#define BTUART_INDEX 2
-#endif
-
-/*
- * Only PXA250 has HWUART, to avoid poluting the code with more macros,
- * artificially introduce this.
- */
-#ifndef CONFIG_CPU_PXA25X
-#define HWUART_INDEX 0xff
-#endif
-
-static uint32_t pxa_uart_get_baud_divider(void)
-{
- if (gd->baudrate == 1200)
- return 768;
- else if (gd->baudrate == 9600)
- return 96;
- else if (gd->baudrate == 19200)
- return 48;
- else if (gd->baudrate == 38400)
- return 24;
- else if (gd->baudrate == 57600)
- return 16;
- else if (gd->baudrate == 115200)
- return 8;
- else /* Unsupported baudrate */
- return 0;
-}
-
-static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
+static uint32_t pxa_uart_get_baud_divider(int baudrate)
{
- switch (uart_index) {
- case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
- case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
- case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
- case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
- default:
- return NULL;
- }
+ return 921600 / baudrate;
}
static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
@@ -110,20 +57,14 @@ static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
/*
* Enable clock and set baud rate, parity etc.
*/
-void pxa_setbrg_dev(uint32_t uart_index)
+void pxa_setbrg_common(struct pxa_uart_regs *uart_regs, int port, int baudrate)
{
- uint32_t divider = 0;
- struct pxa_uart_regs *uart_regs;
-
- divider = pxa_uart_get_baud_divider();
+ uint32_t divider = pxa_uart_get_baud_divider(baudrate);
if (!divider)
hang();
- uart_regs = pxa_uart_index_to_regs(uart_index);
- if (!uart_regs)
- hang();
- pxa_uart_toggle_clock(uart_index, 1);
+ pxa_uart_toggle_clock(port, 1);
/* Disable interrupts and FIFOs */
writel(0, &uart_regs->ier);
@@ -139,13 +80,38 @@ void pxa_setbrg_dev(uint32_t uart_index)
writel(IER_UUE, &uart_regs->ier);
}
+#ifndef CONFIG_DM_SERIAL
+static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
+{
+ switch (uart_index) {
+ case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
+ case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
+ case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
+ case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * Enable clock and set baud rate, parity etc.
+ */
+void pxa_setbrg_dev(uint32_t uart_index)
+{
+ struct pxa_uart_regs *uart_regs = pxa_uart_index_to_regs(uart_index);
+ if (!uart_regs)
+ panic("Failed getting UART registers\n");
+
+ pxa_setbrg_common(uart_regs, uart_index, gd->baudrate);
+}
+
/*
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
int pxa_init_dev(unsigned int uart_index)
{
- pxa_setbrg_dev (uart_index);
+ pxa_setbrg_dev(uart_index);
return 0;
}
@@ -297,3 +263,80 @@ void pxa_serial_initialize(void)
serial_register(&serial_stuart_device);
#endif
}
+#endif /* CONFIG_DM_SERIAL */
+
+#ifdef CONFIG_DM_SERIAL
+static int pxa_serial_probe(struct udevice *dev)
+{
+ struct pxa_serial_platdata *plat = dev->platdata;
+
+ pxa_setbrg_common((struct pxa_uart_regs *)plat->base, plat->port,
+ plat->baudrate);
+ return 0;
+}
+
+static int pxa_serial_putc(struct udevice *dev, const char ch)
+{
+ struct pxa_serial_platdata *plat = dev->platdata;
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ /* Wait for last character to go. */
+ if (!(readl(&uart_regs->lsr) & LSR_TEMT))
+ return -EAGAIN;
+
+ writel(ch, &uart_regs->thr);
+
+ return 0;
+}
+
+static int pxa_serial_getc(struct udevice *dev)
+{
+ struct pxa_serial_platdata *plat = dev->platdata;
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ /* Wait for a character to arrive. */
+ if (!(readl(&uart_regs->lsr) & LSR_DR))
+ return -EAGAIN;
+
+ return readl(&uart_regs->rbr) & 0xff;
+}
+
+int pxa_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct pxa_serial_platdata *plat = dev->platdata;
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+ int port = plat->port;
+
+ pxa_setbrg_common(uart_regs, port, baudrate);
+
+ return 0;
+}
+
+static int pxa_serial_pending(struct udevice *dev, bool input)
+{
+ struct pxa_serial_platdata *plat = dev->platdata;
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ if (input)
+ return readl(&uart_regs->lsr) & LSR_DR ? 1 : 0;
+ else
+ return readl(&uart_regs->lsr) & LSR_TEMT ? 0 : 1;
+
+ return 0;
+}
+
+static const struct dm_serial_ops pxa_serial_ops = {
+ .putc = pxa_serial_putc,
+ .pending = pxa_serial_pending,
+ .getc = pxa_serial_getc,
+ .setbrg = pxa_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_pxa) = {
+ .name = "serial_pxa",
+ .id = UCLASS_SERIAL,
+ .probe = pxa_serial_probe,
+ .ops = &pxa_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index 6851ba9..791f3e8 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -271,6 +271,21 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
{
+ struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ struct kwspi_registers *reg = plat->spireg;
+ u32 data = readl(&reg->cfg);
+
+ data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
+
+ if (mode & SPI_CPHA)
+ data |= KWSPI_CPHA;
+ if (mode & SPI_CPOL)
+ data |= KWSPI_CPOL;
+ if (mode & SPI_LSB_FIRST)
+ data |= (KWSPI_RXLSBF | KWSPI_TXLSBF);
+
+ writel(data, &reg->cfg);
+
return 0;
}
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 105ee4a..15cf0bd 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <dt-structs.h>
#include <errno.h>
#include <spi.h>
#include <linux/errno.h>
@@ -27,6 +28,9 @@ DECLARE_GLOBAL_DATA_PTR;
#define DEBUG_RK_SPI 0
struct rockchip_spi_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_rockchip_rk3288_spi of_plat;
+#endif
s32 frequency; /* Default clock frequency, -1 for none */
fdt_addr_t base;
uint deactivate_delay_us; /* Delay to wait after deactivate */
@@ -106,6 +110,14 @@ static void spi_cs_activate(struct udevice *dev, uint cs)
struct rockchip_spi_priv *priv = dev_get_priv(bus);
struct rockchip_spi *regs = priv->regs;
+ /* If it's too soon to do another transaction, wait */
+ if (plat->deactivate_delay_us && priv->last_transaction_us) {
+ ulong delay_us; /* The delay completed so far */
+ delay_us = timer_get_us() - priv->last_transaction_us;
+ if (delay_us < plat->deactivate_delay_us)
+ udelay(plat->deactivate_delay_us - delay_us);
+ }
+
debug("activate cs%u\n", cs);
writel(1 << cs, &regs->ser);
if (plat->activate_delay_us)
@@ -127,9 +139,29 @@ static void spi_cs_deactivate(struct udevice *dev, uint cs)
priv->last_transaction_us = timer_get_us();
}
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+ struct rockchip_spi_platdata *plat = dev->platdata;
+ struct dtd_rockchip_rk3288_spi *dtplat = &plat->of_plat;
+ struct rockchip_spi_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ plat->base = dtplat->reg[0];
+ plat->frequency = 20000000;
+ ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ if (ret < 0)
+ return ret;
+ dev->req_seq = 0;
+
+ return 0;
+}
+#endif
+
static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
{
- struct rockchip_spi_platdata *plat = bus->platdata;
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct rockchip_spi_platdata *plat = dev_get_platdata(bus);
struct rockchip_spi_priv *priv = dev_get_priv(bus);
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
@@ -153,6 +185,7 @@ static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
debug("%s: base=%x, max-frequency=%d, deactivate_delay=%d\n",
__func__, (uint)plat->base, plat->frequency,
plat->deactivate_delay_us);
+#endif
return 0;
}
@@ -164,6 +197,11 @@ static int rockchip_spi_probe(struct udevice *bus)
int ret;
debug("%s: probe\n", __func__);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ ret = conv_of_platdata(bus);
+ if (ret)
+ return ret;
+#endif
priv->regs = (struct rockchip_spi *)plat->base;
priv->last_transaction_us = timer_get_us();
@@ -369,7 +407,11 @@ static const struct udevice_id rockchip_spi_ids[] = {
};
U_BOOT_DRIVER(rockchip_spi) = {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ .name = "rockchip_rk3288_spi",
+#else
.name = "rockchip_spi",
+#endif
.id = UCLASS_SPI,
.of_match = rockchip_spi_ids,
.ops = &rockchip_spi_ops,
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index d9c49e4..f59a701 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -108,6 +108,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
return dm_spi_xfer(slave->dev, bitlen, dout, din, flags);
}
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
static int spi_child_post_bind(struct udevice *dev)
{
struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
@@ -117,14 +118,16 @@ static int spi_child_post_bind(struct udevice *dev)
return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
}
+#endif
static int spi_post_probe(struct udevice *bus)
{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
struct dm_spi_bus *spi = dev_get_uclass_priv(bus);
spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
"spi-max-frequency", 0);
-
+#endif
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
struct dm_spi_ops *ops = spi_get_ops(bus);
@@ -274,7 +277,11 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
bool created = false;
int ret;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ ret = uclass_first_device_err(UCLASS_SPI, &bus);
+#else
ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
+#endif
if (ret) {
printf("Invalid bus %d (err=%d)\n", busnum, ret);
return ret;
@@ -290,8 +297,11 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
__func__, dev_name, busnum, cs, drv_name);
ret = device_bind_driver(bus, drv_name, dev_name, &dev);
- if (ret)
+ if (ret) {
+ debug("%s: Unable to bind driver (ret=%d)\n", __func__,
+ ret);
return ret;
+ }
plat = dev_get_parent_platdata(dev);
plat->cs = cs;
plat->max_hz = speed;
@@ -436,14 +446,18 @@ UCLASS_DRIVER(spi) = {
.id = UCLASS_SPI,
.name = "spi",
.flags = DM_UC_FLAG_SEQ_ALIAS,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.post_bind = dm_scan_fdt_dev,
+#endif
.post_probe = spi_post_probe,
.child_pre_probe = spi_child_pre_probe,
.per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
.per_child_auto_alloc_size = sizeof(struct spi_slave),
.per_child_platdata_auto_alloc_size =
sizeof(struct dm_spi_slave_platdata),
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.child_post_bind = spi_child_post_bind,
+#endif
};
UCLASS_DRIVER(spi_generic) = {
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index acc9964..0fbbb7c 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -8,6 +8,11 @@
obj-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o
obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += g_dnl.o
+obj-$(CONFIG_SPL_DFU_SUPPORT) += f_dfu.o
+endif
+
# new USB gadget layer dependencies
ifdef CONFIG_USB_GADGET
obj-$(CONFIG_USB_GADGET_AT91) += at91_udc.o
@@ -17,14 +22,14 @@ obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_udc_otg.o
obj-$(CONFIG_USB_GADGET_DWC2_OTG_PHY) += dwc2_udc_otg_phy.o
obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
obj-$(CONFIG_CI_UDC) += ci_udc.o
+ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o
obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
-ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
-endif
obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
endif
+endif
ifdef CONFIG_USB_ETHER
obj-y += ether.o
obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index cd605e6..cc6454f 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -71,9 +71,9 @@ void lcd_ctrl_init(void *lcdbase)
msg_setup->virtual_w_h.body.req.width = w;
msg_setup->virtual_w_h.body.req.height = h;
BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH);
- msg_setup->depth.body.req.bpp = 16;
+ msg_setup->depth.body.req.bpp = 32;
BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER);
- msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_BGR;
+ msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_RGB;
BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE);
msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET);
@@ -103,7 +103,7 @@ void lcd_ctrl_init(void *lcdbase)
panel_info.vl_col = w;
panel_info.vl_row = h;
- panel_info.vl_bpix = LCD_COLOR16;
+ panel_info.vl_bpix = LCD_COLOR32;
gd->fb_base = bus_to_phys(
msg_setup->allocate_buffer.body.resp.fb_address);
diff --git a/drivers/video/display-uclass.c b/drivers/video/display-uclass.c
index e4763de..e752eb0 100644
--- a/drivers/video/display-uclass.c
+++ b/drivers/video/display-uclass.c
@@ -23,10 +23,19 @@ int display_enable(struct udevice *dev, int panel_bpp,
const struct display_timing *timing)
{
struct dm_display_ops *ops = display_get_ops(dev);
+ struct display_plat *disp_uc_plat;
+ int ret;
if (!ops || !ops->enable)
return -ENOSYS;
- return ops->enable(dev, panel_bpp, timing);
+ ret = ops->enable(dev, panel_bpp, timing);
+ if (ret)
+ return ret;
+
+ disp_uc_plat = dev_get_uclass_platdata(dev);
+ disp_uc_plat->in_use = true;
+
+ return 0;
}
int display_read_timing(struct udevice *dev, struct display_timing *timing)
@@ -48,6 +57,13 @@ int display_read_timing(struct udevice *dev, struct display_timing *timing)
return edid_get_timing(buf, ret, timing, &panel_bits_per_colour);
}
+bool display_in_use(struct udevice *dev)
+{
+ struct display_plat *disp_uc_plat = dev_get_uclass_platdata(dev);
+
+ return disp_uc_plat->in_use;
+}
+
UCLASS_DRIVER(display) = {
.id = UCLASS_DISPLAY,
.name = "display",
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index 7976c5e..032b1de 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -132,8 +132,8 @@ static const u32 csc_coeff_default[3][4] = {
static void hdmi_set_clock_regenerator(struct rk3288_hdmi *regs, u32 n, u32 cts)
{
- u8 cts3;
- u8 n3;
+ uint cts3;
+ uint n3;
/* first set ncts_atomic_write (if present) */
n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
@@ -199,7 +199,7 @@ static void hdmi_audio_set_samplerate(struct rk3288_hdmi *regs, u32 pixel_clk)
static void hdmi_video_sample(struct rk3288_hdmi *regs)
{
u32 color_format = 0x01;
- u8 val;
+ uint val;
val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
@@ -256,7 +256,7 @@ static void hdmi_video_packetize(struct rk3288_hdmi *regs)
u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
u32 color_depth = 0;
- u8 val, vp_conf;
+ uint val, vp_conf;
/* set the packetizer registers */
val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
@@ -297,7 +297,7 @@ static void hdmi_video_packetize(struct rk3288_hdmi *regs)
output_select);
}
-static inline void hdmi_phy_test_clear(struct rk3288_hdmi *regs, u8 bit)
+static inline void hdmi_phy_test_clear(struct rk3288_hdmi *regs, uint bit)
{
clrsetbits_le32(&regs->phy_tst0, HDMI_PHY_TST0_TSTCLR_MASK,
bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
@@ -382,7 +382,7 @@ static void hdmi_phy_sel_interface_control(struct rk3288_hdmi *regs,
static int hdmi_phy_configure(struct rk3288_hdmi *regs, u32 mpixelclock)
{
ulong start;
- u8 i, val;
+ uint i, val;
writel(HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
&regs->mc_flowctrl);
@@ -481,8 +481,8 @@ static int hdmi_phy_init(struct rk3288_hdmi *regs, uint mpixelclock)
static void hdmi_av_composer(struct rk3288_hdmi *regs,
const struct display_timing *edid)
{
- u8 mdataenablepolarity = 1;
- u8 inv_val;
+ bool mdataenablepolarity = true;
+ uint inv_val;
uint hbl;
uint vbl;
@@ -553,7 +553,7 @@ static void hdmi_av_composer(struct rk3288_hdmi *regs,
/* hdmi initialization step b.4 */
static void hdmi_enable_video_path(struct rk3288_hdmi *regs)
{
- u8 clkdis;
+ uint clkdis;
/* control period minimum duration */
writel(12, &regs->fc_ctrldur);
@@ -580,7 +580,7 @@ static void hdmi_enable_video_path(struct rk3288_hdmi *regs)
/* workaround to clear the overflow condition */
static void hdmi_clear_overflow(struct rk3288_hdmi *regs)
{
- u8 val, count;
+ uint val, count;
/* tmds software reset */
writel((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &regs->mc_swrstz);
@@ -614,7 +614,7 @@ static void hdmi_audio_fifo_reset(struct rk3288_hdmi *regs)
static void hdmi_init_interrupt(struct rk3288_hdmi *regs)
{
- u8 ih_mute;
+ uint ih_mute;
/*
* boot up defaults are:
@@ -650,11 +650,11 @@ static void hdmi_init_interrupt(struct rk3288_hdmi *regs)
writel(HDMI_IH_PHY_STAT0_HPD, &regs->ih_phy_stat0);
}
-static u8 hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
+static int hdmi_get_plug_in_status(struct rk3288_hdmi *regs)
{
- u8 val = readl(&regs->phy_stat0) & HDMI_PHY_HPD;
+ uint val = readl(&regs->phy_stat0) & HDMI_PHY_HPD;
- return !!(val);
+ return !!val;
}
static int hdmi_wait_for_hpd(struct rk3288_hdmi *regs)
@@ -753,7 +753,7 @@ static int hdmi_read_edid(struct rk3288_hdmi *regs, int block, u8 *buff)
return edid_read_err;
}
-static u8 pre_buf[] = {
+static const u8 pre_buf[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
@@ -899,7 +899,8 @@ static int rk_hdmi_probe(struct udevice *dev)
rk_setreg(&priv->grf->soc_con6, 1 << 15);
/* hdmi data from vop id */
- rk_setreg(&priv->grf->soc_con6, (vop_id == 1) ? (1 << 4) : (1 << 4));
+ rk_clrsetreg(&priv->grf->soc_con6, 1 << 4,
+ (vop_id == 1) ? (1 << 4) : 0);
ret = hdmi_wait_for_hpd(priv->regs);
if (ret < 0) {
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index c6d88d9..eab5486 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -195,7 +195,6 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
struct udevice *disp;
int ret, remote, i, offset;
struct display_plat *disp_uc_plat;
- struct udevice *dev_clk;
struct clk clk;
vop_id = fdtdec_get_int(blob, ep_node, "reg", -1);
@@ -222,6 +221,11 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
disp_uc_plat = dev_get_uclass_platdata(disp);
debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
+ if (display_in_use(disp)) {
+ debug(" - device in use\n");
+ return -EBUSY;
+ }
+
disp_uc_plat->source_id = remote_vop_id;
disp_uc_plat->src_dev = dev;
@@ -238,11 +242,7 @@ int rk_display_init(struct udevice *dev, ulong fbbase,
return ret;
}
- ret = rockchip_get_clk(&dev_clk);
- if (!ret) {
- clk.id = DCLK_VOP0 + remote_vop_id;
- ret = clk_request(dev_clk, &clk);
- }
+ ret = clk_get_by_index(dev, 1, &clk);
if (!ret)
ret = clk_set_rate(&clk, timing.pixelclock.typ);
if (ret) {
@@ -316,6 +316,10 @@ static int rk_vop_probe(struct udevice *dev)
/*
* Try all the ports until we find one that works. In practice this
* tries EDP first if available, then HDMI.
+ *
+ * Note that rockchip_vop_set_clk() always uses NPLL as the source
+ * clock so it is currently not possible to use more than one display
+ * device simultaneously.
*/
port = fdt_subnode_offset(blob, dev->of_offset, "port");
if (port < 0)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 11ca793..3036e3a 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -117,7 +117,8 @@ void video_sync(struct udevice *vid)
if (priv->flush_dcache) {
flush_dcache_range((ulong)priv->fb,
- (ulong)priv->fb + priv->fb_size);
+ ALIGN((ulong)priv->fb + priv->fb_size,
+ CONFIG_SYS_CACHELINE_SIZE));
}
#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
struct video_priv *priv = dev_get_uclass_priv(vid);