Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90ae83f7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'next-spi' of git://git.secretlab.ca/git/linux-2.6

* '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
parents 47c5ba53 65289d63
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
};
+52 −46
Original line number Diff line number Diff line
@@ -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);
@@ -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);

/**
@@ -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));

@@ -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
@@ -394,42 +408,24 @@ int __init
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
	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);

	for (i = 0; i < n; i++, bi++, info++) {
		struct spi_master *master;

		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);
	return 0;
	}

/* 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);
		}
	}
	mutex_unlock(&board_lock);
	return 0;
}

/*-------------------------------------------------------------------------*/
@@ -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;

@@ -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 */
@@ -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);
@@ -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;
	}
+17 −5
Original line number Diff line number Diff line
@@ -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);

	/*
@@ -1099,6 +1108,8 @@ static int bfin_spi_setup(struct spi_device *spi)
	}

	if (chip->chip_select_num >= MAX_CTRL_CS) {
		/* 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");
@@ -1106,6 +1117,7 @@ static int bfin_spi_setup(struct spi_device *spi)
			}
			gpio_direction_output(chip->cs_gpio, 1);
		}
	}

	dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n",
			spi->modalias, spi->bits_per_word, chip->enable_dma);
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -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,