1 /* 2 * Real-time clock support. 3 * 4 * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/devices/hw_mmio_register_block.h> 23 #include "rtc-x1600.h" 24 25 26 27 // Register locations. 28 29 enum Regs : unsigned 30 { 31 Rtc_control = 0x000, // RTCCR 32 Rtc_seconds = 0x004, // RTCSR 33 Rtc_alarm_seconds = 0x008, // RTCSAR 34 Rtc_regulator = 0x00c, // RTCGR 35 36 Hibernate_control = 0x020, // HCR 37 Hibernate_wakeup_filter_counter = 0x024, // HWFCR 38 Hibernate_reset_counter = 0x028, // HRCR 39 Hibernate_wakeup_control = 0x02c, // HWCR 40 Hibernate_wakeup_status = 0x030, // HWRSR 41 Hibernate_scratch_pattern = 0x034, // HSPR 42 Hibernate_write_enable_pattern = 0x03c, // WENR 43 Hibernate_wakeup_pin_configure = 0x048, // WKUPPINCR 44 }; 45 46 // Field definitions. 47 48 enum Control_bits : unsigned 49 { 50 Control_write_ready = 0x80, // WRDY 51 Control_1Hz = 0x40, // 1HZ 52 Control_1Hz_irq_enable = 0x20, // 1HZIE 53 Control_alarm = 0x10, // AF 54 Control_alarm_irq_enable = 0x08, // AIE 55 Control_alarm_enable = 0x04, // AE 56 Control_rtc_enable = 0x01, // RTCE 57 }; 58 59 enum Regulator_bits : unsigned 60 { 61 Regulator_lock = 0x80000000, // LOCK 62 Regulator_adjust_count_mask = 0x03ff0000, // ADJC 63 Regulator_1Hz_cycle_count_mask = 0x0000ffff, // NC1HZ 64 }; 65 66 enum Regulator_limits : unsigned 67 { 68 Regulator_adjust_count_limit = 0x03ff, // ADJC 69 Regulator_1Hz_cycle_count_limit = 0xffff, // NC1HZ 70 }; 71 72 enum Regulator_shifts : unsigned 73 { 74 Regulator_adjust_count_shift = 16, // ADJC 75 Regulator_1Hz_cycle_count_shift = 0, // NC1HZ 76 }; 77 78 enum Hibernate_control_bits : unsigned 79 { 80 Hibernate_power_down = 0x01, // PD 81 }; 82 83 enum Hibernate_wakeup_filter_counter_bits : unsigned 84 { 85 Wakeup_minimum_time_mask = 0xffe0, // HWFCR 86 }; 87 88 enum Hibernate_reset_counter_bits : unsigned 89 { 90 Reset_assert_time_mask = 0x7800, // HRCR 91 }; 92 93 enum Hibernate_wakeup_control_bits : unsigned 94 { 95 Power_detect_enable_mask = 0xfffffff8, // EPDET 96 Rtc_alarm_wakeup_enable = 0x00000001, // EALM 97 }; 98 99 enum Hibernate_wakeup_status_bits : unsigned 100 { 101 Accident_power_down = 0x0100, // APD 102 Hibernate_reset = 0x0020, // HR 103 Pad_pin_reset = 0x0010, // PPR 104 Wakeup_pin_status = 0x0002, // PIN 105 Rtc_alarm_status = 0x0001, // ALM 106 }; 107 108 enum Hibernate_write_enable_pattern_bits : unsigned 109 { 110 Write_enable_status = 0x80000000, // WEN 111 Write_enable_pattern_mask = 0x0000ffff, // WENPAT 112 Write_enable_pattern = 0x0000a55a, // WENPAT 113 }; 114 115 enum Hibernate_wakeup_pin_configure_bits : unsigned 116 { 117 Rtc_oscillator_test_enable = 0x00080000, // OSC_TE 118 Oscillator_xtclk_rtclk = 0x00040000, // OSC_RETON 119 Oscillator_xtclk_low = 0x00000000, // OSC_RETON 120 Rtc_internal_oscillator_enable = 0x00010000, // OSC_EN 121 Wakeup_pin_extended_press_mask = 0x000000f0, // P_JUD_LEN 122 Wakeup_pin_extended_press_enable = 0x0000000f, // P_RST_LEN 123 }; 124 125 126 127 // Peripheral abstraction. 128 129 Rtc_x1600_chip::Rtc_x1600_chip(l4_addr_t addr) 130 { 131 _regs = new Hw::Mmio_register_block<32>(addr); 132 } 133 134 uint32_t 135 Rtc_x1600_chip::read_checked(unsigned reg) 136 { 137 uint32_t last, current; 138 139 wait(); 140 last = _regs[reg]; 141 142 while (1) 143 { 144 wait(); 145 current = _regs[reg]; 146 147 if (current == last) 148 return current; 149 else 150 last = current; 151 } 152 } 153 154 void 155 Rtc_x1600_chip::wait() 156 { 157 while (!(_regs[Rtc_control] & Control_write_ready)); 158 } 159 160 void 161 Rtc_x1600_chip::write_enable() 162 { 163 wait(); 164 _regs[Hibernate_write_enable_pattern] = Write_enable_pattern; 165 166 while (!(_regs[Hibernate_write_enable_pattern] & Write_enable_status)); 167 168 wait(); 169 } 170 171 void 172 Rtc_x1600_chip::disable() 173 { 174 write_enable(); 175 _regs[Rtc_control] = _regs[Rtc_control] & ~Control_rtc_enable; 176 } 177 178 void 179 Rtc_x1600_chip::enable() 180 { 181 write_enable(); 182 _regs[Rtc_control] = _regs[Rtc_control] | Control_rtc_enable; 183 } 184 185 void 186 Rtc_x1600_chip::alarm_disable() 187 { 188 write_enable(); 189 _regs[Rtc_control] = _regs[Rtc_control] & ~Control_alarm_enable; 190 } 191 192 void 193 Rtc_x1600_chip::alarm_enable() 194 { 195 write_enable(); 196 _regs[Rtc_control] = _regs[Rtc_control] | Control_alarm_enable; 197 } 198 199 uint32_t 200 Rtc_x1600_chip::get_seconds() 201 { 202 return read_checked(Rtc_seconds); 203 } 204 205 void 206 Rtc_x1600_chip::set_seconds(uint32_t seconds) 207 { 208 write_enable(); 209 _regs[Rtc_seconds] = seconds; 210 } 211 212 uint32_t 213 Rtc_x1600_chip::get_alarm_seconds() 214 { 215 return read_checked(Rtc_alarm_seconds); 216 } 217 218 void 219 Rtc_x1600_chip::set_alarm_seconds(uint32_t seconds) 220 { 221 write_enable(); 222 _regs[Rtc_alarm_seconds] = seconds; 223 } 224 225 void 226 Rtc_x1600_chip::set_regulator(uint32_t base, uint32_t adjustment) 227 { 228 base = base ? base - 1 : 0; 229 adjustment = adjustment ? adjustment - 1 : 0; 230 231 if (base > Regulator_1Hz_cycle_count_limit) 232 base = Regulator_1Hz_cycle_count_limit; 233 234 if (adjustment > Regulator_adjust_count_limit) 235 adjustment = Regulator_adjust_count_limit; 236 237 write_enable(); 238 _regs[Rtc_regulator] = (base << Regulator_1Hz_cycle_count_shift) | 239 (adjustment << Regulator_adjust_count_shift); 240 } 241 242 void 243 Rtc_x1600_chip::power_down() 244 { 245 write_enable(); 246 _regs[Hibernate_control] = _regs[Hibernate_control] | Hibernate_power_down; 247 } 248 249 250 251 // C language interface functions. 252 253 void 254 *x1600_rtc_init(l4_addr_t rtc_base) 255 { 256 return (void *) new Rtc_x1600_chip(rtc_base); 257 } 258 259 void x1600_rtc_disable(void *rtc) 260 { 261 static_cast<Rtc_x1600_chip *>(rtc)->disable(); 262 } 263 264 void x1600_rtc_enable(void *rtc) 265 { 266 static_cast<Rtc_x1600_chip *>(rtc)->enable(); 267 } 268 269 void x1600_rtc_alarm_disable(void *rtc) 270 { 271 static_cast<Rtc_x1600_chip *>(rtc)->alarm_disable(); 272 } 273 274 void x1600_rtc_alarm_enable(void *rtc) 275 { 276 static_cast<Rtc_x1600_chip *>(rtc)->alarm_enable(); 277 } 278 279 uint32_t x1600_rtc_get_seconds(void *rtc) 280 { 281 return static_cast<Rtc_x1600_chip *>(rtc)->get_seconds(); 282 } 283 284 void x1600_rtc_set_seconds(void *rtc, uint32_t seconds) 285 { 286 static_cast<Rtc_x1600_chip *>(rtc)->set_seconds(seconds); 287 } 288 289 uint32_t x1600_rtc_get_alarm_seconds(void *rtc) 290 { 291 return static_cast<Rtc_x1600_chip *>(rtc)->get_alarm_seconds(); 292 } 293 294 void x1600_rtc_set_alarm_seconds(void *rtc, uint32_t seconds) 295 { 296 static_cast<Rtc_x1600_chip *>(rtc)->set_alarm_seconds(seconds); 297 } 298 299 void x1600_rtc_set_regulator(void *rtc, uint32_t base, uint32_t adjustment) 300 { 301 static_cast<Rtc_x1600_chip *>(rtc)->set_regulator(base, adjustment); 302 } 303 304 void x1600_rtc_power_down(void *rtc) 305 { 306 static_cast<Rtc_x1600_chip *>(rtc)->power_down(); 307 }