summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2013-08-08 15:31:51 -0700
committerPatrick Georgi <patrick@georgi-clan.de>2013-12-21 12:02:24 +0100
commit0dc0d1383df258bbb18dec18e0bf7e00dfda1651 (patch)
treec0aa550e7d53e2ecff0a836f51aa8d66b83b1b46 /src/southbridge
parent2017b4a44fcb8dcf01852d00391d71be5c041523 (diff)
downloadcoreboot-0dc0d1383df258bbb18dec18e0bf7e00dfda1651.tar.xz
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>
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/lynxpoint/chip.h7
-rw-r--r--src/southbridge/intel/lynxpoint/me.h18
-rw-r--r--src/southbridge/intel/lynxpoint/me_9.x.c54
3 files changed, 78 insertions, 1 deletions
diff --git a/src/southbridge/intel/lynxpoint/chip.h b/src/southbridge/intel/lynxpoint/chip.h
index 70f3e63a63..a0e2232788 100644
--- a/src/southbridge/intel/lynxpoint/chip.h
+++ b/src/southbridge/intel/lynxpoint/chip.h
@@ -92,6 +92,13 @@ struct southbridge_intel_lynxpoint_config {
/* I2C voltage select: 0=3.3V 1=1.8V */
uint8_t sio_i2c0_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;
diff --git a/src/southbridge/intel/lynxpoint/me.h b/src/southbridge/intel/lynxpoint/me.h
index d919107609..a72778b88f 100644
--- a/src/southbridge/intel/lynxpoint/me.h
+++ b/src/southbridge/intel/lynxpoint/me.h
@@ -286,6 +286,24 @@ struct me_fw_version {
u16 recovery_hot_fix;
} __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_PERFORM_GLOBAL_RESET 0x1
diff --git a/src/southbridge/intel/lynxpoint/me_9.x.c b/src/southbridge/intel/lynxpoint/me_9.x.c
index d1a692c287..e01316f28e 100644
--- a/src/southbridge/intel/lynxpoint/me_9.x.c
+++ b/src/southbridge/intel/lynxpoint/me_9.x.c
@@ -412,6 +412,30 @@ static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi,
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
* 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__ */
+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 */
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 */
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_payload mbp_data;
@@ -768,7 +817,6 @@ static void intel_me_init(device_t dev)
if (path == ME_NORMAL_BIOS_PATH) {
/* Validate the extend register */
- /* FIXME: force recovery mode on failure. */
intel_me_extend_valid(dev);
}
@@ -800,6 +848,10 @@ static void intel_me_init(device_t dev)
}
#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.
*/