Hi Jason, On Mon, Aug 01, 2011 at 12:48:05AM +0000, Jason Cooper wrote: > This driver can be used for kirkwood SoCs by enabling CONFIG_RTC_MVINTEG. > Tested on Global Scale Technologies Dreamplug. > > Signed-off-by: Jason Cooper <u-b...@lakedaemon.net> > --- > Changes from v1: > - renamed files to mvrtc.{c,h} > - used proper c-structs for register access > - used existing macros for register access > - removed RFC > > arch/arm/include/asm/arch-kirkwood/kirkwood.h | 1 + > drivers/rtc/Makefile | 1 + > drivers/rtc/mvrtc.c | 157 > +++++++++++++++++++++++++ > drivers/rtc/mvrtc.h | 79 +++++++++++++ > 4 files changed, 238 insertions(+), 0 deletions(-) > create mode 100644 drivers/rtc/mvrtc.c > create mode 100644 drivers/rtc/mvrtc.h > > diff --git a/arch/arm/include/asm/arch-kirkwood/kirkwood.h > b/arch/arm/include/asm/arch-kirkwood/kirkwood.h > index 0104418..3c843a0 100644 > --- a/arch/arm/include/asm/arch-kirkwood/kirkwood.h > +++ b/arch/arm/include/asm/arch-kirkwood/kirkwood.h > @@ -50,6 +50,7 @@ > #define KW_MPP_BASE (KW_REGISTER(0x10000)) > #define KW_GPIO0_BASE (KW_REGISTER(0x10100)) > #define KW_GPIO1_BASE (KW_REGISTER(0x10140)) > +#define KW_RTC_BASE (KW_REGISTER(0x10300)) > #define KW_NANDF_BASE (KW_REGISTER(0x10418)) > #define KW_SPI_BASE (KW_REGISTER(0x10600)) > #define KW_CPU_WIN_BASE (KW_REGISTER(0x20000)) > diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile > index e4be4a4..e1591a0 100644 > --- a/drivers/rtc/Makefile > +++ b/drivers/rtc/Makefile > @@ -55,6 +55,7 @@ COBJS-$(CONFIG_MCFRTC) += mcfrtc.o > COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o > COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o > COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o > +COBJS-$(CONFIG_RTC_MVINTEG) += mvrtc.o
What about using CONFIG_RTC_MV ? > COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o > COBJS-$(CONFIG_RTC_PL031) += pl031.o > COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o > diff --git a/drivers/rtc/mvrtc.c b/drivers/rtc/mvrtc.c > new file mode 100644 > index 0000000..0db3b20 > --- /dev/null > +++ b/drivers/rtc/mvrtc.c > @@ -0,0 +1,157 @@ > +/* > + * Copyright (C) 2011 > + * Jason Cooper <u-b...@lakedaemon.net> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +/* > + * Date & Time support for Marvell Integrated RTC > + */ > + > +#include <common.h> > +#include <command.h> > +#include <rtc.h> > +#include "mvrtc.h" > + > +/* This RTC does not support century, so we assume 20 */ > +#define CENTURY 20 > + > +int rtc_get(struct rtc_time *t) > +{ > + u32 time; > + u32 date; > + u8 tens; > + u8 single; Maybe you could use the function bcd2bin() and then hide the "tens" and "single" split. > + struct mvrtc_registers *mvrtc_regs; > + > + mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; > + > + /* read the time register */ > + time = readl(&mvrtc_regs->time); > + > + /* read the date register */ > + date = readl(&mvrtc_regs->date); For example, you could have something like: t->tm_sec = bcd2bin(time & 0x7f); t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & 0x7f); t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & 0x3f); /* 24 hour mode */ ... > + > + /* seconds */ > + tens = ((time & MVRTC_10SEC_MSK) >> MVRTC_10SEC_SFT); > + single = ((time & MVRTC_SEC_MSK) >> MVRTC_SEC_SFT); > + t->tm_sec = 10 * tens + single; > + > + /* minutes */ > + tens = ((time & MVRTC_10MIN_MSK) >> MVRTC_10MIN_SFT); > + single = ((time & MVRTC_MIN_MSK) >> MVRTC_MIN_SFT); > + t->tm_min = 10 * tens + single; > + > + /* hours */ > + tens = ((time & MVRTC_10HOUR_MSK) >> MVRTC_10HOUR_SFT); > + single = ((time & MVRTC_HOUR_MSK) >> MVRTC_HOUR_SFT); > + t->tm_hour = 10 * tens + single; If the RTC operates in 12 hour mode, the code above is wrong. > + > + /* day */ > + t->tm_wday = ((time & MVRTC_DAY_MSK) >> MVRTC_DAY_SFT); > + t->tm_wday--; > + > + /* date */ > + tens = ((date & MVRTC_10DATE_MSK) >> MVRTC_10DATE_SFT); > + single = ((date & MVRTC_DATE_MSK) >> MVRTC_DATE_SFT); > + t->tm_mday = 10 * tens + single; > + > + /* month */ > + tens = ((date & MVRTC_10MON_MSK) >> MVRTC_10MON_SFT); > + single = ((date & MVRTC_MON_MSK) >> MVRTC_MON_SFT); > + t->tm_mon = 10 * tens + single; > + > + /* year */ > + tens = ((date & MVRTC_10YEAR_MSK) >> MVRTC_10YEAR_SFT); > + single = ((date & MVRTC_YEAR_MSK) >> MVRTC_YEAR_SFT); > + t->tm_year = (CENTURY * 100) + (10 * tens) + single; > + > + /* not supported in this RTC */ > + t->tm_yday = 0; > + t->tm_isdst = 0; > + > + return 0; > +} > + > +int rtc_set(struct rtc_time *t) > +{ > + u32 time = 0; > + u32 date = 0; > + u32 tens; > + u32 single; > + struct mvrtc_registers *mvrtc_regs; > + > + mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; > + > + /* seconds */ > + tens = t->tm_sec / 10; > + single = t->tm_sec % 10; Again, you could use the function bin2bcd() and then get ride of this "tens" and "single" split. > + time |= ((tens << MVRTC_10SEC_SFT) & MVRTC_10SEC_MSK) | > + ((single << MVRTC_SEC_SFT) & MVRTC_SEC_MSK); For example, here you could have: time |= bin2bcd(tm->tm_sec) << MVRTC_SEC_SFT; > + > + /* minutes */ > + tens = t->tm_min / 10; > + single = t->tm_min % 10; > + time |= ((tens << MVRTC_10MIN_SFT) & MVRTC_10MIN_MSK) | > + ((single << MVRTC_MIN_SFT) & MVRTC_MIN_MSK); > + > + /* hours (24) */ > + tens = t->tm_hour / 10; > + single = t->tm_hour % 10; > + time |= ((tens << MVRTC_10HOUR_SFT) & MVRTC_10HOUR_MSK) | > + ((single << MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK); > + > + /* day */ > + single = t->tm_wday + 1; > + time |= ((single << MVRTC_DAY_SFT) & MVRTC_DAY_MSK); > + > + /* date */ > + tens = t->tm_mday / 10; > + single = t->tm_mday % 10; > + date |= ((tens << MVRTC_10DATE_SFT) & MVRTC_10DATE_MSK) | > + ((single << MVRTC_DATE_SFT) & MVRTC_DATE_MSK); > + > + /* month */ > + tens = t->tm_mon / 10; > + single = t->tm_mon % 10; > + date |= ((tens << MVRTC_10MON_SFT) & MVRTC_10MON_MSK) | > + ((single << MVRTC_MON_SFT) & MVRTC_MON_MSK); > + > + /* year */ > + if ((t->tm_year / 100) != CENTURY) > + printf("Warning: Only century %d supported.\n", CENTURY); > + tens = (t->tm_year % 100) / 10; > + single = (t->tm_year % 100) % 10; > + date |= ((tens << MVRTC_10YEAR_SFT) & MVRTC_10YEAR_MSK) | > + ((single << MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK); > + > + /* write the time register */ > + writel(time, &mvrtc_regs->time); > + > + /* write the date register */ > + writel(date, &mvrtc_regs->date); > + > + return 0; > +} > + > +void rtc_reset(void) > +{ > + /* no init routine for this RTC needed */ In the Linux driver, there is also a check to ensure that the RTC is ticking. Maybe it could be useful here too, just to let know the RTC is functional (or not). Regards, Simon
signature.asc
Description: Digital signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot