14
14
#include <linux/module.h>
15
15
#include <linux/platform_device.h>
16
16
#include <linux/property.h>
17
+ #include <linux/spi/spi.h>
17
18
#include <linux/types.h>
18
19
19
20
#define IRQ_RESOURCE_TYPE GENMASK(1, 0)
20
21
#define IRQ_RESOURCE_NONE 0
21
22
#define IRQ_RESOURCE_GPIO 1
22
23
#define IRQ_RESOURCE_APIC 2
23
24
25
+ enum smi_bus_type {
26
+ SMI_I2C ,
27
+ SMI_SPI ,
28
+ SMI_AUTO_DETECT ,
29
+ };
30
+
24
31
struct smi_instance {
25
32
const char * type ;
26
33
unsigned int flags ;
27
34
int irq_idx ;
28
35
};
29
36
37
+ struct smi_node {
38
+ enum smi_bus_type bus_type ;
39
+ struct smi_instance instances [];
40
+ };
41
+
30
42
struct smi {
31
43
int i2c_num ;
44
+ int spi_num ;
32
45
struct i2c_client * * i2c_devs ;
46
+ struct spi_device * * spi_devs ;
33
47
};
34
48
35
49
static int smi_get_irq (struct platform_device * pdev , struct acpi_device * adev ,
@@ -59,6 +73,94 @@ static void smi_devs_unregister(struct smi *smi)
59
73
{
60
74
while (smi -> i2c_num > 0 )
61
75
i2c_unregister_device (smi -> i2c_devs [-- smi -> i2c_num ]);
76
+
77
+ while (smi -> spi_num > 0 )
78
+ spi_unregister_device (smi -> spi_devs [-- smi -> spi_num ]);
79
+ }
80
+
81
+ /**
82
+ * smi_spi_probe - Instantiate multiple SPI devices from inst array
83
+ * @pdev: Platform device
84
+ * @adev: ACPI device
85
+ * @smi: Internal struct for Serial multi instantiate driver
86
+ * @inst_array: Array of instances to probe
87
+ *
88
+ * Returns the number of SPI devices instantiate, Zero if none is found or a negative error code.
89
+ */
90
+ static int smi_spi_probe (struct platform_device * pdev , struct acpi_device * adev , struct smi * smi ,
91
+ const struct smi_instance * inst_array )
92
+ {
93
+ struct device * dev = & pdev -> dev ;
94
+ struct spi_controller * ctlr ;
95
+ struct spi_device * spi_dev ;
96
+ char name [50 ];
97
+ int i , ret , count ;
98
+
99
+ ret = acpi_spi_count_resources (adev );
100
+ if (ret < 0 )
101
+ return ret ;
102
+ else if (!ret )
103
+ return - ENODEV ;
104
+
105
+ count = ret ;
106
+
107
+ smi -> spi_devs = devm_kcalloc (dev , count , sizeof (* smi -> spi_devs ), GFP_KERNEL );
108
+ if (!smi -> spi_devs )
109
+ return - ENOMEM ;
110
+
111
+ for (i = 0 ; i < count && inst_array [i ].type ; i ++ ) {
112
+
113
+ spi_dev = acpi_spi_device_alloc (NULL , adev , i );
114
+ if (IS_ERR (spi_dev )) {
115
+ ret = PTR_ERR (spi_dev );
116
+ dev_err_probe (dev , ret , "failed to allocate SPI device %s from ACPI: %d\n" ,
117
+ dev_name (& adev -> dev ), ret );
118
+ goto error ;
119
+ }
120
+
121
+ ctlr = spi_dev -> controller ;
122
+
123
+ strscpy (spi_dev -> modalias , inst_array [i ].type , sizeof (spi_dev -> modalias ));
124
+
125
+ ret = smi_get_irq (pdev , adev , & inst_array [i ]);
126
+ if (ret < 0 ) {
127
+ spi_dev_put (spi_dev );
128
+ goto error ;
129
+ }
130
+ spi_dev -> irq = ret ;
131
+
132
+ snprintf (name , sizeof (name ), "%s-%s-%s.%d" , dev_name (& ctlr -> dev ), dev_name (dev ),
133
+ inst_array [i ].type , i );
134
+ spi_dev -> dev .init_name = name ;
135
+
136
+ ret = spi_add_device (spi_dev );
137
+ if (ret ) {
138
+ dev_err_probe (& ctlr -> dev , ret ,
139
+ "failed to add SPI device %s from ACPI: %d\n" ,
140
+ dev_name (& adev -> dev ), ret );
141
+ spi_dev_put (spi_dev );
142
+ goto error ;
143
+ }
144
+
145
+ dev_dbg (dev , "SPI device %s using chip select %u" , name , spi_dev -> chip_select );
146
+
147
+ smi -> spi_devs [i ] = spi_dev ;
148
+ smi -> spi_num ++ ;
149
+ }
150
+
151
+ if (smi -> spi_num < count ) {
152
+ dev_dbg (dev , "Error finding driver, idx %d\n" , i );
153
+ ret = - ENODEV ;
154
+ goto error ;
155
+ }
156
+
157
+ dev_info (dev , "Instantiated %d SPI devices.\n" , smi -> spi_num );
158
+
159
+ return 0 ;
160
+ error :
161
+ smi_devs_unregister (smi );
162
+
163
+ return ret ;
62
164
}
63
165
64
166
/**
@@ -126,17 +228,17 @@ static int smi_i2c_probe(struct platform_device *pdev, struct acpi_device *adev,
126
228
127
229
static int smi_probe (struct platform_device * pdev )
128
230
{
129
- const struct smi_instance * inst_array ;
130
231
struct device * dev = & pdev -> dev ;
232
+ const struct smi_node * node ;
131
233
struct acpi_device * adev ;
132
234
struct smi * smi ;
133
235
134
236
adev = ACPI_COMPANION (dev );
135
237
if (!adev )
136
238
return - ENODEV ;
137
239
138
- inst_array = device_get_match_data (dev );
139
- if (!inst_array ) {
240
+ node = device_get_match_data (dev );
241
+ if (!node ) {
140
242
dev_dbg (dev , "Error ACPI match data is missing\n" );
141
243
return - ENODEV ;
142
244
}
@@ -147,7 +249,21 @@ static int smi_probe(struct platform_device *pdev)
147
249
148
250
platform_set_drvdata (pdev , smi );
149
251
150
- return smi_i2c_probe (pdev , adev , smi , inst_array );
252
+ switch (node -> bus_type ) {
253
+ case SMI_I2C :
254
+ return smi_i2c_probe (pdev , adev , smi , node -> instances );
255
+ case SMI_SPI :
256
+ return smi_spi_probe (pdev , adev , smi , node -> instances );
257
+ case SMI_AUTO_DETECT :
258
+ if (i2c_acpi_client_count (adev ) > 0 )
259
+ return smi_i2c_probe (pdev , adev , smi , node -> instances );
260
+ else
261
+ return smi_spi_probe (pdev , adev , smi , node -> instances );
262
+ default :
263
+ return - EINVAL ;
264
+ }
265
+
266
+ return 0 ; /* never reached */
151
267
}
152
268
153
269
static int smi_remove (struct platform_device * pdev )
@@ -159,37 +275,46 @@ static int smi_remove(struct platform_device *pdev)
159
275
return 0 ;
160
276
}
161
277
162
- static const struct smi_instance bsg1160_data [] = {
163
- { "bmc150_accel" , IRQ_RESOURCE_GPIO , 0 },
164
- { "bmc150_magn" },
165
- { "bmg160" },
166
- {}
278
+ static const struct smi_node bsg1160_data = {
279
+ .instances = {
280
+ { "bmc150_accel" , IRQ_RESOURCE_GPIO , 0 },
281
+ { "bmc150_magn" },
282
+ { "bmg160" },
283
+ {}
284
+ },
285
+ .bus_type = SMI_I2C ,
167
286
};
168
287
169
- static const struct smi_instance bsg2150_data [] = {
170
- { "bmc150_accel" , IRQ_RESOURCE_GPIO , 0 },
171
- { "bmc150_magn" },
172
- /* The resources describe a 3th client, but it is not really there. */
173
- { "bsg2150_dummy_dev" },
174
- {}
288
+ static const struct smi_node bsg2150_data = {
289
+ .instances = {
290
+ { "bmc150_accel" , IRQ_RESOURCE_GPIO , 0 },
291
+ { "bmc150_magn" },
292
+ /* The resources describe a 3th client, but it is not really there. */
293
+ { "bsg2150_dummy_dev" },
294
+ {}
295
+ },
296
+ .bus_type = SMI_I2C ,
175
297
};
176
298
177
- static const struct smi_instance int3515_data [] = {
178
- { "tps6598x" , IRQ_RESOURCE_APIC , 0 },
179
- { "tps6598x" , IRQ_RESOURCE_APIC , 1 },
180
- { "tps6598x" , IRQ_RESOURCE_APIC , 2 },
181
- { "tps6598x" , IRQ_RESOURCE_APIC , 3 },
182
- {}
299
+ static const struct smi_node int3515_data = {
300
+ .instances = {
301
+ { "tps6598x" , IRQ_RESOURCE_APIC , 0 },
302
+ { "tps6598x" , IRQ_RESOURCE_APIC , 1 },
303
+ { "tps6598x" , IRQ_RESOURCE_APIC , 2 },
304
+ { "tps6598x" , IRQ_RESOURCE_APIC , 3 },
305
+ {}
306
+ },
307
+ .bus_type = SMI_I2C ,
183
308
};
184
309
185
310
/*
186
311
* Note new device-ids must also be added to ignore_serial_bus_ids in
187
312
* drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
188
313
*/
189
314
static const struct acpi_device_id smi_acpi_ids [] = {
190
- { "BSG1160" , (unsigned long )bsg1160_data },
191
- { "BSG2150" , (unsigned long )bsg2150_data },
192
- { "INT3515" , (unsigned long )int3515_data },
315
+ { "BSG1160" , (unsigned long )& bsg1160_data },
316
+ { "BSG2150" , (unsigned long )& bsg2150_data },
317
+ { "INT3515" , (unsigned long )& int3515_data },
193
318
{ }
194
319
};
195
320
MODULE_DEVICE_TABLE (acpi , smi_acpi_ids );
0 commit comments