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 21b07682b6SSantosh Shilimkar #include <linux/kernel.h> 22b07682b6SSantosh Shilimkar #include <linux/errno.h> 23b07682b6SSantosh Shilimkar #include <linux/init.h> 24b07682b6SSantosh Shilimkar #include <linux/module.h> 25b07682b6SSantosh Shilimkar #include <linux/types.h> 26b07682b6SSantosh Shilimkar #include <linux/rtc.h> 27b07682b6SSantosh Shilimkar #include <linux/bcd.h> 28b07682b6SSantosh Shilimkar #include <linux/platform_device.h> 29b07682b6SSantosh Shilimkar #include <linux/interrupt.h> 30b07682b6SSantosh Shilimkar 31b07682b6SSantosh Shilimkar #include <linux/i2c/twl.h> 32b07682b6SSantosh Shilimkar 33b07682b6SSantosh Shilimkar 34b07682b6SSantosh Shilimkar /* 35b07682b6SSantosh Shilimkar * RTC block register offsets (use TWL_MODULE_RTC) 36b07682b6SSantosh Shilimkar */ 37b07682b6SSantosh Shilimkar #define REG_SECONDS_REG 0x00 38b07682b6SSantosh Shilimkar #define REG_MINUTES_REG 0x01 39b07682b6SSantosh Shilimkar #define REG_HOURS_REG 0x02 40b07682b6SSantosh Shilimkar #define REG_DAYS_REG 0x03 41b07682b6SSantosh Shilimkar #define REG_MONTHS_REG 0x04 42b07682b6SSantosh Shilimkar #define REG_YEARS_REG 0x05 43b07682b6SSantosh Shilimkar #define REG_WEEKS_REG 0x06 44b07682b6SSantosh Shilimkar 45b07682b6SSantosh Shilimkar #define REG_ALARM_SECONDS_REG 0x07 46b07682b6SSantosh Shilimkar #define REG_ALARM_MINUTES_REG 0x08 47b07682b6SSantosh Shilimkar #define REG_ALARM_HOURS_REG 0x09 48b07682b6SSantosh Shilimkar #define REG_ALARM_DAYS_REG 0x0A 49b07682b6SSantosh Shilimkar #define REG_ALARM_MONTHS_REG 0x0B 50b07682b6SSantosh Shilimkar #define REG_ALARM_YEARS_REG 0x0C 51b07682b6SSantosh Shilimkar 52b07682b6SSantosh Shilimkar #define REG_RTC_CTRL_REG 0x0D 53b07682b6SSantosh Shilimkar #define REG_RTC_STATUS_REG 0x0E 54b07682b6SSantosh Shilimkar #define REG_RTC_INTERRUPTS_REG 0x0F 55b07682b6SSantosh Shilimkar 56b07682b6SSantosh Shilimkar #define REG_RTC_COMP_LSB_REG 0x10 57b07682b6SSantosh Shilimkar #define REG_RTC_COMP_MSB_REG 0x11 58b07682b6SSantosh Shilimkar 59b07682b6SSantosh Shilimkar /* RTC_CTRL_REG bitfields */ 60b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 61b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 62b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 63b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 64b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 65b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 66b07682b6SSantosh Shilimkar #define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 67b07682b6SSantosh Shilimkar 68b07682b6SSantosh Shilimkar /* RTC_STATUS_REG bitfields */ 69b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_RUN_M 0x02 70b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 71b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 72b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 73b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 74b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_ALARM_M 0x40 75b07682b6SSantosh Shilimkar #define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 76b07682b6SSantosh Shilimkar 77b07682b6SSantosh Shilimkar /* RTC_INTERRUPTS_REG bitfields */ 78b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 79b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 80b07682b6SSantosh Shilimkar #define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 81b07682b6SSantosh Shilimkar 82b07682b6SSantosh Shilimkar 83b07682b6SSantosh Shilimkar /* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ 84b07682b6SSantosh Shilimkar #define ALL_TIME_REGS 6 85b07682b6SSantosh Shilimkar 86b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/ 87b07682b6SSantosh Shilimkar 88b07682b6SSantosh Shilimkar /* 89ef3b7d0dSBalaji T K * Supports 1 byte read from TWL RTC register. 90b07682b6SSantosh Shilimkar */ 91ef3b7d0dSBalaji T K static int twl_rtc_read_u8(u8 *data, u8 reg) 92b07682b6SSantosh Shilimkar { 93b07682b6SSantosh Shilimkar int ret; 94b07682b6SSantosh Shilimkar 95ef3b7d0dSBalaji T K ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, reg); 96b07682b6SSantosh Shilimkar if (ret < 0) 97ef3b7d0dSBalaji T K pr_err("twl_rtc: Could not read TWL" 98b07682b6SSantosh Shilimkar "register %X - error %d\n", reg, ret); 99b07682b6SSantosh Shilimkar return ret; 100b07682b6SSantosh Shilimkar } 101b07682b6SSantosh Shilimkar 102b07682b6SSantosh Shilimkar /* 103ef3b7d0dSBalaji T K * Supports 1 byte write to TWL RTC registers. 104b07682b6SSantosh Shilimkar */ 105ef3b7d0dSBalaji T K static int twl_rtc_write_u8(u8 data, u8 reg) 106b07682b6SSantosh Shilimkar { 107b07682b6SSantosh Shilimkar int ret; 108b07682b6SSantosh Shilimkar 109ef3b7d0dSBalaji T K ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, reg); 110b07682b6SSantosh Shilimkar if (ret < 0) 111ef3b7d0dSBalaji T K pr_err("twl_rtc: Could not write TWL" 112b07682b6SSantosh Shilimkar "register %X - error %d\n", reg, ret); 113b07682b6SSantosh Shilimkar return ret; 114b07682b6SSantosh Shilimkar } 115b07682b6SSantosh Shilimkar 116b07682b6SSantosh Shilimkar /* 117b07682b6SSantosh Shilimkar * Cache the value for timer/alarm interrupts register; this is 118b07682b6SSantosh Shilimkar * only changed by callers holding rtc ops lock (or resume). 119b07682b6SSantosh Shilimkar */ 120b07682b6SSantosh Shilimkar static unsigned char rtc_irq_bits; 121b07682b6SSantosh Shilimkar 122b07682b6SSantosh Shilimkar /* 123b07682b6SSantosh Shilimkar * Enable 1/second update and/or alarm interrupts. 124b07682b6SSantosh Shilimkar */ 125b07682b6SSantosh Shilimkar static int set_rtc_irq_bit(unsigned char bit) 126b07682b6SSantosh Shilimkar { 127b07682b6SSantosh Shilimkar unsigned char val; 128b07682b6SSantosh Shilimkar int ret; 129b07682b6SSantosh Shilimkar 130b07682b6SSantosh Shilimkar val = rtc_irq_bits | bit; 131b07682b6SSantosh Shilimkar val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; 132ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); 133b07682b6SSantosh Shilimkar if (ret == 0) 134b07682b6SSantosh Shilimkar rtc_irq_bits = val; 135b07682b6SSantosh Shilimkar 136b07682b6SSantosh Shilimkar return ret; 137b07682b6SSantosh Shilimkar } 138b07682b6SSantosh Shilimkar 139b07682b6SSantosh Shilimkar /* 140b07682b6SSantosh Shilimkar * Disable update and/or alarm interrupts. 141b07682b6SSantosh Shilimkar */ 142b07682b6SSantosh Shilimkar static int mask_rtc_irq_bit(unsigned char bit) 143b07682b6SSantosh Shilimkar { 144b07682b6SSantosh Shilimkar unsigned char val; 145b07682b6SSantosh Shilimkar int ret; 146b07682b6SSantosh Shilimkar 147b07682b6SSantosh Shilimkar val = rtc_irq_bits & ~bit; 148ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); 149b07682b6SSantosh Shilimkar if (ret == 0) 150b07682b6SSantosh Shilimkar rtc_irq_bits = val; 151b07682b6SSantosh Shilimkar 152b07682b6SSantosh Shilimkar return ret; 153b07682b6SSantosh Shilimkar } 154b07682b6SSantosh Shilimkar 155ef3b7d0dSBalaji T K static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 156b07682b6SSantosh Shilimkar { 157b07682b6SSantosh Shilimkar int ret; 158b07682b6SSantosh Shilimkar 159b07682b6SSantosh Shilimkar if (enabled) 160b07682b6SSantosh Shilimkar ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 161b07682b6SSantosh Shilimkar else 162b07682b6SSantosh Shilimkar ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 163b07682b6SSantosh Shilimkar 164b07682b6SSantosh Shilimkar return ret; 165b07682b6SSantosh Shilimkar } 166b07682b6SSantosh Shilimkar 167ef3b7d0dSBalaji T K static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) 168b07682b6SSantosh Shilimkar { 169b07682b6SSantosh Shilimkar int ret; 170b07682b6SSantosh Shilimkar 171b07682b6SSantosh Shilimkar if (enabled) 172b07682b6SSantosh Shilimkar ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 173b07682b6SSantosh Shilimkar else 174b07682b6SSantosh Shilimkar ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 175b07682b6SSantosh Shilimkar 176b07682b6SSantosh Shilimkar return ret; 177b07682b6SSantosh Shilimkar } 178b07682b6SSantosh Shilimkar 179b07682b6SSantosh Shilimkar /* 180ef3b7d0dSBalaji T K * Gets current TWL RTC time and date parameters. 181b07682b6SSantosh Shilimkar * 182b07682b6SSantosh Shilimkar * The RTC's time/alarm representation is not what gmtime(3) requires 183b07682b6SSantosh Shilimkar * Linux to use: 184b07682b6SSantosh Shilimkar * 185b07682b6SSantosh Shilimkar * - Months are 1..12 vs Linux 0-11 186b07682b6SSantosh Shilimkar * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 187b07682b6SSantosh Shilimkar */ 188ef3b7d0dSBalaji T K static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) 189b07682b6SSantosh Shilimkar { 190b07682b6SSantosh Shilimkar unsigned char rtc_data[ALL_TIME_REGS + 1]; 191b07682b6SSantosh Shilimkar int ret; 192b07682b6SSantosh Shilimkar u8 save_control; 193b07682b6SSantosh Shilimkar 194ef3b7d0dSBalaji T K ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); 195b07682b6SSantosh Shilimkar if (ret < 0) 196b07682b6SSantosh Shilimkar return ret; 197b07682b6SSantosh Shilimkar 198b07682b6SSantosh Shilimkar save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; 199b07682b6SSantosh Shilimkar 200ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); 201b07682b6SSantosh Shilimkar if (ret < 0) 202b07682b6SSantosh Shilimkar return ret; 203b07682b6SSantosh Shilimkar 204ef3b7d0dSBalaji T K ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, 205b07682b6SSantosh Shilimkar REG_SECONDS_REG, ALL_TIME_REGS); 206b07682b6SSantosh Shilimkar 207b07682b6SSantosh Shilimkar if (ret < 0) { 208b07682b6SSantosh Shilimkar dev_err(dev, "rtc_read_time error %d\n", ret); 209b07682b6SSantosh Shilimkar return ret; 210b07682b6SSantosh Shilimkar } 211b07682b6SSantosh Shilimkar 212b07682b6SSantosh Shilimkar tm->tm_sec = bcd2bin(rtc_data[0]); 213b07682b6SSantosh Shilimkar tm->tm_min = bcd2bin(rtc_data[1]); 214b07682b6SSantosh Shilimkar tm->tm_hour = bcd2bin(rtc_data[2]); 215b07682b6SSantosh Shilimkar tm->tm_mday = bcd2bin(rtc_data[3]); 216b07682b6SSantosh Shilimkar tm->tm_mon = bcd2bin(rtc_data[4]) - 1; 217b07682b6SSantosh Shilimkar tm->tm_year = bcd2bin(rtc_data[5]) + 100; 218b07682b6SSantosh Shilimkar 219b07682b6SSantosh Shilimkar return ret; 220b07682b6SSantosh Shilimkar } 221b07682b6SSantosh Shilimkar 222ef3b7d0dSBalaji T K static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) 223b07682b6SSantosh Shilimkar { 224b07682b6SSantosh Shilimkar unsigned char save_control; 225b07682b6SSantosh Shilimkar unsigned char rtc_data[ALL_TIME_REGS + 1]; 226b07682b6SSantosh Shilimkar int ret; 227b07682b6SSantosh Shilimkar 228b07682b6SSantosh Shilimkar rtc_data[1] = bin2bcd(tm->tm_sec); 229b07682b6SSantosh Shilimkar rtc_data[2] = bin2bcd(tm->tm_min); 230b07682b6SSantosh Shilimkar rtc_data[3] = bin2bcd(tm->tm_hour); 231b07682b6SSantosh Shilimkar rtc_data[4] = bin2bcd(tm->tm_mday); 232b07682b6SSantosh Shilimkar rtc_data[5] = bin2bcd(tm->tm_mon + 1); 233b07682b6SSantosh Shilimkar rtc_data[6] = bin2bcd(tm->tm_year - 100); 234b07682b6SSantosh Shilimkar 235b07682b6SSantosh Shilimkar /* Stop RTC while updating the TC registers */ 236ef3b7d0dSBalaji T K ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); 237b07682b6SSantosh Shilimkar if (ret < 0) 238b07682b6SSantosh Shilimkar goto out; 239b07682b6SSantosh Shilimkar 240b07682b6SSantosh Shilimkar save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; 241ef3b7d0dSBalaji T K twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); 242b07682b6SSantosh Shilimkar if (ret < 0) 243b07682b6SSantosh Shilimkar goto out; 244b07682b6SSantosh Shilimkar 245b07682b6SSantosh Shilimkar /* update all the time registers in one shot */ 246ef3b7d0dSBalaji T K ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, 247b07682b6SSantosh Shilimkar REG_SECONDS_REG, ALL_TIME_REGS); 248b07682b6SSantosh Shilimkar if (ret < 0) { 249b07682b6SSantosh Shilimkar dev_err(dev, "rtc_set_time error %d\n", ret); 250b07682b6SSantosh Shilimkar goto out; 251b07682b6SSantosh Shilimkar } 252b07682b6SSantosh Shilimkar 253b07682b6SSantosh Shilimkar /* Start back RTC */ 254b07682b6SSantosh Shilimkar save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; 255ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); 256b07682b6SSantosh Shilimkar 257b07682b6SSantosh Shilimkar out: 258b07682b6SSantosh Shilimkar return ret; 259b07682b6SSantosh Shilimkar } 260b07682b6SSantosh Shilimkar 261b07682b6SSantosh Shilimkar /* 262ef3b7d0dSBalaji T K * Gets current TWL RTC alarm time. 263b07682b6SSantosh Shilimkar */ 264ef3b7d0dSBalaji T K static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 265b07682b6SSantosh Shilimkar { 266b07682b6SSantosh Shilimkar unsigned char rtc_data[ALL_TIME_REGS + 1]; 267b07682b6SSantosh Shilimkar int ret; 268b07682b6SSantosh Shilimkar 269ef3b7d0dSBalaji T K ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, 270b07682b6SSantosh Shilimkar REG_ALARM_SECONDS_REG, ALL_TIME_REGS); 271b07682b6SSantosh Shilimkar if (ret < 0) { 272b07682b6SSantosh Shilimkar dev_err(dev, "rtc_read_alarm error %d\n", ret); 273b07682b6SSantosh Shilimkar return ret; 274b07682b6SSantosh Shilimkar } 275b07682b6SSantosh Shilimkar 276b07682b6SSantosh Shilimkar /* some of these fields may be wildcard/"match all" */ 277b07682b6SSantosh Shilimkar alm->time.tm_sec = bcd2bin(rtc_data[0]); 278b07682b6SSantosh Shilimkar alm->time.tm_min = bcd2bin(rtc_data[1]); 279b07682b6SSantosh Shilimkar alm->time.tm_hour = bcd2bin(rtc_data[2]); 280b07682b6SSantosh Shilimkar alm->time.tm_mday = bcd2bin(rtc_data[3]); 281b07682b6SSantosh Shilimkar alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; 282b07682b6SSantosh Shilimkar alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; 283b07682b6SSantosh Shilimkar 284b07682b6SSantosh Shilimkar /* report cached alarm enable state */ 285b07682b6SSantosh Shilimkar if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) 286b07682b6SSantosh Shilimkar alm->enabled = 1; 287b07682b6SSantosh Shilimkar 288b07682b6SSantosh Shilimkar return ret; 289b07682b6SSantosh Shilimkar } 290b07682b6SSantosh Shilimkar 291ef3b7d0dSBalaji T K static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 292b07682b6SSantosh Shilimkar { 293b07682b6SSantosh Shilimkar unsigned char alarm_data[ALL_TIME_REGS + 1]; 294b07682b6SSantosh Shilimkar int ret; 295b07682b6SSantosh Shilimkar 296ef3b7d0dSBalaji T K ret = twl_rtc_alarm_irq_enable(dev, 0); 297b07682b6SSantosh Shilimkar if (ret) 298b07682b6SSantosh Shilimkar goto out; 299b07682b6SSantosh Shilimkar 300b07682b6SSantosh Shilimkar alarm_data[1] = bin2bcd(alm->time.tm_sec); 301b07682b6SSantosh Shilimkar alarm_data[2] = bin2bcd(alm->time.tm_min); 302b07682b6SSantosh Shilimkar alarm_data[3] = bin2bcd(alm->time.tm_hour); 303b07682b6SSantosh Shilimkar alarm_data[4] = bin2bcd(alm->time.tm_mday); 304b07682b6SSantosh Shilimkar alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); 305b07682b6SSantosh Shilimkar alarm_data[6] = bin2bcd(alm->time.tm_year - 100); 306b07682b6SSantosh Shilimkar 307b07682b6SSantosh Shilimkar /* update all the alarm registers in one shot */ 308ef3b7d0dSBalaji T K ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, 309b07682b6SSantosh Shilimkar REG_ALARM_SECONDS_REG, ALL_TIME_REGS); 310b07682b6SSantosh Shilimkar if (ret) { 311b07682b6SSantosh Shilimkar dev_err(dev, "rtc_set_alarm error %d\n", ret); 312b07682b6SSantosh Shilimkar goto out; 313b07682b6SSantosh Shilimkar } 314b07682b6SSantosh Shilimkar 315b07682b6SSantosh Shilimkar if (alm->enabled) 316ef3b7d0dSBalaji T K ret = twl_rtc_alarm_irq_enable(dev, 1); 317b07682b6SSantosh Shilimkar out: 318b07682b6SSantosh Shilimkar return ret; 319b07682b6SSantosh Shilimkar } 320b07682b6SSantosh Shilimkar 321ef3b7d0dSBalaji T K static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) 322b07682b6SSantosh Shilimkar { 323b07682b6SSantosh Shilimkar unsigned long events = 0; 324b07682b6SSantosh Shilimkar int ret = IRQ_NONE; 325b07682b6SSantosh Shilimkar int res; 326b07682b6SSantosh Shilimkar u8 rd_reg; 327b07682b6SSantosh Shilimkar 328b07682b6SSantosh Shilimkar #ifdef CONFIG_LOCKDEP 329b07682b6SSantosh Shilimkar /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which 330b07682b6SSantosh Shilimkar * we don't want and can't tolerate. Although it might be 331b07682b6SSantosh Shilimkar * friendlier not to borrow this thread context... 332b07682b6SSantosh Shilimkar */ 333b07682b6SSantosh Shilimkar local_irq_enable(); 334b07682b6SSantosh Shilimkar #endif 335b07682b6SSantosh Shilimkar 336ef3b7d0dSBalaji T K res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); 337b07682b6SSantosh Shilimkar if (res) 338b07682b6SSantosh Shilimkar goto out; 339b07682b6SSantosh Shilimkar /* 340b07682b6SSantosh Shilimkar * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. 341b07682b6SSantosh Shilimkar * only one (ALARM or RTC) interrupt source may be enabled 342b07682b6SSantosh Shilimkar * at time, we also could check our results 343b07682b6SSantosh Shilimkar * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] 344b07682b6SSantosh Shilimkar */ 345b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) 346b07682b6SSantosh Shilimkar events |= RTC_IRQF | RTC_AF; 347b07682b6SSantosh Shilimkar else 348b07682b6SSantosh Shilimkar events |= RTC_IRQF | RTC_UF; 349b07682b6SSantosh Shilimkar 350ef3b7d0dSBalaji T K res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, 351b07682b6SSantosh Shilimkar REG_RTC_STATUS_REG); 352b07682b6SSantosh Shilimkar if (res) 353b07682b6SSantosh Shilimkar goto out; 354b07682b6SSantosh Shilimkar 355b07682b6SSantosh Shilimkar /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 356b07682b6SSantosh Shilimkar * needs 2 reads to clear the interrupt. One read is done in 357ef3b7d0dSBalaji T K * do_twl_pwrirq(). Doing the second read, to clear 358b07682b6SSantosh Shilimkar * the bit. 359b07682b6SSantosh Shilimkar * 360b07682b6SSantosh Shilimkar * FIXME the reason PWR_ISR1 needs an extra read is that 361b07682b6SSantosh Shilimkar * RTC_IF retriggered until we cleared REG_ALARM_M above. 362b07682b6SSantosh Shilimkar * But re-reading like this is a bad hack; by doing so we 363b07682b6SSantosh Shilimkar * risk wrongly clearing status for some other IRQ (losing 364b07682b6SSantosh Shilimkar * the interrupt). Be smarter about handling RTC_UF ... 365b07682b6SSantosh Shilimkar */ 366fc7b92fcSBalaji T K res = twl_i2c_read_u8(TWL4030_MODULE_INT, 367b07682b6SSantosh Shilimkar &rd_reg, TWL4030_INT_PWR_ISR1); 368b07682b6SSantosh Shilimkar if (res) 369b07682b6SSantosh Shilimkar goto out; 370b07682b6SSantosh Shilimkar 371b07682b6SSantosh Shilimkar /* Notify RTC core on event */ 372b07682b6SSantosh Shilimkar rtc_update_irq(rtc, 1, events); 373b07682b6SSantosh Shilimkar 374b07682b6SSantosh Shilimkar ret = IRQ_HANDLED; 375b07682b6SSantosh Shilimkar out: 376b07682b6SSantosh Shilimkar return ret; 377b07682b6SSantosh Shilimkar } 378b07682b6SSantosh Shilimkar 379ef3b7d0dSBalaji T K static struct rtc_class_ops twl_rtc_ops = { 380ef3b7d0dSBalaji T K .read_time = twl_rtc_read_time, 381ef3b7d0dSBalaji T K .set_time = twl_rtc_set_time, 382ef3b7d0dSBalaji T K .read_alarm = twl_rtc_read_alarm, 383ef3b7d0dSBalaji T K .set_alarm = twl_rtc_set_alarm, 384ef3b7d0dSBalaji T K .alarm_irq_enable = twl_rtc_alarm_irq_enable, 385ef3b7d0dSBalaji T K .update_irq_enable = twl_rtc_update_irq_enable, 386b07682b6SSantosh Shilimkar }; 387b07682b6SSantosh Shilimkar 388b07682b6SSantosh Shilimkar /*----------------------------------------------------------------------*/ 389b07682b6SSantosh Shilimkar 390ef3b7d0dSBalaji T K static int __devinit twl_rtc_probe(struct platform_device *pdev) 391b07682b6SSantosh Shilimkar { 392b07682b6SSantosh Shilimkar struct rtc_device *rtc; 393b07682b6SSantosh Shilimkar int ret = 0; 394b07682b6SSantosh Shilimkar int irq = platform_get_irq(pdev, 0); 395b07682b6SSantosh Shilimkar u8 rd_reg; 396b07682b6SSantosh Shilimkar 397b07682b6SSantosh Shilimkar if (irq <= 0) 398b07682b6SSantosh Shilimkar return -EINVAL; 399b07682b6SSantosh Shilimkar 400b07682b6SSantosh Shilimkar rtc = rtc_device_register(pdev->name, 401ef3b7d0dSBalaji T K &pdev->dev, &twl_rtc_ops, THIS_MODULE); 402b07682b6SSantosh Shilimkar if (IS_ERR(rtc)) { 403b07682b6SSantosh Shilimkar ret = PTR_ERR(rtc); 404b07682b6SSantosh Shilimkar dev_err(&pdev->dev, "can't register RTC device, err %ld\n", 405b07682b6SSantosh Shilimkar PTR_ERR(rtc)); 406b07682b6SSantosh Shilimkar goto out0; 407b07682b6SSantosh Shilimkar 408b07682b6SSantosh Shilimkar } 409b07682b6SSantosh Shilimkar 410b07682b6SSantosh Shilimkar platform_set_drvdata(pdev, rtc); 411b07682b6SSantosh Shilimkar 412ef3b7d0dSBalaji T K ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); 413b07682b6SSantosh Shilimkar if (ret < 0) 414b07682b6SSantosh Shilimkar goto out1; 415b07682b6SSantosh Shilimkar 416b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) 417b07682b6SSantosh Shilimkar dev_warn(&pdev->dev, "Power up reset detected.\n"); 418b07682b6SSantosh Shilimkar 419b07682b6SSantosh Shilimkar if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) 420b07682b6SSantosh Shilimkar dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); 421b07682b6SSantosh Shilimkar 422b07682b6SSantosh Shilimkar /* Clear RTC Power up reset and pending alarm interrupts */ 423ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); 424b07682b6SSantosh Shilimkar if (ret < 0) 425b07682b6SSantosh Shilimkar goto out1; 426b07682b6SSantosh Shilimkar 427ef3b7d0dSBalaji T K ret = request_irq(irq, twl_rtc_interrupt, 428b07682b6SSantosh Shilimkar IRQF_TRIGGER_RISING, 429b07682b6SSantosh Shilimkar dev_name(&rtc->dev), rtc); 430b07682b6SSantosh Shilimkar if (ret < 0) { 431b07682b6SSantosh Shilimkar dev_err(&pdev->dev, "IRQ is not free.\n"); 432b07682b6SSantosh Shilimkar goto out1; 433b07682b6SSantosh Shilimkar } 434b07682b6SSantosh Shilimkar 435b07682b6SSantosh Shilimkar /* Check RTC module status, Enable if it is off */ 436ef3b7d0dSBalaji T K ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); 437b07682b6SSantosh Shilimkar if (ret < 0) 438b07682b6SSantosh Shilimkar goto out2; 439b07682b6SSantosh Shilimkar 440b07682b6SSantosh Shilimkar if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { 441ef3b7d0dSBalaji T K dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); 442b07682b6SSantosh Shilimkar rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; 443ef3b7d0dSBalaji T K ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); 444b07682b6SSantosh Shilimkar if (ret < 0) 445b07682b6SSantosh Shilimkar goto out2; 446b07682b6SSantosh Shilimkar } 447b07682b6SSantosh Shilimkar 448b07682b6SSantosh Shilimkar /* init cached IRQ enable bits */ 449ef3b7d0dSBalaji T K ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); 450b07682b6SSantosh Shilimkar if (ret < 0) 451b07682b6SSantosh Shilimkar goto out2; 452b07682b6SSantosh Shilimkar 453b07682b6SSantosh Shilimkar return ret; 454b07682b6SSantosh Shilimkar 455b07682b6SSantosh Shilimkar out2: 456b07682b6SSantosh Shilimkar free_irq(irq, rtc); 457b07682b6SSantosh Shilimkar out1: 458b07682b6SSantosh Shilimkar rtc_device_unregister(rtc); 459b07682b6SSantosh Shilimkar out0: 460b07682b6SSantosh Shilimkar return ret; 461b07682b6SSantosh Shilimkar } 462b07682b6SSantosh Shilimkar 463b07682b6SSantosh Shilimkar /* 464ef3b7d0dSBalaji T K * Disable all TWL RTC module interrupts. 465b07682b6SSantosh Shilimkar * Sets status flag to free. 466b07682b6SSantosh Shilimkar */ 467ef3b7d0dSBalaji T K static int __devexit twl_rtc_remove(struct platform_device *pdev) 468b07682b6SSantosh Shilimkar { 469b07682b6SSantosh Shilimkar /* leave rtc running, but disable irqs */ 470b07682b6SSantosh Shilimkar struct rtc_device *rtc = platform_get_drvdata(pdev); 471b07682b6SSantosh Shilimkar int irq = platform_get_irq(pdev, 0); 472b07682b6SSantosh Shilimkar 473b07682b6SSantosh Shilimkar mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); 474b07682b6SSantosh Shilimkar mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 475b07682b6SSantosh Shilimkar 476b07682b6SSantosh Shilimkar free_irq(irq, rtc); 477b07682b6SSantosh Shilimkar 478b07682b6SSantosh Shilimkar rtc_device_unregister(rtc); 479b07682b6SSantosh Shilimkar platform_set_drvdata(pdev, NULL); 480b07682b6SSantosh Shilimkar return 0; 481b07682b6SSantosh Shilimkar } 482b07682b6SSantosh Shilimkar 483ef3b7d0dSBalaji T K static void twl_rtc_shutdown(struct platform_device *pdev) 484b07682b6SSantosh Shilimkar { 485b07682b6SSantosh Shilimkar /* mask timer interrupts, but leave alarm interrupts on to enable 486b07682b6SSantosh Shilimkar power-on when alarm is triggered */ 487b07682b6SSantosh Shilimkar mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 488b07682b6SSantosh Shilimkar } 489b07682b6SSantosh Shilimkar 490b07682b6SSantosh Shilimkar #ifdef CONFIG_PM 491b07682b6SSantosh Shilimkar 492b07682b6SSantosh Shilimkar static unsigned char irqstat; 493b07682b6SSantosh Shilimkar 494ef3b7d0dSBalaji T K static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) 495b07682b6SSantosh Shilimkar { 496b07682b6SSantosh Shilimkar irqstat = rtc_irq_bits; 497b07682b6SSantosh Shilimkar 498b07682b6SSantosh Shilimkar mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); 499b07682b6SSantosh Shilimkar return 0; 500b07682b6SSantosh Shilimkar } 501b07682b6SSantosh Shilimkar 502ef3b7d0dSBalaji T K static int twl_rtc_resume(struct platform_device *pdev) 503b07682b6SSantosh Shilimkar { 504b07682b6SSantosh Shilimkar set_rtc_irq_bit(irqstat); 505b07682b6SSantosh Shilimkar return 0; 506b07682b6SSantosh Shilimkar } 507b07682b6SSantosh Shilimkar 508b07682b6SSantosh Shilimkar #else 509ef3b7d0dSBalaji T K #define twl_rtc_suspend NULL 510ef3b7d0dSBalaji T K #define twl_rtc_resume NULL 511b07682b6SSantosh Shilimkar #endif 512b07682b6SSantosh Shilimkar 513ef3b7d0dSBalaji T K MODULE_ALIAS("platform:twl_rtc"); 514b07682b6SSantosh Shilimkar 515b07682b6SSantosh Shilimkar static struct platform_driver twl4030rtc_driver = { 516ef3b7d0dSBalaji T K .probe = twl_rtc_probe, 517ef3b7d0dSBalaji T K .remove = __devexit_p(twl_rtc_remove), 518ef3b7d0dSBalaji T K .shutdown = twl_rtc_shutdown, 519ef3b7d0dSBalaji T K .suspend = twl_rtc_suspend, 520ef3b7d0dSBalaji T K .resume = twl_rtc_resume, 521b07682b6SSantosh Shilimkar .driver = { 522b07682b6SSantosh Shilimkar .owner = THIS_MODULE, 523ef3b7d0dSBalaji T K .name = "twl_rtc", 524b07682b6SSantosh Shilimkar }, 525b07682b6SSantosh Shilimkar }; 526b07682b6SSantosh Shilimkar 527ef3b7d0dSBalaji T K static int __init twl_rtc_init(void) 528b07682b6SSantosh Shilimkar { 529b07682b6SSantosh Shilimkar return platform_driver_register(&twl4030rtc_driver); 530b07682b6SSantosh Shilimkar } 531ef3b7d0dSBalaji T K module_init(twl_rtc_init); 532b07682b6SSantosh Shilimkar 533ef3b7d0dSBalaji T K static void __exit twl_rtc_exit(void) 534b07682b6SSantosh Shilimkar { 535b07682b6SSantosh Shilimkar platform_driver_unregister(&twl4030rtc_driver); 536b07682b6SSantosh Shilimkar } 537ef3b7d0dSBalaji T K module_exit(twl_rtc_exit); 538b07682b6SSantosh Shilimkar 539b07682b6SSantosh Shilimkar MODULE_AUTHOR("Texas Instruments, MontaVista Software"); 540b07682b6SSantosh Shilimkar MODULE_LICENSE("GPL"); 541