blob: 222d327bdd0832f924e3e3f8e4b9ecc4121b1328 [file] [log] [blame]
Yuiko Oshino281a0c72017-08-11 12:44:58 -04001/*
2 * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <dm.h>
8#include <malloc.h>
9#include <miiphy.h>
10#include <memalign.h>
11#include <usb.h>
12#include <linux/ethtool.h>
13#include <linux/mii.h>
14#include "usb_ether.h"
15#include "lan7x.h"
16
17/*
18 * Lan7x infrastructure commands
19 */
20int lan7x_write_reg(struct usb_device *udev, u32 index, u32 data)
21{
22 int len;
23 ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
24
25 cpu_to_le32s(&data);
26 tmpbuf[0] = data;
27
28 len = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
29 USB_VENDOR_REQUEST_WRITE_REGISTER,
30 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
31 0, index, tmpbuf, sizeof(data),
32 USB_CTRL_SET_TIMEOUT_MS);
33 if (len != sizeof(data)) {
34 debug("%s failed: index=%d, data=%d, len=%d",
35 __func__, index, data, len);
36 return -EIO;
37 }
38 return 0;
39}
40
41int lan7x_read_reg(struct usb_device *udev, u32 index, u32 *data)
42{
43 int len;
44 ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
45
46 len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
47 USB_VENDOR_REQUEST_READ_REGISTER,
48 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
49 0, index, tmpbuf, sizeof(*data),
50 USB_CTRL_GET_TIMEOUT_MS);
51 *data = tmpbuf[0];
52 if (len != sizeof(*data)) {
53 debug("%s failed: index=%d, len=%d", __func__, index, len);
54 return -EIO;
55 }
56
57 le32_to_cpus(data);
58 return 0;
59}
60
61static int lan7x_phy_wait_not_busy(struct usb_device *udev)
62{
63 return lan7x_wait_for_bit(udev, __func__,
64 MII_ACC, MII_ACC_MII_BUSY,
65 false, 100, 0);
66}
67
68int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx)
69{
70 u32 val, addr;
71
72 /* confirm MII not busy */
73 if (lan7x_phy_wait_not_busy(udev)) {
74 debug("MII is busy in %s\n", __func__);
75 return -ETIMEDOUT;
76 }
77
78 /* set the address, index & direction (read from PHY) */
79 addr = (phy_id << 11) | (idx << 6) |
80 MII_ACC_MII_READ | MII_ACC_MII_BUSY;
81 lan7x_write_reg(udev, MII_ACC, addr);
82
83 if (lan7x_phy_wait_not_busy(udev)) {
84 debug("Timed out reading MII reg %02X\n", idx);
85 return -ETIMEDOUT;
86 }
87
88 lan7x_read_reg(udev, MII_DATA, &val);
89
90 return val & 0xFFFF;
91}
92
93void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx, int regval)
94{
95 u32 addr;
96
97 /* confirm MII not busy */
98 if (lan7x_phy_wait_not_busy(udev)) {
99 debug("MII is busy in %s\n", __func__);
100 return;
101 }
102
103 lan7x_write_reg(udev, MII_DATA, regval);
104
105 /* set the address, index & direction (write to PHY) */
106 addr = (phy_id << 11) | (idx << 6) |
107 MII_ACC_MII_WRITE | MII_ACC_MII_BUSY;
108 lan7x_write_reg(udev, MII_ACC, addr);
109
110 if (lan7x_phy_wait_not_busy(udev))
111 debug("Timed out writing MII reg %02X\n", idx);
112}
113
114/*
115 * Lan7x phylib wrappers
116 */
117static int lan7x_phylib_mdio_read(struct mii_dev *bus,
118 int addr, int devad, int reg)
119{
120 struct usb_device *udev = dev_get_parent_priv(bus->priv);
121
122 return lan7x_mdio_read(udev, addr, reg);
123}
124
125static int lan7x_phylib_mdio_write(struct mii_dev *bus,
126 int addr, int devad, int reg, u16 val)
127{
128 struct usb_device *udev = dev_get_parent_priv(bus->priv);
129
130 lan7x_mdio_write(udev, addr, reg, (int)val);
131
132 return 0;
133}
134
135/*
136 * Lan7x eeprom functions
137 */
138static int lan7x_eeprom_confirm_not_busy(struct usb_device *udev)
139{
140 return lan7x_wait_for_bit(udev, __func__,
141 E2P_CMD, E2P_CMD_EPC_BUSY,
142 false, 100, 0);
143}
144
145static int lan7x_wait_eeprom(struct usb_device *udev)
146{
147 return lan7x_wait_for_bit(udev, __func__,
148 E2P_CMD,
149 (E2P_CMD_EPC_BUSY | E2P_CMD_EPC_TIMEOUT),
150 false, 100, 0);
151}
152
153static int lan7x_read_eeprom(struct usb_device *udev,
154 u32 offset, u32 length, u8 *data)
155{
156 u32 val;
157 int i, ret;
158
159 ret = lan7x_eeprom_confirm_not_busy(udev);
160 if (ret)
161 return ret;
162
163 for (i = 0; i < length; i++) {
164 val = E2P_CMD_EPC_BUSY | E2P_CMD_EPC_CMD_READ |
165 (offset & E2P_CMD_EPC_ADDR_MASK);
166 lan7x_write_reg(udev, E2P_CMD, val);
167
168 ret = lan7x_wait_eeprom(udev);
169 if (ret)
170 return ret;
171
172 lan7x_read_reg(udev, E2P_DATA, &val);
173 data[i] = val & 0xFF;
174 offset++;
175 }
176 return ret;
177}
178
179/*
180 * Lan7x phylib functions
181 */
182int lan7x_phylib_register(struct udevice *udev)
183{
184 struct usb_device *usbdev = dev_get_parent_priv(udev);
185 struct lan7x_private *priv = dev_get_priv(udev);
186 int ret;
187
188 priv->mdiobus = mdio_alloc();
189 if (!priv->mdiobus) {
190 printf("mdio_alloc failed\n");
191 return -ENOMEM;
192 }
193 priv->mdiobus->read = lan7x_phylib_mdio_read;
194 priv->mdiobus->write = lan7x_phylib_mdio_write;
195 sprintf(priv->mdiobus->name,
196 "lan7x_mdiobus-d%hu-p%hu", usbdev->devnum, usbdev->portnr);
197 priv->mdiobus->priv = (void *)udev;
198
199 ret = mdio_register(priv->mdiobus);
200 if (ret) {
201 printf("mdio_register failed\n");
202 free(priv->mdiobus);
203 return -ENOMEM;
204 }
205
206 return 0;
207}
208
209int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev)
210{
211 struct lan7x_private *priv = dev_get_priv(udev);
212
213 priv->phydev = phy_connect(priv->mdiobus, dev->phy_id,
214 udev, PHY_INTERFACE_MODE_MII);
215
216 if (!priv->phydev) {
217 printf("phy_connect failed\n");
218 return -ENODEV;
219 }
220 return 0;
221}
222
223int lan7x_eth_phylib_config_start(struct udevice *udev)
224{
225 struct lan7x_private *priv = dev_get_priv(udev);
226 int ret;
227
228 /* configure supported modes */
229 priv->phydev->supported = PHY_BASIC_FEATURES |
230 SUPPORTED_1000baseT_Full |
231 SUPPORTED_Pause |
232 SUPPORTED_Asym_Pause;
233
234 priv->phydev->advertising = ADVERTISED_10baseT_Half |
235 ADVERTISED_10baseT_Full |
236 ADVERTISED_100baseT_Half |
237 ADVERTISED_100baseT_Full |
238 ADVERTISED_1000baseT_Full |
239 ADVERTISED_Pause |
240 ADVERTISED_Asym_Pause |
241 ADVERTISED_Autoneg;
242
243 priv->phydev->autoneg = AUTONEG_ENABLE;
244
245 ret = genphy_config_aneg(priv->phydev);
246 if (ret) {
247 printf("genphy_config_aneg failed\n");
248 return ret;
249 }
250 ret = phy_startup(priv->phydev);
251 if (ret) {
252 printf("phy_startup failed\n");
253 return ret;
254 }
255
256 debug("** %s() speed %i duplex %i adv %X supp %X\n", __func__,
257 priv->phydev->speed, priv->phydev->duplex,
258 priv->phydev->advertising, priv->phydev->supported);
259
260 return 0;
261}
262
263int lan7x_update_flowcontrol(struct usb_device *udev,
264 struct ueth_data *dev,
265 uint32_t *flow, uint32_t *fct_flow)
266{
267 uint32_t lcladv, rmtadv;
268 u8 cap = 0;
269 struct lan7x_private *priv = dev_get_priv(udev->dev);
270
271 debug("** %s()\n", __func__);
272 debug("** %s() priv->phydev->speed %i duplex %i\n", __func__,
273 priv->phydev->speed, priv->phydev->duplex);
274
275 if (priv->phydev->duplex == DUPLEX_FULL) {
276 lcladv = lan7x_mdio_read(udev, dev->phy_id, MII_ADVERTISE);
277 rmtadv = lan7x_mdio_read(udev, dev->phy_id, MII_LPA);
278 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
279
280 debug("TX Flow ");
281 if (cap & FLOW_CTRL_TX) {
282 *flow = (FLOW_CR_TX_FCEN | 0xFFFF);
283 /* set fct_flow thresholds to 20% and 80% */
284 *fct_flow = ((MAX_RX_FIFO_SIZE * 2) / (10 * 512))
285 & 0x7FUL;
286 *fct_flow <<= 8UL;
287 *fct_flow |= ((MAX_RX_FIFO_SIZE * 8) / (10 * 512))
288 & 0x7FUL;
289 debug("EN ");
290 } else {
291 debug("DIS ");
292 }
293 debug("RX Flow ");
294 if (cap & FLOW_CTRL_RX) {
295 *flow |= FLOW_CR_RX_FCEN;
296 debug("EN");
297 } else {
298 debug("DIS");
299 }
300 }
301 debug("\n");
302 return 0;
303}
304
305int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev)
306{
307 int ret;
308
309 memset(enetaddr, 0, 6);
310
311 ret = lan7x_read_eeprom(udev, 0, 1, enetaddr);
312
313 if ((ret == 0) && (enetaddr[0] == EEPROM_INDICATOR)) {
314 ret = lan7x_read_eeprom(udev,
315 EEPROM_MAC_OFFSET, ETH_ALEN,
316 enetaddr);
317 if ((ret == 0) && is_valid_ethaddr(enetaddr)) {
318 /* eeprom values are valid so use them */
319 debug("MAC address read from EEPROM %pM\n",
320 enetaddr);
321 return 0;
322 }
323 }
324 debug("MAC address read from EEPROM invalid %pM\n", enetaddr);
325
326 memset(enetaddr, 0, 6);
327 return -EINVAL;
328}
329
330int lan7x_pmt_phy_reset(struct usb_device *udev,
331 struct ueth_data *dev)
332{
333 int ret;
334 u32 data;
335
336 ret = lan7x_read_reg(udev, PMT_CTL, &data);
337 if (ret)
338 return ret;
339 ret = lan7x_write_reg(udev, PMT_CTL, data | PMT_CTL_PHY_RST);
340 if (ret)
341 return ret;
342
343 /* for LAN7x, we need to check PMT_CTL_READY asserted */
344 ret = lan7x_wait_for_bit(udev, "PMT_CTL_PHY_RST",
345 PMT_CTL, PMT_CTL_PHY_RST,
346 false, 1000, 0); /* could take over 125mS */
347 if (ret)
348 return ret;
349
350 return lan7x_wait_for_bit(udev, "PMT_CTL_READY",
351 PMT_CTL, PMT_CTL_READY,
352 true, 1000, 0);
353}
354
355int lan7x_basic_reset(struct usb_device *udev,
356 struct ueth_data *dev)
357{
358 int ret;
359
360 dev->phy_id = LAN7X_INTERNAL_PHY_ID; /* fixed phy id */
361
362 ret = lan7x_write_reg(udev, HW_CFG, HW_CFG_LRST);
363 if (ret)
364 return ret;
365
366 ret = lan7x_wait_for_bit(udev, "HW_CFG_LRST",
367 HW_CFG, HW_CFG_LRST,
368 false, 1000, 0);
369 if (ret)
370 return ret;
371
372 debug("USB devnum %d portnr %d\n", udev->devnum, udev->portnr);
373
374 return lan7x_pmt_phy_reset(udev, dev);
375}
376
377void lan7x_eth_stop(struct udevice *dev)
378{
379 debug("** %s()\n", __func__);
380}
381
382int lan7x_eth_send(struct udevice *dev, void *packet, int length)
383{
384 struct lan7x_private *priv = dev_get_priv(dev);
385 struct ueth_data *ueth = &priv->ueth;
386 int err;
387 int actual_len;
388 u32 tx_cmd_a;
389 u32 tx_cmd_b;
390 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
391 PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
392
393 debug("** %s(), len %d, buf %#x\n", __func__, length,
394 (unsigned int)(ulong) msg);
395 if (length > PKTSIZE)
396 return -ENOSPC;
397
398 /* LAN7x disable all TX offload features for u-boot */
399 tx_cmd_a = (u32) (length & TX_CMD_A_LEN_MASK) | TX_CMD_A_FCS;
400 tx_cmd_b = 0;
401 cpu_to_le32s(&tx_cmd_a);
402 cpu_to_le32s(&tx_cmd_b);
403
404 /* prepend cmd_a and cmd_b */
405 memcpy(msg, &tx_cmd_a, sizeof(tx_cmd_a));
406 memcpy(msg + sizeof(tx_cmd_a), &tx_cmd_b, sizeof(tx_cmd_b));
407 memcpy(msg + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), (void *)packet,
408 length);
409 err = usb_bulk_msg(ueth->pusb_dev,
410 usb_sndbulkpipe(ueth->pusb_dev, ueth->ep_out),
411 (void *)msg,
412 length + sizeof(tx_cmd_a) +
413 sizeof(tx_cmd_b),
414 &actual_len, USB_BULK_SEND_TIMEOUT_MS);
415 debug("Tx: len = %u, actual = %u, err = %d\n",
416 (unsigned int)(length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)),
417 (unsigned int)actual_len, err);
418
419 return err;
420}
421
422int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp)
423{
424 struct lan7x_private *priv = dev_get_priv(dev);
425 struct ueth_data *ueth = &priv->ueth;
426 uint8_t *ptr;
427 int ret, len;
428 u32 packet_len = 0;
429 u32 rx_cmd_a = 0;
430
431 len = usb_ether_get_rx_bytes(ueth, &ptr);
432 debug("%s: first try, len=%d\n", __func__, len);
433 if (!len) {
434 if (!(flags & ETH_RECV_CHECK_DEVICE))
435 return -EAGAIN;
436 ret = usb_ether_receive(ueth, RX_URB_SIZE);
437 if (ret == -EAGAIN)
438 return ret;
439
440 len = usb_ether_get_rx_bytes(ueth, &ptr);
441 debug("%s: second try, len=%d\n", __func__, len);
442 }
443
444 /*
445 * 1st 4 bytes contain the length of the actual data plus error info.
446 * Extract data length.
447 */
448 if (len < sizeof(packet_len)) {
449 debug("Rx: incomplete packet length\n");
450 goto err;
451 }
452 memcpy(&rx_cmd_a, ptr, sizeof(rx_cmd_a));
453 le32_to_cpus(&rx_cmd_a);
454 if (rx_cmd_a & RX_CMD_A_RXE) {
455 debug("Rx: Error header=%#x", rx_cmd_a);
456 goto err;
457 }
458 packet_len = (u16) (rx_cmd_a & RX_CMD_A_LEN_MASK);
459
460 if (packet_len > len - sizeof(packet_len)) {
461 debug("Rx: too large packet: %d\n", packet_len);
462 goto err;
463 }
464
465 /*
466 * For LAN7x, the length in command A does not
467 * include command A, B, and C length.
468 * So use it as is.
469 */
470
471 *packetp = ptr + 10;
472 return packet_len;
473
474err:
475 usb_ether_advance_rxbuf(ueth, -1);
476 return -EINVAL;
477}
478
479int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
480{
481 struct lan7x_private *priv = dev_get_priv(dev);
482
483 packet_len = ALIGN(packet_len, 4);
484 usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
485
486 return 0;
487}
488
489int lan7x_eth_remove(struct udevice *dev)
490{
491 struct lan7x_private *priv = dev_get_priv(dev);
492
493 debug("** %s()\n", __func__);
494 free(priv->phydev);
495 mdio_unregister(priv->mdiobus);
496 mdio_free(priv->mdiobus);
497
498 return 0;
499}