xref: /linux/drivers/net/ethernet/litex/litex_liteeth.c (revision 59fff63cc2b75dcfe08f9eeb4b2187d73e53843d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * LiteX Liteeth Ethernet
4  *
5  * Copyright 2017 Joel Stanley <joel@jms.id.au>
6  *
7  */
8 
9 #include <linux/etherdevice.h>
10 #include <linux/interrupt.h>
11 #include <linux/litex.h>
12 #include <linux/module.h>
13 #include <linux/of_net.h>
14 #include <linux/platform_device.h>
15 
16 #define LITEETH_WRITER_SLOT       0x00
17 #define LITEETH_WRITER_LENGTH     0x04
18 #define LITEETH_WRITER_ERRORS     0x08
19 #define LITEETH_WRITER_EV_STATUS  0x0C
20 #define LITEETH_WRITER_EV_PENDING 0x10
21 #define LITEETH_WRITER_EV_ENABLE  0x14
22 #define LITEETH_READER_START      0x18
23 #define LITEETH_READER_READY      0x1C
24 #define LITEETH_READER_LEVEL      0x20
25 #define LITEETH_READER_SLOT       0x24
26 #define LITEETH_READER_LENGTH     0x28
27 #define LITEETH_READER_EV_STATUS  0x2C
28 #define LITEETH_READER_EV_PENDING 0x30
29 #define LITEETH_READER_EV_ENABLE  0x34
30 #define LITEETH_PREAMBLE_CRC      0x38
31 #define LITEETH_PREAMBLE_ERRORS   0x3C
32 #define LITEETH_CRC_ERRORS        0x40
33 
34 #define LITEETH_PHY_CRG_RESET     0x00
35 #define LITEETH_MDIO_W            0x04
36 #define LITEETH_MDIO_R            0x0C
37 
38 #define DRV_NAME	"liteeth"
39 
40 struct liteeth {
41 	void __iomem *base;
42 	struct net_device *netdev;
43 	struct device *dev;
44 	u32 slot_size;
45 
46 	/* Tx */
47 	u32 tx_slot;
48 	u32 num_tx_slots;
49 	void __iomem *tx_base;
50 
51 	/* Rx */
52 	u32 rx_slot;
53 	u32 num_rx_slots;
54 	void __iomem *rx_base;
55 };
56 
57 static int liteeth_rx(struct net_device *netdev)
58 {
59 	struct liteeth *priv = netdev_priv(netdev);
60 	struct sk_buff *skb;
61 	unsigned char *data;
62 	u8 rx_slot;
63 	int len;
64 
65 	rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT);
66 	len = litex_read32(priv->base + LITEETH_WRITER_LENGTH);
67 
68 	if (len == 0 || len > 2048)
69 		goto rx_drop;
70 
71 	skb = netdev_alloc_skb_ip_align(netdev, len);
72 	if (!skb) {
73 		netdev_err(netdev, "couldn't get memory\n");
74 		goto rx_drop;
75 	}
76 
77 	data = skb_put(skb, len);
78 	memcpy_fromio(data, priv->rx_base + rx_slot * priv->slot_size, len);
79 	skb->protocol = eth_type_trans(skb, netdev);
80 
81 	dev_sw_netstats_rx_add(netdev, len);
82 
83 	return netif_rx(skb);
84 
85 rx_drop:
86 	netdev->stats.rx_dropped++;
87 	netdev->stats.rx_errors++;
88 
89 	return NET_RX_DROP;
90 }
91 
92 static irqreturn_t liteeth_interrupt(int irq, void *dev_id)
93 {
94 	struct net_device *netdev = dev_id;
95 	struct liteeth *priv = netdev_priv(netdev);
96 	u8 reg;
97 
98 	reg = litex_read8(priv->base + LITEETH_READER_EV_PENDING);
99 	if (reg) {
100 		if (netif_queue_stopped(netdev))
101 			netif_wake_queue(netdev);
102 		litex_write8(priv->base + LITEETH_READER_EV_PENDING, reg);
103 	}
104 
105 	reg = litex_read8(priv->base + LITEETH_WRITER_EV_PENDING);
106 	if (reg) {
107 		liteeth_rx(netdev);
108 		litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
109 	}
110 
111 	return IRQ_HANDLED;
112 }
113 
114 static int liteeth_open(struct net_device *netdev)
115 {
116 	struct liteeth *priv = netdev_priv(netdev);
117 	int err;
118 
119 	/* Clear pending events */
120 	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, 1);
121 	litex_write8(priv->base + LITEETH_READER_EV_PENDING, 1);
122 
123 	err = request_irq(netdev->irq, liteeth_interrupt, 0, netdev->name, netdev);
124 	if (err) {
125 		netdev_err(netdev, "failed to request irq %d\n", netdev->irq);
126 		return err;
127 	}
128 
129 	/* Enable IRQs */
130 	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 1);
131 	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 1);
132 
133 	netif_carrier_on(netdev);
134 	netif_start_queue(netdev);
135 
136 	return 0;
137 }
138 
139 static int liteeth_stop(struct net_device *netdev)
140 {
141 	struct liteeth *priv = netdev_priv(netdev);
142 
143 	netif_stop_queue(netdev);
144 	netif_carrier_off(netdev);
145 
146 	litex_write8(priv->base + LITEETH_WRITER_EV_ENABLE, 0);
147 	litex_write8(priv->base + LITEETH_READER_EV_ENABLE, 0);
148 
149 	free_irq(netdev->irq, netdev);
150 
151 	return 0;
152 }
153 
154 static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb,
155 				      struct net_device *netdev)
156 {
157 	struct liteeth *priv = netdev_priv(netdev);
158 	void __iomem *txbuffer;
159 
160 	if (!litex_read8(priv->base + LITEETH_READER_READY)) {
161 		if (net_ratelimit())
162 			netdev_err(netdev, "LITEETH_READER_READY not ready\n");
163 
164 		netif_stop_queue(netdev);
165 
166 		return NETDEV_TX_BUSY;
167 	}
168 
169 	/* Reject oversize packets */
170 	if (unlikely(skb->len > priv->slot_size)) {
171 		if (net_ratelimit())
172 			netdev_err(netdev, "tx packet too big\n");
173 
174 		dev_kfree_skb_any(skb);
175 		netdev->stats.tx_dropped++;
176 		netdev->stats.tx_errors++;
177 
178 		return NETDEV_TX_OK;
179 	}
180 
181 	txbuffer = priv->tx_base + priv->tx_slot * priv->slot_size;
182 	memcpy_toio(txbuffer, skb->data, skb->len);
183 	litex_write8(priv->base + LITEETH_READER_SLOT, priv->tx_slot);
184 	litex_write16(priv->base + LITEETH_READER_LENGTH, skb->len);
185 	litex_write8(priv->base + LITEETH_READER_START, 1);
186 
187 	dev_sw_netstats_tx_add(netdev, 1, skb->len);
188 
189 	priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots;
190 	dev_kfree_skb_any(skb);
191 
192 	return NETDEV_TX_OK;
193 }
194 
195 static void
196 liteeth_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
197 {
198 	netdev_stats_to_stats64(stats, &netdev->stats);
199 	dev_fetch_sw_netstats(stats, netdev->tstats);
200 }
201 
202 static const struct net_device_ops liteeth_netdev_ops = {
203 	.ndo_open		= liteeth_open,
204 	.ndo_stop		= liteeth_stop,
205 	.ndo_get_stats64	= liteeth_get_stats64,
206 	.ndo_start_xmit         = liteeth_start_xmit,
207 };
208 
209 static void liteeth_setup_slots(struct liteeth *priv)
210 {
211 	struct device_node *np = priv->dev->of_node;
212 	int err;
213 
214 	err = of_property_read_u32(np, "litex,rx-slots", &priv->num_rx_slots);
215 	if (err) {
216 		dev_dbg(priv->dev, "unable to get litex,rx-slots, using 2\n");
217 		priv->num_rx_slots = 2;
218 	}
219 
220 	err = of_property_read_u32(np, "litex,tx-slots", &priv->num_tx_slots);
221 	if (err) {
222 		dev_dbg(priv->dev, "unable to get litex,tx-slots, using 2\n");
223 		priv->num_tx_slots = 2;
224 	}
225 
226 	err = of_property_read_u32(np, "litex,slot-size", &priv->slot_size);
227 	if (err) {
228 		dev_dbg(priv->dev, "unable to get litex,slot-size, using 0x800\n");
229 		priv->slot_size = 0x800;
230 	}
231 }
232 
233 static int liteeth_probe(struct platform_device *pdev)
234 {
235 	struct net_device *netdev;
236 	void __iomem *buf_base;
237 	struct liteeth *priv;
238 	int irq, err;
239 
240 	netdev = devm_alloc_etherdev(&pdev->dev, sizeof(*priv));
241 	if (!netdev)
242 		return -ENOMEM;
243 
244 	SET_NETDEV_DEV(netdev, &pdev->dev);
245 	platform_set_drvdata(pdev, netdev);
246 
247 	priv = netdev_priv(netdev);
248 	priv->netdev = netdev;
249 	priv->dev = &pdev->dev;
250 
251 	netdev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
252 						      struct pcpu_sw_netstats);
253 	if (!netdev->tstats)
254 		return -ENOMEM;
255 
256 	irq = platform_get_irq(pdev, 0);
257 	if (irq < 0)
258 		return irq;
259 	netdev->irq = irq;
260 
261 	priv->base = devm_platform_ioremap_resource_byname(pdev, "mac");
262 	if (IS_ERR(priv->base))
263 		return PTR_ERR(priv->base);
264 
265 	buf_base = devm_platform_ioremap_resource_byname(pdev, "buffer");
266 	if (IS_ERR(buf_base))
267 		return PTR_ERR(buf_base);
268 
269 	liteeth_setup_slots(priv);
270 
271 	/* Rx slots */
272 	priv->rx_base = buf_base;
273 	priv->rx_slot = 0;
274 
275 	/* Tx slots come after Rx slots */
276 	priv->tx_base = buf_base + priv->num_rx_slots * priv->slot_size;
277 	priv->tx_slot = 0;
278 
279 	err = of_get_ethdev_address(pdev->dev.of_node, netdev);
280 	if (err)
281 		eth_hw_addr_random(netdev);
282 
283 	netdev->netdev_ops = &liteeth_netdev_ops;
284 
285 	err = register_netdev(netdev);
286 	if (err) {
287 		dev_err(&pdev->dev, "Failed to register netdev %d\n", err);
288 		return err;
289 	}
290 
291 	netdev_info(netdev, "irq %d slots: tx %d rx %d size %d\n",
292 		    netdev->irq, priv->num_tx_slots, priv->num_rx_slots, priv->slot_size);
293 
294 	return 0;
295 }
296 
297 static void liteeth_remove(struct platform_device *pdev)
298 {
299 	struct net_device *netdev = platform_get_drvdata(pdev);
300 
301 	unregister_netdev(netdev);
302 }
303 
304 static const struct of_device_id liteeth_of_match[] = {
305 	{ .compatible = "litex,liteeth" },
306 	{ }
307 };
308 MODULE_DEVICE_TABLE(of, liteeth_of_match);
309 
310 static struct platform_driver liteeth_driver = {
311 	.probe = liteeth_probe,
312 	.remove_new = liteeth_remove,
313 	.driver = {
314 		.name = DRV_NAME,
315 		.of_match_table = liteeth_of_match,
316 	},
317 };
318 module_platform_driver(liteeth_driver);
319 
320 MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>");
321 MODULE_LICENSE("GPL");
322