soc/amd/picasso/southbridge: make GPP clock outputs configurable

Make the general purpose PCIe clock outputs configurable to be either
permanently enabled, permanently disabled or dynamically enabled via
their corresponding external #CLK_REQx pins in the board's devicetree.

BUG=b:149970243
BRANCH=zork

Change-Id: I3f5760c0b869e8a9416ba9b57d182a88a2eb5e44
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44889
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Felix Held 2020-08-28 01:40:20 +02:00 committed by Patrick Georgi
parent 05ef94795f
commit 82a0a63f99
3 changed files with 54 additions and 0 deletions

View File

@ -154,6 +154,9 @@ struct soc_amd_picasso_config {
USB_OC_PIN_5 = 0x5,
USB_OC_NONE = 0xf,
} usb_port_overcurrent_pin[USB_PORT_COUNT];
/* The array index is the general purpose PCIe clock output number. */
enum gpp_clk_req_setting gpp_clk_config[GPP_CLK_OUTPUT_COUNT];
};
typedef struct soc_amd_picasso_config config_t;

View File

@ -245,6 +245,13 @@
/* IO 0xf0 NCP Error */
#define NCP_WARM_BOOT BIT(7) /* Write-once */
/* this is for the devicetree setting and not the values written to the register */
enum gpp_clk_req_setting {
GPP_CLK_ON, /* GPP clock always on; default */
GPP_CLK_REQ, /* GPP clock controlled by corresponding #CLK_REQx pin */
GPP_CLK_OFF, /* GPP clk off */
};
typedef struct aoac_devs {
unsigned int :7;
unsigned int ic2e:1; /* 7: I2C2 */

View File

@ -307,6 +307,48 @@ static void al2ahb_clock_gate(void)
write8((void *)(al2ahb_base + AL2AHB_CONTROL_HCLK_OFFSET), al2ahb_val);
}
/* configure the genral purpose PCIe clock outputs according to the devicetree settings */
static void gpp_clk_setup(void)
{
const struct soc_amd_picasso_config *cfg = config_of_soc();
/* look-up table to be able to iterate over the PCIe clock output settings */
const uint8_t gpp_clk_shift_lut[GPP_CLK_OUTPUT_COUNT] = {
GPP_CLK0_REQ_SHIFT,
GPP_CLK1_REQ_SHIFT,
GPP_CLK2_REQ_SHIFT,
GPP_CLK3_REQ_SHIFT,
GPP_CLK4_REQ_SHIFT,
GPP_CLK5_REQ_SHIFT,
GPP_CLK6_REQ_SHIFT,
};
uint32_t gpp_clk_ctl = misc_read32(GPP_CLK_CNTRL);
for (int i = 0; i < GPP_CLK_OUTPUT_COUNT; i++) {
gpp_clk_ctl &= ~GPP_CLK_REQ_MASK(gpp_clk_shift_lut[i]);
/*
* The remapping of values is done so that the default of the enum used for the
* devicetree settings is the clock being enabled, so that a missing devicetree
* configuration for this will result in an always active clock and not an
* inactive PCIe clock output.
*/
switch (cfg->gpp_clk_config[i]) {
case GPP_CLK_REQ:
gpp_clk_ctl |= GPP_CLK_REQ_EXT(gpp_clk_shift_lut[i]);
break;
case GPP_CLK_OFF:
gpp_clk_ctl |= GPP_CLK_REQ_OFF(gpp_clk_shift_lut[i]);
break;
case GPP_CLK_ON:
default:
gpp_clk_ctl |= GPP_CLK_REQ_ON(gpp_clk_shift_lut[i]);
}
}
misc_write32(GPP_CLK_CNTRL, gpp_clk_ctl);
}
void southbridge_init(void *chip_info)
{
struct chipset_state *state;
@ -322,6 +364,8 @@ void southbridge_init(void *chip_info)
acpi_clear_pm_gpe_status();
al2ahb_clock_gate();
gpp_clk_setup();
}
void southbridge_final(void *chip_info)