uboot/drivers/rtc/pt7c4338.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Freescale Semiconductor, Inc.
   3 *
   4 * Author:      Priyanka Jain <Priyanka.Jain@freescale.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9/*
  10 * This file provides Date & Time support (no alarms) for PT7C4338 chip.
  11 *
  12 * This file is based on drivers/rtc/ds1337.c
  13 *
  14 * PT7C4338 chip is manufactured by Pericom Technology Inc.
  15 * It is a serial real-time clock which provides
  16 * 1)Low-power clock/calendar.
  17 * 2)Programmable square-wave output.
  18 * It has 56 bytes of nonvolatile RAM.
  19 */
  20
  21#include <common.h>
  22#include <command.h>
  23#include <rtc.h>
  24#include <i2c.h>
  25
  26/* RTC register addresses */
  27#define RTC_SEC_REG_ADDR        0x0
  28#define RTC_MIN_REG_ADDR        0x1
  29#define RTC_HR_REG_ADDR         0x2
  30#define RTC_DAY_REG_ADDR        0x3
  31#define RTC_DATE_REG_ADDR       0x4
  32#define RTC_MON_REG_ADDR        0x5
  33#define RTC_YR_REG_ADDR         0x6
  34#define RTC_CTL_STAT_REG_ADDR   0x7
  35
  36/* RTC second register address bit */
  37#define RTC_SEC_BIT_CH          0x80    /* Clock Halt (in Register 0) */
  38
  39/* RTC control and status register bits */
  40#define RTC_CTL_STAT_BIT_RS0    0x1     /* Rate select 0 */
  41#define RTC_CTL_STAT_BIT_RS1    0x2     /* Rate select 1 */
  42#define RTC_CTL_STAT_BIT_SQWE   0x10    /* Square Wave Enable */
  43#define RTC_CTL_STAT_BIT_OSF    0x20    /* Oscillator Stop Flag */
  44#define RTC_CTL_STAT_BIT_OUT    0x80    /* Output Level Control */
  45
  46/* RTC reset value */
  47#define RTC_PT7C4338_RESET_VAL \
  48        (RTC_CTL_STAT_BIT_RS0 | RTC_CTL_STAT_BIT_RS1 | RTC_CTL_STAT_BIT_OUT)
  49
  50/****** Helper functions ****************************************/
  51static u8 rtc_read(u8 reg)
  52{
  53        return i2c_reg_read(CONFIG_SYS_I2C_RTC_ADDR, reg);
  54}
  55
  56static void rtc_write(u8 reg, u8 val)
  57{
  58        i2c_reg_write(CONFIG_SYS_I2C_RTC_ADDR, reg, val);
  59}
  60/****************************************************************/
  61
  62/* Get the current time from the RTC */
  63int rtc_get(struct rtc_time *tmp)
  64{
  65        int ret = 0;
  66        u8 sec, min, hour, mday, wday, mon, year, ctl_stat;
  67
  68        ctl_stat = rtc_read(RTC_CTL_STAT_REG_ADDR);
  69        sec = rtc_read(RTC_SEC_REG_ADDR);
  70        min = rtc_read(RTC_MIN_REG_ADDR);
  71        hour = rtc_read(RTC_HR_REG_ADDR);
  72        wday = rtc_read(RTC_DAY_REG_ADDR);
  73        mday = rtc_read(RTC_DATE_REG_ADDR);
  74        mon = rtc_read(RTC_MON_REG_ADDR);
  75        year = rtc_read(RTC_YR_REG_ADDR);
  76        debug("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
  77                "hr: %02x min: %02x sec: %02x control_status: %02x\n",
  78                year, mon, mday, wday, hour, min, sec, ctl_stat);
  79
  80        if (ctl_stat & RTC_CTL_STAT_BIT_OSF) {
  81                printf("### Warning: RTC oscillator has stopped\n");
  82                /* clear the OSF flag */
  83                rtc_write(RTC_CTL_STAT_REG_ADDR,
  84                        rtc_read(RTC_CTL_STAT_REG_ADDR)\
  85                        & ~RTC_CTL_STAT_BIT_OSF);
  86                ret = -1;
  87        }
  88
  89        tmp->tm_sec = bcd2bin(sec & 0x7F);
  90        tmp->tm_min = bcd2bin(min & 0x7F);
  91        tmp->tm_hour = bcd2bin(hour & 0x3F);
  92        tmp->tm_mday = bcd2bin(mday & 0x3F);
  93        tmp->tm_mon = bcd2bin(mon & 0x1F);
  94        tmp->tm_year = bcd2bin(year) + 2000;
  95        tmp->tm_wday = bcd2bin((wday - 1) & 0x07);
  96        tmp->tm_yday = 0;
  97        tmp->tm_isdst = 0;
  98        debug("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
  99                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 100                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 101
 102        return ret;
 103}
 104
 105/* Set the RTC */
 106int rtc_set(struct rtc_time *tmp)
 107{
 108        debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 109                tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 110                tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 111
 112        rtc_write(RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100));
 113        rtc_write(RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon));
 114        rtc_write(RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday + 1));
 115        rtc_write(RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday));
 116        rtc_write(RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour));
 117        rtc_write(RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min));
 118        rtc_write(RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec));
 119
 120        return 0;
 121}
 122
 123/* Reset the RTC */
 124void rtc_reset(void)
 125{
 126        rtc_write(RTC_SEC_REG_ADDR, 0x00);      /* clearing Clock Halt  */
 127        rtc_write(RTC_CTL_STAT_REG_ADDR, RTC_PT7C4338_RESET_VAL);
 128}
 129