blob: 302c7a96a7a32e7b4b770d3d5f8ec8dd2229da23 [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
98int internal_init(void)
99{
100 int ret = 0;
101
Carl-Daniel Hailfinger3b7e75a2009-05-14 21:41:10 +0000102 get_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000103
104 /* Initialize PCI access for flash enables */
105 pacc = pci_alloc(); /* Get the pci_access structure */
106 /* Set all options you want -- here we stick with the defaults */
107 pci_init(pacc); /* Initialize the PCI library */
108 pci_scan_bus(pacc); /* We want to get the list of devices */
109
110 /* We look at the lbtable first to see if we need a
111 * mainboard specific flash enable sequence.
112 */
113 coreboot_init();
114
115 /* try to enable it. Failure IS an option, since not all motherboards
116 * really need this to be done, etc., etc.
117 */
118 ret = chipset_flash_enable();
119 if (ret == -2) {
120 printf("WARNING: No chipset found. Flash detection "
121 "will most likely fail.\n");
122 }
123
124 board_flash_enable(lb_vendor, lb_part);
125
126 return ret;
127}
128
129int internal_shutdown(void)
130{
131#if defined(__FreeBSD__) || defined(__DragonFly__)
132 close(io_fd);
133#endif
134
135 return 0;
136}
137
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000138void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000139{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000140 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000141}
142
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000143void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000144{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000145 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000146}
147
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000148void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000149{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000150 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000151}
152
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000153uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000154{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000155 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000156}
157
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000158uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000159{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000160 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000161}
162
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000163uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000164{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000165 return mmio_readl((void *) addr);
166}
167
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000168void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
169{
170 memcpy(buf, (void *)addr, len);
171 return;
172}
173
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000174void mmio_writeb(uint8_t val, void *addr)
175{
176 *(volatile uint8_t *) addr = val;
177}
178
179void mmio_writew(uint16_t val, void *addr)
180{
181 *(volatile uint16_t *) addr = val;
182}
183
184void mmio_writel(uint32_t val, void *addr)
185{
186 *(volatile uint32_t *) addr = val;
187}
188
189uint8_t mmio_readb(void *addr)
190{
191 return *(volatile uint8_t *) addr;
192}
193
194uint16_t mmio_readw(void *addr)
195{
196 return *(volatile uint16_t *) addr;
197}
198
199uint32_t mmio_readl(void *addr)
200{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000201 return *(volatile uint32_t *) addr;
202}
203
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000204void internal_delay(int usecs)
205{
206 /* If the delay is >1 s, use usleep because timing does not need to
207 * be so precise.
208 */
209 if (usecs > 1000000) {
210 usleep(usecs);
211 } else {
212 myusec_delay(usecs);
213 }
214}
215
Uwe Hermannc6915932009-05-17 23:12:17 +0000216/* Fallback map() for programmers which don't need special handling */
217void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
218{
219 return 0;
220}
221
222/* Fallback unmap() for programmers which don't need special handling */
223void fallback_unmap(void *virt_addr, size_t len)
224{
225}
226
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000227/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000228void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000229{
230 chip_writeb(val & 0xff, addr);
231 chip_writeb((val >> 8) & 0xff, addr + 1);
232}
233
234/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000235uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000236{
237 uint16_t val;
238 val = chip_readb(addr);
239 val |= chip_readb(addr + 1) << 8;
240 return val;
241}
242
243/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000244void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000245{
246 chip_writew(val & 0xffff, addr);
247 chip_writew((val >> 16) & 0xffff, addr + 2);
248}
249
250/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000251uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000252{
253 uint32_t val;
254 val = chip_readw(addr);
255 val |= chip_readw(addr + 2) << 16;
256 return val;
257}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000258
259void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
260{
261 size_t i;
262 for (i = 0; i < len; i++)
263 chip_writeb(buf[i], addr + i);
264 return;
265}
266
267void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
268{
269 size_t i;
270 for (i = 0; i < len; i++)
271 buf[i] = chip_readb(addr + i);
272 return;
273}