timer: hpet: enable level triggering
The HPET timer was hard-coded to support only edge triggering interrupts. This adds the necessary bits to enable level triggering for the timer. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
8ada29e06c
commit
afc1b9de13
1 changed files with 22 additions and 1 deletions
|
@ -10,11 +10,14 @@
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/interrupt-controller/intel-ioapic.h>
|
||||||
|
|
||||||
#define HPET_REG32(off) (*(volatile uint32_t *)(long) \
|
#define HPET_REG32(off) (*(volatile uint32_t *)(long) \
|
||||||
(DT_INST_REG_ADDR(0) + (off)))
|
(DT_INST_REG_ADDR(0) + (off)))
|
||||||
|
|
||||||
#define CLK_PERIOD_REG HPET_REG32(0x04) /* High dword of caps reg */
|
#define CLK_PERIOD_REG HPET_REG32(0x04) /* High dword of caps reg */
|
||||||
#define GENERAL_CONF_REG HPET_REG32(0x10)
|
#define GENERAL_CONF_REG HPET_REG32(0x10)
|
||||||
|
#define INTR_STATUS_REG HPET_REG32(0x20)
|
||||||
#define MAIN_COUNTER_REG HPET_REG32(0xf0)
|
#define MAIN_COUNTER_REG HPET_REG32(0xf0)
|
||||||
#define TIMER0_CONF_REG HPET_REG32(0x100)
|
#define TIMER0_CONF_REG HPET_REG32(0x100)
|
||||||
#define TIMER0_COMPARATOR_REG HPET_REG32(0x108)
|
#define TIMER0_COMPARATOR_REG HPET_REG32(0x108)
|
||||||
|
@ -23,7 +26,11 @@
|
||||||
#define GCONF_ENABLE BIT(0)
|
#define GCONF_ENABLE BIT(0)
|
||||||
#define GCONF_LR BIT(1) /* legacy interrupt routing, disables PIT */
|
#define GCONF_LR BIT(1) /* legacy interrupt routing, disables PIT */
|
||||||
|
|
||||||
|
/* INTR_STATUS_REG bits */
|
||||||
|
#define TIMER0_INT_STS BIT(0)
|
||||||
|
|
||||||
/* TIMERn_CONF_REG bits */
|
/* TIMERn_CONF_REG bits */
|
||||||
|
#define TCONF_INT_LEVEL BIT(1)
|
||||||
#define TCONF_INT_ENABLE BIT(2)
|
#define TCONF_INT_ENABLE BIT(2)
|
||||||
#define TCONF_PERIODIC BIT(3)
|
#define TCONF_PERIODIC BIT(3)
|
||||||
#define TCONF_VAL_SET BIT(6)
|
#define TCONF_VAL_SET BIT(6)
|
||||||
|
@ -49,6 +56,15 @@ static void hpet_isr(void *arg)
|
||||||
|
|
||||||
uint32_t now = MAIN_COUNTER_REG;
|
uint32_t now = MAIN_COUNTER_REG;
|
||||||
|
|
||||||
|
#if ((DT_INST_IRQ(0, sense) & IRQ_TYPE_LEVEL) == IRQ_TYPE_LEVEL)
|
||||||
|
/*
|
||||||
|
* Clear interrupt only if level trigger is selected.
|
||||||
|
* When edge trigger is selected, spec says only 0 can
|
||||||
|
* be written.
|
||||||
|
*/
|
||||||
|
INTR_STATUS_REG = TIMER0_INT_STS;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_SMP) &&
|
if (IS_ENABLED(CONFIG_SMP) &&
|
||||||
IS_ENABLED(CONFIG_QEMU_TARGET)) {
|
IS_ENABLED(CONFIG_QEMU_TARGET)) {
|
||||||
/* Qemu in SMP mode has observed the clock going
|
/* Qemu in SMP mode has observed the clock going
|
||||||
|
@ -89,6 +105,11 @@ static void set_timer0_irq(unsigned int irq)
|
||||||
/* 5-bit IRQ field starting at bit 9 */
|
/* 5-bit IRQ field starting at bit 9 */
|
||||||
uint32_t val = (TIMER0_CONF_REG & ~(0x1f << 9)) | ((irq & 0x1f) << 9);
|
uint32_t val = (TIMER0_CONF_REG & ~(0x1f << 9)) | ((irq & 0x1f) << 9);
|
||||||
|
|
||||||
|
#if ((DT_INST_IRQ(0, sense) & IRQ_TYPE_LEVEL) == IRQ_TYPE_LEVEL)
|
||||||
|
/* Level trigger */
|
||||||
|
val |= TCONF_INT_LEVEL;
|
||||||
|
#endif
|
||||||
|
|
||||||
TIMER0_CONF_REG = val;
|
TIMER0_CONF_REG = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +120,7 @@ int z_clock_driver_init(struct device *device)
|
||||||
|
|
||||||
IRQ_CONNECT(DT_INST_IRQN(0),
|
IRQ_CONNECT(DT_INST_IRQN(0),
|
||||||
DT_INST_IRQ(0, priority),
|
DT_INST_IRQ(0, priority),
|
||||||
hpet_isr, 0, 0);
|
hpet_isr, 0, DT_INST_IRQ(0, sense));
|
||||||
set_timer0_irq(DT_INST_IRQN(0));
|
set_timer0_irq(DT_INST_IRQN(0));
|
||||||
irq_enable(DT_INST_IRQN(0));
|
irq_enable(DT_INST_IRQN(0));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue