// SPDX-License-Identifier: GPL-2.0+ /* * Add an IPMI platform device. */ #include #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);