f8584cadb05146714b16e7e9e42d7ef00b3cea24
[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 SERIRQ_CNTL 0x64
39
40 #define GEN_PMCON_1 0xA0
41 #define GEN_PMCON_2 0xA2
42 #define GEN_PMCON_3 0xA4
43
44 #define NMI_OFF 0
45 #define MAINBOARD_POWER_OFF 0
46 #define MAINBOARD_POWER_ON  1
47
48 #ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
49 #define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
50 #endif
51
52 #define ALL             (0xff << 24)
53 #define NONE            (0)
54 #define DISABLED        (1 << 16)
55 #define ENABLED         (0 << 16)
56 #define TRIGGER_EDGE    (0 << 15)
57 #define TRIGGER_LEVEL   (1 << 15)
58 #define POLARITY_HIGH   (0 << 13)
59 #define POLARITY_LOW    (1 << 13)
60 #define PHYSICAL_DEST   (0 << 11)
61 #define LOGICAL_DEST    (1 << 11)
62 #define ExtINT          (7 << 8)
63 #define NMI             (4 << 8)
64 #define SMI             (2 << 8)
65 #define INT             (1 << 8)
66
67 static void setup_ioapic(device_t dev)
68 {
69         int i;
70         u32 value_low, value_high;
71         u32 ioapic_base = 0xfec00000;
72         volatile u32 *l;
73         u32 interrupts;
74         struct resource *res;
75
76         /* Enable IO APIC */
77         res = find_resource(dev, RCBA);
78         if (!res) {
79                 return;
80         }
81         *((u8 *)(res->base + 0x31ff)) |= (1 << 0);
82
83         l = (u32 *) ioapic_base;
84
85         l[0] = 0x01;
86         interrupts = (l[04] >> 16) & 0xff;
87         for (i = 0; i < interrupts; i++) {
88                 l[0] = (i * 2) + 0x10;
89                 l[4] = DISABLED;
90                 value_low = l[4];
91                 l[0] = (i * 2) + 0x11;
92                 l[4] = NONE; /* Should this be an address? */
93                 value_high = l[4];
94                 if (value_low == 0xffffffff) {
95                         printk_warning("%d IO APIC not responding.\n",
96                                 dev_path(dev));
97                         return;
98                 }
99         }
100
101         /* Put the APIC in virtual wire mode */
102         l[0] = 0x12;
103         l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
104 }
105
106 static void i3100_enable_serial_irqs(device_t dev)
107 {
108         /* set packet length and toggle silent mode bit */
109         pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
110         pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
111 }
112
113 typedef struct southbridge_intel_i3100_config config_t;
114
115 static void set_i3100_gpio_use_sel(
116         device_t dev, struct resource *res, config_t *config)
117 {
118         u32 gpio_use_sel, gpio_use_sel2;
119         int i;
120
121         gpio_use_sel = inl(res->base + 0x00) | 0x0000c603;
122         gpio_use_sel2 = inl(res->base + 0x30) | 0x00000100;
123         for (i = 0; i < 64; i++) {
124                 int val;
125                 switch (config->gpio[i] & I3100_GPIO_USE_MASK) {
126                 case I3100_GPIO_USE_AS_NATIVE:
127                         val = 0;
128                         break;
129                 case I3100_GPIO_USE_AS_GPIO:
130                         val = 1;
131                         break;
132                 default:
133                         continue;
134                 }
135                 /* The caller is responsible for not playing with unimplemented bits */
136                 if (i < 32) {
137                         gpio_use_sel &= ~(1 << i);
138                         gpio_use_sel |= (val << i);
139                 } else {
140                         gpio_use_sel2 &= ~(1 << (i - 32));
141                         gpio_use_sel2 |= (val << (i - 32));
142                 }
143         }
144         outl(gpio_use_sel, res->base + 0x00);
145         outl(gpio_use_sel2, res->base + 0x30);
146 }
147
148 static void set_i3100_gpio_direction(
149         device_t dev, struct resource *res, config_t *config)
150 {
151         u32 gpio_io_sel, gpio_io_sel2;
152         int i;
153
154         gpio_io_sel = inl(res->base + 0x04);
155         gpio_io_sel2 = inl(res->base + 0x34);
156         for (i = 0; i < 64; i++) {
157                 int val;
158                 switch (config->gpio[i] & I3100_GPIO_SEL_MASK) {
159                 case I3100_GPIO_SEL_OUTPUT:
160                         val = 0;
161                         break;
162                 case I3100_GPIO_SEL_INPUT:
163                         val = 1;
164                         break;
165                 default:
166                         continue;
167                 }
168                 /* The caller is responsible for not playing with unimplemented bits */
169                 if (i < 32) {
170                         gpio_io_sel &= ~(1 << i);
171                         gpio_io_sel |= (val << i);
172                 } else {
173                         gpio_io_sel2 &= ~(1 << (i - 32));
174                         gpio_io_sel2 |= (val << (i - 32));
175                 }
176         }
177         outl(gpio_io_sel, res->base + 0x04);
178         outl(gpio_io_sel2, res->base + 0x34);
179 }
180
181 static void set_i3100_gpio_level(
182         device_t dev, struct resource *res, config_t *config)
183 {
184         u32 gpio_lvl, gpio_lvl2;
185         u32 gpio_blink;
186         int i;
187
188         gpio_lvl = inl(res->base + 0x0c);
189         gpio_blink = inl(res->base + 0x18);
190         gpio_lvl2 = inl(res->base + 0x38);
191         for (i = 0; i < 64; i++) {
192                 int val, blink;
193                 switch (config->gpio[i] & I3100_GPIO_LVL_MASK) {
194                 case I3100_GPIO_LVL_LOW:
195                         val = 0;
196                         blink = 0;
197                         break;
198                 case I3100_GPIO_LVL_HIGH:
199                         val = 1;
200                         blink = 0;
201                         break;
202                 case I3100_GPIO_LVL_BLINK:
203                         val = 1;
204                         blink = 1;
205                         break;
206                 default:
207                         continue;
208                 }
209                 /* The caller is responsible for not playing with unimplemented bits */
210                 if (i < 32) {
211                         gpio_lvl &= ~(1 << i);
212                         gpio_blink &= ~(1 << i);
213                         gpio_lvl |= (val << i);
214                         gpio_blink |= (blink << i);
215                 } else {
216                         gpio_lvl2 &= ~(1 << (i - 32));
217                         gpio_lvl2 |= (val << (i - 32));
218                 }
219         }
220         outl(gpio_lvl, res->base + 0x0c);
221         outl(gpio_blink, res->base + 0x18);
222         outl(gpio_lvl2, res->base + 0x38);
223 }
224
225 static void set_i3100_gpio_inv(
226         device_t dev, struct resource *res, config_t *config)
227 {
228         u32 gpio_inv;
229         int i;
230
231         gpio_inv = inl(res->base + 0x2c);
232         for (i = 0; i < 32; i++) {
233                 int val;
234                 switch (config->gpio[i] & I3100_GPIO_INV_MASK) {
235                 case I3100_GPIO_INV_OFF:
236                         val = 0;
237                         break;
238                 case I3100_GPIO_INV_ON:
239                         val = 1;
240                         break;
241                 default:
242                         continue;
243                 }
244                 gpio_inv &= ~(1 << i);
245                 gpio_inv |= (val << i);
246         }
247         outl(gpio_inv, res->base + 0x2c);
248 }
249
250 static void i3100_pirq_init(device_t dev)
251 {
252         config_t *config;
253
254         /* Get the chip configuration */
255         config = dev->chip_info;
256
257         if(config->pirq_a_d) {
258                 pci_write_config32(dev, 0x60, config->pirq_a_d);
259         }
260         if(config->pirq_e_h) {
261                 pci_write_config32(dev, 0x68, config->pirq_e_h);
262         }
263 }
264
265 static void i3100_power_options(device_t dev) {
266   u8 reg8;
267   u16 reg16;
268   int pwr_on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
269   int nmi_option;
270
271   /* Which state do we want to goto after g3 (power restored)?
272    * 0 == S0 Full On
273    * 1 == S5 Soft Off
274    */
275   get_option(&pwr_on, "power_on_after_fail");
276   reg8 = pci_read_config8(dev, GEN_PMCON_3);
277   reg8 &= 0xfe;
278   if (pwr_on) {
279     reg8 &= ~1;
280   } else {
281     reg8 |= 1;
282   }
283   /* avoid #S4 assertions */
284   reg8 |= (3 << 4);
285   /* minimum asssertion is 1 to 2 RTCCLK */
286   reg8 &= ~(1 << 3);    
287   pci_write_config8(dev, GEN_PMCON_3, reg8);
288   printk_info("set power %s after power fail\n", pwr_on ? "on" : "off");  
289
290   /* Set up NMI on errors. */
291   reg8 = inb(0x61);
292   /* Higher Nibble must be 0 */
293   reg8 &= 0x0f;
294   /* IOCHK# NMI Enable */
295   reg8 &= ~(1 << 3);
296   /* PCI SERR# Enable */
297   // reg8 &= ~(1 << 2);
298   /* PCI SERR# Disable for now */
299   reg8 |= (1 << 2);
300   outb(reg8, 0x61);
301   
302   reg8 = inb(0x70);
303   nmi_option = NMI_OFF;
304   get_option(&nmi_option, "nmi");
305   if (nmi_option) {
306     /* Set NMI. */
307     printk_info ("NMI sources enabled.\n");
308     reg8 &= ~(1 << 7);  
309   } else {
310     /* Can't mask NMI from PCI-E and NMI_NOW */
311     printk_info ("NMI sources disabled.\n");
312     reg8 |= ( 1 << 7);
313   }
314   outb(reg8, 0x70);
315
316   // Enable CPU_SLP# and Intel Speedstep, set SMI# rate down
317   reg16 = pci_read_config16(dev, GEN_PMCON_1);
318   reg16 &= ~((3 << 0) | (1 << 10));
319   reg16 |= (1 << 3) | (1 << 5);
320   /* CLKRUN_EN */
321   // reg16 |= (1 << 2);
322   pci_write_config16(dev, GEN_PMCON_1, reg16);
323   
324   // Set the board's GPI routing.
325   // i82801gx_gpi_routing(dev);
326 }
327
328 static void i3100_gpio_init(device_t dev)
329 {
330         struct resource *res;
331         config_t *config;
332
333         /* Skip if I don't have any configuration */
334         if (!dev->chip_info) {
335                 return;
336         }
337         /* The programmer is responsible for ensuring
338          * a valid gpio configuration.
339          */
340
341         /* Get the chip configuration */
342         config = dev->chip_info;
343         /* Find the GPIO bar */
344         res = find_resource(dev, GPIO_BAR);
345         if (!res) {
346                 return;
347         }
348
349         /* Set the use selects */
350         set_i3100_gpio_use_sel(dev, res, config);
351
352         /* Set the IO direction */
353         set_i3100_gpio_direction(dev, res, config);
354
355         /* Setup the input inverters */
356         set_i3100_gpio_inv(dev, res, config);
357
358         /* Set the value on the GPIO output pins */
359         set_i3100_gpio_level(dev, res, config);
360
361 }
362
363
364 static void lpc_init(struct device *dev)
365 {
366         setup_ioapic(dev);
367
368         /* Decode 0xffc00000 - 0xffffffff to fwh idsel 0 */
369         pci_write_config32(dev, 0xd0, 0x00000000);
370
371         i3100_enable_serial_irqs(dev);
372
373         /* Set up the PIRQ */
374         i3100_pirq_init(dev);
375
376         /* Setup power options */
377         i3100_power_options(dev);
378
379         /* Set the state of the gpio lines */
380         i3100_gpio_init(dev);
381
382         /* Initialize the real time clock */
383         rtc_init(0);
384
385         /* Initialize isa dma */
386         isa_dma_init();
387 }
388
389 static void i3100_lpc_read_resources(device_t dev)
390 {
391         struct resource *res;
392
393         /* Get the normal pci resources of this device */
394         pci_dev_read_resources(dev);
395
396         /* Add the ACPI BAR */
397         res = pci_get_resource(dev, ACPI_BAR);
398
399         /* Add the GPIO BAR */
400         res = pci_get_resource(dev, GPIO_BAR);
401
402         /* Add an extra subtractive resource for both memory and I/O */
403         res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
404         res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
405
406         res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
407         res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
408
409         /* Add resource for RCBA */
410         res = new_resource(dev, RCBA);
411         res->size = 0x4000;
412         res->limit = 0xffffc000;
413         res->align = 14;
414         res->gran = 14;
415         res->flags = IORESOURCE_MEM;
416 }
417
418 static void i3100_lpc_enable_resources(device_t dev)
419 {
420         u8 acpi_cntl, gpio_cntl;
421
422         /* Enable the normal pci resources */
423         pci_dev_enable_resources(dev);
424
425         /* Enable the ACPI bar */
426         acpi_cntl = pci_read_config8(dev, 0x44);
427         acpi_cntl |= (1 << 7);
428         pci_write_config8(dev, 0x44, acpi_cntl);
429
430         /* Enable the GPIO bar */
431         gpio_cntl = pci_read_config8(dev, 0x4c);
432         gpio_cntl |= (1 << 4);
433         pci_write_config8(dev, 0x4c, gpio_cntl);
434
435         /* Enable the RCBA */
436         pci_write_config32(dev, RCBA, pci_read_config32(dev, RCBA) | (1 << 0));
437
438         enable_childrens_resources(dev);
439 }
440
441 static struct pci_operations lops_pci = {
442         .set_subsystem = 0,
443 };
444
445 static struct device_operations lpc_ops  = {
446         .read_resources   = i3100_lpc_read_resources,
447         .set_resources    = pci_dev_set_resources,
448         .enable_resources = i3100_lpc_enable_resources,
449         .init             = lpc_init,
450         .scan_bus         = scan_static_bus,
451         .enable           = i3100_enable,
452         .ops_pci          = &lops_pci,
453 };
454
455 static struct pci_driver lpc_driver __pci_driver = {
456         .ops    = &lpc_ops,
457         .vendor = PCI_VENDOR_ID_INTEL,
458         .device = PCI_DEVICE_ID_INTEL_3100_LPC,
459 };
460
461 static struct pci_driver lpc_driver_ep80579 __pci_driver = {
462         .ops    = &lpc_ops,
463         .vendor = PCI_VENDOR_ID_INTEL,
464         .device = PCI_DEVICE_ID_INTEL_EP80579_LPC,
465 };