mcs7830.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /*
  2. * Copyright (c) 2013 Gerhard Sittig <gsi@denx.de>
  3. * based on the U-Boot Asix driver as well as information
  4. * from the Linux Moschip driver
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. /*
  9. * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices
  10. */
  11. #include <common.h>
  12. #include <dm.h>
  13. #include <errno.h>
  14. #include <linux/mii.h>
  15. #include <malloc.h>
  16. #include <memalign.h>
  17. #include <usb.h>
  18. #include "usb_ether.h"
  19. #define MCS7830_BASE_NAME "mcs"
  20. #define USBCALL_TIMEOUT 1000
  21. #define LINKSTATUS_TIMEOUT 5000 /* link status, connect timeout */
  22. #define LINKSTATUS_TIMEOUT_RES 50 /* link status, resolution in msec */
  23. #define MCS7830_RX_URB_SIZE 2048
  24. /* command opcodes */
  25. #define MCS7830_WR_BREQ 0x0d
  26. #define MCS7830_RD_BREQ 0x0e
  27. /* register layout, numerical offset specs for USB API calls */
  28. struct mcs7830_regs {
  29. uint8_t multicast_hashes[8];
  30. uint8_t packet_gap[2];
  31. uint8_t phy_data[2];
  32. uint8_t phy_command[2];
  33. uint8_t configuration;
  34. uint8_t ether_address[6];
  35. uint8_t frame_drop_count;
  36. uint8_t pause_threshold;
  37. };
  38. #define REG_MULTICAST_HASH offsetof(struct mcs7830_regs, multicast_hashes)
  39. #define REG_PHY_DATA offsetof(struct mcs7830_regs, phy_data)
  40. #define REG_PHY_CMD offsetof(struct mcs7830_regs, phy_command)
  41. #define REG_CONFIG offsetof(struct mcs7830_regs, configuration)
  42. #define REG_ETHER_ADDR offsetof(struct mcs7830_regs, ether_address)
  43. #define REG_FRAME_DROP_COUNTER offsetof(struct mcs7830_regs, frame_drop_count)
  44. #define REG_PAUSE_THRESHOLD offsetof(struct mcs7830_regs, pause_threshold)
  45. /* bit masks and default values for the above registers */
  46. #define PHY_CMD1_READ 0x40
  47. #define PHY_CMD1_WRITE 0x20
  48. #define PHY_CMD1_PHYADDR 0x01
  49. #define PHY_CMD2_PEND 0x80
  50. #define PHY_CMD2_READY 0x40
  51. #define CONF_CFG 0x80
  52. #define CONF_SPEED100 0x40
  53. #define CONF_FDX_ENABLE 0x20
  54. #define CONF_RXENABLE 0x10
  55. #define CONF_TXENABLE 0x08
  56. #define CONF_SLEEPMODE 0x04
  57. #define CONF_ALLMULTICAST 0x02
  58. #define CONF_PROMISCUOUS 0x01
  59. #define PAUSE_THRESHOLD_DEFAULT 0
  60. /* bit masks for the status byte which follows received ethernet frames */
  61. #define STAT_RX_FRAME_CORRECT 0x20
  62. #define STAT_RX_LARGE_FRAME 0x10
  63. #define STAT_RX_CRC_ERROR 0x08
  64. #define STAT_RX_ALIGNMENT_ERROR 0x04
  65. #define STAT_RX_LENGTH_ERROR 0x02
  66. #define STAT_RX_SHORT_FRAME 0x01
  67. /*
  68. * struct mcs7830_private - private driver data for an individual adapter
  69. * @config: shadow for the network adapter's configuration register
  70. * @mchash: shadow for the network adapter's multicast hash registers
  71. */
  72. struct mcs7830_private {
  73. #ifdef CONFIG_DM_ETH
  74. uint8_t rx_buf[MCS7830_RX_URB_SIZE];
  75. struct ueth_data ueth;
  76. #endif
  77. uint8_t config;
  78. uint8_t mchash[8];
  79. };
  80. /*
  81. * mcs7830_read_reg() - read a register of the network adapter
  82. * @udev: network device to read from
  83. * @idx: index of the register to start reading from
  84. * @size: number of bytes to read
  85. * @data: buffer to read into
  86. * Return: zero upon success, negative upon error
  87. */
  88. static int mcs7830_read_reg(struct usb_device *udev, uint8_t idx,
  89. uint16_t size, void *data)
  90. {
  91. int len;
  92. ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size);
  93. debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size);
  94. len = usb_control_msg(udev,
  95. usb_rcvctrlpipe(udev, 0),
  96. MCS7830_RD_BREQ,
  97. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  98. 0, idx, buf, size,
  99. USBCALL_TIMEOUT);
  100. if (len != size) {
  101. debug("%s() len=%d != sz=%d\n", __func__, len, size);
  102. return -EIO;
  103. }
  104. memcpy(data, buf, size);
  105. return 0;
  106. }
  107. /*
  108. * mcs7830_write_reg() - write a register of the network adapter
  109. * @udev: network device to write to
  110. * @idx: index of the register to start writing to
  111. * @size: number of bytes to write
  112. * @data: buffer holding the data to write
  113. * Return: zero upon success, negative upon error
  114. */
  115. static int mcs7830_write_reg(struct usb_device *udev, uint8_t idx,
  116. uint16_t size, void *data)
  117. {
  118. int len;
  119. ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size);
  120. debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size);
  121. memcpy(buf, data, size);
  122. len = usb_control_msg(udev,
  123. usb_sndctrlpipe(udev, 0),
  124. MCS7830_WR_BREQ,
  125. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  126. 0, idx, buf, size,
  127. USBCALL_TIMEOUT);
  128. if (len != size) {
  129. debug("%s() len=%d != sz=%d\n", __func__, len, size);
  130. return -EIO;
  131. }
  132. return 0;
  133. }
  134. /*
  135. * mcs7830_phy_emit_wait() - emit PHY read/write access, wait for its execution
  136. * @udev: network device to talk to
  137. * @rwflag: PHY_CMD1_READ or PHY_CMD1_WRITE opcode
  138. * @index: number of the PHY register to read or write
  139. * Return: zero upon success, negative upon error
  140. */
  141. static int mcs7830_phy_emit_wait(struct usb_device *udev,
  142. uint8_t rwflag, uint8_t index)
  143. {
  144. int rc;
  145. int retry;
  146. uint8_t cmd[2];
  147. /* send the PHY read/write request */
  148. cmd[0] = rwflag | PHY_CMD1_PHYADDR;
  149. cmd[1] = PHY_CMD2_PEND | (index & 0x1f);
  150. rc = mcs7830_write_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd);
  151. if (rc < 0)
  152. return rc;
  153. /* wait for the response to become available (usually < 1ms) */
  154. retry = 10;
  155. do {
  156. rc = mcs7830_read_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd);
  157. if (rc < 0)
  158. return rc;
  159. if (cmd[1] & PHY_CMD2_READY)
  160. return 0;
  161. if (!retry--)
  162. return -ETIMEDOUT;
  163. mdelay(1);
  164. } while (1);
  165. /* UNREACH */
  166. }
  167. /*
  168. * mcs7830_read_phy() - read a PHY register of the network adapter
  169. * @udev: network device to read from
  170. * @index: index of the PHY register to read from
  171. * Return: non-negative 16bit register content, negative upon error
  172. */
  173. static int mcs7830_read_phy(struct usb_device *udev, uint8_t index)
  174. {
  175. int rc;
  176. uint16_t val;
  177. /* issue the PHY read request and wait for its execution */
  178. rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_READ, index);
  179. if (rc < 0)
  180. return rc;
  181. /* fetch the PHY data which was read */
  182. rc = mcs7830_read_reg(udev, REG_PHY_DATA, sizeof(val), &val);
  183. if (rc < 0)
  184. return rc;
  185. rc = le16_to_cpu(val);
  186. debug("%s(%d) => 0x%04X\n", __func__, index, rc);
  187. return rc;
  188. }
  189. /*
  190. * mcs7830_write_phy() - write a PHY register of the network adapter
  191. * @udev: network device to write to
  192. * @index: index of the PHY register to write to
  193. * @val: value to write to the PHY register
  194. * Return: zero upon success, negative upon error
  195. */
  196. static int mcs7830_write_phy(struct usb_device *udev, uint8_t index,
  197. uint16_t val)
  198. {
  199. int rc;
  200. debug("%s(%d, 0x%04X)\n", __func__, index, val);
  201. /* setup the PHY data which is to get written */
  202. val = cpu_to_le16(val);
  203. rc = mcs7830_write_reg(udev, REG_PHY_DATA, sizeof(val), &val);
  204. if (rc < 0)
  205. return rc;
  206. /* issue the PHY write request and wait for its execution */
  207. rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_WRITE, index);
  208. if (rc < 0)
  209. return rc;
  210. return 0;
  211. }
  212. /*
  213. * mcs7830_write_config() - write to the network adapter's config register
  214. * @udev: network device to write to
  215. * @priv: private data
  216. * Return: zero upon success, negative upon error
  217. *
  218. * the data which gets written is taken from the shadow config register
  219. * within the device driver's private data
  220. */
  221. static int mcs7830_write_config(struct usb_device *udev,
  222. struct mcs7830_private *priv)
  223. {
  224. int rc;
  225. debug("%s()\n", __func__);
  226. rc = mcs7830_write_reg(udev, REG_CONFIG,
  227. sizeof(priv->config), &priv->config);
  228. if (rc < 0) {
  229. debug("writing config to adapter failed\n");
  230. return rc;
  231. }
  232. return 0;
  233. }
  234. /*
  235. * mcs7830_write_mchash() - write the network adapter's multicast filter
  236. * @udev: network device to write to
  237. * @priv: private data
  238. * Return: zero upon success, negative upon error
  239. *
  240. * the data which gets written is taken from the shadow multicast hashes
  241. * within the device driver's private data
  242. */
  243. static int mcs7830_write_mchash(struct usb_device *udev,
  244. struct mcs7830_private *priv)
  245. {
  246. int rc;
  247. debug("%s()\n", __func__);
  248. rc = mcs7830_write_reg(udev, REG_MULTICAST_HASH,
  249. sizeof(priv->mchash), &priv->mchash);
  250. if (rc < 0) {
  251. debug("writing multicast hash to adapter failed\n");
  252. return rc;
  253. }
  254. return 0;
  255. }
  256. /*
  257. * mcs7830_set_autoneg() - setup and trigger ethernet link autonegotiation
  258. * @udev: network device to run link negotiation on
  259. * Return: zero upon success, negative upon error
  260. *
  261. * the routine advertises available media and starts autonegotiation
  262. */
  263. static int mcs7830_set_autoneg(struct usb_device *udev)
  264. {
  265. int adv, flg;
  266. int rc;
  267. debug("%s()\n", __func__);
  268. /*
  269. * algorithm taken from the Linux driver, which took it from
  270. * "the original mcs7830 version 1.4 driver":
  271. *
  272. * enable all media, reset BMCR, enable auto neg, restart
  273. * auto neg while keeping the enable auto neg flag set
  274. */
  275. adv = ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA;
  276. rc = mcs7830_write_phy(udev, MII_ADVERTISE, adv);
  277. flg = 0;
  278. if (!rc)
  279. rc = mcs7830_write_phy(udev, MII_BMCR, flg);
  280. flg |= BMCR_ANENABLE;
  281. if (!rc)
  282. rc = mcs7830_write_phy(udev, MII_BMCR, flg);
  283. flg |= BMCR_ANRESTART;
  284. if (!rc)
  285. rc = mcs7830_write_phy(udev, MII_BMCR, flg);
  286. return rc;
  287. }
  288. /*
  289. * mcs7830_get_rev() - identify a network adapter's chip revision
  290. * @udev: network device to identify
  291. * Return: non-negative number, reflecting the revision number
  292. *
  293. * currently, only "rev C and higher" and "below rev C" are needed, so
  294. * the return value is #1 for "below rev C", and #2 for "rev C and above"
  295. */
  296. static int mcs7830_get_rev(struct usb_device *udev)
  297. {
  298. uint8_t buf[2];
  299. int rc;
  300. int rev;
  301. /* register 22 is readable in rev C and higher */
  302. rc = mcs7830_read_reg(udev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf);
  303. if (rc < 0)
  304. rev = 1;
  305. else
  306. rev = 2;
  307. debug("%s() rc=%d, rev=%d\n", __func__, rc, rev);
  308. return rev;
  309. }
  310. /*
  311. * mcs7830_apply_fixup() - identify an adapter and potentially apply fixups
  312. * @udev: network device to identify and apply fixups to
  313. * Return: zero upon success (no errors emitted from here)
  314. *
  315. * this routine identifies the network adapter's chip revision, and applies
  316. * fixups for known issues
  317. */
  318. static int mcs7830_apply_fixup(struct usb_device *udev)
  319. {
  320. int rev;
  321. int i;
  322. uint8_t thr;
  323. rev = mcs7830_get_rev(udev);
  324. debug("%s() rev=%d\n", __func__, rev);
  325. /*
  326. * rev C requires setting the pause threshold (the Linux driver
  327. * is inconsistent, the implementation does it for "rev C
  328. * exactly", the introductory comment says "rev C and above")
  329. */
  330. if (rev == 2) {
  331. debug("%s: applying rev C fixup\n", __func__);
  332. thr = PAUSE_THRESHOLD_DEFAULT;
  333. for (i = 0; i < 2; i++) {
  334. (void)mcs7830_write_reg(udev, REG_PAUSE_THRESHOLD,
  335. sizeof(thr), &thr);
  336. mdelay(1);
  337. }
  338. }
  339. return 0;
  340. }
  341. /*
  342. * mcs7830_basic_reset() - bring the network adapter into a known first state
  343. * @eth: network device to act upon
  344. * Return: zero upon success, negative upon error
  345. *
  346. * this routine initializes the network adapter such that subsequent invocations
  347. * of the interface callbacks can exchange ethernet frames; link negotiation is
  348. * triggered from here already and continues in background
  349. */
  350. static int mcs7830_basic_reset(struct usb_device *udev,
  351. struct mcs7830_private *priv)
  352. {
  353. int rc;
  354. debug("%s()\n", __func__);
  355. /*
  356. * comment from the respective Linux driver, which
  357. * unconditionally sets the ALLMULTICAST flag as well:
  358. * should not be needed, but does not work otherwise
  359. */
  360. priv->config = CONF_TXENABLE;
  361. priv->config |= CONF_ALLMULTICAST;
  362. rc = mcs7830_set_autoneg(udev);
  363. if (rc < 0) {
  364. error("setting autoneg failed\n");
  365. return rc;
  366. }
  367. rc = mcs7830_write_mchash(udev, priv);
  368. if (rc < 0) {
  369. error("failed to set multicast hash\n");
  370. return rc;
  371. }
  372. rc = mcs7830_write_config(udev, priv);
  373. if (rc < 0) {
  374. error("failed to set configuration\n");
  375. return rc;
  376. }
  377. rc = mcs7830_apply_fixup(udev);
  378. if (rc < 0) {
  379. error("fixup application failed\n");
  380. return rc;
  381. }
  382. return 0;
  383. }
  384. /*
  385. * mcs7830_read_mac() - read an ethernet adapter's MAC address
  386. * @udev: network device to read from
  387. * @enetaddr: place to put ethernet MAC address
  388. * Return: zero upon success, negative upon error
  389. *
  390. * this routine fetches the MAC address stored within the ethernet adapter,
  391. * and stores it in the ethernet interface's data structure
  392. */
  393. static int mcs7830_read_mac(struct usb_device *udev, unsigned char enetaddr[])
  394. {
  395. int rc;
  396. uint8_t buf[ETH_ALEN];
  397. debug("%s()\n", __func__);
  398. rc = mcs7830_read_reg(udev, REG_ETHER_ADDR, ETH_ALEN, buf);
  399. if (rc < 0) {
  400. debug("reading MAC from adapter failed\n");
  401. return rc;
  402. }
  403. memcpy(enetaddr, buf, ETH_ALEN);
  404. return 0;
  405. }
  406. static int mcs7830_write_mac_common(struct usb_device *udev,
  407. unsigned char enetaddr[])
  408. {
  409. int rc;
  410. debug("%s()\n", __func__);
  411. rc = mcs7830_write_reg(udev, REG_ETHER_ADDR, ETH_ALEN, enetaddr);
  412. if (rc < 0) {
  413. debug("writing MAC to adapter failed\n");
  414. return rc;
  415. }
  416. return 0;
  417. }
  418. static int mcs7830_init_common(struct usb_device *udev)
  419. {
  420. int timeout;
  421. int have_link;
  422. debug("%s()\n", __func__);
  423. timeout = 0;
  424. do {
  425. have_link = mcs7830_read_phy(udev, MII_BMSR) & BMSR_LSTATUS;
  426. if (have_link)
  427. break;
  428. udelay(LINKSTATUS_TIMEOUT_RES * 1000);
  429. timeout += LINKSTATUS_TIMEOUT_RES;
  430. } while (timeout < LINKSTATUS_TIMEOUT);
  431. if (!have_link) {
  432. debug("ethernet link is down\n");
  433. return -ETIMEDOUT;
  434. }
  435. return 0;
  436. }
  437. static int mcs7830_send_common(struct ueth_data *ueth, void *packet,
  438. int length)
  439. {
  440. struct usb_device *udev = ueth->pusb_dev;
  441. int rc;
  442. int gotlen;
  443. /* there is a status byte after the ethernet frame */
  444. ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, PKTSIZE + sizeof(uint8_t));
  445. memcpy(buf, packet, length);
  446. rc = usb_bulk_msg(udev,
  447. usb_sndbulkpipe(udev, ueth->ep_out),
  448. &buf[0], length, &gotlen,
  449. USBCALL_TIMEOUT);
  450. debug("%s() TX want len %d, got len %d, rc %d\n",
  451. __func__, length, gotlen, rc);
  452. return rc;
  453. }
  454. static int mcs7830_recv_common(struct ueth_data *ueth, uint8_t *buf)
  455. {
  456. int rc, wantlen, gotlen;
  457. uint8_t sts;
  458. debug("%s()\n", __func__);
  459. /* fetch input data from the adapter */
  460. wantlen = MCS7830_RX_URB_SIZE;
  461. rc = usb_bulk_msg(ueth->pusb_dev,
  462. usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in),
  463. &buf[0], wantlen, &gotlen,
  464. USBCALL_TIMEOUT);
  465. debug("%s() RX want len %d, got len %d, rc %d\n",
  466. __func__, wantlen, gotlen, rc);
  467. if (rc != 0) {
  468. error("RX: failed to receive\n");
  469. return rc;
  470. }
  471. if (gotlen > wantlen) {
  472. error("RX: got too many bytes (%d)\n", gotlen);
  473. return -EIO;
  474. }
  475. /*
  476. * the bulk message that we received from USB contains exactly
  477. * one ethernet frame and a trailing status byte
  478. */
  479. if (gotlen < sizeof(sts))
  480. return -EIO;
  481. gotlen -= sizeof(sts);
  482. sts = buf[gotlen];
  483. if (sts == STAT_RX_FRAME_CORRECT) {
  484. debug("%s() got a frame, len=%d\n", __func__, gotlen);
  485. return gotlen;
  486. }
  487. debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n",
  488. sts,
  489. (sts & STAT_RX_LARGE_FRAME) ? "large" : "-",
  490. (sts & STAT_RX_LENGTH_ERROR) ? "length" : "-",
  491. (sts & STAT_RX_SHORT_FRAME) ? "short" : "-",
  492. (sts & STAT_RX_CRC_ERROR) ? "crc" : "-",
  493. (sts & STAT_RX_ALIGNMENT_ERROR) ? "align" : "-");
  494. return -EIO;
  495. }
  496. #ifndef CONFIG_DM_ETH
  497. /*
  498. * mcs7830_init() - network interface's init callback
  499. * @udev: network device to initialize
  500. * @bd: board information
  501. * Return: zero upon success, negative upon error
  502. *
  503. * after initial setup during probe() and get_info(), this init() callback
  504. * ensures that the link is up and subsequent send() and recv() calls can
  505. * exchange ethernet frames
  506. */
  507. static int mcs7830_init(struct eth_device *eth, bd_t *bd)
  508. {
  509. struct ueth_data *dev = eth->priv;
  510. return mcs7830_init_common(dev->pusb_dev);
  511. }
  512. /*
  513. * mcs7830_send() - network interface's send callback
  514. * @eth: network device to send the frame from
  515. * @packet: ethernet frame content
  516. * @length: ethernet frame length
  517. * Return: zero upon success, negative upon error
  518. *
  519. * this routine send an ethernet frame out of the network interface
  520. */
  521. static int mcs7830_send(struct eth_device *eth, void *packet, int length)
  522. {
  523. struct ueth_data *dev = eth->priv;
  524. return mcs7830_send_common(dev, packet, length);
  525. }
  526. /*
  527. * mcs7830_recv() - network interface's recv callback
  528. * @eth: network device to receive frames from
  529. * Return: zero upon success, negative upon error
  530. *
  531. * this routine checks for available ethernet frames that the network
  532. * interface might have received, and notifies the network stack
  533. */
  534. static int mcs7830_recv(struct eth_device *eth)
  535. {
  536. ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE);
  537. struct ueth_data *ueth = eth->priv;
  538. int len;
  539. len = mcs7830_recv_common(ueth, buf);
  540. if (len <= 0)
  541. net_process_received_packet(buf, len);
  542. return 0;
  543. }
  544. /*
  545. * mcs7830_halt() - network interface's halt callback
  546. * @eth: network device to cease operation of
  547. * Return: none
  548. *
  549. * this routine is supposed to undo the effect of previous initialization and
  550. * ethernet frames exchange; in this implementation it's a NOP
  551. */
  552. static void mcs7830_halt(struct eth_device *eth)
  553. {
  554. debug("%s()\n", __func__);
  555. }
  556. /*
  557. * mcs7830_write_mac() - write an ethernet adapter's MAC address
  558. * @eth: network device to write to
  559. * Return: zero upon success, negative upon error
  560. *
  561. * this routine takes the MAC address from the ethernet interface's data
  562. * structure, and writes it into the ethernet adapter such that subsequent
  563. * exchange of ethernet frames uses this address
  564. */
  565. static int mcs7830_write_mac(struct eth_device *eth)
  566. {
  567. struct ueth_data *ueth = eth->priv;
  568. return mcs7830_write_mac_common(ueth->pusb_dev, eth->enetaddr);
  569. }
  570. /*
  571. * mcs7830_iface_idx - index of detected network interfaces
  572. *
  573. * this counter keeps track of identified supported interfaces,
  574. * to assign unique names as more interfaces are found
  575. */
  576. static int mcs7830_iface_idx;
  577. /*
  578. * mcs7830_eth_before_probe() - network driver's before_probe callback
  579. * Return: none
  580. *
  581. * this routine initializes driver's internal data in preparation of
  582. * subsequent probe callbacks
  583. */
  584. void mcs7830_eth_before_probe(void)
  585. {
  586. mcs7830_iface_idx = 0;
  587. }
  588. /*
  589. * struct mcs7830_dongle - description of a supported Moschip ethernet dongle
  590. * @vendor: 16bit USB vendor identification
  591. * @product: 16bit USB product identification
  592. *
  593. * this structure describes a supported USB ethernet dongle by means of the
  594. * vendor and product codes found during USB enumeration; no flags are held
  595. * here since all supported dongles have identical behaviour, and required
  596. * fixups get determined at runtime, such that no manual configuration is
  597. * needed
  598. */
  599. struct mcs7830_dongle {
  600. uint16_t vendor;
  601. uint16_t product;
  602. };
  603. /*
  604. * mcs7830_dongles - the list of supported Moschip based USB ethernet dongles
  605. */
  606. static const struct mcs7830_dongle mcs7830_dongles[] = {
  607. { 0x9710, 0x7832, }, /* Moschip 7832 */
  608. { 0x9710, 0x7830, }, /* Moschip 7830 */
  609. { 0x9710, 0x7730, }, /* Moschip 7730 */
  610. { 0x0df6, 0x0021, }, /* Sitecom LN 30 */
  611. };
  612. /*
  613. * mcs7830_eth_probe() - network driver's probe callback
  614. * @dev: detected USB device to check
  615. * @ifnum: detected USB interface to check
  616. * @ss: USB ethernet data structure to fill in upon match
  617. * Return: #1 upon match, #0 upon mismatch or error
  618. *
  619. * this routine checks whether the found USB device is supported by
  620. * this ethernet driver, and upon match fills in the USB ethernet
  621. * data structure which later is passed to the get_info callback
  622. */
  623. int mcs7830_eth_probe(struct usb_device *dev, unsigned int ifnum,
  624. struct ueth_data *ss)
  625. {
  626. struct usb_interface *iface;
  627. struct usb_interface_descriptor *iface_desc;
  628. int i;
  629. struct mcs7830_private *priv;
  630. int ep_in_found, ep_out_found, ep_intr_found;
  631. debug("%s()\n", __func__);
  632. /* iterate the list of supported dongles */
  633. iface = &dev->config.if_desc[ifnum];
  634. iface_desc = &iface->desc;
  635. for (i = 0; i < ARRAY_SIZE(mcs7830_dongles); i++) {
  636. if (dev->descriptor.idVendor == mcs7830_dongles[i].vendor &&
  637. dev->descriptor.idProduct == mcs7830_dongles[i].product)
  638. break;
  639. }
  640. if (i == ARRAY_SIZE(mcs7830_dongles))
  641. return 0;
  642. debug("detected USB ethernet device: %04X:%04X\n",
  643. dev->descriptor.idVendor, dev->descriptor.idProduct);
  644. /* fill in driver private data */
  645. priv = calloc(1, sizeof(*priv));
  646. if (!priv)
  647. return 0;
  648. /* fill in the ueth_data structure, attach private data */
  649. memset(ss, 0, sizeof(*ss));
  650. ss->ifnum = ifnum;
  651. ss->pusb_dev = dev;
  652. ss->subclass = iface_desc->bInterfaceSubClass;
  653. ss->protocol = iface_desc->bInterfaceProtocol;
  654. ss->dev_priv = priv;
  655. /*
  656. * a minimum of three endpoints is expected: in (bulk),
  657. * out (bulk), and interrupt; ignore all others
  658. */
  659. ep_in_found = ep_out_found = ep_intr_found = 0;
  660. for (i = 0; i < iface_desc->bNumEndpoints; i++) {
  661. uint8_t eptype, epaddr;
  662. bool is_input;
  663. eptype = iface->ep_desc[i].bmAttributes;
  664. eptype &= USB_ENDPOINT_XFERTYPE_MASK;
  665. epaddr = iface->ep_desc[i].bEndpointAddress;
  666. is_input = epaddr & USB_DIR_IN;
  667. epaddr &= USB_ENDPOINT_NUMBER_MASK;
  668. if (eptype == USB_ENDPOINT_XFER_BULK) {
  669. if (is_input && !ep_in_found) {
  670. ss->ep_in = epaddr;
  671. ep_in_found++;
  672. }
  673. if (!is_input && !ep_out_found) {
  674. ss->ep_out = epaddr;
  675. ep_out_found++;
  676. }
  677. }
  678. if (eptype == USB_ENDPOINT_XFER_INT) {
  679. if (is_input && !ep_intr_found) {
  680. ss->ep_int = epaddr;
  681. ss->irqinterval = iface->ep_desc[i].bInterval;
  682. ep_intr_found++;
  683. }
  684. }
  685. }
  686. debug("endpoints: in %d, out %d, intr %d\n",
  687. ss->ep_in, ss->ep_out, ss->ep_int);
  688. /* apply basic sanity checks */
  689. if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
  690. !ss->ep_in || !ss->ep_out || !ss->ep_int) {
  691. debug("device probe incomplete\n");
  692. return 0;
  693. }
  694. dev->privptr = ss;
  695. return 1;
  696. }
  697. /*
  698. * mcs7830_eth_get_info() - network driver's get_info callback
  699. * @dev: detected USB device
  700. * @ss: USB ethernet data structure filled in at probe()
  701. * @eth: ethernet interface data structure to fill in
  702. * Return: #1 upon success, #0 upon error
  703. *
  704. * this routine registers the mandatory init(), send(), recv(), and
  705. * halt() callbacks with the ethernet interface, can register the
  706. * optional write_hwaddr() callback with the ethernet interface,
  707. * and initiates configuration of the interface such that subsequent
  708. * calls to those callbacks results in network communication
  709. */
  710. int mcs7830_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
  711. struct eth_device *eth)
  712. {
  713. debug("%s()\n", __func__);
  714. if (!eth) {
  715. debug("%s: missing parameter.\n", __func__);
  716. return 0;
  717. }
  718. snprintf(eth->name, sizeof(eth->name), "%s%d",
  719. MCS7830_BASE_NAME, mcs7830_iface_idx++);
  720. eth->init = mcs7830_init;
  721. eth->send = mcs7830_send;
  722. eth->recv = mcs7830_recv;
  723. eth->halt = mcs7830_halt;
  724. eth->write_hwaddr = mcs7830_write_mac;
  725. eth->priv = ss;
  726. if (mcs7830_basic_reset(ss->pusb_dev, ss->dev_priv))
  727. return 0;
  728. if (mcs7830_read_mac(ss->pusb_dev, eth->enetaddr))
  729. return 0;
  730. debug("MAC %pM\n", eth->enetaddr);
  731. return 1;
  732. }
  733. #endif
  734. #ifdef CONFIG_DM_ETH
  735. static int mcs7830_eth_start(struct udevice *dev)
  736. {
  737. struct usb_device *udev = dev_get_parent_priv(dev);
  738. return mcs7830_init_common(udev);
  739. }
  740. void mcs7830_eth_stop(struct udevice *dev)
  741. {
  742. debug("** %s()\n", __func__);
  743. }
  744. int mcs7830_eth_send(struct udevice *dev, void *packet, int length)
  745. {
  746. struct mcs7830_private *priv = dev_get_priv(dev);
  747. struct ueth_data *ueth = &priv->ueth;
  748. return mcs7830_send_common(ueth, packet, length);
  749. }
  750. int mcs7830_eth_recv(struct udevice *dev, int flags, uchar **packetp)
  751. {
  752. struct mcs7830_private *priv = dev_get_priv(dev);
  753. struct ueth_data *ueth = &priv->ueth;
  754. int len;
  755. len = mcs7830_recv_common(ueth, priv->rx_buf);
  756. *packetp = priv->rx_buf;
  757. return len;
  758. }
  759. static int mcs7830_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
  760. {
  761. struct mcs7830_private *priv = dev_get_priv(dev);
  762. packet_len = ALIGN(packet_len, 4);
  763. usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
  764. return 0;
  765. }
  766. int mcs7830_write_hwaddr(struct udevice *dev)
  767. {
  768. struct usb_device *udev = dev_get_parent_priv(dev);
  769. struct eth_pdata *pdata = dev_get_platdata(dev);
  770. return mcs7830_write_mac_common(udev, pdata->enetaddr);
  771. }
  772. static int mcs7830_eth_probe(struct udevice *dev)
  773. {
  774. struct usb_device *udev = dev_get_parent_priv(dev);
  775. struct mcs7830_private *priv = dev_get_priv(dev);
  776. struct eth_pdata *pdata = dev_get_platdata(dev);
  777. struct ueth_data *ueth = &priv->ueth;
  778. if (mcs7830_basic_reset(udev, priv))
  779. return 0;
  780. if (mcs7830_read_mac(udev, pdata->enetaddr))
  781. return 0;
  782. return usb_ether_register(dev, ueth, MCS7830_RX_URB_SIZE);
  783. }
  784. static const struct eth_ops mcs7830_eth_ops = {
  785. .start = mcs7830_eth_start,
  786. .send = mcs7830_eth_send,
  787. .recv = mcs7830_eth_recv,
  788. .free_pkt = mcs7830_free_pkt,
  789. .stop = mcs7830_eth_stop,
  790. .write_hwaddr = mcs7830_write_hwaddr,
  791. };
  792. U_BOOT_DRIVER(mcs7830_eth) = {
  793. .name = "mcs7830_eth",
  794. .id = UCLASS_ETH,
  795. .probe = mcs7830_eth_probe,
  796. .ops = &mcs7830_eth_ops,
  797. .priv_auto_alloc_size = sizeof(struct mcs7830_private),
  798. .platdata_auto_alloc_size = sizeof(struct eth_pdata),
  799. .flags = DM_FLAG_ALLOC_PRIV_DMA,
  800. };
  801. static const struct usb_device_id mcs7830_eth_id_table[] = {
  802. { USB_DEVICE(0x9710, 0x7832) }, /* Moschip 7832 */
  803. { USB_DEVICE(0x9710, 0x7830), }, /* Moschip 7830 */
  804. { USB_DEVICE(0x9710, 0x7730), }, /* Moschip 7730 */
  805. { USB_DEVICE(0x0df6, 0x0021), }, /* Sitecom LN 30 */
  806. { } /* Terminating entry */
  807. };
  808. U_BOOT_USB_DEVICE(mcs7830_eth, mcs7830_eth_id_table);
  809. #endif