diff options
-rw-r--r-- | src/drivers/ipmi/ocp/Kconfig | 5 | ||||
-rw-r--r-- | src/drivers/ipmi/ocp/ipmi_ocp.c | 103 | ||||
-rw-r--r-- | src/drivers/ipmi/ocp/ipmi_ocp.h | 30 |
3 files changed, 138 insertions, 0 deletions
diff --git a/src/drivers/ipmi/ocp/Kconfig b/src/drivers/ipmi/ocp/Kconfig index 7899e69588..26503efb8d 100644 --- a/src/drivers/ipmi/ocp/Kconfig +++ b/src/drivers/ipmi/ocp/Kconfig @@ -3,3 +3,8 @@ config IPMI_OCP default n help This implements OCP specific IPMI command + +config IPMI_OCP_MANU_ID + hex + default 0x0 + depends on IPMI_OCP diff --git a/src/drivers/ipmi/ocp/ipmi_ocp.c b/src/drivers/ipmi/ocp/ipmi_ocp.c index 1866708f10..f96ce24cdd 100644 --- a/src/drivers/ipmi/ocp/ipmi_ocp.c +++ b/src/drivers/ipmi/ocp/ipmi_ocp.c @@ -10,10 +10,110 @@ #include <console/console.h> #include <device/device.h> #include <device/pnp.h> +#include <string.h> +#include <intelblocks/cpulib.h> +#include <arch/cpu.h> #include "chip.h" #include "drivers/ipmi/ipmi_kcs.h" #include "ipmi_ocp.h" +static int ipmi_set_processor_information_param1(struct device *dev) +{ + int ret; + struct ipmi_processor_info_param1_req req1 = {0}; + struct ipmi_rsp rsp; + int mfid = CONFIG_IPMI_OCP_MANU_ID; + + memcpy(&req1.data.manufacturer_id, &mfid, 3); + printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n", + req1.data.manufacturer_id[2], req1.data.manufacturer_id[1], + req1.data.manufacturer_id[0]); + + req1.data.index = 0; + req1.data.parameter_selector = 1; + + /* Get processor name. */ + fill_processor_name(req1.product_name); + printk(BIOS_DEBUG, "IPMI BMC CPU NAME: %s.\n", req1.product_name); + + ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0, + IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req1, + sizeof(req1), (u8 *) &rsp, sizeof(rsp)); + + if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) { + printk(BIOS_ERR, "IPMI BMC: %s command failed (ret=%d rsp=0x%x)\n", + __func__, ret, rsp.completion_code); + return CB_ERR; + } + return CB_SUCCESS; +} + +static int ipmi_set_processor_information_param2(struct device *dev) +{ + int ret; + struct ipmi_processor_info_param2_req req2 = {0}; + struct ipmi_rsp rsp; + uint8_t stepping_id; + int mfid = CONFIG_IPMI_OCP_MANU_ID; + unsigned int core_count, thread_count; + struct cpuinfo_x86 c; + + memcpy(&req2.data.manufacturer_id, &mfid, 3); + printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n", + req2.data.manufacturer_id[2], req2.data.manufacturer_id[1], + req2.data.manufacturer_id[0]); + + req2.data.index = 0; + req2.data.parameter_selector = 2; + + /* Get core number and thread number. */ + cpu_read_topology(&core_count, &thread_count); + req2.core_number = core_count; + req2.thread_number = thread_count; + printk(BIOS_DEBUG, "IPMI BMC CPU has %u cores, %u threads enabled.\n", + req2.core_number, req2.thread_number); + + /* Get processor frequency. */ + req2.processor_freq = 100 * cpu_get_max_ratio(); + printk(BIOS_DEBUG, "IPMI BMC CPU frequency is %u MHz.\n", + req2.processor_freq); + + /* Get revision. */ + get_fms(&c, cpuid_eax(1)); + stepping_id = c.x86_mask; + printk(BIOS_DEBUG, "IPMI BMC CPU stepping id is %x.\n", stepping_id); + switch (stepping_id) { + /* TBD */ + case 0x0a: + req2.revision[0] = 'A'; + req2.revision[1] = '0'; + break; + default: + req2.revision[0] = 'X'; + req2.revision[1] = 'X'; + } + + ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0, + IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req2, + sizeof(req2), (u8 *) &rsp, sizeof(rsp)); + + if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) { + printk(BIOS_ERR, "IPMI: %s command failed (ret=%d rsp=0x%x)\n", + __func__, ret, rsp.completion_code); + return CB_ERR; + } + return CB_SUCCESS; +} + +static void ipmi_set_processor_information(struct device *dev) +{ + if (ipmi_set_processor_information_param1(dev)) + printk(BIOS_ERR, "IPMI BMC set param 1 processor info failed\n"); + + if (ipmi_set_processor_information_param2(dev)) + printk(BIOS_ERR, "IPMI BMC set param 2 processor info failed\n"); +} + static void ipmi_ocp_init(struct device *dev) { /* Add OCP specific IPMI command */ @@ -22,6 +122,9 @@ static void ipmi_ocp_init(struct device *dev) static void ipmi_ocp_final(struct device *dev) { /* Add OCP specific IPMI command */ + + /* Send processor information */ + ipmi_set_processor_information(dev); } static void ipmi_set_resources(struct device *dev) diff --git a/src/drivers/ipmi/ocp/ipmi_ocp.h b/src/drivers/ipmi/ocp/ipmi_ocp.h index 9aebbe9f5a..96b0086298 100644 --- a/src/drivers/ipmi/ocp/ipmi_ocp.h +++ b/src/drivers/ipmi/ocp/ipmi_ocp.h @@ -3,4 +3,34 @@ #ifndef __IPMI_OCP_H #define __IPMI_OCP_H +#include <cpu/x86/msr.h> +#include <cpu/x86/name.h> +#include "drivers/ipmi/ipmi_kcs.h" + +#define IPMI_NETFN_OEM_COMMON 0x36 +#define IPMI_BMC_SET_PROCESSOR_INFORMATION 0x10 +#define IPMI_BMC_GET_PROCESSOR_INFORMATION 0x11 + +#define MSR_CORE_THREAD_COUNT 0x35 +#define MSR_PLATFORM_INFO 0xce + +struct ipmi_processor_info_req { + uint8_t manufacturer_id[3]; + uint8_t index; + uint8_t parameter_selector; +} __packed; + +struct ipmi_processor_info_param1_req { + struct ipmi_processor_info_req data; + char product_name[48]; +} __packed; + +struct ipmi_processor_info_param2_req { + struct ipmi_processor_info_req data; + uint8_t core_number; + uint16_t thread_number; + uint16_t processor_freq; + char revision[2]; +} __packed; + #endif |