1 /********************************************************************************************
2 * FILE PURPOSE: The cpdma driver
3 ********************************************************************************************
4 * FILE NAME: cpdma.c
5 *
6 * DESCRIPTION: The boot loader cpdma driver
7 *
8 ********************************************************************************************/
9 #include "types.h"
10 #include "platform.h"
11 #include "cpdma_loc.h"
12 #include "cpdma_api.h"
13 #include "target.h"
15 /*********************************************************************************************
16 * FUNCTION PURPOSE: Disable all rx channels and clear all the flow registers
17 *********************************************************************************************
18 * DESCRIPTION: The teardown is initiated and polled for completion. The function will
19 * return an error if the teardown is never complete, but will not stay
20 * in the function forever.
21 *********************************************************************************************/
22 int16_t hwCpdmaRxDisable (const cpdmaRxCfg_t *cfg)
23 {
24 uint32_t i;
25 uint32_t v;
26 BOOL done;
28 for (i = 0; i < cfg->nRxChans; i++) {
30 /* If enabled, set the teardown bit */
31 v = DEVICE_REG32_R (cfg->rxBase + CPDMA_REG_RCHAN_CFG_REG_A(i));
32 if ( (v & CPDMA_REG_VAL_RCHAN_A_RX_ENABLE) == CPDMA_REG_VAL_RCHAN_A_RX_ENABLE ) {
33 v = v | CPDMA_REG_VAL_RCHAN_A_RX_TDOWN;
34 DEVICE_REG32_W (cfg->rxBase + CPDMA_REG_RCHAN_CFG_REG_A(i), v);
35 }
37 }
39 /* Poll for completion */
40 for (i = 0, done = FALSE; ( (i < cfg->tdownPollCount) && (done == FALSE) ); i++) {
42 chipDelay32 (100);
44 done = TRUE;
45 v = DEVICE_REG32_R (cfg->rxBase + CPDMA_REG_RCHAN_CFG_REG_A(i));
46 if ( (v & CPDMA_REG_VAL_RCHAN_A_RX_ENABLE) == CPDMA_REG_VAL_RCHAN_A_RX_ENABLE )
47 done = FALSE;
49 }
51 if (done == FALSE)
52 return (-1);
55 /* Clear all of the flow registers */
56 for (i = 0; i < cfg->nRxFlows; i++) {
57 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_A, i), 0);
58 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_B, i), 0);
59 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_C, i), 0);
60 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_D, i), 0);
61 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_E, i), 0);
62 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_F, i), 0);
63 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_G, i), 0);
64 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_H, i), 0);
66 }
68 return (0);
70 } /* hwCpdmaRxDisable */
74 /*********************************************************************************************
75 * FUNCTION PURPOSE: Configure the cpdma receive direction for boot loader
76 *********************************************************************************************
77 * DESCRIPTION: The receive configuration for boot consists of a single flow configuration
78 * which is stored as flow configuration 0. All extended info and psinfo
79 * is stripped.
80 *********************************************************************************************/
81 int16_t hwCpdmaRxConfig (const cpdmaRxCfg_t *cfg)
82 {
83 uint32_t v;
84 uint32_t i;
85 int16_t ret = 0;
88 /* Rx dma channels are disabled during flow configurations.
89 * Even if disable fails attempt to configure the receive so the boot can work */
90 if (hwCpdmaRxDisable (cfg) != 0)
91 ret = -1;
93 /* Configure the flow
94 * The flow is configured to not pass extended info or psinfo, with descriptor
95 * type host */
97 v = CPDMA_REG_VAL_MAKE_RX_FLOW_A( 1, /* extended info passed */
98 1, /* psinfo passed */
99 0, /* Retry on failure to transmit */
100 CPDMA_DESC_TYPE_HOST, /* Host type descriptor */
101 0, /* PS located in descriptor */
102 0, /* SOP offset */
103 cfg->qmNumRx, /* Rx packet destination QM number */
104 cfg->queueRx ); /* Rx packet destination queue */
107 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_A, 0), v);
109 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_B, 0), CPDMA_REG_VAL_RX_FLOW_B_DEFAULT);
110 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_C, 0), CPDMA_REG_VAL_RX_FLOW_C_DEFAULT);
112 v = CPDMA_REG_VAL_MAKE_RX_FLOW_D ( cfg->qmNumFreeBuf, /* Rx packet destination QM number, 1st descriptor */
113 cfg->queueFreeBuf, /* Rx packet destination queue, 1st descriptor */
114 cfg->qmNumFreeBuf, /* Rx packet destination QM number, subsequent descriptors */
115 cfg->queueFreeBuf ); /* Rx packet destination queue, subsequent descriptors */
116 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_D, 0), v);
119 /* Register E uses the same setup as D */
120 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_E, 0), v);
124 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_F, 0), CPDMA_REG_VAL_RX_FLOW_F_DEFAULT);
125 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_G, 0), CPDMA_REG_VAL_RX_FLOW_G_DEFAULT);
126 DEVICE_REG32_W (cfg->flowBase + CPDMA_RX_FLOW_CFG(CPDMA_RX_FLOW_REG_H, 0), CPDMA_REG_VAL_RX_FLOW_H_DEFAULT);
129 /* Enable the rx channels */
130 for (i = 0; i < cfg->nRxChans; i++)
131 DEVICE_REG32_W (cfg->rxBase + CPDMA_REG_RCHAN_CFG_REG_A(i), CPDMA_REG_VAL_RCHAN_A_RX_ENABLE);
134 return (ret);
136 } /* hwCpdmaRxConfig */
139 /*************************************************************************************************
140 * FUNCTION PURPOSE: Configure the cpdma transmit direction for boot loader
141 *************************************************************************************************
142 * DESCRIPTION: The transmit channels are enabled
143 *************************************************************************************************/
144 int16_t hwCpdmaTxConfig (const cpdmaTxCfg_t *cfg)
145 {
146 uint32_t i;
148 /* Disable loopback in the tx direction */
149 DEVICE_REG32_W (cfg->gblCtlBase + CPDMA_REG_EMU_CTL, CPDMA_REG_VAL_EMU_CTL_NO_LOOPBACK);
151 /* Enable all channels. The current state isn't important */
152 for (i = 0; i < cfg->nTxChans; i++) {
153 DEVICE_REG32_W (cfg->txBase + CPDMA_REG_TCHAN_CFG_REG_B(i), 0); /* Priority */
154 DEVICE_REG32_W (cfg->txBase + CPDMA_REG_TCHAN_CFG_REG_A(i), CPDMA_REG_VAL_TCHAN_A_TX_ENABLE);
155 }
157 return (0);
159 } /* hwCpdmaTxConfig */
162 /***************************************************************************************************
163 * FUNCTION PURPOSE: Disable the transmit channels
164 ***************************************************************************************************
165 * DESCRIPTION: The transmit channels are disabled
166 ***************************************************************************************************/
167 int16_t hwCpdmaTxDisable (const cpdmaTxCfg_t *cfg)
168 {
169 uint32_t i;
170 uint32_t v;
172 for (i = 0; i < cfg->nTxChans; i++) {
174 v = DEVICE_REG32_R (cfg->txBase + CPDMA_REG_TCHAN_CFG_REG_A(i));
176 if ( (v & CPDMA_REG_VAL_TCHAN_A_TX_ENABLE) == CPDMA_REG_VAL_TCHAN_A_TX_ENABLE) {
177 v = v | CPDMA_REG_VAL_TCHAN_A_TX_TDOWN;
178 DEVICE_REG32_W (cfg->txBase + CPDMA_REG_TCHAN_CFG_REG_A(i), v);
179 }
180 }
183 return (0);
185 } /* hwCpdmaTxDisable */