slab: warn about duplicated KMC names when tracing
[akaros.git] / kern / drivers / timers / hpet.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <endian.h>
5 #include <pmap.h>
6 #include <acpi.h>
7
8 #include "hpet.h"
9
10 /* The HPET likes 64bit mmreg reads and writes.  If the arch doesn't support
11  * them, then things are a little trickier.  Probably just replace these with
12  * mm64 ops, and quit supporting 32 bit. */
13 static inline void hpet_w64(uintptr_t reg, uint64_t val)
14 {
15         *((volatile uint64_t*)reg) = val;
16 }
17
18 static inline uint64_t hpet_r64(uintptr_t reg)
19 {
20         return *((volatile uint64_t*)reg);
21 }
22
23 struct Atable *parsehpet(struct Atable *parent,
24                          char *name, uint8_t *raw, size_t rawsize)
25 {
26         /* Do we want to keep this table around?  if so, we can use newtable,
27          * which allocs an Atable and puts it on a global stailq.  then we
28          * return that pointer, not as an addr, but as a signal to parse code
29          * about whether or not it is safe to unmap (which we don't do anymore).
30          */
31         struct Atable *hpet = mkatable(parent, HPET, "HPET", raw, rawsize, 0);
32         unsigned long hp_addr;
33         uint32_t evt_blk_id;
34         int nr_timers;
35
36         assert(hpet);
37         printk("HPET table detected at %p, for %d bytes\n", raw, rawsize);
38
39         evt_blk_id = l32get(raw + 36);
40         printd("EV BID 0x%08x\n", evt_blk_id);
41
42         hp_addr = (unsigned long)KADDR_NOCHECK(l64get(raw + 44));
43
44         printd("cap/ip %p\n", hpet_r64(hp_addr + 0x00));
45         printd("config %p\n", hpet_r64(hp_addr + 0x10));
46         printd("irqsts %p\n", hpet_r64(hp_addr + 0x20));
47
48         nr_timers = ((hpet_r64(hp_addr) >> 8) & 0xf) + 1;
49         for (int i = 0; i < nr_timers; i++)
50                 printd("Timer %d, config reg %p\n", i,
51                        hpet_r64(hp_addr + 0x100 + 0x20 * i));
52         /* 0x10, general config register.  bottom two bits are legacy mode and
53          * global enable.  turning them both off.  need to do read-modify-writes
54          * to HPET registers with reserved fields.*/
55         hpet_w64(hp_addr + 0x10, hpet_r64(hp_addr + 0x10) & ~0x3);
56         printk("Disabled the HPET timer\n");
57
58         return finatable_nochildren(hpet);
59 }
60
61 void cmos_dumping_ground()
62 {
63         uint8_t cmos_b;
64
65         /* this stuff tries to turn off various cmos / RTC timer bits.  keeping
66          * around if we need to disable the RTC alarm.  note that the HPET
67          * replaces the RTC periodic function (where available), and in those
68          * cases the RTC alarm function is implemented with SMM. */
69         outb(0x70, 0xb);
70         cmos_b = inb(0x71);
71         printk("cmos b 0x%02x\n", cmos_b);
72
73         cmos_b &= ~((1 << 5) | (1 << 6));
74         outb(0x70, 0xb);
75         outb(0x71, cmos_b);
76
77         outb(0x70, 0xb);
78         cmos_b = inb(0x71);
79         printk("cmos b 0x%02x\n", cmos_b);
80 }