[PATCH 1/7] rtc-cmos: abstract IO accessors

From: Marc Zyngier
Date: Fri Apr 25 2014 - 05:37:24 EST


Currently, rtc-cmos mandates the use of an I/O port, defined in an
architecture dependant way. This prevents the easy integration of
a platform that doesn't have the simple notion of an IO port.

Add wrappers around the CMOS_READ/CMOS_WRITE accessors, in order
to isolate the driver code from the vintage macros.

No feature is added.

Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
---
drivers/rtc/rtc-cmos.c | 72 +++++++++++++++++++++++++----------------------
include/asm-generic/rtc.h | 57 +++++++++++++++++++++----------------
2 files changed, 72 insertions(+), 57 deletions(-)

diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 0963c93..ae895e8 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -221,24 +221,24 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_mon = -1;

spin_lock_irq(&rtc_lock);
- t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
- t->time.tm_min = CMOS_READ(RTC_MINUTES_ALARM);
- t->time.tm_hour = CMOS_READ(RTC_HOURS_ALARM);
+ t->time.tm_sec = do_cmos_read(RTC_SECONDS_ALARM);
+ t->time.tm_min = do_cmos_read(RTC_MINUTES_ALARM);
+ t->time.tm_hour = do_cmos_read(RTC_HOURS_ALARM);

if (cmos->day_alrm) {
/* ignore upper bits on readback per ACPI spec */
- t->time.tm_mday = CMOS_READ(cmos->day_alrm) & 0x3f;
+ t->time.tm_mday = do_cmos_read(cmos->day_alrm) & 0x3f;
if (!t->time.tm_mday)
t->time.tm_mday = -1;

if (cmos->mon_alrm) {
- t->time.tm_mon = CMOS_READ(cmos->mon_alrm);
+ t->time.tm_mon = do_cmos_read(cmos->mon_alrm);
if (!t->time.tm_mon)
t->time.tm_mon = -1;
}
}

- rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control = do_cmos_read(RTC_CONTROL);
spin_unlock_irq(&rtc_lock);

if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
@@ -284,7 +284,7 @@ static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
/* NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
* allegedly some older rtcs need that to handle irqs properly
*/
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+ rtc_intr = do_cmos_read(RTC_INTR_FLAGS);

if (is_hpet_enabled())
return;
@@ -301,11 +301,11 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
/* flush any pending IRQ status, notably for update irqs,
* before we enable new IRQs
*/
- rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control = do_cmos_read(RTC_CONTROL);
cmos_checkintr(cmos, rtc_control);

rtc_control |= mask;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
+ do_cmos_write(rtc_control, RTC_CONTROL);
hpet_set_rtc_irq_bit(mask);

cmos_checkintr(cmos, rtc_control);
@@ -315,9 +315,9 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
{
unsigned char rtc_control;

- rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control = do_cmos_read(RTC_CONTROL);
rtc_control &= ~mask;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
+ do_cmos_write(rtc_control, RTC_CONTROL);
hpet_mask_rtc_irq_bit(mask);

cmos_checkintr(cmos, rtc_control);
@@ -337,7 +337,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
min = t->time.tm_min;
sec = t->time.tm_sec;

- rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control = do_cmos_read(RTC_CONTROL);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
/* Writing 0xff means "don't care" or "match all". */
mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
@@ -353,15 +353,15 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
cmos_irq_disable(cmos, RTC_AIE);

/* update alarm */
- CMOS_WRITE(hrs, RTC_HOURS_ALARM);
- CMOS_WRITE(min, RTC_MINUTES_ALARM);
- CMOS_WRITE(sec, RTC_SECONDS_ALARM);
+ do_cmos_write(hrs, RTC_HOURS_ALARM);
+ do_cmos_write(min, RTC_MINUTES_ALARM);
+ do_cmos_write(sec, RTC_SECONDS_ALARM);

/* the system may support an "enhanced" alarm */
if (cmos->day_alrm) {
- CMOS_WRITE(mday, cmos->day_alrm);
+ do_cmos_write(mday, cmos->day_alrm);
if (cmos->mon_alrm)
- CMOS_WRITE(mon, cmos->mon_alrm);
+ do_cmos_write(mon, cmos->mon_alrm);
}

/* FIXME the HPET alarm glue currently ignores day_alrm
@@ -452,8 +452,8 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq)
unsigned char rtc_control, valid;

spin_lock_irq(&rtc_lock);
- rtc_control = CMOS_READ(RTC_CONTROL);
- valid = CMOS_READ(RTC_VALID);
+ rtc_control = do_cmos_read(RTC_CONTROL);
+ valid = do_cmos_read(RTC_VALID);
spin_unlock_irq(&rtc_lock);

/* NOTE: at least ICH6 reports battery status using a different
@@ -519,7 +519,7 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
spin_lock_irq(&rtc_lock);
for (retval = 0; count; count--, off++, retval++) {
if (off < 128)
- *buf++ = CMOS_READ(off);
+ *buf++ = do_cmos_read(off);
else if (can_bank2)
*buf++ = cmos_read_bank2(off);
else
@@ -560,7 +560,7 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
|| off == cmos->century)
buf++;
else if (off < 128)
- CMOS_WRITE(*buf++, off);
+ do_cmos_write(*buf++, off);
else if (can_bank2)
cmos_write_bank2(*buf++, off);
else
@@ -600,8 +600,8 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
* Note that HPET and RTC are almost certainly out of phase,
* giving different IRQ status ...
*/
- irqstat = CMOS_READ(RTC_INTR_FLAGS);
- rtc_control = CMOS_READ(RTC_CONTROL);
+ irqstat = do_cmos_read(RTC_INTR_FLAGS);
+ rtc_control = do_cmos_read(RTC_CONTROL);
if (is_hpet_enabled())
irqstat = (unsigned long)irq & 0xF0;

@@ -620,9 +620,9 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
if (irqstat & RTC_AIE) {
cmos_rtc.suspend_ctrl &= ~RTC_AIE;
rtc_control &= ~RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
+ do_cmos_write(rtc_control, RTC_CONTROL);
hpet_mask_rtc_irq_bit(RTC_AIE);
- CMOS_READ(RTC_INTR_FLAGS);
+ do_cmos_read(RTC_INTR_FLAGS);
}
spin_unlock(&rtc_lock);

@@ -734,12 +734,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
*/
cmos_rtc.rtc->irq_freq = 1024;
hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+ do_cmos_write(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);

/* disable irqs */
cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);

- rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control = do_cmos_read(RTC_CONTROL);

spin_unlock_irq(&rtc_lock);

@@ -846,7 +846,7 @@ static int cmos_suspend(struct device *dev)

/* only the alarm might be a wakeup event source */
spin_lock_irq(&rtc_lock);
- cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
+ cmos->suspend_ctrl = tmp = do_cmos_read(RTC_CONTROL);
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
unsigned char mask;

@@ -855,7 +855,7 @@ static int cmos_suspend(struct device *dev)
else
mask = RTC_IRQMASK;
tmp &= ~mask;
- CMOS_WRITE(tmp, RTC_CONTROL);
+ do_cmos_write(tmp, RTC_CONTROL);
hpet_mask_rtc_irq_bit(mask);

cmos_checkintr(cmos, tmp);
@@ -912,10 +912,10 @@ static int cmos_resume(struct device *dev)
hpet_rtc_timer_init();

do {
- CMOS_WRITE(tmp, RTC_CONTROL);
+ do_cmos_write(tmp, RTC_CONTROL);
hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);

- mask = CMOS_READ(RTC_INTR_FLAGS);
+ mask = do_cmos_read(RTC_INTR_FLAGS);
mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
if (!is_hpet_enabled() || !is_intr(mask))
break;
@@ -1114,13 +1114,19 @@ static __init void cmos_of_init(struct platform_device *pdev)
if (!node)
return;

+ /*
+ * Try to map an MMIO region first. If it fails, we'll
+ * fallback on I/O access.
+ */
+ rtc_cmos_set_base(of_iomap(node, 0));
+
val = of_get_property(node, "ctrl-reg", NULL);
if (val)
- CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
+ do_cmos_write(be32_to_cpup(val), RTC_CONTROL);

val = of_get_property(node, "freq-reg", NULL);
if (val)
- CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
+ do_cmos_write(be32_to_cpup(val), RTC_FREQ_SELECT);

get_rtc_time(&time);
ret = rtc_valid_tm(&time);
diff --git a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
index fa86f24..313438a 100644
--- a/include/asm-generic/rtc.h
+++ b/include/asm-generic/rtc.h
@@ -28,6 +28,15 @@
#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */

+static inline u8 do_cmos_read(u8 reg)
+{
+ return CMOS_READ(reg);
+}
+
+static inline void do_cmos_write(u8 val, u8 reg)
+{
+ CMOS_WRITE(val, reg);
+}
/*
* Returns true if a clock update is in progress
*/
@@ -37,7 +46,7 @@ static inline unsigned char rtc_is_updating(void)
unsigned long flags;

spin_lock_irqsave(&rtc_lock, flags);
- uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+ uip = (do_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
spin_unlock_irqrestore(&rtc_lock, flags);
return uip;
}
@@ -70,16 +79,16 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
* by the RTC when initially set to a non-zero value.
*/
spin_lock_irqsave(&rtc_lock, flags);
- time->tm_sec = CMOS_READ(RTC_SECONDS);
- time->tm_min = CMOS_READ(RTC_MINUTES);
- time->tm_hour = CMOS_READ(RTC_HOURS);
- time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
- time->tm_mon = CMOS_READ(RTC_MONTH);
- time->tm_year = CMOS_READ(RTC_YEAR);
+ time->tm_sec = do_cmos_read(RTC_SECONDS);
+ time->tm_min = do_cmos_read(RTC_MINUTES);
+ time->tm_hour = do_cmos_read(RTC_HOURS);
+ time->tm_mday = do_cmos_read(RTC_DAY_OF_MONTH);
+ time->tm_mon = do_cmos_read(RTC_MONTH);
+ time->tm_year = do_cmos_read(RTC_YEAR);
#ifdef CONFIG_MACH_DECSTATION
- real_year = CMOS_READ(RTC_DEC_YEAR);
+ real_year = do_cmos_read(RTC_DEC_YEAR);
#endif
- ctrl = CMOS_READ(RTC_CONTROL);
+ ctrl = do_cmos_read(RTC_CONTROL);
spin_unlock_irqrestore(&rtc_lock, flags);

if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
@@ -161,7 +170,7 @@ static inline int __set_rtc_time(struct rtc_time *time)
if (yrs >= 100)
yrs -= 100;

- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ if (!(do_cmos_read(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
sec = bin2bcd(sec);
min = bin2bcd(min);
@@ -171,23 +180,23 @@ static inline int __set_rtc_time(struct rtc_time *time)
yrs = bin2bcd(yrs);
}

- save_control = CMOS_READ(RTC_CONTROL);
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+ save_control = do_cmos_read(RTC_CONTROL);
+ do_cmos_write((save_control|RTC_SET), RTC_CONTROL);
+ save_freq_select = do_cmos_read(RTC_FREQ_SELECT);
+ do_cmos_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);

#ifdef CONFIG_MACH_DECSTATION
- CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
+ do_cmos_write(real_yrs, RTC_DEC_YEAR);
#endif
- CMOS_WRITE(yrs, RTC_YEAR);
- CMOS_WRITE(mon, RTC_MONTH);
- CMOS_WRITE(day, RTC_DAY_OF_MONTH);
- CMOS_WRITE(hrs, RTC_HOURS);
- CMOS_WRITE(min, RTC_MINUTES);
- CMOS_WRITE(sec, RTC_SECONDS);
-
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ do_cmos_write(yrs, RTC_YEAR);
+ do_cmos_write(mon, RTC_MONTH);
+ do_cmos_write(day, RTC_DAY_OF_MONTH);
+ do_cmos_write(hrs, RTC_HOURS);
+ do_cmos_write(min, RTC_MINUTES);
+ do_cmos_write(sec, RTC_SECONDS);
+
+ do_cmos_write(save_control, RTC_CONTROL);
+ do_cmos_write(save_freq_select, RTC_FREQ_SELECT);

spin_unlock_irqrestore(&rtc_lock, flags);

--
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/