summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-04-13 10:59:12 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-13 10:59:12 -0400
commit19ec50839d2574430cba6cb76ac3e8c5a1094d2a (patch)
tree6afd9388b916eddcb5f0fb03456116a47c91bb41 /drivers
parentd92be7a41ef15463eb816a4a2d42bf094b56dfce (diff)
parent96cb4342382290c935d933a08feb57d6d0183071 (diff)
downloadlinux-19ec50839d2574430cba6cb76ac3e8c5a1094d2a.tar.bz2
Merge branch 'mvmdio-updates'
Russell King says: ==================== mvmdio updates This series of patches update mvmdio for Armada 8k CP110. A number of issues were found: 1. The driver fails to disable an interrupt when something goes wrong in the probe function. 2. The interrupt is specified in DT to be optional, but the driver unconditionally writes to the interrupt mask register, which may not exist. 3. The DT binding specifies "reg: address and length of the SMI register" however, when supporting the interrupt, the size must cover the interrupt register as well. Update the binding documentation with this information that was previously omitted. 4. If the register size is too small, have the driver print an error and disable use of the interrupt. 5. Armada 8k needs three clocks for the MDIO interface, otherwise the SoC hangs (since it is part of one of the ethernet interfaces.) GOP clock, MG core clock and MG clock are needed on 8k. Augment the binding and driver to allow three clocks to be specified. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/marvell/mvmdio.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index a0d1b084ecec..90a60b98c28e 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -53,7 +53,7 @@
struct orion_mdio_dev {
struct mutex lock;
void __iomem *regs;
- struct clk *clk;
+ struct clk *clk[3];
/*
* If we have access to the error interrupt pin (which is
* somewhat misnamed as it not only reflects internal errors
@@ -187,7 +187,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
struct resource *r;
struct mii_bus *bus;
struct orion_mdio_dev *dev;
- int ret;
+ int i, ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
@@ -216,11 +216,20 @@ static int orion_mdio_probe(struct platform_device *pdev)
init_waitqueue_head(&dev->smi_busy_wait);
- dev->clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(dev->clk))
- clk_prepare_enable(dev->clk);
+ for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+ dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
+ if (IS_ERR(dev->clk[i]))
+ break;
+ clk_prepare_enable(dev->clk[i]);
+ }
dev->err_interrupt = platform_get_irq(pdev, 0);
+ if (dev->err_interrupt > 0 &&
+ resource_size(r) < MVMDIO_ERR_INT_MASK + 4) {
+ dev_err(&pdev->dev,
+ "disabling interrupt, resource size is too small\n");
+ dev->err_interrupt = 0;
+ }
if (dev->err_interrupt > 0) {
ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
orion_mdio_err_irq,
@@ -251,8 +260,16 @@ static int orion_mdio_probe(struct platform_device *pdev)
return 0;
out_mdio:
- if (!IS_ERR(dev->clk))
- clk_disable_unprepare(dev->clk);
+ if (dev->err_interrupt > 0)
+ writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
+
+ for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+ if (IS_ERR(dev->clk[i]))
+ break;
+ clk_disable_unprepare(dev->clk[i]);
+ clk_put(dev->clk[i]);
+ }
+
return ret;
}
@@ -260,11 +277,18 @@ static int orion_mdio_remove(struct platform_device *pdev)
{
struct mii_bus *bus = platform_get_drvdata(pdev);
struct orion_mdio_dev *dev = bus->priv;
+ int i;
- writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
+ if (dev->err_interrupt > 0)
+ writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
mdiobus_unregister(bus);
- if (!IS_ERR(dev->clk))
- clk_disable_unprepare(dev->clk);
+
+ for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+ if (IS_ERR(dev->clk[i]))
+ break;
+ clk_disable_unprepare(dev->clk[i]);
+ clk_put(dev->clk[i]);
+ }
return 0;
}