diff options
Diffstat (limited to 'drivers/rtc/mc146818.c')
-rw-r--r-- | drivers/rtc/mc146818.c | 312 |
1 files changed, 204 insertions, 108 deletions
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index 44857a6e41..363ade33e3 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -9,10 +9,9 @@ * Date & Time support for the MC146818 (PIXX4) RTC */ -/*#define DEBUG*/ - #include <common.h> #include <command.h> +#include <dm.h> #include <rtc.h> #if defined(__I386__) || defined(CONFIG_MALTA) @@ -24,9 +23,9 @@ #if defined(CONFIG_CMD_DATE) /* Set this to 1 to clear the CMOS RAM */ -#define CLEAR_CMOS 0 +#define CLEAR_CMOS 0 -#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 +#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 #define RTC_SECONDS 0x00 #define RTC_SECONDS_ALARM 0x01 #define RTC_MINUTES 0x02 @@ -37,10 +36,10 @@ #define RTC_DATE_OF_MONTH 0x07 #define RTC_MONTH 0x08 #define RTC_YEAR 0x09 -#define RTC_CONFIG_A 0x0A -#define RTC_CONFIG_B 0x0B -#define RTC_CONFIG_C 0x0C -#define RTC_CONFIG_D 0x0D +#define RTC_CONFIG_A 0x0a +#define RTC_CONFIG_B 0x0b +#define RTC_CONFIG_C 0x0c +#define RTC_CONFIG_D 0x0d #define RTC_REG_SIZE 0x80 #define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) @@ -50,89 +49,7 @@ #define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80 -/* ------------------------------------------------------------------------- */ - -int rtc_get (struct rtc_time *tmp) -{ - uchar sec, min, hour, mday, wday, mon, year; - /* here check if rtc can be accessed */ - while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80); - sec = rtc_read8(RTC_SECONDS); - min = rtc_read8(RTC_MINUTES); - hour = rtc_read8(RTC_HOURS); - mday = rtc_read8(RTC_DATE_OF_MONTH); - wday = rtc_read8(RTC_DAY_OF_WEEK); - mon = rtc_read8(RTC_MONTH); - year = rtc_read8(RTC_YEAR); -#ifdef RTC_DEBUG - printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " - "hr: %02x min: %02x sec: %02x\n", - year, mon, mday, wday, - hour, min, sec ); - printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", - rtc_read8(RTC_CONFIG_D) & 0x3F, - rtc_read8(RTC_HOURS_ALARM), - rtc_read8(RTC_MINUTES_ALARM), - rtc_read8(RTC_SECONDS_ALARM)); -#endif - tmp->tm_sec = bcd2bin (sec & 0x7F); - tmp->tm_min = bcd2bin (min & 0x7F); - tmp->tm_hour = bcd2bin (hour & 0x3F); - tmp->tm_mday = bcd2bin (mday & 0x3F); - tmp->tm_mon = bcd2bin (mon & 0x1F); - tmp->tm_year = bcd2bin (year); - tmp->tm_wday = bcd2bin (wday & 0x07); - if(tmp->tm_year<70) - tmp->tm_year+=2000; - else - tmp->tm_year+=1900; - tmp->tm_yday = 0; - tmp->tm_isdst= 0; -#ifdef RTC_DEBUG - printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", - tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); -#endif - - return 0; -} - -int rtc_set (struct rtc_time *tmp) -{ -#ifdef RTC_DEBUG - printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", - tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); -#endif - rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ - - rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100)); - rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon)); - rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); - rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); - rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour)); - rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min)); - rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec)); - rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ - - return 0; -} - -void rtc_reset (void) -{ - rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ - rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */ - rtc_write8(RTC_CONFIG_B, 0x00); - rtc_write8(RTC_CONFIG_B, 0x00); - rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ -} - -/* ------------------------------------------------------------------------- */ - -/* - * use direct memory access - */ -int rtc_read8(int reg) +static int mc146818_read8(int reg) { #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); @@ -149,7 +66,7 @@ int rtc_read8(int reg) #endif } -void rtc_write8(int reg, uchar val) +static void mc146818_write8(int reg, uchar val) { #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); @@ -165,26 +82,93 @@ void rtc_write8(int reg, uchar val) #endif } -u32 rtc_read32(int reg) +static int mc146818_get(struct rtc_time *tmp) { - u32 value = 0; - int i; + uchar sec, min, hour, mday, wday, mon, year; - for (i = 0; i < sizeof(value); i++) - value |= rtc_read8(reg + i) << (i << 3); + /* here check if rtc can be accessed */ + while ((mc146818_read8(RTC_CONFIG_A) & 0x80) == 0x80) + ; + + sec = mc146818_read8(RTC_SECONDS); + min = mc146818_read8(RTC_MINUTES); + hour = mc146818_read8(RTC_HOURS); + mday = mc146818_read8(RTC_DATE_OF_MONTH); + wday = mc146818_read8(RTC_DAY_OF_WEEK); + mon = mc146818_read8(RTC_MONTH); + year = mc146818_read8(RTC_YEAR); +#ifdef RTC_DEBUG + printf("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x hr: %02x min: %02x sec: %02x\n", + year, mon, mday, wday, hour, min, sec); + printf("Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", + mc146818_read8(RTC_CONFIG_D) & 0x3f, + mc146818_read8(RTC_HOURS_ALARM), + mc146818_read8(RTC_MINUTES_ALARM), + mc146818_read8(RTC_SECONDS_ALARM)); +#endif + tmp->tm_sec = bcd2bin(sec & 0x7f); + tmp->tm_min = bcd2bin(min & 0x7f); + tmp->tm_hour = bcd2bin(hour & 0x3f); + tmp->tm_mday = bcd2bin(mday & 0x3f); + tmp->tm_mon = bcd2bin(mon & 0x1f); + tmp->tm_year = bcd2bin(year); + tmp->tm_wday = bcd2bin(wday & 0x07); + + if (tmp->tm_year < 70) + tmp->tm_year += 2000; + else + tmp->tm_year += 1900; - return value; + tmp->tm_yday = 0; + tmp->tm_isdst = 0; +#ifdef RTC_DEBUG + printf("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + + return 0; } -void rtc_write32(int reg, u32 value) +static int mc146818_set(struct rtc_time *tmp) { - int i; +#ifdef RTC_DEBUG + printf("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + /* Disable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x82); - for (i = 0; i < sizeof(value); i++) - rtc_write8(reg + i, (value >> (i << 3)) & 0xff); + mc146818_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100)); + mc146818_write8(RTC_MONTH, bin2bcd(tmp->tm_mon)); + mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); + mc146818_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); + mc146818_write8(RTC_HOURS, bin2bcd(tmp->tm_hour)); + mc146818_write8(RTC_MINUTES, bin2bcd(tmp->tm_min)); + mc146818_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec)); + + /* Enable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x02); + + return 0; } -void rtc_init(void) +static void mc146818_reset(void) +{ + /* Disable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x82); + + /* Normal OP */ + mc146818_write8(RTC_CONFIG_A, 0x20); + mc146818_write8(RTC_CONFIG_B, 0x00); + mc146818_write8(RTC_CONFIG_B, 0x00); + + /* Enable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x02); +} + +static void mc146818_init(void) { #if CLEAR_CMOS int i; @@ -198,14 +182,126 @@ void rtc_init(void) #endif /* Setup the real time clock */ - rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); + mc146818_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); /* Setup the frequency it operates at */ - rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | - RTC_CONFIG_A_RATE_1024HZ); + mc146818_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | + RTC_CONFIG_A_RATE_1024HZ); /* Ensure all reserved bits are 0 in register D */ - rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); + mc146818_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); /* Clear any pending interrupts */ - rtc_read8(RTC_CONFIG_C); + mc146818_read8(RTC_CONFIG_C); } #endif + +#ifdef CONFIG_DM_RTC + +static int rtc_mc146818_get(struct udevice *dev, struct rtc_time *time) +{ + return mc146818_get(time); +} + +static int rtc_mc146818_set(struct udevice *dev, const struct rtc_time *time) +{ + return mc146818_set((struct rtc_time *)time); +} + +static int rtc_mc146818_reset(struct udevice *dev) +{ + mc146818_reset(); + + return 0; +} + +static int rtc_mc146818_read8(struct udevice *dev, unsigned int reg) +{ + return mc146818_read8(reg); +} + +static int rtc_mc146818_write8(struct udevice *dev, unsigned int reg, int val) +{ + mc146818_write8(reg, val); + + return 0; +} + +static int rtc_mc146818_bind(struct udevice *dev) +{ + mc146818_init(); + + return 0; +} + +static const struct rtc_ops rtc_mc146818_ops = { + .get = rtc_mc146818_get, + .set = rtc_mc146818_set, + .reset = rtc_mc146818_reset, + .read8 = rtc_mc146818_read8, + .write8 = rtc_mc146818_write8, +}; + +static const struct udevice_id rtc_mc146818_ids[] = { + { .compatible = "motorola,mc146818" }, + { } +}; + +U_BOOT_DRIVER(rtc_mc146818) = { + .name = "rtc_mc146818", + .id = UCLASS_RTC, + .of_match = rtc_mc146818_ids, + .bind = rtc_mc146818_bind, + .ops = &rtc_mc146818_ops, +}; + +#else /* !CONFIG_DM_RTC */ + +int rtc_get(struct rtc_time *tmp) +{ + return mc146818_get(tmp); +} + +int rtc_set(struct rtc_time *tmp) +{ + return mc146818_set(tmp); +} + +void rtc_reset(void) +{ + mc146818_reset(); +} + +int rtc_read8(int reg) +{ + return mc146818_read8(reg); +} + +void rtc_write8(int reg, uchar val) +{ + mc146818_write8(reg, val); +} + +u32 rtc_read32(int reg) +{ + u32 value = 0; + int i; + + for (i = 0; i < sizeof(value); i++) + value |= rtc_read8(reg + i) << (i << 3); + + return value; +} + +void rtc_write32(int reg, u32 value) +{ + int i; + + for (i = 0; i < sizeof(value); i++) + rtc_write8(reg + i, (value >> (i << 3)) & 0xff); +} + +void rtc_init(void) +{ + mc146818_init(); +} + +#endif /* CONFIG_DM_RTC */ |