ravb: Add support for r8a7795 SoC
authorKazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
Wed, 30 Sep 2015 06:15:55 +0000 (15:15 +0900)
committerDavid S. Miller <davem@davemloft.net>
Sat, 3 Oct 2015 12:05:21 +0000 (05:05 -0700)
This patch supports the r8a7795 SoC by:
- Using two interrupts
  + One for E-MAC
  + One for everything else
  + Both can be handled by the existing common interrupt handler, which
    affords a simpler update to support the new SoC. In future some
    consideration may be given to implementing multiple interrupt handlers
- Limiting the phy speed to 100Mbit/s for the new SoC;
  at this time it is not clear how this restriction may be lifted
  but I hope it will be possible as more information comes to light

Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
[horms: reworked]
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/renesas/ravb.h
drivers/net/ethernet/renesas/ravb_main.c

index a157aaaaff6a183b161f5d7469fd8a7602be729d..0623fff932e4dea830a24d2c45ff484159feaccf 100644 (file)
@@ -766,6 +766,11 @@ struct ravb_ptp {
        struct ravb_ptp_perout perout[N_PER_OUT];
 };
 
+enum ravb_chip_id {
+       RCAR_GEN2,
+       RCAR_GEN3,
+};
+
 struct ravb_private {
        struct net_device *ndev;
        struct platform_device *pdev;
@@ -806,6 +811,8 @@ struct ravb_private {
        int msg_enable;
        int speed;
        int duplex;
+       int emac_irq;
+       enum ravb_chip_id chip_id;
 
        unsigned no_avb_link:1;
        unsigned avb_link_active_low:1;
index 4ca093d033f898765842232727c7ed7c94b212c2..8cc5ec5ed19a59c9db5b77a2f2ea67c13fbd4247 100644 (file)
@@ -889,6 +889,22 @@ static int ravb_phy_init(struct net_device *ndev)
                return -ENOENT;
        }
 
+       /* This driver only support 10/100Mbit speeds on Gen3
+        * at this time.
+        */
+       if (priv->chip_id == RCAR_GEN3) {
+               int err;
+
+               err = phy_set_max_speed(phydev, SPEED_100);
+               if (err) {
+                       netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
+                       phy_disconnect(phydev);
+                       return err;
+               }
+
+               netdev_info(ndev, "limited PHY to 100Mbit/s\n");
+       }
+
        netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
                    phydev->addr, phydev->irq, phydev->drv->name);
 
@@ -1197,6 +1213,15 @@ static int ravb_open(struct net_device *ndev)
                goto out_napi_off;
        }
 
+       if (priv->chip_id == RCAR_GEN3) {
+               error = request_irq(priv->emac_irq, ravb_interrupt,
+                                   IRQF_SHARED, ndev->name, ndev);
+               if (error) {
+                       netdev_err(ndev, "cannot request IRQ\n");
+                       goto out_free_irq;
+               }
+       }
+
        /* Device init */
        error = ravb_dmac_init(ndev);
        if (error)
@@ -1220,6 +1245,7 @@ out_ptp_stop:
        ravb_ptp_stop(ndev);
 out_free_irq:
        free_irq(ndev->irq, ndev);
+       free_irq(priv->emac_irq, ndev);
 out_napi_off:
        napi_disable(&priv->napi[RAVB_NC]);
        napi_disable(&priv->napi[RAVB_BE]);
@@ -1625,10 +1651,20 @@ static int ravb_mdio_release(struct ravb_private *priv)
        return 0;
 }
 
+static const struct of_device_id ravb_match_table[] = {
+       { .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
+       { .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
+       { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ravb_match_table);
+
 static int ravb_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match;
        struct ravb_private *priv;
+       enum ravb_chip_id chip_id;
        struct net_device *ndev;
        int error, irq, q;
        struct resource *res;
@@ -1657,7 +1693,14 @@ static int ravb_probe(struct platform_device *pdev)
        /* The Ether-specific entries in the device structure. */
        ndev->base_addr = res->start;
        ndev->dma = -1;
-       irq = platform_get_irq(pdev, 0);
+
+       match = of_match_device(of_match_ptr(ravb_match_table), &pdev->dev);
+       chip_id = (enum ravb_chip_id)match->data;
+
+       if (chip_id == RCAR_GEN3)
+               irq = platform_get_irq_byname(pdev, "ch22");
+       else
+               irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                error = irq;
                goto out_release;
@@ -1688,6 +1731,17 @@ static int ravb_probe(struct platform_device *pdev)
        priv->avb_link_active_low =
                of_property_read_bool(np, "renesas,ether-link-active-low");
 
+       if (chip_id == RCAR_GEN3) {
+               irq = platform_get_irq_byname(pdev, "ch24");
+               if (irq < 0) {
+                       error = irq;
+                       goto out_release;
+               }
+               priv->emac_irq = irq;
+       }
+
+       priv->chip_id = chip_id;
+
        /* Set function */
        ndev->netdev_ops = &ravb_netdev_ops;
        ndev->ethtool_ops = &ravb_ethtool_ops;
@@ -1818,13 +1872,6 @@ static const struct dev_pm_ops ravb_dev_pm_ops = {
 #define RAVB_PM_OPS NULL
 #endif
 
-static const struct of_device_id ravb_match_table[] = {
-       { .compatible = "renesas,etheravb-r8a7790" },
-       { .compatible = "renesas,etheravb-r8a7794" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, ravb_match_table);
-
 static struct platform_driver ravb_driver = {
        .probe          = ravb_probe,
        .remove         = ravb_remove,