xref: /openbmc/linux/drivers/net/usb/sr9700.c (revision c9b37458e95629b1d1171457afdcc1bf1eb7881d)
1*c9b37458SLiu Junliang /*
2*c9b37458SLiu Junliang  * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices
3*c9b37458SLiu Junliang  *
4*c9b37458SLiu Junliang  * Author : Liu Junliang <liujunliang_ljl@163.com>
5*c9b37458SLiu Junliang  *
6*c9b37458SLiu Junliang  * Based on dm9601.c
7*c9b37458SLiu Junliang  *
8*c9b37458SLiu Junliang  * This file is licensed under the terms of the GNU General Public License
9*c9b37458SLiu Junliang  * version 2.  This program is licensed "as is" without any warranty of any
10*c9b37458SLiu Junliang  * kind, whether express or implied.
11*c9b37458SLiu Junliang  */
12*c9b37458SLiu Junliang 
13*c9b37458SLiu Junliang #include <linux/module.h>
14*c9b37458SLiu Junliang #include <linux/sched.h>
15*c9b37458SLiu Junliang #include <linux/stddef.h>
16*c9b37458SLiu Junliang #include <linux/init.h>
17*c9b37458SLiu Junliang #include <linux/netdevice.h>
18*c9b37458SLiu Junliang #include <linux/etherdevice.h>
19*c9b37458SLiu Junliang #include <linux/ethtool.h>
20*c9b37458SLiu Junliang #include <linux/mii.h>
21*c9b37458SLiu Junliang #include <linux/usb.h>
22*c9b37458SLiu Junliang #include <linux/crc32.h>
23*c9b37458SLiu Junliang #include <linux/usb/usbnet.h>
24*c9b37458SLiu Junliang 
25*c9b37458SLiu Junliang #include "sr9700.h"
26*c9b37458SLiu Junliang 
27*c9b37458SLiu Junliang static int sr_read(struct usbnet *dev, u8 reg, u16 length, void *data)
28*c9b37458SLiu Junliang {
29*c9b37458SLiu Junliang 	int err;
30*c9b37458SLiu Junliang 
31*c9b37458SLiu Junliang 	err = usbnet_read_cmd(dev, SR_RD_REGS, SR_REQ_RD_REG, 0, reg, data,
32*c9b37458SLiu Junliang 			      length);
33*c9b37458SLiu Junliang 	if ((err != length) && (err >= 0))
34*c9b37458SLiu Junliang 		err = -EINVAL;
35*c9b37458SLiu Junliang 	return err;
36*c9b37458SLiu Junliang }
37*c9b37458SLiu Junliang 
38*c9b37458SLiu Junliang static int sr_write(struct usbnet *dev, u8 reg, u16 length, void *data)
39*c9b37458SLiu Junliang {
40*c9b37458SLiu Junliang 	int err;
41*c9b37458SLiu Junliang 
42*c9b37458SLiu Junliang 	err = usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG, 0, reg, data,
43*c9b37458SLiu Junliang 			       length);
44*c9b37458SLiu Junliang 	if ((err >= 0) && (err < length))
45*c9b37458SLiu Junliang 		err = -EINVAL;
46*c9b37458SLiu Junliang 	return err;
47*c9b37458SLiu Junliang }
48*c9b37458SLiu Junliang 
49*c9b37458SLiu Junliang static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
50*c9b37458SLiu Junliang {
51*c9b37458SLiu Junliang 	return sr_read(dev, reg, 1, value);
52*c9b37458SLiu Junliang }
53*c9b37458SLiu Junliang 
54*c9b37458SLiu Junliang static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
55*c9b37458SLiu Junliang {
56*c9b37458SLiu Junliang 	return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
57*c9b37458SLiu Junliang 				value, reg, NULL, 0);
58*c9b37458SLiu Junliang }
59*c9b37458SLiu Junliang 
60*c9b37458SLiu Junliang static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
61*c9b37458SLiu Junliang {
62*c9b37458SLiu Junliang 	usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
63*c9b37458SLiu Junliang 			       0, reg, data, length);
64*c9b37458SLiu Junliang }
65*c9b37458SLiu Junliang 
66*c9b37458SLiu Junliang static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
67*c9b37458SLiu Junliang {
68*c9b37458SLiu Junliang 	usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
69*c9b37458SLiu Junliang 			       value, reg, NULL, 0);
70*c9b37458SLiu Junliang }
71*c9b37458SLiu Junliang 
72*c9b37458SLiu Junliang static int wait_phy_eeprom_ready(struct usbnet *dev, int phy)
73*c9b37458SLiu Junliang {
74*c9b37458SLiu Junliang 	int i;
75*c9b37458SLiu Junliang 
76*c9b37458SLiu Junliang 	for (i = 0; i < SR_SHARE_TIMEOUT; i++) {
77*c9b37458SLiu Junliang 		u8 tmp = 0;
78*c9b37458SLiu Junliang 		int ret;
79*c9b37458SLiu Junliang 
80*c9b37458SLiu Junliang 		udelay(1);
81*c9b37458SLiu Junliang 		ret = sr_read_reg(dev, EPCR, &tmp);
82*c9b37458SLiu Junliang 		if (ret < 0)
83*c9b37458SLiu Junliang 			return ret;
84*c9b37458SLiu Junliang 
85*c9b37458SLiu Junliang 		/* ready */
86*c9b37458SLiu Junliang 		if (!(tmp & EPCR_ERRE))
87*c9b37458SLiu Junliang 			return 0;
88*c9b37458SLiu Junliang 	}
89*c9b37458SLiu Junliang 
90*c9b37458SLiu Junliang 	netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
91*c9b37458SLiu Junliang 
92*c9b37458SLiu Junliang 	return -EIO;
93*c9b37458SLiu Junliang }
94*c9b37458SLiu Junliang 
95*c9b37458SLiu Junliang static int sr_share_read_word(struct usbnet *dev, int phy, u8 reg,
96*c9b37458SLiu Junliang 			      __le16 *value)
97*c9b37458SLiu Junliang {
98*c9b37458SLiu Junliang 	int ret;
99*c9b37458SLiu Junliang 
100*c9b37458SLiu Junliang 	mutex_lock(&dev->phy_mutex);
101*c9b37458SLiu Junliang 
102*c9b37458SLiu Junliang 	sr_write_reg(dev, EPAR, phy ? (reg | EPAR_PHY_ADR) : reg);
103*c9b37458SLiu Junliang 	sr_write_reg(dev, EPCR, phy ? (EPCR_EPOS | EPCR_ERPRR) : EPCR_ERPRR);
104*c9b37458SLiu Junliang 
105*c9b37458SLiu Junliang 	ret = wait_phy_eeprom_ready(dev, phy);
106*c9b37458SLiu Junliang 	if (ret < 0)
107*c9b37458SLiu Junliang 		goto out_unlock;
108*c9b37458SLiu Junliang 
109*c9b37458SLiu Junliang 	sr_write_reg(dev, EPCR, 0x0);
110*c9b37458SLiu Junliang 	ret = sr_read(dev, EPDR, 2, value);
111*c9b37458SLiu Junliang 
112*c9b37458SLiu Junliang 	netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
113*c9b37458SLiu Junliang 		   phy, reg, *value, ret);
114*c9b37458SLiu Junliang 
115*c9b37458SLiu Junliang out_unlock:
116*c9b37458SLiu Junliang 	mutex_unlock(&dev->phy_mutex);
117*c9b37458SLiu Junliang 	return ret;
118*c9b37458SLiu Junliang }
119*c9b37458SLiu Junliang 
120*c9b37458SLiu Junliang static int sr_share_write_word(struct usbnet *dev, int phy, u8 reg,
121*c9b37458SLiu Junliang 			       __le16 value)
122*c9b37458SLiu Junliang {
123*c9b37458SLiu Junliang 	int ret;
124*c9b37458SLiu Junliang 
125*c9b37458SLiu Junliang 	mutex_lock(&dev->phy_mutex);
126*c9b37458SLiu Junliang 
127*c9b37458SLiu Junliang 	ret = sr_write(dev, EPDR, 2, &value);
128*c9b37458SLiu Junliang 	if (ret < 0)
129*c9b37458SLiu Junliang 		goto out_unlock;
130*c9b37458SLiu Junliang 
131*c9b37458SLiu Junliang 	sr_write_reg(dev, EPAR, phy ? (reg | EPAR_PHY_ADR) : reg);
132*c9b37458SLiu Junliang 	sr_write_reg(dev, EPCR, phy ? (EPCR_WEP | EPCR_EPOS | EPCR_ERPRW) :
133*c9b37458SLiu Junliang 		    (EPCR_WEP | EPCR_ERPRW));
134*c9b37458SLiu Junliang 
135*c9b37458SLiu Junliang 	ret = wait_phy_eeprom_ready(dev, phy);
136*c9b37458SLiu Junliang 	if (ret < 0)
137*c9b37458SLiu Junliang 		goto out_unlock;
138*c9b37458SLiu Junliang 
139*c9b37458SLiu Junliang 	sr_write_reg(dev, EPCR, 0x0);
140*c9b37458SLiu Junliang 
141*c9b37458SLiu Junliang out_unlock:
142*c9b37458SLiu Junliang 	mutex_unlock(&dev->phy_mutex);
143*c9b37458SLiu Junliang 	return ret;
144*c9b37458SLiu Junliang }
145*c9b37458SLiu Junliang 
146*c9b37458SLiu Junliang static int sr_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
147*c9b37458SLiu Junliang {
148*c9b37458SLiu Junliang 	return sr_share_read_word(dev, 0, offset, value);
149*c9b37458SLiu Junliang }
150*c9b37458SLiu Junliang 
151*c9b37458SLiu Junliang static int sr9700_get_eeprom_len(struct net_device *netdev)
152*c9b37458SLiu Junliang {
153*c9b37458SLiu Junliang 	return SR_EEPROM_LEN;
154*c9b37458SLiu Junliang }
155*c9b37458SLiu Junliang 
156*c9b37458SLiu Junliang static int sr9700_get_eeprom(struct net_device *netdev,
157*c9b37458SLiu Junliang 			     struct ethtool_eeprom *eeprom, u8 *data)
158*c9b37458SLiu Junliang {
159*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
160*c9b37458SLiu Junliang 	__le16 *buf = (__le16 *)data;
161*c9b37458SLiu Junliang 	int ret = 0;
162*c9b37458SLiu Junliang 	int i;
163*c9b37458SLiu Junliang 
164*c9b37458SLiu Junliang 	/* access is 16bit */
165*c9b37458SLiu Junliang 	if ((eeprom->offset & 0x01) || (eeprom->len & 0x01))
166*c9b37458SLiu Junliang 		return -EINVAL;
167*c9b37458SLiu Junliang 
168*c9b37458SLiu Junliang 	for (i = 0; i < eeprom->len / 2; i++) {
169*c9b37458SLiu Junliang 		ret = sr_read_eeprom_word(dev, eeprom->offset / 2 + i, buf + i);
170*c9b37458SLiu Junliang 		if (ret < 0)
171*c9b37458SLiu Junliang 			break;
172*c9b37458SLiu Junliang 	}
173*c9b37458SLiu Junliang 
174*c9b37458SLiu Junliang 	return ret;
175*c9b37458SLiu Junliang }
176*c9b37458SLiu Junliang 
177*c9b37458SLiu Junliang static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
178*c9b37458SLiu Junliang {
179*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
180*c9b37458SLiu Junliang 	__le16 res;
181*c9b37458SLiu Junliang 	int rc = 0;
182*c9b37458SLiu Junliang 
183*c9b37458SLiu Junliang 	if (phy_id) {
184*c9b37458SLiu Junliang 		netdev_dbg(netdev, "Only internal phy supported\n");
185*c9b37458SLiu Junliang 		return 0;
186*c9b37458SLiu Junliang 	}
187*c9b37458SLiu Junliang 
188*c9b37458SLiu Junliang 	/* Access NSR_LINKST bit for link status instead of MII_BMSR */
189*c9b37458SLiu Junliang 	if (loc == MII_BMSR) {
190*c9b37458SLiu Junliang 		u8 value;
191*c9b37458SLiu Junliang 
192*c9b37458SLiu Junliang 		sr_read_reg(dev, NSR, &value);
193*c9b37458SLiu Junliang 		if (value & NSR_LINKST)
194*c9b37458SLiu Junliang 			rc = 1;
195*c9b37458SLiu Junliang 	}
196*c9b37458SLiu Junliang 	sr_share_read_word(dev, 1, loc, &res);
197*c9b37458SLiu Junliang 	if (rc == 1)
198*c9b37458SLiu Junliang 		res = le16_to_cpu(res) | BMSR_LSTATUS;
199*c9b37458SLiu Junliang 	else
200*c9b37458SLiu Junliang 		res = le16_to_cpu(res) & ~BMSR_LSTATUS;
201*c9b37458SLiu Junliang 
202*c9b37458SLiu Junliang 	netdev_dbg(netdev, "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
203*c9b37458SLiu Junliang 		   phy_id, loc, res);
204*c9b37458SLiu Junliang 
205*c9b37458SLiu Junliang 	return res;
206*c9b37458SLiu Junliang }
207*c9b37458SLiu Junliang 
208*c9b37458SLiu Junliang static void sr_mdio_write(struct net_device *netdev, int phy_id, int loc,
209*c9b37458SLiu Junliang 			  int val)
210*c9b37458SLiu Junliang {
211*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
212*c9b37458SLiu Junliang 	__le16 res = cpu_to_le16(val);
213*c9b37458SLiu Junliang 
214*c9b37458SLiu Junliang 	if (phy_id) {
215*c9b37458SLiu Junliang 		netdev_dbg(netdev, "Only internal phy supported\n");
216*c9b37458SLiu Junliang 		return;
217*c9b37458SLiu Junliang 	}
218*c9b37458SLiu Junliang 
219*c9b37458SLiu Junliang 	netdev_dbg(netdev, "sr_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
220*c9b37458SLiu Junliang 		   phy_id, loc, val);
221*c9b37458SLiu Junliang 
222*c9b37458SLiu Junliang 	sr_share_write_word(dev, 1, loc, res);
223*c9b37458SLiu Junliang }
224*c9b37458SLiu Junliang 
225*c9b37458SLiu Junliang static u32 sr9700_get_link(struct net_device *netdev)
226*c9b37458SLiu Junliang {
227*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
228*c9b37458SLiu Junliang 	u8 value = 0;
229*c9b37458SLiu Junliang 	int rc = 0;
230*c9b37458SLiu Junliang 
231*c9b37458SLiu Junliang 	/* Get the Link Status directly */
232*c9b37458SLiu Junliang 	sr_read_reg(dev, NSR, &value);
233*c9b37458SLiu Junliang 	if (value & NSR_LINKST)
234*c9b37458SLiu Junliang 		rc = 1;
235*c9b37458SLiu Junliang 
236*c9b37458SLiu Junliang 	return rc;
237*c9b37458SLiu Junliang }
238*c9b37458SLiu Junliang 
239*c9b37458SLiu Junliang static int sr9700_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
240*c9b37458SLiu Junliang {
241*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
242*c9b37458SLiu Junliang 
243*c9b37458SLiu Junliang 	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
244*c9b37458SLiu Junliang }
245*c9b37458SLiu Junliang 
246*c9b37458SLiu Junliang static const struct ethtool_ops sr9700_ethtool_ops = {
247*c9b37458SLiu Junliang 	.get_drvinfo	= usbnet_get_drvinfo,
248*c9b37458SLiu Junliang 	.get_link	= sr9700_get_link,
249*c9b37458SLiu Junliang 	.get_msglevel	= usbnet_get_msglevel,
250*c9b37458SLiu Junliang 	.set_msglevel	= usbnet_set_msglevel,
251*c9b37458SLiu Junliang 	.get_eeprom_len	= sr9700_get_eeprom_len,
252*c9b37458SLiu Junliang 	.get_eeprom	= sr9700_get_eeprom,
253*c9b37458SLiu Junliang 	.get_settings	= usbnet_get_settings,
254*c9b37458SLiu Junliang 	.set_settings	= usbnet_set_settings,
255*c9b37458SLiu Junliang 	.nway_reset	= usbnet_nway_reset,
256*c9b37458SLiu Junliang };
257*c9b37458SLiu Junliang 
258*c9b37458SLiu Junliang static void sr9700_set_multicast(struct net_device *netdev)
259*c9b37458SLiu Junliang {
260*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
261*c9b37458SLiu Junliang 	/* We use the 20 byte dev->data for our 8 byte filter buffer
262*c9b37458SLiu Junliang 	 * to avoid allocating memory that is tricky to free later
263*c9b37458SLiu Junliang 	 */
264*c9b37458SLiu Junliang 	u8 *hashes = (u8 *)&dev->data;
265*c9b37458SLiu Junliang 	/* rx_ctl setting : enable, disable_long, disable_crc */
266*c9b37458SLiu Junliang 	u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG;
267*c9b37458SLiu Junliang 
268*c9b37458SLiu Junliang 	memset(hashes, 0x00, SR_MCAST_SIZE);
269*c9b37458SLiu Junliang 	/* broadcast address */
270*c9b37458SLiu Junliang 	hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG;
271*c9b37458SLiu Junliang 	if (netdev->flags & IFF_PROMISC) {
272*c9b37458SLiu Junliang 		rx_ctl |= RCR_PRMSC;
273*c9b37458SLiu Junliang 	} else if (netdev->flags & IFF_ALLMULTI ||
274*c9b37458SLiu Junliang 		   netdev_mc_count(netdev) > SR_MCAST_MAX) {
275*c9b37458SLiu Junliang 		rx_ctl |= RCR_RUNT;
276*c9b37458SLiu Junliang 	} else if (!netdev_mc_empty(netdev)) {
277*c9b37458SLiu Junliang 		struct netdev_hw_addr *ha;
278*c9b37458SLiu Junliang 
279*c9b37458SLiu Junliang 		netdev_for_each_mc_addr(ha, netdev) {
280*c9b37458SLiu Junliang 			u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
281*c9b37458SLiu Junliang 			hashes[crc >> 3] |= 1 << (crc & 0x7);
282*c9b37458SLiu Junliang 		}
283*c9b37458SLiu Junliang 	}
284*c9b37458SLiu Junliang 
285*c9b37458SLiu Junliang 	sr_write_async(dev, MAR, SR_MCAST_SIZE, hashes);
286*c9b37458SLiu Junliang 	sr_write_reg_async(dev, RCR, rx_ctl);
287*c9b37458SLiu Junliang }
288*c9b37458SLiu Junliang 
289*c9b37458SLiu Junliang static int sr9700_set_mac_address(struct net_device *netdev, void *p)
290*c9b37458SLiu Junliang {
291*c9b37458SLiu Junliang 	struct usbnet *dev = netdev_priv(netdev);
292*c9b37458SLiu Junliang 	struct sockaddr *addr = p;
293*c9b37458SLiu Junliang 
294*c9b37458SLiu Junliang 	if (!is_valid_ether_addr(addr->sa_data)) {
295*c9b37458SLiu Junliang 		netdev_err(netdev, "not setting invalid mac address %pM\n",
296*c9b37458SLiu Junliang 			   addr->sa_data);
297*c9b37458SLiu Junliang 		return -EINVAL;
298*c9b37458SLiu Junliang 	}
299*c9b37458SLiu Junliang 
300*c9b37458SLiu Junliang 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
301*c9b37458SLiu Junliang 	sr_write_async(dev, PAR, 6, netdev->dev_addr);
302*c9b37458SLiu Junliang 
303*c9b37458SLiu Junliang 	return 0;
304*c9b37458SLiu Junliang }
305*c9b37458SLiu Junliang 
306*c9b37458SLiu Junliang static const struct net_device_ops sr9700_netdev_ops = {
307*c9b37458SLiu Junliang 	.ndo_open		= usbnet_open,
308*c9b37458SLiu Junliang 	.ndo_stop		= usbnet_stop,
309*c9b37458SLiu Junliang 	.ndo_start_xmit		= usbnet_start_xmit,
310*c9b37458SLiu Junliang 	.ndo_tx_timeout		= usbnet_tx_timeout,
311*c9b37458SLiu Junliang 	.ndo_change_mtu		= usbnet_change_mtu,
312*c9b37458SLiu Junliang 	.ndo_validate_addr	= eth_validate_addr,
313*c9b37458SLiu Junliang 	.ndo_do_ioctl		= sr9700_ioctl,
314*c9b37458SLiu Junliang 	.ndo_set_rx_mode	= sr9700_set_multicast,
315*c9b37458SLiu Junliang 	.ndo_set_mac_address	= sr9700_set_mac_address,
316*c9b37458SLiu Junliang };
317*c9b37458SLiu Junliang 
318*c9b37458SLiu Junliang static int sr9700_bind(struct usbnet *dev, struct usb_interface *intf)
319*c9b37458SLiu Junliang {
320*c9b37458SLiu Junliang 	struct net_device *netdev;
321*c9b37458SLiu Junliang 	struct mii_if_info *mii;
322*c9b37458SLiu Junliang 	int ret;
323*c9b37458SLiu Junliang 
324*c9b37458SLiu Junliang 	ret = usbnet_get_endpoints(dev, intf);
325*c9b37458SLiu Junliang 	if (ret)
326*c9b37458SLiu Junliang 		goto out;
327*c9b37458SLiu Junliang 
328*c9b37458SLiu Junliang 	netdev = dev->net;
329*c9b37458SLiu Junliang 
330*c9b37458SLiu Junliang 	netdev->netdev_ops = &sr9700_netdev_ops;
331*c9b37458SLiu Junliang 	netdev->ethtool_ops = &sr9700_ethtool_ops;
332*c9b37458SLiu Junliang 	netdev->hard_header_len += SR_TX_OVERHEAD;
333*c9b37458SLiu Junliang 	dev->hard_mtu = netdev->mtu + netdev->hard_header_len;
334*c9b37458SLiu Junliang 	/* bulkin buffer is preferably not less than 3K */
335*c9b37458SLiu Junliang 	dev->rx_urb_size = 3072;
336*c9b37458SLiu Junliang 
337*c9b37458SLiu Junliang 	mii = &dev->mii;
338*c9b37458SLiu Junliang 	mii->dev = netdev;
339*c9b37458SLiu Junliang 	mii->mdio_read = sr_mdio_read;
340*c9b37458SLiu Junliang 	mii->mdio_write = sr_mdio_write;
341*c9b37458SLiu Junliang 	mii->phy_id_mask = 0x1f;
342*c9b37458SLiu Junliang 	mii->reg_num_mask = 0x1f;
343*c9b37458SLiu Junliang 
344*c9b37458SLiu Junliang 	sr_write_reg(dev, NCR, NCR_RST);
345*c9b37458SLiu Junliang 	udelay(20);
346*c9b37458SLiu Junliang 
347*c9b37458SLiu Junliang 	/* read MAC
348*c9b37458SLiu Junliang 	 * After Chip Power on, the Chip will reload the MAC from
349*c9b37458SLiu Junliang 	 * EEPROM automatically to PAR. In case there is no EEPROM externally,
350*c9b37458SLiu Junliang 	 * a default MAC address is stored in PAR for making chip work properly.
351*c9b37458SLiu Junliang 	 */
352*c9b37458SLiu Junliang 	if (sr_read(dev, PAR, ETH_ALEN, netdev->dev_addr) < 0) {
353*c9b37458SLiu Junliang 		netdev_err(netdev, "Error reading MAC address\n");
354*c9b37458SLiu Junliang 		ret = -ENODEV;
355*c9b37458SLiu Junliang 		goto out;
356*c9b37458SLiu Junliang 	}
357*c9b37458SLiu Junliang 
358*c9b37458SLiu Junliang 	/* power up and reset phy */
359*c9b37458SLiu Junliang 	sr_write_reg(dev, PRR, PRR_PHY_RST);
360*c9b37458SLiu Junliang 	/* at least 10ms, here 20ms for safe */
361*c9b37458SLiu Junliang 	mdelay(20);
362*c9b37458SLiu Junliang 	sr_write_reg(dev, PRR, 0);
363*c9b37458SLiu Junliang 	/* at least 1ms, here 2ms for reading right register */
364*c9b37458SLiu Junliang 	udelay(2 * 1000);
365*c9b37458SLiu Junliang 
366*c9b37458SLiu Junliang 	/* receive broadcast packets */
367*c9b37458SLiu Junliang 	sr9700_set_multicast(netdev);
368*c9b37458SLiu Junliang 
369*c9b37458SLiu Junliang 	sr_mdio_write(netdev, mii->phy_id, MII_BMCR, BMCR_RESET);
370*c9b37458SLiu Junliang 	sr_mdio_write(netdev, mii->phy_id, MII_ADVERTISE, ADVERTISE_ALL |
371*c9b37458SLiu Junliang 		      ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
372*c9b37458SLiu Junliang 	mii_nway_restart(mii);
373*c9b37458SLiu Junliang 
374*c9b37458SLiu Junliang out:
375*c9b37458SLiu Junliang 	return ret;
376*c9b37458SLiu Junliang }
377*c9b37458SLiu Junliang 
378*c9b37458SLiu Junliang static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
379*c9b37458SLiu Junliang {
380*c9b37458SLiu Junliang 	struct sk_buff *sr_skb;
381*c9b37458SLiu Junliang 	int len;
382*c9b37458SLiu Junliang 
383*c9b37458SLiu Junliang 	/* skb content (packets) format :
384*c9b37458SLiu Junliang 	 *                    p0            p1            p2    ......    pm
385*c9b37458SLiu Junliang 	 *                 /      \
386*c9b37458SLiu Junliang 	 *            /                \
387*c9b37458SLiu Junliang 	 *        /                            \
388*c9b37458SLiu Junliang 	 *  /                                        \
389*c9b37458SLiu Junliang 	 * p0b0 p0b1 p0b2 p0b3 ...... p0b(n-4) p0b(n-3)...p0bn
390*c9b37458SLiu Junliang 	 *
391*c9b37458SLiu Junliang 	 * p0 : packet 0
392*c9b37458SLiu Junliang 	 * p0b0 : packet 0 byte 0
393*c9b37458SLiu Junliang 	 *
394*c9b37458SLiu Junliang 	 * b0: rx status
395*c9b37458SLiu Junliang 	 * b1: packet length (incl crc) low
396*c9b37458SLiu Junliang 	 * b2: packet length (incl crc) high
397*c9b37458SLiu Junliang 	 * b3..n-4: packet data
398*c9b37458SLiu Junliang 	 * bn-3..bn: ethernet packet crc
399*c9b37458SLiu Junliang 	 */
400*c9b37458SLiu Junliang 	if (unlikely(skb->len < SR_RX_OVERHEAD)) {
401*c9b37458SLiu Junliang 		netdev_err(dev->net, "unexpected tiny rx frame\n");
402*c9b37458SLiu Junliang 		return 0;
403*c9b37458SLiu Junliang 	}
404*c9b37458SLiu Junliang 
405*c9b37458SLiu Junliang 	/* one skb may contains multiple packets */
406*c9b37458SLiu Junliang 	while (skb->len > SR_RX_OVERHEAD) {
407*c9b37458SLiu Junliang 		if (skb->data[0] != 0x40)
408*c9b37458SLiu Junliang 			return 0;
409*c9b37458SLiu Junliang 
410*c9b37458SLiu Junliang 		/* ignore the CRC length */
411*c9b37458SLiu Junliang 		len = (skb->data[1] | (skb->data[2] << 8)) - 4;
412*c9b37458SLiu Junliang 
413*c9b37458SLiu Junliang 		if (len > ETH_FRAME_LEN)
414*c9b37458SLiu Junliang 			return 0;
415*c9b37458SLiu Junliang 
416*c9b37458SLiu Junliang 		/* the last packet of current skb */
417*c9b37458SLiu Junliang 		if (skb->len == (len + SR_RX_OVERHEAD))	{
418*c9b37458SLiu Junliang 			skb_pull(skb, 3);
419*c9b37458SLiu Junliang 			skb->len = len;
420*c9b37458SLiu Junliang 			skb_set_tail_pointer(skb, len);
421*c9b37458SLiu Junliang 			skb->truesize = len + sizeof(struct sk_buff);
422*c9b37458SLiu Junliang 			return 2;
423*c9b37458SLiu Junliang 		}
424*c9b37458SLiu Junliang 
425*c9b37458SLiu Junliang 		/* skb_clone is used for address align */
426*c9b37458SLiu Junliang 		sr_skb = skb_clone(skb, GFP_ATOMIC);
427*c9b37458SLiu Junliang 		if (!sr_skb)
428*c9b37458SLiu Junliang 			return 0;
429*c9b37458SLiu Junliang 
430*c9b37458SLiu Junliang 		sr_skb->len = len;
431*c9b37458SLiu Junliang 		sr_skb->data = skb->data + 3;
432*c9b37458SLiu Junliang 		skb_set_tail_pointer(sr_skb, len);
433*c9b37458SLiu Junliang 		sr_skb->truesize = len + sizeof(struct sk_buff);
434*c9b37458SLiu Junliang 		usbnet_skb_return(dev, sr_skb);
435*c9b37458SLiu Junliang 
436*c9b37458SLiu Junliang 		skb_pull(skb, len + SR_RX_OVERHEAD);
437*c9b37458SLiu Junliang 	};
438*c9b37458SLiu Junliang 
439*c9b37458SLiu Junliang 	return 0;
440*c9b37458SLiu Junliang }
441*c9b37458SLiu Junliang 
442*c9b37458SLiu Junliang static struct sk_buff *sr9700_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
443*c9b37458SLiu Junliang 				       gfp_t flags)
444*c9b37458SLiu Junliang {
445*c9b37458SLiu Junliang 	int len;
446*c9b37458SLiu Junliang 
447*c9b37458SLiu Junliang 	/* SR9700 can only send out one ethernet packet at once.
448*c9b37458SLiu Junliang 	 *
449*c9b37458SLiu Junliang 	 * b0 b1 b2 b3 ...... b(n-4) b(n-3)...bn
450*c9b37458SLiu Junliang 	 *
451*c9b37458SLiu Junliang 	 * b0: rx status
452*c9b37458SLiu Junliang 	 * b1: packet length (incl crc) low
453*c9b37458SLiu Junliang 	 * b2: packet length (incl crc) high
454*c9b37458SLiu Junliang 	 * b3..n-4: packet data
455*c9b37458SLiu Junliang 	 * bn-3..bn: ethernet packet crc
456*c9b37458SLiu Junliang 	 */
457*c9b37458SLiu Junliang 
458*c9b37458SLiu Junliang 	len = skb->len;
459*c9b37458SLiu Junliang 
460*c9b37458SLiu Junliang 	if (skb_headroom(skb) < SR_TX_OVERHEAD) {
461*c9b37458SLiu Junliang 		struct sk_buff *skb2;
462*c9b37458SLiu Junliang 
463*c9b37458SLiu Junliang 		skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags);
464*c9b37458SLiu Junliang 		dev_kfree_skb_any(skb);
465*c9b37458SLiu Junliang 		skb = skb2;
466*c9b37458SLiu Junliang 		if (!skb)
467*c9b37458SLiu Junliang 			return NULL;
468*c9b37458SLiu Junliang 	}
469*c9b37458SLiu Junliang 
470*c9b37458SLiu Junliang 	__skb_push(skb, SR_TX_OVERHEAD);
471*c9b37458SLiu Junliang 
472*c9b37458SLiu Junliang 	/* usbnet adds padding if length is a multiple of packet size
473*c9b37458SLiu Junliang 	 * if so, adjust length value in header
474*c9b37458SLiu Junliang 	 */
475*c9b37458SLiu Junliang 	if ((skb->len % dev->maxpacket) == 0)
476*c9b37458SLiu Junliang 		len++;
477*c9b37458SLiu Junliang 
478*c9b37458SLiu Junliang 	skb->data[0] = len;
479*c9b37458SLiu Junliang 	skb->data[1] = len >> 8;
480*c9b37458SLiu Junliang 
481*c9b37458SLiu Junliang 	return skb;
482*c9b37458SLiu Junliang }
483*c9b37458SLiu Junliang 
484*c9b37458SLiu Junliang static void sr9700_status(struct usbnet *dev, struct urb *urb)
485*c9b37458SLiu Junliang {
486*c9b37458SLiu Junliang 	int link;
487*c9b37458SLiu Junliang 	u8 *buf;
488*c9b37458SLiu Junliang 
489*c9b37458SLiu Junliang 	/* format:
490*c9b37458SLiu Junliang 	   b0: net status
491*c9b37458SLiu Junliang 	   b1: tx status 1
492*c9b37458SLiu Junliang 	   b2: tx status 2
493*c9b37458SLiu Junliang 	   b3: rx status
494*c9b37458SLiu Junliang 	   b4: rx overflow
495*c9b37458SLiu Junliang 	   b5: rx count
496*c9b37458SLiu Junliang 	   b6: tx count
497*c9b37458SLiu Junliang 	   b7: gpr
498*c9b37458SLiu Junliang 	*/
499*c9b37458SLiu Junliang 
500*c9b37458SLiu Junliang 	if (urb->actual_length < 8)
501*c9b37458SLiu Junliang 		return;
502*c9b37458SLiu Junliang 
503*c9b37458SLiu Junliang 	buf = urb->transfer_buffer;
504*c9b37458SLiu Junliang 
505*c9b37458SLiu Junliang 	link = !!(buf[0] & 0x40);
506*c9b37458SLiu Junliang 	if (netif_carrier_ok(dev->net) != link) {
507*c9b37458SLiu Junliang 		usbnet_link_change(dev, link, 1);
508*c9b37458SLiu Junliang 		netdev_dbg(dev->net, "Link Status is: %d\n", link);
509*c9b37458SLiu Junliang 	}
510*c9b37458SLiu Junliang }
511*c9b37458SLiu Junliang 
512*c9b37458SLiu Junliang static int sr9700_link_reset(struct usbnet *dev)
513*c9b37458SLiu Junliang {
514*c9b37458SLiu Junliang 	struct ethtool_cmd ecmd;
515*c9b37458SLiu Junliang 
516*c9b37458SLiu Junliang 	mii_check_media(&dev->mii, 1, 1);
517*c9b37458SLiu Junliang 	mii_ethtool_gset(&dev->mii, &ecmd);
518*c9b37458SLiu Junliang 
519*c9b37458SLiu Junliang 	netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n",
520*c9b37458SLiu Junliang 		   ecmd.speed, ecmd.duplex);
521*c9b37458SLiu Junliang 
522*c9b37458SLiu Junliang 	return 0;
523*c9b37458SLiu Junliang }
524*c9b37458SLiu Junliang 
525*c9b37458SLiu Junliang static const struct driver_info sr9700_driver_info = {
526*c9b37458SLiu Junliang 	.description	= "CoreChip SR9700 USB Ethernet",
527*c9b37458SLiu Junliang 	.flags		= FLAG_ETHER,
528*c9b37458SLiu Junliang 	.bind		= sr9700_bind,
529*c9b37458SLiu Junliang 	.rx_fixup	= sr9700_rx_fixup,
530*c9b37458SLiu Junliang 	.tx_fixup	= sr9700_tx_fixup,
531*c9b37458SLiu Junliang 	.status		= sr9700_status,
532*c9b37458SLiu Junliang 	.link_reset	= sr9700_link_reset,
533*c9b37458SLiu Junliang 	.reset		= sr9700_link_reset,
534*c9b37458SLiu Junliang };
535*c9b37458SLiu Junliang 
536*c9b37458SLiu Junliang static const struct usb_device_id products[] = {
537*c9b37458SLiu Junliang 	{
538*c9b37458SLiu Junliang 		USB_DEVICE(0x0fe6, 0x9700),	/* SR9700 device */
539*c9b37458SLiu Junliang 		.driver_info = (unsigned long)&sr9700_driver_info,
540*c9b37458SLiu Junliang 	},
541*c9b37458SLiu Junliang 	{},			/* END */
542*c9b37458SLiu Junliang };
543*c9b37458SLiu Junliang 
544*c9b37458SLiu Junliang MODULE_DEVICE_TABLE(usb, products);
545*c9b37458SLiu Junliang 
546*c9b37458SLiu Junliang static struct usb_driver sr9700_usb_driver = {
547*c9b37458SLiu Junliang 	.name		= "sr9700",
548*c9b37458SLiu Junliang 	.id_table	= products,
549*c9b37458SLiu Junliang 	.probe		= usbnet_probe,
550*c9b37458SLiu Junliang 	.disconnect	= usbnet_disconnect,
551*c9b37458SLiu Junliang 	.suspend	= usbnet_suspend,
552*c9b37458SLiu Junliang 	.resume		= usbnet_resume,
553*c9b37458SLiu Junliang 	.disable_hub_initiated_lpm = 1,
554*c9b37458SLiu Junliang };
555*c9b37458SLiu Junliang 
556*c9b37458SLiu Junliang module_usb_driver(sr9700_usb_driver);
557*c9b37458SLiu Junliang 
558*c9b37458SLiu Junliang MODULE_AUTHOR("liujl <liujunliang_ljl@163.com>");
559*c9b37458SLiu Junliang MODULE_DESCRIPTION("SR9700 one chip USB 1.1 USB to Ethernet device from http://www.corechip-sz.com/");
560*c9b37458SLiu Junliang MODULE_LICENSE("GPL");
561