xref: /aosp_15_r20/external/coreboot/src/southbridge/amd/pi/hudson/early_setup.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef _HUDSON_EARLY_SETUP_C_
4 #define _HUDSON_EARLY_SETUP_C_
5 
6 #include <assert.h>
7 #include <stdint.h>
8 #include <amdblocks/acpimmio.h>
9 #include <device/mmio.h>
10 #include <device/pci_ops.h>
11 
12 #include "hudson.h"
13 #include "pci_devs.h"
14 #include <Fch/Fch.h>
15 
hudson_pci_port80(void)16 void hudson_pci_port80(void)
17 {
18 	u8 byte;
19 	pci_devfn_t dev;
20 
21 	/* P2P Bridge */
22 	dev = PCI_DEV(0, 0x14, 4);
23 
24 	/* Chip Control: Enable subtractive decoding */
25 	byte = pci_read_config8(dev, 0x40);
26 	byte |= 1 << 5;
27 	pci_write_config8(dev, 0x40, byte);
28 
29 	/* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */
30 	byte = pci_read_config8(dev, 0x4B);
31 	byte |= 1 << 7;
32 	pci_write_config8(dev, 0x4B, byte);
33 
34 	/* The same IO Base and IO Limit here is meaningful because we set the
35 	 * bridge to be subtractive. During early setup stage, we have to make
36 	 * sure that data can go through port 0x80.
37 	 */
38 	/* IO Base: 0xf000 */
39 	byte = pci_read_config8(dev, 0x1C);
40 	byte |= 0xF << 4;
41 	pci_write_config8(dev, 0x1C, byte);
42 
43 	/* IO Limit: 0xf000 */
44 	byte = pci_read_config8(dev, 0x1D);
45 	byte |= 0xF << 4;
46 	pci_write_config8(dev, 0x1D, byte);
47 
48 	/* PCI Command: Enable IO response */
49 	byte = pci_read_config8(dev, 0x04);
50 	byte |= 1 << 0;
51 	pci_write_config8(dev, 0x04, byte);
52 
53 	/* LPC controller */
54 	dev = PCI_DEV(0, 0x14, 3);
55 
56 	byte = pci_read_config8(dev, 0x4A);
57 	byte &= ~(1 << 5); /* disable lpc port 80 */
58 	pci_write_config8(dev, 0x4A, byte);
59 }
60 
hudson_lpc_port80(void)61 void hudson_lpc_port80(void)
62 {
63 	u8 byte;
64 
65 	/* Enable port 80 LPC decode in pci function 3 configuration space. */
66 	const pci_devfn_t dev = PCI_DEV(0, 0x14, 3);
67 	byte = pci_read_config8(dev, 0x4a);
68 	byte |= 1 << 5; /* enable port 80 */
69 	pci_write_config8(dev, 0x4a, byte);
70 }
71 
hudson_lpc_decode(void)72 void hudson_lpc_decode(void)
73 {
74 	u32 tmp;
75 
76 	/* Enable LPC controller */
77 	pm_write8(0xec, pm_read8(0xec) | 0x01);
78 
79 	const pci_devfn_t dev = PCI_DEV(0, 0x14, 3);
80 	/* Serial port enumeration on Hudson:
81 	 * PORT0 - 0x3f8
82 	 * PORT1 - 0x2f8
83 	 * PORT5 - 0x2e8
84 	 * PORT7 - 0x3e8
85 	 */
86 	tmp =  DECODE_ENABLE_SERIAL_PORT0 | DECODE_ENABLE_SERIAL_PORT1
87 	     | DECODE_ENABLE_SERIAL_PORT5 | DECODE_ENABLE_SERIAL_PORT7;
88 
89 	pci_write_config32(dev, LPC_IO_PORT_DECODE_ENABLE, tmp);
90 }
91 
enable_wideio(uint8_t port,uint16_t size)92 static void enable_wideio(uint8_t port, uint16_t size)
93 {
94 	uint32_t wideio_enable[] = {
95 		LPC_WIDEIO0_ENABLE,
96 		LPC_WIDEIO1_ENABLE,
97 		LPC_WIDEIO2_ENABLE
98 	};
99 	uint32_t alt_wideio_enable[] = {
100 		LPC_ALT_WIDEIO0_ENABLE,
101 		LPC_ALT_WIDEIO1_ENABLE,
102 		LPC_ALT_WIDEIO2_ENABLE
103 	};
104 	const pci_devfn_t dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);
105 	uint32_t tmp;
106 
107 	/* Only allow port 0-2 */
108 	assert(port <= ARRAY_SIZE(wideio_enable));
109 
110 	if (size == 16) {
111 		tmp = pci_read_config32(dev, LPC_ALT_WIDEIO_RANGE_ENABLE);
112 		tmp |= alt_wideio_enable[port];
113 		pci_write_config32(dev, LPC_ALT_WIDEIO_RANGE_ENABLE, tmp);
114 	} else {	/* 512 */
115 		tmp = pci_read_config32(dev, LPC_ALT_WIDEIO_RANGE_ENABLE);
116 		tmp &= ~alt_wideio_enable[port];
117 		pci_write_config32(dev, LPC_ALT_WIDEIO_RANGE_ENABLE, tmp);
118 	}
119 
120 	/* Enable the range */
121 	tmp = pci_read_config32(dev, LPC_IO_OR_MEM_DECODE_ENABLE);
122 	tmp |= wideio_enable[port];
123 	pci_write_config32(dev, LPC_IO_OR_MEM_DECODE_ENABLE, tmp);
124 }
125 
126 /*
127  * lpc_wideio_window() may be called any point in romstage, but take
128  * care that AGESA doesn't overwrite the range this function used.
129  * The function checks if there is an empty range and if all ranges are
130  * used the function throws an assert. The function doesn't check for a
131  * duplicate range, for ranges that can  be merged into a single
132  * range, or ranges that overlap.
133  *
134  * The developer is expected to ensure that there are no conflicts.
135  */
lpc_wideio_window(uint16_t base,uint16_t size)136 static void lpc_wideio_window(uint16_t base, uint16_t size)
137 {
138 	const pci_devfn_t dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);
139 	u32 tmp;
140 
141 	/* Support 512 or 16 bytes per range */
142 	assert(size == 512 || size == 16);
143 
144 	/* Find and open Base Register and program it */
145 	tmp = pci_read_config32(dev, LPC_WIDEIO_GENERIC_PORT);
146 
147 	if ((tmp & 0xFFFF) == 0) {	/* WIDEIO0 */
148 		tmp |= base;
149 		pci_write_config32(dev, LPC_WIDEIO_GENERIC_PORT, tmp);
150 		enable_wideio(0, size);
151 	} else if ((tmp & 0xFFFF0000) == 0) {	/* WIDEIO1 */
152 		tmp |= (base << 16);
153 		pci_write_config32(dev, LPC_WIDEIO_GENERIC_PORT, tmp);
154 		enable_wideio(1, size);
155 	} else { /* Check WIDEIO2 register */
156 		tmp = pci_read_config32(dev, LPC_WIDEIO2_GENERIC_PORT);
157 		if ((tmp & 0xFFFF) == 0) {	/* WIDEIO2 */
158 			tmp |= base;
159 			pci_write_config32(dev, LPC_WIDEIO2_GENERIC_PORT, tmp);
160 			enable_wideio(2, size);
161 		} else {	/* All WIDEIO locations used*/
162 			BUG();
163 		}
164 	}
165 }
166 
lpc_wideio_512_window(uint16_t base)167 void lpc_wideio_512_window(uint16_t base)
168 {
169 	assert(IS_ALIGNED(base, 512));
170 	lpc_wideio_window(base, 512);
171 }
172 
lpc_wideio_16_window(uint16_t base)173 void lpc_wideio_16_window(uint16_t base)
174 {
175 	assert(IS_ALIGNED(base, 16));
176 	lpc_wideio_window(base, 16);
177 }
178 
hudson_clk_output_48Mhz(void)179 void hudson_clk_output_48Mhz(void)
180 {
181 	u32 ctrl;
182 
183 	/*
184 	 * Enable the X14M_25M_48M_OSC pin and leaving it at it's default so
185 	 * 48Mhz will be on ball AP13 (FT3b package)
186 	 */
187 	ctrl = misc_read32(FCH_MISC_REG40);
188 
189 	/* clear the OSCOUT1_ClkOutputEnb to enable the 48 Mhz clock */
190 	ctrl &= (u32)~(1 << 2);
191 	misc_write32(FCH_MISC_REG40, ctrl);
192 }
193 
hudson_spibase(void)194 static uintptr_t hudson_spibase(void)
195 {
196 	/* Make sure the base address is predictable */
197 	const pci_devfn_t dev = PCI_DEV(0, 0x14, 3);
198 
199 	u32 base = pci_read_config32(dev, SPIROM_BASE_ADDRESS_REGISTER)
200 							& 0xfffffff0;
201 	if (!base) {
202 		base = SPI_BASE_ADDRESS;
203 		pci_write_config32(dev, SPIROM_BASE_ADDRESS_REGISTER, base
204 							| SPI_ROM_ENABLE);
205 		/* PCI_COMMAND_MEMORY is read-only and enabled. */
206 	}
207 	return (uintptr_t)base;
208 }
209 
hudson_set_spi100(u16 norm,u16 fast,u16 alt,u16 tpm)210 void hudson_set_spi100(u16 norm, u16 fast, u16 alt, u16 tpm)
211 {
212 	uintptr_t base = hudson_spibase();
213 	write16p(base + SPI100_SPEED_CONFIG,
214 			(norm << SPI_NORM_SPEED_NEW_SH) |
215 			(fast << SPI_FAST_SPEED_NEW_SH) |
216 			(alt << SPI_ALT_SPEED_NEW_SH) |
217 			(tpm << SPI_TPM_SPEED_NEW_SH));
218 	write16p(base + SPI100_ENABLE, SPI_USE_SPI100 |
219 		read16p(base + SPI100_ENABLE));
220 }
221 
hudson_disable_4dw_burst(void)222 void hudson_disable_4dw_burst(void)
223 {
224 	uintptr_t base = hudson_spibase();
225 	write16p(base + SPI100_HOST_PREF_CONFIG,
226 		read16p(base + SPI100_HOST_PREF_CONFIG)
227 				& ~SPI_RD4DW_EN_HOST);
228 }
229 
230 /* Hudson 1-3 only.  For Hudson 1, call with fast=1 */
hudson_set_readspeed(u16 norm,u16 fast)231 void hudson_set_readspeed(u16 norm, u16 fast)
232 {
233 	uintptr_t base = hudson_spibase();
234 	write16p(base + SPI_CNTRL1,
235 		(read16p(base + SPI_CNTRL1)
236 		& ~SPI_CNTRL1_SPEED_MASK)
237 		| (norm << SPI_NORM_SPEED_SH)
238 		| (fast << SPI_FAST_SPEED_SH));
239 }
240 
hudson_read_mode(u32 mode)241 void hudson_read_mode(u32 mode)
242 {
243 	uintptr_t base = hudson_spibase();
244 	write32p(base + SPI_CNTRL0,
245 		(read32p(base + SPI_CNTRL0)
246 			& ~SPI_READ_MODE_MASK) | mode);
247 }
248 
hudson_tpm_decode_spi(void)249 void hudson_tpm_decode_spi(void)
250 {
251 	const pci_devfn_t dev = PCI_DEV(0, 0x14, 3);	/* LPC device */
252 
253 	u32 spibase = pci_read_config32(dev, SPIROM_BASE_ADDRESS_REGISTER);
254 	pci_write_config32(dev, SPIROM_BASE_ADDRESS_REGISTER, spibase
255 							| ROUTE_TPM_2_SPI);
256 }
257 
258 #endif
259