mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 11:23:09 -04:00
Merge branch 'mscc-miim'
Michael Walle says: ==================== net: phy: mscc-miim: add MDIO bus frequency support Introduce MDIO bus frequency support. This way the board can have a faster (or maybe slower) bus frequency than the hardware default. changes since v2: - resend, no RFC anymore, because net-next is open again ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
61
Documentation/devicetree/bindings/net/mscc,miim.yaml
Normal file
61
Documentation/devicetree/bindings/net/mscc,miim.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/mscc,miim.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microsemi MII Management Controller (MIIM)
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
allOf:
|
||||
- $ref: "mdio.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mscc,ocelot-miim
|
||||
- microchip,lan966x-miim
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: base address
|
||||
- description: associated reset register for internal PHYs
|
||||
minItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-frequency: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
mdio@107009c {
|
||||
compatible = "mscc,ocelot-miim";
|
||||
reg = <0x107009c 0x36>, <0x10700f0 0x8>;
|
||||
interrupts = <14>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
Microsemi MII Management Controller (MIIM) / MDIO
|
||||
=================================================
|
||||
|
||||
Properties:
|
||||
- compatible: must be "mscc,ocelot-miim" or "microchip,lan966x-miim"
|
||||
- reg: The base address of the MDIO bus controller register bank. Optionally, a
|
||||
second register bank can be defined if there is an associated reset register
|
||||
for internal PHYs
|
||||
- #address-cells: Must be <1>.
|
||||
- #size-cells: Must be <0>. MDIO addresses have no size component.
|
||||
- interrupts: interrupt specifier (refer to the interrupt binding)
|
||||
|
||||
Typically an MDIO bus might have several children.
|
||||
|
||||
Example:
|
||||
mdio@107009c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "mscc,ocelot-miim";
|
||||
reg = <0x107009c 0x36>, <0x10700f0 0x8>;
|
||||
interrupts = <14>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -30,6 +31,8 @@
|
||||
#define MSCC_MIIM_CMD_VLD BIT(31)
|
||||
#define MSCC_MIIM_REG_DATA 0xC
|
||||
#define MSCC_MIIM_DATA_ERROR (BIT(16) | BIT(17))
|
||||
#define MSCC_MIIM_REG_CFG 0x10
|
||||
#define MSCC_MIIM_CFG_PRESCALE_MASK GENMASK(7, 0)
|
||||
|
||||
#define MSCC_PHY_REG_PHY_CFG 0x0
|
||||
#define PHY_CFG_PHY_ENA (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
@@ -50,6 +53,8 @@ struct mscc_miim_dev {
|
||||
int mii_status_offset;
|
||||
struct regmap *phy_regs;
|
||||
const struct mscc_miim_info *info;
|
||||
struct clk *clk;
|
||||
u32 bus_freq;
|
||||
};
|
||||
|
||||
/* When high resolution timers aren't built-in: we can't use usleep_range() as
|
||||
@@ -235,9 +240,32 @@ int mscc_miim_setup(struct device *dev, struct mii_bus **pbus, const char *name,
|
||||
}
|
||||
EXPORT_SYMBOL(mscc_miim_setup);
|
||||
|
||||
static int mscc_miim_clk_set(struct mii_bus *bus)
|
||||
{
|
||||
struct mscc_miim_dev *miim = bus->priv;
|
||||
unsigned long rate;
|
||||
u32 div;
|
||||
|
||||
/* Keep the current settings */
|
||||
if (!miim->bus_freq)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(miim->clk);
|
||||
|
||||
div = DIV_ROUND_UP(rate, 2 * miim->bus_freq) - 1;
|
||||
if (div == 0 || div & ~MSCC_MIIM_CFG_PRESCALE_MASK) {
|
||||
dev_err(&bus->dev, "Incorrect MDIO clock frequency\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(miim->regs, MSCC_MIIM_REG_CFG,
|
||||
MSCC_MIIM_CFG_PRESCALE_MASK, div);
|
||||
}
|
||||
|
||||
static int mscc_miim_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regmap *mii_regmap, *phy_regmap = NULL;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
void __iomem *regs, *phy_regs;
|
||||
struct mscc_miim_dev *miim;
|
||||
struct resource *res;
|
||||
@@ -288,21 +316,47 @@ static int mscc_miim_probe(struct platform_device *pdev)
|
||||
if (!miim->info)
|
||||
return -EINVAL;
|
||||
|
||||
ret = of_mdiobus_register(bus, pdev->dev.of_node);
|
||||
miim->clk = devm_clk_get_optional(&pdev->dev, NULL);
|
||||
if (IS_ERR(miim->clk))
|
||||
return PTR_ERR(miim->clk);
|
||||
|
||||
of_property_read_u32(np, "clock-frequency", &miim->bus_freq);
|
||||
|
||||
if (miim->bus_freq && !miim->clk) {
|
||||
dev_err(&pdev->dev,
|
||||
"cannot use clock-frequency without a clock\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(miim->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mscc_miim_clk_set(bus);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
|
||||
ret = of_mdiobus_register(bus, np);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
|
||||
return ret;
|
||||
goto out_disable_clk;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, bus);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(miim->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mscc_miim_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mii_bus *bus = platform_get_drvdata(pdev);
|
||||
struct mscc_miim_dev *miim = bus->priv;
|
||||
|
||||
clk_disable_unprepare(miim->clk);
|
||||
mdiobus_unregister(bus);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user