Skip to content

Commit 630cf09

Browse files
mitadavem330
authored andcommitted
net: w5100: support SPI interface mode
This adds new w5100-spi driver which shares the bus interface independent code with existing w5100 driver. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Mike Sinkovsky <msink@permonline.ru> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent bf2c6b9 commit 630cf09

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed

drivers/net/ethernet/wiznet/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,18 @@ config WIZNET_BUS_ANY
6969
Performance may decrease compared to explicitly selected bus mode.
7070
endchoice
7171

72+
config WIZNET_W5100_SPI
73+
tristate "WIZnet W5100 Ethernet support for SPI mode"
74+
depends on WIZNET_BUS_ANY
75+
depends on SPI
76+
---help---
77+
In SPI mode host system accesses registers using SPI protocol
78+
(mode 0) on the SPI bus.
79+
80+
Performance decreases compared to other bus interface mode.
81+
In W5100 SPI mode, burst READ/WRITE processing are not provided.
82+
83+
To compile this driver as a module, choose M here: the module
84+
will be called w5100-spi.
85+
7286
endif # NET_VENDOR_WIZNET

drivers/net/ethernet/wiznet/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
obj-$(CONFIG_WIZNET_W5100) += w5100.o
2+
obj-$(CONFIG_WIZNET_W5100_SPI) += w5100-spi.o
23
obj-$(CONFIG_WIZNET_W5300) += w5300.o
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Ethernet driver for the WIZnet W5100 chip.
3+
*
4+
* Copyright (C) 2016 Akinobu Mita <akinobu.mita@gmail.com>
5+
*
6+
* Licensed under the GPL-2 or later.
7+
*/
8+
9+
#include <linux/kernel.h>
10+
#include <linux/module.h>
11+
#include <linux/delay.h>
12+
#include <linux/netdevice.h>
13+
#include <linux/spi/spi.h>
14+
15+
#include "w5100.h"
16+
17+
#define W5100_SPI_WRITE_OPCODE 0xf0
18+
#define W5100_SPI_READ_OPCODE 0x0f
19+
20+
static int w5100_spi_read(struct net_device *ndev, u16 addr)
21+
{
22+
struct spi_device *spi = to_spi_device(ndev->dev.parent);
23+
u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff };
24+
u8 data;
25+
int ret;
26+
27+
ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
28+
29+
return ret ? ret : data;
30+
}
31+
32+
static int w5100_spi_write(struct net_device *ndev, u16 addr, u8 data)
33+
{
34+
struct spi_device *spi = to_spi_device(ndev->dev.parent);
35+
u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data};
36+
37+
return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
38+
}
39+
40+
static int w5100_spi_read16(struct net_device *ndev, u16 addr)
41+
{
42+
u16 data;
43+
int ret;
44+
45+
ret = w5100_spi_read(ndev, addr);
46+
if (ret < 0)
47+
return ret;
48+
data = ret << 8;
49+
ret = w5100_spi_read(ndev, addr + 1);
50+
51+
return ret < 0 ? ret : data | ret;
52+
}
53+
54+
static int w5100_spi_write16(struct net_device *ndev, u16 addr, u16 data)
55+
{
56+
int ret;
57+
58+
ret = w5100_spi_write(ndev, addr, data >> 8);
59+
if (ret)
60+
return ret;
61+
62+
return w5100_spi_write(ndev, addr + 1, data & 0xff);
63+
}
64+
65+
static int w5100_spi_readbulk(struct net_device *ndev, u16 addr, u8 *buf,
66+
int len)
67+
{
68+
int i;
69+
70+
for (i = 0; i < len; i++) {
71+
int ret = w5100_spi_read(ndev, addr + i);
72+
73+
if (ret < 0)
74+
return ret;
75+
buf[i] = ret;
76+
}
77+
78+
return 0;
79+
}
80+
81+
static int w5100_spi_writebulk(struct net_device *ndev, u16 addr, const u8 *buf,
82+
int len)
83+
{
84+
int i;
85+
86+
for (i = 0; i < len; i++) {
87+
int ret = w5100_spi_write(ndev, addr + i, buf[i]);
88+
89+
if (ret)
90+
return ret;
91+
}
92+
93+
return 0;
94+
}
95+
96+
static const struct w5100_ops w5100_spi_ops = {
97+
.may_sleep = true,
98+
.read = w5100_spi_read,
99+
.write = w5100_spi_write,
100+
.read16 = w5100_spi_read16,
101+
.write16 = w5100_spi_write16,
102+
.readbulk = w5100_spi_readbulk,
103+
.writebulk = w5100_spi_writebulk,
104+
};
105+
106+
static int w5100_spi_probe(struct spi_device *spi)
107+
{
108+
return w5100_probe(&spi->dev, &w5100_spi_ops, 0, NULL, spi->irq,
109+
-EINVAL);
110+
}
111+
112+
static int w5100_spi_remove(struct spi_device *spi)
113+
{
114+
return w5100_remove(&spi->dev);
115+
}
116+
117+
static const struct spi_device_id w5100_spi_ids[] = {
118+
{ "w5100", 0 },
119+
{}
120+
};
121+
MODULE_DEVICE_TABLE(spi, w5100_spi_ids);
122+
123+
static struct spi_driver w5100_spi_driver = {
124+
.driver = {
125+
.name = "w5100",
126+
.pm = &w5100_pm_ops,
127+
},
128+
.probe = w5100_spi_probe,
129+
.remove = w5100_spi_remove,
130+
.id_table = w5100_spi_ids,
131+
};
132+
module_spi_driver(w5100_spi_driver);
133+
134+
MODULE_DESCRIPTION("WIZnet W5100 Ethernet driver for SPI mode");
135+
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
136+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)