aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
authorFeng Tang <feng.tang@intel.com>2010-08-02 03:52:15 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-10-22 01:52:16 -0400
commit2b9603a0d7e395fb844af90fba71448bc8019077 (patch)
treeb828ff7c6819766e92dd304eb5e63e12527e516a /drivers/spi/spi.c
parentd4429f608abde89e8bc1e24b43cd503feb95c496 (diff)
spi: enable spi_board_info to be registered after spi_master
Currently spi_register_board_info() has to be called before its related spi_master be registered, otherwise these board info will be just ignored. This patch will remove this order limit, it adds a global spi master list like the existing global board info listr. Whenever a board info or a spi_master is registered, the spi master list or board info list will be scanned, and a new spi device will be created if there is a master-board info match. Signed-off-by: Feng Tang <feng.tang@intel.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c88
1 files changed, 47 insertions, 41 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b5a78a1f4421..0845cd4c5155 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 */
37static void spidev_release(struct device *dev) 32static 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
203struct boardinfo { 198struct 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
209static LIST_HEAD(board_list); 203static LIST_HEAD(board_list);
204static 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 */
210static DEFINE_MUTEX(board_lock); 210static DEFINE_MUTEX(board_lock);
211 211
212/** 212/**
@@ -371,6 +371,20 @@ struct spi_device *spi_new_device(struct spi_master *master,
371} 371}
372EXPORT_SYMBOL_GPL(spi_new_device); 372EXPORT_SYMBOL_GPL(spi_new_device);
373 373
374static 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);
393int __init 407int __init
394spi_register_board_info(struct spi_board_info const *info, unsigned n) 408spi_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)
414static 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}
585EXPORT_SYMBOL_GPL(spi_unregister_master); 591EXPORT_SYMBOL_GPL(spi_unregister_master);