* [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310
@ 2023-12-14 20:14 Tobias Waldekranz
2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz
` (3 more replies)
0 siblings, 4 replies; 26+ messages in thread
From: Tobias Waldekranz @ 2023-12-14 20:14 UTC (permalink / raw)
To: davem, kuba
Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt,
conor+dt, netdev, devicetree
There are two boot options for a 88X3310 PHY:
1. Device loads its firmware from a dedicated serial FLASH
2. Device waits for its firmware to be downloaded over XMDIO
1/4 adds support for the second option. The device reports which mode
it is in via a register, so we only attempt to load a firmware in this
situation. Crucially, if firmware is not available in this case, the
device is not usable _at all_, so we are forced to fail the probe
entirely.
2/4 extends the power up sequence to cover cases where the device has
been hardware strapped to start powered down, in which case all
internal units will be powered down.
3/4 adds support for the LED controller in the PHY. A special DT
attribute is added to control the polarity and drive behavior of each
LED, which we document in 4/4.
Tobias Waldekranz (4):
net: phy: marvell10g: Support firmware loading on 88X3310
net: phy: marvell10g: Fix power-up when strapped to start powered down
net: phy: marvell10g: Add LED support for 88X3310
dt-bindings: net: marvell10g: Document LED polarity
.../bindings/net/marvell,marvell10g.yaml | 60 ++
MAINTAINERS | 1 +
drivers/net/phy/marvell10g.c | 602 +++++++++++++++++-
3 files changed, 660 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/marvell,marvell10g.yaml
--
2.34.1
^ permalink raw reply [flat|nested] 26+ messages in thread* [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310 Tobias Waldekranz @ 2023-12-14 20:14 ` Tobias Waldekranz 2023-12-15 14:30 ` Andrew Lunn ` (4 more replies) 2023-12-14 20:14 ` [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down Tobias Waldekranz ` (2 subsequent siblings) 3 siblings, 5 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-14 20:14 UTC (permalink / raw) To: davem, kuba Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree When probing, if a device is waiting for firmware to be loaded into its RAM, ask userspace for the binary and load it over XMDIO. We have no choice but to bail out of the probe if firmware is not available, as the device does not have any built-in image on which to fall back. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- drivers/net/phy/marvell10g.c | 149 +++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index ad43e280930c..83233b30d7b0 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -25,6 +25,7 @@ #include <linux/bitfield.h> #include <linux/ctype.h> #include <linux/delay.h> +#include <linux/firmware.h> #include <linux/hwmon.h> #include <linux/marvell_phy.h> #include <linux/phy.h> @@ -50,6 +51,13 @@ enum { MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6, MV_PMA_BOOT = 0xc050, MV_PMA_BOOT_FATAL = BIT(0), + MV_PMA_BOOT_PRGS_MASK = 0x0006, + MV_PMA_BOOT_PRGS_INIT = 0x0000, + MV_PMA_BOOT_PRGS_WAIT = 0x0002, + MV_PMA_BOOT_PRGS_CSUM = 0x0004, + MV_PMA_BOOT_PRGS_JRAM = 0x0006, + MV_PMA_BOOT_APP_STARTED = BIT(4), + MV_PMA_BOOT_APP_LOADED = BIT(6), MV_PCS_BASE_T = 0x0000, MV_PCS_BASE_R = 0x1000, @@ -96,6 +104,12 @@ enum { MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380, MV_PCS_PORT_INFO_NPORTS_SHIFT = 7, + /* Firmware downloading */ + MV_PCS_FW_ADDR_LOW = 0xd0f0, + MV_PCS_FW_ADDR_HIGH = 0xd0f1, + MV_PCS_FW_DATA = 0xd0f2, + MV_PCS_FW_CSUM = 0xd0f3, + /* SerDes reinitialization 88E21X0 */ MV_AN_21X0_SERDES_CTRL2 = 0x800f, MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13), @@ -156,6 +170,7 @@ struct mv3310_chip { const struct mv3310_mactype *mactypes; size_t n_mactypes; + const char *firmware_path; #ifdef CONFIG_HWMON int (*hwmon_read_temp_reg)(struct phy_device *phydev); @@ -506,6 +521,132 @@ static const struct sfp_upstream_ops mv3310_sfp_ops = { .module_insert = mv3310_sfp_insert, }; +struct mv3310_fw_hdr { + struct { + u32 size; + u32 addr; + u16 csum; + } __packed data; + + u8 flags; +#define MV3310_FW_HDR_DATA_ONLY BIT(6) + + u8 port_skip; + u32 next_hdr; + u16 csum; + + u8 pad[14]; +} __packed; + +static int mv3310_load_fw_sect(struct phy_device *phydev, + const struct mv3310_fw_hdr *hdr, const u8 *data) +{ + int err = 0; + size_t i; + u16 csum; + + dev_dbg(&phydev->mdio.dev, "Loading %u byte %s section at 0x%08x\n", + hdr->data.size, + (hdr->flags & MV3310_FW_HDR_DATA_ONLY) ? "data" : "executable", + hdr->data.addr); + + for (i = 0, csum = 0; i < hdr->data.size; i++) + csum += data[i]; + + if ((u16)~csum != hdr->data.csum) { + dev_err(&phydev->mdio.dev, "Corrupt section data\n"); + return -EINVAL; + } + + phy_lock_mdio_bus(phydev); + + /* Any existing checksum is cleared by a read */ + __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); + + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_LOW, hdr->data.addr & 0xffff); + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_HIGH, hdr->data.addr >> 16); + + for (i = 0; i < hdr->data.size; i += 2) { + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_DATA, + (data[i + 1] << 8) | data[i]); + } + + csum = __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); + if ((u16)~csum != hdr->data.csum) { + dev_err(&phydev->mdio.dev, "Download failed\n"); + err = -EIO; + goto unlock; + } + + if (hdr->flags & MV3310_FW_HDR_DATA_ONLY) + goto unlock; + + __phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT, 0, MV_PMA_BOOT_APP_LOADED); + mdelay(200); + if (!(__phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT) & MV_PMA_BOOT_APP_STARTED)) { + dev_err(&phydev->mdio.dev, "Application did not startup\n"); + err = -ENODEV; + } + +unlock: + phy_unlock_mdio_bus(phydev); + return err; +} + +static int mv3310_load_fw(struct phy_device *phydev) +{ + const struct mv3310_chip *chip = to_mv3310_chip(phydev); + const struct firmware *fw; + struct mv3310_fw_hdr hdr; + const u8 *sect; + size_t i; + u16 csum; + int err; + + if (!chip->firmware_path) + return -EOPNOTSUPP; + + err = request_firmware(&fw, chip->firmware_path, &phydev->mdio.dev); + if (err) + return err; + + if (fw->size & 1) { + err = -EINVAL; + goto release; + } + + for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { + memcpy(&hdr, sect, sizeof(hdr)); + hdr.data.size = cpu_to_le32(hdr.data.size); + hdr.data.addr = cpu_to_le32(hdr.data.addr); + hdr.data.csum = cpu_to_le16(hdr.data.csum); + hdr.next_hdr = cpu_to_le32(hdr.next_hdr); + hdr.csum = cpu_to_le16(hdr.csum); + + for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) + csum += sect[i]; + + if ((u16)~csum != hdr.csum) { + dev_err(&phydev->mdio.dev, "Corrupt section header\n"); + err = -EINVAL; + break; + } + + err = mv3310_load_fw_sect(phydev, &hdr, sect + sizeof(hdr)); + if (err) + break; + + if (!hdr.next_hdr) + break; + + sect = fw->data + hdr.next_hdr; + } + +release: + release_firmware(fw); + return err; +} + static int mv3310_probe(struct phy_device *phydev) { const struct mv3310_chip *chip = to_mv3310_chip(phydev); @@ -527,6 +668,12 @@ static int mv3310_probe(struct phy_device *phydev) return -ENODEV; } + if ((ret & MV_PMA_BOOT_PRGS_MASK) == MV_PMA_BOOT_PRGS_WAIT) { + ret = mv3310_load_fw(phydev); + if (ret) + return ret; + } + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -1219,6 +1366,7 @@ static const struct mv3310_chip mv3310_type = { .mactypes = mv3310_mactypes, .n_mactypes = ARRAY_SIZE(mv3310_mactypes), + .firmware_path = "mrvl/x3310fw.hdr", #ifdef CONFIG_HWMON .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg, @@ -1489,4 +1637,5 @@ static struct mdio_device_id __maybe_unused mv3310_tbl[] = { }; MODULE_DEVICE_TABLE(mdio, mv3310_tbl); MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver"); +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); MODULE_LICENSE("GPL"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz @ 2023-12-15 14:30 ` Andrew Lunn 2023-12-15 14:34 ` Russell King (Oracle) 2023-12-18 17:11 ` Tobias Waldekranz 2023-12-15 14:33 ` Andrew Lunn ` (3 subsequent siblings) 4 siblings, 2 replies; 26+ messages in thread From: Andrew Lunn @ 2023-12-15 14:30 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Thu, Dec 14, 2023 at 09:14:39PM +0100, Tobias Waldekranz wrote: > When probing, if a device is waiting for firmware to be loaded into > its RAM, ask userspace for the binary and load it over XMDIO. Does a device without firmware have valid ID registers? Is the driver going to probe via bus enumeration, or is it necessary to use a compatible with ID values? > + for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { This validates that the firmware is big enough to hold the header... > + memcpy(&hdr, sect, sizeof(hdr)); > + hdr.data.size = cpu_to_le32(hdr.data.size); > + hdr.data.addr = cpu_to_le32(hdr.data.addr); > + hdr.data.csum = cpu_to_le16(hdr.data.csum); > + hdr.next_hdr = cpu_to_le32(hdr.next_hdr); I'm surprised sparse is not complaining about this. You have the same source and destination, and sparse probably wants the destination to be marked as little endian. > + hdr.csum = cpu_to_le16(hdr.csum); > + > + for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) > + csum += sect[i]; > + > + if ((u16)~csum != hdr.csum) { > + dev_err(&phydev->mdio.dev, "Corrupt section header\n"); > + err = -EINVAL; > + break; > + } > + > + err = mv3310_load_fw_sect(phydev, &hdr, sect + sizeof(hdr)); What i don't see is any validation that the firmware left at sect + sizeof(hdr) big enough to contain hdr.data.size bytes. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-15 14:30 ` Andrew Lunn @ 2023-12-15 14:34 ` Russell King (Oracle) 2023-12-18 17:11 ` Tobias Waldekranz 1 sibling, 0 replies; 26+ messages in thread From: Russell King (Oracle) @ 2023-12-15 14:34 UTC (permalink / raw) To: Andrew Lunn Cc: Tobias Waldekranz, davem, kuba, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Fri, Dec 15, 2023 at 03:30:09PM +0100, Andrew Lunn wrote: > On Thu, Dec 14, 2023 at 09:14:39PM +0100, Tobias Waldekranz wrote: > > When probing, if a device is waiting for firmware to be loaded into > > its RAM, ask userspace for the binary and load it over XMDIO. > > Does a device without firmware have valid ID registers? Yes it does - remember one of the ZII dev boards had a 3310 without firmware, and that can be successfully probed by the driver, which is key to my userspace tooling being able to access the PHY (since userspace can only access devices on MDIO buses that are bound to a netdev.) -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-15 14:30 ` Andrew Lunn 2023-12-15 14:34 ` Russell King (Oracle) @ 2023-12-18 17:11 ` Tobias Waldekranz 1 sibling, 0 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-18 17:11 UTC (permalink / raw) To: Andrew Lunn Cc: davem, kuba, linux, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On fre, dec 15, 2023 at 15:30, Andrew Lunn <andrew@lunn.ch> wrote: > On Thu, Dec 14, 2023 at 09:14:39PM +0100, Tobias Waldekranz wrote: >> When probing, if a device is waiting for firmware to be loaded into >> its RAM, ask userspace for the binary and load it over XMDIO. > > Does a device without firmware have valid ID registers? Is the driver > going to probe via bus enumeration, or is it necessary to use a > compatible with ID values? > >> + for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { > > This validates that the firmware is big enough to hold the header... > >> + memcpy(&hdr, sect, sizeof(hdr)); >> + hdr.data.size = cpu_to_le32(hdr.data.size); >> + hdr.data.addr = cpu_to_le32(hdr.data.addr); >> + hdr.data.csum = cpu_to_le16(hdr.data.csum); >> + hdr.next_hdr = cpu_to_le32(hdr.next_hdr); > > I'm surprised sparse is not complaining about this. You have the same > source and destination, and sparse probably wants the destination to > be marked as little endian. > >> + hdr.csum = cpu_to_le16(hdr.csum); >> + >> + for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) >> + csum += sect[i]; >> + >> + if ((u16)~csum != hdr.csum) { >> + dev_err(&phydev->mdio.dev, "Corrupt section header\n"); >> + err = -EINVAL; >> + break; >> + } >> + >> + err = mv3310_load_fw_sect(phydev, &hdr, sect + sizeof(hdr)); > > What i don't see is any validation that the firmware left at sect + > sizeof(hdr) big enough to contain hdr.data.size bytes. > Thanks Andrew and Russel, for the review! You both make valid points, I'll try to be less clever about this whole section in v2. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz 2023-12-15 14:30 ` Andrew Lunn @ 2023-12-15 14:33 ` Andrew Lunn 2023-12-15 15:52 ` Russell King (Oracle) ` (2 subsequent siblings) 4 siblings, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2023-12-15 14:33 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree > + for (i = 0, csum = 0; i < hdr->data.size; i++) > + csum += data[i]; > + for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { > + memcpy(&hdr, sect, sizeof(hdr)); > + hdr.data.size = cpu_to_le32(hdr.data.size); hdr.data.size is little endian. Doing a for loop using a little endian test seems wrong. Should this actually be le32_to_cpu()? Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz 2023-12-15 14:30 ` Andrew Lunn 2023-12-15 14:33 ` Andrew Lunn @ 2023-12-15 15:52 ` Russell King (Oracle) 2023-12-16 14:35 ` kernel test robot 2023-12-19 9:22 ` Marek Behún 4 siblings, 0 replies; 26+ messages in thread From: Russell King (Oracle) @ 2023-12-15 15:52 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Thu, Dec 14, 2023 at 09:14:39PM +0100, Tobias Waldekranz wrote: > + MV_PMA_BOOT_PRGS_MASK = 0x0006, > + MV_PMA_BOOT_PRGS_INIT = 0x0000, > + MV_PMA_BOOT_PRGS_WAIT = 0x0002, > + MV_PMA_BOOT_PRGS_CSUM = 0x0004, > + MV_PMA_BOOT_PRGS_JRAM = 0x0006, You only seem to use PRGS_WAIT, the rest seem unused. > +struct mv3310_fw_hdr { > + struct { > + u32 size; > + u32 addr; > + u16 csum; > + } __packed data; It's probably better to get rid of this embedded struct and just place the members in the parent struct (although csum woul dneed to be renamed). > + > + u8 flags; > +#define MV3310_FW_HDR_DATA_ONLY BIT(6) > + > + u8 port_skip; > + u32 next_hdr; > + u16 csum; > + > + u8 pad[14]; > +} __packed; > + > +static int mv3310_load_fw_sect(struct phy_device *phydev, > + const struct mv3310_fw_hdr *hdr, const u8 *data) > +{ > + int err = 0; > + size_t i; > + u16 csum; > + > + dev_dbg(&phydev->mdio.dev, "Loading %u byte %s section at 0x%08x\n", > + hdr->data.size, > + (hdr->flags & MV3310_FW_HDR_DATA_ONLY) ? "data" : "executable", > + hdr->data.addr); > + > + for (i = 0, csum = 0; i < hdr->data.size; i++) > + csum += data[i]; > + > + if ((u16)~csum != hdr->data.csum) { > + dev_err(&phydev->mdio.dev, "Corrupt section data\n"); > + return -EINVAL; > + } > + > + phy_lock_mdio_bus(phydev); > + > + /* Any existing checksum is cleared by a read */ > + __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); > + > + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_LOW, hdr->data.addr & 0xffff); > + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_ADDR_HIGH, hdr->data.addr >> 16); > + > + for (i = 0; i < hdr->data.size; i += 2) { > + __phy_write_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_DATA, > + (data[i + 1] << 8) | data[i]); > + } > + > + csum = __phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_FW_CSUM); > + if ((u16)~csum != hdr->data.csum) { > + dev_err(&phydev->mdio.dev, "Download failed\n"); > + err = -EIO; > + goto unlock; > + } > + > + if (hdr->flags & MV3310_FW_HDR_DATA_ONLY) > + goto unlock; > + > + __phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT, 0, MV_PMA_BOOT_APP_LOADED); > + mdelay(200); > + if (!(__phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT) & MV_PMA_BOOT_APP_STARTED)) { > + dev_err(&phydev->mdio.dev, "Application did not startup\n"); > + err = -ENODEV; > + } I'm confused why this is done here - after each section in the firmware file, rather than having loaded all sections in the firmware file and only then starting the application. Surely if there's multiple sections that we're going to load, we want to load _all_ sections before starting the application? -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz ` (2 preceding siblings ...) 2023-12-15 15:52 ` Russell King (Oracle) @ 2023-12-16 14:35 ` kernel test robot 2023-12-19 9:22 ` Marek Behún 4 siblings, 0 replies; 26+ messages in thread From: kernel test robot @ 2023-12-16 14:35 UTC (permalink / raw) To: Tobias Waldekranz, davem, kuba Cc: oe-kbuild-all, linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree Hi Tobias, kernel test robot noticed the following build warnings: [auto build test WARNING on net-next/main] url: https://github.com/intel-lab-lkp/linux/commits/Tobias-Waldekranz/net-phy-marvell10g-Support-firmware-loading-on-88X3310/20231215-041703 base: net-next/main patch link: https://lore.kernel.org/r/20231214201442.660447-2-tobias%40waldekranz.com patch subject: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 config: x86_64-randconfig-123-20231216 (https://download.01.org/0day-ci/archive/20231216/202312162238.aJCgm39Y-lkp@intel.com/config) compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231216/202312162238.aJCgm39Y-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202312162238.aJCgm39Y-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/net/phy/marvell10g.c:620:31: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [addressable] [usertype] size @@ got restricted __le32 [usertype] @@ drivers/net/phy/marvell10g.c:620:31: sparse: expected unsigned int [addressable] [usertype] size drivers/net/phy/marvell10g.c:620:31: sparse: got restricted __le32 [usertype] >> drivers/net/phy/marvell10g.c:621:31: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [addressable] [usertype] addr @@ got restricted __le32 [usertype] @@ drivers/net/phy/marvell10g.c:621:31: sparse: expected unsigned int [addressable] [usertype] addr drivers/net/phy/marvell10g.c:621:31: sparse: got restricted __le32 [usertype] >> drivers/net/phy/marvell10g.c:622:31: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short [addressable] [usertype] csum @@ got restricted __le16 [usertype] @@ drivers/net/phy/marvell10g.c:622:31: sparse: expected unsigned short [addressable] [usertype] csum drivers/net/phy/marvell10g.c:622:31: sparse: got restricted __le16 [usertype] >> drivers/net/phy/marvell10g.c:623:30: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int [addressable] [usertype] next_hdr @@ got restricted __le32 [usertype] @@ drivers/net/phy/marvell10g.c:623:30: sparse: expected unsigned int [addressable] [usertype] next_hdr drivers/net/phy/marvell10g.c:623:30: sparse: got restricted __le32 [usertype] drivers/net/phy/marvell10g.c:624:26: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned short [addressable] [usertype] csum @@ got restricted __le16 [usertype] @@ drivers/net/phy/marvell10g.c:624:26: sparse: expected unsigned short [addressable] [usertype] csum drivers/net/phy/marvell10g.c:624:26: sparse: got restricted __le16 [usertype] vim +620 drivers/net/phy/marvell10g.c 595 596 static int mv3310_load_fw(struct phy_device *phydev) 597 { 598 const struct mv3310_chip *chip = to_mv3310_chip(phydev); 599 const struct firmware *fw; 600 struct mv3310_fw_hdr hdr; 601 const u8 *sect; 602 size_t i; 603 u16 csum; 604 int err; 605 606 if (!chip->firmware_path) 607 return -EOPNOTSUPP; 608 609 err = request_firmware(&fw, chip->firmware_path, &phydev->mdio.dev); 610 if (err) 611 return err; 612 613 if (fw->size & 1) { 614 err = -EINVAL; 615 goto release; 616 } 617 618 for (sect = fw->data; (sect + sizeof(hdr)) < (fw->data + fw->size);) { 619 memcpy(&hdr, sect, sizeof(hdr)); > 620 hdr.data.size = cpu_to_le32(hdr.data.size); > 621 hdr.data.addr = cpu_to_le32(hdr.data.addr); > 622 hdr.data.csum = cpu_to_le16(hdr.data.csum); > 623 hdr.next_hdr = cpu_to_le32(hdr.next_hdr); 624 hdr.csum = cpu_to_le16(hdr.csum); 625 626 for (i = 0, csum = 0; i < offsetof(struct mv3310_fw_hdr, csum); i++) 627 csum += sect[i]; 628 629 if ((u16)~csum != hdr.csum) { 630 dev_err(&phydev->mdio.dev, "Corrupt section header\n"); 631 err = -EINVAL; 632 break; 633 } 634 635 err = mv3310_load_fw_sect(phydev, &hdr, sect + sizeof(hdr)); 636 if (err) 637 break; 638 639 if (!hdr.next_hdr) 640 break; 641 642 sect = fw->data + hdr.next_hdr; 643 } 644 645 release: 646 release_firmware(fw); 647 return err; 648 } 649 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz ` (3 preceding siblings ...) 2023-12-16 14:35 ` kernel test robot @ 2023-12-19 9:22 ` Marek Behún 2023-12-19 10:15 ` Tobias Waldekranz 4 siblings, 1 reply; 26+ messages in thread From: Marek Behún @ 2023-12-19 9:22 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Thu, 14 Dec 2023 21:14:39 +0100 Tobias Waldekranz <tobias@waldekranz.com> wrote: > +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); And do you have permission to publish this firmware into linux-firmware? Because when we tried this with Marvell, their lawyer guy said we can't do that... Marek ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-19 9:22 ` Marek Behún @ 2023-12-19 10:15 ` Tobias Waldekranz 2023-12-19 10:49 ` Marek Behún 2024-01-02 10:12 ` Russell King (Oracle) 0 siblings, 2 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-19 10:15 UTC (permalink / raw) To: Marek Behún Cc: davem, kuba, linux, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: > On Thu, 14 Dec 2023 21:14:39 +0100 > Tobias Waldekranz <tobias@waldekranz.com> wrote: > >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); > > And do you have permission to publish this firmware into linux-firmware? No, I do not. > Because when we tried this with Marvell, their lawyer guy said we can't > do that... I don't even have good enough access to ask the question, much less get rejected by Marvell :) I just used that path so that it would line up with linux-firmware if Marvell was to publish it in the future. Should MODULE_FIRMWARE be avoided for things that are not in linux-firmware? ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-19 10:15 ` Tobias Waldekranz @ 2023-12-19 10:49 ` Marek Behún 2023-12-19 13:15 ` Tobias Waldekranz 2024-01-02 10:12 ` Russell King (Oracle) 1 sibling, 1 reply; 26+ messages in thread From: Marek Behún @ 2023-12-19 10:49 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Tue, 19 Dec 2023 11:15:41 +0100 Tobias Waldekranz <tobias@waldekranz.com> wrote: > On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: > > On Thu, 14 Dec 2023 21:14:39 +0100 > > Tobias Waldekranz <tobias@waldekranz.com> wrote: > > > >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); > > > > And do you have permission to publish this firmware into linux-firmware? > > No, I do not. > > > Because when we tried this with Marvell, their lawyer guy said we can't > > do that... > > I don't even have good enough access to ask the question, much less get > rejected by Marvell :) I just used that path so that it would line up > with linux-firmware if Marvell was to publish it in the future. Yeah, it was pretty stupid in my opinion. The lawyer guy's reasoning was that to download the firmware from Marvell's Customer Portal you have to agree with Terms & Conditions, so it can't be distributed to people who did not agree to Terms & Conditions. We told him that anyone can get access to the firmware without agreeing anyway, since they can just read the SPI NOR module connected to the PHY if we burn the firmware in manufacture... > Should MODULE_FIRMWARE be avoided for things that are not in > linux-firmware? I don't know. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-19 10:49 ` Marek Behún @ 2023-12-19 13:15 ` Tobias Waldekranz 0 siblings, 0 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-19 13:15 UTC (permalink / raw) To: Marek Behún Cc: davem, kuba, linux, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On tis, dec 19, 2023 at 11:49, Marek Behún <kabel@kernel.org> wrote: > On Tue, 19 Dec 2023 11:15:41 +0100 > Tobias Waldekranz <tobias@waldekranz.com> wrote: > >> On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: >> > On Thu, 14 Dec 2023 21:14:39 +0100 >> > Tobias Waldekranz <tobias@waldekranz.com> wrote: >> > >> >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); >> > >> > And do you have permission to publish this firmware into linux-firmware? >> >> No, I do not. >> >> > Because when we tried this with Marvell, their lawyer guy said we can't >> > do that... >> >> I don't even have good enough access to ask the question, much less get >> rejected by Marvell :) I just used that path so that it would line up >> with linux-firmware if Marvell was to publish it in the future. > > Yeah, it was pretty stupid in my opinion. The lawyer guy's reasoning > was that to download the firmware from Marvell's Customer Portal you > have to agree with Terms & Conditions, so it can't be distributed to > people who did not agree to Terms & Conditions. We told him that anyone > can get access to the firmware without agreeing anyway, since they can > just read the SPI NOR module connected to the PHY if we burn the > firmware in manufacture... Yeah, they are needlessly secretive in lots of ways - much to their own detriment, IMO. They also protect their functional specs as if you could just run them through `pdf2rtl`, email the output to TSMC, and have your own 7nm ASIC in the mail the following week. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2023-12-19 10:15 ` Tobias Waldekranz 2023-12-19 10:49 ` Marek Behún @ 2024-01-02 10:12 ` Russell King (Oracle) 2024-01-02 13:09 ` Tobias Waldekranz 1 sibling, 1 reply; 26+ messages in thread From: Russell King (Oracle) @ 2024-01-02 10:12 UTC (permalink / raw) To: Tobias Waldekranz Cc: Marek Behún, davem, kuba, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Tue, Dec 19, 2023 at 11:15:41AM +0100, Tobias Waldekranz wrote: > On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: > > On Thu, 14 Dec 2023 21:14:39 +0100 > > Tobias Waldekranz <tobias@waldekranz.com> wrote: > > > >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); > > > > And do you have permission to publish this firmware into linux-firmware? > > No, I do not. > > > Because when we tried this with Marvell, their lawyer guy said we can't > > do that... > > I don't even have good enough access to ask the question, much less get > rejected by Marvell :) I just used that path so that it would line up > with linux-firmware if Marvell was to publish it in the future. > > Should MODULE_FIRMWARE be avoided for things that are not in > linux-firmware? Without the firmware being published, what use is having this code in mainline kernels? -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2024-01-02 10:12 ` Russell King (Oracle) @ 2024-01-02 13:09 ` Tobias Waldekranz 2024-10-06 16:15 ` Daniel Golle 0 siblings, 1 reply; 26+ messages in thread From: Tobias Waldekranz @ 2024-01-02 13:09 UTC (permalink / raw) To: Russell King (Oracle) Cc: Marek Behún, davem, kuba, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On tis, jan 02, 2024 at 10:12, "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > On Tue, Dec 19, 2023 at 11:15:41AM +0100, Tobias Waldekranz wrote: >> On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: >> > On Thu, 14 Dec 2023 21:14:39 +0100 >> > Tobias Waldekranz <tobias@waldekranz.com> wrote: >> > >> >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); >> > >> > And do you have permission to publish this firmware into linux-firmware? >> >> No, I do not. >> >> > Because when we tried this with Marvell, their lawyer guy said we can't >> > do that... >> >> I don't even have good enough access to ask the question, much less get >> rejected by Marvell :) I just used that path so that it would line up >> with linux-firmware if Marvell was to publish it in the future. >> >> Should MODULE_FIRMWARE be avoided for things that are not in >> linux-firmware? > > Without the firmware being published, what use is having this code in > mainline kernels? Personally, I primarily want this merged so that future contributions to the driver are easier to develop, since I'll be able test them on top of a clean net-next base. More broadly, I suppose it will help others who are looking to support similar boards to run the latest kernel, without the need to juggle external patches which are likely to break as the driver evolves. Having a single, canonical, implementation of firmware loading, instead of multiple slightly-broken-in-different-ways ones floating around, also seems like a net positive. ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2024-01-02 13:09 ` Tobias Waldekranz @ 2024-10-06 16:15 ` Daniel Golle 2024-10-06 21:32 ` Tobias Waldekranz 0 siblings, 1 reply; 26+ messages in thread From: Daniel Golle @ 2024-10-06 16:15 UTC (permalink / raw) To: Tobias Waldekranz Cc: Russell King (Oracle), Marek Behún, davem, kuba, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree Hi Tobias, On Tue, Jan 02, 2024 at 02:09:24PM +0100, Tobias Waldekranz wrote: > On tis, jan 02, 2024 at 10:12, "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > > On Tue, Dec 19, 2023 at 11:15:41AM +0100, Tobias Waldekranz wrote: > >> On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: > >> > On Thu, 14 Dec 2023 21:14:39 +0100 > >> > Tobias Waldekranz <tobias@waldekranz.com> wrote: > >> > > >> >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); > >> > > >> > And do you have permission to publish this firmware into linux-firmware? > >> > >> No, I do not. > >> > >> > Because when we tried this with Marvell, their lawyer guy said we can't > >> > do that... > >> > >> I don't even have good enough access to ask the question, much less get > >> rejected by Marvell :) I just used that path so that it would line up > >> with linux-firmware if Marvell was to publish it in the future. > >> > >> Should MODULE_FIRMWARE be avoided for things that are not in > >> linux-firmware? > > > > Without the firmware being published, what use is having this code in > > mainline kernels? > > Personally, I primarily want this merged so that future contributions to > the driver are easier to develop, since I'll be able test them on top of > a clean net-next base. I've been pointed to your series by Krzysztof Kozlowski who had reviewed the DT part of it. Are you still working on that or going to eventually re-submit it? I understand that the suggested LED support pre-dates commit 7ae215ee7bb8 net: phy: add support for PHY LEDs polarity modes which would allow using generic properties 'active-low' and 'inactive-high-impedance'. I assume that would be applicable to the LED patch which was part of this series as well? In that case, we would no longer need a vendor-specific property for that purpose. If the LEDs are active-low by default (or early boot firmware setting) and you would need a property for setting them to 'active-high' instead, I just suggested that in https://patchwork.kernel.org/project/netdevbpf/patch/e91ca84ac836fc40c94c52733f8fc607bcbed64c.1728145095.git.daniel@makrotopia.org/ which is why I'm now contacting you, as I was a bit confused by Krzysztof's suggestion to take a look at marvell,marvell10g.yaml which would have been introduced by your series. Imho it would be better to use the (now existing) generic properties than resorting to a vendor-specific one. In every case, if you have a minute to look at commit 7ae215ee7bb8 and let us know whether that structure, with or without my suggested addition, would be suitable for your case as well, that would be nice. Thank you for your time and support! Daniel ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 2024-10-06 16:15 ` Daniel Golle @ 2024-10-06 21:32 ` Tobias Waldekranz 0 siblings, 0 replies; 26+ messages in thread From: Tobias Waldekranz @ 2024-10-06 21:32 UTC (permalink / raw) To: Daniel Golle Cc: Russell King (Oracle), Marek Behún, davem, kuba, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On sön, okt 06, 2024 at 17:15, Daniel Golle <daniel@makrotopia.org> wrote: > Hi Tobias, Hi Daniel, > On Tue, Jan 02, 2024 at 02:09:24PM +0100, Tobias Waldekranz wrote: >> On tis, jan 02, 2024 at 10:12, "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: >> > On Tue, Dec 19, 2023 at 11:15:41AM +0100, Tobias Waldekranz wrote: >> >> On tis, dec 19, 2023 at 10:22, Marek Behún <kabel@kernel.org> wrote: >> >> > On Thu, 14 Dec 2023 21:14:39 +0100 >> >> > Tobias Waldekranz <tobias@waldekranz.com> wrote: >> >> > >> >> >> +MODULE_FIRMWARE("mrvl/x3310fw.hdr"); >> >> > >> >> > And do you have permission to publish this firmware into linux-firmware? >> >> >> >> No, I do not. >> >> >> >> > Because when we tried this with Marvell, their lawyer guy said we can't >> >> > do that... >> >> >> >> I don't even have good enough access to ask the question, much less get >> >> rejected by Marvell :) I just used that path so that it would line up >> >> with linux-firmware if Marvell was to publish it in the future. >> >> >> >> Should MODULE_FIRMWARE be avoided for things that are not in >> >> linux-firmware? >> > >> > Without the firmware being published, what use is having this code in >> > mainline kernels? >> >> Personally, I primarily want this merged so that future contributions to >> the driver are easier to develop, since I'll be able test them on top of >> a clean net-next base. > > I've been pointed to your series by Krzysztof Kozlowski who had reviewed > the DT part of it. Are you still working on that or going to eventually > re-submit it? I'm not actively working on it, no, but I still want to get it merged. I, perhaps wrongly, interpreted Russell's lack of reply to my motivation for accepting the firmware loading without having the binary in linux-firmware, as a NAK, and moved on to other things. > I understand that the suggested LED support pre-dates commit > > 7ae215ee7bb8 net: phy: add support for PHY LEDs polarity modes > > which would allow using generic properties 'active-low' and > 'inactive-high-impedance'. I assume that would be applicable to the LED > patch which was part of this series as well? > > In that case, we would no longer need a vendor-specific property for that > purpose. If the LEDs are active-low by default (or early boot firmware > setting) and you would need a property for setting them to 'active-high' > instead, I just suggested that in > > https://patchwork.kernel.org/project/netdevbpf/patch/e91ca84ac836fc40c94c52733f8fc607bcbed64c.1728145095.git.daniel@makrotopia.org/ > > which is why I'm now contacting you, as I was a bit confused by Krzysztof's > suggestion to take a look at marvell,marvell10g.yaml which would have been > introduced by your series. > > Imho it would be better to use the (now existing) generic properties than > resorting to a vendor-specific one. > > In every case, if you have a minute to look at commit 7ae215ee7bb8 and let > us know whether that structure, with or without my suggested addition, > would be suitable for your case as well, that would be nice. To me, it seems cleaner to have a single attribute that defines the behavior you want on the pin (as a string enum). That way you can also explicitly declare that the kernel shouldn't mess with the settings (e.g., `polarity = "keep";`, like you can do with the initial brightness). If you go that way, I would prefer if the "old" attributes where deprecated and only evaluated in case the new attribute is not available. As for how generic it should be: To me it doesn't seem like there's anything PHY-specific about it. I suppose where it might be confusing would be when you have a gpio-led, when that is already taken care of at the GPIO layer. ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down 2023-12-14 20:14 [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310 Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz @ 2023-12-14 20:14 ` Tobias Waldekranz 2023-12-15 15:44 ` Russell King (Oracle) 2023-12-14 20:14 ` [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity Tobias Waldekranz 3 siblings, 1 reply; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-14 20:14 UTC (permalink / raw) To: davem, kuba Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On devices which are hardware strapped to start powered down (PDSTATE == 1), make sure that we clear the power-down bit on all units affected by this setting. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- drivers/net/phy/marvell10g.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 83233b30d7b0..1c1333d867fb 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -344,11 +344,22 @@ static int mv3310_power_down(struct phy_device *phydev) static int mv3310_power_up(struct phy_device *phydev) { + static const u16 resets[][2] = { + { MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1 }, + { MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1 }, + { MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1 }, + { MDIO_MMD_PMAPMD, MDIO_CTRL1 }, + { MDIO_MMD_VEND2, MV_V2_PORT_CTRL }, + }; struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); - int ret; + int i, ret; - ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, - MV_V2_PORT_CTRL_PWRDOWN); + for (i = 0; i < ARRAY_SIZE(resets); i++) { + ret = phy_clear_bits_mmd(phydev, resets[i][0], resets[i][1], + MV_V2_PORT_CTRL_PWRDOWN); + if (ret) + break; + } /* Sometimes, the power down bit doesn't clear immediately, and * a read of this register causes the bit not to clear. Delay -- 2.34.1 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down 2023-12-14 20:14 ` [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down Tobias Waldekranz @ 2023-12-15 15:44 ` Russell King (Oracle) 2023-12-18 18:02 ` Tobias Waldekranz 0 siblings, 1 reply; 26+ messages in thread From: Russell King (Oracle) @ 2023-12-15 15:44 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Thu, Dec 14, 2023 at 09:14:40PM +0100, Tobias Waldekranz wrote: > On devices which are hardware strapped to start powered down (PDSTATE > == 1), make sure that we clear the power-down bit on all units > affected by this setting. > > Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> > --- > drivers/net/phy/marvell10g.c | 17 ++++++++++++++--- > 1 file changed, 14 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c > index 83233b30d7b0..1c1333d867fb 100644 > --- a/drivers/net/phy/marvell10g.c > +++ b/drivers/net/phy/marvell10g.c > @@ -344,11 +344,22 @@ static int mv3310_power_down(struct phy_device *phydev) > > static int mv3310_power_up(struct phy_device *phydev) > { > + static const u16 resets[][2] = { > + { MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1 }, > + { MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1 }, This is not necessary. The documentation states that the power down bit found at each of these is the same physical bit appearing in two different locations. So only one is necessary. > + { MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1 }, > + { MDIO_MMD_PMAPMD, MDIO_CTRL1 }, > + { MDIO_MMD_VEND2, MV_V2_PORT_CTRL }, > + }; > struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > - int ret; > + int i, ret; > > - ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, > - MV_V2_PORT_CTRL_PWRDOWN); > + for (i = 0; i < ARRAY_SIZE(resets); i++) { > + ret = phy_clear_bits_mmd(phydev, resets[i][0], resets[i][1], > + MV_V2_PORT_CTRL_PWRDOWN); While MV_V2_PORT_CTRL_PWRDOWN may correspond with the correct bit for the MDIO CTRL1 register, we have MDIO_CTRL1_LPOWER which describes this bit. Probably the simplest solution would be to leave the existing phy_clear_bits_mmd(), remove the vendor 2 entry from the table, and run through that table first. Lastly, how does this impact a device which has firmware, and the firmware manages the power-down state (the manual states that unused blocks will be powered down - I assume by the firmware.) If this causes blocks which had been powered down by the firmware because they're not being used to then be powered up, that is a regression. Please check that this is not the case. -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down 2023-12-15 15:44 ` Russell King (Oracle) @ 2023-12-18 18:02 ` Tobias Waldekranz 0 siblings, 0 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-18 18:02 UTC (permalink / raw) To: Russell King (Oracle) Cc: davem, kuba, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On fre, dec 15, 2023 at 15:44, "Russell King (Oracle)" <linux@armlinux.org.uk> wrote: > On Thu, Dec 14, 2023 at 09:14:40PM +0100, Tobias Waldekranz wrote: >> On devices which are hardware strapped to start powered down (PDSTATE >> == 1), make sure that we clear the power-down bit on all units >> affected by this setting. >> >> Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> >> --- >> drivers/net/phy/marvell10g.c | 17 ++++++++++++++--- >> 1 file changed, 14 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c >> index 83233b30d7b0..1c1333d867fb 100644 >> --- a/drivers/net/phy/marvell10g.c >> +++ b/drivers/net/phy/marvell10g.c >> @@ -344,11 +344,22 @@ static int mv3310_power_down(struct phy_device *phydev) >> >> static int mv3310_power_up(struct phy_device *phydev) >> { >> + static const u16 resets[][2] = { >> + { MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_CTRL1 }, >> + { MDIO_MMD_PCS, MV_PCS_1000BASEX + MDIO_CTRL1 }, > > This is not necessary. The documentation states that the power down > bit found at each of these is the same physical bit appearing in two > different locations. So only one is necessary. Right, I'll remove the entry for 1000BASE-X in v2. >> + { MDIO_MMD_PCS, MV_PCS_BASE_T + MDIO_CTRL1 }, >> + { MDIO_MMD_PMAPMD, MDIO_CTRL1 }, >> + { MDIO_MMD_VEND2, MV_V2_PORT_CTRL }, >> + }; >> struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); >> - int ret; >> + int i, ret; >> >> - ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, >> - MV_V2_PORT_CTRL_PWRDOWN); >> + for (i = 0; i < ARRAY_SIZE(resets); i++) { >> + ret = phy_clear_bits_mmd(phydev, resets[i][0], resets[i][1], >> + MV_V2_PORT_CTRL_PWRDOWN); > > While MV_V2_PORT_CTRL_PWRDOWN may correspond with the correct bit for > the MDIO CTRL1 register, we have MDIO_CTRL1_LPOWER which describes > this bit. Probably the simplest solution would be to leave the > existing phy_clear_bits_mmd(), remove the vendor 2 entry from the > table, and run through that table first. Yes, I'll fix this in v2. > Lastly, how does this impact a device which has firmware, and the > firmware manages the power-down state (the manual states that unused > blocks will be powered down - I assume by the firmware.) If this > causes blocks which had been powered down by the firmware because > they're not being used to then be powered up, that is a regression. > Please check that this is not the case. This will be very hard for me to test, as I only have access to boards without dedicated FLASHes. That said, I don't think I understand how this is related to how the devices load their firmware. As I understand it, we should pick up the device in the exact same state after the MDIO load as we would if it had booted on its own, via a serial FLASH. The selection of PDSTATE, based on the sample-at-reset pins, is independent of how firmware is loaded. From the manual: The following registers can be set to force the units to power down. I interpret this as the power-down bits only acting as gates to stop firmware from powering up a particular unit. Conversely, clearing one of these bits merely indicates that the firmware is free to power up the unit in question. On a device strapped to PDSTATE==0, I would expect all of these bits to already be cleared, since the manual states that the value of PDSTATE is latched into all these bits at reset. ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 2023-12-14 20:14 [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310 Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down Tobias Waldekranz @ 2023-12-14 20:14 ` Tobias Waldekranz 2023-12-15 14:44 ` Andrew Lunn 2023-12-18 15:55 ` Simon Horman 2023-12-14 20:14 ` [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity Tobias Waldekranz 3 siblings, 2 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-14 20:14 UTC (permalink / raw) To: davem, kuba Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree Pickup the LEDs from the state in which the hardware reset or bootloader left them, but also support further configuration via device tree. This is primarily needed because the electrical polarity and drive behavior is software controlled and not possible to set via hardware strapping. Trigger support: - "none" - "timer": Map 60-100 ms periods to the fast rate (81ms) and 1000-1600 ms periods to the slow rate (1300ms). Defer everything else to software blinking - "netdev": Offload link or duplex information to the solid behavior; tx and/or rx activity to blink behavior. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- drivers/net/phy/marvell10g.c | 436 +++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 1c1333d867fb..73d74977dd05 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -28,6 +28,7 @@ #include <linux/firmware.h> #include <linux/hwmon.h> #include <linux/marvell_phy.h> +#include <linux/of.h> #include <linux/phy.h> #include <linux/sfp.h> #include <linux/netdevice.h> @@ -136,6 +137,14 @@ enum { MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5, MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6, MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7, + MV_V2_LED0_CONTROL = 0xf020, + MV_V2_LED_CONTROL_POLARITY_MASK = 0x0003, + MV_V2_LED_CONTROL_POLARITY_SHIFT = 0, + MV_V2_LED_CONTROL_BLINK_RATE = BIT(2), + MV_V2_LED_CONTROL_SOLID_FUNC_MASK = 0x00f8, + MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT = 3, + MV_V2_LED_CONTROL_BLINK_FUNC_MASK = 0x1f00, + MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT = 8, MV_V2_PORT_INTR_STS = 0xf040, MV_V2_PORT_INTR_MASK = 0xf043, MV_V2_PORT_INTR_STS_WOL_EN = BIT(8), @@ -164,6 +173,7 @@ struct mv3310_mactype { struct mv3310_chip { bool (*has_downshift)(struct phy_device *phydev); void (*init_supported_interfaces)(unsigned long *mask); + int (*leds_probe)(struct phy_device *phydev); int (*get_mactype)(struct phy_device *phydev); int (*set_mactype)(struct phy_device *phydev, int mactype); int (*select_mactype)(unsigned long *interfaces); @@ -177,6 +187,13 @@ struct mv3310_chip { #endif }; +#define MV3310_N_LEDS 4 + +struct mv3310_led { + u8 index; + u16 fw_ctrl; +}; + struct mv3310_priv { DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX); const struct mv3310_mactype *mactype; @@ -186,6 +203,8 @@ struct mv3310_priv { struct device *hwmon_dev; char *hwmon_name; + + struct mv3310_led led[MV3310_N_LEDS]; }; static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev) @@ -193,6 +212,413 @@ static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev) return phydev->drv->driver_data; } +enum mv3310_led_func { + MV3310_LED_FUNC_OFF = 0x00, + MV3310_LED_FUNC_TX_RX = 0x01, + MV3310_LED_FUNC_TX = 0x02, + MV3310_LED_FUNC_RX = 0x03, + MV3310_LED_FUNC_COLLISION = 0x04, + MV3310_LED_FUNC_LINK_COPPER = 0x05, + MV3310_LED_FUNC_LINK_FIBER = 0x06, + MV3310_LED_FUNC_LINK = 0x07, + MV3310_LED_FUNC_10M_LINK = 0x08, + MV3310_LED_FUNC_100M_LINK = 0x09, + MV3310_LED_FUNC_1G_LINK = 0x0a, + MV3310_LED_FUNC_10G_LINK = 0x0b, + MV3310_LED_FUNC_10M_100M_LINK = 0x0c, + MV3310_LED_FUNC_10M_100M_1G_LINK = 0x0d, + MV3310_LED_FUNC_100M_10G_LINK = 0x0e, + MV3310_LED_FUNC_1G_10G_LINK = 0x0f, + MV3310_LED_FUNC_1G_10G_SLAVE = 0x10, + MV3310_LED_FUNC_1G_10G_MASTER = 0x11, + MV3310_LED_FUNC_HALF_DUPLEX = 0x12, + MV3310_LED_FUNC_FULL_DUPLEX = 0x13, + MV3310_LED_FUNC_LINK_EEE = 0x14, + MV3310_LED_FUNC_2G5_LINK = 0x15, + MV3310_LED_FUNC_5G_LINK = 0x16, + MV3310_LED_FUNC_ON = 0x17, + MV3310_LED_FUNC_2G5_5G_SLAVE = 0x18, + MV3310_LED_FUNC_2G5_5G_MASTER = 0x19, + + MV3310_LED_FUNC_SPEED_BLINK = 0x1f +}; + +static int mv3310_led_flags_from_funcs(struct mv3310_led *led, + enum mv3310_led_func solid, + enum mv3310_led_func blink, + unsigned long *flagsp) +{ + unsigned long flags = 0; + + switch (solid) { + case MV3310_LED_FUNC_OFF: + break; + case MV3310_LED_FUNC_LINK_COPPER: + case MV3310_LED_FUNC_LINK_FIBER: + case MV3310_LED_FUNC_LINK: + flags |= TRIGGER_NETDEV_LINK; + break; + case MV3310_LED_FUNC_HALF_DUPLEX: + flags |= TRIGGER_NETDEV_HALF_DUPLEX; + break; + case MV3310_LED_FUNC_FULL_DUPLEX: + flags |= TRIGGER_NETDEV_FULL_DUPLEX; + break; + default: + return -EINVAL; + } + + switch (blink) { + case MV3310_LED_FUNC_OFF: + break; + case MV3310_LED_FUNC_TX: + flags |= TRIGGER_NETDEV_TX; + break; + case MV3310_LED_FUNC_RX: + flags |= TRIGGER_NETDEV_RX; + break; + case MV3310_LED_FUNC_TX_RX: + flags |= TRIGGER_NETDEV_TX | TRIGGER_NETDEV_RX; + break; + default: + return -EINVAL; + } + + *flagsp = flags; + return 0; +} + +static int mv3310_led_funcs_from_flags(struct mv3310_led *led, + unsigned long flags, + enum mv3310_led_func *solid, + enum mv3310_led_func *blink) +{ + unsigned long activity, duplex, link; + + if (flags & ~(BIT(TRIGGER_NETDEV_LINK) | + BIT(TRIGGER_NETDEV_HALF_DUPLEX) | + BIT(TRIGGER_NETDEV_FULL_DUPLEX) | + BIT(TRIGGER_NETDEV_TX) | + BIT(TRIGGER_NETDEV_RX))) + return -EINVAL; + + link = flags & BIT(TRIGGER_NETDEV_LINK); + + duplex = flags & (BIT(TRIGGER_NETDEV_HALF_DUPLEX) | + BIT(TRIGGER_NETDEV_FULL_DUPLEX)); + + activity = flags & (BIT(TRIGGER_NETDEV_TX) | + BIT(TRIGGER_NETDEV_RX)); + + if (link && duplex) + return -EINVAL; + + if (solid) { + if (link) { + *solid = MV3310_LED_FUNC_LINK; + } else if (duplex) { + switch (duplex) { + case BIT(TRIGGER_NETDEV_HALF_DUPLEX): + *solid = MV3310_LED_FUNC_HALF_DUPLEX; + break; + case BIT(TRIGGER_NETDEV_FULL_DUPLEX): + *solid = MV3310_LED_FUNC_FULL_DUPLEX; + break; + default: + break; + } + } else { + *solid = MV3310_LED_FUNC_OFF; + } + } + + if (blink) { + switch (activity) { + case 0: + *blink = MV3310_LED_FUNC_OFF; + break; + case BIT(TRIGGER_NETDEV_TX): + *blink = MV3310_LED_FUNC_TX; + break; + case BIT(TRIGGER_NETDEV_RX): + *blink = MV3310_LED_FUNC_RX; + break; + default: + *blink = MV3310_LED_FUNC_TX_RX; + break; + } + } + + return 0; +} + +static int mv3310_led_get(struct phy_device *phydev, + struct mv3310_led *led, + enum mv3310_led_func *solid, + enum mv3310_led_func *blink, + bool *slow_blink) +{ + int ctrl; + + ctrl = phy_read_mmd(phydev, MDIO_MMD_VEND2, + MV_V2_LED0_CONTROL + led->index); + if (ctrl < 0) + return ctrl; + + *solid = (ctrl & MV_V2_LED_CONTROL_SOLID_FUNC_MASK) >> + MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT; + *blink = (ctrl & MV_V2_LED_CONTROL_BLINK_FUNC_MASK) >> + MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT; + + *slow_blink = !!(ctrl & MV_V2_LED_CONTROL_BLINK_RATE); + return 0; +} + +static int mv3310_led_set(struct phy_device *phydev, + struct mv3310_led *led, + enum mv3310_led_func solid, + enum mv3310_led_func blink, + bool slow_blink) +{ + u16 ctrl = led->fw_ctrl; + + ctrl &= ~MV_V2_LED_CONTROL_SOLID_FUNC_MASK; + ctrl &= ~MV_V2_LED_CONTROL_BLINK_FUNC_MASK; + ctrl &= ~MV_V2_LED_CONTROL_BLINK_RATE; + + ctrl |= solid << MV_V2_LED_CONTROL_SOLID_FUNC_SHIFT; + ctrl |= blink << MV_V2_LED_CONTROL_BLINK_FUNC_SHIFT; + + if (slow_blink) + ctrl |= MV_V2_LED_CONTROL_BLINK_RATE; + + return phy_write_mmd(phydev, MDIO_MMD_VEND2, + MV_V2_LED0_CONTROL + led->index, ctrl); +} + +enum mv3310_led_polarity { + MV3310_LED_POLARITY_ACTIVE_LOW = 0x0, + MV3310_LED_POLARITY_ACTIVE_HIGH = 0x1, + MV3310_LED_POLARITY_ACTIVE_LOW_TRISTATE = 0x2, + MV3310_LED_POLARITY_ACTIVE_HIGH_TRISTATE = 0x3, +}; + +static const char * const mv3310_led_polarity_name[] = { + [MV3310_LED_POLARITY_ACTIVE_LOW] = "active-low", + [MV3310_LED_POLARITY_ACTIVE_HIGH] = "active-high", + [MV3310_LED_POLARITY_ACTIVE_LOW_TRISTATE] = "active-low-tristate", + [MV3310_LED_POLARITY_ACTIVE_HIGH_TRISTATE] = "active-high-tristate", +}; + +static int mv3310_led_polarity_from_str(const char *str, + enum mv3310_led_polarity *polarity) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mv3310_led_polarity_name); i++) { + if (!mv3310_led_polarity_name[i]) + continue; + + if (!strcmp(mv3310_led_polarity_name[i], str)) { + *polarity = i; + return 0; + } + } + + return -ENOENT; +} + +static int mv3310_led_probe_of(struct phy_device *phydev, + struct device_node *np) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + enum mv3310_led_polarity polarity; + struct mv3310_led *led; + const char *str; + u32 index; + u16 ctrl; + int err; + + err = of_property_read_u32(np, "reg", &index); + if (err) + return err; + + if (index >= MV3310_N_LEDS) + return -EINVAL; + + led = &priv->led[index]; + ctrl = led->fw_ctrl; + + err = of_property_read_string(np, "marvell,polarity", &str); + err = err ? : mv3310_led_polarity_from_str(str, &polarity); + if (!err) { + ctrl &= ~MV_V2_LED_CONTROL_POLARITY_MASK; + ctrl |= polarity << MV_V2_LED_CONTROL_POLARITY_SHIFT; + } + + if (ctrl != led->fw_ctrl) { + led->fw_ctrl = ctrl; + + return phy_write_mmd(phydev, MDIO_MMD_VEND2, + MV_V2_LED0_CONTROL + index, ctrl); + } + + return 0; +} + +static int mv3310_leds_probe(struct phy_device *phydev) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + struct device_node *node = phydev->mdio.dev.of_node; + struct device_node *pnp, *np; + int err, val, index; + + /* Save the config left by HW reset or bootloader, to make + * sure that we do not loose any polarity config made by + * firmware. This will be overridden by info from DT, if + * available. + */ + for (index = 0; index < MV3310_N_LEDS; index++) { + val = phy_read_mmd(phydev, MDIO_MMD_VEND2, + MV_V2_LED0_CONTROL + index); + if (val < 0) + return val; + + priv->led[index] = (struct mv3310_led) { + .index = index, + .fw_ctrl = val, + }; + } + + if (!node) + return 0; + + pnp = of_get_child_by_name(node, "leds"); + if (!pnp) + return 0; + + for_each_available_child_of_node(pnp, np) { + err = mv3310_led_probe_of(phydev, np); + if (err) + return err; + } + + return 0; +} + +static int mv3310_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + enum mv3310_led_func solid; + struct mv3310_led *led; + + if (index >= MV3310_N_LEDS) + return -ENODEV; + + led = &priv->led[index]; + + if (value == LED_OFF) + solid = MV3310_LED_FUNC_OFF; + else + solid = MV3310_LED_FUNC_ON; + + return mv3310_led_set(phydev, led, solid, MV3310_LED_FUNC_OFF, false); +} + +static int mv3310_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + struct mv3310_led *led; + bool slow_blink; + int err; + + if (index >= MV3310_N_LEDS) + return -ENODEV; + + led = &priv->led[index]; + + if (*delay_on != *delay_off) + /* Defer anything other than 50% duty cycles to + * software. + */ + return -EINVAL; + + /* Accept values within ~20% of our supported rates (80ms or + * 1300ms periods). + */ + if ((*delay_on >= 30) && (*delay_on <= 50)) + slow_blink = false; + else if (((*delay_on >= 500) && (*delay_on <= 800)) || (*delay_on == 0)) + slow_blink = true; + else + return -EINVAL; + + err = mv3310_led_set(phydev, led, MV3310_LED_FUNC_OFF, + MV3310_LED_FUNC_ON, slow_blink); + if (!err) + *delay_on = *delay_off = slow_blink ? 650 : 40; + + return err; +} + +static int mv3310_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long flags) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + struct mv3310_led *led; + + if (index >= MV3310_N_LEDS) + return -ENODEV; + + led = &priv->led[index]; + + return mv3310_led_funcs_from_flags(led, flags, NULL, NULL); +} + +static int mv3310_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long flags) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + enum mv3310_led_func solid, blink; + struct mv3310_led *led; + int err; + + if (index >= MV3310_N_LEDS) + return -ENODEV; + + led = &priv->led[index]; + + err = mv3310_led_funcs_from_flags(led, flags, &solid, &blink); + if (err) + return err; + + return mv3310_led_set(phydev, led, solid, blink, false); +} + +static int mv3310_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *flags) +{ + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + enum mv3310_led_func solid, blink; + struct mv3310_led *led; + bool slow_blink; + int err; + + if (index >= MV3310_N_LEDS) + return -ENODEV; + + led = &priv->led[index]; + + err = mv3310_led_get(phydev, led, &solid, &blink, &slow_blink); + if (err) + return err; + + return mv3310_led_flags_from_funcs(led, solid, blink, flags); +} + #ifdef CONFIG_HWMON static umode_t mv3310_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, @@ -719,6 +1145,10 @@ static int mv3310_probe(struct phy_device *phydev) if (ret) return ret; + ret = chip->leds_probe ? chip->leds_probe(phydev) : 0; + if (ret) + return ret; + chip->init_supported_interfaces(priv->supported_interfaces); return phy_sfp_probe(phydev, &mv3310_sfp_ops); @@ -1371,6 +1801,7 @@ static void mv2111_init_supported_interfaces(unsigned long *mask) static const struct mv3310_chip mv3310_type = { .has_downshift = mv3310_has_downshift, .init_supported_interfaces = mv3310_init_supported_interfaces, + .leds_probe = mv3310_leds_probe, .get_mactype = mv3310_get_mactype, .set_mactype = mv3310_set_mactype, .select_mactype = mv3310_select_mactype, @@ -1579,6 +2010,11 @@ static struct phy_driver mv3310_drivers[] = { .set_loopback = genphy_c45_loopback, .get_wol = mv3110_get_wol, .set_wol = mv3110_set_wol, + .led_brightness_set = mv3310_led_brightness_set, + .led_blink_set = mv3310_led_blink_set, + .led_hw_is_supported = mv3310_led_hw_is_supported, + .led_hw_control_set = mv3310_led_hw_control_set, + .led_hw_control_get = mv3310_led_hw_control_get, }, { .phy_id = MARVELL_PHY_ID_88X3310, -- 2.34.1 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 2023-12-14 20:14 ` [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 Tobias Waldekranz @ 2023-12-15 14:44 ` Andrew Lunn 2023-12-15 15:12 ` Russell King (Oracle) 2023-12-18 15:55 ` Simon Horman 1 sibling, 1 reply; 26+ messages in thread From: Andrew Lunn @ 2023-12-15 14:44 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree > +static int mv3310_led_funcs_from_flags(struct mv3310_led *led, > + unsigned long flags, > + enum mv3310_led_func *solid, > + enum mv3310_led_func *blink) > +{ > + unsigned long activity, duplex, link; > + > + if (flags & ~(BIT(TRIGGER_NETDEV_LINK) | > + BIT(TRIGGER_NETDEV_HALF_DUPLEX) | > + BIT(TRIGGER_NETDEV_FULL_DUPLEX) | > + BIT(TRIGGER_NETDEV_TX) | > + BIT(TRIGGER_NETDEV_RX))) > + return -EINVAL; This probably should be -EOPNOTSUPP. The trigger will then do the blinking in software. > + > + link = flags & BIT(TRIGGER_NETDEV_LINK); > + > + duplex = flags & (BIT(TRIGGER_NETDEV_HALF_DUPLEX) | > + BIT(TRIGGER_NETDEV_FULL_DUPLEX)); > + > + activity = flags & (BIT(TRIGGER_NETDEV_TX) | > + BIT(TRIGGER_NETDEV_RX)); > + > + if (link && duplex) > + return -EINVAL; It is an odd combination, but again, if the hardware cannot do it, return -EOPNOTSUPP and leave it to the software. Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 2023-12-15 14:44 ` Andrew Lunn @ 2023-12-15 15:12 ` Russell King (Oracle) 0 siblings, 0 replies; 26+ messages in thread From: Russell King (Oracle) @ 2023-12-15 15:12 UTC (permalink / raw) To: Andrew Lunn Cc: Tobias Waldekranz, davem, kuba, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Fri, Dec 15, 2023 at 03:44:07PM +0100, Andrew Lunn wrote: > > +static int mv3310_led_funcs_from_flags(struct mv3310_led *led, > > + unsigned long flags, > > + enum mv3310_led_func *solid, > > + enum mv3310_led_func *blink) > > +{ > > + unsigned long activity, duplex, link; > > + > > + if (flags & ~(BIT(TRIGGER_NETDEV_LINK) | > > + BIT(TRIGGER_NETDEV_HALF_DUPLEX) | > > + BIT(TRIGGER_NETDEV_FULL_DUPLEX) | > > + BIT(TRIGGER_NETDEV_TX) | > > + BIT(TRIGGER_NETDEV_RX))) > > + return -EINVAL; > > This probably should be -EOPNOTSUPP. The trigger will then do the > blinking in software. > > > + > > + link = flags & BIT(TRIGGER_NETDEV_LINK); > > + > > + duplex = flags & (BIT(TRIGGER_NETDEV_HALF_DUPLEX) | > > + BIT(TRIGGER_NETDEV_FULL_DUPLEX)); > > + > > + activity = flags & (BIT(TRIGGER_NETDEV_TX) | > > + BIT(TRIGGER_NETDEV_RX)); > > + > > + if (link && duplex) > > + return -EINVAL; > > It is an odd combination, but again, if the hardware cannot do it, > return -EOPNOTSUPP and leave it to the software. I don't recall how the LED triggers work (whether they logically OR or AND). The hardware supports indicating whether it has a half or full duplex link, and if the LED is programmed for that, then it will illuminate when it has link _and_ the duplex is of the specified type. If the link is down, or the duplex is of the other type, then it won't. I'm guessing that if link is set and duplex is set, then what userspace is asking for is the LED to be illuminated whenever the link is up _or_ the duplex is of the specified type, which basically logically resolves to _only_ "link is up" (because a link that is down has no duplex.) So, I'm not sure "leaving it to software" is good, that combination is effectively just "has link". -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last! ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 2023-12-14 20:14 ` [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 Tobias Waldekranz 2023-12-15 14:44 ` Andrew Lunn @ 2023-12-18 15:55 ` Simon Horman 1 sibling, 0 replies; 26+ messages in thread From: Simon Horman @ 2023-12-18 15:55 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On Thu, Dec 14, 2023 at 09:14:41PM +0100, Tobias Waldekranz wrote: > Pickup the LEDs from the state in which the hardware reset or > bootloader left them, but also support further configuration via > device tree. This is primarily needed because the electrical polarity > and drive behavior is software controlled and not possible to set via > hardware strapping. > > Trigger support: > - "none" > - "timer": Map 60-100 ms periods to the fast rate (81ms) and 1000-1600 > ms periods to the slow rate (1300ms). Defer everything else to > software blinking > - "netdev": Offload link or duplex information to the solid behavior; > tx and/or rx activity to blink behavior. > > Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> ... > +static int mv3310_leds_probe(struct phy_device *phydev) > +{ > + struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); > + struct device_node *node = phydev->mdio.dev.of_node; > + struct device_node *pnp, *np; > + int err, val, index; > + > + /* Save the config left by HW reset or bootloader, to make > + * sure that we do not loose any polarity config made by > + * firmware. This will be overridden by info from DT, if > + * available. > + */ > + for (index = 0; index < MV3310_N_LEDS; index++) { > + val = phy_read_mmd(phydev, MDIO_MMD_VEND2, > + MV_V2_LED0_CONTROL + index); > + if (val < 0) > + return val; > + > + priv->led[index] = (struct mv3310_led) { > + .index = index, > + .fw_ctrl = val, > + }; > + } > + > + if (!node) > + return 0; > + > + pnp = of_get_child_by_name(node, "leds"); > + if (!pnp) > + return 0; > + > + for_each_available_child_of_node(pnp, np) { > + err = mv3310_led_probe_of(phydev, np); > + if (err) Hi Tobias, I think a call to of_node_put(np) is required here to avoid leaking a reference. Flagged by Coccinelle. > + return err; > + } > + > + return 0; > +} ... ^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity 2023-12-14 20:14 [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310 Tobias Waldekranz ` (2 preceding siblings ...) 2023-12-14 20:14 ` [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 Tobias Waldekranz @ 2023-12-14 20:14 ` Tobias Waldekranz 2023-12-15 8:47 ` Krzysztof Kozlowski 2023-12-15 11:19 ` Andrew Lunn 3 siblings, 2 replies; 26+ messages in thread From: Tobias Waldekranz @ 2023-12-14 20:14 UTC (permalink / raw) To: davem, kuba Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree Hardware supports multiple ways of driving attached LEDs, but this is not configurable via any sample-at-reset pins - rather it must be set via software. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- .../bindings/net/marvell,marvell10g.yaml | 60 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/marvell,marvell10g.yaml diff --git a/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml b/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml new file mode 100644 index 000000000000..37ff7fdfdd3d --- /dev/null +++ b/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/marvell,marvell10g.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Alaska X 10G Ethernet PHY + +maintainers: + - Tobias Waldekranz <tobias@waldekranz.com> + +description: | + Bindings for Marvell Alaska X 10G Ethernet PHYs + +allOf: + - $ref: ethernet-phy.yaml# + +properties: + leds: + type: object + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + '^led@[a-f0-9]+$': + $ref: /schemas/leds/common.yaml# + + properties: + marvell,polarity: + description: | + Electrical polarity and drive type for this LED. In the + active state, hardware may drive the pin either low or + high. In the inactive state, the pin can either be + driven to the opposite logic level, or be tristated. + $ref: /schemas/types.yaml#/definitions/string + enum: + - active-low + - active-high + - active-low-tristate + - active-high-tristate + +unevaluatedProperties: false + +examples: + - | + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + reg = <0>; + + marvell,polarity = "active-low-tristate"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index a151988646fe..2def66789f9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12849,6 +12849,7 @@ M: Russell King <linux@armlinux.org.uk> M: Marek Behún <kabel@kernel.org> L: netdev@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/net/marvell,marvell10g.yaml F: drivers/net/phy/marvell10g.c MARVELL MVEBU THERMAL DRIVER -- 2.34.1 ^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity 2023-12-14 20:14 ` [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity Tobias Waldekranz @ 2023-12-15 8:47 ` Krzysztof Kozlowski 2023-12-15 11:19 ` Andrew Lunn 1 sibling, 0 replies; 26+ messages in thread From: Krzysztof Kozlowski @ 2023-12-15 8:47 UTC (permalink / raw) To: Tobias Waldekranz, davem, kuba Cc: linux, kabel, andrew, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree On 14/12/2023 21:14, Tobias Waldekranz wrote: > Hardware supports multiple ways of driving attached LEDs, but this is > not configurable via any sample-at-reset pins - rather it must be set > via software. > > Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> > --- > .../bindings/net/marvell,marvell10g.yaml | 60 +++++++++++++++++++ > MAINTAINERS | 1 + > 2 files changed, 61 insertions(+) > create mode 100644 Documentation/devicetree/bindings/net/marvell,marvell10g.yaml > > diff --git a/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml b/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml > new file mode 100644 > index 000000000000..37ff7fdfdd3d > --- /dev/null > +++ b/Documentation/devicetree/bindings/net/marvell,marvell10g.yaml > @@ -0,0 +1,60 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/net/marvell,marvell10g.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Marvell Alaska X 10G Ethernet PHY > + > +maintainers: > + - Tobias Waldekranz <tobias@waldekranz.com> > + > +description: | Do not need '|' unless you need to preserve formatting. > + Bindings for Marvell Alaska X 10G Ethernet PHYs Drop Bindings for and describe the hardware. You are repeating title, so it is useless. > + > +allOf: > + - $ref: ethernet-phy.yaml# > + > +properties: How is this schema selected/applied? I guess you have exactly the same problem as recently talked about other ethernet PHY bindings. See: https://lore.kernel.org/linux-devicetree/20231209014828.28194-1-ansuelsmth@gmail.com/ > + leds: > + type: object > + > + properties: > + '#address-cells': > + const: 1 > + > + '#size-cells': > + const: 0 > + > + patternProperties: > + '^led@[a-f0-9]+$': > + $ref: /schemas/leds/common.yaml# Are you sure you need to repeat all this? > + > + properties: > + marvell,polarity: > + description: | > + Electrical polarity and drive type for this LED. In the > + active state, hardware may drive the pin either low or > + high. In the inactive state, the pin can either be > + driven to the opposite logic level, or be tristated. > + $ref: /schemas/types.yaml#/definitions/string > + enum: > + - active-low > + - active-high > + - active-low-tristate > + - active-high-tristate > + > +unevaluatedProperties: false > + > +examples: > + - | > + mdio { > + #address-cells = <1>; > + #size-cells = <0>; > + > + ethernet-phy@0 { > + reg = <0>; > + > + marvell,polarity = "active-low-tristate"; It is clearly visible here that your schema is an no-op. You do not allow such property in the phy, but in leds! Best regards, Krzysztof ^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity 2023-12-14 20:14 ` [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity Tobias Waldekranz 2023-12-15 8:47 ` Krzysztof Kozlowski @ 2023-12-15 11:19 ` Andrew Lunn 1 sibling, 0 replies; 26+ messages in thread From: Andrew Lunn @ 2023-12-15 11:19 UTC (permalink / raw) To: Tobias Waldekranz Cc: davem, kuba, linux, kabel, hkallweit1, robh+dt, krzysztof.kozlowski+dt, conor+dt, netdev, devicetree > + properties: > + marvell,polarity: > + description: | > + Electrical polarity and drive type for this LED. In the > + active state, hardware may drive the pin either low or > + high. In the inactive state, the pin can either be > + driven to the opposite logic level, or be tristated. > + $ref: /schemas/types.yaml#/definitions/string > + enum: > + - active-low > + - active-high > + - active-low-tristate > + - active-high-tristate Christian is working on adding a generic active-low property, which any PHY LED could use. The assumption being if the bool property is not present, it defaults to active-high. So we should consider, how popular are these two tristate values? Is this a Marvell only thing, or do other PHYs also have them? Do we want to make them part of the generic PHY led binding? Also, is an enum the correct representation? Maybe tristate should be another bool property? Hi/Low and tristate seem to be orthogonal, so maybe two properties would make it cleaner with respect to generic properties? Please work with Christian on this. Thanks Andrew ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-10-06 21:32 UTC | newest] Thread overview: 26+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-12-14 20:14 [PATCH net-next 0/4] net: phy: marvell10g: Firmware loading and LED support for 88X3310 Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 1/4] net: phy: marvell10g: Support firmware loading on 88X3310 Tobias Waldekranz 2023-12-15 14:30 ` Andrew Lunn 2023-12-15 14:34 ` Russell King (Oracle) 2023-12-18 17:11 ` Tobias Waldekranz 2023-12-15 14:33 ` Andrew Lunn 2023-12-15 15:52 ` Russell King (Oracle) 2023-12-16 14:35 ` kernel test robot 2023-12-19 9:22 ` Marek Behún 2023-12-19 10:15 ` Tobias Waldekranz 2023-12-19 10:49 ` Marek Behún 2023-12-19 13:15 ` Tobias Waldekranz 2024-01-02 10:12 ` Russell King (Oracle) 2024-01-02 13:09 ` Tobias Waldekranz 2024-10-06 16:15 ` Daniel Golle 2024-10-06 21:32 ` Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 2/4] net: phy: marvell10g: Fix power-up when strapped to start powered down Tobias Waldekranz 2023-12-15 15:44 ` Russell King (Oracle) 2023-12-18 18:02 ` Tobias Waldekranz 2023-12-14 20:14 ` [PATCH net-next 3/4] net: phy: marvell10g: Add LED support for 88X3310 Tobias Waldekranz 2023-12-15 14:44 ` Andrew Lunn 2023-12-15 15:12 ` Russell King (Oracle) 2023-12-18 15:55 ` Simon Horman 2023-12-14 20:14 ` [PATCH net-next 4/4] dt-bindings: net: marvell10g: Document LED polarity Tobias Waldekranz 2023-12-15 8:47 ` Krzysztof Kozlowski 2023-12-15 11:19 ` Andrew Lunn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).