1 #include <core/system.h>
2 #include <core/string.h>
3 #include <core/kargs.h>
5 #include <platform/misc.h>
7 static struct ioaddr pit_ioaddr
;
9 #define PIT_CHANNEL0 0x00
12 struct pit_cmd_register
{
24 #define PIT_MODE_RATE_GENERATOR 0x2
25 #define PIT_MODE_SQUARE_WAVE 0x3
26 #define PIT_ACCESS_LOHIBYTE 0x3
28 int x86_pit_setup(struct ioaddr
*io
)
30 printk("i8254: Initializing [%p (%s)]\n", io
->addr
, ioaddr_type_str(io
));
35 #define FBASE 1193182ULL /* PIT Oscillator operates at 1.193182 MHz */
37 static uint32_t atou32(const char *s
)
42 ret
= ret
* 10 + (*s
- '0');
49 uint32_t x86_pit_period_set(uint32_t period_ns
)
51 printk("i8254: requested period %d ns\n", period_ns
);
54 const char *arg_div
= NULL
;
56 if (!kargs_get("i8254.div", &arg_div
)) {
57 div
= atou32(arg_div
);
59 div
= period_ns
/838UL;
62 if (div
== 0) div
= 1;
64 period_ns
= 1000000000UL/(FBASE
/div
);
66 printk("i8254: Setting period to %d ns (div = %d)\n", period_ns
, div
);
68 struct pit_cmd_register cmd
= {
70 .mode
= PIT_MODE_SQUARE_WAVE
,
71 .access
= PIT_ACCESS_LOHIBYTE
,
75 io_out8(&pit_ioaddr
, PIT_CMD
, cmd
.raw
);
76 io_out8(&pit_ioaddr
, PIT_CHANNEL0
, (div
>> 0) & 0xFF);
77 io_out8(&pit_ioaddr
, PIT_CHANNEL0
, (div
>> 8) & 0xFF);