blob: 3e3808ecf5b66f5ef4615a274210ca4dc1018774 [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
133 return ret;
134}
135
136int internal_shutdown(void)
137{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000138 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000139
140 return 0;
141}
142
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000143void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000144{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000145 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000146}
147
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000148void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000149{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000150 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000151}
152
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000153void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000154{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000155 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000156}
157
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000158uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000159{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000160 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000161}
162
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000163uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000164{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000165 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000166}
167
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000168uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000169{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000170 return mmio_readl((void *) addr);
171}
172
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000173void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
174{
175 memcpy(buf, (void *)addr, len);
176 return;
177}
178
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000179void mmio_writeb(uint8_t val, void *addr)
180{
181 *(volatile uint8_t *) addr = val;
182}
183
184void mmio_writew(uint16_t val, void *addr)
185{
186 *(volatile uint16_t *) addr = val;
187}
188
189void mmio_writel(uint32_t val, void *addr)
190{
191 *(volatile uint32_t *) addr = val;
192}
193
194uint8_t mmio_readb(void *addr)
195{
196 return *(volatile uint8_t *) addr;
197}
198
199uint16_t mmio_readw(void *addr)
200{
201 return *(volatile uint16_t *) addr;
202}
203
204uint32_t mmio_readl(void *addr)
205{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000206 return *(volatile uint32_t *) addr;
207}
208
Carl-Daniel Hailfingerca8bfc62009-06-05 17:48:08 +0000209void internal_delay(int usecs)
210{
211 /* If the delay is >1 s, use usleep because timing does not need to
212 * be so precise.
213 */
214 if (usecs > 1000000) {
215 usleep(usecs);
216 } else {
217 myusec_delay(usecs);
218 }
219}
220
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000221/* Fallback shutdown() for programmers which don't need special handling */
222int fallback_shutdown(void)
223{
224 return 0;
225}
226
Uwe Hermannc6915932009-05-17 23:12:17 +0000227/* Fallback map() for programmers which don't need special handling */
228void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
229{
230 return 0;
231}
232
233/* Fallback unmap() for programmers which don't need special handling */
234void fallback_unmap(void *virt_addr, size_t len)
235{
236}
237
Carl-Daniel Hailfinger415e5132009-08-12 11:39:29 +0000238/* No-op fallback for drivers not supporting addr/data pair accesses */
239void fallback_chip_writeb(uint8_t val, chipaddr addr)
240{
241}
242
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000243/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000244void fallback_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000245{
246 chip_writeb(val & 0xff, addr);
247 chip_writeb((val >> 8) & 0xff, addr + 1);
248}
249
250/* Little-endian fallback for drivers not supporting 16 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000251uint16_t fallback_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000252{
253 uint16_t val;
254 val = chip_readb(addr);
255 val |= chip_readb(addr + 1) << 8;
256 return val;
257}
258
259/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000260void fallback_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000261{
262 chip_writew(val & 0xffff, addr);
263 chip_writew((val >> 16) & 0xffff, addr + 2);
264}
265
266/* Little-endian fallback for drivers not supporting 32 bit accesses */
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000267uint32_t fallback_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger9ee10772009-05-16 01:23:55 +0000268{
269 uint32_t val;
270 val = chip_readw(addr);
271 val |= chip_readw(addr + 2) << 16;
272 return val;
273}
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000274
275void fallback_chip_writen(uint8_t *buf, chipaddr addr, size_t len)
276{
277 size_t i;
278 for (i = 0; i < len; i++)
279 chip_writeb(buf[i], addr + i);
280 return;
281}
282
283void fallback_chip_readn(uint8_t *buf, chipaddr addr, size_t len)
284{
285 size_t i;
286 for (i = 0; i < len; i++)
287 buf[i] = chip_readb(addr + i);
288 return;
289}