blob: ea12bbc902be5037ade50bcc49d15efe2c583735 [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 Hailfinger702218d2009-05-08 17:43:22 +000045struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
46{
47 struct pci_dev *temp;
48 struct pci_filter filter;
49
50 pci_filter_init(NULL, &filter);
51 filter.vendor = vendor;
52 filter.device = device;
53
54 for (temp = pacc->devices; temp; temp = temp->next)
55 if (pci_filter_match(&filter, temp))
56 return temp;
57
58 return NULL;
59}
60
61struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
62 uint16_t card_vendor, uint16_t card_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 if ((card_vendor ==
74 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
75 && (card_device ==
76 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
77 return temp;
78 }
79
80 return NULL;
81}
82
Uwe Hermanna0869322009-05-14 20:41:57 +000083void get_io_perms(void)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000084{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000085#if defined (__sun) && (defined(__i386) || defined(__amd64))
86 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
87#elif defined(__FreeBSD__) || defined (__DragonFly__)
88 if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
89#else
90 if (iopl(3) != 0) {
91#endif
Uwe Hermanna0869322009-05-14 20:41:57 +000092 fprintf(stderr, "ERROR: Could not get I/O privileges (%s).\n"
93 "You need to be root.\n", strerror(errno));
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000094 exit(1);
95 }
Uwe Hermanna0869322009-05-14 20:41:57 +000096}
97
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +000098void release_io_perms(void)
99{
100#if defined(__FreeBSD__) || defined(__DragonFly__)
101 close(io_fd);
102#endif
103}
104
Uwe Hermanna0869322009-05-14 20:41:57 +0000105int internal_init(void)
106{
107 int ret = 0;
108
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000109 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000110
111 /* Initialize PCI access for flash enables */
112 pacc = pci_alloc(); /* Get the pci_access structure */
113 /* Set all options you want -- here we stick with the defaults */
114 pci_init(pacc); /* Initialize the PCI library */
115 pci_scan_bus(pacc); /* We want to get the list of devices */
116
117 /* We look at the lbtable first to see if we need a
118 * mainboard specific flash enable sequence.
119 */
120 coreboot_init();
121
122 /* try to enable it. Failure IS an option, since not all motherboards
123 * really need this to be done, etc., etc.
124 */
125 ret = chipset_flash_enable();
126 if (ret == -2) {
127 printf("WARNING: No chipset found. Flash detection "
128 "will most likely fail.\n");
129 }
130
131 board_flash_enable(lb_vendor, lb_part);
132
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000133 /* Even if chipset init returns an error code, we don't want to abort.
134 * The error code might have been a warning only.
135 * Besides that, we don't check the board enable return code either.
136 */
137 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000138}
139
140int internal_shutdown(void)
141{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000142 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000143
144 return 0;
145}
146
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000147void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000148{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000149 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000150}
151
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000152void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000153{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000154 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000155}
156
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000157void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000158{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000159 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000160}
161
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000162uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000163{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000164 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000165}
166
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000167uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000168{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000169 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000170}
171
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000172uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000173{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000174 return mmio_readl((void *) addr);
175}
176
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000177void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
178{
179 memcpy(buf, (void *)addr, len);
180 return;
181}
182
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000183void mmio_writeb(uint8_t val, void *addr)
184{
185 *(volatile uint8_t *) addr = val;
186}
187
188void mmio_writew(uint16_t val, void *addr)
189{
190 *(volatile uint16_t *) addr = val;
191}
192
193void mmio_writel(uint32_t val, void *addr)
194{
195 *(volatile uint32_t *) addr = val;
196}
197
198uint8_t mmio_readb(void *addr)
199{
200 return *(volatile uint8_t *) addr;
201}
202
203uint16_t mmio_readw(void *addr)
204{
205 return *(volatile uint16_t *) addr;
206}
207
208uint32_t mmio_readl(void *addr)
209{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000210 return *(volatile uint32_t *) addr;
211}
212
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000213void internal_delay(int usecs)
214{
215 /* If the delay is >1 s, use usleep because timing does not need to
216 * be so precise.
217 */
218 if (usecs > 1000000) {
219 usleep(usecs);
220 } else {
221 myusec_delay(usecs);
222 }
223}
224
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000225/* No-op shutdown() for programmers which don't need special handling */
226int noop_shutdown(void)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000227{
228 return 0;
229}
230
Uwe Hermannc6915932009-05-17 23:12:17 +0000231/* Fallback map() for programmers which don't need special handling */
232void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
233{
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000234 /* FIXME: Should return phys_addr. */
Uwe Hermannc6915932009-05-17 23:12:17 +0000235 return 0;
236}
237
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000238/* No-op/fallback unmap() for programmers which don't need special handling */
Uwe Hermannc6915932009-05-17 23:12:17 +0000239void fallback_unmap(void *virt_addr, size_t len)
240{
241}
242
Carl-Daniel Hailfinger4740c6f2009-09-16 10:09:21 +0000243/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
244uint8_t noop_chip_readb(const chipaddr addr)
245{
246 return 0xff;
247}
248
249/* No-op chip_writeb() for drivers not supporting addr/data pair accesses */
250void noop_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000251{
252}
253
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000254/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000255void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000256{
257 chip_writeb(val & 0xff, addr);
258 chip_writeb((val >> 8) & 0xff, addr + 1);
259}
260
261/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000262uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000263{
264 uint16_t val;
265 val = chip_readb(addr);
266 val |= chip_readb(addr + 1) << 8;
267 return val;
268}
269
270/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000271void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000272{
273 chip_writew(val & 0xffff, addr);
274 chip_writew((val >> 16) & 0xffff, addr + 2);
275}
276
277/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000278uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000279{
280 uint32_t val;
281 val = chip_readw(addr);
282 val |= chip_readw(addr + 2) << 16;
283 return val;
284}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000285
286void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
287{
288 size_t i;
289 for (i = 0; i < len; i++)
290 chip_writeb(buf[i], addr + i);
291 return;
292}
293
294void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
295{
296 size_t i;
297 for (i = 0; i < len; i++)
298 buf[i] = chip_readb(addr + i);
299 return;
300}