1 From 986172ece10eee928ce66597d76f3f40ac3d25f7 Mon Sep 17 00:00:00 2001
2 From: Yunhui Cui <yunhui.cui@nxp.com>
3 Date: Mon, 8 Aug 2016 14:24:13 +0800
4 Subject: [PATCH 86/93] driver: spi: add spansion s25fs-s family
7 In order to support spansion s25fs512s flash protect/unprotect:
9 [1] Fill callbak flash->lock/unlock/is_locked by spansion_lock/
12 [2] Achieve protect/unprotected by operating sr1nv, cr1nv.
14 Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
16 drivers/mtd/spi/spi_flash.c | 194 +++++++++++++++++++++++++++++++++++++++++++
17 1 file changed, 194 insertions(+)
19 diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
20 index e04bd55..87a92e9 100644
21 --- a/drivers/mtd/spi/spi_flash.c
22 +++ b/drivers/mtd/spi/spi_flash.c
23 @@ -877,6 +877,193 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
27 +#if defined(CONFIG_SPI_FLASH_SPANSION)
29 + * Return 1 if the entire region is locked, 0 otherwise
31 +static int spansion_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len,
37 + stm_get_locked_range(flash, sr, &lock_offs, &lock_len);
39 + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
43 + * Check if a region of the flash is (completely) locked. See spansion_lock() for
46 + * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
47 + * negative on errors.
49 +int spansion_is_locked(struct spi_flash *flash, u32 ofs, size_t len)
52 + u32 sr1nv_offset = 0x0;
56 + cmd[0] = CMD_SPANSION_RDAR;
57 + cmd[1] = sr1nv_offset >> 16;
58 + cmd[2] = sr1nv_offset >> 8;
59 + cmd[3] = sr1nv_offset >> 0;
61 + ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
65 + return spansion_is_locked_sr(flash, ofs, len, sr1nv);
69 + * Lock a region of the flash. Compatible with Spansion s25fs-s family flash.
70 + * Supports only the block protection bits BP{0,1,2} in the Status Register-1
71 + * Non-Volatile(SR1NV).
73 + * Sample table portion for 64MB flash (S25FS512S):
74 + * Configuration Register-1 Non-Volatile(CR1NV[5])== 0
76 + * | BP2 | BP1 | BP0 | Prot Length | Protected Portion
77 + * ------------------------------------------------------------
78 + * | 0 | 0 | 0 | NONE | NONE
79 + * | 0 | 0 | 1 | 1 MB | Upper 1/64
80 + * | 0 | 1 | 0 | 2 MB | Upper 1/32
81 + * | 0 | 1 | 1 | 4 MB | Upper 1/16
82 + * | 1 | 0 | 0 | 8 MB | Upper 1/8
83 + * | 1 | 0 | 1 | 16 MB | Upper 1/4
84 + * | 1 | 1 | 0 | 32 MB | Upper 1/2
85 + * | 1 | 1 | 1 | 64 MB | ALL
87 + * When CR1NV[5] == 1, the Lower memory array are protected.
89 + * Returns negative on errors, 0 on success.
91 +int spansion_lock(struct spi_flash *flash, u32 ofs, size_t len)
93 + u8 status_old, status_new;
94 + u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
95 + u8 shift = ffs(mask) - 1, pow, val;
98 + u32 sr1nv_offset = 0x0;
101 + cmd[0] = CMD_SPANSION_RDAR;
102 + cmd[1] = sr1nv_offset >> 16;
103 + cmd[2] = sr1nv_offset >> 8;
104 + cmd[3] = sr1nv_offset >> 0;
106 + ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
109 + status_old = sr1nv;
111 + /* SPI NOR always locks to the end */
112 + if (ofs + len != flash->size) {
113 + /* Does combined region extend to end? */
114 + if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len,
117 + len = flash->size - ofs;
121 + * Need smallest pow such that:
123 + * 1 / (2^pow) <= (len / size)
125 + * so (assuming power-of-2 size) we do:
127 + * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
129 + pow = ilog2(flash->size) - ilog2(len);
130 + val = mask - (pow << shift);
134 + /* Don't "lock" with no region! */
138 + status_new = (status_old & ~mask) | val;
140 + /* Only modify protection if it will not unlock other areas */
141 + if ((status_new & mask) <= (status_old & mask))
144 + cmd[0] = CMD_SPANSION_WRAR;
145 + ret = spi_flash_cmd_write(flash->spi, cmd, 4, &status_new, 1);
153 + * Unlock a region of the flash. See spansion_lock() for more info
155 + * Returns negative on errors, 0 on success.
157 +int spansion_unlock(struct spi_flash *flash, u32 ofs, size_t len)
159 + uint8_t status_old, status_new;
160 + u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
161 + u8 shift = ffs(mask) - 1, pow, val;
165 + u32 sr1nv_offset = 0x0;
168 + cmd[0] = CMD_SPANSION_RDAR;
169 + cmd[1] = sr1nv_offset >> 16;
170 + cmd[2] = sr1nv_offset >> 8;
171 + cmd[3] = sr1nv_offset >> 0;
173 + ret = spi_flash_cmd_read(flash->spi, cmd, 4, &sr1nv, 1);
176 + status_old = sr1nv;
178 + /* Cannot unlock; would unlock larger region than requested */
179 + if (spansion_is_locked_sr(flash, ofs - flash->erase_size, flash->erase_size,
183 + * Need largest pow such that:
185 + * 1 / (2^pow) >= (len / size)
187 + * so (assuming power-of-2 size) we do:
189 + * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len))
191 + pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len));
192 + if (ofs + len == flash->size) {
193 + val = 0; /* fully unlocked */
195 + val = mask - (pow << shift);
196 + /* Some power-of-two sizes are not supported */
200 + status_new = (status_old & ~mask) | val;
202 + /* Only modify protection if it will not lock other areas */
203 + if ((status_new & mask) >= (status_old & mask))
206 + cmd[0] = CMD_SPANSION_WRAR;
207 + ret = spi_flash_cmd_write(flash->spi, cmd, 4, &status_new, 1);
215 #ifdef CONFIG_SPI_FLASH_MACRONIX
216 static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
217 @@ -1132,6 +1319,13 @@ int spi_flash_scan(struct spi_flash *flash)
218 flash->flash_is_locked = stm_is_locked;
221 +#if defined(CONFIG_SPI_FLASH_SPANSION)
222 + case SPI_FLASH_CFI_MFR_SPANSION:
223 + flash->flash_lock = spansion_lock;
224 + flash->flash_unlock = spansion_unlock;
225 + flash->flash_is_locked = spansion_is_locked;
229 debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);