[U-Boot] [PATCH 1/6] arm/davinci: fix DDR2/mDDR memory controller initialization for Omap L138

follow section 15.2.13.1 (Initializing Following Device Power Up or Reset) of OMAP-L138 DSP+ARM Processor Technical Reference Manual
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c | 26 +++++++++++++++++------ arch/arm/include/asm/arch-davinci/hardware.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c b/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c index df7d6a2..ff2e2e3 100644 --- a/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c +++ b/arch/arm/cpu/arm926ejs/davinci/da850_lowlevel.c @@ -190,13 +190,21 @@ int da850_ddr_setup(void)
setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK); setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN); - - setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN); } - + setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN); writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr); - clrbits_le32(&davinci_syscfg1_regs->ddr_slew, - (1 << DDR_SLEW_CMOSEN_BIT)); + + if (CONFIG_SYS_DA850_DDR2_SDBCR & (1 << DV_DDR_SDCR_DDR2EN_SHIFT)) { + /* DDR2 */ + clrbits_le32(&davinci_syscfg1_regs->ddr_slew, + (1 << DDR_SLEW_DDR_PDENA_BIT) | + (1 << DDR_SLEW_CMOSEN_BIT)); + } else { + /* MOBILE DDR */ + setbits_le32(&davinci_syscfg1_regs->ddr_slew, + (1 << DDR_SLEW_DDR_PDENA_BIT) | + (1 << DDR_SLEW_CMOSEN_BIT)); + }
/* * SDRAM Configuration Register (SDCR): @@ -216,7 +224,11 @@ int da850_ddr_setup(void) writel(tmp, &dv_ddr2_regs_ctrl->sdbcr);
/* write memory configuration and timing */ - writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2); + if (!(CONFIG_SYS_DA850_DDR2_SDBCR & (1 << DV_DDR_SDCR_DDR2EN_SHIFT))) { + /* MOBILE DDR only*/ + writel(CONFIG_SYS_DA850_DDR2_SDBCR2, + &dv_ddr2_regs_ctrl->sdbcr2); + } writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr); writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2);
@@ -240,7 +252,7 @@ int da850_ddr_setup(void)
/* disable self refresh */ clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr, - DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_LPMODEN); + DV_DDR_SDRCR_LPMODEN | DV_DDR_SDRCR_MCLKSTOPEN); writel(CONFIG_SYS_DA850_DDR2_PBBPR, &dv_ddr2_regs_ctrl->pbbpr);
return 0; diff --git a/arch/arm/include/asm/arch-davinci/hardware.h b/arch/arm/include/asm/arch-davinci/hardware.h index b145c6e..56e5743 100644 --- a/arch/arm/include/asm/arch-davinci/hardware.h +++ b/arch/arm/include/asm/arch-davinci/hardware.h @@ -505,6 +505,7 @@ struct davinci_syscfg1_regs { ((struct davinci_syscfg1_regs *)DAVINCI_SYSCFG1_BASE)
#define DDR_SLEW_CMOSEN_BIT 4 +#define DDR_SLEW_DDR_PDENA_BIT 5
#define VTP_POWERDWN (1 << 6) #define VTP_LOCK (1 << 7)

Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c | 5 +++++ arch/arm/include/asm/arch-davinci/hardware.h | 1 + arch/arm/include/asm/arch-davinci/pinmux_defs.h | 1 + 3 files changed, 7 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c b/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c index fa07fb5..dbae5fa 100644 --- a/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c +++ b/arch/arm/cpu/arm926ejs/davinci/da850_pinmux.c @@ -35,6 +35,11 @@ const struct pinmux_config spi1_pins_scs0[] = { };
/* UART pin muxer settings */ +const struct pinmux_config uart0_pins_txrx[] = { + { pinmux(3), 2, 4 }, /* UART0_RXD */ + { pinmux(3), 2, 5 }, /* UART0_TXD */ +}; + const struct pinmux_config uart1_pins_txrx[] = { { pinmux(4), 2, 6 }, /* UART1_RXD */ { pinmux(4), 2, 7 }, /* UART1_TXD */ diff --git a/arch/arm/include/asm/arch-davinci/hardware.h b/arch/arm/include/asm/arch-davinci/hardware.h index 56e5743..76aca24 100644 --- a/arch/arm/include/asm/arch-davinci/hardware.h +++ b/arch/arm/include/asm/arch-davinci/hardware.h @@ -447,6 +447,7 @@ struct davinci_pllc_regs { /* Clock IDs */ enum davinci_clk_ids { DAVINCI_SPI0_CLKID = 2, + DAVINCI_UART0_CLKID = 2, DAVINCI_UART2_CLKID = 2, DAVINCI_MMC_CLKID = 2, DAVINCI_MDIO_CLKID = 4, diff --git a/arch/arm/include/asm/arch-davinci/pinmux_defs.h b/arch/arm/include/asm/arch-davinci/pinmux_defs.h index 07aceaa..eddb3f7 100644 --- a/arch/arm/include/asm/arch-davinci/pinmux_defs.h +++ b/arch/arm/include/asm/arch-davinci/pinmux_defs.h @@ -28,6 +28,7 @@ extern const struct pinmux_config spi1_pins_base[3]; extern const struct pinmux_config spi1_pins_scs0[1];
/* UART pin muxer settings */ +extern const struct pinmux_config uart0_pins_txrx[2]; extern const struct pinmux_config uart1_pins_txrx[2]; extern const struct pinmux_config uart2_pins_txrx[2]; extern const struct pinmux_config uart2_pins_rtscts[2];

also fix NS16550_init() as we need 16x divider
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- drivers/serial/ns16550.c | 2 +- include/ns16550.h | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 0c23955..facadd2 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -52,7 +52,7 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); serial_out(UART_LCRVAL, &com_port->lcr); #if (defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)) || \ - defined(CONFIG_AM33XX) + defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX)
#if defined(CONFIG_APTIX) /* /13 mode so Aptix 6MHz can hit 115200 */ diff --git a/include/ns16550.h b/include/ns16550.h index e9d2eda..51cb5b4 100644 --- a/include/ns16550.h +++ b/include/ns16550.h @@ -46,6 +46,14 @@ struct NS16550 { UART_REG(lsr); /* 5 */ UART_REG(msr); /* 6 */ UART_REG(spr); /* 7 */ +#ifdef CONFIG_SOC_DA8XX + UART_REG(reg8); /* 8 */ + UART_REG(reg9); /* 9 */ + UART_REG(revid1); /* A */ + UART_REG(revid2); /* B */ + UART_REG(pwr_mgmt); /* C */ + UART_REG(mdr1); /* D */ +#else UART_REG(mdr1); /* 8 */ UART_REG(reg9); /* 9 */ UART_REG(regA); /* A */ @@ -58,6 +66,7 @@ struct NS16550 { UART_REG(ssr); /* 11*/ UART_REG(reg12); /* 12*/ UART_REG(osc_12m_sel); /* 13*/ +#endif };
#define thr rbr

current code does not support spi flashes that have 0x90 read_id command, so fix this
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- drivers/mtd/spi/spi_flash.c | 66 +++++++++++++++++++++++----------- drivers/mtd/spi/spi_flash_internal.h | 1 + 2 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index f689cc4..530b7b3 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -306,13 +306,44 @@ static const struct { }; #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+struct spi_flash *spi_analize_flash_probe(struct spi_slave *spi, + u8 *idcode, size_t idcode_len, u8 *id) +{ + struct spi_flash *flash = NULL; + int i, shift; + u8 *idp; + +#ifdef DEBUG + printf("SF: Got idcodes\n"); + print_buffer(0, idcode, 1, idcode_len, 0); +#endif + + /* count the number of continuation bytes */ + for (shift = 0, idp = idcode; + shift < idcode_len && *idp == 0x7f; + ++shift, ++idp) + continue; + + *id = *idp; + /* search the table for matches in shift and id */ + for (i = 0; i < ARRAY_SIZE(flashes); ++i) + if (flashes[i].shift == shift && flashes[i].idcode == *idp) { + /* we have a match, call probe */ + flash = flashes[i].probe(spi, idp); + if (flash) + break; + } + + return flash; +} + struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; struct spi_flash *flash = NULL; - int ret, i, shift; - u8 idcode[IDCODE_LEN], *idp; + u8 cmd[4], idcode[IDCODE_LEN], id; + int ret;
spi = spi_setup_slave(bus, cs, max_hz, spi_mode); if (!spi) { @@ -331,28 +362,23 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, if (ret) goto err_read_id;
-#ifdef DEBUG - printf("SF: Got idcodes\n"); - print_buffer(0, idcode, 1, sizeof(idcode), 0); -#endif + flash = spi_analize_flash_probe(spi, idcode, sizeof(idcode), &id); + if (id == 0xff) { + /* try CMD_READ_ID_NEW command */ + cmd[0] = CMD_READ_ID_NEW; + spi_flash_addr(0x000000, cmd);
- /* count the number of continuation bytes */ - for (shift = 0, idp = idcode; - shift < IDCODE_CONT_LEN && *idp == 0x7f; - ++shift, ++idp) - continue; + ret = spi_flash_cmd_read(spi, cmd, sizeof(cmd), + idcode, sizeof(idcode)); + if (ret) + goto err_read_id;
- /* search the table for matches in shift and id */ - for (i = 0; i < ARRAY_SIZE(flashes); ++i) - if (flashes[i].shift == shift && flashes[i].idcode == *idp) { - /* we have a match, call probe */ - flash = flashes[i].probe(spi, idp); - if (flash) - break; - } + flash = spi_analize_flash_probe(spi, + idcode, sizeof(idcode), &id); + }
if (!flash) { - printf("SF: Unsupported manufacturer %02x\n", *idp); + printf("SF: Unsupported manufacturer %02x\n", id); goto err_manufacturer_probe; }
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 91e036a..b8bd5d5 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -14,6 +14,7 @@
/* Common commands */ #define CMD_READ_ID 0x9f +#define CMD_READ_ID_NEW 0x90
#define CMD_READ_ARRAY_SLOW 0x03 #define CMD_READ_ARRAY_FAST 0x0b

current SST driver does not support well this types of flash, so use linux-3.3 code as a base.
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- drivers/mtd/spi/Makefile | 3 +- drivers/mtd/spi/spi_flash.c | 3 + drivers/mtd/spi/spi_flash_internal.h | 1 + drivers/mtd/spi/sst25l.c | 372 ++++++++++++++++++++++++++++++++++ 4 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/spi/sst25l.c
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 90f8392..9285bf7 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -34,7 +34,8 @@ COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o COBJS-$(CONFIG_SPI_FLASH_EON) += eon.o COBJS-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.o COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o -COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o +COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o +COBJS-$(CONFIG_SPI_FLASH_SST25L) += sst25l.o COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o COBJS-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 530b7b3..d2da542 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -285,6 +285,9 @@ static const struct { #ifdef CONFIG_SPI_FLASH_SST { 0, 0xbf, spi_flash_probe_sst, }, #endif +#ifdef CONFIG_SPI_FLASH_SST25L + { 0, 0xbf, spi_flash_probe_sst25l, }, +#endif #ifdef CONFIG_SPI_FLASH_STMICRO { 0, 0x20, spi_flash_probe_stmicro, }, #endif diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index b8bd5d5..89d9036 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -98,6 +98,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode); +struct spi_flash *spi_flash_probe_sst25l(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/sst25l.c b/drivers/mtd/spi/sst25l.c new file mode 100644 index 0000000..9d7be0d --- /dev/null +++ b/drivers/mtd/spi/sst25l.c @@ -0,0 +1,372 @@ +/* + * Driver for SST25L SPI Flash chips + * + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Copyright 2008, Network Appliance Inc. + * Jason McMullan mcmullan@netapp.com + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. + * TsiChung Liew (Tsi-Chung.Liew@freescale.com) + * Copyright (c) 2008-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <malloc.h> +#include <spi_flash.h> +#include <watchdog.h> + +#include "spi_flash_internal.h" + +#define SST25L_CMD_WRSR 0x01 /* Write status register */ +#define SST25L_CMD_WRDI 0x04 /* Write disable */ +#define SST25L_CMD_RDSR 0x05 /* Read status register */ +#define SST25L_CMD_WREN 0x06 /* Write enable */ +#define SST25L_CMD_READ 0x03 /* High speed read */ + +#define SST25L_CMD_EWSR 0x50 /* Enable write status register */ +#define SST25L_CMD_SECTOR_ERASE 0x20 /* Erase sector */ +#define SST25L_CMD_READ_ID 0x90 /* Read device ID */ +#define SST25L_CMD_AAI_PROGRAM 0xaf /* Auto address increment */ + +#define SST25L_STATUS_BUSY (1 << 0) /* Chip is busy */ +#define SST25L_STATUS_WREN (1 << 1) /* Write enabled */ +#define SST25L_STATUS_BP0 (1 << 2) /* Block protection 0 */ +#define SST25L_STATUS_BP1 (1 << 3) /* Block protection 1 */ + +struct flash_info { + const char *name; + u16 device_id; + u32 page_size; + u32 nr_pages; + u32 erase_size; +}; + +struct sst25l_spi_flash { + struct spi_flash flash; + const struct flash_info *flash_info; +}; + +#define to_sst25l_spi_flash(x) container_of(x, struct sst25l_spi_flash, flash) + +static struct flash_info sst25l_flash_info[] = { + {"sst25vf010a", 0xbf49, 256, 512, 4096}, + {"sst25lf020a", 0xbf43, 256, 1024, 4096}, + {"sst25lf040a", 0xbf44, 256, 2048, 4096}, +}; + +static inline int spi_write_sync(struct spi_slave *spi, + const u8 *data, size_t len) +{ + return spi_xfer(spi, 8 * len, data, + NULL, SPI_XFER_BEGIN | SPI_XFER_END); +} + +static int sst25l_status(struct spi_flash *flash, int *status) +{ + unsigned char cmd_resp[2]; + int err; + + cmd_resp[0] = SST25L_CMD_RDSR; + cmd_resp[1] = 0xff; + + err = spi_xfer(flash->spi, 8 * sizeof(cmd_resp), cmd_resp, cmd_resp, + SPI_XFER_BEGIN | SPI_XFER_END); + if (err < 0) + return err; + + *status = cmd_resp[1]; + return 0; +} + +static int sst25l_write_enable(struct spi_flash *flash, int enable) +{ + unsigned char command[2]; + int status, err; + + command[0] = enable ? SST25L_CMD_WREN : SST25L_CMD_WRDI; + err = spi_write_sync(flash->spi, command, 1); + if (err) + return err; + + command[0] = SST25L_CMD_EWSR; + err = spi_write_sync(flash->spi, command, 1); + if (err) + return err; + + command[0] = SST25L_CMD_WRSR; + command[1] = enable ? 0 : SST25L_STATUS_BP0 | SST25L_STATUS_BP1; + err = spi_write_sync(flash->spi, command, 2); + if (err) + return err; + + if (enable) { + err = sst25l_status(flash, &status); + if (err) + return err; + if (!(status & SST25L_STATUS_WREN)) + return -1; + } + + return 0; +} + +static int sst25l_wait_till_ready(struct spi_flash *flash, + unsigned long timeout) +{ + unsigned long timebase; + int status, err; + + timebase = get_timer(0); + do { + WATCHDOG_RESET(); + + err = sst25l_status(flash, &status); + if (err) + return err; + if (!(status & SST25L_STATUS_BUSY)) + return 0; + + } while (get_timer(timebase) < timeout); + + return -1; +} + +static int sst25l_erase_sector(struct spi_flash *flash, u32 offset) +{ + unsigned char command[4]; + int err; + + err = sst25l_write_enable(flash, 1); + if (err) + return err; + + command[0] = SST25L_CMD_SECTOR_ERASE; + command[1] = offset >> 16; + command[2] = offset >> 8; + command[3] = offset; + err = spi_write_sync(flash->spi, command, 4); + if (err) + return err; + + err = sst25l_wait_till_ready(flash, SPI_FLASH_SECTOR_ERASE_TIMEOUT); + if (err) + return err; + + return sst25l_write_enable(flash, 0); +} + +static int sst25l_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + struct sst25l_spi_flash *sst25l = to_sst25l_spi_flash(flash); + const struct flash_info *flash_info = sst25l->flash_info; + u32 end = offset + len; + int err; + + /* Sanity checks */ + if (len % flash_info->erase_size) + return -1; + + if (offset % flash_info->erase_size) + return -1; + + err = sst25l_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (err) + return err; + + while (offset < end) { + err = sst25l_erase_sector(flash, offset); + if (err) + return err; + offset += flash_info->erase_size; + } + return 0; +} + +static int sst25l_read(struct spi_flash *flash, + u32 offset, size_t len, void *data) +{ + unsigned char command[4]; + int ret; + + command[0] = SST25L_CMD_READ; + command[1] = offset >> 16; + command[2] = offset >> 8; + command[3] = offset; + + /* Wait for previous write/erase to complete */ + ret = sst25l_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret) + return ret; + + ret = spi_xfer(flash->spi, 8 * sizeof(command), command, + NULL, SPI_XFER_BEGIN); + if (ret) + return ret; + + ret = spi_xfer(flash->spi, 8 * len, NULL, data, SPI_XFER_END); + if (ret) + return ret; + + return 0; +} + +static int sst25l_write(struct spi_flash *flash, + u32 offset, size_t len, const char *buf) +{ + struct sst25l_spi_flash *sst25l = to_sst25l_spi_flash(flash); + const struct flash_info *flash_info = sst25l->flash_info; + int i, j, ret, bytes, copied = 0; + unsigned char command[5]; + + if (offset % flash_info->page_size) + return -1; + + ret = sst25l_write_enable(flash, 1); + if (ret) + goto out; + + for (i = 0; i < len; i += flash_info->page_size) { + ret = sst25l_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret) + goto out; + + /* Write the first byte of the page */ + command[0] = SST25L_CMD_AAI_PROGRAM; + command[1] = (offset + i) >> 16; + command[2] = (offset + i) >> 8; + command[3] = (offset + i); + command[4] = buf[i]; + ret = spi_write_sync(flash->spi, command, 5); + if (ret < 0) + goto out; + copied++; + + /* + * Write the remaining bytes using auto address + * increment mode + */ + bytes = min(flash_info->page_size, len - i); + for (j = 1; j < bytes; j++, copied++) { + ret = sst25l_wait_till_ready(flash, + SPI_FLASH_PROG_TIMEOUT); + if (ret) + goto out; + + command[1] = buf[i + j]; + ret = spi_write_sync(flash->spi, command, 2); + if (ret) + goto out; + } + } + +out: + ret = sst25l_write_enable(flash, 0); + if (ret) + return ret; + + return (copied == len) ? 0 : -1; +} + +static int sst25l_flash_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + ret = sst25l_erase(flash, offset, len); + if (ret) { + debug("SF: unable to erase spi flash sector\n"); + return ret; + } + + spi_release_bus(flash->spi); + return ret; +} + +static int sst25l_flash_read(struct spi_flash *flash, + u32 offset, size_t len, void *data) +{ + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + ret = sst25l_read(flash, offset, len, data); + if (ret) { + debug("SF: unable to read spi flash\n"); + return ret; + } + + spi_release_bus(flash->spi); + return ret; +} + +static int sst25l_flash_write(struct spi_flash *flash, + u32 offset, size_t len, const void *buf) +{ + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + ret = sst25l_write(flash, offset, len, buf); + if (ret) { + debug("SF: unable to write spi flash\n"); + return ret; + } + + spi_release_bus(flash->spi); + return ret; +} + +struct spi_flash * +spi_flash_probe_sst25l(struct spi_slave *spi, u8 *idcode) +{ + const struct flash_info *flash_info = NULL; + struct sst25l_spi_flash *stm; + size_t i; + u16 device_id = ((u16)idcode[0] << 8) + idcode[1]; + + for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); ++i) + if (sst25l_flash_info[i].device_id == device_id) { + flash_info = &sst25l_flash_info[i]; + break; + } + + if (flash_info == NULL) { + debug("SF: Unsupported SST25L ID %04x\n", device_id); + return NULL; + } + + stm = malloc(sizeof(*stm)); + if (!stm) { + debug("SF: Failed to allocate memory\n"); + return NULL; + } + + stm->flash_info = flash_info; + stm->flash.spi = spi; + stm->flash.name = flash_info->name; + + stm->flash.read = sst25l_flash_read; + stm->flash.write = sst25l_flash_write; + stm->flash.erase = sst25l_flash_erase; + + stm->flash.page_size = flash_info->page_size; + stm->flash.sector_size = flash_info->erase_size; + stm->flash.size = flash_info->page_size * flash_info->nr_pages; + + return &stm->flash; +}

On Tue, Jun 26, 2012 at 02:33:13PM +0400, Mikhail Kshevetskiy wrote:
current SST driver does not support well this types of flash, so use linux-3.3 code as a base.
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com
The correct form here is to say: Backport from Linux commit .... If this is from the 3.3 release please say that clearly. Thanks!

Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@gmail.com --- drivers/mmc/mmc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index aebe578..69df64a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1253,7 +1253,9 @@ int mmc_startup(struct mmc *mmc) (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28, (mmc->cid[2] >> 24) & 0xf); +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT) init_part(&mmc->block_dev); +#endif
return 0; }
participants (2)
-
Mikhail Kshevetskiy
-
Tom Rini