Lines Matching +full:qmc +full:- +full:chan

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Freescale QMC HDLC Device Driver
14 #include <linux/dma-mapping.h>
27 #include <soc/fsl/qe/qmc.h>
53 return dev_to_hdlc(netdev)->priv; in netdev_to_qmc_hdlc()
61 if (!qmc_hdlc->framer) in qmc_hdlc_framer_set_carrier()
64 guard(mutex)(&qmc_hdlc->carrier_lock); in qmc_hdlc_framer_set_carrier()
66 ret = framer_get_status(qmc_hdlc->framer, &framer_status); in qmc_hdlc_framer_set_carrier()
68 dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); in qmc_hdlc_framer_set_carrier()
72 netif_carrier_on(qmc_hdlc->netdev); in qmc_hdlc_framer_set_carrier()
74 netif_carrier_off(qmc_hdlc->netdev); in qmc_hdlc_framer_set_carrier()
97 if (!qmc_hdlc->framer) in qmc_hdlc_framer_start()
100 ret = framer_power_on(qmc_hdlc->framer); in qmc_hdlc_framer_start()
102 dev_err(qmc_hdlc->dev, "framer power-on failed (%d)\n", ret); in qmc_hdlc_framer_start()
107 ret = framer_get_status(qmc_hdlc->framer, &framer_status); in qmc_hdlc_framer_start()
109 dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); in qmc_hdlc_framer_start()
113 qmc_hdlc->nb.notifier_call = qmc_hdlc_framer_notifier; in qmc_hdlc_framer_start()
114 ret = framer_notifier_register(qmc_hdlc->framer, &qmc_hdlc->nb); in qmc_hdlc_framer_start()
116 dev_err(qmc_hdlc->dev, "framer notifier register failed (%d)\n", ret); in qmc_hdlc_framer_start()
123 framer_power_off(qmc_hdlc->framer); in qmc_hdlc_framer_start()
129 if (!qmc_hdlc->framer) in qmc_hdlc_framer_stop()
132 framer_notifier_unregister(qmc_hdlc->framer, &qmc_hdlc->nb); in qmc_hdlc_framer_stop()
133 framer_power_off(qmc_hdlc->framer); in qmc_hdlc_framer_stop()
142 if (!qmc_hdlc->framer) in qmc_hdlc_framer_set_iface()
145 ret = framer_get_config(qmc_hdlc->framer, &config); in qmc_hdlc_framer_set_iface()
157 return -EINVAL; in qmc_hdlc_framer_set_iface()
160 switch (te1->clock_type) { in qmc_hdlc_framer_set_iface()
171 return -EINVAL; in qmc_hdlc_framer_set_iface()
173 config.line_clock_rate = te1->clock_rate; in qmc_hdlc_framer_set_iface()
175 return framer_set_config(qmc_hdlc->framer, &config); in qmc_hdlc_framer_set_iface()
183 if (!qmc_hdlc->framer) { in qmc_hdlc_framer_get_iface()
188 ret = framer_get_config(qmc_hdlc->framer, &config); in qmc_hdlc_framer_get_iface()
206 te1->clock_type = CLOCK_EXT; in qmc_hdlc_framer_get_iface()
209 te1->clock_type = CLOCK_INT; in qmc_hdlc_framer_get_iface()
212 return -EINVAL; in qmc_hdlc_framer_get_iface()
214 te1->clock_rate = config.line_clock_rate; in qmc_hdlc_framer_get_iface()
222 if (!qmc_hdlc->framer) in qmc_hdlc_framer_init()
225 ret = framer_init(qmc_hdlc->framer); in qmc_hdlc_framer_init()
227 dev_err(qmc_hdlc->dev, "framer init failed (%d)\n", ret); in qmc_hdlc_framer_init()
236 if (!qmc_hdlc->framer) in qmc_hdlc_framer_exit()
239 framer_exit(qmc_hdlc->framer); in qmc_hdlc_framer_exit()
256 netdev = desc->netdev; in qmc_hcld_recv_complete()
259 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_FROM_DEVICE); in qmc_hcld_recv_complete()
262 netdev->stats.rx_errors++; in qmc_hcld_recv_complete()
264 netdev->stats.rx_over_errors++; in qmc_hcld_recv_complete()
266 netdev->stats.rx_frame_errors++; in qmc_hcld_recv_complete()
268 netdev->stats.rx_frame_errors++; in qmc_hcld_recv_complete()
270 netdev->stats.rx_crc_errors++; in qmc_hcld_recv_complete()
271 kfree_skb(desc->skb); in qmc_hcld_recv_complete()
276 crc_size = qmc_hdlc->is_crc32 ? 4 : 2; in qmc_hcld_recv_complete()
278 netdev->stats.rx_length_errors++; in qmc_hcld_recv_complete()
279 kfree_skb(desc->skb); in qmc_hcld_recv_complete()
282 length -= crc_size; in qmc_hcld_recv_complete()
284 netdev->stats.rx_packets++; in qmc_hcld_recv_complete()
285 netdev->stats.rx_bytes += length; in qmc_hcld_recv_complete()
287 skb_put(desc->skb, length); in qmc_hcld_recv_complete()
288 desc->skb->protocol = hdlc_type_trans(desc->skb, netdev); in qmc_hcld_recv_complete()
289 netif_rx(desc->skb); in qmc_hcld_recv_complete()
292 /* Re-queue a transfer using the same descriptor */ in qmc_hcld_recv_complete()
293 ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, desc->dma_size); in qmc_hcld_recv_complete()
295 dev_err(qmc_hdlc->dev, "queue recv desc failed (%d)\n", ret); in qmc_hcld_recv_complete()
296 netdev->stats.rx_errors++; in qmc_hcld_recv_complete()
304 desc->skb = dev_alloc_skb(size); in qmc_hdlc_recv_queue()
305 if (!desc->skb) in qmc_hdlc_recv_queue()
306 return -ENOMEM; in qmc_hdlc_recv_queue()
308 desc->dma_size = size; in qmc_hdlc_recv_queue()
309 desc->dma_addr = dma_map_single(qmc_hdlc->dev, desc->skb->data, in qmc_hdlc_recv_queue()
310 desc->dma_size, DMA_FROM_DEVICE); in qmc_hdlc_recv_queue()
311 ret = dma_mapping_error(qmc_hdlc->dev, desc->dma_addr); in qmc_hdlc_recv_queue()
315 ret = qmc_chan_read_submit(qmc_hdlc->qmc_chan, desc->dma_addr, desc->dma_size, in qmc_hdlc_recv_queue()
323 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_FROM_DEVICE); in qmc_hdlc_recv_queue()
325 kfree_skb(desc->skb); in qmc_hdlc_recv_queue()
326 desc->skb = NULL; in qmc_hdlc_recv_queue()
337 netdev = desc->netdev; in qmc_hdlc_xmit_complete()
340 scoped_guard(spinlock_irqsave, &qmc_hdlc->tx_lock) { in qmc_hdlc_xmit_complete()
341 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_TO_DEVICE); in qmc_hdlc_xmit_complete()
342 skb = desc->skb; in qmc_hdlc_xmit_complete()
343 desc->skb = NULL; /* Release the descriptor */ in qmc_hdlc_xmit_complete()
348 netdev->stats.tx_packets++; in qmc_hdlc_xmit_complete()
349 netdev->stats.tx_bytes += skb->len; in qmc_hdlc_xmit_complete()
358 desc->dma_addr = dma_map_single(qmc_hdlc->dev, desc->skb->data, in qmc_hdlc_xmit_queue()
359 desc->dma_size, DMA_TO_DEVICE); in qmc_hdlc_xmit_queue()
360 ret = dma_mapping_error(qmc_hdlc->dev, desc->dma_addr); in qmc_hdlc_xmit_queue()
362 dev_err(qmc_hdlc->dev, "failed to map skb\n"); in qmc_hdlc_xmit_queue()
366 ret = qmc_chan_write_submit(qmc_hdlc->qmc_chan, desc->dma_addr, desc->dma_size, in qmc_hdlc_xmit_queue()
369 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_TO_DEVICE); in qmc_hdlc_xmit_queue()
370 dev_err(qmc_hdlc->dev, "qmc chan write returns %d\n", ret); in qmc_hdlc_xmit_queue()
383 guard(spinlock_irqsave)(&qmc_hdlc->tx_lock); in qmc_hdlc_xmit()
385 desc = &qmc_hdlc->tx_descs[qmc_hdlc->tx_out]; in qmc_hdlc_xmit()
386 if (WARN_ONCE(desc->skb, "No tx descriptors available\n")) { in qmc_hdlc_xmit()
394 desc->netdev = netdev; in qmc_hdlc_xmit()
395 desc->dma_size = skb->len; in qmc_hdlc_xmit()
396 desc->skb = skb; in qmc_hdlc_xmit()
399 desc->skb = NULL; /* Release the descriptor */ in qmc_hdlc_xmit()
400 if (err == -EBUSY) { in qmc_hdlc_xmit()
405 netdev->stats.tx_dropped++; in qmc_hdlc_xmit()
409 qmc_hdlc->tx_out = (qmc_hdlc->tx_out + 1) % ARRAY_SIZE(qmc_hdlc->tx_descs); in qmc_hdlc_xmit()
411 if (qmc_hdlc->tx_descs[qmc_hdlc->tx_out].skb) in qmc_hdlc_xmit()
425 if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { in qmc_hdlc_xlate_slot_map()
426 dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", in qmc_hdlc_xlate_slot_map()
427 ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); in qmc_hdlc_xlate_slot_map()
428 return -EINVAL; in qmc_hdlc_xlate_slot_map()
431 bitmap_from_u64(ts_mask_avail, ts_info->rx_ts_mask_avail); in qmc_hdlc_xlate_slot_map()
436 dev_err(qmc_hdlc->dev, "Cannot translate timeslots %64pb -> (%64pb, %64pb)\n", in qmc_hdlc_xlate_slot_map()
438 return -EINVAL; in qmc_hdlc_xlate_slot_map()
441 bitmap_to_arr64(&ts_info->tx_ts_mask, ts_mask, 64); in qmc_hdlc_xlate_slot_map()
442 ts_info->rx_ts_mask = ts_info->tx_ts_mask; in qmc_hdlc_xlate_slot_map()
455 if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { in qmc_hdlc_xlate_ts_info()
456 dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", in qmc_hdlc_xlate_ts_info()
457 ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); in qmc_hdlc_xlate_ts_info()
458 return -EINVAL; in qmc_hdlc_xlate_ts_info()
460 if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) { in qmc_hdlc_xlate_ts_info()
461 dev_err(qmc_hdlc->dev, "tx and rx timeslots mismatch (0x%llx, 0x%llx)\n", in qmc_hdlc_xlate_ts_info()
462 ts_info->rx_ts_mask, ts_info->tx_ts_mask); in qmc_hdlc_xlate_ts_info()
463 return -EINVAL; in qmc_hdlc_xlate_ts_info()
466 bitmap_from_u64(ts_mask_avail, ts_info->rx_ts_mask_avail); in qmc_hdlc_xlate_ts_info()
467 bitmap_from_u64(ts_mask, ts_info->rx_ts_mask); in qmc_hdlc_xlate_ts_info()
471 dev_err(qmc_hdlc->dev, "Cannot translate timeslots (%64pb, %64pb) -> %64pb\n", in qmc_hdlc_xlate_ts_info()
473 return -EINVAL; in qmc_hdlc_xlate_ts_info()
478 dev_err(qmc_hdlc->dev, "Slot map out of 32bit (%64pb, %64pb) -> %64pb\n", in qmc_hdlc_xlate_ts_info()
480 return -EINVAL; in qmc_hdlc_xlate_ts_info()
492 ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); in qmc_hdlc_set_iface()
494 dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); in qmc_hdlc_set_iface()
497 ret = qmc_hdlc_xlate_slot_map(qmc_hdlc, te1->slot_map, &ts_info); in qmc_hdlc_set_iface()
501 ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, &ts_info); in qmc_hdlc_set_iface()
503 dev_err(qmc_hdlc->dev, "set QMC channel ts info failed %d\n", ret); in qmc_hdlc_set_iface()
507 qmc_hdlc->slot_map = te1->slot_map; in qmc_hdlc_set_iface()
511 dev_err(qmc_hdlc->dev, "framer set iface failed %d\n", ret); in qmc_hdlc_set_iface()
524 switch (ifs->type) { in qmc_hdlc_ioctl()
526 if (ifs->size < sizeof(te1)) { in qmc_hdlc_ioctl()
528 ret = qmc_hdlc_framer_get_iface(qmc_hdlc, &ifs->type, NULL); in qmc_hdlc_ioctl()
532 if (!ifs->size) in qmc_hdlc_ioctl()
535 ifs->size = sizeof(te1); /* data size wanted */ in qmc_hdlc_ioctl()
536 return -ENOBUFS; in qmc_hdlc_ioctl()
542 ret = qmc_hdlc_framer_get_iface(qmc_hdlc, &ifs->type, &te1); in qmc_hdlc_ioctl()
547 te1.slot_map = qmc_hdlc->slot_map; in qmc_hdlc_ioctl()
549 if (copy_to_user(ifs->ifs_ifsu.te1, &te1, sizeof(te1))) in qmc_hdlc_ioctl()
550 return -EFAULT; in qmc_hdlc_ioctl()
556 return -EPERM; in qmc_hdlc_ioctl()
558 if (netdev->flags & IFF_UP) in qmc_hdlc_ioctl()
559 return -EBUSY; in qmc_hdlc_ioctl()
561 if (copy_from_user(&te1, ifs->ifs_ifsu.te1, sizeof(te1))) in qmc_hdlc_ioctl()
562 return -EFAULT; in qmc_hdlc_ioctl()
564 return qmc_hdlc_set_iface(qmc_hdlc, ifs->type, &te1); in qmc_hdlc_ioctl()
592 * HDLC_MAX_MRU + 4 + 8 for the CRC and some extraspace needed by the QMC in qmc_hdlc_open()
596 chan_param.hdlc.is_crc32 = qmc_hdlc->is_crc32; in qmc_hdlc_open()
597 ret = qmc_chan_set_param(qmc_hdlc->qmc_chan, &chan_param); in qmc_hdlc_open()
599 dev_err(qmc_hdlc->dev, "failed to set param (%d)\n", ret); in qmc_hdlc_open()
604 for (i = 0; i < ARRAY_SIZE(qmc_hdlc->rx_descs); i++) { in qmc_hdlc_open()
605 desc = &qmc_hdlc->rx_descs[i]; in qmc_hdlc_open()
607 desc->netdev = netdev; in qmc_hdlc_open()
609 if (ret == -EBUSY && i != 0) in qmc_hdlc_open()
610 break; /* We use all the QMC chan capability */ in qmc_hdlc_open()
615 ret = qmc_chan_start(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); in qmc_hdlc_open()
617 dev_err(qmc_hdlc->dev, "qmc chan start failed (%d)\n", ret); in qmc_hdlc_open()
626 qmc_chan_reset(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); in qmc_hdlc_open()
627 while (i--) { in qmc_hdlc_open()
628 desc = &qmc_hdlc->rx_descs[i]; in qmc_hdlc_open()
629 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, in qmc_hdlc_open()
631 kfree_skb(desc->skb); in qmc_hdlc_open()
632 desc->skb = NULL; in qmc_hdlc_open()
647 qmc_chan_stop(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); in qmc_hdlc_close()
648 qmc_chan_reset(qmc_hdlc->qmc_chan, QMC_CHAN_ALL); in qmc_hdlc_close()
652 for (i = 0; i < ARRAY_SIZE(qmc_hdlc->tx_descs); i++) { in qmc_hdlc_close()
653 desc = &qmc_hdlc->tx_descs[i]; in qmc_hdlc_close()
654 if (!desc->skb) in qmc_hdlc_close()
656 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, in qmc_hdlc_close()
658 kfree_skb(desc->skb); in qmc_hdlc_close()
659 desc->skb = NULL; in qmc_hdlc_close()
662 for (i = 0; i < ARRAY_SIZE(qmc_hdlc->rx_descs); i++) { in qmc_hdlc_close()
663 desc = &qmc_hdlc->rx_descs[i]; in qmc_hdlc_close()
664 if (!desc->skb) in qmc_hdlc_close()
666 dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, in qmc_hdlc_close()
668 kfree_skb(desc->skb); in qmc_hdlc_close()
669 desc->skb = NULL; in qmc_hdlc_close()
683 return -EINVAL; in qmc_hdlc_attach()
687 qmc_hdlc->is_crc32 = false; in qmc_hdlc_attach()
690 qmc_hdlc->is_crc32 = true; in qmc_hdlc_attach()
693 dev_err(qmc_hdlc->dev, "unsupported parity %u\n", parity); in qmc_hdlc_attach()
694 return -EINVAL; in qmc_hdlc_attach()
709 struct device *dev = &pdev->dev; in qmc_hdlc_probe()
718 return -ENOMEM; in qmc_hdlc_probe()
720 qmc_hdlc->dev = dev; in qmc_hdlc_probe()
721 spin_lock_init(&qmc_hdlc->tx_lock); in qmc_hdlc_probe()
722 mutex_init(&qmc_hdlc->carrier_lock); in qmc_hdlc_probe()
724 qmc_hdlc->qmc_chan = devm_qmc_chan_get_bychild(dev, dev->of_node); in qmc_hdlc_probe()
725 if (IS_ERR(qmc_hdlc->qmc_chan)) in qmc_hdlc_probe()
726 return dev_err_probe(dev, PTR_ERR(qmc_hdlc->qmc_chan), in qmc_hdlc_probe()
727 "get QMC channel failed\n"); in qmc_hdlc_probe()
729 ret = qmc_chan_get_info(qmc_hdlc->qmc_chan, &info); in qmc_hdlc_probe()
731 return dev_err_probe(dev, ret, "get QMC channel info failed\n"); in qmc_hdlc_probe()
734 return dev_err_probe(dev, -EINVAL, "QMC chan mode %d is not QMC_HDLC\n", in qmc_hdlc_probe()
737 ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); in qmc_hdlc_probe()
739 return dev_err_probe(dev, ret, "get QMC channel ts info failed\n"); in qmc_hdlc_probe()
741 ret = qmc_hdlc_xlate_ts_info(qmc_hdlc, &ts_info, &qmc_hdlc->slot_map); in qmc_hdlc_probe()
745 qmc_hdlc->framer = devm_framer_optional_get(dev, "fsl,framer"); in qmc_hdlc_probe()
746 if (IS_ERR(qmc_hdlc->framer)) in qmc_hdlc_probe()
747 return PTR_ERR(qmc_hdlc->framer); in qmc_hdlc_probe()
753 qmc_hdlc->netdev = alloc_hdlcdev(qmc_hdlc); in qmc_hdlc_probe()
754 if (!qmc_hdlc->netdev) { in qmc_hdlc_probe()
755 ret = -ENOMEM; in qmc_hdlc_probe()
759 hdlc = dev_to_hdlc(qmc_hdlc->netdev); in qmc_hdlc_probe()
760 hdlc->attach = qmc_hdlc_attach; in qmc_hdlc_probe()
761 hdlc->xmit = qmc_hdlc_xmit; in qmc_hdlc_probe()
762 SET_NETDEV_DEV(qmc_hdlc->netdev, dev); in qmc_hdlc_probe()
763 qmc_hdlc->netdev->tx_queue_len = ARRAY_SIZE(qmc_hdlc->tx_descs); in qmc_hdlc_probe()
764 qmc_hdlc->netdev->netdev_ops = &qmc_hdlc_netdev_ops; in qmc_hdlc_probe()
765 ret = register_hdlc_device(qmc_hdlc->netdev); in qmc_hdlc_probe()
775 free_netdev(qmc_hdlc->netdev); in qmc_hdlc_probe()
785 unregister_hdlc_device(qmc_hdlc->netdev); in qmc_hdlc_remove()
786 free_netdev(qmc_hdlc->netdev); in qmc_hdlc_remove()
791 { .compatible = "fsl,qmc-hdlc" },
798 .name = "fsl-qmc-hdlc",
807 MODULE_DESCRIPTION("QMC HDLC driver");