designware.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * (C) Copyright 2010
  3. * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. /*
  8. * Designware ethernet IP driver for u-boot
  9. */
  10. #include <common.h>
  11. #include <miiphy.h>
  12. #include <malloc.h>
  13. #include <linux/compiler.h>
  14. #include <linux/err.h>
  15. #include <asm/io.h>
  16. #include "designware.h"
  17. static int configure_phy(struct eth_device *dev);
  18. static void tx_descs_init(struct eth_device *dev)
  19. {
  20. struct dw_eth_dev *priv = dev->priv;
  21. struct eth_dma_regs *dma_p = priv->dma_regs_p;
  22. struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
  23. char *txbuffs = &priv->txbuffs[0];
  24. struct dmamacdescr *desc_p;
  25. u32 idx;
  26. for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
  27. desc_p = &desc_table_p[idx];
  28. desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
  29. desc_p->dmamac_next = &desc_table_p[idx + 1];
  30. #if defined(CONFIG_DW_ALTDESCRIPTOR)
  31. desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
  32. DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
  33. DESC_TXSTS_TXCHECKINSCTRL | \
  34. DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
  35. desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
  36. desc_p->dmamac_cntl = 0;
  37. desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
  38. #else
  39. desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
  40. desc_p->txrx_status = 0;
  41. #endif
  42. }
  43. /* Correcting the last pointer of the chain */
  44. desc_p->dmamac_next = &desc_table_p[0];
  45. writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
  46. }
  47. static void rx_descs_init(struct eth_device *dev)
  48. {
  49. struct dw_eth_dev *priv = dev->priv;
  50. struct eth_dma_regs *dma_p = priv->dma_regs_p;
  51. struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
  52. char *rxbuffs = &priv->rxbuffs[0];
  53. struct dmamacdescr *desc_p;
  54. u32 idx;
  55. for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
  56. desc_p = &desc_table_p[idx];
  57. desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
  58. desc_p->dmamac_next = &desc_table_p[idx + 1];
  59. desc_p->dmamac_cntl =
  60. (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
  61. DESC_RXCTRL_RXCHAIN;
  62. desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
  63. }
  64. /* Correcting the last pointer of the chain */
  65. desc_p->dmamac_next = &desc_table_p[0];
  66. writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
  67. }
  68. static void descs_init(struct eth_device *dev)
  69. {
  70. tx_descs_init(dev);
  71. rx_descs_init(dev);
  72. }
  73. static int mac_reset(struct eth_device *dev)
  74. {
  75. struct dw_eth_dev *priv = dev->priv;
  76. struct eth_mac_regs *mac_p = priv->mac_regs_p;
  77. struct eth_dma_regs *dma_p = priv->dma_regs_p;
  78. ulong start;
  79. int timeout = CONFIG_MACRESET_TIMEOUT;
  80. writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
  81. if (priv->interface != PHY_INTERFACE_MODE_RGMII)
  82. writel(MII_PORTSELECT, &mac_p->conf);
  83. start = get_timer(0);
  84. while (get_timer(start) < timeout) {
  85. if (!(readl(&dma_p->busmode) & DMAMAC_SRST))
  86. return 0;
  87. /* Try again after 10usec */
  88. udelay(10);
  89. };
  90. return -1;
  91. }
  92. static int dw_write_hwaddr(struct eth_device *dev)
  93. {
  94. struct dw_eth_dev *priv = dev->priv;
  95. struct eth_mac_regs *mac_p = priv->mac_regs_p;
  96. u32 macid_lo, macid_hi;
  97. u8 *mac_id = &dev->enetaddr[0];
  98. macid_lo = mac_id[0] + (mac_id[1] << 8) + \
  99. (mac_id[2] << 16) + (mac_id[3] << 24);
  100. macid_hi = mac_id[4] + (mac_id[5] << 8);
  101. writel(macid_hi, &mac_p->macaddr0hi);
  102. writel(macid_lo, &mac_p->macaddr0lo);
  103. return 0;
  104. }
  105. static int dw_eth_init(struct eth_device *dev, bd_t *bis)
  106. {
  107. struct dw_eth_dev *priv = dev->priv;
  108. struct eth_mac_regs *mac_p = priv->mac_regs_p;
  109. struct eth_dma_regs *dma_p = priv->dma_regs_p;
  110. u32 conf;
  111. if (priv->phy_configured != 1)
  112. configure_phy(dev);
  113. /* Print link status only once */
  114. if (!priv->link_printed) {
  115. printf("ENET Speed is %d Mbps - %s duplex connection\n",
  116. priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
  117. priv->link_printed = 1;
  118. }
  119. /* Reset ethernet hardware */
  120. if (mac_reset(dev) < 0)
  121. return -1;
  122. /* Resore the HW MAC address as it has been lost during MAC reset */
  123. dw_write_hwaddr(dev);
  124. writel(FIXEDBURST | PRIORXTX_41 | BURST_16,
  125. &dma_p->busmode);
  126. writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD |
  127. TXSECONDFRAME, &dma_p->opmode);
  128. conf = FRAMEBURSTENABLE | DISABLERXOWN;
  129. if (priv->speed != 1000)
  130. conf |= MII_PORTSELECT;
  131. if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
  132. (priv->interface != PHY_INTERFACE_MODE_GMII)) {
  133. if (priv->speed == 100)
  134. conf |= FES_100;
  135. }
  136. if (priv->duplex == FULL)
  137. conf |= FULLDPLXMODE;
  138. writel(conf, &mac_p->conf);
  139. descs_init(dev);
  140. /*
  141. * Start/Enable xfer at dma as well as mac level
  142. */
  143. writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode);
  144. writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode);
  145. writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
  146. return 0;
  147. }
  148. static int dw_eth_send(struct eth_device *dev, void *packet, int length)
  149. {
  150. struct dw_eth_dev *priv = dev->priv;
  151. struct eth_dma_regs *dma_p = priv->dma_regs_p;
  152. u32 desc_num = priv->tx_currdescnum;
  153. struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
  154. /* Check if the descriptor is owned by CPU */
  155. if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
  156. printf("CPU not owner of tx frame\n");
  157. return -1;
  158. }
  159. memcpy((void *)desc_p->dmamac_addr, packet, length);
  160. #if defined(CONFIG_DW_ALTDESCRIPTOR)
  161. desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
  162. desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
  163. DESC_TXCTRL_SIZE1MASK;
  164. desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
  165. desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
  166. #else
  167. desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
  168. DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
  169. DESC_TXCTRL_TXFIRST;
  170. desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
  171. #endif
  172. /* Test the wrap-around condition. */
  173. if (++desc_num >= CONFIG_TX_DESCR_NUM)
  174. desc_num = 0;
  175. priv->tx_currdescnum = desc_num;
  176. /* Start the transmission */
  177. writel(POLL_DATA, &dma_p->txpolldemand);
  178. return 0;
  179. }
  180. static int dw_eth_recv(struct eth_device *dev)
  181. {
  182. struct dw_eth_dev *priv = dev->priv;
  183. u32 desc_num = priv->rx_currdescnum;
  184. struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
  185. u32 status = desc_p->txrx_status;
  186. int length = 0;
  187. /* Check if the owner is the CPU */
  188. if (!(status & DESC_RXSTS_OWNBYDMA)) {
  189. length = (status & DESC_RXSTS_FRMLENMSK) >> \
  190. DESC_RXSTS_FRMLENSHFT;
  191. NetReceive(desc_p->dmamac_addr, length);
  192. /*
  193. * Make the current descriptor valid again and go to
  194. * the next one
  195. */
  196. desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
  197. /* Test the wrap-around condition. */
  198. if (++desc_num >= CONFIG_RX_DESCR_NUM)
  199. desc_num = 0;
  200. }
  201. priv->rx_currdescnum = desc_num;
  202. return length;
  203. }
  204. static void dw_eth_halt(struct eth_device *dev)
  205. {
  206. struct dw_eth_dev *priv = dev->priv;
  207. mac_reset(dev);
  208. priv->tx_currdescnum = priv->rx_currdescnum = 0;
  209. }
  210. static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val)
  211. {
  212. struct dw_eth_dev *priv = dev->priv;
  213. struct eth_mac_regs *mac_p = priv->mac_regs_p;
  214. ulong start;
  215. u32 miiaddr;
  216. int timeout = CONFIG_MDIO_TIMEOUT;
  217. miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
  218. ((reg << MIIREGSHIFT) & MII_REGMSK);
  219. writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
  220. start = get_timer(0);
  221. while (get_timer(start) < timeout) {
  222. if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
  223. *val = readl(&mac_p->miidata);
  224. return 0;
  225. }
  226. /* Try again after 10usec */
  227. udelay(10);
  228. };
  229. return -1;
  230. }
  231. static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val)
  232. {
  233. struct dw_eth_dev *priv = dev->priv;
  234. struct eth_mac_regs *mac_p = priv->mac_regs_p;
  235. ulong start;
  236. u32 miiaddr;
  237. int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
  238. u16 value;
  239. writel(val, &mac_p->miidata);
  240. miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
  241. ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
  242. writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
  243. start = get_timer(0);
  244. while (get_timer(start) < timeout) {
  245. if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
  246. ret = 0;
  247. break;
  248. }
  249. /* Try again after 10usec */
  250. udelay(10);
  251. };
  252. /* Needed as a fix for ST-Phy */
  253. eth_mdio_read(dev, addr, reg, &value);
  254. return ret;
  255. }
  256. #if defined(CONFIG_DW_SEARCH_PHY)
  257. static int find_phy(struct eth_device *dev)
  258. {
  259. int phy_addr = 0;
  260. u16 ctrl, oldctrl;
  261. do {
  262. eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
  263. oldctrl = ctrl & BMCR_ANENABLE;
  264. ctrl ^= BMCR_ANENABLE;
  265. eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
  266. eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
  267. ctrl &= BMCR_ANENABLE;
  268. if (ctrl == oldctrl) {
  269. phy_addr++;
  270. } else {
  271. ctrl ^= BMCR_ANENABLE;
  272. eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl);
  273. return phy_addr;
  274. }
  275. } while (phy_addr < 32);
  276. return -1;
  277. }
  278. #endif
  279. static int dw_reset_phy(struct eth_device *dev)
  280. {
  281. struct dw_eth_dev *priv = dev->priv;
  282. u16 ctrl;
  283. ulong start;
  284. int timeout = CONFIG_PHYRESET_TIMEOUT;
  285. u32 phy_addr = priv->address;
  286. eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET);
  287. start = get_timer(0);
  288. while (get_timer(start) < timeout) {
  289. eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl);
  290. if (!(ctrl & BMCR_RESET))
  291. break;
  292. /* Try again after 10usec */
  293. udelay(10);
  294. };
  295. if (get_timer(start) >= CONFIG_PHYRESET_TIMEOUT)
  296. return -1;
  297. #ifdef CONFIG_PHY_RESET_DELAY
  298. udelay(CONFIG_PHY_RESET_DELAY);
  299. #endif
  300. return 0;
  301. }
  302. /*
  303. * Add weak default function for board specific PHY configuration
  304. */
  305. int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr,
  306. int (*mii_write)(struct eth_device *, u8, u8, u16),
  307. int dw_reset_phy(struct eth_device *))
  308. {
  309. return 0;
  310. }
  311. static int configure_phy(struct eth_device *dev)
  312. {
  313. struct dw_eth_dev *priv = dev->priv;
  314. int phy_addr;
  315. u16 bmcr;
  316. #if defined(CONFIG_DW_AUTONEG)
  317. u16 bmsr;
  318. u32 timeout;
  319. ulong start;
  320. #endif
  321. #if defined(CONFIG_DW_SEARCH_PHY)
  322. phy_addr = find_phy(dev);
  323. if (phy_addr >= 0)
  324. priv->address = phy_addr;
  325. else
  326. return -1;
  327. #else
  328. phy_addr = priv->address;
  329. #endif
  330. /*
  331. * Some boards need board specific PHY initialization. This is
  332. * after the main driver init code but before the auto negotiation
  333. * is run.
  334. */
  335. if (designware_board_phy_init(dev, phy_addr,
  336. eth_mdio_write, dw_reset_phy) < 0)
  337. return -1;
  338. if (dw_reset_phy(dev) < 0)
  339. return -1;
  340. #if defined(CONFIG_DW_AUTONEG)
  341. /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */
  342. eth_mdio_write(dev, phy_addr, MII_ADVERTISE, 0x1E1);
  343. bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
  344. #else
  345. bmcr = BMCR_SPEED100 | BMCR_FULLDPLX;
  346. #if defined(CONFIG_DW_SPEED10M)
  347. bmcr &= ~BMCR_SPEED100;
  348. #endif
  349. #if defined(CONFIG_DW_DUPLEXHALF)
  350. bmcr &= ~BMCR_FULLDPLX;
  351. #endif
  352. #endif
  353. if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0)
  354. return -1;
  355. /* Read the phy status register and populate priv structure */
  356. #if defined(CONFIG_DW_AUTONEG)
  357. timeout = CONFIG_AUTONEG_TIMEOUT;
  358. start = get_timer(0);
  359. puts("Waiting for PHY auto negotiation to complete");
  360. while (get_timer(start) < timeout) {
  361. eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
  362. if (bmsr & BMSR_ANEGCOMPLETE) {
  363. priv->phy_configured = 1;
  364. break;
  365. }
  366. /* Print dot all 1s to show progress */
  367. if ((get_timer(start) % 1000) == 0)
  368. putc('.');
  369. /* Try again after 1msec */
  370. udelay(1000);
  371. };
  372. if (!(bmsr & BMSR_ANEGCOMPLETE))
  373. puts(" TIMEOUT!\n");
  374. else
  375. puts(" done\n");
  376. #else
  377. priv->phy_configured = 1;
  378. #endif
  379. priv->speed = miiphy_speed(dev->name, phy_addr);
  380. priv->duplex = miiphy_duplex(dev->name, phy_addr);
  381. return 0;
  382. }
  383. #if defined(CONFIG_MII)
  384. static int dw_mii_read(const char *devname, u8 addr, u8 reg, u16 *val)
  385. {
  386. struct eth_device *dev;
  387. dev = eth_get_dev_by_name(devname);
  388. if (dev)
  389. eth_mdio_read(dev, addr, reg, val);
  390. return 0;
  391. }
  392. static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val)
  393. {
  394. struct eth_device *dev;
  395. dev = eth_get_dev_by_name(devname);
  396. if (dev)
  397. eth_mdio_write(dev, addr, reg, val);
  398. return 0;
  399. }
  400. #endif
  401. int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
  402. {
  403. struct eth_device *dev;
  404. struct dw_eth_dev *priv;
  405. dev = (struct eth_device *) malloc(sizeof(struct eth_device));
  406. if (!dev)
  407. return -ENOMEM;
  408. /*
  409. * Since the priv structure contains the descriptors which need a strict
  410. * buswidth alignment, memalign is used to allocate memory
  411. */
  412. priv = (struct dw_eth_dev *) memalign(16, sizeof(struct dw_eth_dev));
  413. if (!priv) {
  414. free(dev);
  415. return -ENOMEM;
  416. }
  417. memset(dev, 0, sizeof(struct eth_device));
  418. memset(priv, 0, sizeof(struct dw_eth_dev));
  419. sprintf(dev->name, "mii%d", id);
  420. dev->iobase = (int)base_addr;
  421. dev->priv = priv;
  422. eth_getenv_enetaddr_by_index("eth", id, &dev->enetaddr[0]);
  423. priv->dev = dev;
  424. priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
  425. priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
  426. DW_DMA_BASE_OFFSET);
  427. priv->address = phy_addr;
  428. priv->phy_configured = 0;
  429. priv->interface = interface;
  430. dev->init = dw_eth_init;
  431. dev->send = dw_eth_send;
  432. dev->recv = dw_eth_recv;
  433. dev->halt = dw_eth_halt;
  434. dev->write_hwaddr = dw_write_hwaddr;
  435. eth_register(dev);
  436. #if defined(CONFIG_MII)
  437. miiphy_register(dev->name, dw_mii_read, dw_mii_write);
  438. #endif
  439. return 1;
  440. }