@@ -40,18 +40,15 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
static int ksz8_ind_write8(struct ksz_device *dev, u8 table, u16 addr, u8 data)
{
- const u16 *regs;
u16 ctrl_addr;
int ret = 0;
- regs = dev->info->regs;
-
mutex_lock(&dev->alu_mutex);
ctrl_addr = IND_ACC_TABLE(table) | addr;
- ret = ksz_write8(dev, regs[REG_IND_BYTE], data);
+ ret = ksz_regfield_write(dev, RF_IND_BYTE, data);
if (!ret)
- ret = ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ret = ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
mutex_unlock(&dev->alu_mutex);
@@ -176,7 +173,7 @@ void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
mutex_lock(&dev->alu_mutex);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
/* It is almost guaranteed to always read the valid bit because of
* slow SPI speed.
@@ -214,7 +211,7 @@ static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
mutex_lock(&dev->alu_mutex);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
/* It is almost guaranteed to always read the valid bit because of
* slow SPI speed.
@@ -265,7 +262,7 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
mutex_lock(&dev->alu_mutex);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
ksz_read32(dev, regs[REG_IND_DATA_LO], &data);
mutex_unlock(&dev->alu_mutex);
@@ -346,7 +343,7 @@ static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr;
mutex_lock(&dev->alu_mutex);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
ksz_read64(dev, regs[REG_IND_DATA_HI], data);
mutex_unlock(&dev->alu_mutex);
}
@@ -362,7 +359,7 @@ static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data)
mutex_lock(&dev->alu_mutex);
ksz_write64(dev, regs[REG_IND_DATA_HI], data);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
mutex_unlock(&dev->alu_mutex);
}
@@ -412,7 +409,7 @@ int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr;
mutex_lock(&dev->alu_mutex);
- ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+ ksz_regfield_write(dev, RF_IND_CTRL_0, ctrl_addr);
rc = ksz8_valid_dyn_entry(dev, &data);
if (rc == -EAGAIN) {
@@ -605,8 +602,9 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{
- u8 restart, speed, ctrl, link;
+ u8 restart, speed, link;
int processed = true;
+ unsigned int ctrl;
const u16 *regs;
u8 val1, val2;
u16 data = 0;
@@ -625,7 +623,7 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
if (ret)
return ret;
- ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+ ret = ksz_regfields_read(dev, p, RF_FORCE_CTRL, &ctrl);
if (ret)
return ret;
@@ -682,7 +680,7 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data = KSZ8795_ID_LO;
break;
case MII_ADVERTISE:
- ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+ ret = ksz_regfields_read(dev, p, RF_LOCAL_CTRL, &ctrl);
if (ret)
return ret;
@@ -759,7 +757,8 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{
- u8 restart, speed, ctrl, data;
+ u8 restart, speed, data;
+ unsigned int ctrl;
const u16 *regs;
u8 p = phy;
int ret;
@@ -788,7 +787,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
return ret;
}
- ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+ ret = ksz_regfields_read(dev, p, RF_FORCE_CTRL, &ctrl);
if (ret)
return ret;
@@ -819,7 +818,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data &= ~PORT_FORCE_FULL_DUPLEX;
if (data != ctrl) {
- ret = ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
+ ret = ksz_regfields_write(dev, p, RF_FORCE_CTRL, data);
if (ret)
return ret;
}
@@ -866,7 +865,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
}
break;
case MII_ADVERTISE:
- ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+ ret = ksz_regfields_read(dev, p, RF_LOCAL_CTRL, &ctrl);
if (ret)
return ret;
@@ -888,7 +887,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_AUTO_NEG_10BT;
if (data != ctrl) {
- ret = ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
+ ret = ksz_regfields_write(dev, p, RF_LOCAL_CTRL, data);
if (ret)
return ret;
}
@@ -136,11 +136,16 @@ static const struct regmap_config ksz8863_regmap_config[] = {
static int ksz8863_smi_probe(struct mdio_device *mdiodev)
{
+ const struct ksz_chip_data *chip;
struct regmap_config rc;
struct ksz_device *dev;
int ret;
int i;
+ chip = device_get_match_data(ddev);
+ if (!chip)
+ return -EINVAL;
+
dev = ksz_switch_alloc(&mdiodev->dev, mdiodev);
if (!dev)
return -ENOMEM;
@@ -159,6 +164,10 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev)
}
}
+ ret = ksz_regfields_init(dev, chip);
+ if (ret)
+ return ret;
+
if (mdiodev->dev.platform_data)
dev->pdata = mdiodev->dev.platform_data;
@@ -16,10 +16,15 @@ KSZ_REGMAP_TABLE(ksz9477, not_used, 16, 0, 0);
static int ksz9477_i2c_probe(struct i2c_client *i2c)
{
+ const struct ksz_chip_data *chip;
struct regmap_config rc;
struct ksz_device *dev;
int i, ret;
+ chip = device_get_match_data(ddev);
+ if (!chip)
+ return -EINVAL;
+
dev = ksz_switch_alloc(&i2c->dev, i2c);
if (!dev)
return -ENOMEM;
@@ -35,6 +40,10 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c)
}
}
+ ret = ksz_regfields_init(dev, chip);
+ if (ret)
+ return ret;
+
if (i2c->dev.platform_data)
dev->pdata = i2c->dev.platform_data;
@@ -295,6 +295,65 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
.exit = lan937x_switch_exit,
};
+#define KSZ8_PORT_BASE 0x10
+#define KSZ8_PORT_SPACING 0x10
+#define KSZ9477_PORT_BASE 0x1000
+#define KSZ9477_PORT_SPACING 0x1000
+
+#define KSZ_REG_FIELD_8(_reg, _lsb, _msb) \
+ { .width = KSZ_REGMAP_8, .regfield = REG_FIELD(_reg, _lsb, _msb) }
+#define KSZ_REG_FIELD_16(_reg, _lsb, _msb) \
+ { .width = KSZ_REGMAP_16, .regfield = REG_FIELD(_reg, _lsb, _msb) }
+#define KSZ_REG_FIELD_32(_reg, _lsb, _msb) \
+ { .width = KSZ_REGMAP_32, .regfield = REG_FIELD(_reg, _lsb, _msb) }
+#define KSZ8_PORT_REG_FIELD_8(_reg, _lsb, _msb) \
+ { \
+ .width = KSZ_REGMAP_8, \
+ .regfield = REG_FIELD_ID(KSZ8_PORT_BASE + (_reg), \
+ _lsb, _msb, KSZ_MAX_NUM_PORTS, \
+ KSZ8_PORT_SPACING) \
+ }
+#define KSZ8_PORT_REG_FIELD_16(_reg, _lsb, _msb) \
+ { \
+ .width = KSZ_REGMAP_16, \
+ .regfield = REG_FIELD_ID(KSZ8_PORT_BASE + (_reg), \
+ _lsb, _msb, KSZ_MAX_NUM_PORTS, \
+ KSZ8_PORT_SPACING) \
+ }
+#define KSZ8_PORT_REG_FIELD_32(_reg, _lsb, _msb) \
+ { \
+ .width = KSZ_REGMAP_32, \
+ .regfield = REG_FIELD_ID(KSZ8_PORT_BASE + (_reg), \
+ _lsb, _msb, KSZ_MAX_NUM_PORTS, \
+ KSZ8_PORT_SPACING) \
+ }
+/* Some registers are wacky, in the sense that they should be per port (and are
+ * accessed using per-port regfields by the driver), but on some hardware, they
+ * are defined in the global address space, so they should be accessed via the
+ * global regfield API. We hack these up by using a REG_FIELD_ID() definition
+ * with a spacing of 0, so that accesses to any port access the same (global)
+ * register.
+ */
+#define KSZ_WACKY_REG_FIELD_8(_reg, _lsb, _msb) \
+ { \
+ .width = KSZ_REGMAP_8, \
+ .regfield = REG_FIELD_ID(_reg, _lsb, _msb, KSZ_MAX_NUM_PORTS, 0) \
+ }
+
+static const struct ksz_reg_field ksz8795_regfields[__KSZ_NUM_REGFIELDS] = {
+ [RF_IND_CTRL_0] = KSZ_REG_FIELD_16(0x6E, 0, 15),
+ [RF_IND_BYTE] = KSZ_REG_FIELD_8(0xA0, 0, 7),
+ [RF_FORCE_CTRL] = KSZ8_PORT_REG_FIELD_8(0x0C, 0, 7),
+ [RF_LOCAL_CTRL] = KSZ8_PORT_REG_FIELD_8(0x07, 0, 7),
+ [RF_GMII_1GBIT] = KSZ8_PORT_REG_FIELD_8(0x06, 6, 6),
+ [RF_MII_SEL] = KSZ8_PORT_REG_FIELD_8(0x06, 2, 2),
+ [RF_RGMII_ID_IG_ENABLE] = KSZ8_PORT_REG_FIELD_8(0x06, 4, 4),
+ [RF_RGMII_ID_EG_ENABLE] = KSZ8_PORT_REG_FIELD_8(0x06, 3, 3),
+ [RF_MII_DUPLEX] = KSZ_WACKY_REG_FIELD_8(0x06, 6, 6), // Global Control 4
+ [RF_MII_TX_FLOW_CTRL] = KSZ_WACKY_REG_FIELD_8(0x06, 5, 5), // Global Control 4
+ [RF_MII_100MBIT] = KSZ_WACKY_REG_FIELD_8(0x06, 4, 4), // Global Control 4
+};
+
static const u16 ksz8795_regs[] = {
[REG_IND_CTRL_0] = 0x6E,
[REG_IND_DATA_8] = 0x70,
@@ -1121,6 +1180,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.regs = ksz8795_regs,
.masks = ksz8795_masks,
.shifts = ksz8795_shifts,
+ .regfields = ksz8795_regfields,
.xmii_ctrl0 = ksz8795_xmii_ctrl0,
.xmii_ctrl1 = ksz8795_xmii_ctrl1,
.supports_mii = {false, false, false, false, true},
@@ -2747,34 +2807,28 @@ static void ksz_set_xmii(struct ksz_device *dev, int port,
{
const u8 *bitval = dev->info->xmii_ctrl1;
struct ksz_port *p = &dev->ports[port];
- const u16 *regs = dev->info->regs;
- u8 data8;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
-
- data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE |
- P_RGMII_ID_EG_ENABLE);
+ unsigned int mii_sel;
switch (interface) {
case PHY_INTERFACE_MODE_MII:
- data8 |= bitval[P_MII_SEL];
+ mii_sel = bitval[P_MII_SEL];
break;
case PHY_INTERFACE_MODE_RMII:
- data8 |= bitval[P_RMII_SEL];
+ mii_sel = bitval[P_RMII_SEL];
break;
case PHY_INTERFACE_MODE_GMII:
- data8 |= bitval[P_GMII_SEL];
+ mii_sel = bitval[P_GMII_SEL];
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
- data8 |= bitval[P_RGMII_SEL];
+ mii_sel = bitval[P_RGMII_SEL];
/* On KSZ9893, disable RGMII in-band status support */
if (dev->chip_id == KSZ9893_CHIP_ID ||
dev->chip_id == KSZ8563_CHIP_ID ||
dev->chip_id == KSZ9563_CHIP_ID)
- data8 &= ~P_MII_MAC_MODE;
+ ksz_regfields_write(dev, port, RF_MII_MAC_MODE, 0);
break;
default:
dev_err(dev->dev, "Unsupported interface '%s' for port %d\n",
@@ -2782,42 +2836,46 @@ static void ksz_set_xmii(struct ksz_device *dev, int port,
return;
}
- if (p->rgmii_tx_val)
- data8 |= P_RGMII_ID_EG_ENABLE;
-
- if (p->rgmii_rx_val)
- data8 |= P_RGMII_ID_IG_ENABLE;
-
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
+ ksz_regfields_write(dev, port, RF_MII_SEL, mii_sel);
+ ksz_regfields_write(dev, port, RF_RGMII_ID_EG_ENABLE,
+ !!p->rgmii_tx_val);
+ ksz_regfields_write(dev, port, RF_RGMII_ID_IG_ENABLE,
+ !!p->rgmii_rx_val);
}
phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit)
{
const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
+ unsigned int mii_sel, ig, eg;
phy_interface_t interface;
- u8 data8;
- u8 val;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
+ int ret;
- val = FIELD_GET(P_MII_SEL_M, data8);
+ ret = ksz_regfields_read(dev, port, RF_MII_SEL, &mii_sel);
+ if (WARN_ON(ret))
+ return PHY_INTERFACE_MODE_NA;
- if (val == bitval[P_MII_SEL]) {
+ if (mii_sel == bitval[P_MII_SEL]) {
if (gbit)
interface = PHY_INTERFACE_MODE_GMII;
else
interface = PHY_INTERFACE_MODE_MII;
- } else if (val == bitval[P_RMII_SEL]) {
+ } else if (mii_sel == bitval[P_RMII_SEL]) {
interface = PHY_INTERFACE_MODE_RGMII;
} else {
+ ret = ksz_regfields_read(dev, port, RF_RGMII_ID_IG_ENABLE, &ig);
+ if (WARN_ON(ret))
+ return PHY_INTERFACE_MODE_NA;
+
+ ret = ksz_regfields_read(dev, port, RF_RGMII_ID_IG_ENABLE, &eg);
+ if (WARN_ON(ret))
+ return PHY_INTERFACE_MODE_NA;
+
interface = PHY_INTERFACE_MODE_RGMII;
- if (data8 & P_RGMII_ID_EG_ENABLE)
+ if (eg)
interface = PHY_INTERFACE_MODE_RGMII_TXID;
- if (data8 & P_RGMII_ID_IG_ENABLE) {
+ if (ig) {
interface = PHY_INTERFACE_MODE_RGMII_RXID;
- if (data8 & P_RGMII_ID_EG_ENABLE)
+ if (eg)
interface = PHY_INTERFACE_MODE_RGMII_ID;
}
}
@@ -2855,14 +2913,13 @@ static void ksz_phylink_mac_config(struct dsa_switch *ds, int port,
bool ksz_get_gbit(struct ksz_device *dev, int port)
{
const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
bool gbit = false;
- u8 data8;
- bool val;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
+ unsigned int val;
+ int ret;
- val = FIELD_GET(P_GMII_1GBIT_M, data8);
+ ret = ksz_regfields_read(dev, port, RF_GMII_1GBIT, &val);
+ if (WARN_ON(ret))
+ return false;
if (val == bitval[P_GMII_1GBIT])
gbit = true;
@@ -2873,39 +2930,27 @@ bool ksz_get_gbit(struct ksz_device *dev, int port)
static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit)
{
const u8 *bitval = dev->info->xmii_ctrl1;
- const u16 *regs = dev->info->regs;
- u8 data8;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8);
-
- data8 &= ~P_GMII_1GBIT_M;
+ unsigned int val;
if (gbit)
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]);
+ val = bitval[P_GMII_1GBIT];
else
- data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]);
+ val = bitval[P_GMII_NOT_1GBIT];
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8);
+ ksz_regfields_write(dev, port, RF_GMII_1GBIT, val);
}
static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed)
{
const u8 *bitval = dev->info->xmii_ctrl0;
- const u16 *regs = dev->info->regs;
- u8 data8;
-
- ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8);
-
- data8 &= ~P_MII_100MBIT_M;
+ unsigned int val;
if (speed == SPEED_100)
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]);
+ val = bitval[P_MII_100MBIT];
else
- data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]);
+ val = bitval[P_MII_10MBIT];
- /* Write the updated value */
- ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8);
+ ksz_regfields_write(dev, port, RF_MII_100MBIT, val);
}
static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed)
@@ -2923,26 +2968,19 @@ static 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];
+ unsigned int val;
if (duplex == DUPLEX_FULL)
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]);
+ val = bitval[P_MII_FULL_DUPLEX];
else
- val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]);
+ val = bitval[P_MII_HALF_DUPLEX];
- if (tx_pause)
- val |= masks[P_MII_TX_FLOW_CTRL];
+ ksz_regfields_write(dev, port, RF_MII_DUPLEX, val);
- if (rx_pause)
- val |= masks[P_MII_RX_FLOW_CTRL];
+ ksz_regfields_write(dev, port, RF_MII_TX_FLOW_CTRL, !!tx_pause);
- ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
+ if (dev->regfields[RF_MII_RX_FLOW_CTRL])
+ ksz_regfields_write(dev, port, RF_MII_RX_FLOW_CTRL, !!rx_pause);
}
static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
@@ -3420,6 +3458,35 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.set_mac_eee = ksz_set_mac_eee,
};
+int ksz_regfields_init(struct ksz_device *dev, const struct ksz_chip_data *chip)
+{
+ const struct ksz_reg_field *regfields = chip->regfields;
+ struct regmap_field *rf;
+ struct regmap *regmap;
+ enum ksz_rf i;
+
+ dev->regfields = devm_kcalloc(dev->dev, __KSZ_NUM_REGFIELDS,
+ sizeof(*dev->regfields), GFP_KERNEL);
+ if (!dev->regfields)
+ return -ENOMEM;
+
+ for (i = 0; i < __KSZ_NUM_REGFIELDS; i++) {
+ if (!regfields[i].regfield.reg)
+ continue;
+
+ regmap = dev->regmap[regfields[i].width];
+
+ rf = devm_regmap_field_alloc(dev->dev, regmap,
+ regfields[i].regfield);
+ if (IS_ERR(rf))
+ return PTR_ERR(rf);
+
+ dev->regfields[i] = rf;
+ }
+
+ return 0;
+}
+
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
{
struct dsa_switch *ds;
@@ -47,6 +47,11 @@ struct ksz_mib_names {
char string[ETH_GSTRING_LEN];
};
+struct ksz_reg_field {
+ enum ksz_regmap_width width;
+ struct reg_field regfield;
+};
+
struct ksz_chip_data {
u32 chip_id;
const char *dev_name;
@@ -68,6 +73,7 @@ struct ksz_chip_data {
const u16 *regs;
const u32 *masks;
const u8 *shifts;
+ const struct ksz_reg_field *regfields;
const u8 *xmii_ctrl0;
const u8 *xmii_ctrl1;
int stp_ctrl_reg;
@@ -145,6 +151,7 @@ struct ksz_device {
struct device *dev;
struct regmap *regmap[__KSZ_NUM_REGMAPS];
+ struct regmap_field **regfields;
void *priv;
int irq;
@@ -235,6 +242,23 @@ enum ksz_regs {
P_XMII_CTRL_1,
};
+enum ksz_rf {
+ RF_IND_CTRL_0,
+ RF_IND_BYTE,
+ RF_FORCE_CTRL,
+ RF_LOCAL_CTRL,
+ RF_GMII_1GBIT,
+ RF_MII_100MBIT,
+ RF_MII_SEL,
+ RF_MII_DUPLEX,
+ RF_MII_TX_FLOW_CTRL,
+ RF_MII_RX_FLOW_CTRL,
+ RF_RGMII_ID_IG_ENABLE,
+ RF_RGMII_ID_EG_ENABLE,
+ RF_MII_MAC_MODE,
+ __KSZ_NUM_REGFIELDS,
+};
+
enum ksz_masks {
PORT_802_1P_REMAPPING,
SW_TAIL_TAG_ENABLE,
@@ -371,6 +395,7 @@ struct ksz_dev_ops {
void (*exit)(struct ksz_device *dev);
};
+int ksz_regfields_init(struct ksz_device *dev, const struct ksz_chip_data *chip);
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
int ksz_switch_register(struct ksz_device *dev);
void ksz_switch_remove(struct ksz_device *dev);
@@ -578,6 +603,30 @@ static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
mask, val);
}
+static inline int ksz_regfield_read(struct ksz_device *dev, enum ksz_rf rf,
+ unsigned int *val)
+{
+ return regmap_field_read(dev->regfields[rf], val);
+}
+
+static inline int ksz_regfield_write(struct ksz_device *dev, enum ksz_rf rf,
+ unsigned int val)
+{
+ return regmap_field_write(dev->regfields[rf], val);
+}
+
+static inline int ksz_regfields_read(struct ksz_device *dev, enum ksz_rf rf,
+ unsigned int port, unsigned int *val)
+{
+ return regmap_fields_read(dev->regfields[rf], port, val);
+}
+
+static inline int ksz_regfields_write(struct ksz_device *dev, enum ksz_rf rf,
+ unsigned int port, unsigned int val)
+{
+ return regmap_fields_write(dev->regfields[rf], port, val);
+}
+
static inline void ksz_regmap_lock(void *__mtx)
{
struct mutex *mtx = __mtx;
@@ -77,6 +77,10 @@ static int ksz_spi_probe(struct spi_device *spi)
}
}
+ ret = ksz_regfields_init(dev, chip);
+ if (ret)
+ return ret;
+
if (spi->dev.platform_data)
dev->pdata = spi->dev.platform_data;