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