Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
qm_pic_timer.c
1 /*
2  * {% copyright %}
3  */
4 
5 #include "qm_pic_timer.h"
6 
7 /*
8  * PIC timer access layer. Supports both Local APIC timer and MVIC timer.
9  *
10  * The MVIC timer differs from the LAPIC specs in that:
11  * - it does not support TSC deadline mode
12  * - vector table lvttimer[3:0] holds the IRQ (not the vector) of the timer
13  */
14 
15 #define LVTTIMER_MODE_PERIODIC_OFFS (17)
16 #define LVTTIMER_INT_MASK_OFFS (16)
17 
18 static void (*callback)(void *data);
19 static void *callback_data;
20 
21 #if (HAS_APIC)
22 #define PIC_TIMER (QM_LAPIC)
23 #else
24 #define PIC_TIMER (QM_PIC_TIMER)
25 #endif
26 
27 QM_ISR_DECLARE(qm_pic_timer_0_isr)
28 {
29  if (callback) {
30  callback(callback_data);
31  }
32 
33 #if (HAS_APIC)
34  /* Use an invalid vector to avoid acknowledging a valid IRQ */
35  QM_ISR_EOI(0);
36 #else
37  QM_ISR_EOI(QM_IRQ_PIC_TIMER_VECTOR);
38 #endif
39 }
40 
42 {
43  QM_CHECK(cfg != NULL, -EINVAL);
44  QM_CHECK(cfg->mode <= QM_PIC_TIMER_MODE_PERIODIC, -EINVAL);
45 
46  /* Stop timer, mask interrupt and program interrupt vector */
47  PIC_TIMER->timer_icr.reg = 0;
48  PIC_TIMER->lvttimer.reg = BIT(LVTTIMER_INT_MASK_OFFS) |
49 #if (HAS_APIC)
50  QM_X86_PIC_TIMER_INT_VECTOR;
51 #else
52  QM_IRQ_PIC_TIMER;
53 #endif
54 
55 #if (HAS_APIC)
56  /* LAPIC has a timer clock divisor, POR default: 2. Set it to 1. */
57  QM_LAPIC->timer_dcr.reg = 0xB;
58 #endif
59 
60  PIC_TIMER->lvttimer.reg |= cfg->mode << LVTTIMER_MODE_PERIODIC_OFFS;
61  callback = cfg->callback;
62  callback_data = cfg->callback_data;
63  if (cfg->int_en) {
64  PIC_TIMER->lvttimer.reg &= ~BIT(LVTTIMER_INT_MASK_OFFS);
65  }
66  return 0;
67 }
68 
69 int qm_pic_timer_set(const uint32_t count)
70 {
71  PIC_TIMER->timer_icr.reg = count;
72 
73  return 0;
74 }
75 
76 int qm_pic_timer_get(uint32_t *const count)
77 {
78  QM_CHECK(count != NULL, -EINVAL);
79 
80  *count = PIC_TIMER->timer_ccr.reg;
81 
82  return 0;
83 }
84 
85 #if (ENABLE_RESTORE_CONTEXT)
87 {
88  QM_CHECK(ctx != NULL, -EINVAL);
89 
90  ctx->timer_icr = PIC_TIMER->timer_ccr.reg;
91  ctx->timer_dcr = PIC_TIMER->timer_dcr.reg;
92  ctx->lvttimer = PIC_TIMER->lvttimer.reg;
93 
94  return 0;
95 }
96 
98 {
99  QM_CHECK(ctx != NULL, -EINVAL);
100 
101  /* The PIC Timer is restored to the value before sleep. */
102  PIC_TIMER->timer_icr.reg = ctx->timer_icr;
103  PIC_TIMER->timer_dcr.reg = ctx->timer_dcr;
104  PIC_TIMER->lvttimer.reg = ctx->lvttimer;
105 
106  return 0;
107 }
108 #else
110 {
111  (void)ctx;
112 
113  return 0;
114 }
115 
117 {
118  (void)ctx;
119 
120  return 0;
121 }
122 #endif
void(* callback)(void *data)
User callback.
Definition: qm_pic_timer.h:38
uint32_t timer_icr
Initial Count Register.
Definition: qm_soc_regs.h:284
PIC TIMER context type.
Definition: qm_soc_regs.h:283
int qm_pic_timer_set(const uint32_t count)
Set the current count value of the PIC timer.
Definition: qm_pic_timer.c:69
int qm_pic_timer_restore_context(const qm_pic_timer_context_t *const ctx)
Restore PIC Timer peripheral's context.
Definition: qm_pic_timer.c:97
bool int_en
Interrupt enable.
Definition: qm_pic_timer.h:31
uint32_t timer_dcr
Divide Configuration Register.
Definition: qm_soc_regs.h:285
QM_ISR_DECLARE(qm_pic_timer_0_isr)
ISR for PIC Timer interrupt.
Definition: qm_pic_timer.c:27
int qm_pic_timer_get(uint32_t *const count)
Get the current count value of the PIC timer.
Definition: qm_pic_timer.c:76
qm_pic_timer_mode_t mode
Operation mode.
Definition: qm_pic_timer.h:30
int qm_pic_timer_set_config(const qm_pic_timer_config_t *const cfg)
Set the PIC timer configuration.
Definition: qm_pic_timer.c:41
uint32_t lvttimer
Timer Entry in Local Vector Table.
Definition: qm_soc_regs.h:286
PIC timer configuration type.
Definition: qm_pic_timer.h:29
int qm_pic_timer_save_context(qm_pic_timer_context_t *const ctx)
Save PIC Timer peripheral's context.
Definition: qm_pic_timer.c:86
void * callback_data
Callback user data.
Definition: qm_pic_timer.h:39