embox

Форк
0
107 строк · 2.7 Кб
1
/**
2
 * @file
3
 * @brief ARM PrimeCell Real Time Clock driver
4
 * @author Denis Deryugin <deryugin.denis@gmail.com>
5
 * @version 0.1
6
 * @date 2019-07-18
7
 */
8

9
#include <time.h>
10

11
#include <drivers/common/memory.h>
12

13
#include <hal/reg.h>
14
#include <kernel/irq.h>
15

16
#include <drivers/rtc.h>
17

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

21
EMBOX_UNIT_INIT(pl031_init);
22

23
#define PL031_BASE      OPTION_GET(NUMBER, base_addr)
24
#define PL031_IRQ       OPTION_GET(NUMBER, irq_nr)
25
#define PL031_TARGET_HZ 1
26

27
#define PL031_DR   (PL031_BASE + 0x00) /* Data register */
28
#define PL031_MR   (PL031_BASE + 0x04) /* Match register */ 
29
#define PL031_LR   (PL031_BASE + 0x08) /* Load register */
30
#define PL031_CR   (PL031_BASE + 0x0C) /* Control register */
31
#define PL031_IMSC (PL031_BASE + 0x10) /* Interrupt Mask Set or Clear register */
32
#define PL031_RIS  (PL031_BASE + 0x14) /* Raw Interrupt Status register */
33
#define PL031_MIS  (PL031_BASE + 0x18) /* Masked Interrupt Status register */
34
#define PL031_ICR  (PL031_BASE + 0x1C) /* Interrupt Clear register */
35

36
#define PL031_CR_START     (1 << 0)
37
#define PL031_IMSC_EN      (1 << 0)
38
#define PL031_ICR_CLEAR    (1 << 0)
39

40
static irq_return_t pl031_irq_handler(unsigned int irq_nr, void *data) {
41

42
	REG32_STORE(PL031_ICR, PL031_ICR_CLEAR); /* Clear interrupt */
43

44
	rtc_update_irq(data, 1, (RTC_AF | RTC_IRQF));
45
	return IRQ_HANDLED;
46
}
47

48
static int pl031_get_time(struct rtc_device *dev, struct tm *tm) {
49
	time_t time;
50
	time = REG32_LOAD(PL031_DR);
51
	gmtime_r(&time, tm);
52
	return 0;
53
}
54

55
static int pl031_set_time(struct rtc_device *dev, struct tm *tm) {
56
	REG32_STORE(PL031_LR, mktime(tm));
57
	return 0;
58
}
59

60
static int pl031_get_alarm(struct rtc_device *dev, struct tm *tm) {
61
	time_t time;
62
	time = REG32_LOAD(PL031_MR);
63
	gmtime_r(&time, tm);
64
	return 0;
65
}
66

67
static int pl031_set_alarm(struct rtc_device *dev, struct tm *tm) {
68
	REG32_STORE(PL031_MR, mktime(tm));
69
	return 0;
70
}
71

72
int pl031_alarm_irq_enable(struct rtc_device *dev, int enabled) {
73
	if (enabled) {
74
		REG32_STORE(PL031_IMSC, PL031_IMSC_EN); /* Enable IRQ */
75
	} else {
76
		REG32_STORE(PL031_IMSC, 0); /* disable IRQ */
77
	}
78
	return 0;
79
}
80

81
static struct rtc_ops pl031_ops = {
82
	.get_time = pl031_get_time,
83
	.set_time = pl031_set_time,
84
	.get_alarm = pl031_get_alarm,
85
	.set_alarm = pl031_set_alarm,
86
	.alarm_irq_enable = pl031_alarm_irq_enable
87
};
88

89
static struct rtc_device pl031_rtc_device = {
90
	.rtc_ops = &pl031_ops
91
};
92

93
RTC_DEVICE_DEF(&pl031_rtc_device);
94

95
static int pl031_init(void) {
96
	REG32_STORE(PL031_CR, PL031_CR_START);  /* Enable counter */
97

98
	return irq_attach(PL031_IRQ,
99
			pl031_irq_handler,
100
			0,
101
			&pl031_rtc_device,
102
			"PL031");
103
}
104

105
STATIC_IRQ_ATTACH(PL031_IRQ, pl031_irq_handler, &pl031_rtc_device;);
106

107
PERIPH_MEMORY_DEFINE(pl031, PL031_BASE, 0x20);
108

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

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

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

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