xref: /aosp_15_r20/external/coreboot/src/drivers/ipmi/ipmi_kcs_ops.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * Place in devicetree.cb:
5  *
6  * chip drivers/ipmi
7  *   device pnp ca2.0 on end         # IPMI KCS
8  * end
9  */
10 
11 #include <arch/io.h>
12 #include <bootstate.h>
13 #include <console/console.h>
14 #include <device/device.h>
15 #include <device/gpio.h>
16 #include <device/pnp.h>
17 #if CONFIG(HAVE_ACPI_TABLES)
18 #include <acpi/acpi.h>
19 #include <acpi/acpigen.h>
20 #endif
21 #if CONFIG(GENERATE_SMBIOS_TABLES)
22 #include <smbios.h>
23 #endif
24 #include <version.h>
25 #include <delay.h>
26 #include <timer.h>
27 #include "ipmi_if.h"
28 #include "ipmi_supermicro_oem.h"
29 #include "chip.h"
30 
31 #define IPMI_GET_DID_RETRY_MS 10000
32 
33 /* 4 bit encoding */
34 static u8 ipmi_revision_major = 0x1;
35 static u8 ipmi_revision_minor = 0x0;
36 
37 static u8 bmc_revision_major = 0x0;
38 static u8 bmc_revision_minor = 0x0;
39 
40 static struct boot_state_callback bscb_post_complete;
41 
bmc_set_post_complete_gpio_callback(void * arg)42 static void bmc_set_post_complete_gpio_callback(void *arg)
43 {
44 	struct drivers_ipmi_config *conf = arg;
45 	const struct gpio_operations *gpio_ops;
46 
47 	if (!conf || !conf->post_complete_gpio)
48 		return;
49 
50 	gpio_ops = dev_get_gpio_ops(conf->gpio_dev);
51 	if (!gpio_ops) {
52 		printk(BIOS_WARNING, "IPMI: specified gpio device is missing gpio ops!\n");
53 		return;
54 	}
55 
56 	/* Set POST Complete pin. The `invert` field controls the polarity. */
57 	gpio_ops->output(conf->post_complete_gpio, conf->post_complete_invert ^ 1);
58 
59 	printk(BIOS_DEBUG, "BMC: POST complete gpio set\n");
60 }
61 
ipmi_kcs_init(struct device * dev)62 static void ipmi_kcs_init(struct device *dev)
63 {
64 	struct ipmi_devid_rsp rsp;
65 	uint32_t man_id = 0, prod_id = 0;
66 	struct drivers_ipmi_config *conf = dev->chip_info;
67 	const struct gpio_operations *gpio_ops;
68 
69 	if (!conf) {
70 		printk(BIOS_WARNING, "IPMI: chip_info is missing! Skip init.\n");
71 		return;
72 	}
73 
74 	if (conf->bmc_jumper_gpio) {
75 		gpio_ops = dev_get_gpio_ops(conf->gpio_dev);
76 		if (!gpio_ops) {
77 			printk(BIOS_WARNING, "IPMI: gpio device is missing gpio ops!\n");
78 		} else {
79 			/* Get jumper value and set device state accordingly */
80 			dev->enabled = gpio_ops->get(conf->bmc_jumper_gpio);
81 			if (!dev->enabled)
82 				printk(BIOS_INFO, "IPMI: Disabled by jumper\n");
83 		}
84 	}
85 
86 	if (!dev->enabled)
87 		return;
88 
89 	printk(BIOS_DEBUG, "IPMI: PNP KCS 0x%x\n", dev->path.pnp.port);
90 
91 	/* Set up boot state callback for POST_COMPLETE# */
92 	if (conf->post_complete_gpio) {
93 		bscb_post_complete.callback = bmc_set_post_complete_gpio_callback;
94 		bscb_post_complete.arg = conf;
95 		boot_state_sched_on_entry(&bscb_post_complete, BS_PAYLOAD_BOOT);
96 	}
97 
98 	/* Get IPMI version for ACPI and SMBIOS */
99 	if (conf->wait_for_bmc && conf->bmc_boot_timeout) {
100 		struct stopwatch sw;
101 		stopwatch_init_msecs_expire(&sw, conf->bmc_boot_timeout * 1000);
102 		printk(BIOS_INFO, "IPMI: Waiting for BMC...\n");
103 
104 		while (!stopwatch_expired(&sw)) {
105 			if (inb(dev->path.pnp.port) != 0xff)
106 				break;
107 			mdelay(100);
108 		}
109 		if (stopwatch_expired(&sw)) {
110 			printk(BIOS_INFO, "IPMI: Waiting for BMC timed out\n");
111 			/* Don't write tables if communication failed */
112 			dev->enabled = 0;
113 			return;
114 		}
115 	}
116 
117 	if (ipmi_process_self_test_result(dev)) {
118 		/* Don't write tables if communication failed */
119 		dev->enabled = 0;
120 		return;
121 	}
122 
123 	if (!wait_ms(IPMI_GET_DID_RETRY_MS, !ipmi_get_device_id(dev, &rsp))) {
124 		printk(BIOS_ERR, "IPMI: BMC does not respond to get device id even "
125 			"after %d ms.\n", IPMI_GET_DID_RETRY_MS);
126 		dev->enabled = 0;
127 		return;
128 	}
129 
130 	/* Queried the IPMI revision from BMC */
131 	ipmi_revision_minor = IPMI_IPMI_VERSION_MINOR(rsp.ipmi_version);
132 	ipmi_revision_major = IPMI_IPMI_VERSION_MAJOR(rsp.ipmi_version);
133 
134 	bmc_revision_major = rsp.fw_rev1;
135 	bmc_revision_minor = rsp.fw_rev2;
136 
137 	memcpy(&man_id, rsp.manufacturer_id, sizeof(rsp.manufacturer_id));
138 
139 	memcpy(&prod_id, rsp.product_id, sizeof(rsp.product_id));
140 
141 	printk(BIOS_INFO, "IPMI: Found man_id 0x%06x, prod_id 0x%04x\n", man_id, prod_id);
142 
143 	printk(BIOS_INFO, "IPMI: Version %01x.%01x\n", ipmi_revision_major,
144 	       ipmi_revision_minor);
145 
146 	if (CONFIG(DRIVERS_IPMI_SUPERMICRO_OEM))
147 		supermicro_ipmi_oem(dev->path.pnp.port);
148 }
149 
150 #if CONFIG(HAVE_ACPI_TABLES)
151 static uint32_t uid_cnt = 0;
152 
153 static unsigned long
ipmi_write_acpi_tables(const struct device * dev,unsigned long current,struct acpi_rsdp * rsdp)154 ipmi_write_acpi_tables(const struct device *dev, unsigned long current,
155 		       struct acpi_rsdp *rsdp)
156 {
157 	struct drivers_ipmi_config *conf = dev->chip_info;
158 	struct acpi_spmi *spmi;
159 	s8 gpe_interrupt = -1;
160 	u32 apic_interrupt = 0;
161 	acpi_addr_t addr = {
162 		.space_id = ACPI_ADDRESS_SPACE_IO,
163 		.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS,
164 		.addrl = dev->path.pnp.port,
165 		.bit_width = 8,
166 	};
167 
168 	switch (CONFIG_IPMI_KCS_REGISTER_SPACING) {
169 	case 4:
170 		addr.bit_offset = 32;
171 		break;
172 	case 16:
173 		addr.bit_offset = 128;
174 		break;
175 	default:
176 		printk(BIOS_ERR, "IPMI: Unsupported register spacing for SPMI\n");
177 		__fallthrough;
178 	case 1:
179 		addr.bit_offset = 8;
180 		break;
181 	}
182 
183 	current = ALIGN_UP(current, 8);
184 	printk(BIOS_DEBUG, "ACPI:    * SPMI at %lx\n", current);
185 	spmi = (struct acpi_spmi *)current;
186 
187 	if (conf) {
188 		if (conf->have_gpe)
189 			gpe_interrupt = conf->gpe_interrupt;
190 		if (conf->have_apic)
191 			apic_interrupt = conf->apic_interrupt;
192 
193 		/* Use command to get UID from ipmi_ssdt */
194 		acpi_create_ipmi(dev, spmi, (ipmi_revision_major << 8) |
195 				 (ipmi_revision_minor << 4), &addr,
196 				 IPMI_INTERFACE_KCS, gpe_interrupt, apic_interrupt,
197 				 conf->uid);
198 
199 		acpi_add_table(rsdp, spmi);
200 
201 		current += spmi->header.length;
202 	} else {
203 		printk(BIOS_WARNING, "IPMI: chip_info is missing!\n");
204 	}
205 
206 	return current;
207 }
208 
ipmi_ssdt(const struct device * dev)209 static void ipmi_ssdt(const struct device *dev)
210 {
211 	const char *scope = acpi_device_scope(dev);
212 	struct drivers_ipmi_config *conf = dev->chip_info;
213 
214 	if (!scope) {
215 		printk(BIOS_ERR, "IPMI: Missing ACPI scope for %s\n",
216 		       dev_path(dev));
217 		return;
218 	}
219 
220 	if (!conf) {
221 		printk(BIOS_WARNING, "IPMI: chip_info is missing!\n");
222 		return;
223 	}
224 
225 	/* Use command to pass UID to ipmi_write_acpi_tables */
226 	conf->uid = uid_cnt++;
227 
228 	/* write SPMI device */
229 	acpigen_write_scope(scope);
230 	acpigen_write_device("SPMI");
231 	acpigen_write_name_string("_HID", "IPI0001");
232 	acpigen_write_name_unicode("_STR", "IPMI_KCS");
233 	acpigen_write_name_byte("_UID", conf->uid);
234 	acpigen_write_STA(0xf);
235 	acpigen_write_name("_CRS");
236 	acpigen_write_resourcetemplate_header();
237 	acpigen_write_io16(dev->path.pnp.port, dev->path.pnp.port, 1, 1, 1);
238 	acpigen_write_io16(dev->path.pnp.port + CONFIG_IPMI_KCS_REGISTER_SPACING,
239 			   dev->path.pnp.port + CONFIG_IPMI_KCS_REGISTER_SPACING, 1, 1, 1);
240 
241 	// FIXME: is that correct?
242 	if (conf->have_apic)
243 		acpigen_write_irq(1 << conf->apic_interrupt);
244 
245 	acpigen_write_resourcetemplate_footer();
246 
247 	acpigen_write_method("_IFT", 0);
248 	acpigen_write_return_byte(1);	// KCS
249 	acpigen_pop_len();
250 
251 	acpigen_write_method("_SRV", 0);
252 	acpigen_write_return_integer((ipmi_revision_major << 8) |
253 				     (ipmi_revision_minor << 4));
254 	acpigen_pop_len();
255 
256 	acpigen_pop_len(); /* pop device */
257 	acpigen_pop_len(); /* pop scope */
258 }
259 #endif
260 
ipmi_bmc_version(uint8_t * ipmi_bmc_major_revision,uint8_t * ipmi_bmc_minor_revision)261 void ipmi_bmc_version(uint8_t *ipmi_bmc_major_revision, uint8_t *ipmi_bmc_minor_revision)
262 {
263 	*ipmi_bmc_major_revision = bmc_revision_major;
264 	*ipmi_bmc_minor_revision = bmc_revision_minor;
265 }
266 
267 #if CONFIG(GENERATE_SMBIOS_TABLES)
ipmi_smbios_data(struct device * dev,int * handle,unsigned long * current)268 static int ipmi_smbios_data(struct device *dev, int *handle,
269 			    unsigned long *current)
270 {
271 	struct drivers_ipmi_config *conf = dev->chip_info;
272 	u8 nv_storage = 0xff;
273 	u8 i2c_address = 0;
274 	u8 register_spacing;
275 
276 	int len = 0;
277 
278 	if (conf) {
279 		if (conf->have_nv_storage)
280 			nv_storage = conf->nv_storage_device_address;
281 		i2c_address = conf->bmc_i2c_address;
282 	}
283 
284 	switch (CONFIG_IPMI_KCS_REGISTER_SPACING) {
285 	case 4:
286 		register_spacing = 1 << 6;
287 		break;
288 	case 16:
289 		register_spacing = 2 << 6;
290 		break;
291 	default:
292 		printk(BIOS_ERR, "IPMI: Unsupported register spacing for SMBIOS\n");
293 		__fallthrough;
294 	case 1:
295 		register_spacing = 0 << 6;
296 		break;
297 	}
298 
299 	// add IPMI Device Information
300 	len += smbios_write_type38(
301 		current, handle,
302 		SMBIOS_BMC_INTERFACE_KCS,
303 		ipmi_revision_minor | (ipmi_revision_major << 4),
304 		i2c_address, // I2C address
305 		nv_storage, // NV storage
306 		dev->path.pnp.port | 1, // IO interface
307 		register_spacing,
308 		0); // no IRQ
309 
310 	len += get_smbios_data(dev, handle, current);
311 
312 	return len;
313 }
314 #endif
315 
ipmi_set_resources(struct device * dev)316 static void ipmi_set_resources(struct device *dev)
317 {
318 	struct resource *res;
319 
320 	for (res = dev->resource_list; res; res = res->next) {
321 		if (!(res->flags & IORESOURCE_ASSIGNED))
322 			continue;
323 
324 		res->flags |= IORESOURCE_STORED;
325 		report_resource_stored(dev, res, "");
326 	}
327 }
328 
ipmi_read_resources(struct device * dev)329 static void ipmi_read_resources(struct device *dev)
330 {
331 	struct resource *res = new_resource(dev, 0);
332 	res->base = dev->path.pnp.port;
333 	res->size = 2;
334 	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
335 }
336 
337 static struct device_operations ops = {
338 	.read_resources   = ipmi_read_resources,
339 	.set_resources    = ipmi_set_resources,
340 	.init             = ipmi_kcs_init,
341 #if CONFIG(HAVE_ACPI_TABLES)
342 	.write_acpi_tables = ipmi_write_acpi_tables,
343 	.acpi_fill_ssdt    = ipmi_ssdt,
344 #endif
345 #if CONFIG(GENERATE_SMBIOS_TABLES)
346 	.get_smbios_data = ipmi_smbios_data,
347 #endif
348 };
349 
enable_dev(struct device * dev)350 static void enable_dev(struct device *dev)
351 {
352 	if (dev->path.type != DEVICE_PATH_PNP)
353 		printk(BIOS_ERR, "%s: Unsupported device type\n",
354 		       dev_path(dev));
355 	else if (dev->path.pnp.port & 1)
356 		printk(BIOS_ERR, "%s: Base address needs to be aligned to 2\n",
357 		       dev_path(dev));
358 	else
359 		dev->ops = &ops;
360 }
361 
362 struct chip_operations drivers_ipmi_ops = {
363 	.name = "IPMI KCS",
364 	.enable_dev = enable_dev,
365 };
366