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