xref: /openbmc/linux/drivers/net/usb/ch9200.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1  /*
2   * USB 10M/100M ethernet adapter
3   *
4   * This file is licensed under the terms of the GNU General Public License
5   * version 2. This program is licensed "as is" without any warranty of any
6   * kind, whether express or implied
7   *
8   */
9  
10  #include <linux/kernel.h>
11  #include <linux/module.h>
12  #include <linux/sched.h>
13  #include <linux/stddef.h>
14  #include <linux/init.h>
15  #include <linux/netdevice.h>
16  #include <linux/etherdevice.h>
17  #include <linux/ethtool.h>
18  #include <linux/mii.h>
19  #include <linux/usb.h>
20  #include <linux/crc32.h>
21  #include <linux/usb/usbnet.h>
22  #include <linux/slab.h>
23  
24  #define CH9200_VID		0x1A86
25  #define CH9200_PID_E092		0xE092
26  
27  #define CTRL_TIMEOUT_MS		1000
28  
29  #define CONTROL_TIMEOUT_MS 1000
30  
31  #define REQUEST_READ	0x0E
32  #define REQUEST_WRITE	0x0F
33  
34  /* Address space:
35   * 00-63 : MII
36   * 64-128: MAC
37   *
38   * Note: all accesses must be 16-bit
39   */
40  
41  #define MAC_REG_CTRL 64
42  #define MAC_REG_STATUS 66
43  #define MAC_REG_INTERRUPT_MASK 68
44  #define MAC_REG_PHY_COMMAND 70
45  #define MAC_REG_PHY_DATA 72
46  #define MAC_REG_STATION_L 74
47  #define MAC_REG_STATION_M 76
48  #define MAC_REG_STATION_H 78
49  #define MAC_REG_HASH_L 80
50  #define MAC_REG_HASH_M1 82
51  #define MAC_REG_HASH_M2 84
52  #define MAC_REG_HASH_H 86
53  #define MAC_REG_THRESHOLD 88
54  #define MAC_REG_FIFO_DEPTH 90
55  #define MAC_REG_PAUSE 92
56  #define MAC_REG_FLOW_CONTROL 94
57  
58  /* Control register bits
59   *
60   * Note: bits 13 and 15 are reserved
61   */
62  #define LOOPBACK		(0x01 << 14)
63  #define BASE100X		(0x01 << 12)
64  #define MBPS_10			(0x01 << 11)
65  #define DUPLEX_MODE		(0x01 << 10)
66  #define PAUSE_FRAME		(0x01 << 9)
67  #define PROMISCUOUS		(0x01 << 8)
68  #define MULTICAST		(0x01 << 7)
69  #define BROADCAST		(0x01 << 6)
70  #define HASH			(0x01 << 5)
71  #define APPEND_PAD		(0x01 << 4)
72  #define APPEND_CRC		(0x01 << 3)
73  #define TRANSMITTER_ACTION	(0x01 << 2)
74  #define RECEIVER_ACTION		(0x01 << 1)
75  #define DMA_ACTION		(0x01 << 0)
76  
77  /* Status register bits
78   *
79   * Note: bits 7-15 are reserved
80   */
81  #define ALIGNMENT		(0x01 << 6)
82  #define FIFO_OVER_RUN		(0x01 << 5)
83  #define FIFO_UNDER_RUN		(0x01 << 4)
84  #define RX_ERROR		(0x01 << 3)
85  #define RX_COMPLETE		(0x01 << 2)
86  #define TX_ERROR		(0x01 << 1)
87  #define TX_COMPLETE		(0x01 << 0)
88  
89  /* FIFO depth register bits
90   *
91   * Note: bits 6 and 14 are reserved
92   */
93  
94  #define ETH_TXBD		(0x01 << 15)
95  #define ETN_TX_FIFO_DEPTH	(0x01 << 8)
96  #define ETH_RXBD		(0x01 << 7)
97  #define ETH_RX_FIFO_DEPTH	(0x01 << 0)
98  
control_read(struct usbnet * dev,unsigned char request,unsigned short value,unsigned short index,void * data,unsigned short size,int timeout)99  static int control_read(struct usbnet *dev,
100  			unsigned char request, unsigned short value,
101  			unsigned short index, void *data, unsigned short size,
102  			int timeout)
103  {
104  	unsigned char *buf = NULL;
105  	unsigned char request_type;
106  	int err = 0;
107  
108  	if (request == REQUEST_READ)
109  		request_type = (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER);
110  	else
111  		request_type = (USB_DIR_IN | USB_TYPE_VENDOR |
112  				USB_RECIP_DEVICE);
113  
114  	netdev_dbg(dev->net, "%s() index=0x%02x size=%d\n",
115  		   __func__, index, size);
116  
117  	buf = kmalloc(size, GFP_KERNEL);
118  	if (!buf) {
119  		err = -ENOMEM;
120  		goto err_out;
121  	}
122  
123  	err = usb_control_msg(dev->udev,
124  			      usb_rcvctrlpipe(dev->udev, 0),
125  			      request, request_type, value, index, buf, size,
126  			      timeout);
127  	if (err == size)
128  		memcpy(data, buf, size);
129  	else if (err >= 0)
130  		err = -EINVAL;
131  	kfree(buf);
132  
133  err_out:
134  	return err;
135  }
136  
control_write(struct usbnet * dev,unsigned char request,unsigned short value,unsigned short index,void * data,unsigned short size,int timeout)137  static int control_write(struct usbnet *dev, unsigned char request,
138  			 unsigned short value, unsigned short index,
139  			 void *data, unsigned short size, int timeout)
140  {
141  	unsigned char *buf = NULL;
142  	unsigned char request_type;
143  	int err = 0;
144  
145  	if (request == REQUEST_WRITE)
146  		request_type = (USB_DIR_OUT | USB_TYPE_VENDOR |
147  				USB_RECIP_OTHER);
148  	else
149  		request_type = (USB_DIR_OUT | USB_TYPE_VENDOR |
150  				USB_RECIP_DEVICE);
151  
152  	netdev_dbg(dev->net, "%s() index=0x%02x size=%d\n",
153  		   __func__, index, size);
154  
155  	if (data) {
156  		buf = kmemdup(data, size, GFP_KERNEL);
157  		if (!buf) {
158  			err = -ENOMEM;
159  			goto err_out;
160  		}
161  	}
162  
163  	err = usb_control_msg(dev->udev,
164  			      usb_sndctrlpipe(dev->udev, 0),
165  			      request, request_type, value, index, buf, size,
166  			      timeout);
167  	if (err >= 0 && err < size)
168  		err = -EINVAL;
169  	kfree(buf);
170  
171  	return 0;
172  
173  err_out:
174  	return err;
175  }
176  
ch9200_mdio_read(struct net_device * netdev,int phy_id,int loc)177  static int ch9200_mdio_read(struct net_device *netdev, int phy_id, int loc)
178  {
179  	struct usbnet *dev = netdev_priv(netdev);
180  	unsigned char buff[2];
181  
182  	netdev_dbg(netdev, "%s phy_id:%02x loc:%02x\n",
183  		   __func__, phy_id, loc);
184  
185  	if (phy_id != 0)
186  		return -ENODEV;
187  
188  	control_read(dev, REQUEST_READ, 0, loc * 2, buff, 0x02,
189  		     CONTROL_TIMEOUT_MS);
190  
191  	return (buff[0] | buff[1] << 8);
192  }
193  
ch9200_mdio_write(struct net_device * netdev,int phy_id,int loc,int val)194  static void ch9200_mdio_write(struct net_device *netdev,
195  			      int phy_id, int loc, int val)
196  {
197  	struct usbnet *dev = netdev_priv(netdev);
198  	unsigned char buff[2];
199  
200  	netdev_dbg(netdev, "%s() phy_id=%02x loc:%02x\n",
201  		   __func__, phy_id, loc);
202  
203  	if (phy_id != 0)
204  		return;
205  
206  	buff[0] = (unsigned char)val;
207  	buff[1] = (unsigned char)(val >> 8);
208  
209  	control_write(dev, REQUEST_WRITE, 0, loc * 2, buff, 0x02,
210  		      CONTROL_TIMEOUT_MS);
211  }
212  
ch9200_link_reset(struct usbnet * dev)213  static int ch9200_link_reset(struct usbnet *dev)
214  {
215  	struct ethtool_cmd ecmd;
216  
217  	mii_check_media(&dev->mii, 1, 1);
218  	mii_ethtool_gset(&dev->mii, &ecmd);
219  
220  	netdev_dbg(dev->net, "%s() speed:%d duplex:%d\n",
221  		   __func__, ecmd.speed, ecmd.duplex);
222  
223  	return 0;
224  }
225  
ch9200_status(struct usbnet * dev,struct urb * urb)226  static void ch9200_status(struct usbnet *dev, struct urb *urb)
227  {
228  	int link;
229  	unsigned char *buf;
230  
231  	if (urb->actual_length < 16)
232  		return;
233  
234  	buf = urb->transfer_buffer;
235  	link = !!(buf[0] & 0x01);
236  
237  	if (link) {
238  		netif_carrier_on(dev->net);
239  		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
240  	} else {
241  		netif_carrier_off(dev->net);
242  	}
243  }
244  
ch9200_tx_fixup(struct usbnet * dev,struct sk_buff * skb,gfp_t flags)245  static struct sk_buff *ch9200_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
246  				       gfp_t flags)
247  {
248  	int i = 0;
249  	int len = 0;
250  	int tx_overhead = 0;
251  
252  	tx_overhead = 0x40;
253  
254  	len = skb->len;
255  	if (skb_cow_head(skb, tx_overhead)) {
256  		dev_kfree_skb_any(skb);
257  		return NULL;
258  	}
259  
260  	__skb_push(skb, tx_overhead);
261  	/* usbnet adds padding if length is a multiple of packet size
262  	 * if so, adjust length value in header
263  	 */
264  	if ((skb->len % dev->maxpacket) == 0)
265  		len++;
266  
267  	skb->data[0] = len;
268  	skb->data[1] = len >> 8;
269  	skb->data[2] = 0x00;
270  	skb->data[3] = 0x80;
271  
272  	for (i = 4; i < 48; i++)
273  		skb->data[i] = 0x00;
274  
275  	skb->data[48] = len;
276  	skb->data[49] = len >> 8;
277  	skb->data[50] = 0x00;
278  	skb->data[51] = 0x80;
279  
280  	for (i = 52; i < 64; i++)
281  		skb->data[i] = 0x00;
282  
283  	return skb;
284  }
285  
ch9200_rx_fixup(struct usbnet * dev,struct sk_buff * skb)286  static int ch9200_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
287  {
288  	int len = 0;
289  	int rx_overhead = 0;
290  
291  	rx_overhead = 64;
292  
293  	if (unlikely(skb->len < rx_overhead)) {
294  		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
295  		return 0;
296  	}
297  
298  	len = (skb->data[skb->len - 16] | skb->data[skb->len - 15] << 8);
299  	skb_trim(skb, len);
300  
301  	return 1;
302  }
303  
get_mac_address(struct usbnet * dev,unsigned char * data)304  static int get_mac_address(struct usbnet *dev, unsigned char *data)
305  {
306  	int err = 0;
307  	unsigned char mac_addr[0x06];
308  	int rd_mac_len = 0;
309  
310  	netdev_dbg(dev->net, "%s:\n\tusbnet VID:%0x PID:%0x\n", __func__,
311  		   le16_to_cpu(dev->udev->descriptor.idVendor),
312  		   le16_to_cpu(dev->udev->descriptor.idProduct));
313  
314  	memset(mac_addr, 0, sizeof(mac_addr));
315  	rd_mac_len = control_read(dev, REQUEST_READ, 0,
316  				  MAC_REG_STATION_L, mac_addr, 0x02,
317  				  CONTROL_TIMEOUT_MS);
318  	rd_mac_len += control_read(dev, REQUEST_READ, 0, MAC_REG_STATION_M,
319  				   mac_addr + 2, 0x02, CONTROL_TIMEOUT_MS);
320  	rd_mac_len += control_read(dev, REQUEST_READ, 0, MAC_REG_STATION_H,
321  				   mac_addr + 4, 0x02, CONTROL_TIMEOUT_MS);
322  	if (rd_mac_len != ETH_ALEN)
323  		err = -EINVAL;
324  
325  	data[0] = mac_addr[5];
326  	data[1] = mac_addr[4];
327  	data[2] = mac_addr[3];
328  	data[3] = mac_addr[2];
329  	data[4] = mac_addr[1];
330  	data[5] = mac_addr[0];
331  
332  	return err;
333  }
334  
ch9200_bind(struct usbnet * dev,struct usb_interface * intf)335  static int ch9200_bind(struct usbnet *dev, struct usb_interface *intf)
336  {
337  	int retval = 0;
338  	unsigned char data[2];
339  	u8 addr[ETH_ALEN];
340  
341  	retval = usbnet_get_endpoints(dev, intf);
342  	if (retval)
343  		return retval;
344  
345  	dev->mii.dev = dev->net;
346  	dev->mii.mdio_read = ch9200_mdio_read;
347  	dev->mii.mdio_write = ch9200_mdio_write;
348  	dev->mii.reg_num_mask = 0x1f;
349  
350  	dev->mii.phy_id_mask = 0x1f;
351  
352  	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
353  	dev->rx_urb_size = 24 * 64 + 16;
354  	mii_nway_restart(&dev->mii);
355  
356  	data[0] = 0x01;
357  	data[1] = 0x0F;
358  	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_THRESHOLD, data,
359  			       0x02, CONTROL_TIMEOUT_MS);
360  
361  	data[0] = 0xA0;
362  	data[1] = 0x90;
363  	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_FIFO_DEPTH, data,
364  			       0x02, CONTROL_TIMEOUT_MS);
365  
366  	data[0] = 0x30;
367  	data[1] = 0x00;
368  	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_PAUSE, data,
369  			       0x02, CONTROL_TIMEOUT_MS);
370  
371  	data[0] = 0x17;
372  	data[1] = 0xD8;
373  	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_FLOW_CONTROL,
374  			       data, 0x02, CONTROL_TIMEOUT_MS);
375  
376  	/* Undocumented register */
377  	data[0] = 0x01;
378  	data[1] = 0x00;
379  	retval = control_write(dev, REQUEST_WRITE, 0, 254, data, 0x02,
380  			       CONTROL_TIMEOUT_MS);
381  
382  	data[0] = 0x5F;
383  	data[1] = 0x0D;
384  	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_CTRL, data, 0x02,
385  			       CONTROL_TIMEOUT_MS);
386  
387  	retval = get_mac_address(dev, addr);
388  	eth_hw_addr_set(dev->net, addr);
389  
390  	return retval;
391  }
392  
393  static const struct driver_info ch9200_info = {
394  	.description = "CH9200 USB to Network Adaptor",
395  	.flags = FLAG_ETHER,
396  	.bind = ch9200_bind,
397  	.rx_fixup = ch9200_rx_fixup,
398  	.tx_fixup = ch9200_tx_fixup,
399  	.status = ch9200_status,
400  	.link_reset = ch9200_link_reset,
401  	.reset = ch9200_link_reset,
402  };
403  
404  static const struct usb_device_id ch9200_products[] = {
405  	{
406  	 USB_DEVICE(0x1A86, 0xE092),
407  	 .driver_info = (unsigned long)&ch9200_info,
408  	 },
409  	{},
410  };
411  
412  MODULE_DEVICE_TABLE(usb, ch9200_products);
413  
414  static struct usb_driver ch9200_driver = {
415  	.name = "ch9200",
416  	.id_table = ch9200_products,
417  	.probe = usbnet_probe,
418  	.disconnect = usbnet_disconnect,
419  	.suspend = usbnet_suspend,
420  	.resume = usbnet_resume,
421  };
422  
423  module_usb_driver(ch9200_driver);
424  
425  MODULE_DESCRIPTION("QinHeng CH9200 USB Network device");
426  MODULE_LICENSE("GPL");
427