xref: /openbmc/linux/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c (revision f6d73b12ca9fd3b1c29a6a725cd751b972c740cf)
1b38dd98fSNobuhiro Iwamatsu // SPDX-License-Identifier: GPL-2.0
2b38dd98fSNobuhiro Iwamatsu /* Toshiba Visconti Ethernet Support
3b38dd98fSNobuhiro Iwamatsu  *
4b38dd98fSNobuhiro Iwamatsu  * (C) Copyright 2020 TOSHIBA CORPORATION
5b38dd98fSNobuhiro Iwamatsu  * (C) Copyright 2020 Toshiba Electronic Devices & Storage Corporation
6b38dd98fSNobuhiro Iwamatsu  */
7b38dd98fSNobuhiro Iwamatsu 
8b38dd98fSNobuhiro Iwamatsu #include <linux/module.h>
93d40aed8SRob Herring #include <linux/of.h>
103d40aed8SRob Herring #include <linux/platform_device.h>
11b38dd98fSNobuhiro Iwamatsu #include <linux/of_net.h>
12b38dd98fSNobuhiro Iwamatsu #include <linux/stmmac.h>
13b38dd98fSNobuhiro Iwamatsu 
14b38dd98fSNobuhiro Iwamatsu #include "stmmac_platform.h"
15b38dd98fSNobuhiro Iwamatsu #include "dwmac4.h"
16b38dd98fSNobuhiro Iwamatsu 
17b38dd98fSNobuhiro Iwamatsu #define REG_ETHER_CONTROL	0x52D4
18b38dd98fSNobuhiro Iwamatsu #define ETHER_ETH_CONTROL_RESET BIT(17)
19b38dd98fSNobuhiro Iwamatsu 
20b38dd98fSNobuhiro Iwamatsu #define REG_ETHER_CLOCK_SEL	0x52D0
21b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_TX_CLK_EN BIT(0)
22b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RX_CLK_EN BIT(1)
23b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RMII_CLK_EN BIT(2)
24b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RMII_CLK_RST BIT(3)
25b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_DIV_SEL_2 BIT(4)
261ba1a4a9SYuji Ishikawa #define ETHER_CLK_SEL_DIV_SEL_20 0
27b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_FREQ_SEL_125M	(BIT(9) | BIT(8))
28b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_FREQ_SEL_50M	BIT(9)
29b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_FREQ_SEL_25M	BIT(8)
30391e5975SNobuhiro Iwamatsu #define ETHER_CLK_SEL_FREQ_SEL_2P5M	0
311ba1a4a9SYuji Ishikawa #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_IN 0
32b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC BIT(10)
33b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV BIT(11)
341ba1a4a9SYuji Ishikawa #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_IN  0
35b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC BIT(12)
36b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV BIT(13)
371ba1a4a9SYuji Ishikawa #define ETHER_CLK_SEL_TX_CLK_O_TX_I	 0
38b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_TX_CLK_O_RMII_I	 BIT(14)
39b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_TX_O_E_N_IN	 BIT(15)
401ba1a4a9SYuji Ishikawa #define ETHER_CLK_SEL_RMII_CLK_SEL_IN	 0
41b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RMII_CLK_SEL_RX_C	 BIT(16)
42b38dd98fSNobuhiro Iwamatsu 
43b38dd98fSNobuhiro Iwamatsu #define ETHER_CLK_SEL_RX_TX_CLK_EN (ETHER_CLK_SEL_RX_CLK_EN | ETHER_CLK_SEL_TX_CLK_EN)
44b38dd98fSNobuhiro Iwamatsu 
45b38dd98fSNobuhiro Iwamatsu #define ETHER_CONFIG_INTF_MII 0
46b38dd98fSNobuhiro Iwamatsu #define ETHER_CONFIG_INTF_RGMII BIT(0)
47b38dd98fSNobuhiro Iwamatsu #define ETHER_CONFIG_INTF_RMII BIT(2)
48b38dd98fSNobuhiro Iwamatsu 
49b38dd98fSNobuhiro Iwamatsu struct visconti_eth {
50b38dd98fSNobuhiro Iwamatsu 	void __iomem *reg;
51b38dd98fSNobuhiro Iwamatsu 	u32 phy_intf_sel;
52b38dd98fSNobuhiro Iwamatsu 	struct clk *phy_ref_clk;
53928d6fe9SYuji Ishikawa 	struct device *dev;
54b38dd98fSNobuhiro Iwamatsu 	spinlock_t lock; /* lock to protect register update */
55b38dd98fSNobuhiro Iwamatsu };
56b38dd98fSNobuhiro Iwamatsu 
visconti_eth_fix_mac_speed(void * priv,unsigned int speed,unsigned int mode)571fc04a0bSShenwei Wang static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
58b38dd98fSNobuhiro Iwamatsu {
59b38dd98fSNobuhiro Iwamatsu 	struct visconti_eth *dwmac = priv;
60928d6fe9SYuji Ishikawa 	struct net_device *netdev = dev_get_drvdata(dwmac->dev);
61928d6fe9SYuji Ishikawa 	unsigned int val, clk_sel_val = 0;
62b38dd98fSNobuhiro Iwamatsu 	unsigned long flags;
63b38dd98fSNobuhiro Iwamatsu 
64b38dd98fSNobuhiro Iwamatsu 	spin_lock_irqsave(&dwmac->lock, flags);
65b38dd98fSNobuhiro Iwamatsu 
66b38dd98fSNobuhiro Iwamatsu 	/* adjust link */
67b38dd98fSNobuhiro Iwamatsu 	val = readl(dwmac->reg + MAC_CTRL_REG);
68b38dd98fSNobuhiro Iwamatsu 	val &= ~(GMAC_CONFIG_PS | GMAC_CONFIG_FES);
69b38dd98fSNobuhiro Iwamatsu 
70b38dd98fSNobuhiro Iwamatsu 	switch (speed) {
71b38dd98fSNobuhiro Iwamatsu 	case SPEED_1000:
72b38dd98fSNobuhiro Iwamatsu 		if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
73b38dd98fSNobuhiro Iwamatsu 			clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_125M;
74b38dd98fSNobuhiro Iwamatsu 		break;
75b38dd98fSNobuhiro Iwamatsu 	case SPEED_100:
76b38dd98fSNobuhiro Iwamatsu 		if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
77b38dd98fSNobuhiro Iwamatsu 			clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_25M;
78b38dd98fSNobuhiro Iwamatsu 		if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RMII)
79b38dd98fSNobuhiro Iwamatsu 			clk_sel_val = ETHER_CLK_SEL_DIV_SEL_2;
80b38dd98fSNobuhiro Iwamatsu 		val |= GMAC_CONFIG_PS | GMAC_CONFIG_FES;
81b38dd98fSNobuhiro Iwamatsu 		break;
82b38dd98fSNobuhiro Iwamatsu 	case SPEED_10:
83b38dd98fSNobuhiro Iwamatsu 		if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
84b38dd98fSNobuhiro Iwamatsu 			clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_2P5M;
85b38dd98fSNobuhiro Iwamatsu 		if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RMII)
86b38dd98fSNobuhiro Iwamatsu 			clk_sel_val = ETHER_CLK_SEL_DIV_SEL_20;
87b38dd98fSNobuhiro Iwamatsu 		val |= GMAC_CONFIG_PS;
88b38dd98fSNobuhiro Iwamatsu 		break;
89b38dd98fSNobuhiro Iwamatsu 	default:
90b38dd98fSNobuhiro Iwamatsu 		/* No bit control */
91928d6fe9SYuji Ishikawa 		netdev_err(netdev, "Unsupported speed request (%d)", speed);
92928d6fe9SYuji Ishikawa 		spin_unlock_irqrestore(&dwmac->lock, flags);
93928d6fe9SYuji Ishikawa 		return;
94b38dd98fSNobuhiro Iwamatsu 	}
95b38dd98fSNobuhiro Iwamatsu 
96b38dd98fSNobuhiro Iwamatsu 	writel(val, dwmac->reg + MAC_CTRL_REG);
97b38dd98fSNobuhiro Iwamatsu 
98b38dd98fSNobuhiro Iwamatsu 	/* Stop internal clock */
99b38dd98fSNobuhiro Iwamatsu 	val = readl(dwmac->reg + REG_ETHER_CLOCK_SEL);
100b38dd98fSNobuhiro Iwamatsu 	val &= ~(ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN);
101b38dd98fSNobuhiro Iwamatsu 	val |= ETHER_CLK_SEL_TX_O_E_N_IN;
102b38dd98fSNobuhiro Iwamatsu 	writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
103b38dd98fSNobuhiro Iwamatsu 
1040959bc4bSYuji Ishikawa 	/* Set Clock-Mux, Start clock, Set TX_O direction */
105b38dd98fSNobuhiro Iwamatsu 	switch (dwmac->phy_intf_sel) {
106b38dd98fSNobuhiro Iwamatsu 	case ETHER_CONFIG_INTF_RGMII:
107b38dd98fSNobuhiro Iwamatsu 		val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC;
108b38dd98fSNobuhiro Iwamatsu 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1090959bc4bSYuji Ishikawa 
110b38dd98fSNobuhiro Iwamatsu 		val |= ETHER_CLK_SEL_RX_TX_CLK_EN;
111b38dd98fSNobuhiro Iwamatsu 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
112b38dd98fSNobuhiro Iwamatsu 
113b38dd98fSNobuhiro Iwamatsu 		val &= ~ETHER_CLK_SEL_TX_O_E_N_IN;
114b38dd98fSNobuhiro Iwamatsu 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1150959bc4bSYuji Ishikawa 		break;
1160959bc4bSYuji Ishikawa 	case ETHER_CONFIG_INTF_RMII:
1170959bc4bSYuji Ishikawa 		val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV |
1180959bc4bSYuji Ishikawa 			ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV | ETHER_CLK_SEL_TX_O_E_N_IN |
1190959bc4bSYuji Ishikawa 			ETHER_CLK_SEL_RMII_CLK_SEL_RX_C;
1200959bc4bSYuji Ishikawa 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1210959bc4bSYuji Ishikawa 
1220959bc4bSYuji Ishikawa 		val |= ETHER_CLK_SEL_RMII_CLK_RST;
1230959bc4bSYuji Ishikawa 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1240959bc4bSYuji Ishikawa 
1250959bc4bSYuji Ishikawa 		val |= ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN;
1260959bc4bSYuji Ishikawa 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1270959bc4bSYuji Ishikawa 		break;
1280959bc4bSYuji Ishikawa 	case ETHER_CONFIG_INTF_MII:
1290959bc4bSYuji Ishikawa 	default:
1300959bc4bSYuji Ishikawa 		val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC |
1310959bc4bSYuji Ishikawa 			ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC | ETHER_CLK_SEL_TX_O_E_N_IN;
1320959bc4bSYuji Ishikawa 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1330959bc4bSYuji Ishikawa 
1340959bc4bSYuji Ishikawa 		val |= ETHER_CLK_SEL_RX_TX_CLK_EN;
1350959bc4bSYuji Ishikawa 		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
1360959bc4bSYuji Ishikawa 		break;
1370959bc4bSYuji Ishikawa 	}
138b38dd98fSNobuhiro Iwamatsu 
139b38dd98fSNobuhiro Iwamatsu 	spin_unlock_irqrestore(&dwmac->lock, flags);
140b38dd98fSNobuhiro Iwamatsu }
141b38dd98fSNobuhiro Iwamatsu 
visconti_eth_init_hw(struct platform_device * pdev,struct plat_stmmacenet_data * plat_dat)142b38dd98fSNobuhiro Iwamatsu static int visconti_eth_init_hw(struct platform_device *pdev, struct plat_stmmacenet_data *plat_dat)
143b38dd98fSNobuhiro Iwamatsu {
144b38dd98fSNobuhiro Iwamatsu 	struct visconti_eth *dwmac = plat_dat->bsp_priv;
145b38dd98fSNobuhiro Iwamatsu 	unsigned int reg_val, clk_sel_val;
146b38dd98fSNobuhiro Iwamatsu 
147b38dd98fSNobuhiro Iwamatsu 	switch (plat_dat->phy_interface) {
148b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_RGMII:
149b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_RGMII_ID:
150b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_RGMII_RXID:
151b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_RGMII_TXID:
152b38dd98fSNobuhiro Iwamatsu 		dwmac->phy_intf_sel = ETHER_CONFIG_INTF_RGMII;
153b38dd98fSNobuhiro Iwamatsu 		break;
154b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_MII:
155b38dd98fSNobuhiro Iwamatsu 		dwmac->phy_intf_sel = ETHER_CONFIG_INTF_MII;
156b38dd98fSNobuhiro Iwamatsu 		break;
157b38dd98fSNobuhiro Iwamatsu 	case PHY_INTERFACE_MODE_RMII:
158b38dd98fSNobuhiro Iwamatsu 		dwmac->phy_intf_sel = ETHER_CONFIG_INTF_RMII;
159b38dd98fSNobuhiro Iwamatsu 		break;
160b38dd98fSNobuhiro Iwamatsu 	default:
161b38dd98fSNobuhiro Iwamatsu 		dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n", plat_dat->phy_interface);
162b38dd98fSNobuhiro Iwamatsu 		return -EOPNOTSUPP;
163b38dd98fSNobuhiro Iwamatsu 	}
164b38dd98fSNobuhiro Iwamatsu 
165b38dd98fSNobuhiro Iwamatsu 	reg_val = dwmac->phy_intf_sel;
166b38dd98fSNobuhiro Iwamatsu 	writel(reg_val, dwmac->reg + REG_ETHER_CONTROL);
167b38dd98fSNobuhiro Iwamatsu 
168b38dd98fSNobuhiro Iwamatsu 	/* Enable TX/RX clock */
169b38dd98fSNobuhiro Iwamatsu 	clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_125M;
170b38dd98fSNobuhiro Iwamatsu 	writel(clk_sel_val, dwmac->reg + REG_ETHER_CLOCK_SEL);
171b38dd98fSNobuhiro Iwamatsu 
172b38dd98fSNobuhiro Iwamatsu 	writel((clk_sel_val | ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN),
173b38dd98fSNobuhiro Iwamatsu 	       dwmac->reg + REG_ETHER_CLOCK_SEL);
174b38dd98fSNobuhiro Iwamatsu 
175b38dd98fSNobuhiro Iwamatsu 	/* release internal-reset */
176b38dd98fSNobuhiro Iwamatsu 	reg_val |= ETHER_ETH_CONTROL_RESET;
177b38dd98fSNobuhiro Iwamatsu 	writel(reg_val, dwmac->reg + REG_ETHER_CONTROL);
178b38dd98fSNobuhiro Iwamatsu 
179b38dd98fSNobuhiro Iwamatsu 	return 0;
180b38dd98fSNobuhiro Iwamatsu }
181b38dd98fSNobuhiro Iwamatsu 
visconti_eth_clock_probe(struct platform_device * pdev,struct plat_stmmacenet_data * plat_dat)182b38dd98fSNobuhiro Iwamatsu static int visconti_eth_clock_probe(struct platform_device *pdev,
183b38dd98fSNobuhiro Iwamatsu 				    struct plat_stmmacenet_data *plat_dat)
184b38dd98fSNobuhiro Iwamatsu {
185b38dd98fSNobuhiro Iwamatsu 	struct visconti_eth *dwmac = plat_dat->bsp_priv;
186b38dd98fSNobuhiro Iwamatsu 	int err;
187b38dd98fSNobuhiro Iwamatsu 
188b38dd98fSNobuhiro Iwamatsu 	dwmac->phy_ref_clk = devm_clk_get(&pdev->dev, "phy_ref_clk");
189b20b54fbSCai Huoqing 	if (IS_ERR(dwmac->phy_ref_clk))
190b20b54fbSCai Huoqing 		return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->phy_ref_clk),
191b20b54fbSCai Huoqing 				     "phy_ref_clk clock not found.\n");
192b38dd98fSNobuhiro Iwamatsu 
193b38dd98fSNobuhiro Iwamatsu 	err = clk_prepare_enable(dwmac->phy_ref_clk);
194b38dd98fSNobuhiro Iwamatsu 	if (err < 0) {
195b38dd98fSNobuhiro Iwamatsu 		dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n", err);
196b38dd98fSNobuhiro Iwamatsu 		return err;
197b38dd98fSNobuhiro Iwamatsu 	}
198b38dd98fSNobuhiro Iwamatsu 
199b38dd98fSNobuhiro Iwamatsu 	return 0;
200b38dd98fSNobuhiro Iwamatsu }
201b38dd98fSNobuhiro Iwamatsu 
visconti_eth_clock_remove(struct platform_device * pdev)202b9bc44feSUwe Kleine-König static void visconti_eth_clock_remove(struct platform_device *pdev)
203b38dd98fSNobuhiro Iwamatsu {
204b38dd98fSNobuhiro Iwamatsu 	struct visconti_eth *dwmac = get_stmmac_bsp_priv(&pdev->dev);
205b38dd98fSNobuhiro Iwamatsu 	struct net_device *ndev = platform_get_drvdata(pdev);
206b38dd98fSNobuhiro Iwamatsu 	struct stmmac_priv *priv = netdev_priv(ndev);
207b38dd98fSNobuhiro Iwamatsu 
208b38dd98fSNobuhiro Iwamatsu 	clk_disable_unprepare(dwmac->phy_ref_clk);
209b38dd98fSNobuhiro Iwamatsu 	clk_disable_unprepare(priv->plat->stmmac_clk);
210b38dd98fSNobuhiro Iwamatsu }
211b38dd98fSNobuhiro Iwamatsu 
visconti_eth_dwmac_probe(struct platform_device * pdev)212b38dd98fSNobuhiro Iwamatsu static int visconti_eth_dwmac_probe(struct platform_device *pdev)
213b38dd98fSNobuhiro Iwamatsu {
214b38dd98fSNobuhiro Iwamatsu 	struct plat_stmmacenet_data *plat_dat;
215b38dd98fSNobuhiro Iwamatsu 	struct stmmac_resources stmmac_res;
216b38dd98fSNobuhiro Iwamatsu 	struct visconti_eth *dwmac;
217b38dd98fSNobuhiro Iwamatsu 	int ret;
218b38dd98fSNobuhiro Iwamatsu 
219b38dd98fSNobuhiro Iwamatsu 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
220b38dd98fSNobuhiro Iwamatsu 	if (ret)
221b38dd98fSNobuhiro Iwamatsu 		return ret;
222b38dd98fSNobuhiro Iwamatsu 
223d54ebfe8SJisheng Zhang 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
224b38dd98fSNobuhiro Iwamatsu 	if (IS_ERR(plat_dat))
225b38dd98fSNobuhiro Iwamatsu 		return PTR_ERR(plat_dat);
226b38dd98fSNobuhiro Iwamatsu 
227b38dd98fSNobuhiro Iwamatsu 	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
228d54ebfe8SJisheng Zhang 	if (!dwmac)
229d54ebfe8SJisheng Zhang 		return -ENOMEM;
230b38dd98fSNobuhiro Iwamatsu 
23117d7fd47SWei Yongjun 	spin_lock_init(&dwmac->lock);
232b38dd98fSNobuhiro Iwamatsu 	dwmac->reg = stmmac_res.addr;
233928d6fe9SYuji Ishikawa 	dwmac->dev = &pdev->dev;
234b38dd98fSNobuhiro Iwamatsu 	plat_dat->bsp_priv = dwmac;
235b38dd98fSNobuhiro Iwamatsu 	plat_dat->fix_mac_speed = visconti_eth_fix_mac_speed;
236b38dd98fSNobuhiro Iwamatsu 
237b38dd98fSNobuhiro Iwamatsu 	ret = visconti_eth_clock_probe(pdev, plat_dat);
238b38dd98fSNobuhiro Iwamatsu 	if (ret)
239d54ebfe8SJisheng Zhang 		return ret;
240b38dd98fSNobuhiro Iwamatsu 
241b38dd98fSNobuhiro Iwamatsu 	visconti_eth_init_hw(pdev, plat_dat);
242b38dd98fSNobuhiro Iwamatsu 
243b38dd98fSNobuhiro Iwamatsu 	plat_dat->dma_cfg->aal = 1;
244b38dd98fSNobuhiro Iwamatsu 
245b38dd98fSNobuhiro Iwamatsu 	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
246b38dd98fSNobuhiro Iwamatsu 	if (ret)
247b38dd98fSNobuhiro Iwamatsu 		goto remove;
248b38dd98fSNobuhiro Iwamatsu 
249b38dd98fSNobuhiro Iwamatsu 	return ret;
250b38dd98fSNobuhiro Iwamatsu 
251b38dd98fSNobuhiro Iwamatsu remove:
252b38dd98fSNobuhiro Iwamatsu 	visconti_eth_clock_remove(pdev);
253b38dd98fSNobuhiro Iwamatsu 
254b38dd98fSNobuhiro Iwamatsu 	return ret;
255b38dd98fSNobuhiro Iwamatsu }
256b38dd98fSNobuhiro Iwamatsu 
visconti_eth_dwmac_remove(struct platform_device * pdev)257f4d05c41SUwe Kleine-König static void visconti_eth_dwmac_remove(struct platform_device *pdev)
258b38dd98fSNobuhiro Iwamatsu {
259*a39058e0SJisheng Zhang 	stmmac_pltfr_remove(pdev);
260b9bc44feSUwe Kleine-König 	visconti_eth_clock_remove(pdev);
261b38dd98fSNobuhiro Iwamatsu }
262b38dd98fSNobuhiro Iwamatsu 
263b38dd98fSNobuhiro Iwamatsu static const struct of_device_id visconti_eth_dwmac_match[] = {
264b38dd98fSNobuhiro Iwamatsu 	{ .compatible = "toshiba,visconti-dwmac" },
265b38dd98fSNobuhiro Iwamatsu 	{ }
266b38dd98fSNobuhiro Iwamatsu };
267b38dd98fSNobuhiro Iwamatsu MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match);
268b38dd98fSNobuhiro Iwamatsu 
269b38dd98fSNobuhiro Iwamatsu static struct platform_driver visconti_eth_dwmac_driver = {
270b38dd98fSNobuhiro Iwamatsu 	.probe  = visconti_eth_dwmac_probe,
271f4d05c41SUwe Kleine-König 	.remove_new = visconti_eth_dwmac_remove,
272b38dd98fSNobuhiro Iwamatsu 	.driver = {
273b38dd98fSNobuhiro Iwamatsu 		.name           = "visconti-eth-dwmac",
274b38dd98fSNobuhiro Iwamatsu 		.of_match_table = visconti_eth_dwmac_match,
275b38dd98fSNobuhiro Iwamatsu 	},
276b38dd98fSNobuhiro Iwamatsu };
277b38dd98fSNobuhiro Iwamatsu module_platform_driver(visconti_eth_dwmac_driver);
278b38dd98fSNobuhiro Iwamatsu 
279b38dd98fSNobuhiro Iwamatsu MODULE_AUTHOR("Toshiba");
280b38dd98fSNobuhiro Iwamatsu MODULE_DESCRIPTION("Toshiba Visconti Ethernet DWMAC glue driver");
281b38dd98fSNobuhiro Iwamatsu MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp");
282b38dd98fSNobuhiro Iwamatsu MODULE_LICENSE("GPL v2");
283