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