[U-Boot] [PATCH] drivers/rtc: add Marvell Integrated RTC.

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-boot@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 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-boot@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; + 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); + + /* 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; + + /* 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; + time |= ((tens << MVRTC_10SEC_SFT) & MVRTC_10SEC_MSK) | + ((single << MVRTC_SEC_SFT) & MVRTC_SEC_MSK); + + /* 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 */ +} diff --git a/drivers/rtc/mvrtc.h b/drivers/rtc/mvrtc.h new file mode 100644 index 0000000..286b223 --- /dev/null +++ b/drivers/rtc/mvrtc.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 + * Jason Cooper u-boot@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 + */ + +#ifndef _MVRTC_H_ +#define _MVRTC_H_ + +#include <asm/arch/kirkwood.h> +#include <compiler.h> + +/* RTC registers */ +struct mvrtc_registers { + u32 time; + u32 date; +}; + +/* time register */ +#define MVRTC_SEC_SFT 0 +#define MVRTC_SEC_MSK (0xf << MVRTC_SEC_SFT) +#define MVRTC_10SEC_SFT 4 +#define MVRTC_10SEC_MSK (0x7 << MVRTC_10SEC_SFT) + +#define MVRTC_MIN_SFT 8 +#define MVRTC_MIN_MSK (0xf << MVRTC_MIN_SFT) +#define MVRTC_10MIN_SFT 12 +#define MVRTC_10MIN_MSK (0x7 << MVRTC_10MIN_SFT) + +#define MVRTC_HOUR_SFT 16 +#define MVRTC_HOUR_MSK (0xf << MVRTC_HOUR_SFT) +#define MVRTC_10HOUR_SFT 20 +#define MVRTC_10HOUR_MSK (0x3 << MVRTC_10HOUR_SFT) + +#define MVRTC_HRFMT_SFT 22 +#define MVRTC_HRFMT12_MSK (0x1 << MVRTC_HRFMT_SFT) +#define MVRTC_HRFMT24_MSK (0x0 << MVRTC_HRFMT_SFT) + +#define MVRTC_DAY_SFT 24 +#define MVRTC_DAY_MSK (0x7 << MVRTC_DAY_SFT) + +/* date register */ +#define MVRTC_DATE_SFT 0 +#define MVRTC_DATE_MSK (0xf << MVRTC_DATE_SFT) +#define MVRTC_10DATE_SFT 4 +#define MVRTC_10DATE_MSK (0x3 << MVRTC_10DATE_SFT) + +#define MVRTC_MON_SFT 8 +#define MVRTC_MON_MSK (0xf << MVRTC_MON_SFT) +#define MVRTC_10MON_SFT 12 +#define MVRTC_10MON_MSK (0x1 << MVRTC_10MON_SFT) + +#define MVRTC_YEAR_SFT 16 +#define MVRTC_YEAR_MSK (0xf << MVRTC_YEAR_SFT) +#define MVRTC_10YEAR_SFT 20 +#define MVRTC_10YEAR_MSK (0xf << MVRTC_10YEAR_SFT) + +#endif

v2. My apologies.
thx,
Jason.

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-boot@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-boot@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

On Mon, Aug 01, 2011 at 11:49:58AM +0000, Simon Guinot wrote:
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-boot@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 ?
Sure.
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-boot@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 */ ...
Awesome, thanks! Will do.
- /* 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.
Will double check, I've been testing it in the evening without problems. I'll set it to just before noon to see what it does.
- /* 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).
Good idea, I'll take a look at the Linux code for that test and implement similar.
Regards,
Simon
Thanks for the comments and suggestions,
Jason.

This driver can be used for kirkwood SoCs by enabling CONFIG_RTC_MV. Tested on Global Scale Technologies Dreamplug.
Signed-off-by: Jason Cooper u-boot@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
Changes from v2: - use bin2bcd() and bcd2bin() to make code easier to read - changed CONFIG_RTC_MVINTEG -> CONFIG_RTC_MV - use 24 hour mode, detect if rtc went into 12 hour mode - add check if ticking to rtc_reset()
arch/arm/include/asm/arch-kirkwood/kirkwood.h | 1 + drivers/rtc/Makefile | 1 + drivers/rtc/mvrtc.c | 124 +++++++++++++++++++++++++ drivers/rtc/mvrtc.h | 65 +++++++++++++ 4 files changed, 191 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..ca27745 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_MV) += mvrtc.o 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..ccc573a --- /dev/null +++ b/drivers/rtc/mvrtc.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2011 + * Jason Cooper u-boot@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; + 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); + + /* test for 12 hour clock (can't tell if it's am/pm) */ + if (time & MVRTC_HRFMT_MSK) { + printf("Error: RTC in 12 hour mode, can't determine AM/PM.\n"); + return -1; + } + + /* time */ + t->tm_sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); + t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & MVRTC_MIN_MSK); + t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK); + t->tm_wday = bcd2bin((time >> MVRTC_DAY_SFT) & MVRTC_DAY_MSK); + t->tm_wday--; + + /* date */ + t->tm_mday = bcd2bin((date >> MVRTC_DATE_SFT) & MVRTC_DATE_MSK); + t->tm_mon = bcd2bin((date >> MVRTC_MON_SFT) & MVRTC_MON_MSK); + t->tm_year = bcd2bin((date >> MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK); + t->tm_year += CENTURY * 100; + + /* 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; /* sets hour format bit to zero, 24hr format. */ + u32 date = 0; + struct mvrtc_registers *mvrtc_regs; + + mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; + + /* check that this code isn't 80+ years old ;-) */ + if ((t->tm_year / 100) != CENTURY) + printf("Warning: Only century %d supported.\n", CENTURY); + + /* time */ + time |= (bin2bcd(t->tm_sec) & MVRTC_SEC_MSK) << MVRTC_SEC_SFT; + time |= (bin2bcd(t->tm_min) & MVRTC_MIN_MSK) << MVRTC_MIN_SFT; + time |= (bin2bcd(t->tm_hour) & MVRTC_HOUR_MSK) << MVRTC_HOUR_SFT; + time |= (bin2bcd(t->tm_wday + 1) & MVRTC_DAY_MSK) << MVRTC_DAY_SFT; + + /* date */ + date |= (bin2bcd(t->tm_mday) & MVRTC_DATE_MSK) << MVRTC_DATE_SFT; + date |= (bin2bcd(t->tm_mon) & MVRTC_MON_MSK) << MVRTC_MON_SFT; + date |= (bin2bcd(t->tm_year % 100) & MVRTC_YEAR_MSK) << MVRTC_YEAR_SFT; + + /* write the time register */ + writel(time, &mvrtc_regs->time); + + /* write the date register */ + writel(date, &mvrtc_regs->date); + + return 0; +} + +void rtc_reset(void) +{ + u32 time; + u32 sec; + struct mvrtc_registers *mvrtc_regs; + + mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE; + + /* no init routine for this RTC needed, just check that it's working */ + time = readl(&mvrtc_regs->time); + sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK); + udelay(1000000); + time = readl(&mvrtc_regs->time); + + if (sec == bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK)) + printf("Error: RTC did not increment.\n"); +} diff --git a/drivers/rtc/mvrtc.h b/drivers/rtc/mvrtc.h new file mode 100644 index 0000000..b9d5c6f --- /dev/null +++ b/drivers/rtc/mvrtc.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011 + * Jason Cooper u-boot@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 + */ + +#ifndef _MVRTC_H_ +#define _MVRTC_H_ + +#include <asm/arch/kirkwood.h> +#include <compiler.h> + +/* RTC registers */ +struct mvrtc_registers { + u32 time; + u32 date; +}; + +/* time register */ +#define MVRTC_SEC_SFT 0 +#define MVRTC_SEC_MSK 0x7f +#define MVRTC_MIN_SFT 8 +#define MVRTC_MIN_MSK 0x7f +#define MVRTC_HOUR_SFT 16 +#define MVRTC_HOUR_MSK 0x3f +#define MVRTC_DAY_SFT 24 +#define MVRTC_DAY_MSK 0x7 + +/* + * Hour format bit + * 1 = 12 hour clock + * 0 = 24 hour clock + */ +#define MVRTC_HRFMT_MSK 0x00400000 + +/* date register */ +#define MVRTC_DATE_SFT 0 +#define MVRTC_DATE_MSK 0x3f +#define MVRTC_MON_SFT 8 +#define MVRTC_MON_MSK 0x1f +#define MVRTC_YEAR_SFT 16 +#define MVRTC_YEAR_MSK 0xff + +#endif

On Mon, Aug 01, 2011 at 02:09:13PM +0000, Jason Cooper wrote:
This driver can be used for kirkwood SoCs by enabling CONFIG_RTC_MV. Tested on Global Scale Technologies Dreamplug.
Signed-off-by: Jason Cooper u-boot@lakedaemon.net
Tested-by: Simon Guinot sguinot@lacie.com
Changes from v1:
- renamed files to mvrtc.{c,h}
- used proper c-structs for register access
- used existing macros for register access
- removed RFC
Changes from v2:
- use bin2bcd() and bcd2bin() to make code easier to read
- changed CONFIG_RTC_MVINTEG -> CONFIG_RTC_MV
- use 24 hour mode, detect if rtc went into 12 hour mode
- add check if ticking to rtc_reset()
arch/arm/include/asm/arch-kirkwood/kirkwood.h | 1 + drivers/rtc/Makefile | 1 + drivers/rtc/mvrtc.c | 124 +++++++++++++++++++++++++ drivers/rtc/mvrtc.h | 65 +++++++++++++ 4 files changed, 191 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..ca27745 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_MV) += mvrtc.o 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..ccc573a --- /dev/null +++ b/drivers/rtc/mvrtc.c @@ -0,0 +1,124 @@ +/*
- Copyright (C) 2011
- Jason Cooper u-boot@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;
- 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);
- /* test for 12 hour clock (can't tell if it's am/pm) */
- if (time & MVRTC_HRFMT_MSK) {
printf("Error: RTC in 12 hour mode, can't determine AM/PM.\n");
return -1;
- }
- /* time */
- t->tm_sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK);
- t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & MVRTC_MIN_MSK);
- t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK);
- t->tm_wday = bcd2bin((time >> MVRTC_DAY_SFT) & MVRTC_DAY_MSK);
- t->tm_wday--;
- /* date */
- t->tm_mday = bcd2bin((date >> MVRTC_DATE_SFT) & MVRTC_DATE_MSK);
- t->tm_mon = bcd2bin((date >> MVRTC_MON_SFT) & MVRTC_MON_MSK);
- t->tm_year = bcd2bin((date >> MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK);
- t->tm_year += CENTURY * 100;
- /* 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; /* sets hour format bit to zero, 24hr format. */
- u32 date = 0;
- struct mvrtc_registers *mvrtc_regs;
- mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE;
- /* check that this code isn't 80+ years old ;-) */
- if ((t->tm_year / 100) != CENTURY)
printf("Warning: Only century %d supported.\n", CENTURY);
- /* time */
- time |= (bin2bcd(t->tm_sec) & MVRTC_SEC_MSK) << MVRTC_SEC_SFT;
- time |= (bin2bcd(t->tm_min) & MVRTC_MIN_MSK) << MVRTC_MIN_SFT;
- time |= (bin2bcd(t->tm_hour) & MVRTC_HOUR_MSK) << MVRTC_HOUR_SFT;
- time |= (bin2bcd(t->tm_wday + 1) & MVRTC_DAY_MSK) << MVRTC_DAY_SFT;
- /* date */
- date |= (bin2bcd(t->tm_mday) & MVRTC_DATE_MSK) << MVRTC_DATE_SFT;
- date |= (bin2bcd(t->tm_mon) & MVRTC_MON_MSK) << MVRTC_MON_SFT;
- date |= (bin2bcd(t->tm_year % 100) & MVRTC_YEAR_MSK) << MVRTC_YEAR_SFT;
- /* write the time register */
- writel(time, &mvrtc_regs->time);
- /* write the date register */
- writel(date, &mvrtc_regs->date);
- return 0;
+}
+void rtc_reset(void) +{
- u32 time;
- u32 sec;
- struct mvrtc_registers *mvrtc_regs;
- mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE;
- /* no init routine for this RTC needed, just check that it's working */
- time = readl(&mvrtc_regs->time);
- sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK);
- udelay(1000000);
- time = readl(&mvrtc_regs->time);
- if (sec == bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK))
printf("Error: RTC did not increment.\n");
+} diff --git a/drivers/rtc/mvrtc.h b/drivers/rtc/mvrtc.h new file mode 100644 index 0000000..b9d5c6f --- /dev/null +++ b/drivers/rtc/mvrtc.h @@ -0,0 +1,65 @@ +/*
- Copyright (C) 2011
- Jason Cooper u-boot@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
- */
+#ifndef _MVRTC_H_ +#define _MVRTC_H_
+#include <asm/arch/kirkwood.h> +#include <compiler.h>
+/* RTC registers */ +struct mvrtc_registers {
- u32 time;
- u32 date;
+};
+/* time register */ +#define MVRTC_SEC_SFT 0 +#define MVRTC_SEC_MSK 0x7f +#define MVRTC_MIN_SFT 8 +#define MVRTC_MIN_MSK 0x7f +#define MVRTC_HOUR_SFT 16 +#define MVRTC_HOUR_MSK 0x3f +#define MVRTC_DAY_SFT 24 +#define MVRTC_DAY_MSK 0x7
+/*
- Hour format bit
- 1 = 12 hour clock
- 0 = 24 hour clock
- */
+#define MVRTC_HRFMT_MSK 0x00400000
+/* date register */ +#define MVRTC_DATE_SFT 0 +#define MVRTC_DATE_MSK 0x3f +#define MVRTC_MON_SFT 8 +#define MVRTC_MON_MSK 0x1f +#define MVRTC_YEAR_SFT 16 +#define MVRTC_YEAR_MSK 0xff
+#endif
1.7.0.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

-----Original Message----- From: Jason Cooper [mailto:u-boot@lakedaemon.net] Sent: Monday, August 01, 2011 7:39 PM To: wd@denx.de; Prafulla Wadaskar Cc: u-boot@lists.denx.de; clint@debian.org; Prabhanjan Sarnaik; Ashish Karkare; Siddarth Gore; bdale@gag.com; Jason Cooper Subject: [PATCH v3] drivers/rtc: add Marvell Integrated RTC.
This driver can be used for kirkwood SoCs by enabling CONFIG_RTC_MV. Tested on Global Scale Technologies Dreamplug.
Signed-off-by: Jason Cooper u-boot@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
Changes from v2:
- use bin2bcd() and bcd2bin() to make code easier to read
- changed CONFIG_RTC_MVINTEG -> CONFIG_RTC_MV
- use 24 hour mode, detect if rtc went into 12 hour mode
- add check if ticking to rtc_reset()
arch/arm/include/asm/arch-kirkwood/kirkwood.h | 1 + drivers/rtc/Makefile | 1 + drivers/rtc/mvrtc.c | 124 +++++++++++++++++++++++++ drivers/rtc/mvrtc.h | 65 +++++++++++++ 4 files changed, 191 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..ca27745 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_MV) += mvrtc.o 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..ccc573a --- /dev/null +++ b/drivers/rtc/mvrtc.c @@ -0,0 +1,124 @@ +/*
- Copyright (C) 2011
- Jason Cooper u-boot@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;
- 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);
- /* test for 12 hour clock (can't tell if it's am/pm) */
- if (time & MVRTC_HRFMT_MSK) {
printf("Error: RTC in 12 hour mode, can't determine AM/PM.\n");
return -1;
- }
- /* time */
- t->tm_sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK);
- t->tm_min = bcd2bin((time >> MVRTC_MIN_SFT) & MVRTC_MIN_MSK);
- t->tm_hour = bcd2bin((time >> MVRTC_HOUR_SFT) & MVRTC_HOUR_MSK);
- t->tm_wday = bcd2bin((time >> MVRTC_DAY_SFT) & MVRTC_DAY_MSK);
- t->tm_wday--;
- /* date */
- t->tm_mday = bcd2bin((date >> MVRTC_DATE_SFT) & MVRTC_DATE_MSK);
- t->tm_mon = bcd2bin((date >> MVRTC_MON_SFT) & MVRTC_MON_MSK);
- t->tm_year = bcd2bin((date >> MVRTC_YEAR_SFT) & MVRTC_YEAR_MSK);
- t->tm_year += CENTURY * 100;
- /* 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; /* sets hour format bit to zero, 24hr format. */
- u32 date = 0;
- struct mvrtc_registers *mvrtc_regs;
- mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE;
- /* check that this code isn't 80+ years old ;-) */
- if ((t->tm_year / 100) != CENTURY)
printf("Warning: Only century %d supported.\n", CENTURY);
- /* time */
- time |= (bin2bcd(t->tm_sec) & MVRTC_SEC_MSK) << MVRTC_SEC_SFT;
- time |= (bin2bcd(t->tm_min) & MVRTC_MIN_MSK) << MVRTC_MIN_SFT;
- time |= (bin2bcd(t->tm_hour) & MVRTC_HOUR_MSK) <<
MVRTC_HOUR_SFT;
- time |= (bin2bcd(t->tm_wday + 1) & MVRTC_DAY_MSK) << MVRTC_DAY_SFT;
- /* date */
- date |= (bin2bcd(t->tm_mday) & MVRTC_DATE_MSK) <<
MVRTC_DATE_SFT;
- date |= (bin2bcd(t->tm_mon) & MVRTC_MON_MSK) <<
MVRTC_MON_SFT;
- date |= (bin2bcd(t->tm_year % 100) & MVRTC_YEAR_MSK) <<
MVRTC_YEAR_SFT;
- /* write the time register */
- writel(time, &mvrtc_regs->time);
- /* write the date register */
- writel(date, &mvrtc_regs->date);
- return 0;
+}
+void rtc_reset(void) +{
- u32 time;
- u32 sec;
- struct mvrtc_registers *mvrtc_regs;
- mvrtc_regs = (struct mvrtc_registers *)KW_RTC_BASE;
- /* no init routine for this RTC needed, just check that it's working
*/
- time = readl(&mvrtc_regs->time);
- sec = bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK);
- udelay(1000000);
- time = readl(&mvrtc_regs->time);
- if (sec == bcd2bin((time >> MVRTC_SEC_SFT) & MVRTC_SEC_MSK))
printf("Error: RTC did not increment.\n");
+} diff --git a/drivers/rtc/mvrtc.h b/drivers/rtc/mvrtc.h new file mode 100644 index 0000000..b9d5c6f --- /dev/null +++ b/drivers/rtc/mvrtc.h @@ -0,0 +1,65 @@ +/*
- Copyright (C) 2011
- Jason Cooper u-boot@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
- */
+#ifndef _MVRTC_H_ +#define _MVRTC_H_
+#include <asm/arch/kirkwood.h> +#include <compiler.h>
+/* RTC registers */ +struct mvrtc_registers {
- u32 time;
- u32 date;
+};
+/* time register */ +#define MVRTC_SEC_SFT 0 +#define MVRTC_SEC_MSK 0x7f +#define MVRTC_MIN_SFT 8 +#define MVRTC_MIN_MSK 0x7f +#define MVRTC_HOUR_SFT 16 +#define MVRTC_HOUR_MSK 0x3f +#define MVRTC_DAY_SFT 24 +#define MVRTC_DAY_MSK 0x7
+/*
- Hour format bit
- 1 = 12 hour clock
- 0 = 24 hour clock
- */
+#define MVRTC_HRFMT_MSK 0x00400000
+/* date register */ +#define MVRTC_DATE_SFT 0 +#define MVRTC_DATE_MSK 0x3f +#define MVRTC_MON_SFT 8 +#define MVRTC_MON_MSK 0x1f +#define MVRTC_YEAR_SFT 16 +#define MVRTC_YEAR_MSK 0xff
+#endif
Acked-By: Prafulla Wadaskar Prafulla@marvell.com
Regards.. Prafulla . .
-- 1.7.0.4

-----Original Message----- From: Jason Cooper [mailto:u-boot@lakedaemon.net] Sent: Monday, August 01, 2011 7:39 PM To: wd@denx.de; Prafulla Wadaskar Cc: u-boot@lists.denx.de; clint@debian.org; Prabhanjan Sarnaik; Ashish Karkare; Siddarth Gore; bdale@gag.com; Jason Cooper Subject: [PATCH v3] drivers/rtc: add Marvell Integrated RTC.
This driver can be used for kirkwood SoCs by enabling CONFIG_RTC_MV. Tested on Global Scale Technologies Dreamplug.
Signed-off-by: Jason Cooper u-boot@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
Changes from v2:
- use bin2bcd() and bcd2bin() to make code easier to read
- changed CONFIG_RTC_MVINTEG -> CONFIG_RTC_MV
- use 24 hour mode, detect if rtc went into 12 hour mode
- add check if ticking to rtc_reset()
arch/arm/include/asm/arch-kirkwood/kirkwood.h | 1 + drivers/rtc/Makefile | 1 + drivers/rtc/mvrtc.c | 124 +++++++++++++++++++++++++ drivers/rtc/mvrtc.h | 65 +++++++++++++ 4 files changed, 191 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/mvrtc.c create mode 100644 drivers/rtc/mvrtc.h
Applied to u-boot-marvell.git master branch
Regards.. Prafulla . .
participants (4)
-
Jason
-
Jason Cooper
-
Prafulla Wadaskar
-
Simon Guinot