blob: dbf9fb97ce634b47ec8b9cb22976568826557d6c [file] [log] [blame]
stepan927d4e22007-04-04 22:45:58 +00001/*
uweb25f1ea2007-08-29 17:52:32 +00002 * This file is part of the flashrom project.
stepan927d4e22007-04-04 22:45:58 +00003 *
uweb25f1ea2007-08-29 17:52:32 +00004 * Copyright (C) 2005-2007 coresystems GmbH <stepan@coresystems.de>
5 * Copyright (C) 2006 Uwe Hermann <uwe@hermann-uwe.de>
uwe6ab4b7b2009-05-09 14:26:04 +00006 * Copyright (C) 2007-2009 Luc Verhaegen <libv@skynet.be>
wardfbe9c652007-09-27 14:29:57 +00007 * Copyright (C) 2007 Carl-Daniel Hailfinger
stepan927d4e22007-04-04 22:45:58 +00008 *
uweb25f1ea2007-08-29 17:52:32 +00009 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
stepan927d4e22007-04-04 22:45:58 +000012 *
uweb25f1ea2007-08-29 17:52:32 +000013 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
stepan927d4e22007-04-04 22:45:58 +000018 */
19
20/*
21 * Contains the board specific flash enables.
22 */
23
Edward O'Callaghanb4300ca2019-09-03 16:15:21 +100024#include <strings.h>
stepan927d4e22007-04-04 22:45:58 +000025#include <string.h>
stepan927d4e22007-04-04 22:45:58 +000026#include "flash.h"
hailfinger428f6852010-07-27 22:41:39 +000027#include "programmer.h"
Mayur Panchalf4796862019-08-05 15:46:12 +100028#include "hwaccess.h"
stepan927d4e22007-04-04 22:45:58 +000029
hailfinger324a9cc2010-05-26 01:45:41 +000030#if defined(__i386__) || defined(__x86_64__)
stuge04909772007-05-04 04:47:04 +000031/*
uwebe4477b2007-08-23 16:08:21 +000032 * Helper functions for many Winbond Super I/Os of the W836xx range.
stuge04909772007-05-04 04:47:04 +000033 */
stuge04909772007-05-04 04:47:04 +000034/* Enter extended functions */
stugeaa35d392009-01-26 02:34:51 +000035void w836xx_ext_enter(uint16_t port)
uwe23438a02007-05-03 10:09:23 +000036{
hailfingere1f062f2008-05-22 13:22:45 +000037 OUTB(0x87, port);
38 OUTB(0x87, port);
stuge04909772007-05-04 04:47:04 +000039}
uwe23438a02007-05-03 10:09:23 +000040
stuge04909772007-05-04 04:47:04 +000041/* Leave extended functions */
stugeaa35d392009-01-26 02:34:51 +000042void w836xx_ext_leave(uint16_t port)
stuge04909772007-05-04 04:47:04 +000043{
hailfingere1f062f2008-05-22 13:22:45 +000044 OUTB(0xAA, port);
stuge04909772007-05-04 04:47:04 +000045}
uwe23438a02007-05-03 10:09:23 +000046
hailfinger7bac0e52009-05-25 23:26:50 +000047/* Generic Super I/O helper functions */
48uint8_t sio_read(uint16_t port, uint8_t reg)
stuge04909772007-05-04 04:47:04 +000049{
hailfinger7bac0e52009-05-25 23:26:50 +000050 OUTB(reg, port);
51 return INB(port + 1);
stuge04909772007-05-04 04:47:04 +000052}
uwe23438a02007-05-03 10:09:23 +000053
hailfinger7bac0e52009-05-25 23:26:50 +000054void sio_write(uint16_t port, uint8_t reg, uint8_t data)
stuge04909772007-05-04 04:47:04 +000055{
hailfinger7bac0e52009-05-25 23:26:50 +000056 OUTB(reg, port);
57 OUTB(data, port + 1);
stuge04909772007-05-04 04:47:04 +000058}
uwe23438a02007-05-03 10:09:23 +000059
hailfinger7bac0e52009-05-25 23:26:50 +000060void sio_mask(uint16_t port, uint8_t reg, uint8_t data, uint8_t mask)
stuge04909772007-05-04 04:47:04 +000061{
rminnich6079a1c2007-10-12 21:22:40 +000062 uint8_t tmp;
uwe23438a02007-05-03 10:09:23 +000063
hailfinger7bac0e52009-05-25 23:26:50 +000064 OUTB(reg, port);
65 tmp = INB(port + 1) & ~mask;
66 OUTB(tmp | (data & mask), port + 1);
uwe23438a02007-05-03 10:09:23 +000067}
68
hailfingerc236f9e2009-12-22 23:42:04 +000069/* Not used yet. */
70#if 0
71static int enable_flash_decode_superio(void)
72{
73 int ret;
74 uint8_t tmp;
75
76 switch (superio.vendor) {
77 case SUPERIO_VENDOR_NONE:
78 ret = -1;
79 break;
80 case SUPERIO_VENDOR_ITE:
81 enter_conf_mode_ite(superio.port);
uwef6f94d42010-03-13 17:28:29 +000082 /* Enable flash mapping. Works for most old ITE style Super I/O. */
hailfingerc236f9e2009-12-22 23:42:04 +000083 tmp = sio_read(superio.port, 0x24);
84 tmp |= 0xfc;
85 sio_write(superio.port, 0x24, tmp);
86 exit_conf_mode_ite(superio.port);
87 ret = 0;
88 break;
89 default:
snelsone42c3802010-05-07 20:09:04 +000090 msg_pdbg("Unhandled Super I/O type!\n");
hailfingerc236f9e2009-12-22 23:42:04 +000091 ret = -1;
92 break;
93 }
94 return ret;
95}
96#endif
97
uwee15beb92010-08-08 17:01:18 +000098/*
mkarcherb2505c02010-05-24 16:03:57 +000099 * SMSC FDC37B787: Raise GPIO50
100 */
uweeb26b6e2010-06-07 19:06:26 +0000101static int fdc37b787_gpio50_raise(uint16_t port)
mkarcherb2505c02010-05-24 16:03:57 +0000102{
103 uint8_t id, val;
104
105 OUTB(0x55, port); /* enter conf mode */
106 id = sio_read(port, 0x20);
107 if (id != 0x44) {
uweeb26b6e2010-06-07 19:06:26 +0000108 msg_perr("\nERROR: FDC37B787: Wrong ID 0x%02X.\n", id);
mkarcherb2505c02010-05-24 16:03:57 +0000109 OUTB(0xAA, port); /* leave conf mode */
110 return -1;
111 }
112
113 sio_write(port, 0x07, 0x08); /* Select Aux I/O subdevice */
114
115 val = sio_read(port, 0xC8); /* GP50 */
116 if ((val & 0x1B) != 0x10) /* output, no invert, GPIO */
117 {
uweeb26b6e2010-06-07 19:06:26 +0000118 msg_perr("\nERROR: GPIO50 mode 0x%02X unexpected.\n", val);
mkarcherb2505c02010-05-24 16:03:57 +0000119 OUTB(0xAA, port);
120 return -1;
121 }
122
123 sio_mask(port, 0xF9, 0x01, 0x01);
124
125 OUTB(0xAA, port); /* Leave conf mode */
126 return 0;
127}
128
uwee15beb92010-08-08 17:01:18 +0000129/*
130 * Suited for:
131 * - Nokia IP530: Intel 440BX + PIIX4 + FDC37B787
mkarcherb2505c02010-05-24 16:03:57 +0000132 */
uweeb26b6e2010-06-07 19:06:26 +0000133static int fdc37b787_gpio50_raise_3f0(void)
mkarcherb2505c02010-05-24 16:03:57 +0000134{
uweeb26b6e2010-06-07 19:06:26 +0000135 return fdc37b787_gpio50_raise(0x3f0);
mkarcherb2505c02010-05-24 16:03:57 +0000136}
137
mkarcher51455562010-06-27 15:07:49 +0000138struct winbond_mux {
139 uint8_t reg; /* 0 if the corresponding pin is not muxed */
140 uint8_t data; /* reg/data/mask may be directly ... */
141 uint8_t mask; /* ... passed to sio_mask */
142};
143
144struct winbond_port {
145 const struct winbond_mux *mux; /* NULL or pointer to mux info for the 8 bits */
146 uint8_t ldn; /* LDN this GPIO register is located in */
147 uint8_t enable_bit; /* bit in 0x30 of that LDN to enable
148 the GPIO port */
149 uint8_t base; /* base register in that LDN for the port */
150};
151
152struct winbond_chip {
153 uint8_t device_id; /* reg 0x20 of the expected w83626x */
154 uint8_t gpio_port_count;
155 const struct winbond_port *port;
156};
157
158
159#define UNIMPLEMENTED_PORT {NULL, 0, 0, 0}
160
161enum winbond_id {
162 WINBOND_W83627HF_ID = 0x52,
mkarcher65f85742010-06-27 15:07:52 +0000163 WINBOND_W83627EHF_ID = 0x88,
mkarcher51455562010-06-27 15:07:49 +0000164 WINBOND_W83627THF_ID = 0x82,
165};
166
167static const struct winbond_mux w83627hf_port2_mux[8] = {
168 {0x2A, 0x01, 0x01}, /* or MIDI */
169 {0x2B, 0x80, 0x80}, /* or SPI */
170 {0x2B, 0x40, 0x40}, /* or SPI */
171 {0x2B, 0x20, 0x20}, /* or power LED */
172 {0x2B, 0x10, 0x10}, /* or watchdog */
173 {0x2B, 0x08, 0x08}, /* or infra red */
174 {0x2B, 0x04, 0x04}, /* or infra red */
175 {0x2B, 0x03, 0x03} /* or IRQ1 input */
176};
177
178static const struct winbond_port w83627hf[3] = {
179 UNIMPLEMENTED_PORT,
180 {w83627hf_port2_mux, 0x08, 0, 0xF0},
uwe8d342eb2011-07-28 08:13:25 +0000181 UNIMPLEMENTED_PORT,
mkarcher51455562010-06-27 15:07:49 +0000182};
183
mkarcher65f85742010-06-27 15:07:52 +0000184static const struct winbond_mux w83627ehf_port2_mux[8] = {
185 {0x29, 0x06, 0x02}, /* or MIDI */
186 {0x29, 0x06, 0x02},
187 {0x24, 0x02, 0x00}, /* or SPI ROM interface */
188 {0x24, 0x02, 0x00},
189 {0x2A, 0x01, 0x01}, /* or keyboard/mouse interface */
190 {0x2A, 0x01, 0x01},
191 {0x2A, 0x01, 0x01},
uwe8d342eb2011-07-28 08:13:25 +0000192 {0x2A, 0x01, 0x01},
mkarcher65f85742010-06-27 15:07:52 +0000193};
194
195static const struct winbond_port w83627ehf[6] = {
196 UNIMPLEMENTED_PORT,
197 {w83627ehf_port2_mux, 0x09, 0, 0xE3},
198 UNIMPLEMENTED_PORT,
199 UNIMPLEMENTED_PORT,
200 UNIMPLEMENTED_PORT,
uwe8d342eb2011-07-28 08:13:25 +0000201 UNIMPLEMENTED_PORT,
mkarcher65f85742010-06-27 15:07:52 +0000202};
203
mkarcher51455562010-06-27 15:07:49 +0000204static const struct winbond_mux w83627thf_port4_mux[8] = {
205 {0x2D, 0x01, 0x01}, /* or watchdog or VID level strap */
206 {0x2D, 0x02, 0x02}, /* or resume reset */
207 {0x2D, 0x04, 0x04}, /* or S3 input */
208 {0x2D, 0x08, 0x08}, /* or PSON# */
209 {0x2D, 0x10, 0x10}, /* or PWROK */
210 {0x2D, 0x20, 0x20}, /* or suspend LED */
211 {0x2D, 0x40, 0x40}, /* or panel switch input */
uwe8d342eb2011-07-28 08:13:25 +0000212 {0x2D, 0x80, 0x80}, /* or panel switch output */
mkarcher51455562010-06-27 15:07:49 +0000213};
214
215static const struct winbond_port w83627thf[5] = {
216 UNIMPLEMENTED_PORT, /* GPIO1 */
217 UNIMPLEMENTED_PORT, /* GPIO2 */
218 UNIMPLEMENTED_PORT, /* GPIO3 */
219 {w83627thf_port4_mux, 0x09, 1, 0xF4},
uwe8d342eb2011-07-28 08:13:25 +0000220 UNIMPLEMENTED_PORT, /* GPIO5 */
mkarcher51455562010-06-27 15:07:49 +0000221};
222
223static const struct winbond_chip winbond_chips[] = {
224 {WINBOND_W83627HF_ID, ARRAY_SIZE(w83627hf), w83627hf },
mkarcher65f85742010-06-27 15:07:52 +0000225 {WINBOND_W83627EHF_ID, ARRAY_SIZE(w83627ehf), w83627ehf},
mkarcher51455562010-06-27 15:07:49 +0000226 {WINBOND_W83627THF_ID, ARRAY_SIZE(w83627thf), w83627thf},
227};
228
uwee15beb92010-08-08 17:01:18 +0000229/*
230 * Detects which Winbond Super I/O is responding at the given base address,
231 * but takes no effort to make sure the chip is really a Winbond Super I/O.
232 */
233static const struct winbond_chip *winbond_superio_detect(uint16_t base)
mkarcher51455562010-06-27 15:07:49 +0000234{
235 uint8_t chipid;
uwee15beb92010-08-08 17:01:18 +0000236 const struct winbond_chip *chip = NULL;
mkarcher51455562010-06-27 15:07:49 +0000237 int i;
238
239 w836xx_ext_enter(base);
240 chipid = sio_read(base, 0x20);
uwee15beb92010-08-08 17:01:18 +0000241
242 for (i = 0; i < ARRAY_SIZE(winbond_chips); i++) {
243 if (winbond_chips[i].device_id == chipid) {
mkarcher51455562010-06-27 15:07:49 +0000244 chip = &winbond_chips[i];
245 break;
246 }
uwee15beb92010-08-08 17:01:18 +0000247 }
248
mkarcher51455562010-06-27 15:07:49 +0000249 w836xx_ext_leave(base);
250 return chip;
251}
252
uwee15beb92010-08-08 17:01:18 +0000253/*
254 * The chipid parameter goes away as soon as we have Super I/O matching in the
255 * board enable table. The call to winbond_superio_detect() goes away as
256 * soon as we have generic Super I/O detection code.
257 */
mkarcher51455562010-06-27 15:07:49 +0000258static int winbond_gpio_set(uint16_t base, enum winbond_id chipid,
259 int pin, int raise)
260{
uwee15beb92010-08-08 17:01:18 +0000261 const struct winbond_chip *chip = NULL;
262 const struct winbond_port *gpio;
mkarcher51455562010-06-27 15:07:49 +0000263 int port = pin / 10;
264 int bit = pin % 10;
265
266 chip = winbond_superio_detect(base);
267 if (!chip) {
268 msg_perr("\nERROR: No supported Winbond Super I/O found\n");
269 return -1;
270 }
mkarcher87ee57f2010-06-29 14:44:40 +0000271 if (chip->device_id != chipid) {
272 msg_perr("\nERROR: Found Winbond chip with ID 0x%x, "
273 "expected %x\n", chip->device_id, chipid);
274 return -1;
275 }
mkarcher51455562010-06-27 15:07:49 +0000276 if (bit >= 8 || port == 0 || port > chip->gpio_port_count) {
277 msg_perr("\nERROR: winbond_gpio_set: Invalid GPIO number %d\n",
278 pin);
279 return -1;
280 }
281
282 gpio = &chip->port[port - 1];
283
284 if (gpio->ldn == 0) {
285 msg_perr("\nERROR: GPIO%d is not supported yet on this"
286 " winbond chip\n", port);
287 return -1;
288 }
289
290 w836xx_ext_enter(base);
291
uwee15beb92010-08-08 17:01:18 +0000292 /* Select logical device. */
mkarcher51455562010-06-27 15:07:49 +0000293 sio_write(base, 0x07, gpio->ldn);
294
295 /* Activate logical device. */
296 sio_mask(base, 0x30, 1 << gpio->enable_bit, 1 << gpio->enable_bit);
297
uwee15beb92010-08-08 17:01:18 +0000298 /* Select GPIO function of that pin. */
mkarcher51455562010-06-27 15:07:49 +0000299 if (gpio->mux && gpio->mux[bit].reg)
300 sio_mask(base, gpio->mux[bit].reg,
301 gpio->mux[bit].data, gpio->mux[bit].mask);
302
uwee15beb92010-08-08 17:01:18 +0000303 sio_mask(base, gpio->base + 0, 0, 1 << bit); /* Make pin output */
mkarcher51455562010-06-27 15:07:49 +0000304 sio_mask(base, gpio->base + 2, 0, 1 << bit); /* Clear inversion */
305 sio_mask(base, gpio->base + 1, raise << bit, 1 << bit);
306
307 w836xx_ext_leave(base);
308
309 return 0;
310}
311
uwee15beb92010-08-08 17:01:18 +0000312/*
uwebe4477b2007-08-23 16:08:21 +0000313 * Winbond W83627HF: Raise GPIO24.
stuge04909772007-05-04 04:47:04 +0000314 *
315 * Suited for:
uwebe4477b2007-08-23 16:08:21 +0000316 * - Agami Aruma
317 * - IWILL DK8-HTX
stepan927d4e22007-04-04 22:45:58 +0000318 */
uwee15beb92010-08-08 17:01:18 +0000319static int w83627hf_gpio24_raise_2e(void)
stepan927d4e22007-04-04 22:45:58 +0000320{
mkarcher51455562010-06-27 15:07:49 +0000321 return winbond_gpio_set(0x2e, WINBOND_W83627HF_ID, 24, 1);
rminnich6079a1c2007-10-12 21:22:40 +0000322}
323
uwee15beb92010-08-08 17:01:18 +0000324/*
mkarcher101a27a2010-08-07 21:49:11 +0000325 * Winbond W83627HF: Raise GPIO25.
326 *
327 * Suited for:
328 * - MSI MS-6577
329 */
uwee15beb92010-08-08 17:01:18 +0000330static int w83627hf_gpio25_raise_2e(void)
mkarcher101a27a2010-08-07 21:49:11 +0000331{
332 return winbond_gpio_set(0x2e, WINBOND_W83627HF_ID, 25, 1);
333}
334
uwee15beb92010-08-08 17:01:18 +0000335/*
stefanctbf8ef7d2011-07-20 16:34:18 +0000336 * Winbond W83627EHF: Raise GPIO22.
mkarcher65f85742010-06-27 15:07:52 +0000337 *
338 * Suited for:
uwee15beb92010-08-08 17:01:18 +0000339 * - ASUS A8N-VM CSM: AMD Socket 939 + GeForce 6150 (C51) + MCP51
mkarcher65f85742010-06-27 15:07:52 +0000340 */
stefanctbf8ef7d2011-07-20 16:34:18 +0000341static int w83627ehf_gpio22_raise_2e(void)
mkarcher65f85742010-06-27 15:07:52 +0000342{
stefanctbf8ef7d2011-07-20 16:34:18 +0000343 return winbond_gpio_set(0x2e, WINBOND_W83627EHF_ID, 22, 1);
mkarcher65f85742010-06-27 15:07:52 +0000344}
345
uwee15beb92010-08-08 17:01:18 +0000346/*
mkarcher51455562010-06-27 15:07:49 +0000347 * Winbond W83627THF: Raise GPIO 44.
rminnich6079a1c2007-10-12 21:22:40 +0000348 *
349 * Suited for:
stugea1efa0e2008-07-21 17:48:40 +0000350 * - MSI K8T Neo2-F
rminnich6079a1c2007-10-12 21:22:40 +0000351 */
uwee15beb92010-08-08 17:01:18 +0000352static int w83627thf_gpio44_raise_2e(void)
rminnich6079a1c2007-10-12 21:22:40 +0000353{
mkarcher51455562010-06-27 15:07:49 +0000354 return winbond_gpio_set(0x2e, WINBOND_W83627THF_ID, 44, 1);
rminnich6079a1c2007-10-12 21:22:40 +0000355}
356
uwee15beb92010-08-08 17:01:18 +0000357/*
mkarcher51455562010-06-27 15:07:49 +0000358 * Winbond W83627THF: Raise GPIO 44.
359 *
360 * Suited for:
361 * - MSI K8N Neo3
362 */
uwee15beb92010-08-08 17:01:18 +0000363static int w83627thf_gpio44_raise_4e(void)
stugea1efa0e2008-07-21 17:48:40 +0000364{
mkarcher51455562010-06-27 15:07:49 +0000365 return winbond_gpio_set(0x4e, WINBOND_W83627THF_ID, 44, 1);
rminnich6079a1c2007-10-12 21:22:40 +0000366}
uwe6ed6d952007-12-04 21:49:06 +0000367
uwee15beb92010-08-08 17:01:18 +0000368/*
mkarcher20636ae2010-08-02 08:29:34 +0000369 * Enable MEMW# and set ROM size to max.
uwee15beb92010-08-08 17:01:18 +0000370 * Supported chips: W83L517D, W83697HF/F/HG, W83697SF/UF/UG
stepan927d4e22007-04-04 22:45:58 +0000371 */
hailfinger7bac0e52009-05-25 23:26:50 +0000372static void w836xx_memw_enable(uint16_t port)
stepan927d4e22007-04-04 22:45:58 +0000373{
hailfinger7bac0e52009-05-25 23:26:50 +0000374 w836xx_ext_enter(port);
375 if (!(sio_read(port, 0x24) & 0x02)) { /* Flash ROM enabled? */
uwe6ab4b7b2009-05-09 14:26:04 +0000376 /* Enable MEMW# and set ROM size select to max. (4M). */
hailfinger7bac0e52009-05-25 23:26:50 +0000377 sio_mask(port, 0x24, 0x28, 0x28);
uwe6ab4b7b2009-05-09 14:26:04 +0000378 }
hailfinger7bac0e52009-05-25 23:26:50 +0000379 w836xx_ext_leave(port);
uwe6ab4b7b2009-05-09 14:26:04 +0000380}
381
uwee15beb92010-08-08 17:01:18 +0000382/*
libv53f58142009-12-23 00:54:26 +0000383 * Suited for:
uwee15beb92010-08-08 17:01:18 +0000384 * - EPoX EP-8K5A2: VIA KT333 + VT8235
385 * - Albatron PM266A Pro: VIA P4M266A + VT8235
386 * - Shuttle AK31 (all versions): VIA KT266 + VT8233
387 * - ASUS A7V8X-MX SE and A7V400-MX: AMD K7 + VIA KM400A + VT8235
388 * - Tyan S2498 (Tomcat K7M): AMD Geode NX + VIA KM400 + VT8237
mkarcher7ad3c252010-08-15 10:21:29 +0000389 * - MSI KM4M-V and KM4AM-V: VIA KM400/KM400A + VT8237
uwec466f572010-09-11 15:25:48 +0000390 * - MSI MS-6561 (745 Ultra): SiS 745 + W83697HF
uwe89e0e7f2010-09-07 18:14:53 +0000391 * - MSI MS-6787 (P4MAM-V/P4MAM-L): VIA P4M266 + VT8235
uweb0beb9f2010-10-05 21:48:43 +0000392 * - ASRock K7S41: SiS 741 + SiS 963 + W83697HF
uwe0e214692011-06-19 16:52:48 +0000393 * - ASRock K7S41GX: SiS 741GX + SiS 963L + W83697HF
uwe6ab4b7b2009-05-09 14:26:04 +0000394 */
uweeb26b6e2010-06-07 19:06:26 +0000395static int w836xx_memw_enable_2e(void)
uwe6ab4b7b2009-05-09 14:26:04 +0000396{
libv53f58142009-12-23 00:54:26 +0000397 w836xx_memw_enable(0x2E);
stepan927d4e22007-04-04 22:45:58 +0000398
libv53f58142009-12-23 00:54:26 +0000399 return 0;
uwe6ab4b7b2009-05-09 14:26:04 +0000400}
401
uwee15beb92010-08-08 17:01:18 +0000402/*
mkarchered00ee62010-03-21 13:36:20 +0000403 * Suited for:
uwee15beb92010-08-08 17:01:18 +0000404 * - Termtek TK-3370 (rev. 2.5b)
mkarchered00ee62010-03-21 13:36:20 +0000405 */
uweeb26b6e2010-06-07 19:06:26 +0000406static int w836xx_memw_enable_4e(void)
mkarchered00ee62010-03-21 13:36:20 +0000407{
408 w836xx_memw_enable(0x4E);
409
410 return 0;
411}
412
uwee15beb92010-08-08 17:01:18 +0000413/*
hailfingerc73ce6e2010-07-10 16:56:32 +0000414 * Suited for all boards with ITE IT8705F.
415 * The SIS950 Super I/O probably requires a similar flash write enable.
libv71e95f52010-01-20 14:45:07 +0000416 */
hailfingerc73ce6e2010-07-10 16:56:32 +0000417int it8705f_write_enable(uint8_t port)
libv71e95f52010-01-20 14:45:07 +0000418{
hailfingerc73ce6e2010-07-10 16:56:32 +0000419 uint8_t tmp;
420 int ret = 0;
421
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000422 if (!(internal_buses_supported & BUS_PARALLEL))
423 return 1;
424
libv71e95f52010-01-20 14:45:07 +0000425 enter_conf_mode_ite(port);
hailfingerc73ce6e2010-07-10 16:56:32 +0000426 tmp = sio_read(port, 0x24);
427 /* Check if at least one flash segment is enabled. */
428 if (tmp & 0xf0) {
429 /* The IT8705F will respond to LPC cycles and translate them. */
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +1000430 internal_buses_supported &= BUS_PARALLEL;
hailfingerc73ce6e2010-07-10 16:56:32 +0000431 /* Flash ROM I/F Writes Enable */
432 tmp |= 0x04;
433 msg_pdbg("Enabling IT8705F flash ROM interface write.\n");
434 if (tmp & 0x02) {
435 /* The data sheet contradicts itself about max size. */
436 max_rom_decode.parallel = 1024 * 1024;
437 msg_pinfo("IT8705F with very unusual settings. Please "
438 "send the output of \"flashrom -V\" to \n"
hailfinger5bae2332010-10-08 11:03:02 +0000439 "flashrom@flashrom.org with "
440 "IT8705: your board name: flashrom -V\n"
441 "as the subject to help us finish "
hailfingerc73ce6e2010-07-10 16:56:32 +0000442 "support for your Super I/O. Thanks.\n");
443 ret = 1;
444 } else if (tmp & 0x08) {
445 max_rom_decode.parallel = 512 * 1024;
446 } else {
447 max_rom_decode.parallel = 256 * 1024;
448 }
449 /* Safety checks. The data sheet is unclear here: Segments 1+3
450 * overlap, no segment seems to cover top - 1MB to top - 512kB.
451 * We assume that certain combinations make no sense.
452 */
453 if (((tmp & 0x02) && !(tmp & 0x08)) || /* 1 MB en, 512 kB dis */
454 (!(tmp & 0x10)) || /* 128 kB dis */
455 (!(tmp & 0x40))) { /* 256/512 kB dis */
456 msg_perr("Inconsistent IT8705F decode size!\n");
457 ret = 1;
458 }
459 if (sio_read(port, 0x25) != 0) {
460 msg_perr("IT8705F flash data pins disabled!\n");
461 ret = 1;
462 }
463 if (sio_read(port, 0x26) != 0) {
464 msg_perr("IT8705F flash address pins 0-7 disabled!\n");
465 ret = 1;
466 }
467 if (sio_read(port, 0x27) != 0) {
468 msg_perr("IT8705F flash address pins 8-15 disabled!\n");
469 ret = 1;
470 }
471 if ((sio_read(port, 0x29) & 0x10) != 0) {
472 msg_perr("IT8705F flash write enable pin disabled!\n");
473 ret = 1;
474 }
475 if ((sio_read(port, 0x29) & 0x08) != 0) {
476 msg_perr("IT8705F flash chip select pin disabled!\n");
477 ret = 1;
478 }
479 if ((sio_read(port, 0x29) & 0x04) != 0) {
480 msg_perr("IT8705F flash read strobe pin disabled!\n");
481 ret = 1;
482 }
483 if ((sio_read(port, 0x29) & 0x03) != 0) {
484 msg_perr("IT8705F flash address pins 16-17 disabled!\n");
485 /* Not really an error if you use flash chips smaller
486 * than 256 kByte, but such a configuration is unlikely.
487 */
488 ret = 1;
489 }
490 msg_pdbg("Maximum IT8705F parallel flash decode size is %u.\n",
491 max_rom_decode.parallel);
492 if (ret) {
493 msg_pinfo("Not enabling IT8705F flash write.\n");
494 } else {
495 sio_write(port, 0x24, tmp);
496 }
497 } else {
498 msg_pdbg("No IT8705F flash segment enabled.\n");
David Hendricks5e79c9f2013-11-04 22:05:08 -0800499 ret = 1;
hailfingerc73ce6e2010-07-10 16:56:32 +0000500 }
libv71e95f52010-01-20 14:45:07 +0000501 exit_conf_mode_ite(port);
502
hailfingerc73ce6e2010-07-10 16:56:32 +0000503 return ret;
libv71e95f52010-01-20 14:45:07 +0000504}
libv53f58142009-12-23 00:54:26 +0000505
mhm0d4fa5f2010-09-13 19:39:25 +0000506/*
507 * The ITE IT8707F is a custom chip made by ITE exclusively for ASUS.
508 * It uses the Winbond command sequence to enter extended configuration
509 * mode and the ITE sequence to exit.
510 *
511 * Registers seems similar to the ones on ITE IT8710F.
512 */
513static int it8707f_write_enable(uint8_t port)
514{
515 uint8_t tmp;
516
517 w836xx_ext_enter(port);
518
519 /* Set bit 3 (GLB_REG_WE) of reg 0x23: Makes reg 0x24-0x2A rw */
520 tmp = sio_read(port, 0x23);
521 tmp |= (1 << 3);
522 sio_write(port, 0x23, tmp);
523
524 /* Set bit 2 (FLASH_WE) and bit 3 (FLASH_IF_EN) of reg 0x24 */
525 tmp = sio_read(port, 0x24);
526 tmp |= (1 << 2) | (1 << 3);
527 sio_write(port, 0x24, tmp);
528
529 /* Clear bit 3 (GLB_REG_WE) of reg 0x23: Makes reg 0x24-0x2A ro */
530 tmp = sio_read(port, 0x23);
531 tmp &= ~(1 << 3);
532 sio_write(port, 0x23, tmp);
533
534 exit_conf_mode_ite(port);
535
536 return 0;
537}
538
539/*
540 * Suited for:
541 * - ASUS P4SC-E: SiS 651 + 962 + ITE IT8707F
542 */
543static int it8707f_write_enable_2e(void)
544{
545 return it8707f_write_enable(0x2e);
546}
547
mkarcherfc0a1e12011-03-06 12:07:19 +0000548#define PC87360_ID 0xE1
549#define PC87364_ID 0xE4
550
551static int pc8736x_gpio_set(uint8_t chipid, uint8_t gpio, int raise)
mkarcherb507b7b2010-02-27 18:35:54 +0000552{
uwee15beb92010-08-08 17:01:18 +0000553 static const int bankbase[] = {0, 4, 8, 10, 12};
554 int gpio_bank = gpio / 8;
555 int gpio_pin = gpio % 8;
556 uint16_t baseport;
557 uint8_t id, val;
mkarcherb507b7b2010-02-27 18:35:54 +0000558
uwee15beb92010-08-08 17:01:18 +0000559 if (gpio_bank > 4) {
mkarcherfc0a1e12011-03-06 12:07:19 +0000560 msg_perr("PC8736x: Invalid GPIO %d\n", gpio);
uwee15beb92010-08-08 17:01:18 +0000561 return -1;
562 }
mkarcherb507b7b2010-02-27 18:35:54 +0000563
uwee15beb92010-08-08 17:01:18 +0000564 id = sio_read(0x2E, 0x20);
mkarcherfc0a1e12011-03-06 12:07:19 +0000565 if (id != chipid) {
uwe8d342eb2011-07-28 08:13:25 +0000566 msg_perr("PC8736x: unexpected ID %02x (expected %02x)\n",
567 id, chipid);
uwee15beb92010-08-08 17:01:18 +0000568 return -1;
569 }
mkarcherb507b7b2010-02-27 18:35:54 +0000570
uwee15beb92010-08-08 17:01:18 +0000571 sio_write(0x2E, 0x07, 0x07); /* Select GPIO device. */
572 baseport = (sio_read(0x2E, 0x60) << 8) | sio_read(0x2E, 0x61);
573 if ((baseport & 0xFFF0) == 0xFFF0 || baseport == 0) {
574 msg_perr("PC87360: invalid GPIO base address %04x\n",
575 baseport);
576 return -1;
577 }
578 sio_mask (0x2E, 0x30, 0x01, 0x01); /* Enable logical device. */
579 sio_write(0x2E, 0xF0, gpio_bank * 16 + gpio_pin);
580 sio_mask (0x2E, 0xF1, 0x01, 0x01); /* Make pin output. */
mkarcherb507b7b2010-02-27 18:35:54 +0000581
uwee15beb92010-08-08 17:01:18 +0000582 val = INB(baseport + bankbase[gpio_bank]);
583 if (raise)
584 val |= 1 << gpio_pin;
585 else
586 val &= ~(1 << gpio_pin);
587 OUTB(val, baseport + bankbase[gpio_bank]);
mkarcherb507b7b2010-02-27 18:35:54 +0000588
uwee15beb92010-08-08 17:01:18 +0000589 return 0;
mkarcherb507b7b2010-02-27 18:35:54 +0000590}
591
uwee15beb92010-08-08 17:01:18 +0000592/*
593 * VIA VT823x: Set one of the GPIO pins.
uwe6ab4b7b2009-05-09 14:26:04 +0000594 */
libv53f58142009-12-23 00:54:26 +0000595static int via_vt823x_gpio_set(uint8_t gpio, int raise)
uwe6ab4b7b2009-05-09 14:26:04 +0000596{
libv53f58142009-12-23 00:54:26 +0000597 struct pci_dev *dev;
uwe6ab4b7b2009-05-09 14:26:04 +0000598 uint16_t base;
libvc89fddc2009-12-09 07:53:01 +0000599 uint8_t val, bit, offset;
uwe6ab4b7b2009-05-09 14:26:04 +0000600
libv53f58142009-12-23 00:54:26 +0000601 dev = pci_dev_find_vendorclass(0x1106, 0x0601);
602 switch (dev->device_id) {
603 case 0x3177: /* VT8235 */
604 case 0x3227: /* VT8237R */
605 case 0x3337: /* VT8237A */
606 break;
607 default:
snelsone42c3802010-05-07 20:09:04 +0000608 msg_perr("\nERROR: VT823x ISA bridge not found.\n");
libv53f58142009-12-23 00:54:26 +0000609 return -1;
610 }
611
libv785ec422009-06-19 13:53:59 +0000612 if ((gpio >= 12) && (gpio <= 15)) {
613 /* GPIO12-15 -> output */
614 val = pci_read_byte(dev, 0xE4);
615 val |= 0x10;
616 pci_write_byte(dev, 0xE4, val);
617 } else if (gpio == 9) {
618 /* GPIO9 -> Output */
619 val = pci_read_byte(dev, 0xE4);
620 val |= 0x20;
621 pci_write_byte(dev, 0xE4, val);
libvc89fddc2009-12-09 07:53:01 +0000622 } else if (gpio == 5) {
623 val = pci_read_byte(dev, 0xE4);
624 val |= 0x01;
625 pci_write_byte(dev, 0xE4, val);
libv785ec422009-06-19 13:53:59 +0000626 } else {
snelsone42c3802010-05-07 20:09:04 +0000627 msg_perr("\nERROR: "
uwe6ab4b7b2009-05-09 14:26:04 +0000628 "VT823x GPIO%02d is not implemented.\n", gpio);
libv53f58142009-12-23 00:54:26 +0000629 return -1;
uwef6641642007-05-09 10:17:44 +0000630 }
stepan927d4e22007-04-04 22:45:58 +0000631
uwe6ab4b7b2009-05-09 14:26:04 +0000632 /* We need the I/O Base Address for this board's flash enable. */
633 base = pci_read_word(dev, 0x88) & 0xff80;
634
libvc89fddc2009-12-09 07:53:01 +0000635 offset = 0x4C + gpio / 8;
636 bit = 0x01 << (gpio % 8);
637
638 val = INB(base + offset);
uwe6ab4b7b2009-05-09 14:26:04 +0000639 if (raise)
640 val |= bit;
641 else
642 val &= ~bit;
libvc89fddc2009-12-09 07:53:01 +0000643 OUTB(val, base + offset);
stepan927d4e22007-04-04 22:45:58 +0000644
uwef6641642007-05-09 10:17:44 +0000645 return 0;
stepan927d4e22007-04-04 22:45:58 +0000646}
647
uwee15beb92010-08-08 17:01:18 +0000648/*
649 * Suited for:
650 * - ASUS M2V-MX: VIA K8M890 + VT8237A + IT8716F
stepan927d4e22007-04-04 22:45:58 +0000651 */
uweeb26b6e2010-06-07 19:06:26 +0000652static int via_vt823x_gpio5_raise(void)
stepan927d4e22007-04-04 22:45:58 +0000653{
libv53f58142009-12-23 00:54:26 +0000654 /* On M2V-MX: GPO5 is connected to WP# and TBL#. */
655 return via_vt823x_gpio_set(5, 1);
uwe6ab4b7b2009-05-09 14:26:04 +0000656}
657
uwee15beb92010-08-08 17:01:18 +0000658/*
659 * Suited for:
660 * - VIA EPIA EK & N & NL
libv785ec422009-06-19 13:53:59 +0000661 */
uweeb26b6e2010-06-07 19:06:26 +0000662static int via_vt823x_gpio9_raise(void)
libv785ec422009-06-19 13:53:59 +0000663{
libv53f58142009-12-23 00:54:26 +0000664 return via_vt823x_gpio_set(9, 1);
libv785ec422009-06-19 13:53:59 +0000665}
666
uwee15beb92010-08-08 17:01:18 +0000667/*
668 * Suited for:
669 * - VIA EPIA M and MII (and maybe other CLE266 based EPIAs)
libv53f58142009-12-23 00:54:26 +0000670 *
671 * We don't need to do this for EPIA M when using coreboot, GPIO15 is never
672 * lowered there.
uwe6ab4b7b2009-05-09 14:26:04 +0000673 */
uweeb26b6e2010-06-07 19:06:26 +0000674static int via_vt823x_gpio15_raise(void)
uwe6ab4b7b2009-05-09 14:26:04 +0000675{
libv53f58142009-12-23 00:54:26 +0000676 return via_vt823x_gpio_set(15, 1);
677}
678
uwee15beb92010-08-08 17:01:18 +0000679/*
libv53f58142009-12-23 00:54:26 +0000680 * Winbond W83697HF Super I/O + VIA VT8235 southbridge
681 *
682 * Suited for:
uwee15beb92010-08-08 17:01:18 +0000683 * - MSI KT4V and KT4V-L: AMD K7 + VIA KT400 + VT8235
684 * - MSI KT4 Ultra: AMD K7 + VIA KT400 + VT8235
libv53f58142009-12-23 00:54:26 +0000685 */
uweeb26b6e2010-06-07 19:06:26 +0000686static int board_msi_kt4v(void)
libv53f58142009-12-23 00:54:26 +0000687{
688 int ret;
689
690 ret = via_vt823x_gpio_set(12, 1);
uwe6ab4b7b2009-05-09 14:26:04 +0000691 w836xx_memw_enable(0x2E);
hailfinger755073f2008-02-09 02:03:06 +0000692
libv53f58142009-12-23 00:54:26 +0000693 return ret;
hailfinger755073f2008-02-09 02:03:06 +0000694}
695
uwee15beb92010-08-08 17:01:18 +0000696/*
697 * Suited for:
698 * - ASUS P5A
uwe691ddb62007-05-20 16:16:13 +0000699 *
700 * This is rather nasty code, but there's no way to do this cleanly.
701 * We're basically talking to some unknown device on SMBus, my guess
702 * is that it is the Winbond W83781D that lives near the DIP BIOS.
703 */
uweeb26b6e2010-06-07 19:06:26 +0000704static int board_asus_p5a(void)
uwe691ddb62007-05-20 16:16:13 +0000705{
706 uint8_t tmp;
707 int i;
708
709#define ASUSP5A_LOOP 5000
710
hailfingere1f062f2008-05-22 13:22:45 +0000711 OUTB(0x00, 0xE807);
712 OUTB(0xEF, 0xE803);
uwe691ddb62007-05-20 16:16:13 +0000713
hailfingere1f062f2008-05-22 13:22:45 +0000714 OUTB(0xFF, 0xE800);
uwe691ddb62007-05-20 16:16:13 +0000715
716 for (i = 0; i < ASUSP5A_LOOP; i++) {
hailfingere1f062f2008-05-22 13:22:45 +0000717 OUTB(0xE1, 0xFF);
718 if (INB(0xE800) & 0x04)
uwe691ddb62007-05-20 16:16:13 +0000719 break;
720 }
721
722 if (i == ASUSP5A_LOOP) {
uweeb26b6e2010-06-07 19:06:26 +0000723 msg_perr("Unable to contact device.\n");
uwe691ddb62007-05-20 16:16:13 +0000724 return -1;
725 }
726
hailfingere1f062f2008-05-22 13:22:45 +0000727 OUTB(0x20, 0xE801);
728 OUTB(0x20, 0xE1);
uwe691ddb62007-05-20 16:16:13 +0000729
hailfingere1f062f2008-05-22 13:22:45 +0000730 OUTB(0xFF, 0xE802);
uwe691ddb62007-05-20 16:16:13 +0000731
732 for (i = 0; i < ASUSP5A_LOOP; i++) {
hailfingere1f062f2008-05-22 13:22:45 +0000733 tmp = INB(0xE800);
uwe691ddb62007-05-20 16:16:13 +0000734 if (tmp & 0x70)
735 break;
736 }
737
738 if ((i == ASUSP5A_LOOP) || !(tmp & 0x10)) {
uweeb26b6e2010-06-07 19:06:26 +0000739 msg_perr("Failed to read device.\n");
uwe691ddb62007-05-20 16:16:13 +0000740 return -1;
741 }
742
hailfingere1f062f2008-05-22 13:22:45 +0000743 tmp = INB(0xE804);
uwe691ddb62007-05-20 16:16:13 +0000744 tmp &= ~0x02;
745
hailfingere1f062f2008-05-22 13:22:45 +0000746 OUTB(0x00, 0xE807);
747 OUTB(0xEE, 0xE803);
uwe691ddb62007-05-20 16:16:13 +0000748
hailfingere1f062f2008-05-22 13:22:45 +0000749 OUTB(tmp, 0xE804);
uwe691ddb62007-05-20 16:16:13 +0000750
hailfingere1f062f2008-05-22 13:22:45 +0000751 OUTB(0xFF, 0xE800);
752 OUTB(0xE1, 0xFF);
uwe691ddb62007-05-20 16:16:13 +0000753
hailfingere1f062f2008-05-22 13:22:45 +0000754 OUTB(0x20, 0xE801);
755 OUTB(0x20, 0xE1);
uwe691ddb62007-05-20 16:16:13 +0000756
hailfingere1f062f2008-05-22 13:22:45 +0000757 OUTB(0xFF, 0xE802);
uwe691ddb62007-05-20 16:16:13 +0000758
759 for (i = 0; i < ASUSP5A_LOOP; i++) {
hailfingere1f062f2008-05-22 13:22:45 +0000760 tmp = INB(0xE800);
uwe691ddb62007-05-20 16:16:13 +0000761 if (tmp & 0x70)
762 break;
763 }
764
765 if ((i == ASUSP5A_LOOP) || !(tmp & 0x10)) {
uweeb26b6e2010-06-07 19:06:26 +0000766 msg_perr("Failed to write to device.\n");
uwe691ddb62007-05-20 16:16:13 +0000767 return -1;
768 }
769
770 return 0;
771}
772
libv6a74dbe2009-12-09 11:39:02 +0000773/*
774 * Set GPIO lines in the Broadcom HT-1000 southbridge.
775 *
uwee15beb92010-08-08 17:01:18 +0000776 * It's not a Super I/O but it uses the same index/data port method.
libv6a74dbe2009-12-09 11:39:02 +0000777 */
uweeb26b6e2010-06-07 19:06:26 +0000778static int board_hp_dl145_g3_enable(void)
libv6a74dbe2009-12-09 11:39:02 +0000779{
780 /* GPIO 0 reg from PM regs */
781 /* Set GPIO 2 and 5 high, connected to flash WP# and TBL# pins. */
782 sio_mask(0xcd6, 0x44, 0x24, 0x24);
783
784 return 0;
785}
786
hailfinger08c281b2010-07-01 11:16:28 +0000787/*
788 * Set GPIO lines in the Broadcom HT-1000 southbridge.
789 *
uwee15beb92010-08-08 17:01:18 +0000790 * It's not a Super I/O but it uses the same index/data port method.
hailfinger08c281b2010-07-01 11:16:28 +0000791 */
792static int board_hp_dl165_g6_enable(void)
793{
794 /* Variant of DL145, with slightly different pin placement. */
795 sio_mask(0xcd6, 0x44, 0x80, 0x80); /* TBL# */
796 sio_mask(0xcd6, 0x46, 0x04, 0x04); /* WP# */
797
798 return 0;
799}
800
uweeb26b6e2010-06-07 19:06:26 +0000801static int board_ibm_x3455(void)
stepan60b4d872007-06-05 12:51:52 +0000802{
uwee15beb92010-08-08 17:01:18 +0000803 /* Raise GPIO13. */
hailfinger9c47a702009-06-01 21:30:42 +0000804 sio_mask(0xcd6, 0x45, 0x20, 0x20);
stepan60b4d872007-06-05 12:51:52 +0000805
806 return 0;
807}
808
uwee15beb92010-08-08 17:01:18 +0000809/*
810 * Suited for:
811 * - Shuttle FN25 (SN25P): AMD S939 + NVIDIA CK804 (nForce4)
libvb13ceec2009-10-21 12:05:50 +0000812 */
uweeb26b6e2010-06-07 19:06:26 +0000813static int board_shuttle_fn25(void)
libvb13ceec2009-10-21 12:05:50 +0000814{
815 struct pci_dev *dev;
816
uwe8d342eb2011-07-28 08:13:25 +0000817 dev = pci_dev_find(0x10DE, 0x0050); /* NVIDIA CK804 ISA bridge. */
libvb13ceec2009-10-21 12:05:50 +0000818 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +0000819 msg_perr("\nERROR: NVIDIA nForce4 ISA bridge not found.\n");
libvb13ceec2009-10-21 12:05:50 +0000820 return -1;
821 }
822
uwe8d342eb2011-07-28 08:13:25 +0000823 /* One of those bits seems to be connected to TBL#, but -ENOINFO. */
libvb13ceec2009-10-21 12:05:50 +0000824 pci_write_byte(dev, 0x92, 0);
825
826 return 0;
827}
828
uwee15beb92010-08-08 17:01:18 +0000829/*
mhmbf2aff92010-09-16 22:09:18 +0000830 * Suited for:
831 * - Elitegroup GeForce6100SM-M: NVIDIA MCP61 + ITE IT8726F
832 */
mhmbf2aff92010-09-16 22:09:18 +0000833static int board_ecs_geforce6100sm_m(void)
834{
835 struct pci_dev *dev;
836 uint32_t tmp;
837
838 dev = pci_dev_find(0x10DE, 0x03EB); /* NVIDIA MCP61 SMBus. */
839 if (!dev) {
840 msg_perr("\nERROR: NVIDIA MCP61 SMBus not found.\n");
841 return -1;
842 }
843
844 tmp = pci_read_byte(dev, 0xE0);
845 tmp &= ~(1 << 3);
846 pci_write_byte(dev, 0xE0, tmp);
847
848 return 0;
849}
850
851/*
libv6db37e62009-12-03 12:25:34 +0000852 * Very similar to AMD 8111 IO Hub.
libv5ac6e5c2009-10-05 16:07:00 +0000853 */
libv6db37e62009-12-03 12:25:34 +0000854static int nvidia_mcp_gpio_set(int gpio, int raise)
libv5ac6e5c2009-10-05 16:07:00 +0000855{
libv6db37e62009-12-03 12:25:34 +0000856 struct pci_dev *dev;
uwe8d342eb2011-07-28 08:13:25 +0000857 uint16_t base, devclass;
libv5ac6e5c2009-10-05 16:07:00 +0000858 uint8_t tmp;
859
libv8068cf92009-12-22 13:04:13 +0000860 if ((gpio < 0) || (gpio >= 0x40)) {
snelsone42c3802010-05-07 20:09:04 +0000861 msg_perr("\nERROR: unsupported GPIO: %d.\n", gpio);
libv5736b072009-06-03 07:50:39 +0000862 return -1;
863 }
864
hailfingerb91c08c2011-08-15 19:54:20 +0000865 /* Check for the ISA bridge first. */
libv8068cf92009-12-22 13:04:13 +0000866 dev = pci_dev_find_vendorclass(0x10DE, 0x0601);
libv6db37e62009-12-03 12:25:34 +0000867 switch (dev->device_id) {
868 case 0x0030: /* CK804 */
869 case 0x0050: /* MCP04 */
870 case 0x0060: /* MCP2 */
mkarcherd2189b42010-06-12 23:07:26 +0000871 case 0x00E0: /* CK8 */
libv6db37e62009-12-03 12:25:34 +0000872 break;
mkarcherbb421582010-06-01 16:09:06 +0000873 case 0x0260: /* MCP51 */
mkarcher41c71342011-03-06 12:09:05 +0000874 case 0x0261: /* MCP51 */
mkarcherbb421582010-06-01 16:09:06 +0000875 case 0x0364: /* MCP55 */
876 /* find SMBus controller on *this* southbridge */
877 /* The infamous Tyan S2915-E has two south bridges; they are
878 easily told apart from each other by the class of the
879 LPC bridge, but have the same SMBus bridge IDs */
880 if (dev->func != 0) {
881 msg_perr("MCP LPC bridge at unexpected function"
882 " number %d\n", dev->func);
883 return -1;
884 }
885
hailfinger86da8ff2010-07-17 22:28:05 +0000886#if PCI_LIB_VERSION >= 0x020200
mkarcherbb421582010-06-01 16:09:06 +0000887 dev = pci_get_dev(pacc, dev->domain, dev->bus, dev->dev, 1);
hailfinger86da8ff2010-07-17 22:28:05 +0000888#else
889 /* pciutils/libpci before version 2.2 is too old to support
890 * PCI domains. Such old machines usually don't have domains
891 * besides domain 0, so this is not a problem.
892 */
893 dev = pci_get_dev(pacc, dev->bus, dev->dev, 1);
894#endif
mkarcherbb421582010-06-01 16:09:06 +0000895 if (!dev) {
896 msg_perr("MCP SMBus controller could not be found\n");
897 return -1;
898 }
899 devclass = pci_read_word(dev, PCI_CLASS_DEVICE);
900 if (devclass != 0x0C05) {
901 msg_perr("Unexpected device class %04x for SMBus"
902 " controller\n", devclass);
903 return -1;
904 }
libv8068cf92009-12-22 13:04:13 +0000905 break;
mkarcherbb421582010-06-01 16:09:06 +0000906 default:
snelsone42c3802010-05-07 20:09:04 +0000907 msg_perr("\nERROR: no NVIDIA LPC/SMBus controller found.\n");
libv6db37e62009-12-03 12:25:34 +0000908 return -1;
909 }
910
911 base = pci_read_long(dev, 0x64) & 0x0000FF00; /* System control area */
912 base += 0xC0;
913
914 tmp = INB(base + gpio);
915 tmp &= ~0x0F; /* null lower nibble */
916 tmp |= 0x04; /* gpio -> output. */
917 if (raise)
918 tmp |= 0x01;
919 OUTB(tmp, base + gpio);
libv5736b072009-06-03 07:50:39 +0000920
921 return 0;
922}
923
uwee15beb92010-08-08 17:01:18 +0000924/*
925 * Suited for:
stefanctd7a27782011-08-07 13:17:20 +0000926 * - ASUS A8M2N-LA (HP OEM "NodusM3-GL8E"): NVIDIA MCP51
uwe75074aa2010-08-15 14:36:18 +0000927 * - ASUS A8N-LA (HP OEM "Nagami-GL8E"): NVIDIA MCP51
uwee15beb92010-08-08 17:01:18 +0000928 * - ASUS M2NBP-VM CSM: NVIDIA MCP51
mkarcher28d6c872010-03-07 16:42:55 +0000929 */
uweeb26b6e2010-06-07 19:06:26 +0000930static int nvidia_mcp_gpio0_raise(void)
mkarcher28d6c872010-03-07 16:42:55 +0000931{
932 return nvidia_mcp_gpio_set(0x00, 1);
933}
934
uwee15beb92010-08-08 17:01:18 +0000935/*
936 * Suited for:
937 * - abit KN8 Ultra: NVIDIA CK804
snelsone1eaba92010-03-19 22:37:29 +0000938 */
uweeb26b6e2010-06-07 19:06:26 +0000939static int nvidia_mcp_gpio2_lower(void)
snelsone1eaba92010-03-19 22:37:29 +0000940{
941 return nvidia_mcp_gpio_set(0x02, 0);
942}
943
uwee15beb92010-08-08 17:01:18 +0000944/*
945 * Suited for:
mkarcherfcd97f82011-04-14 23:14:27 +0000946 * - Foxconn 6150K8MD-8EKRSH: Socket 939 + NVIDIA MCP51
uwe0b7a6ba2010-08-15 15:26:30 +0000947 * - MSI K8N Neo4: NVIDIA CK804. TODO: Should probably be K8N Neo4 Platinum, see http://www.coreboot.org/pipermail/flashrom/2010-August/004362.html.
948 * - MSI K8NGM2-L: NVIDIA MCP51
libv64ace522009-12-23 03:01:36 +0000949 */
uweeb26b6e2010-06-07 19:06:26 +0000950static int nvidia_mcp_gpio2_raise(void)
libv64ace522009-12-23 03:01:36 +0000951{
952 return nvidia_mcp_gpio_set(0x02, 1);
953}
954
uwee15beb92010-08-08 17:01:18 +0000955/*
956 * Suited for:
uwee2c9f9b2010-10-18 22:32:03 +0000957 * - EPoX EP-8NPA7I: Socket 754 + NVIDIA nForce4 4X
uwee05404d2010-10-15 23:02:15 +0000958 */
959static int nvidia_mcp_gpio4_raise(void)
960{
961 return nvidia_mcp_gpio_set(0x04, 1);
962}
963
964/*
965 * Suited for:
uwee15beb92010-08-08 17:01:18 +0000966 * - HP xw9400 (Tyan S2915-E OEM): Dual(!) NVIDIA MCP55
967 *
968 * Notes: a) There are two MCP55 chips, so also two SMBus bridges on that
969 * board. We can't tell the SMBus logical devices apart, but we
970 * can tell the LPC bridge functions apart.
971 * We need to choose the SMBus bridge next to the LPC bridge with
972 * ID 0x364 and the "LPC bridge" class.
973 * b) #TBL is hardwired on that board to a pull-down. It can be
974 * overridden by connecting the two solder points next to F2.
mkarcherbb421582010-06-01 16:09:06 +0000975 */
uweeb26b6e2010-06-07 19:06:26 +0000976static int nvidia_mcp_gpio5_raise(void)
mkarcherbb421582010-06-01 16:09:06 +0000977{
978 return nvidia_mcp_gpio_set(0x05, 1);
979}
980
uwee15beb92010-08-08 17:01:18 +0000981/*
982 * Suited for:
983 * - abit NF7-S: NVIDIA CK804
mkarcher8b7b04a2010-04-11 21:01:06 +0000984 */
uweeb26b6e2010-06-07 19:06:26 +0000985static int nvidia_mcp_gpio8_raise(void)
mkarcher8b7b04a2010-04-11 21:01:06 +0000986{
987 return nvidia_mcp_gpio_set(0x08, 1);
988}
989
uwee15beb92010-08-08 17:01:18 +0000990/*
991 * Suited for:
stefanct371e7e82011-07-07 19:56:58 +0000992 * - GIGABYTE GA-K8NS Pro-939: Socket 939 + NVIDIA nForce3 + CK8
stefanct8fb644d2011-06-13 16:58:54 +0000993 */
994static int nvidia_mcp_gpio0a_raise(void)
995{
996 return nvidia_mcp_gpio_set(0x0a, 1);
997}
998
999/*
1000 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001001 * - MSI K8N Neo2 Platinum: Socket 939 + nForce3 Ultra + CK8
mkarcherd2189b42010-06-12 23:07:26 +00001002 */
mkarcherd291e752010-06-12 23:14:03 +00001003static int nvidia_mcp_gpio0c_raise(void)
mkarcherd2189b42010-06-12 23:07:26 +00001004{
1005 return nvidia_mcp_gpio_set(0x0c, 1);
1006}
1007
uwee15beb92010-08-08 17:01:18 +00001008/*
1009 * Suited for:
1010 * - abit NF-M2 nView: Socket AM2 + NVIDIA MCP51
mkarcher00131382010-07-24 22:50:54 +00001011 */
1012static int nvidia_mcp_gpio4_lower(void)
1013{
1014 return nvidia_mcp_gpio_set(0x04, 0);
1015}
1016
uwee15beb92010-08-08 17:01:18 +00001017/*
1018 * Suited for:
1019 * - ASUS P5ND2-SLI Deluxe: LGA775 + nForce4 SLI + MCP04
libv5ac6e5c2009-10-05 16:07:00 +00001020 */
uweeb26b6e2010-06-07 19:06:26 +00001021static int nvidia_mcp_gpio10_raise(void)
libv5ac6e5c2009-10-05 16:07:00 +00001022{
libv6db37e62009-12-03 12:25:34 +00001023 return nvidia_mcp_gpio_set(0x10, 1);
1024}
libv5ac6e5c2009-10-05 16:07:00 +00001025
uwee15beb92010-08-08 17:01:18 +00001026/*
1027 * Suited for:
1028 * - GIGABYTE GA-K8N-SLI: AMD socket 939 + NVIDIA CK804 + ITE IT8712F
libv6db37e62009-12-03 12:25:34 +00001029 */
uweeb26b6e2010-06-07 19:06:26 +00001030static int nvidia_mcp_gpio21_raise(void)
libv6db37e62009-12-03 12:25:34 +00001031{
1032 return nvidia_mcp_gpio_set(0x21, 0x01);
libv5ac6e5c2009-10-05 16:07:00 +00001033}
1034
uwee15beb92010-08-08 17:01:18 +00001035/*
1036 * Suited for:
1037 * - EPoX EP-8RDA3+: Socket A + nForce2 Ultra 400 + MCP2
libvb8043812009-10-05 18:46:35 +00001038 */
uweeb26b6e2010-06-07 19:06:26 +00001039static int nvidia_mcp_gpio31_raise(void)
libvb8043812009-10-05 18:46:35 +00001040{
libv6db37e62009-12-03 12:25:34 +00001041 return nvidia_mcp_gpio_set(0x31, 0x01);
libvb8043812009-10-05 18:46:35 +00001042}
libv5ac6e5c2009-10-05 16:07:00 +00001043
uwee15beb92010-08-08 17:01:18 +00001044/*
1045 * Suited for:
mkarcher41c71342011-03-06 12:09:05 +00001046 * - GIGABYTE GA-K8N51GMF: Socket 754 + Geforce 6100 + MCP51
1047 * - GIGABYTE GA-K8N51GMF-9: Socket 939 + Geforce 6100 + MCP51
uwe70640ba2010-09-07 17:52:09 +00001048 */
1049static int nvidia_mcp_gpio3b_raise(void)
1050{
1051 return nvidia_mcp_gpio_set(0x3b, 1);
1052}
1053
1054/*
1055 * Suited for:
stefanct634adc82011-11-02 14:31:18 +00001056 * - Sun Ultra 40 M2: Dual Socket F (1207) + MCP55
1057 */
1058static int board_sun_ultra_40_m2(void)
1059{
1060 int ret;
1061 uint8_t reg;
1062 uint16_t base;
1063 struct pci_dev *dev;
1064
1065 ret = nvidia_mcp_gpio4_lower();
1066 if (ret)
1067 return ret;
1068
1069 dev = pci_dev_find(0x10de, 0x0364); /* NVIDIA MCP55 LPC bridge */
1070 if (!dev) {
1071 msg_perr("\nERROR: NVIDIA MCP55 LPC bridge not found.\n");
1072 return -1;
1073 }
1074
1075 base = pci_read_word(dev, 0xb4); /* some IO BAR? */
1076 if (!base)
1077 return -1;
1078
1079 reg = INB(base + 0x4b);
1080 reg |= 0x10;
1081 OUTB(reg, base + 0x4b);
1082
1083 return 0;
1084}
1085
1086/*
1087 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001088 * - Artec Group DBE61 and DBE62
stepanf778f522008-02-20 11:11:18 +00001089 */
uweeb26b6e2010-06-07 19:06:26 +00001090static int board_artecgroup_dbe6x(void)
stepanf778f522008-02-20 11:11:18 +00001091{
1092#define DBE6x_MSR_DIVIL_BALL_OPTS 0x51400015
uwee15beb92010-08-08 17:01:18 +00001093#define DBE6x_PRI_BOOT_LOC_SHIFT 2
1094#define DBE6x_BOOT_OP_LATCHED_SHIFT 8
1095#define DBE6x_SEC_BOOT_LOC_SHIFT 10
stepanf778f522008-02-20 11:11:18 +00001096#define DBE6x_PRI_BOOT_LOC (3 << DBE6x_PRI_BOOT_LOC_SHIFT)
1097#define DBE6x_BOOT_OP_LATCHED (3 << DBE6x_BOOT_OP_LATCHED_SHIFT)
1098#define DBE6x_SEC_BOOT_LOC (3 << DBE6x_SEC_BOOT_LOC_SHIFT)
uwee15beb92010-08-08 17:01:18 +00001099#define DBE6x_BOOT_LOC_FLASH 2
1100#define DBE6x_BOOT_LOC_FWHUB 3
stepanf778f522008-02-20 11:11:18 +00001101
stepanf251ff82009-08-12 18:25:24 +00001102 msr_t msr;
stepanf778f522008-02-20 11:11:18 +00001103 unsigned long boot_loc;
1104
stepanf251ff82009-08-12 18:25:24 +00001105 /* Geode only has a single core */
1106 if (setup_cpu_msr(0))
stepanf778f522008-02-20 11:11:18 +00001107 return -1;
stepanf778f522008-02-20 11:11:18 +00001108
stepanf251ff82009-08-12 18:25:24 +00001109 msr = rdmsr(DBE6x_MSR_DIVIL_BALL_OPTS);
stepanf778f522008-02-20 11:11:18 +00001110
stepanf251ff82009-08-12 18:25:24 +00001111 if ((msr.lo & (DBE6x_BOOT_OP_LATCHED)) ==
stepanf778f522008-02-20 11:11:18 +00001112 (DBE6x_BOOT_LOC_FWHUB << DBE6x_BOOT_OP_LATCHED_SHIFT))
1113 boot_loc = DBE6x_BOOT_LOC_FWHUB;
1114 else
1115 boot_loc = DBE6x_BOOT_LOC_FLASH;
1116
stepanf251ff82009-08-12 18:25:24 +00001117 msr.lo &= ~(DBE6x_PRI_BOOT_LOC | DBE6x_SEC_BOOT_LOC);
1118 msr.lo |= ((boot_loc << DBE6x_PRI_BOOT_LOC_SHIFT) |
uwefa98ca12008-10-18 21:14:13 +00001119 (boot_loc << DBE6x_SEC_BOOT_LOC_SHIFT));
stepanf778f522008-02-20 11:11:18 +00001120
stepanf251ff82009-08-12 18:25:24 +00001121 wrmsr(DBE6x_MSR_DIVIL_BALL_OPTS, msr);
stepanf778f522008-02-20 11:11:18 +00001122
stepanf251ff82009-08-12 18:25:24 +00001123 cleanup_cpu_msr();
stepanf778f522008-02-20 11:11:18 +00001124
stepanf778f522008-02-20 11:11:18 +00001125 return 0;
1126}
1127
uwee15beb92010-08-08 17:01:18 +00001128/*
stefanctdda0e212011-05-17 13:31:55 +00001129 * Suited for:
uwe8d342eb2011-07-28 08:13:25 +00001130 * - ASUS A8AE-LE (Codename AmberineM; used in Compaq Presario 061)
stefanctdda0e212011-05-17 13:31:55 +00001131 * Datasheet(s) used:
1132 * - AMD document 43009 "AMD SB700/710/750 Register Reference Guide" rev. 1.00
1133 */
1134static int amd_sbxxx_gpio9_raise(void)
1135{
1136 struct pci_dev *dev;
1137 uint32_t reg;
1138
uwe8d342eb2011-07-28 08:13:25 +00001139 dev = pci_dev_find(0x1002, 0x4372); /* AMD SMBus controller */
stefanctdda0e212011-05-17 13:31:55 +00001140 if (!dev) {
1141 msg_perr("\nERROR: AMD SMBus Controller (0x4372) not found.\n");
1142 return -1;
1143 }
1144
1145 reg = pci_read_long(dev, 0xA8); /* GPIO_12_to_4_Cntrl CI_Reg: A8h-ABh */
1146 /* enable output (0: enable, 1: tristate):
1147 GPIO9 output enable is at bit 5 in 0xA9 */
1148 reg &= ~((uint32_t)1<<(8+5));
1149 /* raise:
1150 GPIO9 output register is at bit 5 in 0xA8 */
1151 reg |= (1<<5);
1152 pci_write_long(dev, 0xA8, reg);
1153
1154 return 0;
1155}
1156
1157/*
uwe3a3ab2f2010-03-25 23:18:41 +00001158 * Helper function to raise/drop a given gpo line on Intel PIIX4{,E,M}.
libv8d908612009-12-14 10:41:58 +00001159 */
1160static int intel_piix4_gpo_set(unsigned int gpo, int raise)
1161{
mkarcher681bc022010-02-24 00:00:21 +00001162 unsigned int gpo_byte, gpo_bit;
libv8d908612009-12-14 10:41:58 +00001163 struct pci_dev *dev;
1164 uint32_t tmp, base;
1165
hailfingerb91c08c2011-08-15 19:54:20 +00001166 /* GPO{0,8,27,28,30} are always available. */
1167 static const uint32_t nonmuxed_gpos = 0x58000101;
mkarcher6757a5e2010-08-15 22:35:31 +00001168
1169 static const struct {unsigned int reg, mask, value; } piix4_gpo[] = {
uwe8d342eb2011-07-28 08:13:25 +00001170 {0},
1171 {0xB0, 0x0001, 0x0000}, /* GPO1... */
1172 {0xB0, 0x0001, 0x0000},
1173 {0xB0, 0x0001, 0x0000},
1174 {0xB0, 0x0001, 0x0000},
1175 {0xB0, 0x0001, 0x0000},
1176 {0xB0, 0x0001, 0x0000},
1177 {0xB0, 0x0001, 0x0000}, /* ...GPO7: GENCFG bit 0 */
1178 {0},
1179 {0xB0, 0x0100, 0x0000}, /* GPO9: GENCFG bit 8 */
1180 {0xB0, 0x0200, 0x0000}, /* GPO10: GENCFG bit 9 */
1181 {0xB0, 0x0400, 0x0000}, /* GPO11: GENCFG bit 10 */
1182 {0x4E, 0x0100, 0x0000}, /* GPO12... */
1183 {0x4E, 0x0100, 0x0000},
1184 {0x4E, 0x0100, 0x0000}, /* ...GPO14: XBCS bit 8 */
1185 {0xB2, 0x0002, 0x0002}, /* GPO15... */
1186 {0xB2, 0x0002, 0x0002}, /* ...GPO16: GENCFG bit 17 */
1187 {0xB2, 0x0004, 0x0004}, /* GPO17: GENCFG bit 18 */
1188 {0xB2, 0x0008, 0x0008}, /* GPO18: GENCFG bit 19 */
1189 {0xB2, 0x0010, 0x0010}, /* GPO19: GENCFG bit 20 */
1190 {0xB2, 0x0020, 0x0020}, /* GPO20: GENCFG bit 21 */
1191 {0xB2, 0x0040, 0x0040}, /* GPO21: GENCFG bit 22 */
1192 {0xB2, 0x1000, 0x1000}, /* GPO22... */
1193 {0xB2, 0x1000, 0x1000}, /* ...GPO23: GENCFG bit 28 */
1194 {0xB2, 0x2000, 0x2000}, /* GPO24: GENCFG bit 29 */
1195 {0xB2, 0x4000, 0x4000}, /* GPO25: GENCFG bit 30 */
1196 {0xB2, 0x8000, 0x8000}, /* GPO26: GENCFG bit 31 */
1197 {0},
1198 {0},
1199 {0x4E, 0x0100, 0x0000}, /* ...GPO29: XBCS bit 8 */
1200 {0}
mkarcher6757a5e2010-08-15 22:35:31 +00001201 };
1202
libv8d908612009-12-14 10:41:58 +00001203 dev = pci_dev_find(0x8086, 0x7110); /* Intel PIIX4 ISA bridge */
1204 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +00001205 msg_perr("\nERROR: Intel PIIX4 ISA bridge not found.\n");
libv8d908612009-12-14 10:41:58 +00001206 return -1;
1207 }
1208
uwee15beb92010-08-08 17:01:18 +00001209 /* Sanity check. */
libv8d908612009-12-14 10:41:58 +00001210 if (gpo > 30) {
snelsone42c3802010-05-07 20:09:04 +00001211 msg_perr("\nERROR: Intel PIIX4 has no GPO%d.\n", gpo);
libv8d908612009-12-14 10:41:58 +00001212 return -1;
1213 }
1214
uwe8d342eb2011-07-28 08:13:25 +00001215 if ((((1 << gpo) & nonmuxed_gpos) == 0) &&
hailfingerb91c08c2011-08-15 19:54:20 +00001216 ((pci_read_word(dev, piix4_gpo[gpo].reg) & piix4_gpo[gpo].mask) !=
1217 piix4_gpo[gpo].value)) {
1218 msg_perr("\nERROR: PIIX4 GPO%d not programmed for output.\n", gpo);
uwe8d342eb2011-07-28 08:13:25 +00001219 return -1;
libv8d908612009-12-14 10:41:58 +00001220 }
1221
libv8d908612009-12-14 10:41:58 +00001222 dev = pci_dev_find(0x8086, 0x7113); /* Intel PIIX4 PM */
1223 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +00001224 msg_perr("\nERROR: Intel PIIX4 PM not found.\n");
libv8d908612009-12-14 10:41:58 +00001225 return -1;
1226 }
1227
1228 /* PM IO base */
1229 base = pci_read_long(dev, 0x40) & 0x0000FFC0;
1230
mkarcher681bc022010-02-24 00:00:21 +00001231 gpo_byte = gpo >> 3;
1232 gpo_bit = gpo & 7;
1233 tmp = INB(base + 0x34 + gpo_byte); /* GPO register */
libv8d908612009-12-14 10:41:58 +00001234 if (raise)
mkarcher681bc022010-02-24 00:00:21 +00001235 tmp |= 0x01 << gpo_bit;
libv8d908612009-12-14 10:41:58 +00001236 else
mkarcher681bc022010-02-24 00:00:21 +00001237 tmp &= ~(0x01 << gpo_bit);
1238 OUTB(tmp, base + 0x34 + gpo_byte);
libv8d908612009-12-14 10:41:58 +00001239
1240 return 0;
1241}
1242
uwee15beb92010-08-08 17:01:18 +00001243/*
1244 * Suited for:
mhm4791ef92010-09-01 01:21:34 +00001245 * - ASUS P2B-N
1246 */
1247static int intel_piix4_gpo18_lower(void)
1248{
1249 return intel_piix4_gpo_set(18, 0);
1250}
1251
1252/*
1253 * Suited for:
mhmaac0fda2010-09-13 18:22:36 +00001254 * - MSI MS-6163 v2 (MS-6163 Pro): Intel 440BX + PIIX4E + Winbond W83977EF
1255 */
1256static int intel_piix4_gpo14_raise(void)
1257{
1258 return intel_piix4_gpo_set(14, 1);
1259}
1260
1261/*
1262 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001263 * - EPoX EP-BX3
libv8d908612009-12-14 10:41:58 +00001264 */
mkarcher6757a5e2010-08-15 22:35:31 +00001265static int intel_piix4_gpo22_raise(void)
libv8d908612009-12-14 10:41:58 +00001266{
1267 return intel_piix4_gpo_set(22, 1);
1268}
1269
uwee15beb92010-08-08 17:01:18 +00001270/*
1271 * Suited for:
uwe50d483e2010-09-13 23:00:57 +00001272 * - abit BM6
1273 */
1274static int intel_piix4_gpo26_lower(void)
1275{
1276 return intel_piix4_gpo_set(26, 0);
1277}
1278
1279/*
1280 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001281 * - Intel SE440BX-2
snelsonaa2f3d92010-03-19 22:35:21 +00001282 */
uweeb26b6e2010-06-07 19:06:26 +00001283static int intel_piix4_gpo27_lower(void)
snelsonaa2f3d92010-03-19 22:35:21 +00001284{
uwee15beb92010-08-08 17:01:18 +00001285 return intel_piix4_gpo_set(27, 0);
snelsonaa2f3d92010-03-19 22:35:21 +00001286}
1287
uwee15beb92010-08-08 17:01:18 +00001288/*
mhm4f2a2b62010-10-05 21:32:29 +00001289 * Suited for:
1290 * - Dell OptiPlex GX1
1291 */
1292static int intel_piix4_gpo30_lower(void)
1293{
1294 return intel_piix4_gpo_set(30, 0);
1295}
1296
1297/*
uwe3a3ab2f2010-03-25 23:18:41 +00001298 * Set a GPIO line on a given Intel ICH LPC controller.
uwecc6ecc52008-05-22 21:19:38 +00001299 */
libv5afe85c2009-11-28 18:07:51 +00001300static int intel_ich_gpio_set(int gpio, int raise)
uwecc6ecc52008-05-22 21:19:38 +00001301{
uwe3a3ab2f2010-03-25 23:18:41 +00001302 /* Table mapping the different Intel ICH LPC chipsets. */
libv5afe85c2009-11-28 18:07:51 +00001303 static struct {
1304 uint16_t id;
1305 uint8_t base_reg;
1306 uint32_t bank0;
1307 uint32_t bank1;
1308 uint32_t bank2;
1309 } intel_ich_gpio_table[] = {
1310 {0x2410, 0x58, 0x0FE30000, 0, 0}, /* 82801AA (ICH) */
1311 {0x2420, 0x58, 0x0FE30000, 0, 0}, /* 82801AB (ICH0) */
1312 {0x2440, 0x58, 0x1BFF391B, 0, 0}, /* 82801BA (ICH2) */
1313 {0x244C, 0x58, 0x1A23399B, 0, 0}, /* 82801BAM (ICH2M) */
1314 {0x2450, 0x58, 0x1BFF0000, 0, 0}, /* 82801E (C-ICH) */
1315 {0x2480, 0x58, 0x1BFF0000, 0x00000FFF, 0}, /* 82801CA (ICH3-S) */
1316 {0x248C, 0x58, 0x1A230000, 0x00000FFF, 0}, /* 82801CAM (ICH3-M) */
1317 {0x24C0, 0x58, 0x1BFF0000, 0x00000FFF, 0}, /* 82801DB/DBL (ICH4/ICH4-L) */
1318 {0x24CC, 0x58, 0x1A030000, 0x00000FFF, 0}, /* 82801DBM (ICH4-M) */
1319 {0x24D0, 0x58, 0x1BFF0000, 0x00030305, 0}, /* 82801EB/ER (ICH5/ICH5R) */
1320 {0x2640, 0x48, 0x1BFF0000, 0x00030307, 0}, /* 82801FB/FR (ICH6/ICH6R) */
1321 {0x2641, 0x48, 0x1BFF0000, 0x00030307, 0}, /* 82801FBM (ICH6M) */
1322 {0x27B8, 0x48, 0xFFFFFFFF, 0x000300FF, 0}, /* 82801GB/GR (ICH7 Family) */
1323 {0x27B9, 0x48, 0xFFEBFFFE, 0x000300FE, 0}, /* 82801GBM (ICH7-M) */
1324 {0x27BD, 0x48, 0xFFEBFFFE, 0x000300FE, 0}, /* 82801GHM (ICH7-M DH) */
1325 {0x2810, 0x48, 0xFFFFFFFF, 0x00FF0FFF, 0}, /* 82801HB/HR (ICH8/R) */
1326 {0x2811, 0x48, 0xFFFFFFFF, 0x00FF0FFF, 0}, /* 82801HBM (ICH8M-E) */
1327 {0x2812, 0x48, 0xFFFFFFFF, 0x00FF0FFF, 0}, /* 82801HH (ICH8DH) */
1328 {0x2814, 0x48, 0xFFFFFFFF, 0x00FF0FFF, 0}, /* 82801HO (ICH8DO) */
1329 {0x2815, 0x48, 0xFFFFFFFF, 0x00FF0FFF, 0}, /* 82801HEM (ICH8M) */
1330 {0x2912, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IH (ICH9DH) */
1331 {0x2914, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IO (ICH9DO) */
1332 {0x2916, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IR (ICH9R) */
1333 {0x2917, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IEM (ICH9M-E) */
1334 {0x2918, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IB (ICH9) */
1335 {0x2919, 0x48, 0xFFFFFFFF, 0x00FFFFFF, 0}, /* 82801IBM (ICH9M) */
1336 {0x3A14, 0x48, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000100}, /* 82801JDO (ICH10DO) */
1337 {0x3A16, 0x48, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000100}, /* 82801JIR (ICH10R) */
1338 {0x3A18, 0x48, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000100}, /* 82801JIB (ICH10) */
1339 {0x3A1A, 0x48, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000100}, /* 82801JD (ICH10D) */
1340 {0, 0, 0, 0, 0} /* end marker */
1341 };
uwecc6ecc52008-05-22 21:19:38 +00001342
libv5afe85c2009-11-28 18:07:51 +00001343 struct pci_dev *dev;
1344 uint16_t base;
1345 uint32_t tmp;
1346 int i, allowed;
1347
1348 /* First, look for a known LPC bridge */
hailfingerd9bfbe22009-12-14 04:24:42 +00001349 for (dev = pacc->devices; dev; dev = dev->next) {
hailfinger2b8fc0b2010-05-21 23:00:56 +00001350 uint16_t device_class;
1351 /* libpci before version 2.2.4 does not store class info. */
1352 device_class = pci_read_word(dev, PCI_CLASS_DEVICE);
libv5afe85c2009-11-28 18:07:51 +00001353 if ((dev->vendor_id == 0x8086) &&
uwe8d342eb2011-07-28 08:13:25 +00001354 (device_class == 0x0601)) { /* ISA bridge */
libv5afe85c2009-11-28 18:07:51 +00001355 /* Is this device in our list? */
1356 for (i = 0; intel_ich_gpio_table[i].id; i++)
1357 if (dev->device_id == intel_ich_gpio_table[i].id)
1358 break;
1359
1360 if (intel_ich_gpio_table[i].id)
1361 break;
1362 }
hailfingerd9bfbe22009-12-14 04:24:42 +00001363 }
libv5afe85c2009-11-28 18:07:51 +00001364
uwecc6ecc52008-05-22 21:19:38 +00001365 if (!dev) {
uwe8d342eb2011-07-28 08:13:25 +00001366 msg_perr("\nERROR: No known Intel LPC bridge found.\n");
uwecc6ecc52008-05-22 21:19:38 +00001367 return -1;
1368 }
1369
uwee15beb92010-08-08 17:01:18 +00001370 /*
1371 * According to the datasheets, all Intel ICHs have the GPIO bar 5:1
1372 * strapped to zero. From some mobile ICH9 version on, this becomes
1373 * 6:1. The mask below catches all.
1374 */
libv5afe85c2009-11-28 18:07:51 +00001375 base = pci_read_word(dev, intel_ich_gpio_table[i].base_reg) & 0xFFC0;
uwecc6ecc52008-05-22 21:19:38 +00001376
uwee15beb92010-08-08 17:01:18 +00001377 /* Check whether the line is allowed. */
libv5afe85c2009-11-28 18:07:51 +00001378 if (gpio < 32)
1379 allowed = (intel_ich_gpio_table[i].bank0 >> gpio) & 0x01;
1380 else if (gpio < 64)
1381 allowed = (intel_ich_gpio_table[i].bank1 >> (gpio - 32)) & 0x01;
1382 else
1383 allowed = (intel_ich_gpio_table[i].bank2 >> (gpio - 64)) & 0x01;
1384
1385 if (!allowed) {
uwe8d342eb2011-07-28 08:13:25 +00001386 msg_perr("\nERROR: This Intel LPC bridge does not allow"
1387 " setting GPIO%02d\n", gpio);
libv5afe85c2009-11-28 18:07:51 +00001388 return -1;
1389 }
1390
uwe8d342eb2011-07-28 08:13:25 +00001391 msg_pdbg("\nIntel ICH LPC bridge: %sing GPIO%02d.\n",
1392 raise ? "Rais" : "Dropp", gpio);
libv5afe85c2009-11-28 18:07:51 +00001393
1394 if (gpio < 32) {
uwee15beb92010-08-08 17:01:18 +00001395 /* Set line to GPIO. */
libv5afe85c2009-11-28 18:07:51 +00001396 tmp = INL(base);
1397 /* ICH/ICH0 multiplexes 27/28 on the line set. */
1398 if ((gpio == 28) &&
1399 ((dev->device_id == 0x2410) || (dev->device_id == 0x2420)))
1400 tmp |= 1 << 27;
1401 else
1402 tmp |= 1 << gpio;
1403 OUTL(tmp, base);
1404
1405 /* As soon as we are talking to ICH8 and above, this register
1406 decides whether we can set the gpio or not. */
1407 if (dev->device_id > 0x2800) {
1408 tmp = INL(base);
1409 if (!(tmp & (1 << gpio))) {
uwe8d342eb2011-07-28 08:13:25 +00001410 msg_perr("\nERROR: This Intel LPC bridge"
libv5afe85c2009-11-28 18:07:51 +00001411 " does not allow setting GPIO%02d\n",
1412 gpio);
1413 return -1;
1414 }
1415 }
1416
uwee15beb92010-08-08 17:01:18 +00001417 /* Set GPIO to OUTPUT. */
libv5afe85c2009-11-28 18:07:51 +00001418 tmp = INL(base + 0x04);
1419 tmp &= ~(1 << gpio);
1420 OUTL(tmp, base + 0x04);
1421
uwee15beb92010-08-08 17:01:18 +00001422 /* Raise GPIO line. */
libv5afe85c2009-11-28 18:07:51 +00001423 tmp = INL(base + 0x0C);
1424 if (raise)
1425 tmp |= 1 << gpio;
1426 else
1427 tmp &= ~(1 << gpio);
1428 OUTL(tmp, base + 0x0C);
1429 } else if (gpio < 64) {
1430 gpio -= 32;
1431
uwee15beb92010-08-08 17:01:18 +00001432 /* Set line to GPIO. */
libv5afe85c2009-11-28 18:07:51 +00001433 tmp = INL(base + 0x30);
1434 tmp |= 1 << gpio;
1435 OUTL(tmp, base + 0x30);
1436
1437 /* As soon as we are talking to ICH8 and above, this register
1438 decides whether we can set the gpio or not. */
1439 if (dev->device_id > 0x2800) {
1440 tmp = INL(base + 30);
1441 if (!(tmp & (1 << gpio))) {
uwe8d342eb2011-07-28 08:13:25 +00001442 msg_perr("\nERROR: This Intel LPC bridge"
libv5afe85c2009-11-28 18:07:51 +00001443 " does not allow setting GPIO%02d\n",
1444 gpio + 32);
1445 return -1;
1446 }
1447 }
1448
uwee15beb92010-08-08 17:01:18 +00001449 /* Set GPIO to OUTPUT. */
libv5afe85c2009-11-28 18:07:51 +00001450 tmp = INL(base + 0x34);
1451 tmp &= ~(1 << gpio);
1452 OUTL(tmp, base + 0x34);
1453
uwee15beb92010-08-08 17:01:18 +00001454 /* Raise GPIO line. */
libv5afe85c2009-11-28 18:07:51 +00001455 tmp = INL(base + 0x38);
1456 if (raise)
1457 tmp |= 1 << gpio;
1458 else
1459 tmp &= ~(1 << gpio);
1460 OUTL(tmp, base + 0x38);
1461 } else {
1462 gpio -= 64;
1463
uwee15beb92010-08-08 17:01:18 +00001464 /* Set line to GPIO. */
libv5afe85c2009-11-28 18:07:51 +00001465 tmp = INL(base + 0x40);
1466 tmp |= 1 << gpio;
1467 OUTL(tmp, base + 0x40);
1468
1469 tmp = INL(base + 40);
1470 if (!(tmp & (1 << gpio))) {
uwe8d342eb2011-07-28 08:13:25 +00001471 msg_perr("\nERROR: This Intel LPC bridge does "
libv5afe85c2009-11-28 18:07:51 +00001472 "not allow setting GPIO%02d\n", gpio + 64);
1473 return -1;
1474 }
1475
uwee15beb92010-08-08 17:01:18 +00001476 /* Set GPIO to OUTPUT. */
libv5afe85c2009-11-28 18:07:51 +00001477 tmp = INL(base + 0x44);
1478 tmp &= ~(1 << gpio);
1479 OUTL(tmp, base + 0x44);
1480
uwee15beb92010-08-08 17:01:18 +00001481 /* Raise GPIO line. */
libv5afe85c2009-11-28 18:07:51 +00001482 tmp = INL(base + 0x48);
1483 if (raise)
1484 tmp |= 1 << gpio;
1485 else
1486 tmp &= ~(1 << gpio);
1487 OUTL(tmp, base + 0x48);
1488 }
uwecc6ecc52008-05-22 21:19:38 +00001489
1490 return 0;
1491}
1492
uwee15beb92010-08-08 17:01:18 +00001493/*
1494 * Suited for:
1495 * - abit IP35: Intel P35 + ICH9R
1496 * - abit IP35 Pro: Intel P35 + ICH9R
stefanct275b2532011-08-11 04:21:34 +00001497 * - ASUS P5LD2
uwecc6ecc52008-05-22 21:19:38 +00001498 */
uweeb26b6e2010-06-07 19:06:26 +00001499static int intel_ich_gpio16_raise(void)
uwecc6ecc52008-05-22 21:19:38 +00001500{
libv5afe85c2009-11-28 18:07:51 +00001501 return intel_ich_gpio_set(16, 1);
uwecc6ecc52008-05-22 21:19:38 +00001502}
1503
uwee15beb92010-08-08 17:01:18 +00001504/*
1505 * Suited for:
1506 * - HP Puffer2-UL8E (ASUS PTGD-LA OEM): LGA775 + 915 + ICH6
mkarcher5f3a7e12010-07-24 11:14:37 +00001507 */
1508static int intel_ich_gpio18_raise(void)
1509{
1510 return intel_ich_gpio_set(18, 1);
1511}
1512
uwee15beb92010-08-08 17:01:18 +00001513/*
1514 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001515 * - MSI MS-7046: LGA775 + 915P + ICH6
hailfinger3fa8d842009-09-23 02:05:12 +00001516 */
uweeb26b6e2010-06-07 19:06:26 +00001517static int intel_ich_gpio19_raise(void)
hailfinger3fa8d842009-09-23 02:05:12 +00001518{
libv5afe85c2009-11-28 18:07:51 +00001519 return intel_ich_gpio_set(19, 1);
hailfinger3fa8d842009-09-23 02:05:12 +00001520}
1521
uwee15beb92010-08-08 17:01:18 +00001522/*
libvdc84fa32009-11-28 18:26:21 +00001523 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001524 * - ASUS P4B266LM (Sony Vaio PCV-RX650): socket478 + 845D + ICH2
1525 * - ASUS P4C800-E Deluxe: socket478 + 875P + ICH5
mkarcherd8c4e142010-09-10 14:54:18 +00001526 * - ASUS P4P800: Intel socket478 + 865PE + ICH5R
uwee15beb92010-08-08 17:01:18 +00001527 * - ASUS P4P800-E Deluxe: Intel socket478 + 865PE + ICH5R
hailfinger4fb0ef72011-03-06 22:52:55 +00001528 * - ASUS P4P800-VM: Intel socket478 + 865PE + ICH5R
mkarcher15ea7eb2010-09-10 14:46:46 +00001529 * - ASUS P5GD1 Pro: Intel LGA 775 + 915P + ICH6R
stefanctdbca6752011-08-11 05:47:32 +00001530 * - ASUS P5GD2 Premium: Intel LGA775 + 915G + ICH6R
hailfinger45434bb2010-09-13 14:02:22 +00001531 * - ASUS P5GDC Deluxe: Intel socket775 + 915P + ICH6R
uwee15beb92010-08-08 17:01:18 +00001532 * - ASUS P5PE-VM: Intel LGA775 + 865G + ICH5
1533 * - Samsung Polaris 32: socket478 + 865P + ICH5
stuge81664dd2009-02-02 22:55:26 +00001534 */
uweeb26b6e2010-06-07 19:06:26 +00001535static int intel_ich_gpio21_raise(void)
stuge81664dd2009-02-02 22:55:26 +00001536{
libv5afe85c2009-11-28 18:07:51 +00001537 return intel_ich_gpio_set(21, 1);
stuge81664dd2009-02-02 22:55:26 +00001538}
1539
uwee15beb92010-08-08 17:01:18 +00001540/*
mkarcher11f8f3c2010-03-07 16:32:32 +00001541 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001542 * - ASUS P4B266: socket478 + Intel 845D + ICH2
uwe3a3ab2f2010-03-25 23:18:41 +00001543 * - ASUS P4B533-E: socket478 + 845E + ICH4
1544 * - ASUS P4B-MX variant in HP Vectra VL420 SFF: socket478 + 845D + ICH2
Rudolf Marek1d455e22016-08-04 18:14:47 -07001545 * - TriGem Anaheim-3: socket370 + Intel 810 + ICH
libv5afe85c2009-11-28 18:07:51 +00001546 */
uweeb26b6e2010-06-07 19:06:26 +00001547static int intel_ich_gpio22_raise(void)
libv5afe85c2009-11-28 18:07:51 +00001548{
1549 return intel_ich_gpio_set(22, 1);
1550}
1551
uwee15beb92010-08-08 17:01:18 +00001552/*
1553 * Suited for:
stefanctdfd58832011-07-25 20:38:52 +00001554 * - ASUS A8Jm (laptop): Intel 945 + ICH7
stefanct950bded2011-08-25 14:06:50 +00001555 * - ASUS P5LP-LE used in ...
1556 * - HP Media Center m7270.fr Desktop PC as "Lithium-UL8E"
1557 * - Epson Endeavor MT7700
stefanctdfd58832011-07-25 20:38:52 +00001558 */
1559static int intel_ich_gpio34_raise(void)
1560{
1561 return intel_ich_gpio_set(34, 1);
1562}
1563
1564/*
1565 * Suited for:
Carl-Daniel Hailfinger289f4e92016-08-04 15:48:57 -07001566 * - AOpen i945GMx-VFX: Intel 945GM + ICH7-M used in ...
Stefan Tauner718d1eb2016-08-18 18:00:53 -07001567 * - FSC ESPRIMO Q5010 (SMBIOS: D2544-B1)
Carl-Daniel Hailfinger289f4e92016-08-04 15:48:57 -07001568 */
1569static int intel_ich_gpio38_raise(void)
1570{
1571 return intel_ich_gpio_set(38, 1);
1572}
1573
1574/*
1575 * Suited for:
stefanct58c2d772011-07-09 19:46:53 +00001576 * - ASUS M6Ne (laptop): socket 479M (guessed) + Intel 855PM + ICH4-M
1577 */
1578static int intel_ich_gpio43_raise(void)
1579{
1580 return intel_ich_gpio_set(43, 1);
1581}
1582
1583/*
1584 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001585 * - HP Vectra VL400: 815 + ICH + PC87360
mkarcherb507b7b2010-02-27 18:35:54 +00001586 */
uweeb26b6e2010-06-07 19:06:26 +00001587static int board_hp_vl400(void)
mkarcherb507b7b2010-02-27 18:35:54 +00001588{
uwee15beb92010-08-08 17:01:18 +00001589 int ret;
1590 ret = intel_ich_gpio_set(25, 1); /* Master write enable ? */
1591 if (!ret)
mkarcherfc0a1e12011-03-06 12:07:19 +00001592 ret = pc8736x_gpio_set(PC87360_ID, 0x09, 1); /* #WP ? */
uwee15beb92010-08-08 17:01:18 +00001593 if (!ret)
mkarcherfc0a1e12011-03-06 12:07:19 +00001594 ret = pc8736x_gpio_set(PC87360_ID, 0x27, 1); /* #TBL */
1595 return ret;
1596}
1597
1598/*
1599 * Suited for:
1600 * - HP e-Vectra P2706T: 810E + ICH + PC87364
1601 */
1602static int board_hp_p2706t(void)
1603{
1604 int ret;
1605 ret = pc8736x_gpio_set(PC87364_ID, 0x25, 1);
1606 if (!ret)
1607 ret = pc8736x_gpio_set(PC87364_ID, 0x26, 1);
uwee15beb92010-08-08 17:01:18 +00001608 return ret;
mkarcherb507b7b2010-02-27 18:35:54 +00001609}
1610
uwee15beb92010-08-08 17:01:18 +00001611/*
libve42a7c62009-11-28 18:16:31 +00001612 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001613 * - Dell PowerEdge 1850: Intel PPGA604 + E7520 + ICH5R
1614 * - ASRock P4i65GV: Intel Socket478 + 865GV + ICH5R
1615 * - ASRock 775i65G: Intel LGA 775 + 865G + ICH5
uwed6da7d52010-12-02 21:57:42 +00001616 * - MSI MS-6391 (845 Pro4): Intel Socket478 + 845 + ICH2
libv5afe85c2009-11-28 18:07:51 +00001617 */
uweeb26b6e2010-06-07 19:06:26 +00001618static int intel_ich_gpio23_raise(void)
libv5afe85c2009-11-28 18:07:51 +00001619{
1620 return intel_ich_gpio_set(23, 1);
1621}
1622
uwee15beb92010-08-08 17:01:18 +00001623/*
1624 * Suited for:
mkarcher0ea0ef52010-10-05 17:29:35 +00001625 * - GIGABYTE GA-6IEM: Intel Socket370 + i815 + ICH2
uwee15beb92010-08-08 17:01:18 +00001626 * - GIGABYTE GA-8IRML: Intel Socket478 + i845 + ICH2
mkarcher31a4bd42010-07-24 22:27:29 +00001627 */
1628static int intel_ich_gpio25_raise(void)
1629{
1630 return intel_ich_gpio_set(25, 1);
1631}
1632
uwee15beb92010-08-08 17:01:18 +00001633/*
1634 * Suited for:
1635 * - IBASE MB899: i945GM + ICH7
snelson4e249922010-03-19 23:01:34 +00001636 */
uweeb26b6e2010-06-07 19:06:26 +00001637static int intel_ich_gpio26_raise(void)
snelson4e249922010-03-19 23:01:34 +00001638{
1639 return intel_ich_gpio_set(26, 1);
1640}
1641
uwee15beb92010-08-08 17:01:18 +00001642/*
1643 * Suited for:
1644 * - P4SD-LA (HP OEM): i865 + ICH5
stefanct2ecec882011-06-13 16:59:01 +00001645 * - GIGABYTE GA-8IP775: 865P + ICH5
mkarcherf4016092010-08-13 12:49:01 +00001646 * - GIGABYTE GA-8PE667 Ultra 2: socket 478 + i845PE + ICH4
hailfinger344569c2011-06-09 20:59:30 +00001647 * - MSI MS-6788-40 (aka 848P Neo-V)
mkarcher0b183572010-07-24 11:03:48 +00001648 */
hailfinger531e79c2010-07-24 18:47:45 +00001649static int intel_ich_gpio32_raise(void)
mkarcher0b183572010-07-24 11:03:48 +00001650{
1651 return intel_ich_gpio_set(32, 1);
1652}
1653
uwee15beb92010-08-08 17:01:18 +00001654/*
1655 * Suited for:
stefanctf1c118f2011-05-18 01:32:16 +00001656 * - AOpen i975Xa-YDG: i975X + ICH7 + W83627EHF
1657 */
1658static int board_aopen_i975xa_ydg(void)
1659{
1660 int ret;
1661
uwe8d342eb2011-07-28 08:13:25 +00001662 /* Vendor BIOS ends up in LDN6... maybe the board enable is wrong,
stefanctf1c118f2011-05-18 01:32:16 +00001663 * or perhaps it's not needed at all?
uwe8d342eb2011-07-28 08:13:25 +00001664 * The regs it tries to touch are 0xF0, 0xF1, 0xF2 which means if it
1665 * were in the right LDN, it would have to be GPIO1 or GPIO3.
stefanctf1c118f2011-05-18 01:32:16 +00001666 */
1667/*
1668 ret = winbond_gpio_set(0x2e, WINBOND_W83627EHF_ID, x, 0)
1669 if (!ret)
1670*/
1671 ret = intel_ich_gpio_set(33, 1);
1672
1673 return ret;
1674}
1675
1676/*
1677 * Suited for:
uwee15beb92010-08-08 17:01:18 +00001678 * - Acorp 6A815EPD: socket 370 + intel 815 + ICH2
libv5afe85c2009-11-28 18:07:51 +00001679 */
uweeb26b6e2010-06-07 19:06:26 +00001680static int board_acorp_6a815epd(void)
libv5afe85c2009-11-28 18:07:51 +00001681{
1682 int ret;
1683
1684 /* Lower Blocks Lock -- pin 7 of PLCC32 */
1685 ret = intel_ich_gpio_set(22, 1);
1686 if (!ret) /* Top Block Lock -- pin 8 of PLCC32 */
1687 ret = intel_ich_gpio_set(23, 1);
1688
1689 return ret;
1690}
1691
uwee15beb92010-08-08 17:01:18 +00001692/*
1693 * Suited for:
1694 * - Kontron 986LCD-M: Socket478 + 915GM + ICH7R
libv5afe85c2009-11-28 18:07:51 +00001695 */
uweeb26b6e2010-06-07 19:06:26 +00001696static int board_kontron_986lcd_m(void)
stepanb8361b92008-03-17 22:59:40 +00001697{
libv5afe85c2009-11-28 18:07:51 +00001698 int ret;
stepanb8361b92008-03-17 22:59:40 +00001699
libv5afe85c2009-11-28 18:07:51 +00001700 ret = intel_ich_gpio_set(34, 1); /* #TBL */
1701 if (!ret)
1702 ret = intel_ich_gpio_set(35, 1); /* #WP */
stepanb8361b92008-03-17 22:59:40 +00001703
libv5afe85c2009-11-28 18:07:51 +00001704 return ret;
stepanb8361b92008-03-17 22:59:40 +00001705}
1706
uwee15beb92010-08-08 17:01:18 +00001707/*
1708 * Suited for:
1709 * - Soyo SY-7VCA: Pro133A + VT82C686
libv88cd3d22009-06-17 14:43:24 +00001710 */
snelsonef86df92010-03-19 22:49:09 +00001711static int via_apollo_gpo_set(int gpio, int raise)
libv88cd3d22009-06-17 14:43:24 +00001712{
snelsonef86df92010-03-19 22:49:09 +00001713 struct pci_dev *dev;
uwe8d342eb2011-07-28 08:13:25 +00001714 uint32_t base, tmp;
libv88cd3d22009-06-17 14:43:24 +00001715
uwe8d342eb2011-07-28 08:13:25 +00001716 /* VT82C686 power management */
libv88cd3d22009-06-17 14:43:24 +00001717 dev = pci_dev_find(0x1106, 0x3057);
1718 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +00001719 msg_perr("\nERROR: VT82C686 PM device not found.\n");
libv88cd3d22009-06-17 14:43:24 +00001720 return -1;
1721 }
1722
snelsone42c3802010-05-07 20:09:04 +00001723 msg_pdbg("\nVIA Apollo ACPI: %sing GPIO%02d.\n",
uwe8d342eb2011-07-28 08:13:25 +00001724 raise ? "Rais" : "Dropp", gpio);
snelsonef86df92010-03-19 22:49:09 +00001725
uwe8d342eb2011-07-28 08:13:25 +00001726 /* Select GPO function on multiplexed pins. */
libv88cd3d22009-06-17 14:43:24 +00001727 tmp = pci_read_byte(dev, 0x54);
uwe8d342eb2011-07-28 08:13:25 +00001728 switch (gpio) {
1729 case 0:
1730 tmp &= ~0x03;
1731 break;
1732 case 1:
1733 tmp |= 0x04;
1734 break;
1735 case 2:
1736 tmp |= 0x08;
1737 break;
1738 case 3:
1739 tmp |= 0x10;
1740 break;
snelsonef86df92010-03-19 22:49:09 +00001741 }
libv88cd3d22009-06-17 14:43:24 +00001742 pci_write_byte(dev, 0x54, tmp);
1743
1744 /* PM IO base */
1745 base = pci_read_long(dev, 0x48) & 0x0000FF00;
1746
1747 /* Drop GPO0 */
snelsonef86df92010-03-19 22:49:09 +00001748 tmp = INL(base + 0x4C);
1749 if (raise)
1750 tmp |= 1U << gpio;
1751 else
1752 tmp &= ~(1U << gpio);
1753 OUTL(tmp, base + 0x4C);
libv88cd3d22009-06-17 14:43:24 +00001754
1755 return 0;
1756}
1757
uwee15beb92010-08-08 17:01:18 +00001758/*
1759 * Suited for:
1760 * - abit VT6X4: Pro133x + VT82C686A
mkarchere68b8152010-08-15 22:43:23 +00001761 * - abit VA6: Pro133x + VT82C686A
snelsone52df7d2010-03-19 22:30:49 +00001762 */
uweeb26b6e2010-06-07 19:06:26 +00001763static int via_apollo_gpo4_lower(void)
snelsone52df7d2010-03-19 22:30:49 +00001764{
1765 return via_apollo_gpo_set(4, 0);
1766}
1767
uwee15beb92010-08-08 17:01:18 +00001768/*
1769 * Suited for:
1770 * - Soyo SY-7VCA: Pro133A + VT82C686
snelsonef86df92010-03-19 22:49:09 +00001771 */
uweeb26b6e2010-06-07 19:06:26 +00001772static int via_apollo_gpo0_lower(void)
snelsonef86df92010-03-19 22:49:09 +00001773{
1774 return via_apollo_gpo_set(0, 0);
1775}
1776
uwee15beb92010-08-08 17:01:18 +00001777/*
mkarcher2b630cf2011-07-25 17:25:24 +00001778 * Enable some GPIO pin on SiS southbridge and enables SIO flash writes.
uwee15beb92010-08-08 17:01:18 +00001779 *
1780 * Suited for:
1781 * - MSI 651M-L: SiS651 / SiS962
mkarcher2b630cf2011-07-25 17:25:24 +00001782 * - GIGABYTE GA-8SIMLH
mkarchercd460642010-01-09 17:36:06 +00001783 */
mkarcher2b630cf2011-07-25 17:25:24 +00001784static int sis_gpio0_raise_and_w836xx_memw(void)
mkarchercd460642010-01-09 17:36:06 +00001785{
uwee15beb92010-08-08 17:01:18 +00001786 struct pci_dev *dev;
uwef6f94d42010-03-13 17:28:29 +00001787 uint16_t base, temp;
mkarchercd460642010-01-09 17:36:06 +00001788
1789 dev = pci_dev_find(0x1039, 0x0962);
1790 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +00001791 msg_perr("Expected south bridge not found\n");
mkarchercd460642010-01-09 17:36:06 +00001792 return 1;
1793 }
1794
mkarchercd460642010-01-09 17:36:06 +00001795 base = pci_read_word(dev, 0x74);
1796 temp = INW(base + 0x68);
1797 temp &= ~(1 << 0); /* Make pin output? */
mkarcherc9602fb2010-01-09 23:31:13 +00001798 OUTW(temp, base + 0x68);
mkarchercd460642010-01-09 17:36:06 +00001799
1800 temp = INW(base + 0x64);
1801 temp |= (1 << 0); /* Raise output? */
1802 OUTW(temp, base + 0x64);
1803
1804 w836xx_memw_enable(0x2E);
1805
1806 return 0;
1807}
1808
uwee15beb92010-08-08 17:01:18 +00001809/*
libv5bcbdea2009-06-19 13:00:24 +00001810 * Find the runtime registers of an SMSC Super I/O, after verifying its
1811 * chip ID.
1812 *
1813 * Returns the base port of the runtime register block, or 0 on error.
1814 */
1815static uint16_t smsc_find_runtime(uint16_t sio_port, uint16_t chip_id,
1816 uint8_t logical_device)
1817{
1818 uint16_t rt_port = 0;
1819
1820 /* Verify the chip ID. */
uwe619a15a2009-06-28 23:26:37 +00001821 OUTB(0x55, sio_port); /* Enable configuration. */
libv5bcbdea2009-06-19 13:00:24 +00001822 if (sio_read(sio_port, 0x20) != chip_id) {
snelsone42c3802010-05-07 20:09:04 +00001823 msg_perr("\nERROR: SMSC Super I/O not found.\n");
libv5bcbdea2009-06-19 13:00:24 +00001824 goto out;
1825 }
1826
1827 /* If the runtime block is active, get its address. */
1828 sio_write(sio_port, 0x07, logical_device);
1829 if (sio_read(sio_port, 0x30) & 1) {
1830 rt_port = (sio_read(sio_port, 0x60) << 8)
1831 | sio_read(sio_port, 0x61);
1832 }
1833
1834 if (rt_port == 0) {
snelsone42c3802010-05-07 20:09:04 +00001835 msg_perr("\nERROR: "
libv5bcbdea2009-06-19 13:00:24 +00001836 "Super I/O runtime interface not available.\n");
1837 }
1838out:
uwe619a15a2009-06-28 23:26:37 +00001839 OUTB(0xaa, sio_port); /* Disable configuration. */
libv5bcbdea2009-06-19 13:00:24 +00001840 return rt_port;
1841}
1842
uwee15beb92010-08-08 17:01:18 +00001843/*
1844 * Disable write protection on the Mitac 6513WU. WP# on the FWH is
libv5bcbdea2009-06-19 13:00:24 +00001845 * connected to GP30 on the Super I/O, and TBL# is always high.
1846 */
uweeb26b6e2010-06-07 19:06:26 +00001847static int board_mitac_6513wu(void)
libv5bcbdea2009-06-19 13:00:24 +00001848{
1849 struct pci_dev *dev;
1850 uint16_t rt_port;
1851 uint8_t val;
1852
1853 dev = pci_dev_find(0x8086, 0x2410); /* Intel 82801AA ISA bridge */
1854 if (!dev) {
snelsone42c3802010-05-07 20:09:04 +00001855 msg_perr("\nERROR: Intel 82801AA ISA bridge not found.\n");
libv5bcbdea2009-06-19 13:00:24 +00001856 return -1;
1857 }
1858
uwe619a15a2009-06-28 23:26:37 +00001859 rt_port = smsc_find_runtime(0x4e, 0x54 /* LPC47U33x */, 0xa);
libv5bcbdea2009-06-19 13:00:24 +00001860 if (rt_port == 0)
1861 return -1;
1862
1863 /* Configure the GPIO pin. */
1864 val = INB(rt_port + 0x33); /* GP30 config */
uwe619a15a2009-06-28 23:26:37 +00001865 val &= ~0x87; /* Output, non-inverted, GPIO, push/pull */
libv5bcbdea2009-06-19 13:00:24 +00001866 OUTB(val, rt_port + 0x33);
1867
1868 /* Disable write protection. */
1869 val = INB(rt_port + 0x4d); /* GP3 values */
uwe619a15a2009-06-28 23:26:37 +00001870 val |= 0x01; /* Set GP30 high. */
libv5bcbdea2009-06-19 13:00:24 +00001871 OUTB(val, rt_port + 0x4d);
1872
1873 return 0;
1874}
1875
uwee15beb92010-08-08 17:01:18 +00001876/*
1877 * Suited for:
stefanctcfc2c392011-10-21 13:20:11 +00001878 * - abit AV8: Socket939 + K8T800Pro + VT8237
1879 */
1880static int board_abit_av8(void)
1881{
1882 uint8_t val;
1883
1884 /* Raise GPO pins GP22 & GP23 */
1885 val = INB(0x404E);
1886 val |= 0xC0;
1887 OUTB(val, 0x404E);
1888
1889 return 0;
1890}
1891
1892/*
1893 * Suited for:
uwe5b4dd552010-09-14 23:20:35 +00001894 * - ASUS A7V333: VIA KT333 + VT8233A + IT8703F
uwee15beb92010-08-08 17:01:18 +00001895 * - ASUS A7V8X: VIA KT400 + VT8235 + IT8703F
libv1569a562009-07-13 12:40:17 +00001896 */
uwe5b4dd552010-09-14 23:20:35 +00001897static int it8703f_gpio51_raise(void)
libv1569a562009-07-13 12:40:17 +00001898{
1899 uint16_t id, base;
1900 uint8_t tmp;
1901
uwee15beb92010-08-08 17:01:18 +00001902 /* Find the IT8703F. */
libv1569a562009-07-13 12:40:17 +00001903 w836xx_ext_enter(0x2E);
1904 id = (sio_read(0x2E, 0x20) << 8) | sio_read(0x2E, 0x21);
1905 w836xx_ext_leave(0x2E);
1906
1907 if (id != 0x8701) {
snelsone42c3802010-05-07 20:09:04 +00001908 msg_perr("\nERROR: IT8703F Super I/O not found.\n");
libv1569a562009-07-13 12:40:17 +00001909 return -1;
1910 }
1911
uwee15beb92010-08-08 17:01:18 +00001912 /* Get the GP567 I/O base. */
libv1569a562009-07-13 12:40:17 +00001913 w836xx_ext_enter(0x2E);
1914 sio_write(0x2E, 0x07, 0x0C);
1915 base = (sio_read(0x2E, 0x60) << 8) | sio_read(0x2E, 0x61);
1916 w836xx_ext_leave(0x2E);
1917
1918 if (!base) {
snelsone42c3802010-05-07 20:09:04 +00001919 msg_perr("\nERROR: Failed to read IT8703F Super I/O GPIO"
libv1569a562009-07-13 12:40:17 +00001920 " Base.\n");
1921 return -1;
1922 }
1923
1924 /* Raise GP51. */
1925 tmp = INB(base);
1926 tmp |= 0x02;
1927 OUTB(tmp, base);
1928
1929 return 0;
1930}
1931
libv9c4d2b22009-09-01 21:22:23 +00001932/*
stefanct54a39ee2011-11-14 13:00:12 +00001933 * General routine for raising/dropping GPIO lines on the ITE IT87xx.
libv9c4d2b22009-09-01 21:22:23 +00001934 */
stefanct54a39ee2011-11-14 13:00:12 +00001935static int it87_gpio_set(unsigned int gpio, int raise)
libv9c4d2b22009-09-01 21:22:23 +00001936{
stefanct54a39ee2011-11-14 13:00:12 +00001937 int allowed, sio;
libv9c4d2b22009-09-01 21:22:23 +00001938 unsigned int port;
stefanct54a39ee2011-11-14 13:00:12 +00001939 uint16_t base, sioport;
libv9c4d2b22009-09-01 21:22:23 +00001940 uint8_t tmp;
1941
stefanct54a39ee2011-11-14 13:00:12 +00001942 /* IT87 GPIO configuration table */
1943 static const struct it87cfg {
1944 uint16_t id;
1945 uint8_t base_reg;
1946 uint32_t bank0;
1947 uint32_t bank1;
1948 uint32_t bank2;
1949 } it87_gpio_table[] = {
1950 {0x8712, 0x62, 0xCFF3FC00, 0x00FCFF3F, 0},
1951 {0x8718, 0x62, 0xCFF37C00, 0xF3FCDF3F, 0x0000000F},
1952 {0, 0, 0, 0, 0} /* end marker */
1953 };
1954 const struct it87cfg *cfg = NULL;
libv9c4d2b22009-09-01 21:22:23 +00001955
stefanct54a39ee2011-11-14 13:00:12 +00001956 /* Find the Super I/O in the probed list */
1957 for (sio = 0; sio < superio_count; sio++) {
1958 int i;
1959 if (superios[sio].vendor != SUPERIO_VENDOR_ITE)
1960 continue;
1961
1962 /* Is this device in our list? */
1963 for (i = 0; it87_gpio_table[i].id; i++)
1964 if (superios[sio].model == it87_gpio_table[i].id) {
1965 cfg = &it87_gpio_table[i];
1966 goto found;
1967 }
1968 }
1969
1970 if (cfg == NULL) {
1971 msg_perr("\nERROR: No IT87 Super I/O GPIO configuration "
1972 "found.\n");
uwe8d342eb2011-07-28 08:13:25 +00001973 return -1;
libv9c4d2b22009-09-01 21:22:23 +00001974 }
1975
stefanct54a39ee2011-11-14 13:00:12 +00001976found:
1977 /* Check whether the gpio is allowed. */
1978 if (gpio < 32)
1979 allowed = (cfg->bank0 >> gpio) & 0x01;
1980 else if (gpio < 64)
1981 allowed = (cfg->bank1 >> (gpio - 32)) & 0x01;
1982 else if (gpio < 96)
1983 allowed = (cfg->bank2 >> (gpio - 64)) & 0x01;
1984 else
1985 allowed = 0;
libv9c4d2b22009-09-01 21:22:23 +00001986
stefanct54a39ee2011-11-14 13:00:12 +00001987 if (!allowed) {
1988 msg_perr("\nERROR: IT%02X does not allow setting GPIO%02u.\n",
1989 cfg->id, gpio);
libv9c4d2b22009-09-01 21:22:23 +00001990 return -1;
1991 }
1992
stefanct54a39ee2011-11-14 13:00:12 +00001993 /* Read the Simple I/O Base Address Register */
1994 sioport = superios[sio].port;
1995 enter_conf_mode_ite(sioport);
1996 sio_write(sioport, 0x07, 0x07);
1997 base = (sio_read(sioport, cfg->base_reg) << 8) |
1998 sio_read(sioport, cfg->base_reg + 1);
1999 exit_conf_mode_ite(sioport);
libv9c4d2b22009-09-01 21:22:23 +00002000
2001 if (!base) {
stefanct54a39ee2011-11-14 13:00:12 +00002002 msg_perr("\nERROR: Failed to read IT87 Super I/O GPIO Base.\n");
libv9c4d2b22009-09-01 21:22:23 +00002003 return -1;
2004 }
2005
stefanct54a39ee2011-11-14 13:00:12 +00002006 msg_pdbg("Using IT87 GPIO base 0x%04x\n", base);
2007
2008 port = gpio / 10 - 1;
2009 gpio %= 10;
2010
2011 /* set GPIO. */
libv9c4d2b22009-09-01 21:22:23 +00002012 tmp = INB(base + port);
2013 if (raise)
stefanct54a39ee2011-11-14 13:00:12 +00002014 tmp |= 1 << gpio;
libv9c4d2b22009-09-01 21:22:23 +00002015 else
stefanct54a39ee2011-11-14 13:00:12 +00002016 tmp &= ~(1 << gpio);
libv9c4d2b22009-09-01 21:22:23 +00002017 OUTB(tmp, base + port);
2018
2019 return 0;
2020}
2021
uwee15beb92010-08-08 17:01:18 +00002022/*
mkarchercccf1392010-03-09 16:57:06 +00002023 * Suited for:
stefanctdbdba192011-11-19 19:31:17 +00002024 * - ASUS A7N8X-VM/400: NVIDIA nForce2 IGP2 + IT8712F
2025 */
2026static int it8712f_gpio12_raise(void)
2027{
2028 return it87_gpio_set(12, 1);
2029}
2030
2031/*
2032 * Suited for:
uwe3a3ab2f2010-03-25 23:18:41 +00002033 * - ASUS A7V600-X: VIA KT600 + VT8237 + IT8712F
2034 * - ASUS A7V8X-X: VIA KT400 + VT8235 + IT8712F
libv9c4d2b22009-09-01 21:22:23 +00002035 */
stefanct54a39ee2011-11-14 13:00:12 +00002036static int it8712f_gpio31_raise(void)
libv9c4d2b22009-09-01 21:22:23 +00002037{
stefanct54a39ee2011-11-14 13:00:12 +00002038 return it87_gpio_set(32, 1);
2039}
2040
2041/*
2042 * Suited for:
2043 * - ASUS P5N-D: NVIDIA MCP51 + IT8718F
2044 * - ASUS P5N-E SLI: NVIDIA MCP51 + IT8718F
2045 */
2046static int it8718f_gpio63_raise(void)
2047{
2048 return it87_gpio_set(63, 1);
libv9c4d2b22009-09-01 21:22:23 +00002049}
2050
Carl-Daniel Hailfinger289f4e92016-08-04 15:48:57 -07002051/*
2052 * Suited for all boards with ambiguous DMI chassis information, which should be
2053 * whitelisted because they are known to work:
2054 * - MSC Q7 Tunnel Creek Module (Q7-TCTC)
2055 */
2056static int p2_not_a_laptop(void)
2057{
2058 /* label this board as not a laptop */
2059 is_laptop = 0;
2060 msg_pdbg("Laptop detection overridden by P2 board enable.\n");
2061 return 0;
2062}
2063
hailfinger324a9cc2010-05-26 01:45:41 +00002064#endif
2065
uwee15beb92010-08-08 17:01:18 +00002066/*
uwec0751f42009-10-06 13:00:00 +00002067 * Below is the list of boards which need a special "board enable" code in
2068 * flashrom before their ROM chip can be accessed/written to.
2069 *
2070 * NOTE: Please add boards that _don't_ need such enables or don't work yet
2071 * to the respective tables in print.c. Thanks!
2072 *
uwebe4477b2007-08-23 16:08:21 +00002073 * We use 2 sets of IDs here, you're free to choose which is which. This
2074 * is to provide a very high degree of certainty when matching a board on
2075 * the basis of subsystem/card IDs. As not every vendor handles
2076 * subsystem/card IDs in a sane manner.
stepan927d4e22007-04-04 22:45:58 +00002077 *
stuge84659842009-04-20 12:38:17 +00002078 * Keep the second set NULLed if it should be ignored. Keep the subsystem IDs
hailfinger7fcb5b72010-02-04 11:12:04 +00002079 * NULLed if they don't identify the board fully and if you can't use DMI.
2080 * But please take care to provide an as complete set of pci ids as possible;
2081 * autodetection is the preferred behaviour and we would like to make sure that
2082 * matches are unique.
stepanf778f522008-02-20 11:11:18 +00002083 *
mkarcher803b4042010-01-20 14:14:11 +00002084 * If PCI IDs are not sufficient for board matching, the match can be further
2085 * constrained by a string that has to be present in the DMI database for
uwe3a3ab2f2010-03-25 23:18:41 +00002086 * the baseboard or the system entry. The pattern is matched by case sensitive
mkarcher803b4042010-01-20 14:14:11 +00002087 * substring match, unless it is anchored to the beginning (with a ^ in front)
2088 * or the end (with a $ at the end). Both anchors may be specified at the
2089 * same time to match the full field.
2090 *
hailfinger7fcb5b72010-02-04 11:12:04 +00002091 * When a board is matched through DMI, the first and second main PCI IDs
2092 * and the first subsystem PCI ID have to match as well. If you specify the
2093 * first subsystem ID as 0x0:0x0, the DMI matching code expects that the
2094 * subsystem ID of that device is indeed zero.
2095 *
stuge84659842009-04-20 12:38:17 +00002096 * The coreboot ids are used two fold. When running with a coreboot firmware,
2097 * the ids uniquely matches the coreboot board identification string. When a
2098 * legacy bios is installed and when autodetection is not possible, these ids
Carl-Daniel Hailfingere5ec66e2016-08-03 16:10:19 -07002099 * can be used to identify the board through the -p internal:mainboard=
2100 * programmer parameter.
stuge84659842009-04-20 12:38:17 +00002101 *
2102 * When a board is identified through its coreboot ids (in both cases), the
2103 * main pci ids are still required to match, as a safeguard.
stepan927d4e22007-04-04 22:45:58 +00002104 */
stepan927d4e22007-04-04 22:45:58 +00002105
uwec7f7eda2009-05-08 16:23:34 +00002106/* Please keep this list alphabetically ordered by vendor/board name. */
hailfinger4640bdb2011-08-31 16:19:50 +00002107const struct board_match board_matches[] = {
uwe869efa02009-06-21 20:50:22 +00002108
hailfingere52e9f82011-05-05 07:12:40 +00002109 /* first pci-id set [4], second pci-id set [4], dmi identifier, coreboot id [2], phase, vendor name, board name max_rom_... OK? flash enable */
hailfinger324a9cc2010-05-26 01:45:41 +00002110#if defined(__i386__) || defined(__x86_64__)
hailfingere52e9f82011-05-05 07:12:40 +00002111 {0x10DE, 0x0547, 0x147B, 0x1C2F, 0x10DE, 0x0548, 0x147B, 0x1C2F, NULL, NULL, NULL, P3, "abit", "AN-M2", 0, NT, nvidia_mcp_gpio2_raise},
stefanctcfc2c392011-10-21 13:20:11 +00002112 {0x1106, 0x0282, 0x147B, 0x1415, 0x1106, 0x3227, 0x147B, 0x1415, "^AV8 ", NULL, NULL, P3, "abit", "AV8", 0, OK, board_abit_av8},
hailfingere52e9f82011-05-05 07:12:40 +00002113 {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, "^i440BX-W977 (BM6)$", NULL, NULL, P3, "abit", "BM6", 0, OK, intel_piix4_gpo26_lower},
2114 {0x8086, 0x24d3, 0x147b, 0x1014, 0x8086, 0x2578, 0x147b, 0x1014, NULL, NULL, NULL, P3, "abit", "IC7", 0, NT, intel_ich_gpio23_raise},
2115 {0x8086, 0x2930, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, NULL, NULL, NULL, P3, "abit", "IP35", 0, OK, intel_ich_gpio16_raise},
2116 {0x8086, 0x2930, 0x147b, 0x1083, 0x10ec, 0x8167, 0x147b, 0x1083, NULL, NULL, NULL, P3, "abit", "IP35 Pro", 0, OK, intel_ich_gpio16_raise},
2117 {0x10de, 0x0050, 0x147b, 0x1c1a, 0, 0, 0, 0, NULL, NULL, NULL, P3, "abit", "KN8 Ultra", 0, NT, nvidia_mcp_gpio2_lower},
2118 {0x10de, 0x01e0, 0x147b, 0x1c00, 0x10de, 0x0060, 0x147B, 0x1c00, NULL, NULL, NULL, P3, "abit", "NF7-S", 0, OK, nvidia_mcp_gpio8_raise},
Stefan Tauner718d1eb2016-08-18 18:00:53 -07002119 {0x10de, 0x02f0, 0x147b, 0x1c26, 0x10de, 0x0260, 0x147b, 0x1c26, NULL, NULL, NULL, P3, "abit", "NF-M2 nView", 0, OK, nvidia_mcp_gpio4_lower},
hailfingere52e9f82011-05-05 07:12:40 +00002120 {0x1106, 0x0691, 0, 0, 0x1106, 0x3057, 0, 0, "(VA6)$", NULL, NULL, P3, "abit", "VA6", 0, OK, via_apollo_gpo4_lower},
2121 {0x1106, 0x0691, 0, 0, 0x1106, 0x3057, 0, 0, NULL, "abit", "vt6x4", P3, "abit", "VT6X4", 0, OK, via_apollo_gpo4_lower},
2122 {0x105a, 0x0d30, 0x105a, 0x4d33, 0x8086, 0x1130, 0x8086, 0, NULL, NULL, NULL, P3, "Acorp", "6A815EPD", 0, OK, board_acorp_6a815epd},
2123 {0x1022, 0x746B, 0, 0, 0, 0, 0, 0, NULL, "AGAMI", "ARUMA", P3, "agami", "Aruma", 0, OK, w83627hf_gpio24_raise_2e},
2124 {0x1106, 0x3177, 0x17F2, 0x3177, 0x1106, 0x3148, 0x17F2, 0x3148, NULL, NULL, NULL, P3, "Albatron", "PM266A Pro", 0, OK, w836xx_memw_enable_2e},
2125 {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe61", P3, "Artec Group", "DBE61", 0, OK, board_artecgroup_dbe6x},
2126 {0x1022, 0x2090, 0, 0, 0x1022, 0x2080, 0, 0, NULL, "artecgroup", "dbe62", P3, "Artec Group", "DBE62", 0, OK, board_artecgroup_dbe6x},
Carl-Daniel Hailfinger289f4e92016-08-04 15:48:57 -07002127 {0x8086, 0x27b9, 0xa0a0, 0x0632, 0x8086, 0x27da, 0xa0a0, 0x0632, NULL, NULL, NULL, P3, "AOpen", "i945GMx-VFX", 0, OK, intel_ich_gpio38_raise},
stefanctf1c118f2011-05-18 01:32:16 +00002128 {0x8086, 0x277c, 0xa0a0, 0x060b, 0x8086, 0x27da, 0xa0a0, 0x060b, NULL, NULL, NULL, P3, "AOpen", "i975Xa-YDG", 0, OK, board_aopen_i975xa_ydg},
stefanct1bf61862011-11-16 22:08:11 +00002129 {0x8086, 0x27b8, 0x1849, 0x27b8, 0x8086, 0x27da, 0x1849, 0x27da, "^ConRoeXFire-eSATA2", NULL, NULL, P3, "ASRock", "ConRoeXFire-eSATA2", 0, OK, intel_ich_gpio16_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002130 {0x1039, 0x0741, 0x1849, 0x0741, 0x1039, 0x5513, 0x1849, 0x5513, "^K7S41 $", NULL, NULL, P3, "ASRock", "K7S41", 0, OK, w836xx_memw_enable_2e},
uwe0e214692011-06-19 16:52:48 +00002131 {0x1039, 0x0741, 0x1849, 0x0741, 0x1039, 0x5513, 0x1849, 0x5513, "^K7S41GX$", NULL, NULL, P3, "ASRock", "K7S41GX", 0, OK, w836xx_memw_enable_2e},
hailfingere52e9f82011-05-05 07:12:40 +00002132 {0x8086, 0x24D4, 0x1849, 0x24D0, 0x8086, 0x24D5, 0x1849, 0x9739, NULL, NULL, NULL, P3, "ASRock", "P4i65GV", 0, OK, intel_ich_gpio23_raise},
2133 {0x8086, 0x2570, 0x1849, 0x2570, 0x8086, 0x24d3, 0x1849, 0x24d0, NULL, NULL, NULL, P3, "ASRock", "775i65G", 0, OK, intel_ich_gpio23_raise},
stefanctdbdba192011-11-19 19:31:17 +00002134 {0x10DE, 0x0060, 0x1043, 0x80AD, 0x10DE, 0x01E0, 0x1043, 0x80C0, NULL, NULL, NULL, P3, "ASUS", "A7N8X-VM/400", 0, OK, it8712f_gpio12_raise},
stefanct54a39ee2011-11-14 13:00:12 +00002135 {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, NULL, NULL, NULL, P3, "ASUS", "A7V600-X", 0, OK, it8712f_gpio31_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002136 {0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, NULL, P3, "ASUS", "A7V8X-MX SE", 0, OK, w836xx_memw_enable_2e},
2137 {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, NULL, NULL, NULL, P3, "ASUS", "A7V8X", 0, OK, it8703f_gpio51_raise},
2138 {0x1106, 0x3099, 0x1043, 0x807F, 0x1106, 0x3147, 0x1043, 0x808C, NULL, NULL, NULL, P3, "ASUS", "A7V333", 0, OK, it8703f_gpio51_raise},
stefanct54a39ee2011-11-14 13:00:12 +00002139 {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x80A1, NULL, NULL, NULL, P3, "ASUS", "A7V8X-X", 0, OK, it8712f_gpio31_raise},
stefanctdda0e212011-05-17 13:31:55 +00002140 {0x1002, 0x4372, 0x103c, 0x2a26, 0x1002, 0x4377, 0x103c, 0x2a26, NULL, NULL, NULL, P3, "ASUS", "A8AE-LE", 0, OK, amd_sbxxx_gpio9_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002141 {0x8086, 0x27A0, 0x1043, 0x1287, 0x8086, 0x27DF, 0x1043, 0x1287, "^A8J", NULL, NULL, P3, "ASUS", "A8Jm", 0, NT, intel_ich_gpio34_raise},
stefanctd7a27782011-08-07 13:17:20 +00002142 {0x10DE, 0x0260, 0x103C, 0x2A34, 0x10DE, 0x0264, 0x103C, 0x2A34, "NODUSM3", NULL, NULL, P3, "ASUS", "A8M2N-LA (NodusM3-GL8E)", 0, OK, nvidia_mcp_gpio0_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002143 {0x10DE, 0x0260, 0x103c, 0x2a3e, 0x10DE, 0x0264, 0x103c, 0x2a3e, "NAGAMI2L", NULL, NULL, P3, "ASUS", "A8N-LA (Nagami-GL8E)", 0, OK, nvidia_mcp_gpio0_raise},
stefanct577a1a52011-08-06 16:16:45 +00002144 {0x10DE, 0x005E, 0x1043, 0x815A, 0x10DE, 0x0054, 0x1043, 0x815A, "^A8N-SLI DELUXE", NULL, NULL, P3, "ASUS", "A8N-SLI Deluxe", 0, NT, board_shuttle_fn25},
stefanctbf8ef7d2011-07-20 16:34:18 +00002145 {0x10de, 0x0264, 0x1043, 0x81bc, 0x10de, 0x02f0, 0x1043, 0x81cd, NULL, NULL, NULL, P3, "ASUS", "A8N-VM CSM", 0, OK, w83627ehf_gpio22_raise_2e},
hailfingere52e9f82011-05-05 07:12:40 +00002146 {0x10DE, 0x0264, 0x1043, 0x81C0, 0x10DE, 0x0260, 0x1043, 0x81C0, NULL, NULL, NULL, P3, "ASUS", "M2NBP-VM CSM", 0, OK, nvidia_mcp_gpio0_raise},
2147 {0x1106, 0x1336, 0x1043, 0x80ed, 0x1106, 0x3288, 0x1043, 0x8249, NULL, NULL, NULL, P3, "ASUS", "M2V-MX", 0, OK, via_vt823x_gpio5_raise},
stefanct58c2d772011-07-09 19:46:53 +00002148 {0x8086, 0x24cc, 0, 0, 0x8086, 0x24c3, 0x1043, 0x1869, "^M6Ne$", NULL, NULL, P3, "ASUS", "M6Ne", 0, NT, intel_ich_gpio43_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002149 {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, "^P2B-N$", NULL, NULL, P3, "ASUS", "P2B-N", 0, OK, intel_piix4_gpo18_lower},
2150 {0x8086, 0x1A30, 0x1043, 0x8025, 0x8086, 0x244B, 0x104D, 0x80F0, NULL, NULL, NULL, P3, "ASUS", "P4B266-LM", 0, OK, intel_ich_gpio21_raise},
2151 {0x8086, 0x1a30, 0x1043, 0x8070, 0x8086, 0x244b, 0x1043, 0x8028, NULL, NULL, NULL, P3, "ASUS", "P4B266", 0, OK, intel_ich_gpio22_raise},
2152 {0x8086, 0x1A30, 0x1043, 0x8088, 0x8086, 0x24C3, 0x1043, 0x8089, NULL, NULL, NULL, P3, "ASUS", "P4B533-E", 0, NT, intel_ich_gpio22_raise},
stefanct1d40d862011-11-15 08:08:15 +00002153 {0x8086, 0x2560, 0x103C, 0x2A00, 0x8086, 0x24C3, 0x103C, 0x2A01, "^Guppy", NULL, NULL, P3, "ASUS", "P4GV-LA (Guppy)", 0, OK, intel_ich_gpio21_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002154 {0x8086, 0x24D3, 0x1043, 0x80A6, 0x8086, 0x2578, 0x1043, 0x80F6, NULL, NULL, NULL, P3, "ASUS", "P4C800-E Deluxe", 0, OK, intel_ich_gpio21_raise},
2155 {0x8086, 0x2570, 0x1043, 0x80F2, 0x8086, 0x24D5, 0x1043, 0x80F3, NULL, NULL, NULL, P3, "ASUS", "P4P800", 0, NT, intel_ich_gpio21_raise},
stefanctd6efe1a2011-09-03 11:22:27 +00002156 {0x8086, 0x2570, 0x1043, 0x80F2, 0x8086, 0x24D3, 0x1043, 0x80A6, "^P4P800-E$", NULL, NULL, P3, "ASUS", "P4P800-E Deluxe", 0, OK, intel_ich_gpio21_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002157 {0x8086, 0x2570, 0x1043, 0x80A5, 0x8086, 0x24d0, 0, 0, NULL, NULL, NULL, P3, "ASUS", "P4P800-VM", 0, OK, intel_ich_gpio21_raise},
2158 {0x1039, 0x0651, 0x1043, 0x8081, 0x1039, 0x0962, 0, 0, NULL, NULL, NULL, P3, "ASUS", "P4SC-E", 0, OK, it8707f_write_enable_2e},
2159 {0x8086, 0x2570, 0x1043, 0x80A5, 0x105A, 0x24D3, 0x1043, 0x80A6, NULL, NULL, NULL, P3, "ASUS", "P4SD-LA", 0, NT, intel_ich_gpio32_raise},
2160 {0x1039, 0x0661, 0x1043, 0x8113, 0x1039, 0x5513, 0x1043, 0x8087, NULL, NULL, NULL, P3, "ASUS", "P4S800-MX", 512, OK, w836xx_memw_enable_2e},
2161 {0x10B9, 0x1541, 0, 0, 0x10B9, 0x1533, 0, 0, "^P5A$", "asus", "p5a", P3, "ASUS", "P5A", 0, OK, board_asus_p5a},
stefanct26b40f22011-10-22 22:01:09 +00002162 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x814e, "^P5GD1 PRO$", NULL, NULL, P3, "ASUS", "P5GD1 Pro", 0, OK, intel_ich_gpio21_raise},
2163 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x814e, "^P5GD1-VM$", NULL, NULL, P3, "ASUS", "P5GD1-VM/S", 0, OK, intel_ich_gpio21_raise},
2164 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x814e, NULL, NULL, NULL, P3, "ASUS", "P5GD1(-VM)", 0, NT, intel_ich_gpio21_raise},
stefanctdbca6752011-08-11 05:47:32 +00002165 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x813d, "^P5GD2-Premium$", NULL, NULL, P3, "ASUS", "P5GD2 Premium", 0, OK, intel_ich_gpio21_raise},
stefanct26b40f22011-10-22 22:01:09 +00002166 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x813d, "^P5GDC-V$", NULL, NULL, P3, "ASUS", "P5GDC-V Deluxe", 0, OK, intel_ich_gpio21_raise},
2167 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x813d, "^P5GDC$", NULL, NULL, P3, "ASUS", "P5GDC Deluxe", 0, OK, intel_ich_gpio21_raise},
2168 {0x8086, 0x266a, 0x1043, 0x80a6, 0x8086, 0x2668, 0x1043, 0x813d, NULL, NULL, NULL, P3, "ASUS", "P5GD2/C variants", 0, NT, intel_ich_gpio21_raise},
stefanct950bded2011-08-25 14:06:50 +00002169 {0x8086, 0x27b8, 0x103c, 0x2a22, 0x8086, 0x2770, 0x103c, 0x2a22, "^LITHIUM$", NULL, NULL, P3, "ASUS", "P5LP-LE (Lithium-UL8E)",0, OK, intel_ich_gpio34_raise},
2170 {0x8086, 0x27b8, 0x1043, 0x2a22, 0x8086, 0x2770, 0x1043, 0x2a22, "^P5LP-LE$", NULL, NULL, P3, "ASUS", "P5LP-LE (Epson OEM)", 0, OK, intel_ich_gpio34_raise},
stefanctdbca6752011-08-11 05:47:32 +00002171 {0x8086, 0x27da, 0x1043, 0x8179, 0x8086, 0x27b8, 0x1043, 0x8179, "^P5LD2$", NULL, NULL, P3, "ASUS", "P5LD2", 0, NT, intel_ich_gpio16_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002172 {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, NULL, P3, "ASUS", "P5ND2-SLI Deluxe", 0, OK, nvidia_mcp_gpio10_raise},
stefanct54a39ee2011-11-14 13:00:12 +00002173 {0x10DE, 0x0260, 0x1043, 0x81BC, 0x10DE, 0x026C, 0x1043, 0x829E, "^P5N-D$", NULL, NULL, P3, "ASUS", "P5N-D", 0, OK, it8718f_gpio63_raise},
2174 {0x10DE, 0x0260, 0x1043, 0x81BC, 0x10DE, 0x026C, 0x1043, 0x8249, "^P5N-E SLI$",NULL, NULL, P3, "ASUS", "P5N-E SLI", 0, NT, it8718f_gpio63_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002175 {0x8086, 0x24dd, 0x1043, 0x80a6, 0x8086, 0x2570, 0x1043, 0x8157, NULL, NULL, NULL, P3, "ASUS", "P5PE-VM", 0, OK, intel_ich_gpio21_raise},
2176 {0x10b7, 0x9055, 0x1028, 0x0082, 0x8086, 0x7190, 0, 0, NULL, NULL, NULL, P3, "Dell", "OptiPlex GX1", 0, OK, intel_piix4_gpo30_lower},
2177 {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, NULL, P3, "Dell", "PowerEdge 1850", 0, OK, intel_ich_gpio23_raise},
2178 {0x10de, 0x03ea, 0x1019, 0x2602, 0x10de, 0x03e0, 0x1019, 0x2602, NULL, NULL, NULL, P3, "Elitegroup", "GeForce6100SM-M", 0, OK, board_ecs_geforce6100sm_m},
2179 {0x1106, 0x3038, 0x1019, 0x0996, 0x1106, 0x3177, 0x1019, 0x0996, NULL, NULL, NULL, P3, "Elitegroup", "K7VTA3", 256, OK, NULL},
2180 {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3059, 0x1695, 0x3005, NULL, NULL, NULL, P3, "EPoX", "EP-8K5A2", 0, OK, w836xx_memw_enable_2e},
stefanctf5689f92011-08-06 16:16:33 +00002181 {0x10DE, 0x005E, 0x1695, 0x1010, 0x10DE, 0x0050, 0x1695, 0x1010, "8NPA7I", NULL, NULL, P3, "EPoX", "EP-8NPA7I", 0, OK, nvidia_mcp_gpio4_raise},
2182 {0x10DE, 0x005E, 0x1695, 0x1010, 0x10DE, 0x0050, 0x1695, 0x1010, "9NPA7I", NULL, NULL, P3, "EPoX", "EP-9NPA7I", 0, OK, nvidia_mcp_gpio4_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002183 {0x10EC, 0x8139, 0x1695, 0x9001, 0x11C1, 0x5811, 0x1695, 0x9015, NULL, NULL, NULL, P3, "EPoX", "EP-8RDA3+", 0, OK, nvidia_mcp_gpio31_raise},
2184 {0x8086, 0x7110, 0, 0, 0x8086, 0x7190, 0, 0, NULL, "epox", "ep-bx3", P3, "EPoX", "EP-BX3", 0, NT, intel_piix4_gpo22_raise},
2185 {0x10de, 0x02f0, 0x105b, 0x0d01, 0x10de, 0x0264, 0x105b, 0x0d01, NULL, NULL, NULL, P3, "Foxconn", "6150K8MD-8EKRSH", 0, NT, nvidia_mcp_gpio2_raise},
2186 {0x8086, 0x2443, 0x8086, 0x2442, 0x8086, 0x1130, 0x8086, 0x1130, "^6IEM ", NULL, NULL, P3, "GIGABYTE", "GA-6IEM", 0, NT, intel_ich_gpio25_raise},
2187 {0x1106, 0x0686, 0x1106, 0x0686, 0x1106, 0x3058, 0x1458, 0xa000, NULL, NULL, NULL, P3, "GIGABYTE", "GA-7ZM", 512, OK, NULL},
stefanct2ecec882011-06-13 16:59:01 +00002188 {0x8086, 0x2570, 0x1458, 0x2570, 0x8086, 0x24d0, 0, 0, "^8IP775/-G$",NULL, NULL, P3, "GIGABYTE", "GA-8IP775", 0, OK, intel_ich_gpio32_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002189 {0x8086, 0x244b, 0x8086, 0x2442, 0x8086, 0x2445, 0x1458, 0xa002, NULL, NULL, NULL, P3, "GIGABYTE", "GA-8IRML", 0, OK, intel_ich_gpio25_raise},
2190 {0x8086, 0x24c3, 0x1458, 0x24c2, 0x8086, 0x24cd, 0x1458, 0x5004, NULL, NULL, NULL, P3, "GIGABYTE", "GA-8PE667 Ultra 2", 0, OK, intel_ich_gpio32_raise},
stefanctdfd58832011-07-25 20:38:52 +00002191 {0x1039, 0x0651, 0x1039, 0x0651, 0x1039, 0x7002, 0x1458, 0x5004, "^GA-8SIMLH$",NULL, NULL, P3, "GIGABYTE", "GA-8SIMLH", 0, OK, sis_gpio0_raise_and_w836xx_memw},
hailfingere52e9f82011-05-05 07:12:40 +00002192 {0x10DE, 0x02F1, 0x1458, 0x5000, 0x10DE, 0x0261, 0x1458, 0x5001, NULL, NULL, NULL, P3, "GIGABYTE", "GA-K8N51GMF", 0, OK, nvidia_mcp_gpio3b_raise},
2193 {0x10DE, 0x026C, 0x1458, 0xA102, 0x10DE, 0x0260, 0x1458, 0x5001, NULL, NULL, NULL, P3, "GIGABYTE", "GA-K8N51GMF-9", 0, OK, nvidia_mcp_gpio3b_raise},
stefanct8fb644d2011-06-13 16:58:54 +00002194 {0x10de, 0x00e4, 0x1458, 0x0c11, 0x10de, 0x00e0, 0x1458, 0x0c11, NULL, NULL, NULL, P3, "GIGABYTE", "GA-K8NS Pro-939", 0, NT, nvidia_mcp_gpio0a_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002195 {0x10DE, 0x0050, 0x1458, 0x0C11, 0x10DE, 0x005e, 0x1458, 0x5000, NULL, NULL, NULL, P3, "GIGABYTE", "GA-K8N-SLI", 0, OK, nvidia_mcp_gpio21_raise},
stefanct8fb644d2011-06-13 16:58:54 +00002196 {0x8086, 0x2415, 0x103c, 0x1250, 0x10b7, 0x9200, 0x103c, 0x1247, NULL, NULL, NULL, P3, "HP", "e-Vectra P2706T", 0, OK, board_hp_p2706t},
hailfingere52e9f82011-05-05 07:12:40 +00002197 {0x1166, 0x0223, 0x103c, 0x320d, 0x14e4, 0x1678, 0x103c, 0x703e, NULL, "hp", "dl145_g3", P3, "HP", "ProLiant DL145 G3", 0, OK, board_hp_dl145_g3_enable},
2198 {0x1166, 0x0223, 0x103c, 0x320d, 0x14e4, 0x1648, 0x103c, 0x310f, NULL, "hp", "dl165_g6", P3, "HP", "ProLiant DL165 G6", 0, OK, board_hp_dl165_g6_enable},
2199 {0x8086, 0x2580, 0x103c, 0x2a08, 0x8086, 0x2640, 0x103c, 0x2a0a, NULL, NULL, NULL, P3, "HP", "Puffer2-UL8E", 0, OK, intel_ich_gpio18_raise},
stefanct8fb644d2011-06-13 16:58:54 +00002200 {0x8086, 0x2415, 0x103c, 0x1249, 0x10b7, 0x9200, 0x103c, 0x1246, NULL, NULL, NULL, P3, "HP", "Vectra VL400", 0, OK, board_hp_vl400},
hailfingere52e9f82011-05-05 07:12:40 +00002201 {0x8086, 0x1a30, 0x103c, 0x1a30, 0x8086, 0x2443, 0x103c, 0x2440, "^VL420$", NULL, NULL, P3, "HP", "Vectra VL420 SFF", 0, OK, intel_ich_gpio22_raise},
2202 {0x10de, 0x0369, 0x103c, 0x12fe, 0x10de, 0x0364, 0x103c, 0x12fe, NULL, "hp", "xw9400", P3, "HP", "xw9400", 0, OK, nvidia_mcp_gpio5_raise},
2203 {0x8086, 0x27A0, 0, 0, 0x8086, 0x27B9, 0, 0, NULL, "ibase", "mb899", P3, "IBASE", "MB899", 0, OK, intel_ich_gpio26_raise},
2204 {0x1166, 0x0205, 0x1014, 0x0347, 0x1002, 0x515E, 0x1014, 0x0325, NULL, NULL, NULL, P3, "IBM", "x3455", 0, OK, board_ibm_x3455},
2205 {0x1039, 0x5513, 0x8086, 0xd61f, 0x1039, 0x6330, 0x8086, 0xd61f, NULL, NULL, NULL, P3, "Intel", "D201GLY", 0, OK, wbsio_check_for_spi},
2206 {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, "^SE440BX-2$", NULL, NULL, P3, "Intel", "SE440BX-2", 0, NT, intel_piix4_gpo27_lower},
2207 {0x1022, 0x7468, 0, 0, 0, 0, 0, 0, NULL, "iwill", "dk8_htx", P3, "IWILL", "DK8-HTX", 0, OK, w83627hf_gpio24_raise_2e},
2208 {0x8086, 0x27A0, 0x8086, 0x27a0, 0x8086, 0x27b8, 0x8086, 0x27b8, NULL, "kontron", "986lcd-m", P3, "Kontron", "986LCD-M", 0, OK, board_kontron_986lcd_m},
2209 {0x8086, 0x2411, 0x8086, 0x2411, 0x8086, 0x7125, 0x0e11, 0xb165, NULL, NULL, NULL, P3, "Mitac", "6513WU", 0, OK, board_mitac_6513wu},
Carl-Daniel Hailfinger289f4e92016-08-04 15:48:57 -07002210 {0x8086, 0x8186, 0x8086, 0x8186, 0x8086, 0x8800, 0x0000, 0x0000, "^MSC Vertriebs GmbH$", NULL, NULL, P2, "MSC", "Q7-TCTC", 0, OK, p2_not_a_laptop},
hailfingere52e9f82011-05-05 07:12:40 +00002211 {0x10DE, 0x005E, 0x1462, 0x7125, 0x10DE, 0x0052, 0x1462, 0x7125, NULL, NULL, NULL, P3, "MSI", "K8N Neo4-F", 0, OK, nvidia_mcp_gpio2_raise}, /* TODO: Should probably be K8N Neo4 Platinum, see http://www.coreboot.org/pipermail/flashrom/2010-August/004362.html. */
2212 {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, "^MS-6163 (i440BX)$", NULL, NULL, P3, "MSI", "MS-6163 (MS-6163 Pro)", 0, OK, intel_piix4_gpo14_raise},
2213 {0x1039, 0x0745, 0, 0, 0x1039, 0x0018, 0, 0, "^MS-6561", NULL, NULL, P3, "MSI", "MS-6561 (745 Ultra)", 0, OK, w836xx_memw_enable_2e},
2214 {0x8086, 0x2560, 0x1462, 0x5770, 0x8086, 0x2562, 0x1462, 0x5778, NULL, NULL, NULL, P3, "MSI", "MS-6577 (Xenon)", 0, OK, w83627hf_gpio25_raise_2e},
2215 {0x13f6, 0x0111, 0x1462, 0x5900, 0x1106, 0x3177, 0x1106, 0, NULL, NULL, NULL, P3, "MSI", "MS-6590 (KT4 Ultra)", 0, OK, board_msi_kt4v},
2216 {0x1106, 0x3149, 0x1462, 0x7094, 0x10ec, 0x8167, 0x1462, 0x094c, NULL, NULL, NULL, P3, "MSI", "MS-6702E (K8T Neo2-F)", 0, OK, w83627thf_gpio44_raise_2e},
2217 {0x1106, 0x0571, 0x1462, 0x7120, 0x1106, 0x3065, 0x1462, 0x7120, NULL, NULL, NULL, P3, "MSI", "MS-6712 (KT4V)", 0, OK, board_msi_kt4v},
2218 {0x1106, 0x3148, 0 , 0 , 0x1106, 0x3177, 0 , 0 , NULL, "msi", "ms6787", P3, "MSI", "MS-6787 (P4MAM-V/P4MAM-L)", 0, OK, w836xx_memw_enable_2e},
hailfinger344569c2011-06-09 20:59:30 +00002219 {0x8086, 0x24d3, 0x1462, 0x7880, 0x8086, 0x2570, 0, 0, NULL, NULL, NULL, P3, "MSI", "MS-6788-040 (848P NeoV)", 0, OK, intel_ich_gpio32_raise},
mkarcher2b630cf2011-07-25 17:25:24 +00002220 {0x1039, 0x7012, 0x1462, 0x0050, 0x1039, 0x6325, 0x1462, 0x0058, NULL, NULL, NULL, P3, "MSI", "MS-7005 (651M-L)", 0, OK, sis_gpio0_raise_and_w836xx_memw},
hailfingere52e9f82011-05-05 07:12:40 +00002221 {0x10DE, 0x00E0, 0x1462, 0x0250, 0x10DE, 0x00E1, 0x1462, 0x0250, NULL, NULL, NULL, P3, "MSI", "MS-7025 (K8N Neo2 Platinum)", 0, OK, nvidia_mcp_gpio0c_raise},
2222 {0x8086, 0x2658, 0x1462, 0x7046, 0x1106, 0x3044, 0x1462, 0x046d, NULL, NULL, NULL, P3, "MSI", "MS-7046", 0, OK, intel_ich_gpio19_raise},
2223 {0x8086, 0x244b, 0x1462, 0x3910, 0x8086, 0x2442, 0x1462, 0x3910, NULL, NULL, NULL, P3, "MSI", "MS-6391 (845 Pro4)", 0, OK, intel_ich_gpio23_raise},
2224 {0x1106, 0x3149, 0x1462, 0x7061, 0x1106, 0x3227, 0, 0, NULL, NULL, NULL, P3, "MSI", "MS-7061 (KM4M-V/KM4AM-V)", 0, OK, w836xx_memw_enable_2e},
2225 {0x10DE, 0x005E, 0x1462, 0x7135, 0x10DE, 0x0050, 0x1462, 0x7135, NULL, "msi", "k8n-neo3", P3, "MSI", "MS-7135 (K8N Neo3)", 0, OK, w83627thf_gpio44_raise_4e},
2226 {0x10DE, 0x0270, 0x1462, 0x7207, 0x10DE, 0x0264, 0x1462, 0x7207, NULL, NULL, NULL, P3, "MSI", "MS-7207 (K8NGM2-L)", 0, NT, nvidia_mcp_gpio2_raise},
2227 {0x1011, 0x0019, 0xaa55, 0xaa55, 0x8086, 0x7190, 0, 0, NULL, NULL, NULL, P3, "Nokia", "IP530", 0, OK, fdc37b787_gpio50_raise_3f0},
2228 {0x8086, 0x24d3, 0x144d, 0xb025, 0x8086, 0x1050, 0x144d, 0xb025, NULL, NULL, NULL, P3, "Samsung", "Polaris 32", 0, OK, intel_ich_gpio21_raise},
2229 {0x1106, 0x3099, 0, 0, 0x1106, 0x3074, 0, 0, NULL, "shuttle", "ak31", P3, "Shuttle", "AK31", 0, OK, w836xx_memw_enable_2e},
2230 {0x1106, 0x3104, 0x1297, 0xa238, 0x1106, 0x3059, 0x1297, 0xc063, NULL, NULL, NULL, P3, "Shuttle", "AK38N", 256, OK, NULL},
2231 {0x10DE, 0x0050, 0x1297, 0x5036, 0x1412, 0x1724, 0x1297, 0x5036, NULL, NULL, NULL, P3, "Shuttle", "FN25", 0, OK, board_shuttle_fn25},
2232 {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x3058, 0x15DD, 0x7609, NULL, NULL, NULL, P3, "Soyo", "SY-7VCA", 0, OK, via_apollo_gpo0_lower},
stefanct634adc82011-11-02 14:31:18 +00002233 {0x10de, 0x0364, 0x108e, 0x6676, 0x10de, 0x0369, 0x108e, 0x6676, "^Sun Ultra 40 M2", NULL, NULL, P3, "Sun", "Ultra 40 M2", 0, OK, board_sun_ultra_40_m2},
hailfingere52e9f82011-05-05 07:12:40 +00002234 {0x1106, 0x3038, 0x0925, 0x1234, 0x1106, 0x0596, 0x1106, 0, NULL, NULL, NULL, P3, "Tekram", "P6Pro-A5", 256, OK, NULL},
2235 {0x1106, 0x3123, 0x1106, 0x3123, 0x1106, 0x3059, 0x1106, 0x4161, NULL, NULL, NULL, P3, "Termtek", "TK-3370 (Rev:2.5B)", 0, OK, w836xx_memw_enable_4e},
Rudolf Marek1d455e22016-08-04 18:14:47 -07002236 {0x8086, 0x7120, 0x109f, 0x3157, 0x8086, 0x2410, 0, 0, NULL, NULL, NULL, P3, "TriGem", "Anaheim-3", 0, OK, intel_ich_gpio22_raise},
hailfingere52e9f82011-05-05 07:12:40 +00002237 {0x8086, 0x1076, 0x8086, 0x1176, 0x1106, 0x3059, 0x10f1, 0x2498, NULL, NULL, NULL, P3, "Tyan", "S2498 (Tomcat K7M)", 0, OK, w836xx_memw_enable_2e},
2238 {0x1106, 0x0259, 0x1106, 0xAA07, 0x1106, 0x3227, 0x1106, 0xAA07, NULL, NULL, NULL, P3, "VIA", "EPIA EK", 0, NT, via_vt823x_gpio9_raise},
2239 {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, NULL, P3, "VIA", "EPIA M/MII/...", 0, OK, via_vt823x_gpio15_raise},
2240 {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, NULL, NULL, NULL, P3, "VIA", "EPIA-N/NL", 0, OK, via_vt823x_gpio9_raise},
hailfinger324a9cc2010-05-26 01:45:41 +00002241#endif
hailfingere52e9f82011-05-05 07:12:40 +00002242 { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, P3, NULL, NULL, 0, NT, NULL}, /* end marker */
stepan927d4e22007-04-04 22:45:58 +00002243};
2244
uwee15beb92010-08-08 17:01:18 +00002245/*
stepan1037f6f2008-01-18 15:33:10 +00002246 * Match boards on coreboot table gathered vendor and part name.
uwebe4477b2007-08-23 16:08:21 +00002247 * Require main PCI IDs to match too as extra safety.
stepan927d4e22007-04-04 22:45:58 +00002248 */
hailfinger4640bdb2011-08-31 16:19:50 +00002249static const struct board_match *board_match_cbname(const char *vendor,
2250 const char *part)
stepan927d4e22007-04-04 22:45:58 +00002251{
hailfinger4640bdb2011-08-31 16:19:50 +00002252 const struct board_match *board = board_matches;
2253 const struct board_match *partmatch = NULL;
stepan927d4e22007-04-04 22:45:58 +00002254
uwe4b650af2009-05-09 00:47:04 +00002255 for (; board->vendor_name; board++) {
uwefa98ca12008-10-18 21:14:13 +00002256 if (vendor && (!board->lb_vendor
2257 || strcasecmp(board->lb_vendor, vendor)))
uwef6641642007-05-09 10:17:44 +00002258 continue;
stepan927d4e22007-04-04 22:45:58 +00002259
stuge0c1005b2008-07-02 00:47:30 +00002260 if (!board->lb_part || strcasecmp(board->lb_part, part))
uwef6641642007-05-09 10:17:44 +00002261 continue;
stepan927d4e22007-04-04 22:45:58 +00002262
uwef6641642007-05-09 10:17:44 +00002263 if (!pci_dev_find(board->first_vendor, board->first_device))
2264 continue;
stepan927d4e22007-04-04 22:45:58 +00002265
uwef6641642007-05-09 10:17:44 +00002266 if (board->second_vendor &&
uwefa98ca12008-10-18 21:14:13 +00002267 !pci_dev_find(board->second_vendor, board->second_device))
uwef6641642007-05-09 10:17:44 +00002268 continue;
stugeb9b411f2008-01-27 16:21:21 +00002269
2270 if (vendor)
2271 return board;
2272
2273 if (partmatch) {
2274 /* a second entry has a matching part name */
snelsone42c3802010-05-07 20:09:04 +00002275 msg_pinfo("AMBIGUOUS BOARD NAME: %s\n", part);
2276 msg_pinfo("At least vendors '%s' and '%s' match.\n",
uwe8d342eb2011-07-28 08:13:25 +00002277 partmatch->lb_vendor, board->lb_vendor);
Carl-Daniel Hailfingere5ec66e2016-08-03 16:10:19 -07002278 msg_perr("Please use the full -p internal:mainboard=vendor:part syntax.\n");
stugeb9b411f2008-01-27 16:21:21 +00002279 return NULL;
2280 }
2281 partmatch = board;
uwef6641642007-05-09 10:17:44 +00002282 }
uwe6ed6d952007-12-04 21:49:06 +00002283
stugeb9b411f2008-01-27 16:21:21 +00002284 if (partmatch)
2285 return partmatch;
2286
stepan3370c892009-07-30 13:30:17 +00002287 if (!partvendor_from_cbtable) {
2288 /* Only warn if the mainboard type was not gathered from the
2289 * coreboot table. If it was, the coreboot implementor is
2290 * expected to fix flashrom, too.
2291 */
Carl-Daniel Hailfingere5ec66e2016-08-03 16:10:19 -07002292 msg_perr("\nUnknown vendor:board from -p internal:mainboard= programmer parameter:\n%s:%s\n\n",
uwe8d342eb2011-07-28 08:13:25 +00002293 vendor, part);
stepan3370c892009-07-30 13:30:17 +00002294 }
uwef6641642007-05-09 10:17:44 +00002295 return NULL;
stepan927d4e22007-04-04 22:45:58 +00002296}
2297
uwee15beb92010-08-08 17:01:18 +00002298/*
uwebe4477b2007-08-23 16:08:21 +00002299 * Match boards on PCI IDs and subsystem IDs.
hailfinger4640bdb2011-08-31 16:19:50 +00002300 * Second set of IDs can be either main+subsystem IDs, main IDs or no IDs.
stepan927d4e22007-04-04 22:45:58 +00002301 */
hailfinger4640bdb2011-08-31 16:19:50 +00002302const static struct board_match *board_match_pci_ids(enum board_match_phase phase)
stepan927d4e22007-04-04 22:45:58 +00002303{
hailfinger4640bdb2011-08-31 16:19:50 +00002304 const struct board_match *board = board_matches;
stepan927d4e22007-04-04 22:45:58 +00002305
uwe4b650af2009-05-09 00:47:04 +00002306 for (; board->vendor_name; board++) {
mkarcher58fbded2010-02-04 10:58:50 +00002307 if ((!board->first_card_vendor || !board->first_card_device) &&
2308 !board->dmi_pattern)
uwef6641642007-05-09 10:17:44 +00002309 continue;
hailfingere52e9f82011-05-05 07:12:40 +00002310 if (board->phase != phase)
2311 continue;
stepan927d4e22007-04-04 22:45:58 +00002312
uwef6641642007-05-09 10:17:44 +00002313 if (!pci_card_find(board->first_vendor, board->first_device,
uwefa98ca12008-10-18 21:14:13 +00002314 board->first_card_vendor,
2315 board->first_card_device))
uwef6641642007-05-09 10:17:44 +00002316 continue;
stepan927d4e22007-04-04 22:45:58 +00002317
uwef6641642007-05-09 10:17:44 +00002318 if (board->second_vendor) {
2319 if (board->second_card_vendor) {
2320 if (!pci_card_find(board->second_vendor,
uwefa98ca12008-10-18 21:14:13 +00002321 board->second_device,
2322 board->second_card_vendor,
2323 board->second_card_device))
uwef6641642007-05-09 10:17:44 +00002324 continue;
2325 } else {
2326 if (!pci_dev_find(board->second_vendor,
uwefa98ca12008-10-18 21:14:13 +00002327 board->second_device))
uwef6641642007-05-09 10:17:44 +00002328 continue;
2329 }
2330 }
stepan927d4e22007-04-04 22:45:58 +00002331
mkarcher803b4042010-01-20 14:14:11 +00002332 if (board->dmi_pattern) {
2333 if (!has_dmi_support) {
snelsone42c3802010-05-07 20:09:04 +00002334 msg_perr("WARNING: Can't autodetect %s %s,"
uwe8d342eb2011-07-28 08:13:25 +00002335 " DMI info unavailable.\n",
2336 board->vendor_name, board->board_name);
mkarcher803b4042010-01-20 14:14:11 +00002337 continue;
2338 } else {
2339 if (!dmi_match(board->dmi_pattern))
2340 continue;
2341 }
2342 }
2343
uwef6641642007-05-09 10:17:44 +00002344 return board;
2345 }
stepan927d4e22007-04-04 22:45:58 +00002346
uwef6641642007-05-09 10:17:44 +00002347 return NULL;
stepan927d4e22007-04-04 22:45:58 +00002348}
2349
hailfinger4640bdb2011-08-31 16:19:50 +00002350static int unsafe_board_handler(const struct board_match *board)
hailfingere52e9f82011-05-05 07:12:40 +00002351{
2352 if (!board)
2353 return 1;
2354
2355 if (board->status == OK)
2356 return 0;
2357
2358 if (!force_boardenable) {
2359 msg_pinfo("WARNING: Your mainboard is %s %s, but the mainboard-specific\n"
uwe8d342eb2011-07-28 08:13:25 +00002360 "code has not been tested, and thus will not be executed by default.\n"
2361 "Depending on your hardware environment, erasing, writing or even probing\n"
2362 "can fail without running the board specific code.\n\n"
2363 "Please see the man page (section PROGRAMMER SPECIFIC INFO, subsection\n"
2364 "\"internal programmer\") for details.\n",
2365 board->vendor_name, board->board_name);
hailfingere52e9f82011-05-05 07:12:40 +00002366 return 1;
2367 }
2368 msg_pinfo("NOTE: Running an untested board enable procedure.\n"
2369 "Please report success/failure to flashrom@flashrom.org\n"
2370 "with your board name and SUCCESS or FAILURE in the subject.\n");
2371 return 0;
2372}
2373
2374/* FIXME: Should this be identical to board_flash_enable? */
2375static int board_handle_phase(enum board_match_phase phase)
2376{
hailfinger4640bdb2011-08-31 16:19:50 +00002377 const struct board_match *board = NULL;
hailfingere52e9f82011-05-05 07:12:40 +00002378
hailfinger4640bdb2011-08-31 16:19:50 +00002379 board = board_match_pci_ids(phase);
hailfingere52e9f82011-05-05 07:12:40 +00002380
2381 if (unsafe_board_handler(board))
2382 board = NULL;
2383
2384 if (!board)
2385 return 0;
2386
2387 if (!board->enable) {
2388 /* Not sure if there is a valid case for this. */
2389 msg_perr("Board match found, but nothing to do?\n");
2390 return 0;
2391 }
2392
2393 return board->enable();
2394}
2395
2396void board_handle_before_superio(void)
2397{
2398 board_handle_phase(P1);
2399}
2400
2401void board_handle_before_laptop(void)
2402{
2403 board_handle_phase(P2);
2404}
2405
uwe6ed6d952007-12-04 21:49:06 +00002406int board_flash_enable(const char *vendor, const char *part)
stepan927d4e22007-04-04 22:45:58 +00002407{
hailfinger4640bdb2011-08-31 16:19:50 +00002408 const struct board_match *board = NULL;
uwef6641642007-05-09 10:17:44 +00002409 int ret = 0;
stepan927d4e22007-04-04 22:45:58 +00002410
stugeb9b411f2008-01-27 16:21:21 +00002411 if (part)
hailfinger4640bdb2011-08-31 16:19:50 +00002412 board = board_match_cbname(vendor, part);
stepan927d4e22007-04-04 22:45:58 +00002413
uwef6641642007-05-09 10:17:44 +00002414 if (!board)
hailfinger4640bdb2011-08-31 16:19:50 +00002415 board = board_match_pci_ids(P3);
stepan927d4e22007-04-04 22:45:58 +00002416
hailfingere52e9f82011-05-05 07:12:40 +00002417 if (unsafe_board_handler(board))
uwee15beb92010-08-08 17:01:18 +00002418 board = NULL;
mkarcher29a80852010-03-07 22:29:28 +00002419
uwef6641642007-05-09 10:17:44 +00002420 if (board) {
libve9b336e2010-01-20 14:45:03 +00002421 if (board->max_rom_decode_parallel)
2422 max_rom_decode.parallel =
2423 board->max_rom_decode_parallel * 1024;
2424
uwe0ec24c22010-01-28 19:02:36 +00002425 if (board->enable != NULL) {
snelsone42c3802010-05-07 20:09:04 +00002426 msg_pinfo("Disabling flash write protection for "
uwee15beb92010-08-08 17:01:18 +00002427 "board \"%s %s\"... ", board->vendor_name,
2428 board->board_name);
stepan927d4e22007-04-04 22:45:58 +00002429
uweeb26b6e2010-06-07 19:06:26 +00002430 ret = board->enable();
uwe0ec24c22010-01-28 19:02:36 +00002431 if (ret)
snelsone42c3802010-05-07 20:09:04 +00002432 msg_pinfo("FAILED!\n");
uwe0ec24c22010-01-28 19:02:36 +00002433 else
snelsone42c3802010-05-07 20:09:04 +00002434 msg_pinfo("OK.\n");
uwe0ec24c22010-01-28 19:02:36 +00002435 }
uwef6641642007-05-09 10:17:44 +00002436 }
stepan927d4e22007-04-04 22:45:58 +00002437
uwef6641642007-05-09 10:17:44 +00002438 return ret;
stepan927d4e22007-04-04 22:45:58 +00002439}