aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-atmel.c
diff options
context:
space:
mode:
authorRichard Genoud <richard.genoud@gmail.com>2013-11-07 04:34:06 -0500
committerMark Brown <broonie@linaro.org>2014-01-08 08:00:24 -0500
commitd3b72c7e6bf33185a5de1db2164ff237759c554c (patch)
tree3424f0cf9ddffe2a236bb1da8a4182e990fc7013 /drivers/spi/spi-atmel.c
parent9f87d6f26b2fcedfc3d1ec6c65ce568b21546ee2 (diff)
spi: atmel: add support for changing message transfer speed
The only speed available was max_speed (the maximum speed declared for a device). This patch adds the support for spi_tranfer->speed_hz parameter. We can now set a different speed for each spi message. Signed-off-by: Richard Genoud <richard.genoud@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-atmel.c')
-rw-r--r--drivers/spi/spi-atmel.c92
1 files changed, 55 insertions, 37 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 57fa73876223..b96f9a89cdc6 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -694,6 +694,54 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
694 *plen = len; 694 *plen = len;
695} 695}
696 696
697static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
698 struct spi_device *spi,
699 struct spi_transfer *xfer)
700{
701 u32 scbr, csr;
702 unsigned long bus_hz;
703
704 /* v1 chips start out at half the peripheral bus speed. */
705 bus_hz = clk_get_rate(as->clk);
706 if (!atmel_spi_is_v2(as))
707 bus_hz /= 2;
708
709 /*
710 * Calculate the lowest divider that satisfies the
711 * constraint, assuming div32/fdiv/mbz == 0.
712 */
713 if (xfer->speed_hz)
714 scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
715 else
716 /*
717 * This can happend if max_speed is null.
718 * In this case, we set the lowest possible speed
719 */
720 scbr = 0xff;
721
722 /*
723 * If the resulting divider doesn't fit into the
724 * register bitfield, we can't satisfy the constraint.
725 */
726 if (scbr >= (1 << SPI_SCBR_SIZE)) {
727 dev_err(&spi->dev,
728 "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
729 xfer->speed_hz, scbr, bus_hz/255);
730 return -EINVAL;
731 }
732 if (scbr == 0) {
733 dev_err(&spi->dev,
734 "setup: %d Hz too high, scbr %u; max %ld Hz\n",
735 xfer->speed_hz, scbr, bus_hz);
736 return -EINVAL;
737 }
738 csr = spi_readl(as, CSR0 + 4 * spi->chip_select);
739 csr = SPI_BFINS(SCBR, scbr, csr);
740 spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
741
742 return 0;
743}
744
697/* 745/*
698 * Submit next transfer for PDC. 746 * Submit next transfer for PDC.
699 * lock is held, spi irq is blocked 747 * lock is held, spi irq is blocked
@@ -731,6 +779,8 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
731 spi_writel(as, RCR, len); 779 spi_writel(as, RCR, len);
732 spi_writel(as, TCR, len); 780 spi_writel(as, TCR, len);
733 781
782 atmel_spi_set_xfer_speed(as, msg->spi, xfer);
783
734 dev_dbg(&msg->spi->dev, 784 dev_dbg(&msg->spi->dev,
735 " start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", 785 " start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
736 xfer, xfer->len, xfer->tx_buf, 786 xfer, xfer->len, xfer->tx_buf,
@@ -823,6 +873,7 @@ static void atmel_spi_dma_next_xfer(struct spi_master *master,
823 873
824 as->current_transfer = xfer; 874 as->current_transfer = xfer;
825 len = xfer->len; 875 len = xfer->len;
876 atmel_spi_set_xfer_speed(as, msg->spi, xfer);
826 } 877 }
827 878
828 if (atmel_spi_use_dma(as, xfer)) { 879 if (atmel_spi_use_dma(as, xfer)) {
@@ -1264,9 +1315,8 @@ static int atmel_spi_setup(struct spi_device *spi)
1264{ 1315{
1265 struct atmel_spi *as; 1316 struct atmel_spi *as;
1266 struct atmel_spi_device *asd; 1317 struct atmel_spi_device *asd;
1267 u32 scbr, csr; 1318 u32 csr;
1268 unsigned int bits = spi->bits_per_word; 1319 unsigned int bits = spi->bits_per_word;
1269 unsigned long bus_hz;
1270 unsigned int npcs_pin; 1320 unsigned int npcs_pin;
1271 int ret; 1321 int ret;
1272 1322
@@ -1290,33 +1340,7 @@ static int atmel_spi_setup(struct spi_device *spi)
1290 return -EINVAL; 1340 return -EINVAL;
1291 } 1341 }
1292 1342
1293 /* v1 chips start out at half the peripheral bus speed. */ 1343 csr = SPI_BF(BITS, bits - 8);
1294 bus_hz = clk_get_rate(as->clk);
1295 if (!atmel_spi_is_v2(as))
1296 bus_hz /= 2;
1297
1298 if (spi->max_speed_hz) {
1299 /*
1300 * Calculate the lowest divider that satisfies the
1301 * constraint, assuming div32/fdiv/mbz == 0.
1302 */
1303 scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
1304
1305 /*
1306 * If the resulting divider doesn't fit into the
1307 * register bitfield, we can't satisfy the constraint.
1308 */
1309 if (scbr >= (1 << SPI_SCBR_SIZE)) {
1310 dev_dbg(&spi->dev,
1311 "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
1312 spi->max_speed_hz, scbr, bus_hz/255);
1313 return -EINVAL;
1314 }
1315 } else
1316 /* speed zero means "as slow as possible" */
1317 scbr = 0xff;
1318
1319 csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
1320 if (spi->mode & SPI_CPOL) 1344 if (spi->mode & SPI_CPOL)
1321 csr |= SPI_BIT(CPOL); 1345 csr |= SPI_BIT(CPOL);
1322 if (!(spi->mode & SPI_CPHA)) 1346 if (!(spi->mode & SPI_CPHA))
@@ -1363,8 +1387,8 @@ static int atmel_spi_setup(struct spi_device *spi)
1363 asd->csr = csr; 1387 asd->csr = csr;
1364 1388
1365 dev_dbg(&spi->dev, 1389 dev_dbg(&spi->dev,
1366 "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n", 1390 "setup: bpw %u mode 0x%x -> csr%d %08x\n",
1367 bus_hz / scbr, bits, spi->mode, spi->chip_select, csr); 1391 bits, spi->mode, spi->chip_select, csr);
1368 1392
1369 if (!atmel_spi_is_v2(as)) 1393 if (!atmel_spi_is_v2(as))
1370 spi_writel(as, CSR0 + 4 * spi->chip_select, csr); 1394 spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
@@ -1414,12 +1438,6 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
1414 } 1438 }
1415 } 1439 }
1416 1440
1417 /* FIXME implement these protocol options!! */
1418 if (xfer->speed_hz < spi->max_speed_hz) {
1419 dev_dbg(&spi->dev, "can't change speed in transfer\n");
1420 return -ENOPROTOOPT;
1421 }
1422
1423 /* 1441 /*
1424 * DMA map early, for performance (empties dcache ASAP) and 1442 * DMA map early, for performance (empties dcache ASAP) and
1425 * better fault reporting. 1443 * better fault reporting.