Please bear with me - another rename checkin. This qualifies as trivial, no
[coreboot.git] / src / southbridge / intel / i82801db / i82801db_lpc.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  */
18
19 /*
20  * (C) 2004 Linux Networx
21  */
22 #include <console/console.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <device/pci_ops.h>
27 #include <pc80/mc146818rtc.h>
28 #include <pc80/isa-dma.h>
29 #include <arch/io.h>
30 #include "i82801db.h"
31
32 #define ACPI_BAR 0x40
33 #define GPIO_BAR 0x58
34
35 #define NMI_OFF 0
36 #define MAINBOARD_POWER_OFF 0
37 #define MAINBOARD_POWER_ON  1
38
39 #ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
40 #define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
41 #endif
42
43 #define ALL             (0xff << 24)
44 #define NONE            (0)
45 #define DISABLED        (1 << 16)
46 #define ENABLED         (0 << 16)
47 #define TRIGGER_EDGE    (0 << 15)
48 #define TRIGGER_LEVEL   (1 << 15)
49 #define POLARITY_HIGH   (0 << 13)
50 #define POLARITY_LOW    (1 << 13)
51 #define PHYSICAL_DEST   (0 << 11)
52 #define LOGICAL_DEST    (1 << 11)
53 #define ExtINT          (7 << 8)
54 #define NMI             (4 << 8)
55 #define SMI             (2 << 8)
56 #define INT             (1 << 8)
57
58 static void setup_ioapic(void)
59 {
60         int i;
61         unsigned long value_low, value_high;
62         unsigned long ioapic_base = 0xfec00000;
63         volatile unsigned long *l;
64         unsigned interrupts;
65
66         l = (unsigned long *) ioapic_base;
67
68         l[0] = 0x01;
69         interrupts = (l[04] >> 16) & 0xff;
70         for (i = 0; i < interrupts; i++) {
71                 l[0] = (i * 2) + 0x10;
72                 l[4] = DISABLED;
73                 value_low = l[4];
74                 l[0] = (i * 2) + 0x11;
75                 l[4] = NONE; /* Should this be an address? */
76                 value_high = l[4];
77                 if (value_low == 0xffffffff) {
78                         printk_warning("IO APIC not responding.\n");
79                         return;
80                 }
81         }
82
83         /* Put the ioapic in virtual wire mode */
84         l[0] = 0 + 0x10;
85         l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
86 }
87
88 #define SERIRQ_CNTL 0x64
89 static void i82801db_enable_serial_irqs(device_t dev)
90 {
91         /* set packet length and toggle silent mode bit */
92         pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
93         pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(0 << 6)|((21 - 17) << 2)|(0 << 0));
94 }
95
96 #define PCI_DMA_CFG 0x90
97 static void i82801db_pci_dma_cfg(device_t dev)
98 {
99         /* Set PCI DMA CFG to lpc I/F DMA 
100         pci_write_config16(dev, PCI_DMA_CFG, 0xfcff); */
101         pci_write_config16(dev, PCI_DMA_CFG, 0x5455);
102 }
103
104 #define LPC_EN 0xe6
105 static void i82801db_enable_lpc(device_t dev)
106 {
107         /* lpc i/f enable 
108         pci_write_config8(dev, LPC_EN, 0x0d); */
109         pci_write_config16(dev, LPC_EN, 0x3403);
110 }
111
112 typedef struct southbridge_intel_i82801db_config config_t;
113
114 static void set_i82801db_gpio_use_sel(
115         device_t dev, struct resource *res, config_t *config)
116 {
117         uint32_t gpio_use_sel, gpio_use_sel2;
118         int i;
119
120         gpio_use_sel  = 0x1A003180;
121         gpio_use_sel2 = 0x00000007;
122         for(i = 0; i < 64; i++) {
123                 int val;
124                 switch(config->gpio[i] & ICH5R_GPIO_USE_MASK) {
125                 case ICH5R_GPIO_USE_AS_NATIVE: val = 0; break;
126                 case ICH5R_GPIO_USE_AS_GPIO:   val = 1; 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_i82801db_gpio_direction(
144         device_t dev, struct resource *res, config_t *config)
145 {
146         uint32_t gpio_io_sel, gpio_io_sel2;
147         int i;
148
149         gpio_io_sel  = 0x0000ffff;
150         gpio_io_sel2 = 0x00000300;
151         for(i = 0; i < 64; i++) {
152                 int val;
153                 switch(config->gpio[i] & ICH5R_GPIO_SEL_MASK) {
154                 case ICH5R_GPIO_SEL_OUTPUT: val = 0; break;
155                 case ICH5R_GPIO_SEL_INPUT:  val = 1; break;
156                 default: 
157                         continue;
158                 }
159                 /* The caller is responsible for not playing with unimplemented bits */
160                 if (i < 32) {
161                         gpio_io_sel  &= ~( 1 << i);
162                         gpio_io_sel  |= (val << i);
163                 } else {
164                         gpio_io_sel2 &= ~( 1 << (i - 32));
165                         gpio_io_sel2 |= (val << (i - 32));
166                 }
167         }
168         outl(gpio_io_sel,  res->base + 0x04);
169         outl(gpio_io_sel2, res->base + 0x34);
170 }
171
172 static void set_i82801db_gpio_level(
173         device_t dev, struct resource *res, config_t *config)
174 {
175         uint32_t gpio_lvl, gpio_lvl2;
176         uint32_t gpio_blink;
177         int i;
178
179         gpio_lvl   = 0x1b3f0000;
180         gpio_blink = 0x00040000;
181         gpio_lvl2  = 0x00030207;
182         for(i = 0; i < 64; i++) {
183                 int val, blink;
184                 switch(config->gpio[i] & ICH5R_GPIO_LVL_MASK) {
185                 case ICH5R_GPIO_LVL_LOW:   val = 0; blink = 0; break;
186                 case ICH5R_GPIO_LVL_HIGH:  val = 1; blink = 0; break;
187                 case ICH5R_GPIO_LVL_BLINK: val = 1; blink = 1; break;
188                 default: 
189                         continue;
190                 }
191                 /* The caller is responsible for not playing with unimplemented bits */
192                 if (i < 32) {
193                         gpio_lvl   &= ~(   1 << i);
194                         gpio_blink &= ~(   1 << i);
195                         gpio_lvl   |= (  val << i);
196                         gpio_blink |= (blink << i);
197                 } else {
198                         gpio_lvl2  &= ~( 1 << (i - 32));
199                         gpio_lvl2  |= (val << (i - 32));
200                 }
201         }
202         outl(gpio_lvl,   res->base + 0x0c);
203         outl(gpio_blink, res->base + 0x18);
204         outl(gpio_lvl2,  res->base + 0x38);
205 }
206
207 static void set_i82801db_gpio_inv(
208         device_t dev, struct resource *res, config_t *config)
209 {
210         uint32_t gpio_inv;
211         int i;
212
213         gpio_inv   = 0x00000000;
214         for(i = 0; i < 32; i++) {
215                 int val;
216                 switch(config->gpio[i] & ICH5R_GPIO_INV_MASK) {
217                 case ICH5R_GPIO_INV_OFF: val = 0; break;
218                 case ICH5R_GPIO_INV_ON:  val = 1; break;
219                 default: 
220                         continue;
221                 }
222                 gpio_inv &= ~( 1 << i);
223                 gpio_inv |= (val << i);
224         }
225         outl(gpio_inv,   res->base + 0x2c);
226 }
227
228 static void i82801db_pirq_init(device_t dev)
229 {
230         config_t *config;
231
232         /* Get the chip configuration */
233         config = dev->chip_info;
234
235         if(config->pirq_a_d) {
236                 printk_debug("\n\nIRQs A to D = %04x\n\n", config->pirq_a_d);
237                 pci_write_config32(dev, 0x60, config->pirq_a_d);
238         }
239         if(config->pirq_e_h) {
240                 printk_debug("\n\nIRQs e to h = %04x\n\n", config->pirq_e_h);
241                 pci_write_config32(dev, 0x68, config->pirq_e_h);
242         }
243 }
244
245
246 static void i82801db_gpio_init(device_t dev)
247 {
248         struct resource *res;
249         config_t *config;
250
251         /* Skip if I don't have any configuration */
252         if (!dev->chip_info) {
253                 return;
254         }
255         /* The programmer is responsible for ensuring
256          * a valid gpio configuration.
257          */
258
259         /* Get the chip configuration */
260         config = dev->chip_info;
261         /* Find the GPIO bar */
262         res = find_resource(dev, GPIO_BAR);
263         if (!res) {
264                 return; 
265         }
266
267         /* Set the use selects */
268         set_i82801db_gpio_use_sel(dev, res, config);
269
270         /* Set the IO direction */
271         set_i82801db_gpio_direction(dev, res, config);
272
273         /* Setup the input inverters */
274         set_i82801db_gpio_inv(dev, res, config);
275
276         /* Set the value on the GPIO output pins */
277         set_i82801db_gpio_level(dev, res, config);
278
279 }
280
281 static void enable_hpet(struct device *dev)
282 {
283 const unsigned long hpet_address = 0xfed0000;
284
285         uint32_t dword;
286         uint32_t code = (0 & 0x3);
287
288         dword = pci_read_config32(dev, GEN_CNTL);
289         dword |= (1 << 17); /* enable hpet */
290
291         /* Bits [16:15]  Memory Address Range
292          *          00   FED0_0000h - FED0_03FFh
293          *          01   FED0_1000h - FED0_13FFh
294          *          10   FED0_2000h - FED0_23FFh
295          *          11   FED0_3000h - FED0_33FFh
296          */
297
298         dword &= ~(3 << 15); /* clear it */
299         dword |= (code<<15);
300
301         printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
302 }
303
304 static void lpc_init(struct device *dev)
305 {
306         uint8_t byte;
307         uint32_t value;
308         int pwr_on=MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
309
310         /* IO APIC initialization */
311         value = pci_read_config32(dev, 0xd0);
312         value |= (1 << 8)|(1<<7)|(1<<1);
313         pci_write_config32(dev, 0xd0, value);
314         value = pci_read_config32(dev, 0xd4);
315         value |= (1<<1);
316         pci_write_config32(dev, 0xd4, value);
317         setup_ioapic();
318
319         i82801db_enable_serial_irqs(dev);
320
321         i82801db_pci_dma_cfg(dev);
322
323         i82801db_enable_lpc(dev);
324
325         /* Clear SATA to non raid
326         pci_write_config8(dev, 0xae, 0x00);
327         */
328         
329         get_option(&pwr_on, "power_on_after_fail");
330         byte = pci_read_config8(dev, 0xa4);
331         byte &= 0xfe;
332         if (!pwr_on) {
333                 byte |= 1;
334         }
335         pci_write_config8(dev, 0xa4, byte);
336         printk_info("set power %s after power fail\n", pwr_on?"on":"off");
337
338         /* Set up the PIRQ */
339         i82801db_pirq_init(dev);
340         
341         /* Set the state of the gpio lines */
342         i82801db_gpio_init(dev);
343
344         /* Initialize the real time clock */
345         rtc_init(0);
346
347         /* Initialize isa dma */
348         isa_dma_init();
349
350         /* Disable IDE (needed when sata is enabled)
351         pci_write_config8(dev, 0xf2, 0x60);
352         */
353                 
354         enable_hpet(dev);
355 }
356
357 static void i82801db_lpc_read_resources(device_t dev)
358 {
359         struct resource *res;
360
361         /* Get the normal pci resources of this device */
362         pci_dev_read_resources(dev);
363
364         /* Add the ACPI BAR */
365         res = pci_get_resource(dev, ACPI_BAR);
366
367         /* Add the GPIO BAR */
368         res = pci_get_resource(dev, GPIO_BAR);
369
370         /* Add an extra subtractive resource for both memory and I/O */
371         res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
372         res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
373
374         res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
375         res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
376 }
377
378 static void i82801db_lpc_enable_resources(device_t dev)
379 {
380         uint8_t acpi_cntl, gpio_cntl;
381
382         /* Enable the normal pci resources */
383         pci_dev_enable_resources(dev);
384
385         /* Enable the ACPI bar */
386         acpi_cntl = pci_read_config8(dev, 0x44);
387         acpi_cntl |= (1 << 4);
388         pci_write_config8(dev, 0x44, acpi_cntl);
389         
390         /* Enable the GPIO bar */
391         gpio_cntl = pci_read_config8(dev, 0x5c);
392         gpio_cntl |= (1 << 4);
393         pci_write_config8(dev, 0x5c, gpio_cntl);
394
395         enable_childrens_resources(dev);
396 }
397
398 static struct pci_operations lops_pci = {
399         .set_subsystem = 0,
400 };
401
402 static struct device_operations lpc_ops  = {
403         .read_resources   = i82801db_lpc_read_resources,
404         .set_resources    = pci_dev_set_resources,
405         .enable_resources = i82801db_lpc_enable_resources,
406         .init             = lpc_init,
407         .scan_bus         = scan_static_bus,
408         .enable           = i82801db_enable,
409         .ops_pci          = &lops_pci,
410 };
411
412 static const struct pci_driver lpc_driver __pci_driver = {
413         .ops    = &lpc_ops,
414         .vendor = PCI_VENDOR_ID_INTEL,
415         .device = PCI_DEVICE_ID_INTEL_82801DB_LPC,
416 };