tsec.c 28 KB

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