net: stmmac: dwmac-oxnas: Add support for OX810SE
authorNeil Armstrong <narmstrong@baylibre.com>
Tue, 4 Jan 2022 14:56:45 +0000 (15:56 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 12 Jan 2022 17:05:02 +0000 (09:05 -0800)
Add support for OX810SE dwmac glue setup, which is a simplified version
of the OX820 introduced later with more control on the PHY interface.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c

index adfeb8d3293dc6d6f04fa75133f833bc8681bf9a..62a69a91ab22dc76eb45b7cc5647e398925e4430 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 #define DWMAC_RX_VARDELAY(d)           ((d) << DWMAC_RX_VARDELAY_SHIFT)
 #define DWMAC_RXN_VARDELAY(d)          ((d) << DWMAC_RXN_VARDELAY_SHIFT)
 
+struct oxnas_dwmac;
+
+struct oxnas_dwmac_data {
+       int (*setup)(struct oxnas_dwmac *dwmac);
+};
+
 struct oxnas_dwmac {
        struct device   *dev;
        struct clk      *clk;
        struct regmap   *regmap;
+       const struct oxnas_dwmac_data   *data;
 };
 
-static int oxnas_dwmac_init(struct platform_device *pdev, void *priv)
+static int oxnas_dwmac_setup_ox810se(struct oxnas_dwmac *dwmac)
 {
-       struct oxnas_dwmac *dwmac = priv;
        unsigned int value;
        int ret;
 
-       /* Reset HW here before changing the glue configuration */
-       ret = device_reset(dwmac->dev);
-       if (ret)
+       ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
+       if (ret < 0)
                return ret;
 
-       ret = clk_prepare_enable(dwmac->clk);
-       if (ret)
-               return ret;
+       /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
+       value |= BIT(DWMAC_CKEN_GTX)            |
+                /* Use simple mux for 25/125 Mhz clock switching */
+                BIT(DWMAC_SIMPLE_MUX);
+
+       regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
+
+       return 0;
+}
+
+static int oxnas_dwmac_setup_ox820(struct oxnas_dwmac *dwmac)
+{
+       unsigned int value;
+       int ret;
 
        ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
-       if (ret < 0) {
-               clk_disable_unprepare(dwmac->clk);
+       if (ret < 0)
                return ret;
-       }
 
        /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
        value |= BIT(DWMAC_CKEN_GTX)            |
                 /* Use simple mux for 25/125 Mhz clock switching */
-                BIT(DWMAC_SIMPLE_MUX)          |
-                /* set auto switch tx clock source */
-                BIT(DWMAC_AUTO_TX_SOURCE)      |
-                /* enable tx & rx vardelay */
-                BIT(DWMAC_CKEN_TX_OUT)         |
-                BIT(DWMAC_CKEN_TXN_OUT)        |
-                BIT(DWMAC_CKEN_TX_IN)          |
-                BIT(DWMAC_CKEN_RX_OUT)         |
-                BIT(DWMAC_CKEN_RXN_OUT)        |
-                BIT(DWMAC_CKEN_RX_IN);
+               BIT(DWMAC_SIMPLE_MUX)           |
+               /* set auto switch tx clock source */
+               BIT(DWMAC_AUTO_TX_SOURCE)       |
+               /* enable tx & rx vardelay */
+               BIT(DWMAC_CKEN_TX_OUT)          |
+               BIT(DWMAC_CKEN_TXN_OUT) |
+               BIT(DWMAC_CKEN_TX_IN)           |
+               BIT(DWMAC_CKEN_RX_OUT)          |
+               BIT(DWMAC_CKEN_RXN_OUT) |
+               BIT(DWMAC_CKEN_RX_IN);
        regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
 
        /* set tx & rx vardelay */
@@ -100,6 +115,27 @@ static int oxnas_dwmac_init(struct platform_device *pdev, void *priv)
        return 0;
 }
 
+static int oxnas_dwmac_init(struct platform_device *pdev, void *priv)
+{
+       struct oxnas_dwmac *dwmac = priv;
+       int ret;
+
+       /* Reset HW here before changing the glue configuration */
+       ret = device_reset(dwmac->dev);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(dwmac->clk);
+       if (ret)
+               return ret;
+
+       ret = dwmac->data->setup(dwmac);
+       if (ret)
+               clk_disable_unprepare(dwmac->clk);
+
+       return ret;
+}
+
 static void oxnas_dwmac_exit(struct platform_device *pdev, void *priv)
 {
        struct oxnas_dwmac *dwmac = priv;
@@ -128,6 +164,12 @@ static int oxnas_dwmac_probe(struct platform_device *pdev)
                goto err_remove_config_dt;
        }
 
+       dwmac->data = (const struct oxnas_dwmac_data *)of_device_get_match_data(&pdev->dev);
+       if (!dwmac->data) {
+               ret = -EINVAL;
+               goto err_remove_config_dt;
+       }
+
        dwmac->dev = &pdev->dev;
        plat_dat->bsp_priv = dwmac;
        plat_dat->init = oxnas_dwmac_init;
@@ -166,8 +208,23 @@ err_remove_config_dt:
        return ret;
 }
 
+static const struct oxnas_dwmac_data ox810se_dwmac_data = {
+       .setup = oxnas_dwmac_setup_ox810se,
+};
+
+static const struct oxnas_dwmac_data ox820_dwmac_data = {
+       .setup = oxnas_dwmac_setup_ox820,
+};
+
 static const struct of_device_id oxnas_dwmac_match[] = {
-       { .compatible = "oxsemi,ox820-dwmac" },
+       {
+               .compatible = "oxsemi,ox810se-dwmac",
+               .data = &ox810se_dwmac_data,
+       },
+       {
+               .compatible = "oxsemi,ox820-dwmac",
+               .data = &ox820_dwmac_data,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);