embox
105 строк · 2.7 Кб
1/**
2* @file
3* @brief Core clocking device in Raspberry PI
4*
5* See BCM2835-ARM-Peripherals.pdf, 12 chapter for details.
6*
7* A frequency of the System Timer is 1 MHz.
8*
9* @date 02.07.15
10* @author Vita Loginova
11*/
12
13#include <drivers/common/memory.h>14#include <hal/clock.h>15#include <hal/reg.h>16#include <hal/system.h>17#include <kernel/irq.h>18#include <kernel/time/clock_source.h>19#include <sys/mman.h>20#include <hal/mmu.h>21#include <util/binalign.h>22#include <framework/mod/options.h>23
24#include <embox/unit.h>25
26#define BCM2835_SYSTEM_TIMER_BASE OPTION_GET(NUMBER,base_addr)27
28/**
29* Layout of the System Timer Registers.
30*/
31struct raspi_timer_regs {32uint32_t CS; /**< Control/Status */33uint32_t CLO; /**< Counter Lower 32 bits */34uint32_t CHI; /**< Counter Higher 32 bits */35uint32_t C0; /**< Compare 0. DO NOT USE; is used by GPU. */36uint32_t C1; /**< Compare 1 */37uint32_t C2; /**< Compare 2. DO NOT USE; is used by GPU. */38uint32_t C3; /**< Compare 3 */39};40
41/**
42* Need to write one of these values into CS register to clear the
43* match detect status bit and the corresponding interrupt request line.
44*/
45#define BCM2835_SYSTEM_TIMER_MATCH_0 (1 << 0)46#define BCM2835_SYSTEM_TIMER_MATCH_1 (1 << 1)47#define BCM2835_SYSTEM_TIMER_MATCH_2 (1 << 2)48#define BCM2835_SYSTEM_TIMER_MATCH_3 (1 << 3)49
50#define SYSTICK_IRQ 351#define CLOCK_DIVIDER 7052
53#define RELOAD_VALUE (SYS_CLOCK / (CLOCK_DIVIDER * 1000))54
55static volatile struct raspi_timer_regs * const regs =56(volatile struct raspi_timer_regs*)BCM2835_SYSTEM_TIMER_BASE;57
58static inline void raspi_systick_clear(void) {59regs->CS = BCM2835_SYSTEM_TIMER_MATCH_3;60}
61
62static inline void raspi_systick_comare(uint32_t value) {63regs->C3 = regs->CLO + value;64}
65
66static irq_return_t clock_handler(unsigned int irq_nr, void *data) {67raspi_systick_clear();68raspi_systick_comare(RELOAD_VALUE);69
70clock_tick_handler(data);71
72return IRQ_HANDLED;73}
74
75static int raspi_systick_init(struct clock_source *cs) {76irq_attach(SYSTICK_IRQ, clock_handler, 0, cs, "Raspberry PI systick timer");77return 0;78}
79
80static int this_set_periodic(struct clock_source *cs) {81raspi_systick_clear();82/* From that point interrupts will occur. */83raspi_systick_comare(RELOAD_VALUE);84
85return 0;86}
87
88static cycle_t this_read(struct clock_source *cs) {89return regs->CLO;90}
91
92static struct time_event_device raspi_systick_event = {93.set_periodic = this_set_periodic,94.irq_nr = SYSTICK_IRQ,95};96
97static struct time_counter_device raspi_systick_counter = {98.read = this_read,99.cycle_hz = SYS_CLOCK / CLOCK_DIVIDER,100};101
102PERIPH_MEMORY_DEFINE(raspi_systick, BCM2835_SYSTEM_TIMER_BASE, sizeof(struct raspi_timer_regs));103
104CLOCK_SOURCE_DEF(raspi_systick, raspi_systick_init, NULL,105&raspi_systick_event, &raspi_systick_counter);106