| 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 |  |  | }
 |