blob: 24d4b8b4764e905da8d228827722d50e844a1f03 [file] [log] [blame]
Lee Leahy77ff0b12015-05-05 15:07:29 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2013 Google Inc.
Lee Leahy32471722015-04-20 15:20:28 -07006 * Copyright (C) 2015 Intel Corp.
Lee Leahy77ff0b12015-05-05 15:07:29 -07007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Lee Leahy77ff0b12015-05-05 15:07:29 -070016 */
17
Lee Leahy77ff0b12015-05-05 15:07:29 -070018#include <arch/io.h>
19#include <arch/acpi.h>
Lee Leahy2bc9cee2015-06-30 15:25:44 -070020#include <arch/acpigen.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070021#include <bootstate.h>
22#include <cbmem.h>
Lee Leahy32471722015-04-20 15:20:28 -070023#include "chip.h"
Aaron Durbin64031672018-04-21 14:45:32 -060024#include <compiler.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070025#include <console/console.h>
26#include <cpu/x86/smm.h>
27#include <device/device.h>
28#include <device/pci.h>
29#include <device/pci_ids.h>
30#include <pc80/mc146818rtc.h>
Lee Leahy32471722015-04-20 15:20:28 -070031#include <romstage_handoff.h>
Lee Leahy2bc9cee2015-06-30 15:25:44 -070032#include <soc/acpi.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070033#include <soc/iomap.h>
34#include <soc/irq.h>
35#include <soc/lpc.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070036#include <soc/pci_devs.h>
Lee Leahy32471722015-04-20 15:20:28 -070037#include <soc/pm.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070038#include <soc/ramstage.h>
39#include <soc/spi.h>
Lee Leahy32471722015-04-20 15:20:28 -070040#include <spi-generic.h>
41#include <stdint.h>
Hannah Williams3fa80a92017-03-22 16:33:36 -070042#include <reg_script.h>
43
44static const struct reg_script ops[] = {
45 REG_MMIO_RMW32(ILB_BASE_ADDRESS + SCNT,
46 ~SCNT_MODE, 0), /* put LPC SERIRQ in Quiet Mode */
47 REG_SCRIPT_END
48};
49
50static void enable_serirq_quiet_mode(void)
51{
52 reg_script_run(ops);
53}
Lee Leahy77ff0b12015-05-05 15:07:29 -070054
55static inline void
Elyes HAOUASb13fac32018-05-24 22:29:44 +020056add_mmio_resource(struct device *dev, int i, unsigned long addr,
57 unsigned long size)
Lee Leahy77ff0b12015-05-05 15:07:29 -070058{
Lee Leahy32471722015-04-20 15:20:28 -070059 printk(BIOS_SPEW, "%s/%s ( %s, 0x%016lx, 0x%016lx )\n",
60 __FILE__, __func__, dev_name(dev), addr, size);
Lee Leahy77ff0b12015-05-05 15:07:29 -070061 mmio_resource(dev, i, addr >> 10, size >> 10);
62}
63
Elyes HAOUASb13fac32018-05-24 22:29:44 +020064static void sc_add_mmio_resources(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070065{
Lee Leahy32471722015-04-20 15:20:28 -070066 printk(BIOS_SPEW, "%s/%s ( %s )\n",
67 __FILE__, __func__, dev_name(dev));
Lee Leahy77ff0b12015-05-05 15:07:29 -070068 add_mmio_resource(dev, 0xfeb, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE);
69 add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, PMC_BASE_SIZE);
70 add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, IO_BASE_SIZE);
71 add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, ILB_BASE_SIZE);
72 add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, SPI_BASE_SIZE);
73 add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE);
74 add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE);
75 add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE);
76}
77
78/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
79#define LPC_DEFAULT_IO_RANGE_LOWER 0
80#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000
81
82static inline int io_range_in_default(int base, int size)
83{
84 /* Does it start above the range? */
85 if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
86 return 0;
87
88 /* Is it entirely contained? */
89 if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
90 (base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
91 return 1;
92
93 /* This will return not in range for partial overlaps. */
94 return 0;
95}
96
97/*
98 * Note: this function assumes there is no overlap with the default LPC device's
99 * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
100 */
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200101static void sc_add_io_resource(struct device *dev, int base, int size,
102 int index)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700103{
104 struct resource *res;
105
Lee Leahy32471722015-04-20 15:20:28 -0700106 printk(BIOS_SPEW, "%s/%s ( %s, 0x%08x, 0x%08x, 0x%08x )\n",
107 __FILE__, __func__, dev_name(dev), base, size, index);
108
Lee Leahy77ff0b12015-05-05 15:07:29 -0700109 if (io_range_in_default(base, size))
110 return;
111
112 res = new_resource(dev, index);
113 res->base = base;
114 res->size = size;
115 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
116}
117
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200118static void sc_add_io_resources(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700119{
120 struct resource *res;
121
Lee Leahy32471722015-04-20 15:20:28 -0700122 printk(BIOS_SPEW, "%s/%s ( %s )\n",
123 __FILE__, __func__, dev_name(dev));
124
Lee Leahy77ff0b12015-05-05 15:07:29 -0700125 /* Add the default claimed IO range for the LPC device. */
126 res = new_resource(dev, 0);
127 res->base = LPC_DEFAULT_IO_RANGE_LOWER;
128 res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
129 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
130
131 /* GPIO */
132 sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE);
133
134 /* ACPI */
135 sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE);
136}
137
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200138static void sc_read_resources(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700139{
Lee Leahy32471722015-04-20 15:20:28 -0700140 printk(BIOS_SPEW, "%s/%s ( %s )\n",
141 __FILE__, __func__, dev_name(dev));
142
Lee Leahy77ff0b12015-05-05 15:07:29 -0700143 /* Get the normal PCI resources of this device. */
144 pci_dev_read_resources(dev);
145
146 /* Add non-standard MMIO resources. */
147 sc_add_mmio_resources(dev);
148
149 /* Add IO resources. */
150 sc_add_io_resources(dev);
151}
152
153static void sc_rtc_init(void)
154{
Aaron Durbinb19e33f2017-09-15 14:32:13 -0600155 printk(BIOS_SPEW, "%s/%s\n", __FILE__, __func__);
156 cmos_init(rtc_failure());
Lee Leahy77ff0b12015-05-05 15:07:29 -0700157}
158
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200159static void sc_init(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700160{
161 int i;
Lee Leahy32471722015-04-20 15:20:28 -0700162 const unsigned long pr_base = ILB_BASE_ADDRESS + 0x08;
163 const unsigned long ir_base = ILB_BASE_ADDRESS + 0x20;
164 void *gen_pmcon1 = (void *)(PMC_BASE_ADDRESS + GEN_PMCON1);
165 void *actl = (void *)(ILB_BASE_ADDRESS + ACTL);
166 const struct soc_irq_route *ir = &global_soc_irq_route;
167 struct soc_intel_braswell_config *config = dev->chip_info;
168
169 printk(BIOS_SPEW, "%s/%s ( %s )\n",
170 __FILE__, __func__, dev_name(dev));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700171
172 /* Set up the PIRQ PIC routing based on static config. */
Lee Leahy32471722015-04-20 15:20:28 -0700173 for (i = 0; i < NUM_PIRQS; i++)
174 write8((void *)(pr_base + i*sizeof(ir->pic[i])),
175 ir->pic[i]);
176
Lee Leahy77ff0b12015-05-05 15:07:29 -0700177 /* Set up the per device PIRQ routing base on static config. */
Lee Leahy32471722015-04-20 15:20:28 -0700178 for (i = 0; i < NUM_IR_DEVS; i++)
179 write16((void *)(ir_base + i*sizeof(ir->pcidev[i])),
180 ir->pcidev[i]);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700181
182 /* Route SCI to IRQ9 */
183 write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9);
184
185 sc_rtc_init();
186
187 if (config->disable_slp_x_stretch_sus_fail) {
188 printk(BIOS_DEBUG, "Disabling slp_x stretching.\n");
189 write32(gen_pmcon1,
190 read32(gen_pmcon1) | DIS_SLP_X_STRCH_SUS_UP);
191 } else {
192 write32(gen_pmcon1,
193 read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP);
194 }
195
Lee Leahy77ff0b12015-05-05 15:07:29 -0700196}
197
198/*
199 * Common code for the south cluster devices.
200 */
201
Lee Leahy32471722015-04-20 15:20:28 -0700202/* Set bit in function disble register to hide this device. */
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200203static void sc_disable_devfn(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700204{
Lee Leahy32471722015-04-20 15:20:28 -0700205 void *func_dis = (void *)(PMC_BASE_ADDRESS + FUNC_DIS);
206 void *func_dis2 = (void *)(PMC_BASE_ADDRESS + FUNC_DIS2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700207 uint32_t mask = 0;
208 uint32_t mask2 = 0;
209
Lee Leahy32471722015-04-20 15:20:28 -0700210 printk(BIOS_SPEW, "%s/%s ( %s )\n",
211 __FILE__, __func__, dev_name(dev));
212
213#define SET_DIS_MASK(name_) \
214 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
215 mask |= name_ ## _DIS
216#define SET_DIS_MASK2(name_) \
217 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
218 mask2 |= name_ ## _DIS
219
Lee Leahy77ff0b12015-05-05 15:07:29 -0700220 switch (dev->path.pci.devfn) {
Lee Leahy32471722015-04-20 15:20:28 -0700221 SET_DIS_MASK(SDIO);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700222 break;
Lee Leahy32471722015-04-20 15:20:28 -0700223 SET_DIS_MASK(SD);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700224 break;
Lee Leahy32471722015-04-20 15:20:28 -0700225 SET_DIS_MASK(SATA);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700226 break;
Lee Leahy32471722015-04-20 15:20:28 -0700227 SET_DIS_MASK(XHCI);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700228 /* Disable super speed PHY when XHCI is not available. */
229 mask2 |= USH_SS_PHY_DIS;
230 break;
Lee Leahy32471722015-04-20 15:20:28 -0700231 SET_DIS_MASK(LPE);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700232 break;
Lee Leahy32471722015-04-20 15:20:28 -0700233 SET_DIS_MASK(MMC);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700234 break;
Lee Leahy32471722015-04-20 15:20:28 -0700235 SET_DIS_MASK(SIO_DMA1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700236 break;
Lee Leahy32471722015-04-20 15:20:28 -0700237 SET_DIS_MASK(I2C1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700238 break;
Lee Leahy32471722015-04-20 15:20:28 -0700239 SET_DIS_MASK(I2C2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700240 break;
Lee Leahy32471722015-04-20 15:20:28 -0700241 SET_DIS_MASK(I2C3);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700242 break;
Lee Leahy32471722015-04-20 15:20:28 -0700243 SET_DIS_MASK(I2C4);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700244 break;
Lee Leahy32471722015-04-20 15:20:28 -0700245 SET_DIS_MASK(I2C5);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700246 break;
Lee Leahy32471722015-04-20 15:20:28 -0700247 SET_DIS_MASK(I2C6);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700248 break;
Lee Leahy32471722015-04-20 15:20:28 -0700249 SET_DIS_MASK(I2C7);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700250 break;
Lee Leahy32471722015-04-20 15:20:28 -0700251 SET_DIS_MASK(TXE);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700252 break;
Lee Leahy32471722015-04-20 15:20:28 -0700253 SET_DIS_MASK(HDA);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700254 break;
Lee Leahy32471722015-04-20 15:20:28 -0700255 SET_DIS_MASK(PCIE_PORT1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700256 break;
Lee Leahy32471722015-04-20 15:20:28 -0700257 SET_DIS_MASK(PCIE_PORT2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700258 break;
Lee Leahy32471722015-04-20 15:20:28 -0700259 SET_DIS_MASK(PCIE_PORT3);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700260 break;
Lee Leahy32471722015-04-20 15:20:28 -0700261 SET_DIS_MASK(PCIE_PORT4);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700262 break;
Lee Leahy32471722015-04-20 15:20:28 -0700263 SET_DIS_MASK(SIO_DMA2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700264 break;
Lee Leahy32471722015-04-20 15:20:28 -0700265 SET_DIS_MASK(PWM1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700266 break;
Lee Leahy32471722015-04-20 15:20:28 -0700267 SET_DIS_MASK(PWM2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700268 break;
Lee Leahy32471722015-04-20 15:20:28 -0700269 SET_DIS_MASK(HSUART1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700270 break;
Lee Leahy32471722015-04-20 15:20:28 -0700271 SET_DIS_MASK(HSUART2);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700272 break;
Lee Leahy32471722015-04-20 15:20:28 -0700273 SET_DIS_MASK(SPI);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700274 break;
Lee Leahy32471722015-04-20 15:20:28 -0700275 SET_DIS_MASK2(SMBUS);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700276 break;
277 }
278
279 if (mask != 0) {
280 write32(func_dis, read32(func_dis) | mask);
281 /* Ensure posted write hits. */
282 read32(func_dis);
283 }
284
285 if (mask2 != 0) {
286 write32(func_dis2, read32(func_dis2) | mask2);
287 /* Ensure posted write hits. */
288 read32(func_dis2);
289 }
290}
291
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200292static inline void set_d3hot_bits(struct device *dev, int offset)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700293{
294 uint32_t reg8;
Lee Leahy32471722015-04-20 15:20:28 -0700295
296 printk(BIOS_SPEW, "%s/%s ( %s, 0x%08x )\n",
297 __FILE__, __func__, dev_name(dev), offset);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700298 printk(BIOS_DEBUG, "Power management CAP offset 0x%x.\n", offset);
299 reg8 = pci_read_config8(dev, offset + 4);
300 reg8 |= 0x3;
301 pci_write_config8(dev, offset + 4, reg8);
302}
303
Lee Leahy32471722015-04-20 15:20:28 -0700304/*
305 * Parts of the audio subsystem are powered by the HDA device. Therefore, one
Lee Leahy77ff0b12015-05-05 15:07:29 -0700306 * cannot put HDA into D3Hot. Instead perform this workaround to make some of
Lee Leahy32471722015-04-20 15:20:28 -0700307 * the audio paths work for LPE audio.
308 */
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200309static void hda_work_around(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700310{
Lee Leahy32471722015-04-20 15:20:28 -0700311 void *gctl = (void *)(TEMP_BASE_ADDRESS + 0x8);
312
313 printk(BIOS_SPEW, "%s/%s ( %s )\n",
314 __FILE__, __func__, dev_name(dev));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700315
316 /* Need to set magic register 0x43 to 0xd7 in config space. */
317 pci_write_config8(dev, 0x43, 0xd7);
318
Lee Leahy32471722015-04-20 15:20:28 -0700319 /*
320 * Need to set bit 0 of GCTL to take the device out of reset. However,
321 * that requires setting up the 64-bit BAR.
322 */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700323 pci_write_config32(dev, PCI_BASE_ADDRESS_0, TEMP_BASE_ADDRESS);
324 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
325 pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
326 write32(gctl, read32(gctl) | 0x1);
327 pci_write_config8(dev, PCI_COMMAND, 0);
328 pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0);
329}
330
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200331static int place_device_in_d3hot(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700332{
Lee Leahy1072e7d2017-03-16 17:35:32 -0700333 unsigned int offset;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700334
Lee Leahy32471722015-04-20 15:20:28 -0700335 printk(BIOS_SPEW, "%s/%s ( %s )\n",
336 __FILE__, __func__, dev_name(dev));
337
338 /*
339 * Parts of the HDA block are used for LPE audio as well.
340 * Therefore assume the HDA will never be put into D3Hot.
341 */
Lee Leahy77ff0b12015-05-05 15:07:29 -0700342 if (dev->path.pci.devfn == PCI_DEVFN(HDA_DEV, HDA_FUNC)) {
343 hda_work_around(dev);
344 return 0;
345 }
346
347 offset = pci_find_capability(dev, PCI_CAP_ID_PM);
348
349 if (offset != 0) {
350 set_d3hot_bits(dev, offset);
351 return 0;
352 }
353
Lee Leahy32471722015-04-20 15:20:28 -0700354 /*
355 * For some reason some of the devices don't have the capability
356 * pointer set correctly. Work around this by hard coding the offset.
357 */
358#define DEV_CASE(name_) \
359 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
360
Lee Leahy77ff0b12015-05-05 15:07:29 -0700361 switch (dev->path.pci.devfn) {
Lee Leahy32471722015-04-20 15:20:28 -0700362 DEV_CASE(SDIO) :
363 DEV_CASE(SD) :
364 DEV_CASE(MMC) :
365 DEV_CASE(LPE) :
366 DEV_CASE(SIO_DMA1) :
367 DEV_CASE(I2C1) :
368 DEV_CASE(I2C2) :
369 DEV_CASE(I2C3) :
370 DEV_CASE(I2C4) :
371 DEV_CASE(I2C5) :
372 DEV_CASE(I2C6) :
373 DEV_CASE(I2C7) :
374 DEV_CASE(SIO_DMA2) :
375 DEV_CASE(PWM1) :
376 DEV_CASE(PWM2) :
377 DEV_CASE(HSUART1) :
378 DEV_CASE(HSUART2) :
379 DEV_CASE(SPI) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700380 offset = 0x80;
381 break;
Lee Leahy32471722015-04-20 15:20:28 -0700382 DEV_CASE(SATA) :
383 DEV_CASE(XHCI) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700384 offset = 0x70;
385 break;
Lee Leahy32471722015-04-20 15:20:28 -0700386 DEV_CASE(HDA) :
387 DEV_CASE(SMBUS) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700388 offset = 0x50;
389 break;
Lee Leahy32471722015-04-20 15:20:28 -0700390 DEV_CASE(TXE) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700391 /* TXE cannot be placed in D3Hot. */
392 return 0;
Lee Leahy32471722015-04-20 15:20:28 -0700393 DEV_CASE(PCIE_PORT1) :
394 DEV_CASE(PCIE_PORT2) :
395 DEV_CASE(PCIE_PORT3) :
396 DEV_CASE(PCIE_PORT4) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700397 offset = 0xa0;
398 break;
399 }
400
401 if (offset != 0) {
402 set_d3hot_bits(dev, offset);
403 return 0;
404 }
405
406 return -1;
407}
408
409/* Common PCI device function disable. */
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200410void southcluster_enable_dev(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700411{
412 uint32_t reg32;
413
Lee Leahy32471722015-04-20 15:20:28 -0700414 printk(BIOS_SPEW, "%s/%s ( %s )\n",
415 __FILE__, __func__, dev_name(dev));
Lee Leahy77ff0b12015-05-05 15:07:29 -0700416 if (!dev->enabled) {
417 int slot = PCI_SLOT(dev->path.pci.devfn);
418 int func = PCI_FUNC(dev->path.pci.devfn);
419 printk(BIOS_DEBUG, "%s: Disabling device: %02x.%01x\n",
420 dev_path(dev), slot, func);
421
422 /* Ensure memory, io, and bus master are all disabled */
423 reg32 = pci_read_config32(dev, PCI_COMMAND);
424 reg32 &= ~(PCI_COMMAND_MASTER |
425 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
426 pci_write_config32(dev, PCI_COMMAND, reg32);
427
428 /* Place device in D3Hot */
429 if (place_device_in_d3hot(dev) < 0) {
430 printk(BIOS_WARNING,
431 "Could not place %02x.%01x into D3Hot. "
432 "Keeping device visible.\n", slot, func);
433 return;
434 }
435 /* Disable this device if possible */
436 sc_disable_devfn(dev);
437 } else {
438 /* Enable SERR */
439 reg32 = pci_read_config32(dev, PCI_COMMAND);
440 reg32 |= PCI_COMMAND_SERR;
441 pci_write_config32(dev, PCI_COMMAND, reg32);
442 }
443}
444
445static struct device_operations device_ops = {
446 .read_resources = sc_read_resources,
447 .set_resources = pci_dev_set_resources,
448 .enable_resources = NULL,
Lee Leahy2bc9cee2015-06-30 15:25:44 -0700449 .acpi_inject_dsdt_generator = southcluster_inject_dsdt,
450 .write_acpi_tables = southcluster_write_acpi_tables,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700451 .init = sc_init,
452 .enable = southcluster_enable_dev,
Lee Leahy32471722015-04-20 15:20:28 -0700453 .scan_bus = scan_lpc_bus,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700454 .ops_pci = &soc_pci_ops,
455};
456
457static const struct pci_driver southcluster __pci_driver = {
458 .ops = &device_ops,
459 .vendor = PCI_VENDOR_ID_INTEL,
460 .device = LPC_DEVID,
461};
462
Aaron Durbin64031672018-04-21 14:45:32 -0600463int __weak mainboard_get_spi_config(struct spi_config *cfg)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700464{
Lee Leahy32471722015-04-20 15:20:28 -0700465 printk(BIOS_SPEW, "%s/%s ( 0x%p )\n",
466 __FILE__, __func__, (void *)cfg);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700467 return -1;
468}
469
470static void finalize_chipset(void *unused)
471{
Lee Leahy32471722015-04-20 15:20:28 -0700472 void *bcr = (void *)(SPI_BASE_ADDRESS + BCR);
473 void *gcs = (void *)(RCBA_BASE_ADDRESS + GCS);
474 void *gen_pmcon2 = (void *)(PMC_BASE_ADDRESS + GEN_PMCON2);
475 void *etr = (void *)(PMC_BASE_ADDRESS + ETR);
476 uint8_t *spi = (uint8_t *)SPI_BASE_ADDRESS;
Lee Leahy77ff0b12015-05-05 15:07:29 -0700477 struct spi_config cfg;
478
Lee Leahy32471722015-04-20 15:20:28 -0700479 printk(BIOS_SPEW, "%s/%s ( 0x%p )\n",
480 __FILE__, __func__, unused);
481
Lee Leahy77ff0b12015-05-05 15:07:29 -0700482 /* Set the lock enable on the BIOS control register. */
483 write32(bcr, read32(bcr) | BCR_LE);
484
485 /* Set BIOS lock down bit controlling boot block size and swapping. */
486 write32(gcs, read32(gcs) | BILD);
487
488 /* Lock sleep stretching policy and set SMI lock. */
489 write32(gen_pmcon2, read32(gen_pmcon2) | SLPSX_STR_POL_LOCK | SMI_LOCK);
490
491 /* Set the CF9 lock. */
492 write32(etr, read32(etr) | CF9LOCK);
493
494 if (mainboard_get_spi_config(&cfg) < 0) {
495 printk(BIOS_DEBUG, "No SPI lockdown configuration.\n");
496 } else {
497 write16(spi + PREOP, cfg.preop);
498 write16(spi + OPTYPE, cfg.optype);
499 write32(spi + OPMENU0, cfg.opmenu[0]);
500 write32(spi + OPMENU1, cfg.opmenu[1]);
501 write16(spi + HSFSTS, read16(spi + HSFSTS) | FLOCKDN);
502 write32(spi + UVSCC, cfg.uvscc);
503 write32(spi + LVSCC, cfg.lvscc | VCL);
504 }
Lee Leahy32471722015-04-20 15:20:28 -0700505 spi_init();
Hannah Williams3fa80a92017-03-22 16:33:36 -0700506 enable_serirq_quiet_mode();
Lee Leahy77ff0b12015-05-05 15:07:29 -0700507
508 printk(BIOS_DEBUG, "Finalizing SMM.\n");
509 outb(APM_CNT_FINALIZE, APM_CNT);
510}
511
Hannah Williams2cfdde72015-04-15 19:48:07 -0700512BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, finalize_chipset, NULL);