15e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* 25e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * RTC driver for Maxim MAX8997 35e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * 45e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * Copyright (C) 2013 Samsung Electronics Co.Ltd 55e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * 65e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * based on rtc-max8998.c 75e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * 85e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * This program is free software; you can redistribute it and/or modify it 95e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * under the terms of the GNU General Public License as published by the 105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * Free Software Foundation; either version 2 of the License, or (at your 115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * option) any later version. 125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * 135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee */ 145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/slab.h> 165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/rtc.h> 175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/delay.h> 185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/mutex.h> 195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/module.h> 205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/platform_device.h> 215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/mfd/max8997-private.h> 225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#include <linux/irqdomain.h> 235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* Module parameter for WTSR function control */ 255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int wtsr_en = 1; 265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leemodule_param(wtsr_en, int, 0444); 27a895d57da04a4a24cda996e1a72425ff7e7e6c22Masanari IidaMODULE_PARM_DESC(wtsr_en, "Watchdog Timeout & Software Reset (default=on)"); 285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* Module parameter for SMPL function control */ 295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int smpl_en = 1; 305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leemodule_param(smpl_en, int, 0444); 315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa LeeMODULE_PARM_DESC(smpl_en, "Sudden Momentary Power Loss (default=on)"); 325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* RTC Control Register */ 345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define BCD_EN_SHIFT 0 355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define BCD_EN_MASK (1 << BCD_EN_SHIFT) 365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define MODEL24_SHIFT 1 375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define MODEL24_MASK (1 << MODEL24_SHIFT) 385e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* RTC Update Register1 */ 395e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define RTC_UDR_SHIFT 0 405e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) 415e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* WTSR and SMPL Register */ 425e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define WTSRT_SHIFT 0 435e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define SMPLT_SHIFT 2 445e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define WTSR_EN_SHIFT 6 455e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define SMPL_EN_SHIFT 7 465e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define WTSRT_MASK (3 << WTSRT_SHIFT) 475e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define SMPLT_MASK (3 << SMPLT_SHIFT) 485e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT) 495e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT) 505e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* RTC Hour register */ 515e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define HOUR_PM_SHIFT 6 525e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) 535e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee/* RTC Alarm Enable */ 545e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define ALARM_ENABLE_SHIFT 7 555e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) 565e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 575e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeenum { 585e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_SEC = 0, 595e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_MIN, 605e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_HOUR, 615e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_WEEKDAY, 625e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_MONTH, 635e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_YEAR, 645e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_DATE, 655e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_NR_TIME 665e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee}; 675e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 685e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestruct max8997_rtc_info { 695e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct device *dev; 705e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_dev *max8997; 715e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct i2c_client *rtc; 725e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct rtc_device *rtc_dev; 735e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct mutex lock; 745e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int virq; 755e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int rtc_24hr_mode; 765e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee}; 775e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 785e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic void max8997_rtc_data_to_tm(u8 *data, struct rtc_time *tm, 795e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int rtc_24hr_mode) 805e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 815e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_sec = data[RTC_SEC] & 0x7f; 825e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_min = data[RTC_MIN] & 0x7f; 835e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (rtc_24hr_mode) 845e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_hour = data[RTC_HOUR] & 0x1f; 855e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee else { 865e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_hour = data[RTC_HOUR] & 0x0f; 875e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (data[RTC_HOUR] & HOUR_PM_MASK) 885e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_hour += 12; 895e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 905e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 915e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_wday = fls(data[RTC_WEEKDAY] & 0x7f) - 1; 925e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_mday = data[RTC_DATE] & 0x1f; 935e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; 945e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; 955e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_yday = 0; 965e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee tm->tm_isdst = 0; 975e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 985e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 995e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data) 1005e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 1015e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_SEC] = tm->tm_sec; 1025e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_MIN] = tm->tm_min; 1035e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_HOUR] = tm->tm_hour; 1045e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_WEEKDAY] = 1 << tm->tm_wday; 1055e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_DATE] = tm->tm_mday; 1065e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_MONTH] = tm->tm_mon + 1; 107f887a9de5522487debc7601595f4ef791572c044Sachin Kamat data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; 1085e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1095e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (tm->tm_year < 100) { 1105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee pr_warn("%s: MAX8997 RTC cannot handle the year %d." 1115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); 1125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return -EINVAL; 1135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 1145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return 0; 1155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 1165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info) 1185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 1195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 1205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1, 1225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee RTC_UDR_MASK); 1235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) 1245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write update reg(%d)\n", 1255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 1265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee else { 1275e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee /* Minimum 16ms delay required before RTC update. 1285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * Otherwise, we may read and update based on out-of-date 1295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee * value */ 1305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee msleep(20); 1315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 1325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 1345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 1355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm) 1375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 1385e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = dev_get_drvdata(dev); 1395e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 1405e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 1415e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1425e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_lock(&info->lock); 1435e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); 1445e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_unlock(&info->lock); 1455e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1465e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 1475e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, 1485e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret); 1495e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 1505e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 1515e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1525e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); 1535e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1545e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return rtc_valid_tm(tm); 1555e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 1565e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1575e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm) 1585e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 1595e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = dev_get_drvdata(dev); 1605e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 1615e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 1625e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1635e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_tm_to_data(tm, data); 1645e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) 1655e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 1665e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1675e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_lock(&info->lock); 1685e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1695e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data); 1705e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 1715e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, 1725e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret); 1735e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 1745e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 1755e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1765e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_set_update_reg(info); 1775e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeout: 1785e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_unlock(&info->lock); 1795e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 1805e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 1815e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1825e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 1835e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 1845e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = dev_get_drvdata(dev); 1855e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 1865e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 val; 1875e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int i, ret; 1885e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1895e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_lock(&info->lock); 1905e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1915e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 1925e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 1935e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 1945e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", 1955e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, __LINE__, ret); 1965e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 1975e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 1985e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 1995e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); 2005e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2015e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee alrm->enabled = 0; 2025e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee for (i = 0; i < RTC_NR_TIME; i++) { 2035e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (data[i] & ALARM_ENABLE_MASK) { 2045e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee alrm->enabled = 1; 2055e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee break; 2065e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2075e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2085e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2095e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee alrm->pending = 0; 2105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val); 2115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 2125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n", 2135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, __LINE__, ret); 2145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 2155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (val & (1 << 4)) /* RTCA1 */ 2185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee alrm->pending = 1; 2195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeout: 2215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_unlock(&info->lock); 2225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return 0; 2235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 2245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_stop_alarm(struct max8997_rtc_info *info) 2265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 2275e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 2285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret, i; 2295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!mutex_is_locked(&info->lock)) 2315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_warn(info->dev, "%s: should have mutex locked\n", __func__); 2325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 2345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 2355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 2365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", 2375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 2385e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 2395e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2405e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2415e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee for (i = 0; i < RTC_NR_TIME; i++) 2425e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[i] &= ~ALARM_ENABLE_MASK; 2435e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2445e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 2455e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 2465e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 2475e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", 2485e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 2495e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 2505e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2515e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2525e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_set_update_reg(info); 2535e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeout: 2545e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 2555e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 2565e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2575e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_start_alarm(struct max8997_rtc_info *info) 2585e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 2595e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 2605e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 2615e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2625e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!mutex_is_locked(&info->lock)) 2635e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_warn(info->dev, "%s: should have mutex locked\n", __func__); 2645e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2655e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 2665e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 2675e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 2685e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", 2695e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 2705e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 2715e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2725e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2735e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); 2745e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); 2755e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); 2765e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; 2775e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (data[RTC_MONTH] & 0xf) 2785e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); 2795e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (data[RTC_YEAR] & 0x7f) 2805e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); 2815e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (data[RTC_DATE] & 0x1f) 2825e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); 2835e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2845e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 2855e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 2865e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 2875e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", 2885e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 2895e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 2905e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 2915e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 2925e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_set_update_reg(info); 2935e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeout: 2945e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 2955e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 2965e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 2975e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 2985e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = dev_get_drvdata(dev); 2995e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[RTC_NR_TIME]; 3005e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 3015e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3025e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_tm_to_data(&alrm->time, data); 3035e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) 3045e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 3055e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3065e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_info(info->dev, "%s: %d-%02d-%02d %02d:%02d:%02d\n", __func__, 3075e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_YEAR] + 2000, data[RTC_MONTH], data[RTC_DATE], 3085e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[RTC_HOUR], data[RTC_MIN], data[RTC_SEC]); 3095e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_lock(&info->lock); 3115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_stop_alarm(info); 3135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) 3145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 3155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, 3175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data); 3185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 3195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", 3205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 3215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 3225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 3235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_set_update_reg(info); 3255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) 3265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto out; 3275e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (alrm->enabled) 3295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_start_alarm(info); 3305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeout: 3315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_unlock(&info->lock); 3325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 3335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 3345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_alarm_irq_enable(struct device *dev, 3365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee unsigned int enabled) 3375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 3385e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = dev_get_drvdata(dev); 3395e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 3405e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3415e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_lock(&info->lock); 3425e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (enabled) 3435e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_start_alarm(info); 3445e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee else 3455e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_stop_alarm(info); 3465e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_unlock(&info->lock); 3475e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3485e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 3495e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 3505e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3515e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic irqreturn_t max8997_rtc_alarm_irq(int irq, void *data) 3525e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 3535e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = data; 3545e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3555e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); 3565e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3575e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); 3585e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3595e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return IRQ_HANDLED; 3605e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 3615e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3625e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic const struct rtc_class_ops max8997_rtc_ops = { 3635e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .read_time = max8997_rtc_read_time, 3645e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .set_time = max8997_rtc_set_time, 3655e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .read_alarm = max8997_rtc_read_alarm, 3665e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .set_alarm = max8997_rtc_set_alarm, 3675e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .alarm_irq_enable = max8997_rtc_alarm_irq_enable, 3685e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee}; 3695e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3705e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable) 3715e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 3725e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 3735e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 val, mask; 3745e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3755e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!wtsr_en) 3765e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return; 3775e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3785e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (enable) 3795e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT); 3805e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee else 3815e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee val = 0; 3825e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3835e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mask = WTSR_EN_MASK | WTSRT_MASK; 3845e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3855e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_info(info->dev, "%s: %s WTSR\n", __func__, 3865e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee enable ? "enable" : "disable"); 3875e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3885e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); 3895e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 3905e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n", 3915e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 3925e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return; 3935e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 3945e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3955e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_set_update_reg(info); 3965e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 3975e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 3985e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable) 3995e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 4005e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 4015e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 val, mask; 4025e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4035e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!smpl_en) 4045e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return; 4055e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4065e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (enable) 4075e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT); 4085e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee else 4095e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee val = 0; 4105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mask = SMPL_EN_MASK | SMPLT_MASK; 4125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_info(info->dev, "%s: %s SMPL\n", __func__, 4145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee enable ? "enable" : "disable"); 4155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask); 4175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 4185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n", 4195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 4205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return; 4215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 4225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_set_update_reg(info); 4245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee val = 0; 4265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val); 4275e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); 4285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 4295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_init_reg(struct max8997_rtc_info *info) 4315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 4325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee u8 data[2]; 4335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret; 4345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee /* Set RTC control register : Binary mode, 24hour mdoe */ 4365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); 4375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); 4385e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4395e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->rtc_24hr_mode = 1; 4405e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4415e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data); 4425e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 4435e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", 4445e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee __func__, ret); 4455e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 4465e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 4475e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4485e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_set_update_reg(info); 4495e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 4505e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 4515e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4525e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic int max8997_rtc_probe(struct platform_device *pdev) 4535e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 4545e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); 4555e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info; 4565e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee int ret, virq; 4575e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4585e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_rtc_info), 4595e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee GFP_KERNEL); 4605e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!info) 4615e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return -ENOMEM; 4625e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4635e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee mutex_init(&info->lock); 4645e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->dev = &pdev->dev; 4655e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->max8997 = max8997; 4665e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->rtc = max8997->rtc; 4675e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4685e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee platform_set_drvdata(pdev, info); 4695e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4705e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = max8997_rtc_init_reg(info); 4715e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4725e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (ret < 0) { 4735e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); 4745e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 4755e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 4765e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4775e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_enable_wtsr(info, true); 4785e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_enable_smpl(info, true); 4795e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4805e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee device_init_wakeup(&pdev->dev, 1); 4815e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4824ce903cc91534916a3b342bae91c30ba777190fdJingoo Han info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8997-rtc", 4834ce903cc91534916a3b342bae91c30ba777190fdJingoo Han &max8997_rtc_ops, THIS_MODULE); 4845e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4855e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (IS_ERR(info->rtc_dev)) { 4865e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee ret = PTR_ERR(info->rtc_dev); 4875e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 4885e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 4895e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 4905e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 4915e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1); 4925e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee if (!virq) { 4935e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n"); 494406dc00407edfa75c97123c7f8653e850358fb72Sachin Kamat ret = -ENXIO; 4955e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee goto err_out; 4965e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee } 4975e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->virq = virq; 4985e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 499c1879fe80c61f3be6f2ddb82509c2e7f92a484feJingoo Han ret = devm_request_threaded_irq(&pdev->dev, virq, NULL, 500c1879fe80c61f3be6f2ddb82509c2e7f92a484feJingoo Han max8997_rtc_alarm_irq, 0, 5015e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee "rtc-alarm0", info); 502406dc00407edfa75c97123c7f8653e850358fb72Sachin Kamat if (ret < 0) 5035e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", 5045e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee info->virq, ret); 5055e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5065e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leeerr_out: 5075e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee return ret; 5085e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 5095e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5105e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic void max8997_rtc_shutdown(struct platform_device *pdev) 5115e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee{ 5125e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee struct max8997_rtc_info *info = platform_get_drvdata(pdev); 5135e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5145e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_enable_wtsr(info, false); 5155e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee max8997_rtc_enable_smpl(info, false); 5165e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee} 5175e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5185e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic const struct platform_device_id rtc_id[] = { 5195e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee { "max8997-rtc", 0 }, 5205e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee {}, 5215e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee}; 5225e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5235e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leestatic struct platform_driver max8997_rtc_driver = { 5245e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .driver = { 5255e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .name = "max8997-rtc", 5265e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .owner = THIS_MODULE, 5275e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee }, 5285e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .probe = max8997_rtc_probe, 5295e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .shutdown = max8997_rtc_shutdown, 5305e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee .id_table = rtc_id, 5315e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee}; 5325e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5335e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Leemodule_platform_driver(max8997_rtc_driver); 5345e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa Lee 5355e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa LeeMODULE_DESCRIPTION("Maxim MAX8997 RTC driver"); 5365e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa LeeMODULE_AUTHOR("<ms925.kim@samsung.com>"); 5375e0b2704a1d5c246c8282303bbc952cba17f94fcJonghwa LeeMODULE_LICENSE("GPL"); 538