
On Thu, 21 Sep 2017, David Wu wrote:
The rv1108 mac only support rmii interface, so need to add the set_rmii() ops. Use the phy current interface to set rmii or rgmii ops.
Signed-off-by: David Wu david.wu@rock-chips.com Acked-by: Philipp Tomsich philipp.tomsich@theobroma-systems.com
See below for required changes.
drivers/net/gmac_rockchip.c | 67 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index 26f7a96..16b8c2b 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -37,6 +37,7 @@ struct gmac_rockchip_platdata { struct rk_gmac_ops { int (*fix_mac_speed)(struct gmac_rockchip_platdata *pdata, struct dw_eth_dev *priv);
- void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata); void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata);
};
@@ -177,6 +178,40 @@ static int rk3399_gmac_fix_mac_speed(struct gmac_rockchip_platdata *pdata, return 0; }
+static int rv1108_set_rmii_speed(struct gmac_rockchip_platdata *pdata,
struct dw_eth_dev *priv)
+{
- 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;
- }
- rk_clrsetreg(pdata->grf,
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_mac_grf *grf = (struct rk3288_mac_grf *)pdata->grf; @@ -292,6 +327,18 @@ 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) +{
- enum {
RV1108_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4),
RV1108_GMAC_PHY_INTF_SEL_RMII = 4 << 4,
- };
- rk_clrsetreg(pdata->grf,
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); @@ -325,8 +372,12 @@ static int gmac_rockchip_probe(struct udevice *dev) pdata->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF) + data->grf_offset;
- /* Set to RGMII mode */
- ops->set_to_rgmii(pdata);
- if (eth_pdata->phy_interface == PHY_INTERFACE_MODE_RGMII)
ops->set_to_rgmii(pdata);
- else if (eth_pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
ops->set_to_rmii(pdata);
If we have multiple functions and some are optional (e.g. the set_to_rmii is only ever set to anything other than NULL for the RV1108), we need to check whether this is a valid function pointer and emit an error otherwise. With the current code, we'll end up in a SEGV/SYNC-ABORT eventually...
Please protect dispatches through a function pointer, if these pointers could be NULL.
- else
debug("NO interface defined!\n");
Looks like a case for a switch statement.
return designware_eth_probe(dev); } @@ -392,6 +443,16 @@ const struct gmac_rockchip_driver_data rk3399_gmac_data = { .grf_offset = 0xc214, };
+const struct rk_gmac_ops rv1108_gmac_ops = {
- .fix_mac_speed = rv1108_set_rmii_speed,
- .set_to_rmii = rv1108_gmac_set_to_rmii,
+};
+const struct gmac_rockchip_driver_data rv1108_gmac_data = {
- .ops = &rv1108_gmac_ops,
- .grf_offset = 0x900,
+};
static const struct udevice_id rockchip_gmac_ids[] = { { .compatible = "rockchip,rk3288-gmac", .data = (ulong)&rk3288_gmac_data }, @@ -399,6 +460,8 @@ static const struct udevice_id rockchip_gmac_ids[] = { .data = (ulong)&rk3368_gmac_data }, { .compatible = "rockchip,rk3399-gmac", .data = (ulong)&rk3399_gmac_data },
- { .compatible = "rockchip,rv1108-gmac",
{ }.data = (ulong)&rv1108_gmac_data },
};