The RTL839x mdio functions are scattered around the code. Relocate
them to the bus (still inside the ethernet driver).
Additionally provide a consistent SerDes register access through the
mdio bus. Until now when a SerDes directly drives a SFP module there
is no clear rule of how to handle its register set that consists of
two parts:
- c22 phy registers 0-15 live in the fiber page (2) of the SerDes
- other SerDes specific registers exist in pages before and after
The mdio bus and other SerDes functions are a wild mix of directly
looking into page 2 or just using self defined methods to access
data.
Adapt the bus to the new consistent phy interface that mixes the
SerDes register set like classic Realtek phys do it.
- Use register 31 as page select (already in the bus)
- Always keep the common registers 0-15 in place and read fiber page
- Map the SerDes internal registers into the upper vendor specific
registers 16-23 according to the page select register (31).
That gives a register mapping as follows:
+-----------------------+-----------------------+---------------+-------------+
| reg 0x00-0x0f | reg 0x10-0x17 | reg 0x18-0x1e | reg 0x1f |
+-----------------------+-----------------------+---------------+-------------+
| SerDes fiber page (3) | real SerDes registers | zero | SerDes page |
| registers 0 - 15 | in packages of 8 | | select reg |
+-----------------------+-----------------------+---------------+-------------+
Example to make it as clear as possible.
SerDes registers on a RTL839x show
Page / Reg | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B ...
-------------+----------------------------------------------------------------
0 - SDS | 0C03 0F00 7060 7106 074D 0EBF 0F0F 0359 5248 0000 0F80 0000 ...
1 - SDS_EXT | 0000 0000 85FA 8C6D 5CCC 0000 20D8 0003 79AA 8C64 00C3 1482 ...
2 - FIB | 1140 6189 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...
3 - FIB_EXT | 1140 6109 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...
This translates to this phy layout
| SerDes fiber registers normal SerDes registers zero p.sel
Page / Reg | 0x00 0x01 0x02 0x03 ... 0x10 0x11 0x12 0x13 ... 0x18 ... 0x1f
-------------+---------------------------------------------------------------
0 | 1140 6189 001C CA40 ... 0C03 0F00 7060 7106 ... 0000 ... 0000
1 | 1140 6189 001C CA40 ... 5248 0000 0F80 0000 ... 0000 ... 0001
...
4 | 1140 6189 001C CA40 ... 0000 0000 85FA 8C6D ... 0000 ... 0004
...
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19634
Signed-off-by: Robert Marko <robimarko@gmail.com>
224 lines
7.1 KiB
C
224 lines
7.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#ifndef _NET_DSA_RTL83XX_H
|
|
#define _NET_DSA_RTL83XX_H
|
|
|
|
#include <net/dsa.h>
|
|
#include "rtl838x.h"
|
|
|
|
|
|
#define RTL8380_VERSION_A 'A'
|
|
#define RTL8390_VERSION_A 'A'
|
|
#define RTL8380_VERSION_B 'B'
|
|
|
|
struct fdb_update_work {
|
|
struct work_struct work;
|
|
struct net_device *ndev;
|
|
u64 macs[];
|
|
};
|
|
|
|
enum mib_reg {
|
|
MIB_REG_INVALID = 0,
|
|
MIB_REG_STD,
|
|
MIB_REG_PRV
|
|
};
|
|
|
|
#define MIB_ITEM(_reg, _offset, _size) \
|
|
{.reg = _reg, .offset = _offset, .size = _size}
|
|
|
|
#define MIB_LIST_ITEM(_name, _item) \
|
|
{.name = _name, .item = _item}
|
|
|
|
struct rtldsa_mib_item {
|
|
enum mib_reg reg;
|
|
unsigned int offset;
|
|
unsigned int size;
|
|
};
|
|
|
|
struct rtldsa_mib_list_item {
|
|
const char *name;
|
|
struct rtldsa_mib_item item;
|
|
};
|
|
|
|
struct rtldsa_mib_desc {
|
|
struct rtldsa_mib_item symbol_errors;
|
|
|
|
struct rtldsa_mib_item if_in_octets;
|
|
struct rtldsa_mib_item if_out_octets;
|
|
struct rtldsa_mib_item if_in_ucast_pkts;
|
|
struct rtldsa_mib_item if_in_mcast_pkts;
|
|
struct rtldsa_mib_item if_in_bcast_pkts;
|
|
struct rtldsa_mib_item if_out_ucast_pkts;
|
|
struct rtldsa_mib_item if_out_mcast_pkts;
|
|
struct rtldsa_mib_item if_out_bcast_pkts;
|
|
struct rtldsa_mib_item if_out_discards;
|
|
struct rtldsa_mib_item single_collisions;
|
|
struct rtldsa_mib_item multiple_collisions;
|
|
struct rtldsa_mib_item deferred_transmissions;
|
|
struct rtldsa_mib_item late_collisions;
|
|
struct rtldsa_mib_item excessive_collisions;
|
|
struct rtldsa_mib_item crc_align_errors;
|
|
struct rtldsa_mib_item rx_pkts_over_max_octets;
|
|
|
|
struct rtldsa_mib_item unsupported_opcodes;
|
|
|
|
struct rtldsa_mib_item rx_undersize_pkts;
|
|
struct rtldsa_mib_item rx_oversize_pkts;
|
|
struct rtldsa_mib_item rx_fragments;
|
|
struct rtldsa_mib_item rx_jabbers;
|
|
|
|
struct rtldsa_mib_item tx_pkts[ETHTOOL_RMON_HIST_MAX];
|
|
struct rtldsa_mib_item rx_pkts[ETHTOOL_RMON_HIST_MAX];
|
|
struct ethtool_rmon_hist_range rmon_ranges[ETHTOOL_RMON_HIST_MAX];
|
|
|
|
struct rtldsa_mib_item drop_events;
|
|
struct rtldsa_mib_item collisions;
|
|
|
|
struct rtldsa_mib_item rx_pause_frames;
|
|
struct rtldsa_mib_item tx_pause_frames;
|
|
|
|
size_t list_count;
|
|
const struct rtldsa_mib_list_item *list;
|
|
};
|
|
|
|
/* API for switch table access */
|
|
struct table_reg {
|
|
u16 addr;
|
|
u16 data;
|
|
u8 max_data;
|
|
u8 c_bit;
|
|
u8 t_bit;
|
|
u8 rmode;
|
|
u8 tbl;
|
|
struct mutex lock;
|
|
};
|
|
|
|
#define TBL_DESC(_addr, _data, _max_data, _c_bit, _t_bit, _rmode) \
|
|
{ .addr = _addr, .data = _data, .max_data = _max_data, .c_bit = _c_bit, \
|
|
.t_bit = _t_bit, .rmode = _rmode \
|
|
}
|
|
|
|
typedef enum {
|
|
RTL8380_TBL_L2 = 0,
|
|
RTL8380_TBL_0,
|
|
RTL8380_TBL_1,
|
|
RTL8390_TBL_L2,
|
|
RTL8390_TBL_0,
|
|
RTL8390_TBL_1,
|
|
RTL8390_TBL_2,
|
|
RTL9300_TBL_L2,
|
|
RTL9300_TBL_0,
|
|
RTL9300_TBL_1,
|
|
RTL9300_TBL_2,
|
|
RTL9300_TBL_HSB,
|
|
RTL9300_TBL_HSA,
|
|
RTL9310_TBL_0,
|
|
RTL9310_TBL_1,
|
|
RTL9310_TBL_2,
|
|
RTL9310_TBL_3,
|
|
RTL9310_TBL_4,
|
|
RTL9310_TBL_5,
|
|
RTL_TBL_END
|
|
} rtl838x_tbl_reg_t;
|
|
|
|
void rtl_table_init(void);
|
|
struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t);
|
|
void rtl_table_release(struct table_reg *r);
|
|
int rtl_table_read(struct table_reg *r, int idx);
|
|
int rtl_table_write(struct table_reg *r, int idx);
|
|
inline u16 rtl_table_data(struct table_reg *r, int i);
|
|
inline u32 rtl_table_data_r(struct table_reg *r, int i);
|
|
inline void rtl_table_data_w(struct table_reg *r, u32 v, int i);
|
|
|
|
void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv);
|
|
|
|
void rtl83xx_fast_age(struct dsa_switch *ds, int port);
|
|
int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv);
|
|
int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port);
|
|
int rtl83xx_port_is_under(const struct net_device * dev, struct rtl838x_switch_priv *priv);
|
|
void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
|
|
int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data);
|
|
|
|
/* Port register accessor functions for the RTL839x and RTL931X SoCs */
|
|
void rtl839x_mask_port_reg_be(u64 clear, u64 set, int reg);
|
|
u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port);
|
|
u64 rtl839x_get_port_reg_be(int reg);
|
|
void rtl839x_set_port_reg_be(u64 set, int reg);
|
|
void rtl839x_mask_port_reg_le(u64 clear, u64 set, int reg);
|
|
int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate);
|
|
void rtl839x_set_port_reg_le(u64 set, int reg);
|
|
u64 rtl839x_get_port_reg_le(int reg);
|
|
|
|
/* Port register accessor functions for the RTL838x and RTL930X SoCs */
|
|
void rtl838x_mask_port_reg(u64 clear, u64 set, int reg);
|
|
void rtl838x_set_port_reg(u64 set, int reg);
|
|
u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port);
|
|
u64 rtl838x_get_port_reg(int reg);
|
|
int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate);
|
|
|
|
/* RTL838x-specific */
|
|
u32 rtl838x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
|
irqreturn_t rtl838x_switch_irq(int irq, void *dev_id);
|
|
void rtl8380_get_version(struct rtl838x_switch_priv *priv);
|
|
void rtl838x_vlan_profile_dump(int index);
|
|
void rtl8380_sds_rst(int mac);
|
|
int rtl8380_sds_power(int mac, int val);
|
|
void rtl838x_print_matrix(void);
|
|
|
|
/* RTL839x-specific */
|
|
u32 rtl839x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
|
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
|
|
void rtl8390_get_version(struct rtl838x_switch_priv *priv);
|
|
void rtl839x_vlan_profile_dump(int index);
|
|
void rtl839x_exec_tbl2_cmd(u32 cmd);
|
|
void rtl839x_print_matrix(void);
|
|
|
|
/* RTL930x-specific */
|
|
u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
|
irqreturn_t rtl930x_switch_irq(int irq, void *dev_id);
|
|
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
|
|
void rtl930x_vlan_profile_dump(int index);
|
|
int rtl9300_sds_power(int mac, int val);
|
|
extern int rtl9300_serdes_setup(int port, int sds_num, phy_interface_t phy_mode);
|
|
void rtl930x_print_matrix(void);
|
|
|
|
/* RTL931x-specific */
|
|
irqreturn_t rtl931x_switch_irq(int irq, void *dev_id);
|
|
int rtl931x_sds_cmu_band_get(int sds, phy_interface_t mode);
|
|
int rtl931x_sds_cmu_band_set(int sds, bool enable, u32 band, phy_interface_t mode);
|
|
extern void rtl931x_sds_init(u32 sds, phy_interface_t mode);
|
|
void rtl931x_print_matrix(void);
|
|
|
|
int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info);
|
|
int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);
|
|
|
|
/* phy functions that will need to be moved to the future mdio driver */
|
|
|
|
int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
|
int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
|
|
|
int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
|
int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
|
|
|
/*
|
|
* TODO: The following functions are currently not in use. So compiler will complain if
|
|
* they are static and not made available externally. To preserve them for future use
|
|
* collect them in this section.
|
|
*/
|
|
|
|
void rtl838x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port,
|
|
int queue, u32 rate);
|
|
|
|
int rtl8390_sds_power(int mac, int val);
|
|
void rtl839x_pie_rule_dump(struct pie_rule *pr);
|
|
void rtl839x_set_egress_queue(int port, int queue);
|
|
|
|
void rtl9300_dump_debug(void);
|
|
void rtl930x_pie_rule_dump_raw(u32 r[]);
|
|
|
|
void rtl931x_print_matrix(void);
|
|
void rtl931x_set_receive_management_action(int port, rma_ctrl_t type, action_type_t action);
|
|
void rtl931x_sw_init(struct rtl838x_switch_priv *priv);
|
|
|
|
#endif /* _NET_DSA_RTL83XX_H */
|