1010#include <zephyr/drivers/clock_control.h>
1111#include <zephyr/irq.h>
1212#include <zephyr/logging/log.h>
13+ #include <zephyr/sys/barrier.h>
1314
1415#include <fsl_tpm.h>
1516
1617LOG_MODULE_REGISTER (mcux_tpm , CONFIG_COUNTER_LOG_LEVEL );
1718
19+ struct mcux_tpm_channel_data {
20+ counter_alarm_callback_t alarm_callback ;
21+ void * alarm_user_data ;
22+ };
23+
1824#define DEV_CFG (_dev ) ((const struct mcux_tpm_config *)(_dev)->config)
1925#define DEV_DATA (_dev ) ((struct mcux_tpm_data *)(_dev)->data)
2026
@@ -33,10 +39,9 @@ struct mcux_tpm_config {
3339
3440struct mcux_tpm_data {
3541 DEVICE_MMIO_NAMED_RAM (tpm_mmio );
36- counter_alarm_callback_t alarm_callback ;
3742 counter_top_callback_t top_callback ;
3843 uint32_t freq ;
39- void * alarm_user_data ;
44+ struct mcux_tpm_channel_data channels [ TPM_CONTROLS_COUNT ] ;
4045 void * top_user_data ;
4146};
4247
@@ -82,11 +87,16 @@ static int mcux_tpm_set_alarm(const struct device *dev, uint8_t chan_id,
8287 struct mcux_tpm_data * data = dev -> data ;
8388 uint32_t ticks = alarm_cfg -> ticks ;
8489
85- if (chan_id != kTPM_Chnl_0 ) {
90+ if (chan_id >= DEV_CFG ( dev ) -> info . channels ) {
8691 LOG_ERR ("Invalid channel id" );
8792 return - EINVAL ;
8893 }
8994
95+ if (data -> channels [chan_id ].alarm_callback != NULL ) {
96+ LOG_ERR ("channel already in use" );
97+ return - EBUSY ;
98+ }
99+
90100 if (ticks > (top_value )) {
91101 return - EINVAL ;
92102 }
@@ -99,15 +109,11 @@ static int mcux_tpm_set_alarm(const struct device *dev, uint8_t chan_id,
99109 }
100110 }
101111
102- if (data -> alarm_callback ) {
103- return - EBUSY ;
104- }
112+ data -> channels [chan_id ].alarm_callback = alarm_cfg -> callback ;
113+ data -> channels [chan_id ].alarm_user_data = alarm_cfg -> user_data ;
105114
106- data -> alarm_callback = alarm_cfg -> callback ;
107- data -> alarm_user_data = alarm_cfg -> user_data ;
108-
109- TPM_SetupOutputCompare (base , kTPM_Chnl_0 , kTPM_NoOutputSignal , ticks );
110- TPM_EnableInterrupts (base , kTPM_Chnl0InterruptEnable );
115+ TPM_SetupOutputCompare (base , chan_id , kTPM_NoOutputSignal , ticks );
116+ TPM_EnableInterrupts (base , BIT (chan_id ));
111117
112118 return 0 ;
113119}
@@ -117,13 +123,14 @@ static int mcux_tpm_cancel_alarm(const struct device *dev, uint8_t chan_id)
117123 TPM_Type * base = get_base (dev );
118124 struct mcux_tpm_data * data = dev -> data ;
119125
120- if (chan_id != kTPM_Chnl_0 ) {
126+ if (chan_id >= DEV_CFG ( dev ) -> info . channels ) {
121127 LOG_ERR ("Invalid channel id" );
122128 return - EINVAL ;
123129 }
124130
125- TPM_DisableInterrupts (base , kTPM_Chnl0InterruptEnable );
126- data -> alarm_callback = NULL ;
131+ TPM_DisableInterrupts (base , BIT (chan_id ));
132+ data -> channels [chan_id ].alarm_callback = NULL ;
133+ data -> channels [chan_id ].alarm_user_data = NULL ;
127134
128135 return 0 ;
129136}
@@ -135,17 +142,20 @@ void mcux_tpm_isr(const struct device *dev)
135142 uint32_t current = TPM_GetCurrentTimerCount (base );
136143 uint32_t status ;
137144
138- status = TPM_GetStatusFlags (base ) & ( kTPM_Chnl0Flag | kTPM_TimeOverflowFlag );
145+ status = TPM_GetStatusFlags (base );
139146 TPM_ClearStatusFlags (base , status );
140147 barrier_dsync_fence_full ();
141148
142- if ((status & kTPM_Chnl0Flag ) && data -> alarm_callback ) {
143- TPM_DisableInterrupts (base ,
144- kTPM_Chnl0InterruptEnable );
145- counter_alarm_callback_t alarm_cb = data -> alarm_callback ;
149+ for (uint8_t chan = 0 ; chan < DEV_CFG (dev )-> info .channels ; chan ++ ) {
150+ if ((status & BIT (chan )) != 0 && (data -> channels [chan ].alarm_callback != NULL )) {
151+ counter_alarm_callback_t alarm_callback =
152+ data -> channels [chan ].alarm_callback ;
153+ void * alarm_user_data = data -> channels [chan ].alarm_user_data ;
146154
147- data -> alarm_callback = NULL ;
148- alarm_cb (dev , 0 , current , data -> alarm_user_data );
155+ data -> channels [chan ].alarm_callback = NULL ;
156+ data -> channels [chan ].alarm_user_data = NULL ;
157+ alarm_callback (dev , chan , current , alarm_user_data );
158+ }
149159 }
150160
151161 if ((status & kTPM_TimeOverflowFlag ) && data -> top_callback ) {
@@ -157,7 +167,7 @@ static uint32_t mcux_tpm_get_pending_int(const struct device *dev)
157167{
158168 TPM_Type * base = get_base (dev );
159169
160- return ( TPM_GetStatusFlags (base ) & kTPM_Chnl0Flag ) ;
170+ return TPM_GetStatusFlags (base ) ? 1 : 0 ;
161171}
162172
163173static int mcux_tpm_set_top_value (const struct device * dev ,
@@ -167,8 +177,10 @@ static int mcux_tpm_set_top_value(const struct device *dev,
167177 TPM_Type * base = get_base (dev );
168178 struct mcux_tpm_data * data = dev -> data ;
169179
170- if (data -> alarm_callback ) {
171- return - EBUSY ;
180+ for (uint8_t chan = 0 ; chan < config -> info .channels ; chan ++ ) {
181+ if (data -> channels [chan ].alarm_callback ) {
182+ return - EBUSY ;
183+ }
172184 }
173185
174186 /* Check if timer already enabled. */
@@ -228,6 +240,11 @@ static int mcux_tpm_init(const struct device *dev)
228240 return - ENODEV ;
229241 }
230242
243+ for (uint8_t chan = 0 ; chan < DEV_CFG (dev )-> info .channels ; chan ++ ) {
244+ data -> channels [chan ].alarm_callback = NULL ;
245+ data -> channels [chan ].alarm_user_data = NULL ;
246+ }
247+
231248 if (clock_control_on (config -> clock_dev , config -> clock_subsys )) {
232249 LOG_ERR ("Could not turn on clock" );
233250 return - EINVAL ;
@@ -282,7 +299,8 @@ static DEVICE_API(counter, mcux_tpm_driver_api) = {
282299 .info = { \
283300 .max_top_value = TPM_MAX_COUNTER_VALUE(TPM(n)), \
284301 .freq = 0, \
285- .channels = 1, \
302+ .channels = FSL_FEATURE_TPM_CHANNEL_COUNTn( \
303+ (TPM_Type *)DT_INST_REG_ADDR(n)), \
286304 .flags = COUNTER_CONFIG_INFO_COUNT_UP, \
287305 }, \
288306 .irq_config_func = mcux_tpm_irq_config_ ## n, \
0 commit comments