• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <amdblocks/acpi.h>
4 #include <amdblocks/acpimmio.h>
5 #include <amdblocks/amd_pci_util.h>
6 #include <amdblocks/pci_clk_req.h>
7 #include <amdblocks/reset.h>
8 #include <amdblocks/gpio.h>
9 #include <amdblocks/i2c.h>
10 #include <amdblocks/smi.h>
11 #include <assert.h>
12 #include <bootstate.h>
13 #include <cpu/x86/smm.h>
14 #include <device/device.h>
15 #include <device/pci.h>
16 #include <device/pci_ids.h>
17 #include <fw_config.h>
18 #include <soc/amd_pci_int_defs.h>
19 #include <soc/iomap.h>
20 #include <soc/i2c.h>
21 #include <soc/platform_descriptors.h>
22 #include <soc/smi.h>
23 #include <soc/southbridge.h>
24 #include "chip.h"
25 
26 /*
27  * Table of APIC register index and associated IRQ name. Using IDX_XXX_NAME
28  * provides a visible association with the index, therefore helping
29  * maintainability of table. If a new index/name is defined in
30  * amd_pci_int_defs.h, just add the pair at the end of this table.
31  * Order is not important.
32  */
33 static const struct irq_idx_name irq_association[] = {
34 	{ PIRQ_A,	"INTA#" },
35 	{ PIRQ_B,	"INTB#" },
36 	{ PIRQ_C,	"INTC#" },
37 	{ PIRQ_D,	"INTD#" },
38 	{ PIRQ_E,	"INTE#" },
39 	{ PIRQ_F,	"INTF#/GENINT2" },
40 	{ PIRQ_G,	"INTG#" },
41 	{ PIRQ_H,	"INTH#" },
42 	{ PIRQ_MISC,	"Misc" },
43 	{ PIRQ_MISC0,	"Misc0" },
44 	{ PIRQ_HPET_L,	"HPET_L" },
45 	{ PIRQ_HPET_H,	"HPET_H" },
46 	{ PIRQ_SIRQA,	"Ser IRQ INTA" },
47 	{ PIRQ_SIRQB,	"Ser IRQ INTB" },
48 	{ PIRQ_SIRQC,	"Ser IRQ INTC" },
49 	{ PIRQ_SIRQD,	"Ser IRQ INTD" },
50 	{ PIRQ_SCI,	"SCI" },
51 	{ PIRQ_SMBUS,	"SMBUS" },
52 	{ PIRQ_ASF,	"ASF" },
53 	{ PIRQ_PMON,	"PerMon" },
54 	{ PIRQ_SD,	"SD" },
55 	{ PIRQ_SDIO,	"SDIO" },
56 	{ PIRQ_CIR,	"CIR" },
57 	{ PIRQ_GPIOA,	"GPIOa" },
58 	{ PIRQ_GPIOB,	"GPIOb" },
59 	{ PIRQ_GPIOC,	"GPIOc" },
60 	{ PIRQ_SATA,	"SATA" },
61 	{ PIRQ_EMMC,	"eMMC" },
62 	{ PIRQ_GPP0,	"GPP0" },
63 	{ PIRQ_GPP1,	"GPP1" },
64 	{ PIRQ_GPP2,	"GPP2" },
65 	{ PIRQ_GPP3,	"GPP3" },
66 	{ PIRQ_GPIO,	"GPIO" },
67 	{ PIRQ_I2C0,	"I2C0" },
68 	{ PIRQ_I2C1,	"I2C1" },
69 	{ PIRQ_I2C2,	"I2C2" },
70 	{ PIRQ_I2C3,	"I2C3" },
71 	{ PIRQ_UART0,	"UART0" },
72 	{ PIRQ_UART1,	"UART1" },
73 	{ PIRQ_I2C4,	"I2C4" },
74 	{ PIRQ_I2C5,	"I2C5" },
75 };
76 
sb_get_apic_reg_association(size_t * size)77 const struct irq_idx_name *sb_get_apic_reg_association(size_t *size)
78 {
79 	*size = ARRAY_SIZE(irq_association);
80 	return irq_association;
81 }
82 
fch_clk_output_48Mhz(void)83 static void fch_clk_output_48Mhz(void)
84 {
85 	uint32_t ctrl = misc_read32(MISC_CLK_CNTL0);
86 	/* Enable BP_X48M0 Clock Output */
87 	ctrl |= BP_X48M0_OUTPUT_EN;
88 	/* Disable clock output in S0i3 */
89 	ctrl |= BP_X48M0_S0I3_DIS;
90 	misc_write32(MISC_CLK_CNTL0, ctrl);
91 }
92 
fch_init_acpi_ports(void)93 static void fch_init_acpi_ports(void)
94 {
95 	u32 reg;
96 
97 	/* We use some of these ports in SMM regardless of whether or not
98 	 * ACPI tables are generated. Enable these ports indiscriminately.
99 	 */
100 
101 	pm_write16(PM_EVT_BLK, ACPI_PM_EVT_BLK);
102 	pm_write16(PM1_CNT_BLK, ACPI_PM1_CNT_BLK);
103 	pm_write16(PM_TMR_BLK, ACPI_PM_TMR_BLK);
104 	pm_write16(PM_GPE0_BLK, ACPI_GPE0_BLK);
105 
106 	if (CONFIG(HAVE_SMI_HANDLER)) {
107 		/* APMC - SMI Command Port */
108 		pm_write16(PM_ACPI_SMI_CMD, APM_CNT);
109 		configure_smi(SMITYPE_SMI_CMD_PORT, SMI_MODE_SMI);
110 
111 		/* SMI on SlpTyp requires sending SMI before completion
112 		   response of the I/O write. */
113 		reg = pm_read32(PM_PCI_CTRL);
114 		reg |= FORCE_SLPSTATE_RETRY;
115 		pm_write32(PM_PCI_CTRL, reg);
116 
117 		/* Disable SlpTyp feature */
118 		reg = pm_read8(PM_RST_CTRL1);
119 		reg &= ~SLPTYPE_CONTROL_EN;
120 		pm_write8(PM_RST_CTRL1, reg);
121 
122 		configure_smi(SMITYPE_SLP_TYP, SMI_MODE_SMI);
123 	} else {
124 		pm_write16(PM_ACPI_SMI_CMD, 0);
125 	}
126 
127 	/* Decode ACPI registers and enable standard features */
128 	pm_write8(PM_ACPI_CONF, PM_ACPI_DECODE_STD |
129 				PM_ACPI_GLOBAL_EN |
130 				PM_ACPI_RTC_EN_EN |
131 				PM_ACPI_TIMER_EN_EN);
132 }
133 
134 /* Configure the general purpose PCIe clock outputs according to the devicetree settings */
gpp_clk_setup(void)135 static void gpp_clk_setup(void)
136 {
137 	struct soc_amd_cezanne_config *cfg = config_of_soc();
138 	gpp_clk_setup_common(&cfg->gpp_clk_config[0], ARRAY_SIZE(cfg->gpp_clk_config));
139 }
140 
cgpll_clock_gate_init(void)141 static void cgpll_clock_gate_init(void)
142 {
143 	uint32_t t;
144 
145 	t = misc_read32(MISC_CLKGATEDCNTL);
146 	t |= ALINKCLK_GATEOFFEN;
147 	t |= BLINKCLK_GATEOFFEN;
148 	t |= XTAL_PAD_S3_TURNOFF_EN;
149 	t |= XTAL_PAD_S5_TURNOFF_EN;
150 	misc_write32(MISC_CLKGATEDCNTL, t);
151 
152 	t = misc_read32(MISC_CGPLL_CONFIGURATION0);
153 	t |= USB_PHY_CMCLK_S3_DIS;
154 	t |= USB_PHY_CMCLK_S0I3_DIS;
155 	t |= USB_PHY_CMCLK_S5_DIS;
156 	misc_write32(MISC_CGPLL_CONFIGURATION0, t);
157 
158 	t = pm_read32(PM_ISACONTROL);
159 	t |= ABCLKGATEEN;
160 	pm_write32(PM_ISACONTROL, t);
161 }
162 
fch_init(void * chip_info)163 void fch_init(void *chip_info)
164 {
165 	set_resets_to_cold();
166 	i2c_soc_init();
167 	fch_init_acpi_ports();
168 
169 	acpi_pm_gpe_add_events_print_events();
170 	gpio_add_events();
171 
172 	gpp_clk_setup();
173 	fch_clk_output_48Mhz();
174 	cgpll_clock_gate_init();
175 }
176 
fch_final(void * chip_info)177 void fch_final(void *chip_info)
178 {
179 }
180 
set_pci_irqs(void * unused)181 static void set_pci_irqs(void *unused)
182 {
183 	/* Write PCI_INTR regs 0xC00/0xC01 */
184 	write_pci_int_table();
185 
186 	/* pirq_data is consumed by `write_pci_cfg_irqs` */
187 	populate_pirq_data();
188 
189 	/* Write IRQs for all devicetree enabled devices */
190 	write_pci_cfg_irqs();
191 }
192 
193 /*
194  * Hook this function into the PCI state machine
195  * on entry into BS_DEV_ENABLE.
196  */
197 BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, set_pci_irqs, NULL);
198