124 lines · 2.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0+ /* * Add an IPMI platform device. */ #include <linux/platform_device.h>#include "ipmi_plat_data.h"#include "ipmi_si.h" struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,					  struct ipmi_plat_data *p){	struct platform_device *pdev;	unsigned int num_r = 1, size = 0, pidx = 0;	struct resource r[4];	struct property_entry pr[6];	u32 flags;	int rv; 	memset(pr, 0, sizeof(pr));	memset(r, 0, sizeof(r)); 	if (p->iftype == IPMI_PLAT_IF_SI) {		if (p->type == SI_BT)			size = 3;		else if (p->type != SI_TYPE_INVALID)			size = 2; 		if (p->regsize == 0)			p->regsize = DEFAULT_REGSIZE;		if (p->regspacing == 0)			p->regspacing = p->regsize; 		pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);	} else if (p->iftype == IPMI_PLAT_IF_SSIF) {		pr[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", p->addr);	} 	if (p->slave_addr)		pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);	pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);	if (p->regshift)		pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift);	pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize);	/* Last entry must be left NULL to terminate it. */ 	pdev = platform_device_alloc(name, inst);	if (!pdev) {		pr_err("Error allocating IPMI platform device %s.%d\n",		       name, inst);		return NULL;	} 	if (size == 0)		/* An invalid or SSIF interface, no resources. */		goto add_properties; 	/*	 * Register spacing is derived from the resources in	 * the IPMI platform code.	 */ 	if (p->space == IPMI_IO_ADDR_SPACE)		flags = IORESOURCE_IO;	else		flags = IORESOURCE_MEM; 	r[0].start = p->addr;	r[0].end = r[0].start + p->regsize - 1;	r[0].name = "IPMI Address 1";	r[0].flags = flags; 	if (size > 1) {		r[1].start = r[0].start + p->regspacing;		r[1].end = r[1].start + p->regsize - 1;		r[1].name = "IPMI Address 2";		r[1].flags = flags;		num_r++;	} 	if (size > 2) {		r[2].start = r[1].start + p->regspacing;		r[2].end = r[2].start + p->regsize - 1;		r[2].name = "IPMI Address 3";		r[2].flags = flags;		num_r++;	} 	if (p->irq) {		r[num_r].start = p->irq;		r[num_r].end = p->irq;		r[num_r].name = "IPMI IRQ";		r[num_r].flags = IORESOURCE_IRQ;		num_r++;	} 	rv = platform_device_add_resources(pdev, r, num_r);	if (rv) {		dev_err(&pdev->dev,			"Unable to add hard-code resources: %d\n", rv);		goto err;	} add_properties:	rv = device_create_managed_software_node(&pdev->dev, pr, NULL);	if (rv) {		dev_err(&pdev->dev,			"Unable to add hard-code properties: %d\n", rv);		goto err;	} 	rv = platform_device_add(pdev);	if (rv) {		dev_err(&pdev->dev,			"Unable to add hard-code device: %d\n", rv);		goto err;	}	return pdev; err:	platform_device_put(pdev);	return NULL;}EXPORT_SYMBOL(ipmi_platform_add);