blob: 8b19692fa8756eb8cdc9e8a4245d8893ac92242e [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
21#include <stdint.h>
22#include <string.h>
23#include <stdlib.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000024#include <sys/types.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000025#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000026#include "programmer.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000027
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000028#if NEED_PCI == 1
Christian Ruppert0cdb0312009-05-14 18:57:26 +000029struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
30{
31 struct pci_dev *temp;
32
33 for (temp = pacc->devices; temp; temp = temp->next)
34 if (pci_filter_match(&filter, temp))
35 return temp;
36
37 return NULL;
38}
39
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000040struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
41{
42 struct pci_dev *temp;
43 struct pci_filter filter;
44 uint16_t tmp2;
45
46 pci_filter_init(NULL, &filter);
47 filter.vendor = vendor;
48
49 for (temp = pacc->devices; temp; temp = temp->next)
50 if (pci_filter_match(&filter, temp)) {
51 /* Read PCI class */
52 tmp2 = pci_read_word(temp, 0x0a);
53 if (tmp2 == class)
54 return temp;
55 }
56
57 return NULL;
58}
59
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000060struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
61{
62 struct pci_dev *temp;
63 struct pci_filter filter;
64
65 pci_filter_init(NULL, &filter);
66 filter.vendor = vendor;
67 filter.device = device;
68
69 for (temp = pacc->devices; temp; temp = temp->next)
70 if (pci_filter_match(&filter, temp))
71 return temp;
72
73 return NULL;
74}
75
76struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
77 uint16_t card_vendor, uint16_t card_device)
78{
79 struct pci_dev *temp;
80 struct pci_filter filter;
81
82 pci_filter_init(NULL, &filter);
83 filter.vendor = vendor;
84 filter.device = device;
85
86 for (temp = pacc->devices; temp; temp = temp->next)
87 if (pci_filter_match(&filter, temp)) {
88 if ((card_vendor ==
89 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
90 && (card_device ==
91 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
92 return temp;
93 }
94
95 return NULL;
96}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000097#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000098
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +000099#if CONFIG_INTERNAL == 1
Michael Karcher0bdc0922010-02-28 01:33:48 +0000100int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000101int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000102
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000103#if defined(__i386__) || defined(__x86_64__)
104struct superio superio = {};
105
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000106void probe_superio(void)
107{
108 superio = probe_superio_ite();
Uwe Hermann43959702010-03-13 17:28:29 +0000109#if 0
110 /* Winbond Super I/O code is not yet available. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000111 if (superio.vendor == SUPERIO_VENDOR_NONE)
112 superio = probe_superio_winbond();
113#endif
114}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000115#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000116
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000117int is_laptop = 0;
Michael Karcher8c1df282010-02-26 09:51:20 +0000118
Uwe Hermanna0869322009-05-14 20:41:57 +0000119int internal_init(void)
120{
121 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000122 int force_laptop = 0;
123 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000124
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000125 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000126 if (arg && !strcmp(arg,"force")) {
127 force_boardenable = 1;
128 } else if (arg && !strlen(arg)) {
129 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000130 free(arg);
131 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000132 } else if (arg) {
133 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000134 free(arg);
135 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000136 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000137 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000138
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000139 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000140 if (arg && !strcmp(arg,"force")) {
141 force_boardmismatch = 1;
142 } else if (arg && !strlen(arg)) {
143 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000144 free(arg);
145 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000146 } else if (arg) {
147 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000148 free(arg);
149 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000150 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000151 free(arg);
152
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000153 arg = extract_programmer_param("laptop");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000154 if (arg && !strcmp(arg,"force_I_want_a_brick")) {
155 force_laptop = 1;
156 } else if (arg && !strlen(arg)) {
157 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000158 free(arg);
159 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000160 } else if (arg) {
161 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000162 free(arg);
163 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000164 }
165 free(arg);
166
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000167 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000168
169 /* Initialize PCI access for flash enables */
170 pacc = pci_alloc(); /* Get the pci_access structure */
171 /* Set all options you want -- here we stick with the defaults */
172 pci_init(pacc); /* Initialize the PCI library */
173 pci_scan_bus(pacc); /* We want to get the list of devices */
174
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000175 if (processor_flash_enable()) {
176 msg_perr("Processor detection/init failed.\n"
177 "Aborting.\n");
178 return 1;
179 }
180
181#if defined(__i386__) || defined(__x86_64__)
182 /* We look at the cbtable first to see if we need a
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000183 * mainboard specific flash enable sequence.
184 */
185 coreboot_init();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000186
Michael Karcher6701ee82010-01-20 14:14:11 +0000187 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000188
Uwe Hermann43959702010-03-13 17:28:29 +0000189 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000190 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000191#else
192 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
193 * by coreboot.
194 * FIXME: Find a replacement for DMI on non-x86.
195 * FIXME: Enable Super I/O probing once port I/O is possible.
196 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000197#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000198
Uwe Hermann43959702010-03-13 17:28:29 +0000199 /* Warn if a laptop is detected. */
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000200 if (is_laptop) {
201 msg_perr("========================================================================\n"
202 "WARNING! You seem to be running flashrom on a laptop.\n"
203 "Laptops, notebooks and netbooks are difficult to support and we recommend\n"
204 "to use the vendor flashing utility. The embedded controller (EC) in these\n"
205 "machines often interacts badly with flashing.\n"
206 "See http://www.flashrom.org/Laptops for details.\n\n"
207 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
208 "and write may brick your laptop.\n"
209 "Read and probe may irritate your EC and cause fan failure, backlight\n"
210 "failure and sudden poweroff.\n"
211 "You have been warned.\n"
212 "========================================================================\n");
213 if (force_laptop) {
214 msg_perr("Proceeding anyway because user specified "
215 "laptop=force_I_want_a_brick\n");
216 } else {
217 msg_perr("Aborting.\n");
218 exit(1);
219 }
220 }
Michael Karcher8c1df282010-02-26 09:51:20 +0000221
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000222#if __FLASHROM_LITTLE_ENDIAN__
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000223 /* try to enable it. Failure IS an option, since not all motherboards
224 * really need this to be done, etc., etc.
225 */
226 ret = chipset_flash_enable();
227 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000228 msg_perr("WARNING: No chipset found. Flash detection "
229 "will most likely fail.\n");
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000230 }
231
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000232#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000233 /* Probe unconditionally for IT87* LPC->SPI translation and for
234 * IT87* Parallel write enable.
235 */
236 init_superio_ite();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000237#endif
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000238
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000239 board_flash_enable(lb_vendor, lb_part);
240
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000241 /* Even if chipset init returns an error code, we don't want to abort.
242 * The error code might have been a warning only.
243 * Besides that, we don't check the board enable return code either.
244 */
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000245#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000246 return 0;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000247#else
248 msg_perr("Your platform is not supported yet for the internal "
249 "programmer due to missing\n"
250 "flash_base and top/bottom alignment information.\n"
251 "Aborting.\n");
252 return 1;
253#endif
254#else
255 /* FIXME: Remove this unconditional abort once all PCI drivers are
256 * converted to use little-endian accesses for memory BARs.
257 */
258 msg_perr("Your platform is not supported yet for the internal "
259 "programmer because it has\n"
260 "not been converted from native endian to little endian "
261 "access yet.\n"
262 "Aborting.\n");
263 return 1;
264#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000265}
266
267int internal_shutdown(void)
268{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000269 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000270
271 return 0;
272}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000273#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000274
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000275void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000276{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000277 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000278}
279
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000280void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000281{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000282 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000283}
284
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000285void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000286{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000287 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000288}
289
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000290uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000291{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000292 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000293}
294
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000295uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000296{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000297 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000298}
299
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000300uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000301{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000302 return mmio_readl((void *) addr);
303}
304
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000305void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
306{
307 memcpy(buf, (void *)addr, len);
308 return;
309}