1b07682b6SSantosh Shilimkar /* 2ef3b7d0dSBalaji T K * rtc-twl.c -- TWL Real Time Clock interface 3b07682b6SSantosh Shilimkar * 4b07682b6SSantosh Shilimkar * Copyright (C) 2007 MontaVista Software, Inc 5b07682b6SSantosh Shilimkar * Author: Alexandre Rusev <source@mvista.com> 6b07682b6SSantosh Shilimkar * 7b07682b6SSantosh Shilimkar * Based on original TI driver twl4030-rtc.c 8b07682b6SSantosh Shilimkar * Copyright (C) 2006 Texas Instruments, Inc. 9b07682b6SSantosh Shilimkar * 10b07682b6SSantosh Shilimkar * Based on rtc-omap.c 11b07682b6SSantosh Shilimkar * Copyright (C) 2003 MontaVista Software, Inc. 12b07682b6SSantosh Shilimkar * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com> 13b07682b6SSantosh Shilimkar * Copyright (C) 2006 David Brownell 14b07682b6SSantosh Shilimkar * 15b07682b6SSantosh Shilimkar * This program is free software; you can redistribute it and/or 16b07682b6SSantosh Shilimkar * modify it under the terms of the GNU General Public License 17b07682b6SSantosh Shilimkar * as published by the Free Software Foundation; either version 18b07682b6SSantosh Shilimkar * 2 of the License, or (at your option) any later version. 19b07682b6SSantosh Shilimkar */ 20b07682b6SSantosh Shilimkar 21a737e835SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22a737e835SJoe Perches 23b07682b6SSantosh Shilimkar #include <linux/kernel.h> 24b07682b6SSantosh Shilimkar #include <linux/errno.h> 25b07682b6SSantosh Shilimkar #include <linux/init.h> 26b07682b6SSantosh Shilimkar #include <linux/module.h> 27b07682b6SSantosh Shilimkar #include <linux/types.h> 28b07682b6SSantosh Shilimkar #include <linux/rtc.h> 29b07682b6SSantosh Shilimkar #include <linux/bcd.h> 30b07682b6SSantosh Shilimkar #include <linux/platform_device.h> 31b07682b6SSantosh Shilimkar #include <linux/interrupt.h> 32c8a6046eSSachin Kamat #include <linux/of.h> 33b07682b6SSantosh Shilimkar 34b07682b6SSantosh Shilimkar #include <linux/i2c/twl.h> 35b07682b6SSantosh Shilimkar 36e3e7f95bSNicolae Rosia enum twl_class { 37e3e7f95bSNicolae Rosia TWL_4030 = 0, 38e3e7f95bSNicolae Rosia TWL_6030, 39e3e7f95bSNicolae Rosia }; 40b07682b6SSantosh Shilimkar 41b07682b6SSantosh Shilimkar /* 42b07682b6SSantosh Shilimkar * RTC block register offsets (use TWL_MODULE_RTC) 43b07682b6SSantosh Shilimkar */ 44a6b49ffdSBalaji T K enum { 45a6b49ffdSBalaji T K REG_SECONDS_REG = 0, 46a6b49ffdSBalaji T K REG_MINUTES_REG, 47a6b49ffdSBalaji T K REG_HOURS_REG, 48a6b49ffdSBalaji T K REG_DAYS_REG, 49a6b49ffdSBalaji T K REG_MONTHS_REG, 50a6b49ffdSBalaji T K REG_YEARS_REG, 51a6b49ffdSBalaji T K REG_WEEKS_REG, 52b07682b6SSantosh Shilimkar 53a6b49ffdSBalaji T K REG_ALARM_SECONDS_REG, 54a6b49ffdSBalaji T K REG_ALARM_MINUTES_REG, 55a6b49ffdSBalaji T K REG_ALARM_HOURS_REG, 56a6b49ffdSBalaji T K REG_ALARM_DAYS_REG, 57a6b49ffdSBalaji T K REG_ALARM_MONTHS_REG, 58a6b49ffdSBalaji T K REG_ALARM_YEARS_REG, 59b07682b6SSantosh Shilimkar 60a6b49ffdSBalaji T K REG_RTC_CTRL_REG, 61a6b49ffdSBalaji T K REG_RTC_STATUS_REG, 62a6b49ffdSBalaji T K REG_RTC_INTERRUPTS_REG, 63b07682b6SSantosh Shilimkar 64a6b49ffdSBalaji T K REG_RTC_COMP_LSB_REG, 65a6b49ffdSBalaji T K REG_RTC_COMP_MSB_REG, 66a6b49ffdSBalaji T K }; 672e84067bSTobias Klauser static const u8 twl4030_rtc_reg_map[] = { 68a6b49ffdSBalaji T K [REG_SECONDS_REG] = 0x00, 69a6b49ffdSBalaji T K [REG_MINUTES_REG] = 0x01, 70a6b49ffdSBalaji T K [REG_HOURS_REG] = 0x02, 71a6b49ffdSBalaji T K [REG_DAYS_REG] = 0x03, 72a6b49ffdSBalaji T K [REG_MONTHS_REG] = 0x04, 73a6b49ffdSBalaji T K [REG_YEARS_REG] = 0x05, 74a6b49ffdSBalaji T K [REG_WEEKS_REG] = 0x06, 75a6b49ffdSBalaji T K 76a6b49ffdSBalaji T K [REG_ALARM_SECONDS_REG] = 0x07, 77a6b49ffdSBalaji T K [REG_ALARM_MINUTES_REG] = 0x08, 78a6b49ffdSBalaji T K [REG_ALARM_HOURS_REG] = 0x09, 79a6b49ffdSBalaji T K [REG_ALARM_DAYS_REG] = 0x0A, 80a6b49ffdSBalaji T K [REG_ALARM_MONTHS_REG] = 0x0B, 81a6b49ffdSBalaji T K [REG_ALARM_YEARS_REG] = 0x0C, 82a6b49ffdSBalaji T K 83a6b49ffdSBalaji T K [REG_RTC_CTRL_REG] = 0x0D, 84a6b49ffdSBalaji T K [REG_RTC_STATUS_REG] = 0x0E, 85a6b49ffdSBalaji T K [REG_RTC_INTERRUPTS_REG] = 0x0F, 86a6b49ffdSBalaji T K 87a6b49ffdSBalaji T K [REG_RTC_COMP_LSB_REG] = 0x10, 88a6b49ffdSBalaji T K [REG_RTC_COMP_MSB_REG] = 0x11, 89a6b49ffdSBalaji T K }; 902e84067bSTobias Klauser static const u8 twl6030_rtc_reg_map[] = { 91a6b49ffdSBalaji T K [REG_SECONDS_REG] = 0x00, 92a6b49ffdSBalaji T K [REG_MINUTES_REG] = 0x01, 93a6b49ffdSBalaji T K [REG_HOURS_REG] = 0x02, 94a6b49ffdSBalaji T K [REG_DAYS_REG] = 0x03, 95a6b49ffdSBalaji T K [REG_MONTHS_REG] = 0x04, 96a6b49ffdSBalaji T K [REG_YEARS_REG] = 0x05, 97a6b49ffdSBalaji T K [REG_WEEKS_REG] = 0x06, 98a6b49ffdSBalaji T K 99a6b49ffdSBalaji T K [REG_ALARM_SECONDS_REG] = 0x08, 100a6b49ffdSBalaji T K [REG_ALARM_MINUTES_REG] = 0x09, 101a6b49ffdSBalaji T K [REG_ALARM_HOURS_REG] = 0x0A, 102a6b49ffdSBalaji T K [REG_ALARM_DAYS_REG] = 0x0B, 103a6b49ffdSBalaji T K [REG_ALARM_MONTHS_REG] = 0x0C, 104a6b49ffdSBalaji T K [REG_ALARM_YEARS_REG] = 0x0D, 105a6b49ffdSBalaji T K 106a6b49ffdSBalaji T K [REG_RTC_CTRL_REG] = 0x10, 107a6b49ffdSBalaji T K [REG_RTC_STATUS_REG] = 0x11, 108a6b49ffdSBalaji T K [REG_RTC_INTERRUPTS_REG] = 0x12, 109a6b49ffdSBalaji T K 110a6b49ffdSBalaji T K [REG_RTC_COMP_LSB_REG] = 0x13, 111a6b49ffdSBalaji T K [REG_RTC_COMP_MSB_REG] = 0x14, 112a6b49ffdSBalaji T K }; 113b07682b6SSantosh Shilimkar 114b07682b6SSantosh Shilimkar /* RTC_CTRL_REG bitfields */ 115b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 116b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 117b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 118b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 119b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 120b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 121b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 122f3ec434cSKonstantin Shlyakhovoy #define BIT_RTC_CTRL_REG_RTC_V_OPT 0x80 123b07682b6SSantosh Shilimkar 124b07682b6SSantosh Shilimkar /* RTC_STATUS_REG bitfields */ 125b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_RUN_M 0x02 126b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 127b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 128b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 129b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 130b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_ALARM_M 0x40 131b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 132b07682b6SSantosh Shilimkar 133b07682b6SSantosh Shilimkar /* RTC_INTERRUPTS_REG bitfields */ 134b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 135b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 136b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 137b07682b6SSantosh Shilimkar 138b07682b6SSantosh Shilimkar 139b07682b6SSantosh Shilimkar /* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ 140b07682b6SSantosh Shilimkar #define ALL_TIME_REGS 6 141b07682b6SSantosh Shilimkar 142b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/ 143e3e7f95bSNicolae Rosia struct twl_rtc { 144e3e7f95bSNicolae Rosia struct device *dev; 145e3e7f95bSNicolae Rosia struct rtc_device *rtc; 146e3e7f95bSNicolae Rosia u8 *reg_map; 147e3e7f95bSNicolae Rosia /* 148e3e7f95bSNicolae Rosia * Cache the value for timer/alarm interrupts register; this is 149e3e7f95bSNicolae Rosia * only changed by callers holding rtc ops lock (or resume). 150e3e7f95bSNicolae Rosia */ 151e3e7f95bSNicolae Rosia unsigned char rtc_irq_bits; 152e3e7f95bSNicolae Rosia bool wake_enabled; 153e3e7f95bSNicolae Rosia #ifdef CONFIG_PM_SLEEP 154e3e7f95bSNicolae Rosia unsigned char irqstat; 155e3e7f95bSNicolae Rosia #endif 156e3e7f95bSNicolae Rosia enum twl_class class; 157e3e7f95bSNicolae Rosia }; 158b07682b6SSantosh Shilimkar 159b07682b6SSantosh Shilimkar /* 160ef3b7d0dSBalaji T K * Supports 1 byte read from TWL RTC register. 161b07682b6SSantosh Shilimkar */ 162e3e7f95bSNicolae Rosia static int twl_rtc_read_u8(struct twl_rtc *twl_rtc, u8 *data, u8 reg) 163b07682b6SSantosh Shilimkar { 164b07682b6SSantosh Shilimkar int ret; 165b07682b6SSantosh Shilimkar 166e3e7f95bSNicolae Rosia ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (twl_rtc->reg_map[reg])); 167b07682b6SSantosh Shilimkar if (ret < 0) 168a737e835SJoe Perches pr_err("Could not read TWL register %X - error %d\n", reg, ret); 169b07682b6SSantosh Shilimkar return ret; 170b07682b6SSantosh Shilimkar } 171b07682b6SSantosh Shilimkar 172b07682b6SSantosh Shilimkar /* 173ef3b7d0dSBalaji T K * Supports 1 byte write to TWL RTC registers. 174b07682b6SSantosh Shilimkar */ 175e3e7f95bSNicolae Rosia static int twl_rtc_write_u8(struct twl_rtc *twl_rtc, u8 data, u8 reg) 176b07682b6SSantosh Shilimkar { 177b07682b6SSantosh Shilimkar int ret; 178b07682b6SSantosh Shilimkar 179e3e7f95bSNicolae Rosia ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (twl_rtc->reg_map[reg])); 180b07682b6SSantosh Shilimkar if (ret < 0) 181a737e835SJoe Perches pr_err("Could not write TWL register %X - error %d\n", 182a737e835SJoe Perches reg, ret); 183b07682b6SSantosh Shilimkar return ret; 184b07682b6SSantosh Shilimkar } 185b07682b6SSantosh Shilimkar 186b07682b6SSantosh Shilimkar /* 187b07682b6SSantosh Shilimkar * Enable 1/second update and/or alarm interrupts. 188b07682b6SSantosh Shilimkar */ 189e3e7f95bSNicolae Rosia static int set_rtc_irq_bit(struct twl_rtc *twl_rtc, unsigned char bit) 190b07682b6SSantosh Shilimkar { 191b07682b6SSantosh Shilimkar unsigned char val; 192b07682b6SSantosh Shilimkar int ret; 193b07682b6SSantosh Shilimkar 194ce9f6506SVenu Byravarasu /* if the bit is set, return from here */ 195e3e7f95bSNicolae Rosia if (twl_rtc->rtc_irq_bits & bit) 196ce9f6506SVenu Byravarasu return 0; 197ce9f6506SVenu Byravarasu 198e3e7f95bSNicolae Rosia val = twl_rtc->rtc_irq_bits | bit; 199b07682b6SSantosh Shilimkar val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; 200e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, val, REG_RTC_INTERRUPTS_REG); 201b07682b6SSantosh Shilimkar if (ret == 0) 202e3e7f95bSNicolae Rosia twl_rtc->rtc_irq_bits = val; 203b07682b6SSantosh Shilimkar 204b07682b6SSantosh Shilimkar return ret; 205b07682b6SSantosh Shilimkar } 206b07682b6SSantosh Shilimkar 207b07682b6SSantosh Shilimkar /* 208b07682b6SSantosh Shilimkar * Disable update and/or alarm interrupts. 209b07682b6SSantosh Shilimkar */ 210e3e7f95bSNicolae Rosia static int mask_rtc_irq_bit(struct twl_rtc *twl_rtc, unsigned char bit) 211b07682b6SSantosh Shilimkar { 212b07682b6SSantosh Shilimkar unsigned char val; 213b07682b6SSantosh Shilimkar int ret; 214b07682b6SSantosh Shilimkar 215ce9f6506SVenu Byravarasu /* if the bit is clear, return from here */ 216e3e7f95bSNicolae Rosia if (!(twl_rtc->rtc_irq_bits & bit)) 217ce9f6506SVenu Byravarasu return 0; 218ce9f6506SVenu Byravarasu 219e3e7f95bSNicolae Rosia val = twl_rtc->rtc_irq_bits & ~bit; 220e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, val, REG_RTC_INTERRUPTS_REG); 221b07682b6SSantosh Shilimkar if (ret == 0) 222e3e7f95bSNicolae Rosia twl_rtc->rtc_irq_bits = val; 223b07682b6SSantosh Shilimkar 224b07682b6SSantosh Shilimkar return ret; 225b07682b6SSantosh Shilimkar } 226b07682b6SSantosh Shilimkar 227ef3b7d0dSBalaji T K static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 228b07682b6SSantosh Shilimkar { 229ae845894SKevin Hilman struct platform_device *pdev = to_platform_device(dev); 230e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 231ae845894SKevin Hilman int irq = platform_get_irq(pdev, 0); 232b07682b6SSantosh Shilimkar int ret; 233b07682b6SSantosh Shilimkar 234ae845894SKevin Hilman if (enabled) { 235e3e7f95bSNicolae Rosia ret = set_rtc_irq_bit(twl_rtc, 236e3e7f95bSNicolae Rosia BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 237e3e7f95bSNicolae Rosia if (device_can_wakeup(dev) && !twl_rtc->wake_enabled) { 238ae845894SKevin Hilman enable_irq_wake(irq); 239e3e7f95bSNicolae Rosia twl_rtc->wake_enabled = true; 240ae845894SKevin Hilman } 241ae845894SKevin Hilman } else { 242e3e7f95bSNicolae Rosia ret = mask_rtc_irq_bit(twl_rtc, 243e3e7f95bSNicolae Rosia BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 244e3e7f95bSNicolae Rosia if (twl_rtc->wake_enabled) { 245ae845894SKevin Hilman disable_irq_wake(irq); 246e3e7f95bSNicolae Rosia twl_rtc->wake_enabled = false; 247ae845894SKevin Hilman } 248ae845894SKevin Hilman } 249b07682b6SSantosh Shilimkar 250b07682b6SSantosh Shilimkar return ret; 251b07682b6SSantosh Shilimkar } 252b07682b6SSantosh Shilimkar 253b07682b6SSantosh Shilimkar /* 254ef3b7d0dSBalaji T K * Gets current TWL RTC time and date parameters. 255b07682b6SSantosh Shilimkar * 256b07682b6SSantosh Shilimkar * The RTC's time/alarm representation is not what gmtime(3) requires 257b07682b6SSantosh Shilimkar * Linux to use: 258b07682b6SSantosh Shilimkar * 259b07682b6SSantosh Shilimkar * - Months are 1..12 vs Linux 0-11 260b07682b6SSantosh Shilimkar * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 261b07682b6SSantosh Shilimkar */ 262ef3b7d0dSBalaji T K static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) 263b07682b6SSantosh Shilimkar { 264e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 26514591d88SPeter Ujfalusi unsigned char rtc_data[ALL_TIME_REGS]; 266b07682b6SSantosh Shilimkar int ret; 267b07682b6SSantosh Shilimkar u8 save_control; 268f3ec434cSKonstantin Shlyakhovoy u8 rtc_control; 269b07682b6SSantosh Shilimkar 270e3e7f95bSNicolae Rosia ret = twl_rtc_read_u8(twl_rtc, &save_control, REG_RTC_CTRL_REG); 271f3ec434cSKonstantin Shlyakhovoy if (ret < 0) { 272f3ec434cSKonstantin Shlyakhovoy dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret); 273b07682b6SSantosh Shilimkar return ret; 274f3ec434cSKonstantin Shlyakhovoy } 275f3ec434cSKonstantin Shlyakhovoy /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */ 276e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_6030) { 277f3ec434cSKonstantin Shlyakhovoy if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) { 278f3ec434cSKonstantin Shlyakhovoy save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M; 279e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, save_control, 280e3e7f95bSNicolae Rosia REG_RTC_CTRL_REG); 281f3ec434cSKonstantin Shlyakhovoy if (ret < 0) { 282f3ec434cSKonstantin Shlyakhovoy dev_err(dev, "%s clr GET_TIME, error %d\n", 283f3ec434cSKonstantin Shlyakhovoy __func__, ret); 284b07682b6SSantosh Shilimkar return ret; 285f3ec434cSKonstantin Shlyakhovoy } 286f3ec434cSKonstantin Shlyakhovoy } 287f3ec434cSKonstantin Shlyakhovoy } 288f3ec434cSKonstantin Shlyakhovoy 289f3ec434cSKonstantin Shlyakhovoy /* Copy RTC counting registers to static registers or latches */ 290f3ec434cSKonstantin Shlyakhovoy rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M; 291f3ec434cSKonstantin Shlyakhovoy 292f3ec434cSKonstantin Shlyakhovoy /* for twl6030/32 enable read access to static shadowed registers */ 293e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_6030) 294f3ec434cSKonstantin Shlyakhovoy rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT; 295f3ec434cSKonstantin Shlyakhovoy 296e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, rtc_control, REG_RTC_CTRL_REG); 297f3ec434cSKonstantin Shlyakhovoy if (ret < 0) { 298f3ec434cSKonstantin Shlyakhovoy dev_err(dev, "%s: writing CTRL_REG, error %d\n", __func__, ret); 299f3ec434cSKonstantin Shlyakhovoy return ret; 300f3ec434cSKonstantin Shlyakhovoy } 301b07682b6SSantosh Shilimkar 302ef3b7d0dSBalaji T K ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, 303e3e7f95bSNicolae Rosia (twl_rtc->reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); 304b07682b6SSantosh Shilimkar 305b07682b6SSantosh Shilimkar if (ret < 0) { 306f3ec434cSKonstantin Shlyakhovoy dev_err(dev, "%s: reading data, error %d\n", __func__, ret); 307b07682b6SSantosh Shilimkar return ret; 308b07682b6SSantosh Shilimkar } 309b07682b6SSantosh Shilimkar 310f3ec434cSKonstantin Shlyakhovoy /* for twl6030 restore original state of rtc control register */ 311e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_6030) { 312e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG); 313f3ec434cSKonstantin Shlyakhovoy if (ret < 0) { 314f3ec434cSKonstantin Shlyakhovoy dev_err(dev, "%s: restore CTRL_REG, error %d\n", 315f3ec434cSKonstantin Shlyakhovoy __func__, ret); 316f3ec434cSKonstantin Shlyakhovoy return ret; 317f3ec434cSKonstantin Shlyakhovoy } 318f3ec434cSKonstantin Shlyakhovoy } 319f3ec434cSKonstantin Shlyakhovoy 320b07682b6SSantosh Shilimkar tm->tm_sec = bcd2bin(rtc_data[0]); 321b07682b6SSantosh Shilimkar tm->tm_min = bcd2bin(rtc_data[1]); 322b07682b6SSantosh Shilimkar tm->tm_hour = bcd2bin(rtc_data[2]); 323b07682b6SSantosh Shilimkar tm->tm_mday = bcd2bin(rtc_data[3]); 324b07682b6SSantosh Shilimkar tm->tm_mon = bcd2bin(rtc_data[4]) - 1; 325b07682b6SSantosh Shilimkar tm->tm_year = bcd2bin(rtc_data[5]) + 100; 326b07682b6SSantosh Shilimkar 327b07682b6SSantosh Shilimkar return ret; 328b07682b6SSantosh Shilimkar } 329b07682b6SSantosh Shilimkar 330ef3b7d0dSBalaji T K static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) 331b07682b6SSantosh Shilimkar { 332e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 333b07682b6SSantosh Shilimkar unsigned char save_control; 33414591d88SPeter Ujfalusi unsigned char rtc_data[ALL_TIME_REGS]; 335b07682b6SSantosh Shilimkar int ret; 336b07682b6SSantosh Shilimkar 33714591d88SPeter Ujfalusi rtc_data[0] = bin2bcd(tm->tm_sec); 33814591d88SPeter Ujfalusi rtc_data[1] = bin2bcd(tm->tm_min); 33914591d88SPeter Ujfalusi rtc_data[2] = bin2bcd(tm->tm_hour); 34014591d88SPeter Ujfalusi rtc_data[3] = bin2bcd(tm->tm_mday); 34114591d88SPeter Ujfalusi rtc_data[4] = bin2bcd(tm->tm_mon + 1); 34214591d88SPeter Ujfalusi rtc_data[5] = bin2bcd(tm->tm_year - 100); 343b07682b6SSantosh Shilimkar 344b07682b6SSantosh Shilimkar /* Stop RTC while updating the TC registers */ 345e3e7f95bSNicolae Rosia ret = twl_rtc_read_u8(twl_rtc, &save_control, REG_RTC_CTRL_REG); 346b07682b6SSantosh Shilimkar if (ret < 0) 347b07682b6SSantosh Shilimkar goto out; 348b07682b6SSantosh Shilimkar 349b07682b6SSantosh Shilimkar save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; 350e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG); 351b07682b6SSantosh Shilimkar if (ret < 0) 352b07682b6SSantosh Shilimkar goto out; 353b07682b6SSantosh Shilimkar 354b07682b6SSantosh Shilimkar /* update all the time registers in one shot */ 355ef3b7d0dSBalaji T K ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, 356e3e7f95bSNicolae Rosia (twl_rtc->reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); 357b07682b6SSantosh Shilimkar if (ret < 0) { 358b07682b6SSantosh Shilimkar dev_err(dev, "rtc_set_time error %d\n", ret); 359b07682b6SSantosh Shilimkar goto out; 360b07682b6SSantosh Shilimkar } 361b07682b6SSantosh Shilimkar 362b07682b6SSantosh Shilimkar /* Start back RTC */ 363b07682b6SSantosh Shilimkar save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; 364e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, save_control, REG_RTC_CTRL_REG); 365b07682b6SSantosh Shilimkar 366b07682b6SSantosh Shilimkar out: 367b07682b6SSantosh Shilimkar return ret; 368b07682b6SSantosh Shilimkar } 369b07682b6SSantosh Shilimkar 370b07682b6SSantosh Shilimkar /* 371ef3b7d0dSBalaji T K * Gets current TWL RTC alarm time. 372b07682b6SSantosh Shilimkar */ 373ef3b7d0dSBalaji T K static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 374b07682b6SSantosh Shilimkar { 375e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 37614591d88SPeter Ujfalusi unsigned char rtc_data[ALL_TIME_REGS]; 377b07682b6SSantosh Shilimkar int ret; 378b07682b6SSantosh Shilimkar 379ef3b7d0dSBalaji T K ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, 380e3e7f95bSNicolae Rosia twl_rtc->reg_map[REG_ALARM_SECONDS_REG], ALL_TIME_REGS); 381b07682b6SSantosh Shilimkar if (ret < 0) { 382b07682b6SSantosh Shilimkar dev_err(dev, "rtc_read_alarm error %d\n", ret); 383b07682b6SSantosh Shilimkar return ret; 384b07682b6SSantosh Shilimkar } 385b07682b6SSantosh Shilimkar 386b07682b6SSantosh Shilimkar /* some of these fields may be wildcard/"match all" */ 387b07682b6SSantosh Shilimkar alm->time.tm_sec = bcd2bin(rtc_data[0]); 388b07682b6SSantosh Shilimkar alm->time.tm_min = bcd2bin(rtc_data[1]); 389b07682b6SSantosh Shilimkar alm->time.tm_hour = bcd2bin(rtc_data[2]); 390b07682b6SSantosh Shilimkar alm->time.tm_mday = bcd2bin(rtc_data[3]); 391b07682b6SSantosh Shilimkar alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; 392b07682b6SSantosh Shilimkar alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; 393b07682b6SSantosh Shilimkar 394b07682b6SSantosh Shilimkar /* report cached alarm enable state */ 395e3e7f95bSNicolae Rosia if (twl_rtc->rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) 396b07682b6SSantosh Shilimkar alm->enabled = 1; 397b07682b6SSantosh Shilimkar 398b07682b6SSantosh Shilimkar return ret; 399b07682b6SSantosh Shilimkar } 400b07682b6SSantosh Shilimkar 401ef3b7d0dSBalaji T K static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 402b07682b6SSantosh Shilimkar { 403e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 404e3e7f95bSNicolae Rosia 40514591d88SPeter Ujfalusi unsigned char alarm_data[ALL_TIME_REGS]; 406b07682b6SSantosh Shilimkar int ret; 407b07682b6SSantosh Shilimkar 408ef3b7d0dSBalaji T K ret = twl_rtc_alarm_irq_enable(dev, 0); 409b07682b6SSantosh Shilimkar if (ret) 410b07682b6SSantosh Shilimkar goto out; 411b07682b6SSantosh Shilimkar 41214591d88SPeter Ujfalusi alarm_data[0] = bin2bcd(alm->time.tm_sec); 41314591d88SPeter Ujfalusi alarm_data[1] = bin2bcd(alm->time.tm_min); 41414591d88SPeter Ujfalusi alarm_data[2] = bin2bcd(alm->time.tm_hour); 41514591d88SPeter Ujfalusi alarm_data[3] = bin2bcd(alm->time.tm_mday); 41614591d88SPeter Ujfalusi alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); 41714591d88SPeter Ujfalusi alarm_data[5] = bin2bcd(alm->time.tm_year - 100); 418b07682b6SSantosh Shilimkar 419b07682b6SSantosh Shilimkar /* update all the alarm registers in one shot */ 420ef3b7d0dSBalaji T K ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, 421e3e7f95bSNicolae Rosia twl_rtc->reg_map[REG_ALARM_SECONDS_REG], ALL_TIME_REGS); 422b07682b6SSantosh Shilimkar if (ret) { 423b07682b6SSantosh Shilimkar dev_err(dev, "rtc_set_alarm error %d\n", ret); 424b07682b6SSantosh Shilimkar goto out; 425b07682b6SSantosh Shilimkar } 426b07682b6SSantosh Shilimkar 427b07682b6SSantosh Shilimkar if (alm->enabled) 428ef3b7d0dSBalaji T K ret = twl_rtc_alarm_irq_enable(dev, 1); 429b07682b6SSantosh Shilimkar out: 430b07682b6SSantosh Shilimkar return ret; 431b07682b6SSantosh Shilimkar } 432b07682b6SSantosh Shilimkar 433e3e7f95bSNicolae Rosia static irqreturn_t twl_rtc_interrupt(int irq, void *data) 434b07682b6SSantosh Shilimkar { 435e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = data; 4362778ebccSVenu Byravarasu unsigned long events; 437b07682b6SSantosh Shilimkar int ret = IRQ_NONE; 438b07682b6SSantosh Shilimkar int res; 439b07682b6SSantosh Shilimkar u8 rd_reg; 440b07682b6SSantosh Shilimkar 441e3e7f95bSNicolae Rosia res = twl_rtc_read_u8(twl_rtc, &rd_reg, REG_RTC_STATUS_REG); 442b07682b6SSantosh Shilimkar if (res) 443b07682b6SSantosh Shilimkar goto out; 444b07682b6SSantosh Shilimkar /* 445b07682b6SSantosh Shilimkar * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. 446b07682b6SSantosh Shilimkar * only one (ALARM or RTC) interrupt source may be enabled 447b07682b6SSantosh Shilimkar * at time, we also could check our results 448b07682b6SSantosh Shilimkar * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] 449b07682b6SSantosh Shilimkar */ 450b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) 4512778ebccSVenu Byravarasu events = RTC_IRQF | RTC_AF; 452b07682b6SSantosh Shilimkar else 4532778ebccSVenu Byravarasu events = RTC_IRQF | RTC_PF; 454b07682b6SSantosh Shilimkar 455e3e7f95bSNicolae Rosia res = twl_rtc_write_u8(twl_rtc, BIT_RTC_STATUS_REG_ALARM_M, 456b07682b6SSantosh Shilimkar REG_RTC_STATUS_REG); 457b07682b6SSantosh Shilimkar if (res) 458b07682b6SSantosh Shilimkar goto out; 459b07682b6SSantosh Shilimkar 460e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_4030) { 461b07682b6SSantosh Shilimkar /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 462b07682b6SSantosh Shilimkar * needs 2 reads to clear the interrupt. One read is done in 463ef3b7d0dSBalaji T K * do_twl_pwrirq(). Doing the second read, to clear 464b07682b6SSantosh Shilimkar * the bit. 465b07682b6SSantosh Shilimkar * 466b07682b6SSantosh Shilimkar * FIXME the reason PWR_ISR1 needs an extra read is that 467b07682b6SSantosh Shilimkar * RTC_IF retriggered until we cleared REG_ALARM_M above. 468b07682b6SSantosh Shilimkar * But re-reading like this is a bad hack; by doing so we 469b07682b6SSantosh Shilimkar * risk wrongly clearing status for some other IRQ (losing 470b07682b6SSantosh Shilimkar * the interrupt). Be smarter about handling RTC_UF ... 471b07682b6SSantosh Shilimkar */ 472fc7b92fcSBalaji T K res = twl_i2c_read_u8(TWL4030_MODULE_INT, 473b07682b6SSantosh Shilimkar &rd_reg, TWL4030_INT_PWR_ISR1); 474b07682b6SSantosh Shilimkar if (res) 475b07682b6SSantosh Shilimkar goto out; 476a6b49ffdSBalaji T K } 477b07682b6SSantosh Shilimkar 478b07682b6SSantosh Shilimkar /* Notify RTC core on event */ 479e3e7f95bSNicolae Rosia rtc_update_irq(twl_rtc->rtc, 1, events); 480b07682b6SSantosh Shilimkar 481b07682b6SSantosh Shilimkar ret = IRQ_HANDLED; 482b07682b6SSantosh Shilimkar out: 483b07682b6SSantosh Shilimkar return ret; 484b07682b6SSantosh Shilimkar } 485b07682b6SSantosh Shilimkar 48634c7b3acSJulia Lawall static const struct rtc_class_ops twl_rtc_ops = { 487ef3b7d0dSBalaji T K .read_time = twl_rtc_read_time, 488ef3b7d0dSBalaji T K .set_time = twl_rtc_set_time, 489ef3b7d0dSBalaji T K .read_alarm = twl_rtc_read_alarm, 490ef3b7d0dSBalaji T K .set_alarm = twl_rtc_set_alarm, 491ef3b7d0dSBalaji T K .alarm_irq_enable = twl_rtc_alarm_irq_enable, 492b07682b6SSantosh Shilimkar }; 493b07682b6SSantosh Shilimkar 494b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/ 495b07682b6SSantosh Shilimkar 4965a167f45SGreg Kroah-Hartman static int twl_rtc_probe(struct platform_device *pdev) 497b07682b6SSantosh Shilimkar { 498e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc; 4991c02cbfeSNicolae Rosia struct device_node *np = pdev->dev.of_node; 5007e72c686STodd Poynor int ret = -EINVAL; 501b07682b6SSantosh Shilimkar int irq = platform_get_irq(pdev, 0); 502b07682b6SSantosh Shilimkar u8 rd_reg; 503b07682b6SSantosh Shilimkar 5041c02cbfeSNicolae Rosia if (!np) { 5051c02cbfeSNicolae Rosia dev_err(&pdev->dev, "no DT info\n"); 5061c02cbfeSNicolae Rosia return -EINVAL; 5071c02cbfeSNicolae Rosia } 5081c02cbfeSNicolae Rosia 509b07682b6SSantosh Shilimkar if (irq <= 0) 510f53eeb85SJingoo Han return ret; 511b07682b6SSantosh Shilimkar 512e3e7f95bSNicolae Rosia twl_rtc = devm_kzalloc(&pdev->dev, sizeof(*twl_rtc), GFP_KERNEL); 513e3e7f95bSNicolae Rosia if (!twl_rtc) 514e3e7f95bSNicolae Rosia return -ENOMEM; 515d3869ff6SPeter Ujfalusi 516e3e7f95bSNicolae Rosia if (twl_class_is_4030()) { 517e3e7f95bSNicolae Rosia twl_rtc->class = TWL_4030; 518e3e7f95bSNicolae Rosia twl_rtc->reg_map = (u8 *)twl4030_rtc_reg_map; 519e3e7f95bSNicolae Rosia } else if (twl_class_is_6030()) { 520e3e7f95bSNicolae Rosia twl_rtc->class = TWL_6030; 521e3e7f95bSNicolae Rosia twl_rtc->reg_map = (u8 *)twl6030_rtc_reg_map; 522e3e7f95bSNicolae Rosia } else { 523e3e7f95bSNicolae Rosia dev_err(&pdev->dev, "TWL Class not supported.\n"); 524e3e7f95bSNicolae Rosia return -EINVAL; 525e3e7f95bSNicolae Rosia } 526e3e7f95bSNicolae Rosia 527e3e7f95bSNicolae Rosia ret = twl_rtc_read_u8(twl_rtc, &rd_reg, REG_RTC_STATUS_REG); 528b07682b6SSantosh Shilimkar if (ret < 0) 529f53eeb85SJingoo Han return ret; 530b07682b6SSantosh Shilimkar 531b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) 532b07682b6SSantosh Shilimkar dev_warn(&pdev->dev, "Power up reset detected.\n"); 533b07682b6SSantosh Shilimkar 534b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) 535b07682b6SSantosh Shilimkar dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); 536b07682b6SSantosh Shilimkar 537b07682b6SSantosh Shilimkar /* Clear RTC Power up reset and pending alarm interrupts */ 538e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, rd_reg, REG_RTC_STATUS_REG); 539b07682b6SSantosh Shilimkar if (ret < 0) 540f53eeb85SJingoo Han return ret; 541b07682b6SSantosh Shilimkar 542e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_6030) { 543a6b49ffdSBalaji T K twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, 544a6b49ffdSBalaji T K REG_INT_MSK_LINE_A); 545a6b49ffdSBalaji T K twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, 546a6b49ffdSBalaji T K REG_INT_MSK_STS_A); 547a6b49ffdSBalaji T K } 548a6b49ffdSBalaji T K 549f7439bcbSVenu Byravarasu dev_info(&pdev->dev, "Enabling TWL-RTC\n"); 550e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, BIT_RTC_CTRL_REG_STOP_RTC_M, 551e3e7f95bSNicolae Rosia REG_RTC_CTRL_REG); 552b07682b6SSantosh Shilimkar if (ret < 0) 553f53eeb85SJingoo Han return ret; 554b07682b6SSantosh Shilimkar 5558dcebaa9SKevin Hilman /* ensure interrupts are disabled, bootloaders can be strange */ 556e3e7f95bSNicolae Rosia ret = twl_rtc_write_u8(twl_rtc, 0, REG_RTC_INTERRUPTS_REG); 5578dcebaa9SKevin Hilman if (ret < 0) 5588dcebaa9SKevin Hilman dev_warn(&pdev->dev, "unable to disable interrupt\n"); 5598dcebaa9SKevin Hilman 560b07682b6SSantosh Shilimkar /* init cached IRQ enable bits */ 561e3e7f95bSNicolae Rosia ret = twl_rtc_read_u8(twl_rtc, &twl_rtc->rtc_irq_bits, 562e3e7f95bSNicolae Rosia REG_RTC_INTERRUPTS_REG); 563b07682b6SSantosh Shilimkar if (ret < 0) 564f53eeb85SJingoo Han return ret; 565b07682b6SSantosh Shilimkar 566e3e7f95bSNicolae Rosia platform_set_drvdata(pdev, twl_rtc); 567b99b94b5SGrygorii Strashko device_init_wakeup(&pdev->dev, 1); 568b99b94b5SGrygorii Strashko 569e3e7f95bSNicolae Rosia twl_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 570f53eeb85SJingoo Han &twl_rtc_ops, THIS_MODULE); 571e3e7f95bSNicolae Rosia if (IS_ERR(twl_rtc->rtc)) { 5727e72c686STodd Poynor dev_err(&pdev->dev, "can't register RTC device, err %ld\n", 573e3e7f95bSNicolae Rosia PTR_ERR(twl_rtc->rtc)); 574e3e7f95bSNicolae Rosia return PTR_ERR(twl_rtc->rtc); 5757e72c686STodd Poynor } 5767e72c686STodd Poynor 577f53eeb85SJingoo Han ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 578f53eeb85SJingoo Han twl_rtc_interrupt, 5796b91bf1aSKevin Hilman IRQF_TRIGGER_RISING | IRQF_ONESHOT, 580e3e7f95bSNicolae Rosia dev_name(&twl_rtc->rtc->dev), twl_rtc); 5817e72c686STodd Poynor if (ret < 0) { 5827e72c686STodd Poynor dev_err(&pdev->dev, "IRQ is not free.\n"); 583f53eeb85SJingoo Han return ret; 5847e72c686STodd Poynor } 5857e72c686STodd Poynor 5867e72c686STodd Poynor return 0; 587b07682b6SSantosh Shilimkar } 588b07682b6SSantosh Shilimkar 589b07682b6SSantosh Shilimkar /* 590ef3b7d0dSBalaji T K * Disable all TWL RTC module interrupts. 591b07682b6SSantosh Shilimkar * Sets status flag to free. 592b07682b6SSantosh Shilimkar */ 5935a167f45SGreg Kroah-Hartman static int twl_rtc_remove(struct platform_device *pdev) 594b07682b6SSantosh Shilimkar { 595e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = platform_get_drvdata(pdev); 596e3e7f95bSNicolae Rosia 597b07682b6SSantosh Shilimkar /* leave rtc running, but disable irqs */ 598e3e7f95bSNicolae Rosia mask_rtc_irq_bit(twl_rtc, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 599e3e7f95bSNicolae Rosia mask_rtc_irq_bit(twl_rtc, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 600e3e7f95bSNicolae Rosia if (twl_rtc->class == TWL_6030) { 601a6b49ffdSBalaji T K twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, 602a6b49ffdSBalaji T K REG_INT_MSK_LINE_A); 603a6b49ffdSBalaji T K twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, 604a6b49ffdSBalaji T K REG_INT_MSK_STS_A); 605a6b49ffdSBalaji T K } 606a6b49ffdSBalaji T K 607b07682b6SSantosh Shilimkar return 0; 608b07682b6SSantosh Shilimkar } 609b07682b6SSantosh Shilimkar 610ef3b7d0dSBalaji T K static void twl_rtc_shutdown(struct platform_device *pdev) 611b07682b6SSantosh Shilimkar { 612e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = platform_get_drvdata(pdev); 613e3e7f95bSNicolae Rosia 614b07682b6SSantosh Shilimkar /* mask timer interrupts, but leave alarm interrupts on to enable 615b07682b6SSantosh Shilimkar power-on when alarm is triggered */ 616e3e7f95bSNicolae Rosia mask_rtc_irq_bit(twl_rtc, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 617b07682b6SSantosh Shilimkar } 618b07682b6SSantosh Shilimkar 619b9d8c460SJingoo Han #ifdef CONFIG_PM_SLEEP 620b9d8c460SJingoo Han static int twl_rtc_suspend(struct device *dev) 621b07682b6SSantosh Shilimkar { 622e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 623b07682b6SSantosh Shilimkar 624e3e7f95bSNicolae Rosia twl_rtc->irqstat = twl_rtc->rtc_irq_bits; 625e3e7f95bSNicolae Rosia 626e3e7f95bSNicolae Rosia mask_rtc_irq_bit(twl_rtc, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 627b07682b6SSantosh Shilimkar return 0; 628b07682b6SSantosh Shilimkar } 629b07682b6SSantosh Shilimkar 630b9d8c460SJingoo Han static int twl_rtc_resume(struct device *dev) 631b07682b6SSantosh Shilimkar { 632e3e7f95bSNicolae Rosia struct twl_rtc *twl_rtc = dev_get_drvdata(dev); 633e3e7f95bSNicolae Rosia 634e3e7f95bSNicolae Rosia set_rtc_irq_bit(twl_rtc, twl_rtc->irqstat); 635b07682b6SSantosh Shilimkar return 0; 636b07682b6SSantosh Shilimkar } 637b07682b6SSantosh Shilimkar #endif 638b07682b6SSantosh Shilimkar 639b9d8c460SJingoo Han static SIMPLE_DEV_PM_OPS(twl_rtc_pm_ops, twl_rtc_suspend, twl_rtc_resume); 640b9d8c460SJingoo Han 641948170f8SBenoit Cousson static const struct of_device_id twl_rtc_of_match[] = { 642948170f8SBenoit Cousson {.compatible = "ti,twl4030-rtc", }, 643948170f8SBenoit Cousson { }, 644948170f8SBenoit Cousson }; 645948170f8SBenoit Cousson MODULE_DEVICE_TABLE(of, twl_rtc_of_match); 646b07682b6SSantosh Shilimkar 647b07682b6SSantosh Shilimkar static struct platform_driver twl4030rtc_driver = { 648ef3b7d0dSBalaji T K .probe = twl_rtc_probe, 6495a167f45SGreg Kroah-Hartman .remove = twl_rtc_remove, 650ef3b7d0dSBalaji T K .shutdown = twl_rtc_shutdown, 651b07682b6SSantosh Shilimkar .driver = { 652ef3b7d0dSBalaji T K .name = "twl_rtc", 653b9d8c460SJingoo Han .pm = &twl_rtc_pm_ops, 6541c02cbfeSNicolae Rosia .of_match_table = twl_rtc_of_match, 655b07682b6SSantosh Shilimkar }, 656b07682b6SSantosh Shilimkar }; 657b07682b6SSantosh Shilimkar 6585ee67484SPeter Ujfalusi module_platform_driver(twl4030rtc_driver); 659b07682b6SSantosh Shilimkar 660b07682b6SSantosh Shilimkar MODULE_AUTHOR("Texas Instruments, MontaVista Software"); 661b07682b6SSantosh Shilimkar MODULE_LICENSE("GPL"); 662