.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
---|
2 | 2 | |
---|
| 3 | +#define pr_fmt(fmt) "ipmi_hardcode: " fmt |
---|
| 4 | + |
---|
3 | 5 | #include <linux/moduleparam.h> |
---|
4 | 6 | #include <linux/platform_device.h> |
---|
5 | 7 | #include "ipmi_si.h" |
---|
| 8 | +#include "ipmi_plat_data.h" |
---|
6 | 9 | |
---|
7 | | -#define PFX "ipmi_hardcode: " |
---|
8 | 10 | /* |
---|
9 | 11 | * There can be 4 IO ports passed in (with or without IRQs), 4 addresses, |
---|
10 | 12 | * a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS. |
---|
.. | .. |
---|
72 | 74 | " overridden by this parm. This is an array indexed" |
---|
73 | 75 | " by interface number."); |
---|
74 | 76 | |
---|
75 | | -static struct platform_device *ipmi_hc_pdevs[SI_MAX_PARMS]; |
---|
76 | | - |
---|
77 | 77 | static void __init ipmi_hardcode_init_one(const char *si_type_str, |
---|
78 | 78 | unsigned int i, |
---|
79 | 79 | unsigned long addr, |
---|
80 | | - unsigned int flags) |
---|
| 80 | + enum ipmi_addr_space addr_space) |
---|
81 | 81 | { |
---|
82 | | - struct platform_device *pdev; |
---|
83 | | - unsigned int num_r = 1, size; |
---|
84 | | - struct resource r[4]; |
---|
85 | | - struct property_entry p[6]; |
---|
86 | | - enum si_type si_type; |
---|
87 | | - unsigned int regspacing, regsize; |
---|
88 | | - int rv; |
---|
| 82 | + struct ipmi_plat_data p; |
---|
89 | 83 | |
---|
90 | | - memset(p, 0, sizeof(p)); |
---|
91 | | - memset(r, 0, sizeof(r)); |
---|
| 84 | + memset(&p, 0, sizeof(p)); |
---|
92 | 85 | |
---|
| 86 | + p.iftype = IPMI_PLAT_IF_SI; |
---|
93 | 87 | if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) { |
---|
94 | | - size = 2; |
---|
95 | | - si_type = SI_KCS; |
---|
| 88 | + p.type = SI_KCS; |
---|
96 | 89 | } else if (strcmp(si_type_str, "smic") == 0) { |
---|
97 | | - size = 2; |
---|
98 | | - si_type = SI_SMIC; |
---|
| 90 | + p.type = SI_SMIC; |
---|
99 | 91 | } else if (strcmp(si_type_str, "bt") == 0) { |
---|
100 | | - size = 3; |
---|
101 | | - si_type = SI_BT; |
---|
| 92 | + p.type = SI_BT; |
---|
102 | 93 | } else if (strcmp(si_type_str, "invalid") == 0) { |
---|
103 | 94 | /* |
---|
104 | 95 | * Allow a firmware-specified interface to be |
---|
105 | 96 | * disabled. |
---|
106 | 97 | */ |
---|
107 | | - size = 1; |
---|
108 | | - si_type = SI_TYPE_INVALID; |
---|
| 98 | + p.type = SI_TYPE_INVALID; |
---|
109 | 99 | } else { |
---|
110 | 100 | pr_warn("Interface type specified for interface %d, was invalid: %s\n", |
---|
111 | 101 | i, si_type_str); |
---|
112 | 102 | return; |
---|
113 | 103 | } |
---|
114 | 104 | |
---|
115 | | - regsize = regsizes[i]; |
---|
116 | | - if (regsize == 0) |
---|
117 | | - regsize = DEFAULT_REGSIZE; |
---|
| 105 | + p.regsize = regsizes[i]; |
---|
| 106 | + p.slave_addr = slave_addrs[i]; |
---|
| 107 | + p.addr_source = SI_HARDCODED; |
---|
| 108 | + p.regshift = regshifts[i]; |
---|
| 109 | + p.regsize = regsizes[i]; |
---|
| 110 | + p.addr = addr; |
---|
| 111 | + p.space = addr_space; |
---|
118 | 112 | |
---|
119 | | - p[0] = PROPERTY_ENTRY_U8("ipmi-type", si_type); |
---|
120 | | - p[1] = PROPERTY_ENTRY_U8("slave-addr", slave_addrs[i]); |
---|
121 | | - p[2] = PROPERTY_ENTRY_U8("addr-source", SI_HARDCODED); |
---|
122 | | - p[3] = PROPERTY_ENTRY_U8("reg-shift", regshifts[i]); |
---|
123 | | - p[4] = PROPERTY_ENTRY_U8("reg-size", regsize); |
---|
124 | | - /* Last entry must be left NULL to terminate it. */ |
---|
125 | | - |
---|
126 | | - /* |
---|
127 | | - * Register spacing is derived from the resources in |
---|
128 | | - * the IPMI platform code. |
---|
129 | | - */ |
---|
130 | | - regspacing = regspacings[i]; |
---|
131 | | - if (regspacing == 0) |
---|
132 | | - regspacing = regsize; |
---|
133 | | - |
---|
134 | | - r[0].start = addr; |
---|
135 | | - r[0].end = r[0].start + regsize - 1; |
---|
136 | | - r[0].name = "IPMI Address 1"; |
---|
137 | | - r[0].flags = flags; |
---|
138 | | - |
---|
139 | | - if (size > 1) { |
---|
140 | | - r[1].start = r[0].start + regspacing; |
---|
141 | | - r[1].end = r[1].start + regsize - 1; |
---|
142 | | - r[1].name = "IPMI Address 2"; |
---|
143 | | - r[1].flags = flags; |
---|
144 | | - num_r++; |
---|
145 | | - } |
---|
146 | | - |
---|
147 | | - if (size > 2) { |
---|
148 | | - r[2].start = r[1].start + regspacing; |
---|
149 | | - r[2].end = r[2].start + regsize - 1; |
---|
150 | | - r[2].name = "IPMI Address 3"; |
---|
151 | | - r[2].flags = flags; |
---|
152 | | - num_r++; |
---|
153 | | - } |
---|
154 | | - |
---|
155 | | - if (irqs[i]) { |
---|
156 | | - r[num_r].start = irqs[i]; |
---|
157 | | - r[num_r].end = irqs[i]; |
---|
158 | | - r[num_r].name = "IPMI IRQ"; |
---|
159 | | - r[num_r].flags = IORESOURCE_IRQ; |
---|
160 | | - num_r++; |
---|
161 | | - } |
---|
162 | | - |
---|
163 | | - pdev = platform_device_alloc("hardcode-ipmi-si", i); |
---|
164 | | - if (!pdev) { |
---|
165 | | - pr_err("Error allocating IPMI platform device %d\n", i); |
---|
166 | | - return; |
---|
167 | | - } |
---|
168 | | - |
---|
169 | | - rv = platform_device_add_resources(pdev, r, num_r); |
---|
170 | | - if (rv) { |
---|
171 | | - dev_err(&pdev->dev, |
---|
172 | | - "Unable to add hard-code resources: %d\n", rv); |
---|
173 | | - goto err; |
---|
174 | | - } |
---|
175 | | - |
---|
176 | | - rv = platform_device_add_properties(pdev, p); |
---|
177 | | - if (rv) { |
---|
178 | | - dev_err(&pdev->dev, |
---|
179 | | - "Unable to add hard-code properties: %d\n", rv); |
---|
180 | | - goto err; |
---|
181 | | - } |
---|
182 | | - |
---|
183 | | - rv = platform_device_add(pdev); |
---|
184 | | - if (rv) { |
---|
185 | | - dev_err(&pdev->dev, |
---|
186 | | - "Unable to add hard-code device: %d\n", rv); |
---|
187 | | - goto err; |
---|
188 | | - } |
---|
189 | | - |
---|
190 | | - ipmi_hc_pdevs[i] = pdev; |
---|
191 | | - return; |
---|
192 | | - |
---|
193 | | -err: |
---|
194 | | - platform_device_put(pdev); |
---|
| 113 | + ipmi_platform_add("hardcode-ipmi-si", i, &p); |
---|
195 | 114 | } |
---|
196 | 115 | |
---|
197 | 116 | void __init ipmi_hardcode_init(void) |
---|
.. | .. |
---|
220 | 139 | for (i = 0; i < SI_MAX_PARMS; i++) { |
---|
221 | 140 | if (i < num_ports && ports[i]) |
---|
222 | 141 | ipmi_hardcode_init_one(si_type[i], i, ports[i], |
---|
223 | | - IORESOURCE_IO); |
---|
| 142 | + IPMI_IO_ADDR_SPACE); |
---|
224 | 143 | if (i < num_addrs && addrs[i]) |
---|
225 | 144 | ipmi_hardcode_init_one(si_type[i], i, addrs[i], |
---|
226 | | - IORESOURCE_MEM); |
---|
| 145 | + IPMI_MEM_ADDR_SPACE); |
---|
227 | 146 | } |
---|
228 | 147 | } |
---|
229 | 148 | |
---|
| 149 | + |
---|
230 | 150 | void ipmi_si_hardcode_exit(void) |
---|
231 | 151 | { |
---|
232 | | - unsigned int i; |
---|
233 | | - |
---|
234 | | - for (i = 0; i < SI_MAX_PARMS; i++) { |
---|
235 | | - if (ipmi_hc_pdevs[i]) |
---|
236 | | - platform_device_unregister(ipmi_hc_pdevs[i]); |
---|
237 | | - } |
---|
| 152 | + ipmi_remove_platform_device_by_name("hardcode-ipmi-si"); |
---|
238 | 153 | } |
---|
239 | 154 | |
---|
240 | 155 | /* |
---|
241 | 156 | * Returns true of the given address exists as a hardcoded address, |
---|
242 | 157 | * false if not. |
---|
243 | 158 | */ |
---|
244 | | -int ipmi_si_hardcode_match(int addr_type, unsigned long addr) |
---|
| 159 | +int ipmi_si_hardcode_match(int addr_space, unsigned long addr) |
---|
245 | 160 | { |
---|
246 | 161 | unsigned int i; |
---|
247 | 162 | |
---|
248 | | - if (addr_type == IPMI_IO_ADDR_SPACE) { |
---|
| 163 | + if (addr_space == IPMI_IO_ADDR_SPACE) { |
---|
249 | 164 | for (i = 0; i < num_ports; i++) { |
---|
250 | 165 | if (ports[i] == addr) |
---|
251 | 166 | return 1; |
---|