xref: /openbmc/linux/drivers/net/ethernet/vertexcom/mse102x.c (revision 2f207cbf0dd44278af2aa3ff0fc95b0f97cc4e4c)
1*2f207cbfSStefan Wahren // SPDX-License-Identifier: GPL-2.0-only
2*2f207cbfSStefan Wahren /* Copyright (C) 2021 in-tech smart charging GmbH
3*2f207cbfSStefan Wahren  *
4*2f207cbfSStefan Wahren  * driver is based on micrel/ks8851_spi.c
5*2f207cbfSStefan Wahren  */
6*2f207cbfSStefan Wahren 
7*2f207cbfSStefan Wahren #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8*2f207cbfSStefan Wahren 
9*2f207cbfSStefan Wahren #include <linux/interrupt.h>
10*2f207cbfSStefan Wahren #include <linux/module.h>
11*2f207cbfSStefan Wahren #include <linux/kernel.h>
12*2f207cbfSStefan Wahren #include <linux/netdevice.h>
13*2f207cbfSStefan Wahren #include <linux/etherdevice.h>
14*2f207cbfSStefan Wahren #include <linux/ethtool.h>
15*2f207cbfSStefan Wahren #include <linux/cache.h>
16*2f207cbfSStefan Wahren #include <linux/debugfs.h>
17*2f207cbfSStefan Wahren #include <linux/seq_file.h>
18*2f207cbfSStefan Wahren 
19*2f207cbfSStefan Wahren #include <linux/spi/spi.h>
20*2f207cbfSStefan Wahren #include <linux/of_net.h>
21*2f207cbfSStefan Wahren 
22*2f207cbfSStefan Wahren #define MSG_DEFAULT	(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
23*2f207cbfSStefan Wahren 			 NETIF_MSG_TIMER)
24*2f207cbfSStefan Wahren 
25*2f207cbfSStefan Wahren #define DRV_NAME	"mse102x"
26*2f207cbfSStefan Wahren 
27*2f207cbfSStefan Wahren #define DET_CMD		0x0001
28*2f207cbfSStefan Wahren #define DET_SOF		0x0002
29*2f207cbfSStefan Wahren #define DET_DFT		0x55AA
30*2f207cbfSStefan Wahren 
31*2f207cbfSStefan Wahren #define CMD_SHIFT	12
32*2f207cbfSStefan Wahren #define CMD_RTS		(0x1 << CMD_SHIFT)
33*2f207cbfSStefan Wahren #define CMD_CTR		(0x2 << CMD_SHIFT)
34*2f207cbfSStefan Wahren 
35*2f207cbfSStefan Wahren #define CMD_MASK	GENMASK(15, CMD_SHIFT)
36*2f207cbfSStefan Wahren #define LEN_MASK	GENMASK(CMD_SHIFT - 1, 0)
37*2f207cbfSStefan Wahren 
38*2f207cbfSStefan Wahren #define DET_CMD_LEN	4
39*2f207cbfSStefan Wahren #define DET_SOF_LEN	2
40*2f207cbfSStefan Wahren #define DET_DFT_LEN	2
41*2f207cbfSStefan Wahren 
42*2f207cbfSStefan Wahren #define MIN_FREQ_HZ	6000000
43*2f207cbfSStefan Wahren #define MAX_FREQ_HZ	7142857
44*2f207cbfSStefan Wahren 
45*2f207cbfSStefan Wahren struct mse102x_stats {
46*2f207cbfSStefan Wahren 	u64 xfer_err;
47*2f207cbfSStefan Wahren 	u64 invalid_cmd;
48*2f207cbfSStefan Wahren 	u64 invalid_ctr;
49*2f207cbfSStefan Wahren 	u64 invalid_dft;
50*2f207cbfSStefan Wahren 	u64 invalid_len;
51*2f207cbfSStefan Wahren 	u64 invalid_rts;
52*2f207cbfSStefan Wahren 	u64 invalid_sof;
53*2f207cbfSStefan Wahren 	u64 tx_timeout;
54*2f207cbfSStefan Wahren };
55*2f207cbfSStefan Wahren 
56*2f207cbfSStefan Wahren static const char mse102x_gstrings_stats[][ETH_GSTRING_LEN] = {
57*2f207cbfSStefan Wahren 	"SPI transfer errors",
58*2f207cbfSStefan Wahren 	"Invalid command",
59*2f207cbfSStefan Wahren 	"Invalid CTR",
60*2f207cbfSStefan Wahren 	"Invalid DFT",
61*2f207cbfSStefan Wahren 	"Invalid frame length",
62*2f207cbfSStefan Wahren 	"Invalid RTS",
63*2f207cbfSStefan Wahren 	"Invalid SOF",
64*2f207cbfSStefan Wahren 	"TX timeout",
65*2f207cbfSStefan Wahren };
66*2f207cbfSStefan Wahren 
67*2f207cbfSStefan Wahren struct mse102x_net {
68*2f207cbfSStefan Wahren 	struct net_device	*ndev;
69*2f207cbfSStefan Wahren 
70*2f207cbfSStefan Wahren 	u8			rxd[8];
71*2f207cbfSStefan Wahren 	u8			txd[8];
72*2f207cbfSStefan Wahren 
73*2f207cbfSStefan Wahren 	u32			msg_enable ____cacheline_aligned;
74*2f207cbfSStefan Wahren 
75*2f207cbfSStefan Wahren 	struct sk_buff_head	txq;
76*2f207cbfSStefan Wahren 	struct mse102x_stats	stats;
77*2f207cbfSStefan Wahren };
78*2f207cbfSStefan Wahren 
79*2f207cbfSStefan Wahren struct mse102x_net_spi {
80*2f207cbfSStefan Wahren 	struct mse102x_net	mse102x;
81*2f207cbfSStefan Wahren 	struct mutex		lock;		/* Protect SPI frame transfer */
82*2f207cbfSStefan Wahren 	struct work_struct	tx_work;
83*2f207cbfSStefan Wahren 	struct spi_device	*spidev;
84*2f207cbfSStefan Wahren 	struct spi_message	spi_msg;
85*2f207cbfSStefan Wahren 	struct spi_transfer	spi_xfer;
86*2f207cbfSStefan Wahren 
87*2f207cbfSStefan Wahren #ifdef CONFIG_DEBUG_FS
88*2f207cbfSStefan Wahren 	struct dentry		*device_root;
89*2f207cbfSStefan Wahren #endif
90*2f207cbfSStefan Wahren };
91*2f207cbfSStefan Wahren 
92*2f207cbfSStefan Wahren #define to_mse102x_spi(mse) container_of((mse), struct mse102x_net_spi, mse102x)
93*2f207cbfSStefan Wahren 
94*2f207cbfSStefan Wahren #ifdef CONFIG_DEBUG_FS
95*2f207cbfSStefan Wahren 
96*2f207cbfSStefan Wahren static int mse102x_info_show(struct seq_file *s, void *what)
97*2f207cbfSStefan Wahren {
98*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = s->private;
99*2f207cbfSStefan Wahren 
100*2f207cbfSStefan Wahren 	seq_printf(s, "TX ring size        : %u\n",
101*2f207cbfSStefan Wahren 		   skb_queue_len(&mses->mse102x.txq));
102*2f207cbfSStefan Wahren 
103*2f207cbfSStefan Wahren 	seq_printf(s, "IRQ                 : %d\n",
104*2f207cbfSStefan Wahren 		   mses->spidev->irq);
105*2f207cbfSStefan Wahren 
106*2f207cbfSStefan Wahren 	seq_printf(s, "SPI effective speed : %lu\n",
107*2f207cbfSStefan Wahren 		   (unsigned long)mses->spi_xfer.effective_speed_hz);
108*2f207cbfSStefan Wahren 	seq_printf(s, "SPI mode            : %x\n",
109*2f207cbfSStefan Wahren 		   mses->spidev->mode);
110*2f207cbfSStefan Wahren 
111*2f207cbfSStefan Wahren 	return 0;
112*2f207cbfSStefan Wahren }
113*2f207cbfSStefan Wahren DEFINE_SHOW_ATTRIBUTE(mse102x_info);
114*2f207cbfSStefan Wahren 
115*2f207cbfSStefan Wahren static void mse102x_init_device_debugfs(struct mse102x_net_spi *mses)
116*2f207cbfSStefan Wahren {
117*2f207cbfSStefan Wahren 	mses->device_root = debugfs_create_dir(dev_name(&mses->mse102x.ndev->dev),
118*2f207cbfSStefan Wahren 					       NULL);
119*2f207cbfSStefan Wahren 
120*2f207cbfSStefan Wahren 	debugfs_create_file("info", S_IFREG | 0444, mses->device_root, mses,
121*2f207cbfSStefan Wahren 			    &mse102x_info_fops);
122*2f207cbfSStefan Wahren }
123*2f207cbfSStefan Wahren 
124*2f207cbfSStefan Wahren static void mse102x_remove_device_debugfs(struct mse102x_net_spi *mses)
125*2f207cbfSStefan Wahren {
126*2f207cbfSStefan Wahren 	debugfs_remove_recursive(mses->device_root);
127*2f207cbfSStefan Wahren }
128*2f207cbfSStefan Wahren 
129*2f207cbfSStefan Wahren #else /* CONFIG_DEBUG_FS */
130*2f207cbfSStefan Wahren 
131*2f207cbfSStefan Wahren static void mse102x_init_device_debugfs(struct mse102x_net_spi *mses)
132*2f207cbfSStefan Wahren {
133*2f207cbfSStefan Wahren }
134*2f207cbfSStefan Wahren 
135*2f207cbfSStefan Wahren static void mse102x_remove_device_debugfs(struct mse102x_net_spi *mses)
136*2f207cbfSStefan Wahren {
137*2f207cbfSStefan Wahren }
138*2f207cbfSStefan Wahren 
139*2f207cbfSStefan Wahren #endif
140*2f207cbfSStefan Wahren 
141*2f207cbfSStefan Wahren /* SPI register read/write calls.
142*2f207cbfSStefan Wahren  *
143*2f207cbfSStefan Wahren  * All these calls issue SPI transactions to access the chip's registers. They
144*2f207cbfSStefan Wahren  * all require that the necessary lock is held to prevent accesses when the
145*2f207cbfSStefan Wahren  * chip is busy transferring packet data.
146*2f207cbfSStefan Wahren  */
147*2f207cbfSStefan Wahren 
148*2f207cbfSStefan Wahren static void mse102x_tx_cmd_spi(struct mse102x_net *mse, u16 cmd)
149*2f207cbfSStefan Wahren {
150*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
151*2f207cbfSStefan Wahren 	struct spi_transfer *xfer = &mses->spi_xfer;
152*2f207cbfSStefan Wahren 	struct spi_message *msg = &mses->spi_msg;
153*2f207cbfSStefan Wahren 	__be16 txb[2];
154*2f207cbfSStefan Wahren 	int ret;
155*2f207cbfSStefan Wahren 
156*2f207cbfSStefan Wahren 	txb[0] = cpu_to_be16(DET_CMD);
157*2f207cbfSStefan Wahren 	txb[1] = cpu_to_be16(cmd);
158*2f207cbfSStefan Wahren 
159*2f207cbfSStefan Wahren 	xfer->tx_buf = txb;
160*2f207cbfSStefan Wahren 	xfer->rx_buf = NULL;
161*2f207cbfSStefan Wahren 	xfer->len = DET_CMD_LEN;
162*2f207cbfSStefan Wahren 
163*2f207cbfSStefan Wahren 	ret = spi_sync(mses->spidev, msg);
164*2f207cbfSStefan Wahren 	if (ret < 0) {
165*2f207cbfSStefan Wahren 		netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n",
166*2f207cbfSStefan Wahren 			   __func__, ret);
167*2f207cbfSStefan Wahren 		mse->stats.xfer_err++;
168*2f207cbfSStefan Wahren 	}
169*2f207cbfSStefan Wahren }
170*2f207cbfSStefan Wahren 
171*2f207cbfSStefan Wahren static int mse102x_rx_cmd_spi(struct mse102x_net *mse, u8 *rxb)
172*2f207cbfSStefan Wahren {
173*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
174*2f207cbfSStefan Wahren 	struct spi_transfer *xfer = &mses->spi_xfer;
175*2f207cbfSStefan Wahren 	struct spi_message *msg = &mses->spi_msg;
176*2f207cbfSStefan Wahren 	__be16 *txb = (__be16 *)mse->txd;
177*2f207cbfSStefan Wahren 	__be16 *cmd = (__be16 *)mse->rxd;
178*2f207cbfSStefan Wahren 	u8 *trx = mse->rxd;
179*2f207cbfSStefan Wahren 	int ret;
180*2f207cbfSStefan Wahren 
181*2f207cbfSStefan Wahren 	txb[0] = 0;
182*2f207cbfSStefan Wahren 	txb[1] = 0;
183*2f207cbfSStefan Wahren 
184*2f207cbfSStefan Wahren 	xfer->tx_buf = txb;
185*2f207cbfSStefan Wahren 	xfer->rx_buf = trx;
186*2f207cbfSStefan Wahren 	xfer->len = DET_CMD_LEN;
187*2f207cbfSStefan Wahren 
188*2f207cbfSStefan Wahren 	ret = spi_sync(mses->spidev, msg);
189*2f207cbfSStefan Wahren 	if (ret < 0) {
190*2f207cbfSStefan Wahren 		netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n",
191*2f207cbfSStefan Wahren 			   __func__, ret);
192*2f207cbfSStefan Wahren 		mse->stats.xfer_err++;
193*2f207cbfSStefan Wahren 	} else if (*cmd != cpu_to_be16(DET_CMD)) {
194*2f207cbfSStefan Wahren 		net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n",
195*2f207cbfSStefan Wahren 				    __func__, *cmd);
196*2f207cbfSStefan Wahren 		mse->stats.invalid_cmd++;
197*2f207cbfSStefan Wahren 		ret = -EIO;
198*2f207cbfSStefan Wahren 	} else {
199*2f207cbfSStefan Wahren 		memcpy(rxb, trx + 2, 2);
200*2f207cbfSStefan Wahren 	}
201*2f207cbfSStefan Wahren 
202*2f207cbfSStefan Wahren 	return ret;
203*2f207cbfSStefan Wahren }
204*2f207cbfSStefan Wahren 
205*2f207cbfSStefan Wahren static inline void mse102x_push_header(struct sk_buff *skb)
206*2f207cbfSStefan Wahren {
207*2f207cbfSStefan Wahren 	__be16 *header = skb_push(skb, DET_SOF_LEN);
208*2f207cbfSStefan Wahren 
209*2f207cbfSStefan Wahren 	*header = cpu_to_be16(DET_SOF);
210*2f207cbfSStefan Wahren }
211*2f207cbfSStefan Wahren 
212*2f207cbfSStefan Wahren static inline void mse102x_put_footer(struct sk_buff *skb)
213*2f207cbfSStefan Wahren {
214*2f207cbfSStefan Wahren 	__be16 *footer = skb_put(skb, DET_DFT_LEN);
215*2f207cbfSStefan Wahren 
216*2f207cbfSStefan Wahren 	*footer = cpu_to_be16(DET_DFT);
217*2f207cbfSStefan Wahren }
218*2f207cbfSStefan Wahren 
219*2f207cbfSStefan Wahren static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
220*2f207cbfSStefan Wahren 				unsigned int pad)
221*2f207cbfSStefan Wahren {
222*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
223*2f207cbfSStefan Wahren 	struct spi_transfer *xfer = &mses->spi_xfer;
224*2f207cbfSStefan Wahren 	struct spi_message *msg = &mses->spi_msg;
225*2f207cbfSStefan Wahren 	struct sk_buff *tskb;
226*2f207cbfSStefan Wahren 	int ret;
227*2f207cbfSStefan Wahren 
228*2f207cbfSStefan Wahren 	netif_dbg(mse, tx_queued, mse->ndev, "%s: skb %p, %d@%p\n",
229*2f207cbfSStefan Wahren 		  __func__, txp, txp->len, txp->data);
230*2f207cbfSStefan Wahren 
231*2f207cbfSStefan Wahren 	if ((skb_headroom(txp) < DET_SOF_LEN) ||
232*2f207cbfSStefan Wahren 	    (skb_tailroom(txp) < DET_DFT_LEN + pad)) {
233*2f207cbfSStefan Wahren 		tskb = skb_copy_expand(txp, DET_SOF_LEN, DET_DFT_LEN + pad,
234*2f207cbfSStefan Wahren 				       GFP_KERNEL);
235*2f207cbfSStefan Wahren 		if (!tskb)
236*2f207cbfSStefan Wahren 			return -ENOMEM;
237*2f207cbfSStefan Wahren 
238*2f207cbfSStefan Wahren 		dev_kfree_skb(txp);
239*2f207cbfSStefan Wahren 		txp = tskb;
240*2f207cbfSStefan Wahren 	}
241*2f207cbfSStefan Wahren 
242*2f207cbfSStefan Wahren 	mse102x_push_header(txp);
243*2f207cbfSStefan Wahren 
244*2f207cbfSStefan Wahren 	if (pad)
245*2f207cbfSStefan Wahren 		skb_put_zero(txp, pad);
246*2f207cbfSStefan Wahren 
247*2f207cbfSStefan Wahren 	mse102x_put_footer(txp);
248*2f207cbfSStefan Wahren 
249*2f207cbfSStefan Wahren 	xfer->tx_buf = txp->data;
250*2f207cbfSStefan Wahren 	xfer->rx_buf = NULL;
251*2f207cbfSStefan Wahren 	xfer->len = txp->len;
252*2f207cbfSStefan Wahren 
253*2f207cbfSStefan Wahren 	ret = spi_sync(mses->spidev, msg);
254*2f207cbfSStefan Wahren 	if (ret < 0) {
255*2f207cbfSStefan Wahren 		netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n",
256*2f207cbfSStefan Wahren 			   __func__, ret);
257*2f207cbfSStefan Wahren 		mse->stats.xfer_err++;
258*2f207cbfSStefan Wahren 	}
259*2f207cbfSStefan Wahren 
260*2f207cbfSStefan Wahren 	return ret;
261*2f207cbfSStefan Wahren }
262*2f207cbfSStefan Wahren 
263*2f207cbfSStefan Wahren static int mse102x_rx_frame_spi(struct mse102x_net *mse, u8 *buff,
264*2f207cbfSStefan Wahren 				unsigned int frame_len)
265*2f207cbfSStefan Wahren {
266*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
267*2f207cbfSStefan Wahren 	struct spi_transfer *xfer = &mses->spi_xfer;
268*2f207cbfSStefan Wahren 	struct spi_message *msg = &mses->spi_msg;
269*2f207cbfSStefan Wahren 	__be16 *sof = (__be16 *)buff;
270*2f207cbfSStefan Wahren 	__be16 *dft = (__be16 *)(buff + DET_SOF_LEN + frame_len);
271*2f207cbfSStefan Wahren 	int ret;
272*2f207cbfSStefan Wahren 
273*2f207cbfSStefan Wahren 	xfer->rx_buf = buff;
274*2f207cbfSStefan Wahren 	xfer->tx_buf = NULL;
275*2f207cbfSStefan Wahren 	xfer->len = DET_SOF_LEN + frame_len + DET_DFT_LEN;
276*2f207cbfSStefan Wahren 
277*2f207cbfSStefan Wahren 	ret = spi_sync(mses->spidev, msg);
278*2f207cbfSStefan Wahren 	if (ret < 0) {
279*2f207cbfSStefan Wahren 		netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n",
280*2f207cbfSStefan Wahren 			   __func__, ret);
281*2f207cbfSStefan Wahren 		mse->stats.xfer_err++;
282*2f207cbfSStefan Wahren 	} else if (*sof != cpu_to_be16(DET_SOF)) {
283*2f207cbfSStefan Wahren 		netdev_dbg(mse->ndev, "%s: SPI start of frame is invalid (0x%04x)\n",
284*2f207cbfSStefan Wahren 			   __func__, *sof);
285*2f207cbfSStefan Wahren 		mse->stats.invalid_sof++;
286*2f207cbfSStefan Wahren 		ret = -EIO;
287*2f207cbfSStefan Wahren 	} else if (*dft != cpu_to_be16(DET_DFT)) {
288*2f207cbfSStefan Wahren 		netdev_dbg(mse->ndev, "%s: SPI frame tail is invalid (0x%04x)\n",
289*2f207cbfSStefan Wahren 			   __func__, *dft);
290*2f207cbfSStefan Wahren 		mse->stats.invalid_dft++;
291*2f207cbfSStefan Wahren 		ret = -EIO;
292*2f207cbfSStefan Wahren 	}
293*2f207cbfSStefan Wahren 
294*2f207cbfSStefan Wahren 	return ret;
295*2f207cbfSStefan Wahren }
296*2f207cbfSStefan Wahren 
297*2f207cbfSStefan Wahren static void mse102x_dump_packet(const char *msg, int len, const char *data)
298*2f207cbfSStefan Wahren {
299*2f207cbfSStefan Wahren 	printk(KERN_DEBUG ": %s - packet len:%d\n", msg, len);
300*2f207cbfSStefan Wahren 	print_hex_dump(KERN_DEBUG, "pk data: ", DUMP_PREFIX_OFFSET, 16, 1,
301*2f207cbfSStefan Wahren 		       data, len, true);
302*2f207cbfSStefan Wahren }
303*2f207cbfSStefan Wahren 
304*2f207cbfSStefan Wahren static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
305*2f207cbfSStefan Wahren {
306*2f207cbfSStefan Wahren 	struct sk_buff *skb;
307*2f207cbfSStefan Wahren 	unsigned int rxalign;
308*2f207cbfSStefan Wahren 	unsigned int rxlen;
309*2f207cbfSStefan Wahren 	__be16 rx = 0;
310*2f207cbfSStefan Wahren 	u16 cmd_resp;
311*2f207cbfSStefan Wahren 	u8 *rxpkt;
312*2f207cbfSStefan Wahren 	int ret;
313*2f207cbfSStefan Wahren 
314*2f207cbfSStefan Wahren 	mse102x_tx_cmd_spi(mse, CMD_CTR);
315*2f207cbfSStefan Wahren 	ret = mse102x_rx_cmd_spi(mse, (u8 *)&rx);
316*2f207cbfSStefan Wahren 	cmd_resp = be16_to_cpu(rx);
317*2f207cbfSStefan Wahren 
318*2f207cbfSStefan Wahren 	if (ret || ((cmd_resp & CMD_MASK) != CMD_RTS)) {
319*2f207cbfSStefan Wahren 		usleep_range(50, 100);
320*2f207cbfSStefan Wahren 
321*2f207cbfSStefan Wahren 		mse102x_tx_cmd_spi(mse, CMD_CTR);
322*2f207cbfSStefan Wahren 		ret = mse102x_rx_cmd_spi(mse, (u8 *)&rx);
323*2f207cbfSStefan Wahren 		if (ret)
324*2f207cbfSStefan Wahren 			return;
325*2f207cbfSStefan Wahren 
326*2f207cbfSStefan Wahren 		cmd_resp = be16_to_cpu(rx);
327*2f207cbfSStefan Wahren 		if ((cmd_resp & CMD_MASK) != CMD_RTS) {
328*2f207cbfSStefan Wahren 			net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n",
329*2f207cbfSStefan Wahren 					    __func__, cmd_resp);
330*2f207cbfSStefan Wahren 			mse->stats.invalid_rts++;
331*2f207cbfSStefan Wahren 			return;
332*2f207cbfSStefan Wahren 		}
333*2f207cbfSStefan Wahren 
334*2f207cbfSStefan Wahren 		net_dbg_ratelimited("%s: Unexpected response to first CMD\n",
335*2f207cbfSStefan Wahren 				    __func__);
336*2f207cbfSStefan Wahren 	}
337*2f207cbfSStefan Wahren 
338*2f207cbfSStefan Wahren 	rxlen = cmd_resp & LEN_MASK;
339*2f207cbfSStefan Wahren 	if (!rxlen) {
340*2f207cbfSStefan Wahren 		net_dbg_ratelimited("%s: No frame length defined\n", __func__);
341*2f207cbfSStefan Wahren 		mse->stats.invalid_len++;
342*2f207cbfSStefan Wahren 		return;
343*2f207cbfSStefan Wahren 	}
344*2f207cbfSStefan Wahren 
345*2f207cbfSStefan Wahren 	rxalign = ALIGN(rxlen + DET_SOF_LEN + DET_DFT_LEN, 4);
346*2f207cbfSStefan Wahren 	skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign);
347*2f207cbfSStefan Wahren 	if (!skb)
348*2f207cbfSStefan Wahren 		return;
349*2f207cbfSStefan Wahren 
350*2f207cbfSStefan Wahren 	/* 2 bytes Start of frame (before ethernet header)
351*2f207cbfSStefan Wahren 	 * 2 bytes Data frame tail (after ethernet frame)
352*2f207cbfSStefan Wahren 	 * They are copied, but ignored.
353*2f207cbfSStefan Wahren 	 */
354*2f207cbfSStefan Wahren 	rxpkt = skb_put(skb, rxlen) - DET_SOF_LEN;
355*2f207cbfSStefan Wahren 	if (mse102x_rx_frame_spi(mse, rxpkt, rxlen)) {
356*2f207cbfSStefan Wahren 		mse->ndev->stats.rx_errors++;
357*2f207cbfSStefan Wahren 		dev_kfree_skb(skb);
358*2f207cbfSStefan Wahren 		return;
359*2f207cbfSStefan Wahren 	}
360*2f207cbfSStefan Wahren 
361*2f207cbfSStefan Wahren 	if (netif_msg_pktdata(mse))
362*2f207cbfSStefan Wahren 		mse102x_dump_packet(__func__, skb->len, skb->data);
363*2f207cbfSStefan Wahren 
364*2f207cbfSStefan Wahren 	skb->protocol = eth_type_trans(skb, mse->ndev);
365*2f207cbfSStefan Wahren 	netif_rx_ni(skb);
366*2f207cbfSStefan Wahren 
367*2f207cbfSStefan Wahren 	mse->ndev->stats.rx_packets++;
368*2f207cbfSStefan Wahren 	mse->ndev->stats.rx_bytes += rxlen;
369*2f207cbfSStefan Wahren }
370*2f207cbfSStefan Wahren 
371*2f207cbfSStefan Wahren static int mse102x_tx_pkt_spi(struct mse102x_net *mse, struct sk_buff *txb,
372*2f207cbfSStefan Wahren 			      unsigned long work_timeout)
373*2f207cbfSStefan Wahren {
374*2f207cbfSStefan Wahren 	unsigned int pad = 0;
375*2f207cbfSStefan Wahren 	__be16 rx = 0;
376*2f207cbfSStefan Wahren 	u16 cmd_resp;
377*2f207cbfSStefan Wahren 	int ret;
378*2f207cbfSStefan Wahren 	bool first = true;
379*2f207cbfSStefan Wahren 
380*2f207cbfSStefan Wahren 	if (txb->len < 60)
381*2f207cbfSStefan Wahren 		pad = 60 - txb->len;
382*2f207cbfSStefan Wahren 
383*2f207cbfSStefan Wahren 	while (1) {
384*2f207cbfSStefan Wahren 		mse102x_tx_cmd_spi(mse, CMD_RTS | (txb->len + pad));
385*2f207cbfSStefan Wahren 		ret = mse102x_rx_cmd_spi(mse, (u8 *)&rx);
386*2f207cbfSStefan Wahren 		cmd_resp = be16_to_cpu(rx);
387*2f207cbfSStefan Wahren 
388*2f207cbfSStefan Wahren 		if (!ret) {
389*2f207cbfSStefan Wahren 			/* ready to send frame ? */
390*2f207cbfSStefan Wahren 			if (cmd_resp == CMD_CTR)
391*2f207cbfSStefan Wahren 				break;
392*2f207cbfSStefan Wahren 
393*2f207cbfSStefan Wahren 			net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n",
394*2f207cbfSStefan Wahren 					    __func__, cmd_resp);
395*2f207cbfSStefan Wahren 			mse->stats.invalid_ctr++;
396*2f207cbfSStefan Wahren 		}
397*2f207cbfSStefan Wahren 
398*2f207cbfSStefan Wahren 		/* It's not predictable how long / many retries it takes to
399*2f207cbfSStefan Wahren 		 * send at least one packet, so TX timeouts are possible.
400*2f207cbfSStefan Wahren 		 * That's the reason why the netdev watchdog is not used here.
401*2f207cbfSStefan Wahren 		 */
402*2f207cbfSStefan Wahren 		if (time_after(jiffies, work_timeout))
403*2f207cbfSStefan Wahren 			return -ETIMEDOUT;
404*2f207cbfSStefan Wahren 
405*2f207cbfSStefan Wahren 		if (first) {
406*2f207cbfSStefan Wahren 			/* throttle at first issue */
407*2f207cbfSStefan Wahren 			netif_stop_queue(mse->ndev);
408*2f207cbfSStefan Wahren 			/* fast retry */
409*2f207cbfSStefan Wahren 			usleep_range(50, 100);
410*2f207cbfSStefan Wahren 			first = false;
411*2f207cbfSStefan Wahren 		} else {
412*2f207cbfSStefan Wahren 			msleep(20);
413*2f207cbfSStefan Wahren 		}
414*2f207cbfSStefan Wahren 	};
415*2f207cbfSStefan Wahren 
416*2f207cbfSStefan Wahren 	ret = mse102x_tx_frame_spi(mse, txb, pad);
417*2f207cbfSStefan Wahren 	if (ret)
418*2f207cbfSStefan Wahren 		net_dbg_ratelimited("%s: Failed to send (%d), drop frame\n",
419*2f207cbfSStefan Wahren 				    __func__, ret);
420*2f207cbfSStefan Wahren 
421*2f207cbfSStefan Wahren 	return ret;
422*2f207cbfSStefan Wahren }
423*2f207cbfSStefan Wahren 
424*2f207cbfSStefan Wahren #define TX_QUEUE_MAX 10
425*2f207cbfSStefan Wahren 
426*2f207cbfSStefan Wahren static void mse102x_tx_work(struct work_struct *work)
427*2f207cbfSStefan Wahren {
428*2f207cbfSStefan Wahren 	/* Make sure timeout is sufficient to transfer TX_QUEUE_MAX frames */
429*2f207cbfSStefan Wahren 	unsigned long work_timeout = jiffies + msecs_to_jiffies(1000);
430*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses;
431*2f207cbfSStefan Wahren 	struct mse102x_net *mse;
432*2f207cbfSStefan Wahren 	struct sk_buff *txb;
433*2f207cbfSStefan Wahren 	int ret = 0;
434*2f207cbfSStefan Wahren 
435*2f207cbfSStefan Wahren 	mses = container_of(work, struct mse102x_net_spi, tx_work);
436*2f207cbfSStefan Wahren 	mse = &mses->mse102x;
437*2f207cbfSStefan Wahren 
438*2f207cbfSStefan Wahren 	while ((txb = skb_dequeue(&mse->txq))) {
439*2f207cbfSStefan Wahren 		mutex_lock(&mses->lock);
440*2f207cbfSStefan Wahren 		ret = mse102x_tx_pkt_spi(mse, txb, work_timeout);
441*2f207cbfSStefan Wahren 		mutex_unlock(&mses->lock);
442*2f207cbfSStefan Wahren 		if (ret) {
443*2f207cbfSStefan Wahren 			mse->ndev->stats.tx_dropped++;
444*2f207cbfSStefan Wahren 		} else {
445*2f207cbfSStefan Wahren 			mse->ndev->stats.tx_bytes += txb->len;
446*2f207cbfSStefan Wahren 			mse->ndev->stats.tx_packets++;
447*2f207cbfSStefan Wahren 		}
448*2f207cbfSStefan Wahren 
449*2f207cbfSStefan Wahren 		dev_kfree_skb(txb);
450*2f207cbfSStefan Wahren 	}
451*2f207cbfSStefan Wahren 
452*2f207cbfSStefan Wahren 	if (ret == -ETIMEDOUT) {
453*2f207cbfSStefan Wahren 		if (netif_msg_timer(mse))
454*2f207cbfSStefan Wahren 			netdev_err(mse->ndev, "tx work timeout\n");
455*2f207cbfSStefan Wahren 
456*2f207cbfSStefan Wahren 		mse->stats.tx_timeout++;
457*2f207cbfSStefan Wahren 	}
458*2f207cbfSStefan Wahren 
459*2f207cbfSStefan Wahren 	netif_wake_queue(mse->ndev);
460*2f207cbfSStefan Wahren }
461*2f207cbfSStefan Wahren 
462*2f207cbfSStefan Wahren static netdev_tx_t mse102x_start_xmit_spi(struct sk_buff *skb,
463*2f207cbfSStefan Wahren 					  struct net_device *ndev)
464*2f207cbfSStefan Wahren {
465*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
466*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
467*2f207cbfSStefan Wahren 
468*2f207cbfSStefan Wahren 	netif_dbg(mse, tx_queued, ndev,
469*2f207cbfSStefan Wahren 		  "%s: skb %p, %d@%p\n", __func__, skb, skb->len, skb->data);
470*2f207cbfSStefan Wahren 
471*2f207cbfSStefan Wahren 	skb_queue_tail(&mse->txq, skb);
472*2f207cbfSStefan Wahren 
473*2f207cbfSStefan Wahren 	if (skb_queue_len(&mse->txq) >= TX_QUEUE_MAX)
474*2f207cbfSStefan Wahren 		netif_stop_queue(ndev);
475*2f207cbfSStefan Wahren 
476*2f207cbfSStefan Wahren 	schedule_work(&mses->tx_work);
477*2f207cbfSStefan Wahren 
478*2f207cbfSStefan Wahren 	return NETDEV_TX_OK;
479*2f207cbfSStefan Wahren }
480*2f207cbfSStefan Wahren 
481*2f207cbfSStefan Wahren static void mse102x_init_mac(struct mse102x_net *mse, struct device_node *np)
482*2f207cbfSStefan Wahren {
483*2f207cbfSStefan Wahren 	struct net_device *ndev = mse->ndev;
484*2f207cbfSStefan Wahren 	int ret = of_get_ethdev_address(np, ndev);
485*2f207cbfSStefan Wahren 
486*2f207cbfSStefan Wahren 	if (ret) {
487*2f207cbfSStefan Wahren 		eth_hw_addr_random(ndev);
488*2f207cbfSStefan Wahren 		netdev_err(ndev, "Using random MAC address: %pM\n",
489*2f207cbfSStefan Wahren 			   ndev->dev_addr);
490*2f207cbfSStefan Wahren 	}
491*2f207cbfSStefan Wahren }
492*2f207cbfSStefan Wahren 
493*2f207cbfSStefan Wahren /* Assumption: this is called for every incoming packet */
494*2f207cbfSStefan Wahren static irqreturn_t mse102x_irq(int irq, void *_mse)
495*2f207cbfSStefan Wahren {
496*2f207cbfSStefan Wahren 	struct mse102x_net *mse = _mse;
497*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
498*2f207cbfSStefan Wahren 
499*2f207cbfSStefan Wahren 	mutex_lock(&mses->lock);
500*2f207cbfSStefan Wahren 	mse102x_rx_pkt_spi(mse);
501*2f207cbfSStefan Wahren 	mutex_unlock(&mses->lock);
502*2f207cbfSStefan Wahren 
503*2f207cbfSStefan Wahren 	return IRQ_HANDLED;
504*2f207cbfSStefan Wahren }
505*2f207cbfSStefan Wahren 
506*2f207cbfSStefan Wahren static int mse102x_net_open(struct net_device *ndev)
507*2f207cbfSStefan Wahren {
508*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
509*2f207cbfSStefan Wahren 	int ret;
510*2f207cbfSStefan Wahren 
511*2f207cbfSStefan Wahren 	ret = request_threaded_irq(ndev->irq, NULL, mse102x_irq, IRQF_ONESHOT,
512*2f207cbfSStefan Wahren 				   ndev->name, mse);
513*2f207cbfSStefan Wahren 	if (ret < 0) {
514*2f207cbfSStefan Wahren 		netdev_err(ndev, "Failed to get irq: %d\n", ret);
515*2f207cbfSStefan Wahren 		return ret;
516*2f207cbfSStefan Wahren 	}
517*2f207cbfSStefan Wahren 
518*2f207cbfSStefan Wahren 	netif_dbg(mse, ifup, ndev, "opening\n");
519*2f207cbfSStefan Wahren 
520*2f207cbfSStefan Wahren 	netif_start_queue(ndev);
521*2f207cbfSStefan Wahren 
522*2f207cbfSStefan Wahren 	netif_carrier_on(ndev);
523*2f207cbfSStefan Wahren 
524*2f207cbfSStefan Wahren 	netif_dbg(mse, ifup, ndev, "network device up\n");
525*2f207cbfSStefan Wahren 
526*2f207cbfSStefan Wahren 	return 0;
527*2f207cbfSStefan Wahren }
528*2f207cbfSStefan Wahren 
529*2f207cbfSStefan Wahren static int mse102x_net_stop(struct net_device *ndev)
530*2f207cbfSStefan Wahren {
531*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
532*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
533*2f207cbfSStefan Wahren 
534*2f207cbfSStefan Wahren 	netif_info(mse, ifdown, ndev, "shutting down\n");
535*2f207cbfSStefan Wahren 
536*2f207cbfSStefan Wahren 	netif_carrier_off(mse->ndev);
537*2f207cbfSStefan Wahren 
538*2f207cbfSStefan Wahren 	/* stop any outstanding work */
539*2f207cbfSStefan Wahren 	flush_work(&mses->tx_work);
540*2f207cbfSStefan Wahren 
541*2f207cbfSStefan Wahren 	netif_stop_queue(ndev);
542*2f207cbfSStefan Wahren 
543*2f207cbfSStefan Wahren 	skb_queue_purge(&mse->txq);
544*2f207cbfSStefan Wahren 
545*2f207cbfSStefan Wahren 	free_irq(ndev->irq, mse);
546*2f207cbfSStefan Wahren 
547*2f207cbfSStefan Wahren 	return 0;
548*2f207cbfSStefan Wahren }
549*2f207cbfSStefan Wahren 
550*2f207cbfSStefan Wahren static const struct net_device_ops mse102x_netdev_ops = {
551*2f207cbfSStefan Wahren 	.ndo_open		= mse102x_net_open,
552*2f207cbfSStefan Wahren 	.ndo_stop		= mse102x_net_stop,
553*2f207cbfSStefan Wahren 	.ndo_start_xmit		= mse102x_start_xmit_spi,
554*2f207cbfSStefan Wahren 	.ndo_set_mac_address	= eth_mac_addr,
555*2f207cbfSStefan Wahren 	.ndo_validate_addr	= eth_validate_addr,
556*2f207cbfSStefan Wahren };
557*2f207cbfSStefan Wahren 
558*2f207cbfSStefan Wahren /* ethtool support */
559*2f207cbfSStefan Wahren 
560*2f207cbfSStefan Wahren static void mse102x_get_drvinfo(struct net_device *ndev,
561*2f207cbfSStefan Wahren 				struct ethtool_drvinfo *di)
562*2f207cbfSStefan Wahren {
563*2f207cbfSStefan Wahren 	strscpy(di->driver, DRV_NAME, sizeof(di->driver));
564*2f207cbfSStefan Wahren 	strscpy(di->bus_info, dev_name(ndev->dev.parent), sizeof(di->bus_info));
565*2f207cbfSStefan Wahren }
566*2f207cbfSStefan Wahren 
567*2f207cbfSStefan Wahren static u32 mse102x_get_msglevel(struct net_device *ndev)
568*2f207cbfSStefan Wahren {
569*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
570*2f207cbfSStefan Wahren 
571*2f207cbfSStefan Wahren 	return mse->msg_enable;
572*2f207cbfSStefan Wahren }
573*2f207cbfSStefan Wahren 
574*2f207cbfSStefan Wahren static void mse102x_set_msglevel(struct net_device *ndev, u32 to)
575*2f207cbfSStefan Wahren {
576*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
577*2f207cbfSStefan Wahren 
578*2f207cbfSStefan Wahren 	mse->msg_enable = to;
579*2f207cbfSStefan Wahren }
580*2f207cbfSStefan Wahren 
581*2f207cbfSStefan Wahren static void mse102x_get_ethtool_stats(struct net_device *ndev,
582*2f207cbfSStefan Wahren 				      struct ethtool_stats *estats, u64 *data)
583*2f207cbfSStefan Wahren {
584*2f207cbfSStefan Wahren 	struct mse102x_net *mse = netdev_priv(ndev);
585*2f207cbfSStefan Wahren 	struct mse102x_stats *st = &mse->stats;
586*2f207cbfSStefan Wahren 
587*2f207cbfSStefan Wahren 	memcpy(data, st, ARRAY_SIZE(mse102x_gstrings_stats) * sizeof(u64));
588*2f207cbfSStefan Wahren }
589*2f207cbfSStefan Wahren 
590*2f207cbfSStefan Wahren static void mse102x_get_strings(struct net_device *ndev, u32 stringset, u8 *buf)
591*2f207cbfSStefan Wahren {
592*2f207cbfSStefan Wahren 	switch (stringset) {
593*2f207cbfSStefan Wahren 	case ETH_SS_STATS:
594*2f207cbfSStefan Wahren 		memcpy(buf, &mse102x_gstrings_stats,
595*2f207cbfSStefan Wahren 		       sizeof(mse102x_gstrings_stats));
596*2f207cbfSStefan Wahren 		break;
597*2f207cbfSStefan Wahren 	default:
598*2f207cbfSStefan Wahren 		WARN_ON(1);
599*2f207cbfSStefan Wahren 		break;
600*2f207cbfSStefan Wahren 	}
601*2f207cbfSStefan Wahren }
602*2f207cbfSStefan Wahren 
603*2f207cbfSStefan Wahren static int mse102x_get_sset_count(struct net_device *ndev, int sset)
604*2f207cbfSStefan Wahren {
605*2f207cbfSStefan Wahren 	switch (sset) {
606*2f207cbfSStefan Wahren 	case ETH_SS_STATS:
607*2f207cbfSStefan Wahren 		return ARRAY_SIZE(mse102x_gstrings_stats);
608*2f207cbfSStefan Wahren 	default:
609*2f207cbfSStefan Wahren 		return -EINVAL;
610*2f207cbfSStefan Wahren 	}
611*2f207cbfSStefan Wahren }
612*2f207cbfSStefan Wahren 
613*2f207cbfSStefan Wahren static const struct ethtool_ops mse102x_ethtool_ops = {
614*2f207cbfSStefan Wahren 	.get_drvinfo		= mse102x_get_drvinfo,
615*2f207cbfSStefan Wahren 	.get_link		= ethtool_op_get_link,
616*2f207cbfSStefan Wahren 	.get_msglevel		= mse102x_get_msglevel,
617*2f207cbfSStefan Wahren 	.set_msglevel		= mse102x_set_msglevel,
618*2f207cbfSStefan Wahren 	.get_ethtool_stats	= mse102x_get_ethtool_stats,
619*2f207cbfSStefan Wahren 	.get_strings		= mse102x_get_strings,
620*2f207cbfSStefan Wahren 	.get_sset_count		= mse102x_get_sset_count,
621*2f207cbfSStefan Wahren };
622*2f207cbfSStefan Wahren 
623*2f207cbfSStefan Wahren /* driver bus management functions */
624*2f207cbfSStefan Wahren 
625*2f207cbfSStefan Wahren #ifdef CONFIG_PM_SLEEP
626*2f207cbfSStefan Wahren 
627*2f207cbfSStefan Wahren static int mse102x_suspend(struct device *dev)
628*2f207cbfSStefan Wahren {
629*2f207cbfSStefan Wahren 	struct mse102x_net *mse = dev_get_drvdata(dev);
630*2f207cbfSStefan Wahren 	struct net_device *ndev = mse->ndev;
631*2f207cbfSStefan Wahren 
632*2f207cbfSStefan Wahren 	if (netif_running(ndev)) {
633*2f207cbfSStefan Wahren 		netif_device_detach(ndev);
634*2f207cbfSStefan Wahren 		mse102x_net_stop(ndev);
635*2f207cbfSStefan Wahren 	}
636*2f207cbfSStefan Wahren 
637*2f207cbfSStefan Wahren 	return 0;
638*2f207cbfSStefan Wahren }
639*2f207cbfSStefan Wahren 
640*2f207cbfSStefan Wahren static int mse102x_resume(struct device *dev)
641*2f207cbfSStefan Wahren {
642*2f207cbfSStefan Wahren 	struct mse102x_net *mse = dev_get_drvdata(dev);
643*2f207cbfSStefan Wahren 	struct net_device *ndev = mse->ndev;
644*2f207cbfSStefan Wahren 
645*2f207cbfSStefan Wahren 	if (netif_running(ndev)) {
646*2f207cbfSStefan Wahren 		mse102x_net_open(ndev);
647*2f207cbfSStefan Wahren 		netif_device_attach(ndev);
648*2f207cbfSStefan Wahren 	}
649*2f207cbfSStefan Wahren 
650*2f207cbfSStefan Wahren 	return 0;
651*2f207cbfSStefan Wahren }
652*2f207cbfSStefan Wahren #endif
653*2f207cbfSStefan Wahren 
654*2f207cbfSStefan Wahren static SIMPLE_DEV_PM_OPS(mse102x_pm_ops, mse102x_suspend, mse102x_resume);
655*2f207cbfSStefan Wahren 
656*2f207cbfSStefan Wahren static int mse102x_probe_spi(struct spi_device *spi)
657*2f207cbfSStefan Wahren {
658*2f207cbfSStefan Wahren 	struct device *dev = &spi->dev;
659*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses;
660*2f207cbfSStefan Wahren 	struct net_device *ndev;
661*2f207cbfSStefan Wahren 	struct mse102x_net *mse;
662*2f207cbfSStefan Wahren 	int ret;
663*2f207cbfSStefan Wahren 
664*2f207cbfSStefan Wahren 	spi->bits_per_word = 8;
665*2f207cbfSStefan Wahren 	spi->mode |= SPI_MODE_3;
666*2f207cbfSStefan Wahren 	/* enforce minimum speed to ensure device functionality */
667*2f207cbfSStefan Wahren 	spi->master->min_speed_hz = MIN_FREQ_HZ;
668*2f207cbfSStefan Wahren 
669*2f207cbfSStefan Wahren 	if (!spi->max_speed_hz)
670*2f207cbfSStefan Wahren 		spi->max_speed_hz = MAX_FREQ_HZ;
671*2f207cbfSStefan Wahren 
672*2f207cbfSStefan Wahren 	if (spi->max_speed_hz < MIN_FREQ_HZ ||
673*2f207cbfSStefan Wahren 	    spi->max_speed_hz > MAX_FREQ_HZ) {
674*2f207cbfSStefan Wahren 		dev_err(&spi->dev, "SPI max frequency out of range (min: %u, max: %u)\n",
675*2f207cbfSStefan Wahren 			MIN_FREQ_HZ, MAX_FREQ_HZ);
676*2f207cbfSStefan Wahren 		return -EINVAL;
677*2f207cbfSStefan Wahren 	}
678*2f207cbfSStefan Wahren 
679*2f207cbfSStefan Wahren 	ret = spi_setup(spi);
680*2f207cbfSStefan Wahren 	if (ret < 0) {
681*2f207cbfSStefan Wahren 		dev_err(&spi->dev, "Unable to setup SPI device: %d\n", ret);
682*2f207cbfSStefan Wahren 		return ret;
683*2f207cbfSStefan Wahren 	}
684*2f207cbfSStefan Wahren 
685*2f207cbfSStefan Wahren 	ndev = devm_alloc_etherdev(dev, sizeof(struct mse102x_net_spi));
686*2f207cbfSStefan Wahren 	if (!ndev)
687*2f207cbfSStefan Wahren 		return -ENOMEM;
688*2f207cbfSStefan Wahren 
689*2f207cbfSStefan Wahren 	ndev->needed_tailroom += ALIGN(DET_DFT_LEN, 4);
690*2f207cbfSStefan Wahren 	ndev->needed_headroom += ALIGN(DET_SOF_LEN, 4);
691*2f207cbfSStefan Wahren 	ndev->priv_flags &= ~IFF_TX_SKB_SHARING;
692*2f207cbfSStefan Wahren 	ndev->tx_queue_len = 100;
693*2f207cbfSStefan Wahren 
694*2f207cbfSStefan Wahren 	mse = netdev_priv(ndev);
695*2f207cbfSStefan Wahren 	mses = to_mse102x_spi(mse);
696*2f207cbfSStefan Wahren 
697*2f207cbfSStefan Wahren 	mses->spidev = spi;
698*2f207cbfSStefan Wahren 	mutex_init(&mses->lock);
699*2f207cbfSStefan Wahren 	INIT_WORK(&mses->tx_work, mse102x_tx_work);
700*2f207cbfSStefan Wahren 
701*2f207cbfSStefan Wahren 	/* initialise pre-made spi transfer messages */
702*2f207cbfSStefan Wahren 	spi_message_init(&mses->spi_msg);
703*2f207cbfSStefan Wahren 	spi_message_add_tail(&mses->spi_xfer, &mses->spi_msg);
704*2f207cbfSStefan Wahren 
705*2f207cbfSStefan Wahren 	ndev->irq = spi->irq;
706*2f207cbfSStefan Wahren 	mse->ndev = ndev;
707*2f207cbfSStefan Wahren 
708*2f207cbfSStefan Wahren 	/* set the default message enable */
709*2f207cbfSStefan Wahren 	mse->msg_enable = netif_msg_init(-1, MSG_DEFAULT);
710*2f207cbfSStefan Wahren 
711*2f207cbfSStefan Wahren 	skb_queue_head_init(&mse->txq);
712*2f207cbfSStefan Wahren 
713*2f207cbfSStefan Wahren 	SET_NETDEV_DEV(ndev, dev);
714*2f207cbfSStefan Wahren 
715*2f207cbfSStefan Wahren 	dev_set_drvdata(dev, mse);
716*2f207cbfSStefan Wahren 
717*2f207cbfSStefan Wahren 	netif_carrier_off(mse->ndev);
718*2f207cbfSStefan Wahren 	ndev->netdev_ops = &mse102x_netdev_ops;
719*2f207cbfSStefan Wahren 	ndev->ethtool_ops = &mse102x_ethtool_ops;
720*2f207cbfSStefan Wahren 
721*2f207cbfSStefan Wahren 	mse102x_init_mac(mse, dev->of_node);
722*2f207cbfSStefan Wahren 
723*2f207cbfSStefan Wahren 	ret = register_netdev(ndev);
724*2f207cbfSStefan Wahren 	if (ret) {
725*2f207cbfSStefan Wahren 		dev_err(dev, "failed to register network device: %d\n", ret);
726*2f207cbfSStefan Wahren 		return ret;
727*2f207cbfSStefan Wahren 	}
728*2f207cbfSStefan Wahren 
729*2f207cbfSStefan Wahren 	mse102x_init_device_debugfs(mses);
730*2f207cbfSStefan Wahren 
731*2f207cbfSStefan Wahren 	return 0;
732*2f207cbfSStefan Wahren }
733*2f207cbfSStefan Wahren 
734*2f207cbfSStefan Wahren static int mse102x_remove_spi(struct spi_device *spi)
735*2f207cbfSStefan Wahren {
736*2f207cbfSStefan Wahren 	struct mse102x_net *mse = dev_get_drvdata(&spi->dev);
737*2f207cbfSStefan Wahren 	struct mse102x_net_spi *mses = to_mse102x_spi(mse);
738*2f207cbfSStefan Wahren 
739*2f207cbfSStefan Wahren 	if (netif_msg_drv(mse))
740*2f207cbfSStefan Wahren 		dev_info(&spi->dev, "remove\n");
741*2f207cbfSStefan Wahren 
742*2f207cbfSStefan Wahren 	mse102x_remove_device_debugfs(mses);
743*2f207cbfSStefan Wahren 	unregister_netdev(mse->ndev);
744*2f207cbfSStefan Wahren 
745*2f207cbfSStefan Wahren 	return 0;
746*2f207cbfSStefan Wahren }
747*2f207cbfSStefan Wahren 
748*2f207cbfSStefan Wahren static const struct of_device_id mse102x_match_table[] = {
749*2f207cbfSStefan Wahren 	{ .compatible = "vertexcom,mse1021" },
750*2f207cbfSStefan Wahren 	{ .compatible = "vertexcom,mse1022" },
751*2f207cbfSStefan Wahren 	{ }
752*2f207cbfSStefan Wahren };
753*2f207cbfSStefan Wahren MODULE_DEVICE_TABLE(of, mse102x_match_table);
754*2f207cbfSStefan Wahren 
755*2f207cbfSStefan Wahren static struct spi_driver mse102x_driver = {
756*2f207cbfSStefan Wahren 	.driver = {
757*2f207cbfSStefan Wahren 		.name = DRV_NAME,
758*2f207cbfSStefan Wahren 		.of_match_table = mse102x_match_table,
759*2f207cbfSStefan Wahren 		.pm = &mse102x_pm_ops,
760*2f207cbfSStefan Wahren 	},
761*2f207cbfSStefan Wahren 	.probe = mse102x_probe_spi,
762*2f207cbfSStefan Wahren 	.remove = mse102x_remove_spi,
763*2f207cbfSStefan Wahren };
764*2f207cbfSStefan Wahren module_spi_driver(mse102x_driver);
765*2f207cbfSStefan Wahren 
766*2f207cbfSStefan Wahren MODULE_DESCRIPTION("MSE102x Network driver");
767*2f207cbfSStefan Wahren MODULE_AUTHOR("Stefan Wahren <stefan.wahren@in-tech.com>");
768*2f207cbfSStefan Wahren MODULE_LICENSE("GPL");
769*2f207cbfSStefan Wahren MODULE_ALIAS("spi:" DRV_NAME);
770