void rtc_write_ticks( uint8_t ch, uint32_t val ) { rtc_write( RTC_RAM_START + (ch*4) + 0, val & 0xff ); rtc_write( RTC_RAM_START + (ch*4) + 1, (val>>8) & 0xff ); rtc_write( RTC_RAM_START + (ch*4) + 2, (val>>16) & 0xff ); rtc_write( RTC_RAM_START + (ch*4) + 3, (val>>24) & 0xff ); }
/* * Reset the RTC. We also enable the oscillator output on the * SQW/INTB* pin and program it for 32,768 Hz output. Note that * according to the datasheet, turning on the square wave output * increases the current drain on the backup battery from about * 600 nA to 2uA. */ void rtc_reset (void) { rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2); }
/* * ioctl calls for this driver. Why return -ENOTTY upon error? Because * POSIX says so! */ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /* Some sanity checks. */ if (_IOC_TYPE(cmd) != RTC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > RTC_MAX_IOCTL) return -ENOTTY; switch (cmd) { case RTC_RD_TIME: { struct rtc_time tm; get_rtc_time(&tm); if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) { return -EFAULT; } return 0; } break; case RTC_SET_TIME: { #ifdef CONFIG_ETRAX_RTC_READONLY return -EPERM; #else int leap; int century; struct rtc_time tm; memset(&tm, 0, sizeof (struct rtc_time)); if (!capable(CAP_SYS_TIME)) return -EPERM; if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time))) return -EFAULT; /* Convert from struct tm to struct rtc_time. */ tm.tm_year += 1900; tm.tm_mon += 1; leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0; /* Perform some sanity checks. */ if ((tm.tm_year < 1970) || (tm.tm_mon > 12) || (tm.tm_mday == 0) || (tm.tm_mday > days_in_month[tm.tm_mon] + leap) || (tm.tm_hour >= 24) || (tm.tm_min >= 60) || (tm.tm_sec >= 60)) return -EINVAL; century = (tm.tm_year >= 2000) ? 0x80 : 0; tm.tm_year = tm.tm_year % 100; BIN_TO_BCD(tm.tm_year); BIN_TO_BCD(tm.tm_mday); BIN_TO_BCD(tm.tm_hour); BIN_TO_BCD(tm.tm_min); BIN_TO_BCD(tm.tm_sec); tm.tm_mon |= century; rtc_write(RTC_YEAR, tm.tm_year); rtc_write(RTC_MONTH, tm.tm_mon); rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday); rtc_write(RTC_HOURS, tm.tm_hour); rtc_write(RTC_MINUTES, tm.tm_min); rtc_write(RTC_SECONDS, tm.tm_sec); return 0; #endif /* !CONFIG_ETRAX_RTC_READONLY */ } case RTC_VLOW_RD: { int vl_bit = 0; if (rtc_read(RTC_SECONDS) & 0x80) { vl_bit = 1; printk(KERN_WARNING "%s: RTC Voltage Low - reliable " "date/time information is no longer guaranteed!\n", PCF8563_NAME); } if (copy_to_user((int *) arg, &vl_bit, sizeof(int))) return -EFAULT; return 0; } case RTC_VLOW_SET: { /* Clear the VL bit in the seconds register */ int ret = rtc_read(RTC_SECONDS); rtc_write(RTC_SECONDS, (ret & 0x7F)); return 0; } default: return -ENOTTY; } return 0; }
int rtc_get( struct rtc_time *tmp) { if (phantom_flag < 0) phantom_flag = get_phantom_flag(); if (phantom_flag) { unsigned char rtc[8]; phantom_rtc_read(RTC_BASE, rtc); tmp->tm_sec = bcd2bin(rtc[1] & 0x7f); tmp->tm_min = bcd2bin(rtc[2] & 0x7f); tmp->tm_hour = bcd2bin(rtc[3] & 0x1f); tmp->tm_wday = bcd2bin(rtc[4] & 0x7); tmp->tm_mday = bcd2bin(rtc[5] & 0x3f); tmp->tm_mon = bcd2bin(rtc[6] & 0x1f); tmp->tm_year = bcd2bin(rtc[7]) + 1900; tmp->tm_yday = 0; tmp->tm_isdst = 0; if( (rtc[3] & 0x80) && (rtc[3] & 0x40) ) tmp->tm_hour += 12; if (tmp->tm_year < 1970) tmp->tm_year += 100; } else { uchar sec, min, hour; uchar mday, wday, mon, year; int century; uchar reg_a; if (century_flag < 0) century_flag = get_century_flag(); reg_a = rtc_read( RTC_CONTROLA ); /* lock clock registers for read */ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ )); sec = rtc_read( RTC_SECONDS ); min = rtc_read( RTC_MINUTES ); hour = rtc_read( RTC_HOURS ); mday = rtc_read( RTC_DAY_OF_MONTH ); wday = rtc_read( RTC_DAY_OF_WEEK ); mon = rtc_read( RTC_MONTH ); year = rtc_read( RTC_YEAR ); century = rtc_read( RTC_CENTURY ); /* unlock clock registers after read */ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ )); tmp->tm_sec = bcd2bin( sec & 0x7F ); tmp->tm_min = bcd2bin( min & 0x7F ); tmp->tm_hour = bcd2bin( hour & 0x3F ); tmp->tm_mday = bcd2bin( mday & 0x3F ); tmp->tm_mon = bcd2bin( mon & 0x1F ); tmp->tm_wday = bcd2bin( wday & 0x07 ); if (century_flag) { tmp->tm_year = bcd2bin( year ) + ( bcd2bin( century & 0x3F ) * 100 ); } else { tmp->tm_year = bcd2bin( year ) + 1900; if (tmp->tm_year < 1970) tmp->tm_year += 100; } tmp->tm_yday = 0; tmp->tm_isdst= 0; } return 0; }
void pcf8563_writereg(int reg, unsigned char val) { rtc_write(reg, val); }
static void rtc_enable_update(void) { rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD); }
/* write powerkeys to enable rtc functions */ static int rtc_powerkey_init(void) { rtc_write(RTC_POWERKEY1, RTC_POWERKEY1_KEY); rtc_write(RTC_POWERKEY2, RTC_POWERKEY2_KEY); return rtc_write_trigger(); }
/* * set the rtc chip's idea of the time. * stupidly, some callers call with year unmolested; * and some call with year = year - 1900. thanks. */ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) { u8 mon, day, dow, hrs, min, sec, yrs, cen; unsigned long flags; /* * won't have to change this for a while */ if (rtc_tm->tm_year < 1900) { rtc_tm->tm_year += 1900; } if (rtc_tm->tm_year < 1970) { return -EINVAL; } yrs = rtc_tm->tm_year % 100; cen = rtc_tm->tm_year / 100; mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ day = rtc_tm->tm_mday; dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */ hrs = rtc_tm->tm_hour; min = rtc_tm->tm_min; sec = rtc_tm->tm_sec; if ((mon > 12) || (day == 0)) { return -EINVAL; } if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) { return -EINVAL; } if ((hrs >= 24) || (min >= 60) || (sec >= 60)) { return -EINVAL; } /* * each register is a different number of valid bits */ sec = bin2bcd(sec) & 0x7f; min = bin2bcd(min) & 0x7f; hrs = bin2bcd(hrs) & 0x3f; day = bin2bcd(day) & 0x3f; mon = bin2bcd(mon) & 0x1f; yrs = bin2bcd(yrs) & 0xff; cen = bin2bcd(cen) & 0xff; spin_lock_irqsave(&ds1511_lock, flags); rtc_disable_update(); rtc_write(cen, RTC_CENTURY); rtc_write(yrs, RTC_YEAR); rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON); rtc_write(day, RTC_DOM); rtc_write(hrs, RTC_HOUR); rtc_write(min, RTC_MIN); rtc_write(sec, RTC_SEC); rtc_write(dow, RTC_DOW); rtc_enable_update(); spin_unlock_irqrestore(&ds1511_lock, flags); return 0; }
static int __devinit omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { pr_debug("%s: no update irq?\n", pdev->name); return -ENOENT; } omap_rtc_alarm = platform_get_irq(pdev, 1); if (omap_rtc_alarm <= 0) { pr_debug("%s: no alarm irq?\n", pdev->name); return -ENOENT; } /* NOTE: using static mapping for RTC registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res && res->start != OMAP_RTC_BASE) { pr_debug("%s: RTC registers at %08x, expected %08x\n", pdev->name, (unsigned) res->start, OMAP_RTC_BASE); return -ENOENT; } if (res) mem = request_mem_region(res->start, res->end - res->start + 1, pdev->name); else mem = NULL; if (!mem) { pr_debug("%s: RTC registers at %08x are not free\n", pdev->name, OMAP_RTC_BASE); return -EBUSY; } rtc = rtc_device_register(pdev->name, &pdev->dev, &omap_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { pr_debug("%s: can't register RTC device, err %ld\n", pdev->name, PTR_ERR(rtc)); goto fail; } platform_set_drvdata(pdev, rtc); class_set_devdata(&rtc->class_dev, mem); /* clear pending irqs, and set 1/second periodic, * which we'll use instead of update irqs */ rtc_write(0, OMAP_RTC_INTERRUPTS_REG); /* clear old status */ reg = rtc_read(OMAP_RTC_STATUS_REG); if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { pr_info("%s: RTC power up reset detected\n", pdev->name); rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG); } if (reg & (u8) OMAP_RTC_STATUS_ALARM) rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG); /* handle periodic and alarm irqs */ if (request_irq(omap_rtc_timer, rtc_irq, SA_INTERRUPT, rtc->class_dev.class_id, &rtc->class_dev)) { pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_timer); goto fail0; } if (request_irq(omap_rtc_alarm, rtc_irq, SA_INTERRUPT, rtc->class_dev.class_id, &rtc->class_dev)) { pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_alarm); goto fail1; } /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ reg = rtc_read(OMAP_RTC_CTRL_REG); if (reg & (u8) OMAP_RTC_CTRL_STOP) pr_info("%s: already running\n", pdev->name); /* force to 24 hour mode */ new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); new_ctrl |= OMAP_RTC_CTRL_STOP; /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: * * - Boards wired so that RTC_WAKE_INT does something, and muxed * right (W13_1610_RTC_WAKE_INT is the default after chip reset), * should initialize the device wakeup flag appropriately. * * - Boards wired so RTC_ON_nOFF is used as the reset signal, * rather than nPWRON_RESET, should forcibly enable split * power mode. (Some chip errata report that RTC_CTRL_SPLIT * is write-only, and always reads as zero...) */ device_init_wakeup(&pdev->dev, 0); if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) pr_info("%s: split power mode\n", pdev->name); if (reg != new_ctrl) rtc_write(new_ctrl, OMAP_RTC_CTRL_REG); return 0; fail1: free_irq(omap_rtc_timer, NULL); fail0: rtc_device_unregister(rtc); fail: release_resource(mem); return -EIO; }
static void rtc_tasklet_handler(unsigned long data) { u16 irqsta, pdn1, pdn2, spar1; bool pwron_alm = false; spin_lock(&rtc_lock); irqsta = rtc_read(RTC_IRQ_STA); /* read clear */ if (unlikely(!(irqsta & RTC_IRQ_STA_AL))) { #ifndef USER_BUILD_KERNEL if (irqsta & RTC_IRQ_STA_LP) rtc_lp_exception(); #endif spin_unlock(&rtc_lock); enable_irq(MT6573_RTC_IRQ_LINE); return; } #if RTC_RELPWR_WHEN_XRST { /* set AUTO bit because AUTO = 0 when PWREN = 1 and alarm occurs */ u16 bbpu = rtc_read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_AUTO; rtc_write(RTC_BBPU, bbpu); rtc_write_trigger(); } #endif pdn1 = rtc_read(RTC_PDN1); pdn2 = rtc_read(RTC_PDN2); spar1 = rtc_read(RTC_SPAR1); if (pdn1 & 0x0080) { /* power-on time is available */ u16 now_sec, now_min, now_hou, now_dom, now_mth; u16 irqen, min, hou, dom, mth; now_sec = rtc_read(RTC_TC_SEC); now_min = rtc_read(RTC_TC_MIN); now_hou = rtc_read(RTC_TC_HOU); now_dom = rtc_read(RTC_TC_DOM); now_mth = rtc_read(RTC_TC_MTH); if (rtc_read(RTC_TC_SEC) < now_sec) { /* SEC has carried */ now_sec = rtc_read(RTC_TC_SEC); now_min = rtc_read(RTC_TC_MIN); now_hou = rtc_read(RTC_TC_HOU); now_dom = rtc_read(RTC_TC_DOM); now_mth = rtc_read(RTC_TC_MTH); } min = spar1 & 0x003f; hou = (spar1 & 0x07c0) >> 6; dom = (spar1 & 0xf800) >> 11; mth = pdn2 & 0x000f; if (now_mth == mth && now_dom == dom && now_hou == hou && now_min == min && now_sec >= (RTC_PWRON_SEC - 1) && now_sec <= (RTC_PWRON_SEC + 4)) { rtc_write(RTC_PDN1, pdn1 & ~0x0080); rtc_write(RTC_PDN2, pdn2 | 0x0010); rtc_write_trigger(); pwron_alm = true; } else { /* set power-on alarm when power-on time is available */ rtc_write(RTC_AL_MTH, mth); rtc_write(RTC_AL_DOM, dom); rtc_write(RTC_AL_HOU, hou); rtc_write(RTC_AL_MIN, min); rtc_write(RTC_AL_SEC, RTC_PWRON_SEC); rtc_write(RTC_AL_MASK, 0x0050); /* mask YEA and DOW */ rtc_write_trigger(); irqen = rtc_read(RTC_IRQ_EN) | RTC_IRQ_EN_ONESHOT_AL; rtc_write(RTC_IRQ_EN, irqen); rtc_write_trigger(); } }
void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; #if RTC_LSI if (rtc_inited) return; rtc_inited = 1; #endif RtcHandle.Instance = RTC; #if !RTC_LSI // Enable LSE Oscillator RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! RCC_OscInitStruct.LSEState = RCC_LSE_ON; // External 32.768 kHz clock on OSC_IN/OSC_OUT RCC_OscInitStruct.LSIState = RCC_LSI_OFF; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) { // Check if LSE has started correctly // Connect LSE to RTC __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); } else { error("Cannot initialize RTC with LSE\n"); } #else // Enable Power clock __PWR_CLK_ENABLE(); // Enable access to Backup domain HAL_PWR_EnableBkUpAccess(); // Reset Backup domain __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); // Enable LSI clock RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! RCC_OscInitStruct.LSEState = RCC_LSE_OFF; RCC_OscInitStruct.LSIState = RCC_LSI_ON; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { error("Cannot initialize RTC with LSI\n"); } // Connect LSI to RTC __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); #endif // Enable RTC __HAL_RCC_RTC_ENABLE(); RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { error("RTC error: RTC initialization failed."); } #if DEVICE_LOWPOWERTIMER #if RTC_LSI rtc_write(0); #else if (!rtc_isenabled()) { rtc_write(0); } #endif NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_DisableIRQ(RTC_IRQn); NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler); NVIC_EnableIRQ(RTC_IRQn); #endif }
static void rtc_write_trigger(void) { rtc_write(RTC_WRTGR, 1); rtc_busy_wait(); }
void rtc_init(void) { /* step #1: initialize SERCOM */ // enable clock to SERCOM3 - 8MHz core clock, 32KHz slow clock GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM3_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM3_GCLK_ID_SLOW) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(2); PM->APBCMASK.reg |= PM_APBCMASK_SERCOM3; // configure PA22/PA23 as SC3[0] and SC3[1] respectively PORT->Group[0].PMUX[23/2].bit.PMUXO = PORT_PMUX_PMUXO_C_Val; PORT->Group[0].PMUX[22/2].bit.PMUXE = PORT_PMUX_PMUXE_C_Val; PORT->Group[0].PINCFG[23].bit.PMUXEN = 1; PORT->Group[0].PINCFG[22].bit.PMUXEN = 1; // initialize SERCOM3 into TWI mode // high/low time periods are (5+N) GCLK cycles // values of 5 give 400KHz TWI speed // values of 15 give 200KHz TWI speed // values of 75 gives 50KHz TWI speed SERCOM3->I2CM.BAUD.reg = \ (15<<SERCOM_I2CM_BAUD_BAUD_Pos)| \ (15<<SERCOM_I2CM_BAUD_BAUDLOW_Pos); while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); // enable TWI mode SERCOM3->I2CM.CTRLA.reg = \ (3<<SERCOM_I2CM_CTRLA_SDAHOLD_Pos) |\ (0<<SERCOM_I2CM_CTRLA_INACTOUT_Pos) |\ (0<<SERCOM_I2CM_CTRLA_PINOUT_Pos) |\ SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |\ (0<<SERCOM_I2CM_CTRLA_ENABLE_Pos); while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); // don't enable smart mode SERCOM3->I2CM.CTRLB.reg = 0; while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); // force TWI unit into idle mode SERCOM3->I2CM.STATUS.bit.BUSSTATE = 1; while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); // enable! SERCOM3->I2CM.CTRLA.bit.ENABLE = 1; while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); // force TWI unit into idle mode SERCOM3->I2CM.STATUS.bit.BUSSTATE = 1; while(SERCOM3->I2CM.STATUS.bit.SYNCBUSY); /* step #2: initialize RTC chip itself */ // read entire RTC chip rtc_read(0x00,(uint8_t *) &rtc_data,sizeof(rtc_data)); // check config uint8_t csr_int_cache = rtc_data.csr.csr_int; // WRTC=1 (enable RTC) // FOBATB=1 (disable /INT output) // FO=10 (1Hz frequency output) rtc_data.csr.csr_int = (1<<6)|(1<<4)|(10<<0); // clear timestamps, VDD brownout = 2.8V, battery brownouts = see datasheet. rtc_data.csr.csr_pwr_vdd = (1<<7)|(2<<0); rtc_data.csr.csr_pwr_vbat = (0<<6)|(3<<3)|(3<<0); // rest of CSR registers is trimming - leave alone! // disable alarms rtc_data.alarm.alarm_sca0 = 0; rtc_data.alarm.alarm_mna0 = 0; rtc_data.alarm.alarm_hra0 = 0; rtc_data.alarm.alarm_dta0 = 0; rtc_data.alarm.alarm_moa0 = 0; rtc_data.alarm.alarm_dwa0 = 0; // disable DST rtc_data.dstcr.dstcr_DstMoFd = 0; // write everything back to RTC rtc_write(0x07,&rtc_data.csr.csr_sr,42); // if RTCF was set, write new time (00:00, jan 1, 2016) if (csr_int_cache & 0x01) { rtc_data.rtc.rtc_sc = 0x00; rtc_data.rtc.rtc_mn = 0x00; rtc_data.rtc.rtc_hr = 0x00; rtc_data.rtc.rtc_dt = 0x01; rtc_data.rtc.rtc_mo = 0x01; rtc_data.rtc.rtc_yr = 0x16; rtc_data.rtc.rtc_dw = 0; rtc_write(0x00,(uint8_t *) &rtc_data, 7); } }
void rtc_reset (void) { rtc_write (RTC_CTL_REG_ADDR, RTC_DS1337_RESET_VAL); }
static inline void rtc_write_alarm(uint8_t val, enum ds1511reg reg) { rtc_write((val | 0x80), reg); }
/* * ioctl calls for this driver. Why return -ENOTTY upon error? Because * POSIX says so! */ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /* Some sanity checks. */ if (_IOC_TYPE(cmd) != RTC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > RTC_MAX_IOCTL) return -ENOTTY; switch (cmd) { case RTC_RD_TIME: { struct rtc_time tm; mutex_lock(&rtc_lock); memset(&tm, 0, sizeof tm); get_rtc_time(&tm); if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) { mutex_unlock(&rtc_lock); return -EFAULT; } mutex_unlock(&rtc_lock); return 0; } case RTC_SET_TIME: { int leap; int year; int century; struct rtc_time tm; memset(&tm, 0, sizeof tm); if (!capable(CAP_SYS_TIME)) return -EPERM; if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm)) return -EFAULT; /* Convert from struct tm to struct rtc_time. */ tm.tm_year += 1900; tm.tm_mon += 1; /* * Check if tm.tm_year is a leap year. A year is a leap * year if it is divisible by 4 but not 100, except * that years divisible by 400 _are_ leap years. */ year = tm.tm_year; leap = (tm.tm_mon == 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); /* Perform some sanity checks. */ if ((tm.tm_year < 1970) || (tm.tm_mon > 12) || (tm.tm_mday == 0) || (tm.tm_mday > days_in_month[tm.tm_mon] + leap) || (tm.tm_wday >= 7) || (tm.tm_hour >= 24) || (tm.tm_min >= 60) || (tm.tm_sec >= 60)) return -EINVAL; century = (tm.tm_year >= 2000) ? 0x80 : 0; tm.tm_year = tm.tm_year % 100; tm.tm_year = bin2bcd(tm.tm_year); tm.tm_mon = bin2bcd(tm.tm_mon); tm.tm_mday = bin2bcd(tm.tm_mday); tm.tm_hour = bin2bcd(tm.tm_hour); tm.tm_min = bin2bcd(tm.tm_min); tm.tm_sec = bin2bcd(tm.tm_sec); tm.tm_mon |= century; mutex_lock(&rtc_lock); rtc_write(RTC_YEAR, tm.tm_year); rtc_write(RTC_MONTH, tm.tm_mon); rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */ rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday); rtc_write(RTC_HOURS, tm.tm_hour); rtc_write(RTC_MINUTES, tm.tm_min); rtc_write(RTC_SECONDS, tm.tm_sec); mutex_unlock(&rtc_lock); return 0; } case RTC_VL_READ: if (voltage_low) printk(KERN_ERR "%s: RTC Voltage Low - " "reliable date/time information is no " "longer guaranteed!\n", PCF8563_NAME); if (copy_to_user((int *) arg, &voltage_low, sizeof(int))) return -EFAULT; return 0; case RTC_VL_CLR: { /* Clear the VL bit in the seconds register in case * the time has not been set already (which would * have cleared it). This does not really matter * because of the cached voltage_low value but do it * anyway for consistency. */ int ret = rtc_read(RTC_SECONDS); rtc_write(RTC_SECONDS, (ret & 0x7F)); /* Clear the cached value. */ voltage_low = 0; return 0; } default: return -ENOTTY; } return 0; }
static inline void rtc_disable_update(void) { rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD); }
static int omap_rtc_probe(struct platform_device *pdev) { struct omap_rtc *rtc; struct resource *res; u8 reg, mask, new_ctrl; const struct platform_device_id *id_entry; const struct of_device_id *of_id; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; of_id = of_match_device(omap_rtc_of_match, &pdev->dev); if (of_id) { rtc->type = of_id->data; rtc->is_pmic_controller = rtc->type->has_pmic_mode && of_property_read_bool(pdev->dev.of_node, "system-power-controller"); } else { id_entry = platform_get_device_id(pdev); rtc->type = (void *)id_entry->driver_data; } rtc->irq_timer = platform_get_irq(pdev, 0); if (rtc->irq_timer <= 0) return -ENOENT; rtc->irq_alarm = platform_get_irq(pdev, 1); if (rtc->irq_alarm <= 0) return -ENOENT; rtc->clk = devm_clk_get(&pdev->dev, "ext-clk"); if (!IS_ERR(rtc->clk)) rtc->has_ext_clk = true; else rtc->clk = devm_clk_get(&pdev->dev, "int-clk"); if (!IS_ERR(rtc->clk)) clk_prepare_enable(rtc->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); rtc->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(rtc->base)) { clk_disable_unprepare(rtc->clk); return PTR_ERR(rtc->base); } platform_set_drvdata(pdev, rtc); /* Enable the clock/module so that we can access the registers */ pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); rtc->type->unlock(rtc); /* * disable interrupts * * NOTE: ALARM2 is not cleared on AM3352 if rtc_write (writeb) is used */ rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, 0); /* enable RTC functional clock */ if (rtc->type->has_32kclk_en) { reg = rtc_read(rtc, OMAP_RTC_OSC_REG); rtc_writel(rtc, OMAP_RTC_OSC_REG, reg | OMAP_RTC_OSC_32KCLK_EN); } /* clear old status */ reg = rtc_read(rtc, OMAP_RTC_STATUS_REG); mask = OMAP_RTC_STATUS_ALARM; if (rtc->type->has_pmic_mode) mask |= OMAP_RTC_STATUS_ALARM2; if (rtc->type->has_power_up_reset) { mask |= OMAP_RTC_STATUS_POWER_UP; if (reg & OMAP_RTC_STATUS_POWER_UP) dev_info(&pdev->dev, "RTC power up reset detected\n"); } if (reg & mask) rtc_write(rtc, OMAP_RTC_STATUS_REG, reg & mask); /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ reg = rtc_read(rtc, OMAP_RTC_CTRL_REG); if (reg & OMAP_RTC_CTRL_STOP) dev_info(&pdev->dev, "already running\n"); /* force to 24 hour mode */ new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT | OMAP_RTC_CTRL_AUTO_COMP); new_ctrl |= OMAP_RTC_CTRL_STOP; /* * BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: * * - Device wake-up capability setting should come through chip * init logic. OMAP1 boards should initialize the "wakeup capable" * flag in the platform device if the board is wired right for * being woken up by RTC alarm. For OMAP-L138, this capability * is built into the SoC by the "Deep Sleep" capability. * * - Boards wired so RTC_ON_nOFF is used as the reset signal, * rather than nPWRON_RESET, should forcibly enable split * power mode. (Some chip errata report that RTC_CTRL_SPLIT * is write-only, and always reads as zero...) */ if (new_ctrl & OMAP_RTC_CTRL_SPLIT) dev_info(&pdev->dev, "split power mode\n"); if (reg != new_ctrl) rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); /* * If we have the external clock then switch to it so we can keep * ticking across suspend. */ if (rtc->has_ext_clk) { reg = rtc_read(rtc, OMAP_RTC_OSC_REG); reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE; reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC; rtc_writel(rtc, OMAP_RTC_OSC_REG, reg); } rtc->type->lock(rtc); device_init_wakeup(&pdev->dev, true); rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err; } rtc->rtc->ops = &omap_rtc_ops; omap_rtc_nvmem_config.priv = rtc; /* handle periodic and alarm irqs */ ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, dev_name(&rtc->rtc->dev), rtc); if (ret) goto err; if (rtc->irq_timer != rtc->irq_alarm) { ret = devm_request_irq(&pdev->dev, rtc->irq_alarm, rtc_irq, 0, dev_name(&rtc->rtc->dev), rtc); if (ret) goto err; } if (rtc->is_pmic_controller) { if (!pm_power_off) { omap_rtc_power_off_rtc = rtc; pm_power_off = omap_rtc_power_off; } } /* Support ext_wakeup pinconf */ rtc_pinctrl_desc.name = dev_name(&pdev->dev); rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc); if (IS_ERR(rtc->pctldev)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); ret = PTR_ERR(rtc->pctldev); goto err; } ret = rtc_register_device(rtc->rtc); if (ret) goto err; rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config); return 0; err: clk_disable_unprepare(rtc->clk); device_init_wakeup(&pdev->dev, false); rtc->type->lock(rtc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; }
static int ds1511_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; struct resource *res; struct rtc_plat_data *pdata; int ret = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; pdata->size = resource_size(res); if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, pdev->name)) return -EBUSY; ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size); if (!ds1511_base) return -ENOMEM; pdata->ioaddr = ds1511_base; pdata->irq = platform_get_irq(pdev, 0); /* * turn on the clock and the crystal, etc. */ rtc_write(0, RTC_CMD); rtc_write(0, RTC_CMD1); /* * clear the wdog counter */ rtc_write(0, DS1511_WD_MSEC); rtc_write(0, DS1511_WD_SEC); /* * start the clock */ rtc_enable_update(); /* * check for a dying bat-tree */ if (rtc_read(RTC_CMD1) & DS1511_BLF1) dev_warn(&pdev->dev, "voltage-low detected.\n"); spin_lock_init(&pdata->lock); platform_set_drvdata(pdev, pdata); /* * if the platform has an interrupt in mind for this device, * then by all means, set it */ if (pdata->irq > 0) { rtc_read(RTC_CMD1); if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = 0; } } rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &ds1511_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); pdata->rtc = rtc; ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); return ret; }
static int __init omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; const struct platform_device_id *id_entry; const struct of_device_id *of_id; of_id = of_match_device(omap_rtc_of_match, &pdev->dev); if (of_id) pdev->id_entry = of_id->data; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { pr_debug("%s: no update irq?\n", pdev->name); return -ENOENT; } omap_rtc_alarm = platform_get_irq(pdev, 1); if (omap_rtc_alarm <= 0) { pr_debug("%s: no alarm irq?\n", pdev->name); return -ENOENT; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { pr_debug("%s: RTC resource data missing\n", pdev->name); return -ENOENT; } mem = request_mem_region(res->start, resource_size(res), pdev->name); if (!mem) { pr_debug("%s: RTC registers at %08x are not free\n", pdev->name, res->start); return -EBUSY; } rtc_base = ioremap(res->start, resource_size(res)); if (!rtc_base) { pr_debug("%s: RTC registers can't be mapped\n", pdev->name); goto fail; } /* Enable the clock/module so that we can access the registers */ pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); id_entry = platform_get_device_id(pdev); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); } rtc = rtc_device_register(pdev->name, &pdev->dev, &omap_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { pr_debug("%s: can't register RTC device, err %ld\n", pdev->name, PTR_ERR(rtc)); goto fail0; } platform_set_drvdata(pdev, rtc); dev_set_drvdata(&rtc->dev, mem); /* clear pending irqs, and set 1/second periodic, * which we'll use instead of update irqs */ rtc_write(0, OMAP_RTC_INTERRUPTS_REG); /* clear old status */ reg = rtc_read(OMAP_RTC_STATUS_REG); if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { pr_info("%s: RTC power up reset detected\n", pdev->name); rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG); } if (reg & (u8) OMAP_RTC_STATUS_ALARM) rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG); /* handle periodic and alarm irqs */ if (request_irq(omap_rtc_timer, rtc_irq, 0, dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_timer); goto fail1; } if ((omap_rtc_timer != omap_rtc_alarm) && (request_irq(omap_rtc_alarm, rtc_irq, 0, dev_name(&rtc->dev), rtc))) { pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_alarm); goto fail2; } /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ reg = rtc_read(OMAP_RTC_CTRL_REG); if (reg & (u8) OMAP_RTC_CTRL_STOP) pr_info("%s: already running\n", pdev->name); /* force to 24 hour mode */ new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); new_ctrl |= OMAP_RTC_CTRL_STOP; /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: * * - Device wake-up capability setting should come through chip * init logic. OMAP1 boards should initialize the "wakeup capable" * flag in the platform device if the board is wired right for * being woken up by RTC alarm. For OMAP-L138, this capability * is built into the SoC by the "Deep Sleep" capability. * * - Boards wired so RTC_ON_nOFF is used as the reset signal, * rather than nPWRON_RESET, should forcibly enable split * power mode. (Some chip errata report that RTC_CTRL_SPLIT * is write-only, and always reads as zero...) */ if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) pr_info("%s: split power mode\n", pdev->name); if (reg != new_ctrl) rtc_write(new_ctrl, OMAP_RTC_CTRL_REG); return 0; fail2: free_irq(omap_rtc_timer, rtc); fail1: rtc_device_unregister(rtc); fail0: if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(rtc_base); fail: release_mem_region(mem->start, resource_size(mem)); return -EIO; }
static void dcxo_init(void) { /* Buffer setting */ rtc_write(PMIC_RG_DCXO_CW15, 0xA2AA); rtc_write(PMIC_RG_DCXO_CW13, 0x98E9); rtc_write(PMIC_RG_DCXO_CW16, 0x9855); /* 26M enable control */ /* Enable clock buffer XO_SOC, XO_CEL */ rtc_write(PMIC_RG_DCXO_CW00, 0x4805); rtc_write(PMIC_RG_DCXO_CW11, 0x8000); /* Load thermal coefficient */ rtc_write(PMIC_RG_TOP_TMA_KEY, 0x9CA7); rtc_write(PMIC_RG_DCXO_CW21, 0x12A7); rtc_write(PMIC_RG_DCXO_ELR0, 0xD004); rtc_write(PMIC_RG_TOP_TMA_KEY, 0x0000); /* Adjust OSC FPM setting */ rtc_write(PMIC_RG_DCXO_CW07, 0x8FFE); /* Re-Calibrate OSC current */ rtc_write(PMIC_RG_DCXO_CW09, 0x008F); udelay(100); rtc_write(PMIC_RG_DCXO_CW09, 0x408F); mdelay(5); }
static void omap_rtc_shutdown(struct platform_device *pdev) { rtc_write(0, OMAP_RTC_INTERRUPTS_REG); }
void rtc_set( struct rtc_time *tmp ) { if (phantom_flag < 0) phantom_flag = get_phantom_flag(); if (phantom_flag) { uint year; unsigned char rtc[8]; year = tmp->tm_year; year -= (year < 2000) ? 1900 : 2000; rtc[0] = bin2bcd(0); rtc[1] = bin2bcd(tmp->tm_sec); rtc[2] = bin2bcd(tmp->tm_min); rtc[3] = bin2bcd(tmp->tm_hour); rtc[4] = bin2bcd(tmp->tm_wday); rtc[5] = bin2bcd(tmp->tm_mday); rtc[6] = bin2bcd(tmp->tm_mon); rtc[7] = bin2bcd(year); phantom_rtc_write(RTC_BASE, rtc); } else { uchar reg_a; if (century_flag < 0) century_flag = get_century_flag(); /* lock clock registers for write */ reg_a = rtc_read( RTC_CONTROLA ); rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE )); rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon )); rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday )); rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday )); rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour )); rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min )); rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec )); /* break year up into century and year in century */ if (century_flag) { rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 )); rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 )); reg_a &= 0xc0; reg_a |= bin2bcd( tmp->tm_year / 100 ); } else { rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year - ((tmp->tm_year < 2000) ? 1900 : 2000))); } /* unlock clock registers after read */ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE )); } }
int settime_old(todr_chip_handle_t tcr, struct clock_ymdhms *dt) { u_char h; /* Stop the clock */ rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) & ~RTC_START); #ifdef RTC_DEBUG printf("Setting RTC to 0x%08x. Regs before:\n",secs); rtc_print(); #endif rtc_write(RTC_SEC,TOBCD(dt->dt_sec)); rtc_write(RTC_MIN,TOBCD(dt->dt_min)); h = rtc_read(RTC_HRS); if (h & 0x80) { /* time is am/pm format */ if (dt->dt_hour == 0) { rtc_write(RTC_HRS,TOBCD(12)|0x80); } else if (dt->dt_hour < 12) { /* am */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour)|0x80); } else if (dt->dt_hour == 12) { rtc_write(RTC_HRS,TOBCD(12)|0x80|0x20); } else /* pm */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour-12)|0x80|0x20); } else { /* time is 24 hour format */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour)); } rtc_write(RTC_DAY,TOBCD(dt->dt_wday)); rtc_write(RTC_DATE,TOBCD(dt->dt_day)); rtc_write(RTC_MON,TOBCD(dt->dt_mon)); rtc_write(RTC_YR,TOBCD(dt->dt_year%100)); #ifdef RTC_DEBUG printf("Regs after:\n",secs); rtc_print(); #endif /* restart the clock */ rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) | RTC_START); return 0; }
int __init pcf8563_init(void) { static int res; static int first = 1; if (!first) return res; first = 0; /* Initiate the i2c protocol. */ res = i2c_init(); if (res < 0) { printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n"); return res; } /* * First of all we need to reset the chip. This is done by * clearing control1, control2 and clk freq and resetting * all alarms. */ if (rtc_write(RTC_CONTROL1, 0x00) < 0) goto err; if (rtc_write(RTC_CONTROL2, 0x00) < 0) goto err; if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0) goto err; if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0) goto err; /* Reset the alarms. */ if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0) goto err; if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0) goto err; if (rtc_write(RTC_DAY_ALARM, 0x80) < 0) goto err; if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0) goto err; /* Check for low voltage, and warn about it. */ if (rtc_read(RTC_SECONDS) & 0x80) { voltage_low = 1; printk(KERN_WARNING "%s: RTC Voltage Low - reliable " "date/time information is no longer guaranteed!\n", PCF8563_NAME); } return res; err: printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME); res = -1; return res; }
/* * sys_rtc_write * Description: write system RTC * INPUTS: int32_t fd -- file descriptor void* buf -- buffer address int32_t nbytes -- number of bytes pcb_t* mypcb -- Process control block * OUTPUTS: None * RETURN: None * SIDE EFFECTS: None */ extern int32_t sys_rtc_write(int32_t fd, const void* buf, int32_t nbytes, pcb_t* mypcb) { return rtc_write(fd, buf, nbytes); }