263 lines
7.6 KiB
Diff
263 lines
7.6 KiB
Diff
--- a/include/linux/spi/spi.h 2009-12-04 07:00:07.000000000 +0100
|
|
+++ b/include/linux/spi/spi.h 2011-01-18 14:30:48.919450001 +0100
|
|
@@ -68,6 +68,7 @@
|
|
struct device dev;
|
|
struct spi_master *master;
|
|
u32 max_speed_hz;
|
|
+ u16 delay_usecs;
|
|
u8 chip_select;
|
|
u8 mode;
|
|
#define SPI_CPHA 0x01 /* clock phase */
|
|
--- a/include/linux/spi/spidev.h 2009-12-04 07:00:07.000000000 +0100
|
|
+++ b/include/linux/spi/spidev.h 2011-01-18 14:09:47.719449999 +0100
|
|
@@ -124,6 +124,8 @@
|
|
#define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32)
|
|
#define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32)
|
|
|
|
-
|
|
+/* Read / Write SPI device default delay us */
|
|
+#define SPI_IOC_RD_DELAY_US _IOR(SPI_IOC_MAGIC, 5, __u32)
|
|
+#define SPI_IOC_WR_DELAY_US _IOW(SPI_IOC_MAGIC, 5, __u32)
|
|
|
|
#endif /* SPIDEV_H */
|
|
--- a/include/linux/spi/spi_bitbang.h 2009-12-04 07:00:07.000000000 +0100
|
|
+++ b/include/linux/spi/spi_bitbang.h 2011-01-18 13:33:26.731450001 +0100
|
|
@@ -50,7 +50,7 @@
|
|
|
|
/* txrx_word[SPI_MODE_*]() just looks like a shift register */
|
|
u32 (*txrx_word[4])(struct spi_device *spi,
|
|
- unsigned nsecs,
|
|
+ unsigned bit_delay, unsigned byte_delay,
|
|
u32 word, u8 bits);
|
|
};
|
|
|
|
@@ -102,20 +102,22 @@
|
|
|
|
static inline u32
|
|
bitbang_txrx_be_cpha0(struct spi_device *spi,
|
|
- unsigned nsecs, unsigned cpol,
|
|
- u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay,
|
|
+ unsigned cpol, u32 word, u8 bits)
|
|
{
|
|
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
|
|
|
|
+ spidelay(byte_delay);
|
|
+
|
|
/* clock starts at inactive polarity */
|
|
for (word <<= (32 - bits); likely(bits); bits--) {
|
|
|
|
/* setup MSB (to slave) on trailing edge */
|
|
setmosi(spi, word & (1 << 31));
|
|
- spidelay(nsecs); /* T(setup) */
|
|
+ spidelay(bit_delay); /* T(setup) */
|
|
|
|
setsck(spi, !cpol);
|
|
- spidelay(nsecs);
|
|
+ spidelay(bit_delay);
|
|
|
|
/* sample MSB (from slave) on leading edge */
|
|
word <<= 1;
|
|
@@ -127,21 +129,23 @@
|
|
|
|
static inline u32
|
|
bitbang_txrx_be_cpha1(struct spi_device *spi,
|
|
- unsigned nsecs, unsigned cpol,
|
|
- u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay,
|
|
+ unsigned cpol, u32 word, u8 bits)
|
|
{
|
|
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
|
|
|
|
+ spidelay(byte_delay);
|
|
+
|
|
/* clock starts at inactive polarity */
|
|
for (word <<= (32 - bits); likely(bits); bits--) {
|
|
|
|
/* setup MSB (to slave) on leading edge */
|
|
setsck(spi, !cpol);
|
|
setmosi(spi, word & (1 << 31));
|
|
- spidelay(nsecs); /* T(setup) */
|
|
+ spidelay(bit_delay); /* T(setup) */
|
|
|
|
setsck(spi, cpol);
|
|
- spidelay(nsecs);
|
|
+ spidelay(bit_delay);
|
|
|
|
/* sample MSB (from slave) on trailing edge */
|
|
word <<= 1;
|
|
--- a/drivers/spi/spidev.c 2009-12-04 07:00:07.000000000 +0100
|
|
+++ b/drivers/spi/spidev.c 2011-01-18 14:15:00.971449999 +0100
|
|
@@ -362,6 +362,9 @@
|
|
case SPI_IOC_RD_MAX_SPEED_HZ:
|
|
retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
|
|
break;
|
|
+ case SPI_IOC_RD_DELAY_US:
|
|
+ retval = __put_user(spi->delay_usecs, (__u32 __user *)arg);
|
|
+ break;
|
|
|
|
/* write requests */
|
|
case SPI_IOC_WR_MODE:
|
|
@@ -426,7 +429,19 @@
|
|
dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
|
|
}
|
|
break;
|
|
+ case SPI_IOC_WR_DELAY_US:
|
|
+ retval = __get_user(tmp, (__u32 __user *)arg);
|
|
+ if (retval == 0) {
|
|
+ u32 save = spi->delay_usecs;
|
|
|
|
+ spi->delay_usecs = tmp;
|
|
+ retval = spi_setup(spi);
|
|
+ if (retval < 0)
|
|
+ spi->delay_usecs = save;
|
|
+ else
|
|
+ dev_dbg(&spi->dev, "%d us delay\n", tmp);
|
|
+ }
|
|
+ break;
|
|
default:
|
|
/* segmented and/or full-duplex I/O request */
|
|
if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))
|
|
--- a/drivers/spi/spi_bitbang.c 2009-12-04 07:00:07.000000000 +0100
|
|
+++ b/drivers/spi/spi_bitbang.c 2011-01-18 20:53:42.079449999 +0100
|
|
@@ -49,12 +49,14 @@
|
|
|
|
struct spi_bitbang_cs {
|
|
unsigned nsecs; /* (clock cycle time)/2 */
|
|
- u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
|
|
+ u32 (*txrx_word)(struct spi_device *spi,
|
|
+ unsigned bit_delay, unsigned byte_delay,
|
|
u32 word, u8 bits);
|
|
unsigned (*txrx_bufs)(struct spi_device *,
|
|
u32 (*txrx_word)(
|
|
struct spi_device *spi,
|
|
- unsigned nsecs,
|
|
+ unsigned bit_delay,
|
|
+ unsigned byte_delay,
|
|
u32 word, u8 bits),
|
|
unsigned, struct spi_transfer *);
|
|
};
|
|
@@ -62,26 +64,42 @@
|
|
static unsigned bitbang_txrx_8(
|
|
struct spi_device *spi,
|
|
u32 (*txrx_word)(struct spi_device *spi,
|
|
- unsigned nsecs,
|
|
+ unsigned bit_delay, unsigned byte_delay,
|
|
u32 word, u8 bits),
|
|
- unsigned ns,
|
|
+ unsigned bit_delay,
|
|
struct spi_transfer *t
|
|
) {
|
|
unsigned bits = spi->bits_per_word;
|
|
unsigned count = t->len;
|
|
const u8 *tx = t->tx_buf;
|
|
u8 *rx = t->rx_buf;
|
|
+ unsigned byte_delay = spi->delay_usecs;
|
|
|
|
while (likely(count > 0)) {
|
|
u8 word = 0;
|
|
|
|
- if (tx)
|
|
+ if (unlikely(tx))
|
|
word = *tx++;
|
|
- word = txrx_word(spi, ns, word, bits);
|
|
- if (rx)
|
|
+ word = txrx_word(spi, bit_delay, byte_delay, word, bits);
|
|
+ if (likely(rx)) {
|
|
+ /* If we receive a 0x00, fetch one extra byte to sync
|
|
+ the state machine, then break out of the while loop. */
|
|
+ if (unlikely(!word)) {
|
|
+ txrx_word(spi, bit_delay, byte_delay, 0x00, bits); /* discard */
|
|
+ break;
|
|
+ }
|
|
+
|
|
*rx++ = word;
|
|
+ }
|
|
count -= 1;
|
|
}
|
|
+
|
|
+ if (unlikely(tx)) {
|
|
+ /* Signal the end of tx by sending two 0x00's. */
|
|
+ txrx_word(spi, bit_delay, byte_delay, 0x00, bits);
|
|
+ txrx_word(spi, bit_delay, byte_delay, 0x00, bits);
|
|
+ }
|
|
+
|
|
return t->len - count;
|
|
}
|
|
|
|
@@ -156,10 +174,10 @@
|
|
bits_per_word = spi->bits_per_word;
|
|
if (bits_per_word <= 8)
|
|
cs->txrx_bufs = bitbang_txrx_8;
|
|
- else if (bits_per_word <= 16)
|
|
+/* else if (bits_per_word <= 16)
|
|
cs->txrx_bufs = bitbang_txrx_16;
|
|
else if (bits_per_word <= 32)
|
|
- cs->txrx_bufs = bitbang_txrx_32;
|
|
+ cs->txrx_bufs = bitbang_txrx_32; */
|
|
else
|
|
return -EINVAL;
|
|
|
|
@@ -167,8 +185,8 @@
|
|
if (!hz)
|
|
hz = spi->max_speed_hz;
|
|
if (hz) {
|
|
- cs->nsecs = (1000000000/2) / hz;
|
|
- if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
|
|
+ cs->nsecs = (1000000/2) / hz;
|
|
+ if (cs->nsecs > (MAX_UDELAY_MS * 1000))
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -346,12 +364,6 @@
|
|
}
|
|
if (status > 0)
|
|
m->actual_length += status;
|
|
- if (status != t->len) {
|
|
- /* always report some kind of error */
|
|
- if (status >= 0)
|
|
- status = -EREMOTEIO;
|
|
- break;
|
|
- }
|
|
status = 0;
|
|
|
|
/* protocol tweaks before next transfer */
|
|
--- a/drivers/spi/spi_gpio.c 2010-12-14 01:02:26.673204002 +0100
|
|
+++ b/drivers/spi/spi_gpio.c 2011-01-18 13:29:17.915450000 +0100
|
|
@@ -156,27 +156,27 @@
|
|
*/
|
|
|
|
static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
|
|
- unsigned nsecs, u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay, u32 word, u8 bits)
|
|
{
|
|
- return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
|
|
+ return bitbang_txrx_be_cpha0(spi, bit_delay, byte_delay, 0, word, bits);
|
|
}
|
|
|
|
static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
|
|
- unsigned nsecs, u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay, u32 word, u8 bits)
|
|
{
|
|
- return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
|
|
+ return bitbang_txrx_be_cpha1(spi, bit_delay, byte_delay, 0, word, bits);
|
|
}
|
|
|
|
static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
|
|
- unsigned nsecs, u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay, u32 word, u8 bits)
|
|
{
|
|
- return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
|
|
+ return bitbang_txrx_be_cpha0(spi, bit_delay, byte_delay, 1, word, bits);
|
|
}
|
|
|
|
static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
|
|
- unsigned nsecs, u32 word, u8 bits)
|
|
+ unsigned bit_delay, unsigned byte_delay, u32 word, u8 bits)
|
|
{
|
|
- return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
|
|
+ return bitbang_txrx_be_cpha1(spi, bit_delay, byte_delay, 1, word, bits);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|