3 #include <dma_engine_api.h>
4 #include <Magpie_api.h>
6 #include <Magpie_api.h>
9 /***********************Constants***************************/
12 * @brief Descriptor specific bitmaps
14 enum __dma_desc_status{
15 DMA_STATUS_OWN_DRV = 0x0,
16 DMA_STATUS_OWN_DMA = 0x1,
17 DMA_STATUS_OWN_MSK = 0x3
25 enum __dma_burst_size{
31 DMA_BYTE_SWAP_OFF = 0x00,
32 DMA_BYTE_SWAP_ON = 0x01
35 * @brief Interrupt status bits
37 typedef enum __dma_intr_bits{
38 DMA_INTR_TX1_END = (1 << 25),/*TX1 reached the end or Under run*/
39 DMA_INTR_TX0_END = (1 << 24),/*TX0 reached the end or Under run*/
40 DMA_INTR_TX1_DONE = (1 << 17),/*TX1 has transmitted a packet*/
41 DMA_INTR_TX0_DONE = (1 << 16),/*TX1 has transmitted a packet*/
42 DMA_INTR_RX3_END = (1 << 11),/*RX3 reached the end or Under run*/
43 DMA_INTR_RX2_END = (1 << 10),/*RX2 reached the end or Under run*/
44 DMA_INTR_RX1_END = (1 << 9), /*RX1 reached the end or Under run*/
45 DMA_INTR_RX0_END = (1 << 8), /*RX0 reached the end or Under run*/
46 DMA_INTR_RX3_DONE = (1 << 3), /*RX3 received a packet*/
47 DMA_INTR_RX2_DONE = (1 << 2), /*RX2 received a packet*/
48 DMA_INTR_RX1_DONE = (1 << 1), /*RX1 received a packet*/
49 DMA_INTR_RX0_DONE = 1, /*RX0 received a packet*/
52 * @brief Base addresses for various HIF
54 typedef enum __dma_base_off{
55 DMA_BASE_OFF_HST = 0x00053000,
56 DMA_BASE_OFF_GMAC = 0x00054000,
57 DMA_BASE_OFF_PCI = DMA_BASE_OFF_HST,
58 DMA_BASE_OFF_PCIE = DMA_BASE_OFF_HST
61 * @brief Engine offset to add for per engine register reads or
64 typedef enum __dma_eng_off{
65 DMA_ENG_OFF_RX0 = 0x800,
66 DMA_ENG_OFF_RX1 = 0x900,
67 DMA_ENG_OFF_RX2 = 0xa00,
68 DMA_ENG_OFF_RX3 = 0xb00,
69 DMA_ENG_OFF_TX0 = 0xc00,
70 DMA_ENG_OFF_TX1 = 0xd00
75 typedef enum __dma_reg_off{
77 * Common or Non Engine specific
79 DMA_REG_IFTYPE = 0x00,/*XXX*/
80 DMA_REG_ISR = 0x00,/*Interrupt Status Register*/
81 DMA_REG_IMR = 0x04,/*Interrupt Mask Register*/
85 DMA_REG_TXDESC = 0x00,/*TX DP*/
86 DMA_REG_TXSTART = 0x04,/*TX start*/
87 DMA_REG_INTRLIM = 0x08,/*TX Interrupt limit*/
88 DMA_REG_TXBURST = 0x0c,/*TX Burst Size*/
89 DMA_REG_TXSWAP = 0x18,
93 DMA_REG_RXDESC = 0x00,/*RX DP*/
94 DMA_REG_RXSTART = 0x04,/*RX Start*/
95 DMA_REG_RXBURST = 0x08,/*RX Burst Size*/
96 DMA_REG_RXPKTOFF = 0x0c,/*RX Packet Offset*/
100 /*******************************Data types******************************/
102 typedef struct zsDmaDesc __dma_desc_t;
104 typedef struct zsDmaQueue __dma_rxq_t;
106 typedef struct zsTxDmaQueue __dma_txq_t;
109 * @brief Register Address
111 typedef struct __dma_reg_addr{
112 __dma_base_off_t base;/*Base address, Fixed*/
113 __dma_eng_off_t eng;/*Engine offset, Fixed*/
117 * @brief DMA engine's Queue
119 typedef struct __dma_eng_q{
120 __dma_reg_addr_t addr;
130 /***********************Defines*****************************/
132 #define DMA_ADDR_INIT(_eng) { \
133 .base = DMA_BASE_OFF_HST, \
134 .eng = DMA_ENG_OFF_##_eng \
137 * @brief check if the val doesn't lie between the low & high of
140 #define DMA_ENG_CHECK(_val, _low, _high) \
141 ((_val) < DMA_ENGINE_##_low || (_val) > DMA_ENGINE_##_high)
144 /********************************Globals*************************************/
146 __dma_eng_q_t eng_q[DMA_ENGINE_MAX] = {
147 {.addr = DMA_ADDR_INIT(RX0)},
148 {.addr = DMA_ADDR_INIT(RX1)},
149 {.addr = DMA_ADDR_INIT(RX2)},
150 {.addr = DMA_ADDR_INIT(RX3)},
151 {.addr = DMA_ADDR_INIT(TX0)},
152 {.addr = DMA_ADDR_INIT(TX1)},
155 /**********************************API's*************************************/
158 * @brief Read the register
165 __dma_reg_read(A_UINT32 addr)
167 return *((volatile A_UINT32 *)addr);
170 * @brief Write into the register
176 __dma_reg_write(A_UINT32 addr, A_UINT32 val)
178 *((volatile A_UINT32 *)addr) = val;
181 * @brief Set the base address
187 __dma_set_base(dma_engine_t eng_no, dma_iftype_t if_type)
191 eng_q[eng_no].addr.base = DMA_BASE_OFF_GMAC;
194 eng_q[eng_no].addr.base = DMA_BASE_OFF_PCI;
197 eng_q[eng_no].addr.base = DMA_BASE_OFF_PCIE;
204 * @brief init the Transmit queue
212 __dma_lib_tx_init(dma_engine_t eng_no, dma_iftype_t if_type)
214 __dma_desc_t *head = NULL;
217 if(DMA_ENG_CHECK(eng_no, TX0, TX1))
220 DMA_Engine_init_tx_queue(&eng_q[eng_no].txq);
222 __dma_set_base(eng_no, if_type);
224 addr = eng_q[eng_no].addr.base + eng_q[eng_no].addr.eng;
226 head = eng_q[eng_no].txq.head;
228 __dma_reg_write(addr + DMA_REG_TXDESC,(A_UINT32)head);
229 __dma_reg_write(addr + DMA_REG_TXBURST, DMA_BURST_16W);
230 __dma_reg_write(addr + DMA_REG_TXSWAP, DMA_BYTE_SWAP_ON);
236 __dma_lib_rx_config(dma_engine_t eng_no, A_UINT16 num_desc,
239 __dma_desc_t *desc = NULL;
243 * Allocate the Receive Queue
245 DMA_Engine_config_rx_queue(&eng_q[eng_no].rxq, num_desc, gran);
247 desc = eng_q[eng_no].rxq.head;
248 addr = eng_q[eng_no].addr.base + eng_q[eng_no].addr.eng;
250 * Update RX queue head in the H/W, set the burst & say go
252 __dma_reg_write(addr + DMA_REG_RXDESC, (A_UINT32)desc);
253 __dma_reg_write(addr + DMA_REG_RXBURST, DMA_BURST_8W);
254 __dma_reg_write(addr + DMA_REG_RXSWAP, DMA_BYTE_SWAP_ON);
255 __dma_reg_write(addr + DMA_REG_RXSTART, DMA_BIT_SET);
260 * @brief Initialize the DMA engine
267 __dma_lib_rx_init(dma_engine_t eng_no, dma_iftype_t if_type)
269 if(DMA_ENG_CHECK(eng_no, RX0, RX3))
273 * XXX:The init can be called multiple times to setup different
274 * geometries of descriptors
276 DMA_Engine_init_rx_queue(&eng_q[eng_no].rxq);
278 __dma_set_base(eng_no, if_type);
283 * @brief Transmit VBUF for the specified engine number
290 __dma_hard_xmit(dma_engine_t eng_no, VBUF *vbuf)
294 addr = eng_q[eng_no].addr.base + eng_q[eng_no].addr.eng;
296 DMA_Engine_xmit_buf(&eng_q[eng_no].txq, vbuf);
300 __dma_reg_write(addr + DMA_REG_TXSTART, DMA_BIT_SET);
303 * @brief return a VBUF for the specified engine number
310 __dma_reap_xmitted(dma_engine_t eng_no)
312 return DMA_Engine_reap_xmited_buf(&eng_q[eng_no].txq);
315 * @brief flush all xmitted & to be xmitted (if you have the
316 * window) dudes from H/W
321 __dma_flush_xmit(dma_engine_t eng_no)
324 __dma_desc_t *desc, *term;
326 addr = eng_q[eng_no].addr.base + eng_q[eng_no].addr.eng;
328 desc = eng_q[eng_no].txq.head;
329 term = eng_q[eng_no].txq.terminator;
332 * XXX: I don't know how to kick the all dudes out, Ideally
333 * there should be a DMA reset button (the red one)
335 __dma_reg_write(addr + DMA_REG_TXSTART, DMA_BIT_CLEAR);
336 __dma_reg_write(addr + DMA_REG_TXDESC,(A_UINT32)term);
339 * Make the H/W queue ready for TX reap
341 for(;desc != term; desc = desc->nextAddr)
342 desc->status = DMA_STATUS_OWN_DRV;
344 // DMA_Engine_flush_xmit(&eng_q[eng_no].txq);
347 * @brief check if there are xmitted vbufs (dudes) hanging
355 __dma_xmit_done(dma_engine_t eng_no)
357 if(DMA_ENG_CHECK(eng_no, TX0, TX1))
360 return DMA_Engine_has_compl_packets(&eng_q[eng_no].txq);
363 * @brief Reap VBUF's from the specified engine number
370 __dma_reap_recv(dma_engine_t eng)
372 return DMA_Engine_reap_recv_buf(&eng_q[eng].rxq);
375 * @brief return to source, put the vbuf back into the queue, In
376 * case the Engine is stopped so start it again
382 __dma_return_recv(dma_engine_t eng_no, VBUF *vbuf)
386 addr = eng_q[eng_no].addr.base + eng_q[eng_no].addr.eng;
388 DMA_Engine_return_recv_buf(&eng_q[eng_no].rxq, vbuf);
390 __dma_reg_write(addr + DMA_REG_RXSTART, DMA_BIT_SET);
393 * @brief check if there are freshly arrived vbufs (dudes)
400 __dma_recv_pkt(dma_engine_t eng_no)
402 if(DMA_ENG_CHECK(eng_no, RX0, RX3))
405 return DMA_Engine_has_compl_packets(&eng_q[eng_no].rxq);
409 dma_lib_module_install(struct dma_lib_api *apis)
411 apis->tx_init = __dma_lib_tx_init;
412 apis->rx_init = __dma_lib_rx_init;
413 apis->rx_config = __dma_lib_rx_config;
414 apis->hard_xmit = __dma_hard_xmit;
415 apis->flush_xmit = __dma_flush_xmit;
416 apis->xmit_done = __dma_xmit_done;
417 apis->reap_recv = __dma_reap_recv;
418 apis->reap_xmitted = __dma_reap_xmitted;
419 apis->return_recv = __dma_return_recv;
420 apis->recv_pkt = __dma_recv_pkt;