* [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode
@ 2008-08-17 22:53 Daniel Ribeiro
[not found] ` <6669365c0808171553i3f64b667t18fcea589d94411a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Ribeiro @ 2008-08-17 22:53 UTC (permalink / raw)
To: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Hi,
I am converting a driver from ssp.c API to pxa2xx_spi. But
when using PIO mode i am getting bogus rx data.
I did some tests, and it looks like CS is being deasserted
before the IO is done.
The following patch solved the issue for me.
Please CC me on replies, im not subscribed to spi-devel.
--
Daniel Ribeiro
-- patch --
pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode
Signed-off-by: Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 0c452c4..4a9c34e 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -593,6 +593,10 @@ static void int_transfer_complete(struct
driver_data *drv_d {
void __iomem *reg = drv_data->ioaddr;
+ if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
+ dev_err(&drv_data->pdev->dev,
+ "interrupt_transfer: ssp rx stall failed\n");
+
/* Stop SSP */
write_SSSR(drv_data->clear_sr, reg);
write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg);
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
^ permalink raw reply related [flat|nested] 14+ messages in thread[parent not found: <6669365c0808171553i3f64b667t18fcea589d94411a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808171553i3f64b667t18fcea589d94411a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-08-17 22:59 ` Daniel Ribeiro 2008-08-18 18:53 ` Ned Forrester 1 sibling, 0 replies; 14+ messages in thread From: Daniel Ribeiro @ 2008-08-17 22:59 UTC (permalink / raw) To: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f [-- Attachment #1: Type: text/plain, Size: 131 bytes --] As it seems gmail web interface will not allow me to send an inline patch. Here is an attached version. Sorry. -- Daniel Ribeiro [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: wait_rx_stall-before-deasserting-CS-on-PIO-mode.patch --] [-- Type: text/x-diff; name=wait_rx_stall-before-deasserting-CS-on-PIO-mode.patch, Size: 645 bytes --] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com> diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 0c452c4..4a9c34e 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -593,6 +593,10 @@ static void int_transfer_complete(struct driver_data *drv_data) { void __iomem *reg = drv_data->ioaddr; + if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) + dev_err(&drv_data->pdev->dev, + "interrupt_transfer: ssp rx stall failed\n"); + /* Stop SSP */ write_SSSR(drv_data->clear_sr, reg); write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); [-- Attachment #3: Type: text/plain, Size: 363 bytes --] ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ [-- Attachment #4: Type: text/plain, Size: 210 bytes --] _______________________________________________ spi-devel-general mailing list spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/spi-devel-general ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808171553i3f64b667t18fcea589d94411a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-08-17 22:59 ` Daniel Ribeiro @ 2008-08-18 18:53 ` Ned Forrester [not found] ` <48A9C515.3000908-/d+BM93fTQY@public.gmane.org> 1 sibling, 1 reply; 14+ messages in thread From: Ned Forrester @ 2008-08-18 18:53 UTC (permalink / raw) To: Daniel Ribeiro; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > Hi, > > I am converting a driver from ssp.c API to pxa2xx_spi. But > when using PIO mode i am getting bogus rx data. > > I did some tests, and it looks like CS is being deasserted > before the IO is done. > > The following patch solved the issue for me. Can you be more specific about your problem? If CS is not being asserted/deasserted at the right times, then that needs to be fixed. What are you using for CS; this driver only works correctly when a GPIO pin is assigned for CS, and is controlled with the cs_control() callback. The below patch seems to paper over some other problem. wait_ssp_rx_stall() is used to recover from errors, by flushing and discarding words from the RX fifo. Also, int_transfer_complete() is only called from places where we know that all expected characters have been received and transferred to memory. This patch would "fix" a situation where extra words are in the RX FIFO after the expected number have been read. If there are more characters in the FIFO than were transmitted, then that needs to be fixed and not ignored. Can you provide a patch or more information that addresses the underlying problem? > pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode > > Signed-off-by: Daniel Ribeiro <drwyrm-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c > index 0c452c4..4a9c34e 100644 > --- a/drivers/spi/pxa2xx_spi.c > +++ b/drivers/spi/pxa2xx_spi.c > @@ -593,6 +593,10 @@ static void int_transfer_complete(struct driver_data *drv_data) > { > void __iomem *reg = drv_data->ioaddr; > > + if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) > + dev_err(&drv_data->pdev->dev, > + "interrupt_transfer: ssp rx stall failed\n"); > + > /* Stop SSP */ > write_SSSR(drv_data->clear_sr, reg); > write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); > > -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <48A9C515.3000908-/d+BM93fTQY@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <48A9C515.3000908-/d+BM93fTQY@public.gmane.org> @ 2008-08-18 19:27 ` Daniel Ribeiro [not found] ` <6669365c0808181227k2fa01d6fu570cebc10630f55d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 14+ messages in thread From: Daniel Ribeiro @ 2008-08-18 19:27 UTC (permalink / raw) To: Ned Forrester; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f On Mon, Aug 18, 2008 at 3:53 PM, Ned Forrester <nforrester-/d+BM93fTQY@public.gmane.org> wrote: > Can you be more specific about your problem? If CS is not being > asserted/deasserted at the right times, then that needs to be fixed. > What are you using for CS; this driver only works correctly when a GPIO > pin is assigned for CS, and is controlled with the cs_control() callback. Yes, I´m using a gpio for CS. cs_control is OK. > The below patch seems to paper over some other problem. > wait_ssp_rx_stall() is used to recover from errors, by flushing and > discarding words from the RX fifo. Also, int_transfer_complete() is > only called from places where we know that all expected characters have > been received and transferred to memory. Not really, something is really wrong with the call to int_transfer_complete. If i replace the wait_ssp_rx_stall() call with a simple printk() call everything works just fine. Same with an udelay(300). I may be wrong, but it seems that interrupt_transfer calls int_transfer_complete after the total amount of data is put on the FIFO, but it does not guarantee that the IO is actually done before calling it. > This patch would "fix" a situation where extra words are in the RX FIFO > after the expected number have been read. If there are more characters > in the FIFO than were transmitted, then that needs to be fixed and not > ignored. > > Can you provide a patch or more information that addresses the > underlying problem? As I already said, i am converting a working driver from ssp.c´s ssp_read_word/ssp_write_word to pxa2xx_spi. The driver works just fine with: gpio_set_value(cs, 0); ssp_write_word(&ssp_dev, data); ssp_read_word(&ssp_dev, &ret); gpio_set_value(cs, 1); After the conversion i ended with this code: static int ezx_pcap_putget(u32 *data) { struct spi_transfer t; struct spi_message m; spi_message_init(&m); t.len = 4; t.tx_buf = (u8 *)data; t.rx_buf = (u8 *)data; t.bits_per_word = 32; spi_message_add_tail(&t, &m); return spi_sync(pcap.spi, &m); } The driver is a for a PMIC, it has 32 25bit registers, which i need to access trough 32bit spi IO. Without the wait_ssp_rx_stall patch (or any other delay before the CS_DEASSERT) this is what i get: pcap_read: reg_num:3 value:00edf48a pcap_write: reg_num:3 value:00123456 pcap_read: reg_num:3 value:00edf48a pcap_read: reg_num:3 value:00edf48a With the patch, or with an udelay(300) call instead of wait_ssp_rx_stall: pcap_read: reg_num:3 value:00edf48a pcap_write: reg_num:3 value:00123456 pcap_read: reg_num:3 value:00123456 pcap_read: reg_num:3 value:00123456 Since the udelay(300) call works, and it doesnt touch the ssp registers, it looks like int_transfer_complete is being called before it should. -- Daniel Ribeiro ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <6669365c0808181227k2fa01d6fu570cebc10630f55d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808181227k2fa01d6fu570cebc10630f55d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-08-18 20:47 ` Ned Forrester [not found] ` <48A9DFD9.9000708-/d+BM93fTQY@public.gmane.org> 2008-09-11 17:41 ` David Brownell 1 sibling, 1 reply; 14+ messages in thread From: Ned Forrester @ 2008-08-18 20:47 UTC (permalink / raw) To: Daniel Ribeiro; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > On Mon, Aug 18, 2008 at 3:53 PM, Ned Forrester <nforrester-/d+BM93fTQY@public.gmane.org> wrote: >> Can you be more specific about your problem? If CS is not being >> asserted/deasserted at the right times, then that needs to be fixed. >> What are you using for CS; this driver only works correctly when a GPIO >> pin is assigned for CS, and is controlled with the cs_control() callback. > > Yes, IŽm using a gpio for CS. cs_control is OK. OK. >> The below patch seems to paper over some other problem. >> wait_ssp_rx_stall() is used to recover from errors, by flushing and >> discarding words from the RX fifo. Also, int_transfer_complete() is >> only called from places where we know that all expected characters have >> been received and transferred to memory. > > Not really, something is really wrong with the call to int_transfer_complete. > If i replace the wait_ssp_rx_stall() call with a simple printk() call everything > works just fine. Same with an udelay(300). > I may be wrong, but it seems that interrupt_transfer calls int_transfer_complete > after the total amount of data is put on the FIFO, but it does not > guarantee that > the IO is actually done before calling it. Well, if you get the same effect by using a delay, then the problem is not extra data in the fifo. If you read the code in the driver carefully, I think you will find that int_transfer_complete is called after every expected character is read from the FIFO and after that point, there is no opportunity to read anymore characters to memory. I am puzzled as to why a delay in int_transfer_complete would have any influence because nothing is read from the FIFO to memory after it is called. See a suggestion below. >> This patch would "fix" a situation where extra words are in the RX FIFO >> after the expected number have been read. If there are more characters >> in the FIFO than were transmitted, then that needs to be fixed and not >> ignored. >> >> Can you provide a patch or more information that addresses the >> underlying problem? > > As I already said, i am converting a working driver from ssp.cŽs > ssp_read_word/ssp_write_word to pxa2xx_spi. The driver works just > fine with: > > gpio_set_value(cs, 0); > ssp_write_word(&ssp_dev, data); > ssp_read_word(&ssp_dev, &ret); > gpio_set_value(cs, 1); > > After the conversion i ended with this code: > static int ezx_pcap_putget(u32 *data) > { > struct spi_transfer t; > struct spi_message m; > > spi_message_init(&m); > t.len = 4; > t.tx_buf = (u8 *)data; > t.rx_buf = (u8 *)data; > t.bits_per_word = 32; > spi_message_add_tail(&t, &m); > return spi_sync(pcap.spi, &m); > } So far this looks good, but what have you declared about the chip in the chip_info structure? In particular, what timeout and FIFO thresholds? What processor are you using, and which port on that processor; there is a difference in the handling of the end of a transfer between the SSP port on an PXA25x (which has no timeout interrupt) and all other ports handled by this driver (including the NSSP port on the PXA25x and all the ports on the PXA270). > The driver is a for a PMIC, it has 32 25bit registers, which i need to > access trough 32bit spi IO. > Without the wait_ssp_rx_stall patch (or any other delay before the > CS_DEASSERT) this is what i get: OK, this should be possible. > pcap_read: reg_num:3 value:00edf48a > pcap_write: reg_num:3 value:00123456 > pcap_read: reg_num:3 value:00edf48a > pcap_read: reg_num:3 value:00edf48a > > With the patch, or with an udelay(300) call instead of wait_ssp_rx_stall: > pcap_read: reg_num:3 value:00edf48a > pcap_write: reg_num:3 value:00123456 > pcap_read: reg_num:3 value:00123456 > pcap_read: reg_num:3 value:00123456 > > Since the udelay(300) call works, and it doesnt touch the ssp registers, > it looks like int_transfer_complete is being called before it should. Very strange, but I can't draw the same conclusion. int_transfer_complete is only called from 4 places in int_transfer, and then only after verifying that the full count of receive characters has been transfered to memory. Even if the transfer was not complete in hardware, or if the CS was dropped too soon, this delay would not fix the problem. There has to be something else going on. I am not familiar with the chip you are using. Are you certain that when you write a register, you should expect back the same value that you wrote, when received on the same transfer. It makes sense that the chip might do this, but I thought I should ask, because there are other possibilities. One thing that is odd about the setup of your message is the use of the same buffer for transmit and receive. I agree that this should be possible, as nothing is received until the corresponding word has been transmitted. However, this might be obscuring some of the symptoms. Can you try assigning separate buffers for tx and rx, and then test to see what the results are with and without the added delay? This might shed some more light on what is happening. Also try setting up the pxa2xx_spi driver to the correct bits-per-word though chip_info and spi_setup(), and turn off (make 0) the per-transfer bits-per-word, above. This will test to see if there is an error handling the per-transfer changes. I don't think many applications use the per-transfer changes, so that is another possible source of problems. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <48A9DFD9.9000708-/d+BM93fTQY@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <48A9DFD9.9000708-/d+BM93fTQY@public.gmane.org> @ 2008-08-18 23:06 ` Daniel Ribeiro [not found] ` <6669365c0808181606u4ead2f27h1f2286f9365e8a7a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 14+ messages in thread From: Daniel Ribeiro @ 2008-08-18 23:06 UTC (permalink / raw) To: Ned Forrester; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f On Mon, Aug 18, 2008 at 5:47 PM, Ned Forrester <nforrester-/d+BM93fTQY@public.gmane.org> wrote: > So far this looks good, but what have you declared about the chip in the > chip_info structure? In particular, what timeout and FIFO thresholds? > What processor are you using, and which port on that processor; there is > a difference in the handling of the end of a transfer between the SSP > port on an PXA25x (which has no timeout interrupt) and all other ports > handled by this driver (including the NSSP port on the PXA25x and all > the ports on the PXA270). .tx_threshold = 1, .rx_threshold = 1, .timeout = 1000, Its a PXA270, SSP1. >> pcap_read: reg_num:3 value:00edf48a >> pcap_write: reg_num:3 value:00123456 >> pcap_read: reg_num:3 value:00edf48a >> pcap_read: reg_num:3 value:00edf48a >> >> With the patch, or with an udelay(300) call instead of wait_ssp_rx_stall: >> pcap_read: reg_num:3 value:00edf48a >> pcap_write: reg_num:3 value:00123456 >> pcap_read: reg_num:3 value:00123456 >> pcap_read: reg_num:3 value:00123456 >> >> Since the udelay(300) call works, and it doesnt touch the ssp registers, >> it looks like int_transfer_complete is being called before it should. > > Very strange, but I can't draw the same conclusion. > int_transfer_complete is only called from 4 places in int_transfer, and > then only after verifying that the full count of receive characters has > been transfered to memory. Even if the transfer was not complete in > hardware, or if the CS was dropped too soon, this delay would not fix > the problem. There has to be something else going on. > I am not familiar with the chip you are using. Are you certain that > when you write a register, you should expect back the same value that > you wrote, when received on the same transfer. It makes sense that the > chip might do this, but I thought I should ask, because there are other > possibilities. Its not the same transfer. pcap_read and pcap_write each call pcap_putget. So, to _write_a_register_ i write then read a spi word. And to _read_a_register_ i write then read another spi word. Those write/read register operations can´t happen on the same CS assertion. > One thing that is odd about the setup of your message is the use of the > same buffer for transmit and receive. I agree that this should be > possible, as nothing is received until the corresponding word has been > transmitted. However, this might be obscuring some of the symptoms. > Can you try assigning separate buffers for tx and rx, and then test to > see what the results are with and without the added delay? This might > shed some more light on what is happening. I tried this already, used different buffers, and it makes no difference, same wrong behaviour without the delay, and the same correct behaviour with the delay. The fact of using the same buffer is not the issue. > Also try setting up the pxa2xx_spi driver to the correct bits-per-word > though chip_info and spi_setup(), and turn off (make 0) the per-transfer > bits-per-word, above. This will test to see if there is an error > handling the per-transfer changes. I don't think many applications use > the per-transfer changes, so that is another possible source of problems. Same. This doesnt seem to be the issue, as it only changes the ->read and ->write pointers from u8_(reader|writer) to u32_(reader|writer), i certified that the u32 functions are being used, this is enough for me. It seems that checking the full count of receive/transmit bytes that _gets_in/out_the_FIFO_ is not enough to assert that the data is actually _transfered_to_the_hardware_. I will try to explain how i came to this patch a little more verbose, see if agree with me now: do { if (drv_data->read(drv_data)) { int_transfer_complete(drv_data); return IRQ_HANDLED; } } while (drv_data->write(drv_data)); So, if i use u32_writer/u32_reader (t.bits_per_word = 32) to write/read a _single_ 32bits word (t.len = 4), the relevant code path on the above loop would be: first u32_reader call: read_SSSR(reg) & SSSR_RNE /* FIFO is still empty, u32_reader returns 0 */ first u32_writer call: write_SSDR(*(u32 *)(drv_data->tx), reg); drv_data->tx += 4; /* data is transfered to FIFO, writer returns 1 */ second u32_reader call: *(u32 *)(drv_data->rx) = read_SSDR(reg); drv_data->rx += 4; /* u32_reader doesnt loop becase rx == rx_end, reader returns 1 */ then it calls int_transfer_complete. I dont see where it asserts that the hardware transfer was done. Or read_SSDR/write_SSDR do blocking??? Shouldnt the driver wait SSSR_RNE be cleared before assuming that the data was received? while(read_SSSR(reg) & SSSR_RNE) ; Shouldnt it wait SSSR_TNF be set, before assuming the data was written? while(!(read_SSSR(reg) & SSSR_TNF)) ; Shouldnt it check if the SSP port is not doing IO (SSSR_BSY) before calling int_transfer_done? while(read_SSSR(reg) & SSSR_BSY) ; Any of the above 3 blocking loops on the first line of int_transfer_complete() fixes the problem. :) (yes, TNF works too, because threshold = 1. ;) ) And finally, note that ssp_rx_stall() doesnt reads/discards any _data_ from the port as you claimed, it is just a busy loop, equivalent to the third (SSSR_BSY) example above. And it IS called on dma_transfer_complete (by the way, when i configure the driver to use DMA, everything works as it should). -- Daniel Ribeiro ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <6669365c0808181606u4ead2f27h1f2286f9365e8a7a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808181606u4ead2f27h1f2286f9365e8a7a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-08-19 5:58 ` Ned Forrester 2008-08-19 5:58 ` Daniel Ribeiro 1 sibling, 0 replies; 14+ messages in thread From: Ned Forrester @ 2008-08-19 5:58 UTC (permalink / raw) To: Daniel Ribeiro; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > On Mon, Aug 18, 2008 at 5:47 PM, Ned Forrester <nforrester-/d+BM93fTQY@public.gmane.org> wrote: >> So far this looks good, but what have you declared about the chip in the >> chip_info structure? In particular, what timeout and FIFO thresholds? >> What processor are you using, and which port on that processor; there is >> a difference in the handling of the end of a transfer between the SSP >> port on an PXA25x (which has no timeout interrupt) and all other ports >> handled by this driver (including the NSSP port on the PXA25x and all >> the ports on the PXA270). > > .tx_threshold = 1, > .rx_threshold = 1, > .timeout = 1000, The timeout is short (but may not be a problem for you, with only one word transfers); we are having that discussion in another thread. The original author of this driver, Stephen Street, intended for the 1000 default timeout to be 1000usec. Later we discovered that the developer's manuals for the PXA25x and PXA270 processors do not specify what frequency is being counted by the timer. I have shown that on the PXA255 it is counting 99.5MHz, but since both Stephen and I are using PXA255, we do not know what clock is used on the PXA270 or the newer PXA3xx. Perhaps you could set up a test to answer that for the PXA 270, but I digress. At 99.5MHZ, a timer count of 1000 is only 10usec. If the PXA270 uses the same clock, you may be getting a timer interrupt before the hardware even has time to clock out the bits, if you use a slow SSPSCLK. I use a value of 10000 with DMA driven transfers at 11MHZ, but I never want a timeout to occur (my data flow is continuous, a timeout is an error); a value of 100000 is more reasonable for PIO of large transfers, unless you don't mind extra timeout interrupts that might occur when there are latencies in processing (both PIO and DMA modes should be able to deal with this, though in different ways). I'm not sure that this has anything to do with your problem, though, because with 1 word transfers, it should not matter if the single word read is read by the read-while-transmit loop of int_transfer, or if it is read (more commonly) by the timeout loop (higher in the same routine); nor should it matter if the timeout interrupt is invoked more than once to check the receiver fifo. The one data word should be there already, or the driver will wait for the another timeout (the timer is only stopped in int_transfer_complete, and that is only called after all data is received). Note that if the timeout interrupt occurs before the last (or in your case, only) word arrives in the RX FIFO, then the timer will later be reset when the word actually does arrive, and will thus timeout again. There is a possible race condition that is correctly handled in the driver by clearing the SSSR_TINT bit BEFORE checking for words in the FIFO. Otherwise, if the TINT bit were cleared afterward, the data word might arrive after checking for data and before clearing the TINT bit, thus setting up a situation where the timeout interrupt never gets set again. Hmmm... I guess all of the above is just me re-learning how the timeout works, and is thus just for background information. It looks like it does not matter that much if the timeout is short or long: if it is too short, there will be wasted interrupt services with nothing important to do, and if it is too long then transfers are delayed unnecessarily, but the data still flows. > Its a PXA270, SSP1. > >>> pcap_read: reg_num:3 value:00edf48a >>> pcap_write: reg_num:3 value:00123456 >>> pcap_read: reg_num:3 value:00edf48a >>> pcap_read: reg_num:3 value:00edf48a >>> >>> With the patch, or with an udelay(300) call instead of wait_ssp_rx_stall: >>> pcap_read: reg_num:3 value:00edf48a >>> pcap_write: reg_num:3 value:00123456 >>> pcap_read: reg_num:3 value:00123456 >>> pcap_read: reg_num:3 value:00123456 >>> >>> Since the udelay(300) call works, and it doesnt touch the ssp registers, >>> it looks like int_transfer_complete is being called before it should. >> Very strange, but I can't draw the same conclusion. >> int_transfer_complete is only called from 4 places in int_transfer, and >> then only after verifying that the full count of receive characters has >> been transfered to memory. Even if the transfer was not complete in >> hardware, or if the CS was dropped too soon, this delay would not fix >> the problem. There has to be something else going on. >> I am not familiar with the chip you are using. Are you certain that >> when you write a register, you should expect back the same value that >> you wrote, when received on the same transfer. It makes sense that the >> chip might do this, but I thought I should ask, because there are other >> possibilities. > > Its not the same transfer. pcap_read and pcap_write each call pcap_putget. > So, to _write_a_register_ i write then read a spi word. And to _read_a_register_ > i write then read another spi word. Those write/read register operations canŽt > happen on the same CS assertion. Ahhh... Sorry for the confusion. I thought the above results were supposed to show what was received during the receive portion of the same transfer that was doing the writing. No wonder we are talking at cross purposes. So, if I now understand, the write is simply failing, and subsequent reads show the data unchanged from before the write. >> One thing that is odd about the setup of your message is the use of the >> same buffer for transmit and receive. I agree that this should be >> possible, as nothing is received until the corresponding word has been >> transmitted. However, this might be obscuring some of the symptoms. >> Can you try assigning separate buffers for tx and rx, and then test to >> see what the results are with and without the added delay? This might >> shed some more light on what is happening. > > I tried this already, used different buffers, and it makes no difference, same > wrong behaviour without the delay, and the same correct behaviour with the > delay. The fact of using the same buffer is not the issue. OK. Thanks for the info. >> Also try setting up the pxa2xx_spi driver to the correct bits-per-word >> though chip_info and spi_setup(), and turn off (make 0) the per-transfer >> bits-per-word, above. This will test to see if there is an error >> handling the per-transfer changes. I don't think many applications use >> the per-transfer changes, so that is another possible source of problems. > > Same. This doesnt seem to be the issue, as it only changes the ->read and > ->write pointers from u8_(reader|writer) to u32_(reader|writer), i > certified that > the u32 functions are being used, this is enough for me. Well, the u32 functions will be used regardless of whether you specify 32 bits/word as the default (through setup) or whether you specify it per-transfer. In any case, you tested this also, and it is ok. > It seems that checking the full count of receive/transmit bytes that > _gets_in/out_the_FIFO_ is not enough to assert that the data is actually > _transfered_to_the_hardware_. Now that I realize that you are talking about separate write and read transfers, I will try to explain in that context. Note that we are discussing PIO mode below, DMA has similar but different considerations. Checking the received bytes is a perfect measure of bytes transmitted. Every SPI transfer, whether one word or many, and whether intended for the purpose of writing or reading a chip, consists of both transmitting and receiving. It is the transmit that causes SSPSCLK to be generated, and that simultaneously shifts out the transmit data and shifts in the receive data. Thus the RX fifo cannot register a received word until all the clocks have occurred, and all data must be shifted out, and also all data shifted in. However, that does not say that the correct thing happened with the chip select, just that there is a clock pulse on the wire for every bit of the transfer. > I will try to explain how i came to this patch a little more verbose, see if > agree with me now: > > do { > if (drv_data->read(drv_data)) { > int_transfer_complete(drv_data); > return IRQ_HANDLED; > } > } while (drv_data->write(drv_data)); > > So, if i use u32_writer/u32_reader (t.bits_per_word = 32) > to write/read a _single_ 32bits word (t.len = 4), > the relevant code path on the above loop would be: > > first u32_reader call: > read_SSSR(reg) & SSSR_RNE /* FIFO is still empty, u32_reader returns 0 */ Yes. > first u32_writer call: > write_SSDR(*(u32 *)(drv_data->tx), reg); > drv_data->tx += 4; > /* data is transfered to FIFO, writer returns 1 */ Yes. > second u32_reader call: > *(u32 *)(drv_data->rx) = read_SSDR(reg); > drv_data->rx += 4; > /* u32_reader doesnt loop becase rx == rx_end, reader returns 1 */ Not necessarily. The most likely action at this point is that u32_reader will find that the RX FIFO is still empty and thus will return without actually reading; it takes 2.4us to clock out 32 bits at the maximum clock rate of 13MHz (I think that rate is possible on a PXA270). All those extra reads are there, not necessarily to read anything, but make sure, if anything is in the RX FIFO, that it is read out to make room for whatever has been put in the TX FIFO. Without all these attempted reads, some of which might succeed, it is possible, with higher TX and RX FIFO thresholds, to overrun the RX FIFO by having more words in the TX FIFO then there are spaces in the RX FIFO. At this point, in your case of a one word transfer, the int_transfer notes that all words have been placed in the TX FIFO and thus disables the TX Interrupt (TIE). Then int_transfer returns from interrupt service, and the processor waits for the timeout interrupt. When the timeout interrupt occurs, the receiver will be emptied by the earlier code in int_transfer, at: if (irq_status & SSSR_TINT) { Then... > then it calls int_transfer_complete. Yes, after all the the expected characters have been received, whether or not that happened during one call to int_transfer or during a second call responding to the timeout interrupt. > I dont see where it asserts that the hardware transfer was done. Or > read_SSDR/write_SSDR do blocking??? u32_reader will not return true unless it has received all bytes, and it will not receive bytes while the RX fifo is empty. Thus the driver blocks in the sense of return from interrupt, and then waits until there is an interrupt (timeout), so that it can check the receiver again. > Shouldnt the driver wait SSSR_RNE be cleared before assuming that the > data was received? > while(read_SSSR(reg) & SSSR_RNE) ; It has to wait for SSSR_RNE to be SET to read data, and it does. If there are no hardware errors (clock glitches or whatever), then the receiver cannot have words in it after the last expected one is read out; none transmitted, none received. At that point the receiver must be empty; there is no need to check. > Shouldnt it wait SSSR_TNF be set, before assuming the data was written? > while(!(read_SSSR(reg) & SSSR_TNF)) ; No. If all data has been received, then, by definition, it was all transmitted. The receiver needs a clock to receive, and the clock is enabled by transmit. In any case, I don't think you are interpreting SSSR_TNF correctly. It is only clear if there are 16 words in the FIFO, the setting of the threshold is not related to this bit. Incidentally, in the writers, the actual fifo count is checked for 15, because the logic of preventing receiver overruns requires that we never put more than 15 in the transmit fifo; that is, we never want it full and SSSR_TNF will never be clear. The loop above will never evaluate more than once. There must be a delay associated with reading SSSR. I don't know what that delay would be, but you may find out, below. > Shouldnt it check if the SSP port is not doing IO (SSSR_BSY) before > calling int_transfer_done? > while(read_SSSR(reg) & SSSR_BSY) ; That is not necessary. All data has been clocked. > Any of the above 3 blocking loops on the first line of > int_transfer_complete() fixes the problem. :) > (yes, TNF works too, because threshold = 1. ;) ) See above about TNF. So it is not the value of TNF, but perhaps the time spent reading it that matters. I would be interested to know if putting a printk inside the above while loops ever indicates that they were evaluated more than once. The first of your three is effectively part of the readers, you can't get to int_transfer_complete without satisfying it, so I don't accept your point. But keep reading.... > And finally, note that ssp_rx_stall() doesnt reads/discards any _data_ > from the port as you claimed, > it is just a busy loop, equivalent to the third (SSSR_BSY) example above. > And it IS called on dma_transfer_complete (by the way, when i > configure the driver to use DMA, > everything works as it should). My apologies. I misread read_SSSR(ioaddr) as read_SSDR(ioaddr). It has been two years since my first descent into the details of this driver, and I have not revisited wait_ssp_rx_stall recently. I should not operate on memory at my age. Some of the extra work done in dma_transfer complete, prior to clearing chip select (delay), *might* account for why it works and int_transfer_complete does not work. -- It remains to figure out why your fixes help, and what the real problem is. I think it may go back to your original statement: "I did some tests, and it looks like CS is being deasserted before the IO is done." I gather you can scope these signals and measure the timing of CS as it relates to clock and data. What does the chip spec say about the required relationship between CS and the other signals? I gather that some chips require CS to stay asserted briefly after the end of the clocks; this is the reason for having spi_transfer.delay_usecs. Please measure the delay from the last clock to dropping CS and compare that with the requirements of the chip, with and without the changes you tested above. Does this shed light on the problem? If the insertion of the register reads you tested above helped (they may have added 100ns to the time CS is active after the last clock) then you have stumbled on a known bug in the driver, that had not yet been fixed. This bug regarding CS changes was discussed in: Re: [spi-devel-general] [PATCH] atmel_spi: support zero length transfer See David's reply of: 2008-02-23 02:37 I raised the question but, since I don't use chip select at all, I have not produced a patch. There are other issues discussed there about zero length transfers in DMA mode, and about doing DMA mapping in transfer(), rather than in pump_transfers(), just in case you have time on your hands. :-) Basically, the spi_transfer.delay_usecs value is supposed to be applied between the end of a transfer and any change in CS specified by a spi_transfer.cs_change request. In this driver, the order is mistakenly reversed, and the delay is honored AFTER the CS has already changed. Thus if your chip requires a delay between the end of a transfer and the change in CS, and you set delay_usecs to request that, it will not be honored as intended. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808181606u4ead2f27h1f2286f9365e8a7a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-08-19 5:58 ` Ned Forrester @ 2008-08-19 5:58 ` Daniel Ribeiro [not found] ` <6669365c0808182258t6c4a5086xd9425435930e6d8f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 1 sibling, 1 reply; 14+ messages in thread From: Daniel Ribeiro @ 2008-08-19 5:58 UTC (permalink / raw) To: Ned Forrester; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Hi! You were right, there is nothing wrong with the spi transfer. The problem is the hardware. This chip really needs some delay before deasserting CS on register writes. Otherwise it just silently ignores the register write. I no longer think that anything is wrong with spi communication, i can reliably read any chip register. The problem only occurs on register writes, and not even on all registers. On giveback(), if i add a delay _before_ cs_control(CS_DEASSERT), it works. If i add it just _after_ cs_control() it does not work. I see that there is a .delay_usecs field on spi_transfer: * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this @spi_message. But it is only called for the previous transfer when on RUNNING_STATE, so a second spi_transfer is needed on the same spi_message to actually use this feature. Should i submit a patch to use this delay_usecs field also on DONE_STATE, so it actually do something when set on the last spi_transfer? Or should i just cheat pxa2xx_spi with: struct spi_transfer t[2]; struct spi_message m; spi_message_init(&m); t[0].len = 4; t[0].tx_buf = (u8 *)data; t[0].rx_buf = (u8 *)data; t[0].bits_per_word = 32; t[0].delay_usecs = 300; spi_message_add_tail(&t[0], &m); /* trick pxa2xx_spi so it uses t[0].delay_usecs */ t[1].len = 0; spi_message_add_tail(&t[1], &m); return spi_sync(pcap.spi, &m); (with the above code my chip works great without changes to pxa2xx_spi.c) My opinion is that this field should be used to delay also on DONE_STATE: "microseconds to delay after this transfer before changing the chipselect status, then starting the next transfer *or*completing*this*spi_message*" I will be happy to submit a patch to change this if you think the delay on DONE_STATE is acceptable. -- Daniel Ribeiro ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <6669365c0808182258t6c4a5086xd9425435930e6d8f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808182258t6c4a5086xd9425435930e6d8f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-08-19 6:08 ` Ned Forrester 2008-08-19 16:48 ` Ned Forrester 1 sibling, 0 replies; 14+ messages in thread From: Ned Forrester @ 2008-08-19 6:08 UTC (permalink / raw) To: Daniel Ribeiro; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > Hi! > > You were right, there is nothing wrong with the spi transfer. > > The problem is the hardware. This chip really needs some delay before > deasserting CS on register writes. Otherwise it just silently ignores > the register write. > > I no longer think that anything is wrong with spi communication, i can > reliably read any chip register. The problem only occurs on register > writes, and not even on all registers. > > On giveback(), if i add a delay _before_ cs_control(CS_DEASSERT), it works. > If i add it just _after_ cs_control() it does not work. > > I see that there is a .delay_usecs field on spi_transfer: > > * @delay_usecs: microseconds to delay after this transfer before > * (optionally) changing the chipselect status, then starting > * the next transfer or completing this @spi_message. > > But it is only called for the previous transfer when on RUNNING_STATE, > so a second spi_transfer is needed on the same spi_message to actually > use this feature. > > Should i submit a patch to use this delay_usecs field also on > DONE_STATE, so it actually do something when set on the last > spi_transfer? Or should i just cheat pxa2xx_spi with: > > struct spi_transfer t[2]; > struct spi_message m; > > spi_message_init(&m); > t[0].len = 4; > t[0].tx_buf = (u8 *)data; > t[0].rx_buf = (u8 *)data; > t[0].bits_per_word = 32; > t[0].delay_usecs = 300; > spi_message_add_tail(&t[0], &m); > > /* trick pxa2xx_spi so it uses t[0].delay_usecs */ > t[1].len = 0; > spi_message_add_tail(&t[1], &m); > > return spi_sync(pcap.spi, &m); > > (with the above code my chip works great without changes to pxa2xx_spi.c) > > My opinion is that this field should be used to delay also on > DONE_STATE: "microseconds to delay after this transfer before changing > the chipselect status, then starting the next transfer > *or*completing*this*spi_message*" > > I will be happy to submit a patch to change this if you think the > delay on DONE_STATE is acceptable. Wow! Our messages crossed in the ether. I'm glad we agree now on the nature of the problem. Yes, I think that delay_usecs should be honored on every transfer on which it is non-zero. As noted in my previous email, there is a known bug in the driver in this regard, and if you would like to submit a patch for it, that would be great. Exactly what that patch should look like, I'm not sure at the moment. It is very late where I live and I would prefer to consider this tomorrow. I would like to suggest/review this sort of patch, to make sure it is as compatible as possible with my unreleased expansion of this driver. I'm still curious to know how much delay was added by the various patches you tested. My hardware is not available at the moment, so I cannot test, and I would be testing a PXA255, in any case. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808182258t6c4a5086xd9425435930e6d8f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-08-19 6:08 ` Ned Forrester @ 2008-08-19 16:48 ` Ned Forrester 1 sibling, 0 replies; 14+ messages in thread From: Ned Forrester @ 2008-08-19 16:48 UTC (permalink / raw) To: Daniel Ribeiro; +Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > Hi! > > You were right, there is nothing wrong with the spi transfer. > > The problem is the hardware. This chip really needs some delay before > deasserting CS on register writes. Otherwise it just silently ignores > the register write. > > I no longer think that anything is wrong with spi communication, i can > reliably read any chip register. The problem only occurs on register > writes, and not even on all registers. > > On giveback(), if i add a delay _before_ cs_control(CS_DEASSERT), it works. > If i add it just _after_ cs_control() it does not work. > > I see that there is a .delay_usecs field on spi_transfer: > > * @delay_usecs: microseconds to delay after this transfer before > * (optionally) changing the chipselect status, then starting > * the next transfer or completing this @spi_message. > > But it is only called for the previous transfer when on RUNNING_STATE, > so a second spi_transfer is needed on the same spi_message to actually > use this feature. It is true that the delay is implemented only for the case of a message continuing with another transfer (which is wrong), but also that the delay is implemented after the CS change that occurs in either int_transfer_complete or dma_transfer_complete. Because of this, your code fragment below works, not because you made the delay_usecs parameter non-zero, but because you did not make the cs_change parameter true. Thus, when the double transfer is executed, the default behavior of the driver is (correctly) to leave CS asserted through the next transfer; the delay_usecs parameter adds additional delay, but I bet that just executing the next zero-length transfer was sufficient delay. The real problem is that either the delay or the call to deassert CS is implemented in the wrong place. It needs to be invoked prior to each test and call of the cs_change parameter. There are 3 places where this could be done: giveback, dma_transfer_complete, and int_transfer_complete. By the time pump_transfers is executed, the CS change, if any, has already taken place, and the next transfer has already been selected so that pump_transfers has to reach back to "previous" to fetch the delay, kind of awkward. The down side of putting the delay in the logical place (before each test/call for cs_change) is that it moves the udelay() call from soft interrupt context (pump_transfers executing as a tasklet) to hard interrupt context. This is probably a bad idea. See alternate below. > Should i submit a patch to use this delay_usecs field also on > DONE_STATE, so it actually do something when set on the last > spi_transfer? Or should i just cheat pxa2xx_spi with: > > struct spi_transfer t[2]; > struct spi_message m; > > spi_message_init(&m); > t[0].len = 4; > t[0].tx_buf = (u8 *)data; > t[0].rx_buf = (u8 *)data; > t[0].bits_per_word = 32; > t[0].delay_usecs = 300; > spi_message_add_tail(&t[0], &m); > > /* trick pxa2xx_spi so it uses t[0].delay_usecs */ > t[1].len = 0; > spi_message_add_tail(&t[1], &m); > > return spi_sync(pcap.spi, &m); > > (with the above code my chip works great without changes to pxa2xx_spi.c) Agreed, but the driver still needs to be fixed because it does not conform to the standard of the SPI core. Interestingly, you have also stressed another known weakness in the driver that was the main topic of the thread I pointed you to last night: that the driver is not guaranteed to handle zero length transfers properly. That problem should be fixed at the same time. One reason that I have not fixed these known problems lack of time, but the other reason is that I have no easy way to test them. Now that there is a willing tester, it is time to write a patch. > My opinion is that this field should be used to delay also on > DONE_STATE: "microseconds to delay after this transfer before changing > the chipselect status, then starting the next transfer > *or*completing*this*spi_message*" I agree the driver needs a patch, but I think the right way to do it is as follows: 1. Add a check for non-zero delay_usecs and resulting call to udelay in giveback(), just before the test for cs_change and call to cs_control. giveback() is executed in tasklet context (soft interrupt) and so this will be no worst than the current udelay call. 2. Move the test for cs_change and call to cs_control out of both of int_transfer_complete and dma_transfer complete, and put a single test/call based on the "previous" pointer within the RUNNING_STATE test of pump_transfers, and just after the test/execution of the delay. This 3. Fix any issues with the execution of zero-length transfers. (I still have to look at that, but I think that only zero-length, non-descriptor DMA fails; the current driver does not use descriptor DMA, but my version does). 4. See if the driver has to handle transfers longer than 8191 bytes. I have this question open with David Brownell, and I await an answer, so there may be action needed with that, though it could be implemented separately at a later time. > I will be happy to submit a patch to change this if you think the > delay on DONE_STATE is acceptable. Given that there is a bit more to this, and that we should try to make this apply to earlier stable kernels, maybe I should try to write the patch. I will get back, hopefully today, with something. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <6669365c0808181227k2fa01d6fu570cebc10630f55d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-08-18 20:47 ` Ned Forrester @ 2008-09-11 17:41 ` David Brownell [not found] ` <200809111041.20900.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> 1 sibling, 1 reply; 14+ messages in thread From: David Brownell @ 2008-09-11 17:41 UTC (permalink / raw) To: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Cc: Ned Forrester, Daniel Ribeiro Catching up on old mail ... On Monday 18 August 2008, Daniel Ribeiro wrote: > As I already said, i am converting a working driver from ssp.c´s > ssp_read_word/ssp_write_word to pxa2xx_spi. The driver works just > fine with: > > gpio_set_value(cs, 0); > ssp_write_word(&ssp_dev, data); > ssp_read_word(&ssp_dev, &ret); > gpio_set_value(cs, 1); That is, 64 bit times ... two sequential word transfers. > After the conversion i ended with this code: > > static int ezx_pcap_putget(u32 *data) > { > struct spi_transfer t; > struct spi_message m; > > spi_message_init(&m); > t.len = 4; > t.tx_buf = (u8 *)data; > t.rx_buf = (u8 *)data; > t.bits_per_word = 32; That is, 32 bit times ... two *parallel* word transfers. > spi_message_add_tail(&t, &m); > return spi_sync(pcap.spi, &m); > } So "deasserting CS too early" was what you *requested* and it's no wonder the driver did just that. You could instead return spi_write_then_read(pcap.spi, data, 4, data, 4); to get the sequential (not concurrent!) I/O you need. Be careful of byte ordering, of course; you probably should set spi->bits_per_word to 32 and then spi_setup(), as part of your driver init. - Dave ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <200809111041.20900.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode [not found] ` <200809111041.20900.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> @ 2008-09-12 1:53 ` Daniel Ribeiro 2008-09-12 2:53 ` Ned Forrester 2008-09-12 2:59 ` Ned Forrester 0 siblings, 2 replies; 14+ messages in thread From: Daniel Ribeiro @ 2008-09-12 1:53 UTC (permalink / raw) To: David Brownell Cc: Ned Forrester, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Em Qui, 2008-09-11 às 10:41 -0700, David Brownell escreveu: > You could instead > > return spi_write_then_read(pcap.spi, data, 4, data, 4); Tried this already. data == 0x00000000. Anyway, after the latest chipselect fixes, (deassert CS on pump_transfer() || giveback() instead of int_transfer_complete()) the code is working. > to get the sequential (not concurrent!) I/O you need. Be > careful of byte ordering, of course; you probably should > set spi->bits_per_word to 32 and then spi_setup(), as part > of your driver init. Yes, i guess i really should use spi_setup(). My current code is: spi_message_init(&m); t.len = 4; t.tx_buf = (u8 *)data; t.rx_buf = (u8 *)data; t.bits_per_word = 32; t.delay_usecs = 0; t.cs_change = 0; t.speed_hz = 13000000; spi_message_add_tail(&t, &m); return spi_sync(pcap.spi, &m); I noted that if i dont set .delay_usecs it gets a default huge value, same with .speed_hz, it dont use spi_board_info->max_speed_hz as default. Would calling spi_setup() on my driver init solve this? Or is this yet another issue? Thanks for your reply. -- Daniel Ribeiro ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ spi-devel-general mailing list spi-devel-general@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spi-devel-general ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode 2008-09-12 1:53 ` Daniel Ribeiro @ 2008-09-12 2:53 ` Ned Forrester 2008-09-12 2:59 ` Ned Forrester 1 sibling, 0 replies; 14+ messages in thread From: Ned Forrester @ 2008-09-12 2:53 UTC (permalink / raw) To: Daniel Ribeiro Cc: David Brownell, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Daniel Ribeiro wrote: > Em Qui, 2008-09-11 Ã s 10:41 -0700, David Brownell escreveu: > Yes, i guess i really should use spi_setup(). > My current code is: > > spi_message_init(&m); > t.len = 4; > t.tx_buf = (u8 *)data; > t.rx_buf = (u8 *)data; > t.bits_per_word = 32; > t.delay_usecs = 0; > t.cs_change = 0; > t.speed_hz = 13000000; > spi_message_add_tail(&t, &m); > return spi_sync(pcap.spi, &m); > > I noted that if i dont set .delay_usecs it gets a default huge value, > same with .speed_hz, it dont use spi_board_info->max_speed_hz as > default. Would calling spi_setup() on my driver init solve this? Or is > this yet another issue? In a past message, you showed the automatic declarations that went with the above code: > struct spi_transfer t; > struct spi_message m; While spi_message_init() zeros the memory in "m", you don't show any code above, other than your assignments, that clears the memory in "t". Thus, if you omit the assignments for t.delay_usecs or t.speed_hz (or any other member of t), then you are passing uninitialized memory. You could use memset to clear t, or dynamically allocate zeroed memory. Normally, you use the per-transfer values: t.bits_per_word t.speed_hz only when you need to make them different from the default values set when you previously called spi_setup(), and the values of: t.delay_usecs t.cs_change when you need control over the changes in CS between transfers, and optionally a delay prior to changes in CS. Errors in handling these last two were addressed by the patch you tested, and which David pushed recently. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode 2008-09-12 1:53 ` Daniel Ribeiro 2008-09-12 2:53 ` Ned Forrester @ 2008-09-12 2:59 ` Ned Forrester 1 sibling, 0 replies; 14+ messages in thread From: Ned Forrester @ 2008-09-12 2:59 UTC (permalink / raw) To: Daniel Ribeiro Cc: David Brownell, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Ned Forrester wrote: > Daniel Ribeiro wrote: > In a past message, you showed the automatic declarations that went with > the above code: > > > struct spi_transfer t; > > struct spi_message m; > > While spi_message_init() zeros the memory in "m", you don't show any > code above, other than your assignments, that clears the memory in "t". > Thus, if you omit the assignments for t.delay_usecs or t.speed_hz (or > any other member of t), then you are passing uninitialized memory. You > could use memset to clear t, or dynamically allocate zeroed memory. > > Normally, you use the per-transfer values: > > t.bits_per_word > t.speed_hz > > only when you need to make them different from the default values set > when you previously called spi_setup() I forgot to mention that if either of these values is zero, then the default parameters set by initialization or spi_setup are used. If either value is non-zero, then the defaults are overridden. In your case, the uninitialized memory overrode the defaults. -- Ned Forrester nforrester-/d+BM93fTQY@public.gmane.org Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2008-09-12 2:59 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-17 22:53 [PATCH] pxa2xx_spi: wait_rx_stall before deasserting CS on PIO mode Daniel Ribeiro
[not found] ` <6669365c0808171553i3f64b667t18fcea589d94411a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-17 22:59 ` Daniel Ribeiro
2008-08-18 18:53 ` Ned Forrester
[not found] ` <48A9C515.3000908-/d+BM93fTQY@public.gmane.org>
2008-08-18 19:27 ` Daniel Ribeiro
[not found] ` <6669365c0808181227k2fa01d6fu570cebc10630f55d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-18 20:47 ` Ned Forrester
[not found] ` <48A9DFD9.9000708-/d+BM93fTQY@public.gmane.org>
2008-08-18 23:06 ` Daniel Ribeiro
[not found] ` <6669365c0808181606u4ead2f27h1f2286f9365e8a7a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-19 5:58 ` Ned Forrester
2008-08-19 5:58 ` Daniel Ribeiro
[not found] ` <6669365c0808182258t6c4a5086xd9425435930e6d8f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-08-19 6:08 ` Ned Forrester
2008-08-19 16:48 ` Ned Forrester
2008-09-11 17:41 ` David Brownell
[not found] ` <200809111041.20900.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-09-12 1:53 ` Daniel Ribeiro
2008-09-12 2:53 ` Ned Forrester
2008-09-12 2:59 ` Ned Forrester
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.