cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dpaa2-ptp.c (5606B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright 2013-2016 Freescale Semiconductor Inc.
      4 * Copyright 2016-2018 NXP
      5 * Copyright 2020 NXP
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/of.h>
     10#include <linux/of_address.h>
     11#include <linux/msi.h>
     12#include <linux/fsl/mc.h>
     13
     14#include "dpaa2-ptp.h"
     15
     16static int dpaa2_ptp_enable(struct ptp_clock_info *ptp,
     17			    struct ptp_clock_request *rq, int on)
     18{
     19	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
     20	struct fsl_mc_device *mc_dev;
     21	struct device *dev;
     22	u32 mask = 0;
     23	u32 bit;
     24	int err;
     25
     26	dev = ptp_qoriq->dev;
     27	mc_dev = to_fsl_mc_device(dev);
     28
     29	switch (rq->type) {
     30	case PTP_CLK_REQ_EXTTS:
     31		switch (rq->extts.index) {
     32		case 0:
     33			bit = DPRTC_EVENT_ETS1;
     34			break;
     35		case 1:
     36			bit = DPRTC_EVENT_ETS2;
     37			break;
     38		default:
     39			return -EINVAL;
     40		}
     41		if (on)
     42			extts_clean_up(ptp_qoriq, rq->extts.index, false);
     43		break;
     44	case PTP_CLK_REQ_PPS:
     45		bit = DPRTC_EVENT_PPS;
     46		break;
     47	default:
     48		return -EOPNOTSUPP;
     49	}
     50
     51	err = dprtc_get_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
     52				 DPRTC_IRQ_INDEX, &mask);
     53	if (err < 0) {
     54		dev_err(dev, "dprtc_get_irq_mask(): %d\n", err);
     55		return err;
     56	}
     57
     58	if (on)
     59		mask |= bit;
     60	else
     61		mask &= ~bit;
     62
     63	err = dprtc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
     64				 DPRTC_IRQ_INDEX, mask);
     65	if (err < 0) {
     66		dev_err(dev, "dprtc_set_irq_mask(): %d\n", err);
     67		return err;
     68	}
     69
     70	return 0;
     71}
     72
     73static const struct ptp_clock_info dpaa2_ptp_caps = {
     74	.owner		= THIS_MODULE,
     75	.name		= "DPAA2 PTP Clock",
     76	.max_adj	= 512000,
     77	.n_alarm	= 2,
     78	.n_ext_ts	= 2,
     79	.n_per_out	= 3,
     80	.n_pins		= 0,
     81	.pps		= 1,
     82	.adjfine	= ptp_qoriq_adjfine,
     83	.adjtime	= ptp_qoriq_adjtime,
     84	.gettime64	= ptp_qoriq_gettime,
     85	.settime64	= ptp_qoriq_settime,
     86	.enable		= dpaa2_ptp_enable,
     87};
     88
     89static irqreturn_t dpaa2_ptp_irq_handler_thread(int irq, void *priv)
     90{
     91	struct ptp_qoriq *ptp_qoriq = priv;
     92	struct ptp_clock_event event;
     93	struct fsl_mc_device *mc_dev;
     94	struct device *dev;
     95	u32 status = 0;
     96	int err;
     97
     98	dev = ptp_qoriq->dev;
     99	mc_dev = to_fsl_mc_device(dev);
    100
    101	err = dprtc_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
    102				   DPRTC_IRQ_INDEX, &status);
    103	if (unlikely(err)) {
    104		dev_err(dev, "dprtc_get_irq_status err %d\n", err);
    105		return IRQ_NONE;
    106	}
    107
    108	if (status & DPRTC_EVENT_PPS) {
    109		event.type = PTP_CLOCK_PPS;
    110		ptp_clock_event(ptp_qoriq->clock, &event);
    111	}
    112
    113	if (status & DPRTC_EVENT_ETS1)
    114		extts_clean_up(ptp_qoriq, 0, true);
    115
    116	if (status & DPRTC_EVENT_ETS2)
    117		extts_clean_up(ptp_qoriq, 1, true);
    118
    119	err = dprtc_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
    120				     DPRTC_IRQ_INDEX, status);
    121	if (unlikely(err)) {
    122		dev_err(dev, "dprtc_clear_irq_status err %d\n", err);
    123		return IRQ_NONE;
    124	}
    125
    126	return IRQ_HANDLED;
    127}
    128
    129static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
    130{
    131	struct device *dev = &mc_dev->dev;
    132	struct ptp_qoriq *ptp_qoriq;
    133	struct device_node *node;
    134	void __iomem *base;
    135	int err;
    136
    137	ptp_qoriq = devm_kzalloc(dev, sizeof(*ptp_qoriq), GFP_KERNEL);
    138	if (!ptp_qoriq)
    139		return -ENOMEM;
    140
    141	err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
    142	if (err) {
    143		if (err == -ENXIO)
    144			err = -EPROBE_DEFER;
    145		else
    146			dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
    147		goto err_exit;
    148	}
    149
    150	err = dprtc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
    151			 &mc_dev->mc_handle);
    152	if (err) {
    153		dev_err(dev, "dprtc_open err %d\n", err);
    154		goto err_free_mcp;
    155	}
    156
    157	ptp_qoriq->dev = dev;
    158
    159	node = of_find_compatible_node(NULL, NULL, "fsl,dpaa2-ptp");
    160	if (!node) {
    161		err = -ENODEV;
    162		goto err_close;
    163	}
    164
    165	dev->of_node = node;
    166
    167	base = of_iomap(node, 0);
    168	if (!base) {
    169		err = -ENOMEM;
    170		goto err_put;
    171	}
    172
    173	err = fsl_mc_allocate_irqs(mc_dev);
    174	if (err) {
    175		dev_err(dev, "MC irqs allocation failed\n");
    176		goto err_unmap;
    177	}
    178
    179	ptp_qoriq->irq = mc_dev->irqs[0]->virq;
    180
    181	err = request_threaded_irq(ptp_qoriq->irq, NULL,
    182				   dpaa2_ptp_irq_handler_thread,
    183				   IRQF_NO_SUSPEND | IRQF_ONESHOT,
    184				   dev_name(dev), ptp_qoriq);
    185	if (err < 0) {
    186		dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
    187		goto err_free_mc_irq;
    188	}
    189
    190	err = dprtc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
    191				   DPRTC_IRQ_INDEX, 1);
    192	if (err < 0) {
    193		dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
    194		goto err_free_threaded_irq;
    195	}
    196
    197	err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
    198	if (err)
    199		goto err_free_threaded_irq;
    200
    201	dpaa2_phc_index = ptp_qoriq->phc_index;
    202	dpaa2_ptp = ptp_qoriq;
    203	dev_set_drvdata(dev, ptp_qoriq);
    204
    205	return 0;
    206
    207err_free_threaded_irq:
    208	free_irq(ptp_qoriq->irq, ptp_qoriq);
    209err_free_mc_irq:
    210	fsl_mc_free_irqs(mc_dev);
    211err_unmap:
    212	iounmap(base);
    213err_put:
    214	of_node_put(node);
    215err_close:
    216	dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
    217err_free_mcp:
    218	fsl_mc_portal_free(mc_dev->mc_io);
    219err_exit:
    220	return err;
    221}
    222
    223static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
    224{
    225	struct device *dev = &mc_dev->dev;
    226	struct ptp_qoriq *ptp_qoriq;
    227
    228	ptp_qoriq = dev_get_drvdata(dev);
    229
    230	dpaa2_phc_index = -1;
    231	ptp_qoriq_free(ptp_qoriq);
    232
    233	fsl_mc_free_irqs(mc_dev);
    234	dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
    235	fsl_mc_portal_free(mc_dev->mc_io);
    236
    237	return 0;
    238}
    239
    240static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
    241	{
    242		.vendor = FSL_MC_VENDOR_FREESCALE,
    243		.obj_type = "dprtc",
    244	},
    245	{}
    246};
    247MODULE_DEVICE_TABLE(fslmc, dpaa2_ptp_match_id_table);
    248
    249static struct fsl_mc_driver dpaa2_ptp_drv = {
    250	.driver = {
    251		.name = KBUILD_MODNAME,
    252		.owner = THIS_MODULE,
    253	},
    254	.probe = dpaa2_ptp_probe,
    255	.remove = dpaa2_ptp_remove,
    256	.match_id_table = dpaa2_ptp_match_id_table,
    257};
    258
    259module_fsl_mc_driver(dpaa2_ptp_drv);
    260
    261MODULE_LICENSE("GPL v2");
    262MODULE_DESCRIPTION("DPAA2 PTP Clock Driver");