MAX31341/2 RTC Driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RtcBase.cpp Source File

RtcBase.cpp

00001 /*******************************************************************************
00002  * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of Maxim Integrated
00023  * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024  * Products, Inc. Branding Policy.
00025  *
00026  * The mere transfer of this software does not imply any licenses
00027  * of trade secrets, proprietary technology, copyrights, patents,
00028  * trademarks, maskwork rights, or any other form of intellectual
00029  * property whatsoever. Maxim Integrated Products, Inc. retains all
00030  * ownership rights.
00031  *******************************************************************************
00032  */
00033 
00034 #include "RtcBase.h"
00035 
00036 #define pr_err(fmt, ...) if(1) printf(fmt " (%s:%d)\r\n", ## __VA_ARGS__, __func__, __LINE__)
00037 #define pr_debug(fmt, ...) if(0) printf(fmt " (%s:%d)\r\n", ## __VA_ARGS__, __func__, __LINE__)
00038 
00039 #define BCD2BIN(val) (((val) & 15) + ((val) >> 4) * 10)
00040 #define BIN2BCD(val) ((((val) / 10) << 4) + (val) % 10)
00041 
00042 #define POST_INTR_WORK_SIGNAL_ID            0x1
00043 
00044 RtcBase::RtcBase(const regmap_t *regmap, I2C *i2c, PinName inta_pin = NC, PinName intb_pin = NC)
00045 {
00046     if (i2c == NULL) {
00047         pr_err("i2c object is invalid!");
00048         while (1);
00049     }
00050     i2c_handler = i2c;
00051 
00052     this->regmap = regmap;
00053 
00054     sw_reset_release();
00055 
00056     rtc_start();
00057 
00058     irq_disable_all();
00059 
00060     post_intr_work_thread = new Thread();
00061 
00062     post_intr_work_thread->start(Callback<void()>(this, &RtcBase::post_interrupt_work));
00063 
00064     if (inta_pin != NC) {
00065         this->inta_pin = new InterruptIn(inta_pin);
00066 
00067         this->inta_pin->fall(Callback<void()>(this, &RtcBase::interrupt_handler));
00068 
00069         this->inta_pin->enable_irq();
00070     } else {
00071         this->inta_pin = NULL;
00072     }
00073 
00074     if (intb_pin != NC) {
00075         this->intb_pin = new InterruptIn(intb_pin);
00076 
00077         this->intb_pin->fall(Callback<void()>(this, &RtcBase::interrupt_handler));
00078 
00079         this->intb_pin->enable_irq();
00080     } else {
00081         this->intb_pin = NULL;
00082     }
00083 }
00084 
00085 RtcBase::~RtcBase()
00086 {
00087     if (post_intr_work_thread) {
00088         delete post_intr_work_thread;
00089     }
00090 
00091     if (inta_pin) {
00092         delete inta_pin;
00093     }
00094 
00095     if (intb_pin) {
00096         delete intb_pin;
00097     }
00098 }
00099 
00100 int RtcBase::read_register(uint8_t reg, uint8_t *value, uint8_t len)
00101 {
00102     int ret;
00103 
00104     if (value == NULL) {
00105         pr_err("value is invalid!");
00106         return -1;
00107     }
00108 
00109     ret = i2c_handler->write(MAX3134X_I2C_W, (const char *) &reg, 1, true);
00110     if (ret != 0) {
00111         pr_err("i2c write failed with %d!", ret);
00112         return -1;
00113     }
00114 
00115     ret = i2c_handler->read(MAX3134X_I2C_R, (char *) value, len, false);
00116     if (ret < 0) {
00117         pr_err("i2c read failed with %d!", ret);
00118         return -1;
00119     }
00120 
00121     return 0;
00122 }
00123 
00124 int RtcBase::write_register(uint8_t reg, const uint8_t *value, uint8_t len)
00125 {
00126     int ret;
00127     uint8_t *buffer;
00128 
00129     if (value == NULL) {
00130         pr_err("value is invalid!");
00131         return -1;
00132     }
00133 
00134     buffer = new uint8_t[1 + len];
00135     buffer[0] = reg;
00136 
00137     memcpy(&buffer[1], value, len);
00138 
00139     ret = i2c_handler->write(MAX3134X_I2C_W, (const char *)buffer, 1 + len);
00140     if (ret != 0) {
00141         pr_err("i2c write failed with %d!", ret);
00142     }
00143 
00144     delete[] buffer;
00145 
00146     return ret;
00147 }
00148 
00149 int RtcBase::rtc_regs_to_time(struct tm *time, const rtc_time_regs_t *regs)
00150 {
00151     /* tm_sec seconds [0,61] */
00152     time->tm_sec = BCD2BIN(regs->seconds.bcd.value);
00153 
00154     /* tm_min minutes [0,59] */
00155     time->tm_min = BCD2BIN(regs->minutes.bcd.value);
00156 
00157     /* tm_hour hour [0,23] */
00158     time->tm_hour = BCD2BIN(regs->hours.bcd.value);
00159 
00160     /* tm_wday day of week [0,6] (Sunday = 0) */
00161     time->tm_wday = BCD2BIN(regs->day.bcd.value) - 1;
00162 
00163     /* tm_mday day of month [1,31] */
00164     time->tm_mday = BCD2BIN(regs->date.bcd.value);
00165 
00166     /* tm_mon month of year [0,11] */
00167     time->tm_mon = BCD2BIN(regs->month.bcd.value) - 1;
00168 
00169     /* tm_year years since 2000 */
00170     if (regs->month.bits.century) {
00171         time->tm_year = BCD2BIN(regs->year.bcd.value) + 200;
00172     } else {
00173         time->tm_year = BCD2BIN(regs->year.bcd.value) + 100;
00174     }
00175 
00176     /* tm_yday day of year [0,365] */
00177     time->tm_yday = 0; /* TODO */
00178 
00179     /* tm_isdst daylight savings flag */
00180     time->tm_isdst = 0; /* TODO */
00181 
00182     return 0;
00183 }
00184 
00185 int RtcBase::time_to_rtc_regs(rtc_time_regs_t *regs, const struct tm *time)
00186 {
00187     /*********************************************************
00188      * +----------+------+---------------------------+-------+
00189      * | Member   | Type | Meaning                   | Range |
00190      * +----------+------+---------------------------+-------+
00191      * | tm_sec   | int  | seconds after the minute  | 0-61* |
00192      * | tm_min   | int  | minutes after the hour    | 0-59  |
00193      * | tm_hour  | int  | hours since midnight      | 0-23  |
00194      * | tm_mday  | int  | day of the month          | 1-31  |
00195      * | tm_mon   | int  | months since January      | 0-11  |
00196      * | tm_year  | int  | years since 1900          |       |
00197      * | tm_wday  | int  | days since Sunday         | 0-6   |
00198      * | tm_yday  | int  | days since January 1      | 0-365 |
00199      * | tm_isdst | int  | Daylight Saving Time flag |       |
00200      * +----------+------+---------------------------+-------+
00201      * * tm_sec is generally 0-59. The extra range is to accommodate for leap
00202      *   seconds in certain systems.
00203      *********************************************************/
00204     regs->seconds.bcd.value = BIN2BCD(time->tm_sec);
00205 
00206     regs->minutes.bcd.value = BIN2BCD(time->tm_min);
00207 
00208     regs->hours.bcd.value= BIN2BCD(time->tm_hour);
00209 
00210     regs->day.bcd.value = BIN2BCD(time->tm_wday + 1);
00211 
00212     regs->date.bcd.value = BIN2BCD(time->tm_mday);
00213 
00214     regs->month.bcd.value = BIN2BCD(time->tm_mon + 1);
00215 
00216     if (time->tm_year >= 200) {
00217         regs->month.bits.century = 1;
00218         regs->year.bcd.value = BIN2BCD(time->tm_year - 200);
00219     } else if (time->tm_year >= 100) {
00220         regs->month.bits.century = 0;
00221         regs->year.bcd.value = BIN2BCD(time->tm_year - 100);
00222     } else {
00223         pr_err("Invalid set date!");
00224         return -1;
00225     }
00226 
00227     return 0;
00228 }
00229 
00230 int RtcBase::get_time(struct tm *time)
00231 {
00232     rtc_time_regs_t time_regs;
00233 
00234     if (time == NULL) {
00235         pr_err("rtc_ctime is invalid!");
00236         return -1;
00237     }
00238 
00239     if (read_register(regmap->seconds, (uint8_t *) &time_regs,
00240             sizeof(time_regs)) < 0) {
00241         pr_err("read time registers failed!");
00242         return -1;
00243     }
00244 
00245     return rtc_regs_to_time(time, &time_regs);
00246 }
00247 
00248 int RtcBase::set_rtc_time()
00249 {
00250     config_reg2_t reg;
00251 
00252     /* Toggle Set_RTC bit to set RTC date */
00253 
00254     if (read_register(regmap->config_reg2, (uint8_t *)&reg, 1) < 0) {
00255         pr_err("read time registers failed!");
00256         return -1;
00257     }
00258 
00259     reg.bits.set_rtc = CONFIG_REG2_SET_RTC_RTCPRGM;
00260     if (write_register(regmap->config_reg2, (uint8_t *)&reg, 1) < 0) {
00261         pr_err("write config2 register failed!");
00262         return -1;
00263     }
00264 
00265     /* SET_RTC bit should be kept high at least 10ms */
00266     ThisThread::sleep_for(10);
00267 
00268     reg.bits.set_rtc = CONFIG_REG2_SET_RTC_RTCRUN;
00269     if (write_register(regmap->config_reg2, (uint8_t *)&reg, 1) < 0) {
00270         pr_err("write config2 register failed!");
00271         return -1;
00272     }
00273 
00274     return 0;
00275 }
00276 
00277 int RtcBase::set_time(const struct tm *time)
00278 {
00279     rtc_time_regs_t time_regs;
00280 
00281     if (time == NULL) {
00282         pr_err("rtc_ctime is invalid!");
00283         return -1;
00284     }
00285 
00286     time_to_rtc_regs(&time_regs, time);
00287 
00288     if (write_register(regmap->seconds, (const uint8_t *) &time_regs,
00289             sizeof(time_regs)) < 0) {
00290         pr_err("read time registers failed!");
00291         return -1;
00292     }
00293 
00294     return set_rtc_time();
00295 }
00296 
00297 int RtcBase::nvram_write(const uint8_t *buffer, int offset, int length)
00298 {
00299     int totlen;
00300 
00301     if (regmap->ram_start == REG_NOT_AVAILABLE) {
00302         pr_err("Device does not have NVRAM!");
00303         return -1;
00304     }
00305 
00306     totlen = regmap->ram_end - regmap->ram_start + 1;
00307 
00308     if ((offset + length) > totlen) {
00309         return -1;
00310     }
00311 
00312     if (length == 0) {
00313         return 0;
00314     }
00315 
00316     if (write_register(regmap->ram_start + offset, buffer, length) < 0) {
00317         return -1;
00318     }
00319 
00320     return 0;
00321 }
00322 
00323 int RtcBase::nvram_read(uint8_t *buffer, int offset, int length)
00324 {
00325     int totlen;
00326 
00327     if (regmap->ram_start == REG_NOT_AVAILABLE) {
00328         pr_err("Device does not have NVRAM!");
00329         return -1;
00330     }
00331 
00332     totlen = regmap->ram_end - regmap->ram_start + 1;
00333 
00334     if ((offset + length) > totlen) {
00335         return -1;
00336     }
00337 
00338     if (length == 0) {
00339         return -1;
00340     }
00341 
00342     if (read_register(regmap->ram_start + offset, buffer, length) < 0) {
00343         return -1;
00344     }
00345 
00346     return 0;
00347 }
00348 
00349 int RtcBase::nvram_size()
00350 {
00351     if ((regmap->ram_start == REG_NOT_AVAILABLE) ||
00352             (regmap->ram_end == REG_NOT_AVAILABLE)) {
00353         return 0;
00354     }
00355 
00356     return regmap->ram_end - regmap->ram_start + 1;
00357 }
00358 
00359 int RtcBase::time_to_alarm_regs(alarm_regs_t &regs, const struct tm *alarm_time)
00360 {
00361     regs.sec.bcd.value = BIN2BCD(alarm_time->tm_sec);
00362     regs.min.bcd.value = BIN2BCD(alarm_time->tm_min);
00363     regs.hrs.bcd.value = BIN2BCD(alarm_time->tm_hour);
00364 
00365     if (regs.day_date.bits.dy_dt == 0) {
00366         /* Date match */
00367         regs.day_date.bcd_date.value = BIN2BCD(alarm_time->tm_mday);
00368     } else {
00369         /* Day match */
00370         regs.day_date.bcd_day.value = BIN2BCD(alarm_time->tm_wday);
00371     }
00372     regs.mon.bcd.value = BIN2BCD(alarm_time->tm_mon);
00373 
00374     return 0;
00375 }
00376 
00377 int RtcBase::alarm_regs_to_time(struct tm *alarm_time, const alarm_regs_t *regs)
00378 {
00379     alarm_time->tm_sec = BCD2BIN(regs->sec.bcd.value);
00380     alarm_time->tm_min = BCD2BIN(regs->min.bcd.value);
00381     alarm_time->tm_hour = BCD2BIN(regs->hrs.bcd.value);
00382 
00383     if (regs->day_date.bits.dy_dt == 0) { /* date */
00384         alarm_time->tm_mday = BCD2BIN(regs->day_date.bcd_date.value);
00385     } else { /* day */
00386         alarm_time->tm_wday = BCD2BIN(regs->day_date.bcd_day.value);
00387     }
00388 
00389     if (regmap->alm1_mon != REG_NOT_AVAILABLE) {
00390         alarm_time->tm_mon = BCD2BIN(regs->mon.bcd.value) - 1;
00391     }
00392 
00393     if (regmap->alm1_year != REG_NOT_AVAILABLE) {
00394         alarm_time->tm_year = BCD2BIN(regs->year.bcd.value) + 100;  /* XXX no century bit */
00395     }
00396 
00397     return 0;
00398 }
00399 
00400 int RtcBase::set_alarm_period(alarm_no_t alarm_no, alarm_regs_t &regs, alarm_period_t period)
00401 {
00402     regs.sec.bits.a1m1 = 1;
00403     regs.min.bits.a1m2 = 1;
00404     regs.hrs.bits.a1m3 = 1;
00405     regs.day_date.bits.a1m4 = 1;
00406     regs.mon.bits.a1m5 = 1;
00407     regs.mon.bits.a1m6 = 1;
00408     regs.day_date.bits.dy_dt = 1;
00409 
00410     switch (period) {
00411     case ALARM_PERIOD_ONETIME:
00412         if ((alarm_no == ALARM2) || (regmap->alm1_year == REG_NOT_AVAILABLE)) { /* not supported! */
00413             return -1;
00414         }
00415         regs.mon.bits.a1m6 = 0;
00416     case ALARM_PERIOD_YEARLY:
00417         if ((alarm_no == ALARM2) || (regmap->alm1_mon == REG_NOT_AVAILABLE)) { /* not supported! */
00418             return -1;
00419         }
00420         regs.mon.bits.a1m5 = 0;
00421     case ALARM_PERIOD_MONTHLY:
00422         regs.day_date.bits.dy_dt = 0;
00423     case ALARM_PERIOD_WEEKLY:
00424         regs.day_date.bits.a1m4 = 0;
00425     case ALARM_PERIOD_DAILY:
00426         regs.hrs.bits.a1m3 = 0;
00427     case ALARM_PERIOD_HOURLY:
00428         regs.min.bits.a1m2 = 0;
00429     case ALARM_PERIOD_EVERYMINUTE:
00430         regs.sec.bits.a1m1 = 0;
00431     case ALARM_PERIOD_EVERYSECOND:
00432         if ((alarm_no == ALARM2) && (period == ALARM_PERIOD_EVERYSECOND)) {
00433             return -1; /* Alarm2 does not support "once per second" alarm*/
00434         }
00435         break;
00436     default:
00437         return -1;
00438     }
00439 
00440     return 0;
00441 }
00442 
00443 int RtcBase::set_alarm_regs(alarm_no_t alarm_no, const alarm_regs_t *regs)
00444 {
00445     uint8_t *ptr_regs = (uint8_t *)regs;
00446     uint8_t off = 0;
00447     uint8_t dev_ba;
00448     uint8_t len = sizeof(alarm_regs_t);
00449 
00450     if (alarm_no == ALARM1) {
00451         dev_ba = regmap->alm1_sec;
00452         if (regmap->alm1_mon == REG_NOT_AVAILABLE) len -= 2; /* discard mon & year registers */
00453     } else {
00454         dev_ba = regmap->alm2_min;
00455         off = 1;    /* starts from min register */
00456         len -= 3;   /* discard min, mon & sec registers */
00457     }
00458 
00459     return write_register(dev_ba, &ptr_regs[off], len);
00460 }
00461 
00462 int RtcBase::get_alarm_regs(alarm_no_t alarm_no, alarm_regs_t *regs)
00463 {
00464     uint8_t *ptr_regs = (uint8_t *)regs;
00465     uint8_t off = 0;
00466     uint8_t dev_ba;
00467     uint8_t len = sizeof(alarm_regs_t);
00468 
00469     if (alarm_no == ALARM1) {
00470         dev_ba = regmap->alm1_sec;
00471         if (regmap->alm1_mon == REG_NOT_AVAILABLE) len -= 2; /* discard mon & year registers */
00472     } else {
00473         regs->sec.raw = 0;  /* zeroise second register for alarm2 */
00474         dev_ba = regmap->alm2_min;
00475         off = 1;    /* starts from min register (no sec register) */
00476         len -= 2;   /* discard mon & sec registers */
00477     }
00478 
00479     return read_register(dev_ba, &ptr_regs[off], len);
00480 }
00481 
00482 int RtcBase::set_alarm(alarm_no_t alarm_no, const struct tm *alarm_time, alarm_period_t period)
00483 {
00484     int ret;
00485     alarm_regs_t regs;
00486 
00487     ret = set_alarm_period(alarm_no, regs, period);
00488     if (ret) {
00489         return ret;
00490     }
00491 
00492     /* Convert time structure to alarm registers */
00493     ret = time_to_alarm_regs(regs, alarm_time);
00494     if (ret) {
00495         return ret;
00496     }
00497 
00498     ret = set_alarm_regs(alarm_no, &regs);
00499     if (ret) {
00500         return ret;
00501     }
00502 
00503     return 0;
00504 }
00505 
00506 int RtcBase::get_alarm(alarm_no_t alarm_no, struct tm *alarm_time, alarm_period_t *period, bool *is_enabled)
00507 {
00508     int ret;
00509     alarm_regs_t regs;
00510     uint8_t reg;
00511 
00512     ret = get_alarm_regs(alarm_no, &regs);
00513     if (ret) {
00514         return ret;
00515     }
00516 
00517     /* Convert alarm registers to time structure */
00518     ret = alarm_regs_to_time(alarm_time, &regs);
00519     if (ret) {
00520         return ret;
00521     }
00522 
00523     *period = (alarm_no == ALARM1) ? ALARM_PERIOD_EVERYSECOND : ALARM_PERIOD_EVERYMINUTE;
00524 
00525     if ((alarm_no == ALARM1) && (regs.sec.bits.a1m1 == 0)) *period = ALARM_PERIOD_EVERYMINUTE;
00526     if (regs.min.bits.a1m2 == 0) *period = ALARM_PERIOD_HOURLY;
00527     if (regs.hrs.bits.a1m3 == 0) *period = ALARM_PERIOD_DAILY;
00528     if (regs.day_date.bits.a1m4 == 0) *period = ALARM_PERIOD_WEEKLY;
00529     if (regs.day_date.bits.dy_dt == 0) *period = ALARM_PERIOD_MONTHLY;
00530     if ((alarm_no == ALARM1) && (regmap->alm1_mon != REG_NOT_AVAILABLE) && (regs.mon.bits.a1m5 == 0)) *period = ALARM_PERIOD_YEARLY;
00531     if ((alarm_no == ALARM1) && (regmap->alm1_mon != REG_NOT_AVAILABLE) && (regs.mon.bits.a1m6 == 0)) *period = ALARM_PERIOD_ONETIME;
00532 
00533     ret = read_register(regmap->int_en_reg, (uint8_t *)&reg, 1);
00534     if (ret) {
00535         return ret;
00536     }
00537 
00538     if (alarm_no == ALARM1) {
00539         *is_enabled = (reg & (1 << INTR_ID_ALARM1)) != 0;
00540     } else {
00541         *is_enabled = (reg & (1 << INTR_ID_ALARM2)) != 0;
00542     }
00543 
00544     return 0;
00545 }
00546 
00547 int RtcBase::set_power_mgmt_mode(power_mgmt_mode_t mode)
00548 {
00549     int ret;
00550     pwr_mgmt_reg_t reg;
00551 
00552     if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) {
00553         pr_err("Device does not support power mgmt!");
00554         return -1;
00555     }
00556 
00557     ret = read_register(regmap->pwr_mgmt_reg, (uint8_t *)&reg, 1);
00558     if (ret) {
00559         return ret;
00560     }
00561 
00562     reg.bits.d_mode = mode;
00563 
00564     ret = write_register(regmap->pwr_mgmt_reg, (uint8_t *)&reg, 1);
00565     if (ret) {
00566         return ret;
00567     }
00568 
00569     return 0;
00570 }
00571 
00572 int RtcBase::comparator_threshold_level(comp_thresh_t th)
00573 {
00574     int ret;
00575     config_reg2_t reg;
00576 
00577     if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) {
00578         pr_err("Device does not support analog comparator!");
00579         return -1;
00580     }
00581 
00582     ret = read_register(regmap->config_reg2, (uint8_t *)&reg, 1);
00583     if (ret) {
00584         return ret;
00585     }
00586 
00587     reg.bits.bref = th;
00588 
00589     ret = write_register(regmap->config_reg2, (uint8_t *)&reg, 1);
00590     if (ret) {
00591         return ret;
00592     }
00593 
00594     return 0;
00595 }
00596 
00597 int RtcBase::supply_select(power_mgmt_supply_t supply)
00598 {
00599     int ret;
00600     pwr_mgmt_reg_t reg;
00601 
00602     if (regmap->pwr_mgmt_reg == REG_NOT_AVAILABLE) {
00603         pr_err("Device does not support power mgmt!");
00604         return -1;
00605     }
00606 
00607     ret = read_register(regmap->pwr_mgmt_reg, (uint8_t *)&reg, 1);
00608     if (ret) {
00609         return ret;
00610     }
00611 
00612     switch (supply) {
00613     case POW_MGMT_SUPPLY_SEL_VCC:
00614         reg.bits.d_man_sel = 1;
00615         reg.bits.d_vback_sel = 0;
00616         break;
00617     case POW_MGMT_SUPPLY_SEL_AIN:
00618         reg.bits.d_man_sel = 1;
00619         reg.bits.d_vback_sel = 1;
00620         break;
00621     case POW_MGMT_SUPPLY_SEL_AUTO:
00622     default:
00623         reg.bits.d_man_sel = 0;
00624         break;
00625     }
00626 
00627     ret = write_register(regmap->pwr_mgmt_reg, (uint8_t *)&reg, 1);
00628     if (ret) {
00629         return ret;
00630     }
00631 
00632     return 0;
00633 }
00634 
00635 int RtcBase::trickle_charger_enable(trickle_charger_ohm_t res, bool diode)
00636 {
00637     int ret;
00638     struct {
00639         unsigned char ohm      : 2;
00640         unsigned char diode    : 1;
00641         unsigned char schottky : 1;
00642         unsigned char          : 4;
00643     } reg;
00644 
00645     if (regmap->trickle_reg == REG_NOT_AVAILABLE) { /* trickle charger not supported! */
00646         pr_err("Device does not support trickle charger!");
00647         return -1;
00648     }
00649 
00650     reg.ohm = res;
00651 
00652     reg.diode = (diode) ? 1 : 0;
00653 
00654     reg.schottky = 1; /* always enabled */
00655 
00656     ret = write_register(regmap->trickle_reg, (uint8_t *)&reg, 1);
00657     if (ret) {
00658         return ret;
00659     }
00660 
00661     return 0;
00662 }
00663 
00664 int RtcBase::trickle_charger_disable()
00665 {
00666     int ret;
00667     uint8_t reg;
00668 
00669     if (regmap->trickle_reg == REG_NOT_AVAILABLE) { /* trickle charger not supported! */
00670         pr_err("Device does not support trickle charger!");
00671         return -1;
00672     }
00673 
00674     reg = 0;
00675 
00676     ret = write_register(regmap->trickle_reg, &reg, 1);
00677     if (ret) {
00678         return ret;
00679     }
00680 
00681     return 0;
00682 }
00683 
00684 
00685 int RtcBase::set_output_square_wave_frequency(square_wave_out_freq_t freq)
00686 {
00687     int ret;
00688     config_reg1_t reg;
00689 
00690     ret = read_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00691     if (ret) {
00692         return ret;
00693     }
00694 
00695     reg.bits.rs = freq;
00696 
00697     ret = write_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00698     if (ret) {
00699         return ret;
00700     }
00701 
00702     return 0;
00703 }
00704 
00705 int RtcBase::set_clock_sync_delay(sync_delay_t delay)
00706 {
00707     int ret;
00708     clock_sync_reg_t reg;
00709 
00710     ret = read_register(regmap->clock_sync_delay, (uint8_t *)&reg, 1);
00711     if (ret) {
00712         return ret;
00713     }
00714 
00715     reg.bits.sync_delay = delay;
00716 
00717     ret = write_register(regmap->clock_sync_delay, (uint8_t *)&reg, 1);
00718     if (ret) {
00719         return ret;
00720     }
00721 
00722     return 0;
00723 }
00724 
00725 int RtcBase::set_clkin_frequency(clkin_freq_t freq)
00726 {
00727     int ret;
00728     config_reg1_t reg;
00729 
00730     ret = read_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00731     if (ret) {
00732         return ret;
00733     }
00734 
00735     reg.bits.clksel = freq;
00736 
00737     ret = write_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00738     if (ret) {
00739         return ret;
00740     }
00741 
00742     if (freq == CLKIN_FREQ_1HZ) {
00743         ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_1SEC);
00744     } else {
00745         ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_100MS);
00746     }
00747 
00748     return ret;
00749 }
00750 
00751 int RtcBase::configure_intb_clkout_pin(config_intb_clkout_pin_t sel)
00752 {
00753     int ret;
00754     config_reg1_t reg;
00755 
00756     ret = read_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00757     if (ret) {
00758         return ret;
00759     }
00760 
00761     reg.bits.intcn = (sel == CONFIGURE_PIN_AS_INTB) ? 1 : 0;
00762 
00763     ret = write_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00764     if (ret) {
00765         return ret;
00766     }
00767 
00768     return 0;
00769 }
00770 
00771 int RtcBase::configure_inta_clkin_pin(config_inta_clkin_pin_t sel)
00772 {
00773     int ret;
00774     config_reg1_t reg;
00775 
00776     ret = read_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00777     if (ret) {
00778         return ret;
00779     }
00780 
00781     reg.bits.eclk = (sel == CONFIGURE_PIN_AS_CLKIN) ? 1 : 0;
00782 
00783     ret = write_register(regmap->config_reg1, (uint8_t *)&reg, 1);
00784     if (ret) {
00785         return ret;
00786     }
00787 
00788     if (sel == CONFIGURE_PIN_AS_CLKIN) {
00789         /* Default synchronization delay for external clock mode */
00790         ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_1SEC);
00791     } else {
00792         /* Synchronization delay for internal oscillator mode */
00793         ret = set_clock_sync_delay(SYNC_DLY_LESS_THAN_20MS);
00794     }
00795 
00796     return ret;
00797 }
00798 
00799 int RtcBase::timer_init(uint8_t value, bool repeat, timer_freq_t freq)
00800 {
00801     int ret;
00802     timer_config_t reg_cfg;
00803 
00804     ret = read_register(regmap->timer_config, (uint8_t *)&reg_cfg, 1);
00805     if (ret) {
00806         return ret;
00807     }
00808 
00809     reg_cfg.bits.te = 0; /* timer is reset */
00810     reg_cfg.bits.tpause = 1; /* timer is paused */
00811     reg_cfg.bits.trpt = repeat ? 1 : 0; /* Timer repeat mode */
00812     reg_cfg.bits.tfs = freq;    /* Timer frequency */
00813 
00814     ret = write_register(regmap->timer_config, (uint8_t *)&reg_cfg, 1);
00815     if (ret) {
00816         return ret;
00817     }
00818 
00819     ret = write_register(regmap->timer_init, (uint8_t *)&value, 1);
00820     if (ret) {
00821         return ret;
00822     }
00823 
00824     return 0;
00825 }
00826 
00827 uint8_t RtcBase::timer_get()
00828 {
00829     int ret;
00830     uint8_t reg;
00831 
00832     ret = read_register(regmap->timer_count, (uint8_t *)&reg, 1);
00833     if (ret) {
00834         return (uint8_t) - 1;
00835     }
00836 
00837     return reg;
00838 }
00839 
00840 int RtcBase::timer_start()
00841 {
00842     int ret;
00843     timer_config_t reg;
00844 
00845     ret = read_register(regmap->timer_config, (uint8_t *)&reg, 1);
00846     if (ret) {
00847         return ret;
00848     }
00849 
00850     reg.bits.te = 1;
00851     reg.bits.tpause = 0;
00852 
00853     ret = write_register(regmap->timer_config, (uint8_t *)&reg, 1);
00854     if (ret) {
00855         return ret;
00856     }
00857 
00858     return 0;
00859 }
00860 
00861 int RtcBase::timer_pause()
00862 {
00863     int ret;
00864     timer_config_t reg;
00865 
00866     ret = read_register(regmap->timer_config, (uint8_t *)&reg, 1);
00867     if (ret) {
00868         return ret;
00869     }
00870 
00871     reg.bits.te = 1;
00872     reg.bits.tpause = 1;
00873 
00874     ret = write_register(regmap->timer_config, (uint8_t *)&reg, 1);
00875     if (ret) {
00876         return ret;
00877     }
00878 
00879     return 0;
00880 }
00881 
00882 int RtcBase::timer_continue()
00883 {
00884     int ret;
00885     timer_config_t reg;
00886 
00887     ret = read_register(regmap->timer_config, (uint8_t *)&reg, 1);
00888     if (ret) {
00889         return ret;
00890     }
00891 
00892     reg.bits.te = 1;
00893     reg.bits.tpause = 0;
00894 
00895     ret = write_register(regmap->timer_config, (uint8_t *)&reg, 1);
00896     if (ret) {
00897         return ret;
00898     }
00899 
00900     return 0;
00901 }
00902 
00903 int RtcBase::timer_stop()
00904 {
00905     int ret;
00906     timer_config_t reg;
00907 
00908     ret = read_register(regmap->timer_config, (uint8_t *)&reg, 1);
00909     if (ret) {
00910         return ret;
00911     }
00912 
00913     reg.bits.te = 0;
00914     reg.bits.tpause = 1;
00915 
00916     ret = write_register(regmap->timer_config, (uint8_t *)&reg, 1);
00917     if (ret) {
00918         return ret;
00919     }
00920 
00921     return 0;
00922 }
00923 
00924 int RtcBase::data_retention_mode_config(int state)
00925 {
00926     int ret;
00927     config_reg1_t cfg1;
00928     config_reg2_t cfg2;
00929 
00930     ret = read_register(regmap->config_reg1, (uint8_t *)&cfg1, 1);
00931     if (ret) {
00932         return ret;
00933     }
00934 
00935     ret = read_register(regmap->config_reg2, (uint8_t *)&cfg2, 1);
00936     if (ret) {
00937         return ret;
00938     }
00939 
00940     if (state) {
00941         cfg1.bits.osconz = 1;
00942         cfg2.bits.data_reten = 1;
00943     } else {
00944         cfg1.bits.osconz = 0;
00945         cfg2.bits.data_reten = 0;
00946     }
00947 
00948     ret = write_register(regmap->config_reg1, (uint8_t *)&cfg1, 1);
00949     if (ret) {
00950         return ret;
00951     }
00952 
00953     ret = write_register(regmap->config_reg2, (uint8_t *)&cfg2, 1);
00954     if (ret) {
00955         return ret;
00956     }
00957 
00958     return 0;
00959 }
00960 
00961 int RtcBase::data_retention_mode_enter()
00962 {
00963     return data_retention_mode_config(1);
00964 }
00965 
00966 int RtcBase::data_retention_mode_exit()
00967 {
00968     return data_retention_mode_config(0);
00969 }
00970 
00971 int RtcBase::i2c_timeout_config(int enable)
00972 {
00973     int ret;
00974     config_reg2_t reg;
00975 
00976     ret = read_register(regmap->config_reg2, (uint8_t *)&reg, 1);
00977     if (ret) {
00978         return ret;
00979     }
00980 
00981     reg.bits.i2c_timeout = (enable) ? 1 : 0;
00982 
00983     ret = write_register(regmap->config_reg2, (uint8_t *)&reg, 1);
00984     if (ret) {
00985         return ret;
00986     }
00987 
00988     return 0;
00989 }
00990 
00991 int RtcBase::i2c_timeout_enable()
00992 {
00993     return i2c_timeout_config(1);
00994 }
00995 
00996 int RtcBase::i2c_timeout_disable()
00997 {
00998     return i2c_timeout_config(0);
00999 }
01000 
01001 int RtcBase::irq_enable(intr_id_t id)
01002 {
01003     int ret;
01004     uint8_t reg;
01005 
01006     ret = read_register(regmap->int_en_reg, &reg, 1);
01007     if (ret) {
01008         return ret;
01009     }
01010 
01011     reg |= (1 << id);
01012 
01013     ret = write_register(regmap->int_en_reg, &reg, 1);
01014     if (ret) {
01015         return ret;
01016     }
01017 
01018     return 0;
01019 }
01020 
01021 int RtcBase::irq_disable(intr_id_t id)
01022 {
01023     int ret;
01024     uint8_t reg;
01025 
01026     ret = read_register(regmap->int_en_reg, &reg, 1);
01027     if (ret) {
01028         return ret;
01029     }
01030 
01031     reg &= ~(1 << id);
01032 
01033     ret = write_register(regmap->int_en_reg, &reg, 1);
01034     if (ret) {
01035         return ret;
01036     }
01037 
01038     return 0;
01039 }
01040 
01041 int RtcBase::irq_disable_all()
01042 {
01043     int ret;
01044     uint8_t reg = 0;
01045 
01046     ret = write_register(regmap->int_en_reg, &reg, 1);
01047     if (ret) {
01048         return ret;
01049     }
01050 
01051     return 0;
01052 }
01053 
01054 void RtcBase::set_intr_handler(intr_id_t id, interrupt_handler_function func, void *cb)
01055 {
01056     interrupt_handler_list[id].func = func;
01057     interrupt_handler_list[id].cb = cb;
01058 }
01059 
01060 void RtcBase::post_interrupt_work()
01061 {
01062     int ret;
01063     uint8_t reg, inten, mask;
01064 
01065 
01066     while (true) {
01067         Thread::signal_wait(POST_INTR_WORK_SIGNAL_ID);
01068 
01069         ret = read_register(regmap->int_status_reg, &reg, 1);
01070         if (ret) {
01071             pr_err("Read interrupt status register failed!");
01072         }
01073 
01074         ret = read_register(regmap->int_en_reg, &inten, 1);
01075         if (ret) {
01076             pr_err("Read interrupt enable register failed!");
01077         }
01078 
01079         for (int i = 0; i < INTR_ID_END; i++) {
01080             mask = (1 << i);
01081             if ((reg & mask) && (inten & mask)) {
01082                 if (interrupt_handler_list[i].func != NULL) {
01083                     interrupt_handler_list[i].func(interrupt_handler_list[i].cb);
01084                 }
01085             }
01086         }
01087     }
01088 }
01089 
01090 void RtcBase::interrupt_handler()
01091 {
01092     post_intr_work_thread->signal_set(POST_INTR_WORK_SIGNAL_ID);
01093 }
01094 
01095 int RtcBase::sw_reset_assert()
01096 {
01097     int ret;
01098     config_reg1_t config_reg1;
01099 
01100     ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1);
01101     if (ret < 0) {
01102         pr_err("read_register failed!");
01103         return ret;
01104     }
01105 
01106     config_reg1.bits.swrstn = 0;    /* Put device in reset state */
01107 
01108     ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1);
01109     if (ret < 0) {
01110         pr_err("read_register failed!");
01111         return ret;
01112     }
01113 
01114     return 0;
01115 }
01116 
01117 int RtcBase::sw_reset_release()
01118 {
01119     int ret;
01120     config_reg1_t config_reg1;
01121 
01122     ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1);
01123     if (ret < 0) {
01124         pr_err("read_register failed!");
01125         return ret;
01126     }
01127 
01128     config_reg1.bits.swrstn = 1;    /* Remove device from reset state */
01129 
01130     ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1);
01131     if (ret < 0) {
01132         pr_err("read_register failed!");
01133         return ret;
01134     }
01135 
01136     return 0;
01137 }
01138 
01139 int RtcBase::rtc_start()
01140 {
01141     int ret;
01142     config_reg1_t config_reg1;
01143 
01144     ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1);
01145     if (ret < 0) {
01146         pr_err("read_register failed!");
01147         return ret;
01148     }
01149 
01150     config_reg1.bits.osconz = 0;    /* Enable the oscillator */
01151 
01152     ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1);
01153     if (ret < 0) {
01154         pr_err("read_register failed!");
01155         return ret;
01156     }
01157 
01158     return 0;
01159 }
01160 
01161 int RtcBase::rtc_stop()
01162 {
01163     int ret;
01164     config_reg1_t config_reg1;
01165 
01166     ret = read_register(regmap->config_reg1, (uint8_t *) &config_reg1, 1);
01167     if (ret < 0) {
01168         pr_err("read_register failed!");
01169         return ret;
01170     }
01171 
01172     config_reg1.bits.osconz = 1;    /* Disable the oscillator */
01173 
01174     ret = write_register(regmap->config_reg1, (const uint8_t *) &config_reg1, 1);
01175     if (ret < 0) {
01176         pr_err("read_register failed!");
01177         return ret;
01178     }
01179 
01180     return 0;
01181 }