xref: /openbmc/linux/drivers/net/ethernet/sunplus/spl2sw_driver.c (revision fd3040b9394c58bcedb83554bcf1a073021d6b36)
1*fd3040b9SWells Lu // SPDX-License-Identifier: GPL-2.0
2*fd3040b9SWells Lu /* Copyright Sunplus Technology Co., Ltd.
3*fd3040b9SWells Lu  *       All rights reserved.
4*fd3040b9SWells Lu  */
5*fd3040b9SWells Lu 
6*fd3040b9SWells Lu #include <linux/platform_device.h>
7*fd3040b9SWells Lu #include <linux/nvmem-consumer.h>
8*fd3040b9SWells Lu #include <linux/etherdevice.h>
9*fd3040b9SWells Lu #include <linux/netdevice.h>
10*fd3040b9SWells Lu #include <linux/spinlock.h>
11*fd3040b9SWells Lu #include <linux/of_net.h>
12*fd3040b9SWells Lu #include <linux/reset.h>
13*fd3040b9SWells Lu #include <linux/clk.h>
14*fd3040b9SWells Lu #include <linux/of.h>
15*fd3040b9SWells Lu 
16*fd3040b9SWells Lu #include "spl2sw_register.h"
17*fd3040b9SWells Lu #include "spl2sw_define.h"
18*fd3040b9SWells Lu #include "spl2sw_desc.h"
19*fd3040b9SWells Lu #include "spl2sw_mdio.h"
20*fd3040b9SWells Lu #include "spl2sw_phy.h"
21*fd3040b9SWells Lu #include "spl2sw_int.h"
22*fd3040b9SWells Lu #include "spl2sw_mac.h"
23*fd3040b9SWells Lu 
24*fd3040b9SWells Lu /* net device operations */
25*fd3040b9SWells Lu static int spl2sw_ethernet_open(struct net_device *ndev)
26*fd3040b9SWells Lu {
27*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
28*fd3040b9SWells Lu 	struct spl2sw_common *comm = mac->comm;
29*fd3040b9SWells Lu 	u32 mask;
30*fd3040b9SWells Lu 
31*fd3040b9SWells Lu 	netdev_dbg(ndev, "Open port = %x\n", mac->lan_port);
32*fd3040b9SWells Lu 
33*fd3040b9SWells Lu 	comm->enable |= mac->lan_port;
34*fd3040b9SWells Lu 
35*fd3040b9SWells Lu 	spl2sw_mac_hw_start(comm);
36*fd3040b9SWells Lu 
37*fd3040b9SWells Lu 	/* Enable TX and RX interrupts */
38*fd3040b9SWells Lu 	mask = readl(comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
39*fd3040b9SWells Lu 	mask &= ~(MAC_INT_TX | MAC_INT_RX);
40*fd3040b9SWells Lu 	writel(mask, comm->l2sw_reg_base + L2SW_SW_INT_MASK_0);
41*fd3040b9SWells Lu 
42*fd3040b9SWells Lu 	phy_start(ndev->phydev);
43*fd3040b9SWells Lu 
44*fd3040b9SWells Lu 	netif_start_queue(ndev);
45*fd3040b9SWells Lu 
46*fd3040b9SWells Lu 	return 0;
47*fd3040b9SWells Lu }
48*fd3040b9SWells Lu 
49*fd3040b9SWells Lu static int spl2sw_ethernet_stop(struct net_device *ndev)
50*fd3040b9SWells Lu {
51*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
52*fd3040b9SWells Lu 	struct spl2sw_common *comm = mac->comm;
53*fd3040b9SWells Lu 
54*fd3040b9SWells Lu 	netif_stop_queue(ndev);
55*fd3040b9SWells Lu 
56*fd3040b9SWells Lu 	comm->enable &= ~mac->lan_port;
57*fd3040b9SWells Lu 
58*fd3040b9SWells Lu 	phy_stop(ndev->phydev);
59*fd3040b9SWells Lu 
60*fd3040b9SWells Lu 	spl2sw_mac_hw_stop(comm);
61*fd3040b9SWells Lu 
62*fd3040b9SWells Lu 	return 0;
63*fd3040b9SWells Lu }
64*fd3040b9SWells Lu 
65*fd3040b9SWells Lu static int spl2sw_ethernet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
66*fd3040b9SWells Lu {
67*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
68*fd3040b9SWells Lu 	struct spl2sw_common *comm = mac->comm;
69*fd3040b9SWells Lu 	struct spl2sw_skb_info *skbinfo;
70*fd3040b9SWells Lu 	struct spl2sw_mac_desc *txdesc;
71*fd3040b9SWells Lu 	unsigned long flags;
72*fd3040b9SWells Lu 	u32 mapping;
73*fd3040b9SWells Lu 	u32 tx_pos;
74*fd3040b9SWells Lu 	u32 cmd1;
75*fd3040b9SWells Lu 	u32 cmd2;
76*fd3040b9SWells Lu 
77*fd3040b9SWells Lu 	if (unlikely(comm->tx_desc_full == 1)) {
78*fd3040b9SWells Lu 		/* No TX descriptors left. Wait for tx interrupt. */
79*fd3040b9SWells Lu 		netdev_dbg(ndev, "TX descriptor queue full when xmit!\n");
80*fd3040b9SWells Lu 		return NETDEV_TX_BUSY;
81*fd3040b9SWells Lu 	}
82*fd3040b9SWells Lu 
83*fd3040b9SWells Lu 	/* If skb size is shorter than ETH_ZLEN (60), pad it with 0. */
84*fd3040b9SWells Lu 	if (unlikely(skb->len < ETH_ZLEN)) {
85*fd3040b9SWells Lu 		if (skb_padto(skb, ETH_ZLEN))
86*fd3040b9SWells Lu 			return NETDEV_TX_OK;
87*fd3040b9SWells Lu 
88*fd3040b9SWells Lu 		skb_put(skb, ETH_ZLEN - skb->len);
89*fd3040b9SWells Lu 	}
90*fd3040b9SWells Lu 
91*fd3040b9SWells Lu 	mapping = dma_map_single(&comm->pdev->dev, skb->data,
92*fd3040b9SWells Lu 				 skb->len, DMA_TO_DEVICE);
93*fd3040b9SWells Lu 	if (dma_mapping_error(&comm->pdev->dev, mapping)) {
94*fd3040b9SWells Lu 		ndev->stats.tx_errors++;
95*fd3040b9SWells Lu 		dev_kfree_skb(skb);
96*fd3040b9SWells Lu 		return NETDEV_TX_OK;
97*fd3040b9SWells Lu 	}
98*fd3040b9SWells Lu 
99*fd3040b9SWells Lu 	spin_lock_irqsave(&comm->tx_lock, flags);
100*fd3040b9SWells Lu 
101*fd3040b9SWells Lu 	tx_pos = comm->tx_pos;
102*fd3040b9SWells Lu 	txdesc = &comm->tx_desc[tx_pos];
103*fd3040b9SWells Lu 	skbinfo = &comm->tx_temp_skb_info[tx_pos];
104*fd3040b9SWells Lu 	skbinfo->mapping = mapping;
105*fd3040b9SWells Lu 	skbinfo->len = skb->len;
106*fd3040b9SWells Lu 	skbinfo->skb = skb;
107*fd3040b9SWells Lu 
108*fd3040b9SWells Lu 	/* Set up a TX descriptor */
109*fd3040b9SWells Lu 	cmd1 = TXD_OWN | TXD_SOP | TXD_EOP | (mac->to_vlan << 12) |
110*fd3040b9SWells Lu 	       (skb->len & TXD_PKT_LEN);
111*fd3040b9SWells Lu 	cmd2 = skb->len & TXD_BUF_LEN1;
112*fd3040b9SWells Lu 
113*fd3040b9SWells Lu 	if (tx_pos == (TX_DESC_NUM - 1))
114*fd3040b9SWells Lu 		cmd2 |= TXD_EOR;
115*fd3040b9SWells Lu 
116*fd3040b9SWells Lu 	txdesc->addr1 = skbinfo->mapping;
117*fd3040b9SWells Lu 	txdesc->cmd2 = cmd2;
118*fd3040b9SWells Lu 	wmb();	/* Set TXD_OWN after other fields are effective. */
119*fd3040b9SWells Lu 	txdesc->cmd1 = cmd1;
120*fd3040b9SWells Lu 
121*fd3040b9SWells Lu 	/* Move tx_pos to next position */
122*fd3040b9SWells Lu 	tx_pos = ((tx_pos + 1) == TX_DESC_NUM) ? 0 : tx_pos + 1;
123*fd3040b9SWells Lu 
124*fd3040b9SWells Lu 	if (unlikely(tx_pos == comm->tx_done_pos)) {
125*fd3040b9SWells Lu 		netif_stop_queue(ndev);
126*fd3040b9SWells Lu 		comm->tx_desc_full = 1;
127*fd3040b9SWells Lu 	}
128*fd3040b9SWells Lu 	comm->tx_pos = tx_pos;
129*fd3040b9SWells Lu 	wmb();		/* make sure settings are effective. */
130*fd3040b9SWells Lu 
131*fd3040b9SWells Lu 	/* Trigger mac to transmit */
132*fd3040b9SWells Lu 	writel(MAC_TRIG_L_SOC0, comm->l2sw_reg_base + L2SW_CPU_TX_TRIG);
133*fd3040b9SWells Lu 
134*fd3040b9SWells Lu 	spin_unlock_irqrestore(&comm->tx_lock, flags);
135*fd3040b9SWells Lu 	return NETDEV_TX_OK;
136*fd3040b9SWells Lu }
137*fd3040b9SWells Lu 
138*fd3040b9SWells Lu static void spl2sw_ethernet_set_rx_mode(struct net_device *ndev)
139*fd3040b9SWells Lu {
140*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
141*fd3040b9SWells Lu 
142*fd3040b9SWells Lu 	spl2sw_mac_rx_mode_set(mac);
143*fd3040b9SWells Lu }
144*fd3040b9SWells Lu 
145*fd3040b9SWells Lu static int spl2sw_ethernet_set_mac_address(struct net_device *ndev, void *addr)
146*fd3040b9SWells Lu {
147*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
148*fd3040b9SWells Lu 	int err;
149*fd3040b9SWells Lu 
150*fd3040b9SWells Lu 	err = eth_mac_addr(ndev, addr);
151*fd3040b9SWells Lu 	if (err)
152*fd3040b9SWells Lu 		return err;
153*fd3040b9SWells Lu 
154*fd3040b9SWells Lu 	/* Delete the old MAC address */
155*fd3040b9SWells Lu 	netdev_dbg(ndev, "Old Ethernet (MAC) address = %pM\n", mac->mac_addr);
156*fd3040b9SWells Lu 	if (is_valid_ether_addr(mac->mac_addr)) {
157*fd3040b9SWells Lu 		err = spl2sw_mac_addr_del(mac);
158*fd3040b9SWells Lu 		if (err)
159*fd3040b9SWells Lu 			return err;
160*fd3040b9SWells Lu 	}
161*fd3040b9SWells Lu 
162*fd3040b9SWells Lu 	/* Set the MAC address */
163*fd3040b9SWells Lu 	ether_addr_copy(mac->mac_addr, ndev->dev_addr);
164*fd3040b9SWells Lu 	return spl2sw_mac_addr_add(mac);
165*fd3040b9SWells Lu }
166*fd3040b9SWells Lu 
167*fd3040b9SWells Lu static void spl2sw_ethernet_tx_timeout(struct net_device *ndev, unsigned int txqueue)
168*fd3040b9SWells Lu {
169*fd3040b9SWells Lu 	struct spl2sw_mac *mac = netdev_priv(ndev);
170*fd3040b9SWells Lu 	struct spl2sw_common *comm = mac->comm;
171*fd3040b9SWells Lu 	unsigned long flags;
172*fd3040b9SWells Lu 	int i;
173*fd3040b9SWells Lu 
174*fd3040b9SWells Lu 	netdev_err(ndev, "TX timed out!\n");
175*fd3040b9SWells Lu 	ndev->stats.tx_errors++;
176*fd3040b9SWells Lu 
177*fd3040b9SWells Lu 	spin_lock_irqsave(&comm->tx_lock, flags);
178*fd3040b9SWells Lu 
179*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++)
180*fd3040b9SWells Lu 		if (comm->ndev[i])
181*fd3040b9SWells Lu 			netif_stop_queue(comm->ndev[i]);
182*fd3040b9SWells Lu 
183*fd3040b9SWells Lu 	spl2sw_mac_soft_reset(comm);
184*fd3040b9SWells Lu 
185*fd3040b9SWells Lu 	/* Accept TX packets again. */
186*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++)
187*fd3040b9SWells Lu 		if (comm->ndev[i]) {
188*fd3040b9SWells Lu 			netif_trans_update(comm->ndev[i]);
189*fd3040b9SWells Lu 			netif_wake_queue(comm->ndev[i]);
190*fd3040b9SWells Lu 		}
191*fd3040b9SWells Lu 
192*fd3040b9SWells Lu 	spin_unlock_irqrestore(&comm->tx_lock, flags);
193*fd3040b9SWells Lu }
194*fd3040b9SWells Lu 
195*fd3040b9SWells Lu static const struct net_device_ops netdev_ops = {
196*fd3040b9SWells Lu 	.ndo_open = spl2sw_ethernet_open,
197*fd3040b9SWells Lu 	.ndo_stop = spl2sw_ethernet_stop,
198*fd3040b9SWells Lu 	.ndo_start_xmit = spl2sw_ethernet_start_xmit,
199*fd3040b9SWells Lu 	.ndo_set_rx_mode = spl2sw_ethernet_set_rx_mode,
200*fd3040b9SWells Lu 	.ndo_set_mac_address = spl2sw_ethernet_set_mac_address,
201*fd3040b9SWells Lu 	.ndo_do_ioctl = phy_do_ioctl,
202*fd3040b9SWells Lu 	.ndo_tx_timeout = spl2sw_ethernet_tx_timeout,
203*fd3040b9SWells Lu };
204*fd3040b9SWells Lu 
205*fd3040b9SWells Lu static void spl2sw_check_mac_vendor_id_and_convert(u8 *mac_addr)
206*fd3040b9SWells Lu {
207*fd3040b9SWells Lu 	u8 tmp;
208*fd3040b9SWells Lu 
209*fd3040b9SWells Lu 	/* Byte order of MAC address of some samples are reversed.
210*fd3040b9SWells Lu 	 * Check vendor id and convert byte order if it is wrong.
211*fd3040b9SWells Lu 	 * OUI of Sunplus: fc:4b:bc
212*fd3040b9SWells Lu 	 */
213*fd3040b9SWells Lu 	if (mac_addr[5] == 0xfc && mac_addr[4] == 0x4b && mac_addr[3] == 0xbc &&
214*fd3040b9SWells Lu 	    (mac_addr[0] != 0xfc || mac_addr[1] != 0x4b || mac_addr[2] != 0xbc)) {
215*fd3040b9SWells Lu 		/* Swap mac_addr[0] and mac_addr[5] */
216*fd3040b9SWells Lu 		tmp = mac_addr[0];
217*fd3040b9SWells Lu 		mac_addr[0] = mac_addr[5];
218*fd3040b9SWells Lu 		mac_addr[5] = tmp;
219*fd3040b9SWells Lu 
220*fd3040b9SWells Lu 		/* Swap mac_addr[1] and mac_addr[4] */
221*fd3040b9SWells Lu 		tmp = mac_addr[1];
222*fd3040b9SWells Lu 		mac_addr[1] = mac_addr[4];
223*fd3040b9SWells Lu 		mac_addr[4] = tmp;
224*fd3040b9SWells Lu 
225*fd3040b9SWells Lu 		/* Swap mac_addr[2] and mac_addr[3] */
226*fd3040b9SWells Lu 		tmp = mac_addr[2];
227*fd3040b9SWells Lu 		mac_addr[2] = mac_addr[3];
228*fd3040b9SWells Lu 		mac_addr[3] = tmp;
229*fd3040b9SWells Lu 	}
230*fd3040b9SWells Lu }
231*fd3040b9SWells Lu 
232*fd3040b9SWells Lu static int spl2sw_nvmem_get_mac_address(struct device *dev, struct device_node *np,
233*fd3040b9SWells Lu 					void *addrbuf)
234*fd3040b9SWells Lu {
235*fd3040b9SWells Lu 	struct nvmem_cell *cell;
236*fd3040b9SWells Lu 	ssize_t len;
237*fd3040b9SWells Lu 	u8 *mac;
238*fd3040b9SWells Lu 
239*fd3040b9SWells Lu 	/* Get nvmem cell of mac-address from dts. */
240*fd3040b9SWells Lu 	cell = of_nvmem_cell_get(np, "mac-address");
241*fd3040b9SWells Lu 	if (IS_ERR(cell))
242*fd3040b9SWells Lu 		return PTR_ERR(cell);
243*fd3040b9SWells Lu 
244*fd3040b9SWells Lu 	/* Read mac address from nvmem cell. */
245*fd3040b9SWells Lu 	mac = nvmem_cell_read(cell, &len);
246*fd3040b9SWells Lu 	nvmem_cell_put(cell);
247*fd3040b9SWells Lu 	if (IS_ERR(mac))
248*fd3040b9SWells Lu 		return PTR_ERR(mac);
249*fd3040b9SWells Lu 
250*fd3040b9SWells Lu 	if (len != ETH_ALEN) {
251*fd3040b9SWells Lu 		kfree(mac);
252*fd3040b9SWells Lu 		dev_info(dev, "Invalid length of mac address in nvmem!\n");
253*fd3040b9SWells Lu 		return -EINVAL;
254*fd3040b9SWells Lu 	}
255*fd3040b9SWells Lu 
256*fd3040b9SWells Lu 	/* Byte order of some samples are reversed.
257*fd3040b9SWells Lu 	 * Convert byte order here.
258*fd3040b9SWells Lu 	 */
259*fd3040b9SWells Lu 	spl2sw_check_mac_vendor_id_and_convert(mac);
260*fd3040b9SWells Lu 
261*fd3040b9SWells Lu 	/* Check if mac address is valid */
262*fd3040b9SWells Lu 	if (!is_valid_ether_addr(mac)) {
263*fd3040b9SWells Lu 		kfree(mac);
264*fd3040b9SWells Lu 		dev_info(dev, "Invalid mac address in nvmem (%pM)!\n", mac);
265*fd3040b9SWells Lu 		return -EINVAL;
266*fd3040b9SWells Lu 	}
267*fd3040b9SWells Lu 
268*fd3040b9SWells Lu 	ether_addr_copy(addrbuf, mac);
269*fd3040b9SWells Lu 	kfree(mac);
270*fd3040b9SWells Lu 	return 0;
271*fd3040b9SWells Lu }
272*fd3040b9SWells Lu 
273*fd3040b9SWells Lu static u32 spl2sw_init_netdev(struct platform_device *pdev, u8 *mac_addr,
274*fd3040b9SWells Lu 			      struct net_device **r_ndev)
275*fd3040b9SWells Lu {
276*fd3040b9SWells Lu 	struct net_device *ndev;
277*fd3040b9SWells Lu 	struct spl2sw_mac *mac;
278*fd3040b9SWells Lu 	int ret;
279*fd3040b9SWells Lu 
280*fd3040b9SWells Lu 	/* Allocate the devices, and also allocate spl2sw_mac,
281*fd3040b9SWells Lu 	 * we can get it by netdev_priv().
282*fd3040b9SWells Lu 	 */
283*fd3040b9SWells Lu 	ndev = devm_alloc_etherdev(&pdev->dev, sizeof(*mac));
284*fd3040b9SWells Lu 	if (!ndev) {
285*fd3040b9SWells Lu 		*r_ndev = NULL;
286*fd3040b9SWells Lu 		return -ENOMEM;
287*fd3040b9SWells Lu 	}
288*fd3040b9SWells Lu 	SET_NETDEV_DEV(ndev, &pdev->dev);
289*fd3040b9SWells Lu 	ndev->netdev_ops = &netdev_ops;
290*fd3040b9SWells Lu 	mac = netdev_priv(ndev);
291*fd3040b9SWells Lu 	mac->ndev = ndev;
292*fd3040b9SWells Lu 	ether_addr_copy(mac->mac_addr, mac_addr);
293*fd3040b9SWells Lu 
294*fd3040b9SWells Lu 	eth_hw_addr_set(ndev, mac_addr);
295*fd3040b9SWells Lu 	dev_info(&pdev->dev, "Ethernet (MAC) address = %pM\n", mac_addr);
296*fd3040b9SWells Lu 
297*fd3040b9SWells Lu 	ret = register_netdev(ndev);
298*fd3040b9SWells Lu 	if (ret) {
299*fd3040b9SWells Lu 		dev_err(&pdev->dev, "Failed to register net device \"%s\"!\n",
300*fd3040b9SWells Lu 			ndev->name);
301*fd3040b9SWells Lu 		free_netdev(ndev);
302*fd3040b9SWells Lu 		*r_ndev = NULL;
303*fd3040b9SWells Lu 		return ret;
304*fd3040b9SWells Lu 	}
305*fd3040b9SWells Lu 	netdev_dbg(ndev, "Registered net device \"%s\" successfully.\n", ndev->name);
306*fd3040b9SWells Lu 
307*fd3040b9SWells Lu 	*r_ndev = ndev;
308*fd3040b9SWells Lu 	return 0;
309*fd3040b9SWells Lu }
310*fd3040b9SWells Lu 
311*fd3040b9SWells Lu static struct device_node *spl2sw_get_eth_child_node(struct device_node *ether_np, int id)
312*fd3040b9SWells Lu {
313*fd3040b9SWells Lu 	struct device_node *port_np;
314*fd3040b9SWells Lu 	int port_id;
315*fd3040b9SWells Lu 
316*fd3040b9SWells Lu 	for_each_child_of_node(ether_np, port_np) {
317*fd3040b9SWells Lu 		/* It is not a 'port' node, continue. */
318*fd3040b9SWells Lu 		if (strcmp(port_np->name, "port"))
319*fd3040b9SWells Lu 			continue;
320*fd3040b9SWells Lu 
321*fd3040b9SWells Lu 		if (of_property_read_u32(port_np, "reg", &port_id) < 0)
322*fd3040b9SWells Lu 			continue;
323*fd3040b9SWells Lu 
324*fd3040b9SWells Lu 		if (port_id == id)
325*fd3040b9SWells Lu 			return port_np;
326*fd3040b9SWells Lu 	}
327*fd3040b9SWells Lu 
328*fd3040b9SWells Lu 	/* Not found! */
329*fd3040b9SWells Lu 	return NULL;
330*fd3040b9SWells Lu }
331*fd3040b9SWells Lu 
332*fd3040b9SWells Lu static int spl2sw_probe(struct platform_device *pdev)
333*fd3040b9SWells Lu {
334*fd3040b9SWells Lu 	struct device_node *eth_ports_np;
335*fd3040b9SWells Lu 	struct device_node *port_np;
336*fd3040b9SWells Lu 	struct spl2sw_common *comm;
337*fd3040b9SWells Lu 	struct device_node *phy_np;
338*fd3040b9SWells Lu 	phy_interface_t phy_mode;
339*fd3040b9SWells Lu 	struct net_device *ndev;
340*fd3040b9SWells Lu 	struct spl2sw_mac *mac;
341*fd3040b9SWells Lu 	u8 mac_addr[ETH_ALEN];
342*fd3040b9SWells Lu 	int irq, i, ret;
343*fd3040b9SWells Lu 
344*fd3040b9SWells Lu 	if (platform_get_drvdata(pdev))
345*fd3040b9SWells Lu 		return -ENODEV;
346*fd3040b9SWells Lu 
347*fd3040b9SWells Lu 	/* Allocate memory for 'spl2sw_common' area. */
348*fd3040b9SWells Lu 	comm = devm_kzalloc(&pdev->dev, sizeof(*comm), GFP_KERNEL);
349*fd3040b9SWells Lu 	if (!comm)
350*fd3040b9SWells Lu 		return -ENOMEM;
351*fd3040b9SWells Lu 
352*fd3040b9SWells Lu 	comm->pdev = pdev;
353*fd3040b9SWells Lu 	platform_set_drvdata(pdev, comm);
354*fd3040b9SWells Lu 
355*fd3040b9SWells Lu 	spin_lock_init(&comm->tx_lock);
356*fd3040b9SWells Lu 	spin_lock_init(&comm->mdio_lock);
357*fd3040b9SWells Lu 	spin_lock_init(&comm->int_mask_lock);
358*fd3040b9SWells Lu 
359*fd3040b9SWells Lu 	/* Get memory resource 0 from dts. */
360*fd3040b9SWells Lu 	comm->l2sw_reg_base = devm_platform_ioremap_resource(pdev, 0);
361*fd3040b9SWells Lu 	if (IS_ERR(comm->l2sw_reg_base))
362*fd3040b9SWells Lu 		return PTR_ERR(comm->l2sw_reg_base);
363*fd3040b9SWells Lu 
364*fd3040b9SWells Lu 	/* Get irq resource from dts. */
365*fd3040b9SWells Lu 	ret = platform_get_irq(pdev, 0);
366*fd3040b9SWells Lu 	if (ret < 0)
367*fd3040b9SWells Lu 		return ret;
368*fd3040b9SWells Lu 	irq = ret;
369*fd3040b9SWells Lu 
370*fd3040b9SWells Lu 	/* Get clock controller. */
371*fd3040b9SWells Lu 	comm->clk = devm_clk_get(&pdev->dev, NULL);
372*fd3040b9SWells Lu 	if (IS_ERR(comm->clk)) {
373*fd3040b9SWells Lu 		dev_err_probe(&pdev->dev, PTR_ERR(comm->clk),
374*fd3040b9SWells Lu 			      "Failed to retrieve clock controller!\n");
375*fd3040b9SWells Lu 		return PTR_ERR(comm->clk);
376*fd3040b9SWells Lu 	}
377*fd3040b9SWells Lu 
378*fd3040b9SWells Lu 	/* Get reset controller. */
379*fd3040b9SWells Lu 	comm->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
380*fd3040b9SWells Lu 	if (IS_ERR(comm->rstc)) {
381*fd3040b9SWells Lu 		dev_err_probe(&pdev->dev, PTR_ERR(comm->rstc),
382*fd3040b9SWells Lu 			      "Failed to retrieve reset controller!\n");
383*fd3040b9SWells Lu 		return PTR_ERR(comm->rstc);
384*fd3040b9SWells Lu 	}
385*fd3040b9SWells Lu 
386*fd3040b9SWells Lu 	/* Enable clock. */
387*fd3040b9SWells Lu 	ret = clk_prepare_enable(comm->clk);
388*fd3040b9SWells Lu 	if (ret)
389*fd3040b9SWells Lu 		return ret;
390*fd3040b9SWells Lu 	udelay(1);
391*fd3040b9SWells Lu 
392*fd3040b9SWells Lu 	/* Reset MAC */
393*fd3040b9SWells Lu 	reset_control_assert(comm->rstc);
394*fd3040b9SWells Lu 	udelay(1);
395*fd3040b9SWells Lu 	reset_control_deassert(comm->rstc);
396*fd3040b9SWells Lu 	usleep_range(1000, 2000);
397*fd3040b9SWells Lu 
398*fd3040b9SWells Lu 	/* Request irq. */
399*fd3040b9SWells Lu 	ret = devm_request_irq(&pdev->dev, irq, spl2sw_ethernet_interrupt, 0,
400*fd3040b9SWells Lu 			       dev_name(&pdev->dev), comm);
401*fd3040b9SWells Lu 	if (ret) {
402*fd3040b9SWells Lu 		dev_err(&pdev->dev, "Failed to request irq #%d!\n", irq);
403*fd3040b9SWells Lu 		goto out_clk_disable;
404*fd3040b9SWells Lu 	}
405*fd3040b9SWells Lu 
406*fd3040b9SWells Lu 	/* Initialize TX and RX descriptors. */
407*fd3040b9SWells Lu 	ret = spl2sw_descs_init(comm);
408*fd3040b9SWells Lu 	if (ret) {
409*fd3040b9SWells Lu 		dev_err(&pdev->dev, "Fail to initialize mac descriptors!\n");
410*fd3040b9SWells Lu 		spl2sw_descs_free(comm);
411*fd3040b9SWells Lu 		goto out_clk_disable;
412*fd3040b9SWells Lu 	}
413*fd3040b9SWells Lu 
414*fd3040b9SWells Lu 	/* Initialize MAC. */
415*fd3040b9SWells Lu 	spl2sw_mac_init(comm);
416*fd3040b9SWells Lu 
417*fd3040b9SWells Lu 	/* Initialize mdio bus */
418*fd3040b9SWells Lu 	ret = spl2sw_mdio_init(comm);
419*fd3040b9SWells Lu 	if (ret) {
420*fd3040b9SWells Lu 		dev_err(&pdev->dev, "Failed to initialize mdio bus!\n");
421*fd3040b9SWells Lu 		goto out_clk_disable;
422*fd3040b9SWells Lu 	}
423*fd3040b9SWells Lu 
424*fd3040b9SWells Lu 	/* Get child node ethernet-ports. */
425*fd3040b9SWells Lu 	eth_ports_np = of_get_child_by_name(pdev->dev.of_node, "ethernet-ports");
426*fd3040b9SWells Lu 	if (!eth_ports_np) {
427*fd3040b9SWells Lu 		dev_err(&pdev->dev, "No ethernet-ports child node found!\n");
428*fd3040b9SWells Lu 		ret = -ENODEV;
429*fd3040b9SWells Lu 		goto out_free_mdio;
430*fd3040b9SWells Lu 	}
431*fd3040b9SWells Lu 
432*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++) {
433*fd3040b9SWells Lu 		/* Get port@i of node ethernet-ports. */
434*fd3040b9SWells Lu 		port_np = spl2sw_get_eth_child_node(eth_ports_np, i);
435*fd3040b9SWells Lu 		if (!port_np)
436*fd3040b9SWells Lu 			continue;
437*fd3040b9SWells Lu 
438*fd3040b9SWells Lu 		/* Get phy-mode. */
439*fd3040b9SWells Lu 		if (of_get_phy_mode(port_np, &phy_mode)) {
440*fd3040b9SWells Lu 			dev_err(&pdev->dev, "Failed to get phy-mode property of port@%d!\n",
441*fd3040b9SWells Lu 				i);
442*fd3040b9SWells Lu 			continue;
443*fd3040b9SWells Lu 		}
444*fd3040b9SWells Lu 
445*fd3040b9SWells Lu 		/* Get phy-handle. */
446*fd3040b9SWells Lu 		phy_np = of_parse_phandle(port_np, "phy-handle", 0);
447*fd3040b9SWells Lu 		if (!phy_np) {
448*fd3040b9SWells Lu 			dev_err(&pdev->dev, "Failed to get phy-handle property of port@%d!\n",
449*fd3040b9SWells Lu 				i);
450*fd3040b9SWells Lu 			continue;
451*fd3040b9SWells Lu 		}
452*fd3040b9SWells Lu 
453*fd3040b9SWells Lu 		/* Get mac-address from nvmem. */
454*fd3040b9SWells Lu 		ret = spl2sw_nvmem_get_mac_address(&pdev->dev, port_np, mac_addr);
455*fd3040b9SWells Lu 		if (ret == -EPROBE_DEFER) {
456*fd3040b9SWells Lu 			goto out_unregister_dev;
457*fd3040b9SWells Lu 		} else if (ret) {
458*fd3040b9SWells Lu 			dev_info(&pdev->dev, "Generate a random mac address!\n");
459*fd3040b9SWells Lu 			eth_random_addr(mac_addr);
460*fd3040b9SWells Lu 		}
461*fd3040b9SWells Lu 
462*fd3040b9SWells Lu 		/* Initialize the net device. */
463*fd3040b9SWells Lu 		ret = spl2sw_init_netdev(pdev, mac_addr, &ndev);
464*fd3040b9SWells Lu 		if (ret)
465*fd3040b9SWells Lu 			goto out_unregister_dev;
466*fd3040b9SWells Lu 
467*fd3040b9SWells Lu 		ndev->irq = irq;
468*fd3040b9SWells Lu 		comm->ndev[i] = ndev;
469*fd3040b9SWells Lu 		mac = netdev_priv(ndev);
470*fd3040b9SWells Lu 		mac->phy_node = phy_np;
471*fd3040b9SWells Lu 		mac->phy_mode = phy_mode;
472*fd3040b9SWells Lu 		mac->comm = comm;
473*fd3040b9SWells Lu 
474*fd3040b9SWells Lu 		mac->lan_port = 0x1 << i;	/* forward to port i */
475*fd3040b9SWells Lu 		mac->to_vlan = 0x1 << i;	/* vlan group: i     */
476*fd3040b9SWells Lu 		mac->vlan_id = i;		/* vlan group: i     */
477*fd3040b9SWells Lu 
478*fd3040b9SWells Lu 		/* Set MAC address */
479*fd3040b9SWells Lu 		ret = spl2sw_mac_addr_add(mac);
480*fd3040b9SWells Lu 		if (ret)
481*fd3040b9SWells Lu 			goto out_unregister_dev;
482*fd3040b9SWells Lu 
483*fd3040b9SWells Lu 		spl2sw_mac_rx_mode_set(mac);
484*fd3040b9SWells Lu 	}
485*fd3040b9SWells Lu 
486*fd3040b9SWells Lu 	/* Find first valid net device. */
487*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++) {
488*fd3040b9SWells Lu 		if (comm->ndev[i])
489*fd3040b9SWells Lu 			break;
490*fd3040b9SWells Lu 	}
491*fd3040b9SWells Lu 	if (i >= MAX_NETDEV_NUM) {
492*fd3040b9SWells Lu 		dev_err(&pdev->dev, "No valid ethernet port!\n");
493*fd3040b9SWells Lu 		ret = -ENODEV;
494*fd3040b9SWells Lu 		goto out_free_mdio;
495*fd3040b9SWells Lu 	}
496*fd3040b9SWells Lu 
497*fd3040b9SWells Lu 	/* Save first valid net device */
498*fd3040b9SWells Lu 	ndev = comm->ndev[i];
499*fd3040b9SWells Lu 
500*fd3040b9SWells Lu 	ret = spl2sw_phy_connect(comm);
501*fd3040b9SWells Lu 	if (ret) {
502*fd3040b9SWells Lu 		netdev_err(ndev, "Failed to connect phy!\n");
503*fd3040b9SWells Lu 		goto out_unregister_dev;
504*fd3040b9SWells Lu 	}
505*fd3040b9SWells Lu 
506*fd3040b9SWells Lu 	/* Add and enable napi. */
507*fd3040b9SWells Lu 	netif_napi_add(ndev, &comm->rx_napi, spl2sw_rx_poll, NAPI_POLL_WEIGHT);
508*fd3040b9SWells Lu 	napi_enable(&comm->rx_napi);
509*fd3040b9SWells Lu 	netif_napi_add(ndev, &comm->tx_napi, spl2sw_tx_poll, NAPI_POLL_WEIGHT);
510*fd3040b9SWells Lu 	napi_enable(&comm->tx_napi);
511*fd3040b9SWells Lu 	return 0;
512*fd3040b9SWells Lu 
513*fd3040b9SWells Lu out_unregister_dev:
514*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++)
515*fd3040b9SWells Lu 		if (comm->ndev[i])
516*fd3040b9SWells Lu 			unregister_netdev(comm->ndev[i]);
517*fd3040b9SWells Lu 
518*fd3040b9SWells Lu out_free_mdio:
519*fd3040b9SWells Lu 	spl2sw_mdio_remove(comm);
520*fd3040b9SWells Lu 
521*fd3040b9SWells Lu out_clk_disable:
522*fd3040b9SWells Lu 	clk_disable_unprepare(comm->clk);
523*fd3040b9SWells Lu 	return ret;
524*fd3040b9SWells Lu }
525*fd3040b9SWells Lu 
526*fd3040b9SWells Lu static int spl2sw_remove(struct platform_device *pdev)
527*fd3040b9SWells Lu {
528*fd3040b9SWells Lu 	struct spl2sw_common *comm;
529*fd3040b9SWells Lu 	int i;
530*fd3040b9SWells Lu 
531*fd3040b9SWells Lu 	comm = platform_get_drvdata(pdev);
532*fd3040b9SWells Lu 
533*fd3040b9SWells Lu 	spl2sw_phy_remove(comm);
534*fd3040b9SWells Lu 
535*fd3040b9SWells Lu 	/* Unregister and free net device. */
536*fd3040b9SWells Lu 	for (i = 0; i < MAX_NETDEV_NUM; i++)
537*fd3040b9SWells Lu 		if (comm->ndev[i])
538*fd3040b9SWells Lu 			unregister_netdev(comm->ndev[i]);
539*fd3040b9SWells Lu 
540*fd3040b9SWells Lu 	comm->enable = 0;
541*fd3040b9SWells Lu 	spl2sw_mac_hw_stop(comm);
542*fd3040b9SWells Lu 	spl2sw_descs_free(comm);
543*fd3040b9SWells Lu 
544*fd3040b9SWells Lu 	/* Disable and delete napi. */
545*fd3040b9SWells Lu 	napi_disable(&comm->rx_napi);
546*fd3040b9SWells Lu 	netif_napi_del(&comm->rx_napi);
547*fd3040b9SWells Lu 	napi_disable(&comm->tx_napi);
548*fd3040b9SWells Lu 	netif_napi_del(&comm->tx_napi);
549*fd3040b9SWells Lu 
550*fd3040b9SWells Lu 	spl2sw_mdio_remove(comm);
551*fd3040b9SWells Lu 
552*fd3040b9SWells Lu 	clk_disable_unprepare(comm->clk);
553*fd3040b9SWells Lu 
554*fd3040b9SWells Lu 	return 0;
555*fd3040b9SWells Lu }
556*fd3040b9SWells Lu 
557*fd3040b9SWells Lu static const struct of_device_id spl2sw_of_match[] = {
558*fd3040b9SWells Lu 	{.compatible = "sunplus,sp7021-emac"},
559*fd3040b9SWells Lu 	{ /* sentinel */ }
560*fd3040b9SWells Lu };
561*fd3040b9SWells Lu 
562*fd3040b9SWells Lu MODULE_DEVICE_TABLE(of, spl2sw_of_match);
563*fd3040b9SWells Lu 
564*fd3040b9SWells Lu static struct platform_driver spl2sw_driver = {
565*fd3040b9SWells Lu 	.probe = spl2sw_probe,
566*fd3040b9SWells Lu 	.remove = spl2sw_remove,
567*fd3040b9SWells Lu 	.driver = {
568*fd3040b9SWells Lu 		.name = "sp7021_emac",
569*fd3040b9SWells Lu 		.owner = THIS_MODULE,
570*fd3040b9SWells Lu 		.of_match_table = spl2sw_of_match,
571*fd3040b9SWells Lu 	},
572*fd3040b9SWells Lu };
573*fd3040b9SWells Lu 
574*fd3040b9SWells Lu module_platform_driver(spl2sw_driver);
575*fd3040b9SWells Lu 
576*fd3040b9SWells Lu MODULE_AUTHOR("Wells Lu <wellslutw@gmail.com>");
577*fd3040b9SWells Lu MODULE_DESCRIPTION("Sunplus Dual 10M/100M Ethernet driver");
578*fd3040b9SWells Lu MODULE_LICENSE("GPL");
579