From 9b1dd818095fdec6e4952b8ff5c5da20553c4e09 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:46 -0700 Subject: [PATCH 1/8] dt-bindings: net: Fix Broadcom iProc mdio mux driver base address Modify the base address of the Broadcom iProc MDIO mux driver to point to the start of the block's register address space. Signed-off-by: Arun Parameswaran Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt index dfe287a5d6f2..dc8aa68dbc60 100644 --- a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt @@ -18,9 +18,9 @@ at- Documentation/devicetree/bindings/net/mdio-mux.txt for example: - mdio_mux_iproc: mdio-mux@6602023c { + mdio_mux_iproc: mdio-mux@66020000 { compatible = "brcm,mdio-mux-iproc"; - reg = <0x6602023c 0x14>; + reg = <0x66020000 0x250>; #address-cells = <1>; #size-cells = <0>; From 77fefa93bfebe4df44f154f2aa5938e32630d0bf Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:47 -0700 Subject: [PATCH 2/8] net: phy: Fix the register offsets in Broadcom iProc mdio mux driver Modify the register offsets in the Broadcom iProc mdio mux to start from the top of the register address space. Earlier, the base address pointed to the end of the block's register space. The base address will now point to the start of the mdio's address space. The offsets have been fixed to match this. Signed-off-by: Arun Parameswaran Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-bcm-iproc.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 0c5b68e7da51..9b3167054843 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -22,7 +22,7 @@ #include #include -#define MDIO_PARAM_OFFSET 0x00 +#define MDIO_PARAM_OFFSET 0x23c #define MDIO_PARAM_MIIM_CYCLE 29 #define MDIO_PARAM_INTERNAL_SEL 25 #define MDIO_PARAM_BUS_ID 22 @@ -30,20 +30,22 @@ #define MDIO_PARAM_PHY_ID 16 #define MDIO_PARAM_PHY_DATA 0 -#define MDIO_READ_OFFSET 0x04 +#define MDIO_READ_OFFSET 0x240 #define MDIO_READ_DATA_MASK 0xffff -#define MDIO_ADDR_OFFSET 0x08 +#define MDIO_ADDR_OFFSET 0x244 -#define MDIO_CTRL_OFFSET 0x0C +#define MDIO_CTRL_OFFSET 0x248 #define MDIO_CTRL_WRITE_OP 0x1 #define MDIO_CTRL_READ_OP 0x2 -#define MDIO_STAT_OFFSET 0x10 +#define MDIO_STAT_OFFSET 0x24c #define MDIO_STAT_DONE 1 #define BUS_MAX_ADDR 32 #define EXT_BUS_START_ADDR 16 +#define MDIO_REG_ADDR_SPACE_SIZE 0x250 + struct iproc_mdiomux_desc { void *mux_handle; void __iomem *base; @@ -169,6 +171,14 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) md->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res->start & 0xfff) { + /* For backward compatibility in case the + * base address is specified with an offset. + */ + dev_info(&pdev->dev, "fix base address in dt-blob\n"); + res->start &= ~0xfff; + res->end = res->start + MDIO_REG_ADDR_SPACE_SIZE - 1; + } md->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(md->base)) { dev_err(&pdev->dev, "failed to ioremap register\n"); From 18b872d854dc7256863755ece26828aa1856c13f Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:48 -0700 Subject: [PATCH 3/8] arm64: dts: Fix the base address of the Broadcom iProc mdio mux Modify the base address of the mdio mux driver to point to the start of the mdio mux block's register address space. Signed-off-by: Arun Parameswaran Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi | 4 ++-- arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi index 4057197048dc..1a406a76c86a 100644 --- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi @@ -482,9 +482,9 @@ pwm: pwm@66010000 { status = "disabled"; }; - mdio_mux_iproc: mdio-mux@6602023c { + mdio_mux_iproc: mdio-mux@66020000 { compatible = "brcm,mdio-mux-iproc"; - reg = <0x6602023c 0x14>; + reg = <0x66020000 0x250>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi index b203152ad67c..a70e8ddbd66f 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi @@ -278,9 +278,9 @@ hsls { #include "stingray-pinctrl.dtsi" - mdio_mux_iproc: mdio-mux@2023c { + mdio_mux_iproc: mdio-mux@20000 { compatible = "brcm,mdio-mux-iproc"; - reg = <0x0002023c 0x14>; + reg = <0x00020000 0x250>; #address-cells = <1>; #size-cells = <0>; From 5634cb2b376cef882435c3acce57d4f429405254 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:49 -0700 Subject: [PATCH 4/8] net: phy: Disable external master access in bcm mdio mux driver Configure the scan control register in the Broadcom iProc mdio mux driver to disable access to external master. In some SoC's, the scan control register defaults to an incorrect value. Signed-off-by: Arun Parameswaran Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-bcm-iproc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 9b3167054843..4a253c28edbc 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -22,6 +22,9 @@ #include #include +#define MDIO_SCAN_CTRL_OFFSET 0x008 +#define MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR 28 + #define MDIO_PARAM_OFFSET 0x23c #define MDIO_PARAM_MIIM_CYCLE 29 #define MDIO_PARAM_INTERNAL_SEL 25 @@ -53,6 +56,16 @@ struct iproc_mdiomux_desc { struct mii_bus *mii_bus; }; +static void mdio_mux_iproc_config(struct iproc_mdiomux_desc *md) +{ + u32 val; + + /* Disable external mdio master access */ + val = readl(md->base + MDIO_SCAN_CTRL_OFFSET); + val |= BIT(MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR); + writel(val, md->base + MDIO_SCAN_CTRL_OFFSET); +} + static int iproc_mdio_wait_for_idle(void __iomem *base, bool result) { unsigned int timeout = 1000; /* loop for 1s */ @@ -216,6 +229,8 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) goto out_register; } + mdio_mux_iproc_config(md); + dev_info(md->dev, "iProc mdiomux registered\n"); return 0; From 0fe2cd564c35ce322830967e24693a36bf30cc7f Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:50 -0700 Subject: [PATCH 5/8] net: phy: Use devm api for mdio bus allocation in bcm iproc mdio mux Use devm_mdiobus_alloc() instead of mdiobus_alloc() in the Broadcom iProc mdio mux driver. Signed-off-by: Arun Parameswaran Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-bcm-iproc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 4a253c28edbc..e6146b439b45 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -198,7 +198,7 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) return PTR_ERR(md->base); } - md->mii_bus = mdiobus_alloc(); + md->mii_bus = devm_mdiobus_alloc(&pdev->dev); if (!md->mii_bus) { dev_err(&pdev->dev, "mdiomux bus alloc failed\n"); return -ENOMEM; @@ -217,7 +217,7 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) rc = mdiobus_register(bus); if (rc) { dev_err(&pdev->dev, "mdiomux registration failed\n"); - goto out; + return rc; } platform_set_drvdata(pdev, md); @@ -236,8 +236,6 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) out_register: mdiobus_unregister(bus); -out: - mdiobus_free(bus); return rc; } @@ -247,7 +245,6 @@ static int mdio_mux_iproc_remove(struct platform_device *pdev) mdio_mux_uninit(md->mux_handle); mdiobus_unregister(md->mii_bus); - mdiobus_free(md->mii_bus); return 0; } From 0d5204abe527b28bd708d503c8116a0b627845b4 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:51 -0700 Subject: [PATCH 6/8] dt-bindings: net: Add clock handle to Broadcom iProc mdio mux Add clock phandle, of the core clock driving the mdio block, as an optional property to the Broadcom iProc mdio mux. The clock, when specified, will be used to setup the rate adjust registers in the mdio to derrive the mdio's operating frequency. Signed-off-by: Arun Parameswaran Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt index dc8aa68dbc60..b58843f29591 100644 --- a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt @@ -13,6 +13,9 @@ MDIO multiplexer node: Every non-ethernet PHY requires a compatible so that it could be probed based on this compatible string. +Optional properties: +- clocks: phandle of the core clock which drives the mdio block. + Additional information regarding generic multiplexer properties can be found at- Documentation/devicetree/bindings/net/mdio-mux.txt From 56aea577c8c08c9888d805a5ad81def62f89da55 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:52 -0700 Subject: [PATCH 7/8] net: phy: Add support to configure clock in Broadcom iProc mdio mux Add support to configure the internal rate adjust register based on the core clock supplied through device tree in the Broadcom iProc mdio mux. The operating frequency of the mdio mux block is 11MHz. This is derrived by dividing the clock to the mdio mux with the rate adjust register. In some SoC's the default values of the rate adjust register do not yield 11MHz. These SoC's are required to specify the clock via the device tree for proper operation. Signed-off-by: Arun Parameswaran Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-bcm-iproc.c | 41 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index e6146b439b45..c5aae5e3f20f 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. */ - +#include #include #include #include @@ -22,6 +22,10 @@ #include #include +#define MDIO_RATE_ADJ_EXT_OFFSET 0x000 +#define MDIO_RATE_ADJ_INT_OFFSET 0x004 +#define MDIO_RATE_ADJ_DIVIDENT_SHIFT 16 + #define MDIO_SCAN_CTRL_OFFSET 0x008 #define MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR 28 @@ -49,21 +53,38 @@ #define MDIO_REG_ADDR_SPACE_SIZE 0x250 +#define MDIO_OPERATING_FREQUENCY 11000000 +#define MDIO_RATE_ADJ_DIVIDENT 1 + struct iproc_mdiomux_desc { void *mux_handle; void __iomem *base; struct device *dev; struct mii_bus *mii_bus; + struct clk *core_clk; }; static void mdio_mux_iproc_config(struct iproc_mdiomux_desc *md) { + u32 divisor; u32 val; /* Disable external mdio master access */ val = readl(md->base + MDIO_SCAN_CTRL_OFFSET); val |= BIT(MDIO_SCAN_CTRL_OVRIDE_EXT_MSTR); writel(val, md->base + MDIO_SCAN_CTRL_OFFSET); + + if (md->core_clk) { + /* use rate adjust regs to derrive the mdio's operating + * frequency from the specified core clock + */ + divisor = clk_get_rate(md->core_clk) / MDIO_OPERATING_FREQUENCY; + divisor = divisor / (MDIO_RATE_ADJ_DIVIDENT + 1); + val = divisor; + val |= MDIO_RATE_ADJ_DIVIDENT << MDIO_RATE_ADJ_DIVIDENT_SHIFT; + writel(val, md->base + MDIO_RATE_ADJ_EXT_OFFSET); + writel(val, md->base + MDIO_RATE_ADJ_INT_OFFSET); + } } static int iproc_mdio_wait_for_idle(void __iomem *base, bool result) @@ -204,6 +225,19 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) return -ENOMEM; } + md->core_clk = devm_clk_get(&pdev->dev, NULL); + if (md->core_clk == ERR_PTR(-ENOENT) || + md->core_clk == ERR_PTR(-EINVAL)) + md->core_clk = NULL; + else if (IS_ERR(md->core_clk)) + return PTR_ERR(md->core_clk); + + rc = clk_prepare_enable(md->core_clk); + if (rc) { + dev_err(&pdev->dev, "failed to enable core clk\n"); + return rc; + } + bus = md->mii_bus; bus->priv = md; bus->name = "iProc MDIO mux bus"; @@ -217,7 +251,7 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) rc = mdiobus_register(bus); if (rc) { dev_err(&pdev->dev, "mdiomux registration failed\n"); - return rc; + goto out_clk; } platform_set_drvdata(pdev, md); @@ -236,6 +270,8 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) out_register: mdiobus_unregister(bus); +out_clk: + clk_disable_unprepare(md->core_clk); return rc; } @@ -245,6 +281,7 @@ static int mdio_mux_iproc_remove(struct platform_device *pdev) mdio_mux_uninit(md->mux_handle); mdiobus_unregister(md->mii_bus); + clk_disable_unprepare(md->core_clk); return 0; } From 2c7230446bc90bc883890007e2a5da60c399e88a Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Wed, 1 Aug 2018 17:53:53 -0700 Subject: [PATCH 8/8] net: phy: Add pm support to Broadcom iProc mdio mux driver Add support for suspend and resume to the Broadcom iProc mdio mux driver. Signed-off-by: Arun Parameswaran Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-bcm-iproc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index c5aae5e3f20f..c017486e9b86 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -286,6 +286,32 @@ static int mdio_mux_iproc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mdio_mux_iproc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iproc_mdiomux_desc *md = platform_get_drvdata(pdev); + + clk_disable_unprepare(md->core_clk); + + return 0; +} + +static int mdio_mux_iproc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iproc_mdiomux_desc *md = platform_get_drvdata(pdev); + + clk_prepare_enable(md->core_clk); + mdio_mux_iproc_config(md); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mdio_mux_iproc_pm_ops, + mdio_mux_iproc_suspend, mdio_mux_iproc_resume); + static const struct of_device_id mdio_mux_iproc_match[] = { { .compatible = "brcm,mdio-mux-iproc", @@ -298,6 +324,7 @@ static struct platform_driver mdiomux_iproc_driver = { .driver = { .name = "mdio-mux-iproc", .of_match_table = mdio_mux_iproc_match, + .pm = &mdio_mux_iproc_pm_ops, }, .probe = mdio_mux_iproc_probe, .remove = mdio_mux_iproc_remove,