Merge tag 'gvt-fixes-2019-03-21' of https://github.com/intel/gvt-linux into drm-intel...
[linux-2.6-microblaze.git] / drivers / char / ipmi / ipmi_plat_data.c
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
11 struct 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, 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->type == SI_BT)
25                 size = 3;
26         else if (p->type == SI_TYPE_INVALID)
27                 size = 0;
28         else
29                 size = 2;
30
31         if (p->regsize == 0)
32                 p->regsize = DEFAULT_REGSIZE;
33         if (p->regspacing == 0)
34                 p->regspacing = p->regsize;
35
36         pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);
37         if (p->slave_addr)
38                 pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);
39         pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);
40         if (p->regshift)
41                 pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift);
42         pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize);
43         /* Last entry must be left NULL to terminate it. */
44
45         pdev = platform_device_alloc(name, inst);
46         if (!pdev) {
47                 pr_err("Error allocating IPMI platform device %s.%d\n",
48                        name, inst);
49                 return NULL;
50         }
51
52         if (size == 0)
53                 /* An invalid or SSIF interface, no resources. */
54                 goto add_properties;
55
56         /*
57          * Register spacing is derived from the resources in
58          * the IPMI platform code.
59          */
60
61         if (p->space == IPMI_IO_ADDR_SPACE)
62                 flags = IORESOURCE_IO;
63         else
64                 flags = IORESOURCE_MEM;
65
66         r[0].start = p->addr;
67         r[0].end = r[0].start + p->regsize - 1;
68         r[0].name = "IPMI Address 1";
69         r[0].flags = flags;
70
71         if (size > 1) {
72                 r[1].start = r[0].start + p->regspacing;
73                 r[1].end = r[1].start + p->regsize - 1;
74                 r[1].name = "IPMI Address 2";
75                 r[1].flags = flags;
76                 num_r++;
77         }
78
79         if (size > 2) {
80                 r[2].start = r[1].start + p->regspacing;
81                 r[2].end = r[2].start + p->regsize - 1;
82                 r[2].name = "IPMI Address 3";
83                 r[2].flags = flags;
84                 num_r++;
85         }
86
87         if (p->irq) {
88                 r[num_r].start = p->irq;
89                 r[num_r].end = p->irq;
90                 r[num_r].name = "IPMI IRQ";
91                 r[num_r].flags = IORESOURCE_IRQ;
92                 num_r++;
93         }
94
95         rv = platform_device_add_resources(pdev, r, num_r);
96         if (rv) {
97                 dev_err(&pdev->dev,
98                         "Unable to add hard-code resources: %d\n", rv);
99                 goto err;
100         }
101  add_properties:
102         rv = platform_device_add_properties(pdev, pr);
103         if (rv) {
104                 dev_err(&pdev->dev,
105                         "Unable to add hard-code properties: %d\n", rv);
106                 goto err;
107         }
108
109         rv = platform_device_add(pdev);
110         if (rv) {
111                 dev_err(&pdev->dev,
112                         "Unable to add hard-code device: %d\n", rv);
113                 goto err;
114         }
115         return pdev;
116
117 err:
118         platform_device_put(pdev);
119         return NULL;
120 }
121 EXPORT_SYMBOL(ipmi_platform_add);