0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/device.h>
0012 #include <linux/errno.h>
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/mfd/rn5t618.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018 #include <linux/bcd.h>
0019 #include <linux/rtc.h>
0020 #include <linux/slab.h>
0021 #include <linux/irqdomain.h>
0022
0023 struct rc5t619_rtc {
0024 int irq;
0025 struct rtc_device *rtc;
0026 struct rn5t618 *rn5t618;
0027 };
0028
0029 #define CTRL1_ALARM_ENABLED 0x40
0030 #define CTRL1_24HR 0x20
0031 #define CTRL1_PERIODIC_MASK 0xf
0032
0033 #define CTRL2_PON 0x10
0034 #define CTRL2_ALARM_STATUS 0x80
0035 #define CTRL2_CTFG 0x4
0036 #define CTRL2_CTC 0x1
0037
0038 #define MONTH_CENTFLAG 0x80
0039 #define HOUR_PMFLAG 0x20
0040 #define MDAY_DAL_EXT 0x80
0041
0042 static uint8_t rtc5t619_12hour_bcd2bin(uint8_t hour)
0043 {
0044 if (hour & HOUR_PMFLAG) {
0045 hour = bcd2bin(hour & ~HOUR_PMFLAG);
0046 return hour == 12 ? 12 : 12 + hour;
0047 }
0048
0049 hour = bcd2bin(hour);
0050 return hour == 12 ? 0 : hour;
0051 }
0052
0053 static uint8_t rtc5t619_12hour_bin2bcd(uint8_t hour)
0054 {
0055 if (!hour)
0056 return 0x12;
0057
0058 if (hour < 12)
0059 return bin2bcd(hour);
0060
0061 if (hour == 12)
0062 return 0x12 | HOUR_PMFLAG;
0063
0064 return bin2bcd(hour - 12) | HOUR_PMFLAG;
0065 }
0066
0067 static int rc5t619_rtc_periodic_disable(struct device *dev)
0068 {
0069 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0070 int err;
0071
0072
0073 err = regmap_update_bits(rtc->rn5t618->regmap,
0074 RN5T618_RTC_CTRL1, CTRL1_PERIODIC_MASK, 0);
0075 if (err < 0)
0076 return err;
0077
0078
0079 err = regmap_update_bits(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2,
0080 CTRL2_ALARM_STATUS | CTRL2_CTFG | CTRL2_CTC,
0081 0);
0082 if (err < 0)
0083 return err;
0084
0085 return 0;
0086 }
0087
0088
0089 static int rc5t619_rtc_pon_setup(struct device *dev)
0090 {
0091 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0092 int err;
0093 unsigned int reg_data;
0094
0095 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, ®_data);
0096 if (err < 0)
0097 return err;
0098
0099
0100 reg_data &= ~(CTRL2_PON | CTRL2_CTC | 0x4a);
0101 reg_data |= 0x20;
0102 err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, reg_data);
0103 if (err < 0)
0104 return err;
0105
0106
0107 err = regmap_write(rtc->rn5t618->regmap, RN5T618_RTC_ADJUST, 0);
0108 if (err)
0109 return err;
0110
0111 return regmap_update_bits(rtc->rn5t618->regmap,
0112 RN5T618_RTC_CTRL1,
0113 CTRL1_24HR, CTRL1_24HR);
0114 }
0115
0116 static int rc5t619_rtc_read_time(struct device *dev, struct rtc_time *tm)
0117 {
0118 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0119 u8 buff[7];
0120 int err;
0121 int cent_flag;
0122 unsigned int ctrl1;
0123 unsigned int ctrl2;
0124
0125 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
0126 if (err < 0)
0127 return err;
0128
0129 if (ctrl2 & CTRL2_PON)
0130 return -EINVAL;
0131
0132 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
0133 if (err < 0)
0134 return err;
0135
0136 err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS,
0137 buff, sizeof(buff));
0138 if (err < 0)
0139 return err;
0140
0141 if (buff[5] & MONTH_CENTFLAG)
0142 cent_flag = 1;
0143 else
0144 cent_flag = 0;
0145
0146 tm->tm_sec = bcd2bin(buff[0]);
0147 tm->tm_min = bcd2bin(buff[1]);
0148
0149 if (ctrl1 & CTRL1_24HR)
0150 tm->tm_hour = bcd2bin(buff[2]);
0151 else
0152 tm->tm_hour = rtc5t619_12hour_bcd2bin(buff[2]);
0153
0154 tm->tm_wday = bcd2bin(buff[3]);
0155 tm->tm_mday = bcd2bin(buff[4]);
0156 tm->tm_mon = bcd2bin(buff[5] & 0x1f) - 1;
0157 tm->tm_year = bcd2bin(buff[6]) + 100 * cent_flag;
0158
0159 return 0;
0160 }
0161
0162 static int rc5t619_rtc_set_time(struct device *dev, struct rtc_time *tm)
0163 {
0164 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0165 u8 buff[7];
0166 int err;
0167 int cent_flag;
0168 unsigned int ctrl1;
0169 unsigned int ctrl2;
0170
0171 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
0172 if (err < 0)
0173 return err;
0174
0175 if (ctrl2 & CTRL2_PON)
0176 rc5t619_rtc_pon_setup(dev);
0177
0178 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
0179 if (err < 0)
0180 return err;
0181
0182 if (tm->tm_year >= 100)
0183 cent_flag = 1;
0184 else
0185 cent_flag = 0;
0186
0187 buff[0] = bin2bcd(tm->tm_sec);
0188 buff[1] = bin2bcd(tm->tm_min);
0189
0190 if (ctrl1 & CTRL1_24HR)
0191 buff[2] = bin2bcd(tm->tm_hour);
0192 else
0193 buff[2] = rtc5t619_12hour_bin2bcd(tm->tm_hour);
0194
0195 buff[3] = bin2bcd(tm->tm_wday);
0196 buff[4] = bin2bcd(tm->tm_mday);
0197 buff[5] = bin2bcd(tm->tm_mon + 1);
0198 buff[6] = bin2bcd(tm->tm_year - cent_flag * 100);
0199
0200 if (cent_flag)
0201 buff[5] |= MONTH_CENTFLAG;
0202
0203 err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_SECONDS,
0204 buff, sizeof(buff));
0205 if (err < 0) {
0206 dev_err(dev, "failed to program new time: %d\n", err);
0207 return err;
0208 }
0209
0210 return 0;
0211 }
0212
0213
0214 static int rc5t619_rtc_alarm_enable(struct device *dev, unsigned int enabled)
0215 {
0216 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0217
0218 return regmap_update_bits(rtc->rn5t618->regmap,
0219 RN5T618_RTC_CTRL1,
0220 CTRL1_ALARM_ENABLED,
0221 enabled ? CTRL1_ALARM_ENABLED : 0);
0222 }
0223
0224 static int rc5t619_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0225 {
0226 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0227 u8 buff[6];
0228 unsigned int buff_cent;
0229 int err;
0230 int cent_flag;
0231 unsigned int ctrl1;
0232
0233 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
0234 if (err)
0235 return err;
0236
0237 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_MONTH, &buff_cent);
0238 if (err < 0) {
0239 dev_err(dev, "failed to read time: %d\n", err);
0240 return err;
0241 }
0242
0243 if (buff_cent & MONTH_CENTFLAG)
0244 cent_flag = 1;
0245 else
0246 cent_flag = 0;
0247
0248 err = regmap_bulk_read(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC,
0249 buff, sizeof(buff));
0250 if (err)
0251 return err;
0252
0253 buff[3] = buff[3] & 0x3f;
0254
0255 alrm->time.tm_sec = bcd2bin(buff[0]);
0256 alrm->time.tm_min = bcd2bin(buff[1]);
0257
0258 if (ctrl1 & CTRL1_24HR)
0259 alrm->time.tm_hour = bcd2bin(buff[2]);
0260 else
0261 alrm->time.tm_hour = rtc5t619_12hour_bcd2bin(buff[2]);
0262
0263 alrm->time.tm_mday = bcd2bin(buff[3]);
0264 alrm->time.tm_mon = bcd2bin(buff[4]) - 1;
0265 alrm->time.tm_year = bcd2bin(buff[5]) + 100 * cent_flag;
0266 alrm->enabled = !!(ctrl1 & CTRL1_ALARM_ENABLED);
0267 dev_dbg(dev, "read alarm: %ptR\n", &alrm->time);
0268
0269 return 0;
0270 }
0271
0272 static int rc5t619_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0273 {
0274 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0275 u8 buff[6];
0276 int err;
0277 int cent_flag;
0278 unsigned int ctrl1;
0279
0280 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL1, &ctrl1);
0281 if (err)
0282 return err;
0283
0284 err = rc5t619_rtc_alarm_enable(dev, 0);
0285 if (err < 0)
0286 return err;
0287
0288 if (rtc->irq == -1)
0289 return -EINVAL;
0290
0291 if (alrm->enabled == 0)
0292 return 0;
0293
0294 if (alrm->time.tm_year >= 100)
0295 cent_flag = 1;
0296 else
0297 cent_flag = 0;
0298
0299 alrm->time.tm_mon += 1;
0300 buff[0] = bin2bcd(alrm->time.tm_sec);
0301 buff[1] = bin2bcd(alrm->time.tm_min);
0302
0303 if (ctrl1 & CTRL1_24HR)
0304 buff[2] = bin2bcd(alrm->time.tm_hour);
0305 else
0306 buff[2] = rtc5t619_12hour_bin2bcd(alrm->time.tm_hour);
0307
0308 buff[3] = bin2bcd(alrm->time.tm_mday);
0309 buff[4] = bin2bcd(alrm->time.tm_mon);
0310 buff[5] = bin2bcd(alrm->time.tm_year - 100 * cent_flag);
0311 buff[3] |= MDAY_DAL_EXT;
0312
0313 err = regmap_bulk_write(rtc->rn5t618->regmap, RN5T618_RTC_ALARM_Y_SEC,
0314 buff, sizeof(buff));
0315 if (err < 0)
0316 return err;
0317
0318 return rc5t619_rtc_alarm_enable(dev, alrm->enabled);
0319 }
0320
0321 static const struct rtc_class_ops rc5t619_rtc_ops = {
0322 .read_time = rc5t619_rtc_read_time,
0323 .set_time = rc5t619_rtc_set_time,
0324 .set_alarm = rc5t619_rtc_set_alarm,
0325 .read_alarm = rc5t619_rtc_read_alarm,
0326 .alarm_irq_enable = rc5t619_rtc_alarm_enable,
0327 };
0328
0329 static int rc5t619_rtc_alarm_flag_clr(struct device *dev)
0330 {
0331 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0332
0333
0334 return regmap_update_bits(rtc->rn5t618->regmap,
0335 RN5T618_RTC_CTRL2,
0336 CTRL2_ALARM_STATUS | CTRL2_CTC, 0);
0337 }
0338
0339 static irqreturn_t rc5t619_rtc_irq(int irq, void *data)
0340 {
0341 struct device *dev = data;
0342 struct rc5t619_rtc *rtc = dev_get_drvdata(dev);
0343
0344 rc5t619_rtc_alarm_flag_clr(dev);
0345
0346 rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
0347 return IRQ_HANDLED;
0348 }
0349
0350 static int rc5t619_rtc_probe(struct platform_device *pdev)
0351 {
0352 struct device *dev = &pdev->dev;
0353 struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
0354 struct rc5t619_rtc *rtc;
0355 unsigned int ctrl2;
0356 int err;
0357
0358 rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
0359 if (!rtc)
0360 return -ENOMEM;
0361
0362 rtc->rn5t618 = rn5t618;
0363
0364 dev_set_drvdata(dev, rtc);
0365 rtc->irq = -1;
0366
0367 if (rn5t618->irq_data)
0368 rtc->irq = regmap_irq_get_virq(rn5t618->irq_data,
0369 RN5T618_IRQ_RTC);
0370
0371 if (rtc->irq < 0)
0372 rtc->irq = -1;
0373
0374 err = regmap_read(rtc->rn5t618->regmap, RN5T618_RTC_CTRL2, &ctrl2);
0375 if (err < 0)
0376 return err;
0377
0378
0379 err = rc5t619_rtc_periodic_disable(&pdev->dev);
0380 if (err)
0381 return err;
0382
0383 if (ctrl2 & CTRL2_PON) {
0384 err = rc5t619_rtc_alarm_flag_clr(&pdev->dev);
0385 if (err)
0386 return err;
0387 }
0388
0389 rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
0390 if (IS_ERR(rtc->rtc)) {
0391 err = PTR_ERR(rtc->rtc);
0392 dev_err(dev, "RTC device register: err %d\n", err);
0393 return err;
0394 }
0395
0396 rtc->rtc->ops = &rc5t619_rtc_ops;
0397 rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
0398 rtc->rtc->range_max = RTC_TIMESTAMP_END_2099;
0399
0400
0401 if (rtc->irq != -1) {
0402 err = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
0403 rc5t619_rtc_irq,
0404 IRQF_ONESHOT,
0405 "rtc-rc5t619",
0406 &pdev->dev);
0407 if (err < 0) {
0408 dev_err(&pdev->dev, "request IRQ:%d fail\n", rtc->irq);
0409 rtc->irq = -1;
0410
0411 err = rc5t619_rtc_alarm_enable(&pdev->dev, 0);
0412 if (err)
0413 return err;
0414
0415 } else {
0416
0417 device_init_wakeup(&pdev->dev, 1);
0418 enable_irq_wake(rtc->irq);
0419 }
0420 } else {
0421
0422 err = rc5t619_rtc_alarm_enable(&pdev->dev, 0);
0423 if (err)
0424 return err;
0425
0426 dev_warn(&pdev->dev, "rc5t619 interrupt is disabled\n");
0427 }
0428
0429 return devm_rtc_register_device(rtc->rtc);
0430 }
0431
0432 static struct platform_driver rc5t619_rtc_driver = {
0433 .driver = {
0434 .name = "rc5t619-rtc",
0435 },
0436 .probe = rc5t619_rtc_probe,
0437 };
0438
0439 module_platform_driver(rc5t619_rtc_driver);
0440 MODULE_ALIAS("platform:rc5t619-rtc");
0441 MODULE_DESCRIPTION("RICOH RC5T619 RTC driver");
0442 MODULE_LICENSE("GPL");