diff options
Diffstat (limited to 'drivers')
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(®s->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(®s->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(®s->lsr); + unsigned int lsr; + + if (plat->disabled) + return 0; + + lsr = readl(®s->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(®->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, ®->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, ®s->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(®s->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, ®s->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, ®s->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, ®s->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, ®s->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(®s->phy_stat0) & HDMI_PHY_HPD; + uint val = readl(®s->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); |