blob: 69624a0d4d4bcab3d3564427347664f513063b97 [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
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +000034#if NEED_PCI == 1
Christian Ruppert0cdb0312009-05-14 18:57:26 +000035struct pci_dev *pci_dev_find_filter(struct pci_filter filter)
36{
37 struct pci_dev *temp;
38
39 for (temp = pacc->devices; temp; temp = temp->next)
40 if (pci_filter_match(&filter, temp))
41 return temp;
42
43 return NULL;
44}
45
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000046struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
47{
48 struct pci_dev *temp;
49 struct pci_filter filter;
50 uint16_t tmp2;
51
52 pci_filter_init(NULL, &filter);
53 filter.vendor = vendor;
54
55 for (temp = pacc->devices; temp; temp = temp->next)
56 if (pci_filter_match(&filter, temp)) {
57 /* Read PCI class */
58 tmp2 = pci_read_word(temp, 0x0a);
59 if (tmp2 == class)
60 return temp;
61 }
62
63 return NULL;
64}
65
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000066struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
67{
68 struct pci_dev *temp;
69 struct pci_filter filter;
70
71 pci_filter_init(NULL, &filter);
72 filter.vendor = vendor;
73 filter.device = device;
74
75 for (temp = pacc->devices; temp; temp = temp->next)
76 if (pci_filter_match(&filter, temp))
77 return temp;
78
79 return NULL;
80}
81
82struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
83 uint16_t card_vendor, uint16_t card_device)
84{
85 struct pci_dev *temp;
86 struct pci_filter filter;
87
88 pci_filter_init(NULL, &filter);
89 filter.vendor = vendor;
90 filter.device = device;
91
92 for (temp = pacc->devices; temp; temp = temp->next)
93 if (pci_filter_match(&filter, temp)) {
94 if ((card_vendor ==
95 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
96 && (card_device ==
97 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
98 return temp;
99 }
100
101 return NULL;
102}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000103#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000104
Uwe Hermanna0869322009-05-14 20:41:57 +0000105void get_io_perms(void)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000106{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000107#if defined (__sun) && (defined(__i386) || defined(__amd64))
108 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
109#elif defined(__FreeBSD__) || defined (__DragonFly__)
110 if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
111#else
112 if (iopl(3) != 0) {
113#endif
Uwe Hermanna0869322009-05-14 20:41:57 +0000114 fprintf(stderr, "ERROR: Could not get I/O privileges (%s).\n"
115 "You need to be root.\n", strerror(errno));
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000116 exit(1);
117 }
Uwe Hermanna0869322009-05-14 20:41:57 +0000118}
119
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000120void release_io_perms(void)
121{
122#if defined(__FreeBSD__) || defined(__DragonFly__)
123 close(io_fd);
124#endif
125}
126
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000127#if INTERNAL_SUPPORT == 1
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000128struct superio superio = {};
129
130void probe_superio(void)
131{
132 superio = probe_superio_ite();
133#if 0 /* Winbond SuperI/O code is not yet available. */
134 if (superio.vendor == SUPERIO_VENDOR_NONE)
135 superio = probe_superio_winbond();
136#endif
137}
138
Uwe Hermanna0869322009-05-14 20:41:57 +0000139int internal_init(void)
140{
141 int ret = 0;
142
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000143 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000144
145 /* Initialize PCI access for flash enables */
146 pacc = pci_alloc(); /* Get the pci_access structure */
147 /* Set all options you want -- here we stick with the defaults */
148 pci_init(pacc); /* Initialize the PCI library */
149 pci_scan_bus(pacc); /* We want to get the list of devices */
150
151 /* We look at the lbtable first to see if we need a
152 * mainboard specific flash enable sequence.
153 */
154 coreboot_init();
155
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000156 /* Probe for the SuperI/O chip and fill global struct superio. */
157 probe_superio();
158
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000159 /* try to enable it. Failure IS an option, since not all motherboards
160 * really need this to be done, etc., etc.
161 */
162 ret = chipset_flash_enable();
163 if (ret == -2) {
164 printf("WARNING: No chipset found. Flash detection "
165 "will most likely fail.\n");
166 }
167
168 board_flash_enable(lb_vendor, lb_part);
169
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000170 /* Even if chipset init returns an error code, we don't want to abort.
171 * The error code might have been a warning only.
172 * Besides that, we don't check the board enable return code either.
173 */
174 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000175}
176
177int internal_shutdown(void)
178{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000179 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000180
181 return 0;
182}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000183#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000184
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000185void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000186{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000187 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000188}
189
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000190void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000191{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000192 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000193}
194
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000195void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000196{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000197 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000198}
199
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000200uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000201{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000202 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000203}
204
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000205uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000206{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000207 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000208}
209
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000210uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000211{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000212 return mmio_readl((void *) addr);
213}
214
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000215void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
216{
217 memcpy(buf, (void *)addr, len);
218 return;
219}
220
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000221void mmio_writeb(uint8_t val, void *addr)
222{
223 *(volatile uint8_t *) addr = val;
224}
225
226void mmio_writew(uint16_t val, void *addr)
227{
228 *(volatile uint16_t *) addr = val;
229}
230
231void mmio_writel(uint32_t val, void *addr)
232{
233 *(volatile uint32_t *) addr = val;
234}
235
236uint8_t mmio_readb(void *addr)
237{
238 return *(volatile uint8_t *) addr;
239}
240
241uint16_t mmio_readw(void *addr)
242{
243 return *(volatile uint16_t *) addr;
244}
245
246uint32_t mmio_readl(void *addr)
247{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000248 return *(volatile uint32_t *) addr;
249}
250
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000251void internal_delay(int usecs)
252{
253 /* If the delay is >1 s, use usleep because timing does not need to
254 * be so precise.
255 */
256 if (usecs > 1000000) {
257 usleep(usecs);
258 } else {
259 myusec_delay(usecs);
260 }
261}
262
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000263/* No-op shutdown() for programmers which don't need special handling */
264int noop_shutdown(void)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000265{
266 return 0;
267}
268
Uwe Hermannc6915932009-05-17 23:12:17 +0000269/* Fallback map() for programmers which don't need special handling */
270void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
271{
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000272 /* FIXME: Should return phys_addr. */
Uwe Hermannc6915932009-05-17 23:12:17 +0000273 return 0;
274}
275
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000276/* No-op/fallback unmap() for programmers which don't need special handling */
Uwe Hermannc6915932009-05-17 23:12:17 +0000277void fallback_unmap(void *virt_addr, size_t len)
278{
279}
280
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000281/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
282uint8_t noop_chip_readb(const chipaddr addr)
283{
284 return 0xff;
285}
286
287/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
288void noop_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000289{
290}
291
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000292/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000293void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000294{
295 chip_writeb(val & 0xff, addr);
296 chip_writeb((val >> 8) & 0xff, addr + 1);
297}
298
299/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000300uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000301{
302 uint16_t val;
303 val = chip_readb(addr);
304 val |= chip_readb(addr + 1) << 8;
305 return val;
306}
307
308/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000309void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000310{
311 chip_writew(val & 0xffff, addr);
312 chip_writew((val >> 16) & 0xffff, addr + 2);
313}
314
315/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000316uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000317{
318 uint32_t val;
319 val = chip_readw(addr);
320 val |= chip_readw(addr + 2) << 16;
321 return val;
322}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000323
324void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
325{
326 size_t i;
327 for (i = 0; i < len; i++)
328 chip_writeb(buf[i], addr + i);
329 return;
330}
331
332void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
333{
334 size_t i;
335 for (i = 0; i < len; i++)
336 buf[i] = chip_readb(addr + i);
337 return;
338}