Rtwo/kernel/motorola/sm8550/drivers/net/usb/ax_main.h
2025-09-30 19:22:48 -05:00

563 lines
17 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*******************************************************************************
* Copyright (c) 2022 ASIX Electronic Corporation All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
******************************************************************************/
#ifndef __ASIX_MAIN_H
#define __ASIX_MAIN_H
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <uapi/linux/mdio.h>
#include <linux/mdio.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/usb.h>
#include <linux/if_vlan.h>
#include <linux/usb/cdc.h>
#include <linux/suspend.h>
#include <linux/pm_runtime.h>
#include <linux/version.h>
#include <linux/efi.h>
#include <linux/crc32.h>
#include "ax_ioctl.h"
#define napi_alloc_skb(napi, length) netdev_alloc_skb_ip_align(netdev, length)
#define napi_complete_done(n, d) napi_complete(n)
typedef int (*_usb_read_function)(struct ax_device *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, void *data, u16 size);
typedef int (*_usb_write_function)(struct ax_device *dev, u8 cmd, u8 reqtype,
u16 value, u16 index, const void *data,
u16 size);
typedef int (*usb_read_function)(struct ax_device *axdev, u8 cmd, u16 value,
u16 index, u16 size, void *data, int eflag);
typedef int (*usb_write_function)(struct ax_device *axdev, u8 cmd, u16 value,
u16 index, u16 size, void *data);
#define USB_VENDOR_ID_ASIX 0x0B95
#define USB_VENDOR_ID_SITECOM 0x0DF6
#define USB_VENDOR_ID_LENOVO 0x17EF
#define USB_VENDOR_ID_TOSHIBA 0x0930
#define USB_VENDOR_ID_SAMSUNG 0x04E8
#define USB_VENDOR_ID_DLINK 0x2001
#define USB_VENDOR_ID_MAGIC_CONTROL 0x0711
#define AX_DEVICE_ID_179X 0x1790
#define AX_BCDDEVICE_ID_179 0x0100
#define AX_BCDDEVICE_ID_179A 0x0200
#define AX_DEVICE_ID_178A 0x178A
#define AX_BCDDEVICE_ID_178A 0x0100
#define AX_DEVICE_ID_772D AX_DEVICE_ID_179X
#define AX_BCDDEVICE_ID_772D 0x0300
#define AX_DRIVER_STRING_179_178A \
"ASIX AX88179_178A USB Ethernet Controller"
#define AX_DRIVER_STRING_179A_772D \
"ASIX AX88179A_772D USB Ethernet Controller"
#define DRIVER_VERSION "1.0.0"
#define DRIVER_AUTHOR "ASIX"
#define DRIVER_DESC "ASIX USB Ethernet Controller"
#define MODULENAME "ax_usb_nic"
#define AX88179_MAX_TX 4
#define AX88179_MAX_RX 10
#define AX88179_BUF_TX_SIZE (48 * 1024)
#define AX_GSO_DEFAULT_SIZE (15 * 1024)
#define INTBUFSIZE 8
#define TX_ALIGN 4
#define RX_ALIGN 8
#define TX_CASECADES_SIZE AX_GSO_DEFAULT_SIZE
#define AX_TX_HEADER_LEN 8
#define AX_TX_TIMEOUT (5 * HZ)
#define AX_MCAST_FILTER_SIZE 8
#define AX_MAX_MCAST 64
#define AX_TX_QUEUE_SIZE 1
#define US_TO_NS 1000
#define AX_ACCESS_MAC 0x01
#define AX_ACCESS_PHY 0x02
#define AX_ACCESS_WAKEUP 0x03
#define AX_ACCESS_EEPROM 0x04
#define AX_ACCESS_EFUSE 0x05
#define AX_RELOAD_EEPROM_EFUSE 0x06
#define AX_RELOAD_FLASH_EFUSE 0x06
#define AX_FW_MODE 0x08
#define AX_FW_MODE_179A 0x0001
#define AX_USB_EP5_EN 0x0001
#define AX_WRITE_EFUSE_EN 0x09
#define AX_WRITE_EFUSE_DIS 0x0A
#define AX_ACCESS_MFAB 0x10
#define AX_PHY_POLLING 0x90
#define PHYSICAL_LINK_STATUS 0x02
#define AX_USB_SS 0x04
#define AX_USB_HS 0x02
#define AX_USB_FS 0x01
#define GENERAL_STATUS 0x03
#define AX_SECLD 0x04
#define AX_CHIP_STATUS 0x05
#define AX_CHIP_CODE_MASK 0x70
#define CHIP_CODE(x) (((x) & AX_CHIP_CODE_MASK) >> 4)
#define AX_SROM_ADDR 0x07
#define AX_SROM_CMD 0x0a
#define EEP_RD 0x04
#define EEP_WR 0x08
#define EEP_BUSY 0x10
#define AX_SROM_DATA_LOW 0x08
#define AX_SROM_DATA_HIGH 0x09
#define AX_RX_CTL 0x0b
#define AX_RX_CTL_HI 0x0c
#define AX_RX_CTL_DROPCRCERR_HI 0x01
#define AX_RX_CTL_DROPCRCERR 0x0100
#define AX_RX_CTL_IPE 0x0200
#define AX_RX_CTL_TXPADCRC 0x0400
#define AX_RX_CTL_START 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_HA8B 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_STOP 0x0000
#define AX_NODE_ID 0x10
#define AX_MULTI_FILTER_ARRY 0x16
#define AX_MEDIUM_STATUS_MODE 0x22
#define AX_MEDIUM_GIGAMODE 0x0001
#define AX_MEDIUM_FULL_DUPLEX 0x0002
#define AX_MEDIUM_RXFLOW_CTRLEN 0x0010
#define AX_MEDIUM_TXFLOW_CTRLEN 0x0020
#define AX_MEDIUM_RECEIVE_EN 0x0100
#define AX_MEDIUM_PS 0x0200
#define AX_MEDIUM_JUMBO_EN 0x8040
#define AX_MONITOR_MODE 0x24
#define AX_MONITOR_MODE_RWLC 0x02
#define AX_MONITOR_MODE_RWMP 0x04
#define AX_MONITOR_MODE_RWWF 0x08
#define AX_MONITOR_MODE_RW_FLAG 0x10
#define AX_MONITOR_MODE_PMEPOL 0x20
#define AX_MONITOR_MODE_PMETYPE 0x40
#define AX_GPIO_CTRL 0x25
#define AX_GPIO_CTRL_GPIO3EN 0x80
#define AX_GPIO_CTRL_GPIO2EN 0x40
#define AX_GPIO_CTRL_GPIO1EN 0x20
#define AX_PHYPWR_RSTCTL 0x26
#define AX_PHYPWR_RSTCTL_BZ 0x0010
#define AX_PHYPWR_RSTCTL_IPRL 0x0020
#define AX_PHYPWR_RSTCTL_AUTODETACH 0x1000
#define AX_RX_BULKIN_QCTRL 0x2e
#define AX_RX_BULKIN_QCTRL_TIME 0x01
#define AX_RX_BULKIN_QCTRL_IFG 0x02
#define AX_RX_BULKIN_QCTRL_SIZE 0x04
#define AX_RX_BULKIN_QTIMR_LOW 0x2f
#define AX_RX_BULKIN_QTIMR_HIGH 0x30
#define AX_RX_BULKIN_QSIZE 0x31
#define AX_RX_BULKIN_QIFG 0x32
#define AX_CLK_SELECT 0x33
#define AX_CLK_SELECT_BCS 0x01
#define AX_CLK_SELECT_ACS 0x02
#define AX_CLK_SELECT_ACSREQ 0x10
#define AX_CLK_SELECT_ULR 0x08
#define AX_RXCOE_CTL 0x34
#define AX_RXCOE_IP 0x01
#define AX_RXCOE_TCP 0x02
#define AX_RXCOE_UDP 0x04
#define AX_RXCOE_ICMP 0x08
#define AX_RXCOE_IGMP 0x10
#define AX_RXCOE_TCPV6 0x20
#define AX_RXCOE_UDPV6 0x40
#define AX_RXCOE_ICMV6 0x80
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IP | AX_RXCOE_TCP | \
AX_RXCOE_UDP | AX_RXCOE_ICMV6 | \
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
#define AX_TXCOE_CTL 0x35
#define AX_TXCOE_IP 0x01
#define AX_TXCOE_TCP 0x02
#define AX_TXCOE_UDP 0x04
#define AX_TXCOE_ICMP 0x08
#define AX_TXCOE_IGMP 0x10
#define AX_TXCOE_TCPV6 0x20
#define AX_TXCOE_UDPV6 0x40
#define AX_TXCOE_ICMV6 0x80
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
#define AX_PAUSE_WATERLVL_HIGH 0x54
#define AX_PAUSE_WATERLVL_LOW 0x55
#define AX_RX_FREE_BUF_LOW 0x57
#define GMII_PHY_CONTROL 0x00
#define GMII_CONTROL_RESET 0x8000
#define GMII_CONTROL_LOOPBACK 0x4000
#define GMII_CONTROL_10MB 0x0000
#define GMII_CONTROL_100MB 0x2000
#define GMII_CONTROL_1000MB 0x0040
#define GMII_CONTROL_SPEED_BITS 0x2040
#define GMII_CONTROL_ENABLE_AUTO 0x1000
#define GMII_CONTROL_POWER_DOWN 0x0800
#define GMII_CONTROL_ISOLATE 0x0400
#define GMII_CONTROL_START_AUTO 0x0200
#define GMII_CONTROL_FULL_DUPLEX 0x0100
#define GMII_PHY_STATUS 0x01
#define GMII_STATUS_100MB_MASK 0xE000
#define GMII_STATUS_10MB_MASK 0x1800
#define GMII_STATUS_AUTO_DONE 0x0020
#define GMII_STATUS_AUTO 0x0008
#define GMII_STATUS_LINK_UP 0x0004
#define GMII_STATUS_EXTENDED 0x0001
#define GMII_STATUS_100T4 0x8000
#define GMII_STATUS_100TXFD 0x4000
#define GMII_STATUS_100TX 0x2000
#define GMII_STATUS_10TFD 0x1000
#define GMII_STATUS_10T 0x0800
#define GMII_PHY_OUI 0x02
#define GMII_PHY_MODEL 0x03
#define GMII_PHY_ANAR 0x04
#define GMII_ANAR_ASYM_PAUSE 0x0800
#define GMII_ANAR_PAUSE 0x0400
#define GMII_ANAR_100T4 0x0200
#define GMII_ANAR_100TXFD 0x0100
#define GMII_ANAR_100TX 0x0080
#define GMII_ANAR_10TFD 0x0040
#define GMII_ANAR_10T 0x0020
#define GMII_SELECTOR_FIELD 0x001F
#define GMII_PHY_ANLPAR 0x05
#define GMII_ANLPAR_100T4 0x0200
#define GMII_ANLPAR_100TXFD 0x0100
#define GMII_ANLPAR_100TX 0x0080
#define GMII_ANLPAR_10TFD 0x0040
#define GMII_ANLPAR_10T 0x0020
#define GMII_ANLPAR_PAUSE 0x0400
#define GMII_ANLPAR_ASYM_PAUSE 0x0800
#define GMII_ANLPAR_ACK 0x4000
#define GMII_SELECTOR_8023 0x0001
#define GMII_PHY_ANER 0x06
#define GMII_PHY_1000BT_CONTROL 0x09
#define GMII_PHY_1000BT_STATUS 0x0A
#define GMII_PHY_MACR 0x0D
#define GMII_PHY_MAADR 0x0E
#define GMII_PHY_PHYSR 0x11
#define GMII_PHY_PHYSR_SMASK 0xc000
#define GMII_PHY_PHYSR_GIGA 0x8000
#define GMII_PHY_PHYSR_100 0x4000
#define GMII_PHY_PHYSR_FULL 0x2000
#define GMII_PHY_PHYSR_LINK 0x400
#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200
#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100
#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800
#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400
#define GMII_AUX_CTRL_STATUS 0x1C
#define GMII_AUX_ANEG_CPLT 0x8000
#define GMII_AUX_FDX 0x0020
#define GMII_AUX_SPEED_1000 0x0010
#define GMII_AUX_SPEED_100 0x0008
#define GMII_LED_ACTIVE 0x1a
#define GMII_LED_ACTIVE_MASK 0xff8f
#define GMII_LED0_ACTIVE BIT(4)
#define GMII_LED1_ACTIVE BIT(5)
#define GMII_LED2_ACTIVE BIT(6)
#define GMII_LED_LINK 0x1c
#define GMII_LED_LINK_MASK 0xf888
#define GMII_LED0_LINK_10 BIT(0)
#define GMII_LED0_LINK_100 BIT(1)
#define GMII_LED0_LINK_1000 BIT(2)
#define GMII_LED1_LINK_10 BIT(4)
#define GMII_LED1_LINK_100 BIT(5)
#define GMII_LED1_LINK_1000 BIT(6)
#define GMII_LED2_LINK_10 BIT(8)
#define GMII_LED2_LINK_100 BIT(9)
#define GMII_LED2_LINK_1000 BIT(10)
#define LED_VALID BIT(15)
#define LED0_ACTIVE BIT(0)
#define LED0_LINK_10 BIT(1)
#define LED0_LINK_100 BIT(2)
#define LED0_LINK_1000 BIT(3)
#define LED0_FD BIT(4)
#define LED0_USB3_MASK 0x001f
#define LED1_ACTIVE BIT(5)
#define LED1_LINK_10 BIT(6)
#define LED1_LINK_100 BIT(7)
#define LED1_LINK_1000 BIT(8)
#define LED1_FD BIT(9)
#define LED1_USB3_MASK 0x03e0
#define LED2_ACTIVE BIT(10)
#define LED2_LINK_1000 BIT(13)
#define LED2_LINK_100 BIT(12)
#define LED2_LINK_10 BIT(11)
#define LED2_FD BIT(14)
#define LED2_USB3_MASK 0x7c00
#define GMII_PHYPAGE 0x1e
#define GMII_PHY_PAGE_SELECT 0x1f
#define GMII_PHY_PAGE_SELECT_EXT 0x0007
#define GMII_PHY_PAGE_SELECT_PAGE0 0X0000
#define GMII_PHY_PAGE_SELECT_PAGE1 0X0001
#define GMII_PHY_PAGE_SELECT_PAGE2 0X0002
#define GMII_PHY_PAGE_SELECT_PAGE3 0X0003
#define GMII_PHY_PAGE_SELECT_PAGE4 0X0004
#define GMII_PHY_PAGE_SELECT_PAGE5 0X0005
#define GMII_PHY_PAGE_SELECT_PAGE6 0X0006
enum ax_driver_flags {
AX_UNPLUG = 0,
AX_ENABLE,
AX_LINK_CHG,
AX_SELECTIVE_SUSPEND,
AX_SCHEDULE_NAPI,
};
enum ax_chip_version {
AX_VERSION_INVALID = 0,
AX_VERSION_AX88179 = 4,
AX_VERSION_AX88179A_772D = 6,
};
struct ax_device;
struct rx_desc {
struct list_head list;
struct urb *urb;
struct ax_device *context;
void *buffer;
void *head;
};
enum __ax_tx_flags {
AX_TX_NONE = 0,
AX_TX_TIMESTAMPS = 1,
};
enum __mac_pass_ctrl {
MAC_PASS_DISABLED = 0,
MAC_PASS_ENABLE_0 = 1,
MAC_PASS_ENABLE_1 = 2,
};
struct mac_pass {
u8 control;
u8 mac0[8];
u8 mac1[8];
} __packed;
struct tx_desc {
struct list_head list;
struct urb *urb;
struct ax_device *context;
void *buffer;
void *head;
u32 skb_num;
u32 skb_len;
unsigned long flags;
int q_index;
};
struct ax_bulkin_setting {
u8 custom;
u8 bulkin_setting[5];
};
enum ax_ether_link_speed {
ETHER_LINK_NONE = 0,
ETHER_LINK_10 = 1,
ETHER_LINK_100 = 2,
ETHER_LINK_1000 = 3,
ETHER_LINK_2500 = 4,
};
struct ax_link_info {
u8 eth_speed : 3,
full_duplex : 1,
usb_speed : 4;
} __packed;
struct ax_device {
unsigned long flags;
struct usb_device *udev;
struct usb_interface *intf;
struct net_device *netdev;
const struct driver_info *driver_info;
struct napi_struct napi;
struct urb *intr_urb;
struct tx_desc tx_list[32];
struct rx_desc rx_list[32];
struct list_head rx_done, tx_free;
struct sk_buff_head tx_queue[AX_TX_QUEUE_SIZE];
struct sk_buff_head rx_queue;
spinlock_t rx_lock, tx_lock;
struct delayed_work schedule, hw_phy_work;
struct mii_if_info mii;
struct mutex control; /* protects device */
int intr_interval;
u32 saved_wolopts;
u32 msg_enable;
u32 tx_qlen;
u32 coalesce;
u16 speed;
u8 *intr_buff;
u8 tx_align_len;
u8 link;
u16 rxctl;
u8 m_filter[8];
u32 tx_casecade_size;
u32 gso_max_size;
u8 fw_version[4];
struct ax_link_info link_info;
struct ax_link_info intr_link_info;
u8 eee_enabled;
u8 eee_active;
int autodetach;
struct ax_bulkin_setting bin_setting;
bool tx_header_cksum;
unsigned char chip_version;
unsigned char sub_version;
#define AX_ETH_SPEED_MASK 0xF
#define AX_ETH_DUPLEX_FULL 0x10
u8 int_link_info;
u64 bulkin_complete;
u64 bulkin_error;
u64 bulkout_complete;
u64 bulkout_error;
u64 bulkint_complete;
u64 bulkint_error;
};
struct driver_info {
int (*bind)(struct ax_device *axdev);
void (*unbind)(struct ax_device *axdev);
int (*hw_init)(struct ax_device *axdev);
int (*stop)(struct ax_device *axdev);
void (*rx_fixup)(struct ax_device *axdev, struct rx_desc *desc,
int *work_done, int budget);
int (*tx_fixup)(struct ax_device *axdev, struct tx_desc *desc);
int (*link_reset)(struct ax_device *axdev);
int (*system_suspend)(struct ax_device *axdev);
int (*system_resume)(struct ax_device *axdev);
unsigned long napi_weight;
size_t buf_rx_size;
};
struct _async_cmd_handle {
struct ax_device *axdev;
struct usb_ctrlrequest *req;
u8 m_filter[8];
u16 rxctl;
} __packed;
struct ax_device_int_data {
u8 res1;
struct ax_link_info link_info;
#define AX_INT_PPLS_LINK BIT(0)
#define AX_INT_SPLS_LINK BIT(1)
#define AX_INT_CABOFF_UNPLUG BIT(7)
u8 link;
__le16 res2;
u8 status;
__le16 res3;
} __packed;
struct _ax_buikin_setting {
u8 ctrl;
u8 timer_l;
u8 timer_h;
u8 size;
u8 ifg;
} __packed;
#define AX_RXHDR_L4_ERR BIT(8)
#define AX_RXHDR_L3_ERR BIT(9)
#define AX_RXHDR_L4_TYPE_ICMP 2
#define AX_RXHDR_L4_TYPE_IGMP 3
#define AX_RXHDR_L4_TYPE_TCMPV6 5
#define AX_RXHDR_L3_TYPE_IP 1
#define AX_RXHDR_L3_TYPE_IPV6 2
#define AX_RXHDR_L4_TYPE_MASK 0x1c
#define AX_RXHDR_L4_TYPE_UDP 4
#define AX_RXHDR_L4_TYPE_TCP 16
#define AX_RXHDR_L3CSUM_ERR 2
#define AX_RXHDR_L4CSUM_ERR 1
#define AX_RXHDR_CRC_ERR 0x20000000
#define AX_RXHDR_MII_ERR 0x40000000
#define AX_RXHDR_DROP_ERR 0x80000000
int ax_check_ether_addr(struct ax_device *axdev);
int ax_get_mac_pass(struct ax_device *axdev, u8 *mac);
void ax_set_tx_qlen(struct ax_device *dev);
inline void *__rx_buf_align(void *data);
inline void *__tx_buf_align(void *data, u8 tx_align_len);
inline struct net_device_stats *ax_get_stats(struct net_device *dev);
void ax_write_bulk_callback(struct urb *urb);
void ax_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info);
int ax_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd);
int ax_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd);
u32 ax_get_msglevel(struct net_device *netdev);
void ax_set_msglevel(struct net_device *netdev, u32 value);
void ax_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo);
int ax_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo);
int ax_get_sset_count(struct net_device *dev, int sset);
void ax_get_ethtool_stats
(struct net_device *dev, struct ethtool_stats *stats, u64 *data);
void ax_get_strings(struct net_device *netdev, u32 stringset, u8 *data);
void ax_get_pauseparam
(struct net_device *netdev, struct ethtool_pauseparam *pause);
int ax_set_pauseparam
(struct net_device *netdev, struct ethtool_pauseparam *pause);
int ax_get_regs_len(struct net_device *netdev);
void ax_get_regs
(struct net_device *netdev, struct ethtool_regs *regs, void *buf);
int ax_read_cmd
(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data,
int eflag);
int ax_write_cmd
(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data);
int ax_read_cmd_nopm
(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data,
int eflag);
int ax_write_cmd_nopm
(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data);
int ax_write_cmd_async
(struct ax_device *axdev, u8 cmd, u16 value, u16 index, u16 size, void *data);
int ax_mmd_read(struct net_device *netdev, int dev_addr, int reg);
void ax_mmd_write(struct net_device *netdev, int dev_addr, int reg, int val);
int ax_mdio_read(struct net_device *netdev, int phy_id, int reg);
void ax_mdio_write(struct net_device *netdev, int phy_id, int reg, int val);
int ax_usb_command(struct ax_device *axdev, struct _ax_ioctl_command *info);
void ax_print_version(struct ax_device *axdev, const char *str);
#endif /* __ASIX_MAIN_H */