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