tsec.c 22 KB

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