Skip to content

Commit 2b9603a

Browse files
ftang1glikely
authored andcommitted
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 <[email protected]> Signed-off-by: Grant Likely <[email protected]>
1 parent d4429f6 commit 2b9603a

File tree

2 files changed

+50
-41
lines changed

2 files changed

+50
-41
lines changed

drivers/spi/spi.c

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@
2929
#include <linux/spi/spi.h>
3030
#include <linux/of_spi.h>
3131

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-
*/
3732
static void spidev_release(struct device *dev)
3833
{
3934
struct spi_device *spi = to_spi_device(dev);
@@ -202,11 +197,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);
202197

203198
struct boardinfo {
204199
struct list_head list;
205-
unsigned n_board_info;
206-
struct spi_board_info board_info[0];
200+
struct spi_board_info board_info;
207201
};
208202

209203
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+
*/
210210
static DEFINE_MUTEX(board_lock);
211211

212212
/**
@@ -371,6 +371,20 @@ struct spi_device *spi_new_device(struct spi_master *master,
371371
}
372372
EXPORT_SYMBOL_GPL(spi_new_device);
373373

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+
374388
/**
375389
* spi_register_board_info - register SPI devices for a given board
376390
* @info: array of chip descriptors
@@ -393,43 +407,25 @@ EXPORT_SYMBOL_GPL(spi_new_device);
393407
int __init
394408
spi_register_board_info(struct spi_board_info const *info, unsigned n)
395409
{
396-
struct boardinfo *bi;
410+
struct boardinfo *bi;
411+
int i;
397412

398-
bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
413+
bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
399414
if (!bi)
400415
return -ENOMEM;
401-
bi->n_board_info = n;
402-
memcpy(bi->board_info, info, n * sizeof *info);
403416

404-
mutex_lock(&board_lock);
405-
list_add_tail(&bi->list, &board_list);
406-
mutex_unlock(&board_lock);
407-
return 0;
408-
}
417+
for (i = 0; i < n; i++, bi++, info++) {
418+
struct spi_master *master;
409419

410-
/* FIXME someone should add support for a __setup("spi", ...) that
411-
* creates board info from kernel command lines
412-
*/
413-
414-
static void scan_boardinfo(struct spi_master *master)
415-
{
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-
}
420+
memcpy(&bi->board_info, info, sizeof(*info));
421+
mutex_lock(&board_lock);
422+
list_add_tail(&bi->list, &board_list);
423+
list_for_each_entry(master, &spi_master_list, list)
424+
spi_match_master_to_boardinfo(master, &bi->board_info);
425+
mutex_unlock(&board_lock);
431426
}
432-
mutex_unlock(&board_lock);
427+
428+
return 0;
433429
}
434430

435431
/*-------------------------------------------------------------------------*/
@@ -512,6 +508,7 @@ int spi_register_master(struct spi_master *master)
512508
{
513509
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
514510
struct device *dev = master->dev.parent;
511+
struct boardinfo *bi;
515512
int status = -ENODEV;
516513
int dynamic = 0;
517514

@@ -547,8 +544,12 @@ int spi_register_master(struct spi_master *master)
547544
dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
548545
dynamic ? " (dynamic)" : "");
549546

550-
/* populate children from any spi device tables */
551-
scan_boardinfo(master);
547+
mutex_lock(&board_lock);
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+
552553
status = 0;
553554

554555
/* Register devices from the device tree */
@@ -579,7 +580,12 @@ void spi_unregister_master(struct spi_master *master)
579580
{
580581
int dummy;
581582

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);
583589
device_unregister(&master->dev);
584590
}
585591
EXPORT_SYMBOL_GPL(spi_unregister_master);

include/linux/spi/spi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
204204
/**
205205
* struct spi_master - interface to SPI master controller
206206
* @dev: device interface to this driver
207+
* @list: link with the global spi_master list
207208
* @bus_num: board-specific (and often SOC-specific) identifier for a
208209
* given SPI controller.
209210
* @num_chipselect: chipselects are used to distinguish individual
@@ -238,6 +239,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
238239
struct spi_master {
239240
struct device dev;
240241

242+
struct list_head list;
243+
241244
/* other than negative (== assign one dynamically), bus_num is fully
242245
* board-specific. usually that simplifies to being SOC-specific.
243246
* example: one SOC has three SPI controllers, numbered 0..2,

0 commit comments

Comments
 (0)