Commit fc4860c089a6b6603e1ae4f9c1f8bd1b3aadfc8b

Authored by Simon Glass
1 parent b18c68d891

x86: rtc: mc146818: Add helpers to read/write CMOS RAM

On x86 we use CMOS RAM to read and write some settings. Add basic support
for this, including access to registers 128-255.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 2 changed files with 105 additions and 48 deletions Side-by-side Diff

drivers/rtc/mc146818.c
... ... @@ -27,9 +27,6 @@
27 27 /* Set this to 1 to clear the CMOS RAM */
28 28 #define CLEAR_CMOS 0
29 29  
30   -static uchar rtc_read (uchar reg);
31   -static void rtc_write (uchar reg, uchar val);
32   -
33 30 #define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
34 31 #define RTC_SECONDS 0x00
35 32 #define RTC_SECONDS_ALARM 0x01
36 33  
... ... @@ -60,24 +57,24 @@
60 57 {
61 58 uchar sec, min, hour, mday, wday, mon, year;
62 59 /* here check if rtc can be accessed */
63   - while((rtc_read(RTC_CONFIG_A)&0x80)==0x80);
64   - sec = rtc_read (RTC_SECONDS);
65   - min = rtc_read (RTC_MINUTES);
66   - hour = rtc_read (RTC_HOURS);
67   - mday = rtc_read (RTC_DATE_OF_MONTH);
68   - wday = rtc_read (RTC_DAY_OF_WEEK);
69   - mon = rtc_read (RTC_MONTH);
70   - year = rtc_read (RTC_YEAR);
  60 + while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80);
  61 + sec = rtc_read8(RTC_SECONDS);
  62 + min = rtc_read8(RTC_MINUTES);
  63 + hour = rtc_read8(RTC_HOURS);
  64 + mday = rtc_read8(RTC_DATE_OF_MONTH);
  65 + wday = rtc_read8(RTC_DAY_OF_WEEK);
  66 + mon = rtc_read8(RTC_MONTH);
  67 + year = rtc_read8(RTC_YEAR);
71 68 #ifdef RTC_DEBUG
72 69 printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
73 70 "hr: %02x min: %02x sec: %02x\n",
74 71 year, mon, mday, wday,
75 72 hour, min, sec );
76 73 printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
77   - rtc_read (RTC_CONFIG_D) & 0x3F,
78   - rtc_read (RTC_HOURS_ALARM),
79   - rtc_read (RTC_MINUTES_ALARM),
80   - rtc_read (RTC_SECONDS_ALARM) );
  74 + rtc_read8(RTC_CONFIG_D) & 0x3F,
  75 + rtc_read8(RTC_HOURS_ALARM),
  76 + rtc_read8(RTC_MINUTES_ALARM),
  77 + rtc_read8(RTC_SECONDS_ALARM));
81 78 #endif
82 79 tmp->tm_sec = bcd2bin (sec & 0x7F);
83 80 tmp->tm_min = bcd2bin (min & 0x7F);
84 81  
85 82  
86 83  
87 84  
88 85  
89 86  
90 87  
91 88  
92 89  
93 90  
94 91  
95 92  
96 93  
97 94  
98 95  
99 96  
100 97  
101 98  
102 99  
103 100  
... ... @@ -108,81 +105,109 @@
108 105 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
109 106 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
110 107 #endif
111   - rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
  108 + rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
112 109  
113   - rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
114   - rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
115   - rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
116   - rtc_write (RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
117   - rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
118   - rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
119   - rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
120   - rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
  110 + rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
  111 + rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
  112 + rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
  113 + rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
  114 + rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
  115 + rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
  116 + rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec));
  117 + rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
121 118  
122 119 return 0;
123 120 }
124 121  
125 122 void rtc_reset (void)
126 123 {
127   - rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
128   - rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */
129   - rtc_write(RTC_CONFIG_B,0x00);
130   - rtc_write(RTC_CONFIG_B,0x00);
131   - rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
  124 + rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */
  125 + rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */
  126 + rtc_write8(RTC_CONFIG_B, 0x00);
  127 + rtc_write8(RTC_CONFIG_B, 0x00);
  128 + rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */
132 129 }
133 130  
134 131 /* ------------------------------------------------------------------------- */
135 132  
136   -#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
137 133 /*
138 134 * use direct memory access
139 135 */
140   -static uchar rtc_read (uchar reg)
  136 +int rtc_read8(int reg)
141 137 {
  138 +#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
142 139 return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
  140 +#else
  141 + int ofs = 0;
  142 +
  143 + if (reg >= 128) {
  144 + ofs = 2;
  145 + reg -= 128;
  146 + }
  147 + out8(RTC_PORT_MC146818 + ofs, reg);
  148 +
  149 + return in8(RTC_PORT_MC146818 + ofs + 1);
  150 +#endif
143 151 }
144 152  
145   -static void rtc_write (uchar reg, uchar val)
  153 +void rtc_write8(int reg, uchar val)
146 154 {
  155 +#ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
147 156 out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
148   -}
149 157 #else
150   -static uchar rtc_read (uchar reg)
  158 + int ofs = 0;
  159 +
  160 + if (reg >= 128) {
  161 + ofs = 2;
  162 + reg -= 128;
  163 + }
  164 + out8(RTC_PORT_MC146818 + ofs, reg);
  165 + out8(RTC_PORT_MC146818 + ofs + 1, val);
  166 +#endif
  167 +}
  168 +
  169 +u32 rtc_read32(int reg)
151 170 {
152   - out8(RTC_PORT_MC146818,reg);
153   - return in8(RTC_PORT_MC146818 + 1);
  171 + u32 value = 0;
  172 + int i;
  173 +
  174 + for (i = 0; i < sizeof(value); i++)
  175 + value |= rtc_read8(reg + i) << (i << 3);
  176 +
  177 + return value;
154 178 }
155 179  
156   -static void rtc_write (uchar reg, uchar val)
  180 +void rtc_write32(int reg, u32 value)
157 181 {
158   - out8(RTC_PORT_MC146818,reg);
159   - out8(RTC_PORT_MC146818+1, val);
  182 + int i;
  183 +
  184 + for (i = 0; i < sizeof(value); i++)
  185 + rtc_write8(reg + i, (value >> (i << 3)) & 0xff);
160 186 }
161   -#endif
162 187  
163 188 void rtc_init(void)
164 189 {
165 190 #if CLEAR_CMOS
166 191 int i;
167 192  
168   - rtc_write(RTC_SECONDS_ALARM, 0);
169   - rtc_write(RTC_MINUTES_ALARM, 0);
170   - rtc_write(RTC_HOURS_ALARM, 0);
  193 + rtc_write8(RTC_SECONDS_ALARM, 0);
  194 + rtc_write8(RTC_MINUTES_ALARM, 0);
  195 + rtc_write8(RTC_HOURS_ALARM, 0);
171 196 for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
172   - rtc_write(i, 0);
  197 + rtc_write8(i, 0);
173 198 printf("RTC: zeroing CMOS RAM\n");
174 199 #endif
175 200  
176 201 /* Setup the real time clock */
177   - rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H);
  202 + rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H);
178 203 /* Setup the frequency it operates at */
179   - rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
  204 + rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
180 205 RTC_CONFIG_A_RATE_1024HZ);
181 206 /* Ensure all reserved bits are 0 in register D */
182   - rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
  207 + rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
183 208  
184 209 /* Clear any pending interrupts */
185   - rtc_read(RTC_CONFIG_C);
  210 + rtc_read8(RTC_CONFIG_C);
186 211 }
187 212 #endif
... ... @@ -51,6 +51,38 @@
51 51 unsigned int, unsigned int, unsigned int);
52 52  
53 53 /**
  54 + * rtc_read8() - Read an 8-bit register
  55 + *
  56 + * @reg: Register to read
  57 + * @return value read
  58 + */
  59 +int rtc_read8(int reg);
  60 +
  61 +/**
  62 + * rtc_write8() - Write an 8-bit register
  63 + *
  64 + * @reg: Register to write
  65 + * @value: Value to write
  66 + */
  67 +void rtc_write8(int reg, uchar val);
  68 +
  69 +/**
  70 + * rtc_read32() - Read a 32-bit value from the RTC
  71 + *
  72 + * @reg: Offset to start reading from
  73 + * @return value read
  74 + */
  75 +u32 rtc_read32(int reg);
  76 +
  77 +/**
  78 + * rtc_write32() - Write a 32-bit value to the RTC
  79 + *
  80 + * @reg: Register to start writing to
  81 + * @value: Value to write
  82 + */
  83 +void rtc_write32(int reg, u32 value);
  84 +
  85 +/**
54 86 * rtc_init() - Set up the real time clock ready for use
55 87 */
56 88 void rtc_init(void);