OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [main.c] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
 
2
/******************************************************************************
3
**
4
** (C) Copyright 2013 DFC Design, s.r.o., Brno, Czech Republic
5
** Author: Marek Kvas (m.kvas@dspfpga.com)
6
**
7
****************************************************************************
8
**
9
** This file is part of Xenia Ethernet Example project.
10
**
11
** Xenia Ethernet Example project is free software: you can
12
** redistribute it and/or modify it under the terms of
13
** the GNU Lesser General Public License as published by the Free
14
** Software Foundation, either version 3 of the License, or
15
** (at your option) any later version.
16
**
17
** Xenia Ethernet Example project is distributed in the hope that
18
** it will be useful, but WITHOUT ANY WARRANTY; without even
19
** the implied warranty of MERCHANTABILITY or FITNESS FOR A
20
** PARTICULAR PURPOSE.  See the GNU Lesser General Public License
21
** for more details.
22
**
23
** You should have received a copy of the GNU Lesser General Public
24
** License along with Xenia Ethernet Example project.  If not,
25
** see <http://www.gnu.org/licenses/>.
26
****************************************************************************
27
*/
28
 
29
 
30
 
31
 
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <xil_cache.h>
36
#include <sleep.h>
37
#include <xintc.h>
38
#include <xspi.h>
39
#include <xparameters.h>
40
 
41
#include "main.h"
42
#include "uprintf.h"
43
#include "build_time.h"
44
#include "mdio.h"
45
#include "gpio.h"
46
#include "spansion_flash.h"
47
#include "timers.h"
48
#include "iic_wrap.h"
49
#include "iic_id_eeprom.h"
50
#include "udpip_rxaui.h"
51
#include "eth_phy.h"
52
#include "fw.h"
53
 
54
 
55
/* Peripheral IDs, INTC vectors and base addresses */
56
#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
57
#define SPI_DEVICE_ID           XPAR_SPI_0_DEVICE_ID
58
#define TMRCTR_DEVICE_ID        XPAR_TMRCTR_0_DEVICE_ID
59
#define TMRCTR_INTERRUPT_ID     XPAR_INTC_0_TMRCTR_0_VEC_ID
60
#define IIC_DEVICE_ID           XPAR_AXI_IIC_0_DEVICE_ID
61
#define IIC_INTERRUPT_ID        XPAR_INTC_0_IIC_0_VEC_ID
62
#define MDIO_BASEADDR           XPAR_MDIO_MASTER_TOP_0_BASEADDR
63
 
64
 
65
/* Address of Marvell PHY on MDIO bus for Xenie board */
66
#define ETH_PHY_MDIO_ADDR       0
67
 
68
/* Addresses of UID EEPROM on IIC bus for Xenie board */
69
#define ID_EEPROM_IIC_ADDR      0x50
70
 
71
/* Default timeout of IIC operations in milliseconds*/
72
#define IIC_DEFAULT_TIMEOUT_MS  20
73
 
74
/* Macros decomposing version numbers */
75
#define FWREV_TO_MAJOR(A)       (((A)>>8) & 0xf)
76
#define FWREV_TO_MINOR(A)       (((A)>>4) & 0xf)
77
#define FWREV_TO_Z(A)           ((A) & 0xf)
78
 
79
#define BITREV_TO_TARGET(A)     (((A)>>8) & 0xf)
80
#define BITREV_TO_MAJOR(A)      (((A)>>4) & 0xf)
81
#define BITREV_TO_MINOR(A)              ((A) & 0xf)
82
 
83
/*
84
 * Configuration QSPI Flash slave select number
85
 * for Xenie board.
86
 */
87
#define SPANSION_FLASH_CS               0
88
 
89
/*
90
 * Number of bytes per page in the flash device.
91
 */
92
#define SPANSION_FLASH_PAGE_SIZE                256
93
 
94
/*
95
 * Instances to support device drivers
96
 */
97
static XSpi Spi;
98
static XTmrCtr TimerCounterInst;
99
static XIntc InterruptController;
100
static struct iic_wrap_dev iic_wrap_dev;
101
static struct iic_id_eeprom_dev iic_id_eeprom_dev;
102
static struct spansion_flash sf_dev;
103
static struct mdio_struct *mdio_dev_ptr;
104
static struct phy_dev *phy_dev_ptr;
105
 
106
 
107
/*
108
 * Offset in flash where PHY FW header is located
109
 */
110
#define FW_HDR_FLASH_OFFSET 0x00800000u
111
 
112
 
113
 
114
 
115
/* System information defaults */
116
static struct sys_info_s sys_info = {
117 13 DFC
                .fwRev = 0x101,
118 4 DFC
                .eth_status = {-1, -1},
119
                .uid = {00, 00, 00, 00, 00, 00},
120
                .eth_settings = {
121
                                .mac = {10, 20, 30, 40, 50, 60},
122
                                .ip = 0xc0a80a60,
123
                                .netmask = 0xffffff00,
124
                },
125
};
126
 
127
 
128
 
129
 
130
 
131
 
132
 
133
 
134
/*
135
 * Setup how etherned leds should behave.
136
 * There are two LEDs on JT7-1104NL magjack that is on Xenie BB.
137
 * Green LED is connected between LED0(-) and LED1(+).
138
 * Bicolor - two terminal - led is connected between LED2 and LED3.
139
 * Green LED will indicate speed with flashing (10G = 4 flashes,
140
 * 1G = 3 flashes, ...)
141
 * Bicolor LED will indicate activity.
142
 *
143
 */
144
void phy_LED_setup(struct mdio_struct *mdio)
145
{
146
        /* LED0 drive low */
147
        mdio_write_indirect(mdio, ETH_PHY_MDIO_ADDR, 31, 0xf020, 0x0001);
148
        /* LED1 in speed blink mode */
149
        mdio_write_indirect(mdio, ETH_PHY_MDIO_ADDR, 31, 0xf021, 0x00f9);
150
 
151
        /* LED2 blink on TX or RX activity */
152
        mdio_write_indirect(mdio, ETH_PHY_MDIO_ADDR, 31, 0xf022, 0x0101);
153
 
154
        /* LED3 solid on RX activity - effectively changes color of
155
         * activity LED  based on direction*/
156
        mdio_write_indirect(mdio, ETH_PHY_MDIO_ADDR, 31, 0xf023, 0x0011);
157
 
158
}
159
 
160
 
161
/*
162
 * Reset PHY by pulling reset signal down.
163
 * It must toggle direction to commit reset state change.
164
 * Sets clock source to internal and un-reset PHY
165
 */
166
void phy_reset()
167
{
168
        /* This should be set correctly by pull-ups */
169
        gpio_set_out(GPIO0_BANK, GPIO0_ETH_PHY_CLK_SEL); /* 1 - on-board; 0 - external*/
170
        gpio_clear_dir(GPIO0_BANK, GPIO0_ETH_PHY_CLK_SEL);
171
 
172
        /* Pull reset down - assert*/
173
        gpio_set_dir(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N);
174
        gpio_clear_out(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N); /* 1 - active; 0 - reset*/
175
        gpio_clear_dir(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N);
176
 
177
        usleep(100*1000);
178
 
179
        /* Pull reset up - deassert */
180
        gpio_set_dir(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N);
181
        gpio_set_out(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N); /* 1 - active; 0 - reset*/
182
        gpio_clear_dir(GPIO0_BANK, GPIO0_ETH_PHY_RESET_N);
183
 
184
}
185
 
186
/*
187
 * Read bitstream version and build date from
188
 * running bitstream.
189
 */
190
void get_bitstream_version(struct bitstreamRev_s *rev)
191
{
192
        uint32_t tmp;
193
        tmp = gpio_get(VERSION_GPIO_0_BANK);
194
        rev->comp_time = tmp & 0xffffff;
195
        rev->comp_date = (tmp >> 24) & 0xff;
196
        tmp = gpio_get(VERSION_GPIO_1_BANK);
197
        rev->comp_date += (tmp & 0xffff) << 8;
198
        rev->rev = (tmp >> 16) & 0xffff;
199
}
200
 
201
/*
202
 * Print bitstream compile time based on
203
 * info read using get_bitstream_version
204
 */
205
void print_bitstream_compile_time(struct bitstreamRev_s *rev)
206
{
207
        uprintf("20%02x-%02x-%02x %02x:%02x:%02x",
208
                        (rev->comp_date >> 16) & 0xff,
209
                        (rev->comp_date >> 8) & 0xff,
210
                        (rev->comp_date >> 0) & 0xff,
211
                        (rev->comp_time >> 16) & 0xff,
212
                        (rev->comp_time >> 8) & 0xff,
213
                        (rev->comp_time >> 0) & 0xff);
214
}
215
 
216
/* Print unique identifier in MAC address format */
217
void print_UID(u8* uid) {
218
        uprintf("%02x-%02x-%02x-%02x-%02x-%02x",
219
                                   uid[0], uid[1], uid[2], uid[3], uid[4], uid[5]);
220
}
221
 
222
/* Find string description of given PHY link speed */
223
char* phy_speed_to_string(uint16_t speed)
224
{
225
        switch(speed) {
226
        case PHY_ADV_NONE:
227
                return("not resolved yet");
228
                break;
229
        case PHY_SPEED_10M_HD:
230
                return("10 Mbps, half duplex");
231
                break;
232
        case PHY_SPEED_10M_FD:
233
                return("10 Mbps, full duplex");
234
                break;
235
        case PHY_SPEED_100M_HD:
236
                return("100 Mbps, half duplex");
237
                break;
238
        case PHY_SPEED_100M_FD:
239
                return("100 Mbps, full duplex");
240
                break;
241
        case PHY_SPEED_1GIG_HD:
242
                return("1 Gbps, half duplex");
243
                break;
244
        case PHY_SPEED_1GIG_FD:
245
                return("1 Gbps, full duplex");
246
                break;
247
        case PHY_SPEED_10GIG_FD:
248
                return("10 Gbps, full duplex");
249
                break;
250
        case PHY_SPEED_2P5GIG_FD:
251
                return("2.5 Gbps, full duplex");
252
                break;
253
        case PHY_SPEED_5GIG_FD:
254
                return("5 Gbps, full duplex");
255
                break;
256
        default:
257
                return "unknown (error)";
258
                break;
259
        }
260
}
261
 
262
/*
263
 * uprintf back-end function
264
 */
265
extern void outbyte(char c);
266
void uprintf_backend(void *inst, const char *buf, int len)
267
{
268
        while (len > 0) {
269
                outbyte(*buf++);
270
                len--;
271
        }
272
}
273
 
274
 
275
int main()
276
{
277
 
278
    int res;
279
        struct fw_hdr_ext *fw_hdr_ext_ptr;
280
        u8 fw_maj, fw_min, fw_inc,fw_test;
281
 
282
        /* While running from DDR, enable caches */
283
        Xil_ICacheEnable();
284
        Xil_DCacheEnable();
285
 
286
        /*
287
         * Init uprintf
288
         */
289
        uprintf_init(uprintf_backend, NULL);
290
 
291
        /* Init GPIO based controls */
292
        init_gpio_regs();
293
 
294
        get_bitstream_version(&sys_info.bitRev);
295
 
296
        uprintf("\r\n\r\nXenie Ethernet Test v%d.%d.%d (Microblaze SW)\r\n",
297
                        FWREV_TO_MAJOR(sys_info.fwRev),
298
                        FWREV_TO_MINOR(sys_info.fwRev),
299
                        FWREV_TO_Z(sys_info.fwRev));
300
        uprintf("DFC Design, s.r.o.\r\n");
301
        uprintf("Built: %s, %s\r\n\r\n", build_date, build_time);
302
 
303
        uprintf("Underlying bitstream:\r\n");
304
        uprintf("Version:      %d.%d\r\n", BITREV_TO_MAJOR(sys_info.bitRev.rev),
305
                                                                  BITREV_TO_MINOR(sys_info.bitRev.rev));
306
        uprintf("Target board: %d \r\n", BITREV_TO_TARGET(sys_info.bitRev.rev));
307
        uprintf("Built:        ");
308
        print_bitstream_compile_time(&sys_info.bitRev);
309
        uprintf("\r\n\r\n");
310
 
311
        /* Initialize timers that keep millisecond time */
312
        res = timers_init(&TimerCounterInst, TMRCTR_DEVICE_ID);
313
        if(res != XST_SUCCESS) {
314
                uprintf("Cannot initialize timers\r\n");
315
                goto failure;
316
        }
317
 
318
        /* Initialize IIC driver wrapper */
319
        res = iic_wrap_init(&iic_wrap_dev, IIC_DEVICE_ID);
320
        if(res != XST_SUCCESS) {
321
                uprintf("Cannot initialize IIC driver\r\n");
322
                goto failure;
323
        }
324
 
325
        /*
326
         * Initialize interrupt controller and
327
         * connect handlers of peripherals that require interrupts
328
         * (timers and iic).
329
         */
330
        res = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
331
        if (res != XST_SUCCESS) {
332
                uprintf("Cannot initialize XIntc driver\r\n");
333
                goto failure;
334
        }
335
 
336
        res = XIntc_Connect(&InterruptController, TMRCTR_INTERRUPT_ID,
337
                                   (XInterruptHandler)XTmrCtr_InterruptHandler,(void *)&TimerCounterInst);
338
        if (res != XST_SUCCESS) {
339
                uprintf("Cannot connect timer handler to interrupt controller\r\n");
340
                goto failure;
341
        }
342
 
343
        res = XIntc_Connect(&InterruptController, IIC_INTERRUPT_ID,
344
                                           (XInterruptHandler)XIic_InterruptHandler,(void *)&iic_wrap_dev.iic);
345
        if (res != XST_SUCCESS) {
346
                uprintf("Cannot connect IIC handler to interrupt controller\r\n");
347
                goto failure;
348
        }
349
 
350
        /* Start interrupt controller */
351
        res = XIntc_Start(&InterruptController, XIN_REAL_MODE);
352
        if (res != XST_SUCCESS) {
353
                uprintf("Cannot start XIntc\r\n");
354
                goto failure;
355
        }
356
        /* Enable interrupts */
357
        XIntc_Enable(&InterruptController, TMRCTR_INTERRUPT_ID);
358
        XIntc_Enable(&InterruptController, IIC_INTERRUPT_ID);
359
        /*
360
         * Initialize the exception table.
361
         */
362
        Xil_ExceptionInit();
363
 
364
        /* Register the interrupt controller handler with the exception table. */
365
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
366
                         (Xil_ExceptionHandler)XIntc_InterruptHandler,
367
                         &InterruptController);
368
 
369
        /* Enable exceptions */
370
        Xil_ExceptionEnable();
371
 
372
 
373
 
374
        /* Initialize EEPROM containing UID/MAC address*/
375
        res = iic_id_eeprom_init(&iic_id_eeprom_dev, &iic_wrap_dev, ID_EEPROM_IIC_ADDR,
376
                        IIC_DEFAULT_TIMEOUT_MS);
377
        if (res != XST_SUCCESS) {
378
                uprintf("Cannot initialize IIC EEPROM with UID/MAC address driver\r\n");
379
                goto failure;
380
        }
381
 
382
 
383
        /* Read UID/MAC */
384
        res = iic_id_eeprom_getId(&iic_id_eeprom_dev, sys_info.uid);
385
        if (res) {
386
                uprintf("Cannot read UID/MAC from eeprom.\r\nDefault MAC will be used: ");
387
        } else {
388
                uprintf("UID/MAC address read form EEPROM: ");
389
                memcpy(sys_info.eth_settings.mac, sys_info.uid, 6);
390
        }
391
        print_UID(sys_info.eth_settings.mac);
392
        uprintf("\r\n\r\n");
393
 
394
        /*
395
         * Initialize the SPI driver.
396
         */
397
        res = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
398
        if(res != XST_SUCCESS) {
399
                uprintf("Cannot initialize SPI driver\r\n");
400
                goto failure;
401
        }
402
 
403
        /*
404
         * Setup SPI driver to work with flash
405
         */
406
        res = spansion_flash_init(&sf_dev, &Spi, SPANSION_FLASH_CS);
407
        if(res != XST_SUCCESS) {
408
                goto failure;
409
        }
410
 
411
        /*
412
         * Initialize driver used to read flash in quad mode
413
         */
414
        res = spansion_flash_quad_mode(&sf_dev);
415
        if(res != XST_SUCCESS) {
416
                goto failure;
417
        }
418
 
419
        /*
420
         * Initialize MDIO to speed about 12.5 MHz
421
         */
422
        mdio_dev_ptr = (struct mdio_struct *)MDIO_BASEADDR;
423
        mdio_set_options(mdio_dev_ptr, 3, 1);
424
 
425
 
426
        /* Print version of phy control library that we are about to use */
427
        uprintf("Marvel PHY control library reported this version:\r\n%s\r\n",
428
                        phy_get_version_string());
429
        /*
430
         * Try to init PHY driver and so Marvell API
431
         * If call fails we are either after power cycle
432
         * or something wrong happened to PHY and its reset is
433
         * needed.
434
         */
435
        res = phy_init_drv(&phy_dev_ptr, ETH_PHY_MDIO_ADDR,
436
                        (mdio_read_fcn_type)mdio_read_indirect,
437
                        (mdio_write_fcn_type)mdio_write_indirect_nonblocking,
438
                        (mdio_write_burst_fcn_type)mdio_write_indirect_burst,
439
                        (void *)mdio_dev_ptr);
440
        if(res) {
441
                uprintf("Initialization of Marvell API driver failed"
442
                                "- trying again after PHY reset.\r\n");
443
                phy_reset(phy_dev_ptr);
444
                usleep(500*1000);
445
 
446
                /* try again */
447
                res = phy_init_drv(&phy_dev_ptr, ETH_PHY_MDIO_ADDR,
448
                                (mdio_read_fcn_type)mdio_read_indirect,
449
                                (mdio_write_fcn_type)mdio_write_indirect_nonblocking,
450
                                (mdio_write_burst_fcn_type)mdio_write_indirect_burst,
451
                                (void *)mdio_dev_ptr);
452
                if(res) {
453
                        uprintf("Initialization of Marvell API driver failed.\r\n");
454
                        goto failure;
455
                }
456
        }
457
 
458
        /*
459
         * Check whether PHY is running and what FW revision is being used.
460
         * If already running, skip FW upload to save some time during debugging.
461
         */
462
        if(phy_get_fw_rev(phy_dev_ptr, &fw_maj, &fw_min, &fw_inc, &fw_test)) {
463
                uprintf("Marvell PHY is not running any FW\r\n");
464
        } else {
465
                uprintf("Marvell PHY is currently running FW revision: %d.%d.%d.%d\r\n",
466
                        fw_maj, fw_min, fw_inc, fw_test);
467
        }
468
 
469
        /* When PHY is not running any FW (after reset) it returns all 0 in version*/
470
        if ((fw_maj == 0) & (fw_min == 0) & (fw_inc == 0) & (fw_test == 0)) {
471
                uprintf("Looking for FW in flash\r\n");
472
                /* Find and read basic info about FW */
473
                res = fw_find_in_flash(&sf_dev, FW_HDR_FLASH_OFFSET , &fw_hdr_ext_ptr);
474
                if (res < 0) {
475
                        uprintf("FW was not found at offset 0x%08x\r\n", FW_HDR_FLASH_OFFSET);
476
                        goto failure;
477
                }
478
                uprintf("FW was found:\r\n");
479
                /* Print FW info */
480
                fw_print_info(fw_hdr_ext_ptr);
481
 
482
                uprintf("Reading FW from flash to RAM\r\n");
483
                /* Read FW to memory */
484
                res = fw_read_from_flash(&sf_dev, fw_hdr_ext_ptr);
485
                if(res < 0) {
486
                        uprintf("Cannot read FW from flash\r\n");
487
                        goto failure;
488
                }
489
 
490
                uprintf("Updating FW in PHY\r\n");
491
                /* Write fw to PHY */
492
                if (phy_update_fw(phy_dev_ptr, fw_hdr_ext_ptr->fw_data_ptr,
493
                                        fw_hdr_ext_ptr->fw_hdr.fw_length)) {
494
                        uprintf("FW update failed\r\n");
495
                        goto failure;
496
                }
497
                else
498
                {
499
                        /* if the mtdUpdateRamImage() is successful, call the mtdGetFirmwareVersion()
500
                           to check it running and verify the updated version number */
501
                        sleep(1);
502
                        phy_get_fw_rev(phy_dev_ptr, &fw_maj, &fw_min, &fw_inc, &fw_test);
503
                        uprintf("FW updated successfully\r\n");
504
                        uprintf("Currently running FW revision: %d.%d.%d.%d\r\n",
505
                                                fw_maj, fw_min, fw_inc, fw_test);
506
                }
507
 
508
        } else {
509
                uprintf("PHY is already loaded and running don't reload it\r\n");
510
        }
511
 
512
        /* Configure PHY to RGMII mode compatible with Xilinx RXAUI core */
513
        phy_configure_xilinx_rgmii(phy_dev_ptr);
514
 
515
        /* Reset Xilinx RXAUI core */
516
        rxaui_core_reset();
517
 
518
        /* Change default LED behavior to something meaningful for Xenie baseboard*/
519
        phy_LED_setup(mdio_dev_ptr);
520
 
521
        /* Enable only full-duplex modes as UDP/IP core doesn't support half-duplex */
522
        phy_enable_speeds(phy_dev_ptr,
523
                        PHY_SPEED_10M_FD | PHY_SPEED_100M_FD | PHY_SPEED_1GIG_FD |
524
                        PHY_SPEED_10GIG_FD | PHY_SPEED_2P5GIG_FD | PHY_SPEED_5GIG_FD);
525
 
526
 
527
        /*
528
         * Put UDP/IP core to reset (it is by default anyway)
529
         * Set network information for UDP/IP core.
530
         * Core should be in reset because of CDC is not implemented
531
         * for this interface.
532
         */
533
        udp_ip_core_reset(1);
534
        udpip_core_set_host_info(sys_info.eth_settings.mac,
535
                                          sys_info.eth_settings.ip,
536
                                          sys_info.eth_settings.netmask);
537
 
538
 
539
        uprintf("Initialization successful.\r\n\r\n");
540
        /*
541
         * Periodically check Link speed and change it for throttling
542
         */
543
        while(1) {
544
                uint16_t speed;
545
                int link;
546
 
547
                res = phy_is_baseT_up(phy_dev_ptr, &speed, &link);
548
                if(res) {
549
                        uprintf("Cannot get autonegotioation and link status\r\n");
550
                        sys_info.eth_status.link_up = -1;
551
                        sys_info.eth_status.speed = -1;
552
                } else {
553
                        if(sys_info.eth_status.speed != speed) {
554
                                udp_ip_core_reset(1);
555
                                udpip_core_set_speed(speed);
556
                                uprintf("Current link speed is %s\r\n", phy_speed_to_string(speed));
557
                                udp_ip_core_reset(0);
558
                        }
559
                        if(sys_info.eth_status.link_up != link) {
560
                                uprintf("Link is %s\r\n", (link)?"UP":"DOWN");
561
                        }
562
                        sys_info.eth_status.link_up = link;
563
                        sys_info.eth_status.speed = speed;
564
                }
565
                usleep(100*1000);
566
        }
567
 
568
failure:
569
        while(1) {
570
                uprintf("Initialization failed - restart is needed\r\n");
571
                sleep(1);
572
        }
573
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.