2088 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2088 lines
		
	
	
		
			59 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/module.h>
 | |
| #include <linux/of.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 */
 | |
| 	},
 | |
| };
 | |
| 
 | |
| /* 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 void rk3576_set_to_rgmii(struct rk_priv_data *bsp_priv,
 | |
| 				int tx_delay, int rx_delay)
 | |
| {
 | |
| 	struct device *dev = &bsp_priv->pdev->dev;
 | |
| 	unsigned int offset_con;
 | |
| 
 | |
| 	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 ? RK3576_GRF_GMAC_CON1 :
 | |
| 					 RK3576_GRF_GMAC_CON0;
 | |
| 
 | |
| 	regmap_write(bsp_priv->grf, offset_con, RK3576_GMAC_RGMII_MODE);
 | |
| 
 | |
| 	offset_con = bsp_priv->id == 1 ? RK3576_VCCIO0_1_3_IOC_CON4 :
 | |
| 					 RK3576_VCCIO0_1_3_IOC_CON2;
 | |
| 
 | |
| 	/* m0 && m1 delay enabled */
 | |
| 	regmap_write(bsp_priv->php_grf, offset_con,
 | |
| 		     DELAY_ENABLE(RK3576, tx_delay, rx_delay));
 | |
| 	regmap_write(bsp_priv->php_grf, offset_con + 0x4,
 | |
| 		     DELAY_ENABLE(RK3576, tx_delay, rx_delay));
 | |
| 
 | |
| 	/* m0 && m1 delay value */
 | |
| 	regmap_write(bsp_priv->php_grf, offset_con,
 | |
| 		     RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) |
 | |
| 		     RK3576_GMAC_CLK_RX_DL_CFG(rx_delay));
 | |
| 	regmap_write(bsp_priv->php_grf, offset_con + 0x4,
 | |
| 		     RK3576_GMAC_CLK_TX_DL_CFG(tx_delay) |
 | |
| 		     RK3576_GMAC_CLK_RX_DL_CFG(rx_delay));
 | |
| }
 | |
| 
 | |
| static void rk3576_set_to_rmii(struct rk_priv_data *bsp_priv)
 | |
| {
 | |
| 	struct device *dev = &bsp_priv->pdev->dev;
 | |
| 	unsigned int offset_con;
 | |
| 
 | |
| 	if (IS_ERR(bsp_priv->grf)) {
 | |
| 		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 | |
| 					 RK3576_GRF_GMAC_CON0;
 | |
| 
 | |
| 	regmap_write(bsp_priv->grf, offset_con, RK3576_GMAC_RMII_MODE);
 | |
| }
 | |
| 
 | |
| static void rk3576_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
 | |
| {
 | |
| 	struct device *dev = &bsp_priv->pdev->dev;
 | |
| 	unsigned int val = 0, offset_con;
 | |
| 
 | |
| 	switch (speed) {
 | |
| 	case 10:
 | |
| 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
 | |
| 			val = RK3576_GMAC_CLK_RMII_DIV20;
 | |
| 		else
 | |
| 			val = RK3576_GMAC_CLK_RGMII_DIV50;
 | |
| 		break;
 | |
| 	case 100:
 | |
| 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
 | |
| 			val = RK3576_GMAC_CLK_RMII_DIV2;
 | |
| 		else
 | |
| 			val = RK3576_GMAC_CLK_RGMII_DIV5;
 | |
| 		break;
 | |
| 	case 1000:
 | |
| 		if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII)
 | |
| 			val = RK3576_GMAC_CLK_RGMII_DIV1;
 | |
| 		else
 | |
| 			goto err;
 | |
| 		break;
 | |
| 	default:
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 | |
| 					 RK3576_GRF_GMAC_CON0;
 | |
| 
 | |
| 	regmap_write(bsp_priv->grf, offset_con, val);
 | |
| 
 | |
| 	return;
 | |
| err:
 | |
| 	dev_err(dev, "unknown speed value for GMAC speed=%d", speed);
 | |
| }
 | |
| 
 | |
| static void rk3576_set_clock_selection(struct rk_priv_data *bsp_priv, bool input,
 | |
| 				       bool enable)
 | |
| {
 | |
| 	unsigned int val = input ? RK3576_GMAC_CLK_SELECT_IO :
 | |
| 				   RK3576_GMAC_CLK_SELECT_CRU;
 | |
| 	unsigned int offset_con;
 | |
| 
 | |
| 	val |= enable ? RK3576_GMAC_CLK_RMII_NOGATE :
 | |
| 			RK3576_GMAC_CLK_RMII_GATE;
 | |
| 
 | |
| 	offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 :
 | |
| 					 RK3576_GRF_GMAC_CON0;
 | |
| 
 | |
| 	regmap_write(bsp_priv->grf, offset_con, val);
 | |
| }
 | |
| 
 | |
| static const struct rk_gmac_ops rk3576_ops = {
 | |
| 	.set_to_rgmii = rk3576_set_to_rgmii,
 | |
| 	.set_to_rmii = rk3576_set_to_rmii,
 | |
| 	.set_rgmii_speed = rk3576_set_gmac_speed,
 | |
| 	.set_rmii_speed = rk3576_set_gmac_speed,
 | |
| 	.set_clock_selection = rk3576_set_clock_selection,
 | |
| 	.regs_valid = true,
 | |
| 	.regs = {
 | |
| 		0x2a220000, /* gmac0 */
 | |
| 		0x2a230000, /* 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_SELECT_CRU(id)		GRF_BIT(5 * (id) + 4)
 | |
| #define RK3588_GMAC_CLK_SELECT_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_SELECT_IO(bsp_priv->id) :
 | |
| 				   RK3588_GMAC_CLK_SELECT_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, unsigned int mode)
 | |
| {
 | |
| 	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 = devm_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))
 | |
| 		return PTR_ERR(plat_dat->bsp_priv);
 | |
| 
 | |
| 	ret = rk_gmac_clk_init(plat_dat);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	ret = rk_gmac_powerup(plat_dat->bsp_priv);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	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,rk3576-gmac", .data = &rk3576_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");
 |