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:
parent
05ef94795f
commit
82a0a63f99
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue