Home | History | Annotate | Download | only in bfin

Lines Matching refs:dma

1 /* Blackfin Direct Memory Access (DMA) Channel model.
32 /* Note: This DMA implementation requires the producer to be the master when
34 have the two DMA devices thrashing each other with one trying to
83 bfin_dma_enabled (struct bfin_dma *dma)
85 return (dma->config & DMAEN);
89 bfin_dma_running (struct bfin_dma *dma)
91 return (dma->irq_status & DMA_RUN);
95 bfin_dma_get_peer (struct hw *me, struct bfin_dma *dma)
97 if (dma->hw_peer)
98 return dma->hw_peer;
99 return dma->hw_peer = bfin_dmac_get_peer (me, dma->peripheral_map);
103 bfin_dma_process_desc (struct hw *me, struct bfin_dma *dma)
105 bu8 ndsize = (dma->config & NDSIZE) >> NDSIZE_SHIFT;
108 HW_TRACE ((me, "dma starting up %#x", dma->config));
110 switch (dma->config & WDSIZE)
113 dma->ele_size = 4;
116 dma->ele_size = 2;
119 dma->ele_size = 1;
124 if (dma->start_addr & (dma->ele_size - 1))
125 dma->irq_status |= DMA_ERR;
127 if (dma->ele_size != (unsigned) abs (dma->x_modify))
128 hw_abort (me, "DMA config (striding) %#x not supported (x_modify: %d)",
129 dma->config, dma->x_modify);
131 switch (dma->config & DMAFLOW)
136 hw_abort (me, "DMA config error: DMAFLOW_{AUTO,STOP} requires NDSIZE_0");
140 hw_abort (me, "DMA config error: DMAFLOW_ARRAY requires NDSIZE 1...7");
141 sim_read (hw_system (me), dma->curr_desc_ptr, flows, ndsize * 2);
145 hw_abort (me, "DMA config error: DMAFLOW_SMALL requires NDSIZE 1...8");
146 sim_read (hw_system (me), dma->next_desc_ptr, flows, ndsize * 2);
150 hw_abort (me, "DMA config error: DMAFLOW_LARGE requires NDSIZE 1...9");
151 sim_read (hw_system (me), dma->next_desc_ptr, flows, ndsize * 2);
154 hw_abort (me, "DMA config error: invalid DMAFLOW %#x", dma->config);
161 &dma->sal,
162 &dma->sah,
163 &dma->config,
164 &dma->x_count,
165 (void *) &dma->x_modify,
166 &dma->y_count,
167 (void *) &dma->y_modify,
170 switch (dma->config & DMAFLOW)
173 dma->ndph = _flows[1];
178 dma->ndpl = _flows[0];
188 dma->curr_desc_ptr = dma->next_desc_ptr;
189 dma->curr_addr = dma->start_addr;
190 dma->curr_x_count = dma->x_count ? : 0xffff;
191 dma->curr_y_count = dma->y_count ? : 0xffff;
195 bfin_dma_finish_x (struct hw *me, struct bfin_dma *dma)
198 /* XXX: Should this toggle Enable in dma->config ? */
200 if (dma->config & DI_EN)
203 if ((dma->config & DMA2D) && dma->curr_y_count > 1)
205 dma->curr_y_count -= 1;
206 dma->curr_x_count = dma->x_count;
209 dma->curr_addr = dma->curr_addr - dma->x_modify + dma->y_modify;
214 switch (dma->config & DMAFLOW)
217 HW_TRACE ((me, "dma is complete"));
218 dma->irq_status = (dma->irq_status & ~DMA_RUN) | DMA_DONE;
221 bfin_dma_process_desc (me, dma);
231 struct bfin_dma *dma = hw_data (me);
232 if (dma->handler)
234 hw_event_queue_deschedule (me, dma->handler);
235 dma->handler = NULL;
240 dma->handler = hw_event_queue_schedule (me, delay,
241 bfin_dma_hw_event_callback, dma);
244 /* Chew through the DMA over and over. */
248 struct bfin_dma *dma = data;
254 dma->handler = NULL;
255 peer = bfin_dma_get_peer (me, dma);
258 if (dma->x_modify < 0)
260 nr_bytes = dma->ele_size;
262 nr_bytes = min (sizeof (buf), dma->curr_x_count * dma->ele_size);
267 if (dma->config & WNR)
269 HW_TRACE ((me, "dma transfer to 0x%08lx length %u",
270 (unsigned long) dma->curr_addr, nr_bytes));
272 ret = hw_dma_read_buffer (peer, buf, 0, dma->curr_addr, nr_bytes);
273 /* Has the DMA stalled ? abort for now. */
276 /* XXX: How to handle partial DMA transfers ? */
277 if (ret % dma->ele_size)
279 ret = sim_write (hw_system (me), dma->curr_addr, buf, ret);
283 HW_TRACE ((me, "dma transfer from 0x%08lx length %u",
284 (unsigned long) dma->curr_addr, nr_bytes));
286 ret = sim_read (hw_system (me), dma->curr_addr, buf, nr_bytes);
289 /* XXX: How to handle partial DMA transfers ? */
290 if (ret % dma->ele_size)
292 ret = hw_dma_write_buffer (peer, buf, 0, dma->curr_addr, ret, 0);
298 ele_count = ret / dma->ele_size;
299 dma->curr_addr += ele_count * dma->x_modify;
300 dma->curr_x_count -= ele_count;
302 if ((!dma->acked && dma->curr_x_count) || bfin_dma_finish_x (me, dma))
311 dma->irq_status |= DMA_ERR;
318 struct bfin_dma *dma = hw_data (me);
334 mmr_off = addr % dma->base;
335 valuep = (void *)((uintptr_t)dma + mmr_base() + mmr_off);
341 /* XXX: All registers are RO when DMA is enabled (except IRQ_STATUS).
350 /* Don't require 32bit access as all DMA MMRs can be used as 16bit. */
351 if (!bfin_dma_running (dma))
359 HW_TRACE ((me, "discarding write while dma running"));
365 if (!bfin_dma_running (dma))
369 if (!bfin_dma_running (dma))
373 dma->hw_peer = NULL;
376 HW_TRACE ((me, "discarding write while dma running"));
385 if (bfin_dma_enabled (dma))
387 dma->irq_status |= DMA_RUN;
388 bfin_dma_process_desc (me, dma);
390 if (!(dma->peripheral_map & CTYPE) || (dma->config & WNR))
395 dma->irq_status &= ~DMA_RUN;
404 if (!bfin_dma_running (dma))
407 HW_TRACE ((me, "discarding write while dma running"));
422 struct bfin_dma *dma = hw_data (me);
432 mmr_off = addr % dma->base;
433 valuep = (void *)((uintptr_t)dma + mmr_base() + mmr_off);
452 struct bfin_dma *dma = hw_data (me);
458 if (!bfin_dma_enabled (dma) && !bfin_dma_running (dma))
462 ret = sim_read (hw_system (me), dma->curr_addr, dest, nr_bytes);
464 ele_count = ret / dma->ele_size;
465 /* Has the DMA stalled ? abort for now. */
469 dma->curr_addr += ele_count * dma->x_modify;
470 dma->curr_x_count -= ele_count;
472 if (dma->curr_x_count == 0)
473 bfin_dma_finish_x (me, dma);
484 struct bfin_dma *dma = hw_data (me);
490 if (!bfin_dma_enabled (dma) && !bfin_dma_running (dma))
494 ret = sim_write (hw_system (me), dma->curr_addr, source, nr_bytes);
496 ele_count = ret / dma->ele_size;
497 /* Has the DMA stalled ? abort for now. */
501 dma->curr_addr += ele_count * dma->x_modify;
502 dma->curr_x_count -= ele_count;
504 if (dma->curr_x_count == 0)
505 bfin_dma_finish_x (me, dma);
512 { "di", 0, 0, output_port, }, /* DMA Interrupt */
517 attach_bfin_dma_regs (struct hw *me, struct bfin_dma *dma)
541 dma->base = attach_address;
547 struct bfin_dma *dma;
549 dma = HW_ZALLOC (me, struct bfin_dma);
551 set_hw_data (me, dma);
558 attach_bfin_dma_regs (me, dma);
560 /* Initialize the DMA Channel. */
561 dma->peripheral_map = bfin_dmac_default_pmap (me);