blob: f96ce24cddff7c091166f0e295d4714fc14a3b2e [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
10#include <console/console.h>
11#include <device/device.h>
12#include <device/pnp.h>
Tim Chu6b297c02020-06-08 22:52:58 -070013#include <string.h>
14#include <intelblocks/cpulib.h>
15#include <arch/cpu.h>
Tim Chu1343bc32020-07-28 04:27:35 -070016#include "chip.h"
17#include "drivers/ipmi/ipmi_kcs.h"
18#include "ipmi_ocp.h"
19
Tim Chu6b297c02020-06-08 22:52:58 -070020static int ipmi_set_processor_information_param1(struct device *dev)
21{
22 int ret;
23 struct ipmi_processor_info_param1_req req1 = {0};
24 struct ipmi_rsp rsp;
25 int mfid = CONFIG_IPMI_OCP_MANU_ID;
26
27 memcpy(&req1.data.manufacturer_id, &mfid, 3);
28 printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
29 req1.data.manufacturer_id[2], req1.data.manufacturer_id[1],
30 req1.data.manufacturer_id[0]);
31
32 req1.data.index = 0;
33 req1.data.parameter_selector = 1;
34
35 /* Get processor name. */
36 fill_processor_name(req1.product_name);
37 printk(BIOS_DEBUG, "IPMI BMC CPU NAME: %s.\n", req1.product_name);
38
39 ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
40 IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req1,
41 sizeof(req1), (u8 *) &rsp, sizeof(rsp));
42
43 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
44 printk(BIOS_ERR, "IPMI BMC: %s command failed (ret=%d rsp=0x%x)\n",
45 __func__, ret, rsp.completion_code);
46 return CB_ERR;
47 }
48 return CB_SUCCESS;
49}
50
51static int ipmi_set_processor_information_param2(struct device *dev)
52{
53 int ret;
54 struct ipmi_processor_info_param2_req req2 = {0};
55 struct ipmi_rsp rsp;
56 uint8_t stepping_id;
57 int mfid = CONFIG_IPMI_OCP_MANU_ID;
58 unsigned int core_count, thread_count;
59 struct cpuinfo_x86 c;
60
61 memcpy(&req2.data.manufacturer_id, &mfid, 3);
62 printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
63 req2.data.manufacturer_id[2], req2.data.manufacturer_id[1],
64 req2.data.manufacturer_id[0]);
65
66 req2.data.index = 0;
67 req2.data.parameter_selector = 2;
68
69 /* Get core number and thread number. */
70 cpu_read_topology(&core_count, &thread_count);
71 req2.core_number = core_count;
72 req2.thread_number = thread_count;
73 printk(BIOS_DEBUG, "IPMI BMC CPU has %u cores, %u threads enabled.\n",
74 req2.core_number, req2.thread_number);
75
76 /* Get processor frequency. */
77 req2.processor_freq = 100 * cpu_get_max_ratio();
78 printk(BIOS_DEBUG, "IPMI BMC CPU frequency is %u MHz.\n",
79 req2.processor_freq);
80
81 /* Get revision. */
82 get_fms(&c, cpuid_eax(1));
83 stepping_id = c.x86_mask;
84 printk(BIOS_DEBUG, "IPMI BMC CPU stepping id is %x.\n", stepping_id);
85 switch (stepping_id) {
86 /* TBD */
87 case 0x0a:
88 req2.revision[0] = 'A';
89 req2.revision[1] = '0';
90 break;
91 default:
92 req2.revision[0] = 'X';
93 req2.revision[1] = 'X';
94 }
95
96 ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
97 IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req2,
98 sizeof(req2), (u8 *) &rsp, sizeof(rsp));
99
100 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
101 printk(BIOS_ERR, "IPMI: %s command failed (ret=%d rsp=0x%x)\n",
102 __func__, ret, rsp.completion_code);
103 return CB_ERR;
104 }
105 return CB_SUCCESS;
106}
107
108static void ipmi_set_processor_information(struct device *dev)
109{
110 if (ipmi_set_processor_information_param1(dev))
111 printk(BIOS_ERR, "IPMI BMC set param 1 processor info failed\n");
112
113 if (ipmi_set_processor_information_param2(dev))
114 printk(BIOS_ERR, "IPMI BMC set param 2 processor info failed\n");
115}
116
Tim Chu1343bc32020-07-28 04:27:35 -0700117static void ipmi_ocp_init(struct device *dev)
118{
119 /* Add OCP specific IPMI command */
120}
121
122static void ipmi_ocp_final(struct device *dev)
123{
124 /* Add OCP specific IPMI command */
Tim Chu6b297c02020-06-08 22:52:58 -0700125
126 /* Send processor information */
127 ipmi_set_processor_information(dev);
Tim Chu1343bc32020-07-28 04:27:35 -0700128}
129
130static void ipmi_set_resources(struct device *dev)
131{
132 struct resource *res;
133
134 for (res = dev->resource_list; res; res = res->next) {
135 if (!(res->flags & IORESOURCE_ASSIGNED))
136 continue;
137
138 res->flags |= IORESOURCE_STORED;
139 report_resource_stored(dev, res, "");
140 }
141}
142
143static void ipmi_read_resources(struct device *dev)
144{
145 struct resource *res = new_resource(dev, 0);
146 res->base = dev->path.pnp.port;
147 res->size = 2;
148 res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
149}
150
151static struct device_operations ops = {
152 .read_resources = ipmi_read_resources,
153 .set_resources = ipmi_set_resources,
154 .init = ipmi_ocp_init,
155 .final = ipmi_ocp_final,
156};
157
158static void enable_dev(struct device *dev)
159{
160 if (dev->path.type != DEVICE_PATH_PNP)
161 printk(BIOS_ERR, "%s: Unsupported device type\n",
162 dev_path(dev));
163 else if (dev->path.pnp.port & 1)
164 printk(BIOS_ERR, "%s: Base address needs to be aligned to 2\n",
165 dev_path(dev));
166 else
167 dev->ops = &ops;
168}
169
170struct chip_operations drivers_ipmi_ocp_ops = {
171 CHIP_NAME("IPMI OCP")
172 .enable_dev = enable_dev,
173};