xref: /linux/drivers/char/ipmi/ipmi_si_platform.c (revision bfd5bb6f90af092aa345b15cd78143956a13c2a8)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * ipmi_si_platform.c
4  *
5  * Handling for platform devices in IPMI (ACPI, OF, and things
6  * coming from the platform.
7  */
8 #include <linux/types.h>
9 #include <linux/module.h>
10 #include <linux/of_device.h>
11 #include <linux/of_platform.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/acpi.h>
15 #include "ipmi_si.h"
16 #include "ipmi_dmi.h"
17 
18 #define PFX "ipmi_platform: "
19 
20 static bool si_tryplatform = true;
21 #ifdef CONFIG_ACPI
22 static bool          si_tryacpi = true;
23 #endif
24 #ifdef CONFIG_OF
25 static bool          si_tryopenfirmware = true;
26 #endif
27 #ifdef CONFIG_DMI
28 static bool          si_trydmi = true;
29 #else
30 static bool          si_trydmi = false;
31 #endif
32 
33 module_param_named(tryplatform, si_tryplatform, bool, 0);
34 MODULE_PARM_DESC(tryplatform, "Setting this to zero will disable the"
35 		 " default scan of the interfaces identified via platform"
36 		 " interfaces besides ACPI, OpenFirmware, and DMI");
37 #ifdef CONFIG_ACPI
38 module_param_named(tryacpi, si_tryacpi, bool, 0);
39 MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the"
40 		 " default scan of the interfaces identified via ACPI");
41 #endif
42 #ifdef CONFIG_OF
43 module_param_named(tryopenfirmware, si_tryopenfirmware, bool, 0);
44 MODULE_PARM_DESC(tryopenfirmware, "Setting this to zero will disable the"
45 		 " default scan of the interfaces identified via OpenFirmware");
46 #endif
47 #ifdef CONFIG_DMI
48 module_param_named(trydmi, si_trydmi, bool, 0);
49 MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the"
50 		 " default scan of the interfaces identified via DMI");
51 #endif
52 
53 #ifdef CONFIG_ACPI
54 /* For GPE-type interrupts. */
55 static u32 ipmi_acpi_gpe(acpi_handle gpe_device,
56 	u32 gpe_number, void *context)
57 {
58 	struct si_sm_io *io = context;
59 
60 	ipmi_si_irq_handler(io->irq, io->irq_handler_data);
61 	return ACPI_INTERRUPT_HANDLED;
62 }
63 
64 static void acpi_gpe_irq_cleanup(struct si_sm_io *io)
65 {
66 	if (!io->irq)
67 		return;
68 
69 	ipmi_irq_start_cleanup(io);
70 	acpi_remove_gpe_handler(NULL, io->irq, &ipmi_acpi_gpe);
71 }
72 
73 static int acpi_gpe_irq_setup(struct si_sm_io *io)
74 {
75 	acpi_status status;
76 
77 	if (!io->irq)
78 		return 0;
79 
80 	status = acpi_install_gpe_handler(NULL,
81 					  io->irq,
82 					  ACPI_GPE_LEVEL_TRIGGERED,
83 					  &ipmi_acpi_gpe,
84 					  io);
85 	if (status != AE_OK) {
86 		dev_warn(io->dev,
87 			 "Unable to claim ACPI GPE %d, running polled\n",
88 			 io->irq);
89 		io->irq = 0;
90 		return -EINVAL;
91 	} else {
92 		io->irq_cleanup = acpi_gpe_irq_cleanup;
93 		ipmi_irq_finish_setup(io);
94 		dev_info(io->dev, "Using ACPI GPE %d\n", io->irq);
95 		return 0;
96 	}
97 }
98 #endif
99 
100 static struct resource *
101 ipmi_get_info_from_resources(struct platform_device *pdev,
102 			     struct si_sm_io *io)
103 {
104 	struct resource *res, *res_second;
105 
106 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
107 	if (res) {
108 		io->addr_type = IPMI_IO_ADDR_SPACE;
109 	} else {
110 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
111 		if (res)
112 			io->addr_type = IPMI_MEM_ADDR_SPACE;
113 	}
114 	if (!res) {
115 		dev_err(&pdev->dev, "no I/O or memory address\n");
116 		return NULL;
117 	}
118 	io->addr_data = res->start;
119 
120 	io->regspacing = DEFAULT_REGSPACING;
121 	res_second = platform_get_resource(pdev,
122 			       (io->addr_type == IPMI_IO_ADDR_SPACE) ?
123 					IORESOURCE_IO : IORESOURCE_MEM,
124 			       1);
125 	if (res_second) {
126 		if (res_second->start > io->addr_data)
127 			io->regspacing = res_second->start - io->addr_data;
128 	}
129 	io->regsize = DEFAULT_REGSIZE;
130 	io->regshift = 0;
131 
132 	return res;
133 }
134 
135 static int platform_ipmi_probe(struct platform_device *pdev)
136 {
137 	struct si_sm_io io;
138 	u8 type, slave_addr, addr_source;
139 	int rv;
140 
141 	rv = device_property_read_u8(&pdev->dev, "addr-source", &addr_source);
142 	if (rv)
143 		addr_source = SI_PLATFORM;
144 	if (addr_source >= SI_LAST)
145 		return -EINVAL;
146 
147 	if (addr_source == SI_SMBIOS) {
148 		if (!si_trydmi)
149 			return -ENODEV;
150 	} else {
151 		if (!si_tryplatform)
152 			return -ENODEV;
153 	}
154 
155 	rv = device_property_read_u8(&pdev->dev, "ipmi-type", &type);
156 	if (rv)
157 		return -ENODEV;
158 
159 	memset(&io, 0, sizeof(io));
160 	io.addr_source = addr_source;
161 	dev_info(&pdev->dev, PFX "probing via %s\n",
162 		 ipmi_addr_src_to_str(addr_source));
163 
164 	switch (type) {
165 	case SI_KCS:
166 	case SI_SMIC:
167 	case SI_BT:
168 		io.si_type = type;
169 		break;
170 	default:
171 		dev_err(&pdev->dev, "ipmi-type property is invalid\n");
172 		return -EINVAL;
173 	}
174 
175 	if (!ipmi_get_info_from_resources(pdev, &io))
176 		return -EINVAL;
177 
178 	rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
179 	if (rv) {
180 		dev_warn(&pdev->dev, "device has no slave-addr property\n");
181 		io.slave_addr = 0x20;
182 	} else {
183 		io.slave_addr = slave_addr;
184 	}
185 
186 	io.irq = platform_get_irq(pdev, 0);
187 	if (io.irq > 0)
188 		io.irq_setup = ipmi_std_irq_setup;
189 	else
190 		io.irq = 0;
191 
192 	io.dev = &pdev->dev;
193 
194 	pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n",
195 		(io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
196 		io.addr_data, io.regsize, io.regspacing, io.irq);
197 
198 	ipmi_si_add_smi(&io);
199 
200 	return 0;
201 }
202 
203 #ifdef CONFIG_OF
204 static const struct of_device_id of_ipmi_match[] = {
205 	{ .type = "ipmi", .compatible = "ipmi-kcs",
206 	  .data = (void *)(unsigned long) SI_KCS },
207 	{ .type = "ipmi", .compatible = "ipmi-smic",
208 	  .data = (void *)(unsigned long) SI_SMIC },
209 	{ .type = "ipmi", .compatible = "ipmi-bt",
210 	  .data = (void *)(unsigned long) SI_BT },
211 	{},
212 };
213 MODULE_DEVICE_TABLE(of, of_ipmi_match);
214 
215 static int of_ipmi_probe(struct platform_device *pdev)
216 {
217 	const struct of_device_id *match;
218 	struct si_sm_io io;
219 	struct resource resource;
220 	const __be32 *regsize, *regspacing, *regshift;
221 	struct device_node *np = pdev->dev.of_node;
222 	int ret;
223 	int proplen;
224 
225 	if (!si_tryopenfirmware)
226 		return -ENODEV;
227 
228 	dev_info(&pdev->dev, "probing via device tree\n");
229 
230 	match = of_match_device(of_ipmi_match, &pdev->dev);
231 	if (!match)
232 		return -ENODEV;
233 
234 	if (!of_device_is_available(np))
235 		return -EINVAL;
236 
237 	ret = of_address_to_resource(np, 0, &resource);
238 	if (ret) {
239 		dev_warn(&pdev->dev, PFX "invalid address from OF\n");
240 		return ret;
241 	}
242 
243 	regsize = of_get_property(np, "reg-size", &proplen);
244 	if (regsize && proplen != 4) {
245 		dev_warn(&pdev->dev, PFX "invalid regsize from OF\n");
246 		return -EINVAL;
247 	}
248 
249 	regspacing = of_get_property(np, "reg-spacing", &proplen);
250 	if (regspacing && proplen != 4) {
251 		dev_warn(&pdev->dev, PFX "invalid regspacing from OF\n");
252 		return -EINVAL;
253 	}
254 
255 	regshift = of_get_property(np, "reg-shift", &proplen);
256 	if (regshift && proplen != 4) {
257 		dev_warn(&pdev->dev, PFX "invalid regshift from OF\n");
258 		return -EINVAL;
259 	}
260 
261 	memset(&io, 0, sizeof(io));
262 	io.si_type	= (enum si_type) match->data;
263 	io.addr_source	= SI_DEVICETREE;
264 	io.irq_setup	= ipmi_std_irq_setup;
265 
266 	if (resource.flags & IORESOURCE_IO)
267 		io.addr_type = IPMI_IO_ADDR_SPACE;
268 	else
269 		io.addr_type = IPMI_MEM_ADDR_SPACE;
270 
271 	io.addr_data	= resource.start;
272 
273 	io.regsize	= regsize ? be32_to_cpup(regsize) : DEFAULT_REGSIZE;
274 	io.regspacing	= regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING;
275 	io.regshift	= regshift ? be32_to_cpup(regshift) : 0;
276 
277 	io.irq		= irq_of_parse_and_map(pdev->dev.of_node, 0);
278 	io.dev		= &pdev->dev;
279 
280 	dev_dbg(&pdev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n",
281 		io.addr_data, io.regsize, io.regspacing, io.irq);
282 
283 	return ipmi_si_add_smi(&io);
284 }
285 #else
286 #define of_ipmi_match NULL
287 static int of_ipmi_probe(struct platform_device *dev)
288 {
289 	return -ENODEV;
290 }
291 #endif
292 
293 #ifdef CONFIG_ACPI
294 static int find_slave_address(struct si_sm_io *io, int slave_addr)
295 {
296 #ifdef CONFIG_IPMI_DMI_DECODE
297 	if (!slave_addr) {
298 		u32 flags = IORESOURCE_IO;
299 
300 		if (io->addr_type == IPMI_MEM_ADDR_SPACE)
301 			flags = IORESOURCE_MEM;
302 
303 		slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags,
304 						     io->addr_data);
305 	}
306 #endif
307 
308 	return slave_addr;
309 }
310 
311 static int acpi_ipmi_probe(struct platform_device *pdev)
312 {
313 	struct si_sm_io io;
314 	acpi_handle handle;
315 	acpi_status status;
316 	unsigned long long tmp;
317 	struct resource *res;
318 	int rv = -EINVAL;
319 
320 	if (!si_tryacpi)
321 		return -ENODEV;
322 
323 	handle = ACPI_HANDLE(&pdev->dev);
324 	if (!handle)
325 		return -ENODEV;
326 
327 	memset(&io, 0, sizeof(io));
328 	io.addr_source = SI_ACPI;
329 	dev_info(&pdev->dev, PFX "probing via ACPI\n");
330 
331 	io.addr_info.acpi_info.acpi_handle = handle;
332 
333 	/* _IFT tells us the interface type: KCS, BT, etc */
334 	status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
335 	if (ACPI_FAILURE(status)) {
336 		dev_err(&pdev->dev,
337 			"Could not find ACPI IPMI interface type\n");
338 		goto err_free;
339 	}
340 
341 	switch (tmp) {
342 	case 1:
343 		io.si_type = SI_KCS;
344 		break;
345 	case 2:
346 		io.si_type = SI_SMIC;
347 		break;
348 	case 3:
349 		io.si_type = SI_BT;
350 		break;
351 	case 4: /* SSIF, just ignore */
352 		rv = -ENODEV;
353 		goto err_free;
354 	default:
355 		dev_info(&pdev->dev, "unknown IPMI type %lld\n", tmp);
356 		goto err_free;
357 	}
358 
359 	res = ipmi_get_info_from_resources(pdev, &io);
360 	if (!res) {
361 		rv = -EINVAL;
362 		goto err_free;
363 	}
364 
365 	/* If _GPE exists, use it; otherwise use standard interrupts */
366 	status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
367 	if (ACPI_SUCCESS(status)) {
368 		io.irq = tmp;
369 		io.irq_setup = acpi_gpe_irq_setup;
370 	} else {
371 		int irq = platform_get_irq(pdev, 0);
372 
373 		if (irq > 0) {
374 			io.irq = irq;
375 			io.irq_setup = ipmi_std_irq_setup;
376 		}
377 	}
378 
379 	io.slave_addr = find_slave_address(&io, io.slave_addr);
380 
381 	io.dev = &pdev->dev;
382 
383 	dev_info(io.dev, "%pR regsize %d spacing %d irq %d\n",
384 		 res, io.regsize, io.regspacing, io.irq);
385 
386 	return ipmi_si_add_smi(&io);
387 
388 err_free:
389 	return rv;
390 }
391 
392 static const struct acpi_device_id acpi_ipmi_match[] = {
393 	{ "IPI0001", 0 },
394 	{ },
395 };
396 MODULE_DEVICE_TABLE(acpi, acpi_ipmi_match);
397 #else
398 static int acpi_ipmi_probe(struct platform_device *dev)
399 {
400 	return -ENODEV;
401 }
402 #endif
403 
404 static int ipmi_probe(struct platform_device *pdev)
405 {
406 	if (pdev->dev.of_node && of_ipmi_probe(pdev) == 0)
407 		return 0;
408 
409 	if (acpi_ipmi_probe(pdev) == 0)
410 		return 0;
411 
412 	return platform_ipmi_probe(pdev);
413 }
414 
415 static int ipmi_remove(struct platform_device *pdev)
416 {
417 	return ipmi_si_remove_by_dev(&pdev->dev);
418 }
419 
420 struct platform_driver ipmi_platform_driver = {
421 	.driver = {
422 		.name = DEVICE_NAME,
423 		.of_match_table = of_ipmi_match,
424 		.acpi_match_table = ACPI_PTR(acpi_ipmi_match),
425 	},
426 	.probe		= ipmi_probe,
427 	.remove		= ipmi_remove,
428 };
429 
430 void ipmi_si_platform_init(void)
431 {
432 	int rv = platform_driver_register(&ipmi_platform_driver);
433 	if (rv)
434 		pr_err(PFX "Unable to register driver: %d\n", rv);
435 }
436 
437 void ipmi_si_platform_shutdown(void)
438 {
439 	platform_driver_unregister(&ipmi_platform_driver);
440 }
441