From: Gerlando Falauto <gerlando.falauto@keymile.com>
To: Austin Boyle <Austin.Boyle@aviatnet.com>
Cc: linux-mtd@lists.infradead.org,
David Woodhouse <dwmw2@infradead.org>,
linux-kernel@vger.kernel.org,
Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Subject: Re: [PATCH] mtd: m25p80: Flash protection support for STmicro chips
Date: Wed, 20 Nov 2013 21:04:06 +0100 [thread overview]
Message-ID: <528D15B6.2030800@keymile.com> (raw)
In-Reply-To: <1357257748.31023.12.camel@pc786-ubu.GNET.GLOBAL.VPN>
Hi,
On 01/04/2013 01:02 AM, Austin Boyle wrote:
> This patch adds generic support for flash protection on STmicro chips.
> On chips with less than 3 protection bits, the unused bits are don't cares
> and so can be written anyway.
I have two remarks:
1) I believe this introduces incompatibilities with existing bootloaders
which do not support this feature.
Namely, u-boot is not able (to the best of my knowledge) to treat these
bits properly. So as soon as you write something to your SPI nor flash
from within linux, u-boot is not able to erase/rewrite those blocks anymore.
Wouldn't it make more sense to selectively enable this feature, only if
explicity configured to do so (e.g. through its device tree node)?
Like what was used for the Spansion's PPB, see:
http://lists.infradead.org/pipermail/linux-mtd/2013-January/045536.html
> The lock function will only change the
> protection bits if it would not unlock other areas. Similarly, the unlock
> function will not lock currently unlocked areas. Tested on the m25p64.
>
> From: Austin Boyle <Austin.Boyle@aviatnet.com>
> Signed-off-by: Austin Boyle <Austin.Boyle@aviatnet.com>
> ---
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 4eeeb2d..069e34f 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -565,6 +565,96 @@ time_out:
> return ret;
> }
>
> +static int m25p80_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> +{
> + struct m25p *flash = mtd_to_m25p(mtd);
> + uint32_t offset = ofs;
> + uint8_t status_old, status_new;
> + int res = 0;
> +
> + mutex_lock(&flash->lock);
> + /* Wait until finished previous command */
> + if (wait_till_ready(flash)) {
> + res = 1;
> + goto err;
> + }
> +
> + status_old = read_sr(flash);
> +
> + if (offset < flash->mtd.size-(flash->mtd.size/2))
> + status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0;
> + else if (offset < flash->mtd.size-(flash->mtd.size/4))
> + status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
> + else if (offset < flash->mtd.size-(flash->mtd.size/8))
> + status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
> + else if (offset < flash->mtd.size-(flash->mtd.size/16))
> + status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2;
> + else if (offset < flash->mtd.size-(flash->mtd.size/32))
> + status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
> + else if (offset < flash->mtd.size-(flash->mtd.size/64))
> + status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1;
> + else
> + status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0;
2) While I believe this might work on m25p32, m25p64 and m25p128 (i.e.
flashes with 64 blocks or more), it looks incorrect for smaller chips
(namely our m25p80, with just 16 blocks). There, the 1/64 logic scales
down to 1/16, e.g.
- 000 means protect nothing
- 001 means protect 1/16th (=1 blocks) [m25p64 => 1/64th]
- 010 means protect 1/8th (=2 blocks) [m25p64 => 1/32th]
- ...
- 100 means protect 1/2nd (=8 blocks)
- 101,110, 111 mean protect everything
and I assume the same goes for chips with fewer sectors.
Any comments?
Thanks,
Gerlando
> +
> + /* Only modify protection if it will not unlock other areas */
> + if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) >
> + (status_old&(SR_BP2|SR_BP1|SR_BP0))) {
> + write_enable(flash);
> + if (write_sr(flash, status_new) < 0) {
> + res = 1;
> + goto err;
> + }
> + }
> +
> +err: mutex_unlock(&flash->lock);
> + return res;
> +}
> +
> +static int m25p80_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> +{
> + struct m25p *flash = mtd_to_m25p(mtd);
> + uint32_t offset = ofs;
> + uint8_t status_old, status_new;
> + int res = 0;
> +
> + mutex_lock(&flash->lock);
> + /* Wait until finished previous command */
> + if (wait_till_ready(flash)) {
> + res = 1;
> + goto err;
> + }
> +
> + status_old = read_sr(flash);
> +
> + if (offset+len > flash->mtd.size-(flash->mtd.size/64))
> + status_new = status_old & ~(SR_BP2|SR_BP1|SR_BP0);
> + else if (offset+len > flash->mtd.size-(flash->mtd.size/32))
> + status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0;
> + else if (offset+len > flash->mtd.size-(flash->mtd.size/16))
> + status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1;
> + else if (offset+len > flash->mtd.size-(flash->mtd.size/8))
> + status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
> + else if (offset+len > flash->mtd.size-(flash->mtd.size/4))
> + status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2;
> + else if (offset+len > flash->mtd.size-(flash->mtd.size/2))
> + status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
> + else
> + status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
> +
> + /* Only modify protection if it will not lock other areas */
> + if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) <
> + (status_old&(SR_BP2|SR_BP1|SR_BP0))) {
> + write_enable(flash);
> + if (write_sr(flash, status_new) < 0) {
> + res = 1;
> + goto err;
> + }
> + }
> +
> +err: mutex_unlock(&flash->lock);
> + return res;
> +}
> +
> /****************************************************************************/
>
> /*
> @@ -899,6 +989,12 @@ static int m25p_probe(struct spi_device *spi)
> flash->mtd._erase = m25p80_erase;
> flash->mtd._read = m25p80_read;
>
> + /* flash protection support for STmicro chips */
> + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) {
> + flash->mtd._lock = m25p80_lock;
> + flash->mtd._unlock = m25p80_unlock;
> + }
> +
> /* sst flash chips use AAI word program */
> if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
> flash->mtd._write = sst_write;
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
next prev parent reply other threads:[~2013-11-20 20:04 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-04 0:02 [PATCH] mtd: m25p80: Flash protection support for STmicro chips Austin Boyle
2013-01-17 10:41 ` Artem Bityutskiy
2013-11-20 20:04 ` Gerlando Falauto [this message]
2014-02-27 14:34 ` Gerlando Falauto
2014-03-05 8:10 ` Brian Norris
2014-03-05 8:31 ` Brian Norris
2014-03-08 15:26 ` Austin Boyle
[not found] ` <CADnxWiqfaaRoaL+B_WQxx38-gpSDmdFQPLN-bs-moGRECXeJxg@mail.gmail.com>
2014-03-10 9:06 ` Gerlando Falauto
2014-03-13 12:57 ` Austin Boyle
2014-03-13 13:46 ` Gerlando Falauto
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=528D15B6.2030800@keymile.com \
--to=gerlando.falauto@keymile.com \
--cc=Austin.Boyle@aviatnet.com \
--cc=artem.bityutskiy@linux.intel.com \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).