Skip to content

Commit 924bd06

Browse files
drivers: ptp_clock: Add NXP NETC PTP Clock Driver
Add Driver for NXP NETC PTP Clock device Signed-off-by: Qiang Zhao <[email protected]>
1 parent 3934461 commit 924bd06

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed

drivers/ptp_clock/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ zephyr_library()
66

77
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK ptp_clock.c)
88
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK_NXP_ENET ptp_clock_nxp_enet.c)
9+
zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK_NXP_NETC ptp_clock_nxp_netc.c)

drivers/ptp_clock/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ menuconfig PTP_CLOCK
99
if PTP_CLOCK
1010

1111
source "drivers/ptp_clock/Kconfig.nxp_enet"
12+
source "drivers/ptp_clock/Kconfig.nxp_netc"
1213

1314
config PTP_CLOCK_INIT_PRIORITY
1415
int "Init priority"

drivers/ptp_clock/Kconfig.nxp_netc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright 2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config PTP_CLOCK_NXP_NETC
5+
bool "NXP NETC PTP Clock driver"
6+
default y
7+
depends on DT_HAS_NXP_NETC_PTP_CLOCK_ENABLED
8+
depends on ETH_NXP_IMX_NETC
9+
help
10+
Enable NXP NETC PTP clock support.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT nxp_netc_ptp_clock
8+
9+
#include <zephyr/drivers/ptp_clock.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/device.h>
12+
#include <zephyr/drivers/clock_control.h>
13+
#include <zephyr/drivers/pinctrl.h>
14+
15+
#include <fsl_netc_timer.h>
16+
17+
struct ptp_clock_nxp_netc_config {
18+
const struct device *port;
19+
const struct device *clock_dev;
20+
clock_control_subsys_t clock_subsys;
21+
};
22+
23+
struct ptp_clock_nxp_netc_data {
24+
NETC_ENETC_Type *base;
25+
netc_timer_handle_t netc_handle;
26+
struct k_mutex ptp_mutex;
27+
netc_timer_config_t ptp_config;
28+
};
29+
30+
static int ptp_clock_nxp_netc_set(const struct device *dev,
31+
struct net_ptp_time *tm)
32+
{
33+
struct ptp_clock_nxp_netc_data *data = dev->data;
34+
uint64_t nanosecond;
35+
int key;
36+
37+
nanosecond = tm->second * NSEC_PER_SEC + tm->nanosecond;
38+
39+
key = irq_lock();
40+
data->netc_handle.hw.base->TMR_CNT_L = (uint32_t)nanosecond;
41+
data->netc_handle.hw.base->TMR_CNT_H = (uint32_t)(nanosecond >> 32U);
42+
data->netc_handle.hw.base->TMROFF_L = 0U;
43+
data->netc_handle.hw.base->TMROFF_H = 0U;
44+
irq_unlock(key);
45+
46+
return 0;
47+
}
48+
49+
static int ptp_clock_nxp_netc_get(const struct device *dev,
50+
struct net_ptp_time *tm)
51+
{
52+
struct ptp_clock_nxp_netc_data *data = dev->data;
53+
uint64_t nanosecond;
54+
55+
NETC_TimerGetCurrentTime(&data->netc_handle, &nanosecond);
56+
57+
tm->second = nanosecond / NSEC_PER_SEC;
58+
tm->nanosecond = nanosecond % NSEC_PER_SEC;
59+
60+
return 0;
61+
}
62+
63+
static int ptp_clock_nxp_netc_adjust(const struct device *dev,
64+
int increment)
65+
{
66+
struct ptp_clock_nxp_netc_data *data = dev->data;
67+
int key;
68+
69+
key = irq_lock();
70+
NETC_TimerAddOffset(&data->netc_handle, (int64_t)increment * NSEC_PER_SEC);
71+
irq_unlock(key);
72+
73+
return 0;
74+
75+
}
76+
77+
static int ptp_clock_nxp_netc_rate_adjust(const struct device *dev,
78+
double ratio)
79+
{
80+
struct ptp_clock_nxp_netc_data *data = dev->data;
81+
netc_timer_config_t *ptp_config = &data->ptp_config;
82+
83+
ptp_config->defaultPpb = (ratio - 1.0) * 1000000000LL;
84+
85+
k_mutex_lock(&data->ptp_mutex, K_FOREVER);
86+
87+
NETC_TimerAdjustFreq(&data->netc_handle, ptp_config->defaultPpb);
88+
89+
k_mutex_unlock(&data->ptp_mutex);
90+
91+
return 0;
92+
}
93+
94+
static int ptp_clock_nxp_netc_init(const struct device *port)
95+
{
96+
const struct ptp_clock_nxp_netc_config *config = port->config;
97+
struct ptp_clock_nxp_netc_data *data = port->data;
98+
netc_timer_config_t *ptp_config = &data->ptp_config;
99+
uint32_t netc_ref_pll_rate;
100+
int ret = 0;
101+
102+
ret = clock_control_get_rate(config->clock_dev, config->clock_subsys, &netc_ref_pll_rate);
103+
if (ret) {
104+
return ret;
105+
}
106+
ptp_config->refClkHz = netc_ref_pll_rate/2;
107+
ptp_config->entryNum = 0U;
108+
ptp_config->defaultPpb = 0U;
109+
ptp_config->clockSelect = kNETC_TimerSystemClk;
110+
111+
k_mutex_init(&data->ptp_mutex);
112+
113+
ret = NETC_TimerInit(&data->netc_handle, ptp_config);
114+
if (ret != kStatus_Success) {
115+
return ret;
116+
}
117+
118+
NETC_TimerEnable(&data->netc_handle, true);
119+
120+
return ret;
121+
}
122+
123+
124+
static DEVICE_API(ptp_clock, ptp_clock_nxp_netc_api) = {
125+
.set = ptp_clock_nxp_netc_set,
126+
.get = ptp_clock_nxp_netc_get,
127+
.adjust = ptp_clock_nxp_netc_adjust,
128+
.rate_adjust = ptp_clock_nxp_netc_rate_adjust,
129+
};
130+
131+
#define PTP_CLOCK_NXP_NETC_INIT(n) \
132+
static const struct ptp_clock_nxp_netc_config \
133+
ptp_clock_nxp_netc_##n##_config = { \
134+
.port = DEVICE_DT_INST_GET(n), \
135+
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
136+
.clock_subsys = (clock_control_subsys_t) \
137+
DT_INST_CLOCKS_CELL(n, name), \
138+
}; \
139+
\
140+
static struct ptp_clock_nxp_netc_data ptp_clock_nxp_netc_##n##_data; \
141+
\
142+
DEVICE_DT_INST_DEFINE(n, &ptp_clock_nxp_netc_init, NULL, \
143+
&ptp_clock_nxp_netc_##n##_data, \
144+
&ptp_clock_nxp_netc_##n##_config, \
145+
POST_KERNEL, CONFIG_PTP_CLOCK_INIT_PRIORITY, \
146+
&ptp_clock_nxp_netc_api);
147+
148+
DT_INST_FOREACH_STATUS_OKAY(PTP_CLOCK_NXP_NETC_INIT)

0 commit comments

Comments
 (0)