lynxpoint: me: Support ICC clock enables message
This message allows unused clocks to be disabled based on a devicetree setting in each mainboard. Change-Id: Ib1988cab3748490cf24028752562c64ccbce2054 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/65250 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/4450 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
committed by
Patrick Georgi
parent
2017b4a44f
commit
0dc0d1383d
@@ -92,6 +92,13 @@ struct southbridge_intel_lynxpoint_config {
|
|||||||
/* I2C voltage select: 0=3.3V 1=1.8V */
|
/* I2C voltage select: 0=3.3V 1=1.8V */
|
||||||
uint8_t sio_i2c0_voltage;
|
uint8_t sio_i2c0_voltage;
|
||||||
uint8_t sio_i2c1_voltage;
|
uint8_t sio_i2c1_voltage;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clock Disable Map:
|
||||||
|
* [21:16] = CLKOUT_PCIE# 5-0
|
||||||
|
* [24] = CLKOUT_ITPXDP
|
||||||
|
*/
|
||||||
|
uint32_t icc_clock_disable;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct chip_operations southbridge_intel_lynxpoint_ops;
|
extern struct chip_operations southbridge_intel_lynxpoint_ops;
|
||||||
|
@@ -286,6 +286,24 @@ struct me_fw_version {
|
|||||||
u16 recovery_hot_fix;
|
u16 recovery_hot_fix;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* ICC Messages */
|
||||||
|
#define ICC_SET_CLOCK_ENABLES 0x3
|
||||||
|
#define ICC_API_VERSION_LYNXPOINT 0x00030000
|
||||||
|
|
||||||
|
struct icc_header {
|
||||||
|
u32 api_version;
|
||||||
|
u32 icc_command;
|
||||||
|
u32 icc_status;
|
||||||
|
u32 length;
|
||||||
|
u32 reserved;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct icc_clock_enables_msg {
|
||||||
|
u32 clock_enables;
|
||||||
|
u32 clock_mask;
|
||||||
|
u32 no_response: 1;
|
||||||
|
u32 reserved: 31;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define HECI_EOP_STATUS_SUCCESS 0x0
|
#define HECI_EOP_STATUS_SUCCESS 0x0
|
||||||
#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1
|
#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1
|
||||||
|
@@ -412,6 +412,30 @@ static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int mei_sendrecv_icc(struct icc_header *icc,
|
||||||
|
void *req_data, int req_bytes,
|
||||||
|
void *rsp_data, int rsp_bytes)
|
||||||
|
{
|
||||||
|
struct icc_header icc_rsp;
|
||||||
|
|
||||||
|
/* Send header */
|
||||||
|
if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
|
||||||
|
icc, sizeof(*icc), req_bytes ? 0 : 1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Send data if available */
|
||||||
|
if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
|
||||||
|
req_data, req_bytes) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Read header and data, if needed */
|
||||||
|
if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp),
|
||||||
|
rsp_data, rsp_bytes) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
|
* mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
|
||||||
* state machine on the BIOS end doesn't match the ME's state machine.
|
* state machine on the BIOS end doesn't match the ME's state machine.
|
||||||
@@ -610,6 +634,30 @@ void intel_me_finalize_smm(void)
|
|||||||
|
|
||||||
#else /* !__SMM__ */
|
#else /* !__SMM__ */
|
||||||
|
|
||||||
|
static int me_icc_set_clock_enables(u32 mask)
|
||||||
|
{
|
||||||
|
struct icc_clock_enables_msg clk = {
|
||||||
|
.clock_enables = 0, /* Turn off specified clocks */
|
||||||
|
.clock_mask = mask,
|
||||||
|
.no_response = 1, /* Do not expect response */
|
||||||
|
};
|
||||||
|
struct icc_header icc = {
|
||||||
|
.api_version = ICC_API_VERSION_LYNXPOINT,
|
||||||
|
.icc_command = ICC_SET_CLOCK_ENABLES,
|
||||||
|
.length = sizeof(clk),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Send request and wait for response */
|
||||||
|
if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) {
|
||||||
|
printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine the path that we should take based on ME status */
|
/* Determine the path that we should take based on ME status */
|
||||||
static me_bios_path intel_me_path(device_t dev)
|
static me_bios_path intel_me_path(device_t dev)
|
||||||
{
|
{
|
||||||
@@ -760,6 +808,7 @@ static int intel_me_extend_valid(device_t dev)
|
|||||||
/* Check whether ME is present and do basic init */
|
/* Check whether ME is present and do basic init */
|
||||||
static void intel_me_init(device_t dev)
|
static void intel_me_init(device_t dev)
|
||||||
{
|
{
|
||||||
|
struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
|
||||||
me_bios_path path = intel_me_path(dev);
|
me_bios_path path = intel_me_path(dev);
|
||||||
me_bios_payload mbp_data;
|
me_bios_payload mbp_data;
|
||||||
|
|
||||||
@@ -768,7 +817,6 @@ static void intel_me_init(device_t dev)
|
|||||||
|
|
||||||
if (path == ME_NORMAL_BIOS_PATH) {
|
if (path == ME_NORMAL_BIOS_PATH) {
|
||||||
/* Validate the extend register */
|
/* Validate the extend register */
|
||||||
/* FIXME: force recovery mode on failure. */
|
|
||||||
intel_me_extend_valid(dev);
|
intel_me_extend_valid(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,6 +848,10 @@ static void intel_me_init(device_t dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set clock enables according to devicetree */
|
||||||
|
if (config && config->icc_clock_disable)
|
||||||
|
me_icc_set_clock_enables(config->icc_clock_disable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leave the ME unlocked. It will be locked via SMI command later.
|
* Leave the ME unlocked. It will be locked via SMI command later.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user