12
12
#include <linux/mfd/syscon.h>
13
13
#include <linux/module.h>
14
14
#include <linux/of.h>
15
+ #include <linux/of_address.h>
15
16
#include <linux/platform_device.h>
16
17
#include <linux/poll.h>
17
18
#include <linux/regmap.h>
@@ -233,58 +234,154 @@ static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = {
233
234
{ .idr = LPC_IDR4 , .odr = LPC_ODR4 , .str = LPC_STR4 },
234
235
};
235
236
236
- static int aspeed_kcs_probe (struct platform_device * pdev )
237
+ static struct kcs_bmc * aspeed_kcs_probe_of_v1 (struct platform_device * pdev )
237
238
{
238
- struct device * dev = & pdev -> dev ;
239
239
struct aspeed_kcs_bmc * priv ;
240
- struct kcs_bmc * kcs_bmc ;
241
- u32 chan , addr ;
240
+ struct device_node * np ;
241
+ struct kcs_bmc * kcs ;
242
+ u32 channel ;
243
+ u32 slave ;
242
244
int rc ;
243
245
244
- rc = of_property_read_u32 (dev -> of_node , "kcs_chan" , & chan );
245
- if ((rc != 0 ) || (chan == 0 || chan > KCS_CHANNEL_MAX )) {
246
- dev_err (dev , "no valid 'kcs_chan' configured\n" );
247
- return - ENODEV ;
246
+ np = pdev -> dev .of_node ;
247
+
248
+ rc = of_property_read_u32 (np , "kcs_chan" , & channel );
249
+ if ((rc != 0 ) || (channel == 0 || channel > KCS_CHANNEL_MAX )) {
250
+ dev_err (& pdev -> dev , "no valid 'kcs_chan' configured\n" );
251
+ return ERR_PTR (- EINVAL );
252
+ }
253
+
254
+ kcs = kcs_bmc_alloc (& pdev -> dev , sizeof (struct aspeed_kcs_bmc ), channel );
255
+ if (!kcs )
256
+ return ERR_PTR (- ENOMEM );
257
+
258
+ priv = kcs_bmc_priv (kcs );
259
+ priv -> map = syscon_node_to_regmap (pdev -> dev .parent -> of_node );
260
+ if (IS_ERR (priv -> map )) {
261
+ dev_err (& pdev -> dev , "Couldn't get regmap\n" );
262
+ return ERR_PTR (- ENODEV );
248
263
}
249
264
250
- rc = of_property_read_u32 (dev -> of_node , "kcs_addr" , & addr );
265
+ rc = of_property_read_u32 (np , "kcs_addr" , & slave );
251
266
if (rc ) {
252
- dev_err (dev , "no valid 'kcs_addr' configured\n" );
253
- return - ENODEV ;
267
+ dev_err (& pdev -> dev , "no valid 'kcs_addr' configured\n" );
268
+ return ERR_PTR (- EINVAL );
269
+ }
270
+
271
+ kcs -> ioreg = ast_kcs_bmc_ioregs [channel - 1 ];
272
+ aspeed_kcs_set_address (kcs , slave );
273
+
274
+ return kcs ;
275
+ }
276
+
277
+ static int aspeed_kcs_calculate_channel (const struct kcs_ioreg * regs )
278
+ {
279
+ int i ;
280
+
281
+ for (i = 0 ; i < ARRAY_SIZE (ast_kcs_bmc_ioregs ); i ++ ) {
282
+ if (!memcmp (& ast_kcs_bmc_ioregs [i ], regs , sizeof (* regs )))
283
+ return i + 1 ;
254
284
}
255
285
256
- kcs_bmc = kcs_bmc_alloc (dev , sizeof (* priv ), chan );
257
- if (!kcs_bmc )
258
- return - ENOMEM ;
286
+ return - EINVAL ;
287
+ }
288
+
289
+ static struct kcs_bmc * aspeed_kcs_probe_of_v2 (struct platform_device * pdev )
290
+ {
291
+ struct aspeed_kcs_bmc * priv ;
292
+ struct device_node * np ;
293
+ struct kcs_ioreg ioreg ;
294
+ struct kcs_bmc * kcs ;
295
+ const __be32 * reg ;
296
+ int channel ;
297
+ u32 slave ;
298
+ int rc ;
299
+
300
+ np = pdev -> dev .of_node ;
301
+
302
+ /* Don't translate addresses, we want offsets for the regmaps */
303
+ reg = of_get_address (np , 0 , NULL , NULL );
304
+ if (!reg )
305
+ return ERR_PTR (- EINVAL );
306
+ ioreg .idr = be32_to_cpup (reg );
307
+
308
+ reg = of_get_address (np , 1 , NULL , NULL );
309
+ if (!reg )
310
+ return ERR_PTR (- EINVAL );
311
+ ioreg .odr = be32_to_cpup (reg );
312
+
313
+ reg = of_get_address (np , 2 , NULL , NULL );
314
+ if (!reg )
315
+ return ERR_PTR (- EINVAL );
316
+ ioreg .str = be32_to_cpup (reg );
259
317
260
- priv = kcs_bmc_priv (kcs_bmc );
261
- priv -> map = syscon_node_to_regmap (dev -> parent -> of_node );
318
+ channel = aspeed_kcs_calculate_channel (& ioreg );
319
+ if (channel < 0 )
320
+ return ERR_PTR (channel );
321
+
322
+ kcs = kcs_bmc_alloc (& pdev -> dev , sizeof (struct aspeed_kcs_bmc ), channel );
323
+ if (!kcs )
324
+ return ERR_PTR (- ENOMEM );
325
+
326
+ kcs -> ioreg = ioreg ;
327
+
328
+ priv = kcs_bmc_priv (kcs );
329
+ priv -> map = syscon_node_to_regmap (pdev -> dev .parent -> of_node );
262
330
if (IS_ERR (priv -> map )) {
263
- dev_err (dev , "Couldn't get regmap\n" );
264
- return - ENODEV ;
331
+ dev_err (& pdev -> dev , "Couldn't get regmap\n" );
332
+ return ERR_PTR ( - ENODEV ) ;
265
333
}
266
334
267
- kcs_bmc -> ioreg = ast_kcs_bmc_ioregs [chan - 1 ];
335
+ rc = of_property_read_u32 (np , "aspeed,lpc-io-reg" , & slave );
336
+ if (rc )
337
+ return ERR_PTR (rc );
338
+
339
+ aspeed_kcs_set_address (kcs , slave );
340
+
341
+ return kcs ;
342
+ }
343
+
344
+ static int aspeed_kcs_probe (struct platform_device * pdev )
345
+ {
346
+ struct device * dev = & pdev -> dev ;
347
+ struct kcs_bmc * kcs_bmc ;
348
+ struct device_node * np ;
349
+ int rc ;
350
+
351
+ np = pdev -> dev .of_node ;
352
+ if (of_device_is_compatible (np , "aspeed,ast2400-kcs-bmc" ) ||
353
+ of_device_is_compatible (np , "aspeed,ast2500-kcs-bmc" ))
354
+ kcs_bmc = aspeed_kcs_probe_of_v1 (pdev );
355
+ else if (of_device_is_compatible (np , "aspeed,ast2400-kcs-bmc-v2" ) ||
356
+ of_device_is_compatible (np , "aspeed,ast2500-kcs-bmc-v2" ))
357
+ kcs_bmc = aspeed_kcs_probe_of_v2 (pdev );
358
+ else
359
+ return - EINVAL ;
360
+
361
+ if (IS_ERR (kcs_bmc ))
362
+ return PTR_ERR (kcs_bmc );
363
+
268
364
kcs_bmc -> io_inputb = aspeed_kcs_inb ;
269
365
kcs_bmc -> io_outputb = aspeed_kcs_outb ;
270
366
271
- dev_set_drvdata (dev , kcs_bmc );
272
-
273
- aspeed_kcs_set_address (kcs_bmc , addr );
274
- aspeed_kcs_enable_channel (kcs_bmc , true);
275
367
rc = aspeed_kcs_config_irq (kcs_bmc , pdev );
276
368
if (rc )
277
369
return rc ;
278
370
371
+ dev_set_drvdata (dev , kcs_bmc );
372
+
373
+ aspeed_kcs_enable_channel (kcs_bmc , true);
374
+
279
375
rc = misc_register (& kcs_bmc -> miscdev );
280
376
if (rc ) {
281
377
dev_err (dev , "Unable to register device\n" );
282
378
return rc ;
283
379
}
284
380
285
- pr_info ("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n" ,
286
- chan , addr ,
287
- kcs_bmc -> ioreg .idr , kcs_bmc -> ioreg .odr , kcs_bmc -> ioreg .str );
381
+ dev_dbg (& pdev -> dev ,
382
+ "Probed KCS device %d (IDR=0x%x, ODR=0x%x, STR=0x%x)\n" ,
383
+ kcs_bmc -> channel , kcs_bmc -> ioreg .idr , kcs_bmc -> ioreg .odr ,
384
+ kcs_bmc -> ioreg .str );
288
385
289
386
return 0 ;
290
387
}
@@ -301,6 +398,8 @@ static int aspeed_kcs_remove(struct platform_device *pdev)
301
398
static const struct of_device_id ast_kcs_bmc_match [] = {
302
399
{ .compatible = "aspeed,ast2400-kcs-bmc" },
303
400
{ .compatible = "aspeed,ast2500-kcs-bmc" },
401
+ { .compatible = "aspeed,ast2400-kcs-bmc-v2" },
402
+ { .compatible = "aspeed,ast2500-kcs-bmc-v2" },
304
403
{ }
305
404
};
306
405
MODULE_DEVICE_TABLE (of , ast_kcs_bmc_match );
0 commit comments