blob: 8891e2b059ea36bc9cb6c461f8fb29901fc7549d [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
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +000089int spi_prettyprint_status_register_at25f(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
167 msg_cdbg("Some block protection in effect, disabling\n");
168 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) {
178 msg_cerr("spi_write_status_register failed\n");
179 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) {
186 msg_cerr("spi_write_status_register failed\n");
187 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 }
194 return 0;
195}
196
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000197int spi_disable_blockprotect_at25df_sec(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000198{
199 /* FIXME: We should check the security lockdown. */
200 msg_cinfo("Ignoring security lockdown (if present)\n");
201 return spi_disable_blockprotect_at25df(flash);
202}
203
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000204int spi_disable_blockprotect_at25f(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000205{
206 /* spi_disable_blockprotect_at25df is not really the right way to do
207 * this, but the side effects of said function work here as well.
208 */
209 return spi_disable_blockprotect_at25df(flash);
210}
211
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000212int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000213{
214 uint8_t status;
215 int result;
216
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000217 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000218 /* If block protection is disabled, stop here. */
219 if ((status & 0x6c) == 0)
220 return 0;
221
222 msg_cdbg("Some block protection in effect, disabling\n");
223 if (status & (1 << 7)) {
224 msg_cdbg("Need to disable Status Register Write Protect\n");
225 /* Clear bit 7 (WPEN). */
226 result = spi_write_status_register(flash, status & ~(1 << 7));
227 if (result) {
228 msg_cerr("spi_write_status_register failed\n");
229 return result;
230 }
231 }
232 /* Global unprotect. Make sure to mask WPEN as well. */
233 result = spi_write_status_register(flash, status & ~0xec);
234 if (result) {
235 msg_cerr("spi_write_status_register failed\n");
236 return result;
237 }
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000238 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000239 if ((status & 0x6c) != 0) {
240 msg_cerr("Block protection could not be disabled!\n");
241 return 1;
242 }
243 return 0;
244}
245
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000246int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000247{
248 uint8_t status;
249 int result;
250
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000251 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000252 /* If block protection is disabled, stop here. */
253 if ((status & 0x7c) == 0)
254 return 0;
255
256 msg_cdbg("Some block protection in effect, disabling\n");
257 if (status & (1 << 7)) {
258 msg_cdbg("Need to disable Status Register Write Protect\n");
259 /* Clear bit 7 (WPEN). */
260 result = spi_write_status_register(flash, status & ~(1 << 7));
261 if (result) {
262 msg_cerr("spi_write_status_register failed\n");
263 return result;
264 }
265 }
266 /* Global unprotect. Make sure to mask WPEN as well. */
267 result = spi_write_status_register(flash, status & ~0xfc);
268 if (result) {
269 msg_cerr("spi_write_status_register failed\n");
270 return result;
271 }
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000272 status = spi_read_status_register(flash);
Carl-Daniel Hailfinger7a3bd8f2011-05-19 00:06:06 +0000273 if ((status & 0x7c) != 0) {
274 msg_cerr("Block protection could not be disabled!\n");
275 return 1;
276 }
277 return 0;
278}