Add AMD Fam10 B3 default settings to match AMD example code.
[coreboot.git] / util / flashrom / w39v080fa.c
1 /*
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
24 int 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
55 static 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
97 int 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
145 static 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
166 int 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         unlock_winbond_fwhub(flash);
172
173         printf("Erasing:     ");
174
175         for (i = 0; i < total_size; i += flash->page_size)
176                 erase_sector_winbond_fwhub(bios, i);
177
178         printf("\n");
179
180         for (i = 0; i < total_size; i++) {
181                 if (bios[i] != 0xff) {
182                         fprintf(stderr, "Error: Flash chip erase failed at 0x%08x(0x%02x)\n", i, bios[i]);
183                         return -1;
184                 }
185         }
186
187         return 0;
188 }
189
190 int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf)
191 {
192         int i;
193         int total_size = flash->total_size * 1024;
194         volatile uint8_t *bios = flash->virtual_memory;
195
196         if (erase_winbond_fwhub(flash))
197                 return -1;
198
199         printf("Programming: ");
200         for (i = 0; i < total_size; i+=flash->page_size) {
201                 printf("0x%08x\b\b\b\b\b\b\b\b\b\b", i);
202                 write_sector_jedec(bios, buf + i, bios + i, flash->page_size);
203         }
204         printf("\n");
205
206         return 0;
207 }
208