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>
39 #define MAINBOARD_POWER_OFF 0
40 #define MAINBOARD_POWER_ON 1
42 #ifndef MAINBOARD_POWER_ON_AFTER_FAIL
43 #define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON
46 #define ALL (0xff << 24)
48 #define DISABLED (1 << 16)
49 #define ENABLED (0 << 16)
50 #define TRIGGER_EDGE (0 << 15)
51 #define TRIGGER_LEVEL (1 << 15)
52 #define POLARITY_HIGH (0 << 13)
53 #define POLARITY_LOW (1 << 13)
54 #define PHYSICAL_DEST (0 << 11)
55 #define LOGICAL_DEST (1 << 11)
56 #define ExtINT (7 << 8)
61 static void setup_ioapic(device_t dev)
64 u32 value_low, value_high;
65 u32 ioapic_base = 0xfec00000;
71 res = find_resource(dev, RCBA);
75 *((u8 *)(res->base + 0x31ff)) |= (1 << 0);
77 l = (u32 *) ioapic_base;
80 interrupts = (l[04] >> 16) & 0xff;
81 for (i = 0; i < interrupts; i++) {
82 l[0] = (i * 2) + 0x10;
85 l[0] = (i * 2) + 0x11;
86 l[4] = NONE; /* Should this be an address? */
88 if (value_low == 0xffffffff) {
89 printk_warning("%d IO APIC not responding.\n",
95 /* Put the APIC in virtual wire mode */
97 l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
100 #define SERIRQ_CNTL 0x64
101 static void i3100_enable_serial_irqs(device_t dev)
103 /* set packet length and toggle silent mode bit */
104 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
105 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
108 typedef struct southbridge_intel_i3100_config config_t;
110 static void set_i3100_gpio_use_sel(
111 device_t dev, struct resource *res, config_t *config)
113 u32 gpio_use_sel, gpio_use_sel2;
115 gpio_use_sel = 0x1b0ce7c3;
116 gpio_use_sel2 = 0x00000107;
117 outl(gpio_use_sel, res->base + 0x00);
118 outl(gpio_use_sel2, res->base + 0x30);
121 static void set_i3100_gpio_direction(
122 device_t dev, struct resource *res, config_t *config)
124 u32 gpio_io_sel, gpio_io_sel2;
126 gpio_io_sel = 0xed00ffff;
127 gpio_io_sel2 = 0x00000307;
128 outl(gpio_io_sel, res->base + 0x04);
129 outl(gpio_io_sel2, res->base + 0x34);
132 static void set_i3100_gpio_level(
133 device_t dev, struct resource *res, config_t *config)
135 u32 gpio_lvl, gpio_lvl2;
138 gpio_lvl = 0x00030000;
139 gpio_blink = 0x00000000;
140 gpio_lvl2 = 0x00000300;
141 outl(gpio_lvl, res->base + 0x0c);
142 outl(gpio_blink, res->base + 0x18);
143 outl(gpio_lvl2, res->base + 0x38);
146 static void set_i3100_gpio_inv(
147 device_t dev, struct resource *res, config_t *config)
151 gpio_inv = 0x00006000;
152 outl(gpio_inv, res->base + 0x2c);
155 static void i3100_pirq_init(device_t dev)
159 /* Get the chip configuration */
160 config = dev->chip_info;
162 if(config->pirq_a_d) {
163 pci_write_config32(dev, 0x60, config->pirq_a_d);
165 if(config->pirq_e_h) {
166 pci_write_config32(dev, 0x68, config->pirq_e_h);
171 static void i3100_gpio_init(device_t dev)
173 struct resource *res;
176 /* Skip if I don't have any configuration */
177 if (!dev->chip_info) {
180 /* The programmer is responsible for ensuring
181 * a valid gpio configuration.
184 /* Get the chip configuration */
185 config = dev->chip_info;
186 /* Find the GPIO bar */
187 res = find_resource(dev, GPIO_BAR);
192 /* Set the use selects */
193 set_i3100_gpio_use_sel(dev, res, config);
195 /* Set the IO direction */
196 set_i3100_gpio_direction(dev, res, config);
198 /* Setup the input inverters */
199 set_i3100_gpio_inv(dev, res, config);
201 /* Set the value on the GPIO output pins */
202 set_i3100_gpio_level(dev, res, config);
207 static void lpc_init(struct device *dev)
210 int pwr_on = MAINBOARD_POWER_ON_AFTER_FAIL;
214 /* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
215 pci_write_config32(dev, 0xd0, 0x00000000);
217 i3100_enable_serial_irqs(dev);
219 get_option(&pwr_on, "power_on_after_fail");
220 byte = pci_read_config8(dev, 0xa4);
225 pci_write_config8(dev, 0xa4, byte);
226 printk_info("set power %s after power fail\n", pwr_on ? "on" : "off");
228 /* Set up the PIRQ */
229 i3100_pirq_init(dev);
231 /* Set the state of the gpio lines */
232 i3100_gpio_init(dev);
234 /* Initialize the real time clock */
237 /* Initialize isa dma */
241 static void i3100_lpc_read_resources(device_t dev)
243 struct resource *res;
245 /* Get the normal pci resources of this device */
246 pci_dev_read_resources(dev);
248 /* Add the ACPI BAR */
249 res = pci_get_resource(dev, ACPI_BAR);
251 /* Add the GPIO BAR */
252 res = pci_get_resource(dev, GPIO_BAR);
254 /* Add an extra subtractive resource for both memory and I/O */
255 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
256 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
258 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
259 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
261 /* Add resource for RCBA */
262 res = new_resource(dev, RCBA);
264 res->limit = 0xffffc000;
267 res->flags = IORESOURCE_MEM;
270 static void i3100_lpc_enable_resources(device_t dev)
272 u8 acpi_cntl, gpio_cntl;
274 /* Enable the normal pci resources */
275 pci_dev_enable_resources(dev);
277 /* Enable the ACPI bar */
278 acpi_cntl = pci_read_config8(dev, 0x44);
279 acpi_cntl |= (1 << 4);
280 pci_write_config8(dev, 0x44, acpi_cntl);
282 /* Enable the GPIO bar */
283 gpio_cntl = pci_read_config8(dev, 0x4c);
284 gpio_cntl |= (1 << 4);
285 pci_write_config8(dev, 0x4c, gpio_cntl);
287 /* Enable the RCBA */
288 pci_write_config32(dev, RCBA, pci_read_config32(dev, RCBA) | (1 << 0));
290 enable_childrens_resources(dev);
293 static struct pci_operations lops_pci = {
297 static struct device_operations lpc_ops = {
298 .read_resources = i3100_lpc_read_resources,
299 .set_resources = pci_dev_set_resources,
300 .enable_resources = i3100_lpc_enable_resources,
302 .scan_bus = scan_static_bus,
303 .enable = i3100_enable,
304 .ops_pci = &lops_pci,
307 static struct pci_driver lpc_driver __pci_driver = {
309 .vendor = PCI_VENDOR_ID_INTEL,
310 .device = PCI_DEVICE_ID_INTEL_3100_LPC,