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