1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Microchip's LAN865x 10BASE-T1S MAC-PHY driver
4 *
5 * Author: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
6 */
7
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/phy.h>
11 #include <linux/oa_tc6.h>
12
13 #define DRV_NAME "lan8650"
14
15 /* MAC Network Control Register */
16 #define LAN865X_REG_MAC_NET_CTL 0x00010000
17 #define MAC_NET_CTL_TXEN BIT(3) /* Transmit Enable */
18 #define MAC_NET_CTL_RXEN BIT(2) /* Receive Enable */
19
20 /* MAC Network Configuration Reg */
21 #define LAN865X_REG_MAC_NET_CFG 0x00010001
22 #define MAC_NET_CFG_PROMISCUOUS_MODE BIT(4)
23 #define MAC_NET_CFG_MULTICAST_MODE BIT(6)
24 #define MAC_NET_CFG_UNICAST_MODE BIT(7)
25
26 /* MAC Hash Register Bottom */
27 #define LAN865X_REG_MAC_L_HASH 0x00010020
28 /* MAC Hash Register Top */
29 #define LAN865X_REG_MAC_H_HASH 0x00010021
30 /* MAC Specific Addr 1 Bottom Reg */
31 #define LAN865X_REG_MAC_L_SADDR1 0x00010022
32 /* MAC Specific Addr 1 Top Reg */
33 #define LAN865X_REG_MAC_H_SADDR1 0x00010023
34
35 /* MAC TSU Timer Increment Register */
36 #define LAN865X_REG_MAC_TSU_TIMER_INCR 0x00010077
37 #define MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS 0x0028
38
39 struct lan865x_priv {
40 struct work_struct multicast_work;
41 struct net_device *netdev;
42 struct spi_device *spi;
43 struct oa_tc6 *tc6;
44 };
45
lan865x_set_hw_macaddr_low_bytes(struct oa_tc6 * tc6,const u8 * mac)46 static int lan865x_set_hw_macaddr_low_bytes(struct oa_tc6 *tc6, const u8 *mac)
47 {
48 u32 regval;
49
50 regval = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
51
52 return oa_tc6_write_register(tc6, LAN865X_REG_MAC_L_SADDR1, regval);
53 }
54
lan865x_set_hw_macaddr(struct lan865x_priv * priv,const u8 * mac)55 static int lan865x_set_hw_macaddr(struct lan865x_priv *priv, const u8 *mac)
56 {
57 int restore_ret;
58 u32 regval;
59 int ret;
60
61 /* Configure MAC address low bytes */
62 ret = lan865x_set_hw_macaddr_low_bytes(priv->tc6, mac);
63 if (ret)
64 return ret;
65
66 /* Prepare and configure MAC address high bytes */
67 regval = (mac[5] << 8) | mac[4];
68 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_SADDR1,
69 regval);
70 if (!ret)
71 return 0;
72
73 /* Restore the old MAC address low bytes from netdev if the new MAC
74 * address high bytes setting failed.
75 */
76 restore_ret = lan865x_set_hw_macaddr_low_bytes(priv->tc6,
77 priv->netdev->dev_addr);
78 if (restore_ret)
79 return restore_ret;
80
81 return ret;
82 }
83
84 static const struct ethtool_ops lan865x_ethtool_ops = {
85 .get_link_ksettings = phy_ethtool_get_link_ksettings,
86 .set_link_ksettings = phy_ethtool_set_link_ksettings,
87 };
88
lan865x_set_mac_address(struct net_device * netdev,void * addr)89 static int lan865x_set_mac_address(struct net_device *netdev, void *addr)
90 {
91 struct lan865x_priv *priv = netdev_priv(netdev);
92 struct sockaddr *address = addr;
93 int ret;
94
95 ret = eth_prepare_mac_addr_change(netdev, addr);
96 if (ret < 0)
97 return ret;
98
99 if (ether_addr_equal(address->sa_data, netdev->dev_addr))
100 return 0;
101
102 ret = lan865x_set_hw_macaddr(priv, address->sa_data);
103 if (ret)
104 return ret;
105
106 eth_commit_mac_addr_change(netdev, addr);
107
108 return 0;
109 }
110
get_address_bit(u8 addr[ETH_ALEN],u32 bit)111 static u32 get_address_bit(u8 addr[ETH_ALEN], u32 bit)
112 {
113 return ((addr[bit / 8]) >> (bit % 8)) & 1;
114 }
115
lan865x_hash(u8 addr[ETH_ALEN])116 static u32 lan865x_hash(u8 addr[ETH_ALEN])
117 {
118 u32 hash_index = 0;
119
120 for (int i = 0; i < 6; i++) {
121 u32 hash = 0;
122
123 for (int j = 0; j < 8; j++)
124 hash ^= get_address_bit(addr, (j * 6) + i);
125
126 hash_index |= (hash << i);
127 }
128
129 return hash_index;
130 }
131
lan865x_set_specific_multicast_addr(struct lan865x_priv * priv)132 static int lan865x_set_specific_multicast_addr(struct lan865x_priv *priv)
133 {
134 struct netdev_hw_addr *ha;
135 u32 hash_lo = 0;
136 u32 hash_hi = 0;
137 int ret;
138
139 netdev_for_each_mc_addr(ha, priv->netdev) {
140 u32 bit_num = lan865x_hash(ha->addr);
141
142 if (bit_num >= BIT(5))
143 hash_hi |= (1 << (bit_num - BIT(5)));
144 else
145 hash_lo |= (1 << bit_num);
146 }
147
148 /* Enabling specific multicast addresses */
149 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH, hash_hi);
150 if (ret) {
151 netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
152 ret);
153 return ret;
154 }
155
156 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH, hash_lo);
157 if (ret)
158 netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
159 ret);
160
161 return ret;
162 }
163
lan865x_set_all_multicast_addr(struct lan865x_priv * priv)164 static int lan865x_set_all_multicast_addr(struct lan865x_priv *priv)
165 {
166 int ret;
167
168 /* Enabling all multicast addresses */
169 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH,
170 0xffffffff);
171 if (ret) {
172 netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
173 ret);
174 return ret;
175 }
176
177 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH,
178 0xffffffff);
179 if (ret)
180 netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
181 ret);
182
183 return ret;
184 }
185
lan865x_clear_all_multicast_addr(struct lan865x_priv * priv)186 static int lan865x_clear_all_multicast_addr(struct lan865x_priv *priv)
187 {
188 int ret;
189
190 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH, 0);
191 if (ret) {
192 netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
193 ret);
194 return ret;
195 }
196
197 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH, 0);
198 if (ret)
199 netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
200 ret);
201
202 return ret;
203 }
204
lan865x_multicast_work_handler(struct work_struct * work)205 static void lan865x_multicast_work_handler(struct work_struct *work)
206 {
207 struct lan865x_priv *priv = container_of(work, struct lan865x_priv,
208 multicast_work);
209 u32 regval = 0;
210 int ret;
211
212 if (priv->netdev->flags & IFF_PROMISC) {
213 /* Enabling promiscuous mode */
214 regval |= MAC_NET_CFG_PROMISCUOUS_MODE;
215 regval &= (~MAC_NET_CFG_MULTICAST_MODE);
216 regval &= (~MAC_NET_CFG_UNICAST_MODE);
217 } else if (priv->netdev->flags & IFF_ALLMULTI) {
218 /* Enabling all multicast mode */
219 if (lan865x_set_all_multicast_addr(priv))
220 return;
221
222 regval &= (~MAC_NET_CFG_PROMISCUOUS_MODE);
223 regval |= MAC_NET_CFG_MULTICAST_MODE;
224 regval &= (~MAC_NET_CFG_UNICAST_MODE);
225 } else if (!netdev_mc_empty(priv->netdev)) {
226 /* Enabling specific multicast mode */
227 if (lan865x_set_specific_multicast_addr(priv))
228 return;
229
230 regval &= (~MAC_NET_CFG_PROMISCUOUS_MODE);
231 regval |= MAC_NET_CFG_MULTICAST_MODE;
232 regval &= (~MAC_NET_CFG_UNICAST_MODE);
233 } else {
234 /* Enabling local mac address only */
235 if (lan865x_clear_all_multicast_addr(priv))
236 return;
237 }
238 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CFG, regval);
239 if (ret)
240 netdev_err(priv->netdev, "Failed to enable promiscuous/multicast/normal mode: %d\n",
241 ret);
242 }
243
lan865x_set_multicast_list(struct net_device * netdev)244 static void lan865x_set_multicast_list(struct net_device *netdev)
245 {
246 struct lan865x_priv *priv = netdev_priv(netdev);
247
248 schedule_work(&priv->multicast_work);
249 }
250
lan865x_send_packet(struct sk_buff * skb,struct net_device * netdev)251 static netdev_tx_t lan865x_send_packet(struct sk_buff *skb,
252 struct net_device *netdev)
253 {
254 struct lan865x_priv *priv = netdev_priv(netdev);
255
256 return oa_tc6_start_xmit(priv->tc6, skb);
257 }
258
lan865x_hw_disable(struct lan865x_priv * priv)259 static int lan865x_hw_disable(struct lan865x_priv *priv)
260 {
261 u32 regval;
262
263 if (oa_tc6_read_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, ®val))
264 return -ENODEV;
265
266 regval &= ~(MAC_NET_CTL_TXEN | MAC_NET_CTL_RXEN);
267
268 if (oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, regval))
269 return -ENODEV;
270
271 return 0;
272 }
273
lan865x_net_close(struct net_device * netdev)274 static int lan865x_net_close(struct net_device *netdev)
275 {
276 struct lan865x_priv *priv = netdev_priv(netdev);
277 int ret;
278
279 netif_stop_queue(netdev);
280 phy_stop(netdev->phydev);
281 ret = lan865x_hw_disable(priv);
282 if (ret) {
283 netdev_err(netdev, "Failed to disable the hardware: %d\n", ret);
284 return ret;
285 }
286
287 return 0;
288 }
289
lan865x_hw_enable(struct lan865x_priv * priv)290 static int lan865x_hw_enable(struct lan865x_priv *priv)
291 {
292 u32 regval;
293
294 if (oa_tc6_read_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, ®val))
295 return -ENODEV;
296
297 regval |= MAC_NET_CTL_TXEN | MAC_NET_CTL_RXEN;
298
299 if (oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, regval))
300 return -ENODEV;
301
302 return 0;
303 }
304
lan865x_net_open(struct net_device * netdev)305 static int lan865x_net_open(struct net_device *netdev)
306 {
307 struct lan865x_priv *priv = netdev_priv(netdev);
308 int ret;
309
310 ret = lan865x_hw_enable(priv);
311 if (ret) {
312 netdev_err(netdev, "Failed to enable hardware: %d\n", ret);
313 return ret;
314 }
315
316 phy_start(netdev->phydev);
317
318 netif_start_queue(netdev);
319
320 return 0;
321 }
322
323 static const struct net_device_ops lan865x_netdev_ops = {
324 .ndo_open = lan865x_net_open,
325 .ndo_stop = lan865x_net_close,
326 .ndo_start_xmit = lan865x_send_packet,
327 .ndo_set_rx_mode = lan865x_set_multicast_list,
328 .ndo_set_mac_address = lan865x_set_mac_address,
329 .ndo_validate_addr = eth_validate_addr,
330 .ndo_eth_ioctl = phy_do_ioctl_running,
331 };
332
lan865x_probe(struct spi_device * spi)333 static int lan865x_probe(struct spi_device *spi)
334 {
335 struct net_device *netdev;
336 struct lan865x_priv *priv;
337 int ret;
338
339 netdev = alloc_etherdev(sizeof(struct lan865x_priv));
340 if (!netdev)
341 return -ENOMEM;
342
343 priv = netdev_priv(netdev);
344 priv->netdev = netdev;
345 priv->spi = spi;
346 spi_set_drvdata(spi, priv);
347 INIT_WORK(&priv->multicast_work, lan865x_multicast_work_handler);
348
349 priv->tc6 = oa_tc6_init(spi, netdev);
350 if (!priv->tc6) {
351 ret = -ENODEV;
352 goto free_netdev;
353 }
354
355 /* LAN865x Rev.B0/B1 configuration parameters from AN1760
356 * As per the Configuration Application Note AN1760 published in the
357 * link, https://www.microchip.com/en-us/application-notes/an1760
358 * Revision F (DS60001760G - June 2024), configure the MAC to set time
359 * stamping at the end of the Start of Frame Delimiter (SFD) and set the
360 * Timer Increment reg to 40 ns to be used as a 25 MHz internal clock.
361 */
362 ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_TSU_TIMER_INCR,
363 MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS);
364 if (ret) {
365 dev_err(&spi->dev, "Failed to config TSU Timer Incr reg: %d\n",
366 ret);
367 goto oa_tc6_exit;
368 }
369
370 /* As per the point s3 in the below errata, SPI receive Ethernet frame
371 * transfer may halt when starting the next frame in the same data block
372 * (chunk) as the end of a previous frame. The RFA field should be
373 * configured to 01b or 10b for proper operation. In these modes, only
374 * one receive Ethernet frame will be placed in a single data block.
375 * When the RFA field is written to 01b, received frames will be forced
376 * to only start in the first word of the data block payload (SWO=0). As
377 * recommended, enable zero align receive frame feature for proper
378 * operation.
379 *
380 * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/Errata/LAN8650-1-Errata-80001075.pdf
381 */
382 ret = oa_tc6_zero_align_receive_frame_enable(priv->tc6);
383 if (ret) {
384 dev_err(&spi->dev, "Failed to set ZARFE: %d\n", ret);
385 goto oa_tc6_exit;
386 }
387
388 /* Get the MAC address from the SPI device tree node */
389 if (device_get_ethdev_address(&spi->dev, netdev))
390 eth_hw_addr_random(netdev);
391
392 ret = lan865x_set_hw_macaddr(priv, netdev->dev_addr);
393 if (ret) {
394 dev_err(&spi->dev, "Failed to configure MAC: %d\n", ret);
395 goto oa_tc6_exit;
396 }
397
398 netdev->if_port = IF_PORT_10BASET;
399 netdev->irq = spi->irq;
400 netdev->netdev_ops = &lan865x_netdev_ops;
401 netdev->ethtool_ops = &lan865x_ethtool_ops;
402
403 ret = register_netdev(netdev);
404 if (ret) {
405 dev_err(&spi->dev, "Register netdev failed (ret = %d)", ret);
406 goto oa_tc6_exit;
407 }
408
409 return 0;
410
411 oa_tc6_exit:
412 oa_tc6_exit(priv->tc6);
413 free_netdev:
414 free_netdev(priv->netdev);
415 return ret;
416 }
417
lan865x_remove(struct spi_device * spi)418 static void lan865x_remove(struct spi_device *spi)
419 {
420 struct lan865x_priv *priv = spi_get_drvdata(spi);
421
422 cancel_work_sync(&priv->multicast_work);
423 unregister_netdev(priv->netdev);
424 oa_tc6_exit(priv->tc6);
425 free_netdev(priv->netdev);
426 }
427
428 static const struct spi_device_id lan865x_ids[] = {
429 { .name = "lan8650" },
430 { .name = "lan8651" },
431 {},
432 };
433 MODULE_DEVICE_TABLE(spi, lan865x_ids);
434
435 static const struct of_device_id lan865x_dt_ids[] = {
436 { .compatible = "microchip,lan8650" },
437 { .compatible = "microchip,lan8651" },
438 { /* Sentinel */ }
439 };
440 MODULE_DEVICE_TABLE(of, lan865x_dt_ids);
441
442 static struct spi_driver lan865x_driver = {
443 .driver = {
444 .name = DRV_NAME,
445 .of_match_table = lan865x_dt_ids,
446 },
447 .probe = lan865x_probe,
448 .remove = lan865x_remove,
449 .id_table = lan865x_ids,
450 };
451 module_spi_driver(lan865x_driver);
452
453 MODULE_DESCRIPTION(DRV_NAME " 10Base-T1S MACPHY Ethernet Driver");
454 MODULE_AUTHOR("Parthiban Veerasooran <parthiban.veerasooran@microchip.com>");
455 MODULE_LICENSE("GPL");
456