summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorchao bi <chao.bi@intel.com>2012-10-25 09:02:32 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-25 11:29:58 -0700
commit319fb0d21907f771d8ccdb6177fb2fcafabc6ab4 (patch)
tree9f6293ef3a34c288ad25a9638ec6bc463027d3cb /drivers/tty/serial
parentde609582072af195673e72d9e7647d5cba8eb7e4 (diff)
serial: ifx6x60: different SPI word width configure requires different swap process
SPI protocol driver only provide one function (swap_buf()) to swap SPI data into big endian format, which is only available when SPI controller's word width is 16 bits. But word width could be configured as 8/16/32 bits, different word width configure should be mapped to different swap methods.This patch is to make SPI protocol driver choose the right swap function corresponding to SPI word width configuration. cc: liu chuansheng <chuansheng.liu@intel.com> cc: Chen Jun <jun.d.chen@intel.com> Signed-off-by: channing <chao.bi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/ifx6x60.c70
-rw-r--r--drivers/tty/serial/ifx6x60.h1
2 files changed, 61 insertions, 10 deletions
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 5b9bc19ed134..2d2bcbd80670 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 = cpu_to_be16(*buf);
- buf++;
+ *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_32 = cpu_to_be32(*buf_32);
+ buf_32++;
}
}
@@ -449,7 +490,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;
}
@@ -617,7 +658,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 +677,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(
@@ -1001,6 +1043,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;
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index e8464baf9e75..d8869f5a4632 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -124,6 +124,7 @@ struct ifx_spi_device {
#define MR_INPROGRESS 1
#define MR_COMPLETE 2
wait_queue_head_t mdm_reset_wait;
+ void (*swap_buf)(unsigned char *buf, int len, void *end);
};
#endif /* _IFX6X60_H */