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