Re: [PATCH 1/2] dmaengine: qcom_bam_dma: Add v1.3.0 driver support

From: Stanimir Vabanov
Date: Thu Apr 17 2014 - 19:01:45 EST


Hi Andy,

Thanks for the patch!

On 04/17/2014 12:45 AM, Andy Gross wrote:
> This patch adds support for the v1.3.0 version of the BAM dma ip block. This
> patch adds register access abstraction to deal with the changes to the register
> map between the two versions. Blocks of registers moved around within the
> address space, and multipliers used for calculating the pipe registers changed
> as well.
>
> Signed-off-by: Andy Gross <agross@xxxxxxxxxxxxxx>
> ---
> drivers/dma/qcom_bam_dma.c | 177 ++++++++++++++++++++++++++++----------------
> 1 file changed, 114 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/dma/qcom_bam_dma.c b/drivers/dma/qcom_bam_dma.c
> index 82c9231..02f7fef 100644
> --- a/drivers/dma/qcom_bam_dma.c
> +++ b/drivers/dma/qcom_bam_dma.c
> @@ -74,35 +74,49 @@ struct bam_async_desc {
> struct bam_desc_hw desc[0];
> };
>
> -#define BAM_CTRL 0x0000
> -#define BAM_REVISION 0x0004
> -#define BAM_SW_REVISION 0x0080
> -#define BAM_NUM_PIPES 0x003C
> -#define BAM_TIMER 0x0040
> -#define BAM_TIMER_CTRL 0x0044
> -#define BAM_DESC_CNT_TRSHLD 0x0008
> -#define BAM_IRQ_SRCS 0x000C
> -#define BAM_IRQ_SRCS_MSK 0x0010
> -#define BAM_IRQ_SRCS_UNMASKED 0x0030
> -#define BAM_IRQ_STTS 0x0014
> -#define BAM_IRQ_CLR 0x0018
> -#define BAM_IRQ_EN 0x001C
> -#define BAM_CNFG_BITS 0x007C
> -#define BAM_IRQ_SRCS_EE(ee) (0x0800 + ((ee) * 0x80))
> -#define BAM_IRQ_SRCS_MSK_EE(ee) (0x0804 + ((ee) * 0x80))
> -#define BAM_P_CTRL(pipe) (0x1000 + ((pipe) * 0x1000))
> -#define BAM_P_RST(pipe) (0x1004 + ((pipe) * 0x1000))
> -#define BAM_P_HALT(pipe) (0x1008 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_STTS(pipe) (0x1010 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_CLR(pipe) (0x1014 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_EN(pipe) (0x1018 + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_DEST_ADDR(pipe) (0x182C + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_REG(pipe) (0x1818 + ((pipe) * 0x1000))
> -#define BAM_P_SW_OFSTS(pipe) (0x1800 + ((pipe) * 0x1000))
> -#define BAM_P_DATA_FIFO_ADDR(pipe) (0x1824 + ((pipe) * 0x1000))
> -#define BAM_P_DESC_FIFO_ADDR(pipe) (0x181C + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_TRSHLD(pipe) (0x1828 + ((pipe) * 0x1000))
> -#define BAM_P_FIFO_SIZES(pipe) (0x1820 + ((pipe) * 0x1000))
> +/* Register base offset and multplier values. Use version of map as index */
> +static unsigned int ctrl_offs[] = { 0xf80, 0x0 };
> +static unsigned int pipe_offs[] = { 0x0, 0x1000 };
> +static unsigned int ee_offs[] = { 0x1800, 0x800 };
> +static unsigned int evnt_offs[] = { 0x1000, 0x1800 };
> +static unsigned int pipe_mult[] = { 0x80, 0x1000 };
> +static unsigned int evnt_mult[] = { 0x40, 0x1000 };
> +
> +/* relative offset from ctrl register base */
> +#define BAM_CTRL 0x00
> +#define BAM_REVISION 0x04
> +#define BAM_DESC_CNT_TRSHLD 0x08
> +#define BAM_IRQ_SRCS 0x0C
> +#define BAM_IRQ_SRCS_MSK 0x10
> +#define BAM_IRQ_STTS 0x14
> +#define BAM_IRQ_CLR 0x18
> +#define BAM_IRQ_EN 0x1C
> +#define BAM_IRQ_SRCS_UNMASKED 0x30
> +#define BAM_NUM_PIPES 0x3c
> +#define BAM_TIMER 0x40
> +#define BAM_TIMER_CTRL 0x44
> +#define BAM_CNFG_BITS 0x7c
> +
> +/* relative offset from irq register base */
> +#define BAM_IRQ_SRCS_EE 0x00
> +#define BAM_IRQ_SRCS_MSK_EE 0x04
> +
> +/* relative offset from pipe register base */
> +#define BAM_P_CTRL 0x00
> +#define BAM_P_RST 0x04
> +#define BAM_P_HALT 0x08
> +#define BAM_P_IRQ_STTS 0x10
> +#define BAM_P_IRQ_CLR 0x14
> +#define BAM_P_IRQ_EN 0x18
> +
> +/* relative offset from event register base */
> +#define BAM_P_SW_OFSTS 0x00
> +#define BAM_P_EVNT_REG 0x18
> +#define BAM_P_DESC_FIFO_ADDR 0x1C
> +#define BAM_P_FIFO_SIZES 0x20
> +#define BAM_P_DATA_FIFO_ADDR 0x24
> +#define BAM_P_EVNT_TRSHLD 0x28
> +#define BAM_P_EVNT_DEST_ADDR 0x2C
>
> /* BAM CTRL */
> #define BAM_SW_RST BIT(0)
> @@ -292,6 +306,8 @@ struct bam_device {
> /* execution environment ID, from DT */
> u32 ee;
>
> + u32 reg_ver;
> +
> struct clk *bamclk;
> int irq;
>
> @@ -299,6 +315,36 @@ struct bam_device {
> struct tasklet_struct task;
> };
>
> +static inline void __iomem *ctrl_addr(struct bam_device *bdev, u32 reg)
> +{
> + return bdev->regs + ctrl_offs[bdev->reg_ver] + reg;
> +}
> +
> +static inline void __iomem *ee_addr(struct bam_device *bdev, u32 reg)
> +{
> + u32 offset = ee_offs[bdev->reg_ver] + reg + (bdev->ee * 0x80);
> +
> + return bdev->regs + offset;
> +}
> +
> +static inline void __iomem *pipe_addr(struct bam_device *bdev, u32 pipe,
> + u32 reg)
> +{
> + u32 offset = pipe_offs[bdev->reg_ver] + reg;
> +
> + offset += pipe_mult[bdev->reg_ver] * pipe;
> + return bdev->regs + offset;
> +}
> +
> +static inline void __iomem *evnt_addr(struct bam_device *bdev, u32 pipe,
> + u32 reg)
> +{
> + u32 offset = evnt_offs[bdev->reg_ver] + reg;
> +
> + offset += evnt_mult[bdev->reg_ver] * pipe;
> + return bdev->regs + offset;
> +}
> +
> /**
> * bam_reset_channel - Reset individual BAM DMA channel
> * @bchan: bam channel
> @@ -312,8 +358,8 @@ static void bam_reset_channel(struct bam_chan *bchan)
> lockdep_assert_held(&bchan->vc.lock);
>
> /* reset channel */
> - writel_relaxed(1, bdev->regs + BAM_P_RST(bchan->id));
> - writel_relaxed(0, bdev->regs + BAM_P_RST(bchan->id));
> + writel_relaxed(1, pipe_addr(bdev, bchan->id, BAM_P_RST));
> + writel_relaxed(0, pipe_addr(bdev, bchan->id, BAM_P_RST));
>

<snip>

>
> static const struct of_device_id bam_of_match[] = {
> + { .compatible = "qcom,bam-v1.3.0", },
> { .compatible = "qcom,bam-v1.4.0", },

you could use the of_device_id::data field to switch between different
versions.

I mean this:

static const struct of_device_id bam_of_match[] = {
{ .compatible = "qcom,bam-v1.3.0", .data = &reg_offs_v1_3 },
{ .compatible = "qcom,bam-v1.4.0", .data = &reg_offs_v1_4 },
}

and during .probe you will get the correct offsets per version. It then
could be assigned to a variable in bdev.

Then the defines could be:

#define BAM_CTRL(bdev) (bdev->reg_offs->ctrl_offs + 0x00)

I'm not sure how many additional code this will be but it looks clearer.

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