blob: 8547fb3bc623ca1f81367cee54c5e0930ca5dada [file] [log] [blame]
Stefan Reinauerc34ce2e2008-03-18 00:36:18 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
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; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdio.h>
22#include "flash.h"
23
24int probe_winbond_fwhub(struct flashchip *flash)
25{
26 volatile uint8_t *bios = flash->virtual_memory;
27 uint8_t vid, did;
28
29 /* Product Identification Entry */
30 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
31 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
32 *(volatile uint8_t *)(bios + 0x5555) = 0x90;
33 myusec_delay(10);
34
35 /* Read product ID */
36 vid = *(volatile uint8_t *)bios;
37 did = *(volatile uint8_t *)(bios + 0x01);
38
39 /* Product Identifixation Exit */
40 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
41 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
42 *(volatile uint8_t *)(bios + 0x5555) = 0xF0;
43 myusec_delay(10);
44
45 printf_debug("%s: vid 0x%x, did 0x%x\n", __FUNCTION__, vid, did);
46
47 if (vid != flash->manufacture_id || did != flash->model_id)
48 return 0;
49
50 map_flash_registers(flash);
51
52 return 1;
53}
54
55static int unlock_block_winbond_fwhub(struct flashchip *flash, int offset)
56{
57 volatile uint8_t *wrprotect = flash->virtual_registers + offset + 2;
58 uint8_t locking;
59
60 printf_debug("Trying to unlock block @0x%08x = 0x%02x\n", offset, *wrprotect);
61
62 locking = *wrprotect;
63 switch (locking & 0x7 ) {
64 case 0:
65 printf_debug("Full Access.\n");
66 return 0;
67 case 1:
68 printf_debug("Write Lock (Default State).\n");
69 *wrprotect = 0;
70 return 0;
71 case 2:
72 printf_debug("Locked Open (Full Access, Lock Down).\n");
73 return 0;
74 case 3:
75 fprintf(stderr, "Error: Write Lock, Locked Down.\n");
76 return -1;
77 case 4:
78 printf_debug("Read Lock.\n");
79 *wrprotect = 0;
80 return 0;
81 case 5:
82 printf_debug("Read/Write Lock.\n");
83 *wrprotect = 0;
84 return 0;
85 case 6:
86 fprintf(stderr, "Error: Read Lock, Locked Down.\n");
87 return -1;
88 case 7:
89 fprintf(stderr, "Error: Read/Write Lock, Locked Down.\n");
90 return -1;
91 }
92
93 /* We will never reach this point, but GCC doesn't know */
94 return -1;
95}
96
97int unlock_winbond_fwhub(struct flashchip *flash)
98{
99 int i, total_size = flash->total_size * 1024;
100 volatile uint8_t *bios = flash->virtual_memory;
101 uint8_t locking;
102
103 /* Are there any hardware restrictions that we can't overcome?
104 * If flashrom fail here, someone's got to check all those GPIOs.
105 */
106
107 /* Product Identification Entry */
108 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
109 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
110 *(volatile uint8_t *)(bios + 0x5555) = 0x90;
111 myusec_delay(10);
112
113 /* Read Hardware Lock Bits */
114 locking = *(volatile uint8_t *)(bios + 0xffff2);
115
116 /* Product Identification Exit */
117 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
118 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
119 *(volatile uint8_t *)(bios + 0x5555) = 0xF0;
120 myusec_delay(10);
121
122 printf_debug("Lockout bits:\n");
123
124 if (locking & (1<<2))
125 fprintf(stderr, "Error: hardware bootblock locking (#TBL).\n");
126 else
127 printf_debug("No hardware bootblock locking (good!)\n");
128
129 if (locking & (1<<3))
130 fprintf(stderr, "Error: hardware block locking (#WP).\n");
131 else
132 printf_debug("No hardware block locking (good!)\n");
133
134 if (locking & ((1<<2) | (1<<3)))
135 return -1;
136
137 /* Unlock the complete chip */
138 for (i = 0; i < total_size; i += flash->page_size)
139 if (unlock_block_winbond_fwhub(flash, i))
140 return -1;
141
142 return 0;
143}
144
145static int erase_sector_winbond_fwhub(volatile uint8_t *bios, unsigned int sector)
146{
147 /* Remember: too much sleep can waste your day. */
148
149 printf("0x%08x\b\b\b\b\b\b\b\b\b\b", sector);
150
151 /* Sector Erase */
152 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
153 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
154 *(volatile uint8_t *)(bios + 0x5555) = 0x80;
155
156 *(volatile uint8_t *)(bios + 0x5555) = 0xAA;
157 *(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
158 *(volatile uint8_t *)(bios + sector) = 0x30;
159
160 /* wait for Toggle bit ready */
161 toggle_ready_jedec(bios);
162
163 return 0;
164}
165
166int erase_winbond_fwhub(struct flashchip *flash)
167{
168 int i, total_size = flash->total_size * 1024;
169 volatile uint8_t *bios = flash->virtual_memory;
170
171 printf("Erasing: ");
172
173 for (i = 0; i < total_size; i += flash->page_size)
174 erase_sector_winbond_fwhub(bios, i);
175
176 printf("\n");
177
178 for (i = 0; i < total_size; i++) {
179 if (bios[i] != 0xff) {
180 fprintf(stderr, "Error: Flash chip erase failed at 0x%08x(0x%02x)\n", i, bios[i]);
181 return -1;
182 }
183 }
184
185 return 0;
186}
187
188int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf)
189{
190 int i;
191 int total_size = flash->total_size * 1024;
192 volatile uint8_t *bios = flash->virtual_memory;
193
194 if (erase_winbond_fwhub(flash))
195 return -1;
196
197 printf("Programming: ");
198 for (i = 0; i < total_size; i+=flash->page_size) {
199 printf("0x%08x\b\b\b\b\b\b\b\b\b\b", i);
200 write_sector_jedec(bios, buf + i, bios + i, flash->page_size);
201 }
202 printf("\n");
203
204 return 0;
205}
206