xilinx_ll_temac.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * Xilinx xps_ll_temac ethernet driver for u-boot
  3. *
  4. * supports SDMA or FIFO access and MDIO bus communication
  5. *
  6. * Copyright (C) 2011 - 2012 Stephan Linz <linz@li-pro.net>
  7. * Copyright (C) 2008 - 2011 Michal Simek <monstr@monstr.eu>
  8. * Copyright (C) 2008 - 2011 PetaLogix
  9. *
  10. * Based on Yoshio Kashiwagi kashiwagi@co-nss.co.jp driver
  11. * Copyright (C) 2008 Nissin Systems Co.,Ltd.
  12. * March 2008 created
  13. *
  14. * This program is free software; you can redistribute it and/or modify it
  15. * under the terms of the GNU General Public License as published by the
  16. * Free Software Foundation; either version 2 of the License, or (at your
  17. * option) any later version.
  18. *
  19. * [0]: http://www.xilinx.com/support/documentation
  20. *
  21. * [S]: [0]/ip_documentation/xps_ll_temac.pdf
  22. * [A]: [0]/application_notes/xapp1041.pdf
  23. */
  24. #include <config.h>
  25. #include <common.h>
  26. #include <net.h>
  27. #include <netdev.h>
  28. #include <malloc.h>
  29. #include <asm/io.h>
  30. #include <miiphy.h>
  31. #include "xilinx_ll_temac.h"
  32. #include "xilinx_ll_temac_fifo.h"
  33. #include "xilinx_ll_temac_sdma.h"
  34. #include "xilinx_ll_temac_mdio.h"
  35. #if !defined(CONFIG_MII)
  36. # error "LL_TEMAC requires MII -- missing CONFIG_MII"
  37. #endif
  38. #if !defined(CONFIG_PHYLIB)
  39. # error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB"
  40. #endif
  41. struct ll_temac_info {
  42. int flags;
  43. unsigned long base_addr;
  44. unsigned long ctrl_addr;
  45. char *devname;
  46. unsigned int phyaddr;
  47. char *mdio_busname;
  48. };
  49. /* Ethernet interface ready status */
  50. int ll_temac_check_status(struct temac_reg *regs, u32 mask)
  51. {
  52. unsigned timeout = 50; /* 1usec * 50 = 50usec */
  53. /*
  54. * Quote from LL TEMAC documentation: The bits in the RDY
  55. * register are asserted when there is no access in progress.
  56. * When an access is in progress, a bit corresponding to the
  57. * type of access is automatically de-asserted. The bit is
  58. * automatically re-asserted when the access is complete.
  59. */
  60. while (timeout && (!(in_be32(&regs->rdy) & mask))) {
  61. timeout--;
  62. udelay(1);
  63. }
  64. if (!timeout) {
  65. printf("%s: Timeout on 0x%08x @%p\n", __func__,
  66. mask, &regs->rdy);
  67. return 1;
  68. }
  69. return 0;
  70. }
  71. /*
  72. * Indirect write to ll_temac.
  73. *
  74. * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
  75. * page 23, second paragraph, The use of CTL0 register or CTL1 register
  76. */
  77. int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data)
  78. {
  79. out_be32(&regs->lsw, (reg_data & MLSW_MASK));
  80. out_be32(&regs->ctl, CTL_WEN | (regn & CTL_ADDR_MASK));
  81. if (ll_temac_check_status(regs, RSE_CFG_WR))
  82. return 0;
  83. return 1;
  84. }
  85. /*
  86. * Indirect read from ll_temac.
  87. *
  88. * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf
  89. * page 23, second paragraph, The use of CTL0 register or CTL1 register
  90. */
  91. int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data)
  92. {
  93. out_be32(&regs->ctl, (regn & CTL_ADDR_MASK));
  94. if (ll_temac_check_status(regs, RSE_CFG_RR))
  95. return 0;
  96. *reg_data = in_be32(&regs->lsw) & MLSW_MASK;
  97. return 1;
  98. }
  99. /* setting sub-controller and ll_temac to proper setting */
  100. static int ll_temac_setup_ctrl(struct eth_device *dev)
  101. {
  102. struct ll_temac *ll_temac = dev->priv;
  103. struct temac_reg *regs = (struct temac_reg *)dev->iobase;
  104. if (ll_temac->ctrlreset && ll_temac->ctrlreset(dev))
  105. return 0;
  106. if (ll_temac->ctrlinit && ll_temac->ctrlinit(dev))
  107. return 0;
  108. /* Promiscuous mode disable */
  109. if (!ll_temac_indirect_set(regs, TEMAC_AFM, 0))
  110. return 0;
  111. /* Enable Receiver - RX bit */
  112. if (!ll_temac_indirect_set(regs, TEMAC_RCW1, RCW1_RX))
  113. return 0;
  114. /* Enable Transmitter - TX bit */
  115. if (!ll_temac_indirect_set(regs, TEMAC_TC, TC_TX))
  116. return 0;
  117. return 1;
  118. }
  119. /*
  120. * Configure ll_temac based on negotiated speed and duplex
  121. * reported by PHY handling code
  122. */
  123. static int ll_temac_adjust_link(struct eth_device *dev)
  124. {
  125. unsigned int speed, emmc_reg;
  126. struct temac_reg *regs = (struct temac_reg *)dev->iobase;
  127. struct ll_temac *ll_temac = dev->priv;
  128. struct phy_device *phydev = ll_temac->phydev;
  129. if (!phydev->link) {
  130. printf("%s: No link.\n", phydev->dev->name);
  131. return 0;
  132. }
  133. switch (phydev->speed) {
  134. case 1000:
  135. speed = EMMC_LSPD_1000;
  136. break;
  137. case 100:
  138. speed = EMMC_LSPD_100;
  139. break;
  140. case 10:
  141. speed = EMMC_LSPD_10;
  142. break;
  143. default:
  144. return 0;
  145. }
  146. if (!ll_temac_indirect_get(regs, TEMAC_EMMC, &emmc_reg))
  147. return 0;
  148. emmc_reg &= ~EMMC_LSPD_MASK;
  149. emmc_reg |= speed;
  150. if (!ll_temac_indirect_set(regs, TEMAC_EMMC, emmc_reg))
  151. return 0;
  152. printf("%s: PHY is %s with %dbase%s, %s%s\n",
  153. dev->name, phydev->drv->name,
  154. phydev->speed, (phydev->port == PORT_TP) ? "T" : "X",
  155. (phydev->duplex) ? "FDX" : "HDX",
  156. (phydev->port == PORT_OTHER) ? ", unkown mode" : "");
  157. return 1;
  158. }
  159. /* setup mac addr */
  160. static int ll_temac_setup_mac_addr(struct eth_device *dev)
  161. {
  162. struct temac_reg *regs = (struct temac_reg *)dev->iobase;
  163. u32 val;
  164. /* set up unicast MAC address filter */
  165. val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
  166. (dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
  167. val &= UAW0_UADDR_MASK;
  168. if (!ll_temac_indirect_set(regs, TEMAC_UAW0, val))
  169. return 1;
  170. val = ((dev->enetaddr[5] << 8) | dev->enetaddr[4]);
  171. val &= UAW1_UADDR_MASK;
  172. if (!ll_temac_indirect_set(regs, TEMAC_UAW1, val))
  173. return 1;
  174. return 0;
  175. }
  176. /* halt device */
  177. static void ll_temac_halt(struct eth_device *dev)
  178. {
  179. struct ll_temac *ll_temac = dev->priv;
  180. struct temac_reg *regs = (struct temac_reg *)dev->iobase;
  181. /* Disable Receiver */
  182. ll_temac_indirect_set(regs, TEMAC_RCW0, 0);
  183. /* Disable Transmitter */
  184. ll_temac_indirect_set(regs, TEMAC_TC, 0);
  185. if (ll_temac->ctrlhalt)
  186. ll_temac->ctrlhalt(dev);
  187. /* Shut down the PHY, as needed */
  188. phy_shutdown(ll_temac->phydev);
  189. }
  190. static int ll_temac_init(struct eth_device *dev, bd_t *bis)
  191. {
  192. struct ll_temac *ll_temac = dev->priv;
  193. int ret;
  194. printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
  195. dev->name, dev->index, dev->iobase);
  196. if (!ll_temac_setup_ctrl(dev))
  197. return -1;
  198. /* Start up the PHY */
  199. ret = phy_startup(ll_temac->phydev);
  200. if (ret) {
  201. printf("%s: Could not initialize PHY %s\n",
  202. dev->name, ll_temac->phydev->dev->name);
  203. return ret;
  204. }
  205. if (!ll_temac_adjust_link(dev)) {
  206. ll_temac_halt(dev);
  207. return -1;
  208. }
  209. /* If there's no link, fail */
  210. return ll_temac->phydev->link ? 0 : -1;
  211. }
  212. /*
  213. * Discover which PHY is attached to the device, and configure it
  214. * properly. If the PHY is not recognized, then return 0
  215. * (failure). Otherwise, return 1
  216. */
  217. static int ll_temac_phy_init(struct eth_device *dev)
  218. {
  219. struct ll_temac *ll_temac = dev->priv;
  220. struct phy_device *phydev;
  221. unsigned int supported = PHY_GBIT_FEATURES;
  222. /* interface - look at driver/net/tsec.c */
  223. phydev = phy_connect(ll_temac->bus, ll_temac->phyaddr,
  224. dev, PHY_INTERFACE_MODE_NONE);
  225. phydev->supported &= supported;
  226. phydev->advertising = phydev->supported;
  227. ll_temac->phydev = phydev;
  228. phy_config(phydev);
  229. return 1;
  230. }
  231. /*
  232. * Initialize a single ll_temac devices
  233. *
  234. * Returns the result of ll_temac phy interface that were initialized
  235. */
  236. int xilinx_ll_temac_initialize(bd_t *bis, struct ll_temac_info *devinf)
  237. {
  238. struct eth_device *dev;
  239. struct ll_temac *ll_temac;
  240. dev = calloc(1, sizeof(*dev));
  241. if (dev == NULL)
  242. return 0;
  243. ll_temac = calloc(1, sizeof(struct ll_temac));
  244. if (ll_temac == NULL) {
  245. free(dev);
  246. return 0;
  247. }
  248. /* use given name or generate its own unique name */
  249. if (devinf->devname) {
  250. strncpy(dev->name, devinf->devname, sizeof(dev->name));
  251. } else {
  252. snprintf(dev->name, sizeof(dev->name), "lltemac.%lx", devinf->base_addr);
  253. devinf->devname = dev->name;
  254. }
  255. dev->iobase = devinf->base_addr;
  256. dev->priv = ll_temac;
  257. dev->init = ll_temac_init;
  258. dev->halt = ll_temac_halt;
  259. dev->write_hwaddr = ll_temac_setup_mac_addr;
  260. ll_temac->ctrladdr = devinf->ctrl_addr;
  261. if (devinf->flags & XILINX_LL_TEMAC_M_SDMA_PLB) {
  262. #if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
  263. if (devinf->flags & XILINX_LL_TEMAC_M_SDMA_DCR) {
  264. ll_temac_collect_xldcr_sdma_reg_addr(dev);
  265. ll_temac->in32 = ll_temac_xldcr_in32;
  266. ll_temac->out32 = ll_temac_xldcr_out32;
  267. } else
  268. #endif
  269. {
  270. ll_temac_collect_xlplb_sdma_reg_addr(dev);
  271. ll_temac->in32 = ll_temac_xlplb_in32;
  272. ll_temac->out32 = ll_temac_xlplb_out32;
  273. }
  274. ll_temac->ctrlinit = ll_temac_init_sdma;
  275. ll_temac->ctrlhalt = ll_temac_halt_sdma;
  276. ll_temac->ctrlreset = ll_temac_reset_sdma;
  277. dev->recv = ll_temac_recv_sdma;
  278. dev->send = ll_temac_send_sdma;
  279. } else {
  280. ll_temac->in32 = NULL;
  281. ll_temac->out32 = NULL;
  282. ll_temac->ctrlinit = NULL;
  283. ll_temac->ctrlhalt = NULL;
  284. ll_temac->ctrlreset = ll_temac_reset_fifo;
  285. dev->recv = ll_temac_recv_fifo;
  286. dev->send = ll_temac_send_fifo;
  287. }
  288. /* Link to specified MDIO bus */
  289. strncpy(ll_temac->mdio_busname, devinf->mdio_busname, MDIO_NAME_LEN);
  290. ll_temac->bus = miiphy_get_dev_by_name(ll_temac->mdio_busname);
  291. /* Looking for a valid PHY address if it is not yet set */
  292. if (devinf->phyaddr == -1)
  293. ll_temac->phyaddr = ll_temac_phy_addr(ll_temac->bus);
  294. else
  295. ll_temac->phyaddr = devinf->phyaddr;
  296. eth_register(dev);
  297. /* Try to initialize PHY here, and return */
  298. return ll_temac_phy_init(dev);
  299. }
  300. /*
  301. * Initialize a single ll_temac device with its mdio bus behind ll_temac
  302. *
  303. * Returns 1 if the ll_temac device and the mdio bus were initialized
  304. * otherwise returns 0
  305. */
  306. int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
  307. unsigned long ctrl_addr)
  308. {
  309. struct ll_temac_info devinf;
  310. struct ll_temac_mdio_info mdioinf;
  311. int ret;
  312. /* prepare the internal driver informations */
  313. devinf.flags = flags;
  314. devinf.base_addr = base_addr;
  315. devinf.ctrl_addr = ctrl_addr;
  316. devinf.devname = NULL;
  317. devinf.phyaddr = -1;
  318. mdioinf.name = devinf.mdio_busname = NULL;
  319. mdioinf.regs = (struct temac_reg *)devinf.base_addr;
  320. ret = xilinx_ll_temac_mdio_initialize(bis, &mdioinf);
  321. if (ret >= 0) {
  322. /*
  323. * If there was no MDIO bus name then take over the
  324. * new automaticaly generated by the MDIO init code.
  325. */
  326. if (mdioinf.name != devinf.mdio_busname)
  327. devinf.mdio_busname = mdioinf.name;
  328. ret = xilinx_ll_temac_initialize(bis, &devinf);
  329. if (ret > 0)
  330. return 1;
  331. }
  332. return 0;
  333. }