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 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; }
/* * 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 int __exit omap_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); struct resource *mem = dev_get_drvdata(&rtc->dev); const struct platform_device_id *id_entry = platform_get_device_id(pdev); device_init_wakeup(&pdev->dev, 0); /* leave rtc running, but disable irqs */ rtc_write(0, OMAP_RTC_INTERRUPTS_REG); free_irq(omap_rtc_timer, rtc); if (omap_rtc_timer != omap_rtc_alarm) free_irq(omap_rtc_alarm, rtc); rtc_device_unregister(rtc); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); /* Disable the clock/module */ pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(rtc_base); release_mem_region(mem->start, resource_size(mem)); 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 at32_rtc_settime(struct device *dev, struct rtc_time *tm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); unsigned long now; int ret; ret = rtc_tm_to_time(tm, &now); if (ret == 0) rtc_writel(rtc, VAL, now); 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_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; }
/* 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 omap_rtc_scratch_write(void *priv, unsigned int offset, void *_val, size_t bytes) { struct omap_rtc *rtc = priv; u32 *val = _val; int i; rtc->type->unlock(rtc); for (i = 0; i < bytes / 4; i++) rtc_writel(rtc, OMAP_RTC_SCRATCH0_REG + offset + (i * 4), val[i]); rtc->type->lock(rtc); return 0; }
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; }
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 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 __exit omap_rtc_remove(struct platform_device *pdev) { const struct platform_device_id *id_entry = platform_get_device_id(pdev); device_init_wakeup(&pdev->dev, 0); /* leave rtc running, but disable irqs */ rtc_write(0, OMAP_RTC_INTERRUPTS_REG); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); /* Disable the clock/module */ pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); 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 void am3352_rtc_lock(struct omap_rtc *rtc) { rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); rtc_writel(rtc, OMAP_RTC_KICK1_REG, 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; }
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)) 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_device_register(&pdev->dev, pdev->name, &omap_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err; } /* 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"); return PTR_ERR(rtc->pctldev); } return 0; err: 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 __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; }