summaryrefslogtreecommitdiffstats
path: root/drivers/usb/eth/lan7x.h
blob: 7af610be37029f454ad2096b2c4d7206089907bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
 */

#include <console.h>
#include <watchdog.h>

/* USB Vendor Requests */
#define USB_VENDOR_REQUEST_WRITE_REGISTER	0xA0
#define USB_VENDOR_REQUEST_READ_REGISTER	0xA1
#define USB_VENDOR_REQUEST_GET_STATS		0xA2

/* Tx Command A */
#define TX_CMD_A_FCS			BIT(22)
#define TX_CMD_A_LEN_MASK		0x000FFFFF

/* Rx Command A */
#define RX_CMD_A_RXE			BIT(18)
#define RX_CMD_A_LEN_MASK		0x00003FFF

/* SCSRs */
#define ID_REV				0x00
#define ID_REV_CHIP_ID_MASK		0xFFFF0000
#define ID_REV_CHIP_ID_7500		0x7500
#define ID_REV_CHIP_ID_7800		0x7800
#define ID_REV_CHIP_ID_7850		0x7850

#define INT_STS				0x0C

#define HW_CFG				0x010
#define HW_CFG_LRST			BIT(1)

#define PMT_CTL				0x014
#define PMT_CTL_PHY_PWRUP		BIT(10)
#define PMT_CTL_READY			BIT(7)
#define PMT_CTL_PHY_RST			BIT(4)

#define E2P_CMD				0x040
#define E2P_CMD_EPC_BUSY		BIT(31)
#define E2P_CMD_EPC_CMD_READ		0x00000000
#define E2P_CMD_EPC_TIMEOUT		BIT(10)
#define E2P_CMD_EPC_ADDR_MASK		0x000001FF

#define E2P_DATA			0x044

#define RFE_CTL_BCAST_EN		BIT(10)
#define RFE_CTL_DA_PERFECT		BIT(1)

#define FCT_RX_CTL_EN			BIT(31)

#define FCT_TX_CTL_EN			BIT(31)

#define MAC_CR				0x100
#define MAC_CR_ADP			BIT(13)
#define MAC_CR_AUTO_DUPLEX		BIT(12)
#define MAC_CR_AUTO_SPEED		BIT(11)

#define MAC_RX				0x104
#define MAC_RX_FCS_STRIP		BIT(4)
#define MAC_RX_RXEN			BIT(0)

#define MAC_TX				0x108
#define MAC_TX_TXEN			BIT(0)

#define FLOW				0x10C
#define FLOW_CR_TX_FCEN			BIT(30)
#define FLOW_CR_RX_FCEN			BIT(29)

#define RX_ADDRH			0x118
#define RX_ADDRL			0x11C

#define MII_ACC				0x120
#define MII_ACC_MII_READ		0x00000000
#define MII_ACC_MII_WRITE		0x00000002
#define MII_ACC_MII_BUSY		BIT(0)

#define MII_DATA			0x124

#define SS_USB_PKT_SIZE			1024
#define HS_USB_PKT_SIZE			512
#define FS_USB_PKT_SIZE			64

#define MAX_RX_FIFO_SIZE		(12 * 1024)
#define MAX_TX_FIFO_SIZE		(12 * 1024)
#define DEFAULT_BULK_IN_DELAY		0x0800

#define EEPROM_INDICATOR		0xA5
#define EEPROM_MAC_OFFSET		0x01

/* Some extra defines */
#define LAN7X_INTERNAL_PHY_ID		1

#define LAN7X_MAC_RX_MAX_SIZE(mtu) \
	((mtu) << 16)			/* Max frame size */
#define LAN7X_MAC_RX_MAX_SIZE_DEFAULT \
	LAN7X_MAC_RX_MAX_SIZE(PKTSIZE_ALIGN + 4 /* VLAN */ + 4 /* CRC */)

/* Timeouts */
#define USB_CTRL_SET_TIMEOUT_MS		5000
#define USB_CTRL_GET_TIMEOUT_MS		5000
#define USB_BULK_SEND_TIMEOUT_MS	5000
#define USB_BULK_RECV_TIMEOUT_MS	5000
#define TIMEOUT_RESOLUTION_MS		50
#define PHY_CONNECT_TIMEOUT_MS		5000

#define RX_URB_SIZE	2048

/* driver private */
struct lan7x_private {
	struct ueth_data ueth;
	u32 chipid;		/* Chip or device ID */
	struct mii_dev *mdiobus;
	struct phy_device *phydev;
};

/*
 * Lan7x infrastructure commands
 */

int lan7x_write_reg(struct usb_device *udev, u32 index, u32 data);

int lan7x_read_reg(struct usb_device *udev, u32 index, u32 *data);

static inline int lan7x_wait_for_bit(struct usb_device *udev,
				     const char *prefix, const u32 reg,
				     const u32 mask, const bool set,
				     const unsigned int timeout_ms,
				     const bool breakable)
{
	u32 val;
	unsigned long start = get_timer(0);

	while (1) {
		lan7x_read_reg(udev, reg, &val);

		if (!set)
			val = ~val;

		if ((val & mask) == mask)
			return 0;

		if (get_timer(start) > timeout_ms)
			break;

		if (breakable && ctrlc()) {
			puts("Abort\n");
			return -EINTR;
		}

		udelay(1);
		WATCHDOG_RESET();
	}

	debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg,
	      mask, set);

	return -ETIMEDOUT;
}

int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx);

void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx,
		      int regval);

static inline int lan7x_mdio_wait_for_bit(struct usb_device *udev,
					  const char *prefix,
					  int phy_id, const u32 reg,
					  const u32 mask, const bool set,
					  const unsigned int timeout_ms,
					  const bool breakable)
{
	u32 val;
	unsigned long start = get_timer(0);

	while (1) {
		val = lan7x_mdio_read(udev, phy_id, reg);

		if (!set)
			val = ~val;

		if ((val & mask) == mask)
			return 0;

		if (get_timer(start) > timeout_ms)
			break;

		if (breakable && ctrlc()) {
			puts("Abort\n");
			return -EINTR;
		}

		udelay(1);
		WATCHDOG_RESET();
	}

	debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg,
	      mask, set);

	return -ETIMEDOUT;
}

int lan7x_phylib_register(struct udevice *udev);

int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev);

int lan7x_eth_phylib_config_start(struct udevice *udev);

int lan7x_pmt_phy_reset(struct usb_device *udev,
			struct ueth_data *dev);

int lan7x_update_flowcontrol(struct usb_device *udev,
			     struct ueth_data *dev,
			     uint32_t *flow, uint32_t *fct_flow);

int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev);

int lan7x_basic_reset(struct usb_device *udev,
		      struct ueth_data *dev);

void lan7x_eth_stop(struct udevice *dev);

int lan7x_eth_send(struct udevice *dev, void *packet, int length);

int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp);

int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len);

int lan7x_eth_remove(struct udevice *dev);