blob: dc314fbcfb3b9ef4346f71d14caedd9e02f54cb3 [file] [log] [blame]
Ronald G. Minnich182615d2004-08-24 16:20:46 +00001/*
Stefan Reinauer8702ab52010-03-14 17:01:08 +00002 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2003 Linux Networx
5 * Copyright (C) 2004 SuSE Linux AG
6 * Copyright (C) 2004 Tyan Computer
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; version 2 of
11 * the License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Ronald G. Minnich182615d2004-08-24 16:20:46 +000021 */
Stefan Reinauer8702ab52010-03-14 17:01:08 +000022
Ronald G. Minnich182615d2004-08-24 16:20:46 +000023#include <console/console.h>
24#include <device/device.h>
25#include <device/pci.h>
26#include <device/pci_ids.h>
27#include <device/pci_ops.h>
Ronald G. Minnich182615d2004-08-24 16:20:46 +000028#include <pc80/mc146818rtc.h>
Steven J. Magnanief792232005-09-21 13:53:44 +000029#include <pc80/isa-dma.h>
30#include <arch/io.h>
Stefan Reinauer138be832010-02-27 01:50:21 +000031#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +000032
Ronald G. Minnich182615d2004-08-24 16:20:46 +000033#define NMI_OFF 0
34
Stefan Reinauer8702ab52010-03-14 17:01:08 +000035void i82801dx_enable_ioapic(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000036{
Stefan Reinauer8702ab52010-03-14 17:01:08 +000037 u32 dword;
38 volatile u32 *ioapic_sba = (volatile u32 *)0xfec00000;
39 volatile u32 *ioapic_sbd = (volatile u32 *)0xfec00010;
Ronald G. Minnich182615d2004-08-24 16:20:46 +000040
Stefan Reinauer8702ab52010-03-14 17:01:08 +000041 dword = pci_read_config32(dev, GEN_CNTL);
42 dword |= (3 << 7); /* enable ioapic */
43 dword |= (1 << 13); /* coprocessor error enable */
44 dword |= (1 << 1); /* delay transaction enable */
45 dword |= (1 << 2); /* DMA collection buf enable */
46 pci_write_config32(dev, GEN_CNTL, dword);
47 printk_debug("ioapic southbridge enabled %x\n", dword);
48 *ioapic_sba = 0;
49 *ioapic_sbd = (2 << 24);
50 //lyh *ioapic_sba=3;
51 //lyh *ioapic_sbd=1;
52 *ioapic_sba = 0;
53 dword = *ioapic_sbd;
54 printk_debug("Southbridge apic id = %x\n", dword);
55 if (dword != (2 << 24))
56 die("");
57 //lyh *ioapic_sba=3;
58 //lyh dword=*ioapic_sbd;
59 //lyh printk_debug("Southbridge apic DT = %x\n",dword);
60 //lyh if(dword!=1)
61 //lyh die("");
Ronald G. Minnich182615d2004-08-24 16:20:46 +000062
63}
Stefan Reinauer8702ab52010-03-14 17:01:08 +000064
65void i82801dx_enable_serial_irqs(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000066{
Stefan Reinauer8702ab52010-03-14 17:01:08 +000067 pci_write_config8(dev, SERIRQ_CNTL,
68 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Ronald G. Minnich182615d2004-08-24 16:20:46 +000069}
Stefan Reinauer8702ab52010-03-14 17:01:08 +000070
71void i82801dx_lpc_route_dma(struct device *dev, u8 mask)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000072{
Stefan Reinauer8702ab52010-03-14 17:01:08 +000073 u16 word;
74 int i;
75 word = pci_read_config16(dev, PCI_DMA_CFG);
76 word &= ((1 << 10) - (1 << 8));
77 for (i = 0; i < 8; i++) {
78 if (i == 4)
79 continue;
80 word |= ((mask & (1 << i)) ? 3 : 1) << (i * 2);
81 }
82 pci_write_config16(dev, PCI_DMA_CFG, word);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000083}
Stefan Reinauer8702ab52010-03-14 17:01:08 +000084
Stefan Reinauer138be832010-02-27 01:50:21 +000085void i82801dx_rtc_init(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000086{
Stefan Reinauer8702ab52010-03-14 17:01:08 +000087 u8 byte;
88 u32 dword;
89 int rtc_failed;
90 byte = pci_read_config8(dev, GEN_PMCON_3);
91 rtc_failed = byte & RTC_FAILED;
92 if (rtc_failed) {
93 byte &= ~(1 << 1); /* preserve the power fail state */
94 pci_write_config8(dev, GEN_PMCON_3, byte);
95 }
96 dword = pci_read_config32(dev, GEN_STS);
97 rtc_failed |= dword & (1 << 2);
98 rtc_init(rtc_failed);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000099}
100
Stefan Reinauer138be832010-02-27 01:50:21 +0000101void i82801dx_1f0_misc(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000102{
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000103 pci_write_config16(dev, PCICMD, 0x014f);
104 pci_write_config32(dev, PMBASE, 0x00001001);
105 pci_write_config8(dev, ACPI_CNTL, 0x10);
106 pci_write_config32(dev, GPIO_BASE, 0x00001181);
107 pci_write_config8(dev, GPIO_CNTL, 0x10);
108 pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B);
109 pci_write_config8(dev, PIRQE_ROUT, 0x07);
110 pci_write_config8(dev, RTC_CONF, 0x04);
111 pci_write_config8(dev, COM_DEC, 0x10); //lyh E0->
112 pci_write_config16(dev, LPC_EN, 0x000F); //LYH 000D->
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000113}
114
115static void enable_hpet(struct device *dev)
116{
117 const unsigned long hpet_address = 0xfed0000;
118
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000119 u32 dword;
120 u32 code = (0 & 0x3);
121
122 dword = pci_read_config32(dev, GEN_CNTL);
123 dword |= (1 << 17); /* enable hpet */
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000124 /*Bits [16:15]Memory Address Range
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000125 00 FED0_0000h - FED0_03FFh
126 01 FED0_1000h - FED0_13FFh
127 10 FED0_2000h - FED0_23FFh
128 11 FED0_3000h - FED0_33FFh */
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000129
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000130 dword &= ~(3 << 15); /* clear it */
131 dword |= (code << 15);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000132
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000133 printk_debug("enabling HPET @0x%x\n", hpet_address | (code << 12));
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000134}
135
136static void lpc_init(struct device *dev)
137{
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000138 u8 byte;
139 int pwr_on = -1;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +0000140 int nmi_option;
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000141
142 /* IO APIC initialization */
Stefan Reinauer138be832010-02-27 01:50:21 +0000143 i82801dx_enable_ioapic(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000144
Stefan Reinauer138be832010-02-27 01:50:21 +0000145 i82801dx_enable_serial_irqs(dev);
Steven J. Magnanief792232005-09-21 13:53:44 +0000146
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000147#ifdef SUSPICIOUS_LOOKING_CODE
Steven J. Magnanief792232005-09-21 13:53:44 +0000148 // The ICH-4 datasheet does not mention this configuration register.
149 // This code may have been inherited (incorrectly) from code for the AMD 766 southbridge,
150 // which *does* support this functionality.
151
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000152 /* posted memory write enable */
153 byte = pci_read_config8(dev, 0x46);
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000154 pci_write_config8(dev, 0x46, byte | (1 << 0));
Steven J. Magnanief792232005-09-21 13:53:44 +0000155#endif
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000156
157 /* power after power fail */
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000158 /* FIXME this doesn't work! */
159 /* Which state do we want to goto after g3 (power restored)?
160 * 0 == S0 Full On
161 * 1 == S5 Soft Off
162 */
163 pci_write_config8(dev, GEN_PMCON_3, pwr_on ? 0 : 1);
164 printk_info("set power %s after power fail\n", pwr_on ? "on" : "off");
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000165#if 0
166 /* Enable Error reporting */
167 /* Set up sync flood detected */
168 byte = pci_read_config8(dev, 0x47);
169 byte |= (1 << 1);
170 pci_write_config8(dev, 0x47, byte);
171#endif
172
173 /* Set up NMI on errors */
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000174 byte = inb(0x61);
175 byte &= ~(1 << 3); /* IOCHK# NMI Enable */
176 byte &= ~(1 << 2); /* PCI SERR# Enable */
177 outb(byte, 0x61);
178 byte = inb(0x70);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000179 nmi_option = NMI_OFF;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +0000180 get_option(&nmi_option, "nmi");
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000181 if (nmi_option) {
182 byte &= ~(1 << 7); /* set NMI */
183 outb(byte, 0x70);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000184 }
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000185
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000186 /* Initialize the real time clock */
Stefan Reinauer138be832010-02-27 01:50:21 +0000187 i82801dx_rtc_init(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000188
Stefan Reinauer138be832010-02-27 01:50:21 +0000189 i82801dx_lpc_route_dma(dev, 0xff);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000190
191 /* Initialize isa dma */
192 isa_dma_init();
193
Stefan Reinauer138be832010-02-27 01:50:21 +0000194 i82801dx_1f0_misc(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000195 /* Initialize the High Precision Event Timers */
196 enable_hpet(dev);
197}
198
Stefan Reinauer138be832010-02-27 01:50:21 +0000199static void i82801dx_lpc_read_resources(device_t dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000200{
Eric Biederman4f9265f2004-10-22 02:33:51 +0000201 struct resource *res;
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000202
Myles Watson29cc9ed2009-07-02 18:56:24 +0000203 /* Get the normal PCI resources of this device. */
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000204 pci_dev_read_resources(dev);
205
Myles Watson29cc9ed2009-07-02 18:56:24 +0000206 /* Add an extra subtractive resource for both memory and I/O. */
Eric Biederman4f9265f2004-10-22 02:33:51 +0000207 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000208 res->base = 0;
209 res->size = 0x1000;
210 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000211 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Eric Biederman4f9265f2004-10-22 02:33:51 +0000212
213 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000214 res->base = 0xff800000;
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000215 res->size = 0x00800000; /* 8 MB for flash */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000216 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000217 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000218
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000219 res = new_resource(dev, 3); /* IOAPIC */
Myles Watson29cc9ed2009-07-02 18:56:24 +0000220 res->base = 0xfec00000;
221 res->size = 0x00001000;
222 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Eric Biederman4f9265f2004-10-22 02:33:51 +0000223}
224
Stefan Reinauer138be832010-02-27 01:50:21 +0000225static void i82801dx_lpc_enable_resources(device_t dev)
Eric Biederman4f9265f2004-10-22 02:33:51 +0000226{
227 pci_dev_enable_resources(dev);
228 enable_childrens_resources(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000229}
230
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000231static struct device_operations lpc_ops = {
232 .read_resources = i82801dx_lpc_read_resources,
233 .set_resources = pci_dev_set_resources,
Stefan Reinauer138be832010-02-27 01:50:21 +0000234 .enable_resources = i82801dx_lpc_enable_resources,
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000235 .init = lpc_init,
236 .scan_bus = scan_static_bus,
237 .enable = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000238};
239
Stefan Reinauer8702ab52010-03-14 17:01:08 +0000240/* 82801DB/DBL */
241static const struct pci_driver lpc_driver_db __pci_driver = {
242 .ops = &lpc_ops,
243 .vendor = PCI_VENDOR_ID_INTEL,
244 .device = PCI_DEVICE_ID_INTEL_82801DB_LPC,
245};
246
247/* 82801DBM */
248static const struct pci_driver lpc_driver_dbm __pci_driver = {
249 .ops = &lpc_ops,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000250 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermanna29ec062007-11-04 03:21:37 +0000251 .device = PCI_DEVICE_ID_INTEL_82801DBM_LPC,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000252};