xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/gpp_clk/gpp_clk.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <amdblocks/acpimmio.h>
4 #include <amdblocks/pci_clk_req.h>
5 #include <types.h>
6 
7 /* configure the general purpose PCIe clock outputs according to the devicetree settings */
gpp_clk_setup_common(enum gpp_clk_req * gpp_clk_config,size_t gpp_clk_config_num)8 void gpp_clk_setup_common(enum gpp_clk_req *gpp_clk_config, size_t gpp_clk_config_num)
9 {
10 	/* look-up table to be able to iterate over the PCIe clock output settings */
11 	const uint8_t gpp_clk_shift_lut[GPP_CLK_OUTPUT_COUNT] = {
12 		GPP_CLK0_REQ_SHIFT,
13 		GPP_CLK1_REQ_SHIFT,
14 		GPP_CLK2_REQ_SHIFT,
15 		GPP_CLK3_REQ_SHIFT,
16 		GPP_CLK4_REQ_SHIFT,
17 		GPP_CLK5_REQ_SHIFT,
18 		GPP_CLK6_REQ_SHIFT,
19 	};
20 
21 	uint32_t gpp_clk_ctl = misc_read32(GPP_CLK_CNTRL);
22 
23 	pcie_gpp_dxio_update_clk_req_config(gpp_clk_config, gpp_clk_config_num);
24 	for (int i = 0; i < GPP_CLK_OUTPUT_COUNT; i++) {
25 		gpp_clk_ctl &= ~GPP_CLK_REQ_MASK(gpp_clk_shift_lut[i]);
26 		/*
27 		 * The remapping of values is done so that the default of the enum used for the
28 		 * devicetree settings is the clock being enabled, so that a missing devicetree
29 		 * configuration for this will result in an always active clock and not an
30 		 * inactive PCIe clock output. Only the configuration for the clock outputs
31 		 * available on the package is provided via the devicetree; the rest is
32 		 * switched off unconditionally.
33 		 */
34 		switch (i < gpp_clk_config_num ? gpp_clk_config[i] : GPP_CLK_OFF) {
35 		case GPP_CLK_REQ:
36 			gpp_clk_ctl |= GPP_CLK_REQ_EXT(gpp_clk_shift_lut[i]);
37 			break;
38 		case GPP_CLK_OFF:
39 			gpp_clk_ctl |= GPP_CLK_REQ_OFF(gpp_clk_shift_lut[i]);
40 			break;
41 		case GPP_CLK_ON:
42 		default:
43 			gpp_clk_ctl |= GPP_CLK_REQ_ON(gpp_clk_shift_lut[i]);
44 		}
45 	}
46 
47 	misc_write32(GPP_CLK_CNTRL, gpp_clk_ctl);
48 }
49