diff options
author | wangyuhang <wangyuhang2014@gmail.com> | 2013-08-11 06:15:17 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-22 08:47:29 -0400 |
commit | f477b7fb13df2b843997559ff34e87d054ba6538 (patch) | |
tree | 137825623bdd941ebd91a22f985c0352ee83a211 | |
parent | 56ede94a000bb9635b326db38baf66da6dfc174e (diff) |
spi: DUAL and QUAD support
fix the previous patch some mistake below:
1. DT in slave node, use "spi-tx-nbits = <1/2/4>" in place of using
"spi-tx-dual, spi-tx-quad" directly, same to rx. So correct the
previous way to get the property in @of_register_spi_devices().
2. Change the value of transfer bit macro(SPI_NBITS_SINGLE, SPI_NBITS_DUAL
SPI_NBITS_QUAD) to 0x01, 0x02 and 0x04 to match the actual wires.
3. Add the following check
(1)keep the tx_nbits and rx_nbits in spi_transfer is not beyond the
single, dual and quad.
(2)keep tx_nbits and rx_nbits are contained by @spi_device->mode
example: if @spi_device->mode = DUAL, then tx/rx_nbits can not be set
to QUAD(SPI_NBITS_QUAD)
(3)if "@spi_device->mode & SPI_3WIRE", then tx/rx_nbits should be in
single(SPI_NBITS_SINGLE)
Signed-off-by: wangyuhang <wangyuhang2014@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | drivers/spi/spi.c | 96 | ||||
-rw-r--r-- | include/linux/spi/spi.h | 22 |
2 files changed, 116 insertions, 2 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2a20c32c8277..39d38756e984 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -869,6 +869,51 @@ static void of_register_spi_devices(struct spi_master *master) | |||
869 | if (of_find_property(nc, "spi-3wire", NULL)) | 869 | if (of_find_property(nc, "spi-3wire", NULL)) |
870 | spi->mode |= SPI_3WIRE; | 870 | spi->mode |= SPI_3WIRE; |
871 | 871 | ||
872 | /* Device DUAL/QUAD mode */ | ||
873 | prop = of_get_property(nc, "spi-tx-nbits", &len); | ||
874 | if (!prop || len < sizeof(*prop)) { | ||
875 | dev_err(&master->dev, "%s has no 'spi-tx-nbits' property\n", | ||
876 | nc->full_name); | ||
877 | spi_dev_put(spi); | ||
878 | continue; | ||
879 | } | ||
880 | switch (be32_to_cpup(prop)) { | ||
881 | case SPI_NBITS_SINGLE: | ||
882 | break; | ||
883 | case SPI_NBITS_DUAL: | ||
884 | spi->mode |= SPI_TX_DUAL; | ||
885 | break; | ||
886 | case SPI_NBITS_QUAD: | ||
887 | spi->mode |= SPI_TX_QUAD; | ||
888 | break; | ||
889 | default: | ||
890 | dev_err(&master->dev, "spi-tx-nbits value is not supported\n"); | ||
891 | spi_dev_put(spi); | ||
892 | continue; | ||
893 | } | ||
894 | |||
895 | prop = of_get_property(nc, "spi-rx-nbits", &len); | ||
896 | if (!prop || len < sizeof(*prop)) { | ||
897 | dev_err(&master->dev, "%s has no 'spi-rx-nbits' property\n", | ||
898 | nc->full_name); | ||
899 | spi_dev_put(spi); | ||
900 | continue; | ||
901 | } | ||
902 | switch (be32_to_cpup(prop)) { | ||
903 | case SPI_NBITS_SINGLE: | ||
904 | break; | ||
905 | case SPI_NBITS_DUAL: | ||
906 | spi->mode |= SPI_RX_DUAL; | ||
907 | break; | ||
908 | case SPI_NBITS_QUAD: | ||
909 | spi->mode |= SPI_RX_QUAD; | ||
910 | break; | ||
911 | default: | ||
912 | dev_err(&master->dev, "spi-rx-nbits value is not supported\n"); | ||
913 | spi_dev_put(spi); | ||
914 | continue; | ||
915 | } | ||
916 | |||
872 | /* Device speed */ | 917 | /* Device speed */ |
873 | prop = of_get_property(nc, "spi-max-frequency", &len); | 918 | prop = of_get_property(nc, "spi-max-frequency", &len); |
874 | if (!prop || len < sizeof(*prop)) { | 919 | if (!prop || len < sizeof(*prop)) { |
@@ -1316,6 +1361,19 @@ int spi_setup(struct spi_device *spi) | |||
1316 | unsigned bad_bits; | 1361 | unsigned bad_bits; |
1317 | int status = 0; | 1362 | int status = 0; |
1318 | 1363 | ||
1364 | /* check mode to prevent that DUAL and QUAD set at the same time | ||
1365 | */ | ||
1366 | if (((spi->mode & SPI_TX_DUAL) && (spi->mode & SPI_TX_QUAD)) || | ||
1367 | ((spi->mode & SPI_RX_DUAL) && (spi->mode & SPI_RX_QUAD))) { | ||
1368 | dev_err(&spi->dev, | ||
1369 | "setup: can not select dual and quad at the same time\n"); | ||
1370 | return -EINVAL; | ||
1371 | } | ||
1372 | /* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden | ||
1373 | */ | ||
1374 | if ((spi->mode & SPI_3WIRE) && (spi->mode & | ||
1375 | (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD))) | ||
1376 | return -EINVAL; | ||
1319 | /* help drivers fail *cleanly* when they need options | 1377 | /* help drivers fail *cleanly* when they need options |
1320 | * that aren't supported with their current master | 1378 | * that aren't supported with their current master |
1321 | */ | 1379 | */ |
@@ -1378,6 +1436,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1378 | /** | 1436 | /** |
1379 | * Set transfer bits_per_word and max speed as spi device default if | 1437 | * Set transfer bits_per_word and max speed as spi device default if |
1380 | * it is not set for this transfer. | 1438 | * it is not set for this transfer. |
1439 | * Set transfer tx_nbits and rx_nbits as single transfer default | ||
1440 | * (SPI_NBITS_SINGLE) if it is not set for this transfer. | ||
1381 | */ | 1441 | */ |
1382 | list_for_each_entry(xfer, &message->transfers, transfer_list) { | 1442 | list_for_each_entry(xfer, &message->transfers, transfer_list) { |
1383 | if (!xfer->bits_per_word) | 1443 | if (!xfer->bits_per_word) |
@@ -1403,6 +1463,42 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1403 | return -EINVAL; | 1463 | return -EINVAL; |
1404 | if (xfer->speed_hz && master->max_speed_hz && | 1464 | if (xfer->speed_hz && master->max_speed_hz && |
1405 | xfer->speed_hz > master->max_speed_hz) | 1465 | xfer->speed_hz > master->max_speed_hz) |
1466 | |||
1467 | if (xfer->tx_buf && !xfer->tx_nbits) | ||
1468 | xfer->tx_nbits = SPI_NBITS_SINGLE; | ||
1469 | if (xfer->rx_buf && !xfer->rx_nbits) | ||
1470 | xfer->rx_nbits = SPI_NBITS_SINGLE; | ||
1471 | /* check transfer tx/rx_nbits: | ||
1472 | * 1. keep the value is not out of single, dual and quad | ||
1473 | * 2. keep tx/rx_nbits is contained by mode in spi_device | ||
1474 | * 3. if SPI_3WIRE, tx/rx_nbits should be in single | ||
1475 | */ | ||
1476 | if (xfer->tx_nbits != SPI_NBITS_SINGLE && | ||
1477 | xfer->tx_nbits != SPI_NBITS_DUAL && | ||
1478 | xfer->tx_nbits != SPI_NBITS_QUAD) | ||
1479 | return -EINVAL; | ||
1480 | if ((xfer->tx_nbits == SPI_NBITS_DUAL) && | ||
1481 | !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) | ||
1482 | return -EINVAL; | ||
1483 | if ((xfer->tx_nbits == SPI_NBITS_QUAD) && | ||
1484 | !(spi->mode & SPI_TX_QUAD)) | ||
1485 | return -EINVAL; | ||
1486 | if ((spi->mode & SPI_3WIRE) && | ||
1487 | (xfer->tx_nbits != SPI_NBITS_SINGLE)) | ||
1488 | return -EINVAL; | ||
1489 | /* check transfer rx_nbits */ | ||
1490 | if (xfer->rx_nbits != SPI_NBITS_SINGLE && | ||
1491 | xfer->rx_nbits != SPI_NBITS_DUAL && | ||
1492 | xfer->rx_nbits != SPI_NBITS_QUAD) | ||
1493 | return -EINVAL; | ||
1494 | if ((xfer->rx_nbits == SPI_NBITS_DUAL) && | ||
1495 | !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) | ||
1496 | return -EINVAL; | ||
1497 | if ((xfer->rx_nbits == SPI_NBITS_QUAD) && | ||
1498 | !(spi->mode & SPI_RX_QUAD)) | ||
1499 | return -EINVAL; | ||
1500 | if ((spi->mode & SPI_3WIRE) && | ||
1501 | (xfer->rx_nbits != SPI_NBITS_SINGLE)) | ||
1406 | return -EINVAL; | 1502 | return -EINVAL; |
1407 | } | 1503 | } |
1408 | 1504 | ||
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index cdf668156154..ccd7840c4507 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
@@ -74,7 +74,7 @@ struct spi_device { | |||
74 | struct spi_master *master; | 74 | struct spi_master *master; |
75 | u32 max_speed_hz; | 75 | u32 max_speed_hz; |
76 | u8 chip_select; | 76 | u8 chip_select; |
77 | u8 mode; | 77 | u16 mode; |
78 | #define SPI_CPHA 0x01 /* clock phase */ | 78 | #define SPI_CPHA 0x01 /* clock phase */ |
79 | #define SPI_CPOL 0x02 /* clock polarity */ | 79 | #define SPI_CPOL 0x02 /* clock polarity */ |
80 | #define SPI_MODE_0 (0|0) /* (original MicroWire) */ | 80 | #define SPI_MODE_0 (0|0) /* (original MicroWire) */ |
@@ -87,6 +87,10 @@ struct spi_device { | |||
87 | #define SPI_LOOP 0x20 /* loopback mode */ | 87 | #define SPI_LOOP 0x20 /* loopback mode */ |
88 | #define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */ | 88 | #define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */ |
89 | #define SPI_READY 0x80 /* slave pulls low to pause */ | 89 | #define SPI_READY 0x80 /* slave pulls low to pause */ |
90 | #define SPI_TX_DUAL 0x100 /* transmit with 2 wires */ | ||
91 | #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ | ||
92 | #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ | ||
93 | #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ | ||
90 | u8 bits_per_word; | 94 | u8 bits_per_word; |
91 | int irq; | 95 | int irq; |
92 | void *controller_state; | 96 | void *controller_state; |
@@ -454,6 +458,10 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); | |||
454 | * @rx_buf: data to be read (dma-safe memory), or NULL | 458 | * @rx_buf: data to be read (dma-safe memory), or NULL |
455 | * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped | 459 | * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped |
456 | * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped | 460 | * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped |
461 | * @tx_nbits: number of bits used for writting. If 0 the default | ||
462 | * (SPI_NBITS_SINGLE) is used. | ||
463 | * @rx_nbits: number of bits used for reading. If 0 the default | ||
464 | * (SPI_NBITS_SINGLE) is used. | ||
457 | * @len: size of rx and tx buffers (in bytes) | 465 | * @len: size of rx and tx buffers (in bytes) |
458 | * @speed_hz: Select a speed other than the device default for this | 466 | * @speed_hz: Select a speed other than the device default for this |
459 | * transfer. If 0 the default (from @spi_device) is used. | 467 | * transfer. If 0 the default (from @spi_device) is used. |
@@ -508,6 +516,11 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); | |||
508 | * by the results of previous messages and where the whole transaction | 516 | * by the results of previous messages and where the whole transaction |
509 | * ends when the chipselect goes intactive. | 517 | * ends when the chipselect goes intactive. |
510 | * | 518 | * |
519 | * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information | ||
520 | * from device through @tx_nbits and @rx_nbits. In Bi-direction, these | ||
521 | * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x) | ||
522 | * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer. | ||
523 | * | ||
511 | * The code that submits an spi_message (and its spi_transfers) | 524 | * The code that submits an spi_message (and its spi_transfers) |
512 | * to the lower layers is responsible for managing its memory. | 525 | * to the lower layers is responsible for managing its memory. |
513 | * Zero-initialize every field you don't set up explicitly, to | 526 | * Zero-initialize every field you don't set up explicitly, to |
@@ -528,6 +541,11 @@ struct spi_transfer { | |||
528 | dma_addr_t rx_dma; | 541 | dma_addr_t rx_dma; |
529 | 542 | ||
530 | unsigned cs_change:1; | 543 | unsigned cs_change:1; |
544 | u8 tx_nbits; | ||
545 | u8 rx_nbits; | ||
546 | #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */ | ||
547 | #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */ | ||
548 | #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */ | ||
531 | u8 bits_per_word; | 549 | u8 bits_per_word; |
532 | u16 delay_usecs; | 550 | u16 delay_usecs; |
533 | u32 speed_hz; | 551 | u32 speed_hz; |
@@ -875,7 +893,7 @@ struct spi_board_info { | |||
875 | /* mode becomes spi_device.mode, and is essential for chips | 893 | /* mode becomes spi_device.mode, and is essential for chips |
876 | * where the default of SPI_CS_HIGH = 0 is wrong. | 894 | * where the default of SPI_CS_HIGH = 0 is wrong. |
877 | */ | 895 | */ |
878 | u8 mode; | 896 | u16 mode; |
879 | 897 | ||
880 | /* ... may need additional spi_device chip config data here. | 898 | /* ... may need additional spi_device chip config data here. |
881 | * avoid stuff protocol drivers can set; but include stuff | 899 | * avoid stuff protocol drivers can set; but include stuff |