/* * Get RTC ready */ STATUS m41t81_tod_init(void) { UINT8 byte; int polls; int err; /* RTC is on SMBus 1 */ bcm1250_smbus_init(M41T81_SMBUS_CHAN); /* * Reset HT bit to "0" to update registers with current time. */ byte = time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_AHR); byte &= ~M41T81REG_AHR_HT; time_writertc(M41T81_CCR_ADDRESS, M41T81REG_AHR, byte); /* * Try to read from the device. If it does not * respond, fail. We may need to do this for up to 300ms. */ for (polls = 0; polls < 300; polls++) { taskDelay(1); err = time_readrtc(M41T81_CCR_ADDRESS, 0); if (err >= 0) break; /* read is ok */ } return 0; }
/* * Note: the TOD should store the current GMT */ STATUS m41t81_tod_set(int year, /* 1980-2079 */ int month, /* 01-12 */ int day, /* 01-31 */ int hour, /* 00-23 */ int minute, /* 00-59 */ int second) /* 00-59 */ { UINT8 y2k, temp; /* write time */ temp = time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_HR); temp &= (M41T81REG_HR_CB | M41T81REG_HR_CEB); hour = TO_BCD(hour); hour |= temp; time_writertc(M41T81_CCR_ADDRESS, M41T81REG_HR, hour); time_writertc(M41T81_CCR_ADDRESS, M41T81REG_MN, TO_BCD(minute)); second &= ~M41T81REG_SC_ST; time_writertc(M41T81_CCR_ADDRESS, M41T81REG_SC, TO_BCD(second)); /* write date */ time_writertc(M41T81_CCR_ADDRESS, M41T81REG_MO, TO_BCD(month)); time_writertc(M41T81_CCR_ADDRESS, M41T81REG_DT, TO_BCD(day)); y2k = (year >= 2000) ? 0x20 : 0x19; year %= 100; time_writertc(M41T81_CCR_ADDRESS, M41T81REG_YR, TO_BCD(year)); /* * M41T81 does not have a century byte, so we don't need to write y2k * But we should flip the century bit (CB) to "1" for year 20xx and to "0" * for year 19xx. */ temp = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_HR); if (y2k == 0x19) { temp &= ~M41T81REG_HR_CB; } else if (y2k == 0x20) { temp |= M41T81REG_HR_CB; } time_writertc(M41T81_CCR_ADDRESS, M41T81REG_HR, temp); return 0; }
/* * ST M41T81 RTC support. */ static int strtc_match(device_t parent, cfdata_t cf, void *aux) { struct smbus_attach_args *sa = aux; int ret; if ((sa->sa_interface != M41T81_SMBUS_CHAN) || (sa->sa_device != M41T81_SLAVEADDR)) return (0); time_smbus_init(sa->sa_interface); ret = time_readrtc(sa->sa_interface, sa->sa_device, SMB_1BYTE_ADDR, M41T81_SEC); if (ret < 0) return (0); return (!rtcfound); }
STATUS m41t81_tod_get(int *year, /* 1980-2079 */ int *month, /* 01-12 */ int *day, /* 01-31 */ int *hour, /* 00-23 */ int *minute, /* 00-59 */ int *second) /* 00-59 */ { UINT8 byte; byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_HR); byte &= ~(M41T81REG_HR_CB | M41T81REG_HR_CEB); *hour = (UINT8) FROM_BCD(byte); byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_MN); *minute = (UINT8) FROM_BCD(byte); byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_SC); byte &= ~(M41T81REG_SC_ST); *second = (UINT8) FROM_BCD(byte); byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_MO); *month = (UINT8) byte; byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_DT); *day = (UINT8) FROM_BCD(byte); byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_YR); *year = (UINT8) byte; byte = (UINT8) time_readrtc(M41T81_CCR_ADDRESS, M41T81REG_HR); byte &= M41T81REG_HR_CB; if (byte) { *year += 2000; /*Year 20xx*/ } else { *year += 1900; /*Year 19xx*/ } return 0; }