diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h index c917cda7b8..f3b6921c20 100644 --- a/dp/inc/cdp_txrx_cmn.h +++ b/dp/inc/cdp_txrx_cmn.h @@ -2905,4 +2905,29 @@ cdp_enable_mon_reap_timer(ol_txrx_soc_handle soc, return soc->ops->mon_ops->txrx_enable_mon_reap_timer(soc, source, enable); } + +/** + * cdp_get_tsf_time() - get tsf time + * @soc: Datapath soc handle + * @mac_id: mac_id + * @tsf: pointer to update tsf value + * @tsf_sync_soc_time: pointer to update tsf sync time + * + * Return: None. + */ +static inline void +cdp_get_tsf_time(ol_txrx_soc_handle soc, uint32_t tsf_id, uint32_t mac_id, + uint64_t *tsf, uint64_t *tsf_sync_soc_time) +{ + if (!soc) { + dp_cdp_debug("Invalid Instance"); + return; + } + if (!soc->ops->cmn_drv_ops || !soc->ops->cmn_drv_ops->txrx_get_tsf_time) + return; + + soc->ops->cmn_drv_ops->txrx_get_tsf_time(soc, tsf_id, mac_id, tsf, + tsf_sync_soc_time); +} + #endif /* _CDP_TXRX_CMN_H_ */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index c1cb14c353..50da1ac4c8 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -683,6 +683,10 @@ struct cdp_cmn_ops { bool mlo_peers_only); #endif QDF_STATUS (*txrx_umac_reset_deinit)(ol_txrx_soc_handle soc); + void (*txrx_get_tsf_time)(struct cdp_soc_t *soc_hdl, uint32_t tsf_id, + uint32_t mac_id, uint64_t *tsf, + uint64_t *tsf_sync_soc_time); + }; struct cdp_ctrl_ops { diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 3dc22d7f7e..da60fd02f1 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -13554,6 +13554,30 @@ dp_recovery_vdev_flush_peers(struct cdp_soc_t *cdp_soc, dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); } #endif +#ifdef QCA_GET_TSF_VIA_REG +/** + * dp_get_tsf_time() - get tsf time + * @soc: Datapath soc handle + * @mac_id: mac_id + * @tsf: pointer to update tsf value + * @tsf_sync_soc_time: pointer to update tsf sync time + * + * Return: None. + */ +static inline void +dp_get_tsf_time(struct cdp_soc_t *soc_hdl, uint32_t tsf_id, uint32_t mac_id, + uint64_t *tsf, uint64_t *tsf_sync_soc_time) +{ + hal_get_tsf_time(((struct dp_soc *)soc_hdl)->hal_soc, tsf_id, mac_id, + tsf, tsf_sync_soc_time); +} +#else +static inline void +dp_get_tsf_time(struct cdp_soc_t *soc_hdl, uint32_t tsf_id, uint32_t mac_id, + uint64_t *tsf, uint64_t *tsf_sync_soc_time) +{ +} +#endif static struct cdp_cmn_ops dp_ops_cmn = { .txrx_soc_attach_target = dp_soc_attach_target_wifi3, @@ -13675,6 +13699,7 @@ static struct cdp_cmn_ops dp_ops_cmn = { .txrx_recovery_vdev_flush_peers = dp_recovery_vdev_flush_peers, #endif .txrx_umac_reset_deinit = dp_soc_umac_reset_deinit, + .txrx_get_tsf_time = dp_get_tsf_time, }; static struct cdp_ctrl_ops dp_ops_ctrl = { diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 6466070859..fcafc4d7bf 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -1199,6 +1199,9 @@ struct hal_hw_txrx_ops { void (*hal_tx_vdev_mcast_ctrl_set)(hal_soc_handle_t hal_soc_hdl, uint8_t vdev_id, uint8_t mcast_ctrl_val); + void (*hal_get_tsf_time)(hal_soc_handle_t hal_soc_hdl, uint32_t tsf_id, + uint32_t mac_id, uint64_t *tsf, + uint64_t *tsf_sync_soc_time); }; /** diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index c3648c554c..dc1091eb2f 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -3018,4 +3018,25 @@ hal_rx_tlv_l3_type_get(hal_soc_handle_t hal_soc_hdl, uint8_t *buf) hal_soc->ops->hal_rx_tlv_l3_type_get(buf) : HAL_RX_TLV_L3_TYPE_INVALID; } + +/** + * hal_get_tsf_time() - Get tsf time + * @hal_soc_hdl: HAL soc handle + * @mac_id: mac_id + * @tsf: pointer to update tsf value + * @tsf_sync_soc_time: pointer to update tsf sync time + * + * Return: None. + */ +static inline void +hal_get_tsf_time(hal_soc_handle_t hal_soc_hdl, uint32_t tsf_id, + uint32_t mac_id, uint64_t *tsf, + uint64_t *tsf_sync_soc_time) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (hal_soc->ops->hal_get_tsf_time) + hal_soc->ops->hal_get_tsf_time(hal_soc_hdl, tsf_id, mac_id, + tsf, tsf_sync_soc_time); +} #endif /* _HAL_RX_H */ diff --git a/hal/wifi3.0/kiwi/hal_kiwi.c b/hal/wifi3.0/kiwi/hal_kiwi.c index 04d2a2f1ba..5ad8d0fe2f 100644 --- a/hal/wifi3.0/kiwi/hal_kiwi.c +++ b/hal/wifi3.0/kiwi/hal_kiwi.c @@ -126,6 +126,36 @@ #define LINK_DESC_SIZE (NUM_OF_DWORDS_RX_MSDU_LINK << 2) +#ifdef QCA_GET_TSF_VIA_REG +#define PCIE_PCIE_MHI_TIME_LOW 0xA28 +#define PCIE_PCIE_MHI_TIME_HIGH 0xA2C + +#define PMM_REG_BASE 0xB500FC + +#define FW_QTIME_CYCLES_PER_10_USEC 192 + +/* enum to indicate which scratch registers hold which value*/ +/* Obtain from pcie_reg_scratch.h? */ +enum hal_scratch_reg_enum { + PMM_QTIMER_GLOBAL_OFFSET_LO_US, + PMM_QTIMER_GLOBAL_OFFSET_HI_US, + PMM_MAC0_TSF1_OFFSET_LO_US, + PMM_MAC0_TSF1_OFFSET_HI_US, + PMM_MAC0_TSF2_OFFSET_LO_US, + PMM_MAC0_TSF2_OFFSET_HI_US, + PMM_MAC1_TSF1_OFFSET_LO_US, + PMM_MAC1_TSF1_OFFSET_HI_US, + PMM_MAC1_TSF2_OFFSET_LO_US, + PMM_MAC1_TSF2_OFFSET_HI_US, + PMM_MLO_OFFSET_LO_US, + PMM_MLO_OFFSET_HI_US, + PMM_TQM_CLOCK_OFFSET_LO_US, + PMM_TQM_CLOCK_OFFSET_HI_US, + PMM_Q6_CRASH_REASON, + PMM_PMM_REG_MAX +}; +#endif + static uint32_t hal_get_link_desc_size_kiwi(void) { return LINK_DESC_SIZE; @@ -1865,6 +1895,121 @@ static uint32_t hal_get_reo_qdesc_size_kiwi(uint32_t ba_window_size, int tid) sizeof(struct rx_reo_queue_1k); } +#ifdef QCA_GET_TSF_VIA_REG +static inline void +hal_get_tsf_enum(uint32_t tsf_id, uint32_t mac_id, + enum hal_scratch_reg_enum *tsf_enum_low, + enum hal_scratch_reg_enum *tsf_enum_hi) +{ + if (mac_id == 0) { + if (tsf_id == 0) { + *tsf_enum_low = PMM_MAC0_TSF1_OFFSET_LO_US; + *tsf_enum_hi = PMM_MAC0_TSF1_OFFSET_HI_US; + } else if (tsf_id == 1) { + *tsf_enum_low = PMM_MAC0_TSF2_OFFSET_LO_US; + *tsf_enum_hi = PMM_MAC0_TSF2_OFFSET_HI_US; + } + } else if (mac_id == 1) { + if (tsf_id == 0) { + *tsf_enum_low = PMM_MAC1_TSF1_OFFSET_LO_US; + *tsf_enum_hi = PMM_MAC1_TSF1_OFFSET_HI_US; + } else if (tsf_id == 1) { + *tsf_enum_low = PMM_MAC1_TSF2_OFFSET_LO_US; + *tsf_enum_hi = PMM_MAC1_TSF2_OFFSET_HI_US; + } + } +} + +static inline uint32_t +hal_tsf_read_scratch_reg(struct hal_soc *soc, + enum hal_scratch_reg_enum reg_enum) +{ + return hal_read32_mb(soc, PMM_REG_BASE + (reg_enum * 4)); +} + +static inline +uint64_t hal_tsf_get_fw_time(struct hal_soc *soc) +{ + uint64_t fw_time_low; + uint64_t fw_time_high; + + fw_time_low = hal_read32_mb(soc, PCIE_PCIE_MHI_TIME_LOW); + fw_time_high = hal_read32_mb(soc, PCIE_PCIE_MHI_TIME_HIGH); + return (fw_time_high << 32 | fw_time_low); +} + +static inline +uint64_t hal_fw_qtime_to_usecs(uint64_t time) +{ + /* + * Try to preserve precision by multiplying by 10 first. + * If that would cause a wrap around, divide first instead. + */ + if (time * 10 < time) { + time = qdf_do_div(time, FW_QTIME_CYCLES_PER_10_USEC); + return time * 10; + } + + time = time * 10; + time = qdf_do_div(time, FW_QTIME_CYCLES_PER_10_USEC); + + return time; +} + +/** + * hal_get_tsf_time_kiwi() - Get tsf time from scatch register + * @hal_soc_hdl: HAL soc handle + * @mac_id: mac_id + * @tsf: pointer to update tsf value + * @tsf_sync_soc_time: pointer to update tsf sync time + * + * Return: None. + */ +static void +hal_get_tsf_time_kiwi(hal_soc_handle_t hal_soc_hdl, uint32_t tsf_id, + uint32_t mac_id, uint64_t *tsf, + uint64_t *tsf_sync_soc_time) +{ + struct hal_soc *soc = (struct hal_soc *)hal_soc_hdl; + uint64_t global_time_low_offset, global_time_high_offset; + uint64_t tsf_offset_low, tsf_offset_hi; + uint64_t fw_time, global_time, sync_time; + enum hal_scratch_reg_enum tsf_enum_low, tsf_enum_high; + + if (hif_force_wake_request(soc->hif_handle)) + return; + + hal_get_tsf_enum(tsf_id, mac_id, &tsf_enum_low, &tsf_enum_high); + sync_time = qdf_get_log_timestamp(); + fw_time = hal_tsf_get_fw_time(soc); + + global_time_low_offset = + hal_tsf_read_scratch_reg(soc, PMM_QTIMER_GLOBAL_OFFSET_LO_US); + global_time_high_offset = + hal_tsf_read_scratch_reg(soc, PMM_QTIMER_GLOBAL_OFFSET_HI_US); + + tsf_offset_low = hal_tsf_read_scratch_reg(soc, tsf_enum_low); + tsf_offset_hi = hal_tsf_read_scratch_reg(soc, tsf_enum_high); + + fw_time = hal_fw_qtime_to_usecs(fw_time); + global_time = fw_time + + (global_time_low_offset | + (global_time_high_offset << 32)); + + *tsf = global_time + (tsf_offset_low | (tsf_offset_hi << 32)); + *tsf_sync_soc_time = qdf_log_timestamp_to_usecs(sync_time); + + hif_force_wake_release(soc->hif_handle); +} +#else +static inline void +hal_get_tsf_time_kiwi(hal_soc_handle_t hal_soc_hdl, uint32_t tsf_id, + uint32_t mac_id, uint64_t *tsf, + uint64_t *tsf_sync_soc_time) +{ +} +#endif + static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc) { /* init and setup */ @@ -2123,6 +2268,7 @@ static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc) hal_tx_populate_bank_register_be; hal_soc->ops->hal_tx_vdev_mcast_ctrl_set = hal_tx_vdev_mcast_ctrl_set_be; + hal_soc->ops->hal_get_tsf_time = hal_get_tsf_time_kiwi; }; struct hal_hw_srng_config hw_srng_table_kiwi[] = {