/* Will auto-adjust the stored year if required */ void pcf8583_read(struct tm *time) { union { uint8_t bytes[5]; uint16_t words[2]; } tmp; /* Set to default value in case we abort */ memcpy_P(time, &rtc_default_date, sizeof(struct tm)); if (rtc_state != RTC_OK) return; if (i2c_read_registers(PCF8583_ADDR, REG_SECONDS, 5, &tmp)) return; time->tm_sec = bcd2int(tmp.bytes[0]); time->tm_min = bcd2int(tmp.bytes[1]); time->tm_hour = bcd2int(tmp.bytes[2]); time->tm_mday = bcd2int(tmp.bytes[3] & 0b00111111); time->tm_mon = bcd2int(tmp.bytes[4] & 0b00011111)-1; time->tm_wday = bcd2int(tmp.bytes[4] >> 5); /* Check for year rollover */ tmp.bytes[4] = tmp.bytes[3] >> 6; i2c_read_registers(PCF8583_ADDR, REG_YEAR1, 4, &tmp); if ((tmp.words[0] & 3) != tmp.bytes[4]) { /* Year rolled over, increment until the lower two bits match */ while ((tmp.words[0] & 3) != tmp.bytes[4]) tmp.words[0]++; tmp.words[1] = tmp.words[0] ^ 0xffffU; /* Store new year to RTC ram */ i2c_write_registers(PCF8583_ADDR, REG_YEAR1, 4, &tmp); } time->tm_year = tmp.words[0]-1900; }
//returns the date void rtc_get_date(Rtc *p_rtc, uint32_t *ul_year, uint32_t *ul_month, uint32_t *ul_day, uint32_t *ul_week){ uint32_t r; twi_packet_t packet_rx; uint8_t rx_data [8]; int dw,dt,mo,yr; packet_rx.chip = RTC_ADDRESS; packet_rx.addr[0] = 0x3; packet_rx.addr_length = 1; packet_rx.buffer = rx_data; packet_rx.length = 4; if((r=twi_master_read(RTC_BASE_TWI, &packet_rx)) != TWI_SUCCESS){ printf("error in get_date: %d\n",(int)r); return; } //convert from BCD to decimal dw=bcd2int(rx_data[0]); dt=bcd2int(rx_data[1]); mo=bcd2int(rx_data[2]); yr=bcd2int(rx_data[3])+2000; *ul_year = yr; *ul_month= mo; *ul_day = dt; *ul_week = dw; //printf("20%d/%d/%d (%d)\n",yr,mo,dt,dw); }
u32 get_rtc_time() { rm_ctx ctx; u32 hrs, mins; u32 sec; btab->p_set_ctx(0x0200, &ctx); btab->p_bios_call(0x1A, &ctx); hrs = bcd2int(ctx.ch); mins = bcd2int(ctx.cl); sec = bcd2int(ctx.dh); return (hrs * 3600) + (mins * 60) + sec; }
uint32_t rtc_get_time(void) { uint8_t i;//, pm = 0; // 0 1 2 3 4 5 6 // seconds, minutes, hours, days, weekdays, months, years uint8_t date[7]; if(rtc_get_pon() == 1) return 0; rtc_read_page(RTC_PAGE_CLOCK, date, 7); //if(date[2] & (1<< 6)) // PORTB |= (1 << PB4); // pm = 1; date[0] &= 0x7f; date[1] &= 0x7f; date[2] &= 0x3f; date[3] &= 0x3f; date[4] &= 0x07; date[5] &= 0x3f; date[6] &= 0x7f; for(i = 0; i < 7; i++) date[i] = bcd2int(date[i]); //if(pm) // date[2] += 12; return date_convert2timestamp((int16_t)date[6]+2000, date[5], date[3], date[2], date[1], date[0]); }
int cmos_year() { // algorthm patended my microsoft. beware! // don't read the code below, ah! you already // did it. no problem, they can still brainwash you... int off = bcd2int(cmos_read(0x9)); if(off >= 70 ) return 1990 + off; else return 2000 + off; }
int snapgear_rtc_settimeofday(const struct timeval *tv) { int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned long nowtime; if (!use_ds1302) { sh_rtc_settimeofday(tv); return(0); } /* * This is called direct from the kernel timer handling code. * It is supposed to synchronize the kernel clock to the RTC. */ nowtime = tv->tv_sec; #if 1 printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime); #endif /* STOP RTC */ ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); /* * since we're only adjusting minutes and seconds, * don't interfere with hour overflow. This avoids * messing with unknown time zones but requires your * RTC not to be off by more than 15 minutes */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) real_minutes += 30; /* correct for half hour time zone */ real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes)); ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds)); } else { printk(KERN_WARNING "SnapGear RTC: can't update from %d to %d\n", cmos_minutes, real_minutes); retval = -1; } /* START RTC */ ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); return(0); }
//returns unix timestamp void rtc_get_time(Rtc *p_rtc, uint32_t *ul_hour, uint32_t *ul_minute, uint32_t *ul_second){ uint32_t r; twi_packet_t packet_rx; uint8_t rx_data [8]; int sc,mn,hr; packet_rx.chip = RTC_ADDRESS; packet_rx.addr[0] = 0x0; packet_rx.addr_length = 1; packet_rx.buffer = rx_data; packet_rx.length = 3; if((r=twi_master_read(RTC_BASE_TWI, &packet_rx)) != TWI_SUCCESS){ printf("error reading RTC: %d\n",(int)r); return; } //convert from BCD to decimal sc=bcd2int(rx_data[0]); mn=bcd2int(rx_data[1]); hr=bcd2int(rx_data[2]); *ul_hour = hr; *ul_minute = mn; *ul_second = sc; // printf("%d:%d:%d\n",hr,mn,sc); }
extern void mvme147_gettod (int *year, int *mon, int *day, int *hour, int *min, int *sec) { m147_rtc->ctrl = RTC_READ; *year = bcd2int (m147_rtc->bcd_year); *mon = bcd2int (m147_rtc->bcd_mth); *day = bcd2int (m147_rtc->bcd_dom); *hour = bcd2int (m147_rtc->bcd_hr); *min = bcd2int (m147_rtc->bcd_min); *sec = bcd2int (m147_rtc->bcd_sec); m147_rtc->ctrl = 0; }
void ds1302_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec) { #if 0 printk("ds1302_gettod()\n"); #endif *year = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR)); *mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON)); *day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE)); *hour = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR)); *min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); *sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC)); }
int mvme147_hwclk(int op, struct rtc_time *t) { #warning check me! if (!op) { m147_rtc->ctrl = RTC_READ; t->tm_year = bcd2int (m147_rtc->bcd_year); t->tm_mon = bcd2int (m147_rtc->bcd_mth); t->tm_mday = bcd2int (m147_rtc->bcd_dom); t->tm_hour = bcd2int (m147_rtc->bcd_hr); t->tm_min = bcd2int (m147_rtc->bcd_min); t->tm_sec = bcd2int (m147_rtc->bcd_sec); m147_rtc->ctrl = 0; } return 0; }
/* Read the current time from the RTC */ void dsrtc_read(struct tm *time) { uint8_t tmp[7]; /* Set to default value in case we abort */ memcpy_P(time, &rtc_default_date, sizeof(struct tm)); if (rtc_state != RTC_OK) return; if (i2c_read_registers(RTC_ADDR, REG_SECOND, 7, &tmp)) return; time->tm_sec = bcd2int(tmp[REG_SECOND] & 0x7f); time->tm_min = bcd2int(tmp[REG_MINUTE]); time->tm_hour = bcd2int(tmp[REG_HOUR]); time->tm_mday = bcd2int(tmp[REG_DOM]); time->tm_mon = bcd2int(tmp[REG_MONTH] & 0x7f) - 1; time->tm_wday = bcd2int(tmp[REG_DOW]) - 1; time->tm_year = bcd2int(tmp[REG_YEAR]) + 100 * !!(tmp[REG_MONTH] & 0x80) + 100; // FIXME: Leap year calculation is wrong in 2100 }
void snapgear_rtc_gettimeofday(struct timespec *ts) { unsigned int sec, min, hr, day, mon, yr; if (!use_ds1302) { sh_rtc_gettimeofday(ts); return; } sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC)); min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR)); day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE)); mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON)); yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR)); bad_time: if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || hr > 23 || min > 59 || sec > 59) { printk(KERN_ERR "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n"); ds1302_writebyte(RTC_ADDR_MIN, min = 0); ds1302_writebyte(RTC_ADDR_HOUR, hr = 0); ds1302_writebyte(RTC_ADDR_DAY, 7); ds1302_writebyte(RTC_ADDR_DATE, day = 1); ds1302_writebyte(RTC_ADDR_MON, mon = 1); ds1302_writebyte(RTC_ADDR_YEAR, yr = 0); ds1302_writebyte(RTC_ADDR_SEC, sec = 0); } ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec); if (ts->tv_sec < 0) { #if 0 printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec); #endif yr = 100; goto bad_time; } ts->tv_nsec = 0; }
static void print_all_info(int fd, apm_info_t aip, int bioscall_available) { struct apm_bios_arg args; int apmerr; const char *line_msg[] = { "off-line", "on-line" , "backup power"}; printf("APM version: %d.%d\n", aip->ai_major, aip->ai_minor); printf("APM Management: %s\n", aip->ai_status ? "Enabled" : "Disabled"); printf("AC Line status: "); if (aip->ai_acline == APM_UNKNOWN) printf("unknown\n"); else if (aip->ai_acline > 2) printf("invalid value (0x%x)\n", aip->ai_acline); else printf("%s\n", line_msg[aip->ai_acline]); print_batt_stat(aip->ai_batt_stat); print_batt_life(aip->ai_batt_life); print_batt_time(aip->ai_batt_time); if (aip->ai_infoversion >= 1) { printf("Number of batteries: "); if (aip->ai_batteries == ~0U) printf("unknown\n"); else { u_int i; struct apm_pwstatus aps; printf("%d\n", aip->ai_batteries); for (i = 0; i < aip->ai_batteries; ++i) { bzero(&aps, sizeof(aps)); aps.ap_device = PMDV_BATT0 + i; if (ioctl(fd, APMIO_GETPWSTATUS, &aps) == -1) continue; printf("Battery %d:\n", i); if (aps.ap_batt_flag & APM_BATT_NOT_PRESENT) { printf("not present\n"); continue; } printf("\t"); print_batt_stat(aps.ap_batt_stat); printf("\t"); print_batt_life(aps.ap_batt_life); printf("\t"); print_batt_time(aps.ap_batt_time); } } } if (bioscall_available) { /* * try to get the suspend timer */ bzero(&args, sizeof(args)); args.eax = (APM_BIOS) << 8 | APM_RESUMETIMER; args.ebx = PMDV_APMBIOS; args.ecx = 0x0001; if (ioctl(fd, APMIO_BIOS, &args)) { printf("Resume timer: unknown\n"); } else { apmerr = APMERR(args.eax); if (apmerr == 0x0d || apmerr == 0x86) printf("Resume timer: disabled\n"); else if (apmerr) warnx( "failed to get the resume timer: APM error0x%x", apmerr); else { /* * OK. We have the time (all bcd). * CH - seconds * DH - hours * DL - minutes * xh(SI) - month (1-12) * xl(SI) - day of month (1-31) * DI - year */ struct tm tm; char buf[1024]; time_t t; tm.tm_sec = bcd2int(xh(args.ecx)); tm.tm_min = bcd2int(xl(args.edx)); tm.tm_hour = bcd2int(xh(args.edx)); tm.tm_mday = bcd2int(xl(args.esi)); tm.tm_mon = bcd2int(xh(args.esi)) - 1; tm.tm_year = bcd2int(args.edi) - 1900; if (cmos_wall) t = mktime(&tm); else t = timegm(&tm); if (t != -1) { tm = *localtime(&t); strftime(buf, sizeof(buf), "%c", &tm); printf("Resume timer: %s\n", buf); } else printf("Resume timer: unknown\n"); } } /* * Get the ring indicator resume state */ bzero(&args, sizeof(args)); args.eax = (APM_BIOS) << 8 | APM_RESUMEONRING; args.ebx = PMDV_APMBIOS; args.ecx = 0x0002; if (ioctl(fd, APMIO_BIOS, &args) == 0) { printf("Resume on ring indicator: %sabled\n", args.ecx ? "en" : "dis"); } } if (aip->ai_infoversion >= 1) { if (aip->ai_capabilities == 0xff00) return; printf("APM Capabilities:\n"); if (aip->ai_capabilities & 0x01) printf("\tglobal standby state\n"); if (aip->ai_capabilities & 0x02) printf("\tglobal suspend state\n"); if (aip->ai_capabilities & 0x04) printf("\tresume timer from standby\n"); if (aip->ai_capabilities & 0x08) printf("\tresume timer from suspend\n"); if (aip->ai_capabilities & 0x10) printf("\tRI resume from standby\n"); if (aip->ai_capabilities & 0x20) printf("\tRI resume from suspend\n"); if (aip->ai_capabilities & 0x40) printf("\tPCMCIA RI resume from standby\n"); if (aip->ai_capabilities & 0x80) printf("\tPCMCIA RI resume from suspend\n"); } }
static int todds1307_read_rtc(struct rtc_t *rtc) { static ds1307_state_t *statep = NULL; i2c_transfer_t *i2c_tp = NULL; int i2c_cmd_status = I2C_FAILURE; int counter = 4; if (!todds1307_attach_done) { return (todds1307_prom_getdate(rtc)); } statep = ddi_get_soft_state(ds1307_statep, instance); if (statep == NULL) { cmn_err(CE_WARN, "todds1307: ddi_get_soft_state failed"); return (DDI_FAILURE); } mutex_enter(&todds1307_rd_lock); /* * Allocate 1 byte for write buffer and 7 bytes for read buffer to * to accomodate sec, min, hrs, dayOfWeek, dayOfMonth, year */ if ((i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 1, 7, I2C_SLEEP)) != I2C_SUCCESS) { mutex_exit(&todds1307_rd_lock); return (DDI_FAILURE); } do { i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR_RD; i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Start from reg 0x00 */ i2c_tp->i2c_wlen = 1; /* Write one byte address */ i2c_tp->i2c_rlen = 7; /* Read 7 regs */ if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { drv_usecwait(I2C_DELAY); goto done; } /* for first read, need to get valid data */ while (tod_read[0] == -1 && counter > 0) { /* move data to static buffer */ bcopy(i2c_tp->i2c_rbuf, tod_read, 7); /* now read again */ /* Start reading reg from 0x00 */ i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; i2c_tp->i2c_wlen = 1; /* Write one byte address */ i2c_tp->i2c_rlen = 7; /* Read 7 regs */ if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { drv_usecwait(I2C_DELAY); goto done; } /* if they are not the same, then read again */ if (bcmp(tod_read, i2c_tp->i2c_rbuf, 7) != 0) { tod_read[0] = -1; counter--; } } } while (i2c_tp->i2c_rbuf[0] == 0x59 && /* if seconds register is 0x59 (BCD), add data should match */ bcmp(&tod_read[1], &i2c_tp->i2c_rbuf[1], 6) != 0 && counter-- > 0); if (counter < 0) cmn_err(CE_WARN, "i2ctod: TOD Chip failed ??"); /* move data to static buffer */ bcopy(i2c_tp->i2c_rbuf, tod_read, 7); rtc->rtc_year = bcd2int(i2c_tp->i2c_rbuf[6]); rtc->rtc_mon = bcd2int(i2c_tp->i2c_rbuf[5]); rtc->rtc_dom = bcd2int(i2c_tp->i2c_rbuf[4]); rtc->rtc_dow = bcd2int(i2c_tp->i2c_rbuf[3]); rtc->rtc_hrs = bcd2int(i2c_tp->i2c_rbuf[2]); rtc->rtc_min = bcd2int(i2c_tp->i2c_rbuf[1]); rtc->rtc_sec = bcd2int(i2c_tp->i2c_rbuf[0]); done: (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); mutex_exit(&todds1307_rd_lock); return (i2c_cmd_status); }
int cmos_month() { return bcd2int(cmos_read(0x8)); }
int cmos_day_of_month() { return bcd2int(cmos_read(0x7)); }
int cmos_day_of_week() { return bcd2int(cmos_read(0x6)); }
int cmos_seconds() { return bcd2int(cmos_read(0x0)); }
int cmos_minutes() { return bcd2int(cmos_read(0x2)); }
int cmos_hours() { return bcd2int(cmos_read(0x4)); }