Re: [RFC PATCHv2 2/7] OMAP SSI: Introducing OMAP SSI driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Carlos,

Please see my comments inlined.

On Friday 07 May 2010 17:18:32 Carlos Chinea wrote:
[strip]
> diff --git a/drivers/hsi/controllers/omap_ssi.c
[strip]
> +
> +/**
> + * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context
> + * @mode: Bit transmission mode
> + * @channels: Number of channels
> + * @framesize: Frame size in bits
> + * @timeout: RX frame timeout
> + * @divisot: TX divider

Typo: s/divisot/divisor

> + * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
> + */
> +struct omap_ssm_ctx {
> +       u32     mode;
> +       u32     channels;
> +       u32     frame_size;
> +       union   {
> +                       u32     timeout; /* Rx Only */
> +                       struct  {
> +                                       u32     arb_mode;
> +                                       u32     divisor;
> +                       }; /* Tx only */
> +       };
> +};
> +
> +/**
> + * struct omap_ssi_port - OMAP SSI port data
> + * @dev: device associated to the port (HSI port)
> + * @sst_dma: SSI transmitter physical base address
> + * @ssr_dma: SSI receiver physical base address
> + * @sst_base: SSI transmitter base address
> + * @ssr_base: SSI receiver base address

wk_lock description is missing here

> + * @lock: Spin lock to serialize access to the SSI port
> + * @channels: Current number of channels configured (1,2,4 or 8)
> + * @txqueue: TX message queues
> + * @rxqueue: RX message queues
> + * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
> + * @irq: IRQ number
> + * @wake_irq: IRQ number for incoming wake line (-1 if none)
> + * @pio_tasklet: Bottom half for PIO transfers and events
> + * @wake_tasklet: Bottom half for incoming wake events
> + * @wkin_cken: Keep track of clock references due to the incoming wake
>  line
>  + * @wake_refcount: Reference count for output wake line
 
s/wake_refcount/wk_refcount

> + * @sys_mpu_enable: Context for the interrupt enable register for irq 0
> + * @sst: Context for the synchronous serial transmitter
> + * @ssr: Context for the synchronous serial receiver
> + */
> +struct omap_ssi_port {
> +       struct device           *dev;
> +       dma_addr_t              sst_dma;
> +       dma_addr_t              ssr_dma;
> +       unsigned long           sst_base;
> +       unsigned long           ssr_base;
> +       spinlock_t              wk_lock;
> +       spinlock_t              lock;
> +       unsigned int            channels;
> +       struct list_head        txqueue[SSI_MAX_CHANNELS];
> +       struct list_head        rxqueue[SSI_MAX_CHANNELS];
> +       struct list_head        brkqueue;
> +       unsigned int            irq;
> +       int                     wake_irq;
> +       struct tasklet_struct   pio_tasklet;
> +       struct tasklet_struct   wake_tasklet;
> +       unsigned int            wkin_cken:1; /* Workaround */
> +       int                     wk_refcount;
> +       /* OMAP SSI port context */
> +       u32                     sys_mpu_enable; /* We use only one irq */
> +       struct omap_ssm_ctx     sst;
> +       struct omap_ssm_ctx     ssr;
> +};
> +

[strip]

> +
> +static void ssi_pio_complete(struct hsi_port *port, struct list_head
>  *queue) +{
> +       struct hsi_controller *ssi =
>  to_hsi_controller(port->device.parent); +       struct omap_ssi_controller
>  *omap_ssi = hsi_controller_drvdata(ssi); +       struct omap_ssi_port
>  *omap_port = hsi_port_drvdata(port);
> +       struct hsi_msg *msg;
> +       u32 *buf;
> +       u32 val;
> +
> +       spin_lock(&omap_port->lock);
> +       msg = list_first_entry(queue, struct hsi_msg, link);
> +       if ((!msg->sgt.nents) || (!msg->sgt.sgl->length)) {
> +               msg->actual_len = 0;
> +               msg->status = HSI_STATUS_PENDING;
> +       }
> +       if (msg->status == HSI_STATUS_PROCEDING) {
> +               buf = sg_virt(msg->sgt.sgl) + msg->actual_len;
> +               if (msg->ttype == HSI_MSG_WRITE)
> +                       __raw_writel(*buf, omap_port->sst_base +
> +                                      
>  SSI_SST_BUFFER_CH_REG(msg->channel)); +                else
> +                       *buf = __raw_readl(omap_port->ssr_base +
> +                                      
>  SSI_SSR_BUFFER_CH_REG(msg->channel)); +              
>  dev_dbg(&port->device, "ch %d ttype %d 0x%08x\n", msg->channel, +         
>                                               msg->ttype, *buf); +         
>       msg->actual_len += sizeof(*buf);
> +               if (msg->actual_len >= msg->sgt.sgl->length)
> +                       msg->status = HSI_STATUS_COMPLETED;
> +               /*
> +                * Wait for the last written frame to be really sent before
> +                * we call the complete callback
> +                */
> +               if ((msg->status == HSI_STATUS_PROCEDING) ||
> +                       ((msg->status == HSI_STATUS_COMPLETED) &&
> +                               (msg->ttype == HSI_MSG_WRITE)))
> +                       goto out;
> +
> +       }
> +       if (msg->status == HSI_STATUS_PROCEDING)
> +               goto out;
> +       /* Transfer completed at this point */
> +       val = __raw_readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num,
>  0)); +       if (msg->ttype == HSI_MSG_WRITE) {
> +               val &= ~SSI_DATAACCEPT(msg->channel);
> +               ssi_clk_disable(ssi); /* Release clocks for write transfer
>  */ +       } else {
> +               val &= ~SSI_DATAAVAILABLE(msg->channel);
> +       }
> +       __raw_writel(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num,
>  0)); +       list_del(&msg->link);
> +       spin_unlock(&omap_port->lock);
> +       msg->complete(msg);
> +       spin_lock(&omap_port->lock);
> +       ssi_start_transfer(queue);
> +out:
> +       spin_unlock(&omap_port->lock);
> +}
> +
> +static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
> +{
> +       struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
> +       struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
> +       struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
> +       unsigned int dir;
> +       u32 csr;
> +       u32 val;
> +
> +       spin_lock(&omap_ssi->lock);
> +
> +       val = __raw_readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
> +       val &= ~SSI_GDD_LCH(lch);
> +       __raw_writel(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
> +
> +       if (msg->ttype == HSI_MSG_READ) {
> +               dir = DMA_FROM_DEVICE;
> +               val = SSI_DATAAVAILABLE(msg->channel);
> +               ssi_clk_disable(ssi);
> +       } else {
> +               dir = DMA_TO_DEVICE;
> +               val = SSI_DATAACCEPT(msg->channel);
> +               /* Keep clocks reference for write pio event */
> +       }
> +       dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
> +       csr = __raw_readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
> +       omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
> +       if (csr & SSI_CSR_TOUR) { /* Timeout error */
> +               msg->status = HSI_STATUS_ERROR;
> +               msg->actual_len = 0;
> +               list_del(&msg->link); /* Dequeue msg */
> +               spin_unlock(&omap_ssi->lock);
> +               msg->complete(msg);
> +               return;
> +       }
> +
> +       val |= __raw_readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num,
>  0)); +       __raw_writel(val, omap_ssi->sys +
>  SSI_MPU_ENABLE_REG(port->num, 0)); +
> +       msg->status = HSI_STATUS_COMPLETED;
> +       msg->actual_len = sg_dma_len(msg->sgt.sgl);
> +       spin_unlock(&omap_ssi->lock);
> +}

Don't you need to check the queue related to this transfer at this point, to 
start the potentially next queued transfer on the same channel? (calling 
ssi_start_transfer(), like in ssi_pio_complete()?)

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux