P. 1
Kernel Notes

Kernel Notes

|Views: 389|Likes:
Published by rash5377

More info:

Published by: rash5377 on Nov 01, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

01/06/2012

pdf

text

original

The RTC is capable of generating periodic interrupts at rates from 2Hz to 8192Hz. This
is done by setting the PI bit of the RTC Status Register B (which is at address 0xb). The
frequency is selected by writing a 4 bit "rate" value to Status Register A (address 0xa) - the
rate can vary from 0011 to 1111 (binary). Frequency is derived from rate using the formula f
= 65536/2^rate. RTC interrupts are reported via IRQ 8.
Here is a program which puts the RTC in periodic interrupt generation mode.

71

Chapter 11. A Simple Real Time Clock Driver

Example 11-2. rtc.c - generate periodic interrupts

1
2
3 #include linux/config.h
4 #include linux/module.h
5 #include linux/kernel.h
6 #include linux/sched.h
7 #include linux/interrupt.h
8 #include linux/fs.h
9 #include asm/uaccess.h
10 #include asm/io.h
11
12 #define ADDRESS_REG 0x70
13 #define DATA_REG 0x71
14 #define ADDRESS_REG_MASK 0xe0
15 #define STATUS_A 0x0a
16 #define STATUS_B 0x0b
17 #define STATUS_C 0x0c
18
19 #define SECOND 0x00
20
21 #include "rtc.h"
22 #define RTC_IRQ 8
23 #define MODULE_NAME "rtc"
24
25 unsigned char
26 rtc_inb(unsigned char addr)
27 {
28 unsigned char i, j;
29 i = inb(ADDRESS_REG);
30 /* Clear lower 5 bits */
31 i = i & ADDRESS_REG_MASK;
32 i = i | addr;
33 outb(i, ADDRESS_REG);
34 j = inb(DATA_REG);
35 return j;
36 }
37
38 void
39 rtc_outb(unsigned char data, unsigned char addr)
40 {
41 unsigned char i;
42 i = inb(ADDRESS_REG);
43 /* Clear lower 5 bits */
44 i = i & ADDRESS_REG_MASK;
45 i = i | addr;
46 outb(i, ADDRESS_REG);
47 outb(data, DATA_REG);
48 }
49
50 void
51 enable_periodic_interrupt(void)
52 {
53 unsigned char c;
54 c = rtc_inb(STATUS_B);
55 /* set Periodic Interrupt enable bit */

72

Chapter 11. A Simple Real Time Clock Driver

56 c = c | (1 6);
57 rtc_outb(c, STATUS_B);
58 /* It seems that we have to simply read
59 * this register to get interrupts started.
60 * We do it in the ISR also.
61 */
62 rtc_inb(STATUS_C);
63 }
64
65 void
66 disable_periodic_interrupt(void)
67 {
68 unsigned char c;
69 c = rtc_inb(STATUS_B);
70 /* set Periodic Interrupt enable bit */
71 c = c & ~(1 6);
72 rtc_outb(c, STATUS_B);
73 }
74
75 int
76 set_periodic_interrupt_rate(unsigned char rate)
77 {
78 unsigned char c;
79 if((rate 3) && (rate 15)) return -EINVAL;
80 printk("setting rate %d\n", rate);
81 c = rtc_inb(STATUS_A);
82 c = c & ~0xf; /* Clear 4 bits LSB */
83 c = c | rate;
84 rtc_outb(c, STATUS_A);
85 printk("new rate = %d\n", rtc_inb(STATUS_A) & 0xf);
86 return 0;
87 }
88
89 void
90 rtc_int_handler(int irq, void *devid, struct pt_regs *regs)
91 {
92 printk("Handler called...\n");
93 rtc_inb(STATUS_C);
94 }
95
96 int rtc_init_module(void)
97 {
98 int result;
99 result = request_irq(RTC_IRQ, rtc_int_handler,
100 SA_INTERRUPT, MODULE_NAME, 0);
101 if(result 0) {
102 printk("Unable to get IRQ %d\n", RTC_IRQ);
103 return result;
104 }
105 disable_periodic_interrupt();
106 set_periodic_interrupt_rate(15);
107 enable_periodic_interrupt();
108 return result;
109 }
110
111 void rtc_cleanup(void)
112 {

73

Chapter 11. A Simple Real Time Clock Driver

113

free_irq(RTC_IRQ, 0);

114

return;

115 }
116
117 module_init(rtc_init_module);
118 module_exit(rtc_cleanup)

Your Linux kernel may already have an RTC driver compiled in - in that case you will have
to compile a new kernel without the RTC driver - otherwise, the above program may fail to
acquire the interrupt line.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->