Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.13-rc4 256 lines 5.5 kB view raw
1#include <linux/module.h> 2#include <linux/netdevice.h> 3#include <linux/mii.h> 4#include <linux/usb.h> 5#include <linux/usb/cdc.h> 6#include <linux/usb/usbnet.h> 7 8#define RTL815x_REQT_READ 0xc0 9#define RTL815x_REQT_WRITE 0x40 10#define RTL815x_REQ_GET_REGS 0x05 11#define RTL815x_REQ_SET_REGS 0x05 12 13#define MCU_TYPE_PLA 0x0100 14#define OCP_BASE 0xe86c 15#define BASE_MII 0xa400 16 17#define BYTE_EN_DWORD 0xff 18#define BYTE_EN_WORD 0x33 19#define BYTE_EN_BYTE 0x11 20 21#define R815x_PHY_ID 32 22#define REALTEK_VENDOR_ID 0x0bda 23 24 25static int pla_read_word(struct usb_device *udev, u16 index) 26{ 27 int ret; 28 u8 shift = index & 2; 29 __le32 *tmp; 30 31 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 32 if (!tmp) 33 return -ENOMEM; 34 35 index &= ~3; 36 37 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 38 RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, 39 index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); 40 if (ret < 0) 41 goto out2; 42 43 ret = __le32_to_cpu(*tmp); 44 ret >>= (shift * 8); 45 ret &= 0xffff; 46 47out2: 48 kfree(tmp); 49 return ret; 50} 51 52static int pla_write_word(struct usb_device *udev, u16 index, u32 data) 53{ 54 __le32 *tmp; 55 u32 mask = 0xffff; 56 u16 byen = BYTE_EN_WORD; 57 u8 shift = index & 2; 58 int ret; 59 60 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); 61 if (!tmp) 62 return -ENOMEM; 63 64 data &= mask; 65 66 if (shift) { 67 byen <<= shift; 68 mask <<= (shift * 8); 69 data <<= (shift * 8); 70 index &= ~3; 71 } 72 73 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 74 RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, 75 index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); 76 if (ret < 0) 77 goto out3; 78 79 data |= __le32_to_cpu(*tmp) & ~mask; 80 *tmp = __cpu_to_le32(data); 81 82 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 83 RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, 84 index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp), 85 500); 86 87out3: 88 kfree(tmp); 89 return ret; 90} 91 92static int ocp_reg_read(struct usbnet *dev, u16 addr) 93{ 94 u16 ocp_base, ocp_index; 95 int ret; 96 97 ocp_base = addr & 0xf000; 98 ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); 99 if (ret < 0) 100 goto out; 101 102 ocp_index = (addr & 0x0fff) | 0xb000; 103 ret = pla_read_word(dev->udev, ocp_index); 104 105out: 106 return ret; 107} 108 109static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data) 110{ 111 u16 ocp_base, ocp_index; 112 int ret; 113 114 ocp_base = addr & 0xf000; 115 ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); 116 if (ret < 0) 117 goto out1; 118 119 ocp_index = (addr & 0x0fff) | 0xb000; 120 ret = pla_write_word(dev->udev, ocp_index, data); 121 122out1: 123 return ret; 124} 125 126static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) 127{ 128 struct usbnet *dev = netdev_priv(netdev); 129 int ret; 130 131 if (phy_id != R815x_PHY_ID) 132 return -EINVAL; 133 134 if (usb_autopm_get_interface(dev->intf) < 0) 135 return -ENODEV; 136 137 ret = ocp_reg_read(dev, BASE_MII + reg * 2); 138 139 usb_autopm_put_interface(dev->intf); 140 return ret; 141} 142 143static 144void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) 145{ 146 struct usbnet *dev = netdev_priv(netdev); 147 148 if (phy_id != R815x_PHY_ID) 149 return; 150 151 if (usb_autopm_get_interface(dev->intf) < 0) 152 return; 153 154 ocp_reg_write(dev, BASE_MII + reg * 2, val); 155 156 usb_autopm_put_interface(dev->intf); 157} 158 159static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) 160{ 161 int status; 162 163 status = usbnet_cdc_bind(dev, intf); 164 if (status < 0) 165 return status; 166 167 dev->mii.dev = dev->net; 168 dev->mii.mdio_read = r815x_mdio_read; 169 dev->mii.mdio_write = r815x_mdio_write; 170 dev->mii.phy_id_mask = 0x3f; 171 dev->mii.reg_num_mask = 0x1f; 172 dev->mii.phy_id = R815x_PHY_ID; 173 dev->mii.supports_gmii = 1; 174 175 return status; 176} 177 178static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) 179{ 180 int status; 181 182 status = usbnet_cdc_bind(dev, intf); 183 if (status < 0) 184 return status; 185 186 dev->mii.dev = dev->net; 187 dev->mii.mdio_read = r815x_mdio_read; 188 dev->mii.mdio_write = r815x_mdio_write; 189 dev->mii.phy_id_mask = 0x3f; 190 dev->mii.reg_num_mask = 0x1f; 191 dev->mii.phy_id = R815x_PHY_ID; 192 dev->mii.supports_gmii = 0; 193 194 return status; 195} 196 197static const struct driver_info r8152_info = { 198 .description = "RTL8152 ECM Device", 199 .flags = FLAG_ETHER | FLAG_POINTTOPOINT, 200 .bind = r8152_bind, 201 .unbind = usbnet_cdc_unbind, 202 .status = usbnet_cdc_status, 203 .manage_power = usbnet_manage_power, 204}; 205 206static const struct driver_info r8153_info = { 207 .description = "RTL8153 ECM Device", 208 .flags = FLAG_ETHER | FLAG_POINTTOPOINT, 209 .bind = r8153_bind, 210 .unbind = usbnet_cdc_unbind, 211 .status = usbnet_cdc_status, 212 .manage_power = usbnet_manage_power, 213}; 214 215static const struct usb_device_id products[] = { 216{ 217 USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, 218 USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 219#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE) 220 .driver_info = 0, 221#else 222 .driver_info = (unsigned long) &r8152_info, 223#endif 224}, 225 226{ 227 USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, 228 USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 229#if defined(CONFIG_USB_RTL8153) || defined(CONFIG_USB_RTL8153_MODULE) 230 .driver_info = 0, 231#else 232 .driver_info = (unsigned long) &r8153_info, 233#endif 234}, 235 236 { }, /* END */ 237}; 238MODULE_DEVICE_TABLE(usb, products); 239 240static struct usb_driver r815x_driver = { 241 .name = "r815x", 242 .id_table = products, 243 .probe = usbnet_probe, 244 .disconnect = usbnet_disconnect, 245 .suspend = usbnet_suspend, 246 .resume = usbnet_resume, 247 .reset_resume = usbnet_resume, 248 .supports_autosuspend = 1, 249 .disable_hub_initiated_lpm = 1, 250}; 251 252module_usb_driver(r815x_driver); 253 254MODULE_AUTHOR("Hayes Wang"); 255MODULE_DESCRIPTION("Realtek USB ECM device"); 256MODULE_LICENSE("GPL");