Commit 5c4fa2eea0d68764766b5996baa5508f64f1f64b

Authored by Heiko Schocher
Committed by Wolfgang Denk
1 parent 466f0137e8

rtc: add support for Micro Crystal RV-3029-C2 RTC

Signed-off-by: Heiko Schocher <hs@denx.de>

Showing 2 changed files with 125 additions and 0 deletions Side-by-side Diff

drivers/rtc/Makefile
... ... @@ -60,6 +60,7 @@
60 60 COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
61 61 COBJS-$(CONFIG_RTC_RS5C372A) += rs5c372.o
62 62 COBJS-$(CONFIG_RTC_RTC4543) += rtc4543.o
  63 +COBJS-$(CONFIG_RTC_RV3029) += rv3029.o
63 64 COBJS-$(CONFIG_RTC_RX8025) += rx8025.o
64 65 COBJS-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o
65 66 COBJS-$(CONFIG_RTC_S3C44B0) += s3c44b0_rtc.o
drivers/rtc/rv3029.c
  1 +/*
  2 + * (C) Copyright 2010
  3 + * Heiko Schocher, DENX Software Engineering, hs@denx.de
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +#include <common.h>
  24 +#include <command.h>
  25 +#include <i2c.h>
  26 +#include <rtc.h>
  27 +
  28 +#define RTC_RV3029_CTRL_RESET 0x04
  29 +#define RTC_RV3029_CTRL_SYS_R (1 << 4)
  30 +
  31 +#define RTC_RV3029_CLOCK_PAGE 0x08
  32 +#define RTC_RV3029_PAGE_LEN 7
  33 +
  34 +#define RV3029C2_W_SECONDS 0x00
  35 +#define RV3029C2_W_MINUTES 0x01
  36 +#define RV3029C2_W_HOURS 0x02
  37 +#define RV3029C2_W_DATE 0x03
  38 +#define RV3029C2_W_DAYS 0x04
  39 +#define RV3029C2_W_MONTHS 0x05
  40 +#define RV3029C2_W_YEARS 0x06
  41 +
  42 +#define RV3029C2_REG_HR_12_24 (1 << 6) /* 24h/12h mode */
  43 +#define RV3029C2_REG_HR_PM (1 << 5) /* PM/AM bit in 12h mode */
  44 +
  45 +int rtc_get( struct rtc_time *tmp )
  46 +{
  47 + int ret;
  48 + unsigned char buf[RTC_RV3029_PAGE_LEN];
  49 +
  50 + ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1, buf, \
  51 + RTC_RV3029_PAGE_LEN);
  52 + if (ret) {
  53 + printf("%s: error reading RTC: %x\n", __func__, ret);
  54 + return -1;
  55 + }
  56 + tmp->tm_sec = bcd2bin( buf[RV3029C2_W_SECONDS] & 0x7f);
  57 + tmp->tm_min = bcd2bin( buf[RV3029C2_W_MINUTES] & 0x7f);
  58 + if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_12_24) {
  59 + /* 12h format */
  60 + tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x1f);
  61 + if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_PM)
  62 + /* PM flag set */
  63 + tmp->tm_hour += 12;
  64 + } else
  65 + tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x3f);
  66 +
  67 + tmp->tm_mday = bcd2bin( buf[RV3029C2_W_DATE] & 0x3F );
  68 + tmp->tm_mon = bcd2bin( buf[RV3029C2_W_MONTHS] & 0x1F );
  69 + tmp->tm_wday = bcd2bin( buf[RV3029C2_W_DAYS] & 0x07 );
  70 + /* RTC supports only years > 1999 */
  71 + tmp->tm_year = bcd2bin( buf[RV3029C2_W_YEARS]) + 2000;
  72 + tmp->tm_yday = 0;
  73 + tmp->tm_isdst = 0;
  74 +
  75 +#ifdef RTC_DEBUG
  76 + printf( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
  77 + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
  78 + tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
  79 +
  80 +#endif
  81 + return 0;
  82 +}
  83 +
  84 +int rtc_set( struct rtc_time *tmp )
  85 +{
  86 + int ret;
  87 + unsigned char buf[RTC_RV3029_PAGE_LEN];
  88 +#ifdef RTC_DEBUG
  89 + printf( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
  90 + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
  91 + tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  92 +#endif
  93 +
  94 + if (tmp->tm_year < 2000) {
  95 + printf("RTC: year %d < 2000 not possible\n", tmp->tm_year);
  96 + return -1;
  97 + }
  98 + buf[RV3029C2_W_SECONDS] = bin2bcd(tmp->tm_sec);
  99 + buf[RV3029C2_W_MINUTES] = bin2bcd(tmp->tm_min);
  100 + buf[RV3029C2_W_HOURS] = bin2bcd(tmp->tm_hour);
  101 + /* set 24h format */
  102 + buf[RV3029C2_W_HOURS] &= ~RV3029C2_REG_HR_12_24;
  103 + buf[RV3029C2_W_DATE] = bin2bcd(tmp->tm_mday);
  104 + buf[RV3029C2_W_DAYS] = bin2bcd(tmp->tm_wday);
  105 + buf[RV3029C2_W_MONTHS] = bin2bcd(tmp->tm_mon);
  106 + tmp->tm_year -= 2000;
  107 + buf[RV3029C2_W_YEARS] = bin2bcd(tmp->tm_year);
  108 + ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1,
  109 + buf, RTC_RV3029_PAGE_LEN);
  110 +
  111 + /* give the RTC some time to update */
  112 + udelay(1000);
  113 + return 0;
  114 +}
  115 +
  116 +void rtc_reset (void)
  117 +{
  118 + int ret;
  119 + unsigned char buf[RTC_RV3029_PAGE_LEN];
  120 +
  121 + buf[0] = RTC_RV3029_CTRL_SYS_R;
  122 + ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL_RESET, 1,
  123 + buf, 1);
  124 +}