180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2630cf097SAkinobu Mita /*
335ef7d68SAkinobu Mita  * Ethernet driver for the WIZnet W5100/W5200/W5500 chip.
4630cf097SAkinobu Mita  *
5630cf097SAkinobu Mita  * Copyright (C) 2016 Akinobu Mita <akinobu.mita@gmail.com>
6630cf097SAkinobu Mita  *
70c165ff2SAkinobu Mita  * Datasheet:
80c165ff2SAkinobu Mita  * http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf
90c165ff2SAkinobu Mita  * http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf
1035ef7d68SAkinobu Mita  * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf
11630cf097SAkinobu Mita  */
12630cf097SAkinobu Mita 
13630cf097SAkinobu Mita #include <linux/kernel.h>
14630cf097SAkinobu Mita #include <linux/module.h>
15630cf097SAkinobu Mita #include <linux/delay.h>
16630cf097SAkinobu Mita #include <linux/netdevice.h>
17c3875ca7SAkinobu Mita #include <linux/of_net.h>
18b9dd694eSNicolas Saenz Julienne #include <linux/of_device.h>
19630cf097SAkinobu Mita #include <linux/spi/spi.h>
20630cf097SAkinobu Mita 
21630cf097SAkinobu Mita #include "w5100.h"
22630cf097SAkinobu Mita 
23630cf097SAkinobu Mita #define W5100_SPI_WRITE_OPCODE 0xf0
24630cf097SAkinobu Mita #define W5100_SPI_READ_OPCODE 0x0f
25630cf097SAkinobu Mita 
w5100_spi_read(struct net_device * ndev,u32 addr)2635ef7d68SAkinobu Mita static int w5100_spi_read(struct net_device *ndev, u32 addr)
27630cf097SAkinobu Mita {
28630cf097SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
29630cf097SAkinobu Mita 	u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff };
30630cf097SAkinobu Mita 	u8 data;
31630cf097SAkinobu Mita 	int ret;
32630cf097SAkinobu Mita 
33630cf097SAkinobu Mita 	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
34630cf097SAkinobu Mita 
35630cf097SAkinobu Mita 	return ret ? ret : data;
36630cf097SAkinobu Mita }
37630cf097SAkinobu Mita 
w5100_spi_write(struct net_device * ndev,u32 addr,u8 data)3835ef7d68SAkinobu Mita static int w5100_spi_write(struct net_device *ndev, u32 addr, u8 data)
39630cf097SAkinobu Mita {
40630cf097SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
41630cf097SAkinobu Mita 	u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data};
42630cf097SAkinobu Mita 
43630cf097SAkinobu Mita 	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
44630cf097SAkinobu Mita }
45630cf097SAkinobu Mita 
w5100_spi_read16(struct net_device * ndev,u32 addr)4635ef7d68SAkinobu Mita static int w5100_spi_read16(struct net_device *ndev, u32 addr)
47630cf097SAkinobu Mita {
48630cf097SAkinobu Mita 	u16 data;
49630cf097SAkinobu Mita 	int ret;
50630cf097SAkinobu Mita 
51630cf097SAkinobu Mita 	ret = w5100_spi_read(ndev, addr);
52630cf097SAkinobu Mita 	if (ret < 0)
53630cf097SAkinobu Mita 		return ret;
54630cf097SAkinobu Mita 	data = ret << 8;
55630cf097SAkinobu Mita 	ret = w5100_spi_read(ndev, addr + 1);
56630cf097SAkinobu Mita 
57630cf097SAkinobu Mita 	return ret < 0 ? ret : data | ret;
58630cf097SAkinobu Mita }
59630cf097SAkinobu Mita 
w5100_spi_write16(struct net_device * ndev,u32 addr,u16 data)6035ef7d68SAkinobu Mita static int w5100_spi_write16(struct net_device *ndev, u32 addr, u16 data)
61630cf097SAkinobu Mita {
62630cf097SAkinobu Mita 	int ret;
63630cf097SAkinobu Mita 
64630cf097SAkinobu Mita 	ret = w5100_spi_write(ndev, addr, data >> 8);
65630cf097SAkinobu Mita 	if (ret)
66630cf097SAkinobu Mita 		return ret;
67630cf097SAkinobu Mita 
68630cf097SAkinobu Mita 	return w5100_spi_write(ndev, addr + 1, data & 0xff);
69630cf097SAkinobu Mita }
70630cf097SAkinobu Mita 
w5100_spi_readbulk(struct net_device * ndev,u32 addr,u8 * buf,int len)7135ef7d68SAkinobu Mita static int w5100_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
72630cf097SAkinobu Mita 			      int len)
73630cf097SAkinobu Mita {
74630cf097SAkinobu Mita 	int i;
75630cf097SAkinobu Mita 
76630cf097SAkinobu Mita 	for (i = 0; i < len; i++) {
77630cf097SAkinobu Mita 		int ret = w5100_spi_read(ndev, addr + i);
78630cf097SAkinobu Mita 
79630cf097SAkinobu Mita 		if (ret < 0)
80630cf097SAkinobu Mita 			return ret;
81630cf097SAkinobu Mita 		buf[i] = ret;
82630cf097SAkinobu Mita 	}
83630cf097SAkinobu Mita 
84630cf097SAkinobu Mita 	return 0;
85630cf097SAkinobu Mita }
86630cf097SAkinobu Mita 
w5100_spi_writebulk(struct net_device * ndev,u32 addr,const u8 * buf,int len)8735ef7d68SAkinobu Mita static int w5100_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
88630cf097SAkinobu Mita 			       int len)
89630cf097SAkinobu Mita {
90630cf097SAkinobu Mita 	int i;
91630cf097SAkinobu Mita 
92630cf097SAkinobu Mita 	for (i = 0; i < len; i++) {
93630cf097SAkinobu Mita 		int ret = w5100_spi_write(ndev, addr + i, buf[i]);
94630cf097SAkinobu Mita 
95630cf097SAkinobu Mita 		if (ret)
96630cf097SAkinobu Mita 			return ret;
97630cf097SAkinobu Mita 	}
98630cf097SAkinobu Mita 
99630cf097SAkinobu Mita 	return 0;
100630cf097SAkinobu Mita }
101630cf097SAkinobu Mita 
102630cf097SAkinobu Mita static const struct w5100_ops w5100_spi_ops = {
103630cf097SAkinobu Mita 	.may_sleep = true,
1040c165ff2SAkinobu Mita 	.chip_id = W5100,
105630cf097SAkinobu Mita 	.read = w5100_spi_read,
106630cf097SAkinobu Mita 	.write = w5100_spi_write,
107630cf097SAkinobu Mita 	.read16 = w5100_spi_read16,
108630cf097SAkinobu Mita 	.write16 = w5100_spi_write16,
109630cf097SAkinobu Mita 	.readbulk = w5100_spi_readbulk,
110630cf097SAkinobu Mita 	.writebulk = w5100_spi_writebulk,
111630cf097SAkinobu Mita };
112630cf097SAkinobu Mita 
1130c165ff2SAkinobu Mita #define W5200_SPI_WRITE_OPCODE 0x80
1140c165ff2SAkinobu Mita 
1150c165ff2SAkinobu Mita struct w5200_spi_priv {
1160c165ff2SAkinobu Mita 	/* Serialize access to cmd_buf */
1170c165ff2SAkinobu Mita 	struct mutex cmd_lock;
1180c165ff2SAkinobu Mita 
1190c165ff2SAkinobu Mita 	/* DMA (thus cache coherency maintenance) requires the
1200c165ff2SAkinobu Mita 	 * transfer buffers to live in their own cache lines.
1210c165ff2SAkinobu Mita 	 */
1220c165ff2SAkinobu Mita 	u8 cmd_buf[4] ____cacheline_aligned;
1230c165ff2SAkinobu Mita };
1240c165ff2SAkinobu Mita 
w5200_spi_priv(struct net_device * ndev)1250c165ff2SAkinobu Mita static struct w5200_spi_priv *w5200_spi_priv(struct net_device *ndev)
1260c165ff2SAkinobu Mita {
1270c165ff2SAkinobu Mita 	return w5100_ops_priv(ndev);
1280c165ff2SAkinobu Mita }
1290c165ff2SAkinobu Mita 
w5200_spi_init(struct net_device * ndev)1300c165ff2SAkinobu Mita static int w5200_spi_init(struct net_device *ndev)
1310c165ff2SAkinobu Mita {
1320c165ff2SAkinobu Mita 	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
1330c165ff2SAkinobu Mita 
1340c165ff2SAkinobu Mita 	mutex_init(&spi_priv->cmd_lock);
1350c165ff2SAkinobu Mita 
1360c165ff2SAkinobu Mita 	return 0;
1370c165ff2SAkinobu Mita }
1380c165ff2SAkinobu Mita 
w5200_spi_read(struct net_device * ndev,u32 addr)13935ef7d68SAkinobu Mita static int w5200_spi_read(struct net_device *ndev, u32 addr)
1400c165ff2SAkinobu Mita {
1410c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
1420c165ff2SAkinobu Mita 	u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 };
1430c165ff2SAkinobu Mita 	u8 data;
1440c165ff2SAkinobu Mita 	int ret;
1450c165ff2SAkinobu Mita 
1460c165ff2SAkinobu Mita 	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
1470c165ff2SAkinobu Mita 
1480c165ff2SAkinobu Mita 	return ret ? ret : data;
1490c165ff2SAkinobu Mita }
1500c165ff2SAkinobu Mita 
w5200_spi_write(struct net_device * ndev,u32 addr,u8 data)15135ef7d68SAkinobu Mita static int w5200_spi_write(struct net_device *ndev, u32 addr, u8 data)
1520c165ff2SAkinobu Mita {
1530c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
1540c165ff2SAkinobu Mita 	u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data };
1550c165ff2SAkinobu Mita 
1560c165ff2SAkinobu Mita 	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
1570c165ff2SAkinobu Mita }
1580c165ff2SAkinobu Mita 
w5200_spi_read16(struct net_device * ndev,u32 addr)15935ef7d68SAkinobu Mita static int w5200_spi_read16(struct net_device *ndev, u32 addr)
1600c165ff2SAkinobu Mita {
1610c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
1620c165ff2SAkinobu Mita 	u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 };
1630c165ff2SAkinobu Mita 	__be16 data;
1640c165ff2SAkinobu Mita 	int ret;
1650c165ff2SAkinobu Mita 
1660c165ff2SAkinobu Mita 	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data));
1670c165ff2SAkinobu Mita 
1680c165ff2SAkinobu Mita 	return ret ? ret : be16_to_cpu(data);
1690c165ff2SAkinobu Mita }
1700c165ff2SAkinobu Mita 
w5200_spi_write16(struct net_device * ndev,u32 addr,u16 data)17135ef7d68SAkinobu Mita static int w5200_spi_write16(struct net_device *ndev, u32 addr, u16 data)
1720c165ff2SAkinobu Mita {
1730c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
1740c165ff2SAkinobu Mita 	u8 cmd[6] = {
1750c165ff2SAkinobu Mita 		addr >> 8, addr & 0xff,
1760c165ff2SAkinobu Mita 		W5200_SPI_WRITE_OPCODE, 2,
1770c165ff2SAkinobu Mita 		data >> 8, data & 0xff
1780c165ff2SAkinobu Mita 	};
1790c165ff2SAkinobu Mita 
1800c165ff2SAkinobu Mita 	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
1810c165ff2SAkinobu Mita }
1820c165ff2SAkinobu Mita 
w5200_spi_readbulk(struct net_device * ndev,u32 addr,u8 * buf,int len)18335ef7d68SAkinobu Mita static int w5200_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
1840c165ff2SAkinobu Mita 			      int len)
1850c165ff2SAkinobu Mita {
1860c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
1870c165ff2SAkinobu Mita 	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
1880c165ff2SAkinobu Mita 	struct spi_transfer xfer[] = {
1890c165ff2SAkinobu Mita 		{
1900c165ff2SAkinobu Mita 			.tx_buf = spi_priv->cmd_buf,
1910c165ff2SAkinobu Mita 			.len = sizeof(spi_priv->cmd_buf),
1920c165ff2SAkinobu Mita 		},
1930c165ff2SAkinobu Mita 		{
1940c165ff2SAkinobu Mita 			.rx_buf = buf,
1950c165ff2SAkinobu Mita 			.len = len,
1960c165ff2SAkinobu Mita 		},
1970c165ff2SAkinobu Mita 	};
1980c165ff2SAkinobu Mita 	int ret;
1990c165ff2SAkinobu Mita 
2000c165ff2SAkinobu Mita 	mutex_lock(&spi_priv->cmd_lock);
2010c165ff2SAkinobu Mita 
2020c165ff2SAkinobu Mita 	spi_priv->cmd_buf[0] = addr >> 8;
2030c165ff2SAkinobu Mita 	spi_priv->cmd_buf[1] = addr;
2040c165ff2SAkinobu Mita 	spi_priv->cmd_buf[2] = len >> 8;
2050c165ff2SAkinobu Mita 	spi_priv->cmd_buf[3] = len;
2060c165ff2SAkinobu Mita 	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
2070c165ff2SAkinobu Mita 
2080c165ff2SAkinobu Mita 	mutex_unlock(&spi_priv->cmd_lock);
2090c165ff2SAkinobu Mita 
2100c165ff2SAkinobu Mita 	return ret;
2110c165ff2SAkinobu Mita }
2120c165ff2SAkinobu Mita 
w5200_spi_writebulk(struct net_device * ndev,u32 addr,const u8 * buf,int len)21335ef7d68SAkinobu Mita static int w5200_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
2140c165ff2SAkinobu Mita 			       int len)
2150c165ff2SAkinobu Mita {
2160c165ff2SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
2170c165ff2SAkinobu Mita 	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
2180c165ff2SAkinobu Mita 	struct spi_transfer xfer[] = {
2190c165ff2SAkinobu Mita 		{
2200c165ff2SAkinobu Mita 			.tx_buf = spi_priv->cmd_buf,
2210c165ff2SAkinobu Mita 			.len = sizeof(spi_priv->cmd_buf),
2220c165ff2SAkinobu Mita 		},
2230c165ff2SAkinobu Mita 		{
2240c165ff2SAkinobu Mita 			.tx_buf = buf,
2250c165ff2SAkinobu Mita 			.len = len,
2260c165ff2SAkinobu Mita 		},
2270c165ff2SAkinobu Mita 	};
2280c165ff2SAkinobu Mita 	int ret;
2290c165ff2SAkinobu Mita 
2300c165ff2SAkinobu Mita 	mutex_lock(&spi_priv->cmd_lock);
2310c165ff2SAkinobu Mita 
2320c165ff2SAkinobu Mita 	spi_priv->cmd_buf[0] = addr >> 8;
2330c165ff2SAkinobu Mita 	spi_priv->cmd_buf[1] = addr;
2340c165ff2SAkinobu Mita 	spi_priv->cmd_buf[2] = W5200_SPI_WRITE_OPCODE | (len >> 8);
2350c165ff2SAkinobu Mita 	spi_priv->cmd_buf[3] = len;
2360c165ff2SAkinobu Mita 	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
2370c165ff2SAkinobu Mita 
2380c165ff2SAkinobu Mita 	mutex_unlock(&spi_priv->cmd_lock);
2390c165ff2SAkinobu Mita 
2400c165ff2SAkinobu Mita 	return ret;
2410c165ff2SAkinobu Mita }
2420c165ff2SAkinobu Mita 
2430c165ff2SAkinobu Mita static const struct w5100_ops w5200_ops = {
2440c165ff2SAkinobu Mita 	.may_sleep = true,
2450c165ff2SAkinobu Mita 	.chip_id = W5200,
2460c165ff2SAkinobu Mita 	.read = w5200_spi_read,
2470c165ff2SAkinobu Mita 	.write = w5200_spi_write,
2480c165ff2SAkinobu Mita 	.read16 = w5200_spi_read16,
2490c165ff2SAkinobu Mita 	.write16 = w5200_spi_write16,
2500c165ff2SAkinobu Mita 	.readbulk = w5200_spi_readbulk,
2510c165ff2SAkinobu Mita 	.writebulk = w5200_spi_writebulk,
2520c165ff2SAkinobu Mita 	.init = w5200_spi_init,
2530c165ff2SAkinobu Mita };
2540c165ff2SAkinobu Mita 
25535ef7d68SAkinobu Mita #define W5500_SPI_BLOCK_SELECT(addr) (((addr) >> 16) & 0x1f)
25635ef7d68SAkinobu Mita #define W5500_SPI_READ_CONTROL(addr) (W5500_SPI_BLOCK_SELECT(addr) << 3)
25735ef7d68SAkinobu Mita #define W5500_SPI_WRITE_CONTROL(addr)	\
25835ef7d68SAkinobu Mita 	((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2))
25935ef7d68SAkinobu Mita 
26035ef7d68SAkinobu Mita struct w5500_spi_priv {
26135ef7d68SAkinobu Mita 	/* Serialize access to cmd_buf */
26235ef7d68SAkinobu Mita 	struct mutex cmd_lock;
26335ef7d68SAkinobu Mita 
26435ef7d68SAkinobu Mita 	/* DMA (thus cache coherency maintenance) requires the
26535ef7d68SAkinobu Mita 	 * transfer buffers to live in their own cache lines.
26635ef7d68SAkinobu Mita 	 */
26735ef7d68SAkinobu Mita 	u8 cmd_buf[3] ____cacheline_aligned;
26835ef7d68SAkinobu Mita };
26935ef7d68SAkinobu Mita 
w5500_spi_priv(struct net_device * ndev)27035ef7d68SAkinobu Mita static struct w5500_spi_priv *w5500_spi_priv(struct net_device *ndev)
27135ef7d68SAkinobu Mita {
27235ef7d68SAkinobu Mita 	return w5100_ops_priv(ndev);
27335ef7d68SAkinobu Mita }
27435ef7d68SAkinobu Mita 
w5500_spi_init(struct net_device * ndev)27535ef7d68SAkinobu Mita static int w5500_spi_init(struct net_device *ndev)
27635ef7d68SAkinobu Mita {
27735ef7d68SAkinobu Mita 	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
27835ef7d68SAkinobu Mita 
27935ef7d68SAkinobu Mita 	mutex_init(&spi_priv->cmd_lock);
28035ef7d68SAkinobu Mita 
28135ef7d68SAkinobu Mita 	return 0;
28235ef7d68SAkinobu Mita }
28335ef7d68SAkinobu Mita 
w5500_spi_read(struct net_device * ndev,u32 addr)28435ef7d68SAkinobu Mita static int w5500_spi_read(struct net_device *ndev, u32 addr)
28535ef7d68SAkinobu Mita {
28635ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
28735ef7d68SAkinobu Mita 	u8 cmd[3] = {
28835ef7d68SAkinobu Mita 		addr >> 8,
28935ef7d68SAkinobu Mita 		addr,
29035ef7d68SAkinobu Mita 		W5500_SPI_READ_CONTROL(addr)
29135ef7d68SAkinobu Mita 	};
29235ef7d68SAkinobu Mita 	u8 data;
29335ef7d68SAkinobu Mita 	int ret;
29435ef7d68SAkinobu Mita 
29535ef7d68SAkinobu Mita 	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
29635ef7d68SAkinobu Mita 
29735ef7d68SAkinobu Mita 	return ret ? ret : data;
29835ef7d68SAkinobu Mita }
29935ef7d68SAkinobu Mita 
w5500_spi_write(struct net_device * ndev,u32 addr,u8 data)30035ef7d68SAkinobu Mita static int w5500_spi_write(struct net_device *ndev, u32 addr, u8 data)
30135ef7d68SAkinobu Mita {
30235ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
30335ef7d68SAkinobu Mita 	u8 cmd[4] = {
30435ef7d68SAkinobu Mita 		addr >> 8,
30535ef7d68SAkinobu Mita 		addr,
30635ef7d68SAkinobu Mita 		W5500_SPI_WRITE_CONTROL(addr),
30735ef7d68SAkinobu Mita 		data
30835ef7d68SAkinobu Mita 	};
30935ef7d68SAkinobu Mita 
31035ef7d68SAkinobu Mita 	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
31135ef7d68SAkinobu Mita }
31235ef7d68SAkinobu Mita 
w5500_spi_read16(struct net_device * ndev,u32 addr)31335ef7d68SAkinobu Mita static int w5500_spi_read16(struct net_device *ndev, u32 addr)
31435ef7d68SAkinobu Mita {
31535ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
31635ef7d68SAkinobu Mita 	u8 cmd[3] = {
31735ef7d68SAkinobu Mita 		addr >> 8,
31835ef7d68SAkinobu Mita 		addr,
31935ef7d68SAkinobu Mita 		W5500_SPI_READ_CONTROL(addr)
32035ef7d68SAkinobu Mita 	};
32135ef7d68SAkinobu Mita 	__be16 data;
32235ef7d68SAkinobu Mita 	int ret;
32335ef7d68SAkinobu Mita 
32435ef7d68SAkinobu Mita 	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data));
32535ef7d68SAkinobu Mita 
32635ef7d68SAkinobu Mita 	return ret ? ret : be16_to_cpu(data);
32735ef7d68SAkinobu Mita }
32835ef7d68SAkinobu Mita 
w5500_spi_write16(struct net_device * ndev,u32 addr,u16 data)32935ef7d68SAkinobu Mita static int w5500_spi_write16(struct net_device *ndev, u32 addr, u16 data)
33035ef7d68SAkinobu Mita {
33135ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
33235ef7d68SAkinobu Mita 	u8 cmd[5] = {
33335ef7d68SAkinobu Mita 		addr >> 8,
33435ef7d68SAkinobu Mita 		addr,
33535ef7d68SAkinobu Mita 		W5500_SPI_WRITE_CONTROL(addr),
33635ef7d68SAkinobu Mita 		data >> 8,
33735ef7d68SAkinobu Mita 		data
33835ef7d68SAkinobu Mita 	};
33935ef7d68SAkinobu Mita 
34035ef7d68SAkinobu Mita 	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
34135ef7d68SAkinobu Mita }
34235ef7d68SAkinobu Mita 
w5500_spi_readbulk(struct net_device * ndev,u32 addr,u8 * buf,int len)34335ef7d68SAkinobu Mita static int w5500_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
34435ef7d68SAkinobu Mita 			      int len)
34535ef7d68SAkinobu Mita {
34635ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
34735ef7d68SAkinobu Mita 	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
34835ef7d68SAkinobu Mita 	struct spi_transfer xfer[] = {
34935ef7d68SAkinobu Mita 		{
35035ef7d68SAkinobu Mita 			.tx_buf = spi_priv->cmd_buf,
35135ef7d68SAkinobu Mita 			.len = sizeof(spi_priv->cmd_buf),
35235ef7d68SAkinobu Mita 		},
35335ef7d68SAkinobu Mita 		{
35435ef7d68SAkinobu Mita 			.rx_buf = buf,
35535ef7d68SAkinobu Mita 			.len = len,
35635ef7d68SAkinobu Mita 		},
35735ef7d68SAkinobu Mita 	};
35835ef7d68SAkinobu Mita 	int ret;
35935ef7d68SAkinobu Mita 
36035ef7d68SAkinobu Mita 	mutex_lock(&spi_priv->cmd_lock);
36135ef7d68SAkinobu Mita 
36235ef7d68SAkinobu Mita 	spi_priv->cmd_buf[0] = addr >> 8;
36335ef7d68SAkinobu Mita 	spi_priv->cmd_buf[1] = addr;
36435ef7d68SAkinobu Mita 	spi_priv->cmd_buf[2] = W5500_SPI_READ_CONTROL(addr);
36535ef7d68SAkinobu Mita 	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
36635ef7d68SAkinobu Mita 
36735ef7d68SAkinobu Mita 	mutex_unlock(&spi_priv->cmd_lock);
36835ef7d68SAkinobu Mita 
36935ef7d68SAkinobu Mita 	return ret;
37035ef7d68SAkinobu Mita }
37135ef7d68SAkinobu Mita 
w5500_spi_writebulk(struct net_device * ndev,u32 addr,const u8 * buf,int len)37235ef7d68SAkinobu Mita static int w5500_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
37335ef7d68SAkinobu Mita 			       int len)
37435ef7d68SAkinobu Mita {
37535ef7d68SAkinobu Mita 	struct spi_device *spi = to_spi_device(ndev->dev.parent);
37635ef7d68SAkinobu Mita 	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
37735ef7d68SAkinobu Mita 	struct spi_transfer xfer[] = {
37835ef7d68SAkinobu Mita 		{
37935ef7d68SAkinobu Mita 			.tx_buf = spi_priv->cmd_buf,
38035ef7d68SAkinobu Mita 			.len = sizeof(spi_priv->cmd_buf),
38135ef7d68SAkinobu Mita 		},
38235ef7d68SAkinobu Mita 		{
38335ef7d68SAkinobu Mita 			.tx_buf = buf,
38435ef7d68SAkinobu Mita 			.len = len,
38535ef7d68SAkinobu Mita 		},
38635ef7d68SAkinobu Mita 	};
38735ef7d68SAkinobu Mita 	int ret;
38835ef7d68SAkinobu Mita 
38935ef7d68SAkinobu Mita 	mutex_lock(&spi_priv->cmd_lock);
39035ef7d68SAkinobu Mita 
39135ef7d68SAkinobu Mita 	spi_priv->cmd_buf[0] = addr >> 8;
39235ef7d68SAkinobu Mita 	spi_priv->cmd_buf[1] = addr;
39335ef7d68SAkinobu Mita 	spi_priv->cmd_buf[2] = W5500_SPI_WRITE_CONTROL(addr);
39435ef7d68SAkinobu Mita 	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
39535ef7d68SAkinobu Mita 
39635ef7d68SAkinobu Mita 	mutex_unlock(&spi_priv->cmd_lock);
39735ef7d68SAkinobu Mita 
39835ef7d68SAkinobu Mita 	return ret;
39935ef7d68SAkinobu Mita }
40035ef7d68SAkinobu Mita 
40135ef7d68SAkinobu Mita static const struct w5100_ops w5500_ops = {
40235ef7d68SAkinobu Mita 	.may_sleep = true,
40335ef7d68SAkinobu Mita 	.chip_id = W5500,
40435ef7d68SAkinobu Mita 	.read = w5500_spi_read,
40535ef7d68SAkinobu Mita 	.write = w5500_spi_write,
40635ef7d68SAkinobu Mita 	.read16 = w5500_spi_read16,
40735ef7d68SAkinobu Mita 	.write16 = w5500_spi_write16,
40835ef7d68SAkinobu Mita 	.readbulk = w5500_spi_readbulk,
40935ef7d68SAkinobu Mita 	.writebulk = w5500_spi_writebulk,
41035ef7d68SAkinobu Mita 	.init = w5500_spi_init,
41135ef7d68SAkinobu Mita };
41235ef7d68SAkinobu Mita 
413b9dd694eSNicolas Saenz Julienne static const struct of_device_id w5100_of_match[] = {
414b9dd694eSNicolas Saenz Julienne 	{ .compatible = "wiznet,w5100", .data = (const void*)W5100, },
415b9dd694eSNicolas Saenz Julienne 	{ .compatible = "wiznet,w5200", .data = (const void*)W5200, },
416b9dd694eSNicolas Saenz Julienne 	{ .compatible = "wiznet,w5500", .data = (const void*)W5500, },
417b9dd694eSNicolas Saenz Julienne 	{ },
418b9dd694eSNicolas Saenz Julienne };
419b9dd694eSNicolas Saenz Julienne MODULE_DEVICE_TABLE(of, w5100_of_match);
420b9dd694eSNicolas Saenz Julienne 
w5100_spi_probe(struct spi_device * spi)421630cf097SAkinobu Mita static int w5100_spi_probe(struct spi_device *spi)
422630cf097SAkinobu Mita {
423b9dd694eSNicolas Saenz Julienne 	const struct of_device_id *of_id;
4240c165ff2SAkinobu Mita 	const struct w5100_ops *ops;
425b9dd694eSNicolas Saenz Julienne 	kernel_ulong_t driver_data;
42683216e39SMichael Walle 	const void *mac = NULL;
42783216e39SMichael Walle 	u8 tmpmac[ETH_ALEN];
4280c165ff2SAkinobu Mita 	int priv_size;
42983216e39SMichael Walle 	int ret;
43083216e39SMichael Walle 
43183216e39SMichael Walle 	ret = of_get_mac_address(spi->dev.of_node, tmpmac);
43283216e39SMichael Walle 	if (!ret)
43383216e39SMichael Walle 		mac = tmpmac;
4340c165ff2SAkinobu Mita 
435b9dd694eSNicolas Saenz Julienne 	if (spi->dev.of_node) {
436b9dd694eSNicolas Saenz Julienne 		of_id = of_match_device(w5100_of_match, &spi->dev);
437b9dd694eSNicolas Saenz Julienne 		if (!of_id)
438b9dd694eSNicolas Saenz Julienne 			return -ENODEV;
439b9dd694eSNicolas Saenz Julienne 		driver_data = (kernel_ulong_t)of_id->data;
440b9dd694eSNicolas Saenz Julienne 	} else {
441b9dd694eSNicolas Saenz Julienne 		driver_data = spi_get_device_id(spi)->driver_data;
442b9dd694eSNicolas Saenz Julienne 	}
443b9dd694eSNicolas Saenz Julienne 
444b9dd694eSNicolas Saenz Julienne 	switch (driver_data) {
4450c165ff2SAkinobu Mita 	case W5100:
4460c165ff2SAkinobu Mita 		ops = &w5100_spi_ops;
4470c165ff2SAkinobu Mita 		priv_size = 0;
4480c165ff2SAkinobu Mita 		break;
4490c165ff2SAkinobu Mita 	case W5200:
4500c165ff2SAkinobu Mita 		ops = &w5200_ops;
4510c165ff2SAkinobu Mita 		priv_size = sizeof(struct w5200_spi_priv);
4520c165ff2SAkinobu Mita 		break;
45335ef7d68SAkinobu Mita 	case W5500:
45435ef7d68SAkinobu Mita 		ops = &w5500_ops;
45535ef7d68SAkinobu Mita 		priv_size = sizeof(struct w5500_spi_priv);
45635ef7d68SAkinobu Mita 		break;
4570c165ff2SAkinobu Mita 	default:
4580c165ff2SAkinobu Mita 		return -EINVAL;
4590c165ff2SAkinobu Mita 	}
4600c165ff2SAkinobu Mita 
461c3875ca7SAkinobu Mita 	return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL);
462630cf097SAkinobu Mita }
463630cf097SAkinobu Mita 
w5100_spi_remove(struct spi_device * spi)464*a0386bbaSUwe Kleine-König static void w5100_spi_remove(struct spi_device *spi)
465630cf097SAkinobu Mita {
466d40dfa0cSUwe Kleine-König 	w5100_remove(&spi->dev);
467630cf097SAkinobu Mita }
468630cf097SAkinobu Mita 
469630cf097SAkinobu Mita static const struct spi_device_id w5100_spi_ids[] = {
4700c165ff2SAkinobu Mita 	{ "w5100", W5100 },
4710c165ff2SAkinobu Mita 	{ "w5200", W5200 },
47235ef7d68SAkinobu Mita 	{ "w5500", W5500 },
473630cf097SAkinobu Mita 	{}
474630cf097SAkinobu Mita };
475630cf097SAkinobu Mita MODULE_DEVICE_TABLE(spi, w5100_spi_ids);
476630cf097SAkinobu Mita 
477630cf097SAkinobu Mita static struct spi_driver w5100_spi_driver = {
478630cf097SAkinobu Mita 	.driver		= {
479630cf097SAkinobu Mita 		.name	= "w5100",
480630cf097SAkinobu Mita 		.pm	= &w5100_pm_ops,
481b9dd694eSNicolas Saenz Julienne 		.of_match_table = w5100_of_match,
482630cf097SAkinobu Mita 	},
483630cf097SAkinobu Mita 	.probe		= w5100_spi_probe,
484630cf097SAkinobu Mita 	.remove		= w5100_spi_remove,
485630cf097SAkinobu Mita 	.id_table	= w5100_spi_ids,
486630cf097SAkinobu Mita };
487630cf097SAkinobu Mita module_spi_driver(w5100_spi_driver);
488630cf097SAkinobu Mita 
48935ef7d68SAkinobu Mita MODULE_DESCRIPTION("WIZnet W5100/W5200/W5500 Ethernet driver for SPI mode");
490630cf097SAkinobu Mita MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
491630cf097SAkinobu Mita MODULE_LICENSE("GPL");
492