Lines Matching +full:auto +full:- +full:i2c
1 // SPDX-License-Identifier: GPL-2.0+
3 // Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
11 #include <linux/i2c.h>
26 * in S5M_RTC_UDR_CON register. UDR is auto-cleared when data have
48 * specific fields in UDR register. These fields usually are auto-cleared
74 * auto-cleared after successful update.
77 /* Auto-cleared mask in UDR field for writing time and alarm */
131 * Register map for S2MPS15 - in comparison to S2MPS14 the WUDR and AUDR bits
149 struct i2c_client *i2c; member
176 tm->tm_sec = data[RTC_SEC] & 0x7f; in s5m8767_data_to_tm()
177 tm->tm_min = data[RTC_MIN] & 0x7f; in s5m8767_data_to_tm()
179 tm->tm_hour = data[RTC_HOUR] & 0x1f; in s5m8767_data_to_tm()
181 tm->tm_hour = data[RTC_HOUR] & 0x0f; in s5m8767_data_to_tm()
183 tm->tm_hour += 12; in s5m8767_data_to_tm()
186 tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f); in s5m8767_data_to_tm()
187 tm->tm_mday = data[RTC_DATE] & 0x1f; in s5m8767_data_to_tm()
188 tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; in s5m8767_data_to_tm()
189 tm->tm_year = (data[RTC_YEAR1] & 0x7f) + 100; in s5m8767_data_to_tm()
190 tm->tm_yday = 0; in s5m8767_data_to_tm()
191 tm->tm_isdst = 0; in s5m8767_data_to_tm()
196 data[RTC_SEC] = tm->tm_sec; in s5m8767_tm_to_data()
197 data[RTC_MIN] = tm->tm_min; in s5m8767_tm_to_data()
199 if (tm->tm_hour >= 12) in s5m8767_tm_to_data()
200 data[RTC_HOUR] = tm->tm_hour | HOUR_PM_MASK; in s5m8767_tm_to_data()
202 data[RTC_HOUR] = tm->tm_hour & ~HOUR_PM_MASK; in s5m8767_tm_to_data()
204 data[RTC_WEEKDAY] = 1 << tm->tm_wday; in s5m8767_tm_to_data()
205 data[RTC_DATE] = tm->tm_mday; in s5m8767_tm_to_data()
206 data[RTC_MONTH] = tm->tm_mon + 1; in s5m8767_tm_to_data()
207 data[RTC_YEAR1] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; in s5m8767_tm_to_data()
209 if (tm->tm_year < 100) { in s5m8767_tm_to_data()
211 1900 + tm->tm_year); in s5m8767_tm_to_data()
212 return -EINVAL; in s5m8767_tm_to_data()
228 ret = regmap_read(info->regmap, info->regs->udr_update, &data); in s5m8767_wait_for_udr_update()
229 } while (--retry && (data & info->regs->autoclear_udr_mask) && !ret); in s5m8767_wait_for_udr_update()
232 dev_err(info->dev, "waiting for UDR update, reached max number of retries\n"); in s5m8767_wait_for_udr_update()
243 switch (info->device_type) { in s5m_check_peding_alarm_interrupt()
246 ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); in s5m_check_peding_alarm_interrupt()
252 ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, in s5m_check_peding_alarm_interrupt()
257 return -EINVAL; in s5m_check_peding_alarm_interrupt()
263 alarm->pending = 1; in s5m_check_peding_alarm_interrupt()
265 alarm->pending = 0; in s5m_check_peding_alarm_interrupt()
275 ret = regmap_read(info->regmap, info->regs->udr_update, &data); in s5m8767_rtc_set_time_reg()
277 dev_err(info->dev, "failed to read update reg(%d)\n", ret); in s5m8767_rtc_set_time_reg()
281 data |= info->regs->write_time_udr_mask; in s5m8767_rtc_set_time_reg()
283 ret = regmap_write(info->regmap, info->regs->udr_update, data); in s5m8767_rtc_set_time_reg()
285 dev_err(info->dev, "failed to write update reg(%d)\n", ret); in s5m8767_rtc_set_time_reg()
299 ret = regmap_read(info->regmap, info->regs->udr_update, &data); in s5m8767_rtc_set_alarm_reg()
301 dev_err(info->dev, "%s: fail to read update reg(%d)\n", in s5m8767_rtc_set_alarm_reg()
306 data |= info->regs->write_alarm_udr_mask; in s5m8767_rtc_set_alarm_reg()
307 switch (info->device_type) { in s5m8767_rtc_set_alarm_reg()
318 return -EINVAL; in s5m8767_rtc_set_alarm_reg()
321 ret = regmap_write(info->regmap, info->regs->udr_update, data); in s5m8767_rtc_set_alarm_reg()
323 dev_err(info->dev, "%s: fail to write update reg(%d)\n", in s5m8767_rtc_set_alarm_reg()
330 /* On S2MPS13 the AUDR is not auto-cleared */ in s5m8767_rtc_set_alarm_reg()
331 if (info->device_type == S2MPS13X) in s5m8767_rtc_set_alarm_reg()
332 regmap_update_bits(info->regmap, info->regs->udr_update, in s5m8767_rtc_set_alarm_reg()
340 tm->tm_sec = bcd2bin(data[RTC_SEC]); in s5m8763_data_to_tm()
341 tm->tm_min = bcd2bin(data[RTC_MIN]); in s5m8763_data_to_tm()
344 tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x1f); in s5m8763_data_to_tm()
346 tm->tm_hour += 12; in s5m8763_data_to_tm()
348 tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f); in s5m8763_data_to_tm()
351 tm->tm_wday = data[RTC_WEEKDAY] & 0x07; in s5m8763_data_to_tm()
352 tm->tm_mday = bcd2bin(data[RTC_DATE]); in s5m8763_data_to_tm()
353 tm->tm_mon = bcd2bin(data[RTC_MONTH]); in s5m8763_data_to_tm()
354 tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100; in s5m8763_data_to_tm()
355 tm->tm_year -= 1900; in s5m8763_data_to_tm()
360 data[RTC_SEC] = bin2bcd(tm->tm_sec); in s5m8763_tm_to_data()
361 data[RTC_MIN] = bin2bcd(tm->tm_min); in s5m8763_tm_to_data()
362 data[RTC_HOUR] = bin2bcd(tm->tm_hour); in s5m8763_tm_to_data()
363 data[RTC_WEEKDAY] = tm->tm_wday; in s5m8763_tm_to_data()
364 data[RTC_DATE] = bin2bcd(tm->tm_mday); in s5m8763_tm_to_data()
365 data[RTC_MONTH] = bin2bcd(tm->tm_mon); in s5m8763_tm_to_data()
366 data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100); in s5m8763_tm_to_data()
367 data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100); in s5m8763_tm_to_data()
376 if (info->regs->read_time_udr_mask) { in s5m_rtc_read_time()
377 ret = regmap_update_bits(info->regmap, in s5m_rtc_read_time()
378 info->regs->udr_update, in s5m_rtc_read_time()
379 info->regs->read_time_udr_mask, in s5m_rtc_read_time()
380 info->regs->read_time_udr_mask); in s5m_rtc_read_time()
388 ret = regmap_bulk_read(info->regmap, info->regs->time, data, in s5m_rtc_read_time()
389 info->regs->regs_count); in s5m_rtc_read_time()
393 switch (info->device_type) { in s5m_rtc_read_time()
402 s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); in s5m_rtc_read_time()
406 return -EINVAL; in s5m_rtc_read_time()
409 dev_dbg(dev, "%s: %ptR(%d)\n", __func__, tm, tm->tm_wday); in s5m_rtc_read_time()
420 switch (info->device_type) { in s5m_rtc_set_time()
431 return -EINVAL; in s5m_rtc_set_time()
437 dev_dbg(dev, "%s: %ptR(%d)\n", __func__, tm, tm->tm_wday); in s5m_rtc_set_time()
439 ret = regmap_raw_write(info->regmap, info->regs->time, data, in s5m_rtc_set_time()
440 info->regs->regs_count); in s5m_rtc_set_time()
456 ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data, in s5m_rtc_read_alarm()
457 info->regs->regs_count); in s5m_rtc_read_alarm()
461 switch (info->device_type) { in s5m_rtc_read_alarm()
463 s5m8763_data_to_tm(data, &alrm->time); in s5m_rtc_read_alarm()
464 ret = regmap_read(info->regmap, S5M_ALARM0_CONF, &val); in s5m_rtc_read_alarm()
468 alrm->enabled = !!val; in s5m_rtc_read_alarm()
475 s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); in s5m_rtc_read_alarm()
476 alrm->enabled = 0; in s5m_rtc_read_alarm()
477 for (i = 0; i < info->regs->regs_count; i++) { in s5m_rtc_read_alarm()
479 alrm->enabled = 1; in s5m_rtc_read_alarm()
486 return -EINVAL; in s5m_rtc_read_alarm()
489 dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday); in s5m_rtc_read_alarm()
502 ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data, in s5m_rtc_stop_alarm()
503 info->regs->regs_count); in s5m_rtc_stop_alarm()
507 s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode); in s5m_rtc_stop_alarm()
508 dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday); in s5m_rtc_stop_alarm()
510 switch (info->device_type) { in s5m_rtc_stop_alarm()
512 ret = regmap_write(info->regmap, S5M_ALARM0_CONF, 0); in s5m_rtc_stop_alarm()
519 for (i = 0; i < info->regs->regs_count; i++) in s5m_rtc_stop_alarm()
522 ret = regmap_raw_write(info->regmap, info->regs->alarm0, data, in s5m_rtc_stop_alarm()
523 info->regs->regs_count); in s5m_rtc_stop_alarm()
532 return -EINVAL; in s5m_rtc_stop_alarm()
545 ret = regmap_bulk_read(info->regmap, info->regs->alarm0, data, in s5m_rtc_start_alarm()
546 info->regs->regs_count); in s5m_rtc_start_alarm()
550 s5m8767_data_to_tm(data, &tm, info->rtc_24hr_mode); in s5m_rtc_start_alarm()
551 dev_dbg(info->dev, "%s: %ptR(%d)\n", __func__, &tm, tm.tm_wday); in s5m_rtc_start_alarm()
553 switch (info->device_type) { in s5m_rtc_start_alarm()
556 ret = regmap_write(info->regmap, S5M_ALARM0_CONF, alarm0_conf); in s5m_rtc_start_alarm()
574 ret = regmap_raw_write(info->regmap, info->regs->alarm0, data, in s5m_rtc_start_alarm()
575 info->regs->regs_count); in s5m_rtc_start_alarm()
583 return -EINVAL; in s5m_rtc_start_alarm()
595 switch (info->device_type) { in s5m_rtc_set_alarm()
597 s5m8763_tm_to_data(&alrm->time, data); in s5m_rtc_set_alarm()
604 s5m8767_tm_to_data(&alrm->time, data); in s5m_rtc_set_alarm()
608 return -EINVAL; in s5m_rtc_set_alarm()
611 dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday); in s5m_rtc_set_alarm()
617 ret = regmap_raw_write(info->regmap, info->regs->alarm0, data, in s5m_rtc_set_alarm()
618 info->regs->regs_count); in s5m_rtc_set_alarm()
626 if (alrm->enabled) in s5m_rtc_set_alarm()
647 rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); in s5m_rtc_alarm_irq()
665 switch (info->device_type) { in s5m8767_rtc_init_reg()
669 ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON, in s5m8767_rtc_init_reg()
672 dev_err(info->dev, "%s: fail to change UDR time: %d\n", in s5m8767_rtc_init_reg()
679 ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2); in s5m8767_rtc_init_reg()
686 ret = regmap_write(info->regmap, info->regs->ctrl, data[0]); in s5m8767_rtc_init_reg()
700 return -EINVAL; in s5m8767_rtc_init_reg()
703 info->rtc_24hr_mode = 1; in s5m8767_rtc_init_reg()
705 dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", in s5m8767_rtc_init_reg()
715 struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); in s5m_rtc_probe()
716 struct sec_platform_data *pdata = s5m87xx->pdata; in s5m_rtc_probe()
722 dev_err(pdev->dev.parent, "Platform data not supplied\n"); in s5m_rtc_probe()
723 return -ENODEV; in s5m_rtc_probe()
726 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); in s5m_rtc_probe()
728 return -ENOMEM; in s5m_rtc_probe()
730 switch (platform_get_device_id(pdev)->driver_data) { in s5m_rtc_probe()
733 info->regs = &s2mps15_rtc_regs; in s5m_rtc_probe()
738 info->regs = &s2mps14_rtc_regs; in s5m_rtc_probe()
743 info->regs = &s2mps13_rtc_regs; in s5m_rtc_probe()
748 info->regs = &s5m_rtc_regs; in s5m_rtc_probe()
753 info->regs = &s5m_rtc_regs; in s5m_rtc_probe()
757 dev_err(&pdev->dev, in s5m_rtc_probe()
759 platform_get_device_id(pdev)->driver_data); in s5m_rtc_probe()
760 return -ENODEV; in s5m_rtc_probe()
763 info->i2c = i2c_new_dummy_device(s5m87xx->i2c->adapter, RTC_I2C_ADDR); in s5m_rtc_probe()
764 if (IS_ERR(info->i2c)) { in s5m_rtc_probe()
765 dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); in s5m_rtc_probe()
766 return PTR_ERR(info->i2c); in s5m_rtc_probe()
769 info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); in s5m_rtc_probe()
770 if (IS_ERR(info->regmap)) { in s5m_rtc_probe()
771 ret = PTR_ERR(info->regmap); in s5m_rtc_probe()
772 dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n", in s5m_rtc_probe()
777 info->dev = &pdev->dev; in s5m_rtc_probe()
778 info->s5m87xx = s5m87xx; in s5m_rtc_probe()
779 info->device_type = platform_get_device_id(pdev)->driver_data; in s5m_rtc_probe()
781 if (s5m87xx->irq_data) { in s5m_rtc_probe()
782 info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); in s5m_rtc_probe()
783 if (info->irq <= 0) { in s5m_rtc_probe()
784 ret = -EINVAL; in s5m_rtc_probe()
785 dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", in s5m_rtc_probe()
795 device_init_wakeup(&pdev->dev, 1); in s5m_rtc_probe()
797 info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc", in s5m_rtc_probe()
800 if (IS_ERR(info->rtc_dev)) { in s5m_rtc_probe()
801 ret = PTR_ERR(info->rtc_dev); in s5m_rtc_probe()
805 if (!info->irq) { in s5m_rtc_probe()
806 dev_info(&pdev->dev, "Alarm IRQ not available\n"); in s5m_rtc_probe()
810 ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, in s5m_rtc_probe()
811 s5m_rtc_alarm_irq, 0, "rtc-alarm0", in s5m_rtc_probe()
814 dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", in s5m_rtc_probe()
815 info->irq, ret); in s5m_rtc_probe()
822 i2c_unregister_device(info->i2c); in s5m_rtc_probe()
831 i2c_unregister_device(info->i2c); in s5m_rtc_remove()
842 if (info->irq && device_may_wakeup(dev)) in s5m_rtc_resume()
843 ret = disable_irq_wake(info->irq); in s5m_rtc_resume()
853 if (info->irq && device_may_wakeup(dev)) in s5m_rtc_suspend()
854 ret = enable_irq_wake(info->irq); in s5m_rtc_suspend()
863 { "s5m-rtc", S5M8767X },
864 { "s2mps13-rtc", S2MPS13X },
865 { "s2mps14-rtc", S2MPS14X },
866 { "s2mps15-rtc", S2MPS15X },
873 .name = "s5m-rtc",
887 MODULE_ALIAS("platform:s5m-rtc");