coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fch.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /* TODO: Check if this is still correct */
4 
5 #include <amdblocks/acpi.h>
6 #include <amdblocks/acpimmio.h>
8 #include <amdblocks/gpio.h>
9 #include <amdblocks/smi.h>
10 #include <assert.h>
11 #include <bootstate.h>
12 #include <cpu/x86/smm.h>
13 #include <amdblocks/i2c.h>
14 #include <soc/amd_pci_int_defs.h>
15 #include <soc/iomap.h>
16 #include <soc/i2c.h>
17 #include <soc/smi.h>
18 #include <soc/southbridge.h>
19 #include "chip.h"
20 
21 /*
22  * Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
23  * provides a visible association with the index, therefore helping
24  * maintainability of table. If a new index/name is defined in
25  * amd_pci_int_defs.h, just add the pair at the end of this table.
26  * Order is not important.
27  */
28 const static struct irq_idx_name irq_association[] = {
29  { PIRQ_A, "INTA#" },
30  { PIRQ_B, "INTB#" },
31  { PIRQ_C, "INTC#" },
32  { PIRQ_D, "INTD#" },
33  { PIRQ_E, "INTE#" },
34  { PIRQ_F, "INTF#/GENINT2" },
35  { PIRQ_G, "INTG#" },
36  { PIRQ_H, "INTH#" },
37  { PIRQ_MISC, "Misc" },
38  { PIRQ_MISC0, "Misc0" },
39  { PIRQ_HPET_L, "HPET_L" },
40  { PIRQ_HPET_H, "HPET_H" },
41  { PIRQ_SIRQA, "Ser IRQ INTA" },
42  { PIRQ_SIRQB, "Ser IRQ INTB" },
43  { PIRQ_SIRQC, "Ser IRQ INTC" },
44  { PIRQ_SIRQD, "Ser IRQ INTD" },
45  { PIRQ_SCI, "SCI" },
46  { PIRQ_SMBUS, "SMBUS" },
47  { PIRQ_ASF, "ASF" },
48  { PIRQ_PMON, "PerMon" },
49  { PIRQ_SD, "SD" },
50  { PIRQ_SDIO, "SDIO" },
51  { PIRQ_CIR, "CIR" },
52  { PIRQ_GPIOA, "GPIOa" },
53  { PIRQ_GPIOB, "GPIOb" },
54  { PIRQ_GPIOC, "GPIOc" },
55  { PIRQ_EMMC, "eMMC" },
56  { PIRQ_GPP0, "GPP0" },
57  { PIRQ_GPP1, "GPP1" },
58  { PIRQ_GPP2, "GPP2" },
59  { PIRQ_GPP3, "GPP3" },
60  { PIRQ_GPIO, "GPIO" },
61  { PIRQ_I2C0, "I2C0" },
62  { PIRQ_I2C1, "I2C1" },
63  { PIRQ_I2C2, "I2C2" },
64  { PIRQ_I2C3, "I2C3" },
65  { PIRQ_UART0, "UART0" },
66  { PIRQ_UART1, "UART1" },
67  { PIRQ_I2C4, "I2C4" },
68  { PIRQ_UART4, "UART4" },
69  { PIRQ_UART2, "UART2" },
70  { PIRQ_UART3, "UART3" },
71 };
72 
73 const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
74 {
75  *size = ARRAY_SIZE(irq_association);
76  return irq_association;
77 }
78 
79 static void fch_clk_output_48Mhz(void)
80 {
82  /* Enable BP_X48M0 Clock Output */
83  ctrl |= BP_X48M0_OUTPUT_EN;
84  /* Disable clock output in S0i3 */
85  ctrl |= BP_X48M0_S0I3_DIS;
87 }
88 
89 static void fch_init_acpi_ports(void)
90 {
91  u32 reg;
92 
93  /* We use some of these ports in SMM regardless of whether or not
94  * ACPI tables are generated. Enable these ports indiscriminately.
95  */
96 
101 
102  if (CONFIG(HAVE_SMI_HANDLER)) {
103  /* APMC - SMI Command Port */
106 
107  /* SMI on SlpTyp requires sending SMI before completion
108  response of the I/O write. */
109  reg = pm_read32(PM_PCI_CTRL);
110  reg |= FORCE_SLPSTATE_RETRY;
111  pm_write32(PM_PCI_CTRL, reg);
112 
113  /* Disable SlpTyp feature */
114  reg = pm_read8(PM_RST_CTRL1);
115  reg &= ~SLPTYPE_CONTROL_EN;
116  pm_write8(PM_RST_CTRL1, reg);
117 
119  } else {
121  }
122 
123  /* Decode ACPI registers and enable standard features */
128 }
129 
130 /* configure the general purpose PCIe clock outputs according to the devicetree settings */
131 static void gpp_clk_setup(void)
132 {
133  const struct soc_amd_sabrina_config *cfg = config_of_soc();
134 
135  /* look-up table to be able to iterate over the PCIe clock output settings */
136  const uint8_t gpp_clk_shift_lut[GPP_CLK_OUTPUT_COUNT] = {
144  };
145 
146  uint32_t gpp_clk_ctl = misc_read32(GPP_CLK_CNTRL);
147 
148  for (int i = 0; i < GPP_CLK_OUTPUT_COUNT; i++) {
149  gpp_clk_ctl &= ~GPP_CLK_REQ_MASK(gpp_clk_shift_lut[i]);
150  /*
151  * The remapping of values is done so that the default of the enum used for the
152  * devicetree settings is the clock being enabled, so that a missing devicetree
153  * configuration for this will result in an always active clock and not an
154  * inactive PCIe clock output.
155  */
156  switch (cfg->gpp_clk_config[i]) {
157  case GPP_CLK_REQ:
158  gpp_clk_ctl |= GPP_CLK_REQ_EXT(gpp_clk_shift_lut[i]);
159  break;
160  case GPP_CLK_OFF:
161  gpp_clk_ctl |= GPP_CLK_REQ_OFF(gpp_clk_shift_lut[i]);
162  break;
163  case GPP_CLK_ON:
164  default:
165  gpp_clk_ctl |= GPP_CLK_REQ_ON(gpp_clk_shift_lut[i]);
166  }
167  }
168 
169  misc_write32(GPP_CLK_CNTRL, gpp_clk_ctl);
170 }
171 
172 static void cgpll_clock_gate_init(void)
173 {
174  uint32_t t;
175 
177  t |= ALINKCLK_GATEOFFEN;
178  t |= BLINKCLK_GATEOFFEN;
182 
188 
190  t |= ABCLKGATEEN;
192 }
193 
194 void fch_init(void *chip_info)
195 {
196  i2c_soc_init();
198 
200  gpio_add_events();
201 
202  gpp_clk_setup();
205 }
206 
207 void fch_final(void *chip_info)
208 {
209 }
210 
211 static void set_pci_irqs(void *unused)
212 {
213  /* Write PCI_INTR regs 0xC00/0xC01 */
215 
216  /* pirq_data is consumed by `write_pci_cfg_irqs` */
218 
219  /* Write IRQs for all devicetree enabled devices */
221 }
222 
223 /*
224  * Hook this function into the PCI state machine
225  * on entry into BS_DEV_ENABLE.
226  */
@ PIRQ_A
Definition: acpi_pirq_gen.h:22
@ PIRQ_C
Definition: acpi_pirq_gen.h:24
@ PIRQ_G
Definition: acpi_pirq_gen.h:28
@ PIRQ_H
Definition: acpi_pirq_gen.h:29
@ PIRQ_E
Definition: acpi_pirq_gen.h:26
@ PIRQ_D
Definition: acpi_pirq_gen.h:25
@ PIRQ_F
Definition: acpi_pirq_gen.h:27
@ PIRQ_B
Definition: acpi_pirq_gen.h:23
#define SLPTYPE_CONTROL_EN
Definition: acpimmio.h:32
static void pm_write32(uint8_t reg, uint32_t value)
Definition: acpimmio.h:191
static uint8_t pm_read8(uint8_t reg)
Definition: acpimmio.h:166
static void pm_write16(uint8_t reg, uint16_t value)
Definition: acpimmio.h:186
static uint32_t misc_read32(uint8_t reg)
Definition: acpimmio.h:266
static uint32_t pm_read32(uint8_t reg)
Definition: acpimmio.h:176
static void misc_write32(uint8_t reg, uint32_t value)
Definition: acpimmio.h:281
static void pm_write8(uint8_t reg, uint8_t value)
Definition: acpimmio.h:181
#define PM_RST_CTRL1
Definition: acpimmio.h:31
#define ACPI_PM1_CNT_BLK
Definition: iomap.h:43
#define ACPI_PM_TMR_BLK
Definition: iomap.h:44
#define ACPI_GPE0_BLK
Definition: iomap.h:46
#define ACPI_PM_EVT_BLK
Definition: iomap.h:40
@ BS_DEV_ENABLE
Definition: bootstate.h:82
@ BS_ON_ENTRY
Definition: bootstate.h:95
#define ARRAY_SIZE(a)
Definition: helpers.h:12
const struct irq_idx_name * sb_get_apic_reg_association(size_t *size)
Definition: fch.c:75
BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL)
void fch_init(void *chip_info)
Definition: fch.c:290
void fch_final(void *chip_info)
Definition: fch.c:304
#define GPP_CLK_REQ_MASK(clk_shift)
Definition: southbridge.h:98
#define USB_PHY_CMCLK_S3_DIS
Definition: southbridge.h:109
#define GPP_CLK_REQ_ON(clk_shift)
Definition: southbridge.h:99
#define GPP_CLK5_REQ_SHIFT
Definition: southbridge.h:95
#define GPP_CLK2_REQ_SHIFT
Definition: southbridge.h:93
#define XTAL_PAD_S5_TURNOFF_EN
Definition: southbridge.h:107
#define PM_TMR_BLK
Definition: southbridge.h:40
#define PM_ACPI_CONF
Definition: southbridge.h:43
#define GPP_CLK_CNTRL
Definition: southbridge.h:89
#define PM_ACPI_TIMER_EN_EN
Definition: southbridge.h:48
#define FORCE_SLPSTATE_RETRY
Definition: southbridge.h:12
#define PM_ACPI_GLOBAL_EN
Definition: southbridge.h:45
#define MISC_CGPLL_CONFIGURATION0
Definition: southbridge.h:108
#define GPP_CLK_OUTPUT_COUNT
Definition: southbridge.h:97
#define PM_ACPI_DECODE_STD
Definition: southbridge.h:44
#define GPP_CLK6_REQ_SHIFT
Definition: southbridge.h:96
#define BP_X48M0_OUTPUT_EN
Definition: southbridge.h:114
#define BLINKCLK_GATEOFFEN
Definition: southbridge.h:105
#define MISC_CLKGATEDCNTL
Definition: southbridge.h:103
#define GPP_CLK1_REQ_SHIFT
Definition: southbridge.h:91
#define USB_PHY_CMCLK_S0I3_DIS
Definition: southbridge.h:110
#define PM_ACPI_RTC_EN_EN
Definition: southbridge.h:46
#define MISC_CLK_CNTL0
Definition: southbridge.h:112
#define BP_X48M0_S0I3_DIS
Definition: southbridge.h:113
#define PM_EVT_BLK
Definition: southbridge.h:26
#define GPP_CLK4_REQ_SHIFT
Definition: southbridge.h:92
#define GPP_CLK0_REQ_SHIFT
Definition: southbridge.h:90
#define PM_GPE0_BLK
Definition: southbridge.h:41
#define XTAL_PAD_S3_TURNOFF_EN
Definition: southbridge.h:106
#define USB_PHY_CMCLK_S5_DIS
Definition: southbridge.h:111
#define PM_ACPI_SMI_CMD
Definition: southbridge.h:42
#define PM_ISACONTROL
Definition: southbridge.h:9
#define PM_PCI_CTRL
Definition: southbridge.h:11
#define GPP_CLK_REQ_EXT(clk_shift)
Definition: southbridge.h:100
#define ALINKCLK_GATEOFFEN
Definition: southbridge.h:104
#define GPP_CLK_REQ_OFF(clk_shift)
Definition: southbridge.h:101
#define PM1_CNT_BLK
Definition: southbridge.h:39
#define ABCLKGATEEN
Definition: southbridge.h:10
#define GPP_CLK3_REQ_SHIFT
Definition: southbridge.h:94
@ CONFIG
Definition: dsi_common.h:201
#define APM_CNT
Definition: smm.h:19
#define config_of_soc()
Definition: device.h:394
static void gpp_clk_setup(void)
Definition: fch.c:131
static void cgpll_clock_gate_init(void)
Definition: fch.c:172
static void fch_init_acpi_ports(void)
Definition: fch.c:89
static const struct irq_idx_name irq_association[]
Definition: fch.c:28
static void fch_clk_output_48Mhz(void)
Definition: fch.c:79
static void set_pci_irqs(void *unused)
Definition: fch.c:211
@ GPP_CLK_REQ
Definition: chip.h:17
@ GPP_CLK_ON
Definition: chip.h:16
@ GPP_CLK_OFF
Definition: chip.h:18
#define PIRQ_EMMC
#define PIRQ_GPIOB
#define PIRQ_SDIO
#define PIRQ_GPP2
#define PIRQ_GPP1
#define PIRQ_PMON
#define PIRQ_I2C0
#define PIRQ_SIRQA
#define PIRQ_SMBUS
#define PIRQ_HPET_L
#define PIRQ_MISC0
#define PIRQ_ASF
#define PIRQ_GPP0
#define PIRQ_CIR
#define PIRQ_SIRQC
#define PIRQ_SCI
#define PIRQ_GPIOA
#define PIRQ_SIRQD
#define PIRQ_MISC
#define PIRQ_SD
#define PIRQ_UART0
#define PIRQ_HPET_H
#define PIRQ_GPP3
#define PIRQ_I2C3
#define PIRQ_I2C4
#define PIRQ_I2C2
#define PIRQ_UART1
#define PIRQ_I2C1
#define PIRQ_GPIO
#define PIRQ_SIRQB
#define PIRQ_GPIOC
#define SMITYPE_SLP_TYP
Definition: smi.h:107
#define SMITYPE_SMI_CMD_PORT
Definition: smi.h:113
void acpi_pm_gpe_add_events_print_events(void)
Definition: acpi.c:77
void gpio_add_events(void)
Definition: gpio.c:382
void i2c_soc_init(void)
Definition: i2c.c:113
void write_pci_cfg_irqs(void)
Definition: amd_pci_util.c:84
void write_pci_int_table(void)
Definition: amd_pci_util.c:41
void populate_pirq_data(void)
void configure_smi(uint8_t smi_num, uint8_t mode)
Definition: smi_util.c:12
@ SMI_MODE_SMI
Definition: smi.h:10
#define PIRQ_UART3
#define PIRQ_UART2
#define PIRQ_UART4
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned char uint8_t
Definition: stdint.h:8
enum soc_amd_sabrina_config::@425 gpp_clk_config[GPP_CLK_OUTPUT_COUNT]