rtc-rc5t619.c (10116B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * drivers/rtc/rtc-rc5t619.c 4 * 5 * Real time clock driver for RICOH RC5T619 power management chip. 6 * 7 * Copyright (C) 2019 Andreas Kemnade 8 */ 9 10#include <linux/kernel.h> 11#include <linux/device.h> 12#include <linux/errno.h> 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/mfd/rn5t618.h> 16#include <linux/platform_device.h> 17#include <linux/regmap.h> 18#include <linux/bcd.h> 19#include <linux/rtc.h> 20#include <linux/slab.h> 21#include <linux/irqdomain.h> 22 23struct rc5t619_rtc { 24 int irq; 25 struct rtc_device *rtc; 26 struct rn5t618 *rn5t618; 27}; 28 29#define CTRL1_ALARM_ENABLED 0x40 30#define CTRL1_24HR 0x20 31#define CTRL1_PERIODIC_MASK 0xf 32 33#define CTRL2_PON 0x10 34#define CTRL2_ALARM_STATUS 0x80 35#define CTRL2_CTFG 0x4 36#define CTRL2_CTC 0x1 37 38#define MONTH_CENTFLAG 0x80 39#define HOUR_PMFLAG 0x20 40#define MDAY_DAL_EXT 0x80 41 42static uint8_t rtc5t619_12hour_bcd2bin(uint8_t hour) 43{ 44 if (hour & HOUR_PMFLAG) { 45 hour = bcd2bin(hour & ~HOUR_PMFLAG); 46 return hour == 12 ? 12 : 12 + hour; 47 } 48 49 hour = bcd2bin(hour); 50 return hour == 12 ? 0 : hour; 51} 52 53static uint8_t rtc5t619_12hour_bin2bcd(uint8_t hour) 54{ 55 if (!hour) 56 return 0x12; 57 58 if (hour < 12) 59 return bin2bcd(hour); 60 61 if (hour == 12) 62 return 0x12 | HOUR_PMFLAG; 63 64 return bin2bcd(hour - 12) | HOUR_PMFLAG; 65} 66 67static int rc5t619_rtc_periodic_disable(struct device *dev) 68{ 69 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 70 int err; 71 72 /* disable function */ 73 err = regmap_update_bits(rtc->rn5t618->regmap, 74 RN5T618_RTC_CTRL1, CTRL1_PERIODIC_MASK, 0); 75 if (err < 0) 76 return err; 77 78 /* clear alarm flag and CTFG */ 79 err = regmap_update_bits(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, 80 CTRL2_ALARM_STATUS | CTRL2_CTFG | CTRL2_CTC, 81 0); 82 if (err < 0) 83 return err; 84 85 return 0; 86} 87 88/* things to be done once after power on */ 89static int rc5t619_rtc_pon_setup(struct device *dev) 90{ 91 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 92 int err; 93 unsigned int reg_data; 94 95 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, ®_data); 96 if (err < 0) 97 return err; 98 99 /* clear VDET PON */ 100 reg_data &= ~(CTRL2_PON | CTRL2_CTC | 0x4a); /* 0101-1011 */ 101 reg_data |= 0x20; /* 0010-0000 */ 102 err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, reg_data); 103 if (err < 0) 104 return err; 105 106 /* clearing RTC Adjust register */ 107 err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_ADJUST, 0); 108 if (err) 109 return err; 110 111 return regmap_update_bits(rtc->rn5t618->regmap, 112 RN5T618_RTC_CTRL1, 113 CTRL1_24HR, CTRL1_24HR); 114} 115 116static int rc5t619_rtc_read_time(struct device *dev, struct rtc_time *tm) 117{ 118 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 119 u8 buff[7]; 120 int err; 121 int cent_flag; 122 unsigned int ctrl1; 123 unsigned int ctrl2; 124 125 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 126 if (err < 0) 127 return err; 128 129 if (ctrl2 & CTRL2_PON) 130 return -EINVAL; 131 132 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 133 if (err < 0) 134 return err; 135 136 err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS, 137 buff, sizeof(buff)); 138 if (err < 0) 139 return err; 140 141 if (buff[5] & MONTH_CENTFLAG) 142 cent_flag = 1; 143 else 144 cent_flag = 0; 145 146 tm->tm_sec = bcd2bin(buff[0]); 147 tm->tm_min = bcd2bin(buff[1]); 148 149 if (ctrl1 & CTRL1_24HR) 150 tm->tm_hour = bcd2bin(buff[2]); 151 else 152 tm->tm_hour = rtc5t619_12hour_bcd2bin(buff[2]); 153 154 tm->tm_wday = bcd2bin(buff[3]); 155 tm->tm_mday = bcd2bin(buff[4]); 156 tm->tm_mon = bcd2bin(buff[5] & 0x1f) - 1; /* back to system 0-11 */ 157 tm->tm_year = bcd2bin(buff[6]) + 100 * cent_flag; 158 159 return 0; 160} 161 162static int rc5t619_rtc_set_time(struct device *dev, struct rtc_time *tm) 163{ 164 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 165 u8 buff[7]; 166 int err; 167 int cent_flag; 168 unsigned int ctrl1; 169 unsigned int ctrl2; 170 171 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 172 if (err < 0) 173 return err; 174 175 if (ctrl2 & CTRL2_PON) 176 rc5t619_rtc_pon_setup(dev); 177 178 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 179 if (err < 0) 180 return err; 181 182 if (tm->tm_year >= 100) 183 cent_flag = 1; 184 else 185 cent_flag = 0; 186 187 buff[0] = bin2bcd(tm->tm_sec); 188 buff[1] = bin2bcd(tm->tm_min); 189 190 if (ctrl1 & CTRL1_24HR) 191 buff[2] = bin2bcd(tm->tm_hour); 192 else 193 buff[2] = rtc5t619_12hour_bin2bcd(tm->tm_hour); 194 195 buff[3] = bin2bcd(tm->tm_wday); 196 buff[4] = bin2bcd(tm->tm_mday); 197 buff[5] = bin2bcd(tm->tm_mon + 1); /* system set 0-11 */ 198 buff[6] = bin2bcd(tm->tm_year - cent_flag * 100); 199 200 if (cent_flag) 201 buff[5] |= MONTH_CENTFLAG; 202 203 err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS, 204 buff, sizeof(buff)); 205 if (err < 0) { 206 dev_err(dev, "failed to program new time: %d\n", err); 207 return err; 208 } 209 210 return 0; 211} 212 213/* 0-disable, 1-enable */ 214static int rc5t619_rtc_alarm_enable(struct device *dev, unsigned int enabled) 215{ 216 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 217 218 return regmap_update_bits(rtc->rn5t618->regmap, 219 RN5T618_RTC_CTRL1, 220 CTRL1_ALARM_ENABLED, 221 enabled ? CTRL1_ALARM_ENABLED : 0); 222} 223 224static int rc5t619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 225{ 226 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 227 u8 buff[6]; 228 unsigned int buff_cent; 229 int err; 230 int cent_flag; 231 unsigned int ctrl1; 232 233 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 234 if (err) 235 return err; 236 237 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_MONTH, &buff_cent); 238 if (err < 0) { 239 dev_err(dev, "failed to read time: %d\n", err); 240 return err; 241 } 242 243 if (buff_cent & MONTH_CENTFLAG) 244 cent_flag = 1; 245 else 246 cent_flag = 0; 247 248 err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC, 249 buff, sizeof(buff)); 250 if (err) 251 return err; 252 253 buff[3] = buff[3] & 0x3f; 254 255 alrm->time.tm_sec = bcd2bin(buff[0]); 256 alrm->time.tm_min = bcd2bin(buff[1]); 257 258 if (ctrl1 & CTRL1_24HR) 259 alrm->time.tm_hour = bcd2bin(buff[2]); 260 else 261 alrm->time.tm_hour = rtc5t619_12hour_bcd2bin(buff[2]); 262 263 alrm->time.tm_mday = bcd2bin(buff[3]); 264 alrm->time.tm_mon = bcd2bin(buff[4]) - 1; 265 alrm->time.tm_year = bcd2bin(buff[5]) + 100 * cent_flag; 266 alrm->enabled = !!(ctrl1 & CTRL1_ALARM_ENABLED); 267 dev_dbg(dev, "read alarm: %ptR\n", &alrm->time); 268 269 return 0; 270} 271 272static int rc5t619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 273{ 274 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 275 u8 buff[6]; 276 int err; 277 int cent_flag; 278 unsigned int ctrl1; 279 280 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1); 281 if (err) 282 return err; 283 284 err = rc5t619_rtc_alarm_enable(dev, 0); 285 if (err < 0) 286 return err; 287 288 if (rtc->irq == -1) 289 return -EINVAL; 290 291 if (alrm->enabled == 0) 292 return 0; 293 294 if (alrm->time.tm_year >= 100) 295 cent_flag = 1; 296 else 297 cent_flag = 0; 298 299 alrm->time.tm_mon += 1; 300 buff[0] = bin2bcd(alrm->time.tm_sec); 301 buff[1] = bin2bcd(alrm->time.tm_min); 302 303 if (ctrl1 & CTRL1_24HR) 304 buff[2] = bin2bcd(alrm->time.tm_hour); 305 else 306 buff[2] = rtc5t619_12hour_bin2bcd(alrm->time.tm_hour); 307 308 buff[3] = bin2bcd(alrm->time.tm_mday); 309 buff[4] = bin2bcd(alrm->time.tm_mon); 310 buff[5] = bin2bcd(alrm->time.tm_year - 100 * cent_flag); 311 buff[3] |= MDAY_DAL_EXT; 312 313 err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC, 314 buff, sizeof(buff)); 315 if (err < 0) 316 return err; 317 318 return rc5t619_rtc_alarm_enable(dev, alrm->enabled); 319} 320 321static const struct rtc_class_ops rc5t619_rtc_ops = { 322 .read_time = rc5t619_rtc_read_time, 323 .set_time = rc5t619_rtc_set_time, 324 .set_alarm = rc5t619_rtc_set_alarm, 325 .read_alarm = rc5t619_rtc_read_alarm, 326 .alarm_irq_enable = rc5t619_rtc_alarm_enable, 327}; 328 329static int rc5t619_rtc_alarm_flag_clr(struct device *dev) 330{ 331 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 332 333 /* clear alarm-D status bits.*/ 334 return regmap_update_bits(rtc->rn5t618->regmap, 335 RN5T618_RTC_CTRL2, 336 CTRL2_ALARM_STATUS | CTRL2_CTC, 0); 337} 338 339static irqreturn_t rc5t619_rtc_irq(int irq, void *data) 340{ 341 struct device *dev = data; 342 struct rc5t619_rtc *rtc = dev_get_drvdata(dev); 343 344 rc5t619_rtc_alarm_flag_clr(dev); 345 346 rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); 347 return IRQ_HANDLED; 348} 349 350static int rc5t619_rtc_probe(struct platform_device *pdev) 351{ 352 struct device *dev = &pdev->dev; 353 struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); 354 struct rc5t619_rtc *rtc; 355 unsigned int ctrl2; 356 int err; 357 358 rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); 359 if (!rtc) 360 return -ENOMEM; 361 362 rtc->rn5t618 = rn5t618; 363 364 dev_set_drvdata(dev, rtc); 365 rtc->irq = -1; 366 367 if (rn5t618->irq_data) 368 rtc->irq = regmap_irq_get_virq(rn5t618->irq_data, 369 RN5T618_IRQ_RTC); 370 371 if (rtc->irq < 0) 372 rtc->irq = -1; 373 374 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2); 375 if (err < 0) 376 return err; 377 378 /* disable rtc periodic function */ 379 err = rc5t619_rtc_periodic_disable(&pdev->dev); 380 if (err) 381 return err; 382 383 if (ctrl2 & CTRL2_PON) { 384 err = rc5t619_rtc_alarm_flag_clr(&pdev->dev); 385 if (err) 386 return err; 387 } 388 389 rtc->rtc = devm_rtc_allocate_device(&pdev->dev); 390 if (IS_ERR(rtc->rtc)) { 391 err = PTR_ERR(rtc->rtc); 392 dev_err(dev, "RTC device register: err %d\n", err); 393 return err; 394 } 395 396 rtc->rtc->ops = &rc5t619_rtc_ops; 397 rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900; 398 rtc->rtc->range_max = RTC_TIMESTAMP_END_2099; 399 400 /* set interrupt and enable it */ 401 if (rtc->irq != -1) { 402 err = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, 403 rc5t619_rtc_irq, 404 IRQF_ONESHOT, 405 "rtc-rc5t619", 406 &pdev->dev); 407 if (err < 0) { 408 dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq); 409 rtc->irq = -1; 410 411 err = rc5t619_rtc_alarm_enable(&pdev->dev, 0); 412 if (err) 413 return err; 414 415 } else { 416 /* enable wake */ 417 device_init_wakeup(&pdev->dev, 1); 418 enable_irq_wake(rtc->irq); 419 } 420 } else { 421 /* system don't want to using alarm interrupt, so close it */ 422 err = rc5t619_rtc_alarm_enable(&pdev->dev, 0); 423 if (err) 424 return err; 425 426 dev_warn(&pdev->dev, "rc5t619 interrupt is disabled\n"); 427 } 428 429 return devm_rtc_register_device(rtc->rtc); 430} 431 432static struct platform_driver rc5t619_rtc_driver = { 433 .driver = { 434 .name = "rc5t619-rtc", 435 }, 436 .probe = rc5t619_rtc_probe, 437}; 438 439module_platform_driver(rc5t619_rtc_driver); 440MODULE_ALIAS("platform:rc5t619-rtc"); 441MODULE_DESCRIPTION("RICOH RC5T619 RTC driver"); 442MODULE_LICENSE("GPL");