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