embox

Форк
0
94 строки · 3.5 Кб
1
/**
2
 * @file sp804_timer.c
3
 * @brief ARM Dual-Timer (SP804) Module driver
4
 * @author Nishant Malpani <nish.malpani25@gmail.com>
5
 * @date 2020-03-07
6
 *
7
 * @author Svirin Evgeny <eugenysvirin@gmail.com>
8
 * @date 2021-02-20
9
 */
10
#include <drivers/common/memory.h>
11
#include <hal/clock.h>
12
#include <hal/reg.h>
13
#include <kernel/irq.h>
14
#include <kernel/printk.h>
15
#include <kernel/time/clock_source.h>
16
#include <kernel/time/time_device.h>
17

18
#include <framework/mod/options.h>
19
#include <embox/unit.h>
20

21
#define SP804_BASE      OPTION_GET(NUMBER, base_addr) /* Base address */
22
#define SP804_IRQ       OPTION_GET(NUMBER, irq_nr) /* Interrupt Request number */
23
#define SP804_TARGET_HZ OPTION_GET(NUMBER, target_freq) /* Frequency to run the timer at */
24
#define SP804_TIMCLK    OPTION_GET(NUMBER, TIMCLK_freq) /* Frequency of the SP804 clock timer - 1 mHz, frequency of subtraction from Timer1 Load Register */
25

26
#define SP804_T1_LR     (SP804_BASE + 0x00) /* Timer1 Load Register */
27
#define SP804_T1_VR     (SP804_BASE + 0x04) /* Timer1 Current Value Register */
28
#define SP804_T1_CR     (SP804_BASE + 0x08) /* Timer1 Control Register */
29
#define SP804_T1_ICR    (SP804_BASE + 0x0C) /* Timer1 Interrupt Clear Register */
30
#define SP804_T1_RIS    (SP804_BASE + 0x10) /* Timer1 Raw Interrupt Status Register */
31
#define SP804_T1_MIS    (SP804_BASE + 0x14) /* Timer1 Masked Interrupt Status Register */
32
#define SP804_T1_BGL    (SP804_BASE + 0x18) /* Timer1 Background Load Register */
33

34
#define SP804_CR_MASK       (0b11101111) /* Mask for bits 0-7 */
35
#define SP804_CR_WRAPPING   (0 << 0) /* OneShot bit */
36
#define SP804_CR_32BIT      (1 << 1) /* TimerSize bit */
37
#define SP804_CR_TIMERPRE   (0 << 2) /* Prescale bits */
38
#define SP804_CR_INTEN      (1 << 5) /* InterruptEnable bit */
39
#define SP804_CR_PERIODIC   (1 << 6) /* TimerMode bit */
40
#define SP804_CR_TIMEREN    (1 << 7) /* TimerEnable bit */
41
#define SP804_ICR_CLEAR     (1 << 0) /* InterruptClear bit */
42

43
#define SP804_PRESCALE          1 /* Prescaler operation - divide the rate of master clock */
44
#define SP804_LR_VAL            ((SP804_TIMCLK) / (SP804_PRESCALE * SP804_TARGET_HZ))
45

46
static irq_return_t clock_handler(unsigned int irq_nr, void *data) {
47
    clock_tick_handler(data);
48

49
    REG32_STORE(SP804_T1_ICR, SP804_ICR_CLEAR); /* Clear interrupts */
50
    REG32_STORE(SP804_T1_LR, SP804_LR_VAL);
51
    return IRQ_HANDLED;
52
}
53

54
static int sp804_timer_init(struct clock_source *cs) {
55
    return irq_attach(SP804_IRQ,
56
                      clock_handler,
57
                      0,
58
                      cs,
59
                      "SP804");
60
}
61

62
static int this_set_periodic(struct clock_source *cs) {
63
    /* Unset bits 0-7, also disables the timer to proceed with new config settings */
64
    REG32_CLEAR(SP804_T1_CR, SP804_CR_MASK);
65

66
    REG32_STORE(SP804_T1_LR, SP804_LR_VAL); /* Don't care in free-running mode */
67

68
    /* setup Timer 1 as 32-bit interruptable periodic clocksource */
69
    REG32_STORE(SP804_T1_CR, SP804_CR_32BIT | SP804_CR_INTEN | 
70
                SP804_CR_PERIODIC | SP804_CR_TIMEREN);
71

72
    return 0;
73
}
74

75
static cycle_t this_read(struct clock_source *cs) {
76
    return REG32_LOAD(SP804_T1_VR);
77
}
78

79
static struct time_event_device sp804_timer_event = {
80
    .set_periodic   = this_set_periodic,
81
    .irq_nr   = SP804_IRQ,
82
};
83

84
static struct time_counter_device sp804_timer_counter = {
85
    .read     = this_read,
86
    .cycle_hz = 1000,
87
};
88

89
STATIC_IRQ_ATTACH(SP804_IRQ, clock_handler, &this_clock_source);
90

91
PERIPH_MEMORY_DEFINE(sp804, SP804_BASE, 0x1C);
92

93
CLOCK_SOURCE_DEF(sp804_timer, sp804_timer_init, NULL,
94
	&sp804_timer_event, &sp804_timer_counter);
95

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.