Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Marvell RVU Ethernet driver
0003  *
0004  * Copyright (C) 2020 Marvell.
0005  *
0006  */
0007 
0008 #include <linux/module.h>
0009 
0010 #include "otx2_common.h"
0011 #include "otx2_ptp.h"
0012 
0013 static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
0014 {
0015     struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
0016                         ptp_info);
0017     struct ptp_req *req;
0018 
0019     if (!ptp->nic)
0020         return -ENODEV;
0021 
0022     req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
0023     if (!req)
0024         return -ENOMEM;
0025 
0026     req->op = PTP_OP_ADJFINE;
0027     req->scaled_ppm = scaled_ppm;
0028 
0029     return otx2_sync_mbox_msg(&ptp->nic->mbox);
0030 }
0031 
0032 static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh)
0033 {
0034     struct ptp_req *req;
0035 
0036     if (!ptp->nic)
0037         return -ENODEV;
0038 
0039     req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
0040     if (!req)
0041         return -ENOMEM;
0042 
0043     req->op = PTP_OP_SET_THRESH;
0044     req->thresh = thresh;
0045 
0046     return otx2_sync_mbox_msg(&ptp->nic->mbox);
0047 }
0048 
0049 static u64 ptp_cc_read(const struct cyclecounter *cc)
0050 {
0051     struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter);
0052     struct ptp_req *req;
0053     struct ptp_rsp *rsp;
0054     int err;
0055 
0056     if (!ptp->nic)
0057         return 0;
0058 
0059     req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
0060     if (!req)
0061         return 0;
0062 
0063     req->op = PTP_OP_GET_CLOCK;
0064 
0065     err = otx2_sync_mbox_msg(&ptp->nic->mbox);
0066     if (err)
0067         return 0;
0068 
0069     rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
0070                           &req->hdr);
0071     if (IS_ERR(rsp))
0072         return 0;
0073 
0074     return rsp->clk;
0075 }
0076 
0077 static u64 ptp_tstmp_read(struct otx2_ptp *ptp)
0078 {
0079     struct ptp_req *req;
0080     struct ptp_rsp *rsp;
0081     int err;
0082 
0083     if (!ptp->nic)
0084         return 0;
0085 
0086     req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
0087     if (!req)
0088         return 0;
0089 
0090     req->op = PTP_OP_GET_TSTMP;
0091 
0092     err = otx2_sync_mbox_msg(&ptp->nic->mbox);
0093     if (err)
0094         return 0;
0095 
0096     rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
0097                           &req->hdr);
0098     if (IS_ERR(rsp))
0099         return 0;
0100 
0101     return rsp->clk;
0102 }
0103 
0104 static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
0105 {
0106     struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
0107                         ptp_info);
0108     struct otx2_nic *pfvf = ptp->nic;
0109 
0110     mutex_lock(&pfvf->mbox.lock);
0111     timecounter_adjtime(&ptp->time_counter, delta);
0112     mutex_unlock(&pfvf->mbox.lock);
0113 
0114     return 0;
0115 }
0116 
0117 static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
0118                 struct timespec64 *ts)
0119 {
0120     struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
0121                         ptp_info);
0122     struct otx2_nic *pfvf = ptp->nic;
0123     u64 nsec;
0124 
0125     mutex_lock(&pfvf->mbox.lock);
0126     nsec = timecounter_read(&ptp->time_counter);
0127     mutex_unlock(&pfvf->mbox.lock);
0128 
0129     *ts = ns_to_timespec64(nsec);
0130 
0131     return 0;
0132 }
0133 
0134 static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
0135                 const struct timespec64 *ts)
0136 {
0137     struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
0138                         ptp_info);
0139     struct otx2_nic *pfvf = ptp->nic;
0140     u64 nsec;
0141 
0142     nsec = timespec64_to_ns(ts);
0143 
0144     mutex_lock(&pfvf->mbox.lock);
0145     timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
0146     mutex_unlock(&pfvf->mbox.lock);
0147 
0148     return 0;
0149 }
0150 
0151 static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
0152                    enum ptp_pin_function func, unsigned int chan)
0153 {
0154     switch (func) {
0155     case PTP_PF_NONE:
0156     case PTP_PF_EXTTS:
0157         break;
0158     case PTP_PF_PEROUT:
0159     case PTP_PF_PHYSYNC:
0160         return -1;
0161     }
0162     return 0;
0163 }
0164 
0165 static void otx2_ptp_extts_check(struct work_struct *work)
0166 {
0167     struct otx2_ptp *ptp = container_of(work, struct otx2_ptp,
0168                         extts_work.work);
0169     struct ptp_clock_event event;
0170     u64 tstmp, new_thresh;
0171 
0172     mutex_lock(&ptp->nic->mbox.lock);
0173     tstmp = ptp_tstmp_read(ptp);
0174     mutex_unlock(&ptp->nic->mbox.lock);
0175 
0176     if (tstmp != ptp->last_extts) {
0177         event.type = PTP_CLOCK_EXTTS;
0178         event.index = 0;
0179         event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp);
0180         ptp_clock_event(ptp->ptp_clock, &event);
0181         ptp->last_extts = tstmp;
0182 
0183         new_thresh = tstmp % 500000000;
0184         if (ptp->thresh != new_thresh) {
0185             mutex_lock(&ptp->nic->mbox.lock);
0186             ptp_set_thresh(ptp, new_thresh);
0187             mutex_unlock(&ptp->nic->mbox.lock);
0188             ptp->thresh = new_thresh;
0189         }
0190     }
0191     schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
0192 }
0193 
0194 static int otx2_ptp_enable(struct ptp_clock_info *ptp_info,
0195                struct ptp_clock_request *rq, int on)
0196 {
0197     struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
0198                         ptp_info);
0199     int pin;
0200 
0201     if (!ptp->nic)
0202         return -ENODEV;
0203 
0204     switch (rq->type) {
0205     case PTP_CLK_REQ_EXTTS:
0206         pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS,
0207                    rq->extts.index);
0208         if (pin < 0)
0209             return -EBUSY;
0210         if (on)
0211             schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200));
0212         else
0213             cancel_delayed_work_sync(&ptp->extts_work);
0214         return 0;
0215     default:
0216         break;
0217     }
0218     return -EOPNOTSUPP;
0219 }
0220 
0221 int otx2_ptp_init(struct otx2_nic *pfvf)
0222 {
0223     struct otx2_ptp *ptp_ptr;
0224     struct cyclecounter *cc;
0225     struct ptp_req *req;
0226     int err;
0227 
0228     if (is_otx2_lbkvf(pfvf->pdev)) {
0229         pfvf->ptp = NULL;
0230         return 0;
0231     }
0232 
0233     mutex_lock(&pfvf->mbox.lock);
0234     /* check if PTP block is available */
0235     req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox);
0236     if (!req) {
0237         mutex_unlock(&pfvf->mbox.lock);
0238         return -ENOMEM;
0239     }
0240 
0241     req->op = PTP_OP_GET_CLOCK;
0242 
0243     err = otx2_sync_mbox_msg(&pfvf->mbox);
0244     if (err) {
0245         mutex_unlock(&pfvf->mbox.lock);
0246         return err;
0247     }
0248     mutex_unlock(&pfvf->mbox.lock);
0249 
0250     ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL);
0251     if (!ptp_ptr) {
0252         err = -ENOMEM;
0253         goto error;
0254     }
0255 
0256     ptp_ptr->nic = pfvf;
0257 
0258     cc = &ptp_ptr->cycle_counter;
0259     cc->read = ptp_cc_read;
0260     cc->mask = CYCLECOUNTER_MASK(64);
0261     cc->mult = 1;
0262     cc->shift = 0;
0263 
0264     timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
0265              ktime_to_ns(ktime_get_real()));
0266 
0267     snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP");
0268     ptp_ptr->extts_config.index = 0;
0269     ptp_ptr->extts_config.func = PTP_PF_NONE;
0270 
0271     ptp_ptr->ptp_info = (struct ptp_clock_info) {
0272         .owner          = THIS_MODULE,
0273         .name           = "OcteonTX2 PTP",
0274         .max_adj        = 1000000000ull,
0275         .n_ext_ts       = 1,
0276         .n_pins         = 1,
0277         .pps            = 0,
0278         .pin_config     = &ptp_ptr->extts_config,
0279         .adjfine        = otx2_ptp_adjfine,
0280         .adjtime        = otx2_ptp_adjtime,
0281         .gettime64      = otx2_ptp_gettime,
0282         .settime64      = otx2_ptp_settime,
0283         .enable         = otx2_ptp_enable,
0284         .verify         = otx2_ptp_verify_pin,
0285     };
0286 
0287     INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check);
0288 
0289     ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
0290     if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) {
0291         err = ptp_ptr->ptp_clock ?
0292               PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV;
0293         kfree(ptp_ptr);
0294         goto error;
0295     }
0296 
0297     if (is_dev_otx2(pfvf->pdev)) {
0298         ptp_ptr->convert_rx_ptp_tstmp = &otx2_ptp_convert_rx_timestamp;
0299         ptp_ptr->convert_tx_ptp_tstmp = &otx2_ptp_convert_tx_timestamp;
0300     } else {
0301         ptp_ptr->convert_rx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
0302         ptp_ptr->convert_tx_ptp_tstmp = &cn10k_ptp_convert_timestamp;
0303     }
0304 
0305     pfvf->ptp = ptp_ptr;
0306 
0307 error:
0308     return err;
0309 }
0310 EXPORT_SYMBOL_GPL(otx2_ptp_init);
0311 
0312 void otx2_ptp_destroy(struct otx2_nic *pfvf)
0313 {
0314     struct otx2_ptp *ptp = pfvf->ptp;
0315 
0316     if (!ptp)
0317         return;
0318 
0319     ptp_clock_unregister(ptp->ptp_clock);
0320     kfree(ptp);
0321     pfvf->ptp = NULL;
0322 }
0323 EXPORT_SYMBOL_GPL(otx2_ptp_destroy);
0324 
0325 int otx2_ptp_clock_index(struct otx2_nic *pfvf)
0326 {
0327     if (!pfvf->ptp)
0328         return -ENODEV;
0329 
0330     return ptp_clock_index(pfvf->ptp->ptp_clock);
0331 }
0332 EXPORT_SYMBOL_GPL(otx2_ptp_clock_index);
0333 
0334 int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
0335 {
0336     if (!pfvf->ptp)
0337         return -ENODEV;
0338 
0339     *tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
0340 
0341     return 0;
0342 }
0343 EXPORT_SYMBOL_GPL(otx2_ptp_tstamp2time);
0344 
0345 MODULE_AUTHOR("Sunil Goutham <sgoutham@marvell.com>");
0346 MODULE_DESCRIPTION("Marvell RVU NIC PTP Driver");
0347 MODULE_LICENSE("GPL v2");