1.1 --- a/pkg/devices/lib/rtc/src/x1600.cc Sat May 04 01:30:06 2024 +0200
1.2 +++ b/pkg/devices/lib/rtc/src/x1600.cc Sat May 04 01:31:54 2024 +0200
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 * Real-time clock support.
1.6 *
1.7 - * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2023, 2024 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 * This program is free software; you can redistribute it and/or
1.11 * modify it under the terms of the GNU General Public License as
1.12 @@ -19,267 +19,31 @@
1.13 * Boston, MA 02110-1301, USA
1.14 */
1.15
1.16 -#include <l4/devices/hw_mmio_register_block.h>
1.17 #include "rtc-x1600.h"
1.18 -
1.19 -
1.20 -
1.21 -// Register locations.
1.22 -
1.23 -enum Regs : unsigned
1.24 -{
1.25 - Rtc_control = 0x000, // RTCCR
1.26 - Rtc_seconds = 0x004, // RTCSR
1.27 - Rtc_alarm_seconds = 0x008, // RTCSAR
1.28 - Rtc_regulator = 0x00c, // RTCGR
1.29 -
1.30 - Hibernate_control = 0x020, // HCR
1.31 - Hibernate_wakeup_filter_counter = 0x024, // HWFCR
1.32 - Hibernate_reset_counter = 0x028, // HRCR
1.33 - Hibernate_wakeup_control = 0x02c, // HWCR
1.34 - Hibernate_wakeup_status = 0x030, // HWRSR
1.35 - Hibernate_scratch_pattern = 0x034, // HSPR
1.36 - Hibernate_write_enable_pattern = 0x03c, // WENR
1.37 - Hibernate_wakeup_pin_configure = 0x048, // WKUPPINCR
1.38 -};
1.39 -
1.40 -// Field definitions.
1.41 -
1.42 -enum Control_bits : unsigned
1.43 -{
1.44 - Control_write_ready = 0x80, // WRDY
1.45 - Control_1Hz = 0x40, // 1HZ
1.46 - Control_1Hz_irq_enable = 0x20, // 1HZIE
1.47 - Control_alarm = 0x10, // AF
1.48 - Control_alarm_irq_enable = 0x08, // AIE
1.49 - Control_alarm_enable = 0x04, // AE
1.50 - Control_rtc_enable = 0x01, // RTCE
1.51 -};
1.52 -
1.53 -enum Regulator_bits : unsigned
1.54 -{
1.55 - Regulator_lock = 0x80000000, // LOCK
1.56 - Regulator_adjust_count_mask = 0x03ff0000, // ADJC
1.57 - Regulator_1Hz_cycle_count_mask = 0x0000ffff, // NC1HZ
1.58 -};
1.59 -
1.60 -enum Regulator_limits : unsigned
1.61 -{
1.62 - Regulator_adjust_count_limit = 0x03ff, // ADJC
1.63 - Regulator_1Hz_cycle_count_limit = 0xffff, // NC1HZ
1.64 -};
1.65 -
1.66 -enum Regulator_shifts : unsigned
1.67 -{
1.68 - Regulator_adjust_count_shift = 16, // ADJC
1.69 - Regulator_1Hz_cycle_count_shift = 0, // NC1HZ
1.70 -};
1.71 -
1.72 -enum Hibernate_control_bits : unsigned
1.73 -{
1.74 - Hibernate_power_down = 0x01, // PD
1.75 -};
1.76 -
1.77 -enum Hibernate_wakeup_filter_counter_bits : unsigned
1.78 -{
1.79 - Wakeup_minimum_time_mask = 0xffe0, // HWFCR
1.80 -};
1.81 -
1.82 -enum Hibernate_reset_counter_bits : unsigned
1.83 -{
1.84 - Reset_assert_time_mask = 0x7800, // HRCR
1.85 -};
1.86 -
1.87 -enum Hibernate_wakeup_control_bits : unsigned
1.88 -{
1.89 - Power_detect_enable_mask = 0xfffffff8, // EPDET
1.90 - Rtc_alarm_wakeup_enable = 0x00000001, // EALM
1.91 -};
1.92 -
1.93 -enum Hibernate_wakeup_status_bits : unsigned
1.94 -{
1.95 - Accident_power_down = 0x0100, // APD
1.96 - Hibernate_reset = 0x0020, // HR
1.97 - Pad_pin_reset = 0x0010, // PPR
1.98 - Wakeup_pin_status = 0x0002, // PIN
1.99 - Rtc_alarm_status = 0x0001, // ALM
1.100 -};
1.101 -
1.102 -enum Hibernate_write_enable_pattern_bits : unsigned
1.103 -{
1.104 - Write_enable_status = 0x80000000, // WEN
1.105 - Write_enable_pattern_mask = 0x0000ffff, // WENPAT
1.106 - Write_enable_pattern = 0x0000a55a, // WENPAT
1.107 -};
1.108 -
1.109 -enum Hibernate_wakeup_pin_configure_bits : unsigned
1.110 -{
1.111 - Rtc_oscillator_test_enable = 0x00080000, // OSC_TE
1.112 - Oscillator_xtclk_rtclk = 0x00040000, // OSC_RETON
1.113 - Oscillator_xtclk_low = 0x00000000, // OSC_RETON
1.114 - Rtc_internal_oscillator_enable = 0x00010000, // OSC_EN
1.115 - Wakeup_pin_extended_press_mask = 0x000000f0, // P_JUD_LEN
1.116 - Wakeup_pin_extended_press_enable = 0x0000000f, // P_RST_LEN
1.117 -};
1.118 +#include "rtc-defs.h"
1.119
1.120
1.121
1.122 // Peripheral abstraction.
1.123
1.124 -Rtc_x1600_chip::Rtc_x1600_chip(l4_addr_t addr, Cpm_x1600_chip *cpm)
1.125 -: _cpm(cpm)
1.126 -{
1.127 - _regs = new Hw::Mmio_register_block<32>(addr);
1.128 -}
1.129 -
1.130 -uint32_t
1.131 -Rtc_x1600_chip::read_checked(unsigned reg)
1.132 -{
1.133 - uint32_t last, current;
1.134 -
1.135 - wait();
1.136 - last = _regs[reg];
1.137 -
1.138 - while (1)
1.139 - {
1.140 - wait();
1.141 - current = _regs[reg];
1.142 -
1.143 - if (current == last)
1.144 - return current;
1.145 - else
1.146 - last = current;
1.147 - }
1.148 -}
1.149 -
1.150 -void
1.151 -Rtc_x1600_chip::wait()
1.152 +Rtc_x1600_chip::Rtc_x1600_chip(l4_addr_t addr, Cpm_chip *cpm)
1.153 +: Rtc_chip(addr, cpm)
1.154 {
1.155 - while (!(_regs[Rtc_control] & Control_write_ready));
1.156 -}
1.157 -
1.158 -void
1.159 -Rtc_x1600_chip::write_enable()
1.160 -{
1.161 - wait();
1.162 - _regs[Hibernate_write_enable_pattern] = Write_enable_pattern;
1.163 -
1.164 - while (!(_regs[Hibernate_write_enable_pattern] & Write_enable_status));
1.165 -
1.166 - wait();
1.167 -}
1.168 -
1.169 -void
1.170 -Rtc_x1600_chip::disable()
1.171 -{
1.172 - write_enable();
1.173 - _regs[Rtc_control] = _regs[Rtc_control] & ~Control_rtc_enable;
1.174 -}
1.175 -
1.176 -void
1.177 -Rtc_x1600_chip::enable()
1.178 -{
1.179 - write_enable();
1.180 - _regs[Rtc_control] = _regs[Rtc_control] | Control_rtc_enable;
1.181 -}
1.182 -
1.183 -void
1.184 -Rtc_x1600_chip::alarm_disable()
1.185 -{
1.186 - write_enable();
1.187 - _regs[Rtc_control] = _regs[Rtc_control] & ~Control_alarm_enable;
1.188 }
1.189
1.190 void
1.191 -Rtc_x1600_chip::alarm_enable()
1.192 -{
1.193 - write_enable();
1.194 - _regs[Rtc_control] = (_regs[Rtc_control] & ~Control_alarm) | Control_alarm_enable;
1.195 -}
1.196 -
1.197 -void
1.198 -Rtc_x1600_chip::wakeup_alarm_disable()
1.199 -{
1.200 - write_enable();
1.201 - _regs[Hibernate_wakeup_control] = _regs[Hibernate_wakeup_control] & ~Rtc_alarm_wakeup_enable;
1.202 -}
1.203 -
1.204 -void
1.205 -Rtc_x1600_chip::wakeup_alarm_enable()
1.206 -{
1.207 - write_enable();
1.208 - _regs[Hibernate_wakeup_control] = _regs[Hibernate_wakeup_control] | Rtc_alarm_wakeup_enable;
1.209 -}
1.210 -
1.211 -uint32_t
1.212 -Rtc_x1600_chip::get_seconds()
1.213 -{
1.214 - return read_checked(Rtc_seconds);
1.215 -}
1.216 -
1.217 -void
1.218 -Rtc_x1600_chip::set_seconds(uint32_t seconds)
1.219 -{
1.220 - write_enable();
1.221 - _regs[Rtc_seconds] = seconds;
1.222 -}
1.223 -
1.224 -uint32_t
1.225 -Rtc_x1600_chip::get_alarm_seconds()
1.226 -{
1.227 - return read_checked(Rtc_alarm_seconds);
1.228 -}
1.229 -
1.230 -void
1.231 -Rtc_x1600_chip::set_alarm_seconds(uint32_t seconds)
1.232 -{
1.233 - write_enable();
1.234 - _regs[Rtc_alarm_seconds] = seconds;
1.235 -}
1.236 -
1.237 -void
1.238 -Rtc_x1600_chip::set_regulator(uint32_t base, uint32_t adjustment)
1.239 -{
1.240 - base = base ? base - 1 : 0;
1.241 - adjustment = adjustment ? adjustment - 1 : 0;
1.242 -
1.243 - if (base > Regulator_1Hz_cycle_count_limit)
1.244 - base = Regulator_1Hz_cycle_count_limit;
1.245 -
1.246 - if (adjustment > Regulator_adjust_count_limit)
1.247 - adjustment = Regulator_adjust_count_limit;
1.248 -
1.249 - write_enable();
1.250 - _regs[Rtc_regulator] = (base << Regulator_1Hz_cycle_count_shift) |
1.251 - (adjustment << Regulator_adjust_count_shift);
1.252 -}
1.253 -
1.254 -void
1.255 -Rtc_x1600_chip::_power_down()
1.256 +Rtc_x1600_chip::_pre_power_down()
1.257 {
1.258 /* Set CPU frequency to L2 cache frequency before powering down. This is
1.259 apparently necessary according to the X1600 manual. */
1.260
1.261 if (_cpm != NULL)
1.262 _cpm->set_frequency(Clock_cpu, _cpm->get_frequency(Clock_l2cache));
1.263 -
1.264 - write_enable();
1.265 - _regs[Hibernate_control] = _regs[Hibernate_control] | Hibernate_power_down;
1.266 }
1.267
1.268 -void
1.269 -Rtc_x1600_chip::hibernate()
1.270 +Rtc_chip *x1600_rtc_chip(l4_addr_t rtc_base, Cpm_chip *cpm)
1.271 {
1.272 - alarm_enable();
1.273 - wakeup_alarm_enable();
1.274 - _power_down();
1.275 -}
1.276 -
1.277 -void
1.278 -Rtc_x1600_chip::power_down()
1.279 -{
1.280 - wakeup_alarm_disable();
1.281 - _power_down();
1.282 + return new Rtc_x1600_chip(rtc_base, cpm);
1.283 }
1.284
1.285
1.286 @@ -289,60 +53,65 @@
1.287 void
1.288 *x1600_rtc_init(l4_addr_t rtc_base, void *cpm)
1.289 {
1.290 - return (void *) new Rtc_x1600_chip(rtc_base, static_cast<Cpm_x1600_chip *>(cpm));
1.291 + return (void *) x1600_rtc_chip(rtc_base, static_cast<Cpm_chip *>(cpm));
1.292 +}
1.293 +
1.294 +enum Clock_identifiers x1600_rtc_get_clock(void *rtc)
1.295 +{
1.296 + return static_cast<Rtc_chip *>(rtc)->get_clock();
1.297 }
1.298
1.299 void x1600_rtc_disable(void *rtc)
1.300 {
1.301 - static_cast<Rtc_x1600_chip *>(rtc)->disable();
1.302 + static_cast<Rtc_chip *>(rtc)->disable();
1.303 }
1.304
1.305 void x1600_rtc_enable(void *rtc)
1.306 {
1.307 - static_cast<Rtc_x1600_chip *>(rtc)->enable();
1.308 + static_cast<Rtc_chip *>(rtc)->enable();
1.309 }
1.310
1.311 void x1600_rtc_alarm_disable(void *rtc)
1.312 {
1.313 - static_cast<Rtc_x1600_chip *>(rtc)->alarm_disable();
1.314 + static_cast<Rtc_chip *>(rtc)->alarm_disable();
1.315 }
1.316
1.317 void x1600_rtc_alarm_enable(void *rtc)
1.318 {
1.319 - static_cast<Rtc_x1600_chip *>(rtc)->alarm_enable();
1.320 + static_cast<Rtc_chip *>(rtc)->alarm_enable();
1.321 }
1.322
1.323 uint32_t x1600_rtc_get_seconds(void *rtc)
1.324 {
1.325 - return static_cast<Rtc_x1600_chip *>(rtc)->get_seconds();
1.326 + return static_cast<Rtc_chip *>(rtc)->get_seconds();
1.327 }
1.328
1.329 void x1600_rtc_set_seconds(void *rtc, uint32_t seconds)
1.330 {
1.331 - static_cast<Rtc_x1600_chip *>(rtc)->set_seconds(seconds);
1.332 + static_cast<Rtc_chip *>(rtc)->set_seconds(seconds);
1.333 }
1.334
1.335 uint32_t x1600_rtc_get_alarm_seconds(void *rtc)
1.336 {
1.337 - return static_cast<Rtc_x1600_chip *>(rtc)->get_alarm_seconds();
1.338 + return static_cast<Rtc_chip *>(rtc)->get_alarm_seconds();
1.339 }
1.340
1.341 void x1600_rtc_set_alarm_seconds(void *rtc, uint32_t seconds)
1.342 {
1.343 - static_cast<Rtc_x1600_chip *>(rtc)->set_alarm_seconds(seconds);
1.344 + static_cast<Rtc_chip *>(rtc)->set_alarm_seconds(seconds);
1.345 }
1.346
1.347 void x1600_rtc_set_regulator(void *rtc, uint32_t base, uint32_t adjustment)
1.348 {
1.349 - static_cast<Rtc_x1600_chip *>(rtc)->set_regulator(base, adjustment);
1.350 + static_cast<Rtc_chip *>(rtc)->set_regulator(base, adjustment);
1.351 }
1.352
1.353 void x1600_rtc_hibernate(void *rtc)
1.354 {
1.355 - static_cast<Rtc_x1600_chip *>(rtc)->hibernate();
1.356 + static_cast<Rtc_chip *>(rtc)->hibernate();
1.357 }
1.358
1.359 void x1600_rtc_power_down(void *rtc)
1.360 {
1.361 - static_cast<Rtc_x1600_chip *>(rtc)->power_down();
1.362 + static_cast<Rtc_chip *>(rtc)->power_down();
1.363 }