root/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dpaa2_ptp_enable
  2. dpaa2_ptp_irq_handler_thread
  3. dpaa2_ptp_probe
  4. dpaa2_ptp_remove

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

/* [<][>][^][v][top][bottom][index][help] */