119971f5eSYangbo Lu // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
219971f5eSYangbo Lu /* Copyright 2019 NXP */
319971f5eSYangbo Lu
419971f5eSYangbo Lu #include <linux/module.h>
519971f5eSYangbo Lu #include <linux/of.h>
619971f5eSYangbo Lu #include <linux/fsl/ptp_qoriq.h>
719971f5eSYangbo Lu
819971f5eSYangbo Lu #include "enetc.h"
919971f5eSYangbo Lu
1041514737SY.b. Lu int enetc_phc_index = -1;
1141514737SY.b. Lu EXPORT_SYMBOL_GPL(enetc_phc_index);
1241514737SY.b. Lu
1319971f5eSYangbo Lu static struct ptp_clock_info enetc_ptp_caps = {
1419971f5eSYangbo Lu .owner = THIS_MODULE,
1519971f5eSYangbo Lu .name = "ENETC PTP clock",
1619971f5eSYangbo Lu .max_adj = 512000,
1719971f5eSYangbo Lu .n_alarm = 0,
1819971f5eSYangbo Lu .n_ext_ts = 2,
1919971f5eSYangbo Lu .n_per_out = 0,
2019971f5eSYangbo Lu .n_pins = 0,
2119971f5eSYangbo Lu .pps = 1,
2219971f5eSYangbo Lu .adjfine = ptp_qoriq_adjfine,
2319971f5eSYangbo Lu .adjtime = ptp_qoriq_adjtime,
2419971f5eSYangbo Lu .gettime64 = ptp_qoriq_gettime,
2519971f5eSYangbo Lu .settime64 = ptp_qoriq_settime,
2619971f5eSYangbo Lu .enable = ptp_qoriq_enable,
2719971f5eSYangbo Lu };
2819971f5eSYangbo Lu
enetc_ptp_probe(struct pci_dev * pdev,const struct pci_device_id * ent)2919971f5eSYangbo Lu static int enetc_ptp_probe(struct pci_dev *pdev,
3019971f5eSYangbo Lu const struct pci_device_id *ent)
3119971f5eSYangbo Lu {
3219971f5eSYangbo Lu struct ptp_qoriq *ptp_qoriq;
3319971f5eSYangbo Lu void __iomem *base;
3419971f5eSYangbo Lu int err, len, n;
3519971f5eSYangbo Lu
3619971f5eSYangbo Lu if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
3719971f5eSYangbo Lu dev_info(&pdev->dev, "device is disabled, skipping\n");
3819971f5eSYangbo Lu return -ENODEV;
3919971f5eSYangbo Lu }
4019971f5eSYangbo Lu
4119971f5eSYangbo Lu err = pci_enable_device_mem(pdev);
42a72691eeSCai Huoqing if (err)
43a72691eeSCai Huoqing return dev_err_probe(&pdev->dev, err, "device enable failed\n");
4419971f5eSYangbo Lu
4519971f5eSYangbo Lu err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
4619971f5eSYangbo Lu if (err) {
47*cfcfc8f5SChristophe JAILLET dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
4819971f5eSYangbo Lu goto err_dma;
4919971f5eSYangbo Lu }
5019971f5eSYangbo Lu
5119971f5eSYangbo Lu err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
5219971f5eSYangbo Lu if (err) {
5319971f5eSYangbo Lu dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
5419971f5eSYangbo Lu goto err_pci_mem_reg;
5519971f5eSYangbo Lu }
5619971f5eSYangbo Lu
5719971f5eSYangbo Lu pci_set_master(pdev);
5819971f5eSYangbo Lu
5919971f5eSYangbo Lu ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
6019971f5eSYangbo Lu if (!ptp_qoriq) {
6119971f5eSYangbo Lu err = -ENOMEM;
6219971f5eSYangbo Lu goto err_alloc_ptp;
6319971f5eSYangbo Lu }
6419971f5eSYangbo Lu
6519971f5eSYangbo Lu len = pci_resource_len(pdev, ENETC_BAR_REGS);
6619971f5eSYangbo Lu
6719971f5eSYangbo Lu base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
6819971f5eSYangbo Lu if (!base) {
6919971f5eSYangbo Lu err = -ENXIO;
7019971f5eSYangbo Lu dev_err(&pdev->dev, "ioremap() failed\n");
7119971f5eSYangbo Lu goto err_ioremap;
7219971f5eSYangbo Lu }
7319971f5eSYangbo Lu
7419971f5eSYangbo Lu /* Allocate 1 interrupt */
7519971f5eSYangbo Lu n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
7619971f5eSYangbo Lu if (n != 1) {
7719971f5eSYangbo Lu err = -EPERM;
78dd7078f0SChristophe JAILLET goto err_irq_vectors;
7919971f5eSYangbo Lu }
8019971f5eSYangbo Lu
8119971f5eSYangbo Lu ptp_qoriq->irq = pci_irq_vector(pdev, 0);
8219971f5eSYangbo Lu
8319971f5eSYangbo Lu err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq);
8419971f5eSYangbo Lu if (err) {
8519971f5eSYangbo Lu dev_err(&pdev->dev, "request_irq() failed!\n");
8619971f5eSYangbo Lu goto err_irq;
8719971f5eSYangbo Lu }
8819971f5eSYangbo Lu
8919971f5eSYangbo Lu ptp_qoriq->dev = &pdev->dev;
9019971f5eSYangbo Lu
9158066ac9SColin Ian King err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps);
9219971f5eSYangbo Lu if (err)
9319971f5eSYangbo Lu goto err_no_clock;
9419971f5eSYangbo Lu
9541514737SY.b. Lu enetc_phc_index = ptp_qoriq->phc_index;
9619971f5eSYangbo Lu pci_set_drvdata(pdev, ptp_qoriq);
9719971f5eSYangbo Lu
9819971f5eSYangbo Lu return 0;
9919971f5eSYangbo Lu
10019971f5eSYangbo Lu err_no_clock:
10119971f5eSYangbo Lu free_irq(ptp_qoriq->irq, ptp_qoriq);
10219971f5eSYangbo Lu err_irq:
103dd7078f0SChristophe JAILLET pci_free_irq_vectors(pdev);
104dd7078f0SChristophe JAILLET err_irq_vectors:
10519971f5eSYangbo Lu iounmap(base);
10619971f5eSYangbo Lu err_ioremap:
10719971f5eSYangbo Lu kfree(ptp_qoriq);
10819971f5eSYangbo Lu err_alloc_ptp:
10919971f5eSYangbo Lu pci_release_mem_regions(pdev);
11019971f5eSYangbo Lu err_pci_mem_reg:
11119971f5eSYangbo Lu err_dma:
11219971f5eSYangbo Lu pci_disable_device(pdev);
11319971f5eSYangbo Lu
11419971f5eSYangbo Lu return err;
11519971f5eSYangbo Lu }
11619971f5eSYangbo Lu
enetc_ptp_remove(struct pci_dev * pdev)11719971f5eSYangbo Lu static void enetc_ptp_remove(struct pci_dev *pdev)
11819971f5eSYangbo Lu {
11919971f5eSYangbo Lu struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
12019971f5eSYangbo Lu
12141514737SY.b. Lu enetc_phc_index = -1;
12219971f5eSYangbo Lu ptp_qoriq_free(ptp_qoriq);
123dd7078f0SChristophe JAILLET pci_free_irq_vectors(pdev);
12419971f5eSYangbo Lu kfree(ptp_qoriq);
12519971f5eSYangbo Lu
12619971f5eSYangbo Lu pci_release_mem_regions(pdev);
12719971f5eSYangbo Lu pci_disable_device(pdev);
12819971f5eSYangbo Lu }
12919971f5eSYangbo Lu
13019971f5eSYangbo Lu static const struct pci_device_id enetc_ptp_id_table[] = {
13119971f5eSYangbo Lu { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
13219971f5eSYangbo Lu { 0, } /* End of table. */
13319971f5eSYangbo Lu };
13419971f5eSYangbo Lu MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
13519971f5eSYangbo Lu
13619971f5eSYangbo Lu static struct pci_driver enetc_ptp_driver = {
13719971f5eSYangbo Lu .name = KBUILD_MODNAME,
13819971f5eSYangbo Lu .id_table = enetc_ptp_id_table,
13919971f5eSYangbo Lu .probe = enetc_ptp_probe,
14019971f5eSYangbo Lu .remove = enetc_ptp_remove,
14119971f5eSYangbo Lu };
14219971f5eSYangbo Lu module_pci_driver(enetc_ptp_driver);
14319971f5eSYangbo Lu
14419971f5eSYangbo Lu MODULE_DESCRIPTION("ENETC PTP clock driver");
14519971f5eSYangbo Lu MODULE_LICENSE("Dual BSD/GPL");
146