xref: /aosp_15_r20/external/flashrom/w39.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker  * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker  *
4*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2008 coresystems GmbH
5*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2010 Carl-Daniel Hailfinger
6*0d6140beSAndroid Build Coastguard Worker  *
7*0d6140beSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
8*0d6140beSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
9*0d6140beSAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
10*0d6140beSAndroid Build Coastguard Worker  * (at your option) any later version.
11*0d6140beSAndroid Build Coastguard Worker  *
12*0d6140beSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
13*0d6140beSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*0d6140beSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*0d6140beSAndroid Build Coastguard Worker  * GNU General Public License for more details.
16*0d6140beSAndroid Build Coastguard Worker  */
17*0d6140beSAndroid Build Coastguard Worker 
18*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
19*0d6140beSAndroid Build Coastguard Worker #include "chipdrivers.h"
20*0d6140beSAndroid Build Coastguard Worker 
w39_idmode_readb(struct flashctx * flash,unsigned int offset)21*0d6140beSAndroid Build Coastguard Worker static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset)
22*0d6140beSAndroid Build Coastguard Worker {
23*0d6140beSAndroid Build Coastguard Worker 	chipaddr bios = flash->virtual_memory;
24*0d6140beSAndroid Build Coastguard Worker 	uint8_t val;
25*0d6140beSAndroid Build Coastguard Worker 
26*0d6140beSAndroid Build Coastguard Worker 	/* Product Identification Entry */
27*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0xAA, bios + 0x5555);
28*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0x55, bios + 0x2AAA);
29*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0x90, bios + 0x5555);
30*0d6140beSAndroid Build Coastguard Worker 	programmer_delay(flash, 10);
31*0d6140beSAndroid Build Coastguard Worker 
32*0d6140beSAndroid Build Coastguard Worker 	/* Read something, maybe hardware lock bits */
33*0d6140beSAndroid Build Coastguard Worker 	val = chip_readb(flash, bios + offset);
34*0d6140beSAndroid Build Coastguard Worker 
35*0d6140beSAndroid Build Coastguard Worker 	/* Product Identification Exit */
36*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0xAA, bios + 0x5555);
37*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0x55, bios + 0x2AAA);
38*0d6140beSAndroid Build Coastguard Worker 	chip_writeb(flash, 0xF0, bios + 0x5555);
39*0d6140beSAndroid Build Coastguard Worker 	programmer_delay(flash, 10);
40*0d6140beSAndroid Build Coastguard Worker 
41*0d6140beSAndroid Build Coastguard Worker 	return val;
42*0d6140beSAndroid Build Coastguard Worker }
43*0d6140beSAndroid Build Coastguard Worker 
printlock_w39_tblwp(uint8_t lock)44*0d6140beSAndroid Build Coastguard Worker static int printlock_w39_tblwp(uint8_t lock)
45*0d6140beSAndroid Build Coastguard Worker {
46*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Hardware bootblock locking (#TBL) is %sactive.\n",
47*0d6140beSAndroid Build Coastguard Worker 		 (lock & (1 << 2)) ? "" : "not ");
48*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Hardware remaining chip locking (#WP) is %sactive..\n",
49*0d6140beSAndroid Build Coastguard Worker 		(lock & (1 << 3)) ? "" : "not ");
50*0d6140beSAndroid Build Coastguard Worker 	if (lock & ((1 << 2) | (1 << 3)))
51*0d6140beSAndroid Build Coastguard Worker 		return -1;
52*0d6140beSAndroid Build Coastguard Worker 
53*0d6140beSAndroid Build Coastguard Worker 	return 0;
54*0d6140beSAndroid Build Coastguard Worker }
55*0d6140beSAndroid Build Coastguard Worker 
printlock_w39_single_bootblock(uint8_t lock,uint16_t kB)56*0d6140beSAndroid Build Coastguard Worker static int printlock_w39_single_bootblock(uint8_t lock, uint16_t kB)
57*0d6140beSAndroid Build Coastguard Worker {
58*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Software %d kB bootblock locking is %sactive.\n", kB, (lock & 0x03) ? "" : "not ");
59*0d6140beSAndroid Build Coastguard Worker 	if (lock & 0x03)
60*0d6140beSAndroid Build Coastguard Worker 		return -1;
61*0d6140beSAndroid Build Coastguard Worker 
62*0d6140beSAndroid Build Coastguard Worker 	return 0;
63*0d6140beSAndroid Build Coastguard Worker }
64*0d6140beSAndroid Build Coastguard Worker 
printlock_w39_bootblock_64k16k(uint8_t lock)65*0d6140beSAndroid Build Coastguard Worker static int printlock_w39_bootblock_64k16k(uint8_t lock)
66*0d6140beSAndroid Build Coastguard Worker {
67*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Software 64 kB bootblock locking is %sactive.\n",
68*0d6140beSAndroid Build Coastguard Worker 		 (lock & (1 << 0)) ? "" : "not ");
69*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Software 16 kB bootblock locking is %sactive.\n",
70*0d6140beSAndroid Build Coastguard Worker 		 (lock & (1 << 1)) ? "" : "not ");
71*0d6140beSAndroid Build Coastguard Worker 	if (lock & ((1 << 1) | (1 << 0)))
72*0d6140beSAndroid Build Coastguard Worker 		return -1;
73*0d6140beSAndroid Build Coastguard Worker 
74*0d6140beSAndroid Build Coastguard Worker 	return 0;
75*0d6140beSAndroid Build Coastguard Worker }
76*0d6140beSAndroid Build Coastguard Worker 
printlock_w39_common(struct flashctx * flash,unsigned int offset)77*0d6140beSAndroid Build Coastguard Worker static int printlock_w39_common(struct flashctx *flash, unsigned int offset)
78*0d6140beSAndroid Build Coastguard Worker {
79*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
80*0d6140beSAndroid Build Coastguard Worker 
81*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, offset);
82*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Lockout bits:\n");
83*0d6140beSAndroid Build Coastguard Worker 	return printlock_w39_tblwp(lock);
84*0d6140beSAndroid Build Coastguard Worker }
85*0d6140beSAndroid Build Coastguard Worker 
printlock_w39f010(struct flashctx * flash)86*0d6140beSAndroid Build Coastguard Worker int printlock_w39f010(struct flashctx *flash)
87*0d6140beSAndroid Build Coastguard Worker {
88*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
89*0d6140beSAndroid Build Coastguard Worker 	int ret;
90*0d6140beSAndroid Build Coastguard Worker 
91*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x00002);
92*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Bottom boot block:\n");
93*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_single_bootblock(lock, 16);
94*0d6140beSAndroid Build Coastguard Worker 
95*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x1fff2);
96*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Top boot block:\n");
97*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_w39_single_bootblock(lock, 16);
98*0d6140beSAndroid Build Coastguard Worker 
99*0d6140beSAndroid Build Coastguard Worker 	return ret;
100*0d6140beSAndroid Build Coastguard Worker }
101*0d6140beSAndroid Build Coastguard Worker 
printlock_w39l010(struct flashctx * flash)102*0d6140beSAndroid Build Coastguard Worker int printlock_w39l010(struct flashctx *flash)
103*0d6140beSAndroid Build Coastguard Worker {
104*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
105*0d6140beSAndroid Build Coastguard Worker 	int ret;
106*0d6140beSAndroid Build Coastguard Worker 
107*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x00002);
108*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Bottom boot block:\n");
109*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_single_bootblock(lock, 8);
110*0d6140beSAndroid Build Coastguard Worker 
111*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x1fff2);
112*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Top boot block:\n");
113*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_w39_single_bootblock(lock, 8);
114*0d6140beSAndroid Build Coastguard Worker 
115*0d6140beSAndroid Build Coastguard Worker 	return ret;
116*0d6140beSAndroid Build Coastguard Worker }
117*0d6140beSAndroid Build Coastguard Worker 
printlock_w39l020(struct flashctx * flash)118*0d6140beSAndroid Build Coastguard Worker int printlock_w39l020(struct flashctx *flash)
119*0d6140beSAndroid Build Coastguard Worker {
120*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
121*0d6140beSAndroid Build Coastguard Worker 	int ret;
122*0d6140beSAndroid Build Coastguard Worker 
123*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x00002);
124*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Bottom boot block:\n");
125*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_bootblock_64k16k(lock);
126*0d6140beSAndroid Build Coastguard Worker 
127*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x3fff2);
128*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Top boot block:\n");
129*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_w39_bootblock_64k16k(lock);
130*0d6140beSAndroid Build Coastguard Worker 
131*0d6140beSAndroid Build Coastguard Worker 	return ret;
132*0d6140beSAndroid Build Coastguard Worker }
133*0d6140beSAndroid Build Coastguard Worker 
printlock_w39l040(struct flashctx * flash)134*0d6140beSAndroid Build Coastguard Worker int printlock_w39l040(struct flashctx *flash)
135*0d6140beSAndroid Build Coastguard Worker {
136*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
137*0d6140beSAndroid Build Coastguard Worker 	int ret;
138*0d6140beSAndroid Build Coastguard Worker 
139*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x00002);
140*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Bottom boot block:\n");
141*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_bootblock_64k16k(lock);
142*0d6140beSAndroid Build Coastguard Worker 
143*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x7fff2);
144*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Top boot block:\n");
145*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_w39_bootblock_64k16k(lock);
146*0d6140beSAndroid Build Coastguard Worker 
147*0d6140beSAndroid Build Coastguard Worker 	return ret;
148*0d6140beSAndroid Build Coastguard Worker }
149*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040a(struct flashctx * flash)150*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040a(struct flashctx *flash)
151*0d6140beSAndroid Build Coastguard Worker {
152*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock;
153*0d6140beSAndroid Build Coastguard Worker 	int ret = 0;
154*0d6140beSAndroid Build Coastguard Worker 
155*0d6140beSAndroid Build Coastguard Worker 	/* The W39V040A datasheet contradicts itself on the lock register
156*0d6140beSAndroid Build Coastguard Worker 	 * location: 0x00002 and 0x7fff2 are both mentioned. Pick the one
157*0d6140beSAndroid Build Coastguard Worker 	 * which is similar to the other chips of the same family.
158*0d6140beSAndroid Build Coastguard Worker 	 */
159*0d6140beSAndroid Build Coastguard Worker 	lock = w39_idmode_readb(flash, 0x7fff2);
160*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Lockout bits:\n");
161*0d6140beSAndroid Build Coastguard Worker 
162*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_tblwp(lock);
163*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_w39_bootblock_64k16k(lock);
164*0d6140beSAndroid Build Coastguard Worker 
165*0d6140beSAndroid Build Coastguard Worker 	return ret;
166*0d6140beSAndroid Build Coastguard Worker }
167*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040b(struct flashctx * flash)168*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040b(struct flashctx *flash)
169*0d6140beSAndroid Build Coastguard Worker {
170*0d6140beSAndroid Build Coastguard Worker 	return printlock_w39_common(flash, 0x7fff2);
171*0d6140beSAndroid Build Coastguard Worker }
172*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040c(struct flashctx * flash)173*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040c(struct flashctx *flash)
174*0d6140beSAndroid Build Coastguard Worker {
175*0d6140beSAndroid Build Coastguard Worker 	/* Typo in the datasheet? The other chips use 0x7fff2. */
176*0d6140beSAndroid Build Coastguard Worker 	return printlock_w39_common(flash, 0xfff2);
177*0d6140beSAndroid Build Coastguard Worker }
178*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040fa(struct flashctx * flash)179*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040fa(struct flashctx *flash)
180*0d6140beSAndroid Build Coastguard Worker {
181*0d6140beSAndroid Build Coastguard Worker 	int ret = 0;
182*0d6140beSAndroid Build Coastguard Worker 
183*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39v040a(flash);
184*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_regspace2_uniform_64k(flash);
185*0d6140beSAndroid Build Coastguard Worker 
186*0d6140beSAndroid Build Coastguard Worker 	return ret;
187*0d6140beSAndroid Build Coastguard Worker }
188*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040fb(struct flashctx * flash)189*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040fb(struct flashctx *flash)
190*0d6140beSAndroid Build Coastguard Worker {
191*0d6140beSAndroid Build Coastguard Worker 	int ret = 0;
192*0d6140beSAndroid Build Coastguard Worker 
193*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39v040b(flash);
194*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_regspace2_uniform_64k(flash);
195*0d6140beSAndroid Build Coastguard Worker 
196*0d6140beSAndroid Build Coastguard Worker 	return ret;
197*0d6140beSAndroid Build Coastguard Worker }
198*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v040fc(struct flashctx * flash)199*0d6140beSAndroid Build Coastguard Worker int printlock_w39v040fc(struct flashctx *flash)
200*0d6140beSAndroid Build Coastguard Worker {
201*0d6140beSAndroid Build Coastguard Worker 	int ret = 0;
202*0d6140beSAndroid Build Coastguard Worker 
203*0d6140beSAndroid Build Coastguard Worker 	/* W39V040C and W39V040FC use different WP/TBL offsets. */
204*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39_common(flash, 0x7fff2);
205*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_regspace2_uniform_64k(flash);
206*0d6140beSAndroid Build Coastguard Worker 
207*0d6140beSAndroid Build Coastguard Worker 	return ret;
208*0d6140beSAndroid Build Coastguard Worker }
209*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v080a(struct flashctx * flash)210*0d6140beSAndroid Build Coastguard Worker int printlock_w39v080a(struct flashctx *flash)
211*0d6140beSAndroid Build Coastguard Worker {
212*0d6140beSAndroid Build Coastguard Worker 	return printlock_w39_common(flash, 0xffff2);
213*0d6140beSAndroid Build Coastguard Worker }
214*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v080fa(struct flashctx * flash)215*0d6140beSAndroid Build Coastguard Worker int printlock_w39v080fa(struct flashctx *flash)
216*0d6140beSAndroid Build Coastguard Worker {
217*0d6140beSAndroid Build Coastguard Worker 	int ret = 0;
218*0d6140beSAndroid Build Coastguard Worker 
219*0d6140beSAndroid Build Coastguard Worker 	ret = printlock_w39v080a(flash);
220*0d6140beSAndroid Build Coastguard Worker 	ret |= printlock_regspace2_uniform_64k(flash);
221*0d6140beSAndroid Build Coastguard Worker 
222*0d6140beSAndroid Build Coastguard Worker 	return ret;
223*0d6140beSAndroid Build Coastguard Worker }
224*0d6140beSAndroid Build Coastguard Worker 
printlock_w39v080fa_dual(struct flashctx * flash)225*0d6140beSAndroid Build Coastguard Worker int printlock_w39v080fa_dual(struct flashctx *flash)
226*0d6140beSAndroid Build Coastguard Worker {
227*0d6140beSAndroid Build Coastguard Worker 	msg_cinfo("Block locking for W39V080FA in dual mode is "
228*0d6140beSAndroid Build Coastguard Worker 		  "undocumented.\n");
229*0d6140beSAndroid Build Coastguard Worker 	/* Better safe than sorry. */
230*0d6140beSAndroid Build Coastguard Worker 	return -1;
231*0d6140beSAndroid Build Coastguard Worker }
232*0d6140beSAndroid Build Coastguard Worker 
printlock_at49f(struct flashctx * flash)233*0d6140beSAndroid Build Coastguard Worker int printlock_at49f(struct flashctx *flash)
234*0d6140beSAndroid Build Coastguard Worker {
235*0d6140beSAndroid Build Coastguard Worker 	uint8_t lock = w39_idmode_readb(flash, 0x00002);
236*0d6140beSAndroid Build Coastguard Worker 	msg_cdbg("Hardware bootblock lockout is %sactive.\n",
237*0d6140beSAndroid Build Coastguard Worker 		 (lock & 0x01) ? "" : "not ");
238*0d6140beSAndroid Build Coastguard Worker 	return 0;
239*0d6140beSAndroid Build Coastguard Worker }
240