mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-18 21:28:02 +00:00
mediatek: add Airoha AN8855 gigabit switch driver
New revisions of Xiaomi AX3000T with 1.0.84+ stock firmware contain new hardware. This commit add support for Airoha AN8855 gigabit switch driver with 6.6 kernel patches Based on https://patchwork.kernel.org/project/netdevbpf/cover/20241108132511.18801-1-ansuelsmth@gmail.com/ Signed-off-by: Dim Fish <dimfish@gmail.com>
This commit is contained in:
parent
af611bce44
commit
401c3c22aa
@ -83,6 +83,14 @@
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
switch2: switch@1 {
|
||||
compatible = "airoha,an8855";
|
||||
reg = <1>;
|
||||
reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>;
|
||||
airoha,ext-surge;
|
||||
#nvmem-cell-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&switch {
|
||||
@ -124,6 +132,169 @@
|
||||
};
|
||||
};
|
||||
|
||||
&switch2 {
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
shift_sel_port0_tx_a: shift-sel-port0-tx-a@c {
|
||||
reg = <0xc 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 {
|
||||
reg = <0x10 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 {
|
||||
reg = <0x14 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 {
|
||||
reg = <0x18 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c {
|
||||
reg = <0x1c 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 {
|
||||
reg = <0x20 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 {
|
||||
reg = <0x24 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 {
|
||||
reg = <0x28 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port2_tx_a: shift-sel-port2-tx-a@2c {
|
||||
reg = <0x2c 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port2_tx_b: shift-sel-port2-tx-b@30 {
|
||||
reg = <0x30 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port2_tx_c: shift-sel-port2-tx-c@34 {
|
||||
reg = <0x34 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port2_tx_d: shift-sel-port2-tx-d@38 {
|
||||
reg = <0x38 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port3_tx_a: shift-sel-port3-tx-a@4c {
|
||||
reg = <0x4c 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port3_tx_b: shift-sel-port3-tx-b@50 {
|
||||
reg = <0x50 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port3_tx_c: shift-sel-port3-tx-c@54 {
|
||||
reg = <0x54 0x4>;
|
||||
};
|
||||
|
||||
shift_sel_port3_tx_d: shift-sel-port3-tx-d@58 {
|
||||
reg = <0x58 0x4>;
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "wan";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy1>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan2";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy2>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan3";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy3>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan4";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "2500base-x";
|
||||
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
internal_phy1: phy@1 {
|
||||
reg = <1>;
|
||||
|
||||
nvmem-cells = <&shift_sel_port0_tx_a>,
|
||||
<&shift_sel_port0_tx_b>,
|
||||
<&shift_sel_port0_tx_c>,
|
||||
<&shift_sel_port0_tx_d>;
|
||||
nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
|
||||
};
|
||||
|
||||
internal_phy2: phy@2 {
|
||||
reg = <2>;
|
||||
|
||||
nvmem-cells = <&shift_sel_port1_tx_a>,
|
||||
<&shift_sel_port1_tx_b>,
|
||||
<&shift_sel_port1_tx_c>,
|
||||
<&shift_sel_port1_tx_d>;
|
||||
nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
|
||||
};
|
||||
|
||||
internal_phy3: phy@3 {
|
||||
reg = <3>;
|
||||
|
||||
nvmem-cells = <&shift_sel_port2_tx_a>,
|
||||
<&shift_sel_port2_tx_b>,
|
||||
<&shift_sel_port2_tx_c>,
|
||||
<&shift_sel_port2_tx_d>;
|
||||
nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
|
||||
};
|
||||
|
||||
internal_phy4: phy@4 {
|
||||
reg = <4>;
|
||||
|
||||
nvmem-cells = <&shift_sel_port3_tx_a>,
|
||||
<&shift_sel_port3_tx_b>,
|
||||
<&shift_sel_port3_tx_c>,
|
||||
<&shift_sel_port3_tx_d>;
|
||||
nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi0_flash_pins>;
|
||||
|
2585
target/linux/mediatek/files-6.6/drivers/net/dsa/an8855.c
Normal file
2585
target/linux/mediatek/files-6.6/drivers/net/dsa/an8855.c
Normal file
File diff suppressed because it is too large
Load Diff
753
target/linux/mediatek/files-6.6/drivers/net/dsa/an8855.h
Normal file
753
target/linux/mediatek/files-6.6/drivers/net/dsa/an8855.h
Normal file
@ -0,0 +1,753 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2023 Min Yao <min.yao@airoha.com>
|
||||
* Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __AN8855_H
|
||||
#define __AN8855_H
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#define AN8855_NUM_PORTS 6
|
||||
#define AN8855_CPU_PORT 5
|
||||
#define AN8855_NUM_FDB_RECORDS 2048
|
||||
#define AN8855_GPHY_SMI_ADDR_DEFAULT 1
|
||||
#define AN8855_PORT_VID_DEFAULT 0
|
||||
#define AN8855_EFUSE_CELL 50
|
||||
|
||||
#define MTK_TAG_LEN 4
|
||||
#define AN8855_MAX_MTU (15360 - ETH_HLEN - ETH_FCS_LEN - MTK_TAG_LEN)
|
||||
|
||||
#define AN8855_L2_AGING_MS_CONSTANT 1024
|
||||
|
||||
#define AN8855_PHY_FLAGS_EN_CALIBRATION BIT(0)
|
||||
|
||||
/* MII Registers */
|
||||
#define AN8855_PHY_SELECT_PAGE 0x1f
|
||||
#define AN8855_PHY_PAGE GENMASK(2, 0)
|
||||
#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
|
||||
#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
|
||||
#define AN8855_PHY_PAGE_EXTENDED_4 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4)
|
||||
|
||||
/* MII Registers Page 4 */
|
||||
#define AN8855_PBUS_MODE 0x10
|
||||
#define AN8855_PBUS_MODE_ADDR_FIXED 0x0
|
||||
#define AN8855_PBUS_MODE_ADDR_INCR BIT(15)
|
||||
#define AN8855_PBUS_WR_ADDR_HIGH 0x11
|
||||
#define AN8855_PBUS_WR_ADDR_LOW 0x12
|
||||
#define AN8855_PBUS_WR_DATA_HIGH 0x13
|
||||
#define AN8855_PBUS_WR_DATA_LOW 0x14
|
||||
#define AN8855_PBUS_RD_ADDR_HIGH 0x15
|
||||
#define AN8855_PBUS_RD_ADDR_LOW 0x16
|
||||
#define AN8855_PBUS_RD_DATA_HIGH 0x17
|
||||
#define AN8855_PBUS_RD_DATA_LOW 0x18
|
||||
|
||||
/* AN8855_SCU 0x10000000 */
|
||||
#define AN8855_RG_GPIO_LED_MODE 0x10000054
|
||||
#define AN8855_RG_GPIO_LED_SEL(i) (0x10000000 + (0x0058 + ((i) * 4)))
|
||||
#define AN8855_RG_INTB_MODE 0x10000080
|
||||
#define AN8855_RG_RGMII_TXCK_C 0x100001d0
|
||||
|
||||
#define AN8855_PKG_SEL 0x10000094
|
||||
#define AN8855_PAG_SEL_AN8855H 0x2
|
||||
|
||||
/* Register for hw trap status */
|
||||
#define AN8855_HWTRAP 0x1000009c
|
||||
|
||||
#define AN8855_RG_GPIO_L_INV 0x10000010
|
||||
#define AN8855_RG_GPIO_CTRL 0x1000a300
|
||||
#define AN8855_RG_GPIO_DATA 0x1000a304
|
||||
#define AN8855_RG_GPIO_OE 0x1000a314
|
||||
|
||||
#define AN8855_EFUSE_DATA0 0x1000a500
|
||||
#define AN8855_EFUSE_R50O GENMASK(30, 24)
|
||||
|
||||
#define AN8855_CREV 0x10005000
|
||||
#define AN8855_ID 0x8855
|
||||
|
||||
/* Register for system reset */
|
||||
#define AN8855_RST_CTRL 0x100050c0
|
||||
#define AN8855_SYS_CTRL_SYS_RST BIT(31)
|
||||
|
||||
#define AN8855_INT_MASK 0x100050f0
|
||||
#define AN8855_INT_SYS BIT(15)
|
||||
|
||||
#define AN8855_RG_CLK_CPU_ICG 0x10005034
|
||||
#define AN8855_MCU_ENABLE BIT(3)
|
||||
|
||||
#define AN8855_RG_TIMER_CTL 0x1000a100
|
||||
#define AN8855_WDOG_ENABLE BIT(25)
|
||||
|
||||
#define AN8855_RG_GDMP_RAM 0x10010000
|
||||
|
||||
/* Registers to mac forward control for unknown frames */
|
||||
#define AN8855_MFC 0x10200010
|
||||
#define AN8855_CPU_EN BIT(15)
|
||||
#define AN8855_CPU_PORT_IDX GENMASK(12, 8)
|
||||
|
||||
#define AN8855_AAC 0x102000a0
|
||||
#define AN8855_MAC_AUTO_FLUSH BIT(28)
|
||||
/* Control Address Table Age time.
|
||||
* (AN8855_AGE_CNT + 1) * ( AN8855_AGE_UNIT + 1 ) * AN8855_L2_AGING_MS_CONSTANT
|
||||
*/
|
||||
#define AN8855_AGE_CNT GENMASK(20, 12)
|
||||
/* Value in seconds. Value is always incremented of 1 */
|
||||
#define AN8855_AGE_UNIT GENMASK(10, 0)
|
||||
|
||||
/* Registers for ARL Unknown Unicast Forward control */
|
||||
#define AN8855_UNUF 0x102000b4
|
||||
|
||||
/* Registers for ARL Unknown Multicast Forward control */
|
||||
#define AN8855_UNMF 0x102000b8
|
||||
|
||||
/* Registers for ARL Broadcast forward control */
|
||||
#define AN8855_BCF 0x102000bc
|
||||
|
||||
/* Registers for port address age disable */
|
||||
#define AN8855_AGDIS 0x102000c0
|
||||
|
||||
/* Registers for mirror port control */
|
||||
#define AN8855_MIR 0x102000cc
|
||||
#define AN8855_MIRROR_EN BIT(7)
|
||||
#define AN8855_MIRROR_PORT GENMASK(4, 0)
|
||||
|
||||
/* Registers for BPDU and PAE frame control*/
|
||||
#define AN8855_BPC 0x102000D0
|
||||
#define AN8855_BPDU_PORT_FW GENMASK(2, 0)
|
||||
|
||||
enum an8855_bpdu_port_fw {
|
||||
AN8855_BPDU_FOLLOW_MFC = 0,
|
||||
AN8855_BPDU_CPU_EXCLUDE = 4,
|
||||
AN8855_BPDU_CPU_INCLUDE = 5,
|
||||
AN8855_BPDU_CPU_ONLY = 6,
|
||||
AN8855_BPDU_DROP = 7,
|
||||
};
|
||||
|
||||
/* Register for address table control */
|
||||
#define AN8855_ATC 0x10200300
|
||||
#define AN8855_ATC_BUSY BIT(31)
|
||||
#define AN8855_ATC_HASH GENMASK(24, 16)
|
||||
#define AN8855_ATC_HIT GENMASK(15, 12)
|
||||
#define AN8855_ATC_MAT_MASK GENMASK(11, 7)
|
||||
#define AN8855_ATC_MAT(x) FIELD_PREP(AN8855_ATC_MAT_MASK, x)
|
||||
#define AN8855_ATC_SAT GENMASK(5, 4)
|
||||
#define AN8855_ATC_CMD GENMASK(2, 0)
|
||||
|
||||
enum an8855_fdb_mat_cmds {
|
||||
AND8855_FDB_MAT_ALL = 0,
|
||||
AND8855_FDB_MAT_MAC, /* All MAC address */
|
||||
AND8855_FDB_MAT_DYNAMIC_MAC, /* All Dynamic MAC address */
|
||||
AND8855_FDB_MAT_STATIC_MAC, /* All Static Mac Address */
|
||||
AND8855_FDB_MAT_DIP, /* All DIP/GA address */
|
||||
AND8855_FDB_MAT_DIP_IPV4, /* All DIP/GA IPv4 address */
|
||||
AND8855_FDB_MAT_DIP_IPV6, /* All DIP/GA IPv6 address */
|
||||
AND8855_FDB_MAT_DIP_SIP, /* All DIP_SIP address */
|
||||
AND8855_FDB_MAT_DIP_SIP_IPV4, /* All DIP_SIP IPv4 address */
|
||||
AND8855_FDB_MAT_DIP_SIP_IPV6, /* All DIP_SIP IPv6 address */
|
||||
AND8855_FDB_MAT_MAC_CVID, /* All MAC address with CVID */
|
||||
AND8855_FDB_MAT_MAC_FID, /* All MAC address with Filter ID */
|
||||
AND8855_FDB_MAT_MAC_PORT, /* All MAC address with port */
|
||||
AND8855_FDB_MAT_DIP_SIP_DIP_IPV4, /* All DIP_SIP address with DIP_IPV4 */
|
||||
AND8855_FDB_MAT_DIP_SIP_SIP_IPV4, /* All DIP_SIP address with SIP_IPV4 */
|
||||
AND8855_FDB_MAT_DIP_SIP_DIP_IPV6, /* All DIP_SIP address with DIP_IPV6 */
|
||||
AND8855_FDB_MAT_DIP_SIP_SIP_IPV6, /* All DIP_SIP address with SIP_IPV6 */
|
||||
/* All MAC address with MAC type (dynamic or static) with CVID */
|
||||
AND8855_FDB_MAT_MAC_TYPE_CVID,
|
||||
/* All MAC address with MAC type (dynamic or static) with Filter ID */
|
||||
AND8855_FDB_MAT_MAC_TYPE_FID,
|
||||
/* All MAC address with MAC type (dynamic or static) with port */
|
||||
AND8855_FDB_MAT_MAC_TYPE_PORT,
|
||||
};
|
||||
|
||||
enum an8855_fdb_cmds {
|
||||
AN8855_FDB_READ = 0,
|
||||
AN8855_FDB_WRITE = 1,
|
||||
AN8855_FDB_FLUSH = 2,
|
||||
AN8855_FDB_START = 4,
|
||||
AN8855_FDB_NEXT = 5,
|
||||
};
|
||||
|
||||
/* Registers for address table access */
|
||||
#define AN8855_ATA1 0x10200304
|
||||
#define AN8855_ATA1_MAC0 GENMASK(31, 24)
|
||||
#define AN8855_ATA1_MAC1 GENMASK(23, 16)
|
||||
#define AN8855_ATA1_MAC2 GENMASK(15, 8)
|
||||
#define AN8855_ATA1_MAC3 GENMASK(7, 0)
|
||||
#define AN8855_ATA2 0x10200308
|
||||
#define AN8855_ATA2_MAC4 GENMASK(31, 24)
|
||||
#define AN8855_ATA2_MAC5 GENMASK(23, 16)
|
||||
#define AN8855_ATA2_UNAUTH BIT(10)
|
||||
#define AN8855_ATA2_TYPE BIT(9) /* 1: dynamic, 0: static */
|
||||
#define AN8855_ATA2_AGE GENMASK(8, 0)
|
||||
|
||||
/* Register for address table write data */
|
||||
#define AN8855_ATWD 0x10200324
|
||||
#define AN8855_ATWD_FID GENMASK(31, 28)
|
||||
#define AN8855_ATWD_VID GENMASK(27, 16)
|
||||
#define AN8855_ATWD_IVL BIT(15)
|
||||
#define AN8855_ATWD_EG_TAG GENMASK(14, 12)
|
||||
#define AN8855_ATWD_SA_MIR GENMASK(9, 8)
|
||||
#define AN8855_ATWD_SA_FWD GENMASK(7, 5)
|
||||
#define AN8855_ATWD_UPRI GENMASK(4, 2)
|
||||
#define AN8855_ATWD_LEAKY BIT(1)
|
||||
#define AN8855_ATWD_VLD BIT(0) /* vid LOAD */
|
||||
#define AN8855_ATWD2 0x10200328
|
||||
#define AN8855_ATWD2_PORT GENMASK(7, 0)
|
||||
|
||||
/* Registers for table search read address */
|
||||
#define AN8855_ATRDS 0x10200330
|
||||
#define AN8855_ATRD_SEL GENMASK(1, 0)
|
||||
#define AN8855_ATRD0 0x10200334
|
||||
#define AN8855_ATRD0_FID GENMASK(28, 25)
|
||||
#define AN8855_ATRD0_VID GENMASK(21, 10)
|
||||
#define AN8855_ATRD0_IVL BIT(9)
|
||||
#define AN8855_ATRD0_TYPE GENMASK(4, 3)
|
||||
#define AN8855_ATRD0_ARP GENMASK(2, 1)
|
||||
#define AN8855_ATRD0_LIVE BIT(0)
|
||||
#define AN8855_ATRD1 0x10200338
|
||||
#define AN8855_ATRD1_MAC4 GENMASK(31, 24)
|
||||
#define AN8855_ATRD1_MAC5 GENMASK(23, 16)
|
||||
#define AN8855_ATRD1_AGING GENMASK(10, 3)
|
||||
#define AN8855_ATRD2 0x1020033c
|
||||
#define AN8855_ATRD2_MAC0 GENMASK(31, 24)
|
||||
#define AN8855_ATRD2_MAC1 GENMASK(23, 16)
|
||||
#define AN8855_ATRD2_MAC2 GENMASK(15, 8)
|
||||
#define AN8855_ATRD2_MAC3 GENMASK(7, 0)
|
||||
#define AN8855_ATRD3 0x10200340
|
||||
#define AN8855_ATRD3_PORTMASK GENMASK(7, 0)
|
||||
|
||||
enum an8855_fdb_type {
|
||||
AN8855_MAC_TB_TY_MAC = 0,
|
||||
AN8855_MAC_TB_TY_DIP = 1,
|
||||
AN8855_MAC_TB_TY_DIP_SIP = 2,
|
||||
};
|
||||
|
||||
/* Register for vlan table control */
|
||||
#define AN8855_VTCR 0x10200600
|
||||
#define AN8855_VTCR_BUSY BIT(31)
|
||||
#define AN8855_VTCR_FUNC GENMASK(15, 12)
|
||||
#define AN8855_VTCR_VID GENMASK(11, 0)
|
||||
|
||||
enum an8855_vlan_cmd {
|
||||
/* Read/Write the specified VID entry from VAWD register based
|
||||
* on VID.
|
||||
*/
|
||||
AN8855_VTCR_RD_VID = 0,
|
||||
AN8855_VTCR_WR_VID = 1,
|
||||
};
|
||||
|
||||
/* Register for setup vlan write data */
|
||||
#define AN8855_VAWD0 0x10200604
|
||||
/* VLAN Member Control */
|
||||
#define AN8855_VA0_PORT GENMASK(31, 26)
|
||||
/* Egress Tag Control */
|
||||
#define AN8855_VA0_ETAG GENMASK(23, 12)
|
||||
#define AN8855_VA0_ETAG_PORT GENMASK(13, 12)
|
||||
#define AN8855_VA0_ETAG_PORT_SHIFT(port) ((port) * 2)
|
||||
#define AN8855_VA0_ETAG_PORT_MASK(port) (AN8855_VA0_ETAG_PORT << \
|
||||
AN8855_VA0_ETAG_PORT_SHIFT(port))
|
||||
#define AN8855_VA0_ETAG_PORT_VAL(port, val) (FIELD_PREP(AN8855_VA0_ETAG_PORT, (val)) << \
|
||||
AN8855_VA0_ETAG_PORT_SHIFT(port))
|
||||
#define AN8855_VA0_EG_CON BIT(11)
|
||||
#define AN8855_VA0_VTAG_EN BIT(10) /* Per VLAN Egress Tag Control */
|
||||
#define AN8855_VA0_IVL_MAC BIT(5) /* Independent VLAN Learning */
|
||||
#define AN8855_VA0_FID GENMASK(4, 1)
|
||||
#define AN8855_VA0_VLAN_VALID BIT(0) /* VLAN Entry Valid */
|
||||
#define AN8855_VAWD1 0x10200608
|
||||
#define AN8855_VA1_PORT_STAG BIT(1)
|
||||
|
||||
enum an8855_fid {
|
||||
AN8855_FID_STANDALONE = 0,
|
||||
AN8855_FID_BRIDGED = 1,
|
||||
};
|
||||
|
||||
/* Same register field of VAWD0 */
|
||||
#define AN8855_VARD0 0x10200618
|
||||
|
||||
enum an8855_vlan_egress_attr {
|
||||
AN8855_VLAN_EGRESS_UNTAG = 0,
|
||||
AN8855_VLAN_EGRESS_TAG = 2,
|
||||
AN8855_VLAN_EGRESS_STACK = 3,
|
||||
};
|
||||
|
||||
/* Register for port STP state control */
|
||||
#define AN8855_SSP_P(x) (0x10208000 + ((x) * 0x200))
|
||||
/* Up to 16 FID supported, each with the same mask */
|
||||
#define AN8855_FID_PST GENMASK(1, 0)
|
||||
#define AN8855_FID_PST_SHIFT(fid) (2 * (fid))
|
||||
#define AN8855_FID_PST_MASK(fid) (AN8855_FID_PST << \
|
||||
AN8855_FID_PST_SHIFT(fid))
|
||||
#define AN8855_FID_PST_VAL(fid, val) (FIELD_PREP(AN8855_FID_PST, (val)) << \
|
||||
AN8855_FID_PST_SHIFT(fid))
|
||||
|
||||
enum an8855_stp_state {
|
||||
AN8855_STP_DISABLED = 0,
|
||||
AN8855_STP_BLOCKING = 1,
|
||||
AN8855_STP_LISTENING = AN8855_STP_BLOCKING,
|
||||
AN8855_STP_LEARNING = 2,
|
||||
AN8855_STP_FORWARDING = 3
|
||||
};
|
||||
|
||||
/* Register for port control */
|
||||
#define AN8855_PCR_P(x) (0x10208004 + ((x) * 0x200))
|
||||
#define AN8855_EG_TAG GENMASK(29, 28)
|
||||
#define AN8855_PORT_PRI GENMASK(26, 24)
|
||||
#define AN8855_PORT_TX_MIR BIT(20)
|
||||
#define AN8855_PORT_RX_MIR BIT(16)
|
||||
#define AN8855_PORT_VLAN GENMASK(1, 0)
|
||||
|
||||
enum an8855_port_mode {
|
||||
/* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */
|
||||
AN8855_PORT_MATRIX_MODE = 0,
|
||||
|
||||
/* Fallback Mode: Forward received frames with ingress ports that do
|
||||
* not belong to the VLAN member. Frames whose VID is not listed on
|
||||
* the VLAN table are forwarded by the PCR_MATRIX members.
|
||||
*/
|
||||
AN8855_PORT_FALLBACK_MODE = 1,
|
||||
|
||||
/* Check Mode: Forward received frames whose ingress do not
|
||||
* belong to the VLAN member. Discard frames if VID ismiddes on the
|
||||
* VLAN table.
|
||||
*/
|
||||
AN8855_PORT_CHECK_MODE = 2,
|
||||
|
||||
/* Security Mode: Discard any frame due to ingress membership
|
||||
* violation or VID missed on the VLAN table.
|
||||
*/
|
||||
AN8855_PORT_SECURITY_MODE = 3,
|
||||
};
|
||||
|
||||
/* Register for port security control */
|
||||
#define AN8855_PSC_P(x) (0x1020800c + ((x) * 0x200))
|
||||
#define AN8855_SA_DIS BIT(4)
|
||||
|
||||
/* Register for port vlan control */
|
||||
#define AN8855_PVC_P(x) (0x10208010 + ((x) * 0x200))
|
||||
#define AN8855_PORT_SPEC_REPLACE_MODE BIT(11)
|
||||
#define AN8855_PVC_EG_TAG GENMASK(10, 8)
|
||||
#define AN8855_VLAN_ATTR GENMASK(7, 6)
|
||||
#define AN8855_PORT_SPEC_TAG BIT(5)
|
||||
#define AN8855_ACC_FRM GENMASK(1, 0)
|
||||
|
||||
enum an8855_vlan_port_eg_tag {
|
||||
AN8855_VLAN_EG_DISABLED = 0,
|
||||
AN8855_VLAN_EG_CONSISTENT = 1,
|
||||
AN8855_VLAN_EG_UNTAGGED = 4,
|
||||
AN8855_VLAN_EG_SWAP = 5,
|
||||
AN8855_VLAN_EG_TAGGED = 6,
|
||||
AN8855_VLAN_EG_STACK = 7,
|
||||
};
|
||||
|
||||
enum an8855_vlan_port_attr {
|
||||
AN8855_VLAN_USER = 0,
|
||||
AN8855_VLAN_STACK = 1,
|
||||
AN8855_VLAN_TRANSPARENT = 3,
|
||||
};
|
||||
|
||||
enum an8855_vlan_port_acc_frm {
|
||||
AN8855_VLAN_ACC_ALL = 0,
|
||||
AN8855_VLAN_ACC_TAGGED = 1,
|
||||
AN8855_VLAN_ACC_UNTAGGED = 2,
|
||||
};
|
||||
|
||||
#define AN8855_PPBV1_P(x) (0x10208014 + ((x) * 0x200))
|
||||
#define AN8855_PPBV_G0_PORT_VID GENMASK(11, 0)
|
||||
|
||||
#define AN8855_PORTMATRIX_P(x) (0x10208044 + ((x) * 0x200))
|
||||
#define AN8855_PORTMATRIX GENMASK(5, 0)
|
||||
/* Port matrix without the CPU port that should never be removed */
|
||||
#define AN8855_USER_PORTMATRIX GENMASK(4, 0)
|
||||
|
||||
/* Register for port PVID */
|
||||
#define AN8855_PVID_P(x) (0x10208048 + ((x) * 0x200))
|
||||
#define AN8855_G0_PORT_VID GENMASK(11, 0)
|
||||
|
||||
/* Register for port MAC control register */
|
||||
#define AN8855_PMCR_P(x) (0x10210000 + ((x) * 0x200))
|
||||
#define AN8855_PMCR_FORCE_MODE BIT(31)
|
||||
#define AN8855_PMCR_FORCE_SPEED GENMASK(30, 28)
|
||||
#define AN8855_PMCR_FORCE_SPEED_5000 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x4)
|
||||
#define AN8855_PMCR_FORCE_SPEED_2500 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x3)
|
||||
#define AN8855_PMCR_FORCE_SPEED_1000 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x2)
|
||||
#define AN8855_PMCR_FORCE_SPEED_100 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1)
|
||||
#define AN8855_PMCR_FORCE_SPEED_10 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1)
|
||||
#define AN8855_PMCR_FORCE_FDX BIT(25)
|
||||
#define AN8855_PMCR_FORCE_LNK BIT(24)
|
||||
#define AN8855_PMCR_IFG_XMIT GENMASK(21, 20)
|
||||
#define AN8855_PMCR_EXT_PHY BIT(19)
|
||||
#define AN8855_PMCR_MAC_MODE BIT(18)
|
||||
#define AN8855_PMCR_TX_EN BIT(16)
|
||||
#define AN8855_PMCR_RX_EN BIT(15)
|
||||
#define AN8855_PMCR_BACKOFF_EN BIT(12)
|
||||
#define AN8855_PMCR_BACKPR_EN BIT(11)
|
||||
#define AN8855_PMCR_FORCE_EEE5G BIT(9)
|
||||
#define AN8855_PMCR_FORCE_EEE2P5G BIT(8)
|
||||
#define AN8855_PMCR_FORCE_EEE1G BIT(7)
|
||||
#define AN8855_PMCR_FORCE_EEE100 BIT(6)
|
||||
#define AN8855_PMCR_TX_FC_EN BIT(5)
|
||||
#define AN8855_PMCR_RX_FC_EN BIT(4)
|
||||
|
||||
#define AN8855_PMSR_P(x) (0x10210010 + (x) * 0x200)
|
||||
#define AN8855_PMSR_SPEED GENMASK(30, 28)
|
||||
#define AN8855_PMSR_SPEED_5000 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x4)
|
||||
#define AN8855_PMSR_SPEED_2500 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x3)
|
||||
#define AN8855_PMSR_SPEED_1000 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x2)
|
||||
#define AN8855_PMSR_SPEED_100 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x1)
|
||||
#define AN8855_PMSR_SPEED_10 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x0)
|
||||
#define AN8855_PMSR_DPX BIT(25)
|
||||
#define AN8855_PMSR_LNK BIT(24)
|
||||
#define AN8855_PMSR_EEE1G BIT(7)
|
||||
#define AN8855_PMSR_EEE100M BIT(6)
|
||||
#define AN8855_PMSR_RX_FC BIT(5)
|
||||
#define AN8855_PMSR_TX_FC BIT(4)
|
||||
|
||||
#define AN8855_PMEEECR_P(x) (0x10210004 + (x) * 0x200)
|
||||
#define AN8855_LPI_MODE_EN BIT(31)
|
||||
#define AN8855_WAKEUP_TIME_2500 GENMASK(23, 16)
|
||||
#define AN8855_WAKEUP_TIME_1000 GENMASK(15, 8)
|
||||
#define AN8855_WAKEUP_TIME_100 GENMASK(7, 0)
|
||||
#define AN8855_PMEEECR2_P(x) (0x10210008 + (x) * 0x200)
|
||||
#define AN8855_WAKEUP_TIME_5000 GENMASK(7, 0)
|
||||
|
||||
#define AN8855_GMACCR 0x10213e00
|
||||
#define AN8855_MAX_RX_JUMBO GENMASK(7, 4)
|
||||
/* 2K for 0x0, 0x1, 0x2 */
|
||||
#define AN8855_MAX_RX_JUMBO_2K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x0)
|
||||
#define AN8855_MAX_RX_JUMBO_3K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x3)
|
||||
#define AN8855_MAX_RX_JUMBO_4K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x4)
|
||||
#define AN8855_MAX_RX_JUMBO_5K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x5)
|
||||
#define AN8855_MAX_RX_JUMBO_6K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x6)
|
||||
#define AN8855_MAX_RX_JUMBO_7K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x7)
|
||||
#define AN8855_MAX_RX_JUMBO_8K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x8)
|
||||
#define AN8855_MAX_RX_JUMBO_9K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x9)
|
||||
#define AN8855_MAX_RX_JUMBO_12K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xa)
|
||||
#define AN8855_MAX_RX_JUMBO_15K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xb)
|
||||
#define AN8855_MAX_RX_JUMBO_16K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xc)
|
||||
#define AN8855_MAX_RX_PKT_LEN GENMASK(1, 0)
|
||||
#define AN8855_MAX_RX_PKT_1518_1522 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x0)
|
||||
#define AN8855_MAX_RX_PKT_1536 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x1)
|
||||
#define AN8855_MAX_RX_PKT_1552 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x2)
|
||||
#define AN8855_MAX_RX_PKT_JUMBO FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x3)
|
||||
|
||||
#define AN8855_CKGCR 0x10213e1c
|
||||
#define AN8855_LPI_TXIDLE_THD_MASK GENMASK(31, 14)
|
||||
#define AN8855_CKG_LNKDN_PORT_STOP BIT(1)
|
||||
#define AN8855_CKG_LNKDN_GLB_STOP BIT(0)
|
||||
|
||||
/* Register for MIB */
|
||||
#define AN8855_PORT_MIB_COUNTER(x) (0x10214000 + (x) * 0x200)
|
||||
/* Each define is an offset of AN8855_PORT_MIB_COUNTER */
|
||||
#define AN8855_PORT_MIB_TX_DROP 0x00
|
||||
#define AN8855_PORT_MIB_TX_CRC_ERR 0x04
|
||||
#define AN8855_PORT_MIB_TX_UNICAST 0x08
|
||||
#define AN8855_PORT_MIB_TX_MULTICAST 0x0c
|
||||
#define AN8855_PORT_MIB_TX_BROADCAST 0x10
|
||||
#define AN8855_PORT_MIB_TX_COLLISION 0x14
|
||||
#define AN8855_PORT_MIB_TX_SINGLE_COLLISION 0x18
|
||||
#define AN8855_PORT_MIB_TX_MULTIPLE_COLLISION 0x1c
|
||||
#define AN8855_PORT_MIB_TX_DEFERRED 0x20
|
||||
#define AN8855_PORT_MIB_TX_LATE_COLLISION 0x24
|
||||
#define AN8855_PORT_MIB_TX_EXCESSIVE_COLLISION 0x28
|
||||
#define AN8855_PORT_MIB_TX_PAUSE 0x2c
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_64 0x30
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_65_TO_127 0x34
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_128_TO_255 0x38
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_256_TO_511 0x3
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_512_TO_1023 0x40
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_1024_TO_1518 0x44
|
||||
#define AN8855_PORT_MIB_TX_PKT_SZ_1519_TO_MAX 0x48
|
||||
#define AN8855_PORT_MIB_TX_BYTES 0x4c /* 64 bytes */
|
||||
#define AN8855_PORT_MIB_TX_OVERSIZE_DROP 0x54
|
||||
#define AN8855_PORT_MIB_TX_BAD_PKT_BYTES 0x58 /* 64 bytes */
|
||||
#define AN8855_PORT_MIB_RX_DROP 0x80
|
||||
#define AN8855_PORT_MIB_RX_FILTERING 0x84
|
||||
#define AN8855_PORT_MIB_RX_UNICAST 0x88
|
||||
#define AN8855_PORT_MIB_RX_MULTICAST 0x8c
|
||||
#define AN8855_PORT_MIB_RX_BROADCAST 0x90
|
||||
#define AN8855_PORT_MIB_RX_ALIGN_ERR 0x94
|
||||
#define AN8855_PORT_MIB_RX_CRC_ERR 0x98
|
||||
#define AN8855_PORT_MIB_RX_UNDER_SIZE_ERR 0x9c
|
||||
#define AN8855_PORT_MIB_RX_FRAG_ERR 0xa0
|
||||
#define AN8855_PORT_MIB_RX_OVER_SZ_ERR 0xa4
|
||||
#define AN8855_PORT_MIB_RX_JABBER_ERR 0xa8
|
||||
#define AN8855_PORT_MIB_RX_PAUSE 0xac
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_64 0xb0
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_65_TO_127 0xb4
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_128_TO_255 0xb8
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_256_TO_511 0xbc
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_512_TO_1023 0xc0
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_1024_TO_1518 0xc4
|
||||
#define AN8855_PORT_MIB_RX_PKT_SZ_1519_TO_MAX 0xc8
|
||||
#define AN8855_PORT_MIB_RX_BYTES 0xcc /* 64 bytes */
|
||||
#define AN8855_PORT_MIB_RX_CTRL_DROP 0xd4
|
||||
#define AN8855_PORT_MIB_RX_INGRESS_DROP 0xd8
|
||||
#define AN8855_PORT_MIB_RX_ARL_DROP 0xdc
|
||||
#define AN8855_PORT_MIB_FLOW_CONTROL_DROP 0xe0
|
||||
#define AN8855_PORT_MIB_WRED_DROP 0xe4
|
||||
#define AN8855_PORT_MIB_MIRROR_DROP 0xe8
|
||||
#define AN8855_PORT_MIB_RX_BAD_PKT_BYTES 0xec /* 64 bytes */
|
||||
#define AN8855_PORT_MIB_RXS_FLOW_SAMPLING_PKT_DROP 0xf4
|
||||
#define AN8855_PORT_MIB_RXS_FLOW_TOTAL_PKT_DROP 0xf8
|
||||
#define AN8855_PORT_MIB_PORT_CONTROL_DROP 0xfc
|
||||
#define AN8855_MIB_CCR 0x10213e30
|
||||
#define AN8855_CCR_MIB_ENABLE BIT(31)
|
||||
#define AN8855_CCR_RX_OCT_CNT_GOOD BIT(7)
|
||||
#define AN8855_CCR_RX_OCT_CNT_BAD BIT(6)
|
||||
#define AN8855_CCR_TX_OCT_CNT_GOOD BIT(5)
|
||||
#define AN8855_CCR_TX_OCT_CNT_BAD BIT(4)
|
||||
#define AN8855_CCR_RX_OCT_CNT_GOOD_2 BIT(3)
|
||||
#define AN8855_CCR_RX_OCT_CNT_BAD_2 BIT(2)
|
||||
#define AN8855_CCR_TX_OCT_CNT_GOOD_2 BIT(1)
|
||||
#define AN8855_CCR_TX_OCT_CNT_BAD_2 BIT(0)
|
||||
#define AN8855_CCR_MIB_ACTIVATE (AN8855_CCR_MIB_ENABLE | \
|
||||
AN8855_CCR_RX_OCT_CNT_GOOD | \
|
||||
AN8855_CCR_RX_OCT_CNT_BAD | \
|
||||
AN8855_CCR_TX_OCT_CNT_GOOD | \
|
||||
AN8855_CCR_TX_OCT_CNT_BAD | \
|
||||
AN8855_CCR_RX_OCT_CNT_BAD_2 | \
|
||||
AN8855_CCR_TX_OCT_CNT_BAD_2)
|
||||
#define AN8855_MIB_CLR 0x10213e34
|
||||
#define AN8855_MIB_PORT6_CLR BIT(6)
|
||||
#define AN8855_MIB_PORT5_CLR BIT(5)
|
||||
#define AN8855_MIB_PORT4_CLR BIT(4)
|
||||
#define AN8855_MIB_PORT3_CLR BIT(3)
|
||||
#define AN8855_MIB_PORT2_CLR BIT(2)
|
||||
#define AN8855_MIB_PORT1_CLR BIT(1)
|
||||
#define AN8855_MIB_PORT0_CLR BIT(0)
|
||||
|
||||
/* HSGMII/SGMII Configuration register */
|
||||
/* AN8855_HSGMII_AN_CSR_BASE 0x10220000 */
|
||||
#define AN8855_SGMII_REG_AN0 0x10220000
|
||||
/* AN8855_SGMII_AN_ENABLE BMCR_ANENABLE */
|
||||
/* AN8855_SGMII_AN_RESTART BMCR_ANRESTART */
|
||||
#define AN8855_SGMII_REG_AN_13 0x10220034
|
||||
#define AN8855_SGMII_REMOTE_FAULT_DIS BIT(8)
|
||||
#define AN8855_SGMII_IF_MODE GENMASK(5, 0)
|
||||
#define AN8855_SGMII_REG_AN_FORCE_CL37 0x10220060
|
||||
#define AN8855_RG_FORCE_AN_DONE BIT(0)
|
||||
|
||||
/* AN8855_HSGMII_CSR_PCS_BASE 0x10220000 */
|
||||
#define AN8855_RG_HSGMII_PCS_CTROL_1 0x10220a00
|
||||
#define AN8855_RG_TBI_10B_MODE BIT(30)
|
||||
#define AN8855_RG_AN_SGMII_MODE_FORCE 0x10220a24
|
||||
#define AN8855_RG_FORCE_CUR_SGMII_MODE GENMASK(5, 4)
|
||||
#define AN8855_RG_FORCE_CUR_SGMII_SEL BIT(0)
|
||||
|
||||
/* AN8855_MULTI_SGMII_CSR_BASE 0x10224000 */
|
||||
#define AN8855_SGMII_STS_CTRL_0 0x10224018
|
||||
#define AN8855_RG_LINK_MODE_P0 GENMASK(5, 4)
|
||||
#define AN8855_RG_LINK_MODE_P0_SPEED_2500 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x3)
|
||||
#define AN8855_RG_LINK_MODE_P0_SPEED_1000 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x2)
|
||||
#define AN8855_RG_LINK_MODE_P0_SPEED_100 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x1)
|
||||
#define AN8855_RG_LINK_MODE_P0_SPEED_10 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x0)
|
||||
#define AN8855_RG_FORCE_SPD_MODE_P0 BIT(2)
|
||||
#define AN8855_MSG_RX_CTRL_0 0x10224100
|
||||
#define AN8855_MSG_RX_LIK_STS_0 0x10224514
|
||||
#define AN8855_RG_DPX_STS_P3 BIT(24)
|
||||
#define AN8855_RG_DPX_STS_P2 BIT(16)
|
||||
#define AN8855_RG_EEE1G_STS_P1 BIT(12)
|
||||
#define AN8855_RG_DPX_STS_P1 BIT(8)
|
||||
#define AN8855_RG_TXFC_STS_P0 BIT(2)
|
||||
#define AN8855_RG_RXFC_STS_P0 BIT(1)
|
||||
#define AN8855_RG_DPX_STS_P0 BIT(0)
|
||||
#define AN8855_MSG_RX_LIK_STS_2 0x1022451c
|
||||
#define AN8855_RG_RXFC_AN_BYPASS_P3 BIT(11)
|
||||
#define AN8855_RG_RXFC_AN_BYPASS_P2 BIT(10)
|
||||
#define AN8855_RG_RXFC_AN_BYPASS_P1 BIT(9)
|
||||
#define AN8855_RG_TXFC_AN_BYPASS_P3 BIT(7)
|
||||
#define AN8855_RG_TXFC_AN_BYPASS_P2 BIT(6)
|
||||
#define AN8855_RG_TXFC_AN_BYPASS_P1 BIT(5)
|
||||
#define AN8855_RG_DPX_AN_BYPASS_P3 BIT(3)
|
||||
#define AN8855_RG_DPX_AN_BYPASS_P2 BIT(2)
|
||||
#define AN8855_RG_DPX_AN_BYPASS_P1 BIT(1)
|
||||
#define AN8855_RG_DPX_AN_BYPASS_P0 BIT(0)
|
||||
#define AN8855_PHY_RX_FORCE_CTRL_0 0x10224520
|
||||
#define AN8855_RG_FORCE_TXC_SEL BIT(4)
|
||||
|
||||
/* AN8855_XFI_CSR_PCS_BASE 0x10225000 */
|
||||
#define AN8855_RG_USXGMII_AN_CONTROL_0 0x10225bf8
|
||||
|
||||
/* AN8855_MULTI_PHY_RA_CSR_BASE 0x10226000 */
|
||||
#define AN8855_RG_RATE_ADAPT_CTRL_0 0x10226000
|
||||
#define AN8855_RG_RATE_ADAPT_RX_BYPASS BIT(27)
|
||||
#define AN8855_RG_RATE_ADAPT_TX_BYPASS BIT(26)
|
||||
#define AN8855_RG_RATE_ADAPT_RX_EN BIT(4)
|
||||
#define AN8855_RG_RATE_ADAPT_TX_EN BIT(0)
|
||||
#define AN8855_RATE_ADP_P0_CTRL_0 0x10226100
|
||||
#define AN8855_RG_P0_DIS_MII_MODE BIT(31)
|
||||
#define AN8855_RG_P0_MII_MODE BIT(28)
|
||||
#define AN8855_RG_P0_MII_RA_RX_EN BIT(3)
|
||||
#define AN8855_RG_P0_MII_RA_TX_EN BIT(2)
|
||||
#define AN8855_RG_P0_MII_RA_RX_MODE BIT(1)
|
||||
#define AN8855_RG_P0_MII_RA_TX_MODE BIT(0)
|
||||
#define AN8855_MII_RA_AN_ENABLE 0x10226300
|
||||
#define AN8855_RG_P0_RA_AN_EN BIT(0)
|
||||
|
||||
/* AN8855_QP_DIG_CSR_BASE 0x1022a000 */
|
||||
#define AN8855_QP_CK_RST_CTRL_4 0x1022a310
|
||||
#define AN8855_QP_DIG_MODE_CTRL_0 0x1022a324
|
||||
#define AN8855_RG_SGMII_MODE GENMASK(5, 4)
|
||||
#define AN8855_RG_SGMII_AN_EN BIT(0)
|
||||
#define AN8855_QP_DIG_MODE_CTRL_1 0x1022a330
|
||||
#define AN8855_RG_TPHY_SPEED GENMASK(3, 2)
|
||||
|
||||
/* AN8855_SERDES_WRAPPER_BASE 0x1022c000 */
|
||||
#define AN8855_USGMII_CTRL_0 0x1022c000
|
||||
|
||||
/* AN8855_QP_PMA_TOP_BASE 0x1022e000 */
|
||||
#define AN8855_PON_RXFEDIG_CTRL_0 0x1022e100
|
||||
#define AN8855_RG_QP_EQ_RX500M_CK_SEL BIT(12)
|
||||
#define AN8855_PON_RXFEDIG_CTRL_9 0x1022e124
|
||||
#define AN8855_RG_QP_EQ_LEQOSC_DLYCNT GENMASK(2, 0)
|
||||
|
||||
#define AN8855_SS_LCPLL_PWCTL_SETTING_2 0x1022e208
|
||||
#define AN8855_RG_NCPO_ANA_MSB GENMASK(17, 16)
|
||||
#define AN8855_SS_LCPLL_TDC_FLT_2 0x1022e230
|
||||
#define AN8855_RG_LCPLL_NCPO_VALUE GENMASK(30, 0)
|
||||
#define AN8855_SS_LCPLL_TDC_FLT_5 0x1022e23c
|
||||
#define AN8855_RG_LCPLL_NCPO_CHG BIT(24)
|
||||
#define AN8855_SS_LCPLL_TDC_PCW_1 0x1022e248
|
||||
#define AN8855_RG_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0)
|
||||
#define AN8855_INTF_CTRL_8 0x1022e320
|
||||
#define AN8855_INTF_CTRL_9 0x1022e324
|
||||
#define AN8855_INTF_CTRL_10 0x1022e328
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C2_SEL BIT(29)
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C2_FORCE GENMASK(28, 24)
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C1_SEL BIT(21)
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C1_FORCE GENMASK(20, 16)
|
||||
#define AN8855_INTF_CTRL_11 0x1022e32c
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C0B_SEL BIT(6)
|
||||
#define AN8855_RG_DA_QP_TX_FIR_C0B_FORCE GENMASK(5, 0)
|
||||
#define AN8855_PLL_CTRL_0 0x1022e400
|
||||
#define AN8855_RG_PHYA_AUTO_INIT BIT(0)
|
||||
#define AN8855_PLL_CTRL_2 0x1022e408
|
||||
#define AN8855_RG_DA_QP_PLL_SDM_IFM_INTF BIT(30)
|
||||
#define AN8855_RG_DA_QP_PLL_RICO_SEL_INTF BIT(29)
|
||||
#define AN8855_RG_DA_QP_PLL_POSTDIV_EN_INTF BIT(28)
|
||||
#define AN8855_RG_DA_QP_PLL_PHY_CK_EN_INTF BIT(27)
|
||||
#define AN8855_RG_DA_QP_PLL_PFD_OFFSET_EN_INTRF BIT(26)
|
||||
#define AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF GENMASK(25, 24)
|
||||
#define AN8855_RG_DA_QP_PLL_PCK_SEL_INTF BIT(22)
|
||||
#define AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF GENMASK(21, 20)
|
||||
#define AN8855_RG_DA_QP_PLL_IR_INTF GENMASK(19, 16)
|
||||
#define AN8855_RG_DA_QP_PLL_ICOIQ_EN_INTF BIT(14)
|
||||
#define AN8855_RG_DA_QP_PLL_FBKSEL_INTF GENMASK(13, 12)
|
||||
#define AN8855_RG_DA_QP_PLL_BR_INTF GENMASK(10, 8)
|
||||
#define AN8855_RG_DA_QP_PLL_BPD_INTF GENMASK(7, 6)
|
||||
#define AN8855_RG_DA_QP_PLL_BPA_INTF GENMASK(4, 2)
|
||||
#define AN8855_RG_DA_QP_PLL_BC_INTF GENMASK(1, 0)
|
||||
#define AN8855_PLL_CTRL_3 0x1022e40c
|
||||
#define AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF GENMASK(31, 16)
|
||||
#define AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF GENMASK(15, 0)
|
||||
#define AN8855_PLL_CTRL_4 0x1022e410
|
||||
#define AN8855_RG_DA_QP_PLL_SDM_HREN_INTF GENMASK(4, 3)
|
||||
#define AN8855_RG_DA_QP_PLL_ICOLP_EN_INTF BIT(2)
|
||||
#define AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF GENMASK(1, 0)
|
||||
#define AN8855_PLL_CK_CTRL_0 0x1022e414
|
||||
#define AN8855_RG_DA_QP_PLL_TDC_TXCK_SEL_INTF BIT(9)
|
||||
#define AN8855_RG_DA_QP_PLL_SDM_DI_EN_INTF BIT(8)
|
||||
#define AN8855_RX_DLY_0 0x1022e614
|
||||
#define AN8855_RG_QP_RX_SAOSC_EN_H_DLY GENMASK(13, 8)
|
||||
#define AN8855_RG_QP_RX_PI_CAL_EN_H_DLY GENMASK(7, 0)
|
||||
#define AN8855_RX_CTRL_2 0x1022e630
|
||||
#define AN8855_RG_QP_RX_EQ_EN_H_DLY GENMASK(28, 16)
|
||||
#define AN8855_RX_CTRL_5 0x1022e63c
|
||||
#define AN8855_RG_FREDET_CHK_CYCLE GENMASK(29, 10)
|
||||
#define AN8855_RX_CTRL_6 0x1022e640
|
||||
#define AN8855_RG_FREDET_GOLDEN_CYCLE GENMASK(19, 0)
|
||||
#define AN8855_RX_CTRL_7 0x1022e644
|
||||
#define AN8855_RG_FREDET_TOLERATE_CYCLE GENMASK(19, 0)
|
||||
#define AN8855_RX_CTRL_8 0x1022e648
|
||||
#define AN8855_RG_DA_QP_SAOSC_DONE_TIME GENMASK(27, 16)
|
||||
#define AN8855_RG_DA_QP_LEQOS_EN_TIME GENMASK(14, 0)
|
||||
#define AN8855_RX_CTRL_26 0x1022e690
|
||||
#define AN8855_RG_QP_EQ_RETRAIN_ONLY_EN BIT(26)
|
||||
#define AN8855_RG_LINK_NE_EN BIT(24)
|
||||
#define AN8855_RG_LINK_ERRO_EN BIT(23)
|
||||
#define AN8855_RX_CTRL_42 0x1022e6d0
|
||||
#define AN8855_RG_QP_EQ_EN_DLY GENMASK(12, 0)
|
||||
|
||||
/* AN8855_QP_ANA_CSR_BASE 0x1022f000 */
|
||||
#define AN8855_RG_QP_RX_DAC_EN 0x1022f000
|
||||
#define AN8855_RG_QP_SIGDET_HF GENMASK(17, 16)
|
||||
#define AN8855_RG_QP_RXAFE_RESERVE 0x1022f004
|
||||
#define AN8855_RG_QP_CDR_PD_10B_EN BIT(11)
|
||||
#define AN8855_RG_QP_CDR_LPF_BOT_LIM 0x1022f008
|
||||
#define AN8855_RG_QP_CDR_LPF_KP_GAIN GENMASK(26, 24)
|
||||
#define AN8855_RG_QP_CDR_LPF_KI_GAIN GENMASK(22, 20)
|
||||
#define AN8855_RG_QP_CDR_LPF_MJV_LIM 0x1022f00c
|
||||
#define AN8855_RG_QP_CDR_LPF_RATIO GENMASK(5, 4)
|
||||
#define AN8855_RG_QP_CDR_LPF_SETVALUE 0x1022f014
|
||||
#define AN8855_RG_QP_CDR_PR_BUF_IN_SR GENMASK(31, 29)
|
||||
#define AN8855_RG_QP_CDR_PR_BETA_SEL GENMASK(28, 25)
|
||||
#define AN8855_RG_QP_CDR_PR_CKREF_DIV1 0x1022f018
|
||||
#define AN8855_RG_QP_CDR_PR_KBAND_DIV GENMASK(26, 24)
|
||||
#define AN8855_RG_QP_CDR_PR_DAC_BAND GENMASK(12, 8)
|
||||
#define AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE 0x1022f01c
|
||||
#define AN8855_RG_QP_CDR_PR_XFICK_EN BIT(30)
|
||||
#define AN8855_RG_QP_CDR_PR_KBAND_PCIE_MODE BIT(6)
|
||||
#define AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK GENMASK(5, 0)
|
||||
#define AN8855_RG_QP_CDR_FORCE_IBANDLPF_R_OFF 0x1022f020
|
||||
#define AN8855_RG_QP_CDR_PHYCK_SEL GENMASK(17, 16)
|
||||
#define AN8855_RG_QP_CDR_PHYCK_RSTB BIT(13)
|
||||
#define AN8855_RG_QP_CDR_PHYCK_DIV GENMASK(12, 6)
|
||||
#define AN8855_RG_QP_TX_MODE 0x1022f028
|
||||
#define AN8855_RG_QP_TX_RESERVE GENMASK(31, 16)
|
||||
#define AN8855_RG_QP_TX_MODE_16B_EN BIT(0)
|
||||
#define AN8855_RG_QP_PLL_IPLL_DIG_PWR_SEL 0x1022f03c
|
||||
#define AN8855_RG_QP_PLL_SDM_ORD 0x1022f040
|
||||
#define AN8855_RG_QP_PLL_SSC_PHASE_INI BIT(4)
|
||||
#define AN8855_RG_QP_PLL_SSC_TRI_EN BIT(3)
|
||||
|
||||
/* AN8855_ETHER_SYS_BASE 0x1028c800 */
|
||||
#define AN8855_RG_GPHY_AFE_PWD 0x1028c840
|
||||
#define AN8855_RG_GPHY_SMI_ADDR 0x1028c848
|
||||
|
||||
#define MIB_DESC(_s, _o, _n) \
|
||||
{ \
|
||||
.size = (_s), \
|
||||
.offset = (_o), \
|
||||
.name = (_n), \
|
||||
}
|
||||
|
||||
struct an8855_mib_desc {
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct an8855_fdb {
|
||||
u16 vid;
|
||||
u8 port_mask;
|
||||
u8 aging;
|
||||
u8 mac[6];
|
||||
bool noarp;
|
||||
u8 live;
|
||||
u8 type;
|
||||
u8 fid;
|
||||
u8 ivl;
|
||||
};
|
||||
|
||||
struct an8855_priv {
|
||||
struct device *dev;
|
||||
struct dsa_switch *ds;
|
||||
struct mii_bus *bus;
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *reset_gpio;
|
||||
/* Protect ATU or VLAN table access */
|
||||
struct mutex reg_mutex;
|
||||
|
||||
struct phylink_pcs pcs;
|
||||
|
||||
unsigned int phy_base;
|
||||
|
||||
u8 mirror_rx;
|
||||
u8 mirror_tx;
|
||||
u8 port_isolated_map;
|
||||
|
||||
bool phy_require_calib;
|
||||
};
|
||||
|
||||
#endif /* __AN8855_H */
|
268
target/linux/mediatek/files-6.6/drivers/net/phy/air_an8855.c
Normal file
268
target/linux/mediatek/files-6.6/drivers/net/phy/air_an8855.c
Normal file
@ -0,0 +1,268 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/phy.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
|
||||
#define AN8855_PHY_SELECT_PAGE 0x1f
|
||||
/* Mask speculation based on page up to 0x4 */
|
||||
#define AN8855_PHY_PAGE GENMASK(2, 0)
|
||||
#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0)
|
||||
#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1)
|
||||
|
||||
/* MII Registers Page 1 */
|
||||
#define AN8855_PHY_EXT_REG_14 0x14
|
||||
#define AN8855_PHY_EN_DOWN_SHIFT BIT(4)
|
||||
|
||||
/* R50 Calibration regs in MDIO_MMD_VEND1 */
|
||||
#define AN8855_PHY_R500HM_RSEL_TX_AB 0x174
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_A_EN BIT(15)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_A GENMASK(14, 8)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_B_EN BIT(7)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_B GENMASK(6, 0)
|
||||
#define AN8855_PHY_R500HM_RSEL_TX_CD 0x175
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_C_EN BIT(15)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_C GENMASK(14, 8)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_D_EN BIT(7)
|
||||
#define AN8855_PHY_R50OHM_RSEL_TX_D GENMASK(6, 0)
|
||||
|
||||
#define AN8855_SWITCH_EFUSE_R50O GENMASK(30, 24)
|
||||
|
||||
/* PHY TX PAIR DELAY SELECT Register */
|
||||
#define AN8855_PHY_TX_PAIR_DLY_SEL_GBE 0x013
|
||||
#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE GENMASK(14, 12)
|
||||
#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_B_GBE GENMASK(10, 8)
|
||||
#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE GENMASK(6, 4)
|
||||
#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_D_GBE GENMASK(2, 0)
|
||||
/* PHY ADC Register */
|
||||
#define AN8855_PHY_RXADC_CTRL 0x0d8
|
||||
#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A BIT(12)
|
||||
#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_B BIT(8)
|
||||
#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C BIT(4)
|
||||
#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_D BIT(0)
|
||||
#define AN8855_PHY_RXADC_REV_0 0x0d9
|
||||
#define AN8855_PHY_RG_AD_RESERVE0_A GENMASK(15, 8)
|
||||
#define AN8855_PHY_RG_AD_RESERVE0_B GENMASK(7, 0)
|
||||
#define AN8855_PHY_RXADC_REV_1 0x0da
|
||||
#define AN8855_PHY_RG_AD_RESERVE0_C GENMASK(15, 8)
|
||||
#define AN8855_PHY_RG_AD_RESERVE0_D GENMASK(7, 0)
|
||||
|
||||
#define AN8855_PHY_ID 0xc0ff0410
|
||||
|
||||
#define AN8855_PHY_FLAGS_EN_CALIBRATION BIT(0)
|
||||
|
||||
struct air_an8855_priv {
|
||||
u8 calibration_data[4];
|
||||
};
|
||||
|
||||
static const u8 dsa_r50ohm_table[] = {
|
||||
127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
|
||||
127, 127, 127, 127, 127, 127, 127, 126, 122, 117,
|
||||
112, 109, 104, 101, 97, 94, 90, 88, 84, 80,
|
||||
78, 74, 72, 68, 66, 64, 61, 58, 56, 53,
|
||||
51, 48, 47, 44, 42, 40, 38, 36, 34, 32,
|
||||
31, 28, 27, 24, 24, 22, 20, 18, 16, 16,
|
||||
14, 12, 11, 9
|
||||
};
|
||||
|
||||
static int en8855_get_r50ohm_val(struct device *dev, const char *calib_name,
|
||||
u8 *dest)
|
||||
{
|
||||
u32 shift_sel, val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = nvmem_cell_read_u32(dev, calib_name, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
shift_sel = FIELD_GET(AN8855_SWITCH_EFUSE_R50O, val);
|
||||
for (i = 0; i < ARRAY_SIZE(dsa_r50ohm_table); i++)
|
||||
if (dsa_r50ohm_table[i] == shift_sel)
|
||||
break;
|
||||
|
||||
if (i < 8 || i >= ARRAY_SIZE(dsa_r50ohm_table))
|
||||
*dest = dsa_r50ohm_table[25];
|
||||
else
|
||||
*dest = dsa_r50ohm_table[i - 8];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_probe(struct phy_device *phydev)
|
||||
{
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct air_an8855_priv *priv;
|
||||
int ret;
|
||||
|
||||
/* If we don't have a node, skip get calib */
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = en8855_get_r50ohm_val(dev, "tx_a", &priv->calibration_data[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = en8855_get_r50ohm_val(dev, "tx_b", &priv->calibration_data[1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = en8855_get_r50ohm_val(dev, "tx_c", &priv->calibration_data[2]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = en8855_get_r50ohm_val(dev, "tx_d", &priv->calibration_data[3]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
phydev->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_get_downshift(struct phy_device *phydev, u8 *data)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = phy_read_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, AN8855_PHY_EXT_REG_14);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
*data = val & AN8855_PHY_EN_DOWN_SHIFT ? DOWNSHIFT_DEV_DEFAULT_COUNT :
|
||||
DOWNSHIFT_DEV_DISABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_set_downshift(struct phy_device *phydev, u8 cnt)
|
||||
{
|
||||
u16 ds = cnt != DOWNSHIFT_DEV_DISABLE ? AN8855_PHY_EN_DOWN_SHIFT : 0;
|
||||
|
||||
return phy_modify_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1,
|
||||
AN8855_PHY_EXT_REG_14, AN8855_PHY_EN_DOWN_SHIFT,
|
||||
ds);
|
||||
}
|
||||
|
||||
static int an8855_config_init(struct phy_device *phydev)
|
||||
{
|
||||
struct air_an8855_priv *priv = phydev->priv;
|
||||
int ret;
|
||||
|
||||
/* Enable HW auto downshift */
|
||||
ret = an8855_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Apply calibration values, if needed.
|
||||
* AN8855_PHY_FLAGS_EN_CALIBRATION signal this.
|
||||
*/
|
||||
if (priv && phydev->dev_flags & AN8855_PHY_FLAGS_EN_CALIBRATION) {
|
||||
u8 *calibration_data = priv->calibration_data;
|
||||
|
||||
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_AB,
|
||||
AN8855_PHY_R50OHM_RSEL_TX_A | AN8855_PHY_R50OHM_RSEL_TX_B,
|
||||
FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_A, calibration_data[0]) |
|
||||
FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_B, calibration_data[1]));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_CD,
|
||||
AN8855_PHY_R50OHM_RSEL_TX_C | AN8855_PHY_R50OHM_RSEL_TX_D,
|
||||
FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_C, calibration_data[2]) |
|
||||
FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_D, calibration_data[3]));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Apply values to reduce signal noise */
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_TX_PAIR_DLY_SEL_GBE,
|
||||
FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE, 0x4) |
|
||||
FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE, 0x4));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_CTRL,
|
||||
AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A |
|
||||
AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_0,
|
||||
FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_A, 0x1));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_1,
|
||||
FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_C, 0x1));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int an8855_get_tunable(struct phy_device *phydev,
|
||||
struct ethtool_tunable *tuna, void *data)
|
||||
{
|
||||
switch (tuna->id) {
|
||||
case ETHTOOL_PHY_DOWNSHIFT:
|
||||
return an8855_get_downshift(phydev, data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int an8855_set_tunable(struct phy_device *phydev,
|
||||
struct ethtool_tunable *tuna, const void *data)
|
||||
{
|
||||
switch (tuna->id) {
|
||||
case ETHTOOL_PHY_DOWNSHIFT:
|
||||
return an8855_set_downshift(phydev, *(const u8 *)data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int an8855_read_page(struct phy_device *phydev)
|
||||
{
|
||||
return __phy_read(phydev, AN8855_PHY_SELECT_PAGE);
|
||||
}
|
||||
|
||||
static int an8855_write_page(struct phy_device *phydev, int page)
|
||||
{
|
||||
return __phy_write(phydev, AN8855_PHY_SELECT_PAGE, page);
|
||||
}
|
||||
|
||||
static struct phy_driver an8855_driver[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(AN8855_PHY_ID),
|
||||
.name = "Airoha AN8855 internal PHY",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_IS_INTERNAL,
|
||||
.probe = an8855_probe,
|
||||
.config_init = an8855_config_init,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.get_tunable = an8855_get_tunable,
|
||||
.set_tunable = an8855_set_tunable,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = genphy_resume,
|
||||
.read_page = an8855_read_page,
|
||||
.write_page = an8855_write_page,
|
||||
}, };
|
||||
|
||||
module_phy_driver(an8855_driver);
|
||||
|
||||
static struct mdio_device_id __maybe_unused an8855_tbl[] = {
|
||||
{ PHY_ID_MATCH_EXACT(AN8855_PHY_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mdio, an8855_tbl);
|
||||
|
||||
MODULE_DESCRIPTION("Airoha AN8855 PHY driver");
|
||||
MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,5 +1,6 @@
|
||||
CONFIG_64BIT=y
|
||||
# CONFIG_AHCI_MTK is not set
|
||||
CONFIG_AIR_AN8855_PHY=y
|
||||
CONFIG_AIROHA_EN8801SC_PHY=y
|
||||
CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
|
||||
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
|
||||
@ -291,6 +292,7 @@ CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
CONFIG_NET_DSA_AN8855=y
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
CONFIG_NET_DSA_MT7530_MDIO=y
|
||||
CONFIG_NET_DSA_MT7530_MMIO=y
|
||||
|
@ -1,5 +1,6 @@
|
||||
CONFIG_64BIT=y
|
||||
# CONFIG_AHCI_MTK is not set
|
||||
# CONFIG_AIR_AN8855_PHY is not set
|
||||
# CONFIG_AIROHA_EN8801SC_PHY is not set
|
||||
CONFIG_AQUANTIA_PHY=y
|
||||
CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
|
||||
@ -294,6 +295,7 @@ CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
# CONFIG_NET_DSA_AN8855 is not set
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
CONFIG_NET_DSA_MT7530_MDIO=y
|
||||
# CONFIG_NET_DSA_MT7530_MMIO is not set
|
||||
|
@ -1,4 +1,5 @@
|
||||
# CONFIG_AIO is not set
|
||||
# CONFIG_AIR_AN8855_PHY is not set
|
||||
# CONFIG_AIROHA_EN8801SC_PHY is not set
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_32BIT_OFF_T=y
|
||||
@ -410,6 +411,7 @@ CONFIG_NEED_SRCU_NMI_SAFE=y
|
||||
CONFIG_NEON=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
# CONFIG_NET_DSA_AN8855 is not set
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
CONFIG_NET_DSA_MT7530_MDIO=y
|
||||
# CONFIG_NET_DSA_MT7530_MMIO is not set
|
||||
|
@ -1,3 +1,4 @@
|
||||
# CONFIG_AIR_AN8855_PHY is not set
|
||||
# CONFIG_AIROHA_EN8801SC_PHY is not set
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_32BIT_OFF_T=y
|
||||
@ -216,6 +217,7 @@ CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_BPF_LINK=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
# CONFIG_NET_DSA_AN8855 is not set
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
CONFIG_NET_DSA_MT7530_MDIO=y
|
||||
# CONFIG_NET_DSA_MT7530_MMIO is not set
|
||||
|
@ -0,0 +1,197 @@
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
To: Christian Marangi <ansuelsmth@gmail.com>,
|
||||
Andrew Lunn <andrew@lunn.ch>,
|
||||
Florian Fainelli <f.fainelli@gmail.com>,
|
||||
Vladimir Oltean <olteanv@gmail.com>,
|
||||
"David S. Miller" <davem@davemloft.net>,
|
||||
Eric Dumazet <edumazet@google.com>,
|
||||
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
|
||||
Rob Herring <robh@kernel.org>,
|
||||
Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
||||
Conor Dooley <conor+dt@kernel.org>,
|
||||
Heiner Kallweit <hkallweit1@gmail.com>,
|
||||
Russell King <linux@armlinux.org.uk>,
|
||||
Matthias Brugger <matthias.bgg@gmail.com>,
|
||||
AngeloGioacchino Del Regno
|
||||
<angelogioacchino.delregno@collabora.com>,
|
||||
linux-arm-kernel@lists.infradead.org,
|
||||
linux-mediatek@lists.infradead.org, netdev@vger.kernel.org,
|
||||
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
|
||||
upstream@airoha.com
|
||||
Subject: [net-next PATCH v4 0/3] net: dsa: Add Airoha AN8855 support
|
||||
Date: Fri, 8 Nov 2024 14:24:13 +0100 [thread overview]
|
||||
Message-ID: <20241108132511.18801-1-ansuelsmth@gmail.com> (raw)
|
||||
|
||||
This small series add the initial support for the Airoha AN8855 Switch.
|
||||
|
||||
It's a 5 port Gigabit Switch with SGMII/HSGMII upstream port.
|
||||
|
||||
This is starting to get in the wild and there are already some router
|
||||
having this switch chip.
|
||||
|
||||
It's conceptually similar to mediatek switch but register and bits
|
||||
are different. And there is that massive Hell that is the PCS
|
||||
configuration.
|
||||
Saddly for that part we have absolutely NO documentation currently.
|
||||
|
||||
There is this special thing where PHY needs to be calibrated with values
|
||||
from the switch efuse. (the thing have a whole cpu timer and MCU)
|
||||
|
||||
Changes v4:
|
||||
- Set regmap readable_table static (mute compilation warning)
|
||||
- Add support for port_bridge flags (LEARNING, FLOOD)
|
||||
- Reset fdb struct in fdb_dump
|
||||
- Drop support_asym_pause in port_enable
|
||||
- Add define for get_phy_flags
|
||||
- Fix bug for port not inititially part of a bridge
|
||||
(in an8855_setup the port matrix was always cleared but
|
||||
the CPU port was never initially added)
|
||||
- Disable learning and flood for user port by default
|
||||
- Set CPU port to flood and learning by default
|
||||
- Correctly AND force duplex and flow control in an8855_phylink_mac_link_up
|
||||
- Drop RGMII from pcs_config
|
||||
- Check ret in "Disable AN if not in autoneg"
|
||||
- Use devm_mutex_init
|
||||
- Fix typo for AN8855_PORT_CHECK_MODE
|
||||
- Better define AN8855_STP_LISTENING = AN8855_STP_BLOCKING
|
||||
- Fix typo in AN8855_PHY_EN_DOWN_SHIFT
|
||||
- Use paged helper for PHY
|
||||
- Skip calibration in config_init if priv not defined
|
||||
Changes v3:
|
||||
- Out of RFC
|
||||
- Switch PHY code to select_page API
|
||||
- Better describe masks and bits in PHY driver for ADC register
|
||||
- Drop raw values and use define for mii read/write
|
||||
- Switch to absolute PHY address
|
||||
- Replace raw values with mask and bits for pcs_config
|
||||
- Fix typo for ext-surge property name
|
||||
- Drop support for relocating Switch base PHY address on the bus
|
||||
Changes v2:
|
||||
- Drop mutex guard patch
|
||||
- Drop guard usage in DSA driver
|
||||
- Use __mdiobus_write/read
|
||||
- Check return condition and return errors for mii read/write
|
||||
- Fix wrong logic for EEE
|
||||
- Fix link_down (don't force link down with autoneg)
|
||||
- Fix forcing speed on sgmii autoneg
|
||||
- Better document link speed for sgmii reg
|
||||
- Use standard define for sgmii reg
|
||||
- Imlement nvmem support to expose switch EFUSE
|
||||
- Rework PHY calibration with the use of NVMEM producer/consumer
|
||||
- Update DT with new NVMEM property
|
||||
- Move aneg validation for 2500-basex in pcs_config
|
||||
- Move r50Ohm table and function to PHY driver
|
||||
|
||||
Christian Marangi (3):
|
||||
dt-bindings: net: dsa: Add Airoha AN8855 Gigabit Switch documentation
|
||||
net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver
|
||||
net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY
|
||||
|
||||
.../bindings/net/dsa/airoha,an8855.yaml | 242 ++
|
||||
MAINTAINERS | 11 +
|
||||
drivers/net/dsa/Kconfig | 9 +
|
||||
drivers/net/dsa/Makefile | 1 +
|
||||
drivers/net/dsa/an8855.c | 2138 +++++++++++++++++
|
||||
drivers/net/dsa/an8855.h | 638 +++++
|
||||
drivers/net/phy/Kconfig | 5 +
|
||||
drivers/net/phy/Makefile | 1 +
|
||||
drivers/net/phy/air_an8855.c | 268 +++
|
||||
9 files changed, 3313 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855.yaml
|
||||
create mode 100644 drivers/net/dsa/an8855.c
|
||||
create mode 100644 drivers/net/dsa/an8855.h
|
||||
create mode 100644 drivers/net/phy/air_an8855.c
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
||||
--- a/drivers/net/dsa/Kconfig
|
||||
+++ b/drivers/net/dsa/Kconfig
|
||||
@@ -24,6 +24,15 @@ config NET_DSA_LOOP
|
||||
This enables support for a fake mock-up switch chip which
|
||||
exercises the DSA APIs.
|
||||
|
||||
+
|
||||
+config NET_DSA_AN8855
|
||||
+ tristate "Airoha AN8855 Ethernet switch support"
|
||||
+ depends on NET_DSA
|
||||
+ select NET_DSA_TAG_MTK
|
||||
+ help
|
||||
+ This enables support for the Airoha AN8855 Ethernet switch
|
||||
+ chip.
|
||||
+
|
||||
source "drivers/net/dsa/hirschmann/Kconfig"
|
||||
|
||||
config NET_DSA_LANTIQ_GSWIP
|
||||
--- a/drivers/net/dsa/Makefile
|
||||
+++ b/drivers/net/dsa/Makefile
|
||||
@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o
|
||||
ifdef CONFIG_NET_DSA_LOOP
|
||||
obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o
|
||||
endif
|
||||
+obj-$(CONFIG_NET_DSA_AN8855) += an8855.o
|
||||
obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
|
||||
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
|
||||
obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -147,6 +147,11 @@ config AIROHA_EN8801SC_PHY
|
||||
help
|
||||
Currently supports the Airoha EN8801SC PHY.
|
||||
|
||||
+config AIR_AN8855_PHY
|
||||
+ tristate "Airoha AN8855 Internal Gigabit PHY"
|
||||
+ help
|
||||
+ Currently supports the internal Airoha AN8855 Switch PHY.
|
||||
+
|
||||
config AIR_EN8811H_PHY
|
||||
tristate "Airoha EN8811H 2.5 Gigabit PHY"
|
||||
help
|
||||
--- a/drivers/net/phy/Makefile
|
||||
+++ b/drivers/net/phy/Makefile
|
||||
@@ -50,6 +50,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m)
|
||||
obj-$(CONFIG_ADIN_PHY) += adin.o
|
||||
obj-$(CONFIG_ADIN1100_PHY) += adin1100.o
|
||||
obj-$(CONFIG_AIROHA_EN8801SC_PHY) += en8801sc.o
|
||||
+obj-$(CONFIG_AIR_AN8855_PHY) += air_an8855.o
|
||||
obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o
|
||||
obj-$(CONFIG_AMD_PHY) += amd.o
|
||||
obj-$(CONFIG_AQUANTIA_PHY) += aquantia/
|
||||
--- a/include/net/dsa.h
|
||||
+++ b/include/net/dsa.h
|
||||
@@ -1356,6 +1356,7 @@ static inline void dsa_tag_generic_flow_
|
||||
|
||||
void dsa_unregister_switch(struct dsa_switch *ds);
|
||||
int dsa_register_switch(struct dsa_switch *ds);
|
||||
+int devm_dsa_register_switch(struct device *dev, struct dsa_switch *ds);
|
||||
void dsa_switch_shutdown(struct dsa_switch *ds);
|
||||
struct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
|
||||
void dsa_flush_workqueue(void);
|
||||
--- a/net/dsa/dsa.c
|
||||
+++ b/net/dsa/dsa.c
|
||||
@@ -1560,6 +1560,25 @@ int dsa_register_switch(struct dsa_switc
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dsa_register_switch);
|
||||
|
||||
+static void devm_dsa_unregister_switch(void *data)
|
||||
+{
|
||||
+ struct dsa_switch *ds = data;
|
||||
+
|
||||
+ dsa_unregister_switch(ds);
|
||||
+}
|
||||
+
|
||||
+int devm_dsa_register_switch(struct device *dev, struct dsa_switch *ds)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = dsa_register_switch(ds);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return devm_add_action_or_reset(dev, devm_dsa_unregister_switch, ds);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_dsa_register_switch);
|
||||
+
|
||||
static void dsa_switch_remove(struct dsa_switch *ds)
|
||||
{
|
||||
struct dsa_switch_tree *dst = ds->dst;
|
Loading…
Reference in New Issue
Block a user