8e0c460880d853a7de6a78af743c22d88004a759
[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 "i3100.h"
33
34 #define ACPI_BAR 0x40
35 #define GPIO_BAR 0x48
36 #define RCBA 0xf0
37
38 #define NMI_OFF 0
39 #define MAINBOARD_POWER_OFF 0
40 #define MAINBOARD_POWER_ON  1
41
42 #ifndef MAINBOARD_POWER_ON_AFTER_FAIL
43 #define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON
44 #endif
45
46 #define ALL             (0xff << 24)
47 #define NONE            (0)
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)
57 #define NMI             (4 << 8)
58 #define SMI             (2 << 8)
59 #define INT             (1 << 8)
60
61 static void setup_ioapic(device_t dev)
62 {
63         int i;
64         u32 value_low, value_high;
65         u32 ioapic_base = 0xfec00000;
66         volatile u32 *l;
67         u32 interrupts;
68         struct resource *res;
69
70         /* Enable IO APIC */
71         res = find_resource(dev, RCBA);
72         if (!res) {
73                 return;
74         }
75         *((u8 *)(res->base + 0x31ff)) |= (1 << 0);
76
77         l = (u32 *) ioapic_base;
78
79         l[0] = 0x01;
80         interrupts = (l[04] >> 16) & 0xff;
81         for (i = 0; i < interrupts; i++) {
82                 l[0] = (i * 2) + 0x10;
83                 l[4] = DISABLED;
84                 value_low = l[4];
85                 l[0] = (i * 2) + 0x11;
86                 l[4] = NONE; /* Should this be an address? */
87                 value_high = l[4];
88                 if (value_low == 0xffffffff) {
89                         printk_warning("%d IO APIC not responding.\n",
90                                 dev_path(dev));
91                         return;
92                 }
93         }
94
95         /* Put the APIC in virtual wire mode */
96         l[0] = 0x10;
97         l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
98 }
99
100 #define SERIRQ_CNTL 0x64
101 static void i3100_enable_serial_irqs(device_t dev)
102 {
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));
106 }
107
108 typedef struct southbridge_intel_i3100_config config_t;
109
110 static void set_i3100_gpio_use_sel(
111         device_t dev, struct resource *res, config_t *config)
112 {
113         u32 gpio_use_sel, gpio_use_sel2;
114         int i;
115
116         gpio_use_sel = inl(res->base + 0x00) | 0x0000c603;
117         gpio_use_sel2 = inl(res->base + 0x30) | 0x00000100;
118         for (i = 0; i < 64; i++) {
119                 int val;
120                 switch (config->gpio[i] & I3100_GPIO_USE_MASK) {
121                 case I3100_GPIO_USE_AS_NATIVE:
122                         val = 0;
123                         break;
124                 case I3100_GPIO_USE_AS_GPIO:
125                         val = 1;
126                         break;
127                 default:
128                         continue;
129                 }
130                 /* The caller is responsible for not playing with unimplemented bits */
131                 if (i < 32) {
132                         gpio_use_sel &= ~(1 << i);
133                         gpio_use_sel |= (val << i);
134                 } else {
135                         gpio_use_sel2 &= ~(1 << (i - 32));
136                         gpio_use_sel2 |= (val << (i - 32));
137                 }
138         }
139         outl(gpio_use_sel, res->base + 0x00);
140         outl(gpio_use_sel2, res->base + 0x30);
141 }
142
143 static void set_i3100_gpio_direction(
144         device_t dev, struct resource *res, config_t *config)
145 {
146         u32 gpio_io_sel, gpio_io_sel2;
147         int i;
148
149         gpio_io_sel = inl(res->base + 0x04);
150         gpio_io_sel2 = inl(res->base + 0x34);
151         for (i = 0; i < 64; i++) {
152                 int val;
153                 switch (config->gpio[i] & I3100_GPIO_SEL_MASK) {
154                 case I3100_GPIO_SEL_OUTPUT:
155                         val = 0;
156                         break;
157                 case I3100_GPIO_SEL_INPUT:
158                         val = 1;
159                         break;
160                 default:
161                         continue;
162                 }
163                 /* The caller is responsible for not playing with unimplemented bits */
164                 if (i < 32) {
165                         gpio_io_sel &= ~(1 << i);
166                         gpio_io_sel |= (val << i);
167                 } else {
168                         gpio_io_sel2 &= ~(1 << (i - 32));
169                         gpio_io_sel2 |= (val << (i - 32));
170                 }
171         }
172         outl(gpio_io_sel, res->base + 0x04);
173         outl(gpio_io_sel2, res->base + 0x34);
174 }
175
176 static void set_i3100_gpio_level(
177         device_t dev, struct resource *res, config_t *config)
178 {
179         u32 gpio_lvl, gpio_lvl2;
180         u32 gpio_blink;
181         int i;
182
183         gpio_lvl = inl(res->base + 0x0c);
184         gpio_blink = inl(res->base + 0x18);
185         gpio_lvl2 = inl(res->base + 0x38);
186         for (i = 0; i < 64; i++) {
187                 int val, blink;
188                 switch (config->gpio[i] & I3100_GPIO_LVL_MASK) {
189                 case I3100_GPIO_LVL_LOW:
190                         val = 0;
191                         blink = 0;
192                         break;
193                 case I3100_GPIO_LVL_HIGH:
194                         val = 1;
195                         blink = 0;
196                         break;
197                 case I3100_GPIO_LVL_BLINK:
198                         val = 1;
199                         blink = 1;
200                         break;
201                 default:
202                         continue;
203                 }
204                 /* The caller is responsible for not playing with unimplemented bits */
205                 if (i < 32) {
206                         gpio_lvl &= ~(1 << i);
207                         gpio_blink &= ~(1 << i);
208                         gpio_lvl |= (val << i);
209                         gpio_blink |= (blink << i);
210                 } else {
211                         gpio_lvl2 &= ~(1 << (i - 32));
212                         gpio_lvl2 |= (val << (i - 32));
213                 }
214         }
215         outl(gpio_lvl, res->base + 0x0c);
216         outl(gpio_blink, res->base + 0x18);
217         outl(gpio_lvl2, res->base + 0x38);
218 }
219
220 static void set_i3100_gpio_inv(
221         device_t dev, struct resource *res, config_t *config)
222 {
223         u32 gpio_inv;
224         int i;
225
226         gpio_inv = inl(res->base + 0x2c);
227         for (i = 0; i < 32; i++) {
228                 int val;
229                 switch (config->gpio[i] & I3100_GPIO_INV_MASK) {
230                 case I3100_GPIO_INV_OFF:
231                         val = 0;
232                         break;
233                 case I3100_GPIO_INV_ON:
234                         val = 1;
235                         break;
236                 default:
237                         continue;
238                 }
239                 gpio_inv &= ~(1 << i);
240                 gpio_inv |= (val << i);
241         }
242         outl(gpio_inv, res->base + 0x2c);
243 }
244
245 static void i3100_pirq_init(device_t dev)
246 {
247         config_t *config;
248
249         /* Get the chip configuration */
250         config = dev->chip_info;
251
252         if(config->pirq_a_d) {
253                 pci_write_config32(dev, 0x60, config->pirq_a_d);
254         }
255         if(config->pirq_e_h) {
256                 pci_write_config32(dev, 0x68, config->pirq_e_h);
257         }
258 }
259
260
261 static void i3100_gpio_init(device_t dev)
262 {
263         struct resource *res;
264         config_t *config;
265
266         /* Skip if I don't have any configuration */
267         if (!dev->chip_info) {
268                 return;
269         }
270         /* The programmer is responsible for ensuring
271          * a valid gpio configuration.
272          */
273
274         /* Get the chip configuration */
275         config = dev->chip_info;
276         /* Find the GPIO bar */
277         res = find_resource(dev, GPIO_BAR);
278         if (!res) {
279                 return;
280         }
281
282         /* Set the use selects */
283         set_i3100_gpio_use_sel(dev, res, config);
284
285         /* Set the IO direction */
286         set_i3100_gpio_direction(dev, res, config);
287
288         /* Setup the input inverters */
289         set_i3100_gpio_inv(dev, res, config);
290
291         /* Set the value on the GPIO output pins */
292         set_i3100_gpio_level(dev, res, config);
293
294 }
295
296
297 static void lpc_init(struct device *dev)
298 {
299         u8 byte;
300         int pwr_on = MAINBOARD_POWER_ON_AFTER_FAIL;
301
302         setup_ioapic(dev);
303
304         /* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
305         pci_write_config32(dev, 0xd0, 0x00000000);
306
307         i3100_enable_serial_irqs(dev);
308
309         get_option(&pwr_on, "power_on_after_fail");
310         byte = pci_read_config8(dev, 0xa4);
311         byte &= 0xfe;
312         if (!pwr_on) {
313                 byte |= 1;
314         }
315         pci_write_config8(dev, 0xa4, byte);
316         printk_info("set power %s after power fail\n", pwr_on ? "on" : "off");
317
318         /* Set up the PIRQ */
319         i3100_pirq_init(dev);
320
321         /* Set the state of the gpio lines */
322         i3100_gpio_init(dev);
323
324         /* Initialize the real time clock */
325         rtc_init(0);
326
327         /* Initialize isa dma */
328         isa_dma_init();
329 }
330
331 static void i3100_lpc_read_resources(device_t dev)
332 {
333         struct resource *res;
334
335         /* Get the normal pci resources of this device */
336         pci_dev_read_resources(dev);
337
338         /* Add the ACPI BAR */
339         res = pci_get_resource(dev, ACPI_BAR);
340
341         /* Add the GPIO BAR */
342         res = pci_get_resource(dev, GPIO_BAR);
343
344         /* Add an extra subtractive resource for both memory and I/O */
345         res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
346         res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
347
348         res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
349         res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
350
351         /* Add resource for RCBA */
352         res = new_resource(dev, RCBA);
353         res->size = 0x4000;
354         res->limit = 0xffffc000;
355         res->align = 14;
356         res->gran = 14;
357         res->flags = IORESOURCE_MEM;
358 }
359
360 static void i3100_lpc_enable_resources(device_t dev)
361 {
362         u8 acpi_cntl, gpio_cntl;
363
364         /* Enable the normal pci resources */
365         pci_dev_enable_resources(dev);
366
367         /* Enable the ACPI bar */
368         acpi_cntl = pci_read_config8(dev, 0x44);
369         acpi_cntl |= (1 << 7);
370         pci_write_config8(dev, 0x44, acpi_cntl);
371
372         /* Enable the GPIO bar */
373         gpio_cntl = pci_read_config8(dev, 0x4c);
374         gpio_cntl |= (1 << 4);
375         pci_write_config8(dev, 0x4c, gpio_cntl);
376
377         /* Enable the RCBA */
378         pci_write_config32(dev, RCBA, pci_read_config32(dev, RCBA) | (1 << 0));
379
380         enable_childrens_resources(dev);
381 }
382
383 static struct pci_operations lops_pci = {
384         .set_subsystem = 0,
385 };
386
387 static struct device_operations lpc_ops  = {
388         .read_resources   = i3100_lpc_read_resources,
389         .set_resources    = pci_dev_set_resources,
390         .enable_resources = i3100_lpc_enable_resources,
391         .init             = lpc_init,
392         .scan_bus         = scan_static_bus,
393         .enable           = i3100_enable,
394         .ops_pci          = &lops_pci,
395 };
396
397 static struct pci_driver lpc_driver __pci_driver = {
398         .ops    = &lpc_ops,
399         .vendor = PCI_VENDOR_ID_INTEL,
400         .device = PCI_DEVICE_ID_INTEL_3100_LPC,
401 };
402
403 static struct pci_driver lpc_driver_ep80579 __pci_driver = {
404         .ops    = &lpc_ops,
405         .vendor = PCI_VENDOR_ID_INTEL,
406         .device = PCI_DEVICE_ID_INTEL_EP80579_LPC,
407 };