Lines Matching +full:udma +full:- +full:c
1 /*-
3 Copyright (C) 2015 Annapurna Labs Ltd.
10 found at http://www.gnu.org/licenses/gpl-2.0.html
39 * @file al_hal_udma_main.c
71 static void al_udma_set_defaults(struct al_udma *udma) in al_udma_set_defaults() argument
73 uint8_t rev_id = udma->rev_id; in al_udma_set_defaults()
75 if (udma->type == UDMA_TX) { in al_udma_set_defaults()
77 (struct unit_regs*)udma->udma_regs; in al_udma_set_defaults()
80 * This allows the UDMA to have 16 outstanding writes */ in al_udma_set_defaults()
82 al_reg_write32_masked(&tmp_unit_regs->m2s.m2s_rd.data_cfg, in al_udma_set_defaults()
88 al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 1000000); in al_udma_set_defaults()
90 al_reg_write32(&tmp_unit_regs->m2s.m2s_comp.cfg_application_ack in al_udma_set_defaults()
93 if (udma->type == UDMA_RX) { in al_udma_set_defaults()
95 &udma->udma_regs->s2m.s2m_comp.cfg_application_ack, 0); in al_udma_set_defaults()
103 * @param udma_q udma queue data structure
112 if (udma_q->udma->type == UDMA_TX) { in al_udma_q_config()
113 reg_addr = &udma_q->q_regs->m2s_q.rlimit.mask; in al_udma_q_config()
126 * @param udma_q udma queue data structure
135 if (udma_q->udma->type == UDMA_TX) in al_udma_q_config_compl()
136 reg_addr = &udma_q->q_regs->m2s_q.comp_cfg; in al_udma_q_config_compl()
138 reg_addr = &udma_q->q_regs->s2m_q.comp_cfg; in al_udma_q_config_compl()
142 if (udma_q->flags & AL_UDMA_Q_FLAGS_NO_COMP_UPDATE) in al_udma_q_config_compl()
147 if (udma_q->flags & AL_UDMA_Q_FLAGS_EN_COMP_COAL) in al_udma_q_config_compl()
155 if (udma_q->udma->type == UDMA_RX) { in al_udma_q_config_compl()
157 &udma_q->udma->udma_regs->s2m.s2m_comp.cfg_1c); in al_udma_q_config_compl()
160 val |= (udma_q->cdesc_size >> 2) in al_udma_q_config_compl()
162 al_reg_write32(&udma_q->udma->udma_regs->s2m.s2m_comp.cfg_1c in al_udma_q_config_compl()
171 * @param udma_q udma queue data structure
177 al_assert((AL_ADDR_LOW(udma_q->desc_phy_base) & in al_udma_q_set_pointers()
179 al_reg_write32(&udma_q->q_regs->rings.drbp_low, in al_udma_q_set_pointers()
180 AL_ADDR_LOW(udma_q->desc_phy_base)); in al_udma_q_set_pointers()
181 al_reg_write32(&udma_q->q_regs->rings.drbp_high, in al_udma_q_set_pointers()
182 AL_ADDR_HIGH(udma_q->desc_phy_base)); in al_udma_q_set_pointers()
184 al_reg_write32(&udma_q->q_regs->rings.drl, udma_q->size); in al_udma_q_set_pointers()
187 if (udma_q->cdesc_base_ptr == NULL) { in al_udma_q_set_pointers()
188 udma_q->flags |= AL_UDMA_Q_FLAGS_NO_COMP_UPDATE; in al_udma_q_set_pointers()
192 al_assert((AL_ADDR_LOW(udma_q->cdesc_phy_base) & in al_udma_q_set_pointers()
194 al_reg_write32(&udma_q->q_regs->rings.crbp_low, in al_udma_q_set_pointers()
195 AL_ADDR_LOW(udma_q->cdesc_phy_base)); in al_udma_q_set_pointers()
196 al_reg_write32(&udma_q->q_regs->rings.crbp_high, in al_udma_q_set_pointers()
197 AL_ADDR_HIGH(udma_q->cdesc_phy_base)); in al_udma_q_set_pointers()
204 * enable/disable udma queue
206 * @param udma_q udma queue data structure
213 uint32_t reg = al_reg_read32(&udma_q->q_regs->rings.cfg); in al_udma_q_enable()
217 udma_q->status = AL_QUEUE_ENABLED; in al_udma_q_enable()
220 udma_q->status = AL_QUEUE_DISABLED; in al_udma_q_enable()
222 al_reg_write32(&udma_q->q_regs->rings.cfg, reg); in al_udma_q_enable()
231 * Initialize the udma engine
233 int al_udma_init(struct al_udma *udma, struct al_udma_params *udma_params) in al_udma_init() argument
237 al_assert(udma); in al_udma_init()
239 if (udma_params->num_of_queues > DMA_MAX_Q) { in al_udma_init()
240 al_err("udma: invalid num_of_queues parameter\n"); in al_udma_init()
241 return -EINVAL; in al_udma_init()
244 udma->type = udma_params->type; in al_udma_init()
245 udma->num_of_queues = udma_params->num_of_queues; in al_udma_init()
246 udma->gen_regs = &udma_params->udma_regs_base->gen; in al_udma_init()
248 if (udma->type == UDMA_TX) in al_udma_init()
249 udma->udma_regs = (union udma_regs *)&udma_params->udma_regs_base->m2s; in al_udma_init()
251 udma->udma_regs = (union udma_regs *)&udma_params->udma_regs_base->s2m; in al_udma_init()
253 udma->rev_id = al_udma_get_revision(udma_params->udma_regs_base); in al_udma_init()
255 if (udma_params->name == NULL) in al_udma_init()
256 udma->name = ""; in al_udma_init()
258 udma->name = udma_params->name; in al_udma_init()
260 udma->state = UDMA_DISABLE; in al_udma_init()
262 udma->udma_q[i].status = AL_QUEUE_NOT_INITIALIZED; in al_udma_init()
265 al_udma_set_defaults(udma); in al_udma_init()
266 al_dbg("udma [%s] initialized. base %p\n", udma->name, in al_udma_init()
267 udma->udma_regs); in al_udma_init()
272 * Initialize the udma queue data structure
274 int al_udma_q_init(struct al_udma *udma, uint32_t qid, in al_udma_q_init() argument
279 al_assert(udma); in al_udma_q_init()
282 if (qid >= udma->num_of_queues) { in al_udma_q_init()
283 al_err("udma: invalid queue id (%d)\n", qid); in al_udma_q_init()
284 return -EINVAL; in al_udma_q_init()
287 if (udma->udma_q[qid].status == AL_QUEUE_ENABLED) { in al_udma_q_init()
288 al_err("udma: queue (%d) already enabled!\n", qid); in al_udma_q_init()
289 return -EIO; in al_udma_q_init()
292 if (q_params->size < AL_UDMA_MIN_Q_SIZE) { in al_udma_q_init()
293 al_err("udma: queue (%d) size too small\n", qid); in al_udma_q_init()
294 return -EINVAL; in al_udma_q_init()
297 if (q_params->size > AL_UDMA_MAX_Q_SIZE) { in al_udma_q_init()
298 al_err("udma: queue (%d) size too large\n", qid); in al_udma_q_init()
299 return -EINVAL; in al_udma_q_init()
302 if (q_params->size & (q_params->size - 1)) { in al_udma_q_init()
303 al_err("udma: queue (%d) size (%d) must be power of 2\n", in al_udma_q_init()
304 q_params->size, qid); in al_udma_q_init()
305 return -EINVAL; in al_udma_q_init()
308 udma_q = &udma->udma_q[qid]; in al_udma_q_init()
310 if (udma->type == UDMA_TX) in al_udma_q_init()
311 udma_q->q_regs = (union udma_q_regs __iomem *) in al_udma_q_init()
312 &udma->udma_regs->m2s.m2s_q[qid]; in al_udma_q_init()
314 udma_q->q_regs = (union udma_q_regs __iomem *) in al_udma_q_init()
315 &udma->udma_regs->s2m.s2m_q[qid]; in al_udma_q_init()
317 udma_q->adapter_rev_id = q_params->adapter_rev_id; in al_udma_q_init()
318 udma_q->size = q_params->size; in al_udma_q_init()
319 udma_q->size_mask = q_params->size - 1; in al_udma_q_init()
320 udma_q->desc_base_ptr = q_params->desc_base; in al_udma_q_init()
321 udma_q->desc_phy_base = q_params->desc_phy_base; in al_udma_q_init()
322 udma_q->cdesc_base_ptr = q_params->cdesc_base; in al_udma_q_init()
323 udma_q->cdesc_phy_base = q_params->cdesc_phy_base; in al_udma_q_init()
324 udma_q->cdesc_size = q_params->cdesc_size; in al_udma_q_init()
326 udma_q->next_desc_idx = 0; in al_udma_q_init()
327 udma_q->next_cdesc_idx = 0; in al_udma_q_init()
328 udma_q->end_cdesc_ptr = (uint8_t *) udma_q->cdesc_base_ptr + in al_udma_q_init()
329 (udma_q->size - 1) * udma_q->cdesc_size; in al_udma_q_init()
330 udma_q->comp_head_idx = 0; in al_udma_q_init()
331 udma_q->comp_head_ptr = (union al_udma_cdesc *)udma_q->cdesc_base_ptr; in al_udma_q_init()
332 udma_q->desc_ring_id = AL_UDMA_INITIAL_RING_ID; in al_udma_q_init()
333 udma_q->comp_ring_id = AL_UDMA_INITIAL_RING_ID; in al_udma_q_init()
335 udma_q->desc_ctrl_bits = AL_UDMA_INITIAL_RING_ID << in al_udma_q_init()
338 udma_q->pkt_crnt_descs = 0; in al_udma_q_init()
339 udma_q->flags = 0; in al_udma_q_init()
340 udma_q->status = AL_QUEUE_DISABLED; in al_udma_q_init()
341 udma_q->udma = udma; in al_udma_q_init()
342 udma_q->qid = qid; in al_udma_q_init()
352 al_dbg("udma [%s %d]: %s q init. size 0x%x\n" in al_udma_q_init()
354 udma_q->udma->name, udma_q->qid, in al_udma_q_init()
355 udma->type == UDMA_TX ? "Tx" : "Rx", in al_udma_q_init()
356 q_params->size, in al_udma_q_init()
357 (unsigned long long)q_params->desc_phy_base, in al_udma_q_init()
358 q_params->desc_base); in al_udma_q_init()
360 (unsigned long long)q_params->cdesc_phy_base, in al_udma_q_init()
361 q_params->cdesc_base, in al_udma_q_init()
362 q_params->cdesc_size); in al_udma_q_init()
368 * Reset a udma queue
380 /* De-assert scheduling and prefetch */ in al_udma_q_reset()
384 status_reg = &udma_q->q_regs->rings.status; in al_udma_q_reset()
393 remaining_time--; in al_udma_q_reset()
398 al_err("udma [%s %d]: %s timeout waiting for prefetch and " in al_udma_q_reset()
399 "scheduler disable\n", udma_q->udma->name, udma_q->qid, in al_udma_q_reset()
401 return -ETIMEDOUT; in al_udma_q_reset()
406 dcp_reg = &udma_q->q_regs->rings.dcp; in al_udma_q_reset()
407 crhp_reg = &udma_q->q_regs->rings.crhp; in al_udma_q_reset()
416 remaining_time--; in al_udma_q_reset()
421 al_err("udma [%s %d]: %s timeout waiting for dcp==crhp\n", in al_udma_q_reset()
422 udma_q->udma->name, udma_q->qid, __func__); in al_udma_q_reset()
423 return -ETIMEDOUT; in al_udma_q_reset()
427 if (udma_q->udma->type == UDMA_TX) in al_udma_q_reset()
428 q_sw_ctrl_reg = &udma_q->q_regs->m2s_q.q_sw_ctrl; in al_udma_q_reset()
430 q_sw_ctrl_reg = &udma_q->q_regs->s2m_q.q_sw_ctrl; in al_udma_q_reset()
440 int al_udma_q_handle_get(struct al_udma *udma, uint32_t qid, in al_udma_q_handle_get() argument
444 al_assert(udma); in al_udma_q_handle_get()
447 if (unlikely(qid >= udma->num_of_queues)) { in al_udma_q_handle_get()
448 al_err("udma [%s]: invalid queue id (%d)\n", udma->name, qid); in al_udma_q_handle_get()
449 return -EINVAL; in al_udma_q_handle_get()
451 *q_handle = &udma->udma_q[qid]; in al_udma_q_handle_get()
456 * Change the UDMA's state
458 int al_udma_state_set(struct al_udma *udma, enum al_udma_state state) in al_udma_state_set() argument
462 al_assert(udma != NULL); in al_udma_state_set()
463 if (state == udma->state) in al_udma_state_set()
464 al_dbg("udma [%s]: requested state identical to " in al_udma_state_set()
465 "current state (%d)\n", udma->name, state); in al_udma_state_set()
467 al_dbg("udma [%s]: change state from (%s) to (%s)\n", in al_udma_state_set()
468 udma->name, al_udma_states_name[udma->state], in al_udma_state_set()
483 al_err("udma: invalid state (%d)\n", state); in al_udma_state_set()
484 return -EINVAL; in al_udma_state_set()
487 if (udma->type == UDMA_TX) in al_udma_state_set()
488 al_reg_write32(&udma->udma_regs->m2s.m2s.change_state, reg); in al_udma_state_set()
490 al_reg_write32(&udma->udma_regs->s2m.s2m.change_state, reg); in al_udma_state_set()
492 udma->state = state; in al_udma_state_set()
497 * return the current UDMA hardware state
499 enum al_udma_state al_udma_state_get(struct al_udma *udma) in al_udma_state_get() argument
507 if (udma->type == UDMA_TX) in al_udma_state_get()
508 state_reg = al_reg_read32(&udma->udma_regs->m2s.m2s.state); in al_udma_state_get()
510 state_reg = al_reg_read32(&udma->udma_regs->s2m.s2m.state); in al_udma_state_get()
562 al_assert(!(udma_q->flags & AL_UDMA_Q_FLAGS_NO_COMP_UPDATE)); in al_udma_cdesc_packet_get()
565 curr = udma_q->comp_head_ptr; in al_udma_cdesc_packet_get()
566 comp_flags = swap32_from_le(curr->al_desc_comp_tx.ctrl_meta); in al_udma_cdesc_packet_get()
572 count = udma_q->pkt_crnt_descs + 1; in al_udma_cdesc_packet_get()
575 comp_flags = swap32_from_le(curr->al_desc_comp_tx.ctrl_meta); in al_udma_cdesc_packet_get()
582 udma_q->pkt_crnt_descs = count; in al_udma_cdesc_packet_get()
583 udma_q->comp_head_ptr = curr; in al_udma_cdesc_packet_get()
588 al_assert(count <= udma_q->size); in al_udma_cdesc_packet_get()
591 *cdesc = al_udma_cdesc_idx_to_ptr(udma_q, udma_q->next_cdesc_idx); in al_udma_cdesc_packet_get()
592 udma_q->pkt_crnt_descs = 0; in al_udma_cdesc_packet_get()
593 udma_q->comp_head_ptr = al_cdesc_next_update(udma_q, curr); in al_udma_cdesc_packet_get()
595 al_dbg("udma [%s %d]: packet completed. first desc %p (ixd 0x%x)" in al_udma_cdesc_packet_get()
596 " descs %d\n", udma_q->udma->name, udma_q->qid, *cdesc, in al_udma_cdesc_packet_get()
597 udma_q->next_cdesc_idx, count); in al_udma_cdesc_packet_get()
602 /** @} end of UDMA group */