| // 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 int rk_gmac_remove(struct platform_device *pdev) | 
 | { | 
 | 	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev); | 
 | 	int ret = stmmac_dvr_remove(&pdev->dev); | 
 |  | 
 | 	rk_gmac_powerdown(bsp_priv); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | #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 = 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"); |