190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* 290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock 390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Author: Venu Byravarasu <vbyravarasu@nvidia.com> 690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * This program is free software; you can redistribute it and/or modify it 890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * under the terms and conditions of the GNU General Public License, 990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * version 2, as published by the Free Software Foundation. 1090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 1190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * This program is distributed in the hope it will be useful, but WITHOUT 1290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * more details. 1590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 1690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * You should have received a copy of the GNU General Public License 1790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 1990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/kernel.h> 2090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/errno.h> 2190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/init.h> 2290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/module.h> 2390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/types.h> 2490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/rtc.h> 2590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/bcd.h> 2690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/platform_device.h> 2790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/interrupt.h> 2890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#include <linux/mfd/rc5t583.h> 2990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 3090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustruct rc5t583_rtc { 3190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rtc_device *rtc; 3290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* To store the list of enabled interrupts, during system suspend */ 3390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu u32 irqen; 3490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu}; 3590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 3690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* Total number of RTC registers needed to set time*/ 3790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#define NUM_TIME_REGS (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1) 3890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 3990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* Total number of RTC registers needed to set Y-Alarm*/ 4090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#define NUM_YAL_REGS (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1) 4190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 4290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* Set Y-Alarm interrupt */ 4390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#define SET_YAL BIT(5) 4490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 4590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* Get Y-Alarm interrupt status*/ 4690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#define GET_YAL_STATUS BIT(3) 4790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 4890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 4990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 5090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 5190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu u8 val; 5290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 5390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* Set Y-Alarm, based on 'enabled' */ 5490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu val = enabled ? SET_YAL : 0; 5590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 5690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL, 5790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu val); 5890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 5990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 6090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* 6190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Gets current rc5t583 RTC time and date parameters. 6290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 6390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * The RTC's time/alarm representation is not what gmtime(3) requires 6490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Linux to use: 6590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * 6690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * - Months are 1..12 vs Linux 0-11 6790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 6890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu */ 6990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm) 7090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 7190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 7290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu u8 rtc_data[NUM_TIME_REGS]; 7390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 7490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 7590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, 7690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu NUM_TIME_REGS); 7790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) { 7890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(dev, "RTC read time failed with err:%d\n", ret); 7990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 8090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 8190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 8290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_sec = bcd2bin(rtc_data[0]); 8390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_min = bcd2bin(rtc_data[1]); 8490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_hour = bcd2bin(rtc_data[2]); 8590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_wday = bcd2bin(rtc_data[3]); 8690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_mday = bcd2bin(rtc_data[4]); 8790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_mon = bcd2bin(rtc_data[5]) - 1; 8890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu tm->tm_year = bcd2bin(rtc_data[6]) + 100; 8990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 9090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 9190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 9290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 9390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm) 9490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 9590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 9690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu unsigned char rtc_data[NUM_TIME_REGS]; 9790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 9890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 9990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[0] = bin2bcd(tm->tm_sec); 10090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[1] = bin2bcd(tm->tm_min); 10190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[2] = bin2bcd(tm->tm_hour); 10290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[3] = bin2bcd(tm->tm_wday); 10390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[4] = bin2bcd(tm->tm_mday); 10490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[5] = bin2bcd(tm->tm_mon + 1); 10590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_data[6] = bin2bcd(tm->tm_year - 100); 10690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 10790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, 10890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu NUM_TIME_REGS); 10990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) { 11090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(dev, "RTC set time failed with error %d\n", ret); 11190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 11290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 11390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 11490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 11590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 11690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 11790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 11890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 11990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 12090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu unsigned char alarm_data[NUM_YAL_REGS]; 12190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu u32 interrupt_enable; 12290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 12390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 12490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, 12590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu NUM_YAL_REGS); 12690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) { 12790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(dev, "rtc_read_alarm error %d\n", ret); 12890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 12990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 13090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 13190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->time.tm_min = bcd2bin(alarm_data[0]); 13290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->time.tm_hour = bcd2bin(alarm_data[1]); 13390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->time.tm_mday = bcd2bin(alarm_data[2]); 13490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1; 13590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->time.tm_year = bcd2bin(alarm_data[4]) + 100; 13690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 13790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable); 13890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) 13990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 14090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 14190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* check if YALE is set */ 14290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (interrupt_enable & SET_YAL) 14390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alm->enabled = 1; 14490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 14590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 14690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 14790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 14890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 14990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 15090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 15190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu unsigned char alarm_data[NUM_YAL_REGS]; 15290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 15390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 15490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = rc5t583_rtc_alarm_irq_enable(dev, 0); 15590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret) 15690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 15790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 15890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alarm_data[0] = bin2bcd(alm->time.tm_min); 15990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alarm_data[1] = bin2bcd(alm->time.tm_hour); 16090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alarm_data[2] = bin2bcd(alm->time.tm_mday); 16190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alarm_data[3] = bin2bcd(alm->time.tm_mon + 1); 16290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu alarm_data[4] = bin2bcd(alm->time.tm_year - 100); 16390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 16490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, 16590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu NUM_YAL_REGS); 16690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret) { 16790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(dev, "rtc_set_alarm error %d\n", ret); 16890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 16990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 17090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 17190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (alm->enabled) 17290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = rc5t583_rtc_alarm_irq_enable(dev, 1); 17390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 17490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 17590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 17690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 17790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc) 17890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 17990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct device *dev = rtc; 18090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 18190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 18290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu unsigned long events = 0; 18390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 18490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu u32 rtc_reg; 18590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 18690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg); 18790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) 18890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return IRQ_NONE; 18990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 19090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (rtc_reg & GET_YAL_STATUS) { 19190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu events = RTC_IRQF | RTC_AF; 19290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* clear pending Y-alarm interrupt bit */ 19390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_reg &= ~GET_YAL_STATUS; 19490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 19590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 19690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg); 19790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret) 19890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return IRQ_NONE; 19990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 20090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* Notify RTC core on event */ 20190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rtc_update_irq(rc5t583_rtc->rtc, 1, events); 20290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 20390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return IRQ_HANDLED; 20490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 20590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 20690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic const struct rtc_class_ops rc5t583_rtc_ops = { 20790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .read_time = rc5t583_rtc_read_time, 20890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .set_time = rc5t583_rtc_set_time, 20990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .read_alarm = rc5t583_rtc_read_alarm, 21090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .set_alarm = rc5t583_rtc_set_alarm, 21190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable, 21290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu}; 21390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 2145a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int rc5t583_rtc_probe(struct platform_device *pdev) 21590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 21690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 21790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583_rtc *ricoh_rtc; 21890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583_platform_data *pmic_plat_data; 21990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 22090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int irq; 22190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 22290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc), 22390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu GFP_KERNEL); 22490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (!ricoh_rtc) 22590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return -ENOMEM; 22690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 22790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu platform_set_drvdata(pdev, ricoh_rtc); 22890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 22990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* Clear pending interrupts */ 23090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0); 23190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) 23290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 23390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 23490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* clear RTC Adjust register */ 23590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0); 23690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) { 23790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(&pdev->dev, "unable to program rtc_adjust reg\n"); 23890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return -EBUSY; 23990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 24090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 24190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu pmic_plat_data = dev_get_platdata(rc5t583->dev); 24290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu irq = pmic_plat_data->irq_base; 24390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (irq <= 0) { 24490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", 24590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu irq); 24690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 24790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 24890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 24990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu irq += RC5T583_IRQ_YALE; 25090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 25190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW, 25290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu "rtc-rc5t583", &pdev->dev); 25390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (ret < 0) { 25490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(&pdev->dev, "IRQ is not free.\n"); 25590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 25690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 25790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu device_init_wakeup(&pdev->dev, 1); 25890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 2598b7980dbf9e69d36916830f44b206a1e1cfcd174Jingoo Han ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 26090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu &rc5t583_rtc_ops, THIS_MODULE); 26190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu if (IS_ERR(ricoh_rtc->rtc)) { 26290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = PTR_ERR(ricoh_rtc->rtc); 26390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu dev_err(&pdev->dev, "RTC device register: err %d\n", ret); 26490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 26590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu } 26690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 26790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return 0; 26890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 26990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 27090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu/* 27190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Disable rc5t583 RTC interrupts. 27290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu * Sets status flag to free. 27390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu */ 2745a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int rc5t583_rtc_remove(struct platform_device *pdev) 27590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 276e1c2f989e691e8e124b57fd7ba4e15e7873b91e5Jingoo Han struct rc5t583_rtc *rc5t583_rtc = platform_get_drvdata(pdev); 27790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 27890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0); 27990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return 0; 28090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 28190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 28290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#ifdef CONFIG_PM_SLEEP 28390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_suspend(struct device *dev) 28490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 28590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 28690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 28790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu int ret; 28890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 28990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* Store current list of enabled interrupts*/ 29090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, 29190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu &rc5t583_rtc->irqen); 29290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return ret; 29390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 29490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 29590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic int rc5t583_rtc_resume(struct device *dev) 29690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu{ 29790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 29890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 29990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 30090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu /* Restore list of enabled interrupts before suspend */ 30190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1, 30290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu rc5t583_rtc->irqen); 30390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu} 30490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu#endif 30590829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 30629756a52e27d57d8435347c871598e9170a88c47Jingoo Hanstatic SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend, 30729756a52e27d57d8435347c871598e9170a88c47Jingoo Han rc5t583_rtc_resume); 30829756a52e27d57d8435347c871598e9170a88c47Jingoo Han 30990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasustatic struct platform_driver rc5t583_rtc_driver = { 31090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .probe = rc5t583_rtc_probe, 3115a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartman .remove = rc5t583_rtc_remove, 31290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .driver = { 31390829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .owner = THIS_MODULE, 31490829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu .name = "rtc-rc5t583", 31529756a52e27d57d8435347c871598e9170a88c47Jingoo Han .pm = &rc5t583_rtc_pm_ops, 31690829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu }, 31790829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu}; 31890829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasu 31990829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu Byravarasumodule_platform_driver(rc5t583_rtc_driver); 32090829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu ByravarasuMODULE_ALIAS("platform:rtc-rc5t583"); 32190829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu ByravarasuMODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); 32290829c089ef622e54ce1153eb6dcda9ce98cb7c2Venu ByravarasuMODULE_LICENSE("GPL v2"); 323