blob: 8841760c02fd7e0a41702b405138ca9e8d8a05e9 [file] [log] [blame]
Eric Biederman7a5416a2003-06-12 19:23:51 +00001/*
Eric Biederman8d9c1232003-06-17 08:42:17 +00002 * (C) 2003 Linux Networx, SuSE Linux AG
Yinghai Lueef3f952006-01-06 01:56:25 +00003 * 2006.1 yhlu add dest apicid for IRQ0
Eric Biederman7a5416a2003-06-12 19:23:51 +00004 */
Eric Biederman52685572003-05-19 19:16:21 +00005#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>
Eric Biederman5cd81732004-03-11 15:01:31 +000010#include <pc80/mc146818rtc.h>
Eric Biedermandbec2d42004-10-21 10:44:08 +000011#include <pc80/isa-dma.h>
Yinghai Lueef3f952006-01-06 01:56:25 +000012#include <cpu/x86/lapic.h>
Stefan Reinauer0401bd82010-01-16 18:31:34 +000013#include <arch/ioapic.h>
Vladimir Serbinenko83f81ca2014-11-09 13:30:50 +010014#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +020015#include <arch/acpi.h>
16#include <arch/acpigen.h>
Vladimir Serbinenko47432542014-10-05 14:54:26 +020017#include <cpu/amd/powernow.h>
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +020018#endif
Carl-Daniel Hailfinger2ee67792008-10-01 12:52:52 +000019#include <stdlib.h>
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +020020#include <string.h>
Eric Biederman83b991a2003-10-11 06:20:25 +000021#include "amd8111.h"
Eric Biederman52685572003-05-19 19:16:21 +000022
Eric Biederman5cd81732004-03-11 15:01:31 +000023#define NMI_OFF 0
Eric Biederman52685572003-05-19 19:16:21 +000024
Stefan Reinauerbd8e17a2004-02-05 10:00:35 +000025static void enable_hpet(struct device *dev)
26{
27 unsigned long hpet_address;
Stefan Reinauer14e22772010-04-27 06:56:47 +000028
Jonathan A. Kollasch6f0e8bd2015-07-15 13:47:33 -050029 pci_write_config32(dev, 0xa0, CONFIG_HPET_ADDRESS|1);
Yinghai Lueef3f952006-01-06 01:56:25 +000030 hpet_address = pci_read_config32(dev,0xa0)& 0xfffffffe;
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000031 printk(BIOS_DEBUG, "enabling HPET @0x%lx\n", hpet_address);
Stefan Reinauer14e22772010-04-27 06:56:47 +000032
Stefan Reinauerbd8e17a2004-02-05 10:00:35 +000033}
34
Eric Biederman52685572003-05-19 19:16:21 +000035static void lpc_init(struct device *dev)
36{
37 uint8_t byte;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +000038 int nmi_option;
Eric Biederman52685572003-05-19 19:16:21 +000039
Eric Biederman52685572003-05-19 19:16:21 +000040 /* IO APIC initialization */
Eric Biederman7a5416a2003-06-12 19:23:51 +000041 byte = pci_read_config8(dev, 0x4B);
Eric Biederman52685572003-05-19 19:16:21 +000042 byte |= 1;
Eric Biederman7a5416a2003-06-12 19:23:51 +000043 pci_write_config8(dev, 0x4B, byte);
Stefan Reinauer0401bd82010-01-16 18:31:34 +000044 /* Don't rename IO APIC */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080045 setup_ioapic(VIO_APIC_VADDR, 0);
Eric Biederman52685572003-05-19 19:16:21 +000046
47 /* posted memory write enable */
Eric Biederman7a5416a2003-06-12 19:23:51 +000048 byte = pci_read_config8(dev, 0x46);
Stefan Reinauer14e22772010-04-27 06:56:47 +000049 pci_write_config8(dev, 0x46, byte | (1<<0));
Eric Biederman2c018fb2003-07-21 20:13:45 +000050
Jason Schildtc9c4dd62005-10-25 21:04:09 +000051 /* Enable 5Mib Rom window */
Eric Biederman7a5416a2003-06-12 19:23:51 +000052 byte = pci_read_config8(dev, 0x43);
Yinghai Lueef3f952006-01-06 01:56:25 +000053 byte |= 0xc0;
Eric Biederman7a5416a2003-06-12 19:23:51 +000054 pci_write_config8(dev, 0x43, byte);
Eric Biederman52685572003-05-19 19:16:21 +000055
Eric Biederman83b991a2003-10-11 06:20:25 +000056 /* Enable Port 92 fast reset */
57 byte = pci_read_config8(dev, 0x41);
58 byte |= (1 << 5);
59 pci_write_config8(dev, 0x41, byte);
Eric Biederman52685572003-05-19 19:16:21 +000060
Eric Biederman5cd81732004-03-11 15:01:31 +000061 /* Enable Error reporting */
62 /* Set up sync flood detected */
63 byte = pci_read_config8(dev, 0x47);
64 byte |= (1 << 1);
65 pci_write_config8(dev, 0x47, byte);
66
67 /* Set up NMI on errors */
68 byte = pci_read_config8(dev, 0x40);
69 byte |= (1 << 1); /* clear PW2LPC error */
70 byte |= (1 << 6); /* clear LPCERR */
71 pci_write_config8(dev, 0x40, byte);
72 nmi_option = NMI_OFF;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +000073 get_option(&nmi_option, "nmi");
Stefan Reinauer14e22772010-04-27 06:56:47 +000074 if (nmi_option) {
Eric Biederman5cd81732004-03-11 15:01:31 +000075 byte |= (1 << 7); /* set NMI */
76 pci_write_config8(dev, 0x40, byte);
77 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000078
Eric Biederman5cd81732004-03-11 15:01:31 +000079 /* Initialize the real time clock */
Gabe Blackb3f08c62014-04-30 17:12:25 -070080 cmos_init(0);
Eric Biederman5cd81732004-03-11 15:01:31 +000081
82 /* Initialize isa dma */
83 isa_dma_init();
84
85 /* Initialize the High Precision Event Timers */
Stefan Reinauerbd8e17a2004-02-05 10:00:35 +000086 enable_hpet(dev);
Eric Biederman52685572003-05-19 19:16:21 +000087}
88
Eric Biedermane9a271e32003-09-02 03:36:25 +000089static void amd8111_lpc_read_resources(device_t dev)
90{
Eric Biedermandbec2d42004-10-21 10:44:08 +000091 struct resource *res;
Eric Biedermane9a271e32003-09-02 03:36:25 +000092
Myles Watson29cc9ed2009-07-02 18:56:24 +000093 /* Get the normal PCI resources of this device. */
Eric Biedermane9a271e32003-09-02 03:36:25 +000094 pci_dev_read_resources(dev);
95
Myles Watson29cc9ed2009-07-02 18:56:24 +000096 /* Add an extra subtractive resource for both memory and I/O. */
Eric Biedermandbec2d42004-10-21 10:44:08 +000097 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +000098 res->base = 0;
99 res->size = 0x1000;
100 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
101 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
102
Eric Biedermandbec2d42004-10-21 10:44:08 +0000103 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
Myles Watson29cc9ed2009-07-02 18:56:24 +0000104 res->base = 0xff800000;
105 res->size = 0x00800000; /* 8 MB for flash */
106 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
107 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
108
109 res = new_resource(dev, 3); /* IOAPIC */
Uwe Hermann74d1a6e2010-10-12 17:34:08 +0000110 res->base = IO_APIC_ADDR;
Myles Watson29cc9ed2009-07-02 18:56:24 +0000111 res->size = 0x00001000;
112 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000113}
114
Eric Biedermandbec2d42004-10-21 10:44:08 +0000115static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
116{
Stefan Reinauer14e22772010-04-27 06:56:47 +0000117 pci_write_config32(dev, 0x70,
Yinghai Lu9a791df2006-04-03 20:38:34 +0000118 ((device & 0xffff) << 16) | (vendor & 0xffff));
Eric Biedermandbec2d42004-10-21 10:44:08 +0000119}
Li-Ta Lo3a812852004-12-03 22:39:34 +0000120
Vladimir Serbinenko83f81ca2014-11-09 13:30:50 +0100121#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +0200122
123extern u16 pm_base;
124
125unsigned long acpi_fill_mcfg(unsigned long current)
126{
127 /* Just a dummy */
128 return current;
129}
130
Alexander Couzens5eea4582015-04-12 22:18:55 +0200131static void southbridge_acpi_fill_ssdt_generator(device_t device) {
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +0200132#if CONFIG_SET_FIDVID
Vladimir Serbinenko47432542014-10-05 14:54:26 +0200133 amd_generate_powernow(pm_base + 0x10, 6, 1);
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +0200134 acpigen_write_mainboard_resources("\\_SB.PCI0.MBRS", "_CRS");
135#endif
136}
137
138#endif
139
140
Eric Biedermandbec2d42004-10-21 10:44:08 +0000141static struct pci_operations lops_pci = {
142 .set_subsystem = lpci_set_subsystem,
143};
Li-Ta Lo3a812852004-12-03 22:39:34 +0000144
Eric Biederman52685572003-05-19 19:16:21 +0000145static struct device_operations lpc_ops = {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000146 .read_resources = amd8111_lpc_read_resources,
147 .set_resources = pci_dev_set_resources,
Myles Watson7eac4452010-06-17 16:16:56 +0000148 .enable_resources = pci_dev_enable_resources,
Eric Biedermane9a271e32003-09-02 03:36:25 +0000149 .init = lpc_init,
Vladimir Serbinenko83f81ca2014-11-09 13:30:50 +0100150#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
Vladimir Serbinenko6985d4e2014-09-21 14:31:19 +0200151 .write_acpi_tables = acpi_write_hpet,
152 .acpi_fill_ssdt_generator = southbridge_acpi_fill_ssdt_generator,
153#endif
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200154 .scan_bus = scan_lpc_bus,
Eric Biedermandbec2d42004-10-21 10:44:08 +0000155 .enable = amd8111_enable,
156 .ops_pci = &lops_pci,
Eric Biederman52685572003-05-19 19:16:21 +0000157};
158
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000159static const struct pci_driver lpc_driver __pci_driver = {
Eric Biederman52685572003-05-19 19:16:21 +0000160 .ops = &lpc_ops,
161 .vendor = PCI_VENDOR_ID_AMD,
162 .device = PCI_DEVICE_ID_AMD_8111_ISA,
163};