blob: 935240d4238413cea357f1bb7d578ab789fd46dc [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();
Michael Karcher6701ee82010-01-20 14:14:11 +0000155 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000156
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000157 /* Probe for the SuperI/O chip and fill global struct superio. */
158 probe_superio();
159
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000160 /* try to enable it. Failure IS an option, since not all motherboards
161 * really need this to be done, etc., etc.
162 */
163 ret = chipset_flash_enable();
164 if (ret == -2) {
165 printf("WARNING: No chipset found. Flash detection "
166 "will most likely fail.\n");
167 }
168
169 board_flash_enable(lb_vendor, lb_part);
170
Carl-Daniel Hailfinger9246ff42009-09-02 13:43:56 +0000171 /* Even if chipset init returns an error code, we don't want to abort.
172 * The error code might have been a warning only.
173 * Besides that, we don't check the board enable return code either.
174 */
175 return 0;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000176}
177
178int internal_shutdown(void)
179{
Carl-Daniel Hailfingerdb41c592009-08-09 21:50:24 +0000180 release_io_perms();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000181
182 return 0;
183}
Carl-Daniel Hailfinger66ef4e52009-12-13 22:28:00 +0000184#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000185
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000186void internal_chip_writeb(uint8_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000187{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000188 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000189}
190
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000191void internal_chip_writew(uint16_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000192{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000193 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000194}
195
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000196void internal_chip_writel(uint32_t val, chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000197{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000198 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000199}
200
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000201uint8_t internal_chip_readb(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000202{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000203 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000204}
205
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000206uint16_t internal_chip_readw(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000207{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000208 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000209}
210
Carl-Daniel Hailfinger5820f422009-05-16 21:22:56 +0000211uint32_t internal_chip_readl(const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000212{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000213 return mmio_readl((void *) addr);
214}
215
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000216void internal_chip_readn(uint8_t *buf, const chipaddr addr, size_t len)
217{
218 memcpy(buf, (void *)addr, len);
219 return;
220}
221
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000222void mmio_writeb(uint8_t val, void *addr)
223{
224 *(volatile uint8_t *) addr = val;
225}
226
227void mmio_writew(uint16_t val, void *addr)
228{
229 *(volatile uint16_t *) addr = val;
230}
231
232void mmio_writel(uint32_t val, void *addr)
233{
234 *(volatile uint32_t *) addr = val;
235}
236
237uint8_t mmio_readb(void *addr)
238{
239 return *(volatile uint8_t *) addr;
240}
241
242uint16_t mmio_readw(void *addr)
243{
244 return *(volatile uint16_t *) addr;
245}
246
247uint32_t mmio_readl(void *addr)
248{
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000249 return *(volatile uint32_t *) addr;
250}