#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
[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[] = {
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[] = {
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[] = {
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[] = {
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,
DYNAMIC_MAC_TABLE_TIMESTAMP,
ALU_STAT_WRITE,
ALU_STAT_READ,
+ P_MII_TX_FLOW_CTRL,
+ P_MII_RX_FLOW_CTRL,
};
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 {
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 */
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;
#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)
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;
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)
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,
/* 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