1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2019, Vaisala Oyj 4 */ 5 6#include <common.h> 7#include <command.h> 8#include <dm.h> 9#include <i2c.h> 10#include <rtc.h> 11#include <dm/device_compat.h> 12#include <linux/bitops.h> 13 14/* 15 * RTC register addresses 16 */ 17#define RTC_SEC_REG_ADDR 0x00 18#define RTC_MIN_REG_ADDR 0x01 19#define RTC_HR_REG_ADDR 0x02 20#define RTC_DAY_REG_ADDR 0x03 21#define RTC_DATE_REG_ADDR 0x04 22#define RTC_MON_REG_ADDR 0x05 23#define RTC_YR_REG_ADDR 0x06 24#define RTC_CTL_REG_ADDR 0x0e 25#define RTC_STAT_REG_ADDR 0x0f 26#define RTC_TEST_REG_ADDR 0x13 27 28/* 29 * RTC control register bits 30 */ 31#define RTC_CTL_BIT_A1IE BIT(0) /* Alarm 1 interrupt enable */ 32#define RTC_CTL_BIT_A2IE BIT(1) /* Alarm 2 interrupt enable */ 33#define RTC_CTL_BIT_INTCN BIT(2) /* Interrupt control */ 34#define RTC_CTL_BIT_DOSC BIT(7) /* Disable Oscillator */ 35 36/* 37 * RTC status register bits 38 */ 39#define RTC_STAT_BIT_A1F BIT(0) /* Alarm 1 flag */ 40#define RTC_STAT_BIT_A2F BIT(1) /* Alarm 2 flag */ 41#define RTC_STAT_BIT_EN32KHZ BIT(3) /* Enable 32KHz Output */ 42#define RTC_STAT_BIT_BB32KHZ BIT(6) /* Battery backed 32KHz Output */ 43#define RTC_STAT_BIT_OSF BIT(7) /* Oscillator stop flag */ 44 45/* 46 * RTC test register bits 47 */ 48#define RTC_TEST_BIT_SWRST BIT(7) /* Software reset */ 49 50#define RTC_DATE_TIME_REG_SIZE 7 51#define RTC_SRAM_START 0x14 52#define RTC_SRAM_END 0xFF 53#define RTC_SRAM_SIZE 236 54 55struct ds3232_priv_data { 56 u8 max_register; 57 u8 sram_start; 58 int sram_size; 59}; 60 61static int ds3232_rtc_read8(struct udevice *dev, unsigned int reg) 62{ 63 int ret; 64 u8 buf; 65 struct ds3232_priv_data *priv_data; 66 67 priv_data = dev_get_priv(dev); 68 if (!priv_data) 69 return -EINVAL; 70 71 if (reg > priv_data->max_register) 72 return -EINVAL; 73 74 ret = dm_i2c_read(dev, reg, &buf, sizeof(buf)); 75 if (ret < 0) 76 return ret; 77 78 return buf; 79} 80 81static int ds3232_rtc_write8(struct udevice *dev, unsigned int reg, int val) 82{ 83 u8 buf = (u8)val; 84 struct ds3232_priv_data *priv_data; 85 86 priv_data = dev_get_priv(dev); 87 if (!priv_data) 88 return -EINVAL; 89 90 if (reg > priv_data->max_register) 91 return -EINVAL; 92 93 return dm_i2c_write(dev, reg, &buf, sizeof(buf)); 94} 95 96static int reset_sram(struct udevice *dev) 97{ 98 int ret, sram_end, reg; 99 struct ds3232_priv_data *priv_data; 100 101 priv_data = dev_get_priv(dev); 102 if (!priv_data) 103 return -EINVAL; 104 105 sram_end = priv_data->sram_start + priv_data->sram_size; 106 107 for (reg = priv_data->sram_start; reg < sram_end; reg++) { 108 ret = ds3232_rtc_write8(dev, reg, 0x00); 109 if (ret < 0) 110 return ret; 111 } 112 113 return 0; 114} 115 116static int verify_osc(struct udevice *dev) 117{ 118 int ret, rtc_status; 119 120 ret = ds3232_rtc_read8(dev, RTC_STAT_REG_ADDR); 121 if (ret < 0) 122 return ret; 123 124 rtc_status = ret; 125 126 if (rtc_status & RTC_STAT_BIT_OSF) { 127 dev_warn(dev, 128 "oscillator discontinuity flagged, time unreliable\n"); 129 /* 130 * In case OSC was off we cannot trust the SRAM data anymore. 131 * Reset it to 0x00. 132 */ 133 ret = reset_sram(dev); 134 if (ret < 0) 135 return ret; 136 } 137 138 return 0; 139} 140 141static int ds3232_rtc_set(struct udevice *dev, const struct rtc_time *tm) 142{ 143 u8 buf[RTC_DATE_TIME_REG_SIZE]; 144 u8 is_century; 145 146 if (tm->tm_year < 1900 || tm->tm_year > 2099) 147 dev_warn(dev, "WARNING: year should be between 1900 and 2099!\n"); 148 149 is_century = (tm->tm_year >= 2000) ? 0x80 : 0; 150 151 buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec); 152 buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min); 153 buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour); 154 buf[RTC_DAY_REG_ADDR] = bin2bcd(tm->tm_wday + 1); 155 buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday); 156 buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon) | is_century; 157 buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100); 158 159 return dm_i2c_write(dev, 0, buf, sizeof(buf)); 160} 161 162static int ds3232_rtc_get(struct udevice *dev, struct rtc_time *tm) 163{ 164 int ret; 165 u8 buf[RTC_DATE_TIME_REG_SIZE]; 166 u8 is_twelve_hr; 167 u8 is_pm; 168 u8 is_century; 169 170 ret = verify_osc(dev); 171 if (ret < 0) 172 return ret; 173 174 ret = dm_i2c_read(dev, 0, buf, sizeof(buf)); 175 if (ret < 0) 176 return ret; 177 178 /* Extract additional information for AM/PM and century */ 179 is_twelve_hr = buf[RTC_HR_REG_ADDR] & 0x40; 180 is_pm = buf[RTC_HR_REG_ADDR] & 0x20; 181 is_century = buf[RTC_MON_REG_ADDR] & 0x80; 182 183 tm->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F); 184 tm->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F); 185 186 if (is_twelve_hr) 187 tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x1F) 188 + (is_pm ? 12 : 0); 189 else 190 tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR]); 191 192 tm->tm_wday = bcd2bin((buf[RTC_DAY_REG_ADDR] & 0x07) - 1); 193 tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F); 194 tm->tm_mon = bcd2bin((buf[RTC_MON_REG_ADDR] & 0x7F)); 195 tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) 196 + (is_century ? 2000 : 1900); 197 tm->tm_yday = 0; 198 tm->tm_isdst = 0; 199 200 return 0; 201} 202 203static int ds3232_rtc_reset(struct udevice *dev) 204{ 205 int ret; 206 207 ret = reset_sram(dev); 208 if (ret < 0) 209 return ret; 210 211 /* 212 * From datasheet 213 * (https://datasheets.maximintegrated.com/en/ds/DS3232M.pdf): 214 * 215 * The device reset occurs during the normal acknowledge time slot 216 * following the receipt of the data byte carrying that 217 * SWRST instruction a NACK occurs due to the resetting action. 218 * 219 * Therefore we don't verify the result of I2C write operation since it 220 * will fail due the NACK. 221 */ 222 ds3232_rtc_write8(dev, RTC_TEST_REG_ADDR, RTC_TEST_BIT_SWRST); 223 224 return 0; 225} 226 227static int ds3232_probe(struct udevice *dev) 228{ 229 int rtc_status; 230 int ret; 231 struct ds3232_priv_data *priv_data; 232 233 priv_data = dev_get_priv(dev); 234 if (!priv_data) 235 return -EINVAL; 236 237 priv_data->sram_start = RTC_SRAM_START; 238 priv_data->max_register = RTC_SRAM_END; 239 priv_data->sram_size = RTC_SRAM_SIZE; 240 241 ret = ds3232_rtc_read8(dev, RTC_STAT_REG_ADDR); 242 if (ret < 0) 243 return ret; 244 245 rtc_status = ret; 246 247 ret = verify_osc(dev); 248 if (ret < 0) 249 return ret; 250 251 rtc_status &= ~(RTC_STAT_BIT_OSF | RTC_STAT_BIT_A1F | RTC_STAT_BIT_A2F); 252 253 return ds3232_rtc_write8(dev, RTC_STAT_REG_ADDR, rtc_status); 254} 255 256static const struct rtc_ops ds3232_rtc_ops = { 257 .get = ds3232_rtc_get, 258 .set = ds3232_rtc_set, 259 .reset = ds3232_rtc_reset, 260 .read8 = ds3232_rtc_read8, 261 .write8 = ds3232_rtc_write8 262}; 263 264static const struct udevice_id ds3232_rtc_ids[] = { 265 { .compatible = "dallas,ds3232" }, 266 { } 267}; 268 269U_BOOT_DRIVER(rtc_ds3232) = { 270 .name = "rtc-ds3232", 271 .id = UCLASS_RTC, 272 .probe = ds3232_probe, 273 .of_match = ds3232_rtc_ids, 274 .ops = &ds3232_rtc_ops, 275 .priv_auto = sizeof(struct ds3232_priv_data), 276}; 277