mcs7830.c 25 KB

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