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

From: Jason Cooper u-boot@lakedaemon.net
rewrite of the not-merged code from Globalscale Technologies. This RTC is known to exist in the DreamPlug platform and is accessed via two registers.
Signed-off-by: Jason Cooper u-boot@lakedaemon.net --- Questions: - I completely rewrote this, should I add mention of Commercial/GPL2+/BSD (pick your license) source files I based it on? http://people.debian.org/~clint/dreamplug/dreamplug-uboot-gti.tar.gz - The link is a dirty git tree. The uncommitted stuff is how they modified Guruplug u-boot to work on the Dreamplug. - chmod -x the changed files to undo the windows fs stuff. - the usb storage changes are already in. - I'm close on the SPI flash stuff. - This patch is the RTC driver. - Their MPP cfg is cleaner than mine, I'll use theirs. - I'll add the clock stuff in a future patch. - I feel that register definitions should be somewhere else, like SoC code. But I don't know if this is Dreamplug-specific, kirkwood-specific, or other? - common/cmd_date.c assumes I2C interface, is that harmless? - common/cmd_date.c checks return value. The register ops have no return value. I assume it's safe to always return zero? - Is there an easy way to calc the day of the year based on the info in the date register? I don't like leaving that set ot zero. - This is compile-tested. Once I get back to my Dreamplug, I will test. - checkpatch has 2 warnings about volatile. My understanding is that it is needed when reading/writing registers.
drivers/rtc/Makefile | 1 + drivers/rtc/mvinteg_rtc.c | 151 +++++++++++++++++++++++++++++++++++++++++++ drivers/rtc/mvinteg_rtc.h | 89 +++++++++++++++++++++++++ include/configs/dreamplug.h | 8 ++ 4 files changed, 249 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/mvinteg_rtc.c create mode 100644 drivers/rtc/mvinteg_rtc.h
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e4be4a4..ed63e9c 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) += mvinteg_rtc.o COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o COBJS-$(CONFIG_RTC_PL031) += pl031.o COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o diff --git a/drivers/rtc/mvinteg_rtc.c b/drivers/rtc/mvinteg_rtc.c new file mode 100644 index 0000000..1fcfba5 --- /dev/null +++ b/drivers/rtc/mvinteg_rtc.c @@ -0,0 +1,151 @@ +/* + * 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 "mvinteg_rtc.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; + + /* read the time register */ + time = MV_REG_READ(MVINTEG_RTCTIME_REG); + + /* read the date register */ + date = MV_REG_READ(MVINTEG_RTCDATE_REG); + + /* seconds */ + tens = ((time & MVINTEG_10SEC_MSK) >> MVINTEG_10SEC_SFT); + single = ((time & MVINTEG_SEC_MSK) >> MVINTEG_SEC_SFT); + t->tm_sec = 10 * tens + single; + + /* minutes */ + tens = ((time & MVINTEG_10MIN_MSK) >> MVINTEG_10MIN_SFT); + single = ((time & MVINTEG_MIN_MSK) >> MVINTEG_MIN_SFT); + t->tm_min = 10 * tens + single; + + /* hours */ + tens = ((time & MVINTEG_10HOUR_MSK) >> MVINTEG_10HOUR_SFT); + single = ((time & MVINTEG_HOUR_MSK) >> MVINTEG_HOUR_SFT); + t->tm_hour = 10 * tens + single; + + /* day */ + t->tm_wday = ((time & MVINTEG_DAY_MSK) >> MVINTEG_DAY_SFT); + t->tm_wday--; + + /* date */ + tens = ((date & MVINTEG_10DATE_MSK) >> MVINTEG_10DATE_SFT); + single = ((date & MVINTEG_DATE_MSK) >> MVINTEG_DATE_SFT); + t->tm_mday = 10 * tens + single; + + /* month */ + tens = ((date & MVINTEG_10MON_MSK) >> MVINTEG_10MON_SFT); + single = ((date & MVINTEG_MON_MSK) >> MVINTEG_MON_SFT); + t->tm_mon = 10 * tens + single; + + /* year */ + tens = ((date * MVINTEG_10YEAR_MSK) >> MVINTEG_10YEAR_SFT); + single = ((date & MVINTEG_YEAR_MSK) >> MVINTEG_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; + + /* seconds */ + tens = t->tm_sec / 10; + single = t->tm_sec % 10; + time |= ((tens << MVINTEG_10SEC_SFT) & MVINTEG_10SEC_MSK) | + ((single << MVINTEG_SEC_SFT) & MVINTEG_SEC_MSK); + + /* minutes */ + tens = t->tm_min / 10; + single = t->tm_min % 10; + time |= ((tens << MVINTEG_10MIN_SFT) & MVINTEG_10MIN_MSK) | + ((single << MVINTEG_MIN_SFT) & MVINTEG_MIN_MSK); + + /* hours (24) */ + tens = t->tm_hour / 10; + single = t->tm_hour % 10; + time |= ((tens << MVINTEG_10HOUR_SFT) & MVINTEG_10HOUR_MSK) | + ((single << MVINTEG_HOUR_SFT) & MVINTEG_HOUR_MSK); + + /* day */ + single = t->tm_wday + 1; + time |= ((single << MVINTEG_DAY_SFT) & MVINTEG_DAY_MSK); + + /* date */ + tens = t->tm_mday / 10; + single = t->tm_mday % 10; + date |= ((tens << MVINTEG_10DATE_SFT) & MVINTEG_10DATE_MSK) | + ((single << MVINTEG_DATE_SFT) & MVINTEG_DATE_MSK); + + /* month */ + tens = t->tm_mon / 10; + single = t->tm_mon % 10; + date |= ((tens << MVINTEG_10MON_SFT) & MVINTEG_10MON_MSK) | + ((single << MVINTEG_MON_SFT) & MVINTEG_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 << MVINTEG_10YEAR_SFT) & MVINTEG_10YEAR_MSK) | + ((single << MVINTEG_YEAR_SFT) & MVINTEG_YEAR_MSK); + + /* write the time register */ + MV_REG_WRITE(MVINTEG_RTCTIME_REG, time); + + /* write the date register */ + MV_REG_WRITE(MVINTEG_RTCDATE_REG, date); + + return 0; +} + +void rtc_reset(void) +{ + /* no init routine for this RTC needed */ +} diff --git a/drivers/rtc/mvinteg_rtc.h b/drivers/rtc/mvinteg_rtc.h new file mode 100644 index 0000000..08070d9 --- /dev/null +++ b/drivers/rtc/mvinteg_rtc.h @@ -0,0 +1,89 @@ +/* + * 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 _MVINTEG_RTC_H_ +#define _MVINTEG_RTC_H_ + +#include <compiler.h> + +#define INTERNAL_REG_BASE_ADDR 0xf1000000 + +/* register operations macros */ +#define MV_REG_READ(offset) \ + le32_to_cpu( \ + *(volatile unsigned int *)(INTERNAL_REG_BASE_ADDR + offset)) + +#define MV_REG_WRITE(offset, data) \ + do { \ + *(volatile unsigned int *)(INTERNAL_REG_BASE_ADDR + offset) = \ + cpu_to_le32(data) \ + } while (0); + +/* RTC registers */ +#define MVINTEG_RTCTIME_REG 0x10300 +#define MVINTEG_RTCDATE_REG 0x10304 + +/* time register */ +#define MVINTEG_SEC_SFT 0 +#define MVINTEG_SEC_MSK (0xf << MVINTEG_SEC_SFT) +#define MVINTEG_10SEC_SFT 4 +#define MVINTEG_10SEC_MSK (0x7 << MVINTEG_10SEC_SFT) + +#define MVINTEG_MIN_SFT 8 +#define MVINTEG_MIN_MSK (0xf << MVINTEG_MIN_SFT) +#define MVINTEG_10MIN_SFT 12 +#define MVINTEG_10MIN_MSK (0x7 << MVINTEG_10MIN_SFT) + +#define MVINTEG_HOUR_SFT 16 +#define MVINTEG_HOUR_MSK (0xf << MVINTEG_HOUR_SFT) +#define MVINTEG_10HOUR_SFT 20 +#define MVINTEG_10HOUR_MSK (0x3 << MVINTEG_10HOUR_SFT) + +#define MVINTEG_HRFMT_SFT 22 +#define MVINTEG_HRFMT12_MSK (0x1 << MVINTEG_HRFMT_SFT) +#define MVINTEG_HRFMT24_MSK (0x0 << MVINTEG_HRFMT_SFT) + +#define MVINTEG_DAY_SFT 24 +#define MVINTEG_DAY_MSK (0x7 << MVINTEG_DAY_SFT) + +/* date register */ +#define MVINTEG_DATE_SFT 0 +#define MVINTEG_DATE_MSK (0xf << MVINTEG_DATE_SFT) +#define MVINTEG_10DATE_SFT 4 +#define MVINTEG_10DATE_MSK (0x3 << MVINTEG_10DATE_SFT) + +#define MVINTEG_MON_SFT 8 +#define MVINTEG_MON_MSK (0xf << MVINTEG_MON_SFT) +#define MVINTEG_10MON_SFT 12 +#define MVINTEG_10MON_MSK (0x1 << MVINTEG_10MON_SFT) + +#define MVINTEG_YEAR_SFT 16 +#define MVINTEG_YEAR_MSK (0xf << MVINTEG_YEAR_SFT) +#define MVINTEG_10YEAR_SFT 20 +#define MVINTEG_10YEAR_MSK (0xf << MVINTEG_10YEAR_SFT) + +#endif diff --git a/include/configs/dreamplug.h b/include/configs/dreamplug.h index 6aceed9..ed153fe 100644 --- a/include/configs/dreamplug.h +++ b/include/configs/dreamplug.h @@ -109,6 +109,14 @@ #define CONFIG_SYS_ATA_IDE0_OFFSET MV_SATA_PORT0_OFFSET #endif /*CONFIG_MVSATA_IDE*/
+/* + * RTC driver configuration + */ +#ifdef CONFIG_CMD_DATE +#define CONFIG_RTC_MVINTEG +#endif /* CONFIG_CMD_DATE */ + + #define CONFIG_SYS_ALT_MEMTEST
#endif /* _CONFIG_DREAMPLUG_H */

Sorry, this is RFC. In the midst of rebase, commit, checkpatch, repeat I forgot to edit the subject line. My apologies.
thx,
Jason.

On Sun, Jul 24, 2011 at 01:12:01AM +0000, u-boot@lakedaemon.net wrote:
rewrite of the not-merged code from Globalscale Technologies. This RTC is known to exist in the DreamPlug platform and is accessed via two registers.
If I apply this on top of your v4 patch on top of 2011.06, I only need two tweaks to build: MACH_TYPE_DREAMPLUG which will obviously sort itself out, and s/MPP7_GP0/MPP7_GPO/ in board/Marvell/dreamplug/dreamplug.c .
It has not yet been tested on a plug. Do you have a working OpenOCD config for flash/ram?

On Sun, Jul 24, 2011 at 03:56:57PM +0000, Clint Adams wrote:
On Sun, Jul 24, 2011 at 01:12:01AM +0000, u-boot@lakedaemon.net wrote:
rewrite of the not-merged code from Globalscale Technologies. This RTC is known to exist in the DreamPlug platform and is accessed via two registers.
If I apply this on top of your v4 patch on top of 2011.06, I only need two tweaks to build: MACH_TYPE_DREAMPLUG which will obviously sort itself out, and s/MPP7_GP0/MPP7_GPO/ in board/Marvell/dreamplug/dreamplug.c .
Yes, what an embarrassing typo, that shouldn't even build. :-( Well, it was RFC...
It has not yet been tested on a plug. Do you have a working OpenOCD config for flash/ram?
Sort of. The openocd config for the sheevaplug/guruplug is what I use, and is distributed on the dreamplug download page [1]. It does _not_ have support for the SPI flash. You can also use the sheevaplug.cfg shipped with openocd. So, I use openocd or tftp to transfer to RAM, then use u-boot to write to flash.
To test images, or to reflash, I load the known-good u-boot into RAM via openocd, then I'll either reflash it or load a new testing one from there.
To write a u-boot.kwb test image to flash, here is what I do:
openocd$ sheevaplug_init openocd$ load_image u-boot # known good from Marvell openocd$ load_image u-boot.kwb 0x00800000 # monster I created openocd$ resume 0x00600000 # run the known good
then, in u-boot
u-boot$ sf probe 0 u-boot$ sf erase 0x0 0x100000 u-boot$ sf write 0x00800000 0x0 0x100000
If time allows, I'd like to add SPI flash support to OpenOCD. Unfortunately, time is short and the above process works.
hth,
Jason.
[1] http://code.google.com/p/dreamplug/downloads/detail?name=dream_burn_spi.tar....

On Sun, Jul 24, 2011 at 03:13:38PM -0400, Jason wrote:
To write a u-boot.kwb test image to flash, here is what I do:
openocd$ sheevaplug_init openocd$ load_image u-boot # known good from Marvell openocd$ load_image u-boot.kwb 0x00800000 # monster I created openocd$ resume 0x00600000 # run the known good
then, in u-boot
u-boot$ sf probe 0 u-boot$ sf erase 0x0 0x100000 u-boot$ sf write 0x00800000 0x0 0x100000
Okay, here's neat problem. In the globalscale u-boot code, they set the environment address to 0x30000 in the 2MB spi nor flash. So, they have:
#ifdef CONFIG_SPI_FLASH #define CONFIG_ENV_IS_IN_SPI_FLASH 1 #define CONFIG_ENV_SECT_SIZE 0x10000 /* 64K */ #else #define CONFIG_ENV_IS_NOWHERE 1 /* if env in SDRAM */ #endif
and...
#define CONFIG_ENV_SIZE 0x1000 /* 4k */ #define CONFIG_ENV_ADDR 0x30000 #define CONFIG_ENV_OFFSET 0x30000 /* env starts here */
If that's an absolute address, and I wrote my u-boot to 0x0 in the flash, did 'saveenv' to remove the CRC message, then that's why it died after reset, right? I must have overwrote part of u-boot with the env.
In my meager understanding, I thought maybe u-boot structured itself so the env was physically stored 0x30000 into the code and it would magically work. Guess not. :-P
So, what is a standard flash layout? Do I put u-boot at 0x0 and just throw the env out at 0x100000 (1MB), or, put the env at 0x0 and u-boot in the second erase block (0x10000)? Doesn't u-boot have to be at 0x0 so the cpu can find it?
Thanks for any advice.
btw - I have everything else tested and working. RTC, spi flash, cpu speed, etc. This issue is the last holdout before I resubmit v5.
thx,
Jason.

On Tue, Jul 26, 2011 at 02:51:26PM -0400, Jason wrote:
btw - I have everything else tested and working. RTC, spi flash, cpu speed, etc. This issue is the last holdout before I resubmit v5.
Hi Jason,
We same to be having some issues with USB support with your v4 set, particularly that it's unhappy with the internal microsd card. Any ideas?

On Thu, Jul 28, 2011 at 05:14:33PM +0000, Clint Adams wrote:
On Tue, Jul 26, 2011 at 02:51:26PM -0400, Jason wrote:
btw - I have everything else tested and working. RTC, spi flash, cpu speed, etc. This issue is the last holdout before I resubmit v5.
We same to be having some issues with USB support with your v4 set, particularly that it's unhappy with the internal microsd card. Any ideas?
try v5. patch #3 increases the timeout waiting for slow usb chipsets, which works for me.
In the meantime, I'm going to take a more careful look at the usb changes in the tarball you sent me. I checked a few lines of it and it looked like a backported patch that was already in mainline, but I didn't check the whole thing. I'll do so when I address all of Prafulla's comments.
hth,
Jason.
participants (3)
-
Clint Adams
-
Jason
-
u-boot@lakedaemon.net