18c56df37SRadoslaw Biernacki // SPDX-License-Identifier: GPL-2.0
28c56df37SRadoslaw Biernacki /* cavium_ptp.c - PTP 1588 clock on Cavium hardware
38c56df37SRadoslaw Biernacki * Copyright (c) 2003-2015, 2017 Cavium, Inc.
48c56df37SRadoslaw Biernacki */
58c56df37SRadoslaw Biernacki
68c56df37SRadoslaw Biernacki #include <linux/device.h>
78c56df37SRadoslaw Biernacki #include <linux/module.h>
88c56df37SRadoslaw Biernacki #include <linux/timecounter.h>
98c56df37SRadoslaw Biernacki #include <linux/pci.h>
108c56df37SRadoslaw Biernacki
118c56df37SRadoslaw Biernacki #include "cavium_ptp.h"
128c56df37SRadoslaw Biernacki
1334343410SStephen Hemminger #define DRV_NAME "cavium_ptp"
148c56df37SRadoslaw Biernacki
158c56df37SRadoslaw Biernacki #define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C
16aa3afcccSPrakash Brahmajyosyula #define PCI_SUBSYS_DEVID_88XX_PTP 0xA10C
17aa3afcccSPrakash Brahmajyosyula #define PCI_SUBSYS_DEVID_81XX_PTP 0XA20C
18aa3afcccSPrakash Brahmajyosyula #define PCI_SUBSYS_DEVID_83XX_PTP 0xA30C
198c56df37SRadoslaw Biernacki #define PCI_DEVICE_ID_CAVIUM_RST 0xA00E
208c56df37SRadoslaw Biernacki
218c56df37SRadoslaw Biernacki #define PCI_PTP_BAR_NO 0
228c56df37SRadoslaw Biernacki #define PCI_RST_BAR_NO 0
238c56df37SRadoslaw Biernacki
248c56df37SRadoslaw Biernacki #define PTP_CLOCK_CFG 0xF00ULL
258c56df37SRadoslaw Biernacki #define PTP_CLOCK_CFG_PTP_EN BIT(0)
268c56df37SRadoslaw Biernacki #define PTP_CLOCK_LO 0xF08ULL
278c56df37SRadoslaw Biernacki #define PTP_CLOCK_HI 0xF10ULL
288c56df37SRadoslaw Biernacki #define PTP_CLOCK_COMP 0xF18ULL
298c56df37SRadoslaw Biernacki
308c56df37SRadoslaw Biernacki #define RST_BOOT 0x1600ULL
318c56df37SRadoslaw Biernacki #define CLOCK_BASE_RATE 50000000ULL
328c56df37SRadoslaw Biernacki
ptp_cavium_clock_get(void)338c56df37SRadoslaw Biernacki static u64 ptp_cavium_clock_get(void)
348c56df37SRadoslaw Biernacki {
358c56df37SRadoslaw Biernacki struct pci_dev *pdev;
368c56df37SRadoslaw Biernacki void __iomem *base;
378c56df37SRadoslaw Biernacki u64 ret = CLOCK_BASE_RATE * 16;
388c56df37SRadoslaw Biernacki
398c56df37SRadoslaw Biernacki pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
408c56df37SRadoslaw Biernacki PCI_DEVICE_ID_CAVIUM_RST, NULL);
418c56df37SRadoslaw Biernacki if (!pdev)
428c56df37SRadoslaw Biernacki goto error;
438c56df37SRadoslaw Biernacki
448c56df37SRadoslaw Biernacki base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO);
458c56df37SRadoslaw Biernacki if (!base)
468c56df37SRadoslaw Biernacki goto error_put_pdev;
478c56df37SRadoslaw Biernacki
488c56df37SRadoslaw Biernacki ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT) >> 33) & 0x3f);
498c56df37SRadoslaw Biernacki
508c56df37SRadoslaw Biernacki iounmap(base);
518c56df37SRadoslaw Biernacki
528c56df37SRadoslaw Biernacki error_put_pdev:
538c56df37SRadoslaw Biernacki pci_dev_put(pdev);
548c56df37SRadoslaw Biernacki
558c56df37SRadoslaw Biernacki error:
568c56df37SRadoslaw Biernacki return ret;
578c56df37SRadoslaw Biernacki }
588c56df37SRadoslaw Biernacki
cavium_ptp_get(void)598c56df37SRadoslaw Biernacki struct cavium_ptp *cavium_ptp_get(void)
608c56df37SRadoslaw Biernacki {
618c56df37SRadoslaw Biernacki struct cavium_ptp *ptp;
628c56df37SRadoslaw Biernacki struct pci_dev *pdev;
638c56df37SRadoslaw Biernacki
648c56df37SRadoslaw Biernacki pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
658c56df37SRadoslaw Biernacki PCI_DEVICE_ID_CAVIUM_PTP, NULL);
668c56df37SRadoslaw Biernacki if (!pdev)
678c56df37SRadoslaw Biernacki return ERR_PTR(-ENODEV);
688c56df37SRadoslaw Biernacki
698c56df37SRadoslaw Biernacki ptp = pci_get_drvdata(pdev);
708c56df37SRadoslaw Biernacki if (!ptp)
718c56df37SRadoslaw Biernacki ptp = ERR_PTR(-EPROBE_DEFER);
728c56df37SRadoslaw Biernacki if (IS_ERR(ptp))
738c56df37SRadoslaw Biernacki pci_dev_put(pdev);
748c56df37SRadoslaw Biernacki
758c56df37SRadoslaw Biernacki return ptp;
768c56df37SRadoslaw Biernacki }
778c56df37SRadoslaw Biernacki EXPORT_SYMBOL(cavium_ptp_get);
788c56df37SRadoslaw Biernacki
cavium_ptp_put(struct cavium_ptp * ptp)798c56df37SRadoslaw Biernacki void cavium_ptp_put(struct cavium_ptp *ptp)
808c56df37SRadoslaw Biernacki {
8107a2e1cfSJan Glauber if (!ptp)
8207a2e1cfSJan Glauber return;
838c56df37SRadoslaw Biernacki pci_dev_put(ptp->pdev);
848c56df37SRadoslaw Biernacki }
858c56df37SRadoslaw Biernacki EXPORT_SYMBOL(cavium_ptp_put);
868c56df37SRadoslaw Biernacki
878c56df37SRadoslaw Biernacki /**
888c56df37SRadoslaw Biernacki * cavium_ptp_adjfine() - Adjust ptp frequency
89*74c654a8SWang Hai * @ptp_info: PTP clock info
908c56df37SRadoslaw Biernacki * @scaled_ppm: how much to adjust by, in parts per million, but with a
918c56df37SRadoslaw Biernacki * 16 bit binary fractional field
928c56df37SRadoslaw Biernacki */
cavium_ptp_adjfine(struct ptp_clock_info * ptp_info,long scaled_ppm)938c56df37SRadoslaw Biernacki static int cavium_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
948c56df37SRadoslaw Biernacki {
958c56df37SRadoslaw Biernacki struct cavium_ptp *clock =
968c56df37SRadoslaw Biernacki container_of(ptp_info, struct cavium_ptp, ptp_info);
978c56df37SRadoslaw Biernacki unsigned long flags;
988c56df37SRadoslaw Biernacki u64 comp;
998c56df37SRadoslaw Biernacki u64 adj;
1008c56df37SRadoslaw Biernacki bool neg_adj = false;
1018c56df37SRadoslaw Biernacki
1028c56df37SRadoslaw Biernacki if (scaled_ppm < 0) {
1038c56df37SRadoslaw Biernacki neg_adj = true;
1048c56df37SRadoslaw Biernacki scaled_ppm = -scaled_ppm;
1058c56df37SRadoslaw Biernacki }
1068c56df37SRadoslaw Biernacki
1078c56df37SRadoslaw Biernacki /* The hardware adds the clock compensation value to the PTP clock
1088c56df37SRadoslaw Biernacki * on every coprocessor clock cycle. Typical convention is that it
1098c56df37SRadoslaw Biernacki * represent number of nanosecond betwen each cycle. In this
1108c56df37SRadoslaw Biernacki * convention compensation value is in 64 bit fixed-point
1118c56df37SRadoslaw Biernacki * representation where upper 32 bits are number of nanoseconds
1128c56df37SRadoslaw Biernacki * and lower is fractions of nanosecond.
1138c56df37SRadoslaw Biernacki * The scaled_ppm represent the ratio in "parts per bilion" by which the
1148c56df37SRadoslaw Biernacki * compensation value should be corrected.
1158c56df37SRadoslaw Biernacki * To calculate new compenstation value we use 64bit fixed point
1168c56df37SRadoslaw Biernacki * arithmetic on following formula
1178c56df37SRadoslaw Biernacki * comp = tbase + tbase * scaled_ppm / (1M * 2^16)
1188c56df37SRadoslaw Biernacki * where tbase is the basic compensation value calculated initialy
1198c56df37SRadoslaw Biernacki * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian
1208c56df37SRadoslaw Biernacki * independent structure definition to write data to PTP register.
1218c56df37SRadoslaw Biernacki */
1228c56df37SRadoslaw Biernacki comp = ((u64)1000000000ull << 32) / clock->clock_rate;
1238c56df37SRadoslaw Biernacki adj = comp * scaled_ppm;
1248c56df37SRadoslaw Biernacki adj >>= 16;
1258c56df37SRadoslaw Biernacki adj = div_u64(adj, 1000000ull);
1268c56df37SRadoslaw Biernacki comp = neg_adj ? comp - adj : comp + adj;
1278c56df37SRadoslaw Biernacki
1288c56df37SRadoslaw Biernacki spin_lock_irqsave(&clock->spin_lock, flags);
1298c56df37SRadoslaw Biernacki writeq(comp, clock->reg_base + PTP_CLOCK_COMP);
1308c56df37SRadoslaw Biernacki spin_unlock_irqrestore(&clock->spin_lock, flags);
1318c56df37SRadoslaw Biernacki
1328c56df37SRadoslaw Biernacki return 0;
1338c56df37SRadoslaw Biernacki }
1348c56df37SRadoslaw Biernacki
1358c56df37SRadoslaw Biernacki /**
1368c56df37SRadoslaw Biernacki * cavium_ptp_adjtime() - Adjust ptp time
137*74c654a8SWang Hai * @ptp_info: PTP clock info
1388c56df37SRadoslaw Biernacki * @delta: how much to adjust by, in nanosecs
1398c56df37SRadoslaw Biernacki */
cavium_ptp_adjtime(struct ptp_clock_info * ptp_info,s64 delta)1408c56df37SRadoslaw Biernacki static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
1418c56df37SRadoslaw Biernacki {
1428c56df37SRadoslaw Biernacki struct cavium_ptp *clock =
1438c56df37SRadoslaw Biernacki container_of(ptp_info, struct cavium_ptp, ptp_info);
1448c56df37SRadoslaw Biernacki unsigned long flags;
1458c56df37SRadoslaw Biernacki
1468c56df37SRadoslaw Biernacki spin_lock_irqsave(&clock->spin_lock, flags);
1478c56df37SRadoslaw Biernacki timecounter_adjtime(&clock->time_counter, delta);
1488c56df37SRadoslaw Biernacki spin_unlock_irqrestore(&clock->spin_lock, flags);
1498c56df37SRadoslaw Biernacki
1508c56df37SRadoslaw Biernacki /* Sync, for network driver to get latest value */
1518c56df37SRadoslaw Biernacki smp_mb();
1528c56df37SRadoslaw Biernacki
1538c56df37SRadoslaw Biernacki return 0;
1548c56df37SRadoslaw Biernacki }
1558c56df37SRadoslaw Biernacki
1568c56df37SRadoslaw Biernacki /**
1578c56df37SRadoslaw Biernacki * cavium_ptp_gettime() - Get hardware clock time with adjustment
158*74c654a8SWang Hai * @ptp_info: PTP clock info
1598c56df37SRadoslaw Biernacki * @ts: timespec
1608c56df37SRadoslaw Biernacki */
cavium_ptp_gettime(struct ptp_clock_info * ptp_info,struct timespec64 * ts)1618c56df37SRadoslaw Biernacki static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info,
1628c56df37SRadoslaw Biernacki struct timespec64 *ts)
1638c56df37SRadoslaw Biernacki {
1648c56df37SRadoslaw Biernacki struct cavium_ptp *clock =
1658c56df37SRadoslaw Biernacki container_of(ptp_info, struct cavium_ptp, ptp_info);
1668c56df37SRadoslaw Biernacki unsigned long flags;
1678c56df37SRadoslaw Biernacki u64 nsec;
1688c56df37SRadoslaw Biernacki
1698c56df37SRadoslaw Biernacki spin_lock_irqsave(&clock->spin_lock, flags);
1708c56df37SRadoslaw Biernacki nsec = timecounter_read(&clock->time_counter);
1718c56df37SRadoslaw Biernacki spin_unlock_irqrestore(&clock->spin_lock, flags);
1728c56df37SRadoslaw Biernacki
1738c56df37SRadoslaw Biernacki *ts = ns_to_timespec64(nsec);
1748c56df37SRadoslaw Biernacki
1758c56df37SRadoslaw Biernacki return 0;
1768c56df37SRadoslaw Biernacki }
1778c56df37SRadoslaw Biernacki
1788c56df37SRadoslaw Biernacki /**
1798c56df37SRadoslaw Biernacki * cavium_ptp_settime() - Set hardware clock time. Reset adjustment
180*74c654a8SWang Hai * @ptp_info: PTP clock info
1818c56df37SRadoslaw Biernacki * @ts: timespec
1828c56df37SRadoslaw Biernacki */
cavium_ptp_settime(struct ptp_clock_info * ptp_info,const struct timespec64 * ts)1838c56df37SRadoslaw Biernacki static int cavium_ptp_settime(struct ptp_clock_info *ptp_info,
1848c56df37SRadoslaw Biernacki const struct timespec64 *ts)
1858c56df37SRadoslaw Biernacki {
1868c56df37SRadoslaw Biernacki struct cavium_ptp *clock =
1878c56df37SRadoslaw Biernacki container_of(ptp_info, struct cavium_ptp, ptp_info);
1888c56df37SRadoslaw Biernacki unsigned long flags;
1898c56df37SRadoslaw Biernacki u64 nsec;
1908c56df37SRadoslaw Biernacki
1918c56df37SRadoslaw Biernacki nsec = timespec64_to_ns(ts);
1928c56df37SRadoslaw Biernacki
1938c56df37SRadoslaw Biernacki spin_lock_irqsave(&clock->spin_lock, flags);
1948c56df37SRadoslaw Biernacki timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec);
1958c56df37SRadoslaw Biernacki spin_unlock_irqrestore(&clock->spin_lock, flags);
1968c56df37SRadoslaw Biernacki
1978c56df37SRadoslaw Biernacki return 0;
1988c56df37SRadoslaw Biernacki }
1998c56df37SRadoslaw Biernacki
2008c56df37SRadoslaw Biernacki /**
2018c56df37SRadoslaw Biernacki * cavium_ptp_enable() - Request to enable or disable an ancillary feature.
202*74c654a8SWang Hai * @ptp_info: PTP clock info
2038c56df37SRadoslaw Biernacki * @rq: request
2048c56df37SRadoslaw Biernacki * @on: is it on
2058c56df37SRadoslaw Biernacki */
cavium_ptp_enable(struct ptp_clock_info * ptp_info,struct ptp_clock_request * rq,int on)2068c56df37SRadoslaw Biernacki static int cavium_ptp_enable(struct ptp_clock_info *ptp_info,
2078c56df37SRadoslaw Biernacki struct ptp_clock_request *rq, int on)
2088c56df37SRadoslaw Biernacki {
2098c56df37SRadoslaw Biernacki return -EOPNOTSUPP;
2108c56df37SRadoslaw Biernacki }
2118c56df37SRadoslaw Biernacki
cavium_ptp_cc_read(const struct cyclecounter * cc)2128c56df37SRadoslaw Biernacki static u64 cavium_ptp_cc_read(const struct cyclecounter *cc)
2138c56df37SRadoslaw Biernacki {
2148c56df37SRadoslaw Biernacki struct cavium_ptp *clock =
2158c56df37SRadoslaw Biernacki container_of(cc, struct cavium_ptp, cycle_counter);
2168c56df37SRadoslaw Biernacki
2178c56df37SRadoslaw Biernacki return readq(clock->reg_base + PTP_CLOCK_HI);
2188c56df37SRadoslaw Biernacki }
2198c56df37SRadoslaw Biernacki
cavium_ptp_probe(struct pci_dev * pdev,const struct pci_device_id * ent)2208c56df37SRadoslaw Biernacki static int cavium_ptp_probe(struct pci_dev *pdev,
2218c56df37SRadoslaw Biernacki const struct pci_device_id *ent)
2228c56df37SRadoslaw Biernacki {
2238c56df37SRadoslaw Biernacki struct device *dev = &pdev->dev;
2248c56df37SRadoslaw Biernacki struct cavium_ptp *clock;
2258c56df37SRadoslaw Biernacki struct cyclecounter *cc;
2268c56df37SRadoslaw Biernacki u64 clock_cfg;
2278c56df37SRadoslaw Biernacki u64 clock_comp;
2288c56df37SRadoslaw Biernacki int err;
2298c56df37SRadoslaw Biernacki
2308c56df37SRadoslaw Biernacki clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
2318c56df37SRadoslaw Biernacki if (!clock) {
2328c56df37SRadoslaw Biernacki err = -ENOMEM;
2338c56df37SRadoslaw Biernacki goto error;
2348c56df37SRadoslaw Biernacki }
2358c56df37SRadoslaw Biernacki
2368c56df37SRadoslaw Biernacki clock->pdev = pdev;
2378c56df37SRadoslaw Biernacki
2388c56df37SRadoslaw Biernacki err = pcim_enable_device(pdev);
2398c56df37SRadoslaw Biernacki if (err)
2408c56df37SRadoslaw Biernacki goto error_free;
2418c56df37SRadoslaw Biernacki
2428c56df37SRadoslaw Biernacki err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
2438c56df37SRadoslaw Biernacki if (err)
2448c56df37SRadoslaw Biernacki goto error_free;
2458c56df37SRadoslaw Biernacki
2468c56df37SRadoslaw Biernacki clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
2478c56df37SRadoslaw Biernacki
2488c56df37SRadoslaw Biernacki spin_lock_init(&clock->spin_lock);
2498c56df37SRadoslaw Biernacki
2508c56df37SRadoslaw Biernacki cc = &clock->cycle_counter;
2518c56df37SRadoslaw Biernacki cc->read = cavium_ptp_cc_read;
2528c56df37SRadoslaw Biernacki cc->mask = CYCLECOUNTER_MASK(64);
2538c56df37SRadoslaw Biernacki cc->mult = 1;
2548c56df37SRadoslaw Biernacki cc->shift = 0;
2558c56df37SRadoslaw Biernacki
2568c56df37SRadoslaw Biernacki timecounter_init(&clock->time_counter, &clock->cycle_counter,
2578c56df37SRadoslaw Biernacki ktime_to_ns(ktime_get_real()));
2588c56df37SRadoslaw Biernacki
2598c56df37SRadoslaw Biernacki clock->clock_rate = ptp_cavium_clock_get();
2608c56df37SRadoslaw Biernacki
2618c56df37SRadoslaw Biernacki clock->ptp_info = (struct ptp_clock_info) {
2628c56df37SRadoslaw Biernacki .owner = THIS_MODULE,
2638c56df37SRadoslaw Biernacki .name = "ThunderX PTP",
2648c56df37SRadoslaw Biernacki .max_adj = 1000000000ull,
2658c56df37SRadoslaw Biernacki .n_ext_ts = 0,
2668c56df37SRadoslaw Biernacki .n_pins = 0,
2678c56df37SRadoslaw Biernacki .pps = 0,
2688c56df37SRadoslaw Biernacki .adjfine = cavium_ptp_adjfine,
2698c56df37SRadoslaw Biernacki .adjtime = cavium_ptp_adjtime,
2708c56df37SRadoslaw Biernacki .gettime64 = cavium_ptp_gettime,
2718c56df37SRadoslaw Biernacki .settime64 = cavium_ptp_settime,
2728c56df37SRadoslaw Biernacki .enable = cavium_ptp_enable,
2738c56df37SRadoslaw Biernacki };
2748c56df37SRadoslaw Biernacki
2758c56df37SRadoslaw Biernacki clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
2768c56df37SRadoslaw Biernacki clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
2778c56df37SRadoslaw Biernacki writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
2788c56df37SRadoslaw Biernacki
2798c56df37SRadoslaw Biernacki clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate;
2808c56df37SRadoslaw Biernacki writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP);
2818c56df37SRadoslaw Biernacki
2828c56df37SRadoslaw Biernacki clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev);
2838c56df37SRadoslaw Biernacki if (IS_ERR(clock->ptp_clock)) {
2848c56df37SRadoslaw Biernacki err = PTR_ERR(clock->ptp_clock);
2858c56df37SRadoslaw Biernacki goto error_stop;
2868c56df37SRadoslaw Biernacki }
2878c56df37SRadoslaw Biernacki
2888c56df37SRadoslaw Biernacki pci_set_drvdata(pdev, clock);
2898c56df37SRadoslaw Biernacki return 0;
2908c56df37SRadoslaw Biernacki
2918c56df37SRadoslaw Biernacki error_stop:
2928c56df37SRadoslaw Biernacki clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
2938c56df37SRadoslaw Biernacki clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
2948c56df37SRadoslaw Biernacki writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
2958c56df37SRadoslaw Biernacki pcim_iounmap_regions(pdev, 1 << PCI_PTP_BAR_NO);
2968c56df37SRadoslaw Biernacki
2978c56df37SRadoslaw Biernacki error_free:
2988c56df37SRadoslaw Biernacki devm_kfree(dev, clock);
2998c56df37SRadoslaw Biernacki
3008c56df37SRadoslaw Biernacki error:
3018c56df37SRadoslaw Biernacki /* For `cavium_ptp_get()` we need to differentiate between the case
3028c56df37SRadoslaw Biernacki * when the core has not tried to probe this device and the case when
3038c56df37SRadoslaw Biernacki * the probe failed. In the later case we pretend that the
3048c56df37SRadoslaw Biernacki * initialization was successful and keep the error in
3058c56df37SRadoslaw Biernacki * `dev->driver_data`.
3068c56df37SRadoslaw Biernacki */
3078c56df37SRadoslaw Biernacki pci_set_drvdata(pdev, ERR_PTR(err));
3088c56df37SRadoslaw Biernacki return 0;
3098c56df37SRadoslaw Biernacki }
3108c56df37SRadoslaw Biernacki
cavium_ptp_remove(struct pci_dev * pdev)3118c56df37SRadoslaw Biernacki static void cavium_ptp_remove(struct pci_dev *pdev)
3128c56df37SRadoslaw Biernacki {
3138c56df37SRadoslaw Biernacki struct cavium_ptp *clock = pci_get_drvdata(pdev);
3148c56df37SRadoslaw Biernacki u64 clock_cfg;
3158c56df37SRadoslaw Biernacki
3168c56df37SRadoslaw Biernacki if (IS_ERR_OR_NULL(clock))
3178c56df37SRadoslaw Biernacki return;
3188c56df37SRadoslaw Biernacki
3198c56df37SRadoslaw Biernacki ptp_clock_unregister(clock->ptp_clock);
3208c56df37SRadoslaw Biernacki
3218c56df37SRadoslaw Biernacki clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
3228c56df37SRadoslaw Biernacki clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
3238c56df37SRadoslaw Biernacki writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
3248c56df37SRadoslaw Biernacki }
3258c56df37SRadoslaw Biernacki
3268c56df37SRadoslaw Biernacki static const struct pci_device_id cavium_ptp_id_table[] = {
327aa3afcccSPrakash Brahmajyosyula { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP,
328aa3afcccSPrakash Brahmajyosyula PCI_VENDOR_ID_CAVIUM, PCI_SUBSYS_DEVID_88XX_PTP) },
329aa3afcccSPrakash Brahmajyosyula { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP,
330aa3afcccSPrakash Brahmajyosyula PCI_VENDOR_ID_CAVIUM, PCI_SUBSYS_DEVID_81XX_PTP) },
331aa3afcccSPrakash Brahmajyosyula { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP,
332aa3afcccSPrakash Brahmajyosyula PCI_VENDOR_ID_CAVIUM, PCI_SUBSYS_DEVID_83XX_PTP) },
3338c56df37SRadoslaw Biernacki { 0, }
3348c56df37SRadoslaw Biernacki };
3358c56df37SRadoslaw Biernacki
3368c56df37SRadoslaw Biernacki static struct pci_driver cavium_ptp_driver = {
3378c56df37SRadoslaw Biernacki .name = DRV_NAME,
3388c56df37SRadoslaw Biernacki .id_table = cavium_ptp_id_table,
3398c56df37SRadoslaw Biernacki .probe = cavium_ptp_probe,
3408c56df37SRadoslaw Biernacki .remove = cavium_ptp_remove,
3418c56df37SRadoslaw Biernacki };
3428c56df37SRadoslaw Biernacki
34375498aa1SWei Yongjun module_pci_driver(cavium_ptp_driver);
3448c56df37SRadoslaw Biernacki
3458c56df37SRadoslaw Biernacki MODULE_DESCRIPTION(DRV_NAME);
3468c56df37SRadoslaw Biernacki MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
3478c56df37SRadoslaw Biernacki MODULE_LICENSE("GPL v2");
3488c56df37SRadoslaw Biernacki MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table);
349