diff options
| -rw-r--r-- | drivers/dma/amba-pl08x.c | 98 |
1 files changed, 38 insertions, 60 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 202c9e2d2e9e..c025a4b4bae4 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c | |||
| @@ -185,37 +185,17 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch) | |||
| 185 | /* | 185 | /* |
| 186 | * Set the initial DMA register values i.e. those for the first LLI | 186 | * Set the initial DMA register values i.e. those for the first LLI |
| 187 | * The next LLI pointer and the configuration interrupt bit have | 187 | * The next LLI pointer and the configuration interrupt bit have |
| 188 | * been set when the LLIs were constructed | 188 | * been set when the LLIs were constructed. Poke them into the hardware |
| 189 | * and start the transfer. | ||
| 189 | */ | 190 | */ |
| 190 | static void pl08x_set_cregs(struct pl08x_driver_data *pl08x, | 191 | static void pl08x_start_txd(struct pl08x_dma_chan *plchan, |
| 191 | struct pl08x_phy_chan *ch) | 192 | struct pl08x_txd *txd) |
| 192 | { | 193 | { |
| 193 | /* Wait for channel inactive */ | 194 | struct pl08x_driver_data *pl08x = plchan->host; |
| 194 | while (pl08x_phy_channel_busy(ch)) | ||
| 195 | cpu_relax(); | ||
| 196 | |||
| 197 | dev_vdbg(&pl08x->adev->dev, | ||
| 198 | "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, " | ||
| 199 | "cctl=0x%08x, clli=0x%08x, ccfg=0x%08x\n", | ||
| 200 | ch->id, | ||
| 201 | ch->csrc, | ||
| 202 | ch->cdst, | ||
| 203 | ch->cctl, | ||
| 204 | ch->clli, | ||
| 205 | ch->ccfg); | ||
| 206 | |||
| 207 | writel(ch->csrc, ch->base + PL080_CH_SRC_ADDR); | ||
| 208 | writel(ch->cdst, ch->base + PL080_CH_DST_ADDR); | ||
| 209 | writel(ch->clli, ch->base + PL080_CH_LLI); | ||
| 210 | writel(ch->cctl, ch->base + PL080_CH_CONTROL); | ||
| 211 | writel(ch->ccfg, ch->base + PL080_CH_CONFIG); | ||
| 212 | } | ||
| 213 | |||
| 214 | static inline void pl08x_config_phychan_for_txd(struct pl08x_dma_chan *plchan) | ||
| 215 | { | ||
| 216 | struct pl08x_channel_data *cd = plchan->cd; | ||
| 217 | struct pl08x_phy_chan *phychan = plchan->phychan; | 195 | struct pl08x_phy_chan *phychan = plchan->phychan; |
| 218 | struct pl08x_txd *txd = plchan->at; | 196 | u32 val; |
| 197 | |||
| 198 | plchan->at = txd; | ||
| 219 | 199 | ||
| 220 | /* Copy the basic control register calculated at transfer config */ | 200 | /* Copy the basic control register calculated at transfer config */ |
| 221 | phychan->csrc = txd->csrc; | 201 | phychan->csrc = txd->csrc; |
| @@ -224,7 +204,7 @@ static inline void pl08x_config_phychan_for_txd(struct pl08x_dma_chan *plchan) | |||
| 224 | phychan->cctl = txd->cctl; | 204 | phychan->cctl = txd->cctl; |
| 225 | 205 | ||
| 226 | /* Assign the signal to the proper control registers */ | 206 | /* Assign the signal to the proper control registers */ |
| 227 | phychan->ccfg = cd->ccfg; | 207 | phychan->ccfg = plchan->cd->ccfg; |
| 228 | phychan->ccfg &= ~PL080_CONFIG_SRC_SEL_MASK; | 208 | phychan->ccfg &= ~PL080_CONFIG_SRC_SEL_MASK; |
| 229 | phychan->ccfg &= ~PL080_CONFIG_DST_SEL_MASK; | 209 | phychan->ccfg &= ~PL080_CONFIG_DST_SEL_MASK; |
| 230 | /* If it wasn't set from AMBA, ignore it */ | 210 | /* If it wasn't set from AMBA, ignore it */ |
| @@ -240,32 +220,38 @@ static inline void pl08x_config_phychan_for_txd(struct pl08x_dma_chan *plchan) | |||
| 240 | phychan->ccfg |= PL080_CONFIG_ERR_IRQ_MASK; | 220 | phychan->ccfg |= PL080_CONFIG_ERR_IRQ_MASK; |
| 241 | /* Always enable terminal interrupts */ | 221 | /* Always enable terminal interrupts */ |
| 242 | phychan->ccfg |= PL080_CONFIG_TC_IRQ_MASK; | 222 | phychan->ccfg |= PL080_CONFIG_TC_IRQ_MASK; |
| 243 | } | ||
| 244 | 223 | ||
| 245 | /* | 224 | /* Wait for channel inactive */ |
| 246 | * Enable the DMA channel | 225 | while (pl08x_phy_channel_busy(phychan)) |
| 247 | * Assumes all other configuration bits have been set | 226 | cpu_relax(); |
| 248 | * as desired before this code is called | ||
| 249 | */ | ||
| 250 | static void pl08x_enable_phy_chan(struct pl08x_driver_data *pl08x, | ||
| 251 | struct pl08x_phy_chan *ch) | ||
| 252 | { | ||
| 253 | u32 val; | ||
| 254 | 227 | ||
| 255 | /* | 228 | dev_vdbg(&pl08x->adev->dev, |
| 256 | * Do not access config register until channel shows as disabled | 229 | "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, " |
| 257 | */ | 230 | "cctl=0x%08x, clli=0x%08x, ccfg=0x%08x\n", |
| 258 | while (readl(pl08x->base + PL080_EN_CHAN) & (1 << ch->id)) | 231 | phychan->id, |
| 232 | phychan->csrc, | ||
| 233 | phychan->cdst, | ||
| 234 | phychan->cctl, | ||
| 235 | phychan->clli, | ||
| 236 | phychan->ccfg); | ||
| 237 | |||
| 238 | writel(phychan->csrc, phychan->base + PL080_CH_SRC_ADDR); | ||
| 239 | writel(phychan->cdst, phychan->base + PL080_CH_DST_ADDR); | ||
| 240 | writel(phychan->clli, phychan->base + PL080_CH_LLI); | ||
| 241 | writel(phychan->cctl, phychan->base + PL080_CH_CONTROL); | ||
| 242 | writel(phychan->ccfg, phychan->base + PL080_CH_CONFIG); | ||
| 243 | |||
| 244 | /* Enable the DMA channel */ | ||
| 245 | /* Do not access config register until channel shows as disabled */ | ||
| 246 | while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id)) | ||
| 259 | cpu_relax(); | 247 | cpu_relax(); |
| 260 | 248 | ||
| 261 | /* | 249 | /* Do not access config register until channel shows as inactive */ |
| 262 | * Do not access config register until channel shows as inactive | 250 | val = readl(phychan->base + PL080_CH_CONFIG); |
| 263 | */ | ||
| 264 | val = readl(ch->base + PL080_CH_CONFIG); | ||
| 265 | while ((val & PL080_CONFIG_ACTIVE) || (val & PL080_CONFIG_ENABLE)) | 251 | while ((val & PL080_CONFIG_ACTIVE) || (val & PL080_CONFIG_ENABLE)) |
| 266 | val = readl(ch->base + PL080_CH_CONFIG); | 252 | val = readl(phychan->base + PL080_CH_CONFIG); |
| 267 | 253 | ||
| 268 | writel(val | PL080_CONFIG_ENABLE, ch->base + PL080_CH_CONFIG); | 254 | writel(val | PL080_CONFIG_ENABLE, phychan->base + PL080_CH_CONFIG); |
| 269 | } | 255 | } |
| 270 | 256 | ||
| 271 | /* | 257 | /* |
| @@ -1278,7 +1264,6 @@ static void dma_set_runtime_config(struct dma_chan *chan, | |||
| 1278 | static void pl08x_issue_pending(struct dma_chan *chan) | 1264 | static void pl08x_issue_pending(struct dma_chan *chan) |
| 1279 | { | 1265 | { |
| 1280 | struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); | 1266 | struct pl08x_dma_chan *plchan = to_pl08x_chan(chan); |
| 1281 | struct pl08x_driver_data *pl08x = plchan->host; | ||
| 1282 | unsigned long flags; | 1267 | unsigned long flags; |
| 1283 | 1268 | ||
| 1284 | spin_lock_irqsave(&plchan->lock, flags); | 1269 | spin_lock_irqsave(&plchan->lock, flags); |
| @@ -1296,13 +1281,9 @@ static void pl08x_issue_pending(struct dma_chan *chan) | |||
| 1296 | struct pl08x_txd, | 1281 | struct pl08x_txd, |
| 1297 | node); | 1282 | node); |
| 1298 | list_del(&next->node); | 1283 | list_del(&next->node); |
| 1299 | plchan->at = next; | ||
| 1300 | plchan->state = PL08X_CHAN_RUNNING; | 1284 | plchan->state = PL08X_CHAN_RUNNING; |
| 1301 | 1285 | ||
| 1302 | /* Configure the physical channel for the active txd */ | 1286 | pl08x_start_txd(plchan, next); |
| 1303 | pl08x_config_phychan_for_txd(plchan); | ||
| 1304 | pl08x_set_cregs(pl08x, plchan->phychan); | ||
| 1305 | pl08x_enable_phy_chan(pl08x, plchan->phychan); | ||
| 1306 | } | 1287 | } |
| 1307 | 1288 | ||
| 1308 | spin_unlock_irqrestore(&plchan->lock, flags); | 1289 | spin_unlock_irqrestore(&plchan->lock, flags); |
| @@ -1630,11 +1611,8 @@ static void pl08x_tasklet(unsigned long data) | |||
| 1630 | struct pl08x_txd, | 1611 | struct pl08x_txd, |
| 1631 | node); | 1612 | node); |
| 1632 | list_del(&next->node); | 1613 | list_del(&next->node); |
| 1633 | plchan->at = next; | 1614 | |
| 1634 | /* Configure the physical channel for the next txd */ | 1615 | pl08x_start_txd(plchan, next); |
| 1635 | pl08x_config_phychan_for_txd(plchan); | ||
| 1636 | pl08x_set_cregs(pl08x, plchan->phychan); | ||
| 1637 | pl08x_enable_phy_chan(pl08x, plchan->phychan); | ||
| 1638 | } else { | 1616 | } else { |
| 1639 | struct pl08x_dma_chan *waiting = NULL; | 1617 | struct pl08x_dma_chan *waiting = NULL; |
| 1640 | 1618 | ||
