136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan/* 236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * rtc-tps80031.c -- TI TPS80031/TPS80032 RTC driver 336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * RTC driver for TI TPS80031/TPS80032 Fully Integrated 536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * Power Management with Power Path and Battery Charger 636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * Copyright (c) 2012, NVIDIA Corporation. 836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * Author: Laxman Dewangan <ldewangan@nvidia.com> 1036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 1136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * This program is free software; you can redistribute it and/or 1236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * modify it under the terms of the GNU General Public License as 1336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * published by the Free Software Foundation version 2. 1436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 1536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, 1636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * whether express or implied; without even the implied warranty of 1736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * General Public License for more details. 1936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 2036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * You should have received a copy of the GNU General Public License 2136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * along with this program; if not, write to the Free Software 2236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 2336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * 02111-1307, USA 2436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan */ 2536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 2636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/bcd.h> 2736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/device.h> 2836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/err.h> 2936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/init.h> 3036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/kernel.h> 3136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/module.h> 3236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/mfd/tps80031.h> 3336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/platform_device.h> 3436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/pm.h> 3536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/rtc.h> 3636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#include <linux/slab.h> 3736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 3836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define ENABLE_ALARM_INT 0x08 3936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define ALARM_INT_STATUS 0x40 4036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 4136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan/** 4236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * Setting bit to 1 in STOP_RTC will run the RTC and 4336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * setting this bit to 0 will freeze RTC. 4436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan */ 4536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define STOP_RTC 0x1 4636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 4736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan/* Power on reset Values of RTC registers */ 4836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define TPS80031_RTC_POR_YEAR 0 4936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define TPS80031_RTC_POR_MONTH 1 5036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define TPS80031_RTC_POR_DAY 1 5136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 5236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan/* Numbers of registers for time and alarms */ 5336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define TPS80031_RTC_TIME_NUM_REGS 7 5436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define TPS80031_RTC_ALARM_NUM_REGS 6 5536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 5636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan/** 5736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * PMU RTC have only 2 nibbles to store year information, so using an 5836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * offset of 100 to set the base year as 2000 for our driver. 5936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan */ 6036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#define RTC_YEAR_OFFSET 100 6136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 6236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstruct tps80031_rtc { 6336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct rtc_device *rtc; 6436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int irq; 6536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan}; 6636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 6736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm) 6836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 6936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan u8 buff[TPS80031_RTC_TIME_NUM_REGS]; 7036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 7136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 7236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, 7336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_SECONDS_REG, TPS80031_RTC_TIME_NUM_REGS, buff); 7436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 7536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "reading RTC_SECONDS_REG failed, err = %d\n", ret); 7636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 7736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 7836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 7936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_sec = bcd2bin(buff[0]); 8036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_min = bcd2bin(buff[1]); 8136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_hour = bcd2bin(buff[2]); 8236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_mday = bcd2bin(buff[3]); 8336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_mon = bcd2bin(buff[4]) - 1; 8436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; 8536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm->tm_wday = bcd2bin(buff[6]); 8636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 8736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 8836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 8936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_set_time(struct device *dev, struct rtc_time *tm) 9036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 9136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan u8 buff[7]; 9236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 9336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 9436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[0] = bin2bcd(tm->tm_sec); 9536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[1] = bin2bcd(tm->tm_min); 9636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[2] = bin2bcd(tm->tm_hour); 9736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[3] = bin2bcd(tm->tm_mday); 9836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[4] = bin2bcd(tm->tm_mon + 1); 9936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[5] = bin2bcd(tm->tm_year % RTC_YEAR_OFFSET); 10036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[6] = bin2bcd(tm->tm_wday); 10136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 10236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /* Stop RTC while updating the RTC time registers */ 10336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, 10436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_CTRL_REG, STOP_RTC); 10536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 10636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev->parent, "Stop RTC failed, err = %d\n", ret); 10736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 10836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 10936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 11036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, 11136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_SECONDS_REG, 11236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_TIME_NUM_REGS, buff); 11336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 11436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "writing RTC_SECONDS_REG failed, err %d\n", ret); 11536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 11636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 11736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 11836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, 11936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_CTRL_REG, STOP_RTC); 12036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) 12136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev->parent, "Start RTC failed, err = %d\n", ret); 12236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 12336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 12436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 12536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_alarm_irq_enable(struct device *dev, 12636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan unsigned int enable) 12736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 12836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 12936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 13036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (enable) 13136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, 13236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); 13336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan else 13436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_clr_bits(dev->parent, TPS80031_SLAVE_ID1, 13536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_INTERRUPTS_REG, ENABLE_ALARM_INT); 13636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 13736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "Update on RTC_INT failed, err = %d\n", ret); 13836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 13936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 14036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 14136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 14236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 14336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 14436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 14536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan u8 buff[TPS80031_RTC_ALARM_NUM_REGS]; 14636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 14736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 14836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[0] = bin2bcd(alrm->time.tm_sec); 14936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[1] = bin2bcd(alrm->time.tm_min); 15036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[2] = bin2bcd(alrm->time.tm_hour); 15136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[3] = bin2bcd(alrm->time.tm_mday); 15236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[4] = bin2bcd(alrm->time.tm_mon + 1); 15336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan buff[5] = bin2bcd(alrm->time.tm_year % RTC_YEAR_OFFSET); 15436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_writes(dev->parent, TPS80031_SLAVE_ID1, 15536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_ALARM_SECONDS_REG, 15636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_ALARM_NUM_REGS, buff); 15736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 15836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "Writing RTC_ALARM failed, err %d\n", ret); 15936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 16036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 16136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return tps80031_rtc_alarm_irq_enable(dev, alrm->enabled); 16236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 16336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 16436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 16536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 16636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan u8 buff[6]; 16736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 16836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 16936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_reads(dev->parent, TPS80031_SLAVE_ID1, 17036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_ALARM_SECONDS_REG, 17136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_ALARM_NUM_REGS, buff); 17236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 17336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev->parent, 17436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan "reading RTC_ALARM failed, err = %d\n", ret); 17536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 17636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 17736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 17836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_sec = bcd2bin(buff[0]); 17936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_min = bcd2bin(buff[1]); 18036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_hour = bcd2bin(buff[2]); 18136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_mday = bcd2bin(buff[3]); 18236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_mon = bcd2bin(buff[4]) - 1; 18336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan alrm->time.tm_year = bcd2bin(buff[5]) + RTC_YEAR_OFFSET; 18436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 18536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 18636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 18736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int clear_alarm_int_status(struct device *dev, struct tps80031_rtc *rtc) 18836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 18936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 19036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan u8 buf; 19136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 19236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /** 19336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * As per datasheet, A dummy read of this RTC_STATUS_REG register 19436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * is necessary before each I2C read in order to update the status 19536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan * register value. 19636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan */ 19736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_read(dev->parent, TPS80031_SLAVE_ID1, 19836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_STATUS_REG, &buf); 19936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 20036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "reading RTC_STATUS failed. err = %d\n", ret); 20136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 20236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 20336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 20436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /* clear Alarm status bits.*/ 20536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_set_bits(dev->parent, TPS80031_SLAVE_ID1, 20636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_STATUS_REG, ALARM_INT_STATUS); 20736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 20836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(dev, "clear Alarm INT failed, err = %d\n", ret); 20936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 21036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 21136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 21236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 21336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 21436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic irqreturn_t tps80031_rtc_irq(int irq, void *data) 21536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 21636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct device *dev = data; 21736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct tps80031_rtc *rtc = dev_get_drvdata(dev); 21836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 21936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 22036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = clear_alarm_int_status(dev, rtc); 22136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) 22236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 22336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 22436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); 22536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return IRQ_HANDLED; 22636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 22736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 22836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic const struct rtc_class_ops tps80031_rtc_ops = { 22936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .read_time = tps80031_rtc_read_time, 23036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .set_time = tps80031_rtc_set_time, 23136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .set_alarm = tps80031_rtc_set_alarm, 23236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .read_alarm = tps80031_rtc_read_alarm, 23336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .alarm_irq_enable = tps80031_rtc_alarm_irq_enable, 23436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan}; 23536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 23636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_probe(struct platform_device *pdev) 23736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 23836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct tps80031_rtc *rtc; 23936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct rtc_time tm; 24036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan int ret; 24136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 24236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 24336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (!rtc) 24436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return -ENOMEM; 24536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 24636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan rtc->irq = platform_get_irq(pdev, 0); 24736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan platform_set_drvdata(pdev, rtc); 24836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 24936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /* Start RTC */ 25036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_set_bits(pdev->dev.parent, TPS80031_SLAVE_ID1, 25136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan TPS80031_RTC_CTRL_REG, STOP_RTC); 25236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 25336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(&pdev->dev, "failed to start RTC. err = %d\n", ret); 25436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 25536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 25636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 25736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /* If RTC have POR values, set time 01:01:2000 */ 25836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tps80031_rtc_read_time(&pdev->dev, &tm); 25936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if ((tm.tm_year == RTC_YEAR_OFFSET + TPS80031_RTC_POR_YEAR) && 26036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan (tm.tm_mon == (TPS80031_RTC_POR_MONTH - 1)) && 26136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan (tm.tm_mday == TPS80031_RTC_POR_DAY)) { 26236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm.tm_year = 2000; 26336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm.tm_mday = 1; 26436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan tm.tm_mon = 1; 26536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = tps80031_rtc_set_time(&pdev->dev, &tm); 26636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 26736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(&pdev->dev, 26836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan "RTC set time failed, err = %d\n", ret); 26936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 27036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 27136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 27236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 27336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan /* Clear alarm intretupt status if it is there */ 27436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = clear_alarm_int_status(&pdev->dev, rtc); 27536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 27636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(&pdev->dev, "Clear alarm int failed, err = %d\n", ret); 27736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 27836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 27936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 280faa43af9bc96a78b1fcd8067c7d9e3ebd044087eJingoo Han rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 28136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan &tps80031_rtc_ops, THIS_MODULE); 28236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (IS_ERR(rtc->rtc)) { 28336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan ret = PTR_ERR(rtc->rtc); 28436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(&pdev->dev, "RTC registration failed, err %d\n", ret); 28536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 28636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 28736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 2886d77bdca22da510ce1ea43ea07441bbba3ff8881Jingoo Han ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, 2896d77bdca22da510ce1ea43ea07441bbba3ff8881Jingoo Han tps80031_rtc_irq, 29036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan IRQF_ONESHOT | IRQF_EARLY_RESUME, 29136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_name(&pdev->dev), rtc); 29236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (ret < 0) { 29336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n", 29436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan rtc->irq, ret); 29536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return ret; 29636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan } 29736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan device_set_wakeup_capable(&pdev->dev, 1); 29836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 29936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 30036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 30136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#ifdef CONFIG_PM_SLEEP 30236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_suspend(struct device *dev) 30336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 30436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct tps80031_rtc *rtc = dev_get_drvdata(dev); 30536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 30636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (device_may_wakeup(dev)) 30736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan enable_irq_wake(rtc->irq); 30836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 30936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan} 31036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 31136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic int tps80031_rtc_resume(struct device *dev) 31236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan{ 31336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan struct tps80031_rtc *rtc = dev_get_drvdata(dev); 31436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 31536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan if (device_may_wakeup(dev)) 31636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan disable_irq_wake(rtc->irq); 31736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan return 0; 31836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan}; 31936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan#endif 32036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 3217d1376d80228b4ca6e1a0d1e8b88efc23a013f2cJingoo Hanstatic SIMPLE_DEV_PM_OPS(tps80031_pm_ops, tps80031_rtc_suspend, 3227d1376d80228b4ca6e1a0d1e8b88efc23a013f2cJingoo Han tps80031_rtc_resume); 32336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 32436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganstatic struct platform_driver tps80031_rtc_driver = { 32536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .driver = { 32636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .name = "tps80031-rtc", 32736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .owner = THIS_MODULE, 32836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .pm = &tps80031_pm_ops, 32936d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan }, 33036d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan .probe = tps80031_rtc_probe, 33136d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan}; 33236d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 33336d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewanganmodule_platform_driver(tps80031_rtc_driver); 33436d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman Dewangan 33536d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman DewanganMODULE_ALIAS("platform:tps80031-rtc"); 33636d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman DewanganMODULE_DESCRIPTION("TI TPS80031/TPS80032 RTC driver"); 33736d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman DewanganMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 33836d6182411b9f597f9f85ec0c4bb00909fd16d59Laxman DewanganMODULE_LICENSE("GPL v2"); 339