[SPAM] 出口贸易业务

2010-04-21 Thread 张生
 

   你好:
 
   我司可优惠代办贸促会证明书,品质证,健康证等各类CIQ证书,CO产地证.普惠证(FA,FE,

   FF,亚太,中巴)等各类清关证书。提供大小核销单(出口报关单).厂家可合作 退税单‘贴息单  

  代理商检 , 深圳进出口报关等业务
   
   如有业务需要可来电咨询:张先生(业务经理)
  
   传真:0755--25401451  联系电话:0755--25420177手机:13686868548  
 
   QQ:122062143 邮箱:szyongdongjia...@163.com  

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Tue, Apr 20, 2010 at 05:16:10PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 8:12 AM, Mika Westerberg wrote:
 
  This patch adds an SPI master driver for the Cirrus EP93xx SPI controller 
  found
  in EP93xx chips (EP9301, EP9302, EP9307, EP9312 and EP9315).
  
  Signed-off-by: Mika Westerberg mika.westerb...@iki.fi
 
 Mika,
 
 I discovered one gotcha with this driver.  Bear with me through this...
 
 1. ep93xx_spi_process_message is called by the workqueue worker function to 
 handle
a spi_message queued in by the ep93xx_spi_transfer function.  Before 
 starting
the actual transfer the chip select to the device is asserted.
 2. ep93xx_spi_process_transfer processes each transfer in the spi_message, 
 one at a
time, and does a wait_for_completion on each transfer.
 3. When the entire spi_message has been transferred the chip select to the 
 device
is deasserted.

Yes. There is possibility that last transfer -cs_change is set which can be 
used
by SPI controller drivers to keep the chip selected in case next message is 
going
to the same device.

However, I haven't implemented that as it is optional (but trivial to add 
afterwards).

 The problem is if a hardware design uses the SFRM1 pin as part of the chip 
 select
 logic.  The EP93xx User's Guide states that the SFRMOUT signal behaves as a 
 slave
 Select in Motorola SPI mode.  This signal behaves differently depending on 
 the
 SPI_MODE_* used.
 
 Modes 0 and 2:
   SFRMOUT is forced HIGH during idle periods.
   Start of transmission, SFRMOUT is driven LOW.
   Single word transmission, SFRMOUT is returned to its idle HIGH state one
 SCLKOUT period after the last bit has been captured.
   Back-to-back transmissions, SFRMOUT signal is pulsed HIGH between each
 data word transfer.  On completion the SFRMOUT pin returns to its idle
 HIGH state one SCLKOUT period after the last bit has been captured.
 
 Modes 1 and 3:
   SFRMOUT is forced HIGH during idle periods.
   Start of transmission, SFRMOUT is driven LOW.
   Single word transmission, SFRMOUT is returned to its idle HIGH state one
 SCLKOUT period after the last bit has been captured.
   Back-to-back transmissions, SFRMOUT signal is held LOW between each
 data word transfer.  On completion the SFRMOUT pin returns to its idle
 HIGH state one SCLKOUT period after the last bit has been captured.
 
 So, since each transfer does a wait_for_completion, all the data is 
 transmitted
 which causes the SFRMOUT pin to go HIGH between each transfer in the message.

Yes, unfortunately. SFRMOUT cannot be software controlled so it is
not suitable for general purpose chipselect. This was the sole
purpose of using GPIO lines for chipselects.

 For devices like the sst25lf040a SPI Flash on the EDB93xx boards this causes a
 problem.  To read data from that device you need to send a two part message.  
 The
 first part is a write transfer with the one byte command and three byte 
 address.
 This is then followed by a read transfer to get the data.  But since the 
 SFRMOUT
 pin goes high this ends the command.
 
 The driver Ryan and I worked on actually does work with the sst25lf040a on the
 EDB93xx boards.  But now that I know what the issue is, it was actually a race
 condition.  Sometimes it worked and sometimes it didn't...
 
 I would think the Sim.One board (Martin?) would have the same issue with the 
 mmc
 card since that design uses the SFRMOUT pin directly for the chip select.
 
 Is there anyway to keep the transfers going in a muiltipart message?

I'm not exactly sure but polling mode sounds something that could
work around that. It just need to be sure that it transmits
continuously to keep the SFRMOUT asserted.

You could try v3 of the driver with:
# modprobe ep93xx-spi transfer_method=0

and see if it works there.

An alternative would be that interrupt handler schedules tasklet which then
takes next transfer immediately once current transfer is finished.

Thanks,
MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Tue, Apr 20, 2010 at 08:52:26PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 6:10 PM, Martin Guy wrote:
  I have noticed on card insertion, the last line of:
  
  mmc0: problem reading switch capabilities, performance might suffer.
  mmc0: host does not support reading read-only switch. assuming write-enable.
  mmc0: new SD card on SPI
  mmcblk0: mmc0: SD952 MiB
   mmcblk0: p1 p2 p4
  mmcblk0: retrying using single block read
 
 That message might be related to the SFRM1 line being deasserted.

This message comes, depending on the card you are using.

It is easily reproduced with following command:

# fdisk -l

Problem there seems to be that fdisk (and also part of block layer that reads
partition table) seeks to the end of the disk and reads last block. I remember
reading some mail thread about the matter and it could be that some cards
do read-ahead which causes the response message to return failure (address error
as a response to STOP message which is completely bogus).

You can enable MMC debugging and see if this is the case with your card also.

I actually debugged this further some time ago and after failure if card status
register is read, there is no failure at all (card is in correct state).

 You could try cutting the trace going to pin 1 (CS pin) of the mmc socket and
 jumpering it to one of the EGPIO pins on JP15 (the LCD header) or JP16 (the
 keypad header).  You will of course need to modify your platform init to use
 the new chip select line.
 
  and the SDHC cards I have don't work at all, spewing tons of:
  mmcblk0: error -38 sending status comand
  mmcblk0: error -38 sending read/write command, response 0x4, card status 
  0xff04
  end_request: I/O error, dev mmcblk0, sector 7744509
 
 I haven't seen those error messages before.  Of course I don't have any SDHC
 cards... ;-)

With my TS-7260 board, SDHC cards work (but it uses GPIO lines).

MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Tue, Apr 20, 2010 at 12:24:26PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 8:12 AM, Mika Westerberg wrote:
  This patch adds an SPI master driver for the Cirrus EP93xx SPI controller 
  found
  in EP93xx chips (EP9301, EP9302, EP9307, EP9312 and EP9315).
  
  Signed-off-by: Mika Westerberg mika.westerb...@iki.fi
 
 Mika,
 
 I'm still looking this over but I have one quick comment.
 
  +/**
  + * ep93xx_spi_select_device() - select given SPI device
  + * @espi: ep93xx SPI controller struct
  + * @spi: SPI device to select
  + *
  + * Function asserts chipselect line as specified in @spi-chip_select in 
  board
  + * specific manner.
  + *
  + * Note that this function is called from a thread context and can sleep.
  + */
  +static inline void ep93xx_spi_select_device(const struct ep93xx_spi *espi,
  +   struct spi_device *spi)
  +{
  +   if (espi-cs_control)
  +   espi-cs_control(spi, !!(spi-mode  SPI_CS_HIGH));
  +}
  +
  +/**
  + * ep93xx_spi_deselect_device() - deselects given SPI device
  + * @espi: ep93xx SPI controller struct
  + * @spi: SPI device to deselect
  + *
  + * Function deasserts chipselect line as specified in @spi-chip_select in 
  board
  + * specific manner.
  + *
  + * Note that this function is called from a thread context and can sleep.
  + */
  +static inline void ep93xx_spi_deselect_device(const struct ep93xx_spi 
  *espi,
  + struct spi_device *spi)
  +{
  +   if (espi-cs_control)
  +   espi-cs_control(spi, !(spi-mode  SPI_CS_HIGH));
  +}
 
 These two functions can be combined.
 
 /**
  * ep93xx_spi_chip_select() - select/deselect a given SPI device
  * @espi: ep93xx SPI controller struct
  * @spi: SPI device to select
  * @assert: flag to assert the chip select line
  *
  * Note that this function is called from a thread context and can sleep.
  */
 static void ep93xx_spi_chip_select(const struct ep93xx_spi *espi,
struct spi_device *spi, int assert)
 {
   int value = (spi-mode  SPI_CS_HIGH) ? !!assert : !assert;
 
   if (espi-cs_control)
   espi-cs_control(spi, value);
 }
 
 Then just do:
 
 ep93xx_spi_select_device(espi, msg-spi, 1);  /* assert the spi chip select */
 
 ep93xx_spi_select_device(espi, msg-spi, 0);  /* deassert the spi chip select 
 */


I think it is more readable to do:

ep93xx_spi_select_device(espi, msg-spi);

and

ep93xx_spi_deselect_device(espi, msg-spi);

It can be seen from the function names what we are doing.

Thanks,
MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Tue, Apr 20, 2010 at 08:52:26PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 6:10 PM, Martin Guy wrote:
  Not easily, but it seems a likely cause.
  To prevent card deselection mid-message I think we would need to
  handle multi-transfer messages by making the start of transfers 2..N
  continuous with the end of transfers 1..N-1 instead of draining the
  reply from each one before starting the next.
  
  Am I on the right track?
 
 Yes.  I'm just not sure how to implement this.

I made a hack that allows transfer handler to continue to the next transfer 
directly
if there is no special per transfer settings in the message. Could you try that 
out
and report whether SFRMOUT works better with it?

Note that this is just to make sure that we are on the right track.

Patch is against v4 of the driver.

Thanks,
MW

diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c
index 310032d..11dcdd1 100644
--- a/drivers/spi/ep93xx_spi.c
+++ b/drivers/spi/ep93xx_spi.c
@@ -106,6 +106,8 @@ struct ep93xx_spi {
unsigned long   min_rate;
unsigned long   max_rate;
boolrunning;
+   boolcan_continue;
+   struct spi_transfer *last_transfer;
struct workqueue_struct *wq;
struct work_struct  msg_work;
struct completion   wait;
@@ -380,6 +382,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
struct spi_message *msg)
struct ep93xx_spi *espi = spi_master_get_devdata(spi-master);
struct spi_transfer *t;
unsigned long flags;
+   bool can_continue = true;
 
if (!msg || !msg-complete)
return -EINVAL;
@@ -387,11 +390,21 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
struct spi_message *msg)
/* first validate each transfer */
list_for_each_entry(t, msg-transfers, transfer_list) {
if (t-bits_per_word) {
+   can_continue = false;
if (t-bits_per_word  4 || t-bits_per_word  16)
return -EINVAL;
}
-   if (t-speed_hz  t-speed_hz  espi-min_rate)
+   if (t-speed_hz) {
+   can_continue = false;
+   if (t-speed_hz  espi-min_rate)
return -EINVAL;
+   }
+   if (t-cs_change 
+   !list_is_last(t-transfer_list, msg-transfers)) {
+   can_continue = false;
+   }
+   if (t-delay_usecs)
+   can_continue = false;
}
 
/*
@@ -400,7 +413,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
struct spi_message *msg)
 * error in transfer and @msg-state is used to hold pointer to the
 * current transfer (or %NULL if no active current transfer).
 */
-   msg-state = NULL;
+   msg-state = (void *)can_continue;
msg-status = 0;
msg-actual_length = 0;
 
@@ -606,10 +619,33 @@ static void ep93xx_spi_process_message(struct ep93xx_spi 
*espi,
ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg-spi));
ep93xx_spi_select_device(espi, msg-spi);
 
-   list_for_each_entry(t, msg-transfers, transfer_list) {
-   ep93xx_spi_process_transfer(espi, msg, t);
-   if (msg-status)
-   break;
+   if (msg-state) {
+   espi-can_continue = true;
+   espi-last_transfer = list_entry(msg-transfers.prev, struct 
spi_transfer,
+transfer_list);
+   } else {
+   espi-can_continue = false;
+   espi-last_transfer = NULL;
+   }
+
+   /*
+* In case there is no transfer specific settings in this message we
+* can transfer the whole message with interrupts. Otherwise we need
+* to perform transfer specific stuff in thread context.
+*/
+   if (espi-can_continue) {
+   msg-state = list_first_entry(msg-transfers, struct 
spi_transfer,
+ transfer_list);
+   espi-rx = 0;
+   espi-tx = 0;
+   ep93xx_spi_enable_interrupts(espi);
+   wait_for_completion(espi-wait);
+   } else {
+   list_for_each_entry(t, msg-transfers, transfer_list) {
+   ep93xx_spi_process_transfer(espi, msg, t);
+   if (msg-status)
+   break;
+   }
}
 
/*
@@ -792,6 +828,24 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void 
*dev_id)
 * interrupt then.
 */
return IRQ_HANDLED;
+   } else {
+   /*
+* If we can continue 

Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Wed, Apr 21, 2010 at 11:47:13AM -0500, H Hartley Sweeten wrote:
 On Wednesday, April 21, 2010 12:16 AM, Mika Westerberg wrote:
  I think it is more readable to do:
 
  ep93xx_spi_select_device(espi, msg-spi);
 
  and
 
  ep93xx_spi_deselect_device(espi, msg-spi);
 
  It can be seen from the function names what we are doing.
 
 So rename the combined function to ep93xx_spi_cs_control and pass the 
 control
 parameter as a bool; true = selected, false = deselected.
 
 Having the two almost identical functions is a bit redundant.  It also gives 
 you
 two places to have to maintain basically the same operation.  I think this is
 what Grant was referring to with his previous comment.

Agreed. Will do.

Thanks,
MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread H Hartley Sweeten
On Tuesday, April 20, 2010 11:37 PM, Mika Westerberg wrote:
 On Tue, Apr 20, 2010 at 05:16:10PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 8:12 AM, Mika Westerberg wrote:

 This patch adds an SPI master driver for the Cirrus EP93xx SPI controller 
 found
 in EP93xx chips (EP9301, EP9302, EP9307, EP9312 and EP9315).
 
 Signed-off-by: Mika Westerberg mika.westerb...@iki.fi
 
 Mika,
 
 I discovered one gotcha with this driver.  Bear with me through this...
 
 1. ep93xx_spi_process_message is called by the workqueue worker function to 
 handle
a spi_message queued in by the ep93xx_spi_transfer function.  Before 
 starting
the actual transfer the chip select to the device is asserted.
 2. ep93xx_spi_process_transfer processes each transfer in the spi_message, 
 one at a
time, and does a wait_for_completion on each transfer.
 3. When the entire spi_message has been transferred the chip select to the 
 device
is deasserted.

 Yes. There is possibility that last transfer -cs_change is set which can be 
 used
 by SPI controller drivers to keep the chip selected in case next message is 
 going
 to the same device.

 However, I haven't implemented that as it is optional (but trivial to add 
 afterwards).

It should be implemented.  The mmc_spi driver basically requires this.  Refer 
to this
comment in the mmc_spi driver:

 * - We tell the controller to keep the chipselect active from the
 *   beginning of an mmc_host_ops.request until the end.  So beware
 *   of SPI controller drivers that mis-handle the cs_change flag!
 *
 *   However, many cards seem OK with chipselect flapping up/down
 *   during that time ... at least on unshared bus segments.

 The problem is if a hardware design uses the SFRM1 pin as part of the chip 
 select
 logic.  The EP93xx User's Guide states that the SFRMOUT signal behaves as a 
 slave
 Select in Motorola SPI mode.  This signal behaves differently depending on 
 the
 SPI_MODE_* used.
 
 Modes 0 and 2:
   SFRMOUT is forced HIGH during idle periods.
   Start of transmission, SFRMOUT is driven LOW.
   Single word transmission, SFRMOUT is returned to its idle HIGH state one
 SCLKOUT period after the last bit has been captured.
   Back-to-back transmissions, SFRMOUT signal is pulsed HIGH between each
 data word transfer.  On completion the SFRMOUT pin returns to its idle
 HIGH state one SCLKOUT period after the last bit has been captured.
 
 Modes 1 and 3:
   SFRMOUT is forced HIGH during idle periods.
   Start of transmission, SFRMOUT is driven LOW.
   Single word transmission, SFRMOUT is returned to its idle HIGH state one
 SCLKOUT period after the last bit has been captured.
   Back-to-back transmissions, SFRMOUT signal is held LOW between each
 data word transfer.  On completion the SFRMOUT pin returns to its idle
 HIGH state one SCLKOUT period after the last bit has been captured.
 
 So, since each transfer does a wait_for_completion, all the data is 
 transmitted
 which causes the SFRMOUT pin to go HIGH between each transfer in the message.

 Yes, unfortunately. SFRMOUT cannot be software controlled so it is
 not suitable for general purpose chipselect. This was the sole
 purpose of using GPIO lines for chipselects.

I agree.  But existing ep93xx designs, the EDB93xx boards and Sim.One for
instance, use the SFRMOUT either directly for the chip select or as part of
the logic generating the chip select.  If possible it would be nice to handle
this.

 For devices like the sst25lf040a SPI Flash on the EDB93xx boards this causes 
 a
 problem.  To read data from that device you need to send a two part message. 
  The
 first part is a write transfer with the one byte command and three byte 
 address.
 This is then followed by a read transfer to get the data.  But since the 
 SFRMOUT
 pin goes high this ends the command.
 
 The driver Ryan and I worked on actually does work with the sst25lf040a on 
 the
 EDB93xx boards.  But now that I know what the issue is, it was actually a 
 race
 condition.  Sometimes it worked and sometimes it didn't...
 
 I would think the Sim.One board (Martin?) would have the same issue with the 
 mmc
 card since that design uses the SFRMOUT pin directly for the chip select.
 
 Is there anyway to keep the transfers going in a muiltipart message?

 I'm not exactly sure but polling mode sounds something that could
 work around that. It just need to be sure that it transmits
 continuously to keep the SFRMOUT asserted.

 You could try v3 of the driver with:
   # modprobe ep93xx-spi transfer_method=0

 and see if it works there.

I'll try to test this later.  The driver Ryan and I had used polling and it
worked but I think there was a race condition in it which occasionally broke
the transfer.

 An alternative would be that interrupt handler schedules tasklet which then
 takes next transfer immediately once current transfer is finished.

I think you would need to:

1. detect when all the transmit data in a 

Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread H Hartley Sweeten
On Wednesday, April 21, 2010 3:47 AM, Mika Westerberg wrote:
 On Tue, Apr 20, 2010 at 08:52:26PM -0500, H Hartley Sweeten wrote:
 On Tuesday, April 20, 2010 6:10 PM, Martin Guy wrote:
 Not easily, but it seems a likely cause.
 To prevent card deselection mid-message I think we would need to
 handle multi-transfer messages by making the start of transfers 2..N
 continuous with the end of transfers 1..N-1 instead of draining the
 reply from each one before starting the next.
 
 Am I on the right track?
 
 Yes.  I'm just not sure how to implement this.

 I made a hack that allows transfer handler to continue to the next transfer 
 directly
 if there is no special per transfer settings in the message. Could you try 
 that out
 and report whether SFRMOUT works better with it?

 Note that this is just to make sure that we are on the right track.

 Patch is against v4 of the driver.

 Thanks,
 MW

 diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c
 index 310032d..11dcdd1 100644
 --- a/drivers/spi/ep93xx_spi.c
 +++ b/drivers/spi/ep93xx_spi.c
 @@ -106,6 +106,8 @@ struct ep93xx_spi {
   unsigned long   min_rate;
   unsigned long   max_rate;
   boolrunning;
 + boolcan_continue;
 + struct spi_transfer *last_transfer;
   struct workqueue_struct *wq;
   struct work_struct  msg_work;
   struct completion   wait;
 @@ -380,6 +382,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
 struct spi_message *msg)
   struct ep93xx_spi *espi = spi_master_get_devdata(spi-master);
   struct spi_transfer *t;
   unsigned long flags;
 + bool can_continue = true;
  
   if (!msg || !msg-complete)
   return -EINVAL;
 @@ -387,11 +390,21 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
 struct spi_message *msg)
   /* first validate each transfer */
   list_for_each_entry(t, msg-transfers, transfer_list) {
   if (t-bits_per_word) {
 + can_continue = false;
   if (t-bits_per_word  4 || t-bits_per_word  16)
   return -EINVAL;
   }
 - if (t-speed_hz  t-speed_hz  espi-min_rate)
 + if (t-speed_hz) {
 + can_continue = false;
 + if (t-speed_hz  espi-min_rate)
   return -EINVAL;
 + }
 + if (t-cs_change 
 + !list_is_last(t-transfer_list, msg-transfers)) {
 + can_continue = false;
 + }
 + if (t-delay_usecs)
 + can_continue = false;
   }
  
   /*
 @@ -400,7 +413,7 @@ static int ep93xx_spi_transfer(struct spi_device *spi, 
 struct spi_message *msg)
* error in transfer and @msg-state is used to hold pointer to the
* current transfer (or %NULL if no active current transfer).
*/
 - msg-state = NULL;
 + msg-state = (void *)can_continue;
   msg-status = 0;
   msg-actual_length = 0;
  
 @@ -606,10 +619,33 @@ static void ep93xx_spi_process_message(struct 
 ep93xx_spi *espi,
   ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg-spi));
   ep93xx_spi_select_device(espi, msg-spi);
  
 - list_for_each_entry(t, msg-transfers, transfer_list) {
 - ep93xx_spi_process_transfer(espi, msg, t);
 - if (msg-status)
 - break;
 + if (msg-state) {
 + espi-can_continue = true;
 + espi-last_transfer = list_entry(msg-transfers.prev, struct 
 spi_transfer,
 +  transfer_list);
 + } else {
 + espi-can_continue = false;
 + espi-last_transfer = NULL;
 + }
 +
 + /*
 +  * In case there is no transfer specific settings in this message we
 +  * can transfer the whole message with interrupts. Otherwise we need
 +  * to perform transfer specific stuff in thread context.
 +  */
 + if (espi-can_continue) {
 + msg-state = list_first_entry(msg-transfers, struct 
 spi_transfer,
 +   transfer_list);
 + espi-rx = 0;
 + espi-tx = 0;
 + ep93xx_spi_enable_interrupts(espi);
 + wait_for_completion(espi-wait);
 + } else {
 + list_for_each_entry(t, msg-transfers, transfer_list) {
 + ep93xx_spi_process_transfer(espi, msg, t);
 + if (msg-status)
 + break;
 + }
   }
  
   /*
 @@ -792,6 +828,24 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void 
 *dev_id)
* interrupt then.
*/
   return IRQ_HANDLED;
 + } else {
 + /*
 +  * If we can continue 

Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread H Hartley Sweeten
Mika,

I have added some debug messages to the driver trying to figure out
how to chain the transfers in a message together in order to keep
the SFRM signal asserted for the entire message.  I still haven't
worked out a good solution but I did notice something else.

First, every spi transaction, including a single byte transfer, is
going to generate at least two interrupts.  One when the interrupts
are first enabled because the TX FIFO is empty.  And a second when
that byte has been transferred and the TX FIFO is again empty.

The first interrupt can be prevented by priming the TX FIFO before
enabling the interrupts.  All you need to do is call ep93xx_spi_read_write
right before ep93xx_spi_enable_interrupts.

Second, at high clock rates the RX FIFO will actually start to
fill as you are putting data into the TX FIFO.  If you add an inner
reader loop to the writer loop in ep93xx_spi_read_write you can
take advantage of this and reduce the number of interrupts generated
for large transfers.

For instance the mmc_spi driver regularly does 3 transfer messages
where the last transfer is a 512 byte read.  With your current v4
driver this message averages 69 interrupts to complete.  By adding
the inner reader it reduces the number of interrupts to an average
of 40.

Regards,
Hartley

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Wed, Apr 21, 2010 at 01:00:56PM -0500, H Hartley Sweeten wrote:
 Same results are your v4 driver.  But, I think your on the right track.

Thanks for testing.

 I think the problem is in the ep93xx_spi_read_write routine.  That function
 returns 0 as long as there is still data left in the current transfer.  The
 only time it doesn't return 0, which will cause the can_continue, is when:
 
   if (espi-rx == t-len) {
   msg-actual_length += t-len;
   return t-len;
   }
 
 At this point the tx and rx fifos will both be empty, which causes the SSP
 peripheral to raise the SFRM signal.

True.

 A picture is worth a thousand words... Attached is a logic analyzer capture
 of the Read-ID command and response from the SPI Flash.  EGPIO7 is my chip
 select to the flash.  The first 4 SPI MOSI (Tx) blocks are the 0x90, 0x00,
 0x00, 0x00 command to the flash.  You will notice that the SFRM line is
 asserted for those bytes.  A bit later are the 2 SPI MISO (Rx) responses
 from the flash with the ManID/DevID, again with the SFRM line asserted.

Yeah, it clearly shows that SFRMOUT is deasserted between transfers :(

I will try to work out some sort of hack which will keep the FIFOs from
emptying.

MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4 1/2] spi: implemented driver for Cirrus EP93xx SPI controller

2010-04-21 Thread Mika Westerberg
On Wed, Apr 21, 2010 at 09:47:14PM -0500, H Hartley Sweeten wrote:
[...]
 First, every spi transaction, including a single byte transfer, is
 going to generate at least two interrupts.  One when the interrupts
 are first enabled because the TX FIFO is empty.  And a second when
 that byte has been transferred and the TX FIFO is again empty.
 
 The first interrupt can be prevented by priming the TX FIFO before
 enabling the interrupts.  All you need to do is call ep93xx_spi_read_write
 right before ep93xx_spi_enable_interrupts.

OK thanks.

 Second, at high clock rates the RX FIFO will actually start to
 fill as you are putting data into the TX FIFO.  If you add an inner
 reader loop to the writer loop in ep93xx_spi_read_write you can
 take advantage of this and reduce the number of interrupts generated
 for large transfers.

I originally had inner read loop in the first version of the driver
but it wasn't functioning as it should (this was pointed out by
Martin). But now when we have explicit FIFO size handling, I think
that it can be added there again.

Thanks,
MW

--
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general