1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include <linux/module.h>
3 #include <linux/netdevice.h>
6 #include <linux/usb/cdc.h>
7 #include <linux/usb/usbnet.h>
8 #include <linux/usb/r8152.h>
10 #define OCP_BASE 0xe86c
12 static int pla_read_word(struct usbnet
*dev
, u16 index
)
14 u16 byen
= BYTE_EN_WORD
;
24 ret
= usbnet_read_cmd(dev
, RTL8152_REQ_GET_REGS
, RTL8152_REQT_READ
, index
,
25 MCU_TYPE_PLA
| byen
, &tmp
, sizeof(tmp
));
29 ret
= __le32_to_cpu(tmp
);
37 static int pla_write_word(struct usbnet
*dev
, u16 index
, u32 data
)
40 u16 byen
= BYTE_EN_WORD
;
55 ret
= usbnet_read_cmd(dev
, RTL8152_REQ_GET_REGS
, RTL8152_REQT_READ
, index
,
56 MCU_TYPE_PLA
| byen
, &tmp
, sizeof(tmp
));
61 data
|= __le32_to_cpu(tmp
) & ~mask
;
62 tmp
= __cpu_to_le32(data
);
64 ret
= usbnet_write_cmd(dev
, RTL8152_REQ_SET_REGS
, RTL8152_REQT_WRITE
, index
,
65 MCU_TYPE_PLA
| byen
, &tmp
, sizeof(tmp
));
71 static int r8153_ecm_mdio_read(struct net_device
*netdev
, int phy_id
, int reg
)
73 struct usbnet
*dev
= netdev_priv(netdev
);
76 ret
= pla_write_word(dev
, OCP_BASE
, 0xa000);
80 ret
= pla_read_word(dev
, 0xb400 + reg
* 2);
86 static void r8153_ecm_mdio_write(struct net_device
*netdev
, int phy_id
, int reg
, int val
)
88 struct usbnet
*dev
= netdev_priv(netdev
);
91 ret
= pla_write_word(dev
, OCP_BASE
, 0xa000);
95 ret
= pla_write_word(dev
, 0xb400 + reg
* 2, val
);
98 static int r8153_bind(struct usbnet
*dev
, struct usb_interface
*intf
)
102 status
= usbnet_cdc_bind(dev
, intf
);
106 dev
->mii
.dev
= dev
->net
;
107 dev
->mii
.mdio_read
= r8153_ecm_mdio_read
;
108 dev
->mii
.mdio_write
= r8153_ecm_mdio_write
;
109 dev
->mii
.reg_num_mask
= 0x1f;
110 dev
->mii
.supports_gmii
= 1;
115 static const struct driver_info r8153_info
= {
116 .description
= "RTL8153 ECM Device",
119 .unbind
= usbnet_cdc_unbind
,
120 .status
= usbnet_cdc_status
,
121 .manage_power
= usbnet_manage_power
,
124 static const struct usb_device_id products
[] = {
126 USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK
, 0x8153, USB_CLASS_COMM
,
127 USB_CDC_SUBCLASS_ETHERNET
, USB_CDC_PROTO_NONE
),
128 .driver_info
= (unsigned long)&r8153_info
,
133 MODULE_DEVICE_TABLE(usb
, products
);
135 static int rtl8153_ecm_probe(struct usb_interface
*intf
,
136 const struct usb_device_id
*id
)
138 #if IS_REACHABLE(CONFIG_USB_RTL8152)
139 if (rtl8152_get_version(intf
))
143 return usbnet_probe(intf
, id
);
146 static struct usb_driver r8153_ecm_driver
= {
148 .id_table
= products
,
149 .probe
= rtl8153_ecm_probe
,
150 .disconnect
= usbnet_disconnect
,
151 .suspend
= usbnet_suspend
,
152 .resume
= usbnet_resume
,
153 .reset_resume
= usbnet_resume
,
154 .supports_autosuspend
= 1,
155 .disable_hub_initiated_lpm
= 1,
158 module_usb_driver(r8153_ecm_driver
);
160 MODULE_AUTHOR("Hayes Wang");
161 MODULE_DESCRIPTION("Realtek USB ECM device");
162 MODULE_LICENSE("GPL");