rtc-tps65910.c revision eb5eba4ef72248b976465906cfed5fca2e9d8831
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 /* To store the list of enabled interrupts */ 320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 irqstat; 330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* Total number of RTC registers needed to set time*/ 360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) 370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u8 val = 0; 420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (enabled) 440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu val = TPS65910_RTC_INTERRUPTS_IT_ALARM; 450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val); 470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Gets current tps65910 RTC time and date parameters. 510e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 520e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * The RTC's time/alarm representation is not what gmtime(3) requires 530e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Linux to use: 540e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * 550e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * - Months are 1..12 vs Linux 0-11 560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm) 590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char rtc_data[NUM_TIME_REGS]; 610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 630e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 640e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Copy RTC counting registers to static registers or latches */ 650e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 660e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME); 670e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret); 690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 710e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 720e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data, 730e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 740e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 750e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "reading from RTC failed with err:%d\n", ret); 760e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 770e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 780e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 790e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_sec = bcd2bin(rtc_data[0]); 800e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_min = bcd2bin(rtc_data[1]); 810e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_hour = bcd2bin(rtc_data[2]); 820e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_mday = bcd2bin(rtc_data[3]); 830e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_mon = bcd2bin(rtc_data[4]) - 1; 840e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tm->tm_year = bcd2bin(rtc_data[5]) + 100; 850e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 860e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 870e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 880e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm) 900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char rtc_data[NUM_TIME_REGS]; 920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 950e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[0] = bin2bcd(tm->tm_sec); 960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[1] = bin2bcd(tm->tm_min); 970e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[2] = bin2bcd(tm->tm_hour); 980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[3] = bin2bcd(tm->tm_mday); 990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[4] = bin2bcd(tm->tm_mon + 1); 1000e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_data[5] = bin2bcd(tm->tm_year - 100); 1010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1020e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Stop RTC while updating the RTC time registers */ 1030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 1040e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_STOP_RTC, 0); 1050e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC stop failed with err:%d\n", ret); 1070e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1080e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1090e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* update all the time registers in one shot */ 1110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data, 1120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 1130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_set_time error %d\n", ret); 1150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1170e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1180e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Start back RTC */ 1190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, 1200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu TPS65910_RTC_CTRL_STOP_RTC, 1); 1210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 1220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "RTC start failed with err:%d\n", ret); 1230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 1280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Gets current tps65910 RTC alarm time. 1290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 1300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 1310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char alarm_data[NUM_TIME_REGS]; 1330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 int_val; 1340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, 1380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu NUM_TIME_REGS); 1390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) { 1400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_read_alarm error %d\n", ret); 1410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_sec = bcd2bin(alarm_data[0]); 1450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_min = bcd2bin(alarm_data[1]); 1460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_hour = bcd2bin(alarm_data[2]); 1470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_mday = bcd2bin(alarm_data[3]); 1480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; 1490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; 1500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1510e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val); 1520e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 1530e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1540e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1550e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM) 1560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alm->enabled = 1; 1570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 1620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1630e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned char alarm_data[NUM_TIME_REGS]; 1640e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1650e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1660e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1670e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = tps65910_rtc_alarm_irq_enable(dev, 0); 1680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 1690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1710e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[0] = bin2bcd(alm->time.tm_sec); 1720e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[1] = bin2bcd(alm->time.tm_min); 1730e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[2] = bin2bcd(alm->time.tm_hour); 1740e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[3] = bin2bcd(alm->time.tm_mday); 1750e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); 1760e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data[5] = bin2bcd(alm->time.tm_year - 100); 1770e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1780e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* update all the alarm registers in one shot */ 1790e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS, 1800e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu alarm_data, NUM_TIME_REGS); 1810e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) { 1820e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_err(dev, "rtc_set_alarm error %d\n", ret); 1830e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1840e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 1850e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1860e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (alm->enabled) 1870e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = tps65910_rtc_alarm_irq_enable(dev, 1); 1880e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 1900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 1910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 1920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) 1930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 1940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct device *dev = rtc; 1950e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu unsigned long events = 0; 1960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 1970e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 1980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 1990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 rtc_reg; 2000e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg); 2020e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 2030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_NONE; 2040e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2050e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (rtc_reg & TPS65910_RTC_STATUS_ALARM) 2060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu events = RTC_IRQF | RTC_AF; 2070e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2080e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg); 2090e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret) 2100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_NONE; 2110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Notify RTC core on event */ 2130e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_update_irq(tps_rtc->rtc, 1, events); 2140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return IRQ_HANDLED; 2160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 2170e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2180e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic const struct rtc_class_ops tps65910_rtc_ops = { 2190e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .read_time = tps65910_rtc_read_time, 2200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .set_time = tps65910_rtc_set_time, 2210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .read_alarm = tps65910_rtc_read_alarm, 2220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .set_alarm = tps65910_rtc_set_alarm, 2230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, 2240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 2250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2265a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int tps65910_rtc_probe(struct platform_device *pdev) 2270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 2280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps65910 = NULL; 2290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910_rtc *tps_rtc = NULL; 2300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 2310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int irq; 2320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u32 rtc_reg; 2330e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2340e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps65910 = dev_get_drvdata(pdev->dev.parent); 2350e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2360e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc), 2370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu GFP_KERNEL); 2380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (!tps_rtc) 2390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return -ENOMEM; 2400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Clear pending interrupts */ 2420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg); 2430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg); 2470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); 25118c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo 25218c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo /* Enable RTC digital power domain */ 25318c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, 25418c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); 25518c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo if (ret < 0) 25618c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo return ret; 25718c701a9dbe91768e1629f1aece9d50543b3abfaKim, Milo 2580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; 2590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); 2600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 2610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 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); 2670e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 2680e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu } 2690e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2700e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 2710e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, 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 2800e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, 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 platform_set_drvdata(pdev, tps_rtc); 2890e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2900e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return 0; 2910e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 2920e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 2930e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu/* 2940e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Disable tps65910 RTC interrupts. 2950e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu * Sets status flag to free. 2960e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu */ 2975a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartmanstatic int tps65910_rtc_remove(struct platform_device *pdev) 2980e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 2990e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* leave rtc running, but disable irqs */ 3001430e17844e2cd15bc15f3c21b5349e762f6ba41Kim, Milo struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev); 3010e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3021430e17844e2cd15bc15f3c21b5349e762f6ba41Kim, Milo tps65910_rtc_alarm_irq_enable(&pdev->dev, 0); 3030e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3041430e17844e2cd15bc15f3c21b5349e762f6ba41Kim, Milo rtc_device_unregister(tps_rtc->rtc); 3050e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return 0; 3060e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 3070e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3080e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#ifdef CONFIG_PM_SLEEP 3090e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3100e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_suspend(struct device *dev) 3110e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 3120e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 313eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 3140e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu u8 alarm = TPS65910_RTC_INTERRUPTS_IT_ALARM; 3150e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu int ret; 3160e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 317eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan if (device_may_wakeup(dev)) 318eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan enable_irq_wake(tps_rtc->irq); 319eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan 3200e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Store current list of enabled interrupts*/ 3210e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, 3220e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu &tps->rtc->irqstat); 3230e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu if (ret < 0) 3240e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return ret; 3250e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3260e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Enable RTC ALARM interrupt only */ 3270e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, alarm); 3280e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 3290e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3300e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic int tps65910_rtc_resume(struct device *dev) 3310e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu{ 3320e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu struct tps65910 *tps = dev_get_drvdata(dev->parent); 333eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); 334eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan 335eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan if (device_may_wakeup(dev)) 336eb5eba4ef72248b976465906cfed5fca2e9d8831Laxman Dewangan disable_irq_wake(tps_rtc->irq); 3370e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3380e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu /* Restore list of enabled interrupts before suspend */ 3390e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, 3400e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu tps->rtc->irqstat); 3410e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu} 3420e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3430e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic const struct dev_pm_ops tps65910_rtc_pm_ops = { 3440e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .suspend = tps65910_rtc_suspend, 3450e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .resume = tps65910_rtc_resume, 3460e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 3470e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3480e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#define DEV_PM_OPS (&tps65910_rtc_pm_ops) 3490e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#else 3500e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#define DEV_PM_OPS NULL 3510e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu#endif 3520e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3530e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasustatic struct platform_driver tps65910_rtc_driver = { 3540e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .probe = tps65910_rtc_probe, 3555a167f4543e45d45c5672a5cd6cb8ba5ddf4f3eaGreg Kroah-Hartman .remove = tps65910_rtc_remove, 3560e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .driver = { 3570e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .owner = THIS_MODULE, 3580e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .name = "tps65910-rtc", 3590e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu .pm = DEV_PM_OPS, 3600e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu }, 3610e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu}; 3620e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasu 3630e783980b84e7253ba98552d092d1f45ed262d66Venu Byravarasumodule_platform_driver(tps65910_rtc_driver); 3640e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_ALIAS("platform:rtc-tps65910"); 3650e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); 3660e783980b84e7253ba98552d092d1f45ed262d66Venu ByravarasuMODULE_LICENSE("GPL"); 367