// SPDX-License-Identifier: GPL-2.0-or-later /* * rtc-twl.c -- TWL Real Time Clock interface * * Copyright (C) 2007 MontaVista Software, Inc * Author: Alexandre Rusev <source@mvista.com> * * Based on original TI driver twl4030-rtc.c * Copyright (C) 2006 Texas Instruments, Inc. * * Based on rtc-omap.c * Copyright (C) 2003 MontaVista Software, Inc. * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com> * Copyright (C) 2006 David Brownell
*/
/* if the bit is set, return from here */ if (twl_rtc->rtc_irq_bits & bit) return 0;
val = twl_rtc->rtc_irq_bits | bit;
val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
ret = twl_rtc_write_u8(twl_rtc, val, REG_RTC_INTERRUPTS_REG); if (ret == 0)
twl_rtc->rtc_irq_bits = val;
if (enabled) {
ret = set_rtc_irq_bit(twl_rtc,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); if (device_can_wakeup(dev) && !twl_rtc->wake_enabled) {
enable_irq_wake(irq);
twl_rtc->wake_enabled = true;
}
} else {
ret = mask_rtc_irq_bit(twl_rtc,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); if (twl_rtc->wake_enabled) {
disable_irq_wake(irq);
twl_rtc->wake_enabled = false;
}
}
return ret;
}
/* * Gets current TWL RTC time and date parameters. * * The RTC's time/alarm representation is not what gmtime(3) requires * Linux to use: * * - Months are 1..12 vs Linux 0-11 * - Years are 0..99 vs Linux 1900..N (we assume 21st century)
*/ staticint twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ struct twl_rtc *twl_rtc = dev_get_drvdata(dev); unsignedchar rtc_data[ALL_TIME_REGS]; int ret;
u8 save_control;
u8 rtc_control;
ret = twl_rtc_read_u8(twl_rtc, &save_control, REG_RTC_CTRL_REG); if (ret < 0) {
dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret); return ret;
} /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */ if (twl_rtc->class == TWL_6030) { if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) {
save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M;
ret = twl_rtc_write_u8(twl_rtc, save_control,
REG_RTC_CTRL_REG); if (ret < 0) {
dev_err(dev, "%s clr GET_TIME, error %d\n",
__func__, ret); return ret;
}
}
}
/* Copy RTC counting registers to static registers or latches */
rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M;
/* for twl6030/32 enable read access to static shadowed registers */ if (twl_rtc->class == TWL_6030)
rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT;
/* for twl6030 restore original state of rtc control register */ if (twl_rtc->class == TWL_6030) {
ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG); if (ret < 0) {
dev_err(dev, "%s: restore CTRL_REG, error %d\n",
__func__, ret); return ret;
}
}
/* Stop RTC while updating the TC registers */
ret = twl_rtc_read_u8(twl_rtc, &save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out;
save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out;
/* update all the time registers in one shot */
ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data,
(twl_rtc->reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) {
dev_err(dev, "rtc_set_time error %d\n", ret); goto out;
}
/* Start back RTC */
save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG);
/* update all the alarm registers in one shot */
ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
twl_rtc->reg_map[REG_ALARM_SECONDS_REG], ALL_TIME_REGS); if (ret) {
dev_err(dev, "rtc_set_alarm error %d\n", ret); goto out;
}
if (alm->enabled)
ret = twl_rtc_alarm_irq_enable(dev, 1);
out: return ret;
}
static irqreturn_t twl_rtc_interrupt(int irq, void *data)
{ struct twl_rtc *twl_rtc = data; unsignedlong events; int ret = IRQ_NONE; int res;
u8 rd_reg;
res = twl_rtc_read_u8(twl_rtc, &rd_reg, REG_RTC_STATUS_REG); if (res) goto out; /* * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. * only one (ALARM or RTC) interrupt source may be enabled * at time, we also could check our results * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
*/ if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
events = RTC_IRQF | RTC_AF; else
events = RTC_IRQF | RTC_PF;
res = twl_rtc_write_u8(twl_rtc, BIT_RTC_STATUS_REG_ALARM_M,
REG_RTC_STATUS_REG); if (res) goto out;
if (twl_rtc->class == TWL_4030) { /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 * needs 2 reads to clear the interrupt. One read is done in * do_twl_pwrirq(). Doing the second read, to clear * the bit. * * FIXME the reason PWR_ISR1 needs an extra read is that * RTC_IF retriggered until we cleared REG_ALARM_M above. * But re-reading like this is a bad hack; by doing so we * risk wrongly clearing status for some other IRQ (losing * the interrupt). Be smarter about handling RTC_UF ...
*/
res = twl_i2c_read_u8(TWL4030_MODULE_INT,
&rd_reg, TWL4030_INT_PWR_ISR1); if (res) goto out;
}
/* Notify RTC core on event */
rtc_update_irq(twl_rtc->rtc, 1, events);
ret = twl_rtc_read_u8(twl_rtc, &rd_reg, REG_RTC_STATUS_REG); if (ret < 0) return ret;
if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M)
dev_warn(&pdev->dev, "Power up reset detected.\n");
if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
/* Clear RTC Power up reset and pending alarm interrupts */
ret = twl_rtc_write_u8(twl_rtc, rd_reg, REG_RTC_STATUS_REG); if (ret < 0) return ret;
if (twl_rtc->class == TWL_6030) {
twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
REG_INT_MSK_LINE_A);
twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
REG_INT_MSK_STS_A);
}
ret = twl_rtc_write_u8(twl_rtc, BIT_RTC_CTRL_REG_STOP_RTC_M,
REG_RTC_CTRL_REG); if (ret < 0) return ret;
/* ensure interrupts are disabled, bootloaders can be strange */
ret = twl_rtc_write_u8(twl_rtc, 0, REG_RTC_INTERRUPTS_REG); if (ret < 0)
dev_warn(&pdev->dev, "unable to disable interrupt\n");
/* init cached IRQ enable bits */
ret = twl_rtc_read_u8(twl_rtc, &twl_rtc->rtc_irq_bits,
REG_RTC_INTERRUPTS_REG); if (ret < 0) return ret;
/* mask timer interrupts, but leave alarm interrupts on to enable
power-on when alarm is triggered */
mask_rtc_irq_bit(twl_rtc, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.