Re: [RESEND] spi/tegra114: Correct support for cs_change

2013-09-23 Thread Simon Glass
Hi,

On Mon, Sep 23, 2013 at 3:14 PM, Stephen Warren swar...@wwwdotorg.orgwrote:

 On 09/23/2013 03:01 PM, Rhyland Klein wrote:
  On 9/23/2013 3:58 PM, Stephen Warren wrote:
  On 09/23/2013 01:48 PM, Rhyland Klein wrote:
  On 9/23/2013 2:51 PM, Stephen Warren wrote:
  On 09/18/2013 12:17 PM, Rhyland Klein wrote:
  The tegra114 driver wasn't currently handling the cs_change
 functionality.
  It is meant to invert normal behavior, and we were only using it to
 possibly
  delay at the end of a transfer.
  ...
  diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
  ...
  @@ -717,7 +718,12 @@ static int tegra_spi_start_transfer_one(struct
 spi_device *spi,
else if (req_mode == SPI_MODE_3)
command1 |= SPI_CONTROL_MODE_3;
 
  - tegra_spi_writel(tspi, command1, SPI_COMMAND1);
  + if (tspi-cs_control) {
  + if (tspi-cs_control != spi)
  + tegra_spi_writel(tspi, command1,
 SPI_COMMAND1);
 
  Do you really need a separate write call there? The value of command1
  isn't fully set up there (the CS bits are all set up immediately
 after),
  so won't that glitch the CS lines in some cases?
 
  On our hardware (as far as I've seen), the CS line is normally low. We
 
  I assume you meant normally *active* low, not normally low?
 
  I mean that when I look at CS, before a transaction starts, the line is
  low. Then we do a write like this (default SPI_COMMAND1) you see CS rise
  and fall very soon after. This is purely how we generate the edge
  triggers (as far as I can tell on all Tegra hw, though Laxman can
  correct me if I am wrong).

 That sounds broken. Normally, shouldn't CS assert before a transaction,
 stay asserted during a transaction, then deassert after the transaction?
 It shouldn't rise and fall very quickly in between parts of the
 transaction.

  need to generate a falling-edge to trigger the beginning of a SPI
  transaction. Doing this write with the default value of SPI_COMMAND1
  causes a brief rise and fall of CS, giving us our falling-edge.
 
  That sounds like exactly the glitch I was talking about.
 
  Assuming CS isn't held constantly asserted (low), isn't CS de-asserted
  (rises) at the end of transaction n-1, and re-asserted (falls) at the
  start of transaction n? If so, I'm not sure why the setup for
  transaction n needs to both de-assert and then re-assert it? It seems
  like cs_control should be handled at the end of a transaction, not at
  the start of the next one.
 
  cs_change has to maintain state over spi_message boundries, not just
  between spi_transfers within a spi_message.
 
  In this specific case, this is a safe guard.
 
  + if (tspi-cs_control) {
  This sees that the previous transfer stored its spi_device pointer,
  meaning it had cs_change set on the last part of the last spi_message
  (I.E. CS hasn't been deasserted, so the SPI transaction is still
 on-going).
 
  + if (tspi-cs_control != spi)
  This however finds that the device trying to send a SPI message isn't
  the same one that was in the middle of its transaction. This is a
  collision between 2 clients on 1 bus. This simply ends the previous
  transaction (the ongoing one) in favor of starting a new transaction.
 
  Otherwise, this logic allows us to skip the spi of COMMAND1 which would
  normally be used to create the falling edge to start a new transaction,
  leaving the previous one open for more transfers.

 This sounds like something the SPI core should be managing. If a driver
 is using the SPI bus to communicate with a device in a way that needs CS
 left active while outside a transaction, it shouldn't be possible for
 another driver to come along and communicate with another device before
 the first transaction is all complete. The bus should be locked.
 Allowing anything else could corrupt the protocol that required specific
 CS states outside the transaction.


Perhaps the client driver should use spi_sync_locked() instead if it wants
to avoid this problem? To me this driver code seems reasonable in the
circumstances.

Note: at present the Chrome OS EC driver does not support sharing a SPI bus
with anything else, and neither does the EC.

Regards,
Simon
--
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register 
http://pubads.g.doubleclick.net/gampad/clk?id=60133471iu=/4140/ostg.clktrk
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [RESEND] spi/tegra114: Correct support for cs_change

2013-09-23 Thread Simon Glass
[trying again]

Hi,

On Mon, Sep 23, 2013 at 3:14 PM, Stephen Warren swar...@wwwdotorg.org wrote:
 On 09/23/2013 03:01 PM, Rhyland Klein wrote:
 On 9/23/2013 3:58 PM, Stephen Warren wrote:
 On 09/23/2013 01:48 PM, Rhyland Klein wrote:
 On 9/23/2013 2:51 PM, Stephen Warren wrote:
 On 09/18/2013 12:17 PM, Rhyland Klein wrote:
 The tegra114 driver wasn't currently handling the cs_change 
 functionality.
 It is meant to invert normal behavior, and we were only using it to 
 possibly
 delay at the end of a transfer.
 ...
 diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
 ...
 @@ -717,7 +718,12 @@ static int tegra_spi_start_transfer_one(struct 
 spi_device *spi,
   else if (req_mode == SPI_MODE_3)
   command1 |= SPI_CONTROL_MODE_3;

 - tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 + if (tspi-cs_control) {
 + if (tspi-cs_control != spi)
 + tegra_spi_writel(tspi, command1, SPI_COMMAND1);

 Do you really need a separate write call there? The value of command1
 isn't fully set up there (the CS bits are all set up immediately after),
 so won't that glitch the CS lines in some cases?

 On our hardware (as far as I've seen), the CS line is normally low. We

 I assume you meant normally *active* low, not normally low?

 I mean that when I look at CS, before a transaction starts, the line is
 low. Then we do a write like this (default SPI_COMMAND1) you see CS rise
 and fall very soon after. This is purely how we generate the edge
 triggers (as far as I can tell on all Tegra hw, though Laxman can
 correct me if I am wrong).

 That sounds broken. Normally, shouldn't CS assert before a transaction,
 stay asserted during a transaction, then deassert after the transaction?
 It shouldn't rise and fall very quickly in between parts of the transaction.

 need to generate a falling-edge to trigger the beginning of a SPI
 transaction. Doing this write with the default value of SPI_COMMAND1
 causes a brief rise and fall of CS, giving us our falling-edge.

 That sounds like exactly the glitch I was talking about.

 Assuming CS isn't held constantly asserted (low), isn't CS de-asserted
 (rises) at the end of transaction n-1, and re-asserted (falls) at the
 start of transaction n? If so, I'm not sure why the setup for
 transaction n needs to both de-assert and then re-assert it? It seems
 like cs_control should be handled at the end of a transaction, not at
 the start of the next one.

 cs_change has to maintain state over spi_message boundries, not just
 between spi_transfers within a spi_message.

 In this specific case, this is a safe guard.

 + if (tspi-cs_control) {
 This sees that the previous transfer stored its spi_device pointer,
 meaning it had cs_change set on the last part of the last spi_message
 (I.E. CS hasn't been deasserted, so the SPI transaction is still on-going).

 + if (tspi-cs_control != spi)
 This however finds that the device trying to send a SPI message isn't
 the same one that was in the middle of its transaction. This is a
 collision between 2 clients on 1 bus. This simply ends the previous
 transaction (the ongoing one) in favor of starting a new transaction.

 Otherwise, this logic allows us to skip the spi of COMMAND1 which would
 normally be used to create the falling edge to start a new transaction,
 leaving the previous one open for more transfers.

 This sounds like something the SPI core should be managing. If a driver
 is using the SPI bus to communicate with a device in a way that needs CS
 left active while outside a transaction, it shouldn't be possible for
 another driver to come along and communicate with another device before
 the first transaction is all complete. The bus should be locked.
 Allowing anything else could corrupt the protocol that required specific
 CS states outside the transaction.

Perhaps the client driver should use spi_sync_locked() instead if it
wants to avoid this problem? To me this driver code seems reasonable
in the circumstances.

Note: at present the Chrome OS EC driver does not support sharing a
SPI bus with anything else, and neither does the EC.

Regards,
Simon

--
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register 
http://pubads.g.doubleclick.net/gampad/clk?id=60133471iu=/4140/ostg.clktrk
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general