2 * This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * (C) 2004 Linux Networx
22 #include <console/console.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <device/pci_ops.h>
27 #include <pc80/mc146818rtc.h>
28 #include <pc80/isa-dma.h>
36 #define MAINBOARD_POWER_OFF 0
37 #define MAINBOARD_POWER_ON 1
39 #ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
40 #define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
43 #define ALL (0xff << 24)
45 #define DISABLED (1 << 16)
46 #define ENABLED (0 << 16)
47 #define TRIGGER_EDGE (0 << 15)
48 #define TRIGGER_LEVEL (1 << 15)
49 #define POLARITY_HIGH (0 << 13)
50 #define POLARITY_LOW (1 << 13)
51 #define PHYSICAL_DEST (0 << 11)
52 #define LOGICAL_DEST (1 << 11)
53 #define ExtINT (7 << 8)
58 static void setup_ioapic(void)
61 unsigned long value_low, value_high;
62 unsigned long ioapic_base = 0xfec00000;
63 volatile unsigned long *l;
66 l = (unsigned long *) ioapic_base;
69 interrupts = (l[04] >> 16) & 0xff;
70 for (i = 0; i < interrupts; i++) {
71 l[0] = (i * 2) + 0x10;
74 l[0] = (i * 2) + 0x11;
75 l[4] = NONE; /* Should this be an address? */
77 if (value_low == 0xffffffff) {
78 printk_warning("IO APIC not responding.\n");
83 /* Put the ioapic in virtual wire mode */
85 l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
88 #define SERIRQ_CNTL 0x64
89 static void i82801db_enable_serial_irqs(device_t dev)
91 /* set packet length and toggle silent mode bit */
92 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
93 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
96 #define PCI_DMA_CFG 0x90
97 static void i82801db_pci_dma_cfg(device_t dev)
99 /* Set PCI DMA CFG to lpc I/F DMA
100 pci_write_config16(dev, PCI_DMA_CFG, 0xfcff); */
101 pci_write_config16(dev, PCI_DMA_CFG, 0x5455);
105 static void i82801db_enable_lpc(device_t dev)
108 pci_write_config8(dev, LPC_EN, 0x0d); */
109 pci_write_config16(dev, LPC_EN, 0x3403);
112 typedef struct southbridge_intel_i82801db_config config_t;
114 static void set_i82801db_gpio_use_sel(
115 device_t dev, struct resource *res, config_t *config)
117 uint32_t gpio_use_sel, gpio_use_sel2;
120 gpio_use_sel = 0x1A003180;
121 gpio_use_sel2 = 0x00000007;
122 for(i = 0; i < 64; i++) {
124 switch(config->gpio[i] & ICH5R_GPIO_USE_MASK) {
125 case ICH5R_GPIO_USE_AS_NATIVE: val = 0; break;
126 case ICH5R_GPIO_USE_AS_GPIO: val = 1; break;
130 /* The caller is responsible for not playing with unimplemented bits */
132 gpio_use_sel &= ~( 1 << i);
133 gpio_use_sel |= (val << i);
135 gpio_use_sel2 &= ~( 1 << (i - 32));
136 gpio_use_sel2 |= (val << (i - 32));
139 outl(gpio_use_sel, res->base + 0x00);
140 outl(gpio_use_sel2, res->base + 0x30);
143 static void set_i82801db_gpio_direction(
144 device_t dev, struct resource *res, config_t *config)
146 uint32_t gpio_io_sel, gpio_io_sel2;
149 gpio_io_sel = 0x0000ffff;
150 gpio_io_sel2 = 0x00000300;
151 for(i = 0; i < 64; i++) {
153 switch(config->gpio[i] & ICH5R_GPIO_SEL_MASK) {
154 case ICH5R_GPIO_SEL_OUTPUT: val = 0; break;
155 case ICH5R_GPIO_SEL_INPUT: val = 1; break;
159 /* The caller is responsible for not playing with unimplemented bits */
161 gpio_io_sel &= ~( 1 << i);
162 gpio_io_sel |= (val << i);
164 gpio_io_sel2 &= ~( 1 << (i - 32));
165 gpio_io_sel2 |= (val << (i - 32));
168 outl(gpio_io_sel, res->base + 0x04);
169 outl(gpio_io_sel2, res->base + 0x34);
172 static void set_i82801db_gpio_level(
173 device_t dev, struct resource *res, config_t *config)
175 uint32_t gpio_lvl, gpio_lvl2;
179 gpio_lvl = 0x1b3f0000;
180 gpio_blink = 0x00040000;
181 gpio_lvl2 = 0x00030207;
182 for(i = 0; i < 64; i++) {
184 switch(config->gpio[i] & ICH5R_GPIO_LVL_MASK) {
185 case ICH5R_GPIO_LVL_LOW: val = 0; blink = 0; break;
186 case ICH5R_GPIO_LVL_HIGH: val = 1; blink = 0; break;
187 case ICH5R_GPIO_LVL_BLINK: val = 1; blink = 1; break;
191 /* The caller is responsible for not playing with unimplemented bits */
193 gpio_lvl &= ~( 1 << i);
194 gpio_blink &= ~( 1 << i);
195 gpio_lvl |= ( val << i);
196 gpio_blink |= (blink << i);
198 gpio_lvl2 &= ~( 1 << (i - 32));
199 gpio_lvl2 |= (val << (i - 32));
202 outl(gpio_lvl, res->base + 0x0c);
203 outl(gpio_blink, res->base + 0x18);
204 outl(gpio_lvl2, res->base + 0x38);
207 static void set_i82801db_gpio_inv(
208 device_t dev, struct resource *res, config_t *config)
213 gpio_inv = 0x00000000;
214 for(i = 0; i < 32; i++) {
216 switch(config->gpio[i] & ICH5R_GPIO_INV_MASK) {
217 case ICH5R_GPIO_INV_OFF: val = 0; break;
218 case ICH5R_GPIO_INV_ON: val = 1; break;
222 gpio_inv &= ~( 1 << i);
223 gpio_inv |= (val << i);
225 outl(gpio_inv, res->base + 0x2c);
228 static void i82801db_pirq_init(device_t dev)
232 /* Get the chip configuration */
233 config = dev->chip_info;
235 if(config->pirq_a_d) {
236 printk_debug("\n\nIRQs A to D = %04x\n\n", config->pirq_a_d);
237 pci_write_config32(dev, 0x60, config->pirq_a_d);
239 if(config->pirq_e_h) {
240 printk_debug("\n\nIRQs e to h = %04x\n\n", config->pirq_e_h);
241 pci_write_config32(dev, 0x68, config->pirq_e_h);
246 static void i82801db_gpio_init(device_t dev)
248 struct resource *res;
251 /* Skip if I don't have any configuration */
252 if (!dev->chip_info) {
255 /* The programmer is responsible for ensuring
256 * a valid gpio configuration.
259 /* Get the chip configuration */
260 config = dev->chip_info;
261 /* Find the GPIO bar */
262 res = find_resource(dev, GPIO_BAR);
267 /* Set the use selects */
268 set_i82801db_gpio_use_sel(dev, res, config);
270 /* Set the IO direction */
271 set_i82801db_gpio_direction(dev, res, config);
273 /* Setup the input inverters */
274 set_i82801db_gpio_inv(dev, res, config);
276 /* Set the value on the GPIO output pins */
277 set_i82801db_gpio_level(dev, res, config);
281 static void enable_hpet(struct device *dev)
283 const unsigned long hpet_address = 0xfed0000;
286 uint32_t code = (0 & 0x3);
288 dword = pci_read_config32(dev, GEN_CNTL);
289 dword |= (1 << 17); /* enable hpet */
291 /* Bits [16:15] Memory Address Range
292 * 00 FED0_0000h - FED0_03FFh
293 * 01 FED0_1000h - FED0_13FFh
294 * 10 FED0_2000h - FED0_23FFh
295 * 11 FED0_3000h - FED0_33FFh
298 dword &= ~(3 << 15); /* clear it */
301 printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
304 static void lpc_init(struct device *dev)
308 int pwr_on=MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
310 /* IO APIC initialization */
311 value = pci_read_config32(dev, 0xd0);
312 value |= (1 << 8)|(1<<7)|(1<<1);
313 pci_write_config32(dev, 0xd0, value);
314 value = pci_read_config32(dev, 0xd4);
316 pci_write_config32(dev, 0xd4, value);
319 i82801db_enable_serial_irqs(dev);
321 i82801db_pci_dma_cfg(dev);
323 i82801db_enable_lpc(dev);
325 /* Clear SATA to non raid
326 pci_write_config8(dev, 0xae, 0x00);
329 get_option(&pwr_on, "power_on_after_fail");
330 byte = pci_read_config8(dev, 0xa4);
335 pci_write_config8(dev, 0xa4, byte);
336 printk_info("set power %s after power fail\n", pwr_on?"on":"off");
338 /* Set up the PIRQ */
339 i82801db_pirq_init(dev);
341 /* Set the state of the gpio lines */
342 i82801db_gpio_init(dev);
344 /* Initialize the real time clock */
347 /* Initialize isa dma */
350 /* Disable IDE (needed when sata is enabled)
351 pci_write_config8(dev, 0xf2, 0x60);
357 static void i82801db_lpc_read_resources(device_t dev)
359 struct resource *res;
361 /* Get the normal pci resources of this device */
362 pci_dev_read_resources(dev);
364 /* Add the ACPI BAR */
365 res = pci_get_resource(dev, ACPI_BAR);
367 /* Add the GPIO BAR */
368 res = pci_get_resource(dev, GPIO_BAR);
370 /* Add an extra subtractive resource for both memory and I/O */
371 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
372 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
374 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
375 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
378 static void i82801db_lpc_enable_resources(device_t dev)
380 uint8_t acpi_cntl, gpio_cntl;
382 /* Enable the normal pci resources */
383 pci_dev_enable_resources(dev);
385 /* Enable the ACPI bar */
386 acpi_cntl = pci_read_config8(dev, 0x44);
387 acpi_cntl |= (1 << 4);
388 pci_write_config8(dev, 0x44, acpi_cntl);
390 /* Enable the GPIO bar */
391 gpio_cntl = pci_read_config8(dev, 0x5c);
392 gpio_cntl |= (1 << 4);
393 pci_write_config8(dev, 0x5c, gpio_cntl);
395 enable_childrens_resources(dev);
398 static struct pci_operations lops_pci = {
402 static struct device_operations lpc_ops = {
403 .read_resources = i82801db_lpc_read_resources,
404 .set_resources = pci_dev_set_resources,
405 .enable_resources = i82801db_lpc_enable_resources,
407 .scan_bus = scan_static_bus,
408 .enable = i82801db_enable,
409 .ops_pci = &lops_pci,
412 static const struct pci_driver lpc_driver __pci_driver = {
414 .vendor = PCI_VENDOR_ID_INTEL,
415 .device = PCI_DEVICE_ID_INTEL_82801DB_LPC,