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

2013-09-23 Thread Rhyland Klein
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.
 
 I don't really follow this patch description well. It may help if you
 fully spelled out the definition of normal behaviour, what the driver
 was doing, and what it should be doing (which is presumable what it does
 do after this patch).

Yah, I'll explain the cs_change logic a little clearer in the next
version, but for now:

cs_change is meant to invert the normal behavior of the CS line during a
SPI transfer. Normally, the CS line stays asserted from the beginning of
the first transfer until the last is completed within the same
spi_message, and then it is deasserted. There can be any number of
spi_transfers within a spi_message. When cs_change is asserted for a
spi_transfer that is not the last one in the message, this means that
after that transfer is completed, the CS line should be deasserted
(where normally it would stay asserted). Then when the next transfer
starts, it will assert CS again. If the last spi_transfer in a
spi_message has cs_change set, then it means that instead of deasserted
CS at the end of the transaction (spi_message) then it leaves CS asserted.

 
 This patch modifies the logic so that the cs state will be toggled after
 every individual transfer or NOT toggled at the end of the last transfer
 if cs_change is set in that transfer struct.

 Also, this builds in logic so that if a different device tries to start
 a transfer while CS is active from a different device, it will abort the
 previous transfer and start a new one for the new device.
 
 What user-visible impact does this patch have. Does it solve a bug, or
 improve performance, or ...? In other words, how would I test this
 patch, other that testing for regressions in SPI functionality that I
 know already works.

This allows a spi client to send a write, and then any number of reads
as a single spi transaction, but separated into separate spi_messages. I
tested this for ChromeOS where our platform has an embedded controller
which communicates over SPI. It has some quirks, namely when we read
back data, we maybe need to do multiple reads before we start getting
valid data. This means we need to be able to control when the CS line is
deasserted which would be after we know we finally received all the data
we were expecting.

I don't know of any other hardware currently that is good for exercising
this logic on our reference boards.

 
 BTW, I don't think you're using get_maintainer.pl, since Mark Brown is
 the SPI maintainer now, not Grant Likely.

I could have sworn I ran it, but I didn't see Mark come up, I'll
definitely add him for the next revision.

 
 diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
 index 145dd43..a9973de 100644
 --- a/drivers/spi/spi-tegra114.c
 +++ b/drivers/spi/spi-tegra114.c
 @@ -182,6 +182,7 @@ struct tegra_spi_data {
  u32 cur_speed;
  
  struct spi_device   *cur_spi;
 +struct spi_device   *cs_control;
  unsignedcur_pos;
  unsignedcur_len;
  unsignedwords_per_32bit;
 @@ -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
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.

 
 +tspi-cs_control = NULL;
 +} else
 +tegra_spi_writel(tspi, command1, SPI_COMMAND1);
  
  command1 |= SPI_CS_SW_HW;
  if (spi-mode  SPI_CS_HIGH)
 @@ -732,6 +738,9 @@ static int tegra_spi_start_transfer_one(struct 
 spi_device *spi,
  command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
  }
  
 +if (t-len == 0  !t-tx_buf  !t-rx_buf)
 +return 0;
 
 What if !t-len, but t-tx_buf || t-rx_buf ?
 
 This code is also duplicated in tegra_spi_transfer_one_message() after
 this patch. Instead, perhaps the first N lines of
 tegra_spi_start_transfer_one() should be split out into e.g

[RESEND] spi/tegra114: Correct support for cs_change

2013-09-18 Thread Rhyland Klein
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.

This patch modifies the logic so that the cs state will be toggled after
every individual transfer or NOT toggled at the end of the last transfer
if cs_change is set in that transfer struct.

Also, this builds in logic so that if a different device tries to start
a transfer while CS is active from a different device, it will abort the
previous transfer and start a new one for the new device.

This work was based on the spi-atmel driver.

Signed-off-by: Rhyland Klein rkl...@nvidia.com
---

RESEND WITH CORRECT PATCH ANNOTATION IN SUBJECT

 drivers/spi/spi-tegra114.c |   59 ++--
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 145dd43..a9973de 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -182,6 +182,7 @@ struct tegra_spi_data {
u32 cur_speed;
 
struct spi_device   *cur_spi;
+   struct spi_device   *cs_control;
unsignedcur_pos;
unsignedcur_len;
unsignedwords_per_32bit;
@@ -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);
+   tspi-cs_control = NULL;
+   } else
+   tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
command1 |= SPI_CS_SW_HW;
if (spi-mode  SPI_CS_HIGH)
@@ -732,6 +738,9 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
}
 
+   if (t-len == 0  !t-tx_buf  !t-rx_buf)
+   return 0;
+
if (tspi-is_packed)
command1 |= SPI_PACKED;
 
@@ -803,6 +812,17 @@ static int tegra_spi_setup(struct spi_device *spi)
return 0;
 }
 
+static void tegra_spi_transfer_delay(int delay)
+{
+   if (!delay)
+   return;
+
+   if (delay = 1000)
+   mdelay(delay / 1000);
+
+   udelay(delay % 1000);
+}
+
 static int tegra_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
 {
@@ -812,6 +832,7 @@ static int tegra_spi_transfer_one_message(struct spi_master 
*master,
struct spi_transfer *xfer;
struct spi_device *spi = msg-spi;
int ret;
+   bool skip = false;
 
msg-status = 0;
msg-actual_length = 0;
@@ -819,13 +840,20 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
single_xfer = list_is_singular(msg-transfers);
list_for_each_entry(xfer, msg-transfers, transfer_list) {
INIT_COMPLETION(tspi-xfer_completion);
+
ret = tegra_spi_start_transfer_one(spi, xfer,
is_first_msg, single_xfer);
if (ret  0) {
dev_err(tspi-dev,
spi can not start transfer, err %d\n, ret);
-   goto exit;
+   goto complete_xfer;
+   }
+
+   if (xfer-len == 0  !xfer-tx_buf  !xfer-rx_buf) {
+   skip = true;
+   goto complete_xfer;
}
+
is_first_msg = false;
ret = wait_for_completion_timeout(tspi-xfer_completion,
SPI_DMA_TIMEOUT);
@@ -833,24 +861,41 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
dev_err(tspi-dev,
spi trasfer timeout, err %d\n, ret);
ret = -EIO;
-   goto exit;
+   goto complete_xfer;
}
 
if (tspi-tx_status ||  tspi-rx_status) {
dev_err(tspi-dev, Error in Transfer\n);
ret = -EIO;
-   goto exit;
+   goto complete_xfer;
}
msg-actual_length += xfer-len;
-   if (xfer-cs_change  xfer-delay_usecs) {
+
+complete_xfer:
+   if (ret  0 || skip) {
tegra_spi_writel(tspi, tspi-def_command1_reg,
SPI_COMMAND1);
-   udelay(xfer-delay_usecs

[IP REVIEW] spi/tegra114: Correct support for cs_change

2013-09-18 Thread Rhyland Klein
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.

This patch modifies the logic so that the cs state will be toggled after
every individual transfer or NOT toggled at the end of the last transfer
if cs_change is set in that transfer struct.

Also, this builds in logic so that if a different device tries to start
a transfer while CS is active from a different device, it will abort the
previous transfer and start a new one for the new device.

This work was based on the spi-atmel driver.

Signed-off-by: Rhyland Klein rkl...@nvidia.com
---
 drivers/spi/spi-tegra114.c |   59 ++--
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 145dd43..a9973de 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -182,6 +182,7 @@ struct tegra_spi_data {
u32 cur_speed;
 
struct spi_device   *cur_spi;
+   struct spi_device   *cs_control;
unsignedcur_pos;
unsignedcur_len;
unsignedwords_per_32bit;
@@ -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);
+   tspi-cs_control = NULL;
+   } else
+   tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
command1 |= SPI_CS_SW_HW;
if (spi-mode  SPI_CS_HIGH)
@@ -732,6 +738,9 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
}
 
+   if (t-len == 0  !t-tx_buf  !t-rx_buf)
+   return 0;
+
if (tspi-is_packed)
command1 |= SPI_PACKED;
 
@@ -803,6 +812,17 @@ static int tegra_spi_setup(struct spi_device *spi)
return 0;
 }
 
+static void tegra_spi_transfer_delay(int delay)
+{
+   if (!delay)
+   return;
+
+   if (delay = 1000)
+   mdelay(delay / 1000);
+
+   udelay(delay % 1000);
+}
+
 static int tegra_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
 {
@@ -812,6 +832,7 @@ static int tegra_spi_transfer_one_message(struct spi_master 
*master,
struct spi_transfer *xfer;
struct spi_device *spi = msg-spi;
int ret;
+   bool skip = false;
 
msg-status = 0;
msg-actual_length = 0;
@@ -819,13 +840,20 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
single_xfer = list_is_singular(msg-transfers);
list_for_each_entry(xfer, msg-transfers, transfer_list) {
INIT_COMPLETION(tspi-xfer_completion);
+
ret = tegra_spi_start_transfer_one(spi, xfer,
is_first_msg, single_xfer);
if (ret  0) {
dev_err(tspi-dev,
spi can not start transfer, err %d\n, ret);
-   goto exit;
+   goto complete_xfer;
+   }
+
+   if (xfer-len == 0  !xfer-tx_buf  !xfer-rx_buf) {
+   skip = true;
+   goto complete_xfer;
}
+
is_first_msg = false;
ret = wait_for_completion_timeout(tspi-xfer_completion,
SPI_DMA_TIMEOUT);
@@ -833,24 +861,41 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
dev_err(tspi-dev,
spi trasfer timeout, err %d\n, ret);
ret = -EIO;
-   goto exit;
+   goto complete_xfer;
}
 
if (tspi-tx_status ||  tspi-rx_status) {
dev_err(tspi-dev, Error in Transfer\n);
ret = -EIO;
-   goto exit;
+   goto complete_xfer;
}
msg-actual_length += xfer-len;
-   if (xfer-cs_change  xfer-delay_usecs) {
+
+complete_xfer:
+   if (ret  0 || skip) {
tegra_spi_writel(tspi, tspi-def_command1_reg,
SPI_COMMAND1);
-   udelay(xfer-delay_usecs);
+   tegra_spi_transfer_delay(xfer

Re: [PATCH 4/4] spi: remove unused Tegra platform data header

2013-03-08 Thread Rhyland Klein
On 3/2/2013 6:02 PM, Grant Likely wrote:
 On Fri, 15 Feb 2013 15:03:50 -0700, Stephen Warren swar...@wwwdotorg.org 
 wrote:
 From: Stephen Warren swar...@nvidia.com

 The platform data header is no longer used. Delete it.

 Signed-off-by: Stephen Warren swar...@nvidia.com
 I like the diffstat for this series. Applied!

 Thanks,
 g.

 --
 To unsubscribe from this list: send the line unsubscribe linux-tegra in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grant, I was looking to pull these patches. I don't see them in 
linux-next and I
looked at your repo and didn't see them. Can you give me a pointer?

Thanks,
Rhyland

-- 
nvpublic


--
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and remains a good choice in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general