10e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 20e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * rtc-tps65910.c -- TPS65910 Real Time Clock interface 30e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 40e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 50e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Author: Venu Byravarasu <vbyravarasu@nvidia.com> 60e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 70e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Based on original TI driver rtc-twl.c 80e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Copyright (C) 2007 MontaVista Software, Inc 90e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Author: Alexandre Rusev <source@mvista.com> 100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * This program is free software; you can redistribute it and/or 120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * modify it under the terms of the GNU General Public License 130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * as published by the Free Software Foundation; either version 140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 2 of the License, or (at your option) any later version. 150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 170e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/kernel.h> 180e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/errno.h> 190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/init.h> 200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/module.h> 210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/types.h> 220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/rtc.h> 230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/bcd.h> 240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/platform_device.h> 250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/interrupt.h> 260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#include <linux/mfd/tps65910.h> 270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustruct tps65910_rtc { 290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct rtc_device *rtc; 30eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan int irq; 310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* Total number of RTC registers needed to set time*/ 340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) 350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u8 val = 0; 400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (enabled) 420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu val = TPS65910_RTC_INTERRUPTS_IT_ALARM; 430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val); 450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Gets current tps65910 RTC time and date parameters. 490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * The RTC's time/alarm representation is not what gmtime(3) requires 510e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Linux to use: 520e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 530e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * - Months are 1..12 vs Linux 0-11 540e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 550e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm) 570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char rtc_data[NUM_TIME_REGS]; 590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Copy RTC counting registers to static registers or latches */ 630e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 640e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME); 650e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 660e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret); 670e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data, 710e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 720e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 730e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "reading from RTC failed with err:%d\n", ret); 740e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 750e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 760e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 770e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_sec = bcd2bin(rtc_data[0]); 780e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_min = bcd2bin(rtc_data[1]); 790e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_hour = bcd2bin(rtc_data[2]); 800e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_mday = bcd2bin(rtc_data[3]); 810e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_mon = bcd2bin(rtc_data[4]) - 1; 820e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_year = bcd2bin(rtc_data[5]) + 100; 830e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 840e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 850e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 860e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 870e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm) 880e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char rtc_data[NUM_TIME_REGS]; 900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[0] = bin2bcd(tm->tm_sec); 940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[1] = bin2bcd(tm->tm_min); 950e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[2] = bin2bcd(tm->tm_hour); 960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[3] = bin2bcd(tm->tm_mday); 970e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[4] = bin2bcd(tm->tm_mon + 1); 980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[5] = bin2bcd(tm->tm_year - 100); 990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1000e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Stop RTC while updating the RTC time registers */ 1010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 1020e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_STOP_RTC, 0); 1030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1040e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC stop failed with err:%d\n", ret); 1050e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1070e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1080e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* update all the time registers in one shot */ 1090e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data, 1100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 1110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_set_time error %d\n", ret); 1130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Start back RTC */ 1170e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 1180e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_STOP_RTC, 1); 1190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 1200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC start failed with err:%d\n", ret); 1210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 1260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Gets current tps65910 RTC alarm time. 1270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 1280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 1290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char alarm_data[NUM_TIME_REGS]; 1310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 int_val; 1320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, 1360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 1370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_read_alarm error %d\n", ret); 1390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_sec = bcd2bin(alarm_data[0]); 1430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_min = bcd2bin(alarm_data[1]); 1440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_hour = bcd2bin(alarm_data[2]); 1450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_mday = bcd2bin(alarm_data[3]); 1460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; 1470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; 1480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val); 1500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 1510e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1520e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1530e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM) 1540e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->enabled = 1; 1550e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 1600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char alarm_data[NUM_TIME_REGS]; 1620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1630e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1640e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1650e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = tps65910_rtc_alarm_irq_enable(dev, 0); 1660e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 1670e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[0] = bin2bcd(alm->time.tm_sec); 1700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[1] = bin2bcd(alm->time.tm_min); 1710e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[2] = bin2bcd(alm->time.tm_hour); 1720e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[3] = bin2bcd(alm->time.tm_mday); 1730e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); 1740e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[5] = bin2bcd(alm->time.tm_year - 100); 1750e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1760e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* update all the alarm registers in one shot */ 1770e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS, 1780e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data, NUM_TIME_REGS); 1790e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) { 1800e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_set_alarm error %d\n", ret); 1810e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1820e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1830e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1840e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (alm->enabled) 1850e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = tps65910_rtc_alarm_irq_enable(dev, 1); 1860e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1870e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1880e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) 1910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct device *dev = rtc; 1930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned long events = 0; 1940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1950e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 1960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1970e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 rtc_reg; 1980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg); 2000e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 2010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_NONE; 2020e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (rtc_reg & TPS65910_RTC_STATUS_ALARM) 2040e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu events = RTC_IRQF | RTC_AF; 2050e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg); 2070e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 2080e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_NONE; 2090e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Notify RTC core on event */ 2110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_update_irq(tps_rtc->rtc, 1, events); 2120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_HANDLED; 2140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 2150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic const struct rtc_class_ops tps65910_rtc_ops = { 2170e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .read_time = tps65910_rtc_read_time, 2180e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .set_time = tps65910_rtc_set_time, 2190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .read_alarm = tps65910_rtc_read_alarm, 2200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .set_alarm = tps65910_rtc_set_alarm, 2210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, 2220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 2230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2245a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int tps65910_rtc_probe(struct platform_device *pdev) 2250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 2260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps65910 = NULL; 2270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910_rtc *tps_rtc = NULL; 2280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 2290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int irq; 2300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 rtc_reg; 2310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps65910 = dev_get_drvdata(pdev->dev.parent); 2330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc), 2350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu GFP_KERNEL); 2360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (!tps_rtc) 2370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return -ENOMEM; 2380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Clear pending interrupts */ 2400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg); 2410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg); 2450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); 24918c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo 25018c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo /* Enable RTC digital power domain */ 25118c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, 25218c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); 25318c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo if (ret < 0) 25418c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo return ret; 25518c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo 2560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; 2570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); 2580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2619f7d7a1d0f36bed7f533807146483e8fdfe12a89Thierry Reding platform_set_drvdata(pdev, tps_rtc); 2629f7d7a1d0f36bed7f533807146483e8fdfe12a89Thierry Reding 26306f77d18e4be0837868ebba8dff4097103e484c4Venu Byravarasu irq = platform_get_irq(pdev, 0); 2640e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (irq <= 0) { 2650e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", 2660e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu irq); 267dbda161be8ae43133bbeac34da3ad99ffeb63556Sachin Kamat return -ENXIO; 2680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 2690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 271225ccc28726ca8849e5bfc9148c343e258737f3bLaxman Dewangan tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME, 27232c4746c24728a047a1ef985215edec798bfce1fSivaram Nair dev_name(&pdev->dev), &pdev->dev); 2730e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 2740e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(&pdev->dev, "IRQ is not free.\n"); 2750e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2760e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 277eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan tps_rtc->irq = irq; 278eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan device_set_wakeup_capable(&pdev->dev, 1); 2790e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 28097868b3225b74e9982c70717e3174a13bd9cc765Jingoo Han tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 2810e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu &tps65910_rtc_ops, THIS_MODULE); 2820e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (IS_ERR(tps_rtc->rtc)) { 2830e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = PTR_ERR(tps_rtc->rtc); 2840e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(&pdev->dev, "RTC device register: err %d\n", ret); 2850e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2860e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 2870e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2880e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return 0; 2890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 2900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 2920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Disable tps65910 RTC interrupts. 2930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Sets status flag to free. 2940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 2955a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int tps65910_rtc_remove(struct platform_device *pdev) 2960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 2971430e17844e2cd15bc15f3c21b5349e762f6ba41Kim, Milo tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); 2980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return 0; 3000e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 3010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3020e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#ifdef CONFIG_PM_SLEEP 3030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_suspend(struct device *dev) 3040e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 305eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 3060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 307eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan if (device_may_wakeup(dev)) 308eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan enable_irq_wake(tps_rtc->irq); 309dfaf09ac8555141b7311bb69b456bd96886fd90cLaxman Dewangan return 0; 3100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 3110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_resume(struct device *dev) 3130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 314eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 315eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan 316eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan if (device_may_wakeup(dev)) 317eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan disable_irq_wake(tps_rtc->irq); 318dfaf09ac8555141b7311bb69b456bd96886fd90cLaxman Dewangan return 0; 3190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 320176a9f20d29de594c07faaeb10fecff664c956c6Laxman Dewangan#endif 3210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 322e4ae909b34a0a8d799712146a97b6ae67445a49aJingoo Hanstatic SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend, 323e4ae909b34a0a8d799712146a97b6ae67445a49aJingoo Han tps65910_rtc_resume); 3240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic struct platform_driver tps65910_rtc_driver = { 3260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .probe = tps65910_rtc_probe, 3275a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartman .remove = tps65910_rtc_remove, 3280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .driver = { 3290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .owner = THIS_MODULE, 3300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .name = "tps65910-rtc", 331176a9f20d29de594c07faaeb10fecff664c956c6Laxman Dewangan .pm = &tps65910_rtc_pm_ops, 3320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu }, 3330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 3340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasumodule_platform_driver(tps65910_rtc_driver); 3360e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_ALIAS("platform:rtc-tps65910"); 3370e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); 3380e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_LICENSE("GPL"); 339