tsec.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. * tsec.c
  3. * Freescale Three Speed Ethernet Controller driver
  4. *
  5. * This software may be used and distributed according to the
  6. * terms of the GNU Public License, Version 2, incorporated
  7. * herein by reference.
  8. *
  9. * Copyright 2004 Freescale Semiconductor.
  10. * (C) Copyright 2003, Motorola, Inc.
  11. * author Andy Fleming
  12. *
  13. */
  14. #include <config.h>
  15. #include <mpc85xx.h>
  16. #include <mpc86xx.h>
  17. #include <common.h>
  18. #include <malloc.h>
  19. #include <net.h>
  20. #include <command.h>
  21. #if defined(CONFIG_TSEC_ENET)
  22. #include "tsec.h"
  23. #include "miiphy.h"
  24. DECLARE_GLOBAL_DATA_PTR;
  25. #define TX_BUF_CNT 2
  26. static uint rxIdx; /* index of the current RX buffer */
  27. static uint txIdx; /* index of the current TX buffer */
  28. typedef volatile struct rtxbd {
  29. txbd8_t txbd[TX_BUF_CNT];
  30. rxbd8_t rxbd[PKTBUFSRX];
  31. } RTXBD;
  32. struct tsec_info_struct {
  33. unsigned int phyaddr;
  34. u32 flags;
  35. unsigned int phyregidx;
  36. };
  37. /* The tsec_info structure contains 3 values which the
  38. * driver uses to determine how to operate a given ethernet
  39. * device. For now, the structure is initialized with the
  40. * knowledge that all current implementations have 2 TSEC
  41. * devices, and one FEC. The information needed is:
  42. * phyaddr - The address of the PHY which is attached to
  43. * the given device.
  44. *
  45. * flags - This variable indicates whether the device
  46. * supports gigabit speed ethernet, and whether it should be
  47. * in reduced mode.
  48. *
  49. * phyregidx - This variable specifies which ethernet device
  50. * controls the MII Management registers which are connected
  51. * to the PHY. For 8540/8560, only TSEC1 (index 0) has
  52. * access to the PHYs, so all of the entries have "0".
  53. *
  54. * The values specified in the table are taken from the board's
  55. * config file in include/configs/. When implementing a new
  56. * board with ethernet capability, it is necessary to define:
  57. * TSEC1_PHY_ADDR
  58. * TSEC1_PHYIDX
  59. * TSEC2_PHY_ADDR
  60. * TSEC2_PHYIDX
  61. *
  62. * and for 8560:
  63. * FEC_PHY_ADDR
  64. * FEC_PHYIDX
  65. */
  66. static struct tsec_info_struct tsec_info[] = {
  67. #if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1)
  68. {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
  69. #elif defined(CONFIG_MPC86XX_TSEC1)
  70. {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX},
  71. #else
  72. { 0, 0, 0},
  73. #endif
  74. #if defined(CONFIG_MPC85XX_TSEC2) || defined(CONFIG_MPC83XX_TSEC2)
  75. {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
  76. #elif defined(CONFIG_MPC86XX_TSEC2)
  77. {TSEC2_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC2_PHYIDX},
  78. #else
  79. { 0, 0, 0},
  80. #endif
  81. #ifdef CONFIG_MPC85XX_FEC
  82. {FEC_PHY_ADDR, 0, FEC_PHYIDX},
  83. #else
  84. #if defined(CONFIG_MPC85XX_TSEC3) || defined(CONFIG_MPC83XX_TSEC3) || defined(CONFIG_MPC86XX_TSEC3)
  85. {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
  86. #else
  87. { 0, 0, 0},
  88. #endif
  89. #if defined(CONFIG_MPC85XX_TSEC4) || defined(CONFIG_MPC83XX_TSEC4)
  90. {TSEC4_PHY_ADDR, TSEC_REDUCED, TSEC4_PHYIDX},
  91. #elif defined(CONFIG_MPC86XX_TSEC4)
  92. {TSEC4_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC4_PHYIDX},
  93. #else
  94. { 0, 0, 0},
  95. #endif
  96. #endif
  97. };
  98. #define MAXCONTROLLERS (4)
  99. static int relocated = 0;
  100. static struct tsec_private *privlist[MAXCONTROLLERS];
  101. #ifdef __GNUC__
  102. static RTXBD rtx __attribute__ ((aligned(8)));
  103. #else
  104. #error "rtx must be 64-bit aligned"
  105. #endif
  106. static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
  107. static int tsec_recv(struct eth_device* dev);
  108. static int tsec_init(struct eth_device* dev, bd_t * bd);
  109. static void tsec_halt(struct eth_device* dev);
  110. static void init_registers(volatile tsec_t *regs);
  111. static void startup_tsec(struct eth_device *dev);
  112. static int init_phy(struct eth_device *dev);
  113. void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
  114. uint read_phy_reg(struct tsec_private *priv, uint regnum);
  115. struct phy_info * get_phy_info(struct eth_device *dev);
  116. void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
  117. static void adjust_link(struct eth_device *dev);
  118. static void relocate_cmds(void);
  119. static int tsec_miiphy_write(char *devname, unsigned char addr,
  120. unsigned char reg, unsigned short value);
  121. static int tsec_miiphy_read(char *devname, unsigned char addr,
  122. unsigned char reg, unsigned short *value);
  123. /* Initialize device structure. Returns success if PHY
  124. * initialization succeeded (i.e. if it recognizes the PHY)
  125. */
  126. int tsec_initialize(bd_t *bis, int index, char *devname)
  127. {
  128. struct eth_device* dev;
  129. int i;
  130. struct tsec_private *priv;
  131. dev = (struct eth_device*) malloc(sizeof *dev);
  132. if(NULL == dev)
  133. return 0;
  134. memset(dev, 0, sizeof *dev);
  135. priv = (struct tsec_private *) malloc(sizeof(*priv));
  136. if(NULL == priv)
  137. return 0;
  138. privlist[index] = priv;
  139. priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
  140. priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
  141. tsec_info[index].phyregidx*TSEC_SIZE);
  142. priv->phyaddr = tsec_info[index].phyaddr;
  143. priv->flags = tsec_info[index].flags;
  144. sprintf(dev->name, devname);
  145. dev->iobase = 0;
  146. dev->priv = priv;
  147. dev->init = tsec_init;
  148. dev->halt = tsec_halt;
  149. dev->send = tsec_send;
  150. dev->recv = tsec_recv;
  151. /* Tell u-boot to get the addr from the env */
  152. for(i=0;i<6;i++)
  153. dev->enetaddr[i] = 0;
  154. eth_register(dev);
  155. /* Reset the MAC */
  156. priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
  157. priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
  158. #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
  159. && !defined(BITBANGMII)
  160. miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
  161. #endif
  162. /* Try to initialize PHY here, and return */
  163. return init_phy(dev);
  164. }
  165. /* Initializes data structures and registers for the controller,
  166. * and brings the interface up. Returns the link status, meaning
  167. * that it returns success if the link is up, failure otherwise.
  168. * This allows u-boot to find the first active controller. */
  169. int tsec_init(struct eth_device* dev, bd_t * bd)
  170. {
  171. uint tempval;
  172. char tmpbuf[MAC_ADDR_LEN];
  173. int i;
  174. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  175. volatile tsec_t *regs = priv->regs;
  176. /* Make sure the controller is stopped */
  177. tsec_halt(dev);
  178. /* Init MACCFG2. Defaults to GMII */
  179. regs->maccfg2 = MACCFG2_INIT_SETTINGS;
  180. /* Init ECNTRL */
  181. regs->ecntrl = ECNTRL_INIT_SETTINGS;
  182. /* Copy the station address into the address registers.
  183. * Backwards, because little endian MACS are dumb */
  184. for(i=0;i<MAC_ADDR_LEN;i++) {
  185. tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
  186. }
  187. regs->macstnaddr1 = *((uint *)(tmpbuf));
  188. tempval = *((uint *)(tmpbuf +4));
  189. regs->macstnaddr2 = tempval;
  190. /* reset the indices to zero */
  191. rxIdx = 0;
  192. txIdx = 0;
  193. /* Clear out (for the most part) the other registers */
  194. init_registers(regs);
  195. /* Ready the device for tx/rx */
  196. startup_tsec(dev);
  197. /* If there's no link, fail */
  198. return priv->link;
  199. }
  200. /* Write value to the device's PHY through the registers
  201. * specified in priv, modifying the register specified in regnum.
  202. * It will wait for the write to be done (or for a timeout to
  203. * expire) before exiting
  204. */
  205. void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
  206. {
  207. volatile tsec_t *regbase = priv->phyregs;
  208. uint phyid = priv->phyaddr;
  209. int timeout=1000000;
  210. regbase->miimadd = (phyid << 8) | regnum;
  211. regbase->miimcon = value;
  212. asm("sync");
  213. timeout=1000000;
  214. while((regbase->miimind & MIIMIND_BUSY) && timeout--);
  215. }
  216. /* Reads register regnum on the device's PHY through the
  217. * registers specified in priv. It lowers and raises the read
  218. * command, and waits for the data to become valid (miimind
  219. * notvalid bit cleared), and the bus to cease activity (miimind
  220. * busy bit cleared), and then returns the value
  221. */
  222. uint read_phy_reg(struct tsec_private *priv, uint regnum)
  223. {
  224. uint value;
  225. volatile tsec_t *regbase = priv->phyregs;
  226. uint phyid = priv->phyaddr;
  227. /* Put the address of the phy, and the register
  228. * number into MIIMADD */
  229. regbase->miimadd = (phyid << 8) | regnum;
  230. /* Clear the command register, and wait */
  231. regbase->miimcom = 0;
  232. asm("sync");
  233. /* Initiate a read command, and wait */
  234. regbase->miimcom = MIIM_READ_COMMAND;
  235. asm("sync");
  236. /* Wait for the the indication that the read is done */
  237. while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
  238. /* Grab the value read from the PHY */
  239. value = regbase->miimstat;
  240. return value;
  241. }
  242. /* Discover which PHY is attached to the device, and configure it
  243. * properly. If the PHY is not recognized, then return 0
  244. * (failure). Otherwise, return 1
  245. */
  246. static int init_phy(struct eth_device *dev)
  247. {
  248. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  249. struct phy_info *curphy;
  250. /* Assign a Physical address to the TBI */
  251. {
  252. volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
  253. regs->tbipa = TBIPA_VALUE;
  254. regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
  255. regs->tbipa = TBIPA_VALUE;
  256. asm("sync");
  257. }
  258. /* Reset MII (due to new addresses) */
  259. priv->phyregs->miimcfg = MIIMCFG_RESET;
  260. asm("sync");
  261. priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
  262. asm("sync");
  263. while(priv->phyregs->miimind & MIIMIND_BUSY);
  264. if(0 == relocated)
  265. relocate_cmds();
  266. /* Get the cmd structure corresponding to the attached
  267. * PHY */
  268. curphy = get_phy_info(dev);
  269. if(NULL == curphy) {
  270. printf("%s: No PHY found\n", dev->name);
  271. return 0;
  272. }
  273. priv->phyinfo = curphy;
  274. phy_run_commands(priv, priv->phyinfo->config);
  275. return 1;
  276. }
  277. /* Returns which value to write to the control register. */
  278. /* For 10/100, the value is slightly different */
  279. uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
  280. {
  281. if(priv->flags & TSEC_GIGABIT)
  282. return MIIM_CONTROL_INIT;
  283. else
  284. return MIIM_CR_INIT;
  285. }
  286. /* Parse the status register for link, and then do
  287. * auto-negotiation */
  288. uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
  289. {
  290. /*
  291. * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
  292. */
  293. mii_reg = read_phy_reg(priv, MIIM_STATUS);
  294. if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
  295. int i = 0;
  296. puts ("Waiting for PHY auto negotiation to complete");
  297. while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
  298. /*
  299. * Timeout reached ?
  300. */
  301. if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
  302. puts (" TIMEOUT !\n");
  303. priv->link = 0;
  304. return 0;
  305. }
  306. if ((i++ % 1000) == 0) {
  307. putc ('.');
  308. }
  309. udelay (1000); /* 1 ms */
  310. mii_reg = read_phy_reg(priv, MIIM_STATUS);
  311. }
  312. puts (" done\n");
  313. priv->link = 1;
  314. udelay (500000); /* another 500 ms (results in faster booting) */
  315. } else {
  316. priv->link = 1;
  317. }
  318. return 0;
  319. }
  320. /* Parse the 88E1011's status register for speed and duplex
  321. * information */
  322. uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
  323. {
  324. uint speed;
  325. mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
  326. if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
  327. (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
  328. int i = 0;
  329. puts ("Waiting for PHY realtime link");
  330. while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
  331. (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
  332. /*
  333. * Timeout reached ?
  334. */
  335. if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
  336. puts (" TIMEOUT !\n");
  337. priv->link = 0;
  338. break;
  339. }
  340. if ((i++ % 1000) == 0) {
  341. putc ('.');
  342. }
  343. udelay (1000); /* 1 ms */
  344. mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
  345. }
  346. puts (" done\n");
  347. udelay (500000); /* another 500 ms (results in faster booting) */
  348. }
  349. if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
  350. priv->duplexity = 1;
  351. else
  352. priv->duplexity = 0;
  353. speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
  354. switch(speed) {
  355. case MIIM_88E1011_PHYSTAT_GBIT:
  356. priv->speed = 1000;
  357. break;
  358. case MIIM_88E1011_PHYSTAT_100:
  359. priv->speed = 100;
  360. break;
  361. default:
  362. priv->speed = 10;
  363. }
  364. return 0;
  365. }
  366. /* Parse the cis8201's status register for speed and duplex
  367. * information */
  368. uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
  369. {
  370. uint speed;
  371. if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
  372. priv->duplexity = 1;
  373. else
  374. priv->duplexity = 0;
  375. speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
  376. switch(speed) {
  377. case MIIM_CIS8201_AUXCONSTAT_GBIT:
  378. priv->speed = 1000;
  379. break;
  380. case MIIM_CIS8201_AUXCONSTAT_100:
  381. priv->speed = 100;
  382. break;
  383. default:
  384. priv->speed = 10;
  385. break;
  386. }
  387. return 0;
  388. }
  389. /* Parse the vsc8244's status register for speed and duplex
  390. * information */
  391. uint mii_parse_vsc8244(uint mii_reg, struct tsec_private *priv)
  392. {
  393. uint speed;
  394. if(mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
  395. priv->duplexity = 1;
  396. else
  397. priv->duplexity = 0;
  398. speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
  399. switch(speed) {
  400. case MIIM_VSC8244_AUXCONSTAT_GBIT:
  401. priv->speed = 1000;
  402. break;
  403. case MIIM_VSC8244_AUXCONSTAT_100:
  404. priv->speed = 100;
  405. break;
  406. default:
  407. priv->speed = 10;
  408. break;
  409. }
  410. return 0;
  411. }
  412. /* Parse the DM9161's status register for speed and duplex
  413. * information */
  414. uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
  415. {
  416. if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
  417. priv->speed = 100;
  418. else
  419. priv->speed = 10;
  420. if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
  421. priv->duplexity = 1;
  422. else
  423. priv->duplexity = 0;
  424. return 0;
  425. }
  426. /* Hack to write all 4 PHYs with the LED values */
  427. uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
  428. {
  429. uint phyid;
  430. volatile tsec_t *regbase = priv->phyregs;
  431. int timeout=1000000;
  432. for(phyid=0;phyid<4;phyid++) {
  433. regbase->miimadd = (phyid << 8) | mii_reg;
  434. regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
  435. asm("sync");
  436. timeout=1000000;
  437. while((regbase->miimind & MIIMIND_BUSY) && timeout--);
  438. }
  439. return MIIM_CIS8204_SLEDCON_INIT;
  440. }
  441. uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
  442. {
  443. if (priv->flags & TSEC_REDUCED)
  444. return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
  445. else
  446. return MIIM_CIS8204_EPHYCON_INIT;
  447. }
  448. /* Initialized required registers to appropriate values, zeroing
  449. * those we don't care about (unless zero is bad, in which case,
  450. * choose a more appropriate value) */
  451. static void init_registers(volatile tsec_t *regs)
  452. {
  453. /* Clear IEVENT */
  454. regs->ievent = IEVENT_INIT_CLEAR;
  455. regs->imask = IMASK_INIT_CLEAR;
  456. regs->hash.iaddr0 = 0;
  457. regs->hash.iaddr1 = 0;
  458. regs->hash.iaddr2 = 0;
  459. regs->hash.iaddr3 = 0;
  460. regs->hash.iaddr4 = 0;
  461. regs->hash.iaddr5 = 0;
  462. regs->hash.iaddr6 = 0;
  463. regs->hash.iaddr7 = 0;
  464. regs->hash.gaddr0 = 0;
  465. regs->hash.gaddr1 = 0;
  466. regs->hash.gaddr2 = 0;
  467. regs->hash.gaddr3 = 0;
  468. regs->hash.gaddr4 = 0;
  469. regs->hash.gaddr5 = 0;
  470. regs->hash.gaddr6 = 0;
  471. regs->hash.gaddr7 = 0;
  472. regs->rctrl = 0x00000000;
  473. /* Init RMON mib registers */
  474. memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
  475. regs->rmon.cam1 = 0xffffffff;
  476. regs->rmon.cam2 = 0xffffffff;
  477. regs->mrblr = MRBLR_INIT_SETTINGS;
  478. regs->minflr = MINFLR_INIT_SETTINGS;
  479. regs->attr = ATTR_INIT_SETTINGS;
  480. regs->attreli = ATTRELI_INIT_SETTINGS;
  481. }
  482. /* Configure maccfg2 based on negotiated speed and duplex
  483. * reported by PHY handling code */
  484. static void adjust_link(struct eth_device *dev)
  485. {
  486. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  487. volatile tsec_t *regs = priv->regs;
  488. if(priv->link) {
  489. if(priv->duplexity != 0)
  490. regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
  491. else
  492. regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
  493. switch(priv->speed) {
  494. case 1000:
  495. regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
  496. | MACCFG2_GMII);
  497. break;
  498. case 100:
  499. case 10:
  500. regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
  501. | MACCFG2_MII);
  502. /* If We're in reduced mode, we need
  503. * to say whether we're 10 or 100 MB.
  504. */
  505. if ((priv->speed == 100)
  506. && (priv->flags & TSEC_REDUCED))
  507. regs->ecntrl |= ECNTRL_R100;
  508. else
  509. regs->ecntrl &= ~(ECNTRL_R100);
  510. break;
  511. default:
  512. printf("%s: Speed was bad\n", dev->name);
  513. break;
  514. }
  515. printf("Speed: %d, %s duplex\n", priv->speed,
  516. (priv->duplexity) ? "full" : "half");
  517. } else {
  518. printf("%s: No link.\n", dev->name);
  519. }
  520. }
  521. /* Set up the buffers and their descriptors, and bring up the
  522. * interface */
  523. static void startup_tsec(struct eth_device *dev)
  524. {
  525. int i;
  526. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  527. volatile tsec_t *regs = priv->regs;
  528. /* Point to the buffer descriptors */
  529. regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
  530. regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
  531. /* Initialize the Rx Buffer descriptors */
  532. for (i = 0; i < PKTBUFSRX; i++) {
  533. rtx.rxbd[i].status = RXBD_EMPTY;
  534. rtx.rxbd[i].length = 0;
  535. rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
  536. }
  537. rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
  538. /* Initialize the TX Buffer Descriptors */
  539. for(i=0; i<TX_BUF_CNT; i++) {
  540. rtx.txbd[i].status = 0;
  541. rtx.txbd[i].length = 0;
  542. rtx.txbd[i].bufPtr = 0;
  543. }
  544. rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
  545. /* Start up the PHY */
  546. phy_run_commands(priv, priv->phyinfo->startup);
  547. adjust_link(dev);
  548. /* Enable Transmit and Receive */
  549. regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
  550. /* Tell the DMA it is clear to go */
  551. regs->dmactrl |= DMACTRL_INIT_SETTINGS;
  552. regs->tstat = TSTAT_CLEAR_THALT;
  553. regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
  554. }
  555. /* This returns the status bits of the device. The return value
  556. * is never checked, and this is what the 8260 driver did, so we
  557. * do the same. Presumably, this would be zero if there were no
  558. * errors */
  559. static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
  560. {
  561. int i;
  562. int result = 0;
  563. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  564. volatile tsec_t *regs = priv->regs;
  565. /* Find an empty buffer descriptor */
  566. for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
  567. if (i >= TOUT_LOOP) {
  568. debug ("%s: tsec: tx buffers full\n", dev->name);
  569. return result;
  570. }
  571. }
  572. rtx.txbd[txIdx].bufPtr = (uint)packet;
  573. rtx.txbd[txIdx].length = length;
  574. rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
  575. /* Tell the DMA to go */
  576. regs->tstat = TSTAT_CLEAR_THALT;
  577. /* Wait for buffer to be transmitted */
  578. for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
  579. if (i >= TOUT_LOOP) {
  580. debug ("%s: tsec: tx error\n", dev->name);
  581. return result;
  582. }
  583. }
  584. txIdx = (txIdx + 1) % TX_BUF_CNT;
  585. result = rtx.txbd[txIdx].status & TXBD_STATS;
  586. return result;
  587. }
  588. static int tsec_recv(struct eth_device* dev)
  589. {
  590. int length;
  591. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  592. volatile tsec_t *regs = priv->regs;
  593. while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
  594. length = rtx.rxbd[rxIdx].length;
  595. /* Send the packet up if there were no errors */
  596. if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
  597. NetReceive(NetRxPackets[rxIdx], length - 4);
  598. } else {
  599. printf("Got error %x\n",
  600. (rtx.rxbd[rxIdx].status & RXBD_STATS));
  601. }
  602. rtx.rxbd[rxIdx].length = 0;
  603. /* Set the wrap bit if this is the last element in the list */
  604. rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
  605. rxIdx = (rxIdx + 1) % PKTBUFSRX;
  606. }
  607. if(regs->ievent&IEVENT_BSY) {
  608. regs->ievent = IEVENT_BSY;
  609. regs->rstat = RSTAT_CLEAR_RHALT;
  610. }
  611. return -1;
  612. }
  613. /* Stop the interface */
  614. static void tsec_halt(struct eth_device* dev)
  615. {
  616. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  617. volatile tsec_t *regs = priv->regs;
  618. regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
  619. regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
  620. while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
  621. regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
  622. /* Shut down the PHY, as needed */
  623. phy_run_commands(priv, priv->phyinfo->shutdown);
  624. }
  625. struct phy_info phy_info_M88E1011S = {
  626. 0x01410c6,
  627. "Marvell 88E1011S",
  628. 4,
  629. (struct phy_cmd[]) { /* config */
  630. /* Reset and configure the PHY */
  631. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  632. {0x1d, 0x1f, NULL},
  633. {0x1e, 0x200c, NULL},
  634. {0x1d, 0x5, NULL},
  635. {0x1e, 0x0, NULL},
  636. {0x1e, 0x100, NULL},
  637. {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
  638. {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
  639. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  640. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  641. {miim_end,}
  642. },
  643. (struct phy_cmd[]) { /* startup */
  644. /* Status is read once to clear old link state */
  645. {MIIM_STATUS, miim_read, NULL},
  646. /* Auto-negotiate */
  647. {MIIM_STATUS, miim_read, &mii_parse_sr},
  648. /* Read the status */
  649. {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
  650. {miim_end,}
  651. },
  652. (struct phy_cmd[]) { /* shutdown */
  653. {miim_end,}
  654. },
  655. };
  656. struct phy_info phy_info_M88E1111S = {
  657. 0x01410cc,
  658. "Marvell 88E1111S",
  659. 4,
  660. (struct phy_cmd[]) { /* config */
  661. /* Reset and configure the PHY */
  662. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  663. {0x1d, 0x1f, NULL},
  664. {0x1e, 0x200c, NULL},
  665. {0x1d, 0x5, NULL},
  666. {0x1e, 0x0, NULL},
  667. {0x1e, 0x100, NULL},
  668. {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
  669. {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
  670. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  671. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  672. {miim_end,}
  673. },
  674. (struct phy_cmd[]) { /* startup */
  675. /* Status is read once to clear old link state */
  676. {MIIM_STATUS, miim_read, NULL},
  677. /* Auto-negotiate */
  678. {MIIM_STATUS, miim_read, &mii_parse_sr},
  679. /* Read the status */
  680. {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
  681. {miim_end,}
  682. },
  683. (struct phy_cmd[]) { /* shutdown */
  684. {miim_end,}
  685. },
  686. };
  687. struct phy_info phy_info_cis8204 = {
  688. 0x3f11,
  689. "Cicada Cis8204",
  690. 6,
  691. (struct phy_cmd[]) { /* config */
  692. /* Override PHY config settings */
  693. {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
  694. /* Configure some basic stuff */
  695. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  696. {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
  697. {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
  698. {miim_end,}
  699. },
  700. (struct phy_cmd[]) { /* startup */
  701. /* Read the Status (2x to make sure link is right) */
  702. {MIIM_STATUS, miim_read, NULL},
  703. /* Auto-negotiate */
  704. {MIIM_STATUS, miim_read, &mii_parse_sr},
  705. /* Read the status */
  706. {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
  707. {miim_end,}
  708. },
  709. (struct phy_cmd[]) { /* shutdown */
  710. {miim_end,}
  711. },
  712. };
  713. /* Cicada 8201 */
  714. struct phy_info phy_info_cis8201 = {
  715. 0xfc41,
  716. "CIS8201",
  717. 4,
  718. (struct phy_cmd[]) { /* config */
  719. /* Override PHY config settings */
  720. {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
  721. /* Set up the interface mode */
  722. {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
  723. /* Configure some basic stuff */
  724. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  725. {miim_end,}
  726. },
  727. (struct phy_cmd[]) { /* startup */
  728. /* Read the Status (2x to make sure link is right) */
  729. {MIIM_STATUS, miim_read, NULL},
  730. /* Auto-negotiate */
  731. {MIIM_STATUS, miim_read, &mii_parse_sr},
  732. /* Read the status */
  733. {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
  734. {miim_end,}
  735. },
  736. (struct phy_cmd[]) { /* shutdown */
  737. {miim_end,}
  738. },
  739. };
  740. struct phy_info phy_info_VSC8244 = {
  741. 0x3f1b,
  742. "Vitesse VSC8244",
  743. 6,
  744. (struct phy_cmd[]) { /* config */
  745. /* Override PHY config settings */
  746. /* Configure some basic stuff */
  747. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  748. {miim_end,}
  749. },
  750. (struct phy_cmd[]) { /* startup */
  751. /* Read the Status (2x to make sure link is right) */
  752. {MIIM_STATUS, miim_read, NULL},
  753. /* Auto-negotiate */
  754. {MIIM_STATUS, miim_read, &mii_parse_sr},
  755. /* Read the status */
  756. {MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
  757. {miim_end,}
  758. },
  759. (struct phy_cmd[]) { /* shutdown */
  760. {miim_end,}
  761. },
  762. };
  763. struct phy_info phy_info_dm9161 = {
  764. 0x0181b88,
  765. "Davicom DM9161E",
  766. 4,
  767. (struct phy_cmd[]) { /* config */
  768. {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
  769. /* Do not bypass the scrambler/descrambler */
  770. {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
  771. /* Clear 10BTCSR to default */
  772. {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
  773. /* Configure some basic stuff */
  774. {MIIM_CONTROL, MIIM_CR_INIT, NULL},
  775. /* Restart Auto Negotiation */
  776. {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
  777. {miim_end,}
  778. },
  779. (struct phy_cmd[]) { /* startup */
  780. /* Status is read once to clear old link state */
  781. {MIIM_STATUS, miim_read, NULL},
  782. /* Auto-negotiate */
  783. {MIIM_STATUS, miim_read, &mii_parse_sr},
  784. /* Read the status */
  785. {MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
  786. {miim_end,}
  787. },
  788. (struct phy_cmd[]) { /* shutdown */
  789. {miim_end,}
  790. },
  791. };
  792. uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
  793. {
  794. unsigned int speed;
  795. if (priv->link) {
  796. speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
  797. switch (speed) {
  798. case MIIM_LXT971_SR2_10HDX:
  799. priv->speed = 10;
  800. priv->duplexity = 0;
  801. break;
  802. case MIIM_LXT971_SR2_10FDX:
  803. priv->speed = 10;
  804. priv->duplexity = 1;
  805. break;
  806. case MIIM_LXT971_SR2_100HDX:
  807. priv->speed = 100;
  808. priv->duplexity = 0;
  809. default:
  810. priv->speed = 100;
  811. priv->duplexity = 1;
  812. break;
  813. }
  814. } else {
  815. priv->speed = 0;
  816. priv->duplexity = 0;
  817. }
  818. return 0;
  819. }
  820. static struct phy_info phy_info_lxt971 = {
  821. 0x0001378e,
  822. "LXT971",
  823. 4,
  824. (struct phy_cmd []) { /* config */
  825. { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
  826. { miim_end, }
  827. },
  828. (struct phy_cmd []) { /* startup - enable interrupts */
  829. /* { 0x12, 0x00f2, NULL }, */
  830. { MIIM_STATUS, miim_read, NULL },
  831. { MIIM_STATUS, miim_read, &mii_parse_sr },
  832. { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
  833. { miim_end, }
  834. },
  835. (struct phy_cmd []) { /* shutdown - disable interrupts */
  836. { miim_end, }
  837. },
  838. };
  839. /* Parse the DP83865's link and auto-neg status register for speed and duplex
  840. * information */
  841. uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
  842. {
  843. switch (mii_reg & MIIM_DP83865_SPD_MASK) {
  844. case MIIM_DP83865_SPD_1000:
  845. priv->speed = 1000;
  846. break;
  847. case MIIM_DP83865_SPD_100:
  848. priv->speed = 100;
  849. break;
  850. default:
  851. priv->speed = 10;
  852. break;
  853. }
  854. if (mii_reg & MIIM_DP83865_DPX_FULL)
  855. priv->duplexity = 1;
  856. else
  857. priv->duplexity = 0;
  858. return 0;
  859. }
  860. struct phy_info phy_info_dp83865 = {
  861. 0x20005c7,
  862. "NatSemi DP83865",
  863. 4,
  864. (struct phy_cmd[]) { /* config */
  865. {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
  866. {miim_end,}
  867. },
  868. (struct phy_cmd[]) { /* startup */
  869. /* Status is read once to clear old link state */
  870. {MIIM_STATUS, miim_read, NULL},
  871. /* Auto-negotiate */
  872. {MIIM_STATUS, miim_read, &mii_parse_sr},
  873. /* Read the link and auto-neg status */
  874. {MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr},
  875. {miim_end,}
  876. },
  877. (struct phy_cmd[]) { /* shutdown */
  878. {miim_end,}
  879. },
  880. };
  881. struct phy_info *phy_info[] = {
  882. #if 0
  883. &phy_info_cis8201,
  884. #endif
  885. &phy_info_cis8204,
  886. &phy_info_M88E1011S,
  887. &phy_info_M88E1111S,
  888. &phy_info_dm9161,
  889. &phy_info_lxt971,
  890. &phy_info_VSC8244,
  891. &phy_info_dp83865,
  892. NULL
  893. };
  894. /* Grab the identifier of the device's PHY, and search through
  895. * all of the known PHYs to see if one matches. If so, return
  896. * it, if not, return NULL */
  897. struct phy_info * get_phy_info(struct eth_device *dev)
  898. {
  899. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  900. uint phy_reg, phy_ID;
  901. int i;
  902. struct phy_info *theInfo = NULL;
  903. /* Grab the bits from PHYIR1, and put them in the upper half */
  904. phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
  905. phy_ID = (phy_reg & 0xffff) << 16;
  906. /* Grab the bits from PHYIR2, and put them in the lower half */
  907. phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
  908. phy_ID |= (phy_reg & 0xffff);
  909. /* loop through all the known PHY types, and find one that */
  910. /* matches the ID we read from the PHY. */
  911. for(i=0; phy_info[i]; i++) {
  912. if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
  913. theInfo = phy_info[i];
  914. }
  915. if(theInfo == NULL)
  916. {
  917. printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
  918. return NULL;
  919. } else {
  920. debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
  921. }
  922. return theInfo;
  923. }
  924. /* Execute the given series of commands on the given device's
  925. * PHY, running functions as necessary*/
  926. void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
  927. {
  928. int i;
  929. uint result;
  930. volatile tsec_t *phyregs = priv->phyregs;
  931. phyregs->miimcfg = MIIMCFG_RESET;
  932. phyregs->miimcfg = MIIMCFG_INIT_VALUE;
  933. while(phyregs->miimind & MIIMIND_BUSY);
  934. for(i=0;cmd->mii_reg != miim_end;i++) {
  935. if(cmd->mii_data == miim_read) {
  936. result = read_phy_reg(priv, cmd->mii_reg);
  937. if(cmd->funct != NULL)
  938. (*(cmd->funct))(result, priv);
  939. } else {
  940. if(cmd->funct != NULL)
  941. result = (*(cmd->funct))(cmd->mii_reg, priv);
  942. else
  943. result = cmd->mii_data;
  944. write_phy_reg(priv, cmd->mii_reg, result);
  945. }
  946. cmd++;
  947. }
  948. }
  949. /* Relocate the function pointers in the phy cmd lists */
  950. static void relocate_cmds(void)
  951. {
  952. struct phy_cmd **cmdlistptr;
  953. struct phy_cmd *cmd;
  954. int i,j,k;
  955. for(i=0; phy_info[i]; i++) {
  956. /* First thing's first: relocate the pointers to the
  957. * PHY command structures (the structs were done) */
  958. phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
  959. + gd->reloc_off);
  960. phy_info[i]->name += gd->reloc_off;
  961. phy_info[i]->config =
  962. (struct phy_cmd *)((uint)phy_info[i]->config
  963. + gd->reloc_off);
  964. phy_info[i]->startup =
  965. (struct phy_cmd *)((uint)phy_info[i]->startup
  966. + gd->reloc_off);
  967. phy_info[i]->shutdown =
  968. (struct phy_cmd *)((uint)phy_info[i]->shutdown
  969. + gd->reloc_off);
  970. cmdlistptr = &phy_info[i]->config;
  971. j=0;
  972. for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
  973. k=0;
  974. for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
  975. /* Only relocate non-NULL pointers */
  976. if(cmd->funct)
  977. cmd->funct += gd->reloc_off;
  978. k++;
  979. }
  980. j++;
  981. }
  982. }
  983. relocated = 1;
  984. }
  985. #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
  986. && !defined(BITBANGMII)
  987. struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
  988. {
  989. int i;
  990. for(i=0;i<MAXCONTROLLERS;i++) {
  991. if(privlist[i]->phyaddr == phyaddr)
  992. return privlist[i];
  993. }
  994. return NULL;
  995. }
  996. /*
  997. * Read a MII PHY register.
  998. *
  999. * Returns:
  1000. * 0 on success
  1001. */
  1002. static int tsec_miiphy_read(char *devname, unsigned char addr,
  1003. unsigned char reg, unsigned short *value)
  1004. {
  1005. unsigned short ret;
  1006. struct tsec_private *priv = get_priv_for_phy(addr);
  1007. if(NULL == priv) {
  1008. printf("Can't read PHY at address %d\n", addr);
  1009. return -1;
  1010. }
  1011. ret = (unsigned short)read_phy_reg(priv, reg);
  1012. *value = ret;
  1013. return 0;
  1014. }
  1015. /*
  1016. * Write a MII PHY register.
  1017. *
  1018. * Returns:
  1019. * 0 on success
  1020. */
  1021. static int tsec_miiphy_write(char *devname, unsigned char addr,
  1022. unsigned char reg, unsigned short value)
  1023. {
  1024. struct tsec_private *priv = get_priv_for_phy(addr);
  1025. if(NULL == priv) {
  1026. printf("Can't write PHY at address %d\n", addr);
  1027. return -1;
  1028. }
  1029. write_phy_reg(priv, reg, value);
  1030. return 0;
  1031. }
  1032. #endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
  1033. && !defined(BITBANGMII) */
  1034. #endif /* CONFIG_TSEC_ENET */