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:
- 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 },
{ }
};
......
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