"Das U-Boot" Source Tree
at master 196 lines 4.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2008 4 * Tor Krill, Excito Elektronik i Skåne , tor@excito.com 5 * 6 * Modelled after the ds1337 driver 7 */ 8 9/* 10 * Date & Time support (no alarms) for Intersil 11 * ISL1208 Real Time Clock (RTC). 12 */ 13 14#include <command.h> 15#include <dm.h> 16#include <rtc.h> 17#include <i2c.h> 18 19/*---------------------------------------------------------------------*/ 20#ifdef DEBUG_RTC 21#define DEBUGR(fmt,args...) printf(fmt ,##args) 22#else 23#define DEBUGR(fmt,args...) 24#endif 25/*---------------------------------------------------------------------*/ 26 27/* 28 * RTC register addresses 29 */ 30 31#define RTC_SEC_REG_ADDR 0x0 32#define RTC_MIN_REG_ADDR 0x1 33#define RTC_HR_REG_ADDR 0x2 34#define RTC_DATE_REG_ADDR 0x3 35#define RTC_MON_REG_ADDR 0x4 36#define RTC_YR_REG_ADDR 0x5 37#define RTC_DAY_REG_ADDR 0x6 38#define RTC_STAT_REG_ADDR 0x7 39/* 40 * RTC control register bits 41 */ 42 43/* 44 * RTC status register bits 45 */ 46#define RTC_STAT_BIT_ARST 0x80 /* AUTO RESET ENABLE BIT */ 47#define RTC_STAT_BIT_XTOSCB 0x40 /* CRYSTAL OSCILLATOR ENABLE BIT */ 48#define RTC_STAT_BIT_WRTC 0x10 /* WRITE RTC ENABLE BIT */ 49#define RTC_STAT_BIT_ALM 0x04 /* ALARM BIT */ 50#define RTC_STAT_BIT_BAT 0x02 /* BATTERY BIT */ 51#define RTC_STAT_BIT_RTCF 0x01 /* REAL TIME CLOCK FAIL BIT */ 52 53/* 54 * Read an RTC register 55 */ 56 57static int isl1208_rtc_read8(struct udevice *dev, unsigned int reg) 58{ 59 return dm_i2c_reg_read(dev, reg); 60} 61 62/* 63 * Write an RTC register 64 */ 65 66static int isl1208_rtc_write8(struct udevice *dev, unsigned int reg, int val) 67{ 68 return dm_i2c_reg_write(dev, reg, val); 69} 70 71/* 72 * Get the current time from the RTC 73 */ 74 75static int isl1208_rtc_get(struct udevice *dev, struct rtc_time *tmp) 76{ 77 int ret; 78 uchar buf[8], val; 79 80 ret = dm_i2c_read(dev, 0, buf, sizeof(buf)); 81 if (ret < 0) 82 return ret; 83 84 if (buf[RTC_STAT_REG_ADDR] & RTC_STAT_BIT_RTCF) { 85 printf ("### Warning: RTC oscillator has stopped\n"); 86 ret = dm_i2c_read(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 87 if (ret < 0) 88 return ret; 89 90 val = val & ~(RTC_STAT_BIT_BAT | RTC_STAT_BIT_RTCF); 91 ret = dm_i2c_write(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 92 if (ret < 0) 93 return ret; 94 } 95 96 tmp->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F); 97 tmp->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F); 98 tmp->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x3F); 99 tmp->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F); 100 tmp->tm_mon = bcd2bin(buf[RTC_MON_REG_ADDR] & 0x1F); 101 tmp->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) + 2000; 102 tmp->tm_wday = bcd2bin(buf[RTC_DAY_REG_ADDR] & 0x07); 103 tmp->tm_yday = 0; 104 tmp->tm_isdst= 0; 105 106 DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 107 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 108 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 109 110 return 0; 111} 112 113/* 114 * Set the RTC 115 */ 116static int isl1208_rtc_set(struct udevice *dev, const struct rtc_time *tmp) 117{ 118 int ret; 119 uchar val, buf[7]; 120 121 DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 122 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 123 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 124 125 if (tmp->tm_year < 2000 || tmp->tm_year > 2099) 126 printf("WARNING: year should be between 2000 and 2099!\n"); 127 128 /* enable write */ 129 ret = dm_i2c_read(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 130 if (ret < 0) 131 return ret; 132 133 val = val | RTC_STAT_BIT_WRTC; 134 135 ret = dm_i2c_write(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 136 if (ret < 0) 137 return ret; 138 139 buf[RTC_YR_REG_ADDR] = bin2bcd(tmp->tm_year % 100); 140 buf[RTC_MON_REG_ADDR] = bin2bcd(tmp->tm_mon); 141 buf[RTC_DAY_REG_ADDR] = bin2bcd(tmp->tm_wday); 142 buf[RTC_DATE_REG_ADDR] = bin2bcd(tmp->tm_mday); 143 buf[RTC_HR_REG_ADDR] = bin2bcd(tmp->tm_hour) | 0x80; /* 24h clock */ 144 buf[RTC_MIN_REG_ADDR] = bin2bcd(tmp->tm_min); 145 buf[RTC_SEC_REG_ADDR] = bin2bcd(tmp->tm_sec); 146 147 ret = dm_i2c_write(dev, 0, buf, sizeof(buf)); 148 if (ret < 0) 149 return ret; 150 151 /* disable write */ 152 ret = dm_i2c_read(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 153 if (ret < 0) 154 return ret; 155 156 val = val & ~RTC_STAT_BIT_WRTC; 157 ret = dm_i2c_write(dev, RTC_STAT_REG_ADDR, &val, sizeof(val)); 158 if (ret < 0) 159 return ret; 160 161 return 0; 162} 163 164static int isl1208_rtc_reset(struct udevice *dev) 165{ 166 return 0; 167} 168 169static int isl1208_probe(struct udevice *dev) 170{ 171 i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | 172 DM_I2C_CHIP_WR_ADDRESS); 173 174 return 0; 175} 176 177static const struct rtc_ops isl1208_rtc_ops = { 178 .get = isl1208_rtc_get, 179 .set = isl1208_rtc_set, 180 .reset = isl1208_rtc_reset, 181 .read8 = isl1208_rtc_read8, 182 .write8 = isl1208_rtc_write8, 183}; 184 185static const struct udevice_id isl1208_rtc_ids[] = { 186 { .compatible = "isil,isl1208" }, 187 { } 188}; 189 190U_BOOT_DRIVER(rtc_isl1208) = { 191 .name = "rtc-isl1208", 192 .id = UCLASS_RTC, 193 .probe = isl1208_probe, 194 .of_match = isl1208_rtc_ids, 195 .ops = &isl1208_rtc_ops, 196};