We define IO_APIC_ADDR in <arch/ioapic.h>, let's use it.
[coreboot.git] / src / southbridge / intel / i3100 / i3100_lpc.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Linux Networx
5  * Copyright (C) 2008 Arastra, Inc.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 /* This code is based on src/southbridge/intel/esb6300/esb6300_lpc.c */
23
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>
31 #include <arch/io.h>
32 #include <arch/ioapic.h>
33 #include "i3100.h"
34
35 #define ACPI_BAR 0x40
36 #define GPIO_BAR 0x48
37 #define RCBA 0xf0
38
39 #define SERIRQ_CNTL 0x64
40
41 #define GEN_PMCON_1 0xA0
42 #define GEN_PMCON_2 0xA2
43 #define GEN_PMCON_3 0xA4
44
45 #define NMI_OFF 0
46 #define MAINBOARD_POWER_OFF 0
47 #define MAINBOARD_POWER_ON  1
48
49 #ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
50 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
51 #endif
52
53 static void i3100_enable_serial_irqs(device_t dev)
54 {
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));
58 }
59
60 typedef struct southbridge_intel_i3100_config config_t;
61
62 static void set_i3100_gpio_use_sel(
63         device_t dev, struct resource *res, config_t *config)
64 {
65         u32 gpio_use_sel, gpio_use_sel2;
66         int i;
67
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++) {
71                 int val;
72                 switch (config->gpio[i] & I3100_GPIO_USE_MASK) {
73                 case I3100_GPIO_USE_AS_NATIVE:
74                         val = 0;
75                         break;
76                 case I3100_GPIO_USE_AS_GPIO:
77                         val = 1;
78                         break;
79                 default:
80                         continue;
81                 }
82                 /* The caller is responsible for not playing with unimplemented bits */
83                 if (i < 32) {
84                         gpio_use_sel &= ~(1 << i);
85                         gpio_use_sel |= (val << i);
86                 } else {
87                         gpio_use_sel2 &= ~(1 << (i - 32));
88                         gpio_use_sel2 |= (val << (i - 32));
89                 }
90         }
91         outl(gpio_use_sel, res->base + 0x00);
92         outl(gpio_use_sel2, res->base + 0x30);
93 }
94
95 static void set_i3100_gpio_direction(
96         device_t dev, struct resource *res, config_t *config)
97 {
98         u32 gpio_io_sel, gpio_io_sel2;
99         int i;
100
101         gpio_io_sel = inl(res->base + 0x04);
102         gpio_io_sel2 = inl(res->base + 0x34);
103         for (i = 0; i < 64; i++) {
104                 int val;
105                 switch (config->gpio[i] & I3100_GPIO_SEL_MASK) {
106                 case I3100_GPIO_SEL_OUTPUT:
107                         val = 0;
108                         break;
109                 case I3100_GPIO_SEL_INPUT:
110                         val = 1;
111                         break;
112                 default:
113                         continue;
114                 }
115                 /* The caller is responsible for not playing with unimplemented bits */
116                 if (i < 32) {
117                         gpio_io_sel &= ~(1 << i);
118                         gpio_io_sel |= (val << i);
119                 } else {
120                         gpio_io_sel2 &= ~(1 << (i - 32));
121                         gpio_io_sel2 |= (val << (i - 32));
122                 }
123         }
124         outl(gpio_io_sel, res->base + 0x04);
125         outl(gpio_io_sel2, res->base + 0x34);
126 }
127
128 static void set_i3100_gpio_level(
129         device_t dev, struct resource *res, config_t *config)
130 {
131         u32 gpio_lvl, gpio_lvl2;
132         u32 gpio_blink;
133         int i;
134
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++) {
139                 int val, blink;
140                 switch (config->gpio[i] & I3100_GPIO_LVL_MASK) {
141                 case I3100_GPIO_LVL_LOW:
142                         val = 0;
143                         blink = 0;
144                         break;
145                 case I3100_GPIO_LVL_HIGH:
146                         val = 1;
147                         blink = 0;
148                         break;
149                 case I3100_GPIO_LVL_BLINK:
150                         val = 1;
151                         blink = 1;
152                         break;
153                 default:
154                         continue;
155                 }
156                 /* The caller is responsible for not playing with unimplemented bits */
157                 if (i < 32) {
158                         gpio_lvl &= ~(1 << i);
159                         gpio_blink &= ~(1 << i);
160                         gpio_lvl |= (val << i);
161                         gpio_blink |= (blink << i);
162                 } else {
163                         gpio_lvl2 &= ~(1 << (i - 32));
164                         gpio_lvl2 |= (val << (i - 32));
165                 }
166         }
167         outl(gpio_lvl, res->base + 0x0c);
168         outl(gpio_blink, res->base + 0x18);
169         outl(gpio_lvl2, res->base + 0x38);
170 }
171
172 static void set_i3100_gpio_inv(
173         device_t dev, struct resource *res, config_t *config)
174 {
175         u32 gpio_inv;
176         int i;
177
178         gpio_inv = inl(res->base + 0x2c);
179         for (i = 0; i < 32; i++) {
180                 int val;
181                 switch (config->gpio[i] & I3100_GPIO_INV_MASK) {
182                 case I3100_GPIO_INV_OFF:
183                         val = 0;
184                         break;
185                 case I3100_GPIO_INV_ON:
186                         val = 1;
187                         break;
188                 default:
189                         continue;
190                 }
191                 gpio_inv &= ~(1 << i);
192                 gpio_inv |= (val << i);
193         }
194         outl(gpio_inv, res->base + 0x2c);
195 }
196
197 static void i3100_pirq_init(device_t dev)
198 {
199         config_t *config;
200
201         /* Get the chip configuration */
202         config = dev->chip_info;
203
204         if(config->pirq_a_d) {
205                 pci_write_config32(dev, 0x60, config->pirq_a_d);
206         }
207         if(config->pirq_e_h) {
208                 pci_write_config32(dev, 0x68, config->pirq_e_h);
209         }
210 }
211
212 static void i3100_power_options(device_t dev) {
213   u8 reg8;
214   u16 reg16;
215   int pwr_on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
216   int nmi_option;
217
218   /* Which state do we want to goto after g3 (power restored)?
219    * 0 == S0 Full On
220    * 1 == S5 Soft Off
221    */
222   get_option(&pwr_on, "power_on_after_fail");
223   reg8 = pci_read_config8(dev, GEN_PMCON_3);
224   reg8 &= 0xfe;
225   if (pwr_on) {
226     reg8 &= ~1;
227   } else {
228     reg8 |= 1;
229   }
230   /* avoid #S4 assertions */
231   reg8 |= (3 << 4);
232   /* minimum asssertion is 1 to 2 RTCCLK */
233   reg8 &= ~(1 << 3);
234   pci_write_config8(dev, GEN_PMCON_3, reg8);
235   printk(BIOS_INFO, "set power %s after power fail\n", pwr_on ? "on" : "off");
236
237   /* Set up NMI on errors. */
238   reg8 = inb(0x61);
239   /* Higher Nibble must be 0 */
240   reg8 &= 0x0f;
241   /* IOCHK# NMI Enable */
242   reg8 &= ~(1 << 3);
243   /* PCI SERR# Enable */
244   // reg8 &= ~(1 << 2);
245   /* PCI SERR# Disable for now */
246   reg8 |= (1 << 2);
247   outb(reg8, 0x61);
248
249   reg8 = inb(0x70);
250   nmi_option = NMI_OFF;
251   get_option(&nmi_option, "nmi");
252   if (nmi_option) {
253     /* Set NMI. */
254     printk(BIOS_INFO, "NMI sources enabled.\n");
255     reg8 &= ~(1 << 7);
256   } else {
257     /* Can't mask NMI from PCI-E and NMI_NOW */
258     printk(BIOS_INFO, "NMI sources disabled.\n");
259     reg8 |= ( 1 << 7);
260   }
261   outb(reg8, 0x70);
262
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);
267   /* CLKRUN_EN */
268   // reg16 |= (1 << 2);
269   pci_write_config16(dev, GEN_PMCON_1, reg16);
270
271   // Set the board's GPI routing.
272   // i82801gx_gpi_routing(dev);
273 }
274
275 static void i3100_gpio_init(device_t dev)
276 {
277         struct resource *res;
278         config_t *config;
279
280         /* Skip if I don't have any configuration */
281         if (!dev->chip_info) {
282                 return;
283         }
284         /* The programmer is responsible for ensuring
285          * a valid gpio configuration.
286          */
287
288         /* Get the chip configuration */
289         config = dev->chip_info;
290         /* Find the GPIO bar */
291         res = find_resource(dev, GPIO_BAR);
292         if (!res) {
293                 return;
294         }
295
296         /* Set the use selects */
297         set_i3100_gpio_use_sel(dev, res, config);
298
299         /* Set the IO direction */
300         set_i3100_gpio_direction(dev, res, config);
301
302         /* Setup the input inverters */
303         set_i3100_gpio_inv(dev, res, config);
304
305         /* Set the value on the GPIO output pins */
306         set_i3100_gpio_level(dev, res, config);
307
308 }
309
310
311 static void lpc_init(struct device *dev)
312 {
313         struct resource *res;
314
315         /* Enable IO APIC */
316         res = find_resource(dev, RCBA);
317         if (!res) {
318                 return;
319         }
320         *((u8 *)((u32)res->base + 0x31ff)) |= (1 << 0);
321
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)
324         // ... Why?
325         setup_ioapic(IO_APIC_ADDR, 0); // Don't rename IOAPIC ID
326
327         /* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
328         pci_write_config32(dev, 0xd0, 0x00000000);
329
330         i3100_enable_serial_irqs(dev);
331
332         /* Set up the PIRQ */
333         i3100_pirq_init(dev);
334
335         /* Setup power options */
336         i3100_power_options(dev);
337
338         /* Set the state of the gpio lines */
339         i3100_gpio_init(dev);
340
341         /* Initialize the real time clock */
342         rtc_init(0);
343
344         /* Initialize isa dma */
345         isa_dma_init();
346 }
347
348 static void i3100_lpc_read_resources(device_t dev)
349 {
350         struct resource *res;
351
352         /* Get the normal pci resources of this device */
353         pci_dev_read_resources(dev);
354
355         /* Add the ACPI BAR */
356         res = pci_get_resource(dev, ACPI_BAR);
357
358         /* Add the GPIO BAR */
359         res = pci_get_resource(dev, GPIO_BAR);
360
361         /* Add an extra subtractive resource for both memory and I/O. */
362         res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
363         res->base = 0;
364         res->size = 0x1000;
365         res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
366                      IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
367
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;
373
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;
378
379         /* Add resource for RCBA */
380         res = new_resource(dev, RCBA);
381         res->size = 0x4000;
382         res->limit = 0xffffc000;
383         res->align = 14;
384         res->gran = 14;
385         res->flags = IORESOURCE_MEM;
386 }
387
388 static void i3100_lpc_enable_resources(device_t dev)
389 {
390         u8 acpi_cntl, gpio_cntl;
391
392         /* Enable the normal pci resources */
393         pci_dev_enable_resources(dev);
394
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);
399
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);
404
405         /* Enable the RCBA */
406         pci_write_config32(dev, RCBA, pci_read_config32(dev, RCBA) | (1 << 0));
407 }
408
409 static struct pci_operations lops_pci = {
410         .set_subsystem = 0,
411 };
412
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,
417         .init             = lpc_init,
418         .scan_bus         = scan_static_bus,
419         .enable           = i3100_enable,
420         .ops_pci          = &lops_pci,
421 };
422
423 static const struct pci_driver lpc_driver __pci_driver = {
424         .ops    = &lpc_ops,
425         .vendor = PCI_VENDOR_ID_INTEL,
426         .device = PCI_DEVICE_ID_INTEL_3100_LPC,
427 };
428
429 static const struct pci_driver lpc_driver_ep80579 __pci_driver = {
430         .ops    = &lpc_ops,
431         .vendor = PCI_VENDOR_ID_INTEL,
432         .device = PCI_DEVICE_ID_INTEL_EP80579_LPC,
433 };