blob: c9f62c161bf09b06482367be4de8935a2dab25b6 [file] [log] [blame]
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 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; 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
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000021#include <string.h>
22#include <stdlib.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000023#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000024#include "programmer.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000025
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000026#if NEED_PCI == 1
Christian Ruppert0cdb0312009-05-14 18:57:26 +000027struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
28{
29 struct pci_dev *temp;
30
31 for (temp = pacc->devices; temp; temp = temp->next)
32 if (pci_filter_match(&filter, temp))
33 return temp;
34
35 return NULL;
36}
37
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000038struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
39{
40 struct pci_dev *temp;
41 struct pci_filter filter;
42 uint16_t tmp2;
43
44 pci_filter_init(NULL, &filter);
45 filter.vendor = vendor;
46
47 for (temp = pacc->devices; temp; temp = temp->next)
48 if (pci_filter_match(&filter, temp)) {
49 /* Read PCI class */
50 tmp2 = pci_read_word(temp, 0x0a);
51 if (tmp2 == class)
52 return temp;
53 }
54
55 return NULL;
56}
57
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000058struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
59{
60 struct pci_dev *temp;
61 struct pci_filter filter;
62
63 pci_filter_init(NULL, &filter);
64 filter.vendor = vendor;
65 filter.device = device;
66
67 for (temp = pacc->devices; temp; temp = temp->next)
68 if (pci_filter_match(&filter, temp))
69 return temp;
70
71 return NULL;
72}
73
74struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
75 uint16_t card_vendor, uint16_t card_device)
76{
77 struct pci_dev *temp;
78 struct pci_filter filter;
79
80 pci_filter_init(NULL, &filter);
81 filter.vendor = vendor;
82 filter.device = device;
83
84 for (temp = pacc->devices; temp; temp = temp->next)
85 if (pci_filter_match(&filter, temp)) {
86 if ((card_vendor ==
87 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
88 && (card_device ==
89 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
90 return temp;
91 }
92
93 return NULL;
94}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000095#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000096
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +000097#if CONFIG_INTERNAL == 1
Michael Karcher0bdc0922010-02-28 01:33:48 +000098int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000099int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000100
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000101#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000102void probe_superio(void)
103{
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000104 probe_superio_ite();
Uwe Hermann43959702010-03-13 17:28:29 +0000105#if 0
106 /* Winbond Super I/O code is not yet available. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000107 if (superio.vendor == SUPERIO_VENDOR_NONE)
108 superio = probe_superio_winbond();
109#endif
110}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000111
112int superio_count = 0;
113#define SUPERIO_MAX_COUNT 3
114
115struct superio superios[SUPERIO_MAX_COUNT];
116
117int register_superio(struct superio s)
118{
119 if (superio_count == SUPERIO_MAX_COUNT)
120 return 1;
121 superios[superio_count++] = s;
122 return 0;
123}
124
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000125#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000126
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000127int is_laptop = 0;
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000128int laptop_ok = 0;
Michael Karcher8c1df282010-02-26 09:51:20 +0000129
Uwe Hermanna0869322009-05-14 20:41:57 +0000130int internal_init(void)
131{
Peter Lemenkov0a6f9ca2010-09-20 17:23:38 +0000132#if __FLASHROM_LITTLE_ENDIAN__
Uwe Hermanna0869322009-05-14 20:41:57 +0000133 int ret = 0;
Peter Lemenkov0a6f9ca2010-09-20 17:23:38 +0000134#endif
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000135 int force_laptop = 0;
136 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000137
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000138 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000139 if (arg && !strcmp(arg,"force")) {
140 force_boardenable = 1;
141 } else if (arg && !strlen(arg)) {
142 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000143 free(arg);
144 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000145 } else if (arg) {
146 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000147 free(arg);
148 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000149 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000150 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000151
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000152 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000153 if (arg && !strcmp(arg,"force")) {
154 force_boardmismatch = 1;
155 } else if (arg && !strlen(arg)) {
156 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000157 free(arg);
158 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000159 } else if (arg) {
160 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000161 free(arg);
162 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000163 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000164 free(arg);
165
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000166 arg = extract_programmer_param("laptop");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000167 if (arg && !strcmp(arg,"force_I_want_a_brick")) {
168 force_laptop = 1;
169 } else if (arg && !strlen(arg)) {
170 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000171 free(arg);
172 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000173 } else if (arg) {
174 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000175 free(arg);
176 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000177 }
178 free(arg);
179
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000180 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000181
Michael Karcherb9dbe482011-05-11 17:07:07 +0000182 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
183 * is found, the init routine sets the buses_supported bitfield.
184 */
185 buses_supported = CHIP_BUSTYPE_NONSPI;
186
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000187 /* Initialize PCI access for flash enables */
188 pacc = pci_alloc(); /* Get the pci_access structure */
189 /* Set all options you want -- here we stick with the defaults */
190 pci_init(pacc); /* Initialize the PCI library */
191 pci_scan_bus(pacc); /* We want to get the list of devices */
192
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000193 if (processor_flash_enable()) {
194 msg_perr("Processor detection/init failed.\n"
195 "Aborting.\n");
196 return 1;
197 }
198
199#if defined(__i386__) || defined(__x86_64__)
200 /* We look at the cbtable first to see if we need a
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000201 * mainboard specific flash enable sequence.
202 */
203 coreboot_init();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000204
Michael Karcher6701ee82010-01-20 14:14:11 +0000205 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000206
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000207 /* In case Super I/O probing would cause pretty explosions. */
208 board_handle_before_superio();
209
Uwe Hermann43959702010-03-13 17:28:29 +0000210 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000211 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000212#else
213 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
214 * by coreboot.
215 * FIXME: Find a replacement for DMI on non-x86.
216 * FIXME: Enable Super I/O probing once port I/O is possible.
217 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000218#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000219
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000220 /* Check laptop whitelist. */
221 board_handle_before_laptop();
222
223 /* Warn if a non-whitelisted laptop is detected. */
224 if (is_laptop && !laptop_ok) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000225 msg_perr("========================================================================\n"
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000226 "WARNING! You seem to be running flashrom on an unsupported laptop.\n"
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000227 "Laptops, notebooks and netbooks are difficult to support and we recommend\n"
228 "to use the vendor flashing utility. The embedded controller (EC) in these\n"
229 "machines often interacts badly with flashing.\n"
230 "See http://www.flashrom.org/Laptops for details.\n\n"
231 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
232 "and write may brick your laptop.\n"
233 "Read and probe may irritate your EC and cause fan failure, backlight\n"
234 "failure and sudden poweroff.\n"
235 "You have been warned.\n"
236 "========================================================================\n");
237 if (force_laptop) {
238 msg_perr("Proceeding anyway because user specified "
239 "laptop=force_I_want_a_brick\n");
240 } else {
241 msg_perr("Aborting.\n");
242 exit(1);
243 }
244 }
Michael Karcher8c1df282010-02-26 09:51:20 +0000245
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000246#if __FLASHROM_LITTLE_ENDIAN__
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000247 /* try to enable it. Failure IS an option, since not all motherboards
248 * really need this to be done, etc., etc.
249 */
250 ret = chipset_flash_enable();
251 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000252 msg_perr("WARNING: No chipset found. Flash detection "
253 "will most likely fail.\n");
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000254 }
255
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000256#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000257 /* Probe unconditionally for IT87* LPC->SPI translation and for
258 * IT87* Parallel write enable.
259 */
260 init_superio_ite();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000261#endif
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000262
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000263 board_flash_enable(lb_vendor, lb_part);
264
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000265 /* Even if chipset init returns an error code, we don't want to abort.
266 * The error code might have been a warning only.
267 * Besides that, we don't check the board enable return code either.
268 */
Vladimir 'phcoder' Serbinenko5cfc94a2010-09-29 23:37:24 +0000269#if defined(__i386__) || defined(__x86_64__) || defined (__mips)
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000270 return 0;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000271#else
272 msg_perr("Your platform is not supported yet for the internal "
273 "programmer due to missing\n"
274 "flash_base and top/bottom alignment information.\n"
275 "Aborting.\n");
276 return 1;
277#endif
278#else
279 /* FIXME: Remove this unconditional abort once all PCI drivers are
280 * converted to use little-endian accesses for memory BARs.
281 */
282 msg_perr("Your platform is not supported yet for the internal "
283 "programmer because it has\n"
284 "not been converted from native endian to little endian "
285 "access yet.\n"
286 "Aborting.\n");
287 return 1;
288#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000289}
290
291int internal_shutdown(void)
292{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000293 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000294
295 return 0;
296}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000297#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000298
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000299void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000300{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000301 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000302}
303
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000304void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000305{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000306 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000307}
308
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000309void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000310{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000311 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000312}
313
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000314uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000315{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000316 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000317}
318
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000319uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000320{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000321 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000322}
323
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000324uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000325{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000326 return mmio_readl((void *) addr);
327}
328
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000329void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
330{
331 memcpy(buf, (void *)addr, len);
332 return;
333}