tsec.c 25 KB

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