The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Reviewed-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Michal Kubiak <michal.kubiak@intel.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1937 lines
55 KiB
C
1937 lines
55 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/**
|
|
* DOC: dwmac-rk.c - Rockchip RK3288 DWMAC specific glue layer
|
|
*
|
|
* Copyright (C) 2014 Chen-Zhi (Roger Chen)
|
|
*
|
|
* Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>
|
|
*/
|
|
|
|
#include <linux/stmmac.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/of_net.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/mfd/syscon.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/pm_runtime.h>
|
|
|
|
#include "stmmac_platform.h"
|
|
|
|
struct rk_priv_data;
|
|
struct rk_gmac_ops {
|
|
void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay);
|
|
void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
|
|
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_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
|
|
bool enable);
|
|
void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
|
|
bool regs_valid;
|
|
u32 regs[];
|
|
};
|
|
|
|
static const char * const rk_clocks[] = {
|
|
"aclk_mac", "pclk_mac", "mac_clk_tx", "clk_mac_speed",
|
|
};
|
|
|
|
static const char * const rk_rmii_clocks[] = {
|
|
"mac_clk_rx", "clk_mac_ref", "clk_mac_refout",
|
|
};
|
|
|
|
enum rk_clocks_index {
|
|
RK_ACLK_MAC = 0,
|
|
RK_PCLK_MAC,
|
|
RK_MAC_CLK_TX,
|
|
RK_CLK_MAC_SPEED,
|
|
RK_MAC_CLK_RX,
|
|
RK_CLK_MAC_REF,
|
|
RK_CLK_MAC_REFOUT,
|
|
};
|
|
|
|
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;
|
|
|
|
bool clk_enabled;
|
|
bool clock_input;
|
|
bool integrated_phy;
|
|
|
|
struct clk_bulk_data *clks;
|
|
int num_clks;
|
|
struct clk *clk_mac;
|
|
struct clk *clk_phy;
|
|
|
|
struct reset_control *phy_reset;
|
|
|
|
int tx_delay;
|
|
int rx_delay;
|
|
|
|
struct regmap *grf;
|
|
struct regmap *php_grf;
|
|
};
|
|
|
|
#define HIWORD_UPDATE(val, mask, shift) \
|
|
((val) << (shift) | (mask) << ((shift) + 16))
|
|
|
|
#define GRF_BIT(nr) (BIT(nr) | BIT(nr+16))
|
|
#define GRF_CLR_BIT(nr) (BIT(nr+16))
|
|
|
|
#define DELAY_ENABLE(soc, tx, rx) \
|
|
(((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
|
|
((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
|
|
|
|
#define PX30_GRF_GMAC_CON1 0x0904
|
|
|
|
/* PX30_GRF_GMAC_CON1 */
|
|
#define PX30_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | \
|
|
GRF_BIT(6))
|
|
#define PX30_GMAC_SPEED_10M GRF_CLR_BIT(2)
|
|
#define PX30_GMAC_SPEED_100M GRF_BIT(2)
|
|
|
|
static void px30_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
|
|
PX30_GMAC_PHY_INTF_SEL_RMII);
|
|
}
|
|
|
|
static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
int ret;
|
|
|
|
if (!clk_mac_speed) {
|
|
dev_err(dev, "%s: Missing clk_mac_speed clock\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
|
|
PX30_GMAC_SPEED_10M);
|
|
|
|
ret = clk_set_rate(clk_mac_speed, 2500000);
|
|
if (ret)
|
|
dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n",
|
|
__func__, ret);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
|
|
PX30_GMAC_SPEED_100M);
|
|
|
|
ret = clk_set_rate(clk_mac_speed, 25000000);
|
|
if (ret)
|
|
dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n",
|
|
__func__, ret);
|
|
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops px30_ops = {
|
|
.set_to_rmii = px30_set_to_rmii,
|
|
.set_rmii_speed = px30_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3128_GRF_MAC_CON0 0x0168
|
|
#define RK3128_GRF_MAC_CON1 0x016c
|
|
|
|
/* RK3128_GRF_MAC_CON0 */
|
|
#define RK3128_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
|
|
#define RK3128_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
|
|
#define RK3128_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
|
#define RK3128_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
|
#define RK3128_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
|
|
#define RK3128_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
/* RK3128_GRF_MAC_CON1 */
|
|
#define RK3128_GMAC_PHY_INTF_SEL_RGMII \
|
|
(GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
|
|
#define RK3128_GMAC_PHY_INTF_SEL_RMII \
|
|
(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8))
|
|
#define RK3128_GMAC_FLOW_CTRL GRF_BIT(9)
|
|
#define RK3128_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9)
|
|
#define RK3128_GMAC_SPEED_10M GRF_CLR_BIT(10)
|
|
#define RK3128_GMAC_SPEED_100M GRF_BIT(10)
|
|
#define RK3128_GMAC_RMII_CLK_25M GRF_BIT(11)
|
|
#define RK3128_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11)
|
|
#define RK3128_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
|
|
#define RK3128_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13))
|
|
#define RK3128_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13))
|
|
#define RK3128_GMAC_RMII_MODE GRF_BIT(14)
|
|
#define RK3128_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14)
|
|
|
|
static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3128_GMAC_RMII_MODE_CLR);
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON0,
|
|
DELAY_ENABLE(RK3128, tx_delay, rx_delay) |
|
|
RK3128_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3128_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_RMII_CLK_2_5M |
|
|
RK3128_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
|
|
RK3128_GMAC_RMII_CLK_25M |
|
|
RK3128_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3128_ops = {
|
|
.set_to_rgmii = rk3128_set_to_rgmii,
|
|
.set_to_rmii = rk3128_set_to_rmii,
|
|
.set_rgmii_speed = rk3128_set_rgmii_speed,
|
|
.set_rmii_speed = rk3128_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3228_GRF_MAC_CON0 0x0900
|
|
#define RK3228_GRF_MAC_CON1 0x0904
|
|
|
|
#define RK3228_GRF_CON_MUX 0x50
|
|
|
|
/* RK3228_GRF_MAC_CON0 */
|
|
#define RK3228_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
|
|
#define RK3228_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
/* RK3228_GRF_MAC_CON1 */
|
|
#define RK3228_GMAC_PHY_INTF_SEL_RGMII \
|
|
(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
|
|
#define RK3228_GMAC_PHY_INTF_SEL_RMII \
|
|
(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
|
|
#define RK3228_GMAC_FLOW_CTRL GRF_BIT(3)
|
|
#define RK3228_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
|
#define RK3228_GMAC_SPEED_10M GRF_CLR_BIT(2)
|
|
#define RK3228_GMAC_SPEED_100M GRF_BIT(2)
|
|
#define RK3228_GMAC_RMII_CLK_25M GRF_BIT(7)
|
|
#define RK3228_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7)
|
|
#define RK3228_GMAC_CLK_125M (GRF_CLR_BIT(8) | GRF_CLR_BIT(9))
|
|
#define RK3228_GMAC_CLK_25M (GRF_BIT(8) | GRF_BIT(9))
|
|
#define RK3228_GMAC_CLK_2_5M (GRF_CLR_BIT(8) | GRF_BIT(9))
|
|
#define RK3228_GMAC_RMII_MODE GRF_BIT(10)
|
|
#define RK3228_GMAC_RMII_MODE_CLR GRF_CLR_BIT(10)
|
|
#define RK3228_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
|
|
#define RK3228_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
|
#define RK3228_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
|
|
#define RK3228_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1)
|
|
|
|
/* RK3228_GRF_COM_MUX */
|
|
#define RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY GRF_BIT(15)
|
|
|
|
static void rk3228_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3228_GMAC_RMII_MODE_CLR |
|
|
DELAY_ENABLE(RK3228, tx_delay, rx_delay));
|
|
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0,
|
|
RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3228_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_PHY_INTF_SEL_RMII |
|
|
RK3228_GMAC_RMII_MODE);
|
|
|
|
/* set MAC to RMII mode */
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11));
|
|
}
|
|
|
|
static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_RMII_CLK_2_5M |
|
|
RK3228_GMAC_SPEED_10M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1,
|
|
RK3228_GMAC_RMII_CLK_25M |
|
|
RK3228_GMAC_SPEED_100M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv)
|
|
{
|
|
regmap_write(priv->grf, RK3228_GRF_CON_MUX,
|
|
RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY);
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3228_ops = {
|
|
.set_to_rgmii = rk3228_set_to_rgmii,
|
|
.set_to_rmii = rk3228_set_to_rmii,
|
|
.set_rgmii_speed = rk3228_set_rgmii_speed,
|
|
.set_rmii_speed = rk3228_set_rmii_speed,
|
|
.integrated_phy_powerup = rk3228_integrated_phy_powerup,
|
|
};
|
|
|
|
#define RK3288_GRF_SOC_CON1 0x0248
|
|
#define RK3288_GRF_SOC_CON3 0x0250
|
|
|
|
/*RK3288_GRF_SOC_CON1*/
|
|
#define RK3288_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(6) | GRF_CLR_BIT(7) | \
|
|
GRF_CLR_BIT(8))
|
|
#define RK3288_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
|
|
GRF_BIT(8))
|
|
#define RK3288_GMAC_FLOW_CTRL GRF_BIT(9)
|
|
#define RK3288_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9)
|
|
#define RK3288_GMAC_SPEED_10M GRF_CLR_BIT(10)
|
|
#define RK3288_GMAC_SPEED_100M GRF_BIT(10)
|
|
#define RK3288_GMAC_RMII_CLK_25M GRF_BIT(11)
|
|
#define RK3288_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11)
|
|
#define RK3288_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
|
|
#define RK3288_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13))
|
|
#define RK3288_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13))
|
|
#define RK3288_GMAC_RMII_MODE GRF_BIT(14)
|
|
#define RK3288_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14)
|
|
|
|
/*RK3288_GRF_SOC_CON3*/
|
|
#define RK3288_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
|
|
#define RK3288_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
|
|
#define RK3288_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
|
#define RK3288_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
|
#define RK3288_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
|
|
#define RK3288_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3288_GMAC_RMII_MODE_CLR);
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
|
|
DELAY_ENABLE(RK3288, tx_delay, rx_delay) |
|
|
RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_RMII_CLK_2_5M |
|
|
RK3288_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
|
|
RK3288_GMAC_RMII_CLK_25M |
|
|
RK3288_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3288_ops = {
|
|
.set_to_rgmii = rk3288_set_to_rgmii,
|
|
.set_to_rmii = rk3288_set_to_rmii,
|
|
.set_rgmii_speed = rk3288_set_rgmii_speed,
|
|
.set_rmii_speed = rk3288_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3308_GRF_MAC_CON0 0x04a0
|
|
|
|
/* RK3308_GRF_MAC_CON0 */
|
|
#define RK3308_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(2) | GRF_CLR_BIT(3) | \
|
|
GRF_BIT(4))
|
|
#define RK3308_GMAC_FLOW_CTRL GRF_BIT(3)
|
|
#define RK3308_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
|
#define RK3308_GMAC_SPEED_10M GRF_CLR_BIT(0)
|
|
#define RK3308_GMAC_SPEED_100M GRF_BIT(0)
|
|
|
|
static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
|
|
RK3308_GMAC_PHY_INTF_SEL_RMII);
|
|
}
|
|
|
|
static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
|
|
RK3308_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0,
|
|
RK3308_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3308_ops = {
|
|
.set_to_rmii = rk3308_set_to_rmii,
|
|
.set_rmii_speed = rk3308_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3328_GRF_MAC_CON0 0x0900
|
|
#define RK3328_GRF_MAC_CON1 0x0904
|
|
#define RK3328_GRF_MAC_CON2 0x0908
|
|
#define RK3328_GRF_MACPHY_CON1 0xb04
|
|
|
|
/* RK3328_GRF_MAC_CON0 */
|
|
#define RK3328_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
|
|
#define RK3328_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
/* RK3328_GRF_MAC_CON1 */
|
|
#define RK3328_GMAC_PHY_INTF_SEL_RGMII \
|
|
(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
|
|
#define RK3328_GMAC_PHY_INTF_SEL_RMII \
|
|
(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
|
|
#define RK3328_GMAC_FLOW_CTRL GRF_BIT(3)
|
|
#define RK3328_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
|
#define RK3328_GMAC_SPEED_10M GRF_CLR_BIT(2)
|
|
#define RK3328_GMAC_SPEED_100M GRF_BIT(2)
|
|
#define RK3328_GMAC_RMII_CLK_25M GRF_BIT(7)
|
|
#define RK3328_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7)
|
|
#define RK3328_GMAC_CLK_125M (GRF_CLR_BIT(11) | GRF_CLR_BIT(12))
|
|
#define RK3328_GMAC_CLK_25M (GRF_BIT(11) | GRF_BIT(12))
|
|
#define RK3328_GMAC_CLK_2_5M (GRF_CLR_BIT(11) | GRF_BIT(12))
|
|
#define RK3328_GMAC_RMII_MODE GRF_BIT(9)
|
|
#define RK3328_GMAC_RMII_MODE_CLR GRF_CLR_BIT(9)
|
|
#define RK3328_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
|
|
#define RK3328_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
|
#define RK3328_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
|
|
#define RK3328_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
|
|
|
/* RK3328_GRF_MACPHY_CON1 */
|
|
#define RK3328_MACPHY_RMII_MODE GRF_BIT(9)
|
|
|
|
static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
|
|
RK3328_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3328_GMAC_RMII_MODE_CLR |
|
|
RK3328_GMAC_RXCLK_DLY_ENABLE |
|
|
RK3328_GMAC_TXCLK_DLY_ENABLE);
|
|
|
|
regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0,
|
|
RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3328_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
unsigned int reg;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
|
|
RK3328_GRF_MAC_CON1;
|
|
|
|
regmap_write(bsp_priv->grf, reg,
|
|
RK3328_GMAC_PHY_INTF_SEL_RMII |
|
|
RK3328_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
|
|
RK3328_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
|
|
RK3328_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1,
|
|
RK3328_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
unsigned int reg;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 :
|
|
RK3328_GRF_MAC_CON1;
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, reg,
|
|
RK3328_GMAC_RMII_CLK_2_5M |
|
|
RK3328_GMAC_SPEED_10M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, reg,
|
|
RK3328_GMAC_RMII_CLK_25M |
|
|
RK3328_GMAC_SPEED_100M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv)
|
|
{
|
|
regmap_write(priv->grf, RK3328_GRF_MACPHY_CON1,
|
|
RK3328_MACPHY_RMII_MODE);
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3328_ops = {
|
|
.set_to_rgmii = rk3328_set_to_rgmii,
|
|
.set_to_rmii = rk3328_set_to_rmii,
|
|
.set_rgmii_speed = rk3328_set_rgmii_speed,
|
|
.set_rmii_speed = rk3328_set_rmii_speed,
|
|
.integrated_phy_powerup = rk3328_integrated_phy_powerup,
|
|
};
|
|
|
|
#define RK3366_GRF_SOC_CON6 0x0418
|
|
#define RK3366_GRF_SOC_CON7 0x041c
|
|
|
|
/* RK3366_GRF_SOC_CON6 */
|
|
#define RK3366_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_CLR_BIT(11))
|
|
#define RK3366_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_BIT(11))
|
|
#define RK3366_GMAC_FLOW_CTRL GRF_BIT(8)
|
|
#define RK3366_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8)
|
|
#define RK3366_GMAC_SPEED_10M GRF_CLR_BIT(7)
|
|
#define RK3366_GMAC_SPEED_100M GRF_BIT(7)
|
|
#define RK3366_GMAC_RMII_CLK_25M GRF_BIT(3)
|
|
#define RK3366_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3)
|
|
#define RK3366_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
|
|
#define RK3366_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5))
|
|
#define RK3366_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5))
|
|
#define RK3366_GMAC_RMII_MODE GRF_BIT(6)
|
|
#define RK3366_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6)
|
|
|
|
/* RK3366_GRF_SOC_CON7 */
|
|
#define RK3366_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
|
|
#define RK3366_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
|
|
#define RK3366_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
|
#define RK3366_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
|
#define RK3366_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
|
#define RK3366_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
static void rk3366_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3366_GMAC_RMII_MODE_CLR);
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7,
|
|
DELAY_ENABLE(RK3366, tx_delay, rx_delay) |
|
|
RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3366_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_RMII_CLK_2_5M |
|
|
RK3366_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6,
|
|
RK3366_GMAC_RMII_CLK_25M |
|
|
RK3366_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3366_ops = {
|
|
.set_to_rgmii = rk3366_set_to_rgmii,
|
|
.set_to_rmii = rk3366_set_to_rmii,
|
|
.set_rgmii_speed = rk3366_set_rgmii_speed,
|
|
.set_rmii_speed = rk3366_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3368_GRF_SOC_CON15 0x043c
|
|
#define RK3368_GRF_SOC_CON16 0x0440
|
|
|
|
/* RK3368_GRF_SOC_CON15 */
|
|
#define RK3368_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_CLR_BIT(11))
|
|
#define RK3368_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_BIT(11))
|
|
#define RK3368_GMAC_FLOW_CTRL GRF_BIT(8)
|
|
#define RK3368_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8)
|
|
#define RK3368_GMAC_SPEED_10M GRF_CLR_BIT(7)
|
|
#define RK3368_GMAC_SPEED_100M GRF_BIT(7)
|
|
#define RK3368_GMAC_RMII_CLK_25M GRF_BIT(3)
|
|
#define RK3368_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3)
|
|
#define RK3368_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
|
|
#define RK3368_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5))
|
|
#define RK3368_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5))
|
|
#define RK3368_GMAC_RMII_MODE GRF_BIT(6)
|
|
#define RK3368_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6)
|
|
|
|
/* RK3368_GRF_SOC_CON16 */
|
|
#define RK3368_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
|
|
#define RK3368_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
|
|
#define RK3368_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
|
#define RK3368_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
|
#define RK3368_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
|
#define RK3368_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3368_GMAC_RMII_MODE_CLR);
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
|
|
DELAY_ENABLE(RK3368, tx_delay, rx_delay) |
|
|
RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_RMII_CLK_2_5M |
|
|
RK3368_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
|
|
RK3368_GMAC_RMII_CLK_25M |
|
|
RK3368_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3368_ops = {
|
|
.set_to_rgmii = rk3368_set_to_rgmii,
|
|
.set_to_rmii = rk3368_set_to_rmii,
|
|
.set_rgmii_speed = rk3368_set_rgmii_speed,
|
|
.set_rmii_speed = rk3368_set_rmii_speed,
|
|
};
|
|
|
|
#define RK3399_GRF_SOC_CON5 0xc214
|
|
#define RK3399_GRF_SOC_CON6 0xc218
|
|
|
|
/* RK3399_GRF_SOC_CON5 */
|
|
#define RK3399_GMAC_PHY_INTF_SEL_RGMII (GRF_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_CLR_BIT(11))
|
|
#define RK3399_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
|
|
GRF_BIT(11))
|
|
#define RK3399_GMAC_FLOW_CTRL GRF_BIT(8)
|
|
#define RK3399_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(8)
|
|
#define RK3399_GMAC_SPEED_10M GRF_CLR_BIT(7)
|
|
#define RK3399_GMAC_SPEED_100M GRF_BIT(7)
|
|
#define RK3399_GMAC_RMII_CLK_25M GRF_BIT(3)
|
|
#define RK3399_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(3)
|
|
#define RK3399_GMAC_CLK_125M (GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
|
|
#define RK3399_GMAC_CLK_25M (GRF_BIT(4) | GRF_BIT(5))
|
|
#define RK3399_GMAC_CLK_2_5M (GRF_CLR_BIT(4) | GRF_BIT(5))
|
|
#define RK3399_GMAC_RMII_MODE GRF_BIT(6)
|
|
#define RK3399_GMAC_RMII_MODE_CLR GRF_CLR_BIT(6)
|
|
|
|
/* RK3399_GRF_SOC_CON6 */
|
|
#define RK3399_GMAC_TXCLK_DLY_ENABLE GRF_BIT(7)
|
|
#define RK3399_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(7)
|
|
#define RK3399_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
|
|
#define RK3399_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
|
|
#define RK3399_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
|
#define RK3399_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
static void rk3399_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_PHY_INTF_SEL_RGMII |
|
|
RK3399_GMAC_RMII_MODE_CLR);
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6,
|
|
DELAY_ENABLE(RK3399, tx_delay, rx_delay) |
|
|
RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3399_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE);
|
|
}
|
|
|
|
static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10)
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_CLK_2_5M);
|
|
else if (speed == 100)
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_CLK_25M);
|
|
else if (speed == 1000)
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_CLK_125M);
|
|
else
|
|
dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
|
|
}
|
|
|
|
static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_RMII_CLK_2_5M |
|
|
RK3399_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5,
|
|
RK3399_GMAC_RMII_CLK_25M |
|
|
RK3399_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3399_ops = {
|
|
.set_to_rgmii = rk3399_set_to_rgmii,
|
|
.set_to_rmii = rk3399_set_to_rmii,
|
|
.set_rgmii_speed = rk3399_set_rgmii_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 clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
|
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(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_valid = true,
|
|
.regs = {
|
|
0xfe2a0000, /* gmac0 */
|
|
0xfe010000, /* gmac1 */
|
|
0x0, /* sentinel */
|
|
},
|
|
};
|
|
|
|
/* sys_grf */
|
|
#define RK3588_GRF_GMAC_CON7 0X031c
|
|
#define RK3588_GRF_GMAC_CON8 0X0320
|
|
#define RK3588_GRF_GMAC_CON9 0X0324
|
|
|
|
#define RK3588_GMAC_RXCLK_DLY_ENABLE(id) GRF_BIT(2 * (id) + 3)
|
|
#define RK3588_GMAC_RXCLK_DLY_DISABLE(id) GRF_CLR_BIT(2 * (id) + 3)
|
|
#define RK3588_GMAC_TXCLK_DLY_ENABLE(id) GRF_BIT(2 * (id) + 2)
|
|
#define RK3588_GMAC_TXCLK_DLY_DISABLE(id) GRF_CLR_BIT(2 * (id) + 2)
|
|
|
|
#define RK3588_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 8)
|
|
#define RK3588_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 0)
|
|
|
|
/* php_grf */
|
|
#define RK3588_GRF_GMAC_CON0 0X0008
|
|
#define RK3588_GRF_CLK_CON1 0X0070
|
|
|
|
#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id) \
|
|
(GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + (id) * 6))
|
|
#define RK3588_GMAC_PHY_INTF_SEL_RMII(id) \
|
|
(GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + (id) * 6))
|
|
|
|
#define RK3588_GMAC_CLK_RMII_MODE(id) GRF_BIT(5 * (id))
|
|
#define RK3588_GMAC_CLK_RGMII_MODE(id) GRF_CLR_BIT(5 * (id))
|
|
|
|
#define RK3588_GMAC_CLK_SELET_CRU(id) GRF_BIT(5 * (id) + 4)
|
|
#define RK3588_GMAC_CLK_SELET_IO(id) GRF_CLR_BIT(5 * (id) + 4)
|
|
|
|
#define RK3588_GMA_CLK_RMII_DIV2(id) GRF_BIT(5 * (id) + 2)
|
|
#define RK3588_GMA_CLK_RMII_DIV20(id) GRF_CLR_BIT(5 * (id) + 2)
|
|
|
|
#define RK3588_GMAC_CLK_RGMII_DIV1(id) \
|
|
(GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3))
|
|
#define RK3588_GMAC_CLK_RGMII_DIV5(id) \
|
|
(GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
|
|
#define RK3588_GMAC_CLK_RGMII_DIV50(id) \
|
|
(GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
|
|
|
|
#define RK3588_GMAC_CLK_RMII_GATE(id) GRF_BIT(5 * (id) + 1)
|
|
#define RK3588_GMAC_CLK_RMII_NOGATE(id) GRF_CLR_BIT(5 * (id) + 1)
|
|
|
|
static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
u32 offset_con, id = bsp_priv->id;
|
|
|
|
if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
|
|
dev_err(dev, "Missing rockchip,grf or rockchip,php_grf property\n");
|
|
return;
|
|
}
|
|
|
|
offset_con = bsp_priv->id == 1 ? RK3588_GRF_GMAC_CON9 :
|
|
RK3588_GRF_GMAC_CON8;
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
|
|
RK3588_GMAC_PHY_INTF_SEL_RGMII(id));
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1,
|
|
RK3588_GMAC_CLK_RGMII_MODE(id));
|
|
|
|
regmap_write(bsp_priv->grf, RK3588_GRF_GMAC_CON7,
|
|
RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
|
|
RK3588_GMAC_TXCLK_DLY_ENABLE(id));
|
|
|
|
regmap_write(bsp_priv->grf, offset_con,
|
|
RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
|
|
RK3588_GMAC_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rk3588_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->php_grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,php_grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
|
|
RK3588_GMAC_PHY_INTF_SEL_RMII(bsp_priv->id));
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1,
|
|
RK3588_GMAC_CLK_RMII_MODE(bsp_priv->id));
|
|
}
|
|
|
|
static void rk3588_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
unsigned int val = 0, id = bsp_priv->id;
|
|
|
|
switch (speed) {
|
|
case 10:
|
|
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
|
|
val = RK3588_GMA_CLK_RMII_DIV20(id);
|
|
else
|
|
val = RK3588_GMAC_CLK_RGMII_DIV50(id);
|
|
break;
|
|
case 100:
|
|
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
|
|
val = RK3588_GMA_CLK_RMII_DIV2(id);
|
|
else
|
|
val = RK3588_GMAC_CLK_RGMII_DIV5(id);
|
|
break;
|
|
case 1000:
|
|
if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII)
|
|
val = RK3588_GMAC_CLK_RGMII_DIV1(id);
|
|
else
|
|
goto err;
|
|
break;
|
|
default:
|
|
goto err;
|
|
}
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1, val);
|
|
|
|
return;
|
|
err:
|
|
dev_err(dev, "unknown speed value for GMAC speed=%d", speed);
|
|
}
|
|
|
|
static void rk3588_set_clock_selection(struct rk_priv_data *bsp_priv, bool input,
|
|
bool enable)
|
|
{
|
|
unsigned int val = input ? RK3588_GMAC_CLK_SELET_IO(bsp_priv->id) :
|
|
RK3588_GMAC_CLK_SELET_CRU(bsp_priv->id);
|
|
|
|
val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(bsp_priv->id) :
|
|
RK3588_GMAC_CLK_RMII_GATE(bsp_priv->id);
|
|
|
|
regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1, val);
|
|
}
|
|
|
|
static const struct rk_gmac_ops rk3588_ops = {
|
|
.set_to_rgmii = rk3588_set_to_rgmii,
|
|
.set_to_rmii = rk3588_set_to_rmii,
|
|
.set_rgmii_speed = rk3588_set_gmac_speed,
|
|
.set_rmii_speed = rk3588_set_gmac_speed,
|
|
.set_clock_selection = rk3588_set_clock_selection,
|
|
.regs_valid = true,
|
|
.regs = {
|
|
0xfe1b0000, /* gmac0 */
|
|
0xfe1c0000, /* gmac1 */
|
|
0x0, /* sentinel */
|
|
},
|
|
};
|
|
|
|
#define RV1108_GRF_GMAC_CON0 0X0900
|
|
|
|
/* RV1108_GRF_GMAC_CON0 */
|
|
#define RV1108_GMAC_PHY_INTF_SEL_RMII (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | \
|
|
GRF_BIT(6))
|
|
#define RV1108_GMAC_FLOW_CTRL GRF_BIT(3)
|
|
#define RV1108_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
|
|
#define RV1108_GMAC_SPEED_10M GRF_CLR_BIT(2)
|
|
#define RV1108_GMAC_SPEED_100M GRF_BIT(2)
|
|
#define RV1108_GMAC_RMII_CLK_25M GRF_BIT(7)
|
|
#define RV1108_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7)
|
|
|
|
static void rv1108_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
|
|
RV1108_GMAC_PHY_INTF_SEL_RMII);
|
|
}
|
|
|
|
static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (speed == 10) {
|
|
regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
|
|
RV1108_GMAC_RMII_CLK_2_5M |
|
|
RV1108_GMAC_SPEED_10M);
|
|
} else if (speed == 100) {
|
|
regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0,
|
|
RV1108_GMAC_RMII_CLK_25M |
|
|
RV1108_GMAC_SPEED_100M);
|
|
} else {
|
|
dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
|
|
}
|
|
}
|
|
|
|
static const struct rk_gmac_ops rv1108_ops = {
|
|
.set_to_rmii = rv1108_set_to_rmii,
|
|
.set_rmii_speed = rv1108_set_rmii_speed,
|
|
};
|
|
|
|
#define RV1126_GRF_GMAC_CON0 0X0070
|
|
#define RV1126_GRF_GMAC_CON1 0X0074
|
|
#define RV1126_GRF_GMAC_CON2 0X0078
|
|
|
|
/* RV1126_GRF_GMAC_CON0 */
|
|
#define RV1126_GMAC_PHY_INTF_SEL_RGMII \
|
|
(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
|
|
#define RV1126_GMAC_PHY_INTF_SEL_RMII \
|
|
(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
|
|
#define RV1126_GMAC_FLOW_CTRL GRF_BIT(7)
|
|
#define RV1126_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(7)
|
|
#define RV1126_GMAC_M0_RXCLK_DLY_ENABLE GRF_BIT(1)
|
|
#define RV1126_GMAC_M0_RXCLK_DLY_DISABLE GRF_CLR_BIT(1)
|
|
#define RV1126_GMAC_M0_TXCLK_DLY_ENABLE GRF_BIT(0)
|
|
#define RV1126_GMAC_M0_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
|
|
#define RV1126_GMAC_M1_RXCLK_DLY_ENABLE GRF_BIT(3)
|
|
#define RV1126_GMAC_M1_RXCLK_DLY_DISABLE GRF_CLR_BIT(3)
|
|
#define RV1126_GMAC_M1_TXCLK_DLY_ENABLE GRF_BIT(2)
|
|
#define RV1126_GMAC_M1_TXCLK_DLY_DISABLE GRF_CLR_BIT(2)
|
|
|
|
/* RV1126_GRF_GMAC_CON1 */
|
|
#define RV1126_GMAC_M0_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
|
#define RV1126_GMAC_M0_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
/* RV1126_GRF_GMAC_CON2 */
|
|
#define RV1126_GMAC_M1_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
|
|
#define RV1126_GMAC_M1_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
|
|
|
|
static void rv1126_set_to_rgmii(struct rk_priv_data *bsp_priv,
|
|
int tx_delay, int rx_delay)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "Missing rockchip,grf property\n");
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
|
|
RV1126_GMAC_PHY_INTF_SEL_RGMII |
|
|
RV1126_GMAC_M0_RXCLK_DLY_ENABLE |
|
|
RV1126_GMAC_M0_TXCLK_DLY_ENABLE |
|
|
RV1126_GMAC_M1_RXCLK_DLY_ENABLE |
|
|
RV1126_GMAC_M1_TXCLK_DLY_ENABLE);
|
|
|
|
regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON1,
|
|
RV1126_GMAC_M0_CLK_RX_DL_CFG(rx_delay) |
|
|
RV1126_GMAC_M0_CLK_TX_DL_CFG(tx_delay));
|
|
|
|
regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON2,
|
|
RV1126_GMAC_M1_CLK_RX_DL_CFG(rx_delay) |
|
|
RV1126_GMAC_M1_CLK_TX_DL_CFG(tx_delay));
|
|
}
|
|
|
|
static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv)
|
|
{
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (IS_ERR(bsp_priv->grf)) {
|
|
dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
|
|
return;
|
|
}
|
|
|
|
regmap_write(bsp_priv->grf, RV1126_GRF_GMAC_CON0,
|
|
RV1126_GMAC_PHY_INTF_SEL_RMII);
|
|
}
|
|
|
|
static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
|
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 RGMII speed=%d", speed);
|
|
return;
|
|
}
|
|
|
|
ret = clk_set_rate(clk_mac_speed, rate);
|
|
if (ret)
|
|
dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n",
|
|
__func__, rate, ret);
|
|
}
|
|
|
|
static void rv1126_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
|
{
|
|
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
unsigned long rate;
|
|
int ret;
|
|
|
|
switch (speed) {
|
|
case 10:
|
|
rate = 2500000;
|
|
break;
|
|
case 100:
|
|
rate = 25000000;
|
|
break;
|
|
default:
|
|
dev_err(dev, "unknown speed value for RGMII speed=%d", speed);
|
|
return;
|
|
}
|
|
|
|
ret = clk_set_rate(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 rv1126_ops = {
|
|
.set_to_rgmii = rv1126_set_to_rgmii,
|
|
.set_to_rmii = rv1126_set_to_rmii,
|
|
.set_rgmii_speed = rv1126_set_rgmii_speed,
|
|
.set_rmii_speed = rv1126_set_rmii_speed,
|
|
};
|
|
|
|
#define RK_GRF_MACPHY_CON0 0xb00
|
|
#define RK_GRF_MACPHY_CON1 0xb04
|
|
#define RK_GRF_MACPHY_CON2 0xb08
|
|
#define RK_GRF_MACPHY_CON3 0xb0c
|
|
|
|
#define RK_MACPHY_ENABLE GRF_BIT(0)
|
|
#define RK_MACPHY_DISABLE GRF_CLR_BIT(0)
|
|
#define RK_MACPHY_CFG_CLK_50M GRF_BIT(14)
|
|
#define RK_GMAC2PHY_RMII_MODE (GRF_BIT(6) | GRF_CLR_BIT(7))
|
|
#define RK_GRF_CON2_MACPHY_ID HIWORD_UPDATE(0x1234, 0xffff, 0)
|
|
#define RK_GRF_CON3_MACPHY_ID HIWORD_UPDATE(0x35, 0x3f, 0)
|
|
|
|
static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
|
|
{
|
|
if (priv->ops->integrated_phy_powerup)
|
|
priv->ops->integrated_phy_powerup(priv);
|
|
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);
|
|
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);
|
|
|
|
if (priv->phy_reset) {
|
|
/* PHY needs to be disabled before trying to reset it */
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
|
|
if (priv->phy_reset)
|
|
reset_control_assert(priv->phy_reset);
|
|
usleep_range(10, 20);
|
|
if (priv->phy_reset)
|
|
reset_control_deassert(priv->phy_reset);
|
|
usleep_range(10, 20);
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
|
|
msleep(30);
|
|
}
|
|
}
|
|
|
|
static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
|
|
{
|
|
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
|
|
if (priv->phy_reset)
|
|
reset_control_assert(priv->phy_reset);
|
|
}
|
|
|
|
static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
|
|
{
|
|
struct rk_priv_data *bsp_priv = plat->bsp_priv;
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
int phy_iface = bsp_priv->phy_iface;
|
|
int i, j, ret;
|
|
|
|
bsp_priv->clk_enabled = false;
|
|
|
|
bsp_priv->num_clks = ARRAY_SIZE(rk_clocks);
|
|
if (phy_iface == PHY_INTERFACE_MODE_RMII)
|
|
bsp_priv->num_clks += ARRAY_SIZE(rk_rmii_clocks);
|
|
|
|
bsp_priv->clks = devm_kcalloc(dev, bsp_priv->num_clks,
|
|
sizeof(*bsp_priv->clks), GFP_KERNEL);
|
|
if (!bsp_priv->clks)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(rk_clocks); i++)
|
|
bsp_priv->clks[i].id = rk_clocks[i];
|
|
|
|
if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
|
for (j = 0; j < ARRAY_SIZE(rk_rmii_clocks); j++)
|
|
bsp_priv->clks[i++].id = rk_rmii_clocks[j];
|
|
}
|
|
|
|
ret = devm_clk_bulk_get_optional(dev, bsp_priv->num_clks,
|
|
bsp_priv->clks);
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "Failed to get clocks\n");
|
|
|
|
/* "stmmaceth" will be enabled by the core */
|
|
bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
|
|
ret = PTR_ERR_OR_ZERO(bsp_priv->clk_mac);
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "Cannot get stmmaceth clock\n");
|
|
|
|
if (bsp_priv->clock_input) {
|
|
dev_info(dev, "clock input from PHY\n");
|
|
} else if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
|
clk_set_rate(bsp_priv->clk_mac, 50000000);
|
|
}
|
|
|
|
if (plat->phy_node && bsp_priv->integrated_phy) {
|
|
bsp_priv->clk_phy = of_clk_get(plat->phy_node, 0);
|
|
ret = PTR_ERR_OR_ZERO(bsp_priv->clk_phy);
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "Cannot get PHY clock\n");
|
|
clk_set_rate(bsp_priv->clk_phy, 50000000);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
|
|
{
|
|
int ret;
|
|
|
|
if (enable) {
|
|
if (!bsp_priv->clk_enabled) {
|
|
ret = clk_bulk_prepare_enable(bsp_priv->num_clks,
|
|
bsp_priv->clks);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = clk_prepare_enable(bsp_priv->clk_phy);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
|
|
bsp_priv->ops->set_clock_selection(bsp_priv,
|
|
bsp_priv->clock_input, true);
|
|
|
|
mdelay(5);
|
|
bsp_priv->clk_enabled = true;
|
|
}
|
|
} else {
|
|
if (bsp_priv->clk_enabled) {
|
|
clk_bulk_disable_unprepare(bsp_priv->num_clks,
|
|
bsp_priv->clks);
|
|
clk_disable_unprepare(bsp_priv->clk_phy);
|
|
|
|
if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
|
|
bsp_priv->ops->set_clock_selection(bsp_priv,
|
|
bsp_priv->clock_input, false);
|
|
|
|
bsp_priv->clk_enabled = false;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
|
|
{
|
|
struct regulator *ldo = bsp_priv->regulator;
|
|
int ret;
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
if (enable) {
|
|
ret = regulator_enable(ldo);
|
|
if (ret)
|
|
dev_err(dev, "fail to enable phy-supply\n");
|
|
} else {
|
|
ret = regulator_disable(ldo);
|
|
if (ret)
|
|
dev_err(dev, "fail to disable phy-supply\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
|
|
struct plat_stmmacenet_data *plat,
|
|
const struct rk_gmac_ops *ops)
|
|
{
|
|
struct rk_priv_data *bsp_priv;
|
|
struct device *dev = &pdev->dev;
|
|
struct resource *res;
|
|
int ret;
|
|
const char *strings = NULL;
|
|
int value;
|
|
|
|
bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL);
|
|
if (!bsp_priv)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
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 && ops->regs_valid) {
|
|
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(dev, "phy");
|
|
if (IS_ERR(bsp_priv->regulator)) {
|
|
ret = PTR_ERR(bsp_priv->regulator);
|
|
dev_err_probe(dev, ret, "failed to get phy regulator\n");
|
|
return ERR_PTR(ret);
|
|
}
|
|
|
|
ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
|
|
if (ret) {
|
|
dev_err(dev, "Can not read property: clock_in_out.\n");
|
|
bsp_priv->clock_input = true;
|
|
} else {
|
|
dev_info(dev, "clock input or output? (%s).\n",
|
|
strings);
|
|
if (!strcmp(strings, "input"))
|
|
bsp_priv->clock_input = true;
|
|
else
|
|
bsp_priv->clock_input = false;
|
|
}
|
|
|
|
ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
|
|
if (ret) {
|
|
bsp_priv->tx_delay = 0x30;
|
|
dev_err(dev, "Can not read property: tx_delay.");
|
|
dev_err(dev, "set tx_delay to 0x%x\n",
|
|
bsp_priv->tx_delay);
|
|
} else {
|
|
dev_info(dev, "TX delay(0x%x).\n", value);
|
|
bsp_priv->tx_delay = value;
|
|
}
|
|
|
|
ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
|
|
if (ret) {
|
|
bsp_priv->rx_delay = 0x10;
|
|
dev_err(dev, "Can not read property: rx_delay.");
|
|
dev_err(dev, "set rx_delay to 0x%x\n",
|
|
bsp_priv->rx_delay);
|
|
} else {
|
|
dev_info(dev, "RX delay(0x%x).\n", value);
|
|
bsp_priv->rx_delay = value;
|
|
}
|
|
|
|
bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
|
|
"rockchip,grf");
|
|
bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
|
|
"rockchip,php-grf");
|
|
|
|
if (plat->phy_node) {
|
|
bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
|
|
"phy-is-integrated");
|
|
if (bsp_priv->integrated_phy) {
|
|
bsp_priv->phy_reset = of_reset_control_get(plat->phy_node, NULL);
|
|
if (IS_ERR(bsp_priv->phy_reset)) {
|
|
dev_err(&pdev->dev, "No PHY reset control found.\n");
|
|
bsp_priv->phy_reset = NULL;
|
|
}
|
|
}
|
|
}
|
|
dev_info(dev, "integrated PHY? (%s).\n",
|
|
bsp_priv->integrated_phy ? "yes" : "no");
|
|
|
|
bsp_priv->pdev = 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;
|
|
|
|
/*rmii or rgmii*/
|
|
switch (bsp_priv->phy_iface) {
|
|
case PHY_INTERFACE_MODE_RGMII:
|
|
dev_info(dev, "init for RGMII\n");
|
|
bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
|
|
bsp_priv->rx_delay);
|
|
break;
|
|
case PHY_INTERFACE_MODE_RGMII_ID:
|
|
dev_info(dev, "init for RGMII_ID\n");
|
|
bsp_priv->ops->set_to_rgmii(bsp_priv, 0, 0);
|
|
break;
|
|
case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
dev_info(dev, "init for RGMII_RXID\n");
|
|
bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, 0);
|
|
break;
|
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
dev_info(dev, "init for RGMII_TXID\n");
|
|
bsp_priv->ops->set_to_rgmii(bsp_priv, 0, bsp_priv->rx_delay);
|
|
break;
|
|
case PHY_INTERFACE_MODE_RMII:
|
|
dev_info(dev, "init for RMII\n");
|
|
bsp_priv->ops->set_to_rmii(bsp_priv);
|
|
break;
|
|
default:
|
|
dev_err(dev, "NO interface defined!\n");
|
|
}
|
|
|
|
ret = phy_power_on(bsp_priv, true);
|
|
if (ret) {
|
|
gmac_clk_enable(bsp_priv, false);
|
|
return ret;
|
|
}
|
|
|
|
pm_runtime_get_sync(dev);
|
|
|
|
if (bsp_priv->integrated_phy)
|
|
rk_gmac_integrated_phy_powerup(bsp_priv);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void rk_gmac_powerdown(struct rk_priv_data *gmac)
|
|
{
|
|
if (gmac->integrated_phy)
|
|
rk_gmac_integrated_phy_powerdown(gmac);
|
|
|
|
pm_runtime_put_sync(&gmac->pdev->dev);
|
|
|
|
phy_power_on(gmac, false);
|
|
gmac_clk_enable(gmac, false);
|
|
}
|
|
|
|
static void rk_fix_speed(void *priv, unsigned int speed)
|
|
{
|
|
struct rk_priv_data *bsp_priv = priv;
|
|
struct device *dev = &bsp_priv->pdev->dev;
|
|
|
|
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_rgmii_speed)
|
|
bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
|
|
break;
|
|
case PHY_INTERFACE_MODE_RMII:
|
|
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);
|
|
}
|
|
}
|
|
|
|
static int rk_gmac_probe(struct platform_device *pdev)
|
|
{
|
|
struct plat_stmmacenet_data *plat_dat;
|
|
struct stmmac_resources stmmac_res;
|
|
const struct rk_gmac_ops *data;
|
|
int ret;
|
|
|
|
data = of_device_get_match_data(&pdev->dev);
|
|
if (!data) {
|
|
dev_err(&pdev->dev, "no of match data provided\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
|
|
if (ret)
|
|
return ret;
|
|
|
|
plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
|
|
if (IS_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->fix_mac_speed = rk_fix_speed;
|
|
|
|
plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
|
|
if (IS_ERR(plat_dat->bsp_priv)) {
|
|
ret = PTR_ERR(plat_dat->bsp_priv);
|
|
goto err_remove_config_dt;
|
|
}
|
|
|
|
ret = rk_gmac_clk_init(plat_dat);
|
|
if (ret)
|
|
goto err_remove_config_dt;
|
|
|
|
ret = rk_gmac_powerup(plat_dat->bsp_priv);
|
|
if (ret)
|
|
goto err_remove_config_dt;
|
|
|
|
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
|
if (ret)
|
|
goto err_gmac_powerdown;
|
|
|
|
return 0;
|
|
|
|
err_gmac_powerdown:
|
|
rk_gmac_powerdown(plat_dat->bsp_priv);
|
|
err_remove_config_dt:
|
|
stmmac_remove_config_dt(pdev, plat_dat);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void rk_gmac_remove(struct platform_device *pdev)
|
|
{
|
|
struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev);
|
|
|
|
stmmac_dvr_remove(&pdev->dev);
|
|
|
|
rk_gmac_powerdown(bsp_priv);
|
|
}
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
static int rk_gmac_suspend(struct device *dev)
|
|
{
|
|
struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
|
|
int ret = stmmac_suspend(dev);
|
|
|
|
/* Keep the PHY up if we use Wake-on-Lan. */
|
|
if (!device_may_wakeup(dev)) {
|
|
rk_gmac_powerdown(bsp_priv);
|
|
bsp_priv->suspended = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int rk_gmac_resume(struct device *dev)
|
|
{
|
|
struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
|
|
|
|
/* The PHY was up for Wake-on-Lan. */
|
|
if (bsp_priv->suspended) {
|
|
rk_gmac_powerup(bsp_priv);
|
|
bsp_priv->suspended = false;
|
|
}
|
|
|
|
return stmmac_resume(dev);
|
|
}
|
|
#endif /* CONFIG_PM_SLEEP */
|
|
|
|
static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);
|
|
|
|
static const struct of_device_id rk_gmac_dwmac_match[] = {
|
|
{ .compatible = "rockchip,px30-gmac", .data = &px30_ops },
|
|
{ .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops },
|
|
{ .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
|
|
{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
|
|
{ .compatible = "rockchip,rk3308-gmac", .data = &rk3308_ops },
|
|
{ .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops },
|
|
{ .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,rk3588-gmac", .data = &rk3588_ops },
|
|
{ .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops },
|
|
{ .compatible = "rockchip,rv1126-gmac", .data = &rv1126_ops },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
|
|
|
|
static struct platform_driver rk_gmac_dwmac_driver = {
|
|
.probe = rk_gmac_probe,
|
|
.remove_new = rk_gmac_remove,
|
|
.driver = {
|
|
.name = "rk_gmac-dwmac",
|
|
.pm = &rk_gmac_pm_ops,
|
|
.of_match_table = rk_gmac_dwmac_match,
|
|
},
|
|
};
|
|
module_platform_driver(rk_gmac_dwmac_driver);
|
|
|
|
MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
|
|
MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
|
|
MODULE_LICENSE("GPL");
|