2 * (C) 2004 Linux Networx
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <pc80/mc146818rtc.h>
10 #include <pc80/isa-dma.h>
18 #define MAINBOARD_POWER_OFF 0
19 #define MAINBOARD_POWER_ON 1
21 #ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
22 #define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
25 #define ALL (0xff << 24)
27 #define DISABLED (1 << 16)
28 #define ENABLED (0 << 16)
29 #define TRIGGER_EDGE (0 << 15)
30 #define TRIGGER_LEVEL (1 << 15)
31 #define POLARITY_HIGH (0 << 13)
32 #define POLARITY_LOW (1 << 13)
33 #define PHYSICAL_DEST (0 << 11)
34 #define LOGICAL_DEST (1 << 11)
35 #define ExtINT (7 << 8)
40 static void setup_ioapic(void)
43 unsigned long value_low, value_high;
44 unsigned long ioapic_base = 0xfec00000;
45 volatile unsigned long *l;
48 l = (unsigned long *) ioapic_base;
51 interrupts = (l[04] >> 16) & 0xff;
52 for (i = 0; i < interrupts; i++) {
53 l[0] = (i * 2) + 0x10;
56 l[0] = (i * 2) + 0x11;
57 l[4] = NONE; /* Should this be an address? */
59 if (value_low == 0xffffffff) {
60 printk_warning("IO APIC not responding.\n");
65 /* Put the ioapic in virtual wire mode */
67 l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
70 #define SERIRQ_CNTL 0x64
71 static void i82801er_enable_serial_irqs(device_t dev)
73 /* set packet length and toggle silent mode bit */
74 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
75 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
78 #define PCI_DMA_CFG 0x90
79 static void i82801er_pci_dma_cfg(device_t dev)
81 /* Set PCI DMA CFG to lpc I/F DMA */
82 pci_write_config16(dev, PCI_DMA_CFG, 0xfcff);
86 static void i82801er_enable_lpc(device_t dev)
89 pci_write_config8(dev, LPC_EN, 0x0d);
92 typedef struct southbridge_intel_i82801er_config config_t;
94 static void set_i82801er_gpio_use_sel(
95 device_t dev, struct resource *res, config_t *config)
97 uint32_t gpio_use_sel, gpio_use_sel2;
100 gpio_use_sel = 0x1A003180;
101 gpio_use_sel2 = 0x00000007;
102 for(i = 0; i < 64; i++) {
104 switch(config->gpio[i] & ICH5R_GPIO_USE_MASK) {
105 case ICH5R_GPIO_USE_AS_NATIVE: val = 0; break;
106 case ICH5R_GPIO_USE_AS_GPIO: val = 1; break;
110 /* The caller is responsible for not playing with unimplemented bits */
112 gpio_use_sel &= ~( 1 << i);
113 gpio_use_sel |= (val << i);
115 gpio_use_sel2 &= ~( 1 << (i - 32));
116 gpio_use_sel2 |= (val << (i - 32));
119 outl(gpio_use_sel, res->base + 0x00);
120 outl(gpio_use_sel2, res->base + 0x30);
123 static void set_i82801er_gpio_direction(
124 device_t dev, struct resource *res, config_t *config)
126 uint32_t gpio_io_sel, gpio_io_sel2;
129 gpio_io_sel = 0x0000ffff;
130 gpio_io_sel2 = 0x00000300;
131 for(i = 0; i < 64; i++) {
133 switch(config->gpio[i] & ICH5R_GPIO_SEL_MASK) {
134 case ICH5R_GPIO_SEL_OUTPUT: val = 0; break;
135 case ICH5R_GPIO_SEL_INPUT: val = 1; break;
139 /* The caller is responsible for not playing with unimplemented bits */
141 gpio_io_sel &= ~( 1 << i);
142 gpio_io_sel |= (val << i);
144 gpio_io_sel2 &= ~( 1 << (i - 32));
145 gpio_io_sel2 |= (val << (i - 32));
148 outl(gpio_io_sel, res->base + 0x04);
149 outl(gpio_io_sel2, res->base + 0x34);
152 static void set_i82801er_gpio_level(
153 device_t dev, struct resource *res, config_t *config)
155 uint32_t gpio_lvl, gpio_lvl2;
159 gpio_lvl = 0x1b3f0000;
160 gpio_blink = 0x00040000;
161 gpio_lvl2 = 0x00030207;
162 for(i = 0; i < 64; i++) {
164 switch(config->gpio[i] & ICH5R_GPIO_LVL_MASK) {
165 case ICH5R_GPIO_LVL_LOW: val = 0; blink = 0; break;
166 case ICH5R_GPIO_LVL_HIGH: val = 1; blink = 0; break;
167 case ICH5R_GPIO_LVL_BLINK: val = 1; blink = 1; break;
171 /* The caller is responsible for not playing with unimplemented bits */
173 gpio_lvl &= ~( 1 << i);
174 gpio_blink &= ~( 1 << i);
175 gpio_lvl |= ( val << i);
176 gpio_blink |= (blink << i);
178 gpio_lvl2 &= ~( 1 << (i - 32));
179 gpio_lvl2 |= (val << (i - 32));
182 outl(gpio_lvl, res->base + 0x0c);
183 outl(gpio_blink, res->base + 0x18);
184 outl(gpio_lvl2, res->base + 0x38);
187 static void set_i82801er_gpio_inv(
188 device_t dev, struct resource *res, config_t *config)
193 gpio_inv = 0x00000000;
194 for(i = 0; i < 32; i++) {
196 switch(config->gpio[i] & ICH5R_GPIO_INV_MASK) {
197 case ICH5R_GPIO_INV_OFF: val = 0; break;
198 case ICH5R_GPIO_INV_ON: val = 1; break;
202 gpio_inv &= ~( 1 << i);
203 gpio_inv |= (val << i);
205 outl(gpio_inv, res->base + 0x2c);
208 static void i82801er_pirq_init(device_t dev)
212 /* Get the chip configuration */
213 config = dev->chip_info;
215 if(config->pirq_a_d) {
216 pci_write_config32(dev, 0x60, config->pirq_a_d);
218 if(config->pirq_e_h) {
219 pci_write_config32(dev, 0x68, config->pirq_e_h);
224 static void i82801er_gpio_init(device_t dev)
226 struct resource *res;
229 /* Skip if I don't have any configuration */
230 if (!dev->chip_info) {
233 /* The programmer is responsible for ensuring
234 * a valid gpio configuration.
237 /* Get the chip configuration */
238 config = dev->chip_info;
239 /* Find the GPIO bar */
240 res = find_resource(dev, GPIO_BAR);
245 /* Set the use selects */
246 set_i82801er_gpio_use_sel(dev, res, config);
248 /* Set the IO direction */
249 set_i82801er_gpio_direction(dev, res, config);
251 /* Setup the input inverters */
252 set_i82801er_gpio_inv(dev, res, config);
254 /* Set the value on the GPIO output pins */
255 set_i82801er_gpio_level(dev, res, config);
259 static void enable_hpet(struct device *dev)
261 const unsigned long hpet_address = 0xfed0000;
264 uint32_t code = (0 & 0x3);
266 dword = pci_read_config32(dev, GEN_CNTL);
267 dword |= (1 << 17); /* enable hpet */
269 /* Bits [16:15] Memory Address Range
270 * 00 FED0_0000h - FED0_03FFh
271 * 01 FED0_1000h - FED0_13FFh
272 * 10 FED0_2000h - FED0_23FFh
273 * 11 FED0_3000h - FED0_33FFh
276 dword &= ~(3 << 15); /* clear it */
279 printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
282 static void lpc_init(struct device *dev)
286 uint32_t pwr_on=MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
288 /* IO APIC initialization */
289 value = pci_read_config32(dev, 0xd0);
290 value |= (1 << 8)|(1<<7)|(1<<1);
291 pci_write_config32(dev, 0xd0, value);
292 value = pci_read_config32(dev, 0xd4);
294 pci_write_config32(dev, 0xd4, value);
297 i82801er_enable_serial_irqs(dev);
299 i82801er_pci_dma_cfg(dev);
301 i82801er_enable_lpc(dev);
303 /* Clear SATA to non raid */
304 pci_write_config8(dev, 0xae, 0x00);
306 get_option("power_on_after_fail", &pwr_on);
307 byte = pci_read_config8(dev, 0xa4);
312 pci_write_config8(dev, 0xa4, byte);
313 printk_info("set power %s after power fail\n", pwr_on?"on":"off");
315 /* Set up the PIRQ */
316 i82801er_pirq_init(dev);
318 /* Set the state of the gpio lines */
319 i82801er_gpio_init(dev);
321 /* Initialize the real time clock */
324 /* Initialize isa dma */
327 /* Disable IDE (needed when sata is enabled) */
328 pci_write_config8(dev, 0xf2, 0x60);
333 static void i82801er_lpc_read_resources(device_t dev)
335 struct resource *res;
337 /* Get the normal pci resources of this device */
338 pci_dev_read_resources(dev);
340 /* Add the ACPI BAR */
341 res = pci_get_resource(dev, ACPI_BAR);
343 /* Add the GPIO BAR */
344 res = pci_get_resource(dev, GPIO_BAR);
346 /* Add an extra subtractive resource for both memory and I/O */
347 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
348 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
350 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
351 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
354 static void i82801er_lpc_enable_resources(device_t dev)
356 uint8_t acpi_cntl, gpio_cntl;
358 /* Enable the normal pci resources */
359 pci_dev_enable_resources(dev);
361 /* Enable the ACPI bar */
362 acpi_cntl = pci_read_config8(dev, 0x44);
363 acpi_cntl |= (1 << 4);
364 pci_write_config8(dev, 0x44, acpi_cntl);
366 /* Enable the GPIO bar */
367 gpio_cntl = pci_read_config8(dev, 0x5c);
368 gpio_cntl |= (1 << 4);
369 pci_write_config8(dev, 0x5c, gpio_cntl);
371 enable_childrens_resources(dev);
374 static struct pci_operations lops_pci = {
378 static struct device_operations lpc_ops = {
379 .read_resources = i82801er_lpc_read_resources,
380 .set_resources = pci_dev_set_resources,
381 .enable_resources = i82801er_lpc_enable_resources,
383 .scan_bus = scan_static_bus,
384 .enable = i82801er_enable,
385 .ops_pci = &lops_pci,
388 static const struct pci_driver lpc_driver __pci_driver = {
390 .vendor = PCI_VENDOR_ID_INTEL,
391 .device = PCI_DEVICE_ID_INTEL_82801ER_LPC,