net: dsa: mv88e6xxx: factorize EEPROM access
Add a MV88E6XXX_FLAG_EEPROM flag to describe switch models featuring an EEPROM and distribute the EEPROM access routines to all models. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6d5834a1ad
commit
d24645bebc
|
@ -124,6 +124,8 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
|
||||||
#ifdef CONFIG_NET_DSA_HWMON
|
#ifdef CONFIG_NET_DSA_HWMON
|
||||||
.get_temp = mv88e6xxx_get_temp,
|
.get_temp = mv88e6xxx_get_temp,
|
||||||
#endif
|
#endif
|
||||||
|
.get_eeprom = mv88e6xxx_get_eeprom,
|
||||||
|
.set_eeprom = mv88e6xxx_set_eeprom,
|
||||||
.get_regs_len = mv88e6xxx_get_regs_len,
|
.get_regs_len = mv88e6xxx_get_regs_len,
|
||||||
.get_regs = mv88e6xxx_get_regs,
|
.get_regs = mv88e6xxx_get_regs,
|
||||||
};
|
};
|
||||||
|
|
|
@ -153,6 +153,8 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
|
||||||
.get_strings = mv88e6xxx_get_strings,
|
.get_strings = mv88e6xxx_get_strings,
|
||||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||||
|
.get_eeprom = mv88e6xxx_get_eeprom,
|
||||||
|
.set_eeprom = mv88e6xxx_set_eeprom,
|
||||||
.adjust_link = mv88e6xxx_adjust_link,
|
.adjust_link = mv88e6xxx_adjust_link,
|
||||||
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
||||||
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
|
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
|
||||||
|
|
|
@ -133,6 +133,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
|
||||||
#ifdef CONFIG_NET_DSA_HWMON
|
#ifdef CONFIG_NET_DSA_HWMON
|
||||||
.get_temp = mv88e6xxx_get_temp,
|
.get_temp = mv88e6xxx_get_temp,
|
||||||
#endif
|
#endif
|
||||||
|
.get_eeprom = mv88e6xxx_get_eeprom,
|
||||||
|
.set_eeprom = mv88e6xxx_set_eeprom,
|
||||||
.get_regs_len = mv88e6xxx_get_regs_len,
|
.get_regs_len = mv88e6xxx_get_regs_len,
|
||||||
.get_regs = mv88e6xxx_get_regs,
|
.get_regs = mv88e6xxx_get_regs,
|
||||||
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
||||||
|
|
|
@ -125,8 +125,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mutex_init(&ps->eeprom_mutex);
|
|
||||||
|
|
||||||
ret = mv88e6xxx_switch_reset(ps, true);
|
ret = mv88e6xxx_switch_reset(ps, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -138,207 +136,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
|
||||||
return mv88e6xxx_setup_ports(ds);
|
return mv88e6xxx_setup_ports(ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
mutex_lock(&ps->eeprom_mutex);
|
|
||||||
|
|
||||||
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
|
||||||
GLOBAL2_EEPROM_OP_READ |
|
|
||||||
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
|
||||||
if (ret < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_eeprom_busy_wait(ds);
|
|
||||||
if (ret < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
|
|
||||||
error:
|
|
||||||
mutex_unlock(&ps->eeprom_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6352_get_eeprom(struct dsa_switch *ds,
|
|
||||||
struct ethtool_eeprom *eeprom, u8 *data)
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
int len;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
offset = eeprom->offset;
|
|
||||||
len = eeprom->len;
|
|
||||||
eeprom->len = 0;
|
|
||||||
|
|
||||||
eeprom->magic = 0xc3ec4951;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_eeprom_load_wait(ds);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (offset & 1) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = mv88e6352_read_eeprom_word(ds, offset >> 1);
|
|
||||||
if (word < 0)
|
|
||||||
return word;
|
|
||||||
|
|
||||||
*data++ = (word >> 8) & 0xff;
|
|
||||||
|
|
||||||
offset++;
|
|
||||||
len--;
|
|
||||||
eeprom->len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len >= 2) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = mv88e6352_read_eeprom_word(ds, offset >> 1);
|
|
||||||
if (word < 0)
|
|
||||||
return word;
|
|
||||||
|
|
||||||
*data++ = word & 0xff;
|
|
||||||
*data++ = (word >> 8) & 0xff;
|
|
||||||
|
|
||||||
offset += 2;
|
|
||||||
len -= 2;
|
|
||||||
eeprom->len += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = mv88e6352_read_eeprom_word(ds, offset >> 1);
|
|
||||||
if (word < 0)
|
|
||||||
return word;
|
|
||||||
|
|
||||||
*data++ = word & 0xff;
|
|
||||||
|
|
||||||
offset++;
|
|
||||||
len--;
|
|
||||||
eeprom->len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
|
|
||||||
return -EROFS;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
|
|
||||||
u16 data)
|
|
||||||
{
|
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
mutex_lock(&ps->eeprom_mutex);
|
|
||||||
|
|
||||||
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
|
|
||||||
if (ret < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
|
||||||
GLOBAL2_EEPROM_OP_WRITE |
|
|
||||||
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
|
||||||
if (ret < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_eeprom_busy_wait(ds);
|
|
||||||
error:
|
|
||||||
mutex_unlock(&ps->eeprom_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mv88e6352_set_eeprom(struct dsa_switch *ds,
|
|
||||||
struct ethtool_eeprom *eeprom, u8 *data)
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
int ret;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (eeprom->magic != 0xc3ec4951)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ret = mv88e6352_eeprom_is_readonly(ds);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
offset = eeprom->offset;
|
|
||||||
len = eeprom->len;
|
|
||||||
eeprom->len = 0;
|
|
||||||
|
|
||||||
ret = mv88e6xxx_eeprom_load_wait(ds);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (offset & 1) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = mv88e6352_read_eeprom_word(ds, offset >> 1);
|
|
||||||
if (word < 0)
|
|
||||||
return word;
|
|
||||||
|
|
||||||
word = (*data++ << 8) | (word & 0xff);
|
|
||||||
|
|
||||||
ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
offset++;
|
|
||||||
len--;
|
|
||||||
eeprom->len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len >= 2) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = *data++;
|
|
||||||
word |= *data++ << 8;
|
|
||||||
|
|
||||||
ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
offset += 2;
|
|
||||||
len -= 2;
|
|
||||||
eeprom->len += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len) {
|
|
||||||
int word;
|
|
||||||
|
|
||||||
word = mv88e6352_read_eeprom_word(ds, offset >> 1);
|
|
||||||
if (word < 0)
|
|
||||||
return word;
|
|
||||||
|
|
||||||
word = (word & 0xff00) | *data++;
|
|
||||||
|
|
||||||
ret = mv88e6352_write_eeprom_word(ds, offset >> 1, word);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
offset++;
|
|
||||||
len--;
|
|
||||||
eeprom->len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dsa_switch_driver mv88e6352_switch_driver = {
|
struct dsa_switch_driver mv88e6352_switch_driver = {
|
||||||
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
||||||
.probe = mv88e6352_drv_probe,
|
.probe = mv88e6352_drv_probe,
|
||||||
|
@ -358,8 +155,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
|
||||||
.set_temp_limit = mv88e6xxx_set_temp_limit,
|
.set_temp_limit = mv88e6xxx_set_temp_limit,
|
||||||
.get_temp_alarm = mv88e6xxx_get_temp_alarm,
|
.get_temp_alarm = mv88e6xxx_get_temp_alarm,
|
||||||
#endif
|
#endif
|
||||||
.get_eeprom = mv88e6352_get_eeprom,
|
.get_eeprom = mv88e6xxx_get_eeprom,
|
||||||
.set_eeprom = mv88e6352_set_eeprom,
|
.set_eeprom = mv88e6xxx_set_eeprom,
|
||||||
.get_regs_len = mv88e6xxx_get_regs_len,
|
.get_regs_len = mv88e6xxx_get_regs_len,
|
||||||
.get_regs = mv88e6xxx_get_regs,
|
.get_regs = mv88e6xxx_get_regs,
|
||||||
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
.port_bridge_join = mv88e6xxx_port_bridge_join,
|
||||||
|
|
|
@ -823,7 +823,7 @@ static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps)
|
||||||
GLOBAL2_SMI_OP_BUSY);
|
GLOBAL2_SMI_OP_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
|
static int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
|
||||||
|
@ -831,7 +831,7 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
|
||||||
GLOBAL2_EEPROM_OP_LOAD);
|
GLOBAL2_EEPROM_OP_LOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
|
static int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
|
||||||
|
@ -839,6 +839,215 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
|
||||||
GLOBAL2_EEPROM_OP_BUSY);
|
GLOBAL2_EEPROM_OP_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mv88e6xxx_read_eeprom_word(struct dsa_switch *ds, int addr)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&ps->eeprom_mutex);
|
||||||
|
|
||||||
|
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
||||||
|
GLOBAL2_EEPROM_OP_READ |
|
||||||
|
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_eeprom_busy_wait(ds);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA);
|
||||||
|
error:
|
||||||
|
mutex_unlock(&ps->eeprom_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mv88e6xxx_get_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
|
||||||
|
u8 *data)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
int offset;
|
||||||
|
int len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
offset = eeprom->offset;
|
||||||
|
len = eeprom->len;
|
||||||
|
eeprom->len = 0;
|
||||||
|
|
||||||
|
eeprom->magic = 0xc3ec4951;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_eeprom_load_wait(ds);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (offset & 1) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
|
||||||
|
if (word < 0)
|
||||||
|
return word;
|
||||||
|
|
||||||
|
*data++ = (word >> 8) & 0xff;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
len--;
|
||||||
|
eeprom->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len >= 2) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
|
||||||
|
if (word < 0)
|
||||||
|
return word;
|
||||||
|
|
||||||
|
*data++ = word & 0xff;
|
||||||
|
*data++ = (word >> 8) & 0xff;
|
||||||
|
|
||||||
|
offset += 2;
|
||||||
|
len -= 2;
|
||||||
|
eeprom->len += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
|
||||||
|
if (word < 0)
|
||||||
|
return word;
|
||||||
|
|
||||||
|
*data++ = word & 0xff;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
len--;
|
||||||
|
eeprom->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mv88e6xxx_eeprom_is_readonly(struct dsa_switch *ds)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!(ret & GLOBAL2_EEPROM_OP_WRITE_EN))
|
||||||
|
return -EROFS;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mv88e6xxx_write_eeprom_word(struct dsa_switch *ds, int addr,
|
||||||
|
u16 data)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&ps->eeprom_mutex);
|
||||||
|
|
||||||
|
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
|
||||||
|
GLOBAL2_EEPROM_OP_WRITE |
|
||||||
|
(addr & GLOBAL2_EEPROM_OP_ADDR_MASK));
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_eeprom_busy_wait(ds);
|
||||||
|
error:
|
||||||
|
mutex_unlock(&ps->eeprom_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mv88e6xxx_set_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
|
||||||
|
u8 *data)
|
||||||
|
{
|
||||||
|
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||||
|
int offset;
|
||||||
|
int ret;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (eeprom->magic != 0xc3ec4951)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_eeprom_is_readonly(ds);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
offset = eeprom->offset;
|
||||||
|
len = eeprom->len;
|
||||||
|
eeprom->len = 0;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_eeprom_load_wait(ds);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (offset & 1) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
|
||||||
|
if (word < 0)
|
||||||
|
return word;
|
||||||
|
|
||||||
|
word = (*data++ << 8) | (word & 0xff);
|
||||||
|
|
||||||
|
ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
len--;
|
||||||
|
eeprom->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len >= 2) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = *data++;
|
||||||
|
word |= *data++ << 8;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
offset += 2;
|
||||||
|
len -= 2;
|
||||||
|
eeprom->len += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
int word;
|
||||||
|
|
||||||
|
word = mv88e6xxx_read_eeprom_word(ds, offset >> 1);
|
||||||
|
if (word < 0)
|
||||||
|
return word;
|
||||||
|
|
||||||
|
word = (word & 0xff00) | *data++;
|
||||||
|
|
||||||
|
ret = mv88e6xxx_write_eeprom_word(ds, offset >> 1, word);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
len--;
|
||||||
|
eeprom->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
|
static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps)
|
||||||
{
|
{
|
||||||
return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
|
return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP,
|
||||||
|
@ -2596,6 +2805,9 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
|
||||||
|
|
||||||
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
|
INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
|
||||||
|
|
||||||
|
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
|
||||||
|
mutex_init(&ps->eeprom_mutex);
|
||||||
|
|
||||||
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
|
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
|
||||||
mv88e6xxx_ppu_state_init(ps);
|
mv88e6xxx_ppu_state_init(ps);
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,11 @@ enum mv88e6xxx_family {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mv88e6xxx_cap {
|
enum mv88e6xxx_cap {
|
||||||
|
/* EEPROM Command and Data registers.
|
||||||
|
* See GLOBAL2_EEPROM_OP and GLOBAL2_EEPROM_DATA.
|
||||||
|
*/
|
||||||
|
MV88E6XXX_CAP_EEPROM,
|
||||||
|
|
||||||
/* PHY Polling Unit.
|
/* PHY Polling Unit.
|
||||||
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
|
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
|
||||||
*/
|
*/
|
||||||
|
@ -364,6 +369,7 @@ enum mv88e6xxx_cap {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bitmask of capabilities */
|
/* Bitmask of capabilities */
|
||||||
|
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
|
||||||
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
|
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
|
||||||
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
|
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
|
||||||
|
|
||||||
|
@ -379,13 +385,15 @@ enum mv88e6xxx_cap {
|
||||||
MV88E6XXX_FLAG_PPU
|
MV88E6XXX_FLAG_PPU
|
||||||
|
|
||||||
#define MV88E6XXX_FLAGS_FAMILY_6320 \
|
#define MV88E6XXX_FLAGS_FAMILY_6320 \
|
||||||
MV88E6XXX_FLAG_SMI_PHY
|
(MV88E6XXX_FLAG_EEPROM | \
|
||||||
|
MV88E6XXX_FLAG_SMI_PHY)
|
||||||
|
|
||||||
#define MV88E6XXX_FLAGS_FAMILY_6351 \
|
#define MV88E6XXX_FLAGS_FAMILY_6351 \
|
||||||
MV88E6XXX_FLAG_SMI_PHY
|
MV88E6XXX_FLAG_SMI_PHY
|
||||||
|
|
||||||
#define MV88E6XXX_FLAGS_FAMILY_6352 \
|
#define MV88E6XXX_FLAGS_FAMILY_6352 \
|
||||||
MV88E6XXX_FLAG_SMI_PHY
|
(MV88E6XXX_FLAG_EEPROM | \
|
||||||
|
MV88E6XXX_FLAG_SMI_PHY)
|
||||||
|
|
||||||
struct mv88e6xxx_info {
|
struct mv88e6xxx_info {
|
||||||
enum mv88e6xxx_family family;
|
enum mv88e6xxx_family family;
|
||||||
|
@ -521,8 +529,10 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
|
||||||
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
|
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp);
|
||||||
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
|
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp);
|
||||||
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
|
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm);
|
||||||
int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
|
int mv88e6xxx_get_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
|
||||||
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
|
u8 *data);
|
||||||
|
int mv88e6xxx_set_eeprom(struct dsa_switch *ds, struct ethtool_eeprom *eeprom,
|
||||||
|
u8 *data);
|
||||||
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
|
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
|
||||||
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
|
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
|
||||||
struct phy_device *phydev, struct ethtool_eee *e);
|
struct phy_device *phydev, struct ethtool_eee *e);
|
||||||
|
|
Loading…
Reference in New Issue