Skip to content

Commit

Permalink
Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6
Browse files Browse the repository at this point in the history
* 'next-spi' of git://git.secretlab.ca/git/linux-2.6:
  spi/pl022: fix erroneous platform data in U300
  spi: fixed odd static string conventions in core code
  spi/bfin_spi: only request GPIO on first load
  spi/bfin_spi: handle error/status changes after data interrupts
  spi: enable spi_board_info to be registered after spi_master
  • Loading branch information
Linus Torvalds committed Nov 1, 2010
2 parents 47c5ba5 + 65289d6 commit 90ae83f
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 52 deletions.
2 changes: 1 addition & 1 deletion arch/arm/mach-u300/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static struct spi_board_info u300_spi_devices[] = {
.bus_num = 0, /* Only one bus on this chip */
.chip_select = 0,
/* Means SPI_CS_HIGH, change if e.g low CS */
.mode = SPI_MODE_1 | SPI_LSB_FIRST | SPI_LOOP,
.mode = SPI_MODE_1 | SPI_LOOP,
},
#endif
};
Expand Down
98 changes: 52 additions & 46 deletions drivers/spi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
#include <linux/spi/spi.h>
#include <linux/of_spi.h>


/* SPI bustype and spi_master class are registered after board init code
* provides the SPI device tables, ensuring that both are present by the
* time controller driver registration causes spi_devices to "enumerate".
*/
static void spidev_release(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
Expand Down Expand Up @@ -202,11 +197,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);

struct boardinfo {
struct list_head list;
unsigned n_board_info;
struct spi_board_info board_info[0];
struct spi_board_info board_info;
};

static LIST_HEAD(board_list);
static LIST_HEAD(spi_master_list);

/*
* Used to protect add/del opertion for board_info list and
* spi_master list, and their matching process
*/
static DEFINE_MUTEX(board_lock);

/**
Expand Down Expand Up @@ -300,16 +300,16 @@ int spi_add_device(struct spi_device *spi)
*/
status = spi_setup(spi);
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
"setup", dev_name(&spi->dev), status);
dev_err(dev, "can't setup %s, status %d\n",
dev_name(&spi->dev), status);
goto done;
}

/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't %s %s, status %d\n",
"add", dev_name(&spi->dev), status);
dev_err(dev, "can't add %s, status %d\n",
dev_name(&spi->dev), status);
else
dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));

Expand Down Expand Up @@ -371,6 +371,20 @@ struct spi_device *spi_new_device(struct spi_master *master,
}
EXPORT_SYMBOL_GPL(spi_new_device);

static void spi_match_master_to_boardinfo(struct spi_master *master,
struct spi_board_info *bi)
{
struct spi_device *dev;

if (master->bus_num != bi->bus_num)
return;

dev = spi_new_device(master, bi);
if (!dev)
dev_err(master->dev.parent, "can't create new device for %s\n",
bi->modalias);
}

/**
* spi_register_board_info - register SPI devices for a given board
* @info: array of chip descriptors
Expand All @@ -393,43 +407,25 @@ EXPORT_SYMBOL_GPL(spi_new_device);
int __init
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
struct boardinfo *bi;
struct boardinfo *bi;
int i;

bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);

mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);
mutex_unlock(&board_lock);
return 0;
}
for (i = 0; i < n; i++, bi++, info++) {
struct spi_master *master;

/* FIXME someone should add support for a __setup("spi", ...) that
* creates board info from kernel command lines
*/

static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;

mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;

for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
/* NOTE: this relies on spi_new_device to
* issue diagnostics when given bogus inputs
*/
(void) spi_new_device(master, chip);
}
memcpy(&bi->board_info, info, sizeof(*info));
mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);
list_for_each_entry(master, &spi_master_list, list)
spi_match_master_to_boardinfo(master, &bi->board_info);
mutex_unlock(&board_lock);
}
mutex_unlock(&board_lock);

return 0;
}

/*-------------------------------------------------------------------------*/
Expand Down Expand Up @@ -512,6 +508,7 @@ int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = master->dev.parent;
struct boardinfo *bi;
int status = -ENODEV;
int dynamic = 0;

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

/* populate children from any spi device tables */
scan_boardinfo(master);
mutex_lock(&board_lock);
list_add_tail(&master->list, &spi_master_list);
list_for_each_entry(bi, &board_list, list)
spi_match_master_to_boardinfo(master, &bi->board_info);
mutex_unlock(&board_lock);

status = 0;

/* Register devices from the device tree */
Expand Down Expand Up @@ -579,7 +580,12 @@ void spi_unregister_master(struct spi_master *master)
{
int dummy;

dummy = device_for_each_child(&master->dev, NULL, __unregister);
mutex_lock(&board_lock);
list_del(&master->list);
mutex_unlock(&board_lock);

dummy = device_for_each_child(master->dev.parent, &master->dev,
__unregister);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
Expand Down Expand Up @@ -652,7 +658,7 @@ int spi_setup(struct spi_device *spi)
*/
bad_bits = spi->mode & ~spi->master->mode_bits;
if (bad_bits) {
dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
bad_bits);
return -EINVAL;
}
Expand Down
22 changes: 17 additions & 5 deletions drivers/spi/spi_bfin5xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,15 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
dmastat, spistat);

if (drv_data->rx != NULL) {
u16 cr = read_CTRL(drv_data);
/* discard old RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */
write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */
}

clear_dma_irqstat(drv_data->dma_channel);

/*
Expand Down Expand Up @@ -1099,12 +1108,15 @@ static int bfin_spi_setup(struct spi_device *spi)
}

if (chip->chip_select_num >= MAX_CTRL_CS) {
ret = gpio_request(chip->cs_gpio, spi->modalias);
if (ret) {
dev_err(&spi->dev, "gpio_request() error\n");
goto pin_error;
/* Only request on first setup */
if (spi_get_ctldata(spi) == NULL) {
ret = gpio_request(chip->cs_gpio, spi->modalias);
if (ret) {
dev_err(&spi->dev, "gpio_request() error\n");
goto pin_error;
}
gpio_direction_output(chip->cs_gpio, 1);
}
gpio_direction_output(chip->cs_gpio, 1);
}

dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
Expand Down
3 changes: 3 additions & 0 deletions include/linux/spi/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
/**
* struct spi_master - interface to SPI master controller
* @dev: device interface to this driver
* @list: link with the global spi_master list
* @bus_num: board-specific (and often SOC-specific) identifier for a
* given SPI controller.
* @num_chipselect: chipselects are used to distinguish individual
Expand Down Expand Up @@ -238,6 +239,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
struct spi_master {
struct device dev;

struct list_head list;

/* other than negative (== assign one dynamically), bus_num is fully
* board-specific. usually that simplifies to being SOC-specific.
* example: one SOC has three SPI controllers, numbered 0..2,
Expand Down

0 comments on commit 90ae83f

Please sign in to comment.