soc/apollolake: Add helper functions to access Power Management Registers
Change-Id: I928efea33030e03cbbaead6812c617d20446f7c9 Signed-off-by: Hannah Williams <hannah.williams@intel.com> Reviewed-on: https://review.coreboot.org/14289 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
This commit is contained in:
		
				
					committed by
					
						
						Martin Roth
					
				
			
			
				
	
			
			
			
						parent
						
							9c6c791351
						
					
				
				
					commit
					01bc897dfa
				
			@@ -26,8 +26,10 @@ romstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
 | 
				
			|||||||
romstage-y += memmap.c
 | 
					romstage-y += memmap.c
 | 
				
			||||||
romstage-y += mmap_boot.c
 | 
					romstage-y += mmap_boot.c
 | 
				
			||||||
romstage-y += tsc_freq.c
 | 
					romstage-y += tsc_freq.c
 | 
				
			||||||
 | 
					romstage-y += pmutil.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
smm-y += placeholders.c
 | 
					smm-y += placeholders.c
 | 
				
			||||||
 | 
					smm-y += pmutil.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
 | 
					ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
 | 
				
			||||||
ramstage-y += cpu.c
 | 
					ramstage-y += cpu.c
 | 
				
			||||||
@@ -42,6 +44,7 @@ ramstage-y += uart.c
 | 
				
			|||||||
ramstage-y += northbridge.c
 | 
					ramstage-y += northbridge.c
 | 
				
			||||||
ramstage-y += spi.c
 | 
					ramstage-y += spi.c
 | 
				
			||||||
ramstage-y += tsc_freq.c
 | 
					ramstage-y += tsc_freq.c
 | 
				
			||||||
 | 
					ramstage-y += pmutil.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
postcar-y += exit_car.S
 | 
					postcar-y += exit_car.S
 | 
				
			||||||
postcar-y += memmap.c
 | 
					postcar-y += memmap.c
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the coreboot project.
 | 
					 * This file is part of the coreboot project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2016 Intel Corp.
 | 
					 * Copyright (C) 2015-2016 Intel Corp.
 | 
				
			||||||
 * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
 | 
					 * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
@@ -18,19 +18,130 @@
 | 
				
			|||||||
#ifndef _SOC_APOLLOLAKE_PM_H_
 | 
					#ifndef _SOC_APOLLOLAKE_PM_H_
 | 
				
			||||||
#define _SOC_APOLLOLAKE_PM_H_
 | 
					#define _SOC_APOLLOLAKE_PM_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ACPI_BASE_ADDRESS / PMBASE */
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ACPI_BASE_ADDRESS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PM1_STS			0x00
 | 
					#define PM1_STS			0x00
 | 
				
			||||||
 | 
					#define   WAK_STS		(1 << 15)
 | 
				
			||||||
 | 
					#define   PWRBTN_STS		(1 << 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PM1_EN			0x02
 | 
					#define PM1_EN			0x02
 | 
				
			||||||
 | 
					#define   PCIEXPWAK_DIS		(1 << 14)
 | 
				
			||||||
 | 
					#define   USB_WAKE_EN		(1 << 13)
 | 
				
			||||||
 | 
					#define   RTC_EN		(1 << 10)
 | 
				
			||||||
 | 
					#define   PWRBTN_EN     	(1 << 8)
 | 
				
			||||||
 | 
					#define   GBL_EN        	(1 << 5)
 | 
				
			||||||
 | 
					#define   TMROF_EN      	(1 << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PM1_CNT			0x04
 | 
					#define PM1_CNT			0x04
 | 
				
			||||||
 | 
					#define   SLP_EN		(1 << 13)
 | 
				
			||||||
 | 
					#define   SLP_TYP_SHIFT		10
 | 
				
			||||||
 | 
					#define   SLP_TYP		(7 << SLP_TYP_SHIFT)
 | 
				
			||||||
 | 
					#define    SLP_TYP_S0		0
 | 
				
			||||||
 | 
					#define    SLP_TYP_S3		5
 | 
				
			||||||
 | 
					#define    SLP_TYP_S4		6
 | 
				
			||||||
 | 
					#define    SLP_TYP_S5		7
 | 
				
			||||||
 | 
					#define   SCI_EN		(1 << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PM1_TMR			0x08
 | 
					#define PM1_TMR			0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMI_EN			0x40
 | 
					#define SMI_EN			0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMI_OCP_CSE		27
 | 
				
			||||||
 | 
					#define SMI_SPI			26
 | 
				
			||||||
 | 
					#define SMI_SPI_SSMI		25
 | 
				
			||||||
 | 
					#define SMI_SCC2		21
 | 
				
			||||||
 | 
					#define SMI_PCIE		20
 | 
				
			||||||
 | 
					#define SMI_SCS			19
 | 
				
			||||||
 | 
					#define SMI_HOST_SMBUS		18
 | 
				
			||||||
 | 
					#define SMI_XHCI		17
 | 
				
			||||||
 | 
					#define SMI_SMBUS		16
 | 
				
			||||||
 | 
					#define SMI_SERIRQ		15
 | 
				
			||||||
 | 
					#define SMI_PERIODIC		14
 | 
				
			||||||
 | 
					#define SMI_TCO			13
 | 
				
			||||||
 | 
					#define SMI_MCSMI		12
 | 
				
			||||||
 | 
					#define SMI_GPIO_UNLOCK_SSMI	11
 | 
				
			||||||
 | 
					#define SMI_GPIO		10
 | 
				
			||||||
 | 
					#define SMI_BIOS_RLS		7
 | 
				
			||||||
 | 
					#define SMI_SWSMI_TMR		6
 | 
				
			||||||
 | 
					#define SMI_APMC		5
 | 
				
			||||||
 | 
					#define SMI_SLP			4
 | 
				
			||||||
 | 
					#define SMI_LEGACY_USB		3
 | 
				
			||||||
 | 
					#define SMI_BIOS		2
 | 
				
			||||||
 | 
					#define SMI_EOS			1
 | 
				
			||||||
 | 
					#define SMI_GBL			0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define   USB_EN		(1 << SMI_XHCI) /* Legacy USB2 SMI logic */
 | 
				
			||||||
 | 
					#define   PERIODIC_EN		(1 << SMI_PERIODIC) /* SMI on PERIODIC_STS in SMI_STS */
 | 
				
			||||||
 | 
					#define   TCO_EN		(1 << SMI_TCO) /* Enable TCO Logic (BIOSWE et al) */
 | 
				
			||||||
 | 
					#define   BIOS_RLS		(1 << SMI_BIOS_RLS) /* asserts SCI on bit set */
 | 
				
			||||||
 | 
					#define   SWSMI_TMR_EN		(1 << SMI_SWSMI_TMR) /* start software smi timer on bit set */
 | 
				
			||||||
 | 
					#define   APMC_EN		(1 << SMI_APMC) /* Writes to APM_CNT cause SMI# */
 | 
				
			||||||
 | 
					#define   SLP_SMI_EN		(1 << SMI_SLP) /* Write to SLP_EN in PM1_CNT asserts SMI# */
 | 
				
			||||||
 | 
					#define   BIOS_EN		(1 << SMI_BIOS) /* Assert SMI# on GBL_RLS bit */
 | 
				
			||||||
 | 
					#define   EOS			(1 << SMI_EOS) /* End of SMI (deassert SMI#) */
 | 
				
			||||||
 | 
					#define   GBL_SMI_EN		(1 << SMI_GBL) /* Global SMI Enable */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMI_STS			0x44
 | 
					#define SMI_STS			0x44
 | 
				
			||||||
#define GPE_CNTL		0x50
 | 
					#define GPE_CNTL		0x50
 | 
				
			||||||
#define DEVACT_STS		0x4c
 | 
					#define DEVACT_STS		0x4c
 | 
				
			||||||
 | 
					#define TCO_STS			0x64
 | 
				
			||||||
 | 
					#define   TCO_TIMEOUT		(1 << 3)
 | 
				
			||||||
 | 
					#define TCO1_CNT		0x68
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GPE0_REG_MAX		4
 | 
					#define GPE0_REG_MAX		4
 | 
				
			||||||
 | 
					#define GPE0_REG_SIZE		32
 | 
				
			||||||
#define GPE0_STS(x)		(0x20 + (x * 4))
 | 
					#define GPE0_STS(x)		(0x20 + (x * 4))
 | 
				
			||||||
#define GPE0_EN(x)		(0x30 + (x * 4))
 | 
					#define GPE0_EN(x)		(0x30 + (x * 4))
 | 
				
			||||||
 | 
					#define   PME_B0_EN		(1 << 13)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif	/* _SOC_APOLLOLAKE_PM_H_ */
 | 
					/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
 | 
				
			||||||
 | 
					#define PRSTS			0x1000
 | 
				
			||||||
 | 
					#define GEN_PMCON1		0x1020
 | 
				
			||||||
 | 
					#       define PWR_FLR		(1 << 16)
 | 
				
			||||||
 | 
					#       define SUS_PWR_FLR	(1 << 14)
 | 
				
			||||||
 | 
					#define GEN_PMCON2		0x1024
 | 
				
			||||||
 | 
					#       define RPS		(1 <<  2)
 | 
				
			||||||
 | 
					#define GEN_PMCON3		0x1028
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generic sleep state types */
 | 
				
			||||||
 | 
					#define SLEEP_STATE_S0		0
 | 
				
			||||||
 | 
					#define SLEEP_STATE_S3		3
 | 
				
			||||||
 | 
					#define SLEEP_STATE_S5		5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Track power state from reset to log events. */
 | 
				
			||||||
 | 
					struct chipset_power_state {
 | 
				
			||||||
 | 
					        uint16_t pm1_sts;
 | 
				
			||||||
 | 
					        uint16_t pm1_en;
 | 
				
			||||||
 | 
					        uint32_t pm1_cnt;
 | 
				
			||||||
 | 
					        uint32_t gpe0_sts[GPE0_REG_MAX];
 | 
				
			||||||
 | 
					        uint32_t gpe0_en[GPE0_REG_MAX];
 | 
				
			||||||
 | 
					        uint32_t tco_sts;
 | 
				
			||||||
 | 
					        uint32_t prsts;
 | 
				
			||||||
 | 
					        uint32_t gen_pmcon1;
 | 
				
			||||||
 | 
					        uint32_t gen_pmcon2;
 | 
				
			||||||
 | 
					        uint32_t gen_pmcon3;
 | 
				
			||||||
 | 
					        uint32_t prev_sleep_state;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fill_power_state(struct chipset_power_state *ps);
 | 
				
			||||||
 | 
					int chipset_prev_sleep_state(struct chipset_power_state *ps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Power Management Utility Functions. */
 | 
				
			||||||
 | 
					uint32_t clear_smi_status(void);
 | 
				
			||||||
 | 
					uint16_t clear_pm1_status(void);
 | 
				
			||||||
 | 
					uint32_t clear_tco_status(void);
 | 
				
			||||||
 | 
					uint32_t clear_gpe_status(void);
 | 
				
			||||||
 | 
					void clear_pmc_status(void);
 | 
				
			||||||
 | 
					uint32_t get_smi_en(void);
 | 
				
			||||||
 | 
					void enable_smi(uint32_t mask);
 | 
				
			||||||
 | 
					void disable_smi(uint32_t mask);
 | 
				
			||||||
 | 
					void enable_pm1(uint16_t events);
 | 
				
			||||||
 | 
					void enable_pm1_control(uint32_t mask);
 | 
				
			||||||
 | 
					void disable_pm1_control(uint32_t mask);
 | 
				
			||||||
 | 
					void enable_gpe(uint32_t mask);
 | 
				
			||||||
 | 
					void disable_gpe(uint32_t mask);
 | 
				
			||||||
 | 
					void disable_all_gpe(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										327
									
								
								src/soc/intel/apollolake/pmutil.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								src/soc/intel/apollolake/pmutil.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,327 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the coreboot project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 Google Inc.
 | 
				
			||||||
 | 
					 * Copyright (C) 2015-2016 Intel Corp.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; version 2 of the License, or (at your option)
 | 
				
			||||||
 | 
					 * any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <arch/io.h>
 | 
				
			||||||
 | 
					#include <console/console.h>
 | 
				
			||||||
 | 
					#include <rules.h>
 | 
				
			||||||
 | 
					#include <device/pci_def.h>
 | 
				
			||||||
 | 
					#include <soc/iomap.h>
 | 
				
			||||||
 | 
					#include <soc/pm.h>
 | 
				
			||||||
 | 
					#include <device/device.h>
 | 
				
			||||||
 | 
					#include <device/pci.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void print_num_status_bits(int num_bits, uint32_t status,
 | 
				
			||||||
 | 
									  const char * const bit_names[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!status)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = num_bits - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
							if (status & (1 << i)) {
 | 
				
			||||||
 | 
								if (bit_names[i])
 | 
				
			||||||
 | 
									printk(BIOS_DEBUG, "%s ", bit_names[i]);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									printk(BIOS_DEBUG, "BIT%d ", i);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t print_smi_status(uint32_t smi_sts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * const smi_sts_bits[] = {
 | 
				
			||||||
 | 
							[2] = "BIOS",
 | 
				
			||||||
 | 
							[3] = "LEGACY USB",
 | 
				
			||||||
 | 
							[4] = "SLP_SMI",
 | 
				
			||||||
 | 
							[5] = "APM",
 | 
				
			||||||
 | 
							[6] = "SWSMI_TMR",
 | 
				
			||||||
 | 
							[10]= "GPIO_SMI",
 | 
				
			||||||
 | 
							[11]= "GPIO_UNLOCK_SSMI",
 | 
				
			||||||
 | 
							[12] = "MCSMI",
 | 
				
			||||||
 | 
							[13] = "TCO",
 | 
				
			||||||
 | 
							[14] = "PERIODIC",
 | 
				
			||||||
 | 
							[15] = "SERIRQ",
 | 
				
			||||||
 | 
							[16] = "SMBUS_SMI",
 | 
				
			||||||
 | 
							[17] = "XHCI",
 | 
				
			||||||
 | 
							[18] = "HOST_SMBUS",
 | 
				
			||||||
 | 
							[19] = "SCS",
 | 
				
			||||||
 | 
							[20] = "PCI_EXP_SMI",
 | 
				
			||||||
 | 
							[21] = "SCC2",
 | 
				
			||||||
 | 
							[25] = "SPI_SSMI",
 | 
				
			||||||
 | 
							[26] = "SPI",
 | 
				
			||||||
 | 
							[27] = "OCP_CSE",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!smi_sts)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "SMI_STS: ");
 | 
				
			||||||
 | 
						print_num_status_bits(ARRAY_SIZE(smi_sts_bits), smi_sts, smi_sts_bits);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return smi_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t reset_smi_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t smi_sts = inl(ACPI_PMIO_BASE + SMI_STS);
 | 
				
			||||||
 | 
						outl(smi_sts, ACPI_PMIO_BASE + SMI_STS);
 | 
				
			||||||
 | 
						return smi_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t clear_smi_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return print_smi_status(reset_smi_status());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t get_smi_en(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return inl(ACPI_PMIO_BASE + SMI_EN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void enable_smi(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t smi_en = inl(ACPI_PMIO_BASE + SMI_EN);
 | 
				
			||||||
 | 
						smi_en |= mask;
 | 
				
			||||||
 | 
						outl(smi_en, ACPI_PMIO_BASE + SMI_EN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void disable_smi(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t smi_en = inl(ACPI_PMIO_BASE + SMI_EN);
 | 
				
			||||||
 | 
						smi_en &= ~mask;
 | 
				
			||||||
 | 
						outl(smi_en, ACPI_PMIO_BASE + SMI_EN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void enable_pm1_control(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
 | 
				
			||||||
 | 
						pm1_cnt |= mask;
 | 
				
			||||||
 | 
						outl(pm1_cnt, ACPI_PMIO_BASE + PM1_CNT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void disable_pm1_control(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
 | 
				
			||||||
 | 
						pm1_cnt &= ~mask;
 | 
				
			||||||
 | 
						outl(pm1_cnt, ACPI_PMIO_BASE + PM1_CNT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint16_t reset_pm1_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint16_t pm1_sts = inw(ACPI_PMIO_BASE + PM1_STS);
 | 
				
			||||||
 | 
						outw(pm1_sts, ACPI_PMIO_BASE + PM1_STS);
 | 
				
			||||||
 | 
						return pm1_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint16_t print_pm1_status(uint16_t pm1_sts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * const pm1_sts_bits[] = {
 | 
				
			||||||
 | 
							[0] = "TMROF",
 | 
				
			||||||
 | 
							[5] = "GBL",
 | 
				
			||||||
 | 
							[8] = "PWRBTN",
 | 
				
			||||||
 | 
							[10] = "RTC",
 | 
				
			||||||
 | 
							[11] = "PRBTNOR",
 | 
				
			||||||
 | 
							[13] = "USB",
 | 
				
			||||||
 | 
							[14] = "PCIEXPWAK",
 | 
				
			||||||
 | 
							[15] = "WAK",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pm1_sts)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_SPEW, "PM1_STS: ");
 | 
				
			||||||
 | 
						print_num_status_bits(ARRAY_SIZE(pm1_sts_bits), pm1_sts, pm1_sts_bits);
 | 
				
			||||||
 | 
						printk(BIOS_SPEW, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pm1_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t clear_pm1_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return print_pm1_status(reset_pm1_status());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void enable_pm1(uint16_t events)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						outw(events, ACPI_PMIO_BASE + PM1_EN);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t print_tco_status(uint32_t tco_sts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * const tco_sts_bits[] = {
 | 
				
			||||||
 | 
							[3] = "TIMEOUT",
 | 
				
			||||||
 | 
							[17] = "SECOND_TO",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!tco_sts)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "TCO_STS: ");
 | 
				
			||||||
 | 
						print_num_status_bits(ARRAY_SIZE(tco_sts_bits), tco_sts, tco_sts_bits);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tco_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t reset_tco_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t tco_sts = inl(ACPI_PMIO_BASE + TCO_STS);
 | 
				
			||||||
 | 
						uint32_t tco_en = inl(ACPI_PMIO_BASE + TCO1_CNT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outl(tco_sts, ACPI_PMIO_BASE + TCO_STS);
 | 
				
			||||||
 | 
						return tco_sts & tco_en;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t clear_tco_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return print_tco_status(reset_tco_status());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void enable_gpe(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t gpe0a_en = inl(ACPI_PMIO_BASE + GPE0_EN(0));
 | 
				
			||||||
 | 
						gpe0a_en |= mask;
 | 
				
			||||||
 | 
						outl(gpe0a_en, ACPI_PMIO_BASE + GPE0_EN(0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void disable_gpe(uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t gpe0a_en = inl(ACPI_PMIO_BASE + GPE0_EN(0));
 | 
				
			||||||
 | 
						gpe0a_en &= ~mask;
 | 
				
			||||||
 | 
						outl(gpe0a_en, ACPI_PMIO_BASE + GPE0_EN(0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void disable_all_gpe(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						disable_gpe(~0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t reset_gpe_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t gpe_sts = inl(ACPI_PMIO_BASE + GPE0_STS(0));
 | 
				
			||||||
 | 
						outl(gpe_sts, ACPI_PMIO_BASE + GPE0_STS(0));
 | 
				
			||||||
 | 
						return gpe_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t print_gpe_sts(uint32_t gpe_sts)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * const gpe_sts_bits[] = {
 | 
				
			||||||
 | 
							[0] = "PCIE_SCI",
 | 
				
			||||||
 | 
							[2] = "SWGPE",
 | 
				
			||||||
 | 
							[3] = "PCIE_WAKE0",
 | 
				
			||||||
 | 
							[4] = "PUNIT",
 | 
				
			||||||
 | 
							[6] = "PCIE_WAKE1",
 | 
				
			||||||
 | 
							[7] = "PCIE_WAKE2",
 | 
				
			||||||
 | 
							[8] = "PCIE_WAKE3",
 | 
				
			||||||
 | 
							[9] = "PCI_EXP",
 | 
				
			||||||
 | 
							[10] = "BATLOW",
 | 
				
			||||||
 | 
							[11] = "CSE_PME",
 | 
				
			||||||
 | 
							[12] = "XDCI_PME",
 | 
				
			||||||
 | 
							[13] = "XHCI_PME",
 | 
				
			||||||
 | 
							[14] = "AVS_PME",
 | 
				
			||||||
 | 
							[15] = "GPIO_TIER1_SCI",
 | 
				
			||||||
 | 
							[16] = "SMB_WAK",
 | 
				
			||||||
 | 
							[17] = "SATA_PME",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!gpe_sts)
 | 
				
			||||||
 | 
							return gpe_sts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "GPE0a_STS: ");
 | 
				
			||||||
 | 
						print_num_status_bits(ARRAY_SIZE(gpe_sts_bits), gpe_sts, gpe_sts_bits);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return gpe_sts;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t clear_gpe_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return print_gpe_sts(reset_gpe_status());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void clear_pmc_status(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t prsts;
 | 
				
			||||||
 | 
						uint32_t gen_pmcon1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prsts = read32((void *)(PMC_BAR0 + PRSTS));
 | 
				
			||||||
 | 
						gen_pmcon1 = read32((void *)(PMC_BAR0 + GEN_PMCON1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Clear the status bits. The RPS field is cleared on a 0 write. */
 | 
				
			||||||
 | 
						write32((void *)(PMC_BAR0 + GEN_PMCON1), gen_pmcon1 & ~RPS);
 | 
				
			||||||
 | 
						write32((void *)(PMC_BAR0 + PRSTS), prsts);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return 0, 3, or 5 to indicate the previous sleep state. */
 | 
				
			||||||
 | 
					int chipset_prev_sleep_state(struct chipset_power_state *ps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Default to S0. */
 | 
				
			||||||
 | 
						int prev_sleep_state = SLEEP_STATE_S0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ps->pm1_sts & WAK_STS) {
 | 
				
			||||||
 | 
							switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
 | 
				
			||||||
 | 
							case SLP_TYP_S3:
 | 
				
			||||||
 | 
								prev_sleep_state = SLEEP_STATE_S3;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							case SLP_TYP_S5:
 | 
				
			||||||
 | 
								prev_sleep_state = SLEEP_STATE_S5;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return prev_sleep_state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* returns prev_sleep_state */
 | 
				
			||||||
 | 
					int fill_power_state(struct chipset_power_state *ps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						ps->pm1_sts = inw(ACPI_PMIO_BASE + PM1_STS);
 | 
				
			||||||
 | 
						ps->pm1_en = inw(ACPI_PMIO_BASE + PM1_EN);
 | 
				
			||||||
 | 
						ps->pm1_cnt = inl(ACPI_PMIO_BASE + PM1_CNT);
 | 
				
			||||||
 | 
						ps->tco_sts = inl(ACPI_PMIO_BASE + TCO_STS);
 | 
				
			||||||
 | 
						ps->prsts = read32((void *)(PMC_BAR0 + PRSTS));
 | 
				
			||||||
 | 
						ps->gen_pmcon1 =read32((void *)(PMC_BAR0 + GEN_PMCON1));
 | 
				
			||||||
 | 
						ps->gen_pmcon2 = read32((void *)(PMC_BAR0 + GEN_PMCON2));
 | 
				
			||||||
 | 
						ps->gen_pmcon3 = read32((void *)(PMC_BAR0 + GEN_PMCON3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ps->prev_sleep_state = chipset_prev_sleep_state(ps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
 | 
				
			||||||
 | 
							ps->pm1_sts, ps->pm1_en, ps->pm1_cnt);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "prsts: %08x tco_sts: %08x\n",
 | 
				
			||||||
 | 
							ps->prsts, ps->tco_sts);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG,
 | 
				
			||||||
 | 
							 "gen_pmcon1: %08x gen_pmcon2: %08x gen_pmcon3: %08x\n",
 | 
				
			||||||
 | 
							ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3);
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "smi_en: %08x smi_sts: %08x\n",
 | 
				
			||||||
 | 
							inl(ACPI_PMIO_BASE + SMI_EN), inl(ACPI_PMIO_BASE + SMI_STS));
 | 
				
			||||||
 | 
						for (i=0; i < GPE0_REG_MAX; i++) {
 | 
				
			||||||
 | 
							ps->gpe0_sts[i] = inl(ACPI_PMIO_BASE + GPE0_STS(i));
 | 
				
			||||||
 | 
							ps->gpe0_en[i] = inl(ACPI_PMIO_BASE + GPE0_EN(i));
 | 
				
			||||||
 | 
							printk(BIOS_DEBUG, "gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n",
 | 
				
			||||||
 | 
								i, ps->gpe0_sts[i], i, ps->gpe0_en[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						printk(BIOS_DEBUG, "prev_sleep_state %d\n", ps->prev_sleep_state);
 | 
				
			||||||
 | 
						return ps->prev_sleep_state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user