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