mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 07:34:12 +08:00
net: dsa: microchip: add common duplex and flow control function
This patch add common function for configuring the Full/Half duplex and transmit/receive flow control. KSZ8795 uses the Global control register 4 for configuring the duplex and flow control, whereas all other KSZ9477 based switch uses the xMII Control 0 register. Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
aa5b8b73d4
commit
8560664fd3
@ -1178,7 +1178,6 @@
|
|||||||
#define REG_PORT_XMII_CTRL_0 0x0300
|
#define REG_PORT_XMII_CTRL_0 0x0300
|
||||||
|
|
||||||
#define PORT_SGMII_SEL BIT(7)
|
#define PORT_SGMII_SEL BIT(7)
|
||||||
#define PORT_MII_FULL_DUPLEX BIT(6)
|
|
||||||
#define PORT_GRXC_ENABLE BIT(0)
|
#define PORT_GRXC_ENABLE BIT(0)
|
||||||
|
|
||||||
#define REG_PORT_XMII_CTRL_1 0x0301
|
#define REG_PORT_XMII_CTRL_1 0x0301
|
||||||
|
@ -281,11 +281,15 @@ static const u32 ksz8795_masks[] = {
|
|||||||
[DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20),
|
[DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20),
|
||||||
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
|
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
|
||||||
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
|
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
|
||||||
|
[P_MII_TX_FLOW_CTRL] = BIT(5),
|
||||||
|
[P_MII_RX_FLOW_CTRL] = BIT(5),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 ksz8795_xmii_ctrl0[] = {
|
static const u8 ksz8795_xmii_ctrl0[] = {
|
||||||
[P_MII_100MBIT] = 0,
|
[P_MII_100MBIT] = 0,
|
||||||
[P_MII_10MBIT] = 1,
|
[P_MII_10MBIT] = 1,
|
||||||
|
[P_MII_FULL_DUPLEX] = 0,
|
||||||
|
[P_MII_HALF_DUPLEX] = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 ksz8795_xmii_ctrl1[] = {
|
static const u8 ksz8795_xmii_ctrl1[] = {
|
||||||
@ -370,6 +374,8 @@ static const u16 ksz9477_regs[] = {
|
|||||||
static const u32 ksz9477_masks[] = {
|
static const u32 ksz9477_masks[] = {
|
||||||
[ALU_STAT_WRITE] = 0,
|
[ALU_STAT_WRITE] = 0,
|
||||||
[ALU_STAT_READ] = 1,
|
[ALU_STAT_READ] = 1,
|
||||||
|
[P_MII_TX_FLOW_CTRL] = BIT(5),
|
||||||
|
[P_MII_RX_FLOW_CTRL] = BIT(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 ksz9477_shifts[] = {
|
static const u8 ksz9477_shifts[] = {
|
||||||
@ -379,6 +385,8 @@ static const u8 ksz9477_shifts[] = {
|
|||||||
static const u8 ksz9477_xmii_ctrl0[] = {
|
static const u8 ksz9477_xmii_ctrl0[] = {
|
||||||
[P_MII_100MBIT] = 1,
|
[P_MII_100MBIT] = 1,
|
||||||
[P_MII_10MBIT] = 0,
|
[P_MII_10MBIT] = 0,
|
||||||
|
[P_MII_FULL_DUPLEX] = 1,
|
||||||
|
[P_MII_HALF_DUPLEX] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 ksz9477_xmii_ctrl1[] = {
|
static const u8 ksz9477_xmii_ctrl1[] = {
|
||||||
@ -389,6 +397,8 @@ static const u8 ksz9477_xmii_ctrl1[] = {
|
|||||||
static const u32 lan937x_masks[] = {
|
static const u32 lan937x_masks[] = {
|
||||||
[ALU_STAT_WRITE] = 1,
|
[ALU_STAT_WRITE] = 1,
|
||||||
[ALU_STAT_READ] = 2,
|
[ALU_STAT_READ] = 2,
|
||||||
|
[P_MII_TX_FLOW_CTRL] = BIT(5),
|
||||||
|
[P_MII_RX_FLOW_CTRL] = BIT(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 lan937x_shifts[] = {
|
static const u8 lan937x_shifts[] = {
|
||||||
@ -1468,6 +1478,32 @@ void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed)
|
|||||||
ksz_set_100_10mbit(dev, port, speed);
|
ksz_set_100_10mbit(dev, port, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
|
{
|
||||||
|
const u8 *bitval = dev->info->xmii_ctrl0;
|
||||||
|
const u32 *masks = dev->info->masks;
|
||||||
|
const u16 *regs = dev->info->regs;
|
||||||
|
u8 mask;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] |
|
||||||
|
masks[P_MII_RX_FLOW_CTRL];
|
||||||
|
|
||||||
|
if (duplex == DUPLEX_FULL)
|
||||||
|
val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]);
|
||||||
|
else
|
||||||
|
val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]);
|
||||||
|
|
||||||
|
if (tx_pause)
|
||||||
|
val |= masks[P_MII_TX_FLOW_CTRL];
|
||||||
|
|
||||||
|
if (rx_pause)
|
||||||
|
val |= masks[P_MII_RX_FLOW_CTRL];
|
||||||
|
|
||||||
|
ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||||
unsigned int mode,
|
unsigned int mode,
|
||||||
phy_interface_t interface,
|
phy_interface_t interface,
|
||||||
|
@ -197,6 +197,8 @@ enum ksz_masks {
|
|||||||
DYNAMIC_MAC_TABLE_TIMESTAMP,
|
DYNAMIC_MAC_TABLE_TIMESTAMP,
|
||||||
ALU_STAT_WRITE,
|
ALU_STAT_WRITE,
|
||||||
ALU_STAT_READ,
|
ALU_STAT_READ,
|
||||||
|
P_MII_TX_FLOW_CTRL,
|
||||||
|
P_MII_RX_FLOW_CTRL,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ksz_shifts {
|
enum ksz_shifts {
|
||||||
@ -215,6 +217,8 @@ enum ksz_shifts {
|
|||||||
enum ksz_xmii_ctrl0 {
|
enum ksz_xmii_ctrl0 {
|
||||||
P_MII_100MBIT,
|
P_MII_100MBIT,
|
||||||
P_MII_10MBIT,
|
P_MII_10MBIT,
|
||||||
|
P_MII_FULL_DUPLEX,
|
||||||
|
P_MII_HALF_DUPLEX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ksz_xmii_ctrl1 {
|
enum ksz_xmii_ctrl1 {
|
||||||
@ -310,6 +314,8 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
|
|||||||
bool ksz_get_gbit(struct ksz_device *dev, int port);
|
bool ksz_get_gbit(struct ksz_device *dev, int port);
|
||||||
void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit);
|
void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit);
|
||||||
void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed);
|
void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed);
|
||||||
|
void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause);
|
||||||
extern const struct ksz_chip_data ksz_switch_chips[];
|
extern const struct ksz_chip_data ksz_switch_chips[];
|
||||||
|
|
||||||
/* Common register access functions */
|
/* Common register access functions */
|
||||||
@ -416,6 +422,14 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
|
|||||||
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
|
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
|
||||||
|
u8 mask, u8 val)
|
||||||
|
{
|
||||||
|
regmap_update_bits(dev->regmap[0],
|
||||||
|
dev->dev_ops->get_port_addr(port, offset),
|
||||||
|
mask, val);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ksz_regmap_lock(void *__mtx)
|
static inline void ksz_regmap_lock(void *__mtx)
|
||||||
{
|
{
|
||||||
struct mutex *mtx = __mtx;
|
struct mutex *mtx = __mtx;
|
||||||
@ -474,6 +488,7 @@ static inline int is_lan937x(struct ksz_device *dev)
|
|||||||
#define SW_START 0x01
|
#define SW_START 0x01
|
||||||
|
|
||||||
/* xMII configuration */
|
/* xMII configuration */
|
||||||
|
#define P_MII_DUPLEX_M BIT(6)
|
||||||
#define P_MII_100MBIT_M BIT(4)
|
#define P_MII_100MBIT_M BIT(4)
|
||||||
|
|
||||||
#define P_GMII_1GBIT_M BIT(6)
|
#define P_GMII_1GBIT_M BIT(6)
|
||||||
|
@ -234,6 +234,8 @@ int lan937x_reset_switch(struct ksz_device *dev)
|
|||||||
|
|
||||||
void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
||||||
{
|
{
|
||||||
|
const u32 *masks = dev->info->masks;
|
||||||
|
const u16 *regs = dev->info->regs;
|
||||||
struct dsa_switch *ds = dev->ds;
|
struct dsa_switch *ds = dev->ds;
|
||||||
u8 member;
|
u8 member;
|
||||||
|
|
||||||
@ -254,8 +256,9 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
|||||||
lan937x_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
|
lan937x_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
|
||||||
|
|
||||||
if (!dev->info->internal_phy[port])
|
if (!dev->info->internal_phy[port])
|
||||||
lan937x_port_cfg(dev, port, REG_PORT_XMII_CTRL_0,
|
lan937x_port_cfg(dev, port, regs[P_XMII_CTRL_0],
|
||||||
PORT_MII_TX_FLOW_CTRL | PORT_MII_RX_FLOW_CTRL,
|
masks[P_MII_TX_FLOW_CTRL] |
|
||||||
|
masks[P_MII_RX_FLOW_CTRL],
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (cpu_port)
|
if (cpu_port)
|
||||||
@ -346,25 +349,9 @@ static void lan937x_config_interface(struct ksz_device *dev, int port,
|
|||||||
int speed, int duplex,
|
int speed, int duplex,
|
||||||
bool tx_pause, bool rx_pause)
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
u8 xmii_ctrl0;
|
|
||||||
|
|
||||||
ksz_port_set_xmii_speed(dev, port, speed);
|
ksz_port_set_xmii_speed(dev, port, speed);
|
||||||
|
|
||||||
ksz_pread8(dev, port, REG_PORT_XMII_CTRL_0, &xmii_ctrl0);
|
ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
|
||||||
|
|
||||||
xmii_ctrl0 &= ~(PORT_MII_FULL_DUPLEX | PORT_MII_TX_FLOW_CTRL |
|
|
||||||
PORT_MII_RX_FLOW_CTRL);
|
|
||||||
|
|
||||||
if (duplex)
|
|
||||||
xmii_ctrl0 |= PORT_MII_FULL_DUPLEX;
|
|
||||||
|
|
||||||
if (tx_pause)
|
|
||||||
xmii_ctrl0 |= PORT_MII_TX_FLOW_CTRL;
|
|
||||||
|
|
||||||
if (rx_pause)
|
|
||||||
xmii_ctrl0 |= PORT_MII_RX_FLOW_CTRL;
|
|
||||||
|
|
||||||
ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_0, xmii_ctrl0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
|
void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
|
||||||
|
@ -133,9 +133,6 @@
|
|||||||
/* 3 - xMII */
|
/* 3 - xMII */
|
||||||
#define REG_PORT_XMII_CTRL_0 0x0300
|
#define REG_PORT_XMII_CTRL_0 0x0300
|
||||||
#define PORT_SGMII_SEL BIT(7)
|
#define PORT_SGMII_SEL BIT(7)
|
||||||
#define PORT_MII_FULL_DUPLEX BIT(6)
|
|
||||||
#define PORT_MII_TX_FLOW_CTRL BIT(5)
|
|
||||||
#define PORT_MII_RX_FLOW_CTRL BIT(3)
|
|
||||||
#define PORT_GRXC_ENABLE BIT(0)
|
#define PORT_GRXC_ENABLE BIT(0)
|
||||||
|
|
||||||
#define REG_PORT_XMII_CTRL_1 0x0301
|
#define REG_PORT_XMII_CTRL_1 0x0301
|
||||||
|
Loading…
Reference in New Issue
Block a user