tsec.c 26 KB

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