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

Reply via email to