1c9c12d33SAleksey Makarov // SPDX-License-Identifier: GPL-2.0 2*cb0e3ec4SSunil Goutham /* Marvell RVU Ethernet driver 3c9c12d33SAleksey Makarov * 4*cb0e3ec4SSunil Goutham * Copyright (C) 2020 Marvell. 5*cb0e3ec4SSunil Goutham * 6c9c12d33SAleksey Makarov */ 7c9c12d33SAleksey Makarov 8c9c12d33SAleksey Makarov #include "otx2_common.h" 9c9c12d33SAleksey Makarov #include "otx2_ptp.h" 10c9c12d33SAleksey Makarov 11c9c12d33SAleksey Makarov static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) 12c9c12d33SAleksey Makarov { 13c9c12d33SAleksey Makarov struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, 14c9c12d33SAleksey Makarov ptp_info); 15c9c12d33SAleksey Makarov struct ptp_req *req; 16c9c12d33SAleksey Makarov 17c9c12d33SAleksey Makarov if (!ptp->nic) 18c9c12d33SAleksey Makarov return -ENODEV; 19c9c12d33SAleksey Makarov 20c9c12d33SAleksey Makarov req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); 21c9c12d33SAleksey Makarov if (!req) 22c9c12d33SAleksey Makarov return -ENOMEM; 23c9c12d33SAleksey Makarov 24c9c12d33SAleksey Makarov req->op = PTP_OP_ADJFINE; 25c9c12d33SAleksey Makarov req->scaled_ppm = scaled_ppm; 26c9c12d33SAleksey Makarov 27b8d90937SZheng Yongjun return otx2_sync_mbox_msg(&ptp->nic->mbox); 28c9c12d33SAleksey Makarov } 29c9c12d33SAleksey Makarov 30c9c12d33SAleksey Makarov static u64 ptp_cc_read(const struct cyclecounter *cc) 31c9c12d33SAleksey Makarov { 32c9c12d33SAleksey Makarov struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter); 33c9c12d33SAleksey Makarov struct ptp_req *req; 34c9c12d33SAleksey Makarov struct ptp_rsp *rsp; 35c9c12d33SAleksey Makarov int err; 36c9c12d33SAleksey Makarov 37c9c12d33SAleksey Makarov if (!ptp->nic) 38c9c12d33SAleksey Makarov return 0; 39c9c12d33SAleksey Makarov 40c9c12d33SAleksey Makarov req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); 41c9c12d33SAleksey Makarov if (!req) 42c9c12d33SAleksey Makarov return 0; 43c9c12d33SAleksey Makarov 44c9c12d33SAleksey Makarov req->op = PTP_OP_GET_CLOCK; 45c9c12d33SAleksey Makarov 46c9c12d33SAleksey Makarov err = otx2_sync_mbox_msg(&ptp->nic->mbox); 47c9c12d33SAleksey Makarov if (err) 48c9c12d33SAleksey Makarov return 0; 49c9c12d33SAleksey Makarov 50c9c12d33SAleksey Makarov rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0, 51c9c12d33SAleksey Makarov &req->hdr); 52c9c12d33SAleksey Makarov if (IS_ERR(rsp)) 53c9c12d33SAleksey Makarov return 0; 54c9c12d33SAleksey Makarov 55c9c12d33SAleksey Makarov return rsp->clk; 56c9c12d33SAleksey Makarov } 57c9c12d33SAleksey Makarov 58c9c12d33SAleksey Makarov static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) 59c9c12d33SAleksey Makarov { 60c9c12d33SAleksey Makarov struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, 61c9c12d33SAleksey Makarov ptp_info); 62c9c12d33SAleksey Makarov struct otx2_nic *pfvf = ptp->nic; 63c9c12d33SAleksey Makarov 64c9c12d33SAleksey Makarov mutex_lock(&pfvf->mbox.lock); 65c9c12d33SAleksey Makarov timecounter_adjtime(&ptp->time_counter, delta); 66c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 67c9c12d33SAleksey Makarov 68c9c12d33SAleksey Makarov return 0; 69c9c12d33SAleksey Makarov } 70c9c12d33SAleksey Makarov 71c9c12d33SAleksey Makarov static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info, 72c9c12d33SAleksey Makarov struct timespec64 *ts) 73c9c12d33SAleksey Makarov { 74c9c12d33SAleksey Makarov struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, 75c9c12d33SAleksey Makarov ptp_info); 76c9c12d33SAleksey Makarov struct otx2_nic *pfvf = ptp->nic; 77c9c12d33SAleksey Makarov u64 nsec; 78c9c12d33SAleksey Makarov 79c9c12d33SAleksey Makarov mutex_lock(&pfvf->mbox.lock); 80c9c12d33SAleksey Makarov nsec = timecounter_read(&ptp->time_counter); 81c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 82c9c12d33SAleksey Makarov 83c9c12d33SAleksey Makarov *ts = ns_to_timespec64(nsec); 84c9c12d33SAleksey Makarov 85c9c12d33SAleksey Makarov return 0; 86c9c12d33SAleksey Makarov } 87c9c12d33SAleksey Makarov 88c9c12d33SAleksey Makarov static int otx2_ptp_settime(struct ptp_clock_info *ptp_info, 89c9c12d33SAleksey Makarov const struct timespec64 *ts) 90c9c12d33SAleksey Makarov { 91c9c12d33SAleksey Makarov struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, 92c9c12d33SAleksey Makarov ptp_info); 93c9c12d33SAleksey Makarov struct otx2_nic *pfvf = ptp->nic; 94c9c12d33SAleksey Makarov u64 nsec; 95c9c12d33SAleksey Makarov 96c9c12d33SAleksey Makarov nsec = timespec64_to_ns(ts); 97c9c12d33SAleksey Makarov 98c9c12d33SAleksey Makarov mutex_lock(&pfvf->mbox.lock); 99c9c12d33SAleksey Makarov timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec); 100c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 101c9c12d33SAleksey Makarov 102c9c12d33SAleksey Makarov return 0; 103c9c12d33SAleksey Makarov } 104c9c12d33SAleksey Makarov 105c9c12d33SAleksey Makarov static int otx2_ptp_enable(struct ptp_clock_info *ptp_info, 106c9c12d33SAleksey Makarov struct ptp_clock_request *rq, int on) 107c9c12d33SAleksey Makarov { 108c9c12d33SAleksey Makarov return -EOPNOTSUPP; 109c9c12d33SAleksey Makarov } 110c9c12d33SAleksey Makarov 111c9c12d33SAleksey Makarov int otx2_ptp_init(struct otx2_nic *pfvf) 112c9c12d33SAleksey Makarov { 113c9c12d33SAleksey Makarov struct otx2_ptp *ptp_ptr; 114c9c12d33SAleksey Makarov struct cyclecounter *cc; 115c9c12d33SAleksey Makarov struct ptp_req *req; 116c9c12d33SAleksey Makarov int err; 117c9c12d33SAleksey Makarov 118c9c12d33SAleksey Makarov mutex_lock(&pfvf->mbox.lock); 119c9c12d33SAleksey Makarov /* check if PTP block is available */ 120c9c12d33SAleksey Makarov req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox); 121c9c12d33SAleksey Makarov if (!req) { 122c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 123c9c12d33SAleksey Makarov return -ENOMEM; 124c9c12d33SAleksey Makarov } 125c9c12d33SAleksey Makarov 126c9c12d33SAleksey Makarov req->op = PTP_OP_GET_CLOCK; 127c9c12d33SAleksey Makarov 128c9c12d33SAleksey Makarov err = otx2_sync_mbox_msg(&pfvf->mbox); 129c9c12d33SAleksey Makarov if (err) { 130c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 131c9c12d33SAleksey Makarov return err; 132c9c12d33SAleksey Makarov } 133c9c12d33SAleksey Makarov mutex_unlock(&pfvf->mbox.lock); 134c9c12d33SAleksey Makarov 135c9c12d33SAleksey Makarov ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL); 136c9c12d33SAleksey Makarov if (!ptp_ptr) { 137c9c12d33SAleksey Makarov err = -ENOMEM; 138c9c12d33SAleksey Makarov goto error; 139c9c12d33SAleksey Makarov } 140c9c12d33SAleksey Makarov 141c9c12d33SAleksey Makarov ptp_ptr->nic = pfvf; 142c9c12d33SAleksey Makarov 143c9c12d33SAleksey Makarov cc = &ptp_ptr->cycle_counter; 144c9c12d33SAleksey Makarov cc->read = ptp_cc_read; 145c9c12d33SAleksey Makarov cc->mask = CYCLECOUNTER_MASK(64); 146c9c12d33SAleksey Makarov cc->mult = 1; 147c9c12d33SAleksey Makarov cc->shift = 0; 148c9c12d33SAleksey Makarov 149c9c12d33SAleksey Makarov timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter, 150c9c12d33SAleksey Makarov ktime_to_ns(ktime_get_real())); 151c9c12d33SAleksey Makarov 152c9c12d33SAleksey Makarov ptp_ptr->ptp_info = (struct ptp_clock_info) { 153c9c12d33SAleksey Makarov .owner = THIS_MODULE, 154c9c12d33SAleksey Makarov .name = "OcteonTX2 PTP", 155c9c12d33SAleksey Makarov .max_adj = 1000000000ull, 156c9c12d33SAleksey Makarov .n_ext_ts = 0, 157c9c12d33SAleksey Makarov .n_pins = 0, 158c9c12d33SAleksey Makarov .pps = 0, 159c9c12d33SAleksey Makarov .adjfine = otx2_ptp_adjfine, 160c9c12d33SAleksey Makarov .adjtime = otx2_ptp_adjtime, 161c9c12d33SAleksey Makarov .gettime64 = otx2_ptp_gettime, 162c9c12d33SAleksey Makarov .settime64 = otx2_ptp_settime, 163c9c12d33SAleksey Makarov .enable = otx2_ptp_enable, 164c9c12d33SAleksey Makarov }; 165c9c12d33SAleksey Makarov 166c9c12d33SAleksey Makarov ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev); 167c9c12d33SAleksey Makarov if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) { 168c9c12d33SAleksey Makarov err = ptp_ptr->ptp_clock ? 169c9c12d33SAleksey Makarov PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV; 170c9c12d33SAleksey Makarov kfree(ptp_ptr); 171c9c12d33SAleksey Makarov goto error; 172c9c12d33SAleksey Makarov } 173c9c12d33SAleksey Makarov 174c9c12d33SAleksey Makarov pfvf->ptp = ptp_ptr; 175c9c12d33SAleksey Makarov 176c9c12d33SAleksey Makarov error: 177c9c12d33SAleksey Makarov return err; 178c9c12d33SAleksey Makarov } 179c9c12d33SAleksey Makarov 180c9c12d33SAleksey Makarov void otx2_ptp_destroy(struct otx2_nic *pfvf) 181c9c12d33SAleksey Makarov { 182c9c12d33SAleksey Makarov struct otx2_ptp *ptp = pfvf->ptp; 183c9c12d33SAleksey Makarov 184c9c12d33SAleksey Makarov if (!ptp) 185c9c12d33SAleksey Makarov return; 186c9c12d33SAleksey Makarov 187c9c12d33SAleksey Makarov ptp_clock_unregister(ptp->ptp_clock); 188c9c12d33SAleksey Makarov kfree(ptp); 189c9c12d33SAleksey Makarov pfvf->ptp = NULL; 190c9c12d33SAleksey Makarov } 191c9c12d33SAleksey Makarov 192c9c12d33SAleksey Makarov int otx2_ptp_clock_index(struct otx2_nic *pfvf) 193c9c12d33SAleksey Makarov { 194c9c12d33SAleksey Makarov if (!pfvf->ptp) 195c9c12d33SAleksey Makarov return -ENODEV; 196c9c12d33SAleksey Makarov 197c9c12d33SAleksey Makarov return ptp_clock_index(pfvf->ptp->ptp_clock); 198c9c12d33SAleksey Makarov } 199c9c12d33SAleksey Makarov 200c9c12d33SAleksey Makarov int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns) 201c9c12d33SAleksey Makarov { 202c9c12d33SAleksey Makarov if (!pfvf->ptp) 203c9c12d33SAleksey Makarov return -ENODEV; 204c9c12d33SAleksey Makarov 205c9c12d33SAleksey Makarov *tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp); 206c9c12d33SAleksey Makarov 207c9c12d33SAleksey Makarov return 0; 208c9c12d33SAleksey Makarov } 209