static uint32_t s3c_rtc_read(void *opaque, target_phys_addr_t addr) { struct s3c_rtc_state_s *s = (struct s3c_rtc_state_s *) opaque; addr -= s->base; switch (addr) { case S3C_RTC_CON: return s->control; case S3C_RTC_TICNT: return s->tick; case S3C_RTC_ALM: return s->alarm; case S3C_RTC_ALMSEC: return s->almsec; case S3C_RTC_ALMMIN: return s->almmin; case S3C_RTC_ALMHOUR: return s->almhour; case S3C_RTC_ALMDATE: return s->almday; case S3C_RTC_ALMMON: return s->almmon; case S3C_RTC_ALMYEAR: return s->almyear; case S3C_RTC_RST: return s->reset; case S3C_RTC_BCDSEC: s3c_rtc_update(s); return to_bcd(s->tm.tm_sec); case S3C_RTC_BCDMIN: s3c_rtc_update(s); return to_bcd(s->tm.tm_min); case S3C_RTC_BCDHOUR: s3c_rtc_update(s); return to_bcd(s->tm.tm_hour); case S3C_RTC_BCDDATE: s3c_rtc_update(s); return to_bcd(s->tm.tm_mday); case S3C_RTC_BCDDAY: s3c_rtc_update(s); return s->tm.tm_wday; case S3C_RTC_BCDMON: s3c_rtc_update(s); return to_bcd(s->tm.tm_mon + 1); case S3C_RTC_BCDYEAR: s3c_rtc_update(s); return to_bcd(s->tm.tm_year % 100); default: printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr); break; } return 0; }
static void s3c_rtc_write(void *opaque, target_phys_addr_t addr, uint32_t value) { struct s3c_rtc_state_s *s = (struct s3c_rtc_state_s *) opaque; int diff; switch (addr) { case S3C_RTC_CON: s->control = value & 0xf; s->enable = (s->control == 0x1); break; case S3C_RTC_TICNT: s->tick = value; if (s->tick & (1 << 7)) s3c_rtc_tick_mod(s); break; case S3C_RTC_ALM: s->alarm = value; break; case S3C_RTC_ALMSEC: s->almsec = value; break; case S3C_RTC_ALMMIN: s->almmin = value; break; case S3C_RTC_ALMHOUR: s->almhour = value; break; case S3C_RTC_ALMDATE: s->almday = value; break; case S3C_RTC_ALMMON: s->almmon = value; break; case S3C_RTC_ALMYEAR: s->almyear = value; break; case S3C_RTC_RST: s->reset = value & 0xf; break; /* XXX This is not very exact time setting */ case S3C_RTC_BCDSEC: s3c_rtc_update(s); diff = from_bcd(value) - s->tm.tm_sec; s->sec += diff * 1; break; case S3C_RTC_BCDMIN: s3c_rtc_update(s); diff = from_bcd(value) - s->tm.tm_min; s->sec += diff * 60; break; case S3C_RTC_BCDHOUR: s3c_rtc_update(s); diff = from_bcd(value) - s->tm.tm_hour; s->sec += diff * 60 * 60; break; case S3C_RTC_BCDDATE: s3c_rtc_update(s); diff = from_bcd(value) - s->tm.tm_mday; s->sec += diff * 60 * 60 * 24; break; case S3C_RTC_BCDDAY: s3c_rtc_update(s); diff = (value & 7) - s->tm.tm_wday; s->sec += diff * 60 * 60 * 24; break; case S3C_RTC_BCDMON: s3c_rtc_update(s); diff = from_bcd(value) - s->tm.tm_mon - 1; s->sec += diff * 60 * 60 * 24 * 30; break; case S3C_RTC_BCDYEAR: s3c_rtc_update(s); diff = from_bcd(value) - (s->tm.tm_year % 100); s->sec += diff * 60 * 60 * 24 * 365; break; default: printf("%s: Bad register 0x%lx\n", __FUNCTION__, (unsigned long)addr); } }