brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · 747b51a Raw
125 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3/*4 * Add an IPMI platform device.5 */6 7#include <linux/platform_device.h>8#include "ipmi_plat_data.h"9#include "ipmi_si.h"10 11struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,12					  struct ipmi_plat_data *p)13{14	struct platform_device *pdev;15	unsigned int num_r = 1, size = 0, pidx = 0;16	struct resource r[4];17	struct property_entry pr[6];18	u32 flags;19	int rv;20 21	memset(pr, 0, sizeof(pr));22	memset(r, 0, sizeof(r));23 24	if (p->iftype == IPMI_PLAT_IF_SI) {25		if (p->type == SI_BT)26			size = 3;27		else if (p->type != SI_TYPE_INVALID)28			size = 2;29 30		if (p->regsize == 0)31			p->regsize = DEFAULT_REGSIZE;32		if (p->regspacing == 0)33			p->regspacing = p->regsize;34 35		pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);36	} else if (p->iftype == IPMI_PLAT_IF_SSIF) {37		pr[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", p->addr);38	}39 40	if (p->slave_addr)41		pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);42	pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);43	if (p->regshift)44		pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift);45	pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize);46	/* Last entry must be left NULL to terminate it. */47 48	pdev = platform_device_alloc(name, inst);49	if (!pdev) {50		pr_err("Error allocating IPMI platform device %s.%d\n",51		       name, inst);52		return NULL;53	}54 55	if (size == 0)56		/* An invalid or SSIF interface, no resources. */57		goto add_properties;58 59	/*60	 * Register spacing is derived from the resources in61	 * the IPMI platform code.62	 */63 64	if (p->space == IPMI_IO_ADDR_SPACE)65		flags = IORESOURCE_IO;66	else67		flags = IORESOURCE_MEM;68 69	r[0].start = p->addr;70	r[0].end = r[0].start + p->regsize - 1;71	r[0].name = "IPMI Address 1";72	r[0].flags = flags;73 74	if (size > 1) {75		r[1].start = r[0].start + p->regspacing;76		r[1].end = r[1].start + p->regsize - 1;77		r[1].name = "IPMI Address 2";78		r[1].flags = flags;79		num_r++;80	}81 82	if (size > 2) {83		r[2].start = r[1].start + p->regspacing;84		r[2].end = r[2].start + p->regsize - 1;85		r[2].name = "IPMI Address 3";86		r[2].flags = flags;87		num_r++;88	}89 90	if (p->irq) {91		r[num_r].start = p->irq;92		r[num_r].end = p->irq;93		r[num_r].name = "IPMI IRQ";94		r[num_r].flags = IORESOURCE_IRQ;95		num_r++;96	}97 98	rv = platform_device_add_resources(pdev, r, num_r);99	if (rv) {100		dev_err(&pdev->dev,101			"Unable to add hard-code resources: %d\n", rv);102		goto err;103	}104 add_properties:105	rv = device_create_managed_software_node(&pdev->dev, pr, NULL);106	if (rv) {107		dev_err(&pdev->dev,108			"Unable to add hard-code properties: %d\n", rv);109		goto err;110	}111 112	rv = platform_device_add(pdev);113	if (rv) {114		dev_err(&pdev->dev,115			"Unable to add hard-code device: %d\n", rv);116		goto err;117	}118	return pdev;119 120err:121	platform_device_put(pdev);122	return NULL;123}124EXPORT_SYMBOL(ipmi_platform_add);125