From: Simon Guinot <sgui...@lacie.com> Signed-off-by: Simon Guinot <sgui...@lacie.com> --- drivers/mtd/spi/macronix.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 8e4d71c..b587ac9 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -49,6 +49,10 @@ #define CMD_MX25XX_DP 0xb9 /* Deep Power-down */ #define CMD_MX25XX_RES 0xab /* Release from DP, and Read Signature */ +/* Status registers */ +#define MX25XX_SR_BP (0xF << 2) /* Block Protect */ +#define MX25XX_SR_SRWP (1 << 7) /* Write Protect */ + struct macronix_spi_flash_params { u16 idcode; u16 page_size; @@ -120,6 +124,86 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = { }, }; +static int macronix_write_status(struct spi_flash *flash, u8 sr) +{ + u8 cmd[2]; + int ret; + + ret = spi_flash_cmd(flash->spi, CMD_MX25XX_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + return ret; + } + + cmd[0] = CMD_MX25XX_WRSR; + cmd[1] = sr; + ret = spi_xfer(flash->spi, 16, cmd, NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: fail to write status register\n"); + return ret; + } + + spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_END); + + ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: write status register timed out\n"); + return ret; + } + + return 0; +} + +static int macronix_read_status(struct spi_flash *flash, u8 *sr) +{ + u8 cmd = CMD_MX25XX_RDSR; + int ret; + + ret = spi_xfer(flash->spi, 8, &cmd, NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: Failed to send command %02x: %d\n", cmd, ret); + return ret; + } + ret = spi_xfer(flash->spi, 8, NULL, sr, 0); + if (ret) { + debug("SF: fail to read status register: %d\n", ret); + return ret; + } + + spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_END); + + return 0; +} + +static int macronix_disable_protect(struct spi_flash *flash) +{ + int ret; + u8 sr; + + ret = macronix_read_status(flash, &sr); + if (ret) + return ret; + + if ((sr & MX25XX_SR_BP) == 0) + return ret; + + /* Disable status register write protection. */ + sr &= ~MX25XX_SR_SRWP; + ret = macronix_write_status(flash, sr); + if (ret) + return ret; + + /* Disable block protection. */ + sr &= ~MX25XX_SR_BP; + ret = macronix_write_status(flash, sr); + if (ret) + return ret; + + printf("SF: disable write protection\n"); + + return 0; +} + static int macronix_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { @@ -223,5 +307,8 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) * params->sectors_per_block; mcx->flash.size = mcx->flash.sector_size * params->nr_blocks; + if (macronix_disable_protect(&mcx->flash)) + printf("SF: disable write protection failed\n"); + return &mcx->flash; } -- 1.6.3.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot