Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017 Intel Corporation. * Copyright 2019 Google LLC * * Modified from coreboot pmclib.c, pmc.c and pmutil.c */ #define LOG_CATEGORY UCLASS_ACPI_PMC #include <dm.h> #include <dt-structs.h> #include <log.h> #include <spl.h> #include <acpi/acpi_s3.h> #include <asm/io.h> #include <asm/pci.h> #include <asm/arch/pmc.h> #include <linux/bitops.h> #include <power/acpi_pmc.h> #define GPIO_GPE_CFG 0x1050 /* Memory mapped IO registers behind PMC_BASE_ADDRESS */ #define PRSTS 0x1000 #define GEN_PMCON1 0x1020 #define COLD_BOOT_STS BIT(27) #define COLD_RESET_STS BIT(26) #define WARM_RESET_STS BIT(25) #define GLOBAL_RESET_STS BIT(24) #define SRS BIT(20) #define MS4V BIT(18) #define RPS BIT(2) #define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \ WARM_RESET_STS | GLOBAL_RESET_STS | \ SRS | MS4V) #define GEN_PMCON2 0x1024 #define GEN_PMCON3 0x1028 /* Offset of TCO registers from ACPI base I/O address */ #define TCO_REG_OFFSET 0x60 #define TCO1_STS 0x64 #define DMISCI_STS BIT(9) #define BOOT_STS BIT(18) #define TCO2_STS 0x66 #define TCO1_CNT 0x68 #define TCO_LOCK BIT(12) #define TCO2_CNT 0x6a enum { ETR = 0x1048, CF9_LOCK = 1UL << 31, CF9_GLB_RST = 1 << 20, }; static int apl_pmc_fill_power_state(struct udevice *dev) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); upriv->tco1_sts = inw(upriv->acpi_base + TCO1_STS); upriv->tco2_sts = inw(upriv->acpi_base + TCO2_STS); upriv->prsts = readl(upriv->pmc_bar0 + PRSTS); upriv->gen_pmcon1 = readl(upriv->pmc_bar0 + GEN_PMCON1); upriv->gen_pmcon2 = readl(upriv->pmc_bar0 + GEN_PMCON2); upriv->gen_pmcon3 = readl(upriv->pmc_bar0 + GEN_PMCON3); return 0; } static int apl_prev_sleep_state(struct udevice *dev, int prev_sleep_state) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); /* WAK_STS bit will not be set when waking from G3 state */ if (!(upriv->pm1_sts & WAK_STS) && (upriv->gen_pmcon1 & COLD_BOOT_STS)) prev_sleep_state = ACPI_S5; return prev_sleep_state; } static int apl_disable_tco(struct udevice *dev) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); pmc_disable_tco_base(upriv->acpi_base + TCO_REG_OFFSET); return 0; } static int apl_global_reset_set_enable(struct udevice *dev, bool enable) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); if (enable) setbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST); else clrbits_le32(upriv->pmc_bar0 + ETR, CF9_GLB_RST); return 0; } int apl_pmc_ofdata_to_uc_plat(struct udevice *dev) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); struct apl_pmc_plat *plat = dev_get_plat(dev); #if CONFIG_IS_ENABLED(OF_REAL) u32 base[6]; int size; int ret; ret = dev_read_u32_array(dev, "early-regs", base, ARRAY_SIZE(base)); if (ret) return log_msg_ret("Missing/short early-regs", ret); if (xpl_phase() == PHASE_TPL) { upriv->pmc_bar0 = (void *)base[0]; upriv->pmc_bar2 = (void *)base[2]; /* Since PCI is not enabled, we must get the BDF manually */ plat->bdf = pci_get_devfn(dev); if (plat->bdf < 0) return log_msg_ret("Cannot get PMC PCI address", plat->bdf); } upriv->acpi_base = base[4]; /* Get the dwX values for pmc gpe settings */ size = dev_read_size(dev, "gpe0-dw"); if (size < 0) return log_msg_ret("Cannot read gpe0-dm", size); upriv->gpe0_count = size / sizeof(u32); ret = dev_read_u32_array(dev, "gpe0-dw", upriv->gpe0_dw, upriv->gpe0_count); if (ret) return log_msg_ret("Bad gpe0-dw", ret); return pmc_ofdata_to_uc_plat(dev); #else struct dtd_intel_apl_pmc *dtplat = &plat->dtplat; plat->bdf = pci_ofplat_get_devfn(dtplat->reg[0]); upriv->pmc_bar0 = (void *)dtplat->early_regs[0]; upriv->pmc_bar2 = (void *)dtplat->early_regs[2]; upriv->acpi_base = dtplat->early_regs[4]; upriv->gpe0_dwx_mask = dtplat->gpe0_dwx_mask; upriv->gpe0_dwx_shift_base = dtplat->gpe0_dwx_shift_base; upriv->gpe0_sts_reg = dtplat->gpe0_sts; upriv->gpe0_sts_reg += upriv->acpi_base; upriv->gpe0_en_reg = dtplat->gpe0_en; upriv->gpe0_en_reg += upriv->acpi_base; upriv->gpe0_count = min((int)ARRAY_SIZE(dtplat->gpe0_dw), GPE0_REG_MAX); memcpy(upriv->gpe0_dw, dtplat->gpe0_dw, sizeof(dtplat->gpe0_dw)); #endif upriv->gpe_cfg = (u32 *)(upriv->pmc_bar0 + GPIO_GPE_CFG); return 0; } static int enable_pmcbar(struct udevice *dev) { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); struct apl_pmc_plat *priv = dev_get_plat(dev); pci_dev_t pmc = priv->bdf; /* * Set PMC base addresses and enable decoding. BARs 1 and 3 are 64-bit * BARs. */ pci_x86_write_config(pmc, PCI_BASE_ADDRESS_0, (ulong)upriv->pmc_bar0, PCI_SIZE_32); pci_x86_write_config(pmc, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); pci_x86_write_config(pmc, PCI_BASE_ADDRESS_2, (ulong)upriv->pmc_bar2, PCI_SIZE_32); pci_x86_write_config(pmc, PCI_BASE_ADDRESS_3, 0, PCI_SIZE_32); pci_x86_write_config(pmc, PCI_BASE_ADDRESS_4, upriv->acpi_base, PCI_SIZE_16); pci_x86_write_config(pmc, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCI_SIZE_16); return 0; } static int apl_pmc_probe(struct udevice *dev) { if (xpl_phase() == PHASE_TPL) { return enable_pmcbar(dev); } else { struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev); upriv->pmc_bar0 = (void *)dm_pci_read_bar32(dev, 0); upriv->pmc_bar2 = (void *)dm_pci_read_bar32(dev, 2); } return 0; } static const struct acpi_pmc_ops apl_pmc_ops = { .init = apl_pmc_fill_power_state, .prev_sleep_state = apl_prev_sleep_state, .disable_tco = apl_disable_tco, .global_reset_set_enable = apl_global_reset_set_enable, }; #if CONFIG_IS_ENABLED(OF_REAL) static const struct udevice_id apl_pmc_ids[] = { { .compatible = "intel,apl-pmc" }, { } }; #endif U_BOOT_DRIVER(intel_apl_pmc) = { .name = "intel_apl_pmc", .id = UCLASS_ACPI_PMC, .of_match = of_match_ptr(apl_pmc_ids), .of_to_plat = apl_pmc_ofdata_to_uc_plat, .probe = apl_pmc_probe, .ops = &apl_pmc_ops, .plat_auto = sizeof(struct apl_pmc_plat), }; |