From patchwork Wed Sep 15 05:34:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simei Su X-Patchwork-Id: 98881 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 927FCA0C43; Wed, 15 Sep 2021 07:42:17 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1E0CA4003F; Wed, 15 Sep 2021 07:42:17 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 776504003C for ; Wed, 15 Sep 2021 07:42:13 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10107"; a="209315209" X-IronPort-AV: E=Sophos;i="5.85,294,1624345200"; d="scan'208";a="209315209" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Sep 2021 22:42:12 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.85,294,1624345200"; d="scan'208";a="470617511" Received: from unknown (HELO npg-dpdk-cvl-simeisu-118d193.sh.intel.com) ([10.67.119.195]) by fmsmga007.fm.intel.com with ESMTP; 14 Sep 2021 22:42:10 -0700 From: Simei Su To: qi.z.zhang@intel.com Cc: dev@dpdk.org, haiyue.wang@intel.com, Simei Su Date: Wed, 15 Sep 2021 13:34:22 +0800 Message-Id: <20210915053422.319489-1-simei.su@intel.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20210909013049.444061-1-simei.su@intel.com> References: <20210909013049.444061-1-simei.su@intel.com> Subject: [dpdk-dev] [PATCH v3] net/ice: add 1PPS support for E810 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The E810 supports four single-ended GPIO signals (SDP[20:23]). The 1PPS signal outputs via SDP[20:23], which is measured by an oscilloscope. This feature can be turned by a devargs which can select GPIO pin index flexibly. Pin index 0 means SDP20, pin index 1 means SDP21 and so on. The example for test command is as below: ./build/app/dpdk-testpmd -a af:00.0,pps_out='[pin:2]' -c f -n 4 -- -i Signed-off-by: Simei Su Acked-by: Qi Zhang --- v3: * Rebase patch based on the latest code. v2: * Update the ice.rst for the new devargs. * Add the release notes. doc/guides/nics/ice.rst | 8 ++ doc/guides/rel_notes/release_21_11.rst | 4 + drivers/net/ice/ice_ethdev.c | 197 +++++++++++++++++++++++++++++++++ drivers/net/ice/ice_ethdev.h | 15 +++ 4 files changed, 224 insertions(+) diff --git a/doc/guides/nics/ice.rst b/doc/guides/nics/ice.rst index 5bc472f..ebe2cbc 100644 --- a/doc/guides/nics/ice.rst +++ b/doc/guides/nics/ice.rst @@ -219,6 +219,14 @@ Runtime Config Options These ICE_DBG_XXX are defined in ``drivers/net/ice/base/ice_type.h``. +- ``1PPS out support`` + + The E810 supports four single-ended GPIO signals (SDP[20:23]). The 1PPS + signal outputs via SDP[20:23]. User can select GPIO pin index flexibly. + Pin index 0 means SDP20, 1 means SDP21 and so on. For example:: + + -a af:00.0,pps_out='[pin:0]' + Driver compilation and testing ------------------------------ diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index 1465403..dc44739 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -67,6 +67,10 @@ New Features Added command-line options to specify total number of processes and current process ID. Each process owns subset of Rx and Tx queues. +* **Updated Intel ice driver.** + + Added 1PPS out support by a devargs. + Removed Items ------------- diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c index 8d62b84..76dcabf 100644 --- a/drivers/net/ice/ice_ethdev.c +++ b/drivers/net/ice/ice_ethdev.c @@ -29,15 +29,20 @@ #define ICE_PIPELINE_MODE_SUPPORT_ARG "pipeline-mode-support" #define ICE_PROTO_XTR_ARG "proto_xtr" #define ICE_HW_DEBUG_MASK_ARG "hw_debug_mask" +#define ICE_ONE_PPS_OUT_ARG "pps_out" static const char * const ice_valid_args[] = { ICE_SAFE_MODE_SUPPORT_ARG, ICE_PIPELINE_MODE_SUPPORT_ARG, ICE_PROTO_XTR_ARG, ICE_HW_DEBUG_MASK_ARG, + ICE_ONE_PPS_OUT_ARG, NULL }; +#define NSEC_PER_SEC 1000000000 +#define PPS_OUT_DELAY_NS 1 + static const struct rte_mbuf_dynfield ice_proto_xtr_metadata_param = { .name = "intel_pmd_dynfield_proto_xtr_metadata", .size = sizeof(uint32_t), @@ -1786,6 +1791,125 @@ parse_u64(const char *key, const char *value, void *args) return 0; } +static int +lookup_pps_type(const char *pps_name) +{ + static struct { + const char *name; + enum pps_type type; + } pps_type_map[] = { + { "pin", PPS_PIN }, + }; + + uint32_t i; + + for (i = 0; i < RTE_DIM(pps_type_map); i++) { + if (strcmp(pps_name, pps_type_map[i].name) == 0) + return pps_type_map[i].type; + } + + return -1; +} + +static int +parse_pin_set(const char *input, int pps_type, struct ice_devargs *devargs) +{ + const char *str = input; + char *end = NULL; + uint32_t idx; + + while (isblank(*str)) + str++; + + if (!isdigit(*str)) + return -1; + + if (pps_type == PPS_PIN) { + idx = strtoul(str, &end, 10); + if (end == NULL || idx >= ICE_MAX_PIN_NUM) + return -1; + + devargs->pin_idx = idx; + devargs->pps_out_ena = 1; + } + + while (isblank(*end)) + end++; + + if (*end != ']') + return -1; + + return 0; +} + +static int +parse_pps_out_parameter(const char *pins, struct ice_devargs *devargs) +{ + const char *pin_start; + uint32_t idx; + int pps_type; + char pps_name[32]; + + while (isblank(*pins)) + pins++; + + pins++; + while (isblank(*pins)) + pins++; + if (*pins == '\0') + return -1; + + for (idx = 0; ; idx++) { + if (isblank(pins[idx]) || + pins[idx] == ':' || + pins[idx] == '\0') + break; + + pps_name[idx] = pins[idx]; + } + pps_name[idx] = '\0'; + pps_type = lookup_pps_type(pps_name); + if (pps_type < 0) + return -1; + + pins += idx; + + pins += strcspn(pins, ":"); + if (*pins++ != ':') + return -1; + while (isblank(*pins)) + pins++; + + pin_start = pins; + + while (isblank(*pins)) + pins++; + + if (parse_pin_set(pin_start, pps_type, devargs) < 0) + return -1; + + return 0; +} + +static int +handle_pps_out_arg(__rte_unused const char *key, const char *value, + void *extra_args) +{ + struct ice_devargs *devargs = extra_args; + + if (value == NULL || extra_args == NULL) + return -EINVAL; + + if (parse_pps_out_parameter(value, devargs) < 0) { + PMD_DRV_LOG(ERR, + "The GPIO pin parameter is wrong : '%s'", + value); + return -1; + } + + return 0; +} + static int ice_parse_devargs(struct rte_eth_dev *dev) { struct ice_adapter *ad = @@ -1827,6 +1951,11 @@ static int ice_parse_devargs(struct rte_eth_dev *dev) if (ret) goto bail; + ret = rte_kvargs_process(kvlist, ICE_ONE_PPS_OUT_ARG, + &handle_pps_out_arg, &ad->devargs); + if (ret) + goto bail; + bail: rte_kvargs_free(kvlist); return ret; @@ -2286,6 +2415,9 @@ ice_dev_close(struct rte_eth_dev *dev) struct ice_adapter *ad = ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); int ret; + uint32_t val; + uint8_t timer = hw->func_caps.ts_func_info.tmr_index_owned; + uint32_t pin_idx = ad->devargs.pin_idx; if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; @@ -2315,6 +2447,16 @@ ice_dev_close(struct rte_eth_dev *dev) rte_free(pf->proto_xtr); pf->proto_xtr = NULL; + if (ad->devargs.pps_out_ena) { + ICE_WRITE_REG(hw, GLTSYN_AUX_OUT(pin_idx, timer), 0); + ICE_WRITE_REG(hw, GLTSYN_CLKO(pin_idx, timer), 0); + ICE_WRITE_REG(hw, GLTSYN_TGT_L(pin_idx, timer), 0); + ICE_WRITE_REG(hw, GLTSYN_TGT_H(pin_idx, timer), 0); + + val = GLGEN_GPIO_CTL_PIN_DIR_M; + ICE_WRITE_REG(hw, GLGEN_GPIO_CTL(pin_idx), val); + } + /* disable uio intr before callback unregister */ rte_intr_disable(intr_handle); @@ -3318,16 +3460,63 @@ ice_get_init_link_status(struct rte_eth_dev *dev) } static int +ice_pps_out_cfg(struct ice_hw *hw, int idx, int timer) +{ + uint64_t current_time, start_time; + uint32_t hi, lo, lo2, func, val; + + lo = ICE_READ_REG(hw, GLTSYN_TIME_L(timer)); + hi = ICE_READ_REG(hw, GLTSYN_TIME_H(timer)); + lo2 = ICE_READ_REG(hw, GLTSYN_TIME_L(timer)); + + if (lo2 < lo) { + lo = ICE_READ_REG(hw, GLTSYN_TIME_L(timer)); + hi = ICE_READ_REG(hw, GLTSYN_TIME_H(timer)); + } + + current_time = ((uint64_t)hi << 32) | lo; + + start_time = (current_time + NSEC_PER_SEC) / + NSEC_PER_SEC * NSEC_PER_SEC; + start_time = start_time - PPS_OUT_DELAY_NS; + + func = 8 + idx + timer * 4; + val = GLGEN_GPIO_CTL_PIN_DIR_M | + ((func << GLGEN_GPIO_CTL_PIN_FUNC_S) & + GLGEN_GPIO_CTL_PIN_FUNC_M); + + /* Write clkout with half of period value */ + ICE_WRITE_REG(hw, GLTSYN_CLKO(idx, timer), NSEC_PER_SEC / 2); + + /* Write TARGET time register */ + ICE_WRITE_REG(hw, GLTSYN_TGT_L(idx, timer), start_time & 0xffffffff); + ICE_WRITE_REG(hw, GLTSYN_TGT_H(idx, timer), start_time >> 32); + + /* Write AUX_OUT register */ + ICE_WRITE_REG(hw, GLTSYN_AUX_OUT(idx, timer), + GLTSYN_AUX_OUT_0_OUT_ENA_M | GLTSYN_AUX_OUT_0_OUTMOD_M); + + /* Write GPIO CTL register */ + ICE_WRITE_REG(hw, GLGEN_GPIO_CTL(idx), val); + + return 0; +} + +static int ice_dev_start(struct rte_eth_dev *dev) { struct rte_eth_dev_data *data = dev->data; struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct ice_vsi *vsi = pf->main_vsi; + struct ice_adapter *ad = + ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); uint16_t nb_rxq = 0; uint16_t nb_txq, i; uint16_t max_frame_size; int mask, ret; + uint8_t timer = hw->func_caps.ts_func_info.tmr_index_owned; + uint32_t pin_idx = ad->devargs.pin_idx; /* program Tx queues' context in hardware */ for (nb_txq = 0; nb_txq < data->nb_tx_queues; nb_txq++) { @@ -3398,6 +3587,14 @@ ice_dev_start(struct rte_eth_dev *dev) /* Set the max frame size to HW*/ ice_aq_set_mac_cfg(hw, max_frame_size, NULL); + if (ad->devargs.pps_out_ena) { + ret = ice_pps_out_cfg(hw, pin_idx, timer); + if (ret) { + PMD_DRV_LOG(ERR, "Fail to configure 1pps out"); + goto rx_err; + } + } + return 0; /* stop the started queues if failed to start all queues */ diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h index b4bf651..ea9d892 100644 --- a/drivers/net/ice/ice_ethdev.h +++ b/drivers/net/ice/ice_ethdev.h @@ -143,6 +143,12 @@ /* Max number of flexible descriptor rxdid */ #define ICE_FLEX_DESC_RXDID_MAX_NUM 64 +/* Per-channel register definitions */ +#define GLTSYN_AUX_OUT(_chan, _idx) (GLTSYN_AUX_OUT_0(_idx) + ((_chan) * 8)) +#define GLTSYN_CLKO(_chan, _idx) (GLTSYN_CLKO_0(_idx) + ((_chan) * 8)) +#define GLTSYN_TGT_L(_chan, _idx) (GLTSYN_TGT_L_0(_idx) + ((_chan) * 16)) +#define GLTSYN_TGT_H(_chan, _idx) (GLTSYN_TGT_H_0(_idx) + ((_chan) * 16)) + /* DDP package type */ enum ice_pkg_type { ICE_PKG_TYPE_UNKNOWN, @@ -150,6 +156,12 @@ enum ice_pkg_type { ICE_PKG_TYPE_COMMS, }; +enum pps_type { + PPS_NONE, + PPS_PIN, + PPS_MAX, +}; + struct ice_adapter; /** @@ -458,6 +470,7 @@ struct ice_pf { }; #define ICE_MAX_QUEUE_NUM 2048 +#define ICE_MAX_PIN_NUM 4 /** * Cache devargs parse result. @@ -467,6 +480,8 @@ struct ice_devargs { uint8_t proto_xtr_dflt; int pipe_mode_support; uint8_t proto_xtr[ICE_MAX_QUEUE_NUM]; + uint8_t pin_idx; + uint8_t pps_out_ena; }; /**