xref: /openbmc/linux/drivers/net/ethernet/freescale/enetc/enetc_ptp.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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