183d290c5STom Rini /* SPDX-License-Identifier: GPL-2.0+ */
2d2c31979SYuiko Oshino /*
3d2c31979SYuiko Oshino * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
4d2c31979SYuiko Oshino */
5d2c31979SYuiko Oshino
6d2c31979SYuiko Oshino #include <console.h>
7d2c31979SYuiko Oshino #include <watchdog.h>
8d2c31979SYuiko Oshino
9d2c31979SYuiko Oshino /* USB Vendor Requests */
10d2c31979SYuiko Oshino #define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0
11d2c31979SYuiko Oshino #define USB_VENDOR_REQUEST_READ_REGISTER 0xA1
12d2c31979SYuiko Oshino #define USB_VENDOR_REQUEST_GET_STATS 0xA2
13d2c31979SYuiko Oshino
14d2c31979SYuiko Oshino /* Tx Command A */
15d2c31979SYuiko Oshino #define TX_CMD_A_FCS BIT(22)
16d2c31979SYuiko Oshino #define TX_CMD_A_LEN_MASK 0x000FFFFF
17d2c31979SYuiko Oshino
18d2c31979SYuiko Oshino /* Rx Command A */
19d2c31979SYuiko Oshino #define RX_CMD_A_RXE BIT(18)
20d2c31979SYuiko Oshino #define RX_CMD_A_LEN_MASK 0x00003FFF
21d2c31979SYuiko Oshino
22d2c31979SYuiko Oshino /* SCSRs */
23d2c31979SYuiko Oshino #define ID_REV 0x00
24d2c31979SYuiko Oshino #define ID_REV_CHIP_ID_MASK 0xFFFF0000
25d2c31979SYuiko Oshino #define ID_REV_CHIP_ID_7500 0x7500
26d2c31979SYuiko Oshino #define ID_REV_CHIP_ID_7800 0x7800
27d2c31979SYuiko Oshino #define ID_REV_CHIP_ID_7850 0x7850
28d2c31979SYuiko Oshino
29d2c31979SYuiko Oshino #define INT_STS 0x0C
30d2c31979SYuiko Oshino
31d2c31979SYuiko Oshino #define HW_CFG 0x010
32d2c31979SYuiko Oshino #define HW_CFG_LRST BIT(1)
33d2c31979SYuiko Oshino
34d2c31979SYuiko Oshino #define PMT_CTL 0x014
35d2c31979SYuiko Oshino #define PMT_CTL_PHY_PWRUP BIT(10)
36d2c31979SYuiko Oshino #define PMT_CTL_READY BIT(7)
37d2c31979SYuiko Oshino #define PMT_CTL_PHY_RST BIT(4)
38d2c31979SYuiko Oshino
39d2c31979SYuiko Oshino #define E2P_CMD 0x040
40d2c31979SYuiko Oshino #define E2P_CMD_EPC_BUSY BIT(31)
41d2c31979SYuiko Oshino #define E2P_CMD_EPC_CMD_READ 0x00000000
42d2c31979SYuiko Oshino #define E2P_CMD_EPC_TIMEOUT BIT(10)
43d2c31979SYuiko Oshino #define E2P_CMD_EPC_ADDR_MASK 0x000001FF
44d2c31979SYuiko Oshino
45d2c31979SYuiko Oshino #define E2P_DATA 0x044
46d2c31979SYuiko Oshino
47d2c31979SYuiko Oshino #define RFE_CTL_BCAST_EN BIT(10)
48d2c31979SYuiko Oshino #define RFE_CTL_DA_PERFECT BIT(1)
49d2c31979SYuiko Oshino
50d2c31979SYuiko Oshino #define FCT_RX_CTL_EN BIT(31)
51d2c31979SYuiko Oshino
52d2c31979SYuiko Oshino #define FCT_TX_CTL_EN BIT(31)
53d2c31979SYuiko Oshino
54d2c31979SYuiko Oshino #define MAC_CR 0x100
55d2c31979SYuiko Oshino #define MAC_CR_ADP BIT(13)
56d2c31979SYuiko Oshino #define MAC_CR_AUTO_DUPLEX BIT(12)
57d2c31979SYuiko Oshino #define MAC_CR_AUTO_SPEED BIT(11)
58d2c31979SYuiko Oshino
59d2c31979SYuiko Oshino #define MAC_RX 0x104
60d2c31979SYuiko Oshino #define MAC_RX_FCS_STRIP BIT(4)
61d2c31979SYuiko Oshino #define MAC_RX_RXEN BIT(0)
62d2c31979SYuiko Oshino
63d2c31979SYuiko Oshino #define MAC_TX 0x108
64d2c31979SYuiko Oshino #define MAC_TX_TXEN BIT(0)
65d2c31979SYuiko Oshino
66d2c31979SYuiko Oshino #define FLOW 0x10C
67d2c31979SYuiko Oshino #define FLOW_CR_TX_FCEN BIT(30)
68d2c31979SYuiko Oshino #define FLOW_CR_RX_FCEN BIT(29)
69d2c31979SYuiko Oshino
70d2c31979SYuiko Oshino #define RX_ADDRH 0x118
71d2c31979SYuiko Oshino #define RX_ADDRL 0x11C
72d2c31979SYuiko Oshino
73d2c31979SYuiko Oshino #define MII_ACC 0x120
74d2c31979SYuiko Oshino #define MII_ACC_MII_READ 0x00000000
75d2c31979SYuiko Oshino #define MII_ACC_MII_WRITE 0x00000002
76d2c31979SYuiko Oshino #define MII_ACC_MII_BUSY BIT(0)
77d2c31979SYuiko Oshino
78d2c31979SYuiko Oshino #define MII_DATA 0x124
79d2c31979SYuiko Oshino
80d2c31979SYuiko Oshino #define SS_USB_PKT_SIZE 1024
81d2c31979SYuiko Oshino #define HS_USB_PKT_SIZE 512
82d2c31979SYuiko Oshino #define FS_USB_PKT_SIZE 64
83d2c31979SYuiko Oshino
84d2c31979SYuiko Oshino #define MAX_RX_FIFO_SIZE (12 * 1024)
85d2c31979SYuiko Oshino #define MAX_TX_FIFO_SIZE (12 * 1024)
86d2c31979SYuiko Oshino #define DEFAULT_BULK_IN_DELAY 0x0800
87d2c31979SYuiko Oshino
88d2c31979SYuiko Oshino #define EEPROM_INDICATOR 0xA5
89d2c31979SYuiko Oshino #define EEPROM_MAC_OFFSET 0x01
90d2c31979SYuiko Oshino
91d2c31979SYuiko Oshino /* Some extra defines */
92d2c31979SYuiko Oshino #define LAN7X_INTERNAL_PHY_ID 1
93d2c31979SYuiko Oshino
94d2c31979SYuiko Oshino #define LAN7X_MAC_RX_MAX_SIZE(mtu) \
95d2c31979SYuiko Oshino ((mtu) << 16) /* Max frame size */
96d2c31979SYuiko Oshino #define LAN7X_MAC_RX_MAX_SIZE_DEFAULT \
97*dda52510SBin Meng LAN7X_MAC_RX_MAX_SIZE(PKTSIZE_ALIGN + 4 /* VLAN */ + 4 /* CRC */)
98d2c31979SYuiko Oshino
99d2c31979SYuiko Oshino /* Timeouts */
100d2c31979SYuiko Oshino #define USB_CTRL_SET_TIMEOUT_MS 5000
101d2c31979SYuiko Oshino #define USB_CTRL_GET_TIMEOUT_MS 5000
102d2c31979SYuiko Oshino #define USB_BULK_SEND_TIMEOUT_MS 5000
103d2c31979SYuiko Oshino #define USB_BULK_RECV_TIMEOUT_MS 5000
104d2c31979SYuiko Oshino #define TIMEOUT_RESOLUTION_MS 50
105d2c31979SYuiko Oshino #define PHY_CONNECT_TIMEOUT_MS 5000
106d2c31979SYuiko Oshino
107d2c31979SYuiko Oshino #define RX_URB_SIZE 2048
108d2c31979SYuiko Oshino
109d2c31979SYuiko Oshino /* driver private */
110d2c31979SYuiko Oshino struct lan7x_private {
111d2c31979SYuiko Oshino struct ueth_data ueth;
112d2c31979SYuiko Oshino u32 chipid; /* Chip or device ID */
113d2c31979SYuiko Oshino struct mii_dev *mdiobus;
114d2c31979SYuiko Oshino struct phy_device *phydev;
115d2c31979SYuiko Oshino };
116d2c31979SYuiko Oshino
117d2c31979SYuiko Oshino /*
118d2c31979SYuiko Oshino * Lan7x infrastructure commands
119d2c31979SYuiko Oshino */
120d2c31979SYuiko Oshino
121d2c31979SYuiko Oshino int lan7x_write_reg(struct usb_device *udev, u32 index, u32 data);
122d2c31979SYuiko Oshino
123d2c31979SYuiko Oshino int lan7x_read_reg(struct usb_device *udev, u32 index, u32 *data);
124d2c31979SYuiko Oshino
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)125d2c31979SYuiko Oshino static inline int lan7x_wait_for_bit(struct usb_device *udev,
126d2c31979SYuiko Oshino const char *prefix, const u32 reg,
127d2c31979SYuiko Oshino const u32 mask, const bool set,
128d2c31979SYuiko Oshino const unsigned int timeout_ms,
129d2c31979SYuiko Oshino const bool breakable)
130d2c31979SYuiko Oshino {
131d2c31979SYuiko Oshino u32 val;
132d2c31979SYuiko Oshino unsigned long start = get_timer(0);
133d2c31979SYuiko Oshino
134d2c31979SYuiko Oshino while (1) {
135d2c31979SYuiko Oshino lan7x_read_reg(udev, reg, &val);
136d2c31979SYuiko Oshino
137d2c31979SYuiko Oshino if (!set)
138d2c31979SYuiko Oshino val = ~val;
139d2c31979SYuiko Oshino
140d2c31979SYuiko Oshino if ((val & mask) == mask)
141d2c31979SYuiko Oshino return 0;
142d2c31979SYuiko Oshino
143d2c31979SYuiko Oshino if (get_timer(start) > timeout_ms)
144d2c31979SYuiko Oshino break;
145d2c31979SYuiko Oshino
146d2c31979SYuiko Oshino if (breakable && ctrlc()) {
147d2c31979SYuiko Oshino puts("Abort\n");
148d2c31979SYuiko Oshino return -EINTR;
149d2c31979SYuiko Oshino }
150d2c31979SYuiko Oshino
151d2c31979SYuiko Oshino udelay(1);
152d2c31979SYuiko Oshino WATCHDOG_RESET();
153d2c31979SYuiko Oshino }
154d2c31979SYuiko Oshino
155d2c31979SYuiko Oshino debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg,
156d2c31979SYuiko Oshino mask, set);
157d2c31979SYuiko Oshino
158d2c31979SYuiko Oshino return -ETIMEDOUT;
159d2c31979SYuiko Oshino }
160d2c31979SYuiko Oshino
161d2c31979SYuiko Oshino int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx);
162d2c31979SYuiko Oshino
163d2c31979SYuiko Oshino void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx,
164d2c31979SYuiko Oshino int regval);
165d2c31979SYuiko Oshino
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)166d2c31979SYuiko Oshino static inline int lan7x_mdio_wait_for_bit(struct usb_device *udev,
167d2c31979SYuiko Oshino const char *prefix,
168d2c31979SYuiko Oshino int phy_id, const u32 reg,
169d2c31979SYuiko Oshino const u32 mask, const bool set,
170d2c31979SYuiko Oshino const unsigned int timeout_ms,
171d2c31979SYuiko Oshino const bool breakable)
172d2c31979SYuiko Oshino {
173d2c31979SYuiko Oshino u32 val;
174d2c31979SYuiko Oshino unsigned long start = get_timer(0);
175d2c31979SYuiko Oshino
176d2c31979SYuiko Oshino while (1) {
177d2c31979SYuiko Oshino val = lan7x_mdio_read(udev, phy_id, reg);
178d2c31979SYuiko Oshino
179d2c31979SYuiko Oshino if (!set)
180d2c31979SYuiko Oshino val = ~val;
181d2c31979SYuiko Oshino
182d2c31979SYuiko Oshino if ((val & mask) == mask)
183d2c31979SYuiko Oshino return 0;
184d2c31979SYuiko Oshino
185d2c31979SYuiko Oshino if (get_timer(start) > timeout_ms)
186d2c31979SYuiko Oshino break;
187d2c31979SYuiko Oshino
188d2c31979SYuiko Oshino if (breakable && ctrlc()) {
189d2c31979SYuiko Oshino puts("Abort\n");
190d2c31979SYuiko Oshino return -EINTR;
191d2c31979SYuiko Oshino }
192d2c31979SYuiko Oshino
193d2c31979SYuiko Oshino udelay(1);
194d2c31979SYuiko Oshino WATCHDOG_RESET();
195d2c31979SYuiko Oshino }
196d2c31979SYuiko Oshino
197d2c31979SYuiko Oshino debug("%s: Timeout (reg=0x%x mask=%08x wait_set=%i)\n", prefix, reg,
198d2c31979SYuiko Oshino mask, set);
199d2c31979SYuiko Oshino
200d2c31979SYuiko Oshino return -ETIMEDOUT;
201d2c31979SYuiko Oshino }
202d2c31979SYuiko Oshino
203d2c31979SYuiko Oshino int lan7x_phylib_register(struct udevice *udev);
204d2c31979SYuiko Oshino
205d2c31979SYuiko Oshino int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev);
206d2c31979SYuiko Oshino
207d2c31979SYuiko Oshino int lan7x_eth_phylib_config_start(struct udevice *udev);
208d2c31979SYuiko Oshino
209d2c31979SYuiko Oshino int lan7x_pmt_phy_reset(struct usb_device *udev,
210d2c31979SYuiko Oshino struct ueth_data *dev);
211d2c31979SYuiko Oshino
212d2c31979SYuiko Oshino int lan7x_update_flowcontrol(struct usb_device *udev,
213d2c31979SYuiko Oshino struct ueth_data *dev,
214d2c31979SYuiko Oshino uint32_t *flow, uint32_t *fct_flow);
215d2c31979SYuiko Oshino
216d2c31979SYuiko Oshino int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev);
217d2c31979SYuiko Oshino
218d2c31979SYuiko Oshino int lan7x_basic_reset(struct usb_device *udev,
219d2c31979SYuiko Oshino struct ueth_data *dev);
220d2c31979SYuiko Oshino
221d2c31979SYuiko Oshino void lan7x_eth_stop(struct udevice *dev);
222d2c31979SYuiko Oshino
223d2c31979SYuiko Oshino int lan7x_eth_send(struct udevice *dev, void *packet, int length);
224d2c31979SYuiko Oshino
225d2c31979SYuiko Oshino int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp);
226d2c31979SYuiko Oshino
227d2c31979SYuiko Oshino int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len);
228d2c31979SYuiko Oshino
229d2c31979SYuiko Oshino int lan7x_eth_remove(struct udevice *dev);
230