static int at32_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); int ret = 0; spin_lock_irq(&rtc->lock); switch (cmd) { case RTC_AIE_ON: if (rtc_readl(rtc, VAL) > rtc->alarm_time) { ret = -EINVAL; break; } rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); rtc_writel(rtc, IER, RTC_BIT(IER_TOPI)); break; case RTC_AIE_OFF: rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) & ~RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); break; default: ret = -ENOIOCTLCMD; break; } spin_unlock_irq(&rtc->lock); return ret; }
static int at32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); int ret = 0; spin_lock_irq(&rtc->lock); if (enabled) { if (rtc_readl(rtc, VAL) > rtc->alarm_time) { ret = -EINVAL; goto out; } rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); rtc_writel(rtc, IER, RTC_BIT(IER_TOPI)); } else { rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) & ~RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); } out: spin_unlock_irq(&rtc->lock); return ret; }
static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); unsigned long rtc_unix_time; unsigned long alarm_unix_time; int ret; rtc_unix_time = rtc_readl(rtc, VAL); ret = rtc_tm_to_time(&alrm->time, &alarm_unix_time); if (ret) return ret; if (alarm_unix_time < rtc_unix_time) return -EINVAL; spin_lock_irq(&rtc->lock); rtc->alarm_time = alarm_unix_time; rtc_writel(rtc, TOP, rtc->alarm_time); if (alrm->enabled) rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); else rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) & ~RTC_BIT(CTRL_TOPEN)); spin_unlock_irq(&rtc->lock); return ret; }
static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); spin_lock_irq(&rtc->lock); rtc_time_to_tm(rtc->alarm_time, &alrm->time); alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0; spin_unlock_irq(&rtc->lock); return 0; }
static int lpc32xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); wkalrm->enabled = rtc->alarm_enabled; wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & LPC32XX_RTC_INTSTAT_MATCH0); return rtc_valid_tm(&wkalrm->time); }
static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) { struct lpc32xx_rtc *rtc = dev; spin_lock(&rtc->lock); /* Disable alarm interrupt */ rtc_writel(rtc, LPC32XX_RTC_CTRL, rtc_readl(rtc, LPC32XX_RTC_CTRL) & ~LPC32XX_RTC_CTRL_MATCH0); rtc->alarm_enabled = 0; /* * Write a large value to the match value so the RTC won't * keep firing the match status */ rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); spin_unlock(&rtc->lock); rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); return IRQ_HANDLED; }
static int lpc32xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); unsigned long alarmsecs; u32 tmp; int ret; ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs); if (ret < 0) { dev_warn(dev, "Failed to convert time: %d\n", ret); return ret; } spin_lock_irq(&rtc->lock); /* Disable alarm during update */ tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); rtc->alarm_enabled = wkalrm->enabled; if (wkalrm->enabled) { rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_MATCH0); } spin_unlock_irq(&rtc->lock); return 0; }
static void tegra_clocksource_resume(struct clocksource *cs) { u32 usec; usec = timer_readl(TIMERUS_CNTR_1US); tegra_usec_start_time = rtc_readl(RTC_MILLISECONDS_REG)*1000 + (cycle_t)rtc_readl(RTC_SHADOW_SECONDS)*1000000; /* On first time power up the usec timer will be greater than the rtc, since it has smaller time steps. A negative tegra_usec_start_time is not desirable in this case. */ if ((cycle_t)usec > tegra_usec_start_time) tegra_usec_start_time = 0; else tegra_usec_start_time -= usec; }
static int rtc_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config) { struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); unsigned int param = pinconf_to_config_param(*config); u32 val; u16 arg = 0; rtc->type->unlock(rtc); val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc->type->lock(rtc); switch (param) { case PIN_CONFIG_INPUT_ENABLE: if (!(val & OMAP_RTC_PMIC_EXT_WKUP_EN(pin))) return -EINVAL; break; case PIN_CONFIG_ACTIVE_HIGH: if (val & OMAP_RTC_PMIC_EXT_WKUP_POL(pin)) return -EINVAL; break; default: return -ENOTSUPP; }; *config = pinconf_to_config_packed(param, arg); return 0; }
static int at32_rtc_readtime(struct device *dev, struct rtc_time *tm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); unsigned long now; now = rtc_readl(rtc, VAL); rtc_time_to_tm(now, tm); return 0; }
static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) { unsigned long elapsed_sec; struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); rtc_time_to_tm(elapsed_sec, time); return rtc_valid_tm(time); }
static int omap_rtc_scratch_read(void *priv, unsigned int offset, void *_val, size_t bytes) { struct omap_rtc *rtc = priv; u32 *val = _val; int i; for (i = 0; i < bytes / 4; i++) val[i] = rtc_readl(rtc, OMAP_RTC_SCRATCH0_REG + offset + (i * 4)); return 0; }
/* * omap_rtc_poweroff: RTC-controlled power off * * The RTC can be used to control an external PMIC via the pmic_power_en pin, * which can be configured to transition to OFF on ALARM2 events. * * Notes: * The two-second alarm offset is the shortest offset possible as the alarm * registers must be set before the next timer update and the offset * calculation is too heavy for everything to be done within a single access * period (~15 us). * * Called with local interrupts disabled. */ static void omap_rtc_power_off(void) { struct omap_rtc *rtc = omap_rtc_power_off_rtc; struct rtc_time tm; unsigned long now; u32 val; rtc->type->unlock(rtc); /* enable pmic_power_en control */ val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); /* set alarm two seconds from now */ omap_rtc_read_time_raw(rtc, &tm); bcd2tm(&tm); rtc_tm_to_time(&tm, &now); rtc_time_to_tm(now + 2, &tm); if (tm2bcd(&tm) < 0) { dev_err(&rtc->rtc->dev, "power off failed\n"); return; } rtc_wait_not_busy(rtc); rtc_write(rtc, OMAP_RTC_ALARM2_SECONDS_REG, tm.tm_sec); rtc_write(rtc, OMAP_RTC_ALARM2_MINUTES_REG, tm.tm_min); rtc_write(rtc, OMAP_RTC_ALARM2_HOURS_REG, tm.tm_hour); rtc_write(rtc, OMAP_RTC_ALARM2_DAYS_REG, tm.tm_mday); rtc_write(rtc, OMAP_RTC_ALARM2_MONTHS_REG, tm.tm_mon); rtc_write(rtc, OMAP_RTC_ALARM2_YEARS_REG, tm.tm_year); /* * enable ALARM2 interrupt * * NOTE: this fails on AM3352 if rtc_write (writeb) is used */ val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, val | OMAP_RTC_INTERRUPTS_IT_ALARM2); rtc->type->lock(rtc); /* * Wait for alarm to trigger (within two seconds) and external PMIC to * power off the system. Add a 500 ms margin for external latencies * (e.g. debounce circuits). */ mdelay(2500); }
static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id) { struct rtc_at32ap700x *rtc = (struct rtc_at32ap700x *)dev_id; unsigned long isr = rtc_readl(rtc, ISR); unsigned long events = 0; int ret = IRQ_NONE; spin_lock(&rtc->lock); if (isr & RTC_BIT(ISR_TOPI)) { rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) & ~RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, VAL, rtc->alarm_time); events = RTC_AF | RTC_IRQF; rtc_update_irq(rtc->rtc, 1, events); ret = IRQ_HANDLED; } spin_unlock(&rtc->lock); return ret; }
/* Unconditionally disable the alarm */ static int lpc32xx_rtc_freeze(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); spin_lock_irq(&rtc->lock); rtc_writel(rtc, LPC32XX_RTC_CTRL, rtc_readl(rtc, LPC32XX_RTC_CTRL) & ~LPC32XX_RTC_CTRL_MATCH0); spin_unlock_irq(&rtc->lock); return 0; }
static int lpc32xx_rtc_thaw(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); if (rtc->alarm_enabled) { spin_lock_irq(&rtc->lock); rtc_writel(rtc, LPC32XX_RTC_CTRL, rtc_readl(rtc, LPC32XX_RTC_CTRL) | LPC32XX_RTC_CTRL_MATCH0); spin_unlock_irq(&rtc->lock); } return 0; }
static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) { struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); u32 tmp; spin_lock_irq(&rtc->lock); /* RTC must be disabled during count update */ tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); spin_unlock_irq(&rtc->lock); return 0; }
static int rtc_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, unsigned int num_configs) { struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); u32 val; unsigned int param; u16 param_val; int i; rtc->type->unlock(rtc); val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc->type->lock(rtc); /* active low by default */ val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin); for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); param_val = pinconf_to_config_argument(configs[i]); switch (param) { case PIN_CONFIG_INPUT_ENABLE: if (param_val) val |= OMAP_RTC_PMIC_EXT_WKUP_EN(pin); else val &= ~OMAP_RTC_PMIC_EXT_WKUP_EN(pin); break; case PIN_CONFIG_ACTIVE_HIGH: val &= ~OMAP_RTC_PMIC_EXT_WKUP_POL(pin); break; default: dev_err(&rtc->rtc->dev, "Property %u not supported\n", param); return -ENOTSUPP; } } rtc->type->unlock(rtc); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val); rtc->type->lock(rtc); return 0; }
static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); u32 tmp; spin_lock_irq(&rtc->lock); tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); if (enabled) { rtc->alarm_enabled = 1; tmp |= LPC32XX_RTC_CTRL_MATCH0; } else { rtc->alarm_enabled = 0; tmp &= ~LPC32XX_RTC_CTRL_MATCH0; } rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); spin_unlock_irq(&rtc->lock); return 0; }
static int __init at32_rtc_probe(struct platform_device *pdev) { struct resource *regs; struct rtc_at32ap700x *rtc; int irq; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(struct rtc_at32ap700x), GFP_KERNEL); if (!rtc) return -ENOMEM; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { dev_dbg(&pdev->dev, "no mmio resource defined\n"); return -ENXIO; } irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_dbg(&pdev->dev, "could not get irq\n"); return -ENXIO; } rtc->irq = irq; rtc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!rtc->regs) { dev_dbg(&pdev->dev, "could not map I/O memory\n"); return -ENOMEM; } spin_lock_init(&rtc->lock); /* * Maybe init RTC: count from zero at 1 Hz, disable wrap irq. * * Do not reset VAL register, as it can hold an old time * from last JTAG reset. */ if (!(rtc_readl(rtc, CTRL) & RTC_BIT(CTRL_EN))) { rtc_writel(rtc, CTRL, RTC_BIT(CTRL_PCLR)); rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); rtc_writel(rtc, CTRL, RTC_BF(CTRL_PSEL, 0xe) | RTC_BIT(CTRL_EN)); } ret = devm_request_irq(&pdev->dev, irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc); if (ret) { dev_dbg(&pdev->dev, "could not request irq %d\n", irq); return ret; } platform_set_drvdata(pdev, rtc); rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &at32_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { dev_dbg(&pdev->dev, "could not register rtc device\n"); return PTR_ERR(rtc->rtc); } device_init_wakeup(&pdev->dev, 1); dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", (unsigned long)rtc->regs, rtc->irq); return 0; }
static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) { struct resource *res; struct lpc32xx_rtc *rtc; resource_size_t size; int rtcirq; u32 tmp; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Can't get memory resource\n"); return -ENOENT; } rtcirq = platform_get_irq(pdev, 0); if (rtcirq < 0 || rtcirq >= NR_IRQS) { dev_warn(&pdev->dev, "Can't get interrupt resource\n"); rtcirq = -1; } rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (unlikely(!rtc)) { dev_err(&pdev->dev, "Can't allocate memory\n"); return -ENOMEM; } rtc->irq = rtcirq; size = resource_size(res); if (!devm_request_mem_region(&pdev->dev, res->start, size, pdev->name)) { dev_err(&pdev->dev, "RTC registers are not free\n"); return -EBUSY; } rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size); if (!rtc->rtc_base) { dev_err(&pdev->dev, "Can't map memory\n"); return -ENOMEM; } spin_lock_init(&rtc->lock); /* * The RTC is on a separate power domain and can keep it's state * across a chip power cycle. If the RTC has never been previously * setup, then set it up now for the first time. */ tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | LPC32XX_RTC_CTRL_CNTR_DIS | LPC32XX_RTC_CTRL_MATCH0 | LPC32XX_RTC_CTRL_MATCH1 | LPC32XX_RTC_CTRL_ONSW_MATCH0 | LPC32XX_RTC_CTRL_ONSW_MATCH1 | LPC32XX_RTC_CTRL_ONSW_FORCE_HI); rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); /* Clear latched interrupt states */ rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0 | LPC32XX_RTC_INTSTAT_MATCH1 | LPC32XX_RTC_INTSTAT_ONSW); /* Write key value to RTC so it won't reload on reset */ rtc_writel(rtc, LPC32XX_RTC_KEY, LPC32XX_RTC_KEY_ONSW_LOADVAL); } else { rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); } platform_set_drvdata(pdev, rtc); rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { dev_err(&pdev->dev, "Can't get RTC\n"); platform_set_drvdata(pdev, NULL); return PTR_ERR(rtc->rtc); } /* * IRQ is enabled after device registration in case alarm IRQ * is pending upon suspend exit. */ if (rtc->irq >= 0) { if (devm_request_irq(&pdev->dev, rtc->irq, lpc32xx_rtc_alarm_interrupt, IRQF_DISABLED, pdev->name, rtc) < 0) { dev_warn(&pdev->dev, "Can't request interrupt.\n"); rtc->irq = -1; } else { device_init_wakeup(&pdev->dev, 1); } } return 0; }
void read_persistent_clock(struct timespec *ts) { ts->tv_nsec = rtc_readl(RTC_MILLISECONDS_REG) * 1000000; ts->tv_sec = rtc_readl(RTC_SHADOW_SECONDS); }