mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
nvpps: Add support for AGX Orin.
Enable nvpps driver so it can be tested.
- Removed passing of ethernet interface name in DT.
- Require to pass Tegra ethernet controller DT phandle, where PTP server
will run.
Bug 4489344
Bug 3826818
Change-Id: I943ddf4071a55fb409d589473fde0075ac9f7150
Signed-off-by: Hiteshkumar Patel <hiteshkumarg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3076494
(cherry pick from commit 90c8229157)
Signed-off-by: Hiteshkumar Patel <hiteshkumarg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3097855
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
7acb255112
commit
f4720eda1d
@@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2018-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
#include <nvidia/conftest.h>
|
#include <nvidia/conftest.h>
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <uapi/linux/nvpps_ioctl.h>
|
#include <uapi/linux/nvpps_ioctl.h>
|
||||||
#include <linux/hte.h>
|
#include <linux/hte.h>
|
||||||
#include <linux/nvpps.h>
|
#include <linux/nvpps.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
|
||||||
/* the following control flags are for
|
/* the following control flags are for
|
||||||
@@ -41,7 +41,6 @@ static dev_t s_nvpps_devt;
|
|||||||
static DEFINE_MUTEX(s_nvpps_lock);
|
static DEFINE_MUTEX(s_nvpps_lock);
|
||||||
static DEFINE_IDR(s_nvpps_idr);
|
static DEFINE_IDR(s_nvpps_idr);
|
||||||
|
|
||||||
static char *interface_name = "eth0";
|
|
||||||
bool print_pri_ptp_failed = true;
|
bool print_pri_ptp_failed = true;
|
||||||
bool print_sec_ptp_failed = true;
|
bool print_sec_ptp_failed = true;
|
||||||
|
|
||||||
@@ -78,18 +77,18 @@ struct nvpps_device_data {
|
|||||||
wait_queue_head_t pps_event_queue;
|
wait_queue_head_t pps_event_queue;
|
||||||
struct fasync_struct *pps_event_async_queue;
|
struct fasync_struct *pps_event_async_queue;
|
||||||
|
|
||||||
bool memmap_phc_regs;
|
struct device_node *pri_emac_node;
|
||||||
char *iface_nm;
|
struct device_node *sec_emac_node;
|
||||||
char *sec_iface_nm;
|
resource_size_t pri_emac_base_addr;
|
||||||
void __iomem *mac_base_addr;
|
void __iomem *mac_base_addr;
|
||||||
u32 sts_offset;
|
u32 sts_offset;
|
||||||
u32 stns_offset;
|
u32 stns_offset;
|
||||||
void __iomem *tsc_reg_map_base;
|
void __iomem *tsc_reg_map_base;
|
||||||
bool platform_is_orin;
|
|
||||||
u32 tsc_ptp_src;
|
u32 tsc_ptp_src;
|
||||||
bool only_timer_mode;
|
bool only_timer_mode;
|
||||||
bool pri_ptp_failed;
|
bool pri_ptp_failed;
|
||||||
bool sec_ptp_failed;
|
bool sec_ptp_failed;
|
||||||
|
bool support_tsc;
|
||||||
uint8_t k_int_val;
|
uint8_t k_int_val;
|
||||||
uint16_t lock_threshold_val;
|
uint16_t lock_threshold_val;
|
||||||
struct hte_ts_desc desc;
|
struct hte_ts_desc desc;
|
||||||
@@ -103,45 +102,46 @@ struct nvpps_file_data {
|
|||||||
unsigned int pps_event_id_rd;
|
unsigned int pps_event_id_rd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* MAC Base addrs */
|
|
||||||
#define T194_EQOS_BASE_ADDR 0x2490000
|
|
||||||
#define T234_EQOS_BASE_ADDR 0x2310000
|
|
||||||
#define EQOS_STSR_OFFSET 0xb08
|
#define EQOS_STSR_OFFSET 0xb08
|
||||||
#define EQOS_STNSR_OFFSET 0xb0c
|
#define EQOS_STNSR_OFFSET 0xb0c
|
||||||
#define T234_MGBE0_BASE_ADDR 0x6810000
|
|
||||||
#define T234_MGBE1_BASE_ADDR 0x6910000
|
|
||||||
#define T234_MGBE2_BASE_ADDR 0x6a10000
|
|
||||||
#define T234_MGBE3_BASE_ADDR 0x6b10000
|
|
||||||
#define MGBE_STSR_OFFSET 0xd08
|
#define MGBE_STSR_OFFSET 0xd08
|
||||||
#define MGBE_STNSR_OFFSET 0xd0c
|
#define MGBE_STNSR_OFFSET 0xd0c
|
||||||
|
|
||||||
|
#define T234_MGBE0_BASE_ADDR 0x6810000
|
||||||
|
#define T234_MGBE1_BASE_ADDR 0x6910000
|
||||||
|
#define T234_MGBE2_BASE_ADDR 0x6a10000
|
||||||
|
#define T234_MGBE3_BASE_ADDR 0x6b10000
|
||||||
|
#define T234_EQOS_BASE_ADDR 0x2310000
|
||||||
|
#define T194_EQOS_BASE_ADDR 0x2490000
|
||||||
|
|
||||||
|
#define TSC_PTP_SRC_EQOS 0
|
||||||
|
#define TSC_PTP_SRC_MGBE0 1
|
||||||
|
#define TSC_PTP_SRC_MGBE1 2
|
||||||
|
#define TSC_PTP_SRC_MGBE2 3
|
||||||
|
#define TSC_PTP_SRC_MGBE3 4
|
||||||
|
#define TSC_PTP_SRC_INVALID 5
|
||||||
|
|
||||||
/* Below are the tsc register offset from ioremapped
|
/* Below are the tsc register offset from ioremapped
|
||||||
* virtual base region stored in tsc_reg_map_base.
|
* virtual base region stored in tsc_reg_map_base.
|
||||||
*/
|
*/
|
||||||
#define TSC_STSCRSR_OFFSET 0x0
|
#define TSC_STSCRSR_OFFSET 0x104
|
||||||
#define TSC_CAPTURE_CONFIGURATION_PTX_OFFSET 0x58
|
#define TSC_CAPTURE_CONFIGURATION_PTX_OFFSET (TSC_STSCRSR_OFFSET + 0x58)
|
||||||
#define TSC_CAPTURE_CONTROL_PTX_OFFSET 0x5c
|
#define TSC_CAPTURE_CONTROL_PTX_OFFSET (TSC_STSCRSR_OFFSET + 0x5c)
|
||||||
#define TSC_LOCKING_CONFIGURATION_OFFSET 0xe4
|
#define TSC_LOCKING_CONFIGURATION_OFFSET (TSC_STSCRSR_OFFSET + 0xe4)
|
||||||
#define TSC_LOCKING_CONTROL_OFFSET 0xe8
|
#define TSC_LOCKING_CONTROL_OFFSET (TSC_STSCRSR_OFFSET + 0xe8)
|
||||||
#define TSC_LOCKING_STATUS_OFFSET 0xec
|
#define TSC_LOCKING_STATUS_OFFSET (TSC_STSCRSR_OFFSET + 0xec)
|
||||||
#define TSC_LOCKING_REF_FREQUENCY_CONFIGURATION_OFFSET 0xf0
|
#define TSC_LOCKING_REF_FREQUENCY_CONFIGURATION_OFFSET (TSC_STSCRSR_OFFSET + 0xf0)
|
||||||
#define TSC_LOCKING_DIFF_CONFIGURATION_OFFSET 0xf4
|
#define TSC_LOCKING_DIFF_CONFIGURATION_OFFSET (TSC_STSCRSR_OFFSET + 0xf4)
|
||||||
#define TSC_LOCKING_ADJUST_CONFIGURATION_OFFSET 0x108
|
#define TSC_LOCKING_ADJUST_CONFIGURATION_OFFSET (TSC_STSCRSR_OFFSET + 0x108)
|
||||||
#define TSC_LOCKING_FAST_ADJUST_CONFIGURATION_OFFSET 0x10c
|
#define TSC_LOCKING_FAST_ADJUST_CONFIGURATION_OFFSET (TSC_STSCRSR_OFFSET + 0x10c)
|
||||||
#define TSC_LOCKING_ADJUST_NUM_CONTROL_OFFSET 0x110
|
#define TSC_LOCKING_ADJUST_NUM_CONTROL_OFFSET (TSC_STSCRSR_OFFSET + 0x110)
|
||||||
#define TSC_LOCKING_ADJUST_DELTA_CONTROL_OFFSET 0x114
|
#define TSC_LOCKING_ADJUST_DELTA_CONTROL_OFFSET (TSC_STSCRSR_OFFSET + 0x114)
|
||||||
|
|
||||||
#define TSC_LOCKING_FAST_ADJUST_CONFIGURATION_OFFSET_K_INT_SHIFT 8
|
#define TSC_LOCKING_FAST_ADJUST_CONFIGURATION_OFFSET_K_INT_SHIFT 8
|
||||||
|
|
||||||
#define SRC_SELECT_BIT_OFFSET 8
|
#define SRC_SELECT_BIT_OFFSET 8
|
||||||
#define SRC_SELECT_BITS 0xff
|
#define SRC_SELECT_BITS 0xff
|
||||||
|
|
||||||
#define TSC_PTP_SRC_EQOS 0
|
|
||||||
#define TSC_PTP_SRC_MGBE0 1
|
|
||||||
#define TSC_PTP_SRC_MGBE1 2
|
|
||||||
#define TSC_PTP_SRC_MGBE2 3
|
|
||||||
#define TSC_PTP_SRC_MGBE3 4
|
|
||||||
|
|
||||||
#define TSC_LOCKED_STATUS_BIT_OFFSET 1
|
#define TSC_LOCKED_STATUS_BIT_OFFSET 1
|
||||||
#define TSC_ALIGNED_STATUS_BIT_OFFSET 0
|
#define TSC_ALIGNED_STATUS_BIT_OFFSET 0
|
||||||
|
|
||||||
@@ -152,6 +152,8 @@ struct nvpps_file_data {
|
|||||||
#define MAC_STNSR_TSSS_LPOS 0
|
#define MAC_STNSR_TSSS_LPOS 0
|
||||||
#define MAC_STNSR_TSSS_HPOS 30
|
#define MAC_STNSR_TSSS_HPOS 30
|
||||||
|
|
||||||
|
static struct device_node *emac_node;
|
||||||
|
|
||||||
#define GET_VALUE(data, lbit, hbit) ((data >> lbit) & (~(~0<<(hbit-lbit+1))))
|
#define GET_VALUE(data, lbit, hbit) ((data >> lbit) & (~(~0<<(hbit-lbit+1))))
|
||||||
#define MAC_STNSR_OFFSET (BASE_ADDRESS + pdev_data->stns_offset)
|
#define MAC_STNSR_OFFSET (BASE_ADDRESS + pdev_data->stns_offset)
|
||||||
#define MAC_STNSR_RD(data) do {\
|
#define MAC_STNSR_RD(data) do {\
|
||||||
@@ -162,6 +164,13 @@ struct nvpps_file_data {
|
|||||||
(data) = ioread32(MAC_STSR_OFFSET);\
|
(data) = ioread32(MAC_STSR_OFFSET);\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tegra_chip_data Tegra chip specific data
|
||||||
|
* @support_tsc: Supported TSC sync by chip
|
||||||
|
*/
|
||||||
|
struct tegra_chip_data {
|
||||||
|
bool support_tsc;
|
||||||
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
|
||||||
static inline u64 __arch_counter_get_cntvct(void)
|
static inline u64 __arch_counter_get_cntvct(void)
|
||||||
@@ -181,12 +190,12 @@ static inline u64 __arch_counter_get_cntvct(void)
|
|||||||
*
|
*
|
||||||
* This API is available irrespective of nvpps dt availablity
|
* This API is available irrespective of nvpps dt availablity
|
||||||
* When nvpps dt node is not present, interface name will
|
* When nvpps dt node is not present, interface name will
|
||||||
* default to "eth0".
|
* default to "eth0"
|
||||||
*/
|
*/
|
||||||
int nvpps_get_ptp_ts(void *ts)
|
int nvpps_get_ptp_ts(void *ts)
|
||||||
{
|
{
|
||||||
//TODO : should we support this API with memmapped method
|
//TODO : should we support this API with memmapped method
|
||||||
return tegra_get_hwtime(interface_name, ts, PTP_HWTIME);
|
return tegra_get_hwtime(emac_node, ts, PTP_HWTIME);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvpps_get_ptp_ts);
|
EXPORT_SYMBOL(nvpps_get_ptp_ts);
|
||||||
|
|
||||||
@@ -239,13 +248,13 @@ static void nvpps_get_ts(struct nvpps_device_data *pdev_data, u64 irq_tsc)
|
|||||||
struct ptp_tsc_data ptp_tsc_ts = {0}, sec_ptp_tsc_ts = {0};
|
struct ptp_tsc_data ptp_tsc_ts = {0}, sec_ptp_tsc_ts = {0};
|
||||||
|
|
||||||
/* get the PTP timestamp */
|
/* get the PTP timestamp */
|
||||||
if (pdev_data->memmap_phc_regs) {
|
if (pdev_data->mac_base_addr) {
|
||||||
/* get both the phc(using memmap reg) and tsc */
|
/* get both the phc(using memmap reg) and tsc */
|
||||||
phc = get_systime(pdev_data, &tsc);
|
phc = get_systime(pdev_data, &tsc);
|
||||||
/*TODO : support fetching ptp offset using memmap method */
|
/*TODO : support fetching ptp offset using memmap method */
|
||||||
} else {
|
} else {
|
||||||
/* get PTP_TSC concurrent timestamp(using ptp notifier) from MAC driver */
|
/* get PTP_TSC concurrent timestamp(using ptp notifier) from MAC driver */
|
||||||
if (tegra_get_hwtime(pdev_data->iface_nm, &ptp_tsc_ts, PTP_TSC_HWTIME)) {
|
if (tegra_get_hwtime(pdev_data->pri_emac_node, &ptp_tsc_ts, PTP_TSC_HWTIME)) {
|
||||||
pdev_data->pri_ptp_failed = true;
|
pdev_data->pri_ptp_failed = true;
|
||||||
} else {
|
} else {
|
||||||
pdev_data->pri_ptp_failed = false;
|
pdev_data->pri_ptp_failed = false;
|
||||||
@@ -254,15 +263,15 @@ static void nvpps_get_ts(struct nvpps_device_data *pdev_data, u64 irq_tsc)
|
|||||||
tsc = ptp_tsc_ts.tsc_ts / pdev_data->tsc_res_ns;
|
tsc = ptp_tsc_ts.tsc_ts / pdev_data->tsc_res_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pdev_data->support_tsc) &&
|
||||||
if ((pdev_data->platform_is_orin) &&
|
|
||||||
/* primary & secondary ptp interface are not same */
|
/* primary & secondary ptp interface are not same */
|
||||||
(strncmp(pdev_data->iface_nm, pdev_data->sec_iface_nm, strlen(pdev_data->iface_nm)))) {
|
(pdev_data->pri_emac_node != pdev_data->sec_emac_node)) {
|
||||||
|
|
||||||
/* get PTP_TSC concurrent timestamp(using ptp notifier) from MAC
|
/* get PTP_TSC concurrent timestamp(using ptp notifier) from MAC
|
||||||
* driver for secondary interface
|
* driver for secondary interface
|
||||||
*/
|
*/
|
||||||
if (tegra_get_hwtime(pdev_data->sec_iface_nm, &sec_ptp_tsc_ts, PTP_TSC_HWTIME)) {
|
if (tegra_get_hwtime(pdev_data->sec_emac_node, &sec_ptp_tsc_ts,
|
||||||
|
PTP_TSC_HWTIME)) {
|
||||||
pdev_data->sec_ptp_failed = true;
|
pdev_data->sec_ptp_failed = true;
|
||||||
} else {
|
} else {
|
||||||
pdev_data->sec_ptp_failed = false;
|
pdev_data->sec_ptp_failed = false;
|
||||||
@@ -590,16 +599,16 @@ static long nvpps_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||||||
/* check flag to print ptp failure msg */
|
/* check flag to print ptp failure msg */
|
||||||
if ((pdev_data->pri_ptp_failed) && (print_pri_ptp_failed)) {
|
if ((pdev_data->pri_ptp_failed) && (print_pri_ptp_failed)) {
|
||||||
dev_warn_ratelimited(pdev_data->dev,
|
dev_warn_ratelimited(pdev_data->dev,
|
||||||
"failed to get PTP_TSC concurrent timestamp from interface(%s)\nMake sure ptp is running\n",
|
"failed to get PTP_TSC timestamp from emac instance\n");
|
||||||
pdev_data->iface_nm);
|
dev_warn_ratelimited(pdev_data->dev, "Make sure PTP is running\n");
|
||||||
print_pri_ptp_failed = false;
|
print_pri_ptp_failed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check flag to print ptp failure msg */
|
/* check flag to print ptp failure msg */
|
||||||
if ((pdev_data->sec_ptp_failed) && (print_sec_ptp_failed)) {
|
if ((pdev_data->sec_ptp_failed) && (print_sec_ptp_failed)) {
|
||||||
dev_warn_ratelimited(pdev_data->dev,
|
dev_warn_ratelimited(pdev_data->dev,
|
||||||
"failed to get PTP_TSC concurrent timestamp from interface(%s)\nMake sure ptp is running\n",
|
"failed to get PTP_TSC timestamp from emac instance\n");
|
||||||
pdev_data->iface_nm);
|
dev_warn_ratelimited(pdev_data->dev, "Make sure PTP is running\n");
|
||||||
print_sec_ptp_failed = false;
|
print_sec_ptp_failed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +676,7 @@ static long nvpps_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||||||
"ioctl: Unsupported clockid\n");
|
"ioctl: Unsupported clockid\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tegra_get_hwtime(pdev_data->iface_nm, &ns, PTP_HWTIME);
|
err = tegra_get_hwtime(pdev_data->pri_emac_node, &ns, PTP_HWTIME);
|
||||||
mutex_unlock(&pdev_data->ts_lock);
|
mutex_unlock(&pdev_data->ts_lock);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_dbg(pdev_data->dev,
|
dev_dbg(pdev_data->dev,
|
||||||
@@ -758,113 +767,62 @@ static void nvpps_dev_release(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void nvpps_fill_default_mac_phc_info(struct platform_device *pdev,
|
static void nvpps_fill_default_mac_phc_info(struct platform_device *pdev,
|
||||||
struct nvpps_device_data *pdev_data)
|
struct nvpps_device_data *pdev_data)
|
||||||
{
|
{
|
||||||
bool use_eqos_mac = false;
|
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
bool memmap_phc_regs;
|
||||||
|
|
||||||
pdev_data->platform_is_orin = false;
|
/* identify the tsc_ptp_src and sts_offset */
|
||||||
|
if (pdev_data->pri_emac_base_addr == T234_MGBE0_BASE_ADDR) {
|
||||||
/* Get default params from dt */
|
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
||||||
pdev_data->iface_nm = (char *)of_get_property(np, "interface", NULL);
|
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
||||||
pdev_data->sec_iface_nm = (char *)of_get_property(np, "sec_interface", NULL);
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_MGBE0;
|
||||||
pdev_data->memmap_phc_regs = of_property_read_bool(np, "memmap_phc_regs");
|
} else if (pdev_data->pri_emac_base_addr == T234_MGBE1_BASE_ADDR) {
|
||||||
|
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
||||||
/* For orin */
|
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
||||||
if (of_machine_is_compatible("nvidia,tegra234")) {
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_MGBE1;
|
||||||
pdev_data->platform_is_orin = true;
|
} else if (pdev_data->pri_emac_base_addr == T234_MGBE2_BASE_ADDR) {
|
||||||
|
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
||||||
/* set default seconday interface for ptp timestamp */
|
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
||||||
if (pdev_data->sec_iface_nm == NULL) {
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_MGBE2;
|
||||||
pdev_data->sec_iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
} else if (pdev_data->pri_emac_base_addr == T234_MGBE3_BASE_ADDR) {
|
||||||
}
|
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
||||||
|
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
||||||
if (pdev_data->memmap_phc_regs) {
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_MGBE3;
|
||||||
/* TODO: Add support to map secondary interfaces PHC registers */
|
} else if (pdev_data->pri_emac_base_addr == T234_EQOS_BASE_ADDR) {
|
||||||
dev_info(&pdev->dev, "using mem mapped MAC PHC reg method\n");
|
pdev_data->sts_offset = EQOS_STSR_OFFSET;
|
||||||
if (pdev_data->iface_nm == NULL) {
|
pdev_data->stns_offset = EQOS_STNSR_OFFSET;
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_EQOS;
|
||||||
dev_warn(&pdev->dev, "interface property not provided. Using default interface(%s)\n", pdev_data->iface_nm);
|
} else if (pdev_data->pri_emac_base_addr == T194_EQOS_BASE_ADDR) {
|
||||||
use_eqos_mac = true;
|
pdev_data->sts_offset = EQOS_STSR_OFFSET;
|
||||||
} else {
|
pdev_data->stns_offset = EQOS_STNSR_OFFSET;
|
||||||
if (!strncmp(pdev_data->iface_nm, "eqos_0", sizeof("eqos_0"))) {
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_EQOS;
|
||||||
use_eqos_mac = true;
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe0_0", sizeof("mgbe0_0"))) {
|
|
||||||
/* remap base address for mgbe0_0 */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T234_MGBE0_BASE_ADDR, SZ_4K);
|
|
||||||
dev_info(&pdev->dev, "map MGBE0_0 to (%p)\n", pdev_data->mac_base_addr);
|
|
||||||
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
|
||||||
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe1_0", sizeof("mgbe1_0"))) {
|
|
||||||
/* remap base address for mgbe1_0 */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T234_MGBE1_BASE_ADDR, SZ_4K);
|
|
||||||
dev_info(&pdev->dev, "map MGBE1_0 to (%p)\n", pdev_data->mac_base_addr);
|
|
||||||
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
|
||||||
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe2_0", sizeof("mgbe2_0"))) {
|
|
||||||
/* remap base address for mgbe2_0 */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T234_MGBE2_BASE_ADDR, SZ_4K);
|
|
||||||
dev_info(&pdev->dev, "map MGBE2_0 to (%p)\n", pdev_data->mac_base_addr);
|
|
||||||
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
|
||||||
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe3_0", sizeof("mgbe3_0"))) {
|
|
||||||
/* remap base address for mgbe3_0 */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T234_MGBE3_BASE_ADDR, SZ_4K);
|
|
||||||
dev_info(&pdev->dev, "map MGBE3_0 to (%p)\n", pdev_data->mac_base_addr);
|
|
||||||
pdev_data->sts_offset = MGBE_STSR_OFFSET;
|
|
||||||
pdev_data->stns_offset = MGBE_STNSR_OFFSET;
|
|
||||||
} else {
|
|
||||||
dev_warn(&pdev->dev, "Invalid interface(%s). Using default interface(eqos_0)\n", pdev_data->iface_nm);
|
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
|
||||||
use_eqos_mac = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_eqos_mac) {
|
|
||||||
/* remap base address for eqos */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T234_EQOS_BASE_ADDR, SZ_4K);
|
|
||||||
dev_info(&pdev->dev, "map EQOS to (%p)\n", pdev_data->mac_base_addr);
|
|
||||||
pdev_data->sts_offset = EQOS_STSR_OFFSET;
|
|
||||||
pdev_data->stns_offset = EQOS_STNSR_OFFSET;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Using ptp-notifier method */
|
|
||||||
if (pdev_data->iface_nm) {
|
|
||||||
if ((!strncmp(pdev_data->iface_nm, "eqos_0", sizeof("eqos_0"))) ||
|
|
||||||
(!strncmp(pdev_data->iface_nm, "mgbe0_0", sizeof("mgbe0_0"))) ||
|
|
||||||
(!strncmp(pdev_data->iface_nm, "mgbe1_0", sizeof("mgbe1_0"))) ||
|
|
||||||
(!strncmp(pdev_data->iface_nm, "mgbe2_0", sizeof("mgbe2_0"))) ||
|
|
||||||
(!strncmp(pdev_data->iface_nm, "mgbe3_0", sizeof("mgbe3_0")))) {
|
|
||||||
dev_info(&pdev->dev, "using ptp notifier method with interface(%s)\n", pdev_data->iface_nm);
|
|
||||||
} else {
|
|
||||||
dev_warn(&pdev->dev, "Invalid interface(%s). Using default interface(eqos_0)\n", pdev_data->iface_nm);
|
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
|
||||||
dev_info(&pdev->dev, "using ptp notifier method with interface(%s)\n", pdev_data->iface_nm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (pdev_data->memmap_phc_regs) {
|
pdev_data->tsc_ptp_src = TSC_PTP_SRC_INVALID;
|
||||||
if (!(pdev_data->iface_nm && (strncmp(pdev_data->iface_nm, "eqos_0", sizeof("eqos_0")) == 0))) {
|
dev_err(&pdev->dev, "Invalid EMAC base address\n");
|
||||||
dev_warn(&pdev->dev, "Invalid interface(%s). Using default interface(eqos_0)\n", pdev_data->iface_nm);
|
return;
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
}
|
||||||
}
|
|
||||||
|
/* Get default params from dt */
|
||||||
dev_info(&pdev->dev, "using mem mapped MAC PHC reg method with %s MAC\n", pdev_data->iface_nm);
|
memmap_phc_regs = of_property_read_bool(np, "memmap_phc_regs");
|
||||||
/* remap base address for eqos */
|
|
||||||
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, T194_EQOS_BASE_ADDR, SZ_4K);
|
if (memmap_phc_regs) {
|
||||||
dev_info(&pdev->dev, "map EQOS to (%p)\n", pdev_data->mac_base_addr);
|
/* TODO: Add support to map secondary interfaces PHC registers */
|
||||||
pdev_data->sts_offset = EQOS_STSR_OFFSET;
|
pdev_data->mac_base_addr = devm_ioremap(&pdev->dev, pdev_data->pri_emac_base_addr,
|
||||||
pdev_data->stns_offset = EQOS_STNSR_OFFSET;
|
SZ_4K);
|
||||||
} else {
|
if (pdev_data->mac_base_addr == NULL) {
|
||||||
pdev_data->iface_nm = devm_kstrdup(&pdev->dev, "eqos_0", GFP_KERNEL);
|
dev_err(&pdev->dev, "failed to ioremap emac base address 0x%llx\n",
|
||||||
dev_info(&pdev->dev, "using ptp notifier method with default interface(%s)\n", pdev_data->iface_nm);
|
pdev_data->pri_emac_base_addr);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
dev_info(&pdev->dev, "using mem mapped MAC PHC reg method with emac %s\n",
|
||||||
|
pdev_data->pri_emac_node->full_name);
|
||||||
|
} else {
|
||||||
|
if (pdev_data->pri_emac_node != NULL)
|
||||||
|
dev_info(&pdev->dev, "using ptp notifier method on emac %s\n",
|
||||||
|
pdev_data->pri_emac_node->full_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface_name = devm_kstrdup(&pdev->dev, pdev_data->iface_nm, GFP_KERNEL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nvpps_gpio_hte_setup(struct nvpps_device_data *pdev_data)
|
static int nvpps_gpio_hte_setup(struct nvpps_device_data *pdev_data)
|
||||||
@@ -875,7 +833,7 @@ static int nvpps_gpio_hte_setup(struct nvpps_device_data *pdev_data)
|
|||||||
pdev_data->use_gpio_int_timestamp = false;
|
pdev_data->use_gpio_int_timestamp = false;
|
||||||
pdev_data->gpio_in = devm_gpiod_get_optional(&pdev->dev, "nvpps", 0);
|
pdev_data->gpio_in = devm_gpiod_get_optional(&pdev->dev, "nvpps", 0);
|
||||||
if (!pdev_data->gpio_in) {
|
if (!pdev_data->gpio_in) {
|
||||||
dev_warn(&pdev->dev, "PPS GPIO not provided in DT, only Timer mode available\n");
|
dev_info(&pdev->dev, "PPS GPIO not provided in DT, only Timer mode available\n");
|
||||||
pdev_data->only_timer_mode = true;
|
pdev_data->only_timer_mode = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -963,26 +921,15 @@ static void nvpps_ptp_tsc_sync_config(struct platform_device *pdev)
|
|||||||
writel(0x313, pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
writel(0x313, pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
||||||
writel(0x1, pdev_data->tsc_reg_map_base + TSC_STSCRSR_OFFSET);
|
writel(0x1, pdev_data->tsc_reg_map_base + TSC_STSCRSR_OFFSET);
|
||||||
|
|
||||||
//Select PTP src for TSC to lock on based on nw interface
|
|
||||||
if (!strncmp(pdev_data->iface_nm, "mgbe0_0", sizeof("mgbe0_0"))) {
|
|
||||||
pdev_data->tsc_ptp_src = (TSC_PTP_SRC_MGBE0 << SRC_SELECT_BIT_OFFSET);
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe1_0", sizeof("mgbe1_0"))) {
|
|
||||||
pdev_data->tsc_ptp_src = (TSC_PTP_SRC_MGBE1 << SRC_SELECT_BIT_OFFSET);
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe2_0", sizeof("mgbe2_0"))) {
|
|
||||||
pdev_data->tsc_ptp_src = (TSC_PTP_SRC_MGBE2 << SRC_SELECT_BIT_OFFSET);
|
|
||||||
} else if (!strncmp(pdev_data->iface_nm, "mgbe3_0", sizeof("mgbe3_0"))) {
|
|
||||||
pdev_data->tsc_ptp_src = (TSC_PTP_SRC_MGBE3 << SRC_SELECT_BIT_OFFSET);
|
|
||||||
} else {
|
|
||||||
pdev_data->tsc_ptp_src = (TSC_PTP_SRC_EQOS << SRC_SELECT_BIT_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
tsc_config_ptx_0 = readl(pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
tsc_config_ptx_0 = readl(pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
||||||
/* clear and set the ptp src based on ethernet interface passed
|
/* clear and set the ptp src based on ethernet interface passed
|
||||||
* from dt for tsc to lock onto.
|
* from dt for tsc to lock onto.
|
||||||
*/
|
*/
|
||||||
tsc_config_ptx_0 = tsc_config_ptx_0 &
|
tsc_config_ptx_0 = tsc_config_ptx_0 &
|
||||||
~(SRC_SELECT_BITS << SRC_SELECT_BIT_OFFSET);
|
~(SRC_SELECT_BITS << SRC_SELECT_BIT_OFFSET);
|
||||||
tsc_config_ptx_0 = tsc_config_ptx_0 | pdev_data->tsc_ptp_src;
|
if (pdev_data->tsc_ptp_src != TSC_PTP_SRC_INVALID)
|
||||||
|
tsc_config_ptx_0 = tsc_config_ptx_0 |
|
||||||
|
(pdev_data->tsc_ptp_src << SRC_SELECT_BIT_OFFSET);
|
||||||
writel(tsc_config_ptx_0, pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
writel(tsc_config_ptx_0, pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
||||||
tsc_config_ptx_0 = readl(pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
tsc_config_ptx_0 = readl(pdev_data->tsc_reg_map_base + TSC_CAPTURE_CONFIGURATION_PTX_OFFSET);
|
||||||
dev_info(&pdev->dev, "TSC config ptx 0x%x\n", tsc_config_ptx_0);
|
dev_info(&pdev->dev, "TSC config ptx 0x%x\n", tsc_config_ptx_0);
|
||||||
@@ -998,6 +945,9 @@ static int nvpps_probe(struct platform_device *pdev)
|
|||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
dev_t devt;
|
dev_t devt;
|
||||||
int err;
|
int err;
|
||||||
|
const struct tegra_chip_data *cdata = NULL;
|
||||||
|
struct resource res;
|
||||||
|
int index;
|
||||||
|
|
||||||
dev_info(&pdev->dev, "%s\n", __FUNCTION__);
|
dev_info(&pdev->dev, "%s\n", __FUNCTION__);
|
||||||
|
|
||||||
@@ -1011,6 +961,37 @@ static int nvpps_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emac_node = NULL;
|
||||||
|
|
||||||
|
pdev_data->pri_emac_node = of_parse_phandle(np, "primary-emac", 0);
|
||||||
|
if (pdev_data->pri_emac_node == NULL) {
|
||||||
|
dev_info(&pdev->dev, "primary-emac node not found\n");
|
||||||
|
} else {
|
||||||
|
dev_info(&pdev->dev, "primary-emac found %s", pdev_data->pri_emac_node->full_name);
|
||||||
|
index = of_property_match_string(pdev_data->pri_emac_node, "reg-names", "mac");
|
||||||
|
if (index >= 0) {
|
||||||
|
if (of_address_to_resource(pdev_data->pri_emac_node, index, &res)) {
|
||||||
|
dev_err(&pdev->dev, "failed to parse primary emac reg property\n");
|
||||||
|
} else {
|
||||||
|
pdev_data->pri_emac_base_addr = res.start;
|
||||||
|
dev_info(&pdev->dev, "primary emac base address 0x%llx\n",
|
||||||
|
pdev_data->pri_emac_base_addr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev_info(&pdev->dev, "failed to find ethernet mac registers\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emac_node = pdev_data->pri_emac_node;
|
||||||
|
pdev_data->sec_emac_node = of_parse_phandle(np, "sec-emac", 0);
|
||||||
|
if (pdev_data->sec_emac_node == NULL) {
|
||||||
|
dev_info(&pdev->dev, "sec-emac node not found\n");
|
||||||
|
pdev_data->sec_emac_node = pdev_data->pri_emac_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdata = of_device_get_match_data(&pdev->dev);
|
||||||
|
pdev_data->support_tsc = cdata->support_tsc;
|
||||||
|
|
||||||
nvpps_fill_default_mac_phc_info(pdev, pdev_data);
|
nvpps_fill_default_mac_phc_info(pdev, pdev_data);
|
||||||
|
|
||||||
init_waitqueue_head(&pdev_data->pps_event_queue);
|
init_waitqueue_head(&pdev_data->pps_event_queue);
|
||||||
@@ -1100,7 +1081,7 @@ static int nvpps_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
pdev_data->evt_mode = (pdev_data->only_timer_mode) ? NVPPS_MODE_TIMER : NVPPS_MODE_GPIO;
|
pdev_data->evt_mode = (pdev_data->only_timer_mode) ? NVPPS_MODE_TIMER : NVPPS_MODE_GPIO;
|
||||||
|
|
||||||
if (pdev_data->platform_is_orin) {
|
if (pdev_data->support_tsc) {
|
||||||
struct resource *tsc_mem;
|
struct resource *tsc_mem;
|
||||||
|
|
||||||
tsc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
tsc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
@@ -1130,6 +1111,8 @@ static int nvpps_probe(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_ret:
|
error_ret:
|
||||||
|
of_node_put(pdev_data->pri_emac_node);
|
||||||
|
of_node_put(pdev_data->sec_emac_node);
|
||||||
cdev_del(&pdev_data->cdev);
|
cdev_del(&pdev_data->cdev);
|
||||||
mutex_lock(&s_nvpps_lock);
|
mutex_lock(&s_nvpps_lock);
|
||||||
idr_remove(&s_nvpps_idr, pdev_data->id);
|
idr_remove(&s_nvpps_idr, pdev_data->id);
|
||||||
@@ -1149,18 +1132,21 @@ static int nvpps_remove(struct platform_device *pdev)
|
|||||||
pdev_data->timer_inited = false;
|
pdev_data->timer_inited = false;
|
||||||
del_timer_sync(&pdev_data->timer);
|
del_timer_sync(&pdev_data->timer);
|
||||||
}
|
}
|
||||||
if (pdev_data->memmap_phc_regs) {
|
if (pdev_data->mac_base_addr) {
|
||||||
devm_iounmap(&pdev->dev, pdev_data->mac_base_addr);
|
devm_iounmap(&pdev->dev, pdev_data->mac_base_addr);
|
||||||
dev_info(&pdev->dev, "unmap MAC reg space %p for nvpps\n",
|
dev_info(&pdev->dev, "unmap MAC reg space %p for nvpps\n",
|
||||||
pdev_data->mac_base_addr);
|
pdev_data->mac_base_addr);
|
||||||
}
|
}
|
||||||
if (pdev_data->platform_is_orin) {
|
if (pdev_data->support_tsc) {
|
||||||
del_timer_sync(&pdev_data->tsc_timer);
|
del_timer_sync(&pdev_data->tsc_timer);
|
||||||
iounmap(pdev_data->tsc_reg_map_base);
|
iounmap(pdev_data->tsc_reg_map_base);
|
||||||
}
|
}
|
||||||
device_destroy(s_nvpps_class, pdev_data->dev->devt);
|
device_destroy(s_nvpps_class, pdev_data->dev->devt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
of_node_put(pdev_data->pri_emac_node);
|
||||||
|
of_node_put(pdev_data->sec_emac_node);
|
||||||
|
|
||||||
#ifndef NVPPS_NO_DT
|
#ifndef NVPPS_NO_DT
|
||||||
class_unregister(s_nvpps_class);
|
class_unregister(s_nvpps_class);
|
||||||
class_destroy(s_nvpps_class);
|
class_destroy(s_nvpps_class);
|
||||||
@@ -1188,8 +1174,15 @@ static int nvpps_resume(struct platform_device *pdev)
|
|||||||
|
|
||||||
|
|
||||||
#ifndef NVPPS_NO_DT
|
#ifndef NVPPS_NO_DT
|
||||||
|
static const struct tegra_chip_data tegra234_chip_data = {
|
||||||
|
.support_tsc = true,
|
||||||
|
};
|
||||||
|
static const struct tegra_chip_data tegra194_chip_data = {
|
||||||
|
.support_tsc = false,
|
||||||
|
};
|
||||||
static const struct of_device_id nvpps_of_table[] = {
|
static const struct of_device_id nvpps_of_table[] = {
|
||||||
{ .compatible = "nvidia,tegra194-nvpps", },
|
{ .compatible = "nvidia,tegra194-nvpps", .data = &tegra194_chip_data },
|
||||||
|
{ .compatible = "nvidia,tegra234-nvpps", .data = &tegra234_chip_data },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, nvpps_of_table);
|
MODULE_DEVICE_TABLE(of, nvpps_of_table);
|
||||||
@@ -1269,4 +1262,4 @@ module_platform_driver(nvpps_plat_driver);
|
|||||||
|
|
||||||
MODULE_DESCRIPTION("NVidia Tegra PPS Driver");
|
MODULE_DESCRIPTION("NVidia Tegra PPS Driver");
|
||||||
MODULE_AUTHOR("David Tao tehyut@nvidia.com");
|
MODULE_AUTHOR("David Tao tehyut@nvidia.com");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/platform/tegra/ptp-notifier.h>
|
#include <linux/platform/tegra/ptp-notifier.h>
|
||||||
|
|
||||||
static int (*get_systime[MAX_MAC_INSTANCES])(struct net_device *, void *, int);
|
static int (*get_systime[MAX_MAC_INSTANCES])(struct net_device *, void *, int);
|
||||||
@@ -91,47 +91,65 @@ void tegra_unregister_hwtime_source(struct net_device *dev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_unregister_hwtime_source);
|
EXPORT_SYMBOL(tegra_unregister_hwtime_source);
|
||||||
|
|
||||||
int tegra_get_hwtime(const char *intf_name, void *ts, int ts_type)
|
int tegra_get_hwtime(const struct device_node *emac_node, void *ts, int ts_type)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0, index = 0;
|
int ret = 0, index = 0;
|
||||||
struct net_device *dev;
|
struct net_device *dev = NULL;
|
||||||
|
struct net_device *intf_dev = NULL;
|
||||||
|
const char *intf_name = "eth0";
|
||||||
|
|
||||||
|
if (!ts) {
|
||||||
|
pr_err("%s: time-stamp ptr is NULL\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emac_node == NULL) {
|
||||||
|
pr_debug("EMAC node is invalid, using default interface %s\n", intf_name);
|
||||||
|
intf_dev = dev_get_by_name(&init_net, intf_name);
|
||||||
|
if (!intf_dev || !(intf_dev->flags & IFF_UP)) {
|
||||||
|
pr_debug("Network interface %s is not %s", intf_name,
|
||||||
|
!intf_dev ? "found":"up");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ptp_notifier_lock, flags);
|
raw_spin_lock_irqsave(&ptp_notifier_lock, flags);
|
||||||
if (!intf_name || !ts) {
|
|
||||||
pr_err("passed Interface_name or time-stamp ptr is NULL");
|
|
||||||
raw_spin_unlock_irqrestore(&ptp_notifier_lock, flags);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
dev = dev_get_by_name(&init_net, intf_name);
|
|
||||||
|
|
||||||
if (!dev || !(dev->flags & IFF_UP)) {
|
|
||||||
pr_debug("dev is NULL or intf is not up for %s\n", intf_name);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
for (index = 0; index < MAX_MAC_INSTANCES; index++) {
|
for (index = 0; index < MAX_MAC_INSTANCES; index++) {
|
||||||
if (dev == registered_ndev[index])
|
dev = registered_ndev[index];
|
||||||
|
if (dev == NULL) {
|
||||||
|
pr_debug("No registered net device for index %d\n", index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (emac_node == dev->dev.parent->of_node) {
|
||||||
|
pr_debug("found emac name (%s)\n", emac_node->full_name);
|
||||||
break;
|
break;
|
||||||
|
} else if (intf_dev && intf_dev == dev) {
|
||||||
|
pr_debug("found ethenet interface (%s)\n", intf_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (index == MAX_MAC_INSTANCES) {
|
if (index == MAX_MAC_INSTANCES) {
|
||||||
pr_debug("Interface: %s is not registered to get HW time", intf_name);
|
pr_debug("%s: ethernet device %s is not registered!\n", __func__,
|
||||||
|
!emac_node ? intf_name : emac_node->full_name);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_systime[index])
|
if (get_systime[index])
|
||||||
ret = (get_systime[index])(dev, ts, ts_type);
|
ret = (get_systime[index])(dev, ts, ts_type);
|
||||||
else
|
else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
unlock:
|
||||||
out:
|
|
||||||
if (dev)
|
|
||||||
dev_put(dev);
|
|
||||||
raw_spin_unlock_irqrestore(&ptp_notifier_lock, flags);
|
raw_spin_unlock_irqrestore(&ptp_notifier_lock, flags);
|
||||||
|
out:
|
||||||
|
if (intf_dev)
|
||||||
|
dev_put(intf_dev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_get_hwtime);
|
EXPORT_SYMBOL(tegra_get_hwtime);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __PTP_NOTIFIER_H
|
#ifndef __PTP_NOTIFIER_H
|
||||||
#define __PTP_NOTIFIER_H
|
#define __PTP_NOTIFIER_H
|
||||||
@@ -45,6 +43,7 @@ int tegra_hwtime_notifier_call_chain(unsigned int val, void *v);
|
|||||||
* Clients may call the API every anytime PTP/TSC time is needed.
|
* Clients may call the API every anytime PTP/TSC time is needed.
|
||||||
* If HW time source is not registered, returns -EINVAL
|
* If HW time source is not registered, returns -EINVAL
|
||||||
*/
|
*/
|
||||||
int tegra_get_hwtime(const char *intf_name, void *ts, int ts_type);
|
int tegra_get_hwtime(const struct device_node *emac_node, void *ts, int ts_type);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __PTP_NOTIFIER_H */
|
#endif /* __PTP_NOTIFIER_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user