blob: dbc5eccf963fbf80f14d6cfadbc877379761d1e9 [file] [log] [blame]
Mariusz Szafranskia4041332017-08-02 17:28:17 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 - 2017 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pci_ids.h>
21#include <arch/io.h>
22#include <arch/ioapic.h>
23#include <arch/acpi.h>
Mariusz Szafranskia4041332017-08-02 17:28:17 +020024#include <cpu/x86/smm.h>
25#include <bootstate.h>
26
27#include <soc/lpc.h>
28#include <soc/pci_devs.h>
29#include <soc/ramstage.h>
30#include <soc/iomap.h>
31#include <soc/pcr.h>
32#include <soc/p2sb.h>
33#include <soc/acpi.h>
34
35#include "chip.h"
36
37/* PCH-LP redirection entries */
38#define PCH_LP_REDIR_ETR 120
39
40/**
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +010041 * Set miscellaneous static southbridge features.
Mariusz Szafranskia4041332017-08-02 17:28:17 +020042 *
43 * @param dev PCI device with I/O APIC control registers
44 */
45static void pch_enable_ioapic(struct device *dev)
46{
47 u32 reg32;
48
49 set_ioapic_id((void *)IO_APIC_ADDR, IO_APIC0);
50
51 /* affirm full set of redirection table entries ("write once") */
52 reg32 = io_apic_read((void *)IO_APIC_ADDR, 0x01);
53
54 reg32 &= ~0x00ff0000;
55 reg32 |= (PCH_LP_REDIR_ETR - 1) << 16;
56
57 io_apic_write((void *)IO_APIC_ADDR, 0x01, reg32);
58
59 /*
60 * Select Boot Configuration register (0x03) and
61 * use Processor System Bus (0x01) to deliver interrupts.
62 */
63 io_apic_write((void *)IO_APIC_ADDR, 0x03, 0x01);
64}
65
66/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
67 * 0x00 - 0000 = Reserved
68 * 0x01 - 0001 = Reserved
69 * 0x02 - 0010 = Reserved
70 * 0x03 - 0011 = IRQ3
71 * 0x04 - 0100 = IRQ4
72 * 0x05 - 0101 = IRQ5
73 * 0x06 - 0110 = IRQ6
74 * 0x07 - 0111 = IRQ7
75 * 0x08 - 1000 = Reserved
76 * 0x09 - 1001 = IRQ9
77 * 0x0A - 1010 = IRQ10
78 * 0x0B - 1011 = IRQ11
79 * 0x0C - 1100 = IRQ12
80 * 0x0D - 1101 = Reserved
81 * 0x0E - 1110 = IRQ14
82 * 0x0F - 1111 = IRQ15
83 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
84 * 0x80 - The PIRQ is not routed.
85 */
86
Elyes HAOUAS2ec41832018-05-27 17:40:58 +020087static void pch_pirq_init(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +020088{
Elyes HAOUAS2ec41832018-05-27 17:40:58 +020089 struct device *irq_dev;
Mariusz Szafranskia4041332017-08-02 17:28:17 +020090 /* Get the chip configuration */
91 config_t *config = dev->chip_info;
92
93 /* Initialize PIRQ Routings */
94 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQA_ROUT),
95 config->pirqa_routing);
96 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQB_ROUT),
97 config->pirqb_routing);
98 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQC_ROUT),
99 config->pirqc_routing);
100 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQD_ROUT),
101 config->pirqd_routing);
102
103 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQE_ROUT),
104 config->pirqe_routing);
105 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQF_ROUT),
106 config->pirqf_routing);
107 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQG_ROUT),
108 config->pirqg_routing);
109 write8((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIRQH_ROUT),
110 config->pirqh_routing);
111
112 /* Initialize device's Interrupt Routings */
113 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR00),
114 config->ir00_routing);
115 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR01),
116 config->ir01_routing);
117 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR02),
118 config->ir02_routing);
119 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR03),
120 config->ir03_routing);
121 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR04),
122 config->ir04_routing);
123 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR05),
124 config->ir05_routing);
125 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR06),
126 config->ir06_routing);
127 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR07),
128 config->ir07_routing);
129 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR08),
130 config->ir08_routing);
131 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR09),
132 config->ir09_routing);
133 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR10),
134 config->ir10_routing);
135 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR11),
136 config->ir11_routing);
137 write16((void *)PCH_PCR_ADDRESS(PID_ITSS, PCR_ITSS_PIR12),
138 config->ir12_routing);
139
140 /* Initialize device's Interrupt Polarity Control */
141 write32((void *)PCH_PCR_ADDRESS(PID_ITSS, PCH_PCR_ITSS_IPC0),
142 config->ipc0);
143 write32((void *)PCH_PCR_ADDRESS(PID_ITSS, PCH_PCR_ITSS_IPC1),
144 config->ipc1);
145 write32((void *)PCH_PCR_ADDRESS(PID_ITSS, PCH_PCR_ITSS_IPC2),
146 config->ipc2);
147 write32((void *)PCH_PCR_ADDRESS(PID_ITSS, PCH_PCR_ITSS_IPC3),
148 config->ipc3);
149
150 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
151 u8 int_pin = 0, int_line = 0;
152
153 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
154 continue;
155
156 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
157
158 switch (int_pin) {
159 case 1: /* INTA# */
160 int_line = config->pirqa_routing;
161 break;
162 case 2: /* INTB# */
163 int_line = config->pirqb_routing;
164 break;
165 case 3: /* INTC# */
166 int_line = config->pirqc_routing;
167 break;
168 case 4: /* INTD# */
169 int_line = config->pirqd_routing;
170 break;
171 }
172
173 if (!int_line)
174 continue;
175
176 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
177 }
178}
179
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200180static void pci_p2sb_read_resources(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200181{
182 struct resource *res;
183
184 /* Add MMIO resource
185 * Use 0xda as an unused index for PCR BAR.
186 */
187 res = new_resource(dev, 0xda);
188 res->base = DEFAULT_PCR_BASE;
189 res->size = 16 * 1024 * 1024; /* 16MB PCR config space */
190 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
191 IORESOURCE_ASSIGNED;
192 printk(BIOS_DEBUG,
193 "Adding P2SB PCR config space BAR 0x%08lx-0x%08lx.\n",
194 (unsigned long)(res->base),
195 (unsigned long)(res->base + res->size));
196
197 /* Add MMIO resource
198 * Use 0xdb as an unused index for IOAPIC.
199 */
200 res = new_resource(dev, 0xdb); /* IOAPIC */
201 res->base = IO_APIC_ADDR;
202 res->size = 0x00001000;
203 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
204}
205
206static void pch_enable_serial_irqs(struct device *dev)
207{
208 /* Set packet length and toggle silent mode bit for one frame. */
209 pci_write_config8(dev, SERIRQ_CNTL,
210 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
211#if !IS_ENABLED(CONFIG_SERIRQ_CONTINUOUS_MODE)
212 pci_write_config8(dev, SERIRQ_CNTL,
213 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
214#endif
215}
216
217static void lpc_init(struct device *dev)
218{
219 printk(BIOS_DEBUG, "pch: lpc_init\n");
220
221 /* Get the base address */
222
223 /* Set the value for PCI command register. */
224 pci_write_config16(dev, PCI_COMMAND,
225 PCI_COMMAND_SPECIAL | PCI_COMMAND_MASTER |
226 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
227
228 /* Serial IRQ initialization. */
229 pch_enable_serial_irqs(dev);
230
231 /* IO APIC initialization. */
232 pch_enable_ioapic(dev);
233
234 /* Setup the PIRQ. */
235 pch_pirq_init(dev);
236}
237
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200238static void pch_lpc_add_mmio_resources(struct device *dev) { /* TODO */ }
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200239
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200240static void pch_lpc_add_io_resources(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200241{
242 struct resource *res;
243 u8 io_index = 0;
244
245 /* Add an extra subtractive resource for both memory and I/O. */
246 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
247 res->base = 0;
248 res->size = 0x1000;
249 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
250 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
251
252 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
253 res->base = 0xff000000;
254 res->size = 0x01000000; /* 16 MB for flash */
255 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
256 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
257}
258
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200259static void lpc_read_resources(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200260{
261 /* Get the normal PCI resources of this device. */
262 pci_dev_read_resources(dev);
263
264 /* Add non-standard MMIO resources. */
265 pch_lpc_add_mmio_resources(dev);
266
267 /* Add IO resources. */
268 pch_lpc_add_io_resources(dev);
269
270 /* Add MMIO resource for IOAPIC. */
271 pci_p2sb_read_resources(dev);
272}
273
274static void pch_decode_init(struct device *dev) { /* TODO */ }
275
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200276static void lpc_enable_resources(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200277{
278 pch_decode_init(dev);
279 pci_dev_enable_resources(dev);
280}
281
282/* Set bit in Function Disable register to hide this device */
283static void pch_hide_devfn(uint32_t devfn) { /* TODO */ }
284
Elyes HAOUAS2ec41832018-05-27 17:40:58 +0200285void southcluster_enable_dev(struct device *dev)
Mariusz Szafranskia4041332017-08-02 17:28:17 +0200286{
287 u32 reg32;
288
289 if (!dev->enabled) {
290 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
291
292 /* Ensure memory, io, and bus master are all disabled */
293 reg32 = pci_read_config32(dev, PCI_COMMAND);
294 reg32 &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
295 PCI_COMMAND_IO);
296 pci_write_config32(dev, PCI_COMMAND, reg32);
297
298 /* Hide this device if possible */
299 pch_hide_devfn(dev->path.pci.devfn);
300 } else {
301 /* Enable SERR */
302 reg32 = pci_read_config32(dev, PCI_COMMAND);
303 reg32 |= PCI_COMMAND_SERR;
304 pci_write_config32(dev, PCI_COMMAND, reg32);
305 }
306}
307
308static struct device_operations device_ops = {
309 .read_resources = lpc_read_resources,
310 .set_resources = pci_dev_set_resources,
311#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
312 .acpi_inject_dsdt_generator = southcluster_inject_dsdt,
313 .write_acpi_tables = southcluster_write_acpi_tables,
314#endif
315 .enable_resources = lpc_enable_resources,
316 .init = lpc_init,
317 .enable = southcluster_enable_dev,
318 .scan_bus = scan_lpc_bus,
319 .ops_pci = &soc_pci_ops,
320};
321
322static const struct pci_driver lpc_driver __pci_driver = {
323 .ops = &device_ops,
324 .vendor = PCI_VENDOR_ID_INTEL,
325 .device = LPC_DEVID,
326};
327
328static void finalize_chipset(void *unused)
329{
330 printk(BIOS_DEBUG, "Finalizing SMM.\n");
331 outb(APM_CNT_FINALIZE, APM_CNT);
332}
333
334BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, finalize_chipset, NULL);
335BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, finalize_chipset, NULL);