Commit 885e4056 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 5796254e 3bb3d6b1
...@@ -24,6 +24,7 @@ select: ...@@ -24,6 +24,7 @@ select:
- rockchip,rk3366-gmac - rockchip,rk3366-gmac
- rockchip,rk3368-gmac - rockchip,rk3368-gmac
- rockchip,rk3399-gmac - rockchip,rk3399-gmac
- rockchip,rk3568-gmac
- rockchip,rv1108-gmac - rockchip,rv1108-gmac
required: required:
- compatible - compatible
...@@ -33,7 +34,8 @@ allOf: ...@@ -33,7 +34,8 @@ allOf:
properties: properties:
compatible: compatible:
items: oneOf:
- items:
- enum: - enum:
- rockchip,px30-gmac - rockchip,px30-gmac
- rockchip,rk3128-gmac - rockchip,rk3128-gmac
...@@ -45,6 +47,10 @@ properties: ...@@ -45,6 +47,10 @@ properties:
- rockchip,rk3368-gmac - rockchip,rk3368-gmac
- rockchip,rk3399-gmac - rockchip,rk3399-gmac
- rockchip,rv1108-gmac - rockchip,rv1108-gmac
- items:
- enum:
- rockchip,rk3568-gmac
- const: snps,dwmac-4.20a
clocks: clocks:
minItems: 5 minItems: 5
......
...@@ -33,11 +33,13 @@ struct rk_gmac_ops { ...@@ -33,11 +33,13 @@ struct rk_gmac_ops {
void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); 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 (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
u32 regs[];
}; };
struct rk_priv_data { struct rk_priv_data {
struct platform_device *pdev; struct platform_device *pdev;
phy_interface_t phy_iface; phy_interface_t phy_iface;
int id;
struct regulator *regulator; struct regulator *regulator;
bool suspended; bool suspended;
const struct rk_gmac_ops *ops; const struct rk_gmac_ops *ops;
...@@ -996,6 +998,107 @@ static const struct rk_gmac_ops rk3399_ops = { ...@@ -996,6 +998,107 @@ static const struct rk_gmac_ops rk3399_ops = {
.set_rmii_speed = rk3399_set_rmii_speed, .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 #define RV1108_GRF_GMAC_CON0 0X0900
/* RV1108_GRF_GMAC_CON0 */ /* RV1108_GRF_GMAC_CON0 */
...@@ -1264,6 +1367,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, ...@@ -1264,6 +1367,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
{ {
struct rk_priv_data *bsp_priv; struct rk_priv_data *bsp_priv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res;
int ret; int ret;
const char *strings = NULL; const char *strings = NULL;
int value; int value;
...@@ -1275,6 +1379,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, ...@@ -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); of_get_phy_mode(dev->of_node, &bsp_priv->phy_iface);
bsp_priv->ops = ops; 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"); bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
if (IS_ERR(bsp_priv->regulator)) { if (IS_ERR(bsp_priv->regulator)) {
if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) { if (PTR_ERR(bsp_priv->regulator) == -EPROBE_DEFER) {
...@@ -1342,11 +1462,36 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, ...@@ -1342,11 +1462,36 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
return bsp_priv; 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) static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
{ {
int ret; int ret;
struct device *dev = &bsp_priv->pdev->dev; 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); ret = gmac_clk_enable(bsp_priv, true);
if (ret) if (ret)
return ret; return ret;
...@@ -1417,9 +1562,11 @@ static void rk_fix_speed(void *priv, unsigned int speed) ...@@ -1417,9 +1562,11 @@ static void rk_fix_speed(void *priv, unsigned int speed)
case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_TXID:
if (bsp_priv->ops->set_rgmii_speed)
bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
break; break;
case PHY_INTERFACE_MODE_RMII: case PHY_INTERFACE_MODE_RMII:
if (bsp_priv->ops->set_rmii_speed)
bsp_priv->ops->set_rmii_speed(bsp_priv, speed); bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
break; break;
default: default:
...@@ -1448,6 +1595,10 @@ static int rk_gmac_probe(struct platform_device *pdev) ...@@ -1448,6 +1595,10 @@ static int rk_gmac_probe(struct platform_device *pdev)
if (IS_ERR(plat_dat)) if (IS_ERR(plat_dat))
return PTR_ERR(plat_dat); return PTR_ERR(plat_dat);
/* 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->has_gmac = true;
plat_dat->fix_mac_speed = rk_fix_speed; plat_dat->fix_mac_speed = rk_fix_speed;
...@@ -1530,6 +1681,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = { ...@@ -1530,6 +1681,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
{ .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops },
{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops }, { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
{ .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops }, { .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops },
{ } { }
}; };
......
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