diff mbox series

[U-Boot,v2,06/18] net: gmac_rockchip: Add support for the RV1108 GMAC

Message ID 1510218149-78706-1-git-send-email-david.wu@rock-chips.com
State Changes Requested
Delegated to: Philipp Tomsich
Headers show
Series Add gmac support for rk3399-evb rv1108-evb rk3328-evb and rk3229-evb | expand

Commit Message

David Wu Nov. 9, 2017, 9:02 a.m. UTC
The rv1108 GMAC only support rmii interface, so need to add the
set_rmii() ops. Use the phy current interface to set rmii or
rgmii ops. At the same time, need to set the mac clock rate of
rmii with 50M, the clock rate of rgmii with 125M.

Signed-off-by: David Wu <david.wu@rock-chips.com>
---

Changes in v2:
- Add check whether the set rgmii/rmii function is a valid function pointer
- Use current phy interface to set mac clock rate
- Clean the grf offset at gmac_rockchip.c

 drivers/net/gmac_rockchip.c | 89 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 82 insertions(+), 7 deletions(-)

Comments

Philipp Tomsich Nov. 20, 2017, 3:05 p.m. UTC | #1
> The rv1108 GMAC only support rmii interface, so need to add the
> set_rmii() ops. Use the phy current interface to set rmii or
> rgmii ops. At the same time, need to set the mac clock rate of
> rmii with 50M, the clock rate of rgmii with 125M.
> 
> Signed-off-by: David Wu <david.wu@rock-chips.com>
> ---
> 
> Changes in v2:
> - Add check whether the set rgmii/rmii function is a valid function pointer
> - Use current phy interface to set mac clock rate
> - Clean the grf offset at gmac_rockchip.c
> 
>  drivers/net/gmac_rockchip.c | 89 +++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 82 insertions(+), 7 deletions(-)
> 

Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Philipp Tomsich Nov. 26, 2017, 2:36 p.m. UTC | #2
On Thu, 9 Nov 2017, David Wu wrote:

> The rv1108 GMAC only support rmii interface, so need to add the
> set_rmii() ops. Use the phy current interface to set rmii or
> rgmii ops. At the same time, need to set the mac clock rate of
> rmii with 50M, the clock rate of rgmii with 125M.
>
> Signed-off-by: David Wu <david.wu@rock-chips.com>
> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

See below for requested changes.

> ---
>
> Changes in v2:
> - Add check whether the set rgmii/rmii function is a valid function pointer
> - Use current phy interface to set mac clock rate
> - Clean the grf offset at gmac_rockchip.c
>
> drivers/net/gmac_rockchip.c | 89 +++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 82 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
> index 586ccbf..22e3941 100644
> --- a/drivers/net/gmac_rockchip.c
> +++ b/drivers/net/gmac_rockchip.c
> @@ -18,6 +18,7 @@
> #include <asm/arch/grf_rk3288.h>
> #include <asm/arch/grf_rk3368.h>
> #include <asm/arch/grf_rk3399.h>
> +#include <asm/arch/grf_rv1108.h>
> #include <dm/pinctrl.h>
> #include <dt-bindings/clock/rk3288-cru.h>
> #include "designware.h"
> @@ -37,6 +38,7 @@ struct gmac_rockchip_platdata {
>
> struct rk_gmac_ops {
> 	int (*fix_mac_speed)(struct dw_eth_dev *priv);
> +	void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata);
> 	void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata);
> };
>
> @@ -142,6 +144,41 @@ static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
> 	return 0;
> }
>
> +static int rv1108_set_rmii_speed(struct dw_eth_dev *priv)
> +{
> +	struct rv1108_grf *grf;
> +	int clk, speed;
> +	enum {
> +		RV1108_GMAC_SPEED_MASK		= BIT(2),
> +		RV1108_GMAC_SPEED_10M		= 0 << 2,
> +		RV1108_GMAC_SPEED_100M		= 1 << 2,
> +		RV1108_GMAC_CLK_SEL_MASK	= BIT(7),
> +		RV1108_GMAC_CLK_SEL_2_5M	= 0 << 7,
> +		RV1108_GMAC_CLK_SEL_25M		= 1 << 7,
> +	};
> +
> +	switch (priv->phydev->speed) {
> +	case 10:
> +		clk = RV1108_GMAC_CLK_SEL_2_5M;
> +		speed = RV1108_GMAC_SPEED_10M;
> +		break;
> +	case 100:
> +		clk = RV1108_GMAC_CLK_SEL_25M;
> +		speed = RV1108_GMAC_SPEED_100M;
> +		break;
> +	default:
> +		debug("Unknown phy speed: %d\n", priv->phydev->speed);
> +		return -EINVAL;
> +	}
> +
> +	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +	rk_clrsetreg(&grf->gmac_con0,
> +		     RV1108_GMAC_CLK_SEL_MASK | RV1108_GMAC_SPEED_MASK,
> +		     clk | speed);
> +
> +	return 0;
> +}
> +
> static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
> {
> 	struct rk3288_grf *grf;
> @@ -221,11 +258,28 @@ static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
> 		     pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT);
> }
>
> +static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata)
> +{
> +	struct rv1108_grf *grf;
> +
> +	enum {
> +		RV1108_GMAC_PHY_INTF_SEL_MASK  = GENMASK(6, 4),
> +		RV1108_GMAC_PHY_INTF_SEL_RMII  = 4 << 4,
> +	};
> +
> +	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> +	rk_clrsetreg(&grf->gmac_con0,
> +		     RV1108_GMAC_PHY_INTF_SEL_MASK,
> +		     RV1108_GMAC_PHY_INTF_SEL_RMII);
> +}
> +
> static int gmac_rockchip_probe(struct udevice *dev)
> {
> 	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
> 	struct rk_gmac_ops *ops =
> 		(struct rk_gmac_ops *)dev_get_driver_data(dev);
> +	struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
> +	struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata;
> 	struct clk clk;
> 	int ret;
>
> @@ -233,13 +287,27 @@ static int gmac_rockchip_probe(struct udevice *dev)
> 	if (ret)
> 		return ret;
>
> -	/* Since mac_clk is fed by an external clock we can use 0 here */
> -	ret = clk_set_rate(&clk, 0);
> -	if (ret)
> -		return ret;
> -
> -	/* Set to RGMII mode */
> -	ops->set_to_rgmii(pdata);
> +	switch (eth_pdata->phy_interface) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +		ret = clk_set_rate(&clk, 125000000);
> +		if (IS_ERR_VALUE(ret))
> +			return ret;
> +		/* Set to RGMII mode */
> +		if (ops->set_to_rgmii)
> +			ops->set_to_rgmii(pdata);

This avoids a crash, but shouldn't it handle the error (of no set_to_rgmii 
being present?  As of now, it will chain through into designware_eth_probe 
and eventually return successful completion.

> +		break;
> +	case PHY_INTERFACE_MODE_RMII:
> +		ret = clk_set_rate(&clk, 50000000);
> +		if (IS_ERR_VALUE(ret))
> +			return ret;
> +		/* Set to RMII mode */
> +		if (ops->set_to_rmii)
> +			ops->set_to_rmii(pdata);

Same.

> +		break;
> +	default:
> +		debug("NO interface defined!\n");
> +		return -ENXIO;
> +	}
>
> 	return designware_eth_probe(dev);
> }
> @@ -289,6 +357,11 @@ const struct rk_gmac_ops rk3399_gmac_ops = {
> 	.set_to_rgmii = rk3399_gmac_set_to_rgmii,
> };
>
> +const struct rk_gmac_ops rv1108_gmac_ops = {
> +	.fix_mac_speed = rv1108_set_rmii_speed,
> +	.set_to_rmii = rv1108_gmac_set_to_rmii,
> +};
> +
> static const struct udevice_id rockchip_gmac_ids[] = {
> 	{ .compatible = "rockchip,rk3288-gmac",
> 	  .data = (ulong)&rk3288_gmac_ops },
> @@ -296,6 +369,8 @@ static const struct udevice_id rockchip_gmac_ids[] = {
> 	  .data = (ulong)&rk3368_gmac_ops },
> 	{ .compatible = "rockchip,rk3399-gmac",
> 	  .data = (ulong)&rk3399_gmac_ops },
> +	{ .compatible = "rockchip,rv1108-gmac",
> +	  .data = (ulong)&rv1108_gmac_ops },
> 	{ }
> };
>
>
diff mbox series

Patch

diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 586ccbf..22e3941 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -18,6 +18,7 @@ 
 #include <asm/arch/grf_rk3288.h>
 #include <asm/arch/grf_rk3368.h>
 #include <asm/arch/grf_rk3399.h>
+#include <asm/arch/grf_rv1108.h>
 #include <dm/pinctrl.h>
 #include <dt-bindings/clock/rk3288-cru.h>
 #include "designware.h"
@@ -37,6 +38,7 @@  struct gmac_rockchip_platdata {
 
 struct rk_gmac_ops {
 	int (*fix_mac_speed)(struct dw_eth_dev *priv);
+	void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata);
 	void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata);
 };
 
@@ -142,6 +144,41 @@  static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
+static int rv1108_set_rmii_speed(struct dw_eth_dev *priv)
+{
+	struct rv1108_grf *grf;
+	int clk, speed;
+	enum {
+		RV1108_GMAC_SPEED_MASK		= BIT(2),
+		RV1108_GMAC_SPEED_10M		= 0 << 2,
+		RV1108_GMAC_SPEED_100M		= 1 << 2,
+		RV1108_GMAC_CLK_SEL_MASK	= BIT(7),
+		RV1108_GMAC_CLK_SEL_2_5M	= 0 << 7,
+		RV1108_GMAC_CLK_SEL_25M		= 1 << 7,
+	};
+
+	switch (priv->phydev->speed) {
+	case 10:
+		clk = RV1108_GMAC_CLK_SEL_2_5M;
+		speed = RV1108_GMAC_SPEED_10M;
+		break;
+	case 100:
+		clk = RV1108_GMAC_CLK_SEL_25M;
+		speed = RV1108_GMAC_SPEED_100M;
+		break;
+	default:
+		debug("Unknown phy speed: %d\n", priv->phydev->speed);
+		return -EINVAL;
+	}
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	rk_clrsetreg(&grf->gmac_con0,
+		     RV1108_GMAC_CLK_SEL_MASK | RV1108_GMAC_SPEED_MASK,
+		     clk | speed);
+
+	return 0;
+}
+
 static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
 {
 	struct rk3288_grf *grf;
@@ -221,11 +258,28 @@  static void rk3399_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata)
 		     pdata->tx_delay << RK3399_CLK_TX_DL_CFG_GMAC_SHIFT);
 }
 
+static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata)
+{
+	struct rv1108_grf *grf;
+
+	enum {
+		RV1108_GMAC_PHY_INTF_SEL_MASK  = GENMASK(6, 4),
+		RV1108_GMAC_PHY_INTF_SEL_RMII  = 4 << 4,
+	};
+
+	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+	rk_clrsetreg(&grf->gmac_con0,
+		     RV1108_GMAC_PHY_INTF_SEL_MASK,
+		     RV1108_GMAC_PHY_INTF_SEL_RMII);
+}
+
 static int gmac_rockchip_probe(struct udevice *dev)
 {
 	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
 	struct rk_gmac_ops *ops =
 		(struct rk_gmac_ops *)dev_get_driver_data(dev);
+	struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
+	struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata;
 	struct clk clk;
 	int ret;
 
@@ -233,13 +287,27 @@  static int gmac_rockchip_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	/* Since mac_clk is fed by an external clock we can use 0 here */
-	ret = clk_set_rate(&clk, 0);
-	if (ret)
-		return ret;
-
-	/* Set to RGMII mode */
-	ops->set_to_rgmii(pdata);
+	switch (eth_pdata->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+		ret = clk_set_rate(&clk, 125000000);
+		if (IS_ERR_VALUE(ret))
+			return ret;
+		/* Set to RGMII mode */
+		if (ops->set_to_rgmii)
+			ops->set_to_rgmii(pdata);
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		ret = clk_set_rate(&clk, 50000000);
+		if (IS_ERR_VALUE(ret))
+			return ret;
+		/* Set to RMII mode */
+		if (ops->set_to_rmii)
+			ops->set_to_rmii(pdata);
+		break;
+	default:
+		debug("NO interface defined!\n");
+		return -ENXIO;
+	}
 
 	return designware_eth_probe(dev);
 }
@@ -289,6 +357,11 @@  const struct rk_gmac_ops rk3399_gmac_ops = {
 	.set_to_rgmii = rk3399_gmac_set_to_rgmii,
 };
 
+const struct rk_gmac_ops rv1108_gmac_ops = {
+	.fix_mac_speed = rv1108_set_rmii_speed,
+	.set_to_rmii = rv1108_gmac_set_to_rmii,
+};
+
 static const struct udevice_id rockchip_gmac_ids[] = {
 	{ .compatible = "rockchip,rk3288-gmac",
 	  .data = (ulong)&rk3288_gmac_ops },
@@ -296,6 +369,8 @@  static const struct udevice_id rockchip_gmac_ids[] = {
 	  .data = (ulong)&rk3368_gmac_ops },
 	{ .compatible = "rockchip,rk3399-gmac",
 	  .data = (ulong)&rk3399_gmac_ops },
+	{ .compatible = "rockchip,rv1108-gmac",
+	  .data = (ulong)&rv1108_gmac_ops },
 	{ }
 };