xilinx_ll_temac.c 9.7 KB

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