diff options
Diffstat (limited to 'drivers/net/dwc_eth_qos_rockchip.c')
-rw-r--r-- | drivers/net/dwc_eth_qos_rockchip.c | 292 |
1 files changed, 291 insertions, 1 deletions
diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c index f3a0f63003e..d646d3ebac8 100644 --- a/drivers/net/dwc_eth_qos_rockchip.c +++ b/drivers/net/dwc_eth_qos_rockchip.c @@ -50,6 +50,132 @@ struct rockchip_platform_data { (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) +#define RK3528_VO_GRF_GMAC_CON 0x0018 +#define RK3528_VPU_GRF_GMAC_CON5 0x0018 +#define RK3528_VPU_GRF_GMAC_CON6 0x001c + +#define RK3528_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) +#define RK3528_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) +#define RK3528_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) +#define RK3528_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) + +#define RK3528_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 8) +#define RK3528_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 0) + +#define RK3528_GMAC0_PHY_INTF_SEL_RMII GRF_BIT(1) +#define RK3528_GMAC1_PHY_INTF_SEL_RGMII GRF_CLR_BIT(8) +#define RK3528_GMAC1_PHY_INTF_SEL_RMII GRF_BIT(8) + +#define RK3528_GMAC1_CLK_SELECT_CRU GRF_CLR_BIT(12) +#define RK3528_GMAC1_CLK_SELECT_IO GRF_BIT(12) + +#define RK3528_GMAC0_CLK_RMII_DIV2 GRF_BIT(3) +#define RK3528_GMAC0_CLK_RMII_DIV20 GRF_CLR_BIT(3) +#define RK3528_GMAC1_CLK_RMII_DIV2 GRF_BIT(10) +#define RK3528_GMAC1_CLK_RMII_DIV20 GRF_CLR_BIT(10) + +#define RK3528_GMAC1_CLK_RGMII_DIV1 (GRF_CLR_BIT(11) | GRF_CLR_BIT(10)) +#define RK3528_GMAC1_CLK_RGMII_DIV5 (GRF_BIT(11) | GRF_BIT(10)) +#define RK3528_GMAC1_CLK_RGMII_DIV50 (GRF_BIT(11) | GRF_CLR_BIT(10)) + +#define RK3528_GMAC0_CLK_RMII_GATE GRF_BIT(2) +#define RK3528_GMAC0_CLK_RMII_NOGATE GRF_CLR_BIT(2) +#define RK3528_GMAC1_CLK_RMII_GATE GRF_BIT(9) +#define RK3528_GMAC1_CLK_RMII_NOGATE GRF_CLR_BIT(9) + +static int rk3528_set_to_rgmii(struct udevice *dev, + int tx_delay, int rx_delay) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + + regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5, + RK3528_GMAC1_PHY_INTF_SEL_RGMII); + + regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5, + DELAY_ENABLE(RK3528, tx_delay, rx_delay)); + + regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON6, + RK3528_GMAC_CLK_RX_DL_CFG(rx_delay) | + RK3528_GMAC_CLK_TX_DL_CFG(tx_delay)); + + return 0; +} + +static int rk3528_set_to_rmii(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + + if (data->id == 1) + regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5, + RK3528_GMAC1_PHY_INTF_SEL_RMII); + else + regmap_write(data->grf, RK3528_VO_GRF_GMAC_CON, + RK3528_GMAC0_PHY_INTF_SEL_RMII | + RK3528_GMAC0_CLK_RMII_DIV2); + + return 0; +} + +static int rk3528_set_gmac_speed(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 val, reg; + + switch (eqos->phy->speed) { + case SPEED_10: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = data->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 : + RK3528_GMAC0_CLK_RMII_DIV20; + else + val = RK3528_GMAC1_CLK_RGMII_DIV50; + break; + case SPEED_100: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = data->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 : + RK3528_GMAC0_CLK_RMII_DIV2; + else + val = RK3528_GMAC1_CLK_RGMII_DIV5; + break; + case SPEED_1000: + if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII) + val = RK3528_GMAC1_CLK_RGMII_DIV1; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + reg = data->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 : + RK3528_VO_GRF_GMAC_CON; + regmap_write(data->grf, reg, val); + + return 0; +} + +static void rk3528_set_clock_selection(struct udevice *dev, bool enable) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 val; + + if (data->id == 1) { + val = data->clock_input ? RK3528_GMAC1_CLK_SELECT_IO : + RK3528_GMAC1_CLK_SELECT_CRU; + val |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE : + RK3528_GMAC1_CLK_RMII_GATE; + regmap_write(data->grf, RK3528_VPU_GRF_GMAC_CON5, val); + } else { + val = enable ? RK3528_GMAC0_CLK_RMII_NOGATE : + RK3528_GMAC0_CLK_RMII_GATE; + regmap_write(data->grf, RK3528_VO_GRF_GMAC_CON, val); + } +} + #define RK3568_GRF_GMAC0_CON0 0x0380 #define RK3568_GRF_GMAC0_CON1 0x0384 #define RK3568_GRF_GMAC1_CON0 0x0388 @@ -134,6 +260,145 @@ static int rk3568_set_gmac_speed(struct udevice *dev) return 0; } +/* VCCIO0_1_3_IOC */ +#define RK3576_VCCIO0_1_3_IOC_CON2 0x6408 +#define RK3576_VCCIO0_1_3_IOC_CON3 0x640c +#define RK3576_VCCIO0_1_3_IOC_CON4 0x6410 +#define RK3576_VCCIO0_1_3_IOC_CON5 0x6414 + +#define RK3576_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) +#define RK3576_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) +#define RK3576_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7) +#define RK3576_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7) + +#define RK3576_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) +#define RK3576_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) + +/* SDGMAC_GRF */ +#define RK3576_GRF_GMAC_CON0 0x0020 +#define RK3576_GRF_GMAC_CON1 0x0024 + +#define RK3576_GMAC_RMII_MODE GRF_BIT(3) +#define RK3576_GMAC_RGMII_MODE GRF_CLR_BIT(3) + +#define RK3576_GMAC_CLK_SELECT_IO GRF_BIT(7) +#define RK3576_GMAC_CLK_SELECT_CRU GRF_CLR_BIT(7) + +#define RK3576_GMAC_CLK_RMII_DIV2 GRF_BIT(5) +#define RK3576_GMAC_CLK_RMII_DIV20 GRF_CLR_BIT(5) + +#define RK3576_GMAC_CLK_RGMII_DIV1 \ + (GRF_CLR_BIT(6) | GRF_CLR_BIT(5)) +#define RK3576_GMAC_CLK_RGMII_DIV5 \ + (GRF_BIT(6) | GRF_BIT(5)) +#define RK3576_GMAC_CLK_RGMII_DIV50 \ + (GRF_BIT(6) | GRF_CLR_BIT(5)) + +#define RK3576_GMAC_CLK_RMII_GATE GRF_BIT(4) +#define RK3576_GMAC_CLK_RMII_NOGATE GRF_CLR_BIT(4) + +static int rk3576_set_to_rgmii(struct udevice *dev, + int tx_delay, int rx_delay) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 offset_con; + + offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(data->grf, offset_con, RK3576_GMAC_RGMII_MODE); + + offset_con = data->id == 1 ? RK3576_VCCIO0_1_3_IOC_CON4 : + RK3576_VCCIO0_1_3_IOC_CON2; + + /* m0 && m1 delay enabled */ + regmap_write(data->php_grf, offset_con, + DELAY_ENABLE(RK3576, tx_delay, rx_delay)); + regmap_write(data->php_grf, offset_con + 0x4, + DELAY_ENABLE(RK3576, tx_delay, rx_delay)); + + /* m0 && m1 delay value */ + regmap_write(data->php_grf, offset_con, + RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) | + RK3576_GMAC_CLK_RX_DL_CFG(rx_delay)); + regmap_write(data->php_grf, offset_con + 0x4, + RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) | + RK3576_GMAC_CLK_RX_DL_CFG(rx_delay)); + + return 0; +} + +static int rk3576_set_to_rmii(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 offset_con; + + offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(data->grf, offset_con, RK3576_GMAC_RMII_MODE); + + return 0; +} + +static int rk3576_set_gmac_speed(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + u32 val = 0, offset_con; + + switch (eqos->phy->speed) { + case SPEED_10: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV20; + else + val = RK3576_GMAC_CLK_RGMII_DIV50; + break; + case SPEED_100: + if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RMII_DIV2; + else + val = RK3576_GMAC_CLK_RGMII_DIV5; + break; + case SPEED_1000: + if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII) + val = RK3576_GMAC_CLK_RGMII_DIV1; + else + return -EINVAL; + break; + default: + return -EINVAL; + } + + offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(data->grf, offset_con, val); + + return 0; +} + +static void rk3576_set_clock_selection(struct udevice *dev, bool enable) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct rockchip_platform_data *data = pdata->priv_pdata; + + u32 val = data->clock_input ? RK3576_GMAC_CLK_SELECT_IO : + RK3576_GMAC_CLK_SELECT_CRU; + u32 offset_con; + + val |= enable ? RK3576_GMAC_CLK_RMII_NOGATE : + RK3576_GMAC_CLK_RMII_GATE; + + offset_con = data->id == 1 ? RK3576_GRF_GMAC_CON1 : + RK3576_GRF_GMAC_CON0; + + regmap_write(data->grf, offset_con, val); +} + #define RK3588_DELAY_ENABLE(id, tx, rx) \ (((tx) ? RK3588_GMAC_TXCLK_DLY_ENABLE(id) : RK3588_GMAC_TXCLK_DLY_DISABLE(id)) | \ ((rx) ? RK3588_GMAC_RXCLK_DLY_ENABLE(id) : RK3588_GMAC_RXCLK_DLY_DISABLE(id))) @@ -270,6 +535,18 @@ static void rk3588_set_clock_selection(struct udevice *dev, bool enable) static const struct rk_gmac_ops rk_gmac_ops[] = { { + .compatible = "rockchip,rk3528-gmac", + .set_to_rgmii = rk3528_set_to_rgmii, + .set_to_rmii = rk3528_set_to_rmii, + .set_gmac_speed = rk3528_set_gmac_speed, + .set_clock_selection = rk3528_set_clock_selection, + .regs = { + 0xffbd0000, /* gmac0 */ + 0xffbe0000, /* gmac1 */ + 0x0, /* sentinel */ + }, + }, + { .compatible = "rockchip,rk3568-gmac", .set_to_rgmii = rk3568_set_to_rgmii, .set_to_rmii = rk3568_set_to_rmii, @@ -281,6 +558,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = { }, }, { + .compatible = "rockchip,rk3576-gmac", + .set_to_rgmii = rk3576_set_to_rgmii, + .set_to_rmii = rk3576_set_to_rmii, + .set_gmac_speed = rk3576_set_gmac_speed, + .set_clock_selection = rk3576_set_clock_selection, + .regs = { + 0x2a220000, /* gmac0 */ + 0x2a230000, /* gmac1 */ + 0x0, /* sentinel */ + }, + }, + { .compatible = "rockchip,rk3588-gmac", .set_to_rgmii = rk3588_set_to_rgmii, .set_to_rmii = rk3588_set_to_rmii, @@ -357,7 +646,8 @@ static int eqos_probe_resources_rk(struct udevice *dev) goto err_free; } - if (device_is_compatible(dev, "rockchip,rk3588-gmac")) { + if (device_is_compatible(dev, "rockchip,rk3588-gmac") || + device_is_compatible(dev, "rockchip,rk3576-gmac")) { data->php_grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf"); if (IS_ERR(data->php_grf)) { |