Platform real time clock driver for Dallas 1511 chip.
PATCH 1/1 Platform real time clock driver for Dallas 1511 chip.
Add RTC support for DS1511 RTC/WDT chip.
--- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-ds1511.c | 665 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 676 insertions(+), 0 deletions(-)
drivers/rtc/Kconfig +10 -0
@@ -302,6 +302,16 @@ config RTC_DRV_DS1216 help If you say yes here you get support for the Dallas DS1216 RTC chips. +config RTC_DRV_DS1511 + tristate "Dallas DS1511" + depends on RTC_CLASS + help + If you say yes here you get support for the + Dallas DS1511 timekeeping/watchdog chip. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1511. + config RTC_DRV_DS1553 tristate "Dallas DS1553" help
drivers/rtc/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o +obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
drivers/rtc/rtc-ds1511.c new file +665 -0
665 lines not on this page · raw message
Signature · 1 line
1.4.4.4
Quoted 15 lines · On Tue, 4 Dec 2007 12:00:05 -0800 Andrew Sharp <[email protected]> wrote:
Add RTC support for DS1511 RTC/WDT chip.
...
drivers/rtc/rtc-ds1511.c new file +10
-0+typedef enum ds1511reg { + DS1511_SEC = 0x0, + DS1511_MIN = 0x1, + DS1511_HOUR = 0x2, + DS1511_DOW = 0x3, + DS1511_DOM = 0x4, + DS1511_MONTH = 0x5, + DS1511_YEAR = 0x6, + DS1511_CENTURY = 0x7, + DS1511_AM1_SEC = 0x8,
drivers/rtc/rtc-ds1511.c line 48
Quoted 10 lines
drivers/rtc/rtc-ds1511.c new file +10
-0+DS1511_AM2_MIN =0x9 , +DS1511_AM3_HOUR =0xa , +DS1511_AM4_DATE =0xb , +DS1511_WD_MSEC =0xc , +DS1511_WD_SEC =0xd , +DS1511_CONTROL_A =0xe , +DS1511_CONTROL_B =0xf , +DS1511_RAMADDR_LSB =0x10 , +DS1511_RAMDATA =0x13 +} ds1511reg_t;
Please remove the typedef and just use `enum ds1511reg' everywhere.
Quoted 2 lines
+ static noinline void
+rtc_write(uint8_t val,uint32_treg)
It's unusual (unique) to indent the function declaration by a single space in this way. Maybe an editor option which needs fixing?
Also, although there are good reasons to always put a newline after the declaration of the return type, kernel code generally doesn't do that except as a way of avoiding 80-col wraparound sometimes.
IOW, please use
static noinline void rtc_write(uint8_t val, uint32_t reg) {
Why was this function declared noinline?
Quoted 20 lines
drivers/rtc/rtc-ds1511.c new file +20
-0+{ +writeb (val, ds1511_base + (reg * reg_spacing)); +} + +static inline void +rtc_write_alarm (uint8_t val,ds1511reg_t reg) +{ +rtc_write ((val |0x80 ), reg); +} + + static noinline uint8_t +rtc_read (ds1511reg_t reg) +{ +return readb (ds1511_base + (reg * reg_spacing)); +} + +static inline void +rtc_disable_update (void ) +{ +rtc_write ((rtc_read (RTC_CMD ) & ~RTC_TE ),RTC_CMD );
drivers/rtc/rtc-ds1511.c line 138
Quoted 10 lines
drivers/rtc/rtc-ds1511.c new file +10
-0+} + + static noinline void +rtc_enable_update (void ) +{ +rtc_write ((rtc_read (RTC_CMD ) |RTC_TE ),RTC_CMD ); +} + +//#define DS1511_WDOG_RESET_SUPPORT +//#undef DS1511_WDOG_RESET_SUPPORT
c99-style comments will generate checkpatch warnings.
Please run checkpatch. It detects a lot of coding-style breakage in this patch.
Quoted 27 lines
drivers/rtc/rtc-ds1511.c new file +27
-0+#ifdef DS1511_WDOG_RESET_SUPPORT +/* +* just enough code to set the watchdog timer so that it +* will reboot the system +*/ +void +ds1511_wdog_set (unsigned long deciseconds) +{ +/* +* the wdog timer can take 99.99 seconds +*/ + deciseconds %=10000 ; +/* +* set the wdog values in the wdog registers +*/ +rtc_write (BIN2BCD (deciseconds %100 ),DS1511_WD_MSEC ); +rtc_write (BIN2BCD (deciseconds /100 ),DS1511_WD_SEC ); +/* +* set wdog enable and wdog 'steering' bit to issue a reset +*/ +rtc_write (DS1511_WDE |DS1511_WDS ,RTC_CMD ); +} + +void +ds1511_wdog_disable (void ) +{ +/*
drivers/rtc/rtc-ds1511.c line 175
Quoted 10 lines
drivers/rtc/rtc-ds1511.c new file +10
-0+* clear wdog enable and wdog 'steering' bits +*/ +rtc_write (rtc_read (RTC_CMD ) & ~(DS1511_WDE |DS1511_WDS ),RTC_CMD ); +/* +* clear the wdog counter +*/ +rtc_write (0 ,DS1511_WD_MSEC ); + rtc_write(0, DS1511_WD_SEC); +} +#endif
What's the story here? This code is permanently disabled?
Quoted 4 lines
+ int
drivers/rtc/rtc-ds1511.c new file +3
-0+ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) +{ + struct platform_device *pdev = to_platform_device(dev);
drivers/rtc/rtc-ds1511.c line 259
Quoted 10 lines
drivers/rtc/rtc-ds1511.c new file +10
-0+struct rtc_plat_data *pdata =platform_get_drvdata (pdev); +unsigned int century; +unsigned int flags; + +/* +* give enough time to update RTC in case of continuous read +*/ +if (pdata->last_jiffies == jiffies) { +msleep (1 ); + }
hm, that could be pretty obnoxious for some applications, I expect. They'll run veeeery sloooowly, and inconsistently slowly across different values of CONFIG_HZ. And the uninterruptible sleep will contribute to system load average.
What's going on here?
Do other RTC drivers do things like this?
Quoted 49 lines
drivers/rtc/rtc-ds1511.c new file +49
-0+ pdata->last_jiffies = jiffies; + +spin_lock_irqsave (&ds1511_lock, flags); +rtc_disable_update (); + + rtc_tm->tm_sec =rtc_read (RTC_SEC ) &0x7f ; + rtc_tm->tm_min =rtc_read (RTC_MIN ) &0x7f ; + rtc_tm->tm_hour =rtc_read (RTC_HOUR ) &0x3f ; + rtc_tm->tm_mday =rtc_read (RTC_DOM ) &0x3f ; + rtc_tm->tm_wday =rtc_read (RTC_DOW ) &0x7 ; + rtc_tm->tm_mon =rtc_read (RTC_MON ) &0x1f ; + rtc_tm->tm_year =rtc_read (RTC_YEAR ) &0x7f ; + century =rtc_read (RTC_CENTURY ); + +rtc_enable_update (); +spin_unlock_irqrestore (&ds1511_lock, flags); + + rtc_tm->tm_sec =BCD2BIN (rtc_tm->tm_sec); + rtc_tm->tm_min =BCD2BIN (rtc_tm->tm_min); + rtc_tm->tm_hour =BCD2BIN (rtc_tm->tm_hour); + rtc_tm->tm_mday =BCD2BIN (rtc_tm->tm_mday); + rtc_tm->tm_wday =BCD2BIN (rtc_tm->tm_wday); + rtc_tm->tm_mon =BCD2BIN (rtc_tm->tm_mon); + rtc_tm->tm_year =BCD2BIN (rtc_tm->tm_year); + century =BCD2BIN (century) *100 ; + +/* +* Account for differences between how the RTC uses the values +* and how they are defined in a struct rtc_time; +*/ + century += rtc_tm->tm_year; + rtc_tm->tm_year = century -1900 ; + + rtc_tm->tm_mon--; + +if (rtc_valid_tm (rtc_tm) <0 ) { +dev_err (dev,"retrieved date/time is not valid.\n" ); +rtc_time_to_tm (0 , rtc_tm); + } +return 0 ; +} + +/* +* write the alarm register settings +* +* we only have the use to interrupt every second, otherwise +* known as the update interrupt, or the interrupt if the whole +* date/hours/mins/secs matches. the ds1511 has many more +* permutations, but the kernel doesn't.
drivers/rtc/rtc-ds1511.c line 318
Quoted 10 lines
drivers/rtc/rtc-ds1511.c new file +10
-0+*/ +static void +ds1511_rtc_update_alarm (struct rtc_plat_data *pdata) +{ +unsigned long flags; + +spin_lock_irqsave (&pdata->rtc->irq_lock, flags); +rtc_write (pdata->alrm_mday <0 || (pdata->irqen &RTC_UF ) ? +0x80 :BIN2BCD (pdata->alrm_mday) &0x3f , +RTC_ALARM_DATE );
hm. You appear to be a C precedence whizz ;)
Quoted 14 lines
drivers/rtc/rtc-ds1511.c new file +14
-0+rtc_write (pdata->alrm_hour <0 || (pdata->irqen &RTC_UF ) ? +0x80 :BIN2BCD (pdata->alrm_hour) &0x3f , +RTC_ALARM_HOUR ); +rtc_write (pdata->alrm_min <0 || (pdata->irqen &RTC_UF ) ? +0x80 :BIN2BCD (pdata->alrm_min) &0x7f , +RTC_ALARM_MIN ); +rtc_write (pdata->alrm_sec <0 || (pdata->irqen &RTC_UF ) ? +0x80 :BIN2BCD (pdata->alrm_sec) &0x7f , +RTC_ALARM_SEC ); +rtc_write (rtc_read (RTC_CMD ) | (pdata->irqen ?RTC_TIE :0 ),RTC_CMD ); +rtc_read (RTC_CMD1 );/* clear interrupts */ +spin_unlock_irqrestore (&pdata->rtc->irq_lock, flags); +} +