linux/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2/* Copyright 2019 NXP */
   3
   4#include <linux/module.h>
   5#include <linux/of.h>
   6#include <linux/fsl/ptp_qoriq.h>
   7
   8#include "enetc.h"
   9
  10int enetc_phc_index = -1;
  11EXPORT_SYMBOL(enetc_phc_index);
  12
  13static struct ptp_clock_info enetc_ptp_caps = {
  14        .owner          = THIS_MODULE,
  15        .name           = "ENETC PTP clock",
  16        .max_adj        = 512000,
  17        .n_alarm        = 0,
  18        .n_ext_ts       = 2,
  19        .n_per_out      = 0,
  20        .n_pins         = 0,
  21        .pps            = 1,
  22        .adjfine        = ptp_qoriq_adjfine,
  23        .adjtime        = ptp_qoriq_adjtime,
  24        .gettime64      = ptp_qoriq_gettime,
  25        .settime64      = ptp_qoriq_settime,
  26        .enable         = ptp_qoriq_enable,
  27};
  28
  29static int enetc_ptp_probe(struct pci_dev *pdev,
  30                           const struct pci_device_id *ent)
  31{
  32        struct ptp_qoriq *ptp_qoriq;
  33        void __iomem *base;
  34        int err, len, n;
  35
  36        if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
  37                dev_info(&pdev->dev, "device is disabled, skipping\n");
  38                return -ENODEV;
  39        }
  40
  41        err = pci_enable_device_mem(pdev);
  42        if (err) {
  43                dev_err(&pdev->dev, "device enable failed\n");
  44                return err;
  45        }
  46
  47        /* set up for high or low dma */
  48        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
  49        if (err) {
  50                err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
  51                if (err) {
  52                        dev_err(&pdev->dev,
  53                                "DMA configuration failed: 0x%x\n", err);
  54                        goto err_dma;
  55                }
  56        }
  57
  58        err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
  59        if (err) {
  60                dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
  61                goto err_pci_mem_reg;
  62        }
  63
  64        pci_set_master(pdev);
  65
  66        ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
  67        if (!ptp_qoriq) {
  68                err = -ENOMEM;
  69                goto err_alloc_ptp;
  70        }
  71
  72        len = pci_resource_len(pdev, ENETC_BAR_REGS);
  73
  74        base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
  75        if (!base) {
  76                err = -ENXIO;
  77                dev_err(&pdev->dev, "ioremap() failed\n");
  78                goto err_ioremap;
  79        }
  80
  81        /* Allocate 1 interrupt */
  82        n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
  83        if (n != 1) {
  84                err = -EPERM;
  85                goto err_irq_vectors;
  86        }
  87
  88        ptp_qoriq->irq = pci_irq_vector(pdev, 0);
  89
  90        err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq);
  91        if (err) {
  92                dev_err(&pdev->dev, "request_irq() failed!\n");
  93                goto err_irq;
  94        }
  95
  96        ptp_qoriq->dev = &pdev->dev;
  97
  98        err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps);
  99        if (err)
 100                goto err_no_clock;
 101
 102        enetc_phc_index = ptp_qoriq->phc_index;
 103        pci_set_drvdata(pdev, ptp_qoriq);
 104
 105        return 0;
 106
 107err_no_clock:
 108        free_irq(ptp_qoriq->irq, ptp_qoriq);
 109err_irq:
 110        pci_free_irq_vectors(pdev);
 111err_irq_vectors:
 112        iounmap(base);
 113err_ioremap:
 114        kfree(ptp_qoriq);
 115err_alloc_ptp:
 116        pci_release_mem_regions(pdev);
 117err_pci_mem_reg:
 118err_dma:
 119        pci_disable_device(pdev);
 120
 121        return err;
 122}
 123
 124static void enetc_ptp_remove(struct pci_dev *pdev)
 125{
 126        struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
 127
 128        enetc_phc_index = -1;
 129        ptp_qoriq_free(ptp_qoriq);
 130        pci_free_irq_vectors(pdev);
 131        kfree(ptp_qoriq);
 132
 133        pci_release_mem_regions(pdev);
 134        pci_disable_device(pdev);
 135}
 136
 137static const struct pci_device_id enetc_ptp_id_table[] = {
 138        { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
 139        { 0, } /* End of table. */
 140};
 141MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
 142
 143static struct pci_driver enetc_ptp_driver = {
 144        .name = KBUILD_MODNAME,
 145        .id_table = enetc_ptp_id_table,
 146        .probe = enetc_ptp_probe,
 147        .remove = enetc_ptp_remove,
 148};
 149module_pci_driver(enetc_ptp_driver);
 150
 151MODULE_DESCRIPTION("ENETC PTP clock driver");
 152MODULE_LICENSE("Dual BSD/GPL");
 153