Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  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_GPL(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		return dev_err_probe(&pdev->dev, err, "device enable failed\n");
 44
 45	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 46	if (err) {
 47		dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
 48		goto err_dma;
 49	}
 50
 51	err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
 52	if (err) {
 53		dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
 54		goto err_pci_mem_reg;
 55	}
 56
 57	pci_set_master(pdev);
 58
 59	ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
 60	if (!ptp_qoriq) {
 61		err = -ENOMEM;
 62		goto err_alloc_ptp;
 63	}
 64
 65	len = pci_resource_len(pdev, ENETC_BAR_REGS);
 66
 67	base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
 68	if (!base) {
 69		err = -ENXIO;
 70		dev_err(&pdev->dev, "ioremap() failed\n");
 71		goto err_ioremap;
 72	}
 73
 74	/* Allocate 1 interrupt */
 75	n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
 76	if (n != 1) {
 77		err = -EPERM;
 78		goto err_irq_vectors;
 79	}
 80
 81	ptp_qoriq->irq = pci_irq_vector(pdev, 0);
 82
 83	err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq);
 84	if (err) {
 85		dev_err(&pdev->dev, "request_irq() failed!\n");
 86		goto err_irq;
 87	}
 88
 89	ptp_qoriq->dev = &pdev->dev;
 90
 91	err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps);
 92	if (err)
 93		goto err_no_clock;
 94
 95	enetc_phc_index = ptp_qoriq->phc_index;
 96	pci_set_drvdata(pdev, ptp_qoriq);
 97
 98	return 0;
 99
100err_no_clock:
101	free_irq(ptp_qoriq->irq, ptp_qoriq);
102err_irq:
103	pci_free_irq_vectors(pdev);
104err_irq_vectors:
105	iounmap(base);
106err_ioremap:
107	kfree(ptp_qoriq);
108err_alloc_ptp:
109	pci_release_mem_regions(pdev);
110err_pci_mem_reg:
111err_dma:
112	pci_disable_device(pdev);
113
114	return err;
115}
116
117static void enetc_ptp_remove(struct pci_dev *pdev)
118{
119	struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
120
121	enetc_phc_index = -1;
122	ptp_qoriq_free(ptp_qoriq);
123	pci_free_irq_vectors(pdev);
124	kfree(ptp_qoriq);
125
126	pci_release_mem_regions(pdev);
127	pci_disable_device(pdev);
128}
129
130static const struct pci_device_id enetc_ptp_id_table[] = {
131	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
132	{ 0, } /* End of table. */
133};
134MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
135
136static struct pci_driver enetc_ptp_driver = {
137	.name = KBUILD_MODNAME,
138	.id_table = enetc_ptp_id_table,
139	.probe = enetc_ptp_probe,
140	.remove = enetc_ptp_remove,
141};
142module_pci_driver(enetc_ptp_driver);
143
144MODULE_DESCRIPTION("ENETC PTP clock driver");
145MODULE_LICENSE("Dual BSD/GPL");