blob: bbad788ecbf4afbb2e4e51055d43251907b47bb3 [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>
24#include <fcntl.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <errno.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000028#include "flash.h"
29
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000030#if NEED_PCI == 1
Christian Ruppert0cdb0312009-05-14 18:57:26 +000031struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
32{
33 struct pci_dev *temp;
34
35 for (temp = pacc->devices; temp; temp = temp->next)
36 if (pci_filter_match(&filter, temp))
37 return temp;
38
39 return NULL;
40}
41
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000042struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
43{
44 struct pci_dev *temp;
45 struct pci_filter filter;
46 uint16_t tmp2;
47
48 pci_filter_init(NULL, &filter);
49 filter.vendor = vendor;
50
51 for (temp = pacc->devices; temp; temp = temp->next)
52 if (pci_filter_match(&filter, temp)) {
53 /* Read PCI class */
54 tmp2 = pci_read_word(temp, 0x0a);
55 if (tmp2 == class)
56 return temp;
57 }
58
59 return NULL;
60}
61
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000062struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
63{
64 struct pci_dev *temp;
65 struct pci_filter filter;
66
67 pci_filter_init(NULL, &filter);
68 filter.vendor = vendor;
69 filter.device = device;
70
71 for (temp = pacc->devices; temp; temp = temp->next)
72 if (pci_filter_match(&filter, temp))
73 return temp;
74
75 return NULL;
76}
77
78struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
79 uint16_t card_vendor, uint16_t card_device)
80{
81 struct pci_dev *temp;
82 struct pci_filter filter;
83
84 pci_filter_init(NULL, &filter);
85 filter.vendor = vendor;
86 filter.device = device;
87
88 for (temp = pacc->devices; temp; temp = temp->next)
89 if (pci_filter_match(&filter, temp)) {
90 if ((card_vendor ==
91 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
92 && (card_device ==
93 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
94 return temp;
95 }
96
97 return NULL;
98}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000099#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000100
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000101#if INTERNAL_SUPPORT == 1
Michael Karcher0bdc0922010-02-28 01:33:48 +0000102int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000103int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000104
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000105#if defined(__i386__) || defined(__x86_64__)
106struct superio superio = {};
107
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000108void probe_superio(void)
109{
110 superio = probe_superio_ite();
Uwe Hermann43959702010-03-13 17:28:29 +0000111#if 0
112 /* Winbond Super I/O code is not yet available. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000113 if (superio.vendor == SUPERIO_VENDOR_NONE)
114 superio = probe_superio_winbond();
115#endif
116}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000117#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000118
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000119int is_laptop = 0;
Michael Karcher8c1df282010-02-26 09:51:20 +0000120
Uwe Hermanna0869322009-05-14 20:41:57 +0000121int internal_init(void)
122{
123 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000124 int force_laptop = 0;
125 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000126
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000127 arg = extract_param(&programmer_param, "boardenable=", ",:");
128 if (arg && !strcmp(arg,"force")) {
129 force_boardenable = 1;
130 } else if (arg && !strlen(arg)) {
131 msg_perr("Missing argument for boardenable.\n");
132 } else if (arg) {
133 msg_perr("Unknown argument for boardenable: %s\n", arg);
134 exit(1);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000135 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000136 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000137
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000138 arg = extract_param(&programmer_param, "boardmismatch=", ",:");
139 if (arg && !strcmp(arg,"force")) {
140 force_boardmismatch = 1;
141 } else if (arg && !strlen(arg)) {
142 msg_perr("Missing argument for boardmismatch.\n");
143 } else if (arg) {
144 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
145 exit(1);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000146 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000147 free(arg);
148
149 arg = extract_param(&programmer_param, "laptop=", ",:");
150 if (arg && !strcmp(arg,"force_I_want_a_brick")) {
151 force_laptop = 1;
152 } else if (arg && !strlen(arg)) {
153 msg_perr("Missing argument for laptop.\n");
154 } else if (arg) {
155 msg_perr("Unknown argument for laptop: %s\n", arg);
156 exit(1);
157 }
158 free(arg);
159
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000160 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000161
162 /* Initialize PCI access for flash enables */
163 pacc = pci_alloc(); /* Get the pci_access structure */
164 /* Set all options you want -- here we stick with the defaults */
165 pci_init(pacc); /* Initialize the PCI library */
166 pci_scan_bus(pacc); /* We want to get the list of devices */
167
168 /* We look at the lbtable first to see if we need a
169 * mainboard specific flash enable sequence.
170 */
171 coreboot_init();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000172
173#if defined(__i386__) || defined(__x86_64__)
Michael Karcher6701ee82010-01-20 14:14:11 +0000174 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000175
Uwe Hermann43959702010-03-13 17:28:29 +0000176 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000177 probe_superio();
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000178#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000179
Uwe Hermann43959702010-03-13 17:28:29 +0000180 /* Warn if a laptop is detected. */
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000181 if (is_laptop) {
182 msg_perr("========================================================================\n"
183 "WARNING! You seem to be running flashrom on a laptop.\n"
184 "Laptops, notebooks and netbooks are difficult to support and we recommend\n"
185 "to use the vendor flashing utility. The embedded controller (EC) in these\n"
186 "machines often interacts badly with flashing.\n"
187 "See http://www.flashrom.org/Laptops for details.\n\n"
188 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
189 "and write may brick your laptop.\n"
190 "Read and probe may irritate your EC and cause fan failure, backlight\n"
191 "failure and sudden poweroff.\n"
192 "You have been warned.\n"
193 "========================================================================\n");
194 if (force_laptop) {
195 msg_perr("Proceeding anyway because user specified "
196 "laptop=force_I_want_a_brick\n");
197 } else {
198 msg_perr("Aborting.\n");
199 exit(1);
200 }
201 }
Michael Karcher8c1df282010-02-26 09:51:20 +0000202
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000203 /* try to enable it. Failure IS an option, since not all motherboards
204 * really need this to be done, etc., etc.
205 */
206 ret = chipset_flash_enable();
207 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000208 msg_perr("WARNING: No chipset found. Flash detection "
209 "will most likely fail.\n");
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000210 }
211
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000212#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000213 /* Probe for IT87* LPC->SPI translation unconditionally. */
214 it87xx_probe_spi_flash(NULL);
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000215#endif
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000216
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000217 board_flash_enable(lb_vendor, lb_part);
218
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000219 /* Even if chipset init returns an error code, we don't want to abort.
220 * The error code might have been a warning only.
221 * Besides that, we don't check the board enable return code either.
222 */
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000223 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000224}
225
226int internal_shutdown(void)
227{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000228 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000229
230 return 0;
231}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000232#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000233
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000234void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000235{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000236 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000237}
238
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000239void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000240{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000241 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000242}
243
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000244void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000245{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000246 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000247}
248
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000249uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000250{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000251 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000252}
253
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000254uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000255{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000256 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000257}
258
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000259uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000260{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000261 return mmio_readl((void *) addr);
262}
263
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000264void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
265{
266 memcpy(buf, (void *)addr, len);
267 return;
268}