IMX Spi and 24bit data.
bpringle at sympatico.ca
bpringle at sympatico.ca
Tue Nov 9 11:42:17 EST 2010
Below is a 'example' patch to the imx SPI driver. The issue is that
soc-cache.c for 24bit SPI values only creates byte arrays of size
three. The IMX SPI driver examines memory that is 32 bits for this
case and could possibly cause a trap if the final byte of the array is
at a unmapped location. (also, the data is possibly not aligned).
I guess the main question is the 'spi.h' interface expecting a padding
to 32bits for 24bit values. In this case, soc-cache is wrong. But I
suspect that the spi systems is expecting packed data.
Also, I looked in little_endian.h for some thing appropriate. Do we
have a 24bit extraction macro somewhere?. I guess soc-core would be
using this if we did.
Sorry, if this is a known issue.
Regards,
Bill Pringlemeir.
I see my tabs are all messed up too. I just want to know if this is
the approriate way to handle this. My byte order may be messed up as
I haven't tested this... I have just padded soc-core.c for now.
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 7972e90..54c6a5a 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -116,6 +116,31 @@ MXC_SPI_BUF_TX(u16)
MXC_SPI_BUF_RX(u32)
MXC_SPI_BUF_TX(u32)
+static void spi_imx_buf_rx_u24(struct spi_imx_data *spi_imx)
+{
+ unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);
+ if (spi_imx->rx_buf) {
+ u8 *data = (u8 *)spi_imx->rx_buf;
+ data[0] = (val >> 16) & 0xff;
+ data[1] = (val >> 8) & 0xff;
+ data[2] = val & 0xff;
+ spi_imx->rx_buf += 3;
+ }
+}
+
+static void spi_imx_buf_tx_u24(struct spi_imx_data *spi_imx)
+{
+ u32 val = 0;
+
+ if (spi_imx->tx_buf) {
+ u8 *data = (u8 *)spi_imx->rx_buf;
+ val = data[0] << 16 | data[1] << 8 | data[0];
+ spi_imx->tx_buf += 3;
+ }
+ spi_imx->count -= 3;
+ writel(val, spi_imx->base + MXC_CSPITXDATA);
+}
+
/* First entry is reserved, second entry is valid only if SDHC_SPIEN is set
* (which is currently not the case in this driver)
*/
@@ -433,6 +458,11 @@ static int spi_imx_setupxfer(struct spi_device *spi,
} else if (config.bpw <= 16) {
spi_imx->rx = spi_imx_buf_rx_u16;
spi_imx->tx = spi_imx_buf_tx_u16;
+#if 0
+ } else if (config.bpw <= 24) {
+ spi_imx->rx = spi_imx_buf_rx_u24;
+ spi_imx->tx = spi_imx_buf_tx_u24;
+#endif
} else if (config.bpw <= 32) {
spi_imx->rx = spi_imx_buf_rx_u32;
spi_imx->tx = spi_imx_buf_tx_u32;
More information about the linux-arm-kernel
mailing list