tsec.c 25 KB

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