blob: 803e7e483a413e90d2675fbc9d1a36176bf3308f [file] [log] [blame]
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2010 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "flash.h"
21#include "chipdrivers.h"
22#include "spi.h"
23
24/* Prettyprint the status register. Works for Atmel A25/A26 series. */
25
Stefan Tauner1ba08f62012-08-02 23:51:28 +000026static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status)
27{
28 msg_cdbg("Chip status register: Write Protect Enable (WPEN) "
29 "is %sset\n", (status & (1 << 7)) ? "" : "not ");
30}
31
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000032static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
33{
34 msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) "
35 "is %sset\n", (status & (1 << 7)) ? "" : "not ");
36}
37
38static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status)
39{
40 msg_cdbg("Chip status register: Erase/Program Error (EPE) "
41 "is %sset\n", (status & (1 << 5)) ? "" : "not ");
42 msg_cdbg("Chip status register: WP# pin (WPP) "
43 "is %sasserted\n", (status & (1 << 4)) ? "not " : "");
44}
45
46static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
47{
48 msg_cdbg("Chip status register: Software Protection Status (SWP): ");
49 switch (status & (3 << 2)) {
50 case 0x0 << 2:
51 msg_cdbg("no sectors are protected\n");
52 break;
53 case 0x1 << 2:
54 msg_cdbg("some sectors are protected\n");
55 /* FIXME: Read individual Sector Protection Registers. */
56 break;
57 case 0x3 << 2:
58 msg_cdbg("all sectors are protected\n");
59 break;
60 default:
61 msg_cdbg("reserved for future use\n");
62 break;
63 }
64}
65
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +000066int spi_prettyprint_status_register_at25df(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000067{
68 uint8_t status;
69
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000070 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000071 msg_cdbg("Chip status register is %02x\n", status);
72
73 spi_prettyprint_status_register_atmel_at25_srpl(status);
74 spi_prettyprint_status_register_bit(status, 6);
75 spi_prettyprint_status_register_atmel_at25_epewpp(status);
76 spi_prettyprint_status_register_atmel_at25_swp(status);
77 spi_prettyprint_status_register_welwip(status);
78 return 0;
79}
80
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +000081int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000082{
83 /* FIXME: We should check the security lockdown. */
84 msg_cdbg("Ignoring security lockdown (if present)\n");
85 msg_cdbg("Ignoring status register byte 2\n");
86 return spi_prettyprint_status_register_at25df(flash);
87}
88
Stefan Tauner7bf4ed92012-08-26 21:04:27 +000089int spi_prettyprint_status_register_at25f512b(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000090{
91 uint8_t status;
92
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000093 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +000094 msg_cdbg("Chip status register is %02x\n", status);
95
96 spi_prettyprint_status_register_atmel_at25_srpl(status);
97 spi_prettyprint_status_register_bit(status, 6);
98 spi_prettyprint_status_register_atmel_at25_epewpp(status);
99 spi_prettyprint_status_register_bit(status, 3);
Stefan Tauner1ba08f62012-08-02 23:51:28 +0000100 spi_prettyprint_status_register_bp(status, 0);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000101 spi_prettyprint_status_register_welwip(status);
102 return 0;
103}
104
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000105int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000106{
107 uint8_t status;
108
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000109 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000110 msg_cdbg("Chip status register is %02x\n", status);
111
Stefan Tauner1ba08f62012-08-02 23:51:28 +0000112 spi_prettyprint_status_register_atmel_at25_wpen(status);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000113 msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
114 "%sset\n", (status & (1 << 6)) ? "" : "not ");
115 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
116 "%sset\n", (status & (1 << 5)) ? "" : "not ");
Stefan Tauner1ba08f62012-08-02 23:51:28 +0000117 spi_prettyprint_status_register_bit(status, 4);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000118 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
119 "%sset\n", (status & (1 << 3)) ? "" : "not ");
120 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
121 "%sset\n", (status & (1 << 2)) ? "" : "not ");
122 /* FIXME: Pretty-print detailed sector protection status. */
123 spi_prettyprint_status_register_welwip(status);
124 return 0;
125}
126
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000127int spi_prettyprint_status_register_at25fs040(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000128{
129 uint8_t status;
130
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000131 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000132 msg_cdbg("Chip status register is %02x\n", status);
133
Stefan Tauner1ba08f62012-08-02 23:51:28 +0000134 spi_prettyprint_status_register_atmel_at25_wpen(status);
135 spi_prettyprint_status_register_bp(status, 4);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000136 /* FIXME: Pretty-print detailed sector protection status. */
137 spi_prettyprint_status_register_welwip(status);
138 return 0;
139}
140
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000141int spi_prettyprint_status_register_atmel_at26df081a(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000142{
143 uint8_t status;
144
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000145 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000146 msg_cdbg("Chip status register is %02x\n", status);
147
148 spi_prettyprint_status_register_atmel_at25_srpl(status);
149 msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) "
150 "is %sset\n", (status & (1 << 6)) ? "" : "not ");
151 spi_prettyprint_status_register_atmel_at25_epewpp(status);
152 spi_prettyprint_status_register_atmel_at25_swp(status);
153 spi_prettyprint_status_register_welwip(status);
154 return 0;
155}
156
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000157int spi_disable_blockprotect_at25df(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000158{
159 uint8_t status;
160 int result;
161
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000162 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000163 /* If block protection is disabled, stop here. */
164 if ((status & (3 << 2)) == 0)
165 return 0;
166
Stefan Tauner87fbb772012-08-02 23:56:49 +0000167 msg_cdbg("Some block protection in effect, disabling... ");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000168 if (status & (1 << 7)) {
169 msg_cdbg("Need to disable Sector Protection Register Lock\n");
170 if ((status & (1 << 4)) == 0) {
171 msg_cerr("WP# pin is active, disabling "
172 "write protection is impossible.\n");
173 return 1;
174 }
175 /* All bits except bit 7 (SPRL) are readonly. */
176 result = spi_write_status_register(flash, status & ~(1 << 7));
177 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000178 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000179 return result;
180 }
181
182 }
183 /* Global unprotect. Make sure to mask SPRL as well. */
184 result = spi_write_status_register(flash, status & ~0xbc);
185 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000186 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000187 return result;
188 }
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000189 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000190 if ((status & (3 << 2)) != 0) {
191 msg_cerr("Block protection could not be disabled!\n");
192 return 1;
193 }
Stefan Tauner87fbb772012-08-02 23:56:49 +0000194 msg_cdbg("done.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000195 return 0;
196}
197
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000198int spi_disable_blockprotect_at25df_sec(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000199{
200 /* FIXME: We should check the security lockdown. */
201 msg_cinfo("Ignoring security lockdown (if present)\n");
202 return spi_disable_blockprotect_at25df(flash);
203}
204
Stefan Tauner7bf4ed92012-08-26 21:04:27 +0000205int spi_disable_blockprotect_at25f512b(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000206{
207 /* spi_disable_blockprotect_at25df is not really the right way to do
208 * this, but the side effects of said function work here as well.
209 */
210 return spi_disable_blockprotect_at25df(flash);
211}
212
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000213int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000214{
215 uint8_t status;
216 int result;
217
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000218 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000219 /* If block protection is disabled, stop here. */
220 if ((status & 0x6c) == 0)
221 return 0;
222
Stefan Tauner87fbb772012-08-02 23:56:49 +0000223 msg_cdbg("Some block protection in effect, disabling... ");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000224 if (status & (1 << 7)) {
225 msg_cdbg("Need to disable Status Register Write Protect\n");
226 /* Clear bit 7 (WPEN). */
227 result = spi_write_status_register(flash, status & ~(1 << 7));
228 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000229 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000230 return result;
231 }
232 }
233 /* Global unprotect. Make sure to mask WPEN as well. */
234 result = spi_write_status_register(flash, status & ~0xec);
235 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000236 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000237 return result;
238 }
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000239 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000240 if ((status & 0x6c) != 0) {
241 msg_cerr("Block protection could not be disabled!\n");
242 return 1;
243 }
Stefan Tauner87fbb772012-08-02 23:56:49 +0000244 msg_cdbg("done.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000245 return 0;
246}
247
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000248int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000249{
250 uint8_t status;
251 int result;
252
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000253 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000254 /* If block protection is disabled, stop here. */
255 if ((status & 0x7c) == 0)
256 return 0;
257
Stefan Tauner87fbb772012-08-02 23:56:49 +0000258 msg_cdbg("Some block protection in effect, disabling... ");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000259 if (status & (1 << 7)) {
260 msg_cdbg("Need to disable Status Register Write Protect\n");
261 /* Clear bit 7 (WPEN). */
262 result = spi_write_status_register(flash, status & ~(1 << 7));
263 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000264 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000265 return result;
266 }
267 }
268 /* Global unprotect. Make sure to mask WPEN as well. */
269 result = spi_write_status_register(flash, status & ~0xfc);
270 if (result) {
Stefan Tauner87fbb772012-08-02 23:56:49 +0000271 msg_cerr("spi_write_status_register failed.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000272 return result;
273 }
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000274 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000275 if ((status & 0x7c) != 0) {
276 msg_cerr("Block protection could not be disabled!\n");
277 return 1;
278 }
Stefan Tauner87fbb772012-08-02 23:56:49 +0000279 msg_cdbg("done.\n");
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000280 return 0;
281}