blob: fc662c5528876ff77c5eafa60783adee5369ae20 [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
30#if defined(__FreeBSD__) || defined(__DragonFly__)
31int io_fd;
32#endif
33
Christian Ruppert0cdb0312009-05-14 18:57:26 +000034struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
35{
36 struct pci_dev *temp;
37
38 for (temp = pacc->devices; temp; temp = temp->next)
39 if (pci_filter_match(&filter, temp))
40 return temp;
41
42 return NULL;
43}
44
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000045struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
46{
47 struct pci_dev *temp;
48 struct pci_filter filter;
49 uint16_t tmp2;
50
51 pci_filter_init(NULL, &filter);
52 filter.vendor = vendor;
53
54 for (temp = pacc->devices; temp; temp = temp->next)
55 if (pci_filter_match(&filter, temp)) {
56 /* Read PCI class */
57 tmp2 = pci_read_word(temp, 0x0a);
58 if (tmp2 == class)
59 return temp;
60 }
61
62 return NULL;
63}
64
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000065struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
66{
67 struct pci_dev *temp;
68 struct pci_filter filter;
69
70 pci_filter_init(NULL, &filter);
71 filter.vendor = vendor;
72 filter.device = device;
73
74 for (temp = pacc->devices; temp; temp = temp->next)
75 if (pci_filter_match(&filter, temp))
76 return temp;
77
78 return NULL;
79}
80
81struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
82 uint16_t card_vendor, uint16_t card_device)
83{
84 struct pci_dev *temp;
85 struct pci_filter filter;
86
87 pci_filter_init(NULL, &filter);
88 filter.vendor = vendor;
89 filter.device = device;
90
91 for (temp = pacc->devices; temp; temp = temp->next)
92 if (pci_filter_match(&filter, temp)) {
93 if ((card_vendor ==
94 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
95 && (card_device ==
96 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
97 return temp;
98 }
99
100 return NULL;
101}
102
Uwe Hermanna0869322009-05-14 20:41:57 +0000103void get_io_perms(void)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000104{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000105#if defined (__sun) && (defined(__i386) || defined(__amd64))
106 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
107#elif defined(__FreeBSD__) || defined (__DragonFly__)
108 if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
109#else
110 if (iopl(3) != 0) {
111#endif
Uwe Hermanna0869322009-05-14 20:41:57 +0000112 fprintf(stderr, "ERROR: Could not get I/O privileges (%s).\n"
113 "You need to be root.\n", strerror(errno));
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000114 exit(1);
115 }
Uwe Hermanna0869322009-05-14 20:41:57 +0000116}
117
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000118void release_io_perms(void)
119{
120#if defined(__FreeBSD__) || defined(__DragonFly__)
121 close(io_fd);
122#endif
123}
124
Uwe Hermanna0869322009-05-14 20:41:57 +0000125int internal_init(void)
126{
127 int ret = 0;
128
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000129 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000130
131 /* Initialize PCI access for flash enables */
132 pacc = pci_alloc(); /* Get the pci_access structure */
133 /* Set all options you want -- here we stick with the defaults */
134 pci_init(pacc); /* Initialize the PCI library */
135 pci_scan_bus(pacc); /* We want to get the list of devices */
136
137 /* We look at the lbtable first to see if we need a
138 * mainboard specific flash enable sequence.
139 */
140 coreboot_init();
141
142 /* try to enable it. Failure IS an option, since not all motherboards
143 * really need this to be done, etc., etc.
144 */
145 ret = chipset_flash_enable();
146 if (ret == -2) {
147 printf("WARNING: No chipset found. Flash detection "
148 "will most likely fail.\n");
149 }
150
151 board_flash_enable(lb_vendor, lb_part);
152
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000153 /* Even if chipset init returns an error code, we don't want to abort.
154 * The error code might have been a warning only.
155 * Besides that, we don't check the board enable return code either.
156 */
157 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000158}
159
160int internal_shutdown(void)
161{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000162 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000163
164 return 0;
165}
166
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000167void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000168{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000169 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000170}
171
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000172void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000173{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000174 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000175}
176
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000177void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000178{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000179 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000180}
181
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000182uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000183{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000184 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000185}
186
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000187uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000188{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000189 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000190}
191
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000192uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000193{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000194 return mmio_readl((void *) addr);
195}
196
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000197void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
198{
199 memcpy(buf, (void *)addr, len);
200 return;
201}
202
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000203void mmio_writeb(uint8_t val, void *addr)
204{
205 *(volatile uint8_t *) addr = val;
206}
207
208void mmio_writew(uint16_t val, void *addr)
209{
210 *(volatile uint16_t *) addr = val;
211}
212
213void mmio_writel(uint32_t val, void *addr)
214{
215 *(volatile uint32_t *) addr = val;
216}
217
218uint8_t mmio_readb(void *addr)
219{
220 return *(volatile uint8_t *) addr;
221}
222
223uint16_t mmio_readw(void *addr)
224{
225 return *(volatile uint16_t *) addr;
226}
227
228uint32_t mmio_readl(void *addr)
229{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000230 return *(volatile uint32_t *) addr;
231}
232
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000233void internal_delay(int usecs)
234{
235 /* If the delay is >1 s, use usleep because timing does not need to
236 * be so precise.
237 */
238 if (usecs > 1000000) {
239 usleep(usecs);
240 } else {
241 myusec_delay(usecs);
242 }
243}
244
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000245/* No-op shutdown() for programmers which don't need special handling */
246int noop_shutdown(void)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000247{
248 return 0;
249}
250
Uwe Hermannc6915932009-05-17 23:12:17 +0000251/* Fallback map() for programmers which don't need special handling */
252void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
253{
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000254 /* FIXME: Should return phys_addr. */
Uwe Hermannc6915932009-05-17 23:12:17 +0000255 return 0;
256}
257
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000258/* No-op/fallback unmap() for programmers which don't need special handling */
Uwe Hermannc6915932009-05-17 23:12:17 +0000259void fallback_unmap(void *virt_addr, size_t len)
260{
261}
262
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000263/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
264uint8_t noop_chip_readb(const chipaddr addr)
265{
266 return 0xff;
267}
268
269/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
270void noop_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000271{
272}
273
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000274/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000275void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000276{
277 chip_writeb(val & 0xff, addr);
278 chip_writeb((val >> 8) & 0xff, addr + 1);
279}
280
281/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000282uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000283{
284 uint16_t val;
285 val = chip_readb(addr);
286 val |= chip_readb(addr + 1) << 8;
287 return val;
288}
289
290/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000291void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000292{
293 chip_writew(val & 0xffff, addr);
294 chip_writew((val >> 16) & 0xffff, addr + 2);
295}
296
297/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000298uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000299{
300 uint32_t val;
301 val = chip_readw(addr);
302 val |= chip_readw(addr + 2) << 16;
303 return val;
304}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000305
306void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
307{
308 size_t i;
309 for (i = 0; i < len; i++)
310 chip_writeb(buf[i], addr + i);
311 return;
312}
313
314void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
315{
316 size_t i;
317 for (i = 0; i < len; i++)
318 buf[i] = chip_readb(addr + i);
319 return;
320}