blob: cfb83d7588f66b3c3ae24f795da7b98a9da1aa90 [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
Uwe Hermanna0869322009-05-14 20:41:57 +0000128int internal_init(void)
129{
130 int ret = 0;
131
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000132 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000133
134 /* Initialize PCI access for flash enables */
135 pacc = pci_alloc(); /* Get the pci_access structure */
136 /* Set all options you want -- here we stick with the defaults */
137 pci_init(pacc); /* Initialize the PCI library */
138 pci_scan_bus(pacc); /* We want to get the list of devices */
139
140 /* We look at the lbtable first to see if we need a
141 * mainboard specific flash enable sequence.
142 */
143 coreboot_init();
144
145 /* try to enable it. Failure IS an option, since not all motherboards
146 * really need this to be done, etc., etc.
147 */
148 ret = chipset_flash_enable();
149 if (ret == -2) {
150 printf("WARNING: No chipset found. Flash detection "
151 "will most likely fail.\n");
152 }
153
154 board_flash_enable(lb_vendor, lb_part);
155
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000156 /* Even if chipset init returns an error code, we don't want to abort.
157 * The error code might have been a warning only.
158 * Besides that, we don't check the board enable return code either.
159 */
160 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000161}
162
163int internal_shutdown(void)
164{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000165 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000166
167 return 0;
168}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000169#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000170
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000171void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000172{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000173 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000174}
175
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000176void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000177{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000178 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000179}
180
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000181void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000182{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000183 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000184}
185
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000186uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000187{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000188 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000189}
190
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000191uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000192{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000193 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000194}
195
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000196uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000197{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000198 return mmio_readl((void *) addr);
199}
200
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000201void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
202{
203 memcpy(buf, (void *)addr, len);
204 return;
205}
206
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000207void mmio_writeb(uint8_t val, void *addr)
208{
209 *(volatile uint8_t *) addr = val;
210}
211
212void mmio_writew(uint16_t val, void *addr)
213{
214 *(volatile uint16_t *) addr = val;
215}
216
217void mmio_writel(uint32_t val, void *addr)
218{
219 *(volatile uint32_t *) addr = val;
220}
221
222uint8_t mmio_readb(void *addr)
223{
224 return *(volatile uint8_t *) addr;
225}
226
227uint16_t mmio_readw(void *addr)
228{
229 return *(volatile uint16_t *) addr;
230}
231
232uint32_t mmio_readl(void *addr)
233{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000234 return *(volatile uint32_t *) addr;
235}
236
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000237void internal_delay(int usecs)
238{
239 /* If the delay is >1 s, use usleep because timing does not need to
240 * be so precise.
241 */
242 if (usecs > 1000000) {
243 usleep(usecs);
244 } else {
245 myusec_delay(usecs);
246 }
247}
248
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000249/* No-op shutdown() for programmers which don't need special handling */
250int noop_shutdown(void)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000251{
252 return 0;
253}
254
Uwe Hermannc6915932009-05-17 23:12:17 +0000255/* Fallback map() for programmers which don't need special handling */
256void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
257{
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000258 /* FIXME: Should return phys_addr. */
Uwe Hermannc6915932009-05-17 23:12:17 +0000259 return 0;
260}
261
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000262/* No-op/fallback unmap() for programmers which don't need special handling */
Uwe Hermannc6915932009-05-17 23:12:17 +0000263void fallback_unmap(void *virt_addr, size_t len)
264{
265}
266
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000267/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
268uint8_t noop_chip_readb(const chipaddr addr)
269{
270 return 0xff;
271}
272
273/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
274void noop_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000275{
276}
277
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000278/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000279void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000280{
281 chip_writeb(val & 0xff, addr);
282 chip_writeb((val >> 8) & 0xff, addr + 1);
283}
284
285/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000286uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000287{
288 uint16_t val;
289 val = chip_readb(addr);
290 val |= chip_readb(addr + 1) << 8;
291 return val;
292}
293
294/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000295void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000296{
297 chip_writew(val & 0xffff, addr);
298 chip_writew((val >> 16) & 0xffff, addr + 2);
299}
300
301/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000302uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000303{
304 uint32_t val;
305 val = chip_readw(addr);
306 val |= chip_readw(addr + 2) << 16;
307 return val;
308}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000309
310void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
311{
312 size_t i;
313 for (i = 0; i < len; i++)
314 chip_writeb(buf[i], addr + i);
315 return;
316}
317
318void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
319{
320 size_t i;
321 for (i = 0; i < len; i++)
322 buf[i] = chip_readb(addr + i);
323 return;
324}