aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2012-08-22 09:49:17 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-08-22 15:00:44 -0400
commitf6f46de1063c8829713cd9d5b960dd8cb66cde8b (patch)
tree3367d20d24223f9e149188eb2997b66111237633 /drivers
parent3ce8859e2e72713d3619285cab609d05c3591fc4 (diff)
spi/pl022: Add chip select handling via GPIO
This patch adds the ability for the driver to control the chip select directly. This enables independence from cs_control callbacks. Configurable via platform_data, to be extended as DT in the following patch. Based on the initial patch by Alexandre Pereira da Silva <aletes.xgr@gmail.com> Signed-off-by: Roland Stigge <stigge@antcom.de> Acked-by: Alexandre Pereira da Silva <aletes.xgr@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi-pl022.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 47c6753fb31b..cf47802f00c9 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -40,6 +40,7 @@
40#include <linux/dma-mapping.h> 40#include <linux/dma-mapping.h>
41#include <linux/scatterlist.h> 41#include <linux/scatterlist.h>
42#include <linux/pm_runtime.h> 42#include <linux/pm_runtime.h>
43#include <linux/gpio.h>
43 44
44/* 45/*
45 * This macro is used to define some register default values. 46 * This macro is used to define some register default values.
@@ -356,6 +357,8 @@ struct vendor_data {
356 * @sgt_rx: scattertable for the RX transfer 357 * @sgt_rx: scattertable for the RX transfer
357 * @sgt_tx: scattertable for the TX transfer 358 * @sgt_tx: scattertable for the TX transfer
358 * @dummypage: a dummy page used for driving data on the bus with DMA 359 * @dummypage: a dummy page used for driving data on the bus with DMA
360 * @cur_cs: current chip select (gpio)
361 * @chipselects: list of chipselects (gpios)
359 */ 362 */
360struct pl022 { 363struct pl022 {
361 struct amba_device *adev; 364 struct amba_device *adev;
@@ -389,6 +392,8 @@ struct pl022 {
389 char *dummypage; 392 char *dummypage;
390 bool dma_running; 393 bool dma_running;
391#endif 394#endif
395 int cur_cs;
396 int *chipselects;
392}; 397};
393 398
394/** 399/**
@@ -433,6 +438,14 @@ static void null_cs_control(u32 command)
433 pr_debug("pl022: dummy chip select control, CS=0x%x\n", command); 438 pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
434} 439}
435 440
441static void pl022_cs_control(struct pl022 *pl022, u32 command)
442{
443 if (gpio_is_valid(pl022->cur_cs))
444 gpio_set_value(pl022->cur_cs, command);
445 else
446 pl022->cur_chip->cs_control(command);
447}
448
436/** 449/**
437 * giveback - current spi_message is over, schedule next message and call 450 * giveback - current spi_message is over, schedule next message and call
438 * callback of this message. Assumes that caller already 451 * callback of this message. Assumes that caller already
@@ -479,7 +492,7 @@ static void giveback(struct pl022 *pl022)
479 if (next_msg && next_msg->spi != pl022->cur_msg->spi) 492 if (next_msg && next_msg->spi != pl022->cur_msg->spi)
480 next_msg = NULL; 493 next_msg = NULL;
481 if (!next_msg || pl022->cur_msg->state == STATE_ERROR) 494 if (!next_msg || pl022->cur_msg->state == STATE_ERROR)
482 pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); 495 pl022_cs_control(pl022, SSP_CHIP_DESELECT);
483 else 496 else
484 pl022->next_msg_cs_active = true; 497 pl022->next_msg_cs_active = true;
485 498
@@ -818,8 +831,7 @@ static void dma_callback(void *data)
818 /* Update total bytes transferred */ 831 /* Update total bytes transferred */
819 msg->actual_length += pl022->cur_transfer->len; 832 msg->actual_length += pl022->cur_transfer->len;
820 if (pl022->cur_transfer->cs_change) 833 if (pl022->cur_transfer->cs_change)
821 pl022->cur_chip-> 834 pl022_cs_control(pl022, SSP_CHIP_DESELECT);
822 cs_control(SSP_CHIP_DESELECT);
823 835
824 /* Move to next transfer */ 836 /* Move to next transfer */
825 msg->state = next_transfer(pl022); 837 msg->state = next_transfer(pl022);
@@ -1252,8 +1264,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
1252 /* Update total bytes transferred */ 1264 /* Update total bytes transferred */
1253 msg->actual_length += pl022->cur_transfer->len; 1265 msg->actual_length += pl022->cur_transfer->len;
1254 if (pl022->cur_transfer->cs_change) 1266 if (pl022->cur_transfer->cs_change)
1255 pl022->cur_chip-> 1267 pl022_cs_control(pl022, SSP_CHIP_DESELECT);
1256 cs_control(SSP_CHIP_DESELECT);
1257 /* Move to next transfer */ 1268 /* Move to next transfer */
1258 msg->state = next_transfer(pl022); 1269 msg->state = next_transfer(pl022);
1259 tasklet_schedule(&pl022->pump_transfers); 1270 tasklet_schedule(&pl022->pump_transfers);
@@ -1338,7 +1349,7 @@ static void pump_transfers(unsigned long data)
1338 1349
1339 /* Reselect chip select only if cs_change was requested */ 1350 /* Reselect chip select only if cs_change was requested */
1340 if (previous->cs_change) 1351 if (previous->cs_change)
1341 pl022->cur_chip->cs_control(SSP_CHIP_SELECT); 1352 pl022_cs_control(pl022, SSP_CHIP_SELECT);
1342 } else { 1353 } else {
1343 /* STATE_START */ 1354 /* STATE_START */
1344 message->state = STATE_RUNNING; 1355 message->state = STATE_RUNNING;
@@ -1377,7 +1388,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
1377 1388
1378 /* Enable target chip, if not already active */ 1389 /* Enable target chip, if not already active */
1379 if (!pl022->next_msg_cs_active) 1390 if (!pl022->next_msg_cs_active)
1380 pl022->cur_chip->cs_control(SSP_CHIP_SELECT); 1391 pl022_cs_control(pl022, SSP_CHIP_SELECT);
1381 1392
1382 if (set_up_next_transfer(pl022, pl022->cur_transfer)) { 1393 if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
1383 /* Error path */ 1394 /* Error path */
@@ -1429,12 +1440,12 @@ static void do_polling_transfer(struct pl022 *pl022)
1429 if (previous->delay_usecs) 1440 if (previous->delay_usecs)
1430 udelay(previous->delay_usecs); 1441 udelay(previous->delay_usecs);
1431 if (previous->cs_change) 1442 if (previous->cs_change)
1432 pl022->cur_chip->cs_control(SSP_CHIP_SELECT); 1443 pl022_cs_control(pl022, SSP_CHIP_SELECT);
1433 } else { 1444 } else {
1434 /* STATE_START */ 1445 /* STATE_START */
1435 message->state = STATE_RUNNING; 1446 message->state = STATE_RUNNING;
1436 if (!pl022->next_msg_cs_active) 1447 if (!pl022->next_msg_cs_active)
1437 pl022->cur_chip->cs_control(SSP_CHIP_SELECT); 1448 pl022_cs_control(pl022, SSP_CHIP_SELECT);
1438 } 1449 }
1439 1450
1440 /* Configuration Changing Per Transfer */ 1451 /* Configuration Changing Per Transfer */
@@ -1466,7 +1477,7 @@ static void do_polling_transfer(struct pl022 *pl022)
1466 /* Update total byte transferred */ 1477 /* Update total byte transferred */
1467 message->actual_length += pl022->cur_transfer->len; 1478 message->actual_length += pl022->cur_transfer->len;
1468 if (pl022->cur_transfer->cs_change) 1479 if (pl022->cur_transfer->cs_change)
1469 pl022->cur_chip->cs_control(SSP_CHIP_DESELECT); 1480 pl022_cs_control(pl022, SSP_CHIP_DESELECT);
1470 /* Move to next transfer */ 1481 /* Move to next transfer */
1471 message->state = next_transfer(pl022); 1482 message->state = next_transfer(pl022);
1472 } 1483 }
@@ -1495,6 +1506,7 @@ static int pl022_transfer_one_message(struct spi_master *master,
1495 1506
1496 /* Setup the SPI using the per chip configuration */ 1507 /* Setup the SPI using the per chip configuration */
1497 pl022->cur_chip = spi_get_ctldata(msg->spi); 1508 pl022->cur_chip = spi_get_ctldata(msg->spi);
1509 pl022->cur_cs = pl022->chipselects[msg->spi->chip_select];
1498 1510
1499 restore_state(pl022); 1511 restore_state(pl022);
1500 flush(pl022); 1512 flush(pl022);
@@ -1840,8 +1852,9 @@ static int pl022_setup(struct spi_device *spi)
1840 chip->xfer_type = chip_info->com_mode; 1852 chip->xfer_type = chip_info->com_mode;
1841 if (!chip_info->cs_control) { 1853 if (!chip_info->cs_control) {
1842 chip->cs_control = null_cs_control; 1854 chip->cs_control = null_cs_control;
1843 dev_warn(&spi->dev, 1855 if (!gpio_is_valid(pl022->chipselects[spi->chip_select]))
1844 "chip select function is NULL for this chip\n"); 1856 dev_warn(&spi->dev,
1857 "invalid chip select\n");
1845 } else 1858 } else
1846 chip->cs_control = chip_info->cs_control; 1859 chip->cs_control = chip_info->cs_control;
1847 1860
@@ -1993,7 +2006,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
1993 struct pl022_ssp_controller *platform_info = adev->dev.platform_data; 2006 struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
1994 struct spi_master *master; 2007 struct spi_master *master;
1995 struct pl022 *pl022 = NULL; /*Data for this driver */ 2008 struct pl022 *pl022 = NULL; /*Data for this driver */
1996 int status = 0; 2009 int status = 0, i;
1997 2010
1998 dev_info(&adev->dev, 2011 dev_info(&adev->dev,
1999 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid); 2012 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
@@ -2004,7 +2017,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2004 } 2017 }
2005 2018
2006 /* Allocate master with space for data */ 2019 /* Allocate master with space for data */
2007 master = spi_alloc_master(dev, sizeof(struct pl022)); 2020 master = spi_alloc_master(dev, sizeof(struct pl022) + sizeof(int) *
2021 platform_info->num_chipselect);
2008 if (master == NULL) { 2022 if (master == NULL) {
2009 dev_err(&adev->dev, "probe - cannot alloc SPI master\n"); 2023 dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
2010 status = -ENOMEM; 2024 status = -ENOMEM;
@@ -2016,6 +2030,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2016 pl022->master_info = platform_info; 2030 pl022->master_info = platform_info;
2017 pl022->adev = adev; 2031 pl022->adev = adev;
2018 pl022->vendor = id->data; 2032 pl022->vendor = id->data;
2033 /* Point chipselects to allocated memory beyond the main struct */
2034 pl022->chipselects = (int *) pl022 + sizeof(struct pl022);
2019 2035
2020 /* 2036 /*
2021 * Bus Number Which has been Assigned to this SSP controller 2037 * Bus Number Which has been Assigned to this SSP controller
@@ -2030,6 +2046,10 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
2030 master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; 2046 master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
2031 master->rt = platform_info->rt; 2047 master->rt = platform_info->rt;
2032 2048
2049 if (platform_info->num_chipselect && platform_info->chipselects)
2050 for (i = 0; i < platform_info->num_chipselect; i++)
2051 pl022->chipselects[i] = platform_info->chipselects[i];
2052
2033 /* 2053 /*
2034 * Supports mode 0-3, loopback, and active low CS. Transfers are 2054 * Supports mode 0-3, loopback, and active low CS. Transfers are
2035 * always MS bit first on the original pl022. 2055 * always MS bit first on the original pl022.