linux/drivers/char/ipmi/ipmi_plat_data.c
<<
>>
Prefs
   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 in
  61         * the IPMI platform code.
  62         */
  63
  64        if (p->space == IPMI_IO_ADDR_SPACE)
  65                flags = IORESOURCE_IO;
  66        else
  67                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 = platform_device_add_properties(pdev, pr);
 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