6060#define  TIMER_CONF_FSB_EN 		BIT(14) /* FSB interrupt delivery   */ 
6161						/* enable                   */ 
6262
63- /* 
64-  * The following MMIO initialization and register access functions 
65-  * should work on generic x86 hardware. If the targeted SoC requires 
66-  * special handling of HPET registers, these functions will need to be 
67-  * implemented in the SoC layer by first defining the macro 
68-  * HPET_USE_CUSTOM_REG_ACCESS_FUNCS in soc.h to signal such intent. 
69-  * 
70-  * This is a list of functions which must be implemented in the SoC 
71-  * layer: 
72-  *   void hpet_mmio_init(void) 
73-  *   uint32_t hpet_counter_get(void) 
74-  *   uint32_t hpet_counter_clk_period_get(void) 
75-  *   uint32_t hpet_gconf_get(void) 
76-  *   void hpet_gconf_set(uint32_t val) 
77-  *   void hpet_int_sts_set(uint32_t val) 
78-  *   uint32_t hpet_timer_conf_get(void) 
79-  *   void hpet_timer_conf_set(uint32_t val) 
80-  *   void hpet_timer_comparator_set(uint32_t val) 
81-  */ 
82- #ifndef  HPET_USE_CUSTOM_REG_ACCESS_FUNCS 
8363DEVICE_MMIO_TOPLEVEL_STATIC (hpet_regs , DT_DRV_INST (0 ));
8464
8565#define  HPET_REG_ADDR (off )			\
@@ -105,17 +85,6 @@ DEVICE_MMIO_TOPLEVEL_STATIC(hpet_regs, DT_DRV_INST(0));
10585#define  TIMER0_COMPARATOR_LOW_REG 	HPET_REG_ADDR(0x108)
10686#define  TIMER0_COMPARATOR_HIGH_REG 	HPET_REG_ADDR(0x10c)
10787
108- /** 
109-  * @brief Setup memory mappings needed to access HPET registers. 
110-  * 
111-  * This is called in sys_clock_driver_init() to setup any memory 
112-  * mappings needed to access HPET registers. 
113-  */ 
114- static  inline  void  hpet_mmio_init (void )
115- {
116- 	DEVICE_MMIO_TOPLEVEL_MAP (hpet_regs , K_MEM_CACHE_NONE );
117- }
118- 
11988/** 
12089 * @brief Return the value of the main counter. 
12190 * 
@@ -210,6 +179,19 @@ static inline void hpet_timer_conf_set(uint32_t val)
210179	sys_write32 (val , TIMER0_CONF_REG );
211180}
212181
182+ /* 
183+  * The following register access functions should work on generic x86 
184+  * hardware. If the targeted SoC requires special handling of HPET 
185+  * registers, these functions will need to be implemented in the SoC 
186+  * layer by first defining the macro HPET_USE_CUSTOM_REG_ACCESS_FUNCS 
187+  * in soc.h to signal such intent. 
188+  * 
189+  * This is a list of functions which must be implemented in the SoC 
190+  * layer: 
191+  *   void hpet_timer_comparator_set(uint32_t val) 
192+  */ 
193+ #ifndef  HPET_USE_CUSTOM_REG_ACCESS_FUNCS 
194+ 
213195/** 
214196 * @brief Write to the Timer Comparator Value Register 
215197 * 
@@ -239,6 +221,21 @@ static inline void hpet_timer_comparator_set(uint64_t val)
239221#define  HPET_CMP_MIN_DELAY 		(1000)
240222#endif 
241223
224+ /* 
225+  * HPET_INT_LEVEL_TRIGGER is used to set HPET interrupt as level trigger 
226+  * for ARM CPU with NVIC like EHL PSE, whose DTS interrupt setting 
227+  * has no "sense" cell. 
228+  */ 
229+ #if  (DT_INST_IRQ_HAS_CELL (0 , sense ))
230+ #ifdef  HPET_INT_LEVEL_TRIGGER 
231+ __WARN ("HPET_INT_LEVEL_TRIGGER has no effect, DTS setting is used instead" )
232+ #undef  HPET_INT_LEVEL_TRIGGER
233+ #endif 
234+ #if  ((DT_INST_IRQ (0 , sense ) &  IRQ_TYPE_LEVEL ) ==  IRQ_TYPE_LEVEL )
235+ #define  HPET_INT_LEVEL_TRIGGER 
236+ #endif 
237+ #endif  /* (DT_INST_IRQ_HAS_CELL(0, sense)) */ 
238+ 
242239static  __pinned_bss  struct  k_spinlock  lock ;
243240static  __pinned_bss  uint64_t  last_count ;
244241
@@ -260,7 +257,7 @@ static void hpet_isr(const void *arg)
260257
261258	uint64_t  now  =  hpet_counter_get ();
262259
263- #if   (( DT_INST_IRQ ( 0 ,  sense )  &   IRQ_TYPE_LEVEL )  ==   IRQ_TYPE_LEVEL ) 
260+ #ifdef    HPET_INT_LEVEL_TRIGGER 
264261	/* 
265262	 * Clear interrupt only if level trigger is selected. 
266263	 * When edge trigger is selected, spec says only 0 can 
@@ -300,18 +297,22 @@ static void hpet_isr(const void *arg)
300297}
301298
302299__pinned_func 
303- static  void  set_timer0_irq (unsigned int   irq )
300+ static  void  config_timer0 (unsigned int   irq )
304301{
305302	uint32_t  val  =  hpet_timer_conf_get ();
306303
307304	/* 5-bit IRQ field starting at bit 9 */ 
308305	val  =  (val  &  ~(0x1f  << 9 )) | ((irq  &  0x1f ) << 9 );
309306
310- #if   (( DT_INST_IRQ ( 0 ,  sense )  &   IRQ_TYPE_LEVEL )  ==   IRQ_TYPE_LEVEL ) 
311- 	/* Level  trigger */ 
307+ #ifdef    HPET_INT_LEVEL_TRIGGER 
308+ 	/* Set level  trigger if selected  */ 
312309	val  |= TIMER_CONF_INT_LEVEL ;
313310#endif 
314311
312+ 	val  &=  ~((uint32_t )(TIMER_CONF_MODE32  | TIMER_CONF_PERIODIC  |
313+ 			TIMER_CONF_FSB_EN ));
314+ 	val  |= TIMER_CONF_INT_ENABLE ;
315+ 
315316	hpet_timer_conf_set (val );
316317}
317318
@@ -325,12 +326,18 @@ int sys_clock_driver_init(const struct device *dev)
325326	ARG_UNUSED (hz );
326327	ARG_UNUSED (z_clock_hw_cycles_per_sec );
327328
328- 	hpet_mmio_init ( );
329+ 	DEVICE_MMIO_TOPLEVEL_MAP ( hpet_regs ,  K_MEM_CACHE_NONE );
329330
331+ #if  DT_INST_IRQ_HAS_CELL (0 , sense )
330332	IRQ_CONNECT (DT_INST_IRQN (0 ),
331333		    DT_INST_IRQ (0 , priority ),
332334		    hpet_isr , 0 , DT_INST_IRQ (0 , sense ));
333- 	set_timer0_irq (DT_INST_IRQN (0 ));
335+ #else 
336+ 	IRQ_CONNECT (DT_INST_IRQN (0 ),
337+ 		    DT_INST_IRQ (0 , priority ),
338+ 		    hpet_isr , 0 , 0 );
339+ #endif 
340+ 	config_timer0 (DT_INST_IRQN (0 ));
334341	irq_enable (DT_INST_IRQN (0 ));
335342
336343#ifdef  CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME 
@@ -349,13 +356,6 @@ int sys_clock_driver_init(const struct device *dev)
349356	reg  |= GCONF_LR  | GCONF_ENABLE ;
350357	hpet_gconf_set (reg );
351358
352- 	reg  =  hpet_timer_conf_get ();
353- 	reg  &= ~TIMER_CONF_PERIODIC ;
354- 	reg  &= ~TIMER_CONF_FSB_EN ;
355- 	reg  &= ~TIMER_CONF_MODE32 ;
356- 	reg  |= TIMER_CONF_INT_ENABLE ;
357- 	hpet_timer_conf_set (reg );
358- 
359359	last_count  =  hpet_counter_get ();
360360	if  (cyc_per_tick  >= HPET_CMP_MIN_DELAY ) {
361361		hpet_timer_comparator_set (last_count  +  cyc_per_tick );
0 commit comments