diff mbox

[U-Boot,v2,2/6] sf: disable write protection for Macronix flash

Message ID 1304284220-15215-3-git-send-email-sguinot@lacie.com
State Changes Requested
Headers show

Commit Message

Simon Guinot May 1, 2011, 9:10 p.m. UTC
Signed-off-by: Simon Guinot <sguinot@lacie.com>
---
 drivers/mtd/spi/macronix.c |   87 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 87 insertions(+), 0 deletions(-)

Comments

Mike Frysinger May 1, 2011, 10:16 p.m. UTC | #1
this needs to be rewritten to use the common spi flash code.  please
see the sst_unlock func for an example of how to do this.
-mike
Prafulla Wadaskar May 2, 2011, 8:53 a.m. UTC | #2
> -----Original Message-----
> From: Simon Guinot [mailto:sguinot@lacie.com]
> Sent: Monday, May 02, 2011 2:40 AM
> To: Prafulla Wadaskar; Albert ARIBAUD; Wolfgang Denk
> Cc: u-boot@lists.denx.de; Simon Guinot
> Subject: [PATCH v2 2/6] sf: disable write protection for Macronix flash
> 
> Signed-off-by: Simon Guinot <sguinot@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");
> +

This will forced disable the flash being written.
What if some one has purposely protected certain flash sectors?

This feature should be addressed through protect CLI

Regards..
Prafulla . .
   
>  	return &mcx->flash;
>  }
> --
> 1.6.3.1
Simon Guinot May 2, 2011, 9:58 a.m. UTC | #3
Hi Prafulla,

On Mon, May 02, 2011 at 01:53:29AM -0700, Prafulla Wadaskar wrote:
> >  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");
> > +
> 
> This will forced disable the flash being written.

Yes, as the SST driver do. Maybe it is good enough for the Macronix
driver too ?

> What if some one has purposely protected certain flash sectors?

Honestly, I don't know. Block protection for SPI flashes is not
supported either by u-boot (except for SST which only disable it)
nor by Linux. So, I am not sure this feature is really used.

> 
> This feature should be addressed through protect CLI

I could add an unlock method to the SPI flash operation structure.
And then, I could bind this method to a CLI command "sf unlock"...

Do you want me to do that ?

Regards,

Simon
Prafulla Wadaskar May 2, 2011, 10:01 a.m. UTC | #4
> -----Original Message-----
> From: Simon Guinot [mailto:simon.guinot@sequanux.org]
> Sent: Monday, May 02, 2011 3:28 PM
> To: Prafulla Wadaskar
> Cc: Simon Guinot; Albert ARIBAUD; Wolfgang Denk; u-boot@lists.denx.de;
> Prabhanjan Sarnaik; Ashish Karkare; Mike Frysinger
> Subject: Re: [U-Boot] [PATCH v2 2/6] sf: disable write protection for
> Macronix flash
> 
> Hi Prafulla,
> 
> On Mon, May 02, 2011 at 01:53:29AM -0700, Prafulla Wadaskar wrote:
> > >  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");
> > > +
> >
> > This will forced disable the flash being written.
> 
> Yes, as the SST driver do. Maybe it is good enough for the Macronix
> driver too ?
> 
> > What if some one has purposely protected certain flash sectors?
> 
> Honestly, I don't know. Block protection for SPI flashes is not
> supported either by u-boot (except for SST which only disable it)
> nor by Linux. So, I am not sure this feature is really used.
> 
> >
> > This feature should be addressed through protect CLI
> 
> I could add an unlock method to the SPI flash operation structure.
> And then, I could bind this method to a CLI command "sf unlock"...
> 
> Do you want me to do that ?

Let's get Mike's opinion on this.

Regards..
Prafulla . .
Mike Frysinger May 2, 2011, 12:17 p.m. UTC | #5
On Mon, May 2, 2011 at 04:53, Prafulla Wadaskar wrote:
> From: Simon Guinot [mailto:sguinot@lacie.com]
>> --- a/drivers/mtd/spi/macronix.c
>> +++ b/drivers/mtd/spi/macronix.c
>> +     if (macronix_disable_protect(&mcx->flash))
>> +             printf("SF: disable write protection failed\n");
>
> This will forced disable the flash being written.
> What if some one has purposely protected certain flash sectors?
>
> This feature should be addressed through protect CLI

there is no spi flash protect api today, so until that happens, what
Simon is proposing is correct
-mike
diff mbox

Patch

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;
 }