FMF-ART / mbed-dev-lib

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
80:bdf1132a57cf
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:9b334a45a8ff 1 /* MPS2 Peripheral Library
bogdanm 0:9b334a45a8ff 2 *
bogdanm 0:9b334a45a8ff 3 * Copyright (c) 2006-2015 ARM Limited
bogdanm 0:9b334a45a8ff 4 * All rights reserved.
bogdanm 0:9b334a45a8ff 5 *
bogdanm 0:9b334a45a8ff 6 * Redistribution and use in source and binary forms, with or without
bogdanm 0:9b334a45a8ff 7 * modification, are permitted provided that the following conditions are met:
bogdanm 0:9b334a45a8ff 8 *
bogdanm 0:9b334a45a8ff 9 * 1. Redistributions of source code must retain the above copyright notice,
bogdanm 0:9b334a45a8ff 10 * this list of conditions and the following disclaimer.
bogdanm 0:9b334a45a8ff 11 *
bogdanm 0:9b334a45a8ff 12 * 2. Redistributions in binary form must reproduce the above copyright notice,
bogdanm 0:9b334a45a8ff 13 * this list of conditions and the following disclaimer in the documentation
bogdanm 0:9b334a45a8ff 14 * and/or other materials provided with the distribution.
bogdanm 0:9b334a45a8ff 15 *
bogdanm 0:9b334a45a8ff 16 * 3. Neither the name of the copyright holder nor the names of its contributors
bogdanm 0:9b334a45a8ff 17 * may be used to endorse or promote products derived from this software without
bogdanm 0:9b334a45a8ff 18 * specific prior written permission.
bogdanm 0:9b334a45a8ff 19 *
bogdanm 0:9b334a45a8ff 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
bogdanm 0:9b334a45a8ff 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
bogdanm 0:9b334a45a8ff 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
bogdanm 0:9b334a45a8ff 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
bogdanm 0:9b334a45a8ff 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
bogdanm 0:9b334a45a8ff 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
bogdanm 0:9b334a45a8ff 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
bogdanm 0:9b334a45a8ff 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
bogdanm 0:9b334a45a8ff 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
bogdanm 0:9b334a45a8ff 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
bogdanm 0:9b334a45a8ff 30 * POSSIBILITY OF SUCH DAMAGE.
bogdanm 0:9b334a45a8ff 31 */
bogdanm 0:9b334a45a8ff 32
bogdanm 0:9b334a45a8ff 33 /*
bogdanm 0:9b334a45a8ff 34 * Code implementation file for the LAN Ethernet interface.
bogdanm 0:9b334a45a8ff 35 */
bogdanm 0:9b334a45a8ff 36
bogdanm 0:9b334a45a8ff 37 #include <stdio.h>
bogdanm 0:9b334a45a8ff 38
bogdanm 0:9b334a45a8ff 39 #include "ETH_MPS2.h"
bogdanm 0:9b334a45a8ff 40 #include "fpga.h"
bogdanm 0:9b334a45a8ff 41
bogdanm 0:9b334a45a8ff 42 // SMSC9220 low-level operations
bogdanm 0:9b334a45a8ff 43 unsigned int smsc9220_mac_regread(unsigned char regoffset, unsigned int *data)
bogdanm 0:9b334a45a8ff 44 {
bogdanm 0:9b334a45a8ff 45 unsigned int val, maccmd;
bogdanm 0:9b334a45a8ff 46 int timedout;
bogdanm 0:9b334a45a8ff 47 int error;
bogdanm 0:9b334a45a8ff 48
bogdanm 0:9b334a45a8ff 49 error = 0;
bogdanm 0:9b334a45a8ff 50 val = SMSC9220->MAC_CSR_CMD;
bogdanm 0:9b334a45a8ff 51 if(!(val & ((unsigned int)1 << 31))) { // Make sure there's no pending operation
bogdanm 0:9b334a45a8ff 52 maccmd = 0;
bogdanm 0:9b334a45a8ff 53 maccmd |= regoffset;
bogdanm 0:9b334a45a8ff 54 maccmd |= ((unsigned int)1 << 30); // Indicates read
bogdanm 0:9b334a45a8ff 55 maccmd |= ((unsigned int)1 << 31); // Start bit
bogdanm 0:9b334a45a8ff 56 SMSC9220->MAC_CSR_CMD = maccmd; // Start operation
bogdanm 0:9b334a45a8ff 57
bogdanm 0:9b334a45a8ff 58 timedout = 50;
bogdanm 0:9b334a45a8ff 59 do {
bogdanm 0:9b334a45a8ff 60 val = SMSC9220->BYTE_TEST; // A no-op read.
bogdanm 0:9b334a45a8ff 61 Sleepms(1);
bogdanm 0:9b334a45a8ff 62 timedout--;
bogdanm 0:9b334a45a8ff 63 } while(timedout && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31)));
bogdanm 0:9b334a45a8ff 64
bogdanm 0:9b334a45a8ff 65 if(!timedout) {
bogdanm 0:9b334a45a8ff 66 error = 1;
bogdanm 0:9b334a45a8ff 67 }
bogdanm 0:9b334a45a8ff 68 else
bogdanm 0:9b334a45a8ff 69 *data = SMSC9220->MAC_CSR_DATA;
bogdanm 0:9b334a45a8ff 70 } else {
bogdanm 0:9b334a45a8ff 71 *data = 0;
bogdanm 0:9b334a45a8ff 72 }
bogdanm 0:9b334a45a8ff 73 return error;
bogdanm 0:9b334a45a8ff 74 }
bogdanm 0:9b334a45a8ff 75
bogdanm 0:9b334a45a8ff 76 unsigned int smsc9220_mac_regwrite(unsigned char regoffset, unsigned int data)
bogdanm 0:9b334a45a8ff 77 {
bogdanm 0:9b334a45a8ff 78 unsigned int read, maccmd;
bogdanm 0:9b334a45a8ff 79 int timedout;
bogdanm 0:9b334a45a8ff 80 int error;
bogdanm 0:9b334a45a8ff 81
bogdanm 0:9b334a45a8ff 82 error = 0;
bogdanm 0:9b334a45a8ff 83 read = SMSC9220->MAC_CSR_CMD;
bogdanm 0:9b334a45a8ff 84 if(!(read & ((unsigned int)1 << 31))) { // Make sure there's no pending operation
bogdanm 0:9b334a45a8ff 85 SMSC9220->MAC_CSR_DATA = data; // Store data.
bogdanm 0:9b334a45a8ff 86 maccmd = 0;
bogdanm 0:9b334a45a8ff 87 maccmd |= regoffset;
bogdanm 0:9b334a45a8ff 88 maccmd &= ~((unsigned int)1 << 30); // Clear indicates write
bogdanm 0:9b334a45a8ff 89 maccmd |= ((unsigned int)1 << 31); // Indicate start of operation
bogdanm 0:9b334a45a8ff 90 SMSC9220->MAC_CSR_CMD = maccmd;
bogdanm 0:9b334a45a8ff 91
bogdanm 0:9b334a45a8ff 92 timedout = 50;
bogdanm 0:9b334a45a8ff 93 do {
bogdanm 0:9b334a45a8ff 94 read = SMSC9220->BYTE_TEST; // A no-op read.
bogdanm 0:9b334a45a8ff 95 Sleepms(1);
bogdanm 0:9b334a45a8ff 96 timedout--;
bogdanm 0:9b334a45a8ff 97 } while(timedout && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31)));
bogdanm 0:9b334a45a8ff 98
bogdanm 0:9b334a45a8ff 99 if(!timedout) {
bogdanm 0:9b334a45a8ff 100 error = 1;
bogdanm 0:9b334a45a8ff 101 }
bogdanm 0:9b334a45a8ff 102 } else {
bogdanm 0:9b334a45a8ff 103 printf("Warning: SMSC9220 MAC CSR is busy. No data written.\n");
bogdanm 0:9b334a45a8ff 104 }
bogdanm 0:9b334a45a8ff 105 return error;
bogdanm 0:9b334a45a8ff 106 }
bogdanm 0:9b334a45a8ff 107
bogdanm 0:9b334a45a8ff 108 unsigned int smsc9220_phy_regread(unsigned char regoffset, unsigned short *data)
bogdanm 0:9b334a45a8ff 109 {
bogdanm 0:9b334a45a8ff 110 unsigned int val, phycmd; int error;
bogdanm 0:9b334a45a8ff 111 int timedout;
bogdanm 0:9b334a45a8ff 112
bogdanm 0:9b334a45a8ff 113 error = 0;
bogdanm 0:9b334a45a8ff 114
bogdanm 0:9b334a45a8ff 115 smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val);
bogdanm 0:9b334a45a8ff 116
bogdanm 0:9b334a45a8ff 117 if(!(val & 1)) { // Not busy
bogdanm 0:9b334a45a8ff 118 phycmd = 0;
bogdanm 0:9b334a45a8ff 119 phycmd |= (1 << 11); // 1 to [15:11]
bogdanm 0:9b334a45a8ff 120 phycmd |= ((regoffset & 0x1F) << 6); // Put regoffset to [10:6]
bogdanm 0:9b334a45a8ff 121 phycmd &= ~(1 << 1); // Clear [1] indicates read.
bogdanm 0:9b334a45a8ff 122 phycmd |= (1 << 0); // Set [0] indicates operation start
bogdanm 0:9b334a45a8ff 123
bogdanm 0:9b334a45a8ff 124 smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd);
bogdanm 0:9b334a45a8ff 125
bogdanm 0:9b334a45a8ff 126 val = 0;
bogdanm 0:9b334a45a8ff 127 timedout = 50;
bogdanm 0:9b334a45a8ff 128 do {
bogdanm 0:9b334a45a8ff 129 Sleepms(1);
bogdanm 0:9b334a45a8ff 130 timedout--;
bogdanm 0:9b334a45a8ff 131 smsc9220_mac_regread(SMSC9220_MAC_MII_ACC,&val);
bogdanm 0:9b334a45a8ff 132 } while(timedout && (val & ((unsigned int)1 << 0)));
bogdanm 0:9b334a45a8ff 133
bogdanm 0:9b334a45a8ff 134 if(!timedout) {
bogdanm 0:9b334a45a8ff 135 error = 1;
bogdanm 0:9b334a45a8ff 136 }
bogdanm 0:9b334a45a8ff 137 else
bogdanm 0:9b334a45a8ff 138 smsc9220_mac_regread(SMSC9220_MAC_MII_DATA, (unsigned int *)data);
bogdanm 0:9b334a45a8ff 139
bogdanm 0:9b334a45a8ff 140 } else {
bogdanm 0:9b334a45a8ff 141 *data = 0;
bogdanm 0:9b334a45a8ff 142 }
bogdanm 0:9b334a45a8ff 143 return error;
bogdanm 0:9b334a45a8ff 144 }
bogdanm 0:9b334a45a8ff 145
bogdanm 0:9b334a45a8ff 146 unsigned int smsc9220_phy_regwrite(unsigned char regoffset, unsigned short data)
bogdanm 0:9b334a45a8ff 147 {
bogdanm 0:9b334a45a8ff 148 unsigned int val, phycmd; int error;
bogdanm 0:9b334a45a8ff 149 int timedout;
bogdanm 0:9b334a45a8ff 150
bogdanm 0:9b334a45a8ff 151 error = 0;
bogdanm 0:9b334a45a8ff 152
bogdanm 0:9b334a45a8ff 153 smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val);
bogdanm 0:9b334a45a8ff 154
bogdanm 0:9b334a45a8ff 155 if(!(val & 1)) { // Not busy
bogdanm 0:9b334a45a8ff 156 smsc9220_mac_regwrite(SMSC9220_MAC_MII_DATA, (data & 0xFFFF)); // Load the data
bogdanm 0:9b334a45a8ff 157 phycmd = 0;
bogdanm 0:9b334a45a8ff 158 phycmd |= (1 << 11); // 1 to [15:11]
bogdanm 0:9b334a45a8ff 159 phycmd |= ((regoffset & 0x1F) << 6); // Put regoffset to [10:6]
bogdanm 0:9b334a45a8ff 160 phycmd |= (1 << 1); // Set [1] indicates write.
bogdanm 0:9b334a45a8ff 161 phycmd |= (1 << 0); // Set [0] indicates operation start
bogdanm 0:9b334a45a8ff 162 smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd); // Start operation
bogdanm 0:9b334a45a8ff 163
bogdanm 0:9b334a45a8ff 164 phycmd = 0;
bogdanm 0:9b334a45a8ff 165 timedout = 50;
bogdanm 0:9b334a45a8ff 166
bogdanm 0:9b334a45a8ff 167 do {
bogdanm 0:9b334a45a8ff 168
bogdanm 0:9b334a45a8ff 169 Sleepms(1);
bogdanm 0:9b334a45a8ff 170 timedout--;
bogdanm 0:9b334a45a8ff 171 smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &phycmd);
bogdanm 0:9b334a45a8ff 172 } while(timedout && (phycmd & (1 << 0)));
bogdanm 0:9b334a45a8ff 173
bogdanm 0:9b334a45a8ff 174 if(!timedout) {
bogdanm 0:9b334a45a8ff 175 error = 1;
bogdanm 0:9b334a45a8ff 176 }
bogdanm 0:9b334a45a8ff 177
bogdanm 0:9b334a45a8ff 178 } else {
bogdanm 0:9b334a45a8ff 179 printf("Warning: SMSC9220 MAC MII is busy. No data written.\n");
bogdanm 0:9b334a45a8ff 180 }
bogdanm 0:9b334a45a8ff 181 return error;
bogdanm 0:9b334a45a8ff 182 }
bogdanm 0:9b334a45a8ff 183
bogdanm 0:9b334a45a8ff 184 // Returns smsc9220 id.
bogdanm 0:9b334a45a8ff 185 unsigned int smsc9220_read_id(void)
bogdanm 0:9b334a45a8ff 186 {
bogdanm 0:9b334a45a8ff 187 return SMSC9220->ID_REV;
bogdanm 0:9b334a45a8ff 188 }
bogdanm 0:9b334a45a8ff 189
bogdanm 0:9b334a45a8ff 190 // Initiates a soft reset, returns failure or success.
bogdanm 0:9b334a45a8ff 191 unsigned int smsc9220_soft_reset(void)
bogdanm 0:9b334a45a8ff 192 {
bogdanm 0:9b334a45a8ff 193 int timedout;
bogdanm 0:9b334a45a8ff 194
bogdanm 0:9b334a45a8ff 195 timedout = 10;
bogdanm 0:9b334a45a8ff 196 // Soft reset
bogdanm 0:9b334a45a8ff 197 SMSC9220->HW_CFG |= 1;
bogdanm 0:9b334a45a8ff 198
bogdanm 0:9b334a45a8ff 199 do {
bogdanm 0:9b334a45a8ff 200 Sleepms(1);
bogdanm 0:9b334a45a8ff 201 timedout--;
bogdanm 0:9b334a45a8ff 202 } while(timedout && (SMSC9220->HW_CFG & 1));
bogdanm 0:9b334a45a8ff 203
bogdanm 0:9b334a45a8ff 204 if(!timedout)
bogdanm 0:9b334a45a8ff 205 return 1;
bogdanm 0:9b334a45a8ff 206
bogdanm 0:9b334a45a8ff 207 return 0;
bogdanm 0:9b334a45a8ff 208 }
bogdanm 0:9b334a45a8ff 209
bogdanm 0:9b334a45a8ff 210 void smsc9220_set_txfifo(unsigned int val)
bogdanm 0:9b334a45a8ff 211 {
bogdanm 0:9b334a45a8ff 212 // 2kb minimum, 14kb maximum
bogdanm 0:9b334a45a8ff 213 if(val < 2 || val > 14)
bogdanm 0:9b334a45a8ff 214 return;
bogdanm 0:9b334a45a8ff 215
bogdanm 0:9b334a45a8ff 216 SMSC9220->HW_CFG = val << 16;
bogdanm 0:9b334a45a8ff 217 }
bogdanm 0:9b334a45a8ff 218
bogdanm 0:9b334a45a8ff 219
bogdanm 0:9b334a45a8ff 220 unsigned int smsc9220_wait_eeprom(void)
bogdanm 0:9b334a45a8ff 221 {
bogdanm 0:9b334a45a8ff 222 int timedout;
bogdanm 0:9b334a45a8ff 223
bogdanm 0:9b334a45a8ff 224 timedout = 50;
bogdanm 0:9b334a45a8ff 225
bogdanm 0:9b334a45a8ff 226 do {
bogdanm 0:9b334a45a8ff 227 Sleepms(1);
bogdanm 0:9b334a45a8ff 228 timedout--;
bogdanm 0:9b334a45a8ff 229
bogdanm 0:9b334a45a8ff 230 } while(timedout && (SMSC9220->E2P_CMD & ((unsigned int) 1 << 31)));
bogdanm 0:9b334a45a8ff 231
bogdanm 0:9b334a45a8ff 232 if(!timedout)
bogdanm 0:9b334a45a8ff 233 return 1;
bogdanm 0:9b334a45a8ff 234
bogdanm 0:9b334a45a8ff 235 return 0;
bogdanm 0:9b334a45a8ff 236 }
bogdanm 0:9b334a45a8ff 237
bogdanm 0:9b334a45a8ff 238 /* initialise irqs */
bogdanm 0:9b334a45a8ff 239 void smsc9220_init_irqs(void)
bogdanm 0:9b334a45a8ff 240 {
bogdanm 0:9b334a45a8ff 241 SMSC9220->INT_EN = 0x0;
bogdanm 0:9b334a45a8ff 242 SMSC9220->INT_STS = 0xFFFFFFFF; // clear all interrupts
bogdanm 0:9b334a45a8ff 243 SMSC9220->IRQ_CFG = 0x22000100; // irq deassertion at 220 usecs and master IRQ enable.
bogdanm 0:9b334a45a8ff 244 }
bogdanm 0:9b334a45a8ff 245
bogdanm 0:9b334a45a8ff 246 unsigned int smsc9220_check_phy(void)
bogdanm 0:9b334a45a8ff 247 {
bogdanm 0:9b334a45a8ff 248 unsigned short phyid1, phyid2;
bogdanm 0:9b334a45a8ff 249
bogdanm 0:9b334a45a8ff 250 smsc9220_phy_regread(SMSC9220_PHY_ID1,&phyid1);
bogdanm 0:9b334a45a8ff 251 smsc9220_phy_regread(SMSC9220_PHY_ID2,&phyid2);
bogdanm 0:9b334a45a8ff 252 return ((phyid1 == 0xFFFF && phyid2 == 0xFFFF) ||
bogdanm 0:9b334a45a8ff 253 (phyid1 == 0x0 && phyid2 == 0x0));
bogdanm 0:9b334a45a8ff 254 }
bogdanm 0:9b334a45a8ff 255
bogdanm 0:9b334a45a8ff 256 unsigned int smsc9220_reset_phy(void)
bogdanm 0:9b334a45a8ff 257 {
bogdanm 0:9b334a45a8ff 258 unsigned short read;
bogdanm 0:9b334a45a8ff 259 int error;
bogdanm 0:9b334a45a8ff 260
bogdanm 0:9b334a45a8ff 261 error = 0;
bogdanm 0:9b334a45a8ff 262 if(smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &read)) {
bogdanm 0:9b334a45a8ff 263 error = 1;
bogdanm 0:9b334a45a8ff 264 return error;
bogdanm 0:9b334a45a8ff 265 }
bogdanm 0:9b334a45a8ff 266
bogdanm 0:9b334a45a8ff 267 read |= (1 << 15);
bogdanm 0:9b334a45a8ff 268 if(smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, read)) {
bogdanm 0:9b334a45a8ff 269 error = 1;
bogdanm 0:9b334a45a8ff 270 return error;
bogdanm 0:9b334a45a8ff 271 }
bogdanm 0:9b334a45a8ff 272 return 0;
bogdanm 0:9b334a45a8ff 273 }
bogdanm 0:9b334a45a8ff 274
bogdanm 0:9b334a45a8ff 275 /* Advertise all speeds and pause capabilities */
bogdanm 0:9b334a45a8ff 276 void smsc9220_advertise_cap(void)
bogdanm 0:9b334a45a8ff 277 {
bogdanm 0:9b334a45a8ff 278 unsigned short aneg_adv;
bogdanm 0:9b334a45a8ff 279 aneg_adv = 0;
bogdanm 0:9b334a45a8ff 280
bogdanm 0:9b334a45a8ff 281
bogdanm 0:9b334a45a8ff 282 smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv);
bogdanm 0:9b334a45a8ff 283 aneg_adv |= 0xDE0;
bogdanm 0:9b334a45a8ff 284
bogdanm 0:9b334a45a8ff 285 smsc9220_phy_regwrite(SMSC9220_PHY_ANEG_ADV, aneg_adv);
bogdanm 0:9b334a45a8ff 286 smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv);
bogdanm 0:9b334a45a8ff 287 return;
bogdanm 0:9b334a45a8ff 288 }
bogdanm 0:9b334a45a8ff 289
bogdanm 0:9b334a45a8ff 290 void smsc9220_establish_link(void)
bogdanm 0:9b334a45a8ff 291 {
bogdanm 0:9b334a45a8ff 292 unsigned short bcr;
bogdanm 0:9b334a45a8ff 293
bogdanm 0:9b334a45a8ff 294 smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr);
bogdanm 0:9b334a45a8ff 295 bcr |= (1 << 12) | (1 << 9);
bogdanm 0:9b334a45a8ff 296 smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, bcr);
bogdanm 0:9b334a45a8ff 297 smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr);
bogdanm 0:9b334a45a8ff 298
bogdanm 0:9b334a45a8ff 299 {
bogdanm 0:9b334a45a8ff 300 unsigned int hw_cfg;
bogdanm 0:9b334a45a8ff 301
bogdanm 0:9b334a45a8ff 302 hw_cfg = 0;
bogdanm 0:9b334a45a8ff 303 hw_cfg = SMSC9220->HW_CFG;
bogdanm 0:9b334a45a8ff 304
bogdanm 0:9b334a45a8ff 305 hw_cfg &= 0xF0000;
bogdanm 0:9b334a45a8ff 306 hw_cfg |= (1 << 20);
bogdanm 0:9b334a45a8ff 307 SMSC9220->HW_CFG = hw_cfg;
bogdanm 0:9b334a45a8ff 308 }
bogdanm 0:9b334a45a8ff 309
bogdanm 0:9b334a45a8ff 310 return;
bogdanm 0:9b334a45a8ff 311 }
bogdanm 0:9b334a45a8ff 312
bogdanm 0:9b334a45a8ff 313 void smsc9220_enable_xmit(void)
bogdanm 0:9b334a45a8ff 314 {
bogdanm 0:9b334a45a8ff 315 SMSC9220->TX_CFG = 0x2; // Enable trasmission
bogdanm 0:9b334a45a8ff 316 return;
bogdanm 0:9b334a45a8ff 317 }
bogdanm 0:9b334a45a8ff 318
bogdanm 0:9b334a45a8ff 319 void smsc9220_enable_mac_xmit(void)
bogdanm 0:9b334a45a8ff 320 {
bogdanm 0:9b334a45a8ff 321 unsigned int mac_cr;
bogdanm 0:9b334a45a8ff 322
bogdanm 0:9b334a45a8ff 323 mac_cr = 0;
bogdanm 0:9b334a45a8ff 324 smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr);
bogdanm 0:9b334a45a8ff 325
bogdanm 0:9b334a45a8ff 326 mac_cr |= (1 << 3); // xmit enable
bogdanm 0:9b334a45a8ff 327 mac_cr |= (1 << 28); // Heartbeat disable
bogdanm 0:9b334a45a8ff 328
bogdanm 0:9b334a45a8ff 329 smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr);
bogdanm 0:9b334a45a8ff 330 return;
bogdanm 0:9b334a45a8ff 331 }
bogdanm 0:9b334a45a8ff 332
bogdanm 0:9b334a45a8ff 333 void smsc9220_enable_mac_recv(void)
bogdanm 0:9b334a45a8ff 334 {
bogdanm 0:9b334a45a8ff 335 unsigned int mac_cr;
bogdanm 0:9b334a45a8ff 336
bogdanm 0:9b334a45a8ff 337 mac_cr = 0;
bogdanm 0:9b334a45a8ff 338 smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr);
bogdanm 0:9b334a45a8ff 339 mac_cr |= (1 << 2); // Recv enable
bogdanm 0:9b334a45a8ff 340 smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr);
bogdanm 0:9b334a45a8ff 341
bogdanm 0:9b334a45a8ff 342 return;
bogdanm 0:9b334a45a8ff 343 }
bogdanm 0:9b334a45a8ff 344
bogdanm 0:9b334a45a8ff 345
bogdanm 0:9b334a45a8ff 346 unsigned int smsc9220_check_ready(void)
bogdanm 0:9b334a45a8ff 347 {
bogdanm 0:9b334a45a8ff 348 return !(SMSC9220->PMT_CTRL & 1);
bogdanm 0:9b334a45a8ff 349 }
bogdanm 0:9b334a45a8ff 350
bogdanm 0:9b334a45a8ff 351 /* Generate a soft irq */
bogdanm 0:9b334a45a8ff 352 void smsc9220_set_soft_int(void)
bogdanm 0:9b334a45a8ff 353 {
bogdanm 0:9b334a45a8ff 354 SMSC9220->INT_EN |= 0x80000000;
bogdanm 0:9b334a45a8ff 355 }
bogdanm 0:9b334a45a8ff 356
bogdanm 0:9b334a45a8ff 357 /* clear soft irq */
bogdanm 0:9b334a45a8ff 358 void smsc9220_clear_soft_int(void)
bogdanm 0:9b334a45a8ff 359 {
bogdanm 0:9b334a45a8ff 360 SMSC9220->INT_STS |= 0x80000000;
bogdanm 0:9b334a45a8ff 361 }
bogdanm 0:9b334a45a8ff 362
bogdanm 0:9b334a45a8ff 363
bogdanm 0:9b334a45a8ff 364 unsigned int smsc9220_recv_packet(unsigned int *recvbuf, unsigned int *index)
bogdanm 0:9b334a45a8ff 365 {
bogdanm 0:9b334a45a8ff 366 unsigned int rxfifo_inf; // Tells us the status of rx payload and status fifos.
bogdanm 0:9b334a45a8ff 367 unsigned int rxfifo_stat;
bogdanm 0:9b334a45a8ff 368
bogdanm 0:9b334a45a8ff 369 unsigned int pktsize;
bogdanm 0:9b334a45a8ff 370 unsigned int dwords_to_read;
bogdanm 0:9b334a45a8ff 371
bogdanm 0:9b334a45a8ff 372 rxfifo_inf = SMSC9220->RX_FIFO_INF;
bogdanm 0:9b334a45a8ff 373
bogdanm 0:9b334a45a8ff 374 if(rxfifo_inf & 0xFFFF) { // If there's data
bogdanm 0:9b334a45a8ff 375 rxfifo_stat = SMSC9220->RX_STAT_PORT;
bogdanm 0:9b334a45a8ff 376 if(rxfifo_stat != 0) { // Fetch status of this packet
bogdanm 0:9b334a45a8ff 377 pktsize = ((rxfifo_stat >> 16) & 0x3FFF);
bogdanm 0:9b334a45a8ff 378 if(rxfifo_stat & (1 << 15)) {
bogdanm 0:9b334a45a8ff 379 printf("Error occured during receiving of packets on the bus.\n");
bogdanm 0:9b334a45a8ff 380 return 1;
bogdanm 0:9b334a45a8ff 381 } else {
bogdanm 0:9b334a45a8ff 382 /* Below formula (recommended by SMSC9220 code)
bogdanm 0:9b334a45a8ff 383 * gives 1 more than required. This is perhaps because
bogdanm 0:9b334a45a8ff 384 * a last word is needed for not word aligned packets.
bogdanm 0:9b334a45a8ff 385 */
bogdanm 0:9b334a45a8ff 386 dwords_to_read = (pktsize + 3) >> 2;
bogdanm 0:9b334a45a8ff 387 // PIO copy of data received:
bogdanm 0:9b334a45a8ff 388 while(dwords_to_read > 0) {
bogdanm 0:9b334a45a8ff 389 recvbuf[*index] = SMSC9220->RX_DATA_PORT;
bogdanm 0:9b334a45a8ff 390 (*index)++;
bogdanm 0:9b334a45a8ff 391 dwords_to_read--;
bogdanm 0:9b334a45a8ff 392 }
bogdanm 0:9b334a45a8ff 393 }
bogdanm 0:9b334a45a8ff 394 } else {
bogdanm 0:9b334a45a8ff 395 return 1;
bogdanm 0:9b334a45a8ff 396 }
bogdanm 0:9b334a45a8ff 397 } else {
bogdanm 0:9b334a45a8ff 398 return 1;
bogdanm 0:9b334a45a8ff 399 }
bogdanm 0:9b334a45a8ff 400
bogdanm 0:9b334a45a8ff 401 rxfifo_stat = SMSC9220->RX_STAT_PORT;
bogdanm 0:9b334a45a8ff 402 rxfifo_inf = SMSC9220->RX_FIFO_INF;
bogdanm 0:9b334a45a8ff 403
bogdanm 0:9b334a45a8ff 404 return 0;
bogdanm 0:9b334a45a8ff 405 }
bogdanm 0:9b334a45a8ff 406
bogdanm 0:9b334a45a8ff 407
bogdanm 0:9b334a45a8ff 408 // Does the actual transfer of data to FIFO, note it does no
bogdanm 0:9b334a45a8ff 409 // fifo availability checking. This should be done by caller.
bogdanm 0:9b334a45a8ff 410 // Assumes the whole frame is transferred at once as a single segment
bogdanm 0:9b334a45a8ff 411 void smsc9220_xmit_packet(unsigned char * pkt, unsigned int length)
bogdanm 0:9b334a45a8ff 412 {
bogdanm 0:9b334a45a8ff 413 unsigned int txcmd_a, txcmd_b;
bogdanm 0:9b334a45a8ff 414 unsigned int dwords_to_write;
bogdanm 0:9b334a45a8ff 415 volatile unsigned int dwritten;
bogdanm 0:9b334a45a8ff 416 unsigned int *pktptr;
bogdanm 0:9b334a45a8ff 417 volatile unsigned int xmit_stat, xmit_stat2, xmit_inf;
bogdanm 0:9b334a45a8ff 418 int i;
bogdanm 0:9b334a45a8ff 419
bogdanm 0:9b334a45a8ff 420 pktptr = (unsigned int *) pkt;
bogdanm 0:9b334a45a8ff 421 txcmd_a = 0;
bogdanm 0:9b334a45a8ff 422 txcmd_b = 0;
bogdanm 0:9b334a45a8ff 423
bogdanm 0:9b334a45a8ff 424 txcmd_a |= (1 << 12) | (1 << 13); // First and last segments
bogdanm 0:9b334a45a8ff 425 txcmd_a |= length & 0x7FF; // [10:0] contains length
bogdanm 0:9b334a45a8ff 426
bogdanm 0:9b334a45a8ff 427 txcmd_b |= ((length & 0xFFFF) << 16); // [31:16] contains length
bogdanm 0:9b334a45a8ff 428 txcmd_b |= length & 0x7FF; // [10:0] also contains length
bogdanm 0:9b334a45a8ff 429
bogdanm 0:9b334a45a8ff 430
bogdanm 0:9b334a45a8ff 431 SMSC9220->TX_DATA_PORT = txcmd_a;
bogdanm 0:9b334a45a8ff 432 SMSC9220->TX_DATA_PORT = txcmd_b;
bogdanm 0:9b334a45a8ff 433 dwritten = dwords_to_write = (length + 3) >> 2;
bogdanm 0:9b334a45a8ff 434
bogdanm 0:9b334a45a8ff 435 // PIO Copy to FIFO. Could replace this with DMA.
bogdanm 0:9b334a45a8ff 436 while(dwords_to_write > 0) {
bogdanm 0:9b334a45a8ff 437 SMSC9220->TX_DATA_PORT = *pktptr;
bogdanm 0:9b334a45a8ff 438 pktptr++;
bogdanm 0:9b334a45a8ff 439 dwords_to_write--;
bogdanm 0:9b334a45a8ff 440 }
bogdanm 0:9b334a45a8ff 441
bogdanm 0:9b334a45a8ff 442 xmit_stat = SMSC9220->TX_STAT_PORT;
bogdanm 0:9b334a45a8ff 443 xmit_stat2 = SMSC9220->TX_STAT_PORT;
bogdanm 0:9b334a45a8ff 444 xmit_inf = SMSC9220->TX_FIFO_INF;
bogdanm 0:9b334a45a8ff 445
bogdanm 0:9b334a45a8ff 446 if(xmit_stat2 != 0 ) {
bogdanm 0:9b334a45a8ff 447 for(i = 0; i < 6; i++) {
bogdanm 0:9b334a45a8ff 448 xmit_stat2 = SMSC9220->TX_STAT_PORT;
bogdanm 0:9b334a45a8ff 449 }
bogdanm 0:9b334a45a8ff 450 }
bogdanm 0:9b334a45a8ff 451 }