2 * This file is part of the coreboot project.
4 * Copyright (C) 2004 Linux Networx
5 * Copyright (C) 2008 Arastra, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 /* This code is based on src/southbridge/intel/esb6300/esb6300_lpc.c */
24 #include <console/console.h>
25 #include <device/device.h>
26 #include <device/pci.h>
27 #include <device/pci_ids.h>
28 #include <device/pci_ops.h>
29 #include <pc80/mc146818rtc.h>
30 #include <pc80/isa-dma.h>
32 #include <arch/ioapic.h>
39 #define SERIRQ_CNTL 0x64
41 #define GEN_PMCON_1 0xA0
42 #define GEN_PMCON_2 0xA2
43 #define GEN_PMCON_3 0xA4
46 #define MAINBOARD_POWER_OFF 0
47 #define MAINBOARD_POWER_ON 1
49 #ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
50 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
53 static void i3100_enable_serial_irqs(device_t dev)
55 /* set packet length and toggle silent mode bit */
56 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
57 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
60 typedef struct southbridge_intel_i3100_config config_t;
62 static void set_i3100_gpio_use_sel(
63 device_t dev, struct resource *res, config_t *config)
65 u32 gpio_use_sel, gpio_use_sel2;
68 gpio_use_sel = inl(res->base + 0x00) | 0x0000c603;
69 gpio_use_sel2 = inl(res->base + 0x30) | 0x00000100;
70 for (i = 0; i < 64; i++) {
72 switch (config->gpio[i] & I3100_GPIO_USE_MASK) {
73 case I3100_GPIO_USE_AS_NATIVE:
76 case I3100_GPIO_USE_AS_GPIO:
82 /* The caller is responsible for not playing with unimplemented bits */
84 gpio_use_sel &= ~(1 << i);
85 gpio_use_sel |= (val << i);
87 gpio_use_sel2 &= ~(1 << (i - 32));
88 gpio_use_sel2 |= (val << (i - 32));
91 outl(gpio_use_sel, res->base + 0x00);
92 outl(gpio_use_sel2, res->base + 0x30);
95 static void set_i3100_gpio_direction(
96 device_t dev, struct resource *res, config_t *config)
98 u32 gpio_io_sel, gpio_io_sel2;
101 gpio_io_sel = inl(res->base + 0x04);
102 gpio_io_sel2 = inl(res->base + 0x34);
103 for (i = 0; i < 64; i++) {
105 switch (config->gpio[i] & I3100_GPIO_SEL_MASK) {
106 case I3100_GPIO_SEL_OUTPUT:
109 case I3100_GPIO_SEL_INPUT:
115 /* The caller is responsible for not playing with unimplemented bits */
117 gpio_io_sel &= ~(1 << i);
118 gpio_io_sel |= (val << i);
120 gpio_io_sel2 &= ~(1 << (i - 32));
121 gpio_io_sel2 |= (val << (i - 32));
124 outl(gpio_io_sel, res->base + 0x04);
125 outl(gpio_io_sel2, res->base + 0x34);
128 static void set_i3100_gpio_level(
129 device_t dev, struct resource *res, config_t *config)
131 u32 gpio_lvl, gpio_lvl2;
135 gpio_lvl = inl(res->base + 0x0c);
136 gpio_blink = inl(res->base + 0x18);
137 gpio_lvl2 = inl(res->base + 0x38);
138 for (i = 0; i < 64; i++) {
140 switch (config->gpio[i] & I3100_GPIO_LVL_MASK) {
141 case I3100_GPIO_LVL_LOW:
145 case I3100_GPIO_LVL_HIGH:
149 case I3100_GPIO_LVL_BLINK:
156 /* The caller is responsible for not playing with unimplemented bits */
158 gpio_lvl &= ~(1 << i);
159 gpio_blink &= ~(1 << i);
160 gpio_lvl |= (val << i);
161 gpio_blink |= (blink << i);
163 gpio_lvl2 &= ~(1 << (i - 32));
164 gpio_lvl2 |= (val << (i - 32));
167 outl(gpio_lvl, res->base + 0x0c);
168 outl(gpio_blink, res->base + 0x18);
169 outl(gpio_lvl2, res->base + 0x38);
172 static void set_i3100_gpio_inv(
173 device_t dev, struct resource *res, config_t *config)
178 gpio_inv = inl(res->base + 0x2c);
179 for (i = 0; i < 32; i++) {
181 switch (config->gpio[i] & I3100_GPIO_INV_MASK) {
182 case I3100_GPIO_INV_OFF:
185 case I3100_GPIO_INV_ON:
191 gpio_inv &= ~(1 << i);
192 gpio_inv |= (val << i);
194 outl(gpio_inv, res->base + 0x2c);
197 static void i3100_pirq_init(device_t dev)
201 /* Get the chip configuration */
202 config = dev->chip_info;
204 if(config->pirq_a_d) {
205 pci_write_config32(dev, 0x60, config->pirq_a_d);
207 if(config->pirq_e_h) {
208 pci_write_config32(dev, 0x68, config->pirq_e_h);
212 static void i3100_power_options(device_t dev) {
215 int pwr_on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
218 /* Which state do we want to goto after g3 (power restored)?
222 get_option(&pwr_on, "power_on_after_fail");
223 reg8 = pci_read_config8(dev, GEN_PMCON_3);
230 /* avoid #S4 assertions */
232 /* minimum asssertion is 1 to 2 RTCCLK */
234 pci_write_config8(dev, GEN_PMCON_3, reg8);
235 printk(BIOS_INFO, "set power %s after power fail\n", pwr_on ? "on" : "off");
237 /* Set up NMI on errors. */
239 /* Higher Nibble must be 0 */
241 /* IOCHK# NMI Enable */
243 /* PCI SERR# Enable */
244 // reg8 &= ~(1 << 2);
245 /* PCI SERR# Disable for now */
250 nmi_option = NMI_OFF;
251 get_option(&nmi_option, "nmi");
254 printk(BIOS_INFO, "NMI sources enabled.\n");
257 /* Can't mask NMI from PCI-E and NMI_NOW */
258 printk(BIOS_INFO, "NMI sources disabled.\n");
263 // Enable CPU_SLP# and Intel Speedstep, set SMI# rate down
264 reg16 = pci_read_config16(dev, GEN_PMCON_1);
265 reg16 &= ~((3 << 0) | (1 << 10));
266 reg16 |= (1 << 3) | (1 << 5);
268 // reg16 |= (1 << 2);
269 pci_write_config16(dev, GEN_PMCON_1, reg16);
271 // Set the board's GPI routing.
272 // i82801gx_gpi_routing(dev);
275 static void i3100_gpio_init(device_t dev)
277 struct resource *res;
280 /* Skip if I don't have any configuration */
281 if (!dev->chip_info) {
284 /* The programmer is responsible for ensuring
285 * a valid gpio configuration.
288 /* Get the chip configuration */
289 config = dev->chip_info;
290 /* Find the GPIO bar */
291 res = find_resource(dev, GPIO_BAR);
296 /* Set the use selects */
297 set_i3100_gpio_use_sel(dev, res, config);
299 /* Set the IO direction */
300 set_i3100_gpio_direction(dev, res, config);
302 /* Setup the input inverters */
303 set_i3100_gpio_inv(dev, res, config);
305 /* Set the value on the GPIO output pins */
306 set_i3100_gpio_level(dev, res, config);
311 static void lpc_init(struct device *dev)
313 struct resource *res;
316 res = find_resource(dev, RCBA);
320 *((u8 *)((u32)res->base + 0x31ff)) |= (1 << 0);
322 // TODO this code sets int 0 of the IOAPIC in Virtual Wire Mode
323 // (register 0x10/0x11) while the old code used int 1 (register 0x12)
325 setup_ioapic(IO_APIC_ADDR, 0); // Don't rename IOAPIC ID
327 /* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
328 pci_write_config32(dev, 0xd0, 0x00000000);
330 i3100_enable_serial_irqs(dev);
332 /* Set up the PIRQ */
333 i3100_pirq_init(dev);
335 /* Setup power options */
336 i3100_power_options(dev);
338 /* Set the state of the gpio lines */
339 i3100_gpio_init(dev);
341 /* Initialize the real time clock */
344 /* Initialize isa dma */
348 static void i3100_lpc_read_resources(device_t dev)
350 struct resource *res;
352 /* Get the normal pci resources of this device */
353 pci_dev_read_resources(dev);
355 /* Add the ACPI BAR */
356 res = pci_get_resource(dev, ACPI_BAR);
358 /* Add the GPIO BAR */
359 res = pci_get_resource(dev, GPIO_BAR);
361 /* Add an extra subtractive resource for both memory and I/O. */
362 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
365 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
366 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
368 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
369 res->base = 0xff800000;
370 res->size = 0x00800000; /* 8 MB for flash */
371 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
372 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
374 res = new_resource(dev, 3); /* IOAPIC */
375 res->base = IO_APIC_ADDR;
376 res->size = 0x00001000;
377 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
379 /* Add resource for RCBA */
380 res = new_resource(dev, RCBA);
382 res->limit = 0xffffc000;
385 res->flags = IORESOURCE_MEM;
388 static void i3100_lpc_enable_resources(device_t dev)
390 u8 acpi_cntl, gpio_cntl;
392 /* Enable the normal pci resources */
393 pci_dev_enable_resources(dev);
395 /* Enable the ACPI bar */
396 acpi_cntl = pci_read_config8(dev, 0x44);
397 acpi_cntl |= (1 << 7);
398 pci_write_config8(dev, 0x44, acpi_cntl);
400 /* Enable the GPIO bar */
401 gpio_cntl = pci_read_config8(dev, 0x4c);
402 gpio_cntl |= (1 << 4);
403 pci_write_config8(dev, 0x4c, gpio_cntl);
405 /* Enable the RCBA */
406 pci_write_config32(dev, RCBA, pci_read_config32(dev, RCBA) | (1 << 0));
409 static struct pci_operations lops_pci = {
413 static struct device_operations lpc_ops = {
414 .read_resources = i3100_lpc_read_resources,
415 .set_resources = pci_dev_set_resources,
416 .enable_resources = i3100_lpc_enable_resources,
418 .scan_bus = scan_static_bus,
419 .enable = i3100_enable,
420 .ops_pci = &lops_pci,
423 static const struct pci_driver lpc_driver __pci_driver = {
425 .vendor = PCI_VENDOR_ID_INTEL,
426 .device = PCI_DEVICE_ID_INTEL_3100_LPC,
429 static const struct pci_driver lpc_driver_ep80579 __pci_driver = {
431 .vendor = PCI_VENDOR_ID_INTEL,
432 .device = PCI_DEVICE_ID_INTEL_EP80579_LPC,