Commit 2716a527 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'arm-ox810se-add-ethernet-support'

Neil Armstrong says:

====================
ARM: ox810se: Add Ethernet support

This adds support for the Synopsys DWMAC controller found in the
OX820SE SoC, by using almost the same glue code as the OX820.
====================

Link: https://lore.kernel.org/r/20220104145646.135877-1-narmstrong@baylibre.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4e5bd03a 72f1f7e4
...@@ -9,6 +9,9 @@ Required properties on all platforms: ...@@ -9,6 +9,9 @@ Required properties on all platforms:
- compatible: For the OX820 SoC, it should be : - compatible: For the OX820 SoC, it should be :
- "oxsemi,ox820-dwmac" to select glue - "oxsemi,ox820-dwmac" to select glue
- "snps,dwmac-3.512" to select IP version. - "snps,dwmac-3.512" to select IP version.
For the OX810SE SoC, it should be :
- "oxsemi,ox810se-dwmac" to select glue
- "snps,dwmac-3.512" to select IP version.
- clocks: Should contain phandles to the following clocks - clocks: Should contain phandles to the following clocks
- clock-names: Should contain the following: - clock-names: Should contain the following:
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
...@@ -48,46 +49,60 @@ ...@@ -48,46 +49,60 @@
#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT) #define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT)
#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_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 oxnas_dwmac {
struct device *dev; struct device *dev;
struct clk *clk; struct clk *clk;
struct regmap *regmap; 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; unsigned int value;
int ret; int ret;
/* Reset HW here before changing the glue configuration */ ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
ret = device_reset(dwmac->dev); if (ret < 0)
if (ret)
return ret; return ret;
ret = clk_prepare_enable(dwmac->clk); /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
if (ret) value |= BIT(DWMAC_CKEN_GTX) |
return ret; /* 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); ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
if (ret < 0) { if (ret < 0)
clk_disable_unprepare(dwmac->clk);
return ret; return ret;
}
/* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
value |= BIT(DWMAC_CKEN_GTX) | value |= BIT(DWMAC_CKEN_GTX) |
/* Use simple mux for 25/125 Mhz clock switching */ /* Use simple mux for 25/125 Mhz clock switching */
BIT(DWMAC_SIMPLE_MUX) | BIT(DWMAC_SIMPLE_MUX) |
/* set auto switch tx clock source */ /* set auto switch tx clock source */
BIT(DWMAC_AUTO_TX_SOURCE) | BIT(DWMAC_AUTO_TX_SOURCE) |
/* enable tx & rx vardelay */ /* enable tx & rx vardelay */
BIT(DWMAC_CKEN_TX_OUT) | BIT(DWMAC_CKEN_TX_OUT) |
BIT(DWMAC_CKEN_TXN_OUT) | BIT(DWMAC_CKEN_TXN_OUT) |
BIT(DWMAC_CKEN_TX_IN) | BIT(DWMAC_CKEN_TX_IN) |
BIT(DWMAC_CKEN_RX_OUT) | BIT(DWMAC_CKEN_RX_OUT) |
BIT(DWMAC_CKEN_RXN_OUT) | BIT(DWMAC_CKEN_RXN_OUT) |
BIT(DWMAC_CKEN_RX_IN); BIT(DWMAC_CKEN_RX_IN);
regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value); regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
/* set tx & rx vardelay */ /* set tx & rx vardelay */
...@@ -100,6 +115,27 @@ static int oxnas_dwmac_init(struct platform_device *pdev, void *priv) ...@@ -100,6 +115,27 @@ static int oxnas_dwmac_init(struct platform_device *pdev, void *priv)
return 0; 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) static void oxnas_dwmac_exit(struct platform_device *pdev, void *priv)
{ {
struct oxnas_dwmac *dwmac = priv; struct oxnas_dwmac *dwmac = priv;
...@@ -128,6 +164,12 @@ static int oxnas_dwmac_probe(struct platform_device *pdev) ...@@ -128,6 +164,12 @@ static int oxnas_dwmac_probe(struct platform_device *pdev)
goto err_remove_config_dt; 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; dwmac->dev = &pdev->dev;
plat_dat->bsp_priv = dwmac; plat_dat->bsp_priv = dwmac;
plat_dat->init = oxnas_dwmac_init; plat_dat->init = oxnas_dwmac_init;
...@@ -166,8 +208,23 @@ static int oxnas_dwmac_probe(struct platform_device *pdev) ...@@ -166,8 +208,23 @@ static int oxnas_dwmac_probe(struct platform_device *pdev)
return ret; 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[] = { 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); MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment