Re-integrate "USE_OPTION_TABLE" code.
[coreboot.git] / src / pc80 / mc146818rtc_early.c
1 #include <pc80/mc146818rtc.h>
2 #include <fallback.h>
3
4 #ifndef CONFIG_MAX_REBOOT_CNT
5 #error "CONFIG_MAX_REBOOT_CNT not defined"
6 #endif
7 #if  CONFIG_MAX_REBOOT_CNT > 15
8 #error "CONFIG_MAX_REBOOT_CNT too high"
9 #endif
10
11 static int cmos_error(void)
12 {
13         unsigned char reg_d;
14         /* See if the cmos error condition has been flagged */
15         reg_d = cmos_read(RTC_REG_D);
16         return (reg_d & RTC_VRT) == 0;
17 }
18
19 static int cmos_chksum_valid(void)
20 {
21 #if CONFIG_USE_OPTION_TABLE
22         unsigned char addr;
23         unsigned long sum, old_sum;
24         sum = 0;
25         /* Comput the cmos checksum */
26         for(addr = LB_CKS_RANGE_START; addr <= LB_CKS_RANGE_END; addr++) {
27                 sum += cmos_read(addr);
28         }
29         sum = (sum & 0xffff) ^ 0xffff;
30
31         /* Read the stored checksum */
32         old_sum = cmos_read(LB_CKS_LOC) << 8;
33         old_sum |=  cmos_read(LB_CKS_LOC+1);
34
35         return sum == old_sum;
36 #else
37         return 0;
38 #endif
39 }
40
41
42 static inline int last_boot_normal(void)
43 {
44         unsigned char byte;
45         byte = cmos_read(RTC_BOOT_BYTE);
46         return (byte & (1 << 1));
47 }
48
49 static inline int do_normal_boot(void)
50 {
51         unsigned char byte;
52
53         if (cmos_error() || !cmos_chksum_valid()) {
54                 /* There are no impossible values, no checksums so just
55                  * trust whatever value we have in the the cmos,
56                  * but clear the fallback bit.
57                  */
58                 byte = cmos_read(RTC_BOOT_BYTE);
59                 byte &= 0x0c;
60                 byte |= CONFIG_MAX_REBOOT_CNT << 4;
61                 cmos_write(byte, RTC_BOOT_BYTE);
62         }
63
64         /* The RTC_BOOT_BYTE is now o.k. see where to go. */
65         byte = cmos_read(RTC_BOOT_BYTE);
66
67         /* Are we in normal mode? */
68         if (byte & 1) {
69                 byte &= 0x0f; /* yes, clear the boot count */
70         }
71
72         /* Properly set the last boot flag */
73         byte &= 0xfc;
74         if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
75                 byte |= (1<<1);
76         }
77
78         /* Are we already at the max count? */
79         if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
80                 byte += 1 << 4; /* No, add 1 to the count */
81         }
82         else {
83                 byte &= 0xfc;   /* Yes, put in fallback mode */
84         }
85
86         /* Save the boot byte */
87         cmos_write(byte, RTC_BOOT_BYTE);
88
89         return (byte & (1<<1));
90 }
91
92 unsigned read_option(unsigned start, unsigned size, unsigned def)
93 {
94 #if CONFIG_USE_OPTION_TABLE
95         unsigned byte;
96         byte = cmos_read(start/8);
97         return (byte >> (start & 7U)) & ((1U << size) - 1U);
98 #else
99         return def;
100 #endif
101 }