2 * Copyright (C) 2012-2013 Czech Technical University in Prague
4 * Created on: 28.2.2013
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
33 * Test command for Ethernet PHY
42 #include "sys/phy_dp83848h.h"
45 /* ************************************************* */
46 /* Emac frame buffer related stuff */
47 /* ************************************************* */
48 typedef struct _EMAC_Desc {
49 struct _EMAC_Desc *pNext; /* Pointer to next descriptor in chain */
50 uint8_t *pBuffer; /* Pointer to data buffer */
51 uint32_t BufOffLen; /* Buffer Offset(MSW) and Length(LSW) */
52 uint32_t PktFlgLen; /* Packet Flags(MSW) and Length(LSW) */
56 #define EMAC_DSC_FLAG_SOP 0x80000000u
57 #define EMAC_DSC_FLAG_EOP 0x40000000u
58 #define EMAC_DSC_FLAG_OWNER 0x20000000u
59 #define EMAC_DSC_FLAG_EOQ 0x10000000u
60 #define EMAC_DSC_FLAG_TDOWNCMPLT 0x08000000u
61 #define EMAC_DSC_FLAG_PASSCRC 0x04000000u
63 /* ************************************************* */
65 /* ************************************************* */
67 uint8_t destination[6];
74 /* ************************************************* */
78 unsigned int emacCtrlBase = EMAC_CTRL_BASE;
79 unsigned int emacBase = EMAC_BASE;
80 unsigned int emacCtrlRamBase = EMAC_CTRL_RAM_BASE;
81 unsigned int mdioBase = MDIO_BASE;
83 int rx_irq_cnt; /* Interrupt counters */
86 unsigned int phyalive;
90 unsigned int intvectraw;
93 * Emac address is used only in this debugging tool. During emac_test is't called rpp_init().
94 * MAC address defined in eth.h have no efect in this test file.
97 uint8_t emacAddress[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
98 uint32_t emacPhyAddress = 0x1; /* Address of PHY on "MDIO bus"
99 (depends on PHY configuration) */
100 int channel = 0; /* Emac has 8 RX and TX channels; we use only one */
102 EMAC_Desc fr1 __attribute__((aligned(4))); /* Frame descriptor of Ethernet frame to be sent */
104 /* Frame descriptor used for receiving frames --
105 it might be placed in normal RAM or in CPPI ram of EMAC */
106 //EMAC_Desc rx_desc __attribute__((aligned(4)));
107 volatile EMAC_Desc *rx_desc = ((EMAC_Desc *)EMAC_CTRL_RAM_BASE);
110 #define BUFF_SIZE 2048
111 uint8_t rx_buff[BUFF_SIZE]; /* Buffer for data reception */
113 eth_frame_t efr1; /* Buffer for TX -- Before sending some data we have to
114 prepare it in "Ethernet frame" format */
121 for (i = 0; i < 65555; i++)
125 int emac_test(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
128 unsigned char input = 0;
129 volatile unsigned int delay = 0xfff;
133 #ifdef TARGET_TMS570_RPP
134 /* Deactivate reset pin of PHY */
135 dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
137 dmmREG->PC5 = (1 << DMM_CLK); /* Set to L */
139 dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
143 /* Prepare RX Packet buffer descriptor */
144 rx_desc->pBuffer = rx_buff;
145 rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
146 rx_desc->pNext = NULL;
147 rx_desc->BufOffLen = BUFF_SIZE;
150 /* Fill some testing Ethernet frame with relevant data */
151 efr1.destination[0] = 0x00;
152 efr1.destination[1] = 0x21;
153 efr1.destination[2] = 0x70;
154 efr1.destination[3] = 0xb5;
155 efr1.destination[4] = 0x4b;
156 efr1.destination[5] = 0xea;
157 efr1.source[0] = 0xff;
158 efr1.source[1] = 0xff;
159 efr1.source[2] = 0xff;
160 efr1.source[3] = 0xff;
161 efr1.source[4] = 0xff;
162 efr1.source[5] = 0xff;
171 EMACInit(emacCtrlBase, emacBase);
172 MDIOInit(mdioBase, 0x0, 0x0);
173 dummy_wait(); // FIXME
175 EMACMACSrcAddrSet(emacBase, emacAddress);
176 /* Be sure to program all eight MAC address registers -
177 * whether the receive channel is to be enabled or not.
179 for (chan = 0; chan < 8; chan++)
180 EMACMACAddrSet(emacBase, chan, emacAddress, EMAC_MACADDR_NO_MATCH_NO_FILTER);
182 phyalive = MDIOPhyAliveStatusGet(mdioBase);
184 rpp_sci_printf("PHY not alive\r\n");
188 phylink = MDIOPhyLinkStatusGet(mdioBase);
190 rpp_sci_printf("PHY link down\r\n");
192 rpp_sci_printf("PHY link up\r\n");
194 rpp_sci_printf("Configuring PHY and EMAC...\r\n");
195 PHY_auto_negotiate(mdioBase, emacPhyAddress, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
197 /* Set the EMAC with the negotiation results if it is successful */
198 PHY_partner_ability_get(mdioBase, emacPhyAddress, &data);
199 if (data & PHY_100BASETXDUPL_m) {
200 EMACDuplexSet(emacBase, EMAC_DUPLEX_FULL);
203 else if (data & PHY_100BASETX_m) {
204 EMACDuplexSet(emacBase, EMAC_DUPLEX_HALF);
211 for (chan = 0; chan < 8; chan++) {
212 EMACTxHdrDescPtrWrite(emacBase, 0, chan);
213 EMACRxHdrDescPtrWrite(emacBase, 0, chan);
216 //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_RX);
217 //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_TX);
219 EMACRxBroadCastEnable(emacBase, channel);
220 EMACRxPromiscEnable(emacBase, channel);
222 EMACTxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
223 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
225 EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
227 //EMACRxUnicastSet(emacBase, 0);
228 EMACTxEnable(emacBase);
229 EMACRxEnable(emacBase);
231 EMACMIIEnable(emacBase);
233 phylink = MDIOPhyLinkStatusGet(mdioBase);
235 rpp_sci_printf("PHY link down\r\n");
237 rpp_sci_printf("PHY link up\r\n");
241 for (j = 0; j < 8; j++) {
243 fr1.pBuffer = (uint8_t *)&efr1;
245 fr1.PktFlgLen = (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | EMAC_DSC_FLAG_OWNER | 65);
247 EMACTxHdrDescPtrWrite(emacBase, (unsigned int)&fr1, channel);
248 rpp_sci_printf("Packet sent\r\n");
249 while (fr1.PktFlgLen == EMAC_DSC_FLAG_OWNER)
250 if (rpp_sci_read_nb(1, &input) == SUCCESS)
253 intvect = EMACIntVectorGet(emacBase);
254 intvectraw = EMACIntVectorRawGet(emacBase);
262 rpp_sci_printf("Trying to receive some data\r\n");
263 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
265 for (j = 0; j < 8; j++) {
266 while (!(rx_desc->PktFlgLen & EMAC_DSC_FLAG_SOP))
267 if (rpp_sci_read_nb(1, &input) == SUCCESS)
272 rpp_sci_printf("Received packet:\r\n");
273 rpp_sci_printf("Length: %d\r\n", rx_desc->PktFlgLen & 0xffff);
275 for (i = 0; i < (rx_desc->PktFlgLen & 0xffff); i++) {
276 i2str(rx_fr, rx_desc->pBuffer[i], 0, 16);
277 rpp_sci_printf("%x ", rx_desc->pBuffer[i]);
278 if (((i+1) % 8) == 0)
279 rpp_sci_printf("\r\n");
282 /* Reinitialize RX buffer */
283 rx_desc->pBuffer = rx_buff;
284 rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
285 rx_desc->pNext = NULL;
286 rx_desc->BufOffLen = BUFF_SIZE;
287 EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
288 rpp_sci_printf("\r\n-------------------------------------------\r\n");
291 EMACRxIntPulseDisable(emacBase, emacCtrlBase, 0, channel);
301 cmd_des_t const cmd_des_test_ethernet = {
303 "ethernet", "Temporary command to test Ethernet communication",
304 "### Command syntax ###\n"
308 "### Description ###\n"
310 "Command tries to send a few ethernet frames. No real connection or\n"
311 "meaningful packets are sent. This only tests, if Ethernet is just\n"
313 CMD_HANDLER(emac_test), (void *)&cmd_list_emac
316 cmd_des_t const *cmd_list_emac[] = {
317 &cmd_des_test_ethernet,