2 * This file is part of the coreboot project.
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2014 Google Inc.
6 * Copyright (C) 2015 Intel Corporation.
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.
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.
19 #include <console/console.h>
20 #include <device/device.h>
21 #include <device/pci.h>
22 #include <device/pci_ids.h>
24 #include <arch/ioapic.h>
25 #include <arch/acpi.h>
27 #include <pc80/mc146818rtc.h>
28 #include <reg_script.h>
31 #include <soc/iomap.h>
32 #include <soc/pci_devs.h>
35 #include <cpu/x86/smm.h>
37 #include <soc/ramstage.h>
38 #if IS_ENABLED(CONFIG_CHROMEOS)
39 #include <vendorcode/google/chromeos/chromeos.h>
42 static const struct reg_script pch_pmc_misc_init_script
[] = {
43 /* SLP_S4=4s, SLP_S3=50ms, disable SLP_X stretching after SUS loss. */
44 REG_PCI_RMW16(GEN_PMCON_B
,
45 ~(S4MAW_MASK
| SLP_S3_MIN_ASST_WDTH_MASK
),
46 S4MAW_4S
| SLP_S3_MIN_ASST_WDTH_50MS
|
47 DIS_SLP_X_STRCH_SUS_UP
),
48 /* Enable SCI and clear SLP requests. */
49 REG_IO_RMW32(ACPI_BASE_ADDRESS
+ PM1_CNT
, ~SLP_TYP
, SCI_EN
),
53 static const struct reg_script pmc_write1_to_clear_script
[] = {
54 REG_PCI_OR32(GEN_PMCON_A
, 0),
55 REG_PCI_OR32(GEN_PMCON_B
, 0),
56 REG_PCI_OR32(GEN_PMCON_B
, 0),
57 REG_RES_OR32(PWRMBASE
, GBLRST_CAUSE0
, 0),
58 REG_RES_OR32(PWRMBASE
, GBLRST_CAUSE1
, 0),
62 static void pch_pmc_add_mmio_resources(device_t dev
)
66 /* Memory-mmapped I/O registers. */
67 res
= new_resource(dev
, PWRMBASE
);
68 res
->base
= PCH_PWRM_BASE_ADDRESS
;
69 res
->size
= PCH_PWRM_BASE_SIZE
;
70 res
->flags
= IORESOURCE_MEM
| IORESOURCE_ASSIGNED
|
71 IORESOURCE_FIXED
| IORESOURCE_RESERVE
;
74 static void pch_pmc_add_io_resource(device_t dev
, u16 base
, u16 size
, int index
)
77 res
= new_resource(dev
, index
);
80 res
->flags
= IORESOURCE_IO
| IORESOURCE_ASSIGNED
| IORESOURCE_FIXED
;
83 static void pch_pmc_add_io_resources(device_t dev
)
86 pch_pmc_add_io_resource(dev
, ACPI_BASE_ADDRESS
, ACPI_BASE_SIZE
, ABASE
);
89 static void pch_pmc_read_resources(device_t dev
)
91 /* Get the normal PCI resources of this device. */
92 pci_dev_read_resources(dev
);
94 /* Add non-standard MMIO resources. */
95 pch_pmc_add_mmio_resources(dev
);
97 /* Add IO resources. */
98 pch_pmc_add_io_resources(dev
);
101 static void pch_set_acpi_mode(void)
103 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER
) && acpi_slp_type
!= 3) {
104 printk(BIOS_DEBUG
, "Disabling ACPI via APMC:\n");
105 outb(APM_CNT_ACPI_DISABLE
, APM_CNT
);
106 printk(BIOS_DEBUG
, "done.\n");
110 #if IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS)
112 * Preserve Vboot NV data when clearing CMOS as it will
113 * have been re-initialized already by Vboot firmware init.
115 static void pch_cmos_init_preserve(int reset
)
117 uint8_t vbnv
[CONFIG_VBNV_SIZE
];
128 static void pch_rtc_init(void)
132 /*PMC Controller Device 0x1F, Func 02*/
133 device_t dev
= PCH_DEV_PMC
;
134 reg8
= pci_read_config8(dev
, GEN_PMCON_B
);
135 rtc_failed
= reg8
& RTC_BATTERY_DEAD
;
137 reg8
&= ~RTC_BATTERY_DEAD
;
138 pci_write_config8(dev
, GEN_PMCON_B
, reg8
);
139 printk(BIOS_DEBUG
, "rtc_failed = 0x%x\n", rtc_failed
);
142 #if IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS)
143 pch_cmos_init_preserve(rtc_failed
);
145 cmos_init(rtc_failed
);
149 static void pmc_gpe_init(config_t
*config
)
153 uint32_t gpio_cfg_reg
;
154 const uint32_t gpio_cfg_mask
=
155 (GPE0_DWX_MASK
<< GPE0_DW0_SHIFT
) |
156 (GPE0_DWX_MASK
<< GPE0_DW1_SHIFT
) |
157 (GPE0_DWX_MASK
<< GPE0_DW2_SHIFT
);
159 pmc_regs
= pmc_mmio_regs();
162 /* Route the GPIOs to the GPE0 block. Determine that all values
163 * are different, and if they aren't use the reset values. */
164 if (config
->gpe0_dw0
== config
->gpe0_dw1
||
165 config
->gpe0_dw1
== config
->gpe0_dw2
) {
166 printk(BIOS_INFO
, "PMC: Using default GPE route.\n");
167 gpio_cfg
= read32(pmc_regs
+ GPIO_CFG
);
169 gpio_cfg
|= (uint32_t)config
->gpe0_dw0
<< GPE0_DW0_SHIFT
;
170 gpio_cfg
|= (uint32_t)config
->gpe0_dw1
<< GPE0_DW1_SHIFT
;
171 gpio_cfg
|= (uint32_t)config
->gpe0_dw2
<< GPE0_DW2_SHIFT
;
173 gpio_cfg_reg
= read32(pmc_regs
+ GPIO_CFG
) & ~gpio_cfg_mask
;
174 gpio_cfg_reg
|= gpio_cfg
& gpio_cfg_mask
;
175 write32(pmc_regs
+ GPIO_CFG
, gpio_cfg_reg
);
177 /* Set the routes in the GPIO communities as well. */
178 gpio_route_gpe(gpio_cfg_reg
>> GPE0_DW0_SHIFT
);
180 /* Set GPE enables based on devictree. */
181 enable_all_gpe(config
->gpe0_en_1
, config
->gpe0_en_2
,
182 config
->gpe0_en_3
, config
->gpe0_en_4
);
185 static void pch_power_options(void)
189 /*PMC Controller Device 0x1F, Func 02*/
190 device_t dev
= PCH_DEV_PMC
;
191 /* Get the chip configuration */
192 config_t
*config
= dev
->chip_info
;
193 int pwr_on
= CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
;
196 * Which state do we want to goto after g3 (power restored)?
200 * If the option is not existent (Laptops), use Kconfig setting.
202 /*TODO: cmos_layout.bin need to verify; cause wrong CMOS setup*/
203 //get_option(&pwr_on, "power_on_after_fail");
204 pwr_on
= MAINBOARD_POWER_ON
;
205 reg16
= pci_read_config16(dev
, GEN_PMCON_B
);
208 case MAINBOARD_POWER_OFF
:
212 case MAINBOARD_POWER_ON
:
216 case MAINBOARD_POWER_KEEP
:
218 state
= "state keep";
223 pci_write_config16(dev
, GEN_PMCON_B
, reg16
);
224 printk(BIOS_INFO
, "Set power %s after power failure.\n", state
);
226 /* Set up GPE configuration. */
227 pmc_gpe_init(config
);
230 static void config_deep_sX(uint32_t offset
, uint32_t mask
, int sx
, int enable
)
233 uint8_t *pmcbase
= pmc_mmio_regs();
235 printk(BIOS_DEBUG
, "%sabling Deep S%c\n",
236 enable
? "En" : "Dis", sx
+ '0');
237 reg
= read32(pmcbase
+ offset
);
242 write32(pmcbase
+ offset
, reg
);
245 static void config_deep_s5(int on
)
247 /* Treat S4 the same as S5. */
248 config_deep_sX(S4_PWRGATE_POL
, S4DC_GATE_SUS
| S4AC_GATE_SUS
, 4, on
);
249 config_deep_sX(S5_PWRGATE_POL
, S5DC_GATE_SUS
| S5AC_GATE_SUS
, 5, on
);
252 static void config_deep_s3(int on
)
254 config_deep_sX(S3_PWRGATE_POL
, S3DC_GATE_SUS
| S3AC_GATE_SUS
, 3, on
);
257 static void config_deep_sx(uint32_t deepsx_config
)
260 uint8_t *pmcbase
= pmc_mmio_regs();
262 reg
= read32(pmcbase
+ DSX_CFG
);
263 reg
&= ~DSX_CFG_MASK
;
264 reg
|= deepsx_config
;
265 write32(pmcbase
+ DSX_CFG
, reg
);
268 static void pmc_init(struct device
*dev
)
270 config_t
*config
= dev
->chip_info
;
274 /* Initialize power management */
277 /* Note that certain bits may be cleared from running script as
278 * certain bit fields are write 1 to clear. */
279 reg_script_run_on_dev(dev
, pch_pmc_misc_init_script
);
282 config_deep_s3(config
->deep_s3_enable
);
283 config_deep_s5(config
->deep_s5_enable
);
284 config_deep_sx(config
->deep_sx_config
);
286 /* Clear registers that contain write-1-to-clear bits. */
287 reg_script_run_on_dev(dev
, pmc_write1_to_clear_script
);
290 static struct device_operations device_ops
= {
291 .read_resources
= &pch_pmc_read_resources
,
292 .set_resources
= &pci_dev_set_resources
,
293 .enable_resources
= &pci_dev_enable_resources
,
295 .scan_bus
= &scan_lpc_bus
,
296 .ops_pci
= &soc_pci_ops
,
299 static const unsigned short pci_device_ids
[] = {
304 static const struct pci_driver pch_lpc __pci_driver
= {
306 .vendor
= PCI_VENDOR_ID_INTEL
,
307 .devices
= pci_device_ids
,