Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-03-03 Thread Marek Vasut
On Monday, March 03, 2014 at 11:23:33 AM, Yao Yuan wrote:
> Hi, Marek
> 
> Marek Vasut wrote:
> > On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
> > 
> > [...]
> > 
> > > +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
> > > + struct imx_i2c_dma *dma = i2c_imx->dma;
> > > + struct dma_chan *dma_chan;
> > > +
> > > + dma_chan = dma->chan_tx;
> > > + dma->chan_tx = NULL;
> > > + dma->buf_tx = 0;
> > > + dma->len_tx = 0;
> > > + dma_release_channel(dma_chan);
> > > +
> > > + dma_chan = dma->chan_rx;
> > > + dma->chan_tx = NULL;
> > > + dma->buf_rx = 0;
> > > + dma->len_rx = 0;
> > > + dma_release_channel(dma_chan);
> > 
> > You must make _DEAD_ _SURE_ this function is not ever called while the
> > DMA is still active. In your case, I have a feeling that's not handled.
> 
> Thanks for your attention.
> This few days I look up the code for the realization of
> dma_release_channel(). I found that it will disable the dma request first.
> So it's may safe. And drivers hadn't check whether dma is still active
> before dma_release_channel() as a usually usage. Because it will be
> disabled automatic.
> 
> The only problem is that, it will be forced to cancel the transfer which
> was not yet completed. Looking forward to hearing from you.

OK

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-03-03 Thread Yao Yuan
Hi, Marek

Marek Vasut wrote:
> On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
> 
> [...]
> 
> > +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
> > +   struct imx_i2c_dma *dma = i2c_imx->dma;
> > +   struct dma_chan *dma_chan;
> > +
> > +   dma_chan = dma->chan_tx;
> > +   dma->chan_tx = NULL;
> > +   dma->buf_tx = 0;
> > +   dma->len_tx = 0;
> > +   dma_release_channel(dma_chan);
> > +
> > +   dma_chan = dma->chan_rx;
> > +   dma->chan_tx = NULL;
> > +   dma->buf_rx = 0;
> > +   dma->len_rx = 0;
> > +   dma_release_channel(dma_chan);
> 
> You must make _DEAD_ _SURE_ this function is not ever called while the
> DMA is still active. In your case, I have a feeling that's not handled.
>

Thanks for your attention.
This few days I look up the code for the realization of dma_release_channel(). 
I found that it will disable the dma request first. So it's may safe. 
And drivers hadn't check whether dma is still active before 
dma_release_channel() as a usually usage.
Because it will be disabled automatic.

The only problem is that, it will be forced to cancel the transfer which was 
not yet completed.
Looking forward to hearing from you.

Best regards,
Yuan Yao
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a���
0��h���i

RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-03-03 Thread Yao Yuan
Hi, Marek

Marek Vasut wrote:
 On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
 
 [...]
 
  +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
  +   struct imx_i2c_dma *dma = i2c_imx-dma;
  +   struct dma_chan *dma_chan;
  +
  +   dma_chan = dma-chan_tx;
  +   dma-chan_tx = NULL;
  +   dma-buf_tx = 0;
  +   dma-len_tx = 0;
  +   dma_release_channel(dma_chan);
  +
  +   dma_chan = dma-chan_rx;
  +   dma-chan_tx = NULL;
  +   dma-buf_rx = 0;
  +   dma-len_rx = 0;
  +   dma_release_channel(dma_chan);
 
 You must make _DEAD_ _SURE_ this function is not ever called while the
 DMA is still active. In your case, I have a feeling that's not handled.


Thanks for your attention.
This few days I look up the code for the realization of dma_release_channel(). 
I found that it will disable the dma request first. So it's may safe. 
And drivers hadn't check whether dma is still active before 
dma_release_channel() as a usually usage.
Because it will be disabled automatic.

The only problem is that, it will be forced to cancel the transfer which was 
not yet completed.
Looking forward to hearing from you.

Best regards,
Yuan Yao
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�j:+v���zZ+��+zf���h���~i���z��w���?��)ߢf��^jǫy�m��@A�a���
0��h���i

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-03-03 Thread Marek Vasut
On Monday, March 03, 2014 at 11:23:33 AM, Yao Yuan wrote:
 Hi, Marek
 
 Marek Vasut wrote:
  On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
  
  [...]
  
   +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
   + struct imx_i2c_dma *dma = i2c_imx-dma;
   + struct dma_chan *dma_chan;
   +
   + dma_chan = dma-chan_tx;
   + dma-chan_tx = NULL;
   + dma-buf_tx = 0;
   + dma-len_tx = 0;
   + dma_release_channel(dma_chan);
   +
   + dma_chan = dma-chan_rx;
   + dma-chan_tx = NULL;
   + dma-buf_rx = 0;
   + dma-len_rx = 0;
   + dma_release_channel(dma_chan);
  
  You must make _DEAD_ _SURE_ this function is not ever called while the
  DMA is still active. In your case, I have a feeling that's not handled.
 
 Thanks for your attention.
 This few days I look up the code for the realization of
 dma_release_channel(). I found that it will disable the dma request first.
 So it's may safe. And drivers hadn't check whether dma is still active
 before dma_release_channel() as a usually usage. Because it will be
 disabled automatic.
 
 The only problem is that, it will be forced to cancel the transfer which
 was not yet completed. Looking forward to hearing from you.

OK

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 11:59:25 AM, Lothar Waßmann wrote:
> Hi,
> 
> Marek Vasut wrote:
> > On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
> > 
> > [...]
> > 
> > > Yes, here have two dma channels, one for RX and the other one for TX.
> > > When we request the channel we should determine it for TX or RX.
> > 
> > Sorry, I don't quite understand this. If you have two DMA channels, can
> > you not use them both to do full-duplex SPI transfer ?
> 
> SPI != I2C

You got me, sorry.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 12:36:01 PM, Yao Yuan wrote:
> Hi Marek,
> 
> > On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
> > 
> > [...]
> > 
> > > > > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata
> > > > > = {
> > > > > 
> > > > >   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > > > >   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > > > >   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > > > > 
> > > > > + .has_dma_support= true,
> > > > 
> > > > So why exactly don't we have a DT prop for determining whether the
> > > > controller has DMA support ?
> > > > 
> > > > What about the other controllers, do they not support DMA for some
> > > > specific reason? Please elaborate on that, thank you !
> > > 
> > > Sorry for my fault. I will modify it.
> > 
> > I would prefer if you could explain why other controllers do have DMA
> > disabled even if the hardware does support the DMA operation.
> 
> Well, Because of the I2C in I.MX hardware don't support the DMA operation.
> But here I also think has_dma_support isn't necessary.

OK, got it now. Thanks!

> > > > Also, can the DMA not do full-duplex operation ? What I see here is
> > > > just
> > > > half- duplex operations , one for RX and the other one for TX .
> > > 
> > > Yes, here have two dma channels, one for RX and the other one for TX.
> > > When we request the channel we should determine it for TX or RX.
> > 
> > Sorry, I don't quite understand this. If you have two DMA channels, can
> > you not use them both to do full-duplex SPI transfer ?
> 
> Sorry, There are also hard for me. I don't understand what is full-duplex
> for dma?

Sorry, nevermind. I was confused by this and some SPI patches review. Like 
Lothar (thanks!) pointed out, using only half-duplex operation is OK.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Yao Yuan
Hi Marek,
> On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
> 
> [...]
> 
> > > > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata
> > > > = {
> > > >
> > > > .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > > > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > > > .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > > >
> > > > +   .has_dma_support= true,
> > >
> > > So why exactly don't we have a DT prop for determining whether the
> > > controller has DMA support ?
> > >
> > > What about the other controllers, do they not support DMA for some
> > > specific reason? Please elaborate on that, thank you !
> >
> > Sorry for my fault. I will modify it.
> 
> I would prefer if you could explain why other controllers do have DMA
> disabled even if the hardware does support the DMA operation.
> 

Well, Because of the I2C in I.MX hardware don't support the DMA operation. 
But here I also think has_dma_support isn't necessary.

> > > Also, can the DMA not do full-duplex operation ? What I see here is
> > > just
> > > half- duplex operations , one for RX and the other one for TX .
> >
> > Yes, here have two dma channels, one for RX and the other one for TX.
> > When we request the channel we should determine it for TX or RX.
> 
> Sorry, I don't quite understand this. If you have two DMA channels, can
> you not use them both to do full-duplex SPI transfer ?
> 

Sorry, There are also hard for me. I don't understand what is full-duplex for 
dma? 
A DMA engine can only read or write at the same time. And a dma channel request 
for only DMA_MEM_TO_DEV or DMA_DEV_TO_MEM almost.
Also i2c is a half-duplex bus.
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a���
0��h���i

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Lothar Waßmann
Hi,

Marek Vasut wrote:
> On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
> 
> [...]
> > Yes, here have two dma channels, one for RX and the other one for TX.
> > When we request the channel we should determine it for TX or RX.
> 
> Sorry, I don't quite understand this. If you have two DMA channels, can you 
> not 
> use them both to do full-duplex SPI transfer ?
> 
SPI != I2C


Lothar Waßmann
-- 
___

Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | i...@karo-electronics.de
___
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 03:23:52 AM, Shawn Guo wrote:
> On Fri, Feb 28, 2014 at 10:13:02AM +0800, Shawn Guo wrote:
> > On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
> > > > @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata
> > > > imx1_i2c_hwdata  = {
> > > > 
> > > > .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > > > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > > > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > > > 
> > > > +   .has_dma_support= false,
> > > > 
> > > >  };
> > > > 
> > > > @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata
> > > > imx21_i2c_hwdata  = { .ndivs= 
ARRAY_SIZE(imx_i2c_clk_div),
> > > > 
> > > > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > > > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > > > 
> > > > +   .has_dma_support= false,
> > > > 
> > > >  };
> > > > 
> > > > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > > > 
> > > > .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > > > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > > > .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > > > 
> > > > +   .has_dma_support= true,
> > > 
> > > So why exactly don't we have a DT prop for determining whether the
> > > controller has DMA support ?
> > 
> > Using DMA or PIO is a decision that should be made by driver on its own,
> > not device tree.
> 
> Sorry.  I misunderstood it.  Yes, we can look at the DT property 'dmas'
> to know if the controller has DMA capability.

You're right. Whether or not does the hardware support DMA transfers is a 
property of the hardware, that's why it should be in DT.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:

[...]

> > > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > > 
> > >   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > >   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > >   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > > 
> > > + .has_dma_support= true,
> > 
> > So why exactly don't we have a DT prop for determining whether the
> > controller has DMA support ?
> > 
> > What about the other controllers, do they not support DMA for some
> > specific reason? Please elaborate on that, thank you !
> 
> Sorry for my fault. I will modify it.

I would prefer if you could explain why other controllers do have DMA disabled 
even if the hardware does support the DMA operation.
 
> > [...]
> > 
> > > +static void i2c_imx_dma_tx_callback(void *arg)
> > 
> > [...]
> > 
> > > +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct
> > > +i2c_msg
> > > *msgs) +{
> > 
> > [...]
> > 
> > > +static void i2c_imx_dma_rx_callback(void *arg)
> > 
> > [...]
> > 
> > > +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct
> > > +i2c_msg
> > > *msgs) +{
> > 
> > [...]
> > 
> > Looks like there's quite a bit of code duplication in the four functions
> > above, can you not unify them ?
> 
> Yes, There's looks like quite a bit of code duplication in the four
> functions above. I also hate quite a bit of code duplication.
> But there are many differences in fact.
> If unify them we should add many conditional statements and auxiliary
> variable. I think it's superfluous and will damage the readability.
> So, I am very confused. And if you think unify them will be better I will
> modify it. Thanks for your suggestion and looking forward to hearing from
> you.

I'd say try it, the RX and TX callback look almost the same. So does the 
i2c_imx_dma_rx() and i2c_imx_dma_tx() .

> > Also, can the DMA not do full-duplex operation ? What I see here is just
> > half- duplex operations , one for RX and the other one for TX .
> 
> Yes, here have two dma channels, one for RX and the other one for TX.
> When we request the channel we should determine it for TX or RX.

Sorry, I don't quite understand this. If you have two DMA channels, can you not 
use them both to do full-duplex SPI transfer ?

> > > +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
> > > + struct imx_i2c_dma *dma = i2c_imx->dma;
> > > + struct dma_chan *dma_chan;
> > > +
> > > + dma_chan = dma->chan_tx;
> > > + dma->chan_tx = NULL;
> > > + dma->buf_tx = 0;
> > > + dma->len_tx = 0;
> > > + dma_release_channel(dma_chan);
> > > +
> > > + dma_chan = dma->chan_rx;
> > > + dma->chan_tx = NULL;
> > > + dma->buf_rx = 0;
> > > + dma->len_rx = 0;
> > > + dma_release_channel(dma_chan);
> > 
> > You must make _DEAD_ _SURE_ this function is not ever called while the
> > DMA is still active. In your case, I have a feeling that's not handled.
> 
> I think this function will not called while the DMA is still
> active because of the Linux synchronization mechanism - completion.
> I used it in the dma function.

This doesn't check whether the completion is actually finished anywhere. I 
don't 
quite understand how this is safe .

[...]

> > > +static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
> > > + struct i2c_msg *msgs)
> > > +{
> > 
> > Looks like almost an duplication as well...
> 
> Considering the symmetric with them i2c_imx_dma_write.
> i2c_imx_dma_write and i2c_imx_pio_write have many differences. So I
> separate them. But i2c_imx_dma_read and i2c_imx_pio_read is the same at
> first part. I may should unify them. But it's will not symmetric with them
> i2c_imx_dma_write if unified them. So I don't know which will be better?
> Looking forward to hearing from you.

The dma_read() looks almost like dma_write(), so I'd also try merging them 
together.

> > Besides, full-duplex DMA operation is missing, please explain why.
> > 
> > THanks!
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:

[...]

   @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
   
 .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
 .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
 .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
   
   + .has_dma_support= true,
  
  So why exactly don't we have a DT prop for determining whether the
  controller has DMA support ?
  
  What about the other controllers, do they not support DMA for some
  specific reason? Please elaborate on that, thank you !
 
 Sorry for my fault. I will modify it.

I would prefer if you could explain why other controllers do have DMA disabled 
even if the hardware does support the DMA operation.
 
  [...]
  
   +static void i2c_imx_dma_tx_callback(void *arg)
  
  [...]
  
   +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct
   +i2c_msg
   *msgs) +{
  
  [...]
  
   +static void i2c_imx_dma_rx_callback(void *arg)
  
  [...]
  
   +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct
   +i2c_msg
   *msgs) +{
  
  [...]
  
  Looks like there's quite a bit of code duplication in the four functions
  above, can you not unify them ?
 
 Yes, There's looks like quite a bit of code duplication in the four
 functions above. I also hate quite a bit of code duplication.
 But there are many differences in fact.
 If unify them we should add many conditional statements and auxiliary
 variable. I think it's superfluous and will damage the readability.
 So, I am very confused. And if you think unify them will be better I will
 modify it. Thanks for your suggestion and looking forward to hearing from
 you.

I'd say try it, the RX and TX callback look almost the same. So does the 
i2c_imx_dma_rx() and i2c_imx_dma_tx() .

  Also, can the DMA not do full-duplex operation ? What I see here is just
  half- duplex operations , one for RX and the other one for TX .
 
 Yes, here have two dma channels, one for RX and the other one for TX.
 When we request the channel we should determine it for TX or RX.

Sorry, I don't quite understand this. If you have two DMA channels, can you not 
use them both to do full-duplex SPI transfer ?

   +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
   + struct imx_i2c_dma *dma = i2c_imx-dma;
   + struct dma_chan *dma_chan;
   +
   + dma_chan = dma-chan_tx;
   + dma-chan_tx = NULL;
   + dma-buf_tx = 0;
   + dma-len_tx = 0;
   + dma_release_channel(dma_chan);
   +
   + dma_chan = dma-chan_rx;
   + dma-chan_tx = NULL;
   + dma-buf_rx = 0;
   + dma-len_rx = 0;
   + dma_release_channel(dma_chan);
  
  You must make _DEAD_ _SURE_ this function is not ever called while the
  DMA is still active. In your case, I have a feeling that's not handled.
 
 I think this function will not called while the DMA is still
 active because of the Linux synchronization mechanism - completion.
 I used it in the dma function.

This doesn't check whether the completion is actually finished anywhere. I 
don't 
quite understand how this is safe .

[...]

   +static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
   + struct i2c_msg *msgs)
   +{
  
  Looks like almost an duplication as well...
 
 Considering the symmetric with them i2c_imx_dma_write.
 i2c_imx_dma_write and i2c_imx_pio_write have many differences. So I
 separate them. But i2c_imx_dma_read and i2c_imx_pio_read is the same at
 first part. I may should unify them. But it's will not symmetric with them
 i2c_imx_dma_write if unified them. So I don't know which will be better?
 Looking forward to hearing from you.

The dma_read() looks almost like dma_write(), so I'd also try merging them 
together.

  Besides, full-duplex DMA operation is missing, please explain why.
  
  THanks!
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 03:23:52 AM, Shawn Guo wrote:
 On Fri, Feb 28, 2014 at 10:13:02AM +0800, Shawn Guo wrote:
  On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
@@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata
imx1_i2c_hwdata  = {

.ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
.i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
.i2cr_ien_opcode= I2CR_IEN_OPCODE_1,

+   .has_dma_support= false,

 };

@@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata
imx21_i2c_hwdata  = { .ndivs= 
ARRAY_SIZE(imx_i2c_clk_div),

.i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
.i2cr_ien_opcode= I2CR_IEN_OPCODE_1,

+   .has_dma_support= false,

 };

@@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {

.ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
.i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
.i2cr_ien_opcode= I2CR_IEN_OPCODE_0,

+   .has_dma_support= true,
   
   So why exactly don't we have a DT prop for determining whether the
   controller has DMA support ?
  
  Using DMA or PIO is a decision that should be made by driver on its own,
  not device tree.
 
 Sorry.  I misunderstood it.  Yes, we can look at the DT property 'dmas'
 to know if the controller has DMA capability.

You're right. Whether or not does the hardware support DMA transfers is a 
property of the hardware, that's why it should be in DT.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Lothar Waßmann
Hi,

Marek Vasut wrote:
 On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
 
 [...]
  Yes, here have two dma channels, one for RX and the other one for TX.
  When we request the channel we should determine it for TX or RX.
 
 Sorry, I don't quite understand this. If you have two DMA channels, can you 
 not 
 use them both to do full-duplex SPI transfer ?
 
SPI != I2C


Lothar Waßmann
-- 
___

Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | i...@karo-electronics.de
___
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Yao Yuan
Hi Marek,
 On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
 
 [...]
 
@@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata
= {
   
.ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
.i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
.i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
   
+   .has_dma_support= true,
  
   So why exactly don't we have a DT prop for determining whether the
   controller has DMA support ?
  
   What about the other controllers, do they not support DMA for some
   specific reason? Please elaborate on that, thank you !
 
  Sorry for my fault. I will modify it.
 
 I would prefer if you could explain why other controllers do have DMA
 disabled even if the hardware does support the DMA operation.
 

Well, Because of the I2C in I.MX hardware don't support the DMA operation. 
But here I also think has_dma_support isn't necessary.

   Also, can the DMA not do full-duplex operation ? What I see here is
   just
   half- duplex operations , one for RX and the other one for TX .
 
  Yes, here have two dma channels, one for RX and the other one for TX.
  When we request the channel we should determine it for TX or RX.
 
 Sorry, I don't quite understand this. If you have two DMA channels, can
 you not use them both to do full-duplex SPI transfer ?
 

Sorry, There are also hard for me. I don't understand what is full-duplex for 
dma? 
A DMA engine can only read or write at the same time. And a dma channel request 
for only DMA_MEM_TO_DEV or DMA_DEV_TO_MEM almost.
Also i2c is a half-duplex bus.
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�j:+v���zZ+��+zf���h���~i���z��w���?��)ߢf��^jǫy�m��@A�a���
0��h���i

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 12:36:01 PM, Yao Yuan wrote:
 Hi Marek,
 
  On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
  
  [...]
  
 @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata
 = {
 
   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
 
 + .has_dma_support= true,

So why exactly don't we have a DT prop for determining whether the
controller has DMA support ?

What about the other controllers, do they not support DMA for some
specific reason? Please elaborate on that, thank you !
   
   Sorry for my fault. I will modify it.
  
  I would prefer if you could explain why other controllers do have DMA
  disabled even if the hardware does support the DMA operation.
 
 Well, Because of the I2C in I.MX hardware don't support the DMA operation.
 But here I also think has_dma_support isn't necessary.

OK, got it now. Thanks!

Also, can the DMA not do full-duplex operation ? What I see here is
just
half- duplex operations , one for RX and the other one for TX .
   
   Yes, here have two dma channels, one for RX and the other one for TX.
   When we request the channel we should determine it for TX or RX.
  
  Sorry, I don't quite understand this. If you have two DMA channels, can
  you not use them both to do full-duplex SPI transfer ?
 
 Sorry, There are also hard for me. I don't understand what is full-duplex
 for dma?

Sorry, nevermind. I was confused by this and some SPI patches review. Like 
Lothar (thanks!) pointed out, using only half-duplex operation is OK.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-28 Thread Marek Vasut
On Friday, February 28, 2014 at 11:59:25 AM, Lothar Waßmann wrote:
 Hi,
 
 Marek Vasut wrote:
  On Friday, February 28, 2014 at 06:19:18 AM, Yao Yuan wrote:
  
  [...]
  
   Yes, here have two dma channels, one for RX and the other one for TX.
   When we request the channel we should determine it for TX or RX.
  
  Sorry, I don't quite understand this. If you have two DMA channels, can
  you not use them both to do full-duplex SPI transfer ?
 
 SPI != I2C

You got me, sorry.

Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Yao Yuan
Hi Marek,

Thank you very much for your suggestion.

> -Original Message-
> From: Marek Vasut [mailto:ma...@denx.de]
> Sent: Friday, February 28, 2014 4:40 AM
> To: linux-arm-ker...@lists.infradead.org
> Cc: Yuan Yao-B46683; w...@the-dreams.de; mark.rutl...@arm.com;
> shawn@linaro.org; linux-kernel@vger.kernel.org; linux-
> i...@vger.kernel.org
> Subject: Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver
> 
> On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
> 
> [...]
> 
> > */ @@ -63,6 +68,9 @@
> >  /* Default value */
> >  #define IMX_I2C_BIT_RATE   10  /* 100kHz */
> >
> > +/* enable DMA if transfer size is bigger than this threshold */
> > +#define IMX_I2C_DMA_THRESHOLD  16
> 
> So what's the unit here , potatoes or beers or what ? I suppose it's
> bytes , but please make it explicit in the comment ...
> 

Yes it's bytes. I will make it explicit in the comment.

> [...]
> 
> >  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = { @@ -193,6
> > +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> > .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> >
> >  };
> >
> > @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata
> =
> > { .ndivs= ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> >
> >  };
> >
> > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > +   .has_dma_support= true,
> 
> So why exactly don't we have a DT prop for determining whether the
> controller has DMA support ?
> 
> What about the other controllers, do they not support DMA for some
> specific reason? Please elaborate on that, thank you !

Sorry for my fault. I will modify it.

> [...]
> 
> > +static void i2c_imx_dma_tx_callback(void *arg)
> [...]
> > +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct
> > +i2c_msg
> > *msgs) +{
> [...]
> > +static void i2c_imx_dma_rx_callback(void *arg)
> [...]
> > +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct
> > +i2c_msg
> > *msgs) +{
> [...]
> 
> Looks like there's quite a bit of code duplication in the four functions
> above, can you not unify them ?
> 

Yes, There's looks like quite a bit of code duplication in the four functions 
above.
I also hate quite a bit of code duplication.
But there are many differences in fact.
If unify them we should add many conditional statements and auxiliary variable.
I think it's superfluous and will damage the readability.
So, I am very confused. And if you think unify them will be better I will 
modify it. 
Thanks for your suggestion and looking forward to hearing from you.


> Also, can the DMA not do full-duplex operation ? What I see here is just
> half- duplex operations , one for RX and the other one for TX .
> 

Yes, here have two dma channels, one for RX and the other one for TX.
When we request the channel we should determine it for TX or RX.

> > +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
> > +   struct imx_i2c_dma *dma = i2c_imx->dma;
> > +   struct dma_chan *dma_chan;
> > +
> > +   dma_chan = dma->chan_tx;
> > +   dma->chan_tx = NULL;
> > +   dma->buf_tx = 0;
> > +   dma->len_tx = 0;
> > +   dma_release_channel(dma_chan);
> > +
> > +   dma_chan = dma->chan_rx;
> > +   dma->chan_tx = NULL;
> > +   dma->buf_rx = 0;
> > +   dma->len_rx = 0;
> > +   dma_release_channel(dma_chan);
> 
> You must make _DEAD_ _SURE_ this function is not ever called while the
> DMA is still active. In your case, I have a feeling that's not handled.
>

I think this function will not called while the DMA is still 
active because of the Linux synchronization mechanism - completion. 
I used it in the dma function.

> > +}
> >  /** Functions for IMX I2C adapter driver
> > ***
> > **
> > 
> > */
> >
> > @@ -425,7 +600,8 @@ static irqreturn_t i2c_imx_isr(int irq, void
> *dev_id)
> > return IRQ_NONE;
> > 

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Fri, Feb 28, 2014 at 10:13:02AM +0800, Shawn Guo wrote:
> On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
> > > @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = 
> > > {
> > >   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > >   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > >   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > > + .has_dma_support= false,
> > > 
> > >  };
> > > 
> > > @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
> > > { .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > >   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > >   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > > + .has_dma_support= false,
> > > 
> > >  };
> > > 
> > > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > >   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > >   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > >   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > > + .has_dma_support= true,
> > 
> > So why exactly don't we have a DT prop for determining whether the 
> > controller 
> > has DMA support ?
> 
> Using DMA or PIO is a decision that should be made by driver on its own,
> not device tree.

Sorry.  I misunderstood it.  Yes, we can look at the DT property 'dmas'
to know if the controller has DMA capability.

Shawn

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
> > @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> > .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> > 
> >  };
> > 
> > @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
> > { .ndivs= ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> > 
> >  };
> > 
> > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > +   .has_dma_support= true,
> 
> So why exactly don't we have a DT prop for determining whether the controller 
> has DMA support ?

Using DMA or PIO is a decision that should be made by driver on its own,
not device tree.

Shawn

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Marek Vasut
On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:

[...]

> */ @@ -63,6 +68,9 @@
>  /* Default value */
>  #define IMX_I2C_BIT_RATE 10  /* 100kHz */
> 
> +/* enable DMA if transfer size is bigger than this threshold */
> +#define IMX_I2C_DMA_THRESHOLD16

So what's the unit here , potatoes or beers or what ? I suppose it's bytes , 
but 
please make it explicit in the comment ...

[...]

>  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
>   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> + .has_dma_support= false,
> 
>  };
> 
> @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
> { .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> + .has_dma_support= false,
> 
>  };
> 
> @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
>   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> + .has_dma_support= true,

So why exactly don't we have a DT prop for determining whether the controller 
has DMA support ?

What about the other controllers, do they not support DMA for some specific 
reason? Please elaborate on that, thank you !
[...]

> +static void i2c_imx_dma_tx_callback(void *arg)
[...]
> +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct i2c_msg
> *msgs) +{
[...]
> +static void i2c_imx_dma_rx_callback(void *arg)
[...]
> +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct i2c_msg
> *msgs) +{
[...]

Looks like there's quite a bit of code duplication in the four functions above, 
can you not unify them ?

Also, can the DMA not do full-duplex operation ? What I see here is just half-
duplex operations , one for RX and the other one for TX .

> +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
> +{
> + struct imx_i2c_dma *dma = i2c_imx->dma;
> + struct dma_chan *dma_chan;
> +
> + dma_chan = dma->chan_tx;
> + dma->chan_tx = NULL;
> + dma->buf_tx = 0;
> + dma->len_tx = 0;
> + dma_release_channel(dma_chan);
> +
> + dma_chan = dma->chan_rx;
> + dma->chan_tx = NULL;
> + dma->buf_rx = 0;
> + dma->len_rx = 0;
> + dma_release_channel(dma_chan);

You must make _DEAD_ _SURE_ this function is not ever called while the DMA is 
still active. In your case, I have a feeling that's not handled.

> +}
>  /** Functions for IMX I2C adapter driver
> ***
> **
> */
> 
> @@ -425,7 +600,8 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
>   return IRQ_NONE;
>  }
> 
> -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg
> *msgs) +static int i2c_imx_pio_write(struct imx_i2c_struct *i2c_imx,
> + struct i2c_msg *msgs)
>  {
>   int i, result;
> 
> @@ -458,7 +634,56 @@ static int i2c_imx_write(struct imx_i2c_struct
> *i2c_imx, struct i2c_msg *msgs) return 0;
>  }
> 
> -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg
> *msgs) +static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
> + struct i2c_msg *msgs)
> +{
> + int result, timeout=1000;
> + unsigned int temp = 0;
> +
> + reinit_completion(_imx->dma->cmd_complete);
> + result = i2c_imx_dma_tx(i2c_imx, msgs);
> + if(result)
> + return result;
> +
> + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
> + temp |= I2CR_DMAEN;
> + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
> +
> + /* write slave address */
> + imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
> + result = wait_for_completion_interruptible_timeout(
> + _imx->dma->cmd_complete,
> + msecs_to_jiffies(1000));

Pull the magic constant of 1000 out and #define it as some I2C_IMX_DMA_TIMEOUT 
please .

> + if (result == 0)
> + return  -ETIMEDOUT;
> +
> + /* waiting for Transfer complete. */
> + while(timeout--) {
> + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
> + if (temp & 0x80)
> + break;
> + udelay(10);
> + }
> +
> + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
> + temp &= ~I2CR_DMAEN;
> + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
> +
> + /* write the last byte */
> + imx_i2c_write_reg(msgs->buf[msgs->len-1], i2c_imx, IMX_I2C_I2DR);
> + result = 

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 08:55:45PM +0800, Shawn Guo wrote:
> On Thu, Feb 27, 2014 at 02:05:14PM +0800, Yuan Yao wrote:
> > Add dma support for i2c. This function depend on DMA driver.
> > You can turn on it by write both the dmas and dma-name properties in dts 
> > node.
> > And you should set ".has_dma_support" as true for dma support in 
> > imx_i2c_hwdata struct.
> > 
> > Signed-off-by: Yuan Yao 
> 
> Just added a few people who might be interested.

Still missed one - Marek.  Sorry.

Shawn

> 
> > ---
> >  drivers/i2c/busses/i2c-imx.c | 358 
> > +--
> >  1 file changed, 344 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> > index db895fb..6ec392b 100644
> > --- a/drivers/i2c/busses/i2c-imx.c
> > +++ b/drivers/i2c/busses/i2c-imx.c
> > @@ -37,22 +37,27 @@
> >  /** Includes 
> > ***
> >  
> > ***/
> >  
> > -#include 
> > -#include 
> > -#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> > +#include 
> >  #include 
> > -#include 
> > -#include 
> > -#include 
> > -#include 
> > +#include 
> > +#include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> > +#include 
> > +#include 
> > +#include 
> >  
> >  /** Defines 
> > 
> >  
> > ***/
> > @@ -63,6 +68,9 @@
> >  /* Default value */
> >  #define IMX_I2C_BIT_RATE   10  /* 100kHz */
> >  
> > +/* enable DMA if transfer size is bigger than this threshold */
> > +#define IMX_I2C_DMA_THRESHOLD  16
> > +
> >  /* IMX I2C registers:
> >   * the I2C register offset is different between SoCs,
> >   * to provid support for all these chips, split the
> > @@ -88,6 +96,7 @@
> >  #define I2SR_IBB   0x20
> >  #define I2SR_IAAS  0x40
> >  #define I2SR_ICF   0x80
> > +#define I2CR_DMAEN 0x02
> >  #define I2CR_RSTA  0x04
> >  #define I2CR_TXAK  0x08
> >  #define I2CR_MTX   0x10
> > @@ -172,6 +181,17 @@ struct imx_i2c_hwdata {
> > unsignedndivs;
> > unsignedi2sr_clr_opcode;
> > unsignedi2cr_ien_opcode;
> > +   boolhas_dma_support;
> > +};
> > +
> > +struct imx_i2c_dma {
> > +   struct dma_chan *chan_tx;
> > +   struct dma_chan *chan_rx;
> > +   dma_addr_t  buf_tx;
> > +   dma_addr_t  buf_rx;
> > +   unsigned intlen_tx;
> > +   unsigned intlen_rx;
> > +   struct completion   cmd_complete;
> >  };
> >  
> >  struct imx_i2c_struct {
> > @@ -184,6 +204,9 @@ struct imx_i2c_struct {
> > int stopped;
> > unsigned intifdr; /* IMX_I2C_IFDR */
> > const struct imx_i2c_hwdata *hwdata;
> > +
> > +   booluse_dma;
> > +   struct imx_i2c_dma  *dma;
> >  };
> >  
> >  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> > @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> > .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> >  
> >  };
> >  
> > @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  = {
> > .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> > +   .has_dma_support= false,
> >  
> >  };
> >  
> > @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
> > .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
> > .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
> > .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> > +   .has_dma_support= true,
> >  
> >  };
> >  
> > @@ -254,6 +280,155 @@ static inline unsigned char imx_i2c_read_reg(struct 
> > imx_i2c_struct *i2c_imx,
> > return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
> >  }
> >  
> > +/** Functions for DMA support 
> > 
> > +**/
> > +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, u32 
> > phy_addr)
> > +{
> > +   struct imx_i2c_dma *dma = i2c_imx->dma;
> > +   struct dma_slave_config dma_sconfig;
> > +   int ret;
> > +
> > +   dma->chan_tx = dma_request_slave_channel(_imx->adapter.dev, "tx");
> > +   if (!dma->chan_tx) {
> > +   dev_err(_imx->adapter.dev,
> > +   "Dma tx channel request failed!\n");
> > +   return -ENODEV;

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 02:05:14PM +0800, Yuan Yao wrote:
> Add dma support for i2c. This function depend on DMA driver.
> You can turn on it by write both the dmas and dma-name properties in dts node.
> And you should set ".has_dma_support" as true for dma support in 
> imx_i2c_hwdata struct.
> 
> Signed-off-by: Yuan Yao 

Just added a few people who might be interested.

Shawn

> ---
>  drivers/i2c/busses/i2c-imx.c | 358 
> +--
>  1 file changed, 344 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index db895fb..6ec392b 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -37,22 +37,27 @@
>  /** Includes 
> ***
>  
> ***/
>  
> -#include 
> -#include 
> -#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
> +#include 
>  #include 
> -#include 
> -#include 
> -#include 
> -#include 
> +#include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
> +#include 
> +#include 
> +#include 
>  
>  /** Defines 
> 
>  
> ***/
> @@ -63,6 +68,9 @@
>  /* Default value */
>  #define IMX_I2C_BIT_RATE 10  /* 100kHz */
>  
> +/* enable DMA if transfer size is bigger than this threshold */
> +#define IMX_I2C_DMA_THRESHOLD16
> +
>  /* IMX I2C registers:
>   * the I2C register offset is different between SoCs,
>   * to provid support for all these chips, split the
> @@ -88,6 +96,7 @@
>  #define I2SR_IBB 0x20
>  #define I2SR_IAAS0x40
>  #define I2SR_ICF 0x80
> +#define I2CR_DMAEN   0x02
>  #define I2CR_RSTA0x04
>  #define I2CR_TXAK0x08
>  #define I2CR_MTX 0x10
> @@ -172,6 +181,17 @@ struct imx_i2c_hwdata {
>   unsignedndivs;
>   unsignedi2sr_clr_opcode;
>   unsignedi2cr_ien_opcode;
> + boolhas_dma_support;
> +};
> +
> +struct imx_i2c_dma {
> + struct dma_chan *chan_tx;
> + struct dma_chan *chan_rx;
> + dma_addr_t  buf_tx;
> + dma_addr_t  buf_rx;
> + unsigned intlen_tx;
> + unsigned intlen_rx;
> + struct completion   cmd_complete;
>  };
>  
>  struct imx_i2c_struct {
> @@ -184,6 +204,9 @@ struct imx_i2c_struct {
>   int stopped;
>   unsigned intifdr; /* IMX_I2C_IFDR */
>   const struct imx_i2c_hwdata *hwdata;
> +
> + booluse_dma;
> + struct imx_i2c_dma  *dma;
>  };
>  
>  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
> @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
>   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> + .has_dma_support= false,
>  
>  };
>  
> @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  = {
>   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
> + .has_dma_support= false,
>  
>  };
>  
> @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
>   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
>   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
>   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
> + .has_dma_support= true,
>  
>  };
>  
> @@ -254,6 +280,155 @@ static inline unsigned char imx_i2c_read_reg(struct 
> imx_i2c_struct *i2c_imx,
>   return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));
>  }
>  
> +/** Functions for DMA support 
> 
> +**/
> +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, u32 phy_addr)
> +{
> + struct imx_i2c_dma *dma = i2c_imx->dma;
> + struct dma_slave_config dma_sconfig;
> + int ret;
> +
> + dma->chan_tx = dma_request_slave_channel(_imx->adapter.dev, "tx");
> + if (!dma->chan_tx) {
> + dev_err(_imx->adapter.dev,
> + "Dma tx channel request failed!\n");
> + return -ENODEV;
> + }
> +
> + dma_sconfig.dst_addr = (dma_addr_t)phy_addr +
> + (IMX_I2C_I2DR << i2c_imx->hwdata->regshift);
> + dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + dma_sconfig.dst_maxburst = 1;
> + dma_sconfig.direction = DMA_MEM_TO_DEV;
> + ret = 

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 02:05:14PM +0800, Yuan Yao wrote:
 Add dma support for i2c. This function depend on DMA driver.
 You can turn on it by write both the dmas and dma-name properties in dts node.
 And you should set .has_dma_support as true for dma support in 
 imx_i2c_hwdata struct.
 
 Signed-off-by: Yuan Yao yao.y...@freescale.com

Just added a few people who might be interested.

Shawn

 ---
  drivers/i2c/busses/i2c-imx.c | 358 
 +--
  1 file changed, 344 insertions(+), 14 deletions(-)
 
 diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
 index db895fb..6ec392b 100644
 --- a/drivers/i2c/busses/i2c-imx.c
 +++ b/drivers/i2c/busses/i2c-imx.c
 @@ -37,22 +37,27 @@
  /** Includes 
 ***
  
 ***/
  
 -#include linux/init.h
 -#include linux/kernel.h
 -#include linux/module.h
 +#include linux/clk.h
 +#include linux/completion.h
 +#include linux/delay.h
 +#include linux/dma-mapping.h
 +#include linux/dmaengine.h
 +#include linux/dmapool.h
  #include linux/errno.h
  #include linux/err.h
  #include linux/interrupt.h
 -#include linux/delay.h
  #include linux/i2c.h
 +#include linux/init.h
  #include linux/io.h
 -#include linux/sched.h
 -#include linux/platform_device.h
 -#include linux/clk.h
 -#include linux/slab.h
 +#include linux/kernel.h
 +#include linux/module.h
  #include linux/of.h
  #include linux/of_device.h
 +#include linux/of_dma.h
  #include linux/platform_data/i2c-imx.h
 +#include linux/platform_device.h
 +#include linux/sched.h
 +#include linux/slab.h
  
  /** Defines 
 
  
 ***/
 @@ -63,6 +68,9 @@
  /* Default value */
  #define IMX_I2C_BIT_RATE 10  /* 100kHz */
  
 +/* enable DMA if transfer size is bigger than this threshold */
 +#define IMX_I2C_DMA_THRESHOLD16
 +
  /* IMX I2C registers:
   * the I2C register offset is different between SoCs,
   * to provid support for all these chips, split the
 @@ -88,6 +96,7 @@
  #define I2SR_IBB 0x20
  #define I2SR_IAAS0x40
  #define I2SR_ICF 0x80
 +#define I2CR_DMAEN   0x02
  #define I2CR_RSTA0x04
  #define I2CR_TXAK0x08
  #define I2CR_MTX 0x10
 @@ -172,6 +181,17 @@ struct imx_i2c_hwdata {
   unsignedndivs;
   unsignedi2sr_clr_opcode;
   unsignedi2cr_ien_opcode;
 + boolhas_dma_support;
 +};
 +
 +struct imx_i2c_dma {
 + struct dma_chan *chan_tx;
 + struct dma_chan *chan_rx;
 + dma_addr_t  buf_tx;
 + dma_addr_t  buf_rx;
 + unsigned intlen_tx;
 + unsigned intlen_rx;
 + struct completion   cmd_complete;
  };
  
  struct imx_i2c_struct {
 @@ -184,6 +204,9 @@ struct imx_i2c_struct {
   int stopped;
   unsigned intifdr; /* IMX_I2C_IFDR */
   const struct imx_i2c_hwdata *hwdata;
 +
 + booluse_dma;
 + struct imx_i2c_dma  *dma;
  };
  
  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
 @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
 + .has_dma_support= false,
  
  };
  
 @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  = {
   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
 + .has_dma_support= false,
  
  };
  
 @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
 + .has_dma_support= true,
  
  };
  
 @@ -254,6 +280,155 @@ static inline unsigned char imx_i2c_read_reg(struct 
 imx_i2c_struct *i2c_imx,
   return readb(i2c_imx-base + (reg  i2c_imx-hwdata-regshift));
  }
  
 +/** Functions for DMA support 
 
 +**/
 +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, u32 phy_addr)
 +{
 + struct imx_i2c_dma *dma = i2c_imx-dma;
 + struct dma_slave_config dma_sconfig;
 + int ret;
 +
 + dma-chan_tx = dma_request_slave_channel(i2c_imx-adapter.dev, tx);
 + if (!dma-chan_tx) {
 + dev_err(i2c_imx-adapter.dev,
 + Dma tx channel request failed!\n);
 + return -ENODEV;
 + }
 +
 +  

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 08:55:45PM +0800, Shawn Guo wrote:
 On Thu, Feb 27, 2014 at 02:05:14PM +0800, Yuan Yao wrote:
  Add dma support for i2c. This function depend on DMA driver.
  You can turn on it by write both the dmas and dma-name properties in dts 
  node.
  And you should set .has_dma_support as true for dma support in 
  imx_i2c_hwdata struct.
  
  Signed-off-by: Yuan Yao yao.y...@freescale.com
 
 Just added a few people who might be interested.

Still missed one - Marek.  Sorry.

Shawn

 
  ---
   drivers/i2c/busses/i2c-imx.c | 358 
  +--
   1 file changed, 344 insertions(+), 14 deletions(-)
  
  diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
  index db895fb..6ec392b 100644
  --- a/drivers/i2c/busses/i2c-imx.c
  +++ b/drivers/i2c/busses/i2c-imx.c
  @@ -37,22 +37,27 @@
   /** Includes 
  ***
   
  ***/
   
  -#include linux/init.h
  -#include linux/kernel.h
  -#include linux/module.h
  +#include linux/clk.h
  +#include linux/completion.h
  +#include linux/delay.h
  +#include linux/dma-mapping.h
  +#include linux/dmaengine.h
  +#include linux/dmapool.h
   #include linux/errno.h
   #include linux/err.h
   #include linux/interrupt.h
  -#include linux/delay.h
   #include linux/i2c.h
  +#include linux/init.h
   #include linux/io.h
  -#include linux/sched.h
  -#include linux/platform_device.h
  -#include linux/clk.h
  -#include linux/slab.h
  +#include linux/kernel.h
  +#include linux/module.h
   #include linux/of.h
   #include linux/of_device.h
  +#include linux/of_dma.h
   #include linux/platform_data/i2c-imx.h
  +#include linux/platform_device.h
  +#include linux/sched.h
  +#include linux/slab.h
   
   /** Defines 
  
   
  ***/
  @@ -63,6 +68,9 @@
   /* Default value */
   #define IMX_I2C_BIT_RATE   10  /* 100kHz */
   
  +/* enable DMA if transfer size is bigger than this threshold */
  +#define IMX_I2C_DMA_THRESHOLD  16
  +
   /* IMX I2C registers:
* the I2C register offset is different between SoCs,
* to provid support for all these chips, split the
  @@ -88,6 +96,7 @@
   #define I2SR_IBB   0x20
   #define I2SR_IAAS  0x40
   #define I2SR_ICF   0x80
  +#define I2CR_DMAEN 0x02
   #define I2CR_RSTA  0x04
   #define I2CR_TXAK  0x08
   #define I2CR_MTX   0x10
  @@ -172,6 +181,17 @@ struct imx_i2c_hwdata {
  unsignedndivs;
  unsignedi2sr_clr_opcode;
  unsignedi2cr_ien_opcode;
  +   boolhas_dma_support;
  +};
  +
  +struct imx_i2c_dma {
  +   struct dma_chan *chan_tx;
  +   struct dma_chan *chan_rx;
  +   dma_addr_t  buf_tx;
  +   dma_addr_t  buf_rx;
  +   unsigned intlen_tx;
  +   unsigned intlen_rx;
  +   struct completion   cmd_complete;
   };
   
   struct imx_i2c_struct {
  @@ -184,6 +204,9 @@ struct imx_i2c_struct {
  int stopped;
  unsigned intifdr; /* IMX_I2C_IFDR */
  const struct imx_i2c_hwdata *hwdata;
  +
  +   booluse_dma;
  +   struct imx_i2c_dma  *dma;
   };
   
   static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
  @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
  .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
   
   };
   
  @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  = {
  .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
   
   };
   
  @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
  .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
  +   .has_dma_support= true,
   
   };
   
  @@ -254,6 +280,155 @@ static inline unsigned char imx_i2c_read_reg(struct 
  imx_i2c_struct *i2c_imx,
  return readb(i2c_imx-base + (reg  i2c_imx-hwdata-regshift));
   }
   
  +/** Functions for DMA support 
  
  +**/
  +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, u32 
  phy_addr)
  +{
  +   struct imx_i2c_dma *dma = i2c_imx-dma;
  +   struct dma_slave_config dma_sconfig;
  +   int ret;
  +
  +   dma-chan_tx = dma_request_slave_channel(i2c_imx-adapter.dev, tx);
  +   if 

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Marek Vasut
On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:

[...]

 */ @@ -63,6 +68,9 @@
  /* Default value */
  #define IMX_I2C_BIT_RATE 10  /* 100kHz */
 
 +/* enable DMA if transfer size is bigger than this threshold */
 +#define IMX_I2C_DMA_THRESHOLD16

So what's the unit here , potatoes or beers or what ? I suppose it's bytes , 
but 
please make it explicit in the comment ...

[...]

  static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
 @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
   .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
 + .has_dma_support= false,
 
  };
 
 @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
 { .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
 + .has_dma_support= false,
 
  };
 
 @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
   .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
   .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
   .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
 + .has_dma_support= true,

So why exactly don't we have a DT prop for determining whether the controller 
has DMA support ?

What about the other controllers, do they not support DMA for some specific 
reason? Please elaborate on that, thank you !
[...]

 +static void i2c_imx_dma_tx_callback(void *arg)
[...]
 +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct i2c_msg
 *msgs) +{
[...]
 +static void i2c_imx_dma_rx_callback(void *arg)
[...]
 +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct i2c_msg
 *msgs) +{
[...]

Looks like there's quite a bit of code duplication in the four functions above, 
can you not unify them ?

Also, can the DMA not do full-duplex operation ? What I see here is just half-
duplex operations , one for RX and the other one for TX .

 +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
 +{
 + struct imx_i2c_dma *dma = i2c_imx-dma;
 + struct dma_chan *dma_chan;
 +
 + dma_chan = dma-chan_tx;
 + dma-chan_tx = NULL;
 + dma-buf_tx = 0;
 + dma-len_tx = 0;
 + dma_release_channel(dma_chan);
 +
 + dma_chan = dma-chan_rx;
 + dma-chan_tx = NULL;
 + dma-buf_rx = 0;
 + dma-len_rx = 0;
 + dma_release_channel(dma_chan);

You must make _DEAD_ _SURE_ this function is not ever called while the DMA is 
still active. In your case, I have a feeling that's not handled.

 +}
  /** Functions for IMX I2C adapter driver
 ***
 **
 */
 
 @@ -425,7 +600,8 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
   return IRQ_NONE;
  }
 
 -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg
 *msgs) +static int i2c_imx_pio_write(struct imx_i2c_struct *i2c_imx,
 + struct i2c_msg *msgs)
  {
   int i, result;
 
 @@ -458,7 +634,56 @@ static int i2c_imx_write(struct imx_i2c_struct
 *i2c_imx, struct i2c_msg *msgs) return 0;
  }
 
 -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg
 *msgs) +static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
 + struct i2c_msg *msgs)
 +{
 + int result, timeout=1000;
 + unsigned int temp = 0;
 +
 + reinit_completion(i2c_imx-dma-cmd_complete);
 + result = i2c_imx_dma_tx(i2c_imx, msgs);
 + if(result)
 + return result;
 +
 + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
 + temp |= I2CR_DMAEN;
 + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
 +
 + /* write slave address */
 + imx_i2c_write_reg(msgs-addr  1, i2c_imx, IMX_I2C_I2DR);
 + result = wait_for_completion_interruptible_timeout(
 + i2c_imx-dma-cmd_complete,
 + msecs_to_jiffies(1000));

Pull the magic constant of 1000 out and #define it as some I2C_IMX_DMA_TIMEOUT 
please .

 + if (result == 0)
 + return  -ETIMEDOUT;
 +
 + /* waiting for Transfer complete. */
 + while(timeout--) {
 + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
 + if (temp  0x80)
 + break;
 + udelay(10);
 + }
 +
 + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
 + temp = ~I2CR_DMAEN;
 + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
 +
 + /* write the last byte */
 + imx_i2c_write_reg(msgs-buf[msgs-len-1], i2c_imx, IMX_I2C_I2DR);
 + result = i2c_imx_trx_complete(i2c_imx);
 + if (result)
 + return result;
 +
 + result = i2c_imx_acked(i2c_imx);
 + if 

Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
  @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
  .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
  
   };
  
  @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
  { .ndivs= ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
  
   };
  
  @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
  .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
  +   .has_dma_support= true,
 
 So why exactly don't we have a DT prop for determining whether the controller 
 has DMA support ?

Using DMA or PIO is a decision that should be made by driver on its own,
not device tree.

Shawn

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Shawn Guo
On Fri, Feb 28, 2014 at 10:13:02AM +0800, Shawn Guo wrote:
 On Thu, Feb 27, 2014 at 09:39:35PM +0100, Marek Vasut wrote:
   @@ -193,6 +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = 
   {
 .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
 .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
 .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
   + .has_dma_support= false,
   
};
   
   @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata  =
   { .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
 .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
 .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
   + .has_dma_support= false,
   
};
   
   @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
 .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
 .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
 .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
   + .has_dma_support= true,
  
  So why exactly don't we have a DT prop for determining whether the 
  controller 
  has DMA support ?
 
 Using DMA or PIO is a decision that should be made by driver on its own,
 not device tree.

Sorry.  I misunderstood it.  Yes, we can look at the DT property 'dmas'
to know if the controller has DMA capability.

Shawn

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/3] i2c: add DMA support for freescale i2c driver

2014-02-27 Thread Yao Yuan
Hi Marek,

Thank you very much for your suggestion.

 -Original Message-
 From: Marek Vasut [mailto:ma...@denx.de]
 Sent: Friday, February 28, 2014 4:40 AM
 To: linux-arm-ker...@lists.infradead.org
 Cc: Yuan Yao-B46683; w...@the-dreams.de; mark.rutl...@arm.com;
 shawn@linaro.org; linux-kernel@vger.kernel.org; linux-
 i...@vger.kernel.org
 Subject: Re: [PATCH 1/3] i2c: add DMA support for freescale i2c driver
 
 On Thursday, February 27, 2014 at 07:05:14 AM, Yuan Yao wrote:
 
 [...]
 
  */ @@ -63,6 +68,9 @@
   /* Default value */
   #define IMX_I2C_BIT_RATE   10  /* 100kHz */
 
  +/* enable DMA if transfer size is bigger than this threshold */
  +#define IMX_I2C_DMA_THRESHOLD  16
 
 So what's the unit here , potatoes or beers or what ? I suppose it's
 bytes , but please make it explicit in the comment ...
 

Yes it's bytes. I will make it explicit in the comment.

 [...]
 
   static const struct imx_i2c_hwdata imx1_i2c_hwdata  = { @@ -193,6
  +216,7 @@ static const struct imx_i2c_hwdata imx1_i2c_hwdata  = {
  .ndivs  = ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
 
   };
 
  @@ -203,6 +227,7 @@ static const struct imx_i2c_hwdata imx21_i2c_hwdata
 =
  { .ndivs= ARRAY_SIZE(imx_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W0C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_1,
  +   .has_dma_support= false,
 
   };
 
  @@ -213,6 +238,7 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {
  .ndivs  = ARRAY_SIZE(vf610_i2c_clk_div),
  .i2sr_clr_opcode= I2SR_CLR_OPCODE_W1C,
  .i2cr_ien_opcode= I2CR_IEN_OPCODE_0,
  +   .has_dma_support= true,
 
 So why exactly don't we have a DT prop for determining whether the
 controller has DMA support ?
 
 What about the other controllers, do they not support DMA for some
 specific reason? Please elaborate on that, thank you !

Sorry for my fault. I will modify it.

 [...]
 
  +static void i2c_imx_dma_tx_callback(void *arg)
 [...]
  +static int i2c_imx_dma_tx(struct imx_i2c_struct *i2c_imx, struct
  +i2c_msg
  *msgs) +{
 [...]
  +static void i2c_imx_dma_rx_callback(void *arg)
 [...]
  +static int i2c_imx_dma_rx(struct imx_i2c_struct *i2c_imx, struct
  +i2c_msg
  *msgs) +{
 [...]
 
 Looks like there's quite a bit of code duplication in the four functions
 above, can you not unify them ?
 

Yes, There's looks like quite a bit of code duplication in the four functions 
above.
I also hate quite a bit of code duplication.
But there are many differences in fact.
If unify them we should add many conditional statements and auxiliary variable.
I think it's superfluous and will damage the readability.
So, I am very confused. And if you think unify them will be better I will 
modify it. 
Thanks for your suggestion and looking forward to hearing from you.


 Also, can the DMA not do full-duplex operation ? What I see here is just
 half- duplex operations , one for RX and the other one for TX .
 

Yes, here have two dma channels, one for RX and the other one for TX.
When we request the channel we should determine it for TX or RX.

  +static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) {
  +   struct imx_i2c_dma *dma = i2c_imx-dma;
  +   struct dma_chan *dma_chan;
  +
  +   dma_chan = dma-chan_tx;
  +   dma-chan_tx = NULL;
  +   dma-buf_tx = 0;
  +   dma-len_tx = 0;
  +   dma_release_channel(dma_chan);
  +
  +   dma_chan = dma-chan_rx;
  +   dma-chan_tx = NULL;
  +   dma-buf_rx = 0;
  +   dma-len_rx = 0;
  +   dma_release_channel(dma_chan);
 
 You must make _DEAD_ _SURE_ this function is not ever called while the
 DMA is still active. In your case, I have a feeling that's not handled.


I think this function will not called while the DMA is still 
active because of the Linux synchronization mechanism - completion. 
I used it in the dma function.

  +}
   /** Functions for IMX I2C adapter driver
  ***
  **
  
  */
 
  @@ -425,7 +600,8 @@ static irqreturn_t i2c_imx_isr(int irq, void
 *dev_id)
  return IRQ_NONE;
   }
 
  -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct
  i2c_msg
  *msgs) +static int i2c_imx_pio_write(struct imx_i2c_struct *i2c_imx,
  +   struct i2c_msg *msgs)
   {
  int i, result;
 
  @@ -458,7 +634,56 @@ static int i2c_imx_write(struct imx_i2c_struct
  *i2c_imx, struct i2c_msg *msgs) return 0;  }
 
  -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct
  i2c_msg
  *msgs) +static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
  +   struct i2c_msg *msgs)
  +{
  +   int result, timeout=1000;
  +   unsigned int temp = 0;
  +
  +   reinit_completion(i2c_imx-dma