1/* 2 * Epson RX8010 RTC driver. 3 * 4 * Copyright (c) 2017, General Electric Company 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include <command.h> 20#include <common.h> 21#include <dm.h> 22#include <i2c.h> 23#include <rtc.h> 24#include <linux/bitops.h> 25 26/*---------------------------------------------------------------------*/ 27/* #undef DEBUG_RTC */ 28 29#ifdef DEBUG_RTC 30#define DEBUGR(fmt, args...) printf(fmt, ##args) 31#else 32#define DEBUGR(fmt, args...) 33#endif 34/*---------------------------------------------------------------------*/ 35 36#ifndef CFG_SYS_I2C_RTC_ADDR 37# define CFG_SYS_I2C_RTC_ADDR 0x32 38#endif 39 40/* 41 * RTC register addresses 42 */ 43#define RX8010_SEC 0x10 44#define RX8010_MIN 0x11 45#define RX8010_HOUR 0x12 46#define RX8010_WDAY 0x13 47#define RX8010_MDAY 0x14 48#define RX8010_MONTH 0x15 49#define RX8010_YEAR 0x16 50#define RX8010_YEAR 0x16 51#define RX8010_RESV17 0x17 52#define RX8010_ALMIN 0x18 53#define RX8010_ALHOUR 0x19 54#define RX8010_ALWDAY 0x1A 55#define RX8010_TCOUNT0 0x1B 56#define RX8010_TCOUNT1 0x1C 57#define RX8010_EXT 0x1D 58#define RX8010_FLAG 0x1E 59#define RX8010_CTRL 0x1F 60/* 0x20 to 0x2F are user registers */ 61#define RX8010_RESV30 0x30 62#define RX8010_RESV31 0x32 63#define RX8010_IRQ 0x32 64 65#define RX8010_EXT_WADA BIT(3) 66 67#define RX8010_FLAG_VLF BIT(1) 68#define RX8010_FLAG_AF BIT(3) 69#define RX8010_FLAG_TF BIT(4) 70#define RX8010_FLAG_UF BIT(5) 71 72#define RX8010_CTRL_AIE BIT(3) 73#define RX8010_CTRL_UIE BIT(5) 74#define RX8010_CTRL_STOP BIT(6) 75#define RX8010_CTRL_TEST BIT(7) 76 77#define RX8010_ALARM_AE BIT(7) 78 79#ifdef CONFIG_DM_RTC 80 81#define DEV_TYPE struct udevice 82 83#else 84 85/* Local udevice */ 86struct ludevice { 87 u8 chip; 88}; 89 90#define DEV_TYPE struct ludevice 91 92#endif 93 94static int rx8010sj_rtc_read8(DEV_TYPE *dev, unsigned int reg) 95{ 96 u8 val; 97 int ret; 98 99#ifdef CONFIG_DM_RTC 100 ret = dm_i2c_read(dev, reg, &val, sizeof(val)); 101#else 102 ret = i2c_read(dev->chip, reg, 1, &val, 1); 103#endif 104 105 return ret < 0 ? ret : val; 106} 107 108static int rx8010sj_rtc_write8(DEV_TYPE *dev, unsigned int reg, int val) 109{ 110 int ret; 111 u8 lval = val; 112 113#ifdef CONFIG_DM_RTC 114 ret = dm_i2c_write(dev, reg, &lval, 1); 115#else 116 ret = i2c_write(dev->chip, reg, 1, &lval, 1); 117#endif 118 119 return ret < 0 ? ret : 0; 120} 121 122static int validate_time(const struct rtc_time *tm) 123{ 124 if ((tm->tm_year < 2000) || (tm->tm_year > 2099)) 125 return -EINVAL; 126 127 if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) 128 return -EINVAL; 129 130 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) 131 return -EINVAL; 132 133 if ((tm->tm_wday < 0) || (tm->tm_wday > 6)) 134 return -EINVAL; 135 136 if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) 137 return -EINVAL; 138 139 if ((tm->tm_min < 0) || (tm->tm_min > 59)) 140 return -EINVAL; 141 142 if ((tm->tm_sec < 0) || (tm->tm_sec > 59)) 143 return -EINVAL; 144 145 return 0; 146} 147 148void rx8010sj_rtc_init(DEV_TYPE *dev) 149{ 150 u8 ctrl[2]; 151 int need_clear = 0, ret = 0; 152 153 /* Initialize reserved registers as specified in datasheet */ 154 ret = rx8010sj_rtc_write8(dev, RX8010_RESV17, 0xD8); 155 if (ret < 0) 156 goto error; 157 158 ret = rx8010sj_rtc_write8(dev, RX8010_RESV30, 0x00); 159 if (ret < 0) 160 goto error; 161 162 ret = rx8010sj_rtc_write8(dev, RX8010_RESV31, 0x08); 163 if (ret < 0) 164 goto error; 165 166 ret = rx8010sj_rtc_write8(dev, RX8010_IRQ, 0x00); 167 if (ret < 0) 168 goto error; 169 170 for (int i = 0; i < 2; i++) { 171 ret = rx8010sj_rtc_read8(dev, RX8010_FLAG + i); 172 if (ret < 0) 173 goto error; 174 175 ctrl[i] = ret; 176 } 177 178 if (ctrl[0] & RX8010_FLAG_VLF) 179 printf("RTC low voltage detected\n"); 180 181 if (ctrl[0] & RX8010_FLAG_AF) { 182 printf("Alarm was detected\n"); 183 need_clear = 1; 184 } 185 186 if (ctrl[0] & RX8010_FLAG_TF) 187 need_clear = 1; 188 189 if (ctrl[0] & RX8010_FLAG_UF) 190 need_clear = 1; 191 192 if (need_clear) { 193 ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF); 194 ret = rx8010sj_rtc_write8(dev, RX8010_FLAG, ctrl[0]); 195 if (ret < 0) 196 goto error; 197 } 198 199 return; 200 201error: 202 printf("Error rtc init.\n"); 203} 204 205/* Get the current time from the RTC */ 206static int rx8010sj_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp) 207{ 208 u8 date[7]; 209 int flagreg; 210 int ret; 211 212 flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG); 213 if (flagreg < 0) { 214 DEBUGR("Error reading from RTC. err: %d\n", flagreg); 215 return -EIO; 216 } 217 218 if (flagreg & RX8010_FLAG_VLF) { 219 DEBUGR("RTC low voltage detected\n"); 220 return -EINVAL; 221 } 222 223 for (int i = 0; i < 7; i++) { 224 ret = rx8010sj_rtc_read8(dev, RX8010_SEC + i); 225 if (ret < 0) { 226 DEBUGR("Error reading from RTC. err: %d\n", ret); 227 return -EIO; 228 } 229 date[i] = ret; 230 } 231 232 tmp->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f); 233 tmp->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f); 234 tmp->tm_hour = bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f); 235 tmp->tm_mday = bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f); 236 tmp->tm_mon = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f); 237 tmp->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 2000; 238 tmp->tm_wday = 0; 239 tmp->tm_yday = 0; 240 tmp->tm_isdst = 0; 241 242 DEBUGR("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 243 tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, 244 tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 245 246 return 0; 247} 248 249/* Set the RTC */ 250static int rx8010sj_rtc_set(DEV_TYPE *dev, const struct rtc_time *tm) 251{ 252 u8 date[7]; 253 int ctrl, flagreg; 254 int ret; 255 256 ret = validate_time(tm); 257 if (ret < 0) 258 return -EINVAL; 259 260 /* set STOP bit before changing clock/calendar */ 261 ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL); 262 if (ctrl < 0) 263 return ctrl; 264 ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl | RX8010_CTRL_STOP); 265 if (ret < 0) 266 return ret; 267 268 date[RX8010_SEC - RX8010_SEC] = bin2bcd(tm->tm_sec); 269 date[RX8010_MIN - RX8010_SEC] = bin2bcd(tm->tm_min); 270 date[RX8010_HOUR - RX8010_SEC] = bin2bcd(tm->tm_hour); 271 date[RX8010_MDAY - RX8010_SEC] = bin2bcd(tm->tm_mday); 272 date[RX8010_MONTH - RX8010_SEC] = bin2bcd(tm->tm_mon); 273 date[RX8010_YEAR - RX8010_SEC] = bin2bcd(tm->tm_year - 2000); 274 date[RX8010_WDAY - RX8010_SEC] = bin2bcd(tm->tm_wday); 275 276 for (int i = 0; i < 7; i++) { 277 ret = rx8010sj_rtc_write8(dev, RX8010_SEC + i, date[i]); 278 if (ret < 0) { 279 DEBUGR("Error writing to RTC. err: %d\n", ret); 280 return -EIO; 281 } 282 } 283 284 /* clear STOP bit after changing clock/calendar */ 285 ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL); 286 if (ctrl < 0) 287 return ctrl; 288 289 ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl & ~RX8010_CTRL_STOP); 290 if (ret < 0) 291 return ret; 292 293 flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG); 294 if (flagreg < 0) 295 return flagreg; 296 297 if (flagreg & RX8010_FLAG_VLF) 298 ret = rx8010sj_rtc_write8(dev, RX8010_FLAG, 299 flagreg & ~RX8010_FLAG_VLF); 300 301 return 0; 302} 303 304/* Reset the RTC. */ 305static int rx8010sj_rtc_reset(DEV_TYPE *dev) 306{ 307 /* Not needed */ 308 return 0; 309} 310 311#ifndef CONFIG_DM_RTC 312 313int rtc_get(struct rtc_time *tm) 314{ 315 struct ludevice dev = { 316 .chip = CFG_SYS_I2C_RTC_ADDR, 317 }; 318 319 return rx8010sj_rtc_get(&dev, tm); 320} 321 322int rtc_set(struct rtc_time *tm) 323{ 324 struct ludevice dev = { 325 .chip = CFG_SYS_I2C_RTC_ADDR, 326 }; 327 328 return rx8010sj_rtc_set(&dev, tm); 329} 330 331void rtc_reset(void) 332{ 333 struct ludevice dev = { 334 .chip = CFG_SYS_I2C_RTC_ADDR, 335 }; 336 337 rx8010sj_rtc_reset(&dev); 338} 339 340void rtc_init(void) 341{ 342 struct ludevice dev = { 343 .chip = CFG_SYS_I2C_RTC_ADDR, 344 }; 345 346 rx8010sj_rtc_init(&dev); 347} 348 349#else 350 351static int rx8010sj_probe(struct udevice *dev) 352{ 353 rx8010sj_rtc_init(dev); 354 355 return 0; 356} 357 358static const struct rtc_ops rx8010sj_rtc_ops = { 359 .get = rx8010sj_rtc_get, 360 .set = rx8010sj_rtc_set, 361 .read8 = rx8010sj_rtc_read8, 362 .write8 = rx8010sj_rtc_write8, 363 .reset = rx8010sj_rtc_reset, 364}; 365 366static const struct udevice_id rx8010sj_rtc_ids[] = { 367 { .compatible = "epson,rx8010sj-rtc" }, 368 { .compatible = "epson,rx8010" }, 369 { } 370}; 371 372U_BOOT_DRIVER(rx8010sj_rtc) = { 373 .name = "rx8010sj_rtc", 374 .id = UCLASS_RTC, 375 .probe = rx8010sj_probe, 376 .of_match = rx8010sj_rtc_ids, 377 .ops = &rx8010sj_rtc_ops, 378}; 379 380#endif 381