2014-04-16 21:45:51

by Andy Gross

[permalink] [raw]
Subject: [PATCH 0/2] dmaengine: qcom_bam_dma: Add support for v1.3.0

This set of patches adds support for the v1.3.0 version of the QCOM BAM
dmaengine driver. The older version of the BAM is present in the MSM8x64,
APQ8064, and IPQ8064 processors.

Due to register address space changes between versions, all of the register
accesses have to be calculated using different offsets and multipliers that are
specific to that version of the IP block.

Andy Gross (2):
dmaengine: qcom_bam_dma: Add v1.3.0 driver support
dmaengine: qcom_bam_dma: Add binding for v1.3.0

.../devicetree/bindings/dma/qcom_bam_dma.txt | 4 +-
drivers/dma/qcom_bam_dma.c | 177 +++++++++++++-------
2 files changed, 117 insertions(+), 64 deletions(-)

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


2014-04-16 21:45:52

by Andy Gross

[permalink] [raw]
Subject: [PATCH 2/2] dmaengine: qcom_bam_dma: Add binding for v1.3.0

Add the device tree binding support for the v1.3.0 version of the QCOM BAM DMA
driver.

Signed-off-by: Andy Gross <[email protected]>
---
.../devicetree/bindings/dma/qcom_bam_dma.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
index d75a9d7..802572f 100644
--- a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
+++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
@@ -1,7 +1,9 @@
QCOM BAM DMA controller

Required properties:
-- compatible: must contain "qcom,bam-v1.4.0" for MSM8974
+- compatible: must contain one of the following:
+ "qcom,bam-v1.4.0" for MSM8974
+ "qcom,bam-v1.3.0" for APQ8064, IPQ8064, MSM8x64
- reg: Address range for DMA registers
- interrupts: Should contain the one interrupt shared by all channels
- #dma-cells: must be <1>, the cell in the dmas property of the client device
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

2014-04-16 21:46:55

by Andy Gross

[permalink] [raw]
Subject: [PATCH 1/2] dmaengine: qcom_bam_dma: Add v1.3.0 driver support

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 <[email protected]>
---
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));

/* don't allow cpu to reorder BAM register accesses done after this */
wmb();
@@ -342,17 +388,18 @@ static void bam_chan_init_hw(struct bam_chan *bchan,
* because we allocated 1 more descriptor (8 bytes) than we can use
*/
writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)),
- bdev->regs + BAM_P_DESC_FIFO_ADDR(bchan->id));
- writel_relaxed(BAM_DESC_FIFO_SIZE, bdev->regs +
- BAM_P_FIFO_SIZES(bchan->id));
+ evnt_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR));
+ writel_relaxed(BAM_DESC_FIFO_SIZE, evnt_addr(bdev, bchan->id,
+ BAM_P_FIFO_SIZES));

/* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */
- writel_relaxed(P_DEFAULT_IRQS_EN, bdev->regs + BAM_P_IRQ_EN(bchan->id));
+ writel_relaxed(P_DEFAULT_IRQS_EN,
+ pipe_addr(bdev, bchan->id, BAM_P_IRQ_EN));

/* unmask the specific pipe and EE combo */
- val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ val = readl_relaxed(ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));
val |= BIT(bchan->id);
- writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ writel_relaxed(val, ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));

/* don't allow cpu to reorder the channel enable done below */
wmb();
@@ -362,7 +409,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan,
if (dir == DMA_DEV_TO_MEM)
val |= P_DIRECTION;

- writel_relaxed(val, bdev->regs + BAM_P_CTRL(bchan->id));
+ writel_relaxed(val, pipe_addr(bdev, bchan->id, BAM_P_CTRL));

bchan->initialized = 1;

@@ -427,12 +474,12 @@ static void bam_free_chan(struct dma_chan *chan)
bchan->fifo_virt = NULL;

/* mask irq for pipe/channel */
- val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ val = readl_relaxed(ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));
val &= ~BIT(bchan->id);
- writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ writel_relaxed(val, ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));

/* disable irq */
- writel_relaxed(0, bdev->regs + BAM_P_IRQ_EN(bchan->id));
+ writel_relaxed(0, pipe_addr(bdev, bchan->id, BAM_P_IRQ_EN));
}

/**
@@ -570,14 +617,14 @@ static int bam_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
switch (cmd) {
case DMA_PAUSE:
spin_lock_irqsave(&bchan->vc.lock, flag);
- writel_relaxed(1, bdev->regs + BAM_P_HALT(bchan->id));
+ writel_relaxed(1, pipe_addr(bdev, bchan->id, BAM_P_HALT));
bchan->paused = 1;
spin_unlock_irqrestore(&bchan->vc.lock, flag);
break;

case DMA_RESUME:
spin_lock_irqsave(&bchan->vc.lock, flag);
- writel_relaxed(0, bdev->regs + BAM_P_HALT(bchan->id));
+ writel_relaxed(0, pipe_addr(bdev, bchan->id, BAM_P_HALT));
bchan->paused = 0;
spin_unlock_irqrestore(&bchan->vc.lock, flag);
break;
@@ -613,7 +660,7 @@ static u32 process_channel_irqs(struct bam_device *bdev)
unsigned long flags;
struct bam_async_desc *async_desc;

- srcs = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_EE(bdev->ee));
+ srcs = readl_relaxed(ee_addr(bdev, BAM_IRQ_SRCS_EE));

/* return early if no pipe/channel interrupts are present */
if (!(srcs & P_IRQ))
@@ -626,11 +673,9 @@ static u32 process_channel_irqs(struct bam_device *bdev)
continue;

/* clear pipe irq */
- pipe_stts = readl_relaxed(bdev->regs +
- BAM_P_IRQ_STTS(i));
+ pipe_stts = readl_relaxed(pipe_addr(bdev, i, BAM_P_IRQ_STTS));

- writel_relaxed(pipe_stts, bdev->regs +
- BAM_P_IRQ_CLR(i));
+ writel_relaxed(pipe_stts, pipe_addr(bdev, i, BAM_P_IRQ_CLR));

spin_lock_irqsave(&bchan->vc.lock, flags);
async_desc = bchan->curr_txd;
@@ -681,12 +726,12 @@ static irqreturn_t bam_dma_irq(int irq, void *data)
tasklet_schedule(&bdev->task);

if (srcs & BAM_IRQ)
- clr_mask = readl_relaxed(bdev->regs + BAM_IRQ_STTS);
+ clr_mask = readl_relaxed(ctrl_addr(bdev, BAM_IRQ_STTS));

/* don't allow reorder of the various accesses to the BAM registers */
mb();

- writel_relaxed(clr_mask, bdev->regs + BAM_IRQ_CLR);
+ writel_relaxed(clr_mask, ctrl_addr(bdev, BAM_IRQ_CLR));

return IRQ_HANDLED;
}
@@ -750,7 +795,7 @@ static void bam_apply_new_config(struct bam_chan *bchan,
else
maxburst = bchan->slave.dst_maxburst;

- writel_relaxed(maxburst, bdev->regs + BAM_DESC_CNT_TRSHLD);
+ writel_relaxed(maxburst, ctrl_addr(bdev, BAM_DESC_CNT_TRSHLD));

bchan->reconfigure = 0;
}
@@ -814,7 +859,7 @@ static void bam_start_dma(struct bam_chan *bchan)
/* ensure descriptor writes and dma start not reordered */
wmb();
writel_relaxed(bchan->tail * sizeof(struct bam_desc_hw),
- bdev->regs + BAM_P_EVNT_REG(bchan->id));
+ evnt_addr(bdev, bchan->id, BAM_P_EVNT_REG));
}

/**
@@ -902,43 +947,45 @@ static int bam_init(struct bam_device *bdev)
u32 val;

/* read revision and configuration information */
- val = readl_relaxed(bdev->regs + BAM_REVISION) >> NUM_EES_SHIFT;
+ val = readl_relaxed(ctrl_addr(bdev, BAM_REVISION)) >> NUM_EES_SHIFT;
val &= NUM_EES_MASK;

/* check that configured EE is within range */
if (bdev->ee >= val)
return -EINVAL;

- val = readl_relaxed(bdev->regs + BAM_NUM_PIPES);
+ val = readl_relaxed(ctrl_addr(bdev, BAM_NUM_PIPES));
bdev->num_channels = val & BAM_NUM_PIPES_MASK;

/* s/w reset bam */
/* after reset all pipes are disabled and idle */
- val = readl_relaxed(bdev->regs + BAM_CTRL);
+ val = readl_relaxed(ctrl_addr(bdev, BAM_CTRL));
val |= BAM_SW_RST;
- writel_relaxed(val, bdev->regs + BAM_CTRL);
+ writel_relaxed(val, ctrl_addr(bdev, BAM_CTRL));
val &= ~BAM_SW_RST;
- writel_relaxed(val, bdev->regs + BAM_CTRL);
+ writel_relaxed(val, ctrl_addr(bdev, BAM_CTRL));

/* make sure previous stores are visible before enabling BAM */
wmb();

/* enable bam */
val |= BAM_EN;
- writel_relaxed(val, bdev->regs + BAM_CTRL);
+ writel_relaxed(val, ctrl_addr(bdev, BAM_CTRL));

/* set descriptor threshhold, start with 4 bytes */
- writel_relaxed(DEFAULT_CNT_THRSHLD, bdev->regs + BAM_DESC_CNT_TRSHLD);
+ writel_relaxed(DEFAULT_CNT_THRSHLD,
+ ctrl_addr(bdev, BAM_DESC_CNT_TRSHLD));

/* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
- writel_relaxed(BAM_CNFG_BITS_DEFAULT, bdev->regs + BAM_CNFG_BITS);
+ writel_relaxed(BAM_CNFG_BITS_DEFAULT,
+ ctrl_addr(bdev, BAM_CNFG_BITS));

/* enable irqs for errors */
writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
- bdev->regs + BAM_IRQ_EN);
+ ctrl_addr(bdev, BAM_IRQ_EN));

/* unmask global bam interrupt */
- writel_relaxed(BAM_IRQ_MSK, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ writel_relaxed(BAM_IRQ_MSK, ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));

return 0;
}
@@ -980,6 +1027,9 @@ static int bam_dma_probe(struct platform_device *pdev)
return ret;
}

+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,bam-v1.4.0"))
+ bdev->reg_ver = 1;
+
bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
if (IS_ERR(bdev->bamclk))
return PTR_ERR(bdev->bamclk);
@@ -1068,7 +1118,7 @@ static int bam_dma_remove(struct platform_device *pdev)
dma_async_device_unregister(&bdev->common);

/* mask all interrupts for this execution environment */
- writel_relaxed(0, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
+ writel_relaxed(0, ee_addr(bdev, BAM_IRQ_SRCS_MSK_EE));

devm_free_irq(bdev->dev, bdev->irq, bdev);

@@ -1089,6 +1139,7 @@ static int bam_dma_remove(struct platform_device *pdev)
}

static const struct of_device_id bam_of_match[] = {
+ { .compatible = "qcom,bam-v1.3.0", },
{ .compatible = "qcom,bam-v1.4.0", },
{}
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

2014-04-17 23:01:37

by Stanimir Varbanov

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

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 <[email protected]>
> ---
> 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

2014-04-18 19:41:06

by Andy Gross

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

On Fri, Apr 18, 2014 at 02:01:19AM +0300, Stanimir Vabanov wrote:

<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.


That's not a bad idea. I'll try this out and see how it looks.

--
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation