tsec.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  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. /*
  274. * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
  275. */
  276. mii_reg = read_phy_reg(priv, MIIM_STATUS);
  277. if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
  278. int i = 0;
  279. puts ("Waiting for PHY auto negotiation to complete");
  280. while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
  281. /*
  282. * Timeout reached ?
  283. */
  284. if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
  285. puts (" TIMEOUT !\n");
  286. priv->link = 0;
  287. break;
  288. }
  289. if ((i++ % 1000) == 0) {
  290. putc ('.');
  291. }
  292. udelay (1000); /* 1 ms */
  293. mii_reg = read_phy_reg(priv, MIIM_STATUS);
  294. }
  295. puts (" done\n");
  296. priv->link = 1;
  297. udelay (500000); /* another 500 ms (results in faster booting) */
  298. } else {
  299. priv->link = 1;
  300. }
  301. return 0;
  302. }
  303. /* Parse the 88E1011's status register for speed and duplex
  304. * information */
  305. uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
  306. {
  307. uint speed;
  308. mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
  309. if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
  310. (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
  311. int i = 0;
  312. puts ("Waiting for PHY realtime link");
  313. while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
  314. (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
  315. /*
  316. * Timeout reached ?
  317. */
  318. if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
  319. puts (" TIMEOUT !\n");
  320. priv->link = 0;
  321. break;
  322. }
  323. if ((i++ % 1000) == 0) {
  324. putc ('.');
  325. }
  326. udelay (1000); /* 1 ms */
  327. mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
  328. }
  329. puts (" done\n");
  330. udelay (500000); /* another 500 ms (results in faster booting) */
  331. }
  332. if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
  333. priv->duplexity = 1;
  334. else
  335. priv->duplexity = 0;
  336. speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
  337. switch(speed) {
  338. case MIIM_88E1011_PHYSTAT_GBIT:
  339. priv->speed = 1000;
  340. break;
  341. case MIIM_88E1011_PHYSTAT_100:
  342. priv->speed = 100;
  343. break;
  344. default:
  345. priv->speed = 10;
  346. }
  347. return 0;
  348. }
  349. /* Parse the cis8201's status register for speed and duplex
  350. * information */
  351. uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
  352. {
  353. uint speed;
  354. if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
  355. priv->duplexity = 1;
  356. else
  357. priv->duplexity = 0;
  358. speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
  359. switch(speed) {
  360. case MIIM_CIS8201_AUXCONSTAT_GBIT:
  361. priv->speed = 1000;
  362. break;
  363. case MIIM_CIS8201_AUXCONSTAT_100:
  364. priv->speed = 100;
  365. break;
  366. default:
  367. priv->speed = 10;
  368. break;
  369. }
  370. return 0;
  371. }
  372. /* Parse the DM9161's status register for speed and duplex
  373. * information */
  374. uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
  375. {
  376. if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
  377. priv->speed = 100;
  378. else
  379. priv->speed = 10;
  380. if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
  381. priv->duplexity = 1;
  382. else
  383. priv->duplexity = 0;
  384. return 0;
  385. }
  386. /* Hack to write all 4 PHYs with the LED values */
  387. uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
  388. {
  389. uint phyid;
  390. volatile tsec_t *regbase = priv->phyregs;
  391. int timeout=1000000;
  392. for(phyid=0;phyid<4;phyid++) {
  393. regbase->miimadd = (phyid << 8) | mii_reg;
  394. regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
  395. asm("sync");
  396. timeout=1000000;
  397. while((regbase->miimind & MIIMIND_BUSY) && timeout--);
  398. }
  399. return MIIM_CIS8204_SLEDCON_INIT;
  400. }
  401. uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
  402. {
  403. if (priv->flags & TSEC_REDUCED)
  404. return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
  405. else
  406. return MIIM_CIS8204_EPHYCON_INIT;
  407. }
  408. /* Initialized required registers to appropriate values, zeroing
  409. * those we don't care about (unless zero is bad, in which case,
  410. * choose a more appropriate value) */
  411. static void init_registers(volatile tsec_t *regs)
  412. {
  413. /* Clear IEVENT */
  414. regs->ievent = IEVENT_INIT_CLEAR;
  415. regs->imask = IMASK_INIT_CLEAR;
  416. regs->hash.iaddr0 = 0;
  417. regs->hash.iaddr1 = 0;
  418. regs->hash.iaddr2 = 0;
  419. regs->hash.iaddr3 = 0;
  420. regs->hash.iaddr4 = 0;
  421. regs->hash.iaddr5 = 0;
  422. regs->hash.iaddr6 = 0;
  423. regs->hash.iaddr7 = 0;
  424. regs->hash.gaddr0 = 0;
  425. regs->hash.gaddr1 = 0;
  426. regs->hash.gaddr2 = 0;
  427. regs->hash.gaddr3 = 0;
  428. regs->hash.gaddr4 = 0;
  429. regs->hash.gaddr5 = 0;
  430. regs->hash.gaddr6 = 0;
  431. regs->hash.gaddr7 = 0;
  432. regs->rctrl = 0x00000000;
  433. /* Init RMON mib registers */
  434. memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
  435. regs->rmon.cam1 = 0xffffffff;
  436. regs->rmon.cam2 = 0xffffffff;
  437. regs->mrblr = MRBLR_INIT_SETTINGS;
  438. regs->minflr = MINFLR_INIT_SETTINGS;
  439. regs->attr = ATTR_INIT_SETTINGS;
  440. regs->attreli = ATTRELI_INIT_SETTINGS;
  441. }
  442. /* Configure maccfg2 based on negotiated speed and duplex
  443. * reported by PHY handling code */
  444. static void adjust_link(struct eth_device *dev)
  445. {
  446. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  447. volatile tsec_t *regs = priv->regs;
  448. if(priv->link) {
  449. if(priv->duplexity != 0)
  450. regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
  451. else
  452. regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
  453. switch(priv->speed) {
  454. case 1000:
  455. regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
  456. | MACCFG2_GMII);
  457. break;
  458. case 100:
  459. case 10:
  460. regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
  461. | MACCFG2_MII);
  462. /* If We're in reduced mode, we need
  463. * to say whether we're 10 or 100 MB.
  464. */
  465. if ((priv->speed == 100)
  466. && (priv->flags & TSEC_REDUCED))
  467. regs->ecntrl |= ECNTRL_R100;
  468. else
  469. regs->ecntrl &= ~(ECNTRL_R100);
  470. break;
  471. default:
  472. printf("%s: Speed was bad\n", dev->name);
  473. break;
  474. }
  475. printf("Speed: %d, %s duplex\n", priv->speed,
  476. (priv->duplexity) ? "full" : "half");
  477. } else {
  478. printf("%s: No link.\n", dev->name);
  479. }
  480. }
  481. /* Set up the buffers and their descriptors, and bring up the
  482. * interface */
  483. static void startup_tsec(struct eth_device *dev)
  484. {
  485. int i;
  486. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  487. volatile tsec_t *regs = priv->regs;
  488. /* Point to the buffer descriptors */
  489. regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
  490. regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
  491. /* Initialize the Rx Buffer descriptors */
  492. for (i = 0; i < PKTBUFSRX; i++) {
  493. rtx.rxbd[i].status = RXBD_EMPTY;
  494. rtx.rxbd[i].length = 0;
  495. rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
  496. }
  497. rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
  498. /* Initialize the TX Buffer Descriptors */
  499. for(i=0; i<TX_BUF_CNT; i++) {
  500. rtx.txbd[i].status = 0;
  501. rtx.txbd[i].length = 0;
  502. rtx.txbd[i].bufPtr = 0;
  503. }
  504. rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
  505. /* Start up the PHY */
  506. phy_run_commands(priv, priv->phyinfo->startup);
  507. adjust_link(dev);
  508. /* Enable Transmit and Receive */
  509. regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
  510. /* Tell the DMA it is clear to go */
  511. regs->dmactrl |= DMACTRL_INIT_SETTINGS;
  512. regs->tstat = TSTAT_CLEAR_THALT;
  513. regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
  514. }
  515. /* This returns the status bits of the device. The return value
  516. * is never checked, and this is what the 8260 driver did, so we
  517. * do the same. Presumably, this would be zero if there were no
  518. * errors */
  519. static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
  520. {
  521. int i;
  522. int result = 0;
  523. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  524. volatile tsec_t *regs = priv->regs;
  525. /* Find an empty buffer descriptor */
  526. for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
  527. if (i >= TOUT_LOOP) {
  528. debug ("%s: tsec: tx buffers full\n", dev->name);
  529. return result;
  530. }
  531. }
  532. rtx.txbd[txIdx].bufPtr = (uint)packet;
  533. rtx.txbd[txIdx].length = length;
  534. rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
  535. /* Tell the DMA to go */
  536. regs->tstat = TSTAT_CLEAR_THALT;
  537. /* Wait for buffer to be transmitted */
  538. for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
  539. if (i >= TOUT_LOOP) {
  540. debug ("%s: tsec: tx error\n", dev->name);
  541. return result;
  542. }
  543. }
  544. txIdx = (txIdx + 1) % TX_BUF_CNT;
  545. result = rtx.txbd[txIdx].status & TXBD_STATS;
  546. return result;
  547. }
  548. static int tsec_recv(struct eth_device* dev)
  549. {
  550. int length;
  551. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  552. volatile tsec_t *regs = priv->regs;
  553. while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
  554. length = rtx.rxbd[rxIdx].length;
  555. /* Send the packet up if there were no errors */
  556. if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
  557. NetReceive(NetRxPackets[rxIdx], length - 4);
  558. } else {
  559. printf("Got error %x\n",
  560. (rtx.rxbd[rxIdx].status & RXBD_STATS));
  561. }
  562. rtx.rxbd[rxIdx].length = 0;
  563. /* Set the wrap bit if this is the last element in the list */
  564. rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
  565. rxIdx = (rxIdx + 1) % PKTBUFSRX;
  566. }
  567. if(regs->ievent&IEVENT_BSY) {
  568. regs->ievent = IEVENT_BSY;
  569. regs->rstat = RSTAT_CLEAR_RHALT;
  570. }
  571. return -1;
  572. }
  573. /* Stop the interface */
  574. static void tsec_halt(struct eth_device* dev)
  575. {
  576. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  577. volatile tsec_t *regs = priv->regs;
  578. regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
  579. regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
  580. while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
  581. regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
  582. /* Shut down the PHY, as needed */
  583. phy_run_commands(priv, priv->phyinfo->shutdown);
  584. }
  585. struct phy_info phy_info_M88E1011S = {
  586. 0x01410c6,
  587. "Marvell 88E1011S",
  588. 4,
  589. (struct phy_cmd[]) { /* config */
  590. /* Reset and configure the PHY */
  591. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  592. {0x1d, 0x1f, NULL},
  593. {0x1e, 0x200c, NULL},
  594. {0x1d, 0x5, NULL},
  595. {0x1e, 0x0, NULL},
  596. {0x1e, 0x100, NULL},
  597. {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
  598. {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
  599. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  600. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  601. {miim_end,}
  602. },
  603. (struct phy_cmd[]) { /* startup */
  604. /* Status is read once to clear old link state */
  605. {MIIM_STATUS, miim_read, NULL},
  606. /* Auto-negotiate */
  607. {MIIM_STATUS, miim_read, &mii_parse_sr},
  608. /* Read the status */
  609. {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
  610. {miim_end,}
  611. },
  612. (struct phy_cmd[]) { /* shutdown */
  613. {miim_end,}
  614. },
  615. };
  616. struct phy_info phy_info_M88E1111S = {
  617. 0x01410cc,
  618. "Marvell 88E1111S",
  619. 4,
  620. (struct phy_cmd[]) { /* config */
  621. /* Reset and configure the PHY */
  622. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  623. {0x1d, 0x1f, NULL},
  624. {0x1e, 0x200c, NULL},
  625. {0x1d, 0x5, NULL},
  626. {0x1e, 0x0, NULL},
  627. {0x1e, 0x100, NULL},
  628. {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
  629. {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
  630. {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
  631. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  632. {miim_end,}
  633. },
  634. (struct phy_cmd[]) { /* startup */
  635. /* Status is read once to clear old link state */
  636. {MIIM_STATUS, miim_read, NULL},
  637. /* Auto-negotiate */
  638. {MIIM_STATUS, miim_read, &mii_parse_sr},
  639. /* Read the status */
  640. {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
  641. {miim_end,}
  642. },
  643. (struct phy_cmd[]) { /* shutdown */
  644. {miim_end,}
  645. },
  646. };
  647. struct phy_info phy_info_cis8204 = {
  648. 0x3f11,
  649. "Cicada Cis8204",
  650. 6,
  651. (struct phy_cmd[]) { /* config */
  652. /* Override PHY config settings */
  653. {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
  654. /* Configure some basic stuff */
  655. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  656. {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
  657. {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
  658. {miim_end,}
  659. },
  660. (struct phy_cmd[]) { /* startup */
  661. /* Read the Status (2x to make sure link is right) */
  662. {MIIM_STATUS, miim_read, NULL},
  663. /* Auto-negotiate */
  664. {MIIM_STATUS, miim_read, &mii_parse_sr},
  665. /* Read the status */
  666. {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
  667. {miim_end,}
  668. },
  669. (struct phy_cmd[]) { /* shutdown */
  670. {miim_end,}
  671. },
  672. };
  673. /* Cicada 8201 */
  674. struct phy_info phy_info_cis8201 = {
  675. 0xfc41,
  676. "CIS8201",
  677. 4,
  678. (struct phy_cmd[]) { /* config */
  679. /* Override PHY config settings */
  680. {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
  681. /* Set up the interface mode */
  682. {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
  683. /* Configure some basic stuff */
  684. {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
  685. {miim_end,}
  686. },
  687. (struct phy_cmd[]) { /* startup */
  688. /* Read the Status (2x to make sure link is right) */
  689. {MIIM_STATUS, miim_read, NULL},
  690. /* Auto-negotiate */
  691. {MIIM_STATUS, miim_read, &mii_parse_sr},
  692. /* Read the status */
  693. {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
  694. {miim_end,}
  695. },
  696. (struct phy_cmd[]) { /* shutdown */
  697. {miim_end,}
  698. },
  699. };
  700. struct phy_info phy_info_dm9161 = {
  701. 0x0181b88,
  702. "Davicom DM9161E",
  703. 4,
  704. (struct phy_cmd[]) { /* config */
  705. {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
  706. /* Do not bypass the scrambler/descrambler */
  707. {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
  708. /* Clear 10BTCSR to default */
  709. {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
  710. /* Configure some basic stuff */
  711. {MIIM_CONTROL, MIIM_CR_INIT, NULL},
  712. /* Restart Auto Negotiation */
  713. {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
  714. {miim_end,}
  715. },
  716. (struct phy_cmd[]) { /* startup */
  717. /* Status is read once to clear old link state */
  718. {MIIM_STATUS, miim_read, NULL},
  719. /* Auto-negotiate */
  720. {MIIM_STATUS, miim_read, &mii_parse_sr},
  721. /* Read the status */
  722. {MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
  723. {miim_end,}
  724. },
  725. (struct phy_cmd[]) { /* shutdown */
  726. {miim_end,}
  727. },
  728. };
  729. uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
  730. {
  731. unsigned int speed;
  732. if (priv->link) {
  733. speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
  734. switch (speed) {
  735. case MIIM_LXT971_SR2_10HDX:
  736. priv->speed = 10;
  737. priv->duplexity = 0;
  738. break;
  739. case MIIM_LXT971_SR2_10FDX:
  740. priv->speed = 10;
  741. priv->duplexity = 1;
  742. break;
  743. case MIIM_LXT971_SR2_100HDX:
  744. priv->speed = 100;
  745. priv->duplexity = 0;
  746. default:
  747. priv->speed = 100;
  748. priv->duplexity = 1;
  749. break;
  750. }
  751. } else {
  752. priv->speed = 0;
  753. priv->duplexity = 0;
  754. }
  755. return 0;
  756. }
  757. static struct phy_info phy_info_lxt971 = {
  758. 0x0001378e,
  759. "LXT971",
  760. 4,
  761. (struct phy_cmd []) { /* config */
  762. { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
  763. { miim_end, }
  764. },
  765. (struct phy_cmd []) { /* startup - enable interrupts */
  766. /* { 0x12, 0x00f2, NULL }, */
  767. { MIIM_STATUS, miim_read, NULL },
  768. { MIIM_STATUS, miim_read, &mii_parse_sr },
  769. { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
  770. { miim_end, }
  771. },
  772. (struct phy_cmd []) { /* shutdown - disable interrupts */
  773. { miim_end, }
  774. },
  775. };
  776. struct phy_info *phy_info[] = {
  777. #if 0
  778. &phy_info_cis8201,
  779. #endif
  780. &phy_info_cis8204,
  781. &phy_info_M88E1011S,
  782. &phy_info_M88E1111S,
  783. &phy_info_dm9161,
  784. &phy_info_lxt971,
  785. NULL
  786. };
  787. /* Grab the identifier of the device's PHY, and search through
  788. * all of the known PHYs to see if one matches. If so, return
  789. * it, if not, return NULL */
  790. struct phy_info * get_phy_info(struct eth_device *dev)
  791. {
  792. struct tsec_private *priv = (struct tsec_private *)dev->priv;
  793. uint phy_reg, phy_ID;
  794. int i;
  795. struct phy_info *theInfo = NULL;
  796. /* Grab the bits from PHYIR1, and put them in the upper half */
  797. phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
  798. phy_ID = (phy_reg & 0xffff) << 16;
  799. /* Grab the bits from PHYIR2, and put them in the lower half */
  800. phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
  801. phy_ID |= (phy_reg & 0xffff);
  802. /* loop through all the known PHY types, and find one that */
  803. /* matches the ID we read from the PHY. */
  804. for(i=0; phy_info[i]; i++) {
  805. if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
  806. theInfo = phy_info[i];
  807. }
  808. if(theInfo == NULL)
  809. {
  810. printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
  811. return NULL;
  812. } else {
  813. debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
  814. }
  815. return theInfo;
  816. }
  817. /* Execute the given series of commands on the given device's
  818. * PHY, running functions as necessary*/
  819. void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
  820. {
  821. int i;
  822. uint result;
  823. volatile tsec_t *phyregs = priv->phyregs;
  824. phyregs->miimcfg = MIIMCFG_RESET;
  825. phyregs->miimcfg = MIIMCFG_INIT_VALUE;
  826. while(phyregs->miimind & MIIMIND_BUSY);
  827. for(i=0;cmd->mii_reg != miim_end;i++) {
  828. if(cmd->mii_data == miim_read) {
  829. result = read_phy_reg(priv, cmd->mii_reg);
  830. if(cmd->funct != NULL)
  831. (*(cmd->funct))(result, priv);
  832. } else {
  833. if(cmd->funct != NULL)
  834. result = (*(cmd->funct))(cmd->mii_reg, priv);
  835. else
  836. result = cmd->mii_data;
  837. write_phy_reg(priv, cmd->mii_reg, result);
  838. }
  839. cmd++;
  840. }
  841. }
  842. /* Relocate the function pointers in the phy cmd lists */
  843. static void relocate_cmds(void)
  844. {
  845. struct phy_cmd **cmdlistptr;
  846. struct phy_cmd *cmd;
  847. int i,j,k;
  848. DECLARE_GLOBAL_DATA_PTR;
  849. for(i=0; phy_info[i]; i++) {
  850. /* First thing's first: relocate the pointers to the
  851. * PHY command structures (the structs were done) */
  852. phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
  853. + gd->reloc_off);
  854. phy_info[i]->name += gd->reloc_off;
  855. phy_info[i]->config =
  856. (struct phy_cmd *)((uint)phy_info[i]->config
  857. + gd->reloc_off);
  858. phy_info[i]->startup =
  859. (struct phy_cmd *)((uint)phy_info[i]->startup
  860. + gd->reloc_off);
  861. phy_info[i]->shutdown =
  862. (struct phy_cmd *)((uint)phy_info[i]->shutdown
  863. + gd->reloc_off);
  864. cmdlistptr = &phy_info[i]->config;
  865. j=0;
  866. for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
  867. k=0;
  868. for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
  869. /* Only relocate non-NULL pointers */
  870. if(cmd->funct)
  871. cmd->funct += gd->reloc_off;
  872. k++;
  873. }
  874. j++;
  875. }
  876. }
  877. relocated = 1;
  878. }
  879. #ifndef CONFIG_BITBANGMII
  880. struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
  881. {
  882. int i;
  883. for(i=0;i<MAXCONTROLLERS;i++) {
  884. if(privlist[i]->phyaddr == phyaddr)
  885. return privlist[i];
  886. }
  887. return NULL;
  888. }
  889. /*
  890. * Read a MII PHY register.
  891. *
  892. * Returns:
  893. * 0 on success
  894. */
  895. int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
  896. {
  897. unsigned short ret;
  898. struct tsec_private *priv = get_priv_for_phy(addr);
  899. if(NULL == priv) {
  900. printf("Can't read PHY at address %d\n", addr);
  901. return -1;
  902. }
  903. ret = (unsigned short)read_phy_reg(priv, reg);
  904. *value = ret;
  905. return 0;
  906. }
  907. /*
  908. * Write a MII PHY register.
  909. *
  910. * Returns:
  911. * 0 on success
  912. */
  913. int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
  914. {
  915. struct tsec_private *priv = get_priv_for_phy(addr);
  916. if(NULL == priv) {
  917. printf("Can't write PHY at address %d\n", addr);
  918. return -1;
  919. }
  920. write_phy_reg(priv, reg, value);
  921. return 0;
  922. }
  923. #endif /* CONFIG_BITBANGMII */
  924. #endif /* CONFIG_TSEC_ENET */