On Fri, Sep 03, 2010 at 10:36:54AM +0900, Jassi Brar wrote:
> We can't do without setting channel and bus width to
> same size.
> Inorder to do that, define a new callback to be used
> to do read/write of appropriate widths.
> 
> Signed-off-by: Jassi Brar <[email protected]>
> ---
>  drivers/spi/spi_s3c64xx.c |   78 +++++++++++++++++++++++++++++++++++++-------
>  1 files changed, 65 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index 39816bb..8aa9f85 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -174,12 +174,59 @@ struct s3c64xx_spi_driver_data {
>       unsigned                        state;
>       unsigned                        cur_mode, cur_bpw;
>       unsigned                        cur_speed;
> +     void (*do_xfer)(void *ptr, void *fifo, unsigned sz, bool rd);

Looking at the code; it appears that it would be better to have
separate read and write transfer hooks.

>  };
>  
>  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
>       .name = "samsung-spi-dma",
>  };
>  
> +static void s3c64xx_spi_xfer8(void *ptr, void __iomem *fifo,
> +             unsigned len, bool read)
> +{
> +     u8 *buf = (u8 *)ptr;

ptr is already a void* which makes this an unnecessary cast.

> +     int i = 0;
> +
> +     if (read)
> +             while (i < len)
> +                     buf[i++] = readb(fifo);

perhaps ioread8_rep() instead of open-coding?  If so, then
ioread*_rep() and iowrite*_rep() can be used in all these cases.

In fact, the 8, 16 and 32 versions have the same signature and so
could possibly be used directly without these hooks.

g.

> +     else
> +             while (i < len)
> +                     writeb(buf[i++], fifo);
> +}
> +
> +static void s3c64xx_spi_xfer16(void *ptr, void __iomem *fifo,
> +             unsigned len, bool read)
> +{
> +     u16 *buf = (u16 *)ptr;
> +     int i = 0;
> +
> +     len /= 2;
> +
> +     if (read)
> +             while (i < len)
> +                     buf[i++] = readw(fifo);
> +     else
> +             while (i < len)
> +                     writew(buf[i++], fifo);
> +}
> +
> +static void s3c64xx_spi_xfer32(void *ptr, void __iomem *fifo,
> +             unsigned len, bool read)
> +{
> +     u32 *buf = (u32 *)ptr;
> +     int i = 0;
> +
> +     len /= 4;
> +
> +     if (read)
> +             while (i < len)
> +                     buf[i++] = readl(fifo);
> +     else
> +             while (i < len)
> +                     writel(buf[i++], fifo);
> +}
> +
>  static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
>  {
>       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
> @@ -260,10 +307,8 @@ static void enable_datapath(struct 
> s3c64xx_spi_driver_data *sdd,
>                                               xfer->tx_dma, xfer->len);
>                       s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
>               } else {
> -                     unsigned char *buf = (unsigned char *) xfer->tx_buf;
> -                     int i = 0;
> -                     while (i < xfer->len)
> -                             writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
> +                     sdd->do_xfer((void *)xfer->tx_buf,
> +                             regs + S3C64XX_SPI_TX_DATA, xfer->len, false);
>               }
>       }
>  
> @@ -360,20 +405,14 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data 
> *sdd,
>                               return -EIO;
>               }
>       } else {
> -             unsigned char *buf;
> -             int i;
> -
>               /* If it was only Tx */
>               if (xfer->rx_buf == NULL) {
>                       sdd->state &= ~TXBUSY;
>                       return 0;
>               }
>  
> -             i = 0;
> -             buf = xfer->rx_buf;
> -             while (i < xfer->len)
> -                     buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
> -
> +             sdd->do_xfer(xfer->rx_buf,
> +                     regs + S3C64XX_SPI_RX_DATA, xfer->len, true);
>               sdd->state &= ~RXBUSY;
>       }
>  
> @@ -423,15 +462,20 @@ static void s3c64xx_spi_config(struct 
> s3c64xx_spi_driver_data *sdd)
>       switch (sdd->cur_bpw) {
>       case 32:
>               val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
> +             val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
> +             sdd->do_xfer = s3c64xx_spi_xfer32;
>               break;
>       case 16:
>               val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
> +             val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
> +             sdd->do_xfer = s3c64xx_spi_xfer16;
>               break;
>       default:
>               val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
> +             val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
> +             sdd->do_xfer = s3c64xx_spi_xfer8;
>               break;
>       }
> -     val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
>  
>       writel(val, regs + S3C64XX_SPI_MODE_CFG);
>  
> @@ -610,6 +654,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data 
> *sdd,
>               bpw = xfer->bits_per_word ? : spi->bits_per_word;
>               speed = xfer->speed_hz ? : spi->max_speed_hz;
>  
> +             if (bpw != 8 && xfer->len % (bpw / 8)) {
> +                     dev_err(&spi->dev,
> +                             "Xfer length(%u) not a multiple of word 
> size(%u)\n",
> +                             xfer->len, bpw / 8);
> +                     status = -EIO;
> +                     goto out;
> +             }
> +
>               if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
>                       sdd->cur_bpw = bpw;
>                       sdd->cur_speed = speed;
> -- 
> 1.6.2.5
> 

------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
_______________________________________________
spi-devel-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

Reply via email to