mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 09:55:29 +07:00
3cd83bac48
It was being done in two different places now that hard-coded devices use platform devices, and it's about to be three with hotmod switching to platform devices. So put the code in one place. This required some rework on some interfaces to make the type space clean. Signed-off-by: Corey Minyard <cminyard@mvista.com>
122 lines
2.6 KiB
C
122 lines
2.6 KiB
C
// 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, 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->type == SI_BT)
|
|
size = 3;
|
|
else if (p->type == SI_TYPE_INVALID)
|
|
size = 0;
|
|
else
|
|
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);
|
|
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 = platform_device_add_properties(pdev, pr);
|
|
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);
|