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