blob: 59225d2c9a760293e2f1e3898f134dd2abc371cc [file] [log] [blame]
Ronald G. Minnich182615d2004-08-24 16:20:46 +00001/*
2 * (C) 2003 Linux Networx, SuSE Linux AG
3 * (C) 2004 Tyan Computer
4 */
5#include <console/console.h>
6#include <device/device.h>
7#include <device/pci.h>
8#include <device/pci_ids.h>
9#include <device/pci_ops.h>
Ronald G. Minnich182615d2004-08-24 16:20:46 +000010#include <pc80/mc146818rtc.h>
Steven J. Magnanief792232005-09-21 13:53:44 +000011#include <pc80/isa-dma.h>
12#include <arch/io.h>
Stefan Reinauer138be832010-02-27 01:50:21 +000013#include "i82801dx.h"
Ronald G. Minnich182615d2004-08-24 16:20:46 +000014
Steven J. Magnanief792232005-09-21 13:53:44 +000015
Ronald G. Minnich182615d2004-08-24 16:20:46 +000016
17#define NMI_OFF 0
18
Stefan Reinauer138be832010-02-27 01:50:21 +000019void i82801dx_enable_ioapic( struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000020{
21 uint32_t dword;
22 volatile uint32_t *ioapic_sba = (volatile uint32_t *)0xfec00000;
23 volatile uint32_t *ioapic_sbd = (volatile uint32_t *)0xfec00010;
24
25 dword = pci_read_config32(dev, GEN_CNTL);
26 dword |= (3 << 7); /* enable ioapic */
27 dword |= (1 <<13); /* coprocessor error enable */
28 dword |= (1 << 1); /* delay transaction enable */
29 dword |= (1 << 2); /* DMA collection buf enable */
30 pci_write_config32(dev, GEN_CNTL, dword);
31 printk_debug("ioapic southbridge enabled %x\n",dword);
32 *ioapic_sba=0;
33 *ioapic_sbd=(2<<24);
34 //lyh *ioapic_sba=3;
35 //lyh *ioapic_sbd=1;
36 *ioapic_sba=0;
37 dword=*ioapic_sbd;
38 printk_debug("Southbridge apic id = %x\n",dword);
39 if(dword!=(2<<24))
Carl-Daniel Hailfinger87e70502009-06-05 11:41:51 +000040 die("");
Ronald G. Minnich182615d2004-08-24 16:20:46 +000041 //lyh *ioapic_sba=3;
42 //lyh dword=*ioapic_sbd;
43 //lyh printk_debug("Southbridge apic DT = %x\n",dword);
44 //lyh if(dword!=1)
Carl-Daniel Hailfinger87e70502009-06-05 11:41:51 +000045 //lyh die("");
Ronald G. Minnich182615d2004-08-24 16:20:46 +000046
47
48}
Stefan Reinauer138be832010-02-27 01:50:21 +000049void i82801dx_enable_serial_irqs( struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000050{
51 pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0<< 0));
52}
Stefan Reinauer138be832010-02-27 01:50:21 +000053void i82801dx_lpc_route_dma( struct device *dev, uint8_t mask)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000054{
55 uint16_t word;
56 int i;
Steven J. Magnanief792232005-09-21 13:53:44 +000057 word = pci_read_config16(dev, PCI_DMA_CFG);
Ronald G. Minnich182615d2004-08-24 16:20:46 +000058 word &= ((1 << 10) - (1 << 8));
59 for(i = 0; i < 8; i++) {
60 if (i == 4)
61 continue;
62 word |= ((mask & (1 << i))? 3:1) << (i*2);
63 }
64 pci_write_config16(dev, PCI_DMA_CFG, word);
65}
Stefan Reinauer138be832010-02-27 01:50:21 +000066void i82801dx_rtc_init(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000067{
68 uint8_t byte;
69 uint32_t dword;
70 int rtc_failed;
71 byte = pci_read_config8(dev, GEN_PMCON_3);
72 rtc_failed = byte & RTC_FAILED;
73 if (rtc_failed) {
74 byte &= ~(1 << 1); /* preserve the power fail state */
75 pci_write_config8(dev, GEN_PMCON_3, byte);
76 }
77 dword = pci_read_config32(dev, GEN_STS);
78 rtc_failed |= dword & (1 << 2);
79 rtc_init(rtc_failed);
80}
81
82
Stefan Reinauer138be832010-02-27 01:50:21 +000083void i82801dx_1f0_misc(struct device *dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +000084{
85 pci_write_config16(dev, PCICMD, 0x014f);
86 pci_write_config32(dev, PMBASE, 0x00001001);
87 pci_write_config8(dev, ACPI_CNTL, 0x10);
88 pci_write_config32(dev, GPIO_BASE, 0x00001181);
89 pci_write_config8(dev, GPIO_CNTL, 0x10);
90 pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B);
91 pci_write_config8(dev, PIRQE_ROUT, 0x07);
92 pci_write_config8(dev, RTC_CONF, 0x04);
93 pci_write_config8(dev, COM_DEC, 0x10); //lyh E0->
94 pci_write_config16(dev, LPC_EN, 0x000F); //LYH 000D->
95}
96
97static void enable_hpet(struct device *dev)
98{
99 const unsigned long hpet_address = 0xfed0000;
100
101 uint32_t dword;
102 uint32_t code = (0 & 0x3);
103
104 dword = pci_read_config32(dev, GEN_CNTL);
105 dword |= (1 << 17); /* enable hpet */
106 /*Bits [16:15]Memory Address Range
107 00 FED0_0000h - FED0_03FFh
108 01 FED0_1000h - FED0_13FFh
109 10 FED0_2000h - FED0_23FFh
110 11 FED0_3000h - FED0_33FFh*/
111
112 dword &= ~(3 << 15); /* clear it */
113 dword |= (code<<15);
114
115 printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
116}
117
118static void lpc_init(struct device *dev)
119{
120 uint8_t byte;
121 int pwr_on=-1;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +0000122 int nmi_option;
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000123
124 /* IO APIC initialization */
Stefan Reinauer138be832010-02-27 01:50:21 +0000125 i82801dx_enable_ioapic(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000126
Stefan Reinauer138be832010-02-27 01:50:21 +0000127 i82801dx_enable_serial_irqs(dev);
Steven J. Magnanief792232005-09-21 13:53:44 +0000128
129#ifdef SUSPICIOUS_LOOKING_CODE
130 // The ICH-4 datasheet does not mention this configuration register.
131 // This code may have been inherited (incorrectly) from code for the AMD 766 southbridge,
132 // which *does* support this functionality.
133
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000134 /* posted memory write enable */
135 byte = pci_read_config8(dev, 0x46);
136 pci_write_config8(dev, 0x46, byte | (1<<0));
Steven J. Magnanief792232005-09-21 13:53:44 +0000137#endif
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000138
139 /* power after power fail */
140 /* FIXME this doesn't work! */
141 /* Which state do we want to goto after g3 (power restored)?
142 * 0 == S0 Full On
143 * 1 == S5 Soft Off
144 */
145 pci_write_config8(dev, GEN_PMCON_3, pwr_on?0:1);
146 printk_info("set power %s after power fail\n", pwr_on?"on":"off");
147#if 0
148 /* Enable Error reporting */
149 /* Set up sync flood detected */
150 byte = pci_read_config8(dev, 0x47);
151 byte |= (1 << 1);
152 pci_write_config8(dev, 0x47, byte);
153#endif
154
155 /* Set up NMI on errors */
Steven J. Magnanief792232005-09-21 13:53:44 +0000156 byte = inb(0x61);
157 byte &= ~(1 << 3); /* IOCHK# NMI Enable */
158 byte &= ~(1 << 2); /* PCI SERR# Enable */
159 outb(byte, 0x61);
160 byte = inb(0x70);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000161 nmi_option = NMI_OFF;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +0000162 get_option(&nmi_option, "nmi");
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000163 if (nmi_option) {
Steven J. Magnanief792232005-09-21 13:53:44 +0000164 byte &= ~(1 << 7); /* set NMI */
165 outb(byte, 0x70);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000166 }
167
168 /* Initialize the real time clock */
Stefan Reinauer138be832010-02-27 01:50:21 +0000169 i82801dx_rtc_init(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000170
Stefan Reinauer138be832010-02-27 01:50:21 +0000171 i82801dx_lpc_route_dma(dev, 0xff);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000172
173 /* Initialize isa dma */
174 isa_dma_init();
175
Stefan Reinauer138be832010-02-27 01:50:21 +0000176 i82801dx_1f0_misc(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000177 /* Initialize the High Precision Event Timers */
178 enable_hpet(dev);
179}
180
Stefan Reinauer138be832010-02-27 01:50:21 +0000181static void i82801dx_lpc_read_resources(device_t dev)
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000182{
Eric Biederman4f9265f2004-10-22 02:33:51 +0000183 struct resource *res;
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000184
Myles Watson29cc9ed2009-07-02 18:56:24 +0000185 /* Get the normal PCI resources of this device. */
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000186 pci_dev_read_resources(dev);
187
Myles Watson29cc9ed2009-07-02 18:56:24 +0000188 /* Add an extra subtractive resource for both memory and I/O. */
Eric Biederman4f9265f2004-10-22 02:33:51 +0000189 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000190 res->base = 0;
191 res->size = 0x1000;
192 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
193 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Eric Biederman4f9265f2004-10-22 02:33:51 +0000194
195 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000196 res->base = 0xff800000;
197 res->size = 0x00800000; /* 8 MB for flash */
198 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
199 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
200
201 res = new_resource(dev, 3); /* IOAPIC */
202 res->base = 0xfec00000;
203 res->size = 0x00001000;
204 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Eric Biederman4f9265f2004-10-22 02:33:51 +0000205}
206
Stefan Reinauer138be832010-02-27 01:50:21 +0000207static void i82801dx_lpc_enable_resources(device_t dev)
Eric Biederman4f9265f2004-10-22 02:33:51 +0000208{
209 pci_dev_enable_resources(dev);
210 enable_childrens_resources(dev);
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000211}
212
213static struct device_operations lpc_ops = {
Stefan Reinauer138be832010-02-27 01:50:21 +0000214 .read_resources = i82801dx_lpc_read_resources,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000215 .set_resources = pci_dev_set_resources,
Stefan Reinauer138be832010-02-27 01:50:21 +0000216 .enable_resources = i82801dx_lpc_enable_resources,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000217 .init = lpc_init,
218 .scan_bus = scan_static_bus,
Stefan Reinauer138be832010-02-27 01:50:21 +0000219 .enable = i82801dx_enable,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000220};
221
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000222static const struct pci_driver lpc_driver __pci_driver = {
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000223 .ops = &lpc_ops,
224 .vendor = PCI_VENDOR_ID_INTEL,
Uwe Hermanna29ec062007-11-04 03:21:37 +0000225 .device = PCI_DEVICE_ID_INTEL_82801DBM_LPC,
Ronald G. Minnich182615d2004-08-24 16:20:46 +0000226};