mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 19:24:01 -04:00
Merge branch 'stmmac-RK3568'
Ezequiel Garcia says: ==================== stmmmac: RK3568 Here's the third version of this patchset, taking the feedback from Heiko and Chen-Yu Tsai. Although this solution is a tad ugly as it hardcodes the register addresses, we believe it's the most robust approach. See: https://lore.kernel.org/netdev/CAGb2v67ZBR=XDFPeXQc429HNu_dbY__-KN50tvBW44fXMs78_w@mail.gmail.com/ This is tested on RK3566 EVB2 and seems to work well. Once the RK3568 devicetree lands upstream, we'll post patches to add network support for RK3566 and RK3568. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -24,6 +24,7 @@ select:
|
||||
- rockchip,rk3366-gmac
|
||||
- rockchip,rk3368-gmac
|
||||
- rockchip,rk3399-gmac
|
||||
- rockchip,rk3568-gmac
|
||||
- rockchip,rv1108-gmac
|
||||
required:
|
||||
- compatible
|
||||
@@ -33,18 +34,23 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- rockchip,px30-gmac
|
||||
- rockchip,rk3128-gmac
|
||||
- rockchip,rk3228-gmac
|
||||
- rockchip,rk3288-gmac
|
||||
- rockchip,rk3308-gmac
|
||||
- rockchip,rk3328-gmac
|
||||
- rockchip,rk3366-gmac
|
||||
- rockchip,rk3368-gmac
|
||||
- rockchip,rk3399-gmac
|
||||
- rockchip,rv1108-gmac
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-gmac
|
||||
- rockchip,rk3128-gmac
|
||||
- rockchip,rk3228-gmac
|
||||
- rockchip,rk3288-gmac
|
||||
- rockchip,rk3308-gmac
|
||||
- rockchip,rk3328-gmac
|
||||
- rockchip,rk3366-gmac
|
||||
- rockchip,rk3368-gmac
|
||||
- rockchip,rk3399-gmac
|
||||
- rockchip,rv1108-gmac
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3568-gmac
|
||||
- const: snps,dwmac-4.20a
|
||||
|
||||
clocks:
|
||||
minItems: 5
|
||||
|
||||
@@ -33,11 +33,13 @@ struct rk_gmac_ops {
|
||||
void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
|
||||
void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
|
||||
void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
|
||||
u32 regs[];
|
||||
};
|
||||
|
||||
struct rk_priv_data {
|
||||
struct platform_device *pdev;
|
||||
phy_interface_t phy_iface;
|
||||
int id;
|
||||
struct regulator *regulator;
|
||||
bool suspended;
|
||||
const struct rk_gmac_ops *ops;
|
||||
@@ -996,6 +998,107 @@ static const struct rk_gmac_ops rk3399_ops = {
|
||||
.set_rmii_speed = rk3399_set_rmii_speed,
|
||||
};
|
||||
|
||||
#define RK3568_GRF_GMAC0_CON0 0x0380
|
||||
#define RK3568_GRF_GMAC0_CON1 0x0384
|
||||
#define RK3568_GRF_GMAC1_CON0 0x0388
|
||||
#define RK3568_GRF_GMAC1_CON1 0x038c
|
||||
|
||||
/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
|
||||
#define RK3568_GMAC_PHY_INTF_SEL_RGMII \
|
||||
(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
|
||||
#define RK3568_GMAC_PHY_INTF_SEL_RMII \
|
||||
(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
|
||||
#define RK3568_GMAC_FLOW_CTRL GRF_BIT(3)
|
||||
#define RK3568_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
||||
#define RK3568_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
|
||||
#define RK3568_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1)
|
||||
#define RK3568_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
|
||||
#define RK3568_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
||||
|
||||
/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
|
||||
#define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
||||
#define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
||||
|
||||
static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
||||
int tx_delay, int rx_delay)
|
||||
{
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
u32 con0, con1;
|
||||
|
||||
if (IS_ERR(bsp_priv->grf)) {
|
||||
dev_err(dev, "Missing rockchip,grf property\n");
|
||||
return;
|
||||
}
|
||||
|
||||
con0 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON0 :
|
||||
RK3568_GRF_GMAC0_CON0;
|
||||
con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
|
||||
RK3568_GRF_GMAC0_CON1;
|
||||
|
||||
regmap_write(bsp_priv->grf, con0,
|
||||
RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
||||
RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
|
||||
|
||||
regmap_write(bsp_priv->grf, con1,
|
||||
RK3568_GMAC_PHY_INTF_SEL_RGMII |
|
||||
RK3568_GMAC_RXCLK_DLY_ENABLE |
|
||||
RK3568_GMAC_TXCLK_DLY_ENABLE);
|
||||
}
|
||||
|
||||
static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
|
||||
{
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
u32 con1;
|
||||
|
||||
if (IS_ERR(bsp_priv->grf)) {
|
||||
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 :
|
||||
RK3568_GRF_GMAC0_CON1;
|
||||
regmap_write(bsp_priv->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
|
||||
}
|
||||
|
||||
static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
{
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
||||
switch (speed) {
|
||||
case 10:
|
||||
rate = 2500000;
|
||||
break;
|
||||
case 100:
|
||||
rate = 25000000;
|
||||
break;
|
||||
case 1000:
|
||||
rate = 125000000;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unknown speed value for GMAC speed=%d", speed);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, rate);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n",
|
||||
__func__, rate, ret);
|
||||
}
|
||||
|
||||
static const struct rk_gmac_ops rk3568_ops = {
|
||||
.set_to_rgmii = rk3568_set_to_rgmii,
|
||||
.set_to_rmii = rk3568_set_to_rmii,
|
||||
.set_rgmii_speed = rk3568_set_gmac_speed,
|
||||
.set_rmii_speed = rk3568_set_gmac_speed,
|
||||
.regs = {
|
||||
0xfe2a0000, /* gmac0 */
|
||||
0xfe010000, /* gmac1 */
|
||||
0x0, /* sentinel */
|
||||
},
|
||||
};
|
||||
|
||||
#define RV1108_GRF_GMAC_CON0 0X0900
|
||||
|
||||
/* RV1108_GRF_GMAC_CON0 */
|
||||
@@ -1264,6 +1367,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
|
||||
{
|
||||
struct rk_priv_data *bsp_priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
const char *strings = NULL;
|
||||
int value;
|
||||
@@ -1275,6 +1379,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
|
||||
of_get_phy_mode(dev->of_node, &bsp_priv->phy_iface);
|
||||
bsp_priv->ops = ops;
|
||||
|
||||
/* Some SoCs have multiple MAC controllers, which need
|
||||
* to be distinguished.
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res) {
|
||||
int i = 0;
|
||||
|
||||
while (ops->regs[i]) {
|
||||
if (ops->regs[i] == res->start) {
|
||||
bsp_priv->id = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
|
||||
if (IS_ERR(bsp_priv->regulator)) {
|
||||
if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
|
||||
@@ -1342,11 +1462,36 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
|
||||
return bsp_priv;
|
||||
}
|
||||
|
||||
static int rk_gmac_check_ops(struct rk_priv_data *bsp_priv)
|
||||
{
|
||||
switch (bsp_priv->phy_iface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
if (!bsp_priv->ops->set_to_rgmii)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
if (!bsp_priv->ops->set_to_rmii)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
dev_err(&bsp_priv->pdev->dev,
|
||||
"unsupported interface %d", bsp_priv->phy_iface);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
|
||||
ret = rk_gmac_check_ops(bsp_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gmac_clk_enable(bsp_priv, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1417,10 +1562,12 @@ static void rk_fix_speed(void *priv, unsigned int speed)
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
|
||||
if (bsp_priv->ops->set_rgmii_speed)
|
||||
bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
|
||||
if (bsp_priv->ops->set_rmii_speed)
|
||||
bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
|
||||
@@ -1448,7 +1595,11 @@ static int rk_gmac_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(plat_dat))
|
||||
return PTR_ERR(plat_dat);
|
||||
|
||||
plat_dat->has_gmac = true;
|
||||
/* If the stmmac is not already selected as gmac4,
|
||||
* then make sure we fallback to gmac.
|
||||
*/
|
||||
if (!plat_dat->has_gmac4)
|
||||
plat_dat->has_gmac = true;
|
||||
plat_dat->fix_mac_speed = rk_fix_speed;
|
||||
|
||||
plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
|
||||
@@ -1530,6 +1681,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
|
||||
{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
|
||||
{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
|
||||
{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
|
||||
{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
|
||||
{ .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops },
|
||||
{ }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user