diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 30eeb7bffad8..384c482058d1 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -840,9 +840,9 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc) irq = &dw->irq[pos]; if (chan->dir == EDMA_DIR_WRITE) - irq->wr_mask |= BIT(chan->id); + bitmap_set(irq->wr_mask, chan->id, 1); else - irq->rd_mask |= BIT(chan->id); + bitmap_set(irq->rd_mask, chan->id, 1); irq->dw = dw; memcpy(&chan->msi, &irq->msi, sizeof(chan->msi)); @@ -983,6 +983,8 @@ int dw_edma_probe(struct dw_edma_chip *chip) struct dw_edma *dw; u32 wr_alloc = 0; u32 rd_alloc = 0; + u16 max_wr_cnt; + u16 max_rd_cnt; int i, err; if (!chip) @@ -998,20 +1000,25 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; - if (dw->chip->mf == EDMA_MF_HDMA_NATIVE) + if (dw->chip->mf == EDMA_MF_HDMA_NATIVE) { dw_hdma_v0_core_register(dw); - else + max_wr_cnt = HDMA_MAX_WR_CH; + max_rd_cnt = HDMA_MAX_RD_CH; + } else { dw_edma_v0_core_register(dw); + max_wr_cnt = EDMA_MAX_WR_CH; + max_rd_cnt = EDMA_MAX_RD_CH; + } raw_spin_lock_init(&dw->lock); dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt, dw_edma_core_ch_count(dw, EDMA_DIR_WRITE)); - dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH); + dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, max_wr_cnt); dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt, dw_edma_core_ch_count(dw, EDMA_DIR_READ)); - dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH); + dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, max_rd_cnt); if (!dw->wr_ch_cnt && !dw->rd_ch_cnt) return -EINVAL; diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 3c958ca05144..e39c11bc91fb 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -84,9 +84,10 @@ struct dw_edma_chan { struct dw_edma_irq { struct msi_msg msi; - u32 wr_mask; - u32 rd_mask; struct dw_edma *dw; + + DECLARE_BITMAP(wr_mask, HDMA_MAX_WR_CH); + DECLARE_BITMAP(rd_mask, HDMA_MAX_RD_CH); }; struct dw_edma { diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c index 791c46e8ae4c..b34e1e45aeb3 100644 --- a/drivers/dma/dw-edma/dw-edma-pcie.c +++ b/drivers/dma/dw-edma/dw-edma-pcie.c @@ -62,11 +62,11 @@ struct dw_edma_pcie_data { /* eDMA registers location */ struct dw_edma_block rg; /* eDMA memory linked list location */ - struct dw_edma_block ll_wr[EDMA_MAX_WR_CH]; - struct dw_edma_block ll_rd[EDMA_MAX_RD_CH]; + struct dw_edma_block ll_wr[HDMA_MAX_WR_CH]; + struct dw_edma_block ll_rd[HDMA_MAX_RD_CH]; /* eDMA memory data location */ - struct dw_edma_block dt_wr[EDMA_MAX_WR_CH]; - struct dw_edma_block dt_rd[EDMA_MAX_RD_CH]; + struct dw_edma_block dt_wr[HDMA_MAX_WR_CH]; + struct dw_edma_block dt_rd[HDMA_MAX_RD_CH]; /* Other */ enum dw_edma_map_format mf; u8 irqs; diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 7b4933c66f9f..7bb3ec461cce 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -239,7 +239,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, irqreturn_t ret = IRQ_NONE; struct dw_edma_chan *chan; unsigned long off; - u32 mask; + unsigned long *mask; if (dir == EDMA_DIR_WRITE) { total = dw->wr_ch_cnt; @@ -252,7 +252,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, } val = dw_edma_v0_core_status_done_int(dw, dir); - val &= mask; + val &= *mask; for_each_set_bit(pos, &val, total) { chan = &dw->chan[pos + off]; @@ -263,7 +263,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, } val = dw_edma_v0_core_status_abort_int(dw, dir); - val &= mask; + val &= *mask; for_each_set_bit(pos, &val, total) { chan = &dw->chan[pos + off]; diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 4bf5a441afbf..87ba3e8c9fa1 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -53,13 +53,24 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch) static void dw_hdma_v0_core_off(struct dw_edma *dw) { int id; + enum dw_edma_dir dir; - for (id = 0; id < HDMA_V0_MAX_NR_CH; id++) { - SET_BOTH_CH_32(dw, id, int_setup, - HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); - SET_BOTH_CH_32(dw, id, int_clear, - HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); - SET_BOTH_CH_32(dw, id, ch_en, 0); + dir = EDMA_DIR_WRITE; + for (id = 0; id < dw->wr_ch_cnt; id++) { + SET_CH_32(dw, dir, id, int_setup, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_CH_32(dw, dir, id, int_clear, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_CH_32(dw, dir, id, ch_en, 0); + } + + dir = EDMA_DIR_READ; + for (id = 0; id < dw->rd_ch_cnt; id++) { + SET_CH_32(dw, dir, id, int_setup, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_CH_32(dw, dir, id, int_clear, + HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK); + SET_CH_32(dw, dir, id, ch_en, 0); } } @@ -118,7 +129,7 @@ dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, unsigned long total, pos, val; irqreturn_t ret = IRQ_NONE; struct dw_edma_chan *chan; - unsigned long off, mask; + unsigned long off, *mask; if (dir == EDMA_DIR_WRITE) { total = dw->wr_ch_cnt; @@ -130,7 +141,7 @@ dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, mask = dw_irq->rd_mask; } - for_each_set_bit(pos, &mask, total) { + for_each_set_bit(pos, mask, total) { chan = &dw->chan[pos + off]; val = dw_hdma_v0_core_status_int(chan); diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h index 7759ba9b4850..48e40efceb2e 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-regs.h +++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h @@ -11,7 +11,7 @@ #include -#define HDMA_V0_MAX_NR_CH 8 +#define HDMA_V0_MAX_NR_CH 64 #define HDMA_V0_CH_EN BIT(0) #define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6) #define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5) diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h index 1fafd5b0e315..da7a5cc93ad4 100644 --- a/include/linux/dma/edma.h +++ b/include/linux/dma/edma.h @@ -14,6 +14,8 @@ #define EDMA_MAX_WR_CH 8 #define EDMA_MAX_RD_CH 8 +#define HDMA_MAX_WR_CH 64 +#define HDMA_MAX_RD_CH 64 struct dw_edma; @@ -89,12 +91,12 @@ struct dw_edma_chip { u16 ll_wr_cnt; u16 ll_rd_cnt; /* link list address */ - struct dw_edma_region ll_region_wr[EDMA_MAX_WR_CH]; - struct dw_edma_region ll_region_rd[EDMA_MAX_RD_CH]; + struct dw_edma_region ll_region_wr[HDMA_MAX_WR_CH]; + struct dw_edma_region ll_region_rd[HDMA_MAX_RD_CH]; /* data region */ - struct dw_edma_region dt_region_wr[EDMA_MAX_WR_CH]; - struct dw_edma_region dt_region_rd[EDMA_MAX_RD_CH]; + struct dw_edma_region dt_region_wr[HDMA_MAX_WR_CH]; + struct dw_edma_region dt_region_rd[HDMA_MAX_RD_CH]; /* interrupt emulation */ int db_irq;