diff options
| -rw-r--r-- | drivers/rtc/rtc-isl12057.c | 313 |
1 files changed, 305 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c index 6e1fcfb5d7e6..3ec73ad7f2d8 100644 --- a/drivers/rtc/rtc-isl12057.c +++ b/drivers/rtc/rtc-isl12057.c | |||
| @@ -79,8 +79,10 @@ | |||
| 79 | #define ISL12057_MEM_MAP_LEN 0x10 | 79 | #define ISL12057_MEM_MAP_LEN 0x10 |
| 80 | 80 | ||
| 81 | struct isl12057_rtc_data { | 81 | struct isl12057_rtc_data { |
| 82 | struct rtc_device *rtc; | ||
| 82 | struct regmap *regmap; | 83 | struct regmap *regmap; |
| 83 | struct mutex lock; | 84 | struct mutex lock; |
| 85 | int irq; | ||
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 86 | static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) | 88 | static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) |
| @@ -160,14 +162,47 @@ static int isl12057_i2c_validate_chip(struct regmap *regmap) | |||
| 160 | return 0; | 162 | return 0; |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | static int isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm) | 165 | static int _isl12057_rtc_clear_alarm(struct device *dev) |
| 166 | { | ||
| 167 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
| 168 | int ret; | ||
| 169 | |||
| 170 | ret = regmap_update_bits(data->regmap, ISL12057_REG_SR, | ||
| 171 | ISL12057_REG_SR_A1F, 0); | ||
| 172 | if (ret) | ||
| 173 | dev_err(dev, "%s: clearing alarm failed (%d)\n", __func__, ret); | ||
| 174 | |||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int _isl12057_rtc_update_alarm(struct device *dev, int enable) | ||
| 179 | { | ||
| 180 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | ret = regmap_update_bits(data->regmap, ISL12057_REG_INT, | ||
| 184 | ISL12057_REG_INT_A1IE, | ||
| 185 | enable ? ISL12057_REG_INT_A1IE : 0); | ||
| 186 | if (ret) | ||
| 187 | dev_err(dev, "%s: changing alarm interrupt flag failed (%d)\n", | ||
| 188 | __func__, ret); | ||
| 189 | |||
| 190 | return ret; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* | ||
| 194 | * Note: as we only read from device and do not perform any update, there is | ||
| 195 | * no need for an equivalent function which would try and get driver's main | ||
| 196 | * lock. Here, it is safe for everyone if we just use regmap internal lock | ||
| 197 | * on the device when reading. | ||
| 198 | */ | ||
| 199 | static int _isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 164 | { | 200 | { |
| 165 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | 201 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); |
| 166 | u8 regs[ISL12057_RTC_SEC_LEN]; | 202 | u8 regs[ISL12057_RTC_SEC_LEN]; |
| 167 | unsigned int sr; | 203 | unsigned int sr; |
| 168 | int ret; | 204 | int ret; |
| 169 | 205 | ||
| 170 | mutex_lock(&data->lock); | ||
| 171 | ret = regmap_read(data->regmap, ISL12057_REG_SR, &sr); | 206 | ret = regmap_read(data->regmap, ISL12057_REG_SR, &sr); |
| 172 | if (ret) { | 207 | if (ret) { |
| 173 | dev_err(dev, "%s: unable to read oscillator status flag (%d)\n", | 208 | dev_err(dev, "%s: unable to read oscillator status flag (%d)\n", |
| @@ -187,8 +222,6 @@ static int isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 187 | __func__, ret); | 222 | __func__, ret); |
| 188 | 223 | ||
| 189 | out: | 224 | out: |
| 190 | mutex_unlock(&data->lock); | ||
| 191 | |||
| 192 | if (ret) | 225 | if (ret) |
| 193 | return ret; | 226 | return ret; |
| 194 | 227 | ||
| @@ -197,6 +230,168 @@ out: | |||
| 197 | return rtc_valid_tm(tm); | 230 | return rtc_valid_tm(tm); |
| 198 | } | 231 | } |
| 199 | 232 | ||
| 233 | static int isl12057_rtc_update_alarm(struct device *dev, int enable) | ||
| 234 | { | ||
| 235 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | mutex_lock(&data->lock); | ||
| 239 | ret = _isl12057_rtc_update_alarm(dev, enable); | ||
| 240 | mutex_unlock(&data->lock); | ||
| 241 | |||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 246 | { | ||
| 247 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
| 248 | struct rtc_time rtc_tm, *alarm_tm = &alarm->time; | ||
| 249 | unsigned long rtc_secs, alarm_secs; | ||
| 250 | u8 regs[ISL12057_A1_SEC_LEN]; | ||
| 251 | unsigned int ir; | ||
| 252 | int ret; | ||
| 253 | |||
| 254 | mutex_lock(&data->lock); | ||
| 255 | ret = regmap_bulk_read(data->regmap, ISL12057_REG_A1_SC, regs, | ||
| 256 | ISL12057_A1_SEC_LEN); | ||
| 257 | if (ret) { | ||
| 258 | dev_err(dev, "%s: reading alarm section failed (%d)\n", | ||
| 259 | __func__, ret); | ||
| 260 | goto err_unlock; | ||
| 261 | } | ||
| 262 | |||
| 263 | alarm_tm->tm_sec = bcd2bin(regs[0] & 0x7f); | ||
| 264 | alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f); | ||
| 265 | alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f); | ||
| 266 | alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f); | ||
| 267 | alarm_tm->tm_wday = -1; | ||
| 268 | |||
| 269 | /* | ||
| 270 | * The alarm section does not store year/month. We use the ones in rtc | ||
| 271 | * section as a basis and increment month and then year if needed to get | ||
| 272 | * alarm after current time. | ||
| 273 | */ | ||
| 274 | ret = _isl12057_rtc_read_time(dev, &rtc_tm); | ||
| 275 | if (ret) | ||
| 276 | goto err_unlock; | ||
| 277 | |||
| 278 | alarm_tm->tm_year = rtc_tm.tm_year; | ||
| 279 | alarm_tm->tm_mon = rtc_tm.tm_mon; | ||
| 280 | |||
| 281 | ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); | ||
| 282 | if (ret) | ||
| 283 | goto err_unlock; | ||
| 284 | |||
| 285 | ret = rtc_tm_to_time(alarm_tm, &alarm_secs); | ||
| 286 | if (ret) | ||
| 287 | goto err_unlock; | ||
| 288 | |||
| 289 | if (alarm_secs < rtc_secs) { | ||
| 290 | if (alarm_tm->tm_mon == 11) { | ||
| 291 | alarm_tm->tm_mon = 0; | ||
| 292 | alarm_tm->tm_year += 1; | ||
| 293 | } else { | ||
| 294 | alarm_tm->tm_mon += 1; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir); | ||
| 299 | if (ret) { | ||
| 300 | dev_err(dev, "%s: reading alarm interrupt flag failed (%d)\n", | ||
| 301 | __func__, ret); | ||
| 302 | goto err_unlock; | ||
| 303 | } | ||
| 304 | |||
| 305 | alarm->enabled = !!(ir & ISL12057_REG_INT_A1IE); | ||
| 306 | |||
| 307 | err_unlock: | ||
| 308 | mutex_unlock(&data->lock); | ||
| 309 | |||
| 310 | return ret; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int isl12057_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 314 | { | ||
| 315 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
| 316 | struct rtc_time *alarm_tm = &alarm->time; | ||
| 317 | unsigned long rtc_secs, alarm_secs; | ||
| 318 | u8 regs[ISL12057_A1_SEC_LEN]; | ||
| 319 | struct rtc_time rtc_tm; | ||
| 320 | int ret, enable = 1; | ||
| 321 | |||
| 322 | mutex_lock(&data->lock); | ||
| 323 | ret = _isl12057_rtc_read_time(dev, &rtc_tm); | ||
| 324 | if (ret) | ||
| 325 | goto err_unlock; | ||
| 326 | |||
| 327 | ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); | ||
| 328 | if (ret) | ||
| 329 | goto err_unlock; | ||
| 330 | |||
| 331 | ret = rtc_tm_to_time(alarm_tm, &alarm_secs); | ||
| 332 | if (ret) | ||
| 333 | goto err_unlock; | ||
| 334 | |||
| 335 | /* If alarm time is before current time, disable the alarm */ | ||
| 336 | if (!alarm->enabled || alarm_secs <= rtc_secs) { | ||
| 337 | enable = 0; | ||
| 338 | } else { | ||
| 339 | /* | ||
| 340 | * Chip only support alarms up to one month in the future. Let's | ||
| 341 | * return an error if we get something after that limit. | ||
| 342 | * Comparison is done by incrementing rtc_tm month field by one | ||
| 343 | * and checking alarm value is still below. | ||
| 344 | */ | ||
| 345 | if (rtc_tm.tm_mon == 11) { /* handle year wrapping */ | ||
| 346 | rtc_tm.tm_mon = 0; | ||
| 347 | rtc_tm.tm_year += 1; | ||
| 348 | } else { | ||
| 349 | rtc_tm.tm_mon += 1; | ||
| 350 | } | ||
| 351 | |||
| 352 | ret = rtc_tm_to_time(&rtc_tm, &rtc_secs); | ||
| 353 | if (ret) | ||
| 354 | goto err_unlock; | ||
| 355 | |||
| 356 | if (alarm_secs > rtc_secs) { | ||
| 357 | dev_err(dev, "%s: max for alarm is one month (%d)\n", | ||
| 358 | __func__, ret); | ||
| 359 | ret = -EINVAL; | ||
| 360 | goto err_unlock; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | /* Disable the alarm before modifying it */ | ||
| 365 | ret = _isl12057_rtc_update_alarm(dev, 0); | ||
| 366 | if (ret < 0) { | ||
| 367 | dev_err(dev, "%s: unable to disable the alarm (%d)\n", | ||
| 368 | __func__, ret); | ||
| 369 | goto err_unlock; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Program alarm registers */ | ||
| 373 | regs[0] = bin2bcd(alarm_tm->tm_sec) & 0x7f; | ||
| 374 | regs[1] = bin2bcd(alarm_tm->tm_min) & 0x7f; | ||
| 375 | regs[2] = bin2bcd(alarm_tm->tm_hour) & 0x3f; | ||
| 376 | regs[3] = bin2bcd(alarm_tm->tm_mday) & 0x3f; | ||
| 377 | |||
| 378 | ret = regmap_bulk_write(data->regmap, ISL12057_REG_A1_SC, regs, | ||
| 379 | ISL12057_A1_SEC_LEN); | ||
| 380 | if (ret < 0) { | ||
| 381 | dev_err(dev, "%s: writing alarm section failed (%d)\n", | ||
| 382 | __func__, ret); | ||
| 383 | goto err_unlock; | ||
| 384 | } | ||
| 385 | |||
| 386 | /* Enable or disable alarm */ | ||
| 387 | ret = _isl12057_rtc_update_alarm(dev, enable); | ||
| 388 | |||
| 389 | err_unlock: | ||
| 390 | mutex_unlock(&data->lock); | ||
| 391 | |||
| 392 | return ret; | ||
| 393 | } | ||
| 394 | |||
| 200 | static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm) | 395 | static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm) |
| 201 | { | 396 | { |
| 202 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | 397 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); |
| @@ -262,9 +457,48 @@ static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap) | |||
| 262 | return 0; | 457 | return 0; |
| 263 | } | 458 | } |
| 264 | 459 | ||
| 460 | static int isl12057_rtc_alarm_irq_enable(struct device *dev, | ||
| 461 | unsigned int enable) | ||
| 462 | { | ||
| 463 | struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
| 464 | int ret = -ENOTTY; | ||
| 465 | |||
| 466 | if (rtc_data->irq) | ||
| 467 | ret = isl12057_rtc_update_alarm(dev, enable); | ||
| 468 | |||
| 469 | return ret; | ||
| 470 | } | ||
| 471 | |||
| 472 | static irqreturn_t isl12057_rtc_interrupt(int irq, void *data) | ||
| 473 | { | ||
| 474 | struct i2c_client *client = data; | ||
| 475 | struct isl12057_rtc_data *rtc_data = dev_get_drvdata(&client->dev); | ||
| 476 | struct rtc_device *rtc = rtc_data->rtc; | ||
| 477 | int ret, handled = IRQ_NONE; | ||
| 478 | unsigned int sr; | ||
| 479 | |||
| 480 | ret = regmap_read(rtc_data->regmap, ISL12057_REG_SR, &sr); | ||
| 481 | if (!ret && (sr & ISL12057_REG_SR_A1F)) { | ||
| 482 | dev_dbg(&client->dev, "RTC alarm!\n"); | ||
| 483 | |||
| 484 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); | ||
| 485 | |||
| 486 | /* Acknowledge and disable the alarm */ | ||
| 487 | _isl12057_rtc_clear_alarm(&client->dev); | ||
| 488 | _isl12057_rtc_update_alarm(&client->dev, 0); | ||
| 489 | |||
| 490 | handled = IRQ_HANDLED; | ||
| 491 | } | ||
| 492 | |||
| 493 | return handled; | ||
| 494 | } | ||
| 495 | |||
| 265 | static const struct rtc_class_ops rtc_ops = { | 496 | static const struct rtc_class_ops rtc_ops = { |
| 266 | .read_time = isl12057_rtc_read_time, | 497 | .read_time = _isl12057_rtc_read_time, |
| 267 | .set_time = isl12057_rtc_set_time, | 498 | .set_time = isl12057_rtc_set_time, |
| 499 | .read_alarm = isl12057_rtc_read_alarm, | ||
| 500 | .set_alarm = isl12057_rtc_set_alarm, | ||
| 501 | .alarm_irq_enable = isl12057_rtc_alarm_irq_enable, | ||
| 268 | }; | 502 | }; |
| 269 | 503 | ||
| 270 | static struct regmap_config isl12057_rtc_regmap_config = { | 504 | static struct regmap_config isl12057_rtc_regmap_config = { |
| @@ -277,7 +511,6 @@ static int isl12057_probe(struct i2c_client *client, | |||
| 277 | { | 511 | { |
| 278 | struct device *dev = &client->dev; | 512 | struct device *dev = &client->dev; |
| 279 | struct isl12057_rtc_data *data; | 513 | struct isl12057_rtc_data *data; |
| 280 | struct rtc_device *rtc; | ||
| 281 | struct regmap *regmap; | 514 | struct regmap *regmap; |
| 282 | int ret; | 515 | int ret; |
| 283 | 516 | ||
| @@ -310,10 +543,72 @@ static int isl12057_probe(struct i2c_client *client, | |||
| 310 | data->regmap = regmap; | 543 | data->regmap = regmap; |
| 311 | dev_set_drvdata(dev, data); | 544 | dev_set_drvdata(dev, data); |
| 312 | 545 | ||
| 313 | rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE); | 546 | if (client->irq > 0) { |
| 314 | return PTR_ERR_OR_ZERO(rtc); | 547 | ret = devm_request_threaded_irq(dev, client->irq, NULL, |
| 548 | isl12057_rtc_interrupt, | ||
| 549 | IRQF_SHARED|IRQF_ONESHOT, | ||
| 550 | DRV_NAME, client); | ||
| 551 | if (!ret) | ||
| 552 | data->irq = client->irq; | ||
| 553 | else | ||
| 554 | dev_err(dev, "%s: irq %d unavailable (%d)\n", __func__, | ||
| 555 | client->irq, ret); | ||
| 556 | } | ||
| 557 | |||
| 558 | device_init_wakeup(dev, !!data->irq); | ||
| 559 | |||
| 560 | data->rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, | ||
| 561 | THIS_MODULE); | ||
| 562 | ret = PTR_ERR_OR_ZERO(data->rtc); | ||
| 563 | if (ret) { | ||
| 564 | dev_err(dev, "%s: unable to register RTC device (%d)\n", | ||
| 565 | __func__, ret); | ||
| 566 | goto err; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* We cannot support UIE mode if we do not have an IRQ line */ | ||
| 570 | if (!data->irq) | ||
| 571 | data->rtc->uie_unsupported = 1; | ||
| 572 | |||
| 573 | err: | ||
| 574 | return ret; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int isl12057_remove(struct i2c_client *client) | ||
| 578 | { | ||
| 579 | struct isl12057_rtc_data *rtc_data = dev_get_drvdata(&client->dev); | ||
| 580 | |||
| 581 | if (rtc_data->irq) | ||
| 582 | device_init_wakeup(&client->dev, false); | ||
| 583 | |||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | #ifdef CONFIG_PM_SLEEP | ||
| 588 | static int isl12057_rtc_suspend(struct device *dev) | ||
| 589 | { | ||
| 590 | struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
| 591 | |||
| 592 | if (device_may_wakeup(dev)) | ||
| 593 | return enable_irq_wake(rtc_data->irq); | ||
| 594 | |||
| 595 | return 0; | ||
| 315 | } | 596 | } |
| 316 | 597 | ||
| 598 | static int isl12057_rtc_resume(struct device *dev) | ||
| 599 | { | ||
| 600 | struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev); | ||
| 601 | |||
| 602 | if (device_may_wakeup(dev)) | ||
| 603 | return disable_irq_wake(rtc_data->irq); | ||
| 604 | |||
| 605 | return 0; | ||
| 606 | } | ||
| 607 | #endif | ||
| 608 | |||
| 609 | static SIMPLE_DEV_PM_OPS(isl12057_rtc_pm_ops, isl12057_rtc_suspend, | ||
| 610 | isl12057_rtc_resume); | ||
| 611 | |||
| 317 | #ifdef CONFIG_OF | 612 | #ifdef CONFIG_OF |
| 318 | static const struct of_device_id isl12057_dt_match[] = { | 613 | static const struct of_device_id isl12057_dt_match[] = { |
| 319 | { .compatible = "isl,isl12057" }, | 614 | { .compatible = "isl,isl12057" }, |
| @@ -331,9 +626,11 @@ static struct i2c_driver isl12057_driver = { | |||
| 331 | .driver = { | 626 | .driver = { |
| 332 | .name = DRV_NAME, | 627 | .name = DRV_NAME, |
| 333 | .owner = THIS_MODULE, | 628 | .owner = THIS_MODULE, |
| 629 | .pm = &isl12057_rtc_pm_ops, | ||
| 334 | .of_match_table = of_match_ptr(isl12057_dt_match), | 630 | .of_match_table = of_match_ptr(isl12057_dt_match), |
| 335 | }, | 631 | }, |
| 336 | .probe = isl12057_probe, | 632 | .probe = isl12057_probe, |
| 633 | .remove = isl12057_remove, | ||
| 337 | .id_table = isl12057_id, | 634 | .id_table = isl12057_id, |
| 338 | }; | 635 | }; |
| 339 | module_i2c_driver(isl12057_driver); | 636 | module_i2c_driver(isl12057_driver); |
