summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/ifx6x60.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/ifx6x60.c')
-rw-r--r--drivers/tty/serial/ifx6x60.c87
1 files changed, 72 insertions, 15 deletions
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19..fbda374 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -152,26 +152,67 @@ ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
}
/**
- * swap_buf
+ * swap_buf_8
* @buf: our buffer
* @len : number of bytes (not words) in the buffer
* @end: end of buffer
*
* Swap the contents of a buffer into big endian format
*/
-static inline void swap_buf(u16 *buf, int len, void *end)
+static inline void swap_buf_8(unsigned char *buf, int len, void *end)
+{
+ /* don't swap buffer if SPI word width is 8 bits */
+ return;
+}
+
+/**
+ * swap_buf_16
+ * @buf: our buffer
+ * @len : number of bytes (not words) in the buffer
+ * @end: end of buffer
+ *
+ * Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_16(unsigned char *buf, int len, void *end)
{
int n;
+ u16 *buf_16 = (u16 *)buf;
len = ((len + 1) >> 1);
- if ((void *)&buf[len] > end) {
- pr_err("swap_buf: swap exceeds boundary (%p > %p)!",
- &buf[len], end);
+ if ((void *)&buf_16[len] > end) {
+ pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!",
+ &buf_16[len], end);
+ return;
+ }
+ for (n = 0; n < len; n++) {
+ *buf_16 = cpu_to_be16(*buf_16);
+ buf_16++;
+ }
+}
+
+/**
+ * swap_buf_32
+ * @buf: our buffer
+ * @len : number of bytes (not words) in the buffer
+ * @end: end of buffer
+ *
+ * Swap the contents of a buffer into big endian format
+ */
+static inline void swap_buf_32(unsigned char *buf, int len, void *end)
+{
+ int n;
+
+ u32 *buf_32 = (u32 *)buf;
+ len = (len + 3) >> 2;
+
+ if ((void *)&buf_32[len] > end) {
+ pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n",
+ &buf_32[len], end);
return;
}
for (n = 0; n < len; n++) {
- *buf = cpu_to_be16(*buf);
- buf++;
+ *buf_32 = cpu_to_be32(*buf_32);
+ buf_32++;
}
}
@@ -190,9 +231,7 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
if (!val) {
if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
&ifx_dev->flags)) {
- ifx_dev->spi_timer.expires =
- jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
- add_timer(&ifx_dev->spi_timer);
+ mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ);
}
}
@@ -449,7 +488,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
tx_count-IFX_SPI_HEADER_OVERHEAD,
ifx_dev->spi_more);
/* swap actual data in the buffer */
- swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count,
+ ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count,
&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
return tx_count;
}
@@ -530,12 +569,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
/* clear any old data; can't do this in 'close' */
kfifo_reset(&ifx_dev->tx_fifo);
+ /* clear any flag which may be set in port shutdown procedure */
+ clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
+ clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
+
/* put port data into this tty */
tty->driver_data = ifx_dev;
/* allows flip string push from int context */
tty->low_latency = 1;
+ /* set flag to allows data transfer */
+ set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
+
return 0;
}
@@ -551,6 +597,7 @@ static void ifx_port_shutdown(struct tty_port *port)
struct ifx_spi_device *ifx_dev =
container_of(port, struct ifx_spi_device, tty_port);
+ clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
mrdy_set_low(ifx_dev);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
tasklet_kill(&ifx_dev->io_work_tasklet);
@@ -617,7 +664,7 @@ static void ifx_spi_complete(void *ctx)
if (!ifx_dev->spi_msg.status) {
/* check header validity, get comm flags */
- swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
+ ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
&length, &more, &cts);
@@ -636,7 +683,8 @@ static void ifx_spi_complete(void *ctx)
actual_length = min((unsigned int)length,
ifx_dev->spi_msg.actual_length);
- swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
+ ifx_dev->swap_buf(
+ (ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
actual_length,
&ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
ifx_spi_insert_flip_string(
@@ -705,7 +753,8 @@ static void ifx_spi_io(unsigned long data)
int retval;
struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
- if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) {
+ if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
+ test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
if (ifx_dev->gpio.unack_srdy_int_nb > 0)
ifx_dev->gpio.unack_srdy_int_nb--;
@@ -826,7 +875,7 @@ error_ret:
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
{
if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
- del_timer_sync(&ifx_dev->spi_timer);
+ del_timer(&ifx_dev->spi_timer);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
}
@@ -1001,6 +1050,14 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV;
}
+ /* init swap_buf function according to word width configuration */
+ if (spi->bits_per_word == 32)
+ ifx_dev->swap_buf = swap_buf_32;
+ else if (spi->bits_per_word == 16)
+ ifx_dev->swap_buf = swap_buf_16;
+ else
+ ifx_dev->swap_buf = swap_buf_8;
+
/* ensure SPI protocol flags are initialized to enable transfer */
ifx_dev->spi_more = 0;
ifx_dev->spi_slave_cts = 0;