diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 98 |
1 files changed, 52 insertions, 46 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b5a78a1f4421..709c836607de 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -29,11 +29,6 @@ | |||
29 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
30 | #include <linux/of_spi.h> | 30 | #include <linux/of_spi.h> |
31 | 31 | ||
32 | |||
33 | /* SPI bustype and spi_master class are registered after board init code | ||
34 | * provides the SPI device tables, ensuring that both are present by the | ||
35 | * time controller driver registration causes spi_devices to "enumerate". | ||
36 | */ | ||
37 | static void spidev_release(struct device *dev) | 32 | static void spidev_release(struct device *dev) |
38 | { | 33 | { |
39 | struct spi_device *spi = to_spi_device(dev); | 34 | struct spi_device *spi = to_spi_device(dev); |
@@ -202,11 +197,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver); | |||
202 | 197 | ||
203 | struct boardinfo { | 198 | struct boardinfo { |
204 | struct list_head list; | 199 | struct list_head list; |
205 | unsigned n_board_info; | 200 | struct spi_board_info board_info; |
206 | struct spi_board_info board_info[0]; | ||
207 | }; | 201 | }; |
208 | 202 | ||
209 | static LIST_HEAD(board_list); | 203 | static LIST_HEAD(board_list); |
204 | static LIST_HEAD(spi_master_list); | ||
205 | |||
206 | /* | ||
207 | * Used to protect add/del opertion for board_info list and | ||
208 | * spi_master list, and their matching process | ||
209 | */ | ||
210 | static DEFINE_MUTEX(board_lock); | 210 | static DEFINE_MUTEX(board_lock); |
211 | 211 | ||
212 | /** | 212 | /** |
@@ -300,16 +300,16 @@ int spi_add_device(struct spi_device *spi) | |||
300 | */ | 300 | */ |
301 | status = spi_setup(spi); | 301 | status = spi_setup(spi); |
302 | if (status < 0) { | 302 | if (status < 0) { |
303 | dev_err(dev, "can't %s %s, status %d\n", | 303 | dev_err(dev, "can't setup %s, status %d\n", |
304 | "setup", dev_name(&spi->dev), status); | 304 | dev_name(&spi->dev), status); |
305 | goto done; | 305 | goto done; |
306 | } | 306 | } |
307 | 307 | ||
308 | /* Device may be bound to an active driver when this returns */ | 308 | /* Device may be bound to an active driver when this returns */ |
309 | status = device_add(&spi->dev); | 309 | status = device_add(&spi->dev); |
310 | if (status < 0) | 310 | if (status < 0) |
311 | dev_err(dev, "can't %s %s, status %d\n", | 311 | dev_err(dev, "can't add %s, status %d\n", |
312 | "add", dev_name(&spi->dev), status); | 312 | dev_name(&spi->dev), status); |
313 | else | 313 | else |
314 | dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev)); | 314 | dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev)); |
315 | 315 | ||
@@ -371,6 +371,20 @@ struct spi_device *spi_new_device(struct spi_master *master, | |||
371 | } | 371 | } |
372 | EXPORT_SYMBOL_GPL(spi_new_device); | 372 | EXPORT_SYMBOL_GPL(spi_new_device); |
373 | 373 | ||
374 | static void spi_match_master_to_boardinfo(struct spi_master *master, | ||
375 | struct spi_board_info *bi) | ||
376 | { | ||
377 | struct spi_device *dev; | ||
378 | |||
379 | if (master->bus_num != bi->bus_num) | ||
380 | return; | ||
381 | |||
382 | dev = spi_new_device(master, bi); | ||
383 | if (!dev) | ||
384 | dev_err(master->dev.parent, "can't create new device for %s\n", | ||
385 | bi->modalias); | ||
386 | } | ||
387 | |||
374 | /** | 388 | /** |
375 | * spi_register_board_info - register SPI devices for a given board | 389 | * spi_register_board_info - register SPI devices for a given board |
376 | * @info: array of chip descriptors | 390 | * @info: array of chip descriptors |
@@ -393,43 +407,25 @@ EXPORT_SYMBOL_GPL(spi_new_device); | |||
393 | int __init | 407 | int __init |
394 | spi_register_board_info(struct spi_board_info const *info, unsigned n) | 408 | spi_register_board_info(struct spi_board_info const *info, unsigned n) |
395 | { | 409 | { |
396 | struct boardinfo *bi; | 410 | struct boardinfo *bi; |
411 | int i; | ||
397 | 412 | ||
398 | bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); | 413 | bi = kzalloc(n * sizeof(*bi), GFP_KERNEL); |
399 | if (!bi) | 414 | if (!bi) |
400 | return -ENOMEM; | 415 | return -ENOMEM; |
401 | bi->n_board_info = n; | ||
402 | memcpy(bi->board_info, info, n * sizeof *info); | ||
403 | 416 | ||
404 | mutex_lock(&board_lock); | 417 | for (i = 0; i < n; i++, bi++, info++) { |
405 | list_add_tail(&bi->list, &board_list); | 418 | struct spi_master *master; |
406 | mutex_unlock(&board_lock); | ||
407 | return 0; | ||
408 | } | ||
409 | 419 | ||
410 | /* FIXME someone should add support for a __setup("spi", ...) that | 420 | memcpy(&bi->board_info, info, sizeof(*info)); |
411 | * creates board info from kernel command lines | 421 | mutex_lock(&board_lock); |
412 | */ | 422 | list_add_tail(&bi->list, &board_list); |
413 | 423 | list_for_each_entry(master, &spi_master_list, list) | |
414 | static void scan_boardinfo(struct spi_master *master) | 424 | spi_match_master_to_boardinfo(master, &bi->board_info); |
415 | { | 425 | mutex_unlock(&board_lock); |
416 | struct boardinfo *bi; | ||
417 | |||
418 | mutex_lock(&board_lock); | ||
419 | list_for_each_entry(bi, &board_list, list) { | ||
420 | struct spi_board_info *chip = bi->board_info; | ||
421 | unsigned n; | ||
422 | |||
423 | for (n = bi->n_board_info; n > 0; n--, chip++) { | ||
424 | if (chip->bus_num != master->bus_num) | ||
425 | continue; | ||
426 | /* NOTE: this relies on spi_new_device to | ||
427 | * issue diagnostics when given bogus inputs | ||
428 | */ | ||
429 | (void) spi_new_device(master, chip); | ||
430 | } | ||
431 | } | 426 | } |
432 | mutex_unlock(&board_lock); | 427 | |
428 | return 0; | ||
433 | } | 429 | } |
434 | 430 | ||
435 | /*-------------------------------------------------------------------------*/ | 431 | /*-------------------------------------------------------------------------*/ |
@@ -512,6 +508,7 @@ int spi_register_master(struct spi_master *master) | |||
512 | { | 508 | { |
513 | static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); | 509 | static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); |
514 | struct device *dev = master->dev.parent; | 510 | struct device *dev = master->dev.parent; |
511 | struct boardinfo *bi; | ||
515 | int status = -ENODEV; | 512 | int status = -ENODEV; |
516 | int dynamic = 0; | 513 | int dynamic = 0; |
517 | 514 | ||
@@ -547,8 +544,12 @@ int spi_register_master(struct spi_master *master) | |||
547 | dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), | 544 | dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), |
548 | dynamic ? " (dynamic)" : ""); | 545 | dynamic ? " (dynamic)" : ""); |
549 | 546 | ||
550 | /* populate children from any spi device tables */ | 547 | mutex_lock(&board_lock); |
551 | scan_boardinfo(master); | 548 | list_add_tail(&master->list, &spi_master_list); |
549 | list_for_each_entry(bi, &board_list, list) | ||
550 | spi_match_master_to_boardinfo(master, &bi->board_info); | ||
551 | mutex_unlock(&board_lock); | ||
552 | |||
552 | status = 0; | 553 | status = 0; |
553 | 554 | ||
554 | /* Register devices from the device tree */ | 555 | /* Register devices from the device tree */ |
@@ -579,7 +580,12 @@ void spi_unregister_master(struct spi_master *master) | |||
579 | { | 580 | { |
580 | int dummy; | 581 | int dummy; |
581 | 582 | ||
582 | dummy = device_for_each_child(&master->dev, NULL, __unregister); | 583 | mutex_lock(&board_lock); |
584 | list_del(&master->list); | ||
585 | mutex_unlock(&board_lock); | ||
586 | |||
587 | dummy = device_for_each_child(master->dev.parent, &master->dev, | ||
588 | __unregister); | ||
583 | device_unregister(&master->dev); | 589 | device_unregister(&master->dev); |
584 | } | 590 | } |
585 | EXPORT_SYMBOL_GPL(spi_unregister_master); | 591 | EXPORT_SYMBOL_GPL(spi_unregister_master); |
@@ -652,7 +658,7 @@ int spi_setup(struct spi_device *spi) | |||
652 | */ | 658 | */ |
653 | bad_bits = spi->mode & ~spi->master->mode_bits; | 659 | bad_bits = spi->mode & ~spi->master->mode_bits; |
654 | if (bad_bits) { | 660 | if (bad_bits) { |
655 | dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", | 661 | dev_err(&spi->dev, "setup: unsupported mode bits %x\n", |
656 | bad_bits); | 662 | bad_bits); |
657 | return -EINVAL; | 663 | return -EINVAL; |
658 | } | 664 | } |