mcs7830.c 25 KB

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