embox

Форк
0
108 строк · 2.4 Кб
1
/**
2
 * @file
3
 * @brief High Precision Event Timer (HPET) driver
4
 *
5
 * @date 03.04.13
6
 * @author Roman Kurbatov
7
 */
8

9
#include <stdio.h>
10
#include <stdint.h>
11
#include <sys/mman.h>
12

13
#include <kernel/time/time_device.h>
14
#include <kernel/time/clock_source.h>
15
#include <kernel/time/ktime.h>
16
#include <kernel/printk.h>
17

18
#include <embox/unit.h>
19

20
#include <acpi.h>
21

22
//#define HPET_DEBUG
23

24
#ifdef HPET_DEBUG
25
#include <util/log.h>
26
#endif
27

28
#define HPET_GEN_CAP_REG    0x000
29
#define HPET_GEN_CONF_REG   0x010
30
#define HPET_GEN_INT_REG    0x020
31
#define HPET_MAIN_CNT_REG   0x0F0
32

33
#define ENABLE_CNF          0x1
34

35
#define FEMPTOSEC_IN_SEC    1000000000000000ULL /* 10^15 */
36

37
//ACPI_GENERIC_ADDRESS __attribute__((packed));
38
//ACPI_TABLE_HPET __attribute__((packed));
39

40
static cycle_t hpet_read(struct clock_source *cs);
41

42

43
static ACPI_TABLE_HPET *hpet_table;
44
static uintptr_t hpet_base_address;
45

46
static inline uint64_t hpet_get_register(uintptr_t offset) {
47
	return *((volatile uint64_t *) (hpet_base_address + offset));
48
}
49

50
static inline void hpet_set_register(uintptr_t offset, uint64_t value) {
51
	*((volatile uint64_t *) (hpet_base_address + offset)) = value;
52
}
53

54
static uint32_t hpet_get_hz(void) {
55
	uint64_t reg;
56
	uint32_t period;
57

58
	reg = hpet_get_register(HPET_GEN_CAP_REG);
59
	period = reg >> 32;
60

61
	return FEMPTOSEC_IN_SEC / period;
62
}
63

64
static void hpet_start_counter(void) {
65
	uint64_t reg;
66

67
	reg = hpet_get_register(HPET_GEN_CONF_REG);
68
	reg |= ENABLE_CNF;
69
	hpet_set_register(HPET_GEN_CONF_REG, reg);
70
}
71

72
static int hpet_init(struct clock_source *cs) {
73
	ACPI_STATUS status;
74

75
	status = AcpiGetTable("HPET", 1, (ACPI_TABLE_HEADER **) &hpet_table);
76
	if (ACPI_FAILURE(status)) {
77
		printk("Unable to get HPET table\n");
78
		return -1;
79
	}
80

81
	hpet_base_address = hpet_table->Address.Address;
82
	hpet_base_address = (uintptr_t)mmap_device_memory((void *)hpet_base_address,
83
	    0x100, PROT_READ | PROT_WRITE, MAP_SHARED,
84
	    (uintptr_t)hpet_base_address);
85
	cs->counter_device->cycle_hz = hpet_get_hz();
86
	hpet_start_counter();
87

88
#ifdef HPET_DEBUG
89
	log_debug("Hz: %u", hpet_counter_device.cycle_hz);
90
	for (int i = 0; i < 10; ++i) {
91
		ksleep(1000);
92
		log_debug("%llu", (*hpet_clock_source.read)(&hpet_clock_source));
93
	}
94
#endif
95

96
	return 0;
97
}
98

99
static cycle_t hpet_read(struct clock_source *cs) {
100
	return hpet_get_register(HPET_MAIN_CNT_REG);
101
}
102

103
static struct time_counter_device hpet_counter_device = {
104
	.read = &hpet_read
105
};
106

107
CLOCK_SOURCE_DEF(hpet, hpet_init, NULL,
108
	NULL, &hpet_counter_device);
109

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

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

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

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