Commit b2fef875 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-dsa-microchip-fix-writes-to-phy-registers-0x10'

Rasmus Villemoes says:

====================
net: dsa: microchip: fix writes to phy registers >= 0x10

Patch 1 is just a simplification, technically unrelated to the other
two patches. But it would be a bit inconsistent to have the new
ksz_prmw32() introduced in patch 2 use ksz_rmw32() while leaving
ksz_prmw8() as-is.

The actual fix is of course patch 3. I can definitely see some weird
behaviour on our ksz9567 when writing to phy registers 0x1e and 0x1f
(with phytool from userspace), though it does not seem that the effect
is always to write zeroes to the buddy register as the errata sheet
says would be the case. In our case, the switch is connected via i2c;
I hope somebody with other switches and/or the SPI variants can test
this.
====================

Link: https://lore.kernel.org/r/20230620113855.733526-1-linux@rasmusvillemoes.dkSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0c3d6fd4 5c844d57
...@@ -329,11 +329,27 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) ...@@ -329,11 +329,27 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{ {
u32 mask, val32;
/* No real PHY after this. */ /* No real PHY after this. */
if (!dev->info->internal_phy[addr]) if (!dev->info->internal_phy[addr])
return 0; return 0;
return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); if (reg < 0x10)
return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
/* Errata: When using SPI, I2C, or in-band register access,
* writes to certain PHY registers should be performed as
* 32-bit writes instead of 16-bit writes.
*/
val32 = val;
mask = 0xffff;
if ((reg & 1) == 0) {
val32 <<= 16;
mask <<= 16;
}
reg &= ~1;
return ksz_prmw32(dev, addr, 0x100 + (reg << 1), mask, val32);
} }
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member) void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member)
......
...@@ -578,17 +578,15 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset, ...@@ -578,17 +578,15 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset, static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset,
u8 mask, u8 val) u8 mask, u8 val)
{ {
int ret; return ksz_rmw8(dev, dev->dev_ops->get_port_addr(port, offset),
mask, val);
ret = regmap_update_bits(ksz_regmap_8(dev), }
dev->dev_ops->get_port_addr(port, offset),
mask, val);
if (ret)
dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n",
dev->dev_ops->get_port_addr(port, offset),
ERR_PTR(ret));
return ret; static inline int ksz_prmw32(struct ksz_device *dev, int port, int offset,
u32 mask, u32 val)
{
return ksz_rmw32(dev, 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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment