123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // 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);
|