Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 1 | /* QLogic qed NIC Driver |
| 2 | * Copyright (c) 2015-2017 QLogic Corporation |
| 3 | * |
| 4 | * This software is available to you under a choice of one of two |
| 5 | * licenses. You may choose to be licensed under the terms of the GNU |
| 6 | * General Public License (GPL) Version 2, available from the file |
| 7 | * COPYING in the main directory of this source tree, or the |
| 8 | * OpenIB.org BSD license below: |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or |
| 11 | * without modification, are permitted provided that the following |
| 12 | * conditions are met: |
| 13 | * |
| 14 | * - Redistributions of source code must retain the above |
| 15 | * copyright notice, this list of conditions and the following |
| 16 | * disclaimer. |
| 17 | * |
| 18 | * - Redistributions in binary form must reproduce the above |
| 19 | * copyright notice, this list of conditions and the following |
| 20 | * disclaimer in the documentation and /or other materials |
| 21 | * provided with the distribution. |
| 22 | * |
| 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 30 | * SOFTWARE. |
| 31 | */ |
| 32 | #include <linux/types.h> |
| 33 | #include "qed.h" |
| 34 | #include "qed_dev_api.h" |
| 35 | #include "qed_hw.h" |
| 36 | #include "qed_l2.h" |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 37 | #include "qed_mcp.h" |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 38 | #include "qed_reg_addr.h" |
| 39 | |
| 40 | /* 16 nano second time quantas to wait before making a Drift adjustment */ |
| 41 | #define QED_DRIFT_CNTR_TIME_QUANTA_SHIFT 0 |
| 42 | /* Nano seconds to add/subtract when making a Drift adjustment */ |
| 43 | #define QED_DRIFT_CNTR_ADJUSTMENT_SHIFT 28 |
| 44 | /* Add/subtract the Adjustment_Value when making a Drift adjustment */ |
| 45 | #define QED_DRIFT_CNTR_DIRECTION_SHIFT 31 |
| 46 | #define QED_TIMESTAMP_MASK BIT(16) |
| 47 | |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 48 | static enum qed_resc_lock qed_ptcdev_to_resc(struct qed_hwfn *p_hwfn) |
| 49 | { |
| 50 | switch (qed_device_get_port_id(p_hwfn->cdev)) { |
| 51 | case 0: |
| 52 | return QED_RESC_LOCK_PTP_PORT0; |
| 53 | case 1: |
| 54 | return QED_RESC_LOCK_PTP_PORT1; |
| 55 | case 2: |
| 56 | return QED_RESC_LOCK_PTP_PORT2; |
| 57 | case 3: |
| 58 | return QED_RESC_LOCK_PTP_PORT3; |
| 59 | default: |
| 60 | return QED_RESC_LOCK_RESC_INVALID; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | static int qed_ptp_res_lock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| 65 | { |
| 66 | struct qed_resc_lock_params params; |
| 67 | enum qed_resc_lock resource; |
| 68 | int rc; |
| 69 | |
| 70 | resource = qed_ptcdev_to_resc(p_hwfn); |
| 71 | if (resource == QED_RESC_LOCK_RESC_INVALID) |
| 72 | return -EINVAL; |
| 73 | |
| 74 | qed_mcp_resc_lock_default_init(¶ms, NULL, resource, true); |
| 75 | |
| 76 | rc = qed_mcp_resc_lock(p_hwfn, p_ptt, ¶ms); |
| 77 | if (rc && rc != -EINVAL) { |
| 78 | return rc; |
| 79 | } else if (rc == -EINVAL) { |
| 80 | /* MFW doesn't support resource locking, first PF on the port |
| 81 | * has lock ownership. |
| 82 | */ |
Tomer Tayar | 78cea9f | 2017-05-23 09:41:22 +0300 | [diff] [blame] | 83 | if (p_hwfn->abs_pf_id < p_hwfn->cdev->num_ports_in_engine) |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 84 | return 0; |
| 85 | |
| 86 | DP_INFO(p_hwfn, "PF doesn't have lock ownership\n"); |
| 87 | return -EBUSY; |
| 88 | } else if (!rc && !params.b_granted) { |
| 89 | DP_INFO(p_hwfn, "Failed to acquire ptp resource lock\n"); |
| 90 | return -EBUSY; |
| 91 | } |
| 92 | |
| 93 | return rc; |
| 94 | } |
| 95 | |
| 96 | static int qed_ptp_res_unlock(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| 97 | { |
| 98 | struct qed_resc_unlock_params params; |
| 99 | enum qed_resc_lock resource; |
| 100 | int rc; |
| 101 | |
| 102 | resource = qed_ptcdev_to_resc(p_hwfn); |
| 103 | if (resource == QED_RESC_LOCK_RESC_INVALID) |
| 104 | return -EINVAL; |
| 105 | |
| 106 | qed_mcp_resc_lock_default_init(NULL, ¶ms, resource, true); |
| 107 | |
| 108 | rc = qed_mcp_resc_unlock(p_hwfn, p_ptt, ¶ms); |
| 109 | if (rc == -EINVAL) { |
| 110 | /* MFW doesn't support locking, first PF has lock ownership */ |
Tomer Tayar | 78cea9f | 2017-05-23 09:41:22 +0300 | [diff] [blame] | 111 | if (p_hwfn->abs_pf_id < p_hwfn->cdev->num_ports_in_engine) { |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 112 | rc = 0; |
| 113 | } else { |
| 114 | DP_INFO(p_hwfn, "PF doesn't have lock ownership\n"); |
| 115 | return -EINVAL; |
| 116 | } |
| 117 | } else if (rc) { |
| 118 | DP_INFO(p_hwfn, "Failed to release the ptp resource lock\n"); |
| 119 | } |
| 120 | |
| 121 | return rc; |
| 122 | } |
| 123 | |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 124 | /* Read Rx timestamp */ |
| 125 | static int qed_ptp_hw_read_rx_ts(struct qed_dev *cdev, u64 *timestamp) |
| 126 | { |
| 127 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 128 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
| 129 | u32 val; |
| 130 | |
| 131 | *timestamp = 0; |
| 132 | val = qed_rd(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID); |
| 133 | if (!(val & QED_TIMESTAMP_MASK)) { |
| 134 | DP_INFO(p_hwfn, "Invalid Rx timestamp, buf_seqid = %d\n", val); |
| 135 | return -EINVAL; |
| 136 | } |
| 137 | |
| 138 | val = qed_rd(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_TS_LSB); |
| 139 | *timestamp = qed_rd(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_TS_MSB); |
| 140 | *timestamp <<= 32; |
| 141 | *timestamp |= val; |
| 142 | |
| 143 | /* Reset timestamp register to allow new timestamp */ |
| 144 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID, |
| 145 | QED_TIMESTAMP_MASK); |
| 146 | |
| 147 | return 0; |
| 148 | } |
| 149 | |
| 150 | /* Read Tx timestamp */ |
| 151 | static int qed_ptp_hw_read_tx_ts(struct qed_dev *cdev, u64 *timestamp) |
| 152 | { |
| 153 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 154 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
| 155 | u32 val; |
| 156 | |
| 157 | *timestamp = 0; |
| 158 | val = qed_rd(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_SEQID); |
| 159 | if (!(val & QED_TIMESTAMP_MASK)) { |
| 160 | DP_INFO(p_hwfn, "Invalid Tx timestamp, buf_seqid = %d\n", val); |
| 161 | return -EINVAL; |
| 162 | } |
| 163 | |
| 164 | val = qed_rd(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_TS_LSB); |
| 165 | *timestamp = qed_rd(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_TS_MSB); |
| 166 | *timestamp <<= 32; |
| 167 | *timestamp |= val; |
| 168 | |
| 169 | /* Reset timestamp register to allow new timestamp */ |
| 170 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_SEQID, QED_TIMESTAMP_MASK); |
| 171 | |
| 172 | return 0; |
| 173 | } |
| 174 | |
| 175 | /* Read Phy Hardware Clock */ |
| 176 | static int qed_ptp_hw_read_cc(struct qed_dev *cdev, u64 *phc_cycles) |
| 177 | { |
| 178 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 179 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
| 180 | u32 temp = 0; |
| 181 | |
| 182 | temp = qed_rd(p_hwfn, p_ptt, NIG_REG_TSGEN_SYNC_TIME_LSB); |
| 183 | *phc_cycles = qed_rd(p_hwfn, p_ptt, NIG_REG_TSGEN_SYNC_TIME_MSB); |
| 184 | *phc_cycles <<= 32; |
| 185 | *phc_cycles |= temp; |
| 186 | |
| 187 | return 0; |
| 188 | } |
| 189 | |
| 190 | /* Filter PTP protocol packets that need to be timestamped */ |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 191 | static int qed_ptp_hw_cfg_filters(struct qed_dev *cdev, |
| 192 | enum qed_ptp_filter_type rx_type, |
| 193 | enum qed_ptp_hwtstamp_tx_type tx_type) |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 194 | { |
| 195 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 196 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 197 | u32 rule_mask, enable_cfg = 0x0; |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 198 | |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 199 | switch (rx_type) { |
| 200 | case QED_PTP_FILTER_NONE: |
| 201 | enable_cfg = 0x0; |
| 202 | rule_mask = 0x3FFF; |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 203 | break; |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 204 | case QED_PTP_FILTER_ALL: |
| 205 | enable_cfg = 0x7; |
| 206 | rule_mask = 0x3CAA; |
| 207 | break; |
| 208 | case QED_PTP_FILTER_V1_L4_EVENT: |
| 209 | enable_cfg = 0x3; |
| 210 | rule_mask = 0x3FFA; |
| 211 | break; |
| 212 | case QED_PTP_FILTER_V1_L4_GEN: |
| 213 | enable_cfg = 0x3; |
| 214 | rule_mask = 0x3FFE; |
| 215 | break; |
| 216 | case QED_PTP_FILTER_V2_L4_EVENT: |
| 217 | enable_cfg = 0x5; |
| 218 | rule_mask = 0x3FAA; |
| 219 | break; |
| 220 | case QED_PTP_FILTER_V2_L4_GEN: |
| 221 | enable_cfg = 0x5; |
| 222 | rule_mask = 0x3FEE; |
| 223 | break; |
| 224 | case QED_PTP_FILTER_V2_L2_EVENT: |
| 225 | enable_cfg = 0x5; |
| 226 | rule_mask = 0x3CFF; |
| 227 | break; |
| 228 | case QED_PTP_FILTER_V2_L2_GEN: |
| 229 | enable_cfg = 0x5; |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 230 | rule_mask = 0x3EFF; |
| 231 | break; |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 232 | case QED_PTP_FILTER_V2_EVENT: |
| 233 | enable_cfg = 0x5; |
| 234 | rule_mask = 0x3CAA; |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 235 | break; |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 236 | case QED_PTP_FILTER_V2_GEN: |
| 237 | enable_cfg = 0x5; |
| 238 | rule_mask = 0x3EEE; |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 239 | break; |
| 240 | default: |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 241 | DP_INFO(p_hwfn, "Invalid PTP filter type %d\n", rx_type); |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 242 | return -EINVAL; |
| 243 | } |
| 244 | |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 245 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0); |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 246 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_RULE_MASK, rule_mask); |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 247 | qed_wr(p_hwfn, p_ptt, NIG_REG_RX_PTP_EN, enable_cfg); |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 248 | |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 249 | if (tx_type == QED_PTP_HWTSTAMP_TX_OFF) { |
| 250 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, 0x0); |
| 251 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0x7FF); |
| 252 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, 0x3FFF); |
| 253 | } else { |
| 254 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, enable_cfg); |
| 255 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0); |
| 256 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, rule_mask); |
| 257 | } |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 258 | |
| 259 | /* Reset possibly old timestamps */ |
| 260 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID, |
| 261 | QED_TIMESTAMP_MASK); |
| 262 | |
| 263 | return 0; |
| 264 | } |
| 265 | |
| 266 | /* Adjust the HW clock by a rate given in parts-per-billion (ppb) units. |
| 267 | * FW/HW accepts the adjustment value in terms of 3 parameters: |
| 268 | * Drift period - adjustment happens once in certain number of nano seconds. |
| 269 | * Drift value - time is adjusted by a certain value, for example by 5 ns. |
| 270 | * Drift direction - add or subtract the adjustment value. |
| 271 | * The routine translates ppb into the adjustment triplet in an optimal manner. |
| 272 | */ |
| 273 | static int qed_ptp_hw_adjfreq(struct qed_dev *cdev, s32 ppb) |
| 274 | { |
| 275 | s64 best_val = 0, val, best_period = 0, period, approx_dev, dif, dif2; |
| 276 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 277 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
| 278 | u32 drift_ctr_cfg = 0, drift_state; |
| 279 | int drift_dir = 1; |
| 280 | |
| 281 | if (ppb < 0) { |
| 282 | ppb = -ppb; |
| 283 | drift_dir = 0; |
| 284 | } |
| 285 | |
| 286 | if (ppb > 1) { |
| 287 | s64 best_dif = ppb, best_approx_dev = 1; |
| 288 | |
| 289 | /* Adjustment value is up to +/-7ns, find an optimal value in |
| 290 | * this range. |
| 291 | */ |
| 292 | for (val = 7; val > 0; val--) { |
| 293 | period = div_s64(val * 1000000000, ppb); |
| 294 | period -= 8; |
| 295 | period >>= 4; |
| 296 | if (period < 1) |
| 297 | period = 1; |
| 298 | if (period > 0xFFFFFFE) |
| 299 | period = 0xFFFFFFE; |
| 300 | |
| 301 | /* Check both rounding ends for approximate error */ |
| 302 | approx_dev = period * 16 + 8; |
| 303 | dif = ppb * approx_dev - val * 1000000000; |
| 304 | dif2 = dif + 16 * ppb; |
| 305 | |
| 306 | if (dif < 0) |
| 307 | dif = -dif; |
| 308 | if (dif2 < 0) |
| 309 | dif2 = -dif2; |
| 310 | |
| 311 | /* Determine which end gives better approximation */ |
| 312 | if (dif * (approx_dev + 16) > dif2 * approx_dev) { |
| 313 | period++; |
| 314 | approx_dev += 16; |
| 315 | dif = dif2; |
| 316 | } |
| 317 | |
| 318 | /* Track best approximation found so far */ |
| 319 | if (best_dif * approx_dev > dif * best_approx_dev) { |
| 320 | best_dif = dif; |
| 321 | best_val = val; |
| 322 | best_period = period; |
| 323 | best_approx_dev = approx_dev; |
| 324 | } |
| 325 | } |
| 326 | } else if (ppb == 1) { |
| 327 | /* This is a special case as its the only value which wouldn't |
| 328 | * fit in a s64 variable. In order to prevent castings simple |
| 329 | * handle it seperately. |
| 330 | */ |
| 331 | best_val = 4; |
| 332 | best_period = 0xee6b27f; |
| 333 | } else { |
| 334 | best_val = 0; |
| 335 | best_period = 0xFFFFFFF; |
| 336 | } |
| 337 | |
| 338 | drift_ctr_cfg = (best_period << QED_DRIFT_CNTR_TIME_QUANTA_SHIFT) | |
| 339 | (((int)best_val) << QED_DRIFT_CNTR_ADJUSTMENT_SHIFT) | |
| 340 | (((int)drift_dir) << QED_DRIFT_CNTR_DIRECTION_SHIFT); |
| 341 | |
| 342 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_RST_DRIFT_CNTR, 0x1); |
| 343 | |
| 344 | drift_state = qed_rd(p_hwfn, p_ptt, NIG_REG_TSGEN_RST_DRIFT_CNTR); |
| 345 | if (drift_state & 1) { |
| 346 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_DRIFT_CNTR_CONF, |
| 347 | drift_ctr_cfg); |
| 348 | } else { |
| 349 | DP_INFO(p_hwfn, "Drift counter is not reset\n"); |
| 350 | return -EINVAL; |
| 351 | } |
| 352 | |
| 353 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_RST_DRIFT_CNTR, 0x0); |
| 354 | |
| 355 | return 0; |
| 356 | } |
| 357 | |
| 358 | static int qed_ptp_hw_enable(struct qed_dev *cdev) |
| 359 | { |
| 360 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
sudarsana.kalluru@cavium.com | d179bd1 | 2017-04-26 09:00:53 -0700 | [diff] [blame] | 361 | struct qed_ptt *p_ptt; |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 362 | int rc; |
| 363 | |
sudarsana.kalluru@cavium.com | d179bd1 | 2017-04-26 09:00:53 -0700 | [diff] [blame] | 364 | p_ptt = qed_ptt_acquire(p_hwfn); |
| 365 | if (!p_ptt) { |
| 366 | DP_NOTICE(p_hwfn, "Failed to acquire PTT for PTP\n"); |
| 367 | return -EBUSY; |
| 368 | } |
| 369 | |
| 370 | p_hwfn->p_ptp_ptt = p_ptt; |
| 371 | |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 372 | rc = qed_ptp_res_lock(p_hwfn, p_ptt); |
| 373 | if (rc) { |
| 374 | DP_INFO(p_hwfn, |
| 375 | "Couldn't acquire the resource lock, skip ptp enable for this PF\n"); |
sudarsana.kalluru@cavium.com | d179bd1 | 2017-04-26 09:00:53 -0700 | [diff] [blame] | 376 | qed_ptt_release(p_hwfn, p_ptt); |
| 377 | p_hwfn->p_ptp_ptt = NULL; |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 378 | return rc; |
| 379 | } |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 380 | |
| 381 | /* Reset PTP event detection rules - will be configured in the IOCTL */ |
| 382 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0x7FF); |
| 383 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_RULE_MASK, 0x3FFF); |
| 384 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0x7FF); |
| 385 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, 0x3FFF); |
| 386 | |
| 387 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, 7); |
| 388 | qed_wr(p_hwfn, p_ptt, NIG_REG_RX_PTP_EN, 7); |
| 389 | |
| 390 | qed_wr(p_hwfn, p_ptt, NIG_REG_TS_OUTPUT_ENABLE_PDA, 0x1); |
| 391 | |
| 392 | /* Pause free running counter */ |
Mintz, Yuval | 9c79dda | 2017-03-14 16:23:54 +0200 | [diff] [blame] | 393 | if (QED_IS_BB_B0(p_hwfn->cdev)) |
| 394 | qed_wr(p_hwfn, p_ptt, NIG_REG_TIMESYNC_GEN_REG_BB, 2); |
| 395 | if (QED_IS_AH(p_hwfn->cdev)) |
| 396 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_FREECNT_UPDATE_K2, 2); |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 397 | |
| 398 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_FREE_CNT_VALUE_LSB, 0); |
| 399 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_FREE_CNT_VALUE_MSB, 0); |
| 400 | /* Resume free running counter */ |
Mintz, Yuval | 9c79dda | 2017-03-14 16:23:54 +0200 | [diff] [blame] | 401 | if (QED_IS_BB_B0(p_hwfn->cdev)) |
| 402 | qed_wr(p_hwfn, p_ptt, NIG_REG_TIMESYNC_GEN_REG_BB, 4); |
| 403 | if (QED_IS_AH(p_hwfn->cdev)) { |
| 404 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_FREECNT_UPDATE_K2, 4); |
| 405 | qed_wr(p_hwfn, p_ptt, NIG_REG_PTP_LATCH_OSTS_PKT_TIME, 1); |
| 406 | } |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 407 | |
| 408 | /* Disable drift register */ |
| 409 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_DRIFT_CNTR_CONF, 0x0); |
| 410 | qed_wr(p_hwfn, p_ptt, NIG_REG_TSGEN_RST_DRIFT_CNTR, 0x0); |
| 411 | |
| 412 | /* Reset possibly old timestamps */ |
| 413 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_HOST_BUF_SEQID, |
| 414 | QED_TIMESTAMP_MASK); |
| 415 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_BUF_SEQID, QED_TIMESTAMP_MASK); |
| 416 | |
| 417 | return 0; |
| 418 | } |
| 419 | |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 420 | static int qed_ptp_hw_disable(struct qed_dev *cdev) |
| 421 | { |
| 422 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); |
| 423 | struct qed_ptt *p_ptt = p_hwfn->p_ptp_ptt; |
| 424 | |
sudarsana.kalluru@cavium.com | db82f70 | 2017-04-26 09:00:50 -0700 | [diff] [blame] | 425 | qed_ptp_res_unlock(p_hwfn, p_ptt); |
| 426 | |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 427 | /* Reset PTP event detection rules */ |
| 428 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_PARAM_MASK, 0x7FF); |
| 429 | qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_PTP_RULE_MASK, 0x3FFF); |
| 430 | |
| 431 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_PARAM_MASK, 0x7FF); |
| 432 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_LLH_PTP_RULE_MASK, 0x3FFF); |
| 433 | |
| 434 | /* Disable the PTP feature */ |
| 435 | qed_wr(p_hwfn, p_ptt, NIG_REG_RX_PTP_EN, 0x0); |
| 436 | qed_wr(p_hwfn, p_ptt, NIG_REG_TX_PTP_EN, 0x0); |
| 437 | |
sudarsana.kalluru@cavium.com | d179bd1 | 2017-04-26 09:00:53 -0700 | [diff] [blame] | 438 | qed_ptt_release(p_hwfn, p_ptt); |
| 439 | p_hwfn->p_ptp_ptt = NULL; |
| 440 | |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 441 | return 0; |
| 442 | } |
| 443 | |
| 444 | const struct qed_eth_ptp_ops qed_ptp_ops_pass = { |
sudarsana.kalluru@cavium.com | 8d3f87d | 2017-05-02 01:11:03 -0700 | [diff] [blame] | 445 | .cfg_filters = qed_ptp_hw_cfg_filters, |
Sudarsana Reddy Kalluru | c78c70f | 2017-02-15 10:24:10 +0200 | [diff] [blame] | 446 | .read_rx_ts = qed_ptp_hw_read_rx_ts, |
| 447 | .read_tx_ts = qed_ptp_hw_read_tx_ts, |
| 448 | .read_cc = qed_ptp_hw_read_cc, |
| 449 | .adjfreq = qed_ptp_hw_adjfreq, |
| 450 | .disable = qed_ptp_hw_disable, |
| 451 | .enable = qed_ptp_hw_enable, |
| 452 | }; |