Commit 8560664f authored by Arun Ramadoss's avatar Arun Ramadoss Committed by David S. Miller
Browse files

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: default avatarArun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aa5b8b73
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1178,7 +1178,6 @@
#define REG_PORT_XMII_CTRL_0		0x0300

#define PORT_SGMII_SEL			BIT(7)
#define PORT_MII_FULL_DUPLEX		BIT(6)
#define PORT_GRXC_ENABLE		BIT(0)

#define REG_PORT_XMII_CTRL_1		0x0301
+36 −0
Original line number Diff line number Diff line
@@ -281,11 +281,15 @@ static const u32 ksz8795_masks[] = {
	[DYNAMIC_MAC_TABLE_FID]		= GENMASK(26, 20),
	[DYNAMIC_MAC_TABLE_SRC_PORT]	= GENMASK(26, 24),
	[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[] = {
	[P_MII_100MBIT]			= 0,
	[P_MII_10MBIT]			= 1,
	[P_MII_FULL_DUPLEX]		= 0,
	[P_MII_HALF_DUPLEX]		= 1,
};

static const u8 ksz8795_xmii_ctrl1[] = {
@@ -370,6 +374,8 @@ static const u16 ksz9477_regs[] = {
static const u32 ksz9477_masks[] = {
	[ALU_STAT_WRITE]		= 0,
	[ALU_STAT_READ]			= 1,
	[P_MII_TX_FLOW_CTRL]		= BIT(5),
	[P_MII_RX_FLOW_CTRL]		= BIT(3),
};

static const u8 ksz9477_shifts[] = {
@@ -379,6 +385,8 @@ static const u8 ksz9477_shifts[] = {
static const u8 ksz9477_xmii_ctrl0[] = {
	[P_MII_100MBIT]			= 1,
	[P_MII_10MBIT]			= 0,
	[P_MII_FULL_DUPLEX]		= 1,
	[P_MII_HALF_DUPLEX]		= 0,
};

static const u8 ksz9477_xmii_ctrl1[] = {
@@ -389,6 +397,8 @@ static const u8 ksz9477_xmii_ctrl1[] = {
static const u32 lan937x_masks[] = {
	[ALU_STAT_WRITE]		= 1,
	[ALU_STAT_READ]			= 2,
	[P_MII_TX_FLOW_CTRL]		= BIT(5),
	[P_MII_RX_FLOW_CTRL]		= BIT(3),
};

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);
}

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,
				    unsigned int mode,
				    phy_interface_t interface,
+15 −0
Original line number Diff line number Diff line
@@ -197,6 +197,8 @@ enum ksz_masks {
	DYNAMIC_MAC_TABLE_TIMESTAMP,
	ALU_STAT_WRITE,
	ALU_STAT_READ,
	P_MII_TX_FLOW_CTRL,
	P_MII_RX_FLOW_CTRL,
};

enum ksz_shifts {
@@ -215,6 +217,8 @@ enum ksz_shifts {
enum ksz_xmii_ctrl0 {
	P_MII_100MBIT,
	P_MII_10MBIT,
	P_MII_FULL_DUPLEX,
	P_MII_HALF_DUPLEX,
};

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);
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_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[];

/* 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);
}

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)
{
	struct mutex *mtx = __mtx;
@@ -474,6 +488,7 @@ static inline int is_lan937x(struct ksz_device *dev)
#define SW_START			0x01

/* xMII configuration */
#define P_MII_DUPLEX_M			BIT(6)
#define P_MII_100MBIT_M			BIT(4)

#define P_GMII_1GBIT_M			BIT(6)
+6 −19
Original line number Diff line number Diff line
@@ -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)
{
	const u32 *masks = dev->info->masks;
	const u16 *regs = dev->info->regs;
	struct dsa_switch *ds = dev->ds;
	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);

	if (!dev->info->internal_phy[port])
		lan937x_port_cfg(dev, port, REG_PORT_XMII_CTRL_0,
				 PORT_MII_TX_FLOW_CTRL | PORT_MII_RX_FLOW_CTRL,
		lan937x_port_cfg(dev, port, regs[P_XMII_CTRL_0],
				 masks[P_MII_TX_FLOW_CTRL] |
				 masks[P_MII_RX_FLOW_CTRL],
				 true);

	if (cpu_port)
@@ -346,25 +349,9 @@ static void lan937x_config_interface(struct ksz_device *dev, int port,
				     int speed, int duplex,
				     bool tx_pause, bool rx_pause)
{
	u8 xmii_ctrl0;

	ksz_port_set_xmii_speed(dev, port, speed);

	ksz_pread8(dev, port, REG_PORT_XMII_CTRL_0, &xmii_ctrl0);

	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);
	ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
}

void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
+0 −3
Original line number Diff line number Diff line
@@ -133,9 +133,6 @@
/* 3 - xMII */
#define REG_PORT_XMII_CTRL_0		0x0300
#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 REG_PORT_XMII_CTRL_1		0x0301