blob: ee38bb0076038e761f4e3790db48fbf080b457b3 [file] [log] [blame]
Tim Chu1343bc32020-07-28 04:27:35 -07001/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Place in devicetree.cb:
4 *
5 * chip drivers/ipmi/ocp # OCP specific IPMI porting
6 device pnp ca2.1 on end
7 * end
8 */
9
Marc Jones882a5682020-10-02 20:31:23 -060010#include <arch/cpu.h>
Tim Chu1343bc32020-07-28 04:27:35 -070011#include <console/console.h>
12#include <device/device.h>
13#include <device/pnp.h>
Marc Jones882a5682020-10-02 20:31:23 -060014#include <drivers/ipmi/ipmi_kcs.h>
Johnny Lin3acea5c2021-01-08 15:24:25 +080015#include <drivers/ocp/dmi/ocp_dmi.h>
Tim Chu6b297c02020-06-08 22:52:58 -070016#include <intelblocks/cpulib.h>
Marc Jones882a5682020-10-02 20:31:23 -060017#include <string.h>
18#include <types.h>
19
Tim Chu1343bc32020-07-28 04:27:35 -070020#include "ipmi_ocp.h"
21
Tim Chu6b297c02020-06-08 22:52:58 -070022static int ipmi_set_processor_information_param1(struct device *dev)
23{
24 int ret;
25 struct ipmi_processor_info_param1_req req1 = {0};
26 struct ipmi_rsp rsp;
27 int mfid = CONFIG_IPMI_OCP_MANU_ID;
28
29 memcpy(&req1.data.manufacturer_id, &mfid, 3);
30 printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
31 req1.data.manufacturer_id[2], req1.data.manufacturer_id[1],
32 req1.data.manufacturer_id[0]);
33
34 req1.data.index = 0;
35 req1.data.parameter_selector = 1;
36
37 /* Get processor name. */
38 fill_processor_name(req1.product_name);
39 printk(BIOS_DEBUG, "IPMI BMC CPU NAME: %s.\n", req1.product_name);
40
41 ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
42 IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req1,
43 sizeof(req1), (u8 *) &rsp, sizeof(rsp));
44
45 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
46 printk(BIOS_ERR, "IPMI BMC: %s command failed (ret=%d rsp=0x%x)\n",
47 __func__, ret, rsp.completion_code);
48 return CB_ERR;
49 }
50 return CB_SUCCESS;
51}
52
53static int ipmi_set_processor_information_param2(struct device *dev)
54{
55 int ret;
56 struct ipmi_processor_info_param2_req req2 = {0};
57 struct ipmi_rsp rsp;
58 uint8_t stepping_id;
59 int mfid = CONFIG_IPMI_OCP_MANU_ID;
60 unsigned int core_count, thread_count;
61 struct cpuinfo_x86 c;
62
63 memcpy(&req2.data.manufacturer_id, &mfid, 3);
64 printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
65 req2.data.manufacturer_id[2], req2.data.manufacturer_id[1],
66 req2.data.manufacturer_id[0]);
67
68 req2.data.index = 0;
69 req2.data.parameter_selector = 2;
70
71 /* Get core number and thread number. */
72 cpu_read_topology(&core_count, &thread_count);
73 req2.core_number = core_count;
74 req2.thread_number = thread_count;
75 printk(BIOS_DEBUG, "IPMI BMC CPU has %u cores, %u threads enabled.\n",
76 req2.core_number, req2.thread_number);
77
78 /* Get processor frequency. */
79 req2.processor_freq = 100 * cpu_get_max_ratio();
80 printk(BIOS_DEBUG, "IPMI BMC CPU frequency is %u MHz.\n",
81 req2.processor_freq);
82
83 /* Get revision. */
84 get_fms(&c, cpuid_eax(1));
85 stepping_id = c.x86_mask;
86 printk(BIOS_DEBUG, "IPMI BMC CPU stepping id is %x.\n", stepping_id);
87 switch (stepping_id) {
88 /* TBD */
89 case 0x0a:
90 req2.revision[0] = 'A';
91 req2.revision[1] = '0';
92 break;
93 default:
94 req2.revision[0] = 'X';
95 req2.revision[1] = 'X';
96 }
97
98 ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
99 IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req2,
100 sizeof(req2), (u8 *) &rsp, sizeof(rsp));
101
102 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
103 printk(BIOS_ERR, "IPMI: %s command failed (ret=%d rsp=0x%x)\n",
104 __func__, ret, rsp.completion_code);
105 return CB_ERR;
106 }
107 return CB_SUCCESS;
108}
109
110static void ipmi_set_processor_information(struct device *dev)
111{
112 if (ipmi_set_processor_information_param1(dev))
113 printk(BIOS_ERR, "IPMI BMC set param 1 processor info failed\n");
114
115 if (ipmi_set_processor_information_param2(dev))
116 printk(BIOS_ERR, "IPMI BMC set param 2 processor info failed\n");
117}
118
Johnny Lin3acea5c2021-01-08 15:24:25 +0800119static enum cb_err ipmi_set_ppin(struct device *dev)
120{
121 int ret;
122 struct ipmi_rsp rsp;
123 struct ppin_req req = {0};
124
125 req.cpu0_lo = xeon_sp_ppin[0].lo;
126 req.cpu0_hi = xeon_sp_ppin[0].hi;
127 if (CONFIG_MAX_SOCKET > 1) {
128 req.cpu1_lo = xeon_sp_ppin[1].lo;
129 req.cpu1_hi = xeon_sp_ppin[1].hi;
130 }
131 ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM, 0x0, IPMI_OEM_SET_PPIN,
132 (const unsigned char *) &req, sizeof(req), (unsigned char *) &rsp, sizeof(rsp));
133
134 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
135 printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
136 __func__, ret, rsp.completion_code);
137 return CB_ERR;
138 }
139 printk(BIOS_DEBUG, "IPMI: %s command success\n", __func__);
140 return CB_SUCCESS;
141}
142
Tim Chu1343bc32020-07-28 04:27:35 -0700143static void ipmi_ocp_init(struct device *dev)
144{
145 /* Add OCP specific IPMI command */
146}
147
148static void ipmi_ocp_final(struct device *dev)
149{
150 /* Add OCP specific IPMI command */
Tim Chu6b297c02020-06-08 22:52:58 -0700151
152 /* Send processor information */
153 ipmi_set_processor_information(dev);
Johnny Lin3acea5c2021-01-08 15:24:25 +0800154 if (CONFIG(OCP_DMI))
155 ipmi_set_ppin(dev);
Tim Chu1343bc32020-07-28 04:27:35 -0700156}
157
158static void ipmi_set_resources(struct device *dev)
159{
160 struct resource *res;
161
162 for (res = dev->resource_list; res; res = res->next) {
163 if (!(res->flags & IORESOURCE_ASSIGNED))
164 continue;
165
166 res->flags |= IORESOURCE_STORED;
167 report_resource_stored(dev, res, "");
168 }
169}
170
171static void ipmi_read_resources(struct device *dev)
172{
173 struct resource *res = new_resource(dev, 0);
174 res->base = dev->path.pnp.port;
175 res->size = 2;
176 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
177}
178
179static struct device_operations ops = {
180 .read_resources = ipmi_read_resources,
181 .set_resources = ipmi_set_resources,
182 .init = ipmi_ocp_init,
183 .final = ipmi_ocp_final,
184};
185
186static void enable_dev(struct device *dev)
187{
188 if (dev->path.type != DEVICE_PATH_PNP)
189 printk(BIOS_ERR, "%s: Unsupported device type\n",
190 dev_path(dev));
191 else if (dev->path.pnp.port & 1)
192 printk(BIOS_ERR, "%s: Base address needs to be aligned to 2\n",
193 dev_path(dev));
194 else
195 dev->ops = &ops;
196}
197
198struct chip_operations drivers_ipmi_ocp_ops = {
199 CHIP_NAME("IPMI OCP")
200 .enable_dev = enable_dev,
201};