summaryrefslogtreecommitdiffstats
path: root/drivers/dma/owl-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/owl-dma.c')
-rw-r--r--drivers/dma/owl-dma.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
index 948d1bead860..331c8d8b10a3 100644
--- a/drivers/dma/owl-dma.c
+++ b/drivers/dma/owl-dma.c
@@ -149,6 +149,11 @@ enum owl_dmadesc_offsets {
OWL_DMADESC_SIZE
};
+enum owl_dma_id {
+ S900_DMA,
+ S700_DMA,
+};
+
/**
* struct owl_dma_lli - Link list for dma transfer
* @hw: hardware link list
@@ -213,6 +218,7 @@ struct owl_dma_vchan {
* @pchans: array of data for the physical channels
* @nr_vchans: the number of physical channels
* @vchans: array of data for the physical channels
+ * @devid: device id based on OWL SoC
*/
struct owl_dma {
struct dma_device dma;
@@ -227,6 +233,7 @@ struct owl_dma {
unsigned int nr_vchans;
struct owl_dma_vchan *vchans;
+ enum owl_dma_id devid;
};
static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
@@ -316,6 +323,10 @@ static inline u32 llc_hw_ctrlb(u32 int_ctl)
{
u32 ctl;
+ /*
+ * Irrespective of the SoC, ctrlb value starts filling from
+ * bit 18.
+ */
ctl = BIT_FIELD(int_ctl, 7, 0, 18);
return ctl;
@@ -372,6 +383,7 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
struct dma_slave_config *sconfig,
bool is_cyclic)
{
+ struct owl_dma *od = to_owl_dma(vchan->vc.chan.device);
u32 mode, ctrlb;
mode = OWL_DMA_MODE_PW(0);
@@ -427,14 +439,26 @@ static inline int owl_dma_cfg_lli(struct owl_dma_vchan *vchan,
lli->hw[OWL_DMADESC_DADDR] = dst;
lli->hw[OWL_DMADESC_SRC_STRIDE] = 0;
lli->hw[OWL_DMADESC_DST_STRIDE] = 0;
- /*
- * Word starts from offset 0xC is shared between frame length
- * (max frame length is 1MB) and frame count, where first 20
- * bits are for frame length and rest of 12 bits are for frame
- * count.
- */
- lli->hw[OWL_DMADESC_FLEN] = len | FCNT_VAL << 20;
- lli->hw[OWL_DMADESC_CTRLB] = ctrlb;
+
+ if (od->devid == S700_DMA) {
+ /* Max frame length is 1MB */
+ lli->hw[OWL_DMADESC_FLEN] = len;
+ /*
+ * On S700, word starts from offset 0x1C is shared between
+ * frame count and ctrlb, where first 12 bits are for frame
+ * count and rest of 20 bits are for ctrlb.
+ */
+ lli->hw[OWL_DMADESC_CTRLB] = FCNT_VAL | ctrlb;
+ } else {
+ /*
+ * On S900, word starts from offset 0xC is shared between
+ * frame length (max frame length is 1MB) and frame count,
+ * where first 20 bits are for frame length and rest of
+ * 12 bits are for frame count.
+ */
+ lli->hw[OWL_DMADESC_FLEN] = len | FCNT_VAL << 20;
+ lli->hw[OWL_DMADESC_CTRLB] = ctrlb;
+ }
return 0;
}
@@ -596,7 +620,7 @@ static irqreturn_t owl_dma_interrupt(int irq, void *dev_id)
global_irq_pending = dma_readl(od, OWL_DMA_IRQ_PD0);
- if (chan_irq_pending && !(global_irq_pending & BIT(i))) {
+ if (chan_irq_pending && !(global_irq_pending & BIT(i))) {
dev_dbg(od->dma.dev,
"global and channel IRQ pending match err\n");
@@ -1054,6 +1078,13 @@ static struct dma_chan *owl_dma_of_xlate(struct of_phandle_args *dma_spec,
return chan;
}
+static const struct of_device_id owl_dma_match[] = {
+ { .compatible = "actions,s900-dma", .data = (void *)S900_DMA,},
+ { .compatible = "actions,s700-dma", .data = (void *)S700_DMA,},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, owl_dma_match);
+
static int owl_dma_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1083,6 +1114,8 @@ static int owl_dma_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "dma-channels %d, dma-requests %d\n",
nr_channels, nr_requests);
+ od->devid = (enum owl_dma_id)of_device_get_match_data(&pdev->dev);
+
od->nr_pchans = nr_channels;
od->nr_vchans = nr_requests;
@@ -1215,12 +1248,6 @@ static int owl_dma_remove(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id owl_dma_match[] = {
- { .compatible = "actions,s900-dma", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, owl_dma_match);
-
static struct platform_driver owl_dma_driver = {
.probe = owl_dma_probe,
.remove = owl_dma_remove,