[U-Boot] [PATCH 1/2] SPI: mxc_spi: fix swapping bug and add missing swapping in unaligned rx case

We need to shift only one time in each cycle in the swapping loop for unaligned tx case. Currently two byte shift operations are performed in each loop cycle causing zero gaps in the transmited data, so not all data scheduled for transmition is actually transmited.
The proper swapping in unaligned rx case is missing, so add it as we need to put the received data into the rx buffer in the correct byte order.
Signed-off-by: Anatolij Gustschin agust@denx.de --- drivers/spi/mxc_spi.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index d558137..9ed2891 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -304,7 +304,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, /* Buffer is not 32-bit aligned */ if ((unsigned long)dout & 0x03) { data = 0; - for (i = 0; i < 4; i++, data <<= 8) { + for (i = 0; i < 4; i++) { data = (data << 8) | (*dout++ & 0xFF); } } else { @@ -337,11 +337,11 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, if (bitlen % 32) { data = reg_read(mxcs->base + MXC_CSPIRXDATA); cnt = (bitlen % 32) / 8; + data = cpu_to_be32(data) >> ((sizeof(data) - cnt) * 8); debug("SPI Rx unaligned: 0x%x\n", data); if (din) { - for (i = 0; i < cnt; i++, data >>= 8) { - *din++ = data & 0xFF; - } + memcpy(din, &data, cnt); + din += cnt; } nbytes -= cnt; }

The MXC SPI driver didn't calculate the SPI clock up to now and just used lowest possible divider 512 for DATA RATE in the control register. This results in very low transfer rates.
The patch adds code to calculate and setup the SPI clock frequency for transfers.
Signed-off-by: Anatolij Gustschin agust@denx.de --- drivers/spi/mxc_spi.c | 22 +++++++++++++++++++++- 1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 9ed2891..07c62c2 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -438,12 +438,25 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs) return cs; }
+u32 get_cspi_div(u32 div) +{ + int i; + + for (i = 0; i < 8; i++) { + if (div <= (4 << i)) + return i; + } + return i; +} + struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { unsigned int ctrl_reg; struct mxc_spi_slave *mxcs; int ret; + u32 clk_src; + u32 div;
if (bus >= ARRAY_SIZE(spi_bases)) return NULL; @@ -477,9 +490,16 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } #else + clk_src = mx31_get_ipg_clk(); + div = clk_src / max_hz; + div = get_cspi_div(div); + + debug("clk %d Hz, div %d, real clk %d Hz\n", + max_hz, div, clk_src / (4 << div)); + ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) | MXC_CSPICTRL_BITCOUNT(31) | - MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */ + MXC_CSPICTRL_DATARATE(div) | MXC_CSPICTRL_EN | MXC_CSPICTRL_MODE;

On 01/16/2011 07:17 PM, Anatolij Gustschin wrote:
The MXC SPI driver didn't calculate the SPI clock up to now and just used lowest possible divider 512 for DATA RATE in the control register. This results in very low transfer rates.
Hi August,
I sent last friday a patch for mxc_spi.c, too, adding support for mx35, and the two patches now conflict. Is it ok for you if I rebase your patch on top of mine and I post it again ?
Best Regards, Stefano

Hello Stefano,
On Mon, 17 Jan 2011 10:00:51 +0100 Stefano Babic sbabic@denx.de wrote:
On 01/16/2011 07:17 PM, Anatolij Gustschin wrote:
The MXC SPI driver didn't calculate the SPI clock up to now and just used lowest possible divider 512 for DATA RATE in the control register. This results in very low transfer rates.
Hi August,
I sent last friday a patch for mxc_spi.c, too, adding support for mx35, and the two patches now conflict. Is it ok for you if I rebase your patch on top of mine and I post it again ?
Yes, it is ok.
Thanks, Anatolij
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de

On Mon, 17 Jan 2011 10:30:09 +0100 Anatolij Gustschin agust@denx.de wrote:
Hello Stefano,
On Mon, 17 Jan 2011 10:00:51 +0100 Stefano Babic sbabic@denx.de wrote:
On 01/16/2011 07:17 PM, Anatolij Gustschin wrote:
The MXC SPI driver didn't calculate the SPI clock up to now and just used lowest possible divider 512 for DATA RATE in the control register. This results in very low transfer rates.
Hi August,
I sent last friday a patch for mxc_spi.c, too, adding support for mx35, and the two patches now conflict. Is it ok for you if I rebase your patch on top of mine and I post it again ?
Yes, it is ok.
BTW: While at it, could you then also please fix a mistake in the commit description: it should be "... just highest possible divider 512".
Thanks, Anatolij
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de

On 01/17/2011 10:36 AM, Anatolij Gustschin wrote:
BTW: While at it, could you then also please fix a mistake in the commit description: it should be "... just highest possible divider 512".
Of course, I will do it.
Stefano

From: Anatolij Gustschin agust@denx.de
The MXC SPI driver didn't calculate the SPI clock up to now and just highest possible divider 512 for DATA RATE in the control register. This results in very low transfer rates.
The patch adds code to calculate and setup the SPI clock frequency for transfers.
Signed-off-by: Anatolij Gustschin agust@denx.de Signed-off-by: Stefano Babic sbabic@denx.de --- Changes:
The patch is rebased on the current patches already sent for this driver (support for MX35). Tested on a MX35 board.
Modified commit message as suggested by Anatolij
drivers/spi/mxc_spi.c | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 0e42d41..32be7b0 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -71,6 +71,7 @@ static unsigned long spi_bases[] = { };
#define spi_cfg spi_cfg_mx3 +#define mxc_get_clock(x) mx31_get_ipg_clk()
#elif defined(CONFIG_MX51) #include <asm/arch/imx-regs.h> @@ -201,15 +202,36 @@ void spi_cs_deactivate(struct spi_slave *slave) !(mxcs->ss_pol)); }
+u32 get_cspi_div(u32 div) +{ + int i; + + for (i = 0; i < 8; i++) { + if (div <= (4 << i)) + return i; + } + return i; +} + #if defined(CONFIG_MX31) || defined(CONFIG_MX35) static s32 spi_cfg_mx3(struct mxc_spi_slave *mxcs, unsigned int cs, unsigned int max_hz, unsigned int mode) { unsigned int ctrl_reg; + u32 clk_src; + u32 div; + + clk_src = mxc_get_clock(MXC_CSPI_CLK); + + div = clk_src / max_hz; + div = get_cspi_div(div); + + debug("clk %d Hz, div %d, real clk %d Hz\n", + max_hz, div, clk_src / (4 << div));
ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) | MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS) | - MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */ + MXC_CSPICTRL_DATARATE(div) | MXC_CSPICTRL_EN | #ifdef CONFIG_MX35 MXC_CSPICTRL_SSCTL |

Hello.
Stefano Babic wrote:
From: Anatolij Gustschin agust@denx.de
The MXC SPI driver didn't calculate the SPI clock up to now and just highest possible divider 512 for DATA
^ I think "used" shouldn't have been ommitted here.
RATE in the control register. This results in very low transfer rates.
The patch adds code to calculate and setup the SPI clock frequency for transfers.
Signed-off-by: Anatolij Gustschin agust@denx.de Signed-off-by: Stefano Babic sbabic@denx.de
WBR, Sergei

On 01/18/2011 04:37 PM, Sergei Shtylyov wrote:
Hello.
Stefano Babic wrote:
From: Anatolij Gustschin agust@denx.de
The MXC SPI driver didn't calculate the SPI clock up to now and just highest possible divider 512 for DATA
^
I think "used" shouldn't have been ommitted here.
Right. I fix it.
Best regards, Stefano Babic

On 01/16/2011 07:17 PM, Anatolij Gustschin wrote:
We need to shift only one time in each cycle in the swapping loop for unaligned tx case. Currently two byte shift operations are performed in each loop cycle causing zero gaps in the transmited data, so not all data scheduled for transmition is actually transmited.
Tested on a mx35pdk.
Tested-by: Stefano Babic sbabic@denx.de
Best regards, Stefano Babic
participants (3)
-
Anatolij Gustschin
-
Sergei Shtylyov
-
Stefano Babic