rtc-rc5t583.c (8138B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock 4 * 5 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 6 * Author: Venu Byravarasu <vbyravarasu@nvidia.com> 7 */ 8 9#include <linux/kernel.h> 10#include <linux/errno.h> 11#include <linux/init.h> 12#include <linux/module.h> 13#include <linux/types.h> 14#include <linux/rtc.h> 15#include <linux/bcd.h> 16#include <linux/platform_device.h> 17#include <linux/interrupt.h> 18#include <linux/mfd/rc5t583.h> 19 20struct rc5t583_rtc { 21 struct rtc_device *rtc; 22 /* To store the list of enabled interrupts, during system suspend */ 23 u32 irqen; 24}; 25 26/* Total number of RTC registers needed to set time*/ 27#define NUM_TIME_REGS (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1) 28 29/* Total number of RTC registers needed to set Y-Alarm*/ 30#define NUM_YAL_REGS (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1) 31 32/* Set Y-Alarm interrupt */ 33#define SET_YAL BIT(5) 34 35/* Get Y-Alarm interrupt status*/ 36#define GET_YAL_STATUS BIT(3) 37 38static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 39{ 40 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 41 u8 val; 42 43 /* Set Y-Alarm, based on 'enabled' */ 44 val = enabled ? SET_YAL : 0; 45 46 return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL, 47 val); 48} 49 50/* 51 * Gets current rc5t583 RTC time and date parameters. 52 * 53 * The RTC's time/alarm representation is not what gmtime(3) requires 54 * Linux to use: 55 * 56 * - Months are 1..12 vs Linux 0-11 57 * - Years are 0..99 vs Linux 1900..N (we assume 21st century) 58 */ 59static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm) 60{ 61 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 62 u8 rtc_data[NUM_TIME_REGS]; 63 int ret; 64 65 ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, 66 NUM_TIME_REGS); 67 if (ret < 0) { 68 dev_err(dev, "RTC read time failed with err:%d\n", ret); 69 return ret; 70 } 71 72 tm->tm_sec = bcd2bin(rtc_data[0]); 73 tm->tm_min = bcd2bin(rtc_data[1]); 74 tm->tm_hour = bcd2bin(rtc_data[2]); 75 tm->tm_wday = bcd2bin(rtc_data[3]); 76 tm->tm_mday = bcd2bin(rtc_data[4]); 77 tm->tm_mon = bcd2bin(rtc_data[5]) - 1; 78 tm->tm_year = bcd2bin(rtc_data[6]) + 100; 79 80 return ret; 81} 82 83static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm) 84{ 85 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 86 unsigned char rtc_data[NUM_TIME_REGS]; 87 int ret; 88 89 rtc_data[0] = bin2bcd(tm->tm_sec); 90 rtc_data[1] = bin2bcd(tm->tm_min); 91 rtc_data[2] = bin2bcd(tm->tm_hour); 92 rtc_data[3] = bin2bcd(tm->tm_wday); 93 rtc_data[4] = bin2bcd(tm->tm_mday); 94 rtc_data[5] = bin2bcd(tm->tm_mon + 1); 95 rtc_data[6] = bin2bcd(tm->tm_year - 100); 96 97 ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, 98 NUM_TIME_REGS); 99 if (ret < 0) { 100 dev_err(dev, "RTC set time failed with error %d\n", ret); 101 return ret; 102 } 103 104 return ret; 105} 106 107static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 108{ 109 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 110 unsigned char alarm_data[NUM_YAL_REGS]; 111 u32 interrupt_enable; 112 int ret; 113 114 ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, 115 NUM_YAL_REGS); 116 if (ret < 0) { 117 dev_err(dev, "rtc_read_alarm error %d\n", ret); 118 return ret; 119 } 120 121 alm->time.tm_sec = 0; 122 alm->time.tm_min = bcd2bin(alarm_data[0]); 123 alm->time.tm_hour = bcd2bin(alarm_data[1]); 124 alm->time.tm_mday = bcd2bin(alarm_data[2]); 125 alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1; 126 alm->time.tm_year = bcd2bin(alarm_data[4]) + 100; 127 128 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable); 129 if (ret < 0) 130 return ret; 131 132 /* check if YALE is set */ 133 if (interrupt_enable & SET_YAL) 134 alm->enabled = 1; 135 136 return ret; 137} 138 139static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 140{ 141 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 142 unsigned char alarm_data[NUM_YAL_REGS]; 143 int ret; 144 145 ret = rc5t583_rtc_alarm_irq_enable(dev, 0); 146 if (ret) 147 return ret; 148 149 alarm_data[0] = bin2bcd(alm->time.tm_min); 150 alarm_data[1] = bin2bcd(alm->time.tm_hour); 151 alarm_data[2] = bin2bcd(alm->time.tm_mday); 152 alarm_data[3] = bin2bcd(alm->time.tm_mon + 1); 153 alarm_data[4] = bin2bcd(alm->time.tm_year - 100); 154 155 ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, 156 NUM_YAL_REGS); 157 if (ret) { 158 dev_err(dev, "rtc_set_alarm error %d\n", ret); 159 return ret; 160 } 161 162 if (alm->enabled) 163 ret = rc5t583_rtc_alarm_irq_enable(dev, 1); 164 165 return ret; 166} 167 168static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc) 169{ 170 struct device *dev = rtc; 171 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 172 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 173 unsigned long events = 0; 174 int ret; 175 u32 rtc_reg; 176 177 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg); 178 if (ret < 0) 179 return IRQ_NONE; 180 181 if (rtc_reg & GET_YAL_STATUS) { 182 events = RTC_IRQF | RTC_AF; 183 /* clear pending Y-alarm interrupt bit */ 184 rtc_reg &= ~GET_YAL_STATUS; 185 } 186 187 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg); 188 if (ret) 189 return IRQ_NONE; 190 191 /* Notify RTC core on event */ 192 rtc_update_irq(rc5t583_rtc->rtc, 1, events); 193 194 return IRQ_HANDLED; 195} 196 197static const struct rtc_class_ops rc5t583_rtc_ops = { 198 .read_time = rc5t583_rtc_read_time, 199 .set_time = rc5t583_rtc_set_time, 200 .read_alarm = rc5t583_rtc_read_alarm, 201 .set_alarm = rc5t583_rtc_set_alarm, 202 .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable, 203}; 204 205static int rc5t583_rtc_probe(struct platform_device *pdev) 206{ 207 struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); 208 struct rc5t583_rtc *ricoh_rtc; 209 struct rc5t583_platform_data *pmic_plat_data; 210 int ret; 211 int irq; 212 213 ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc), 214 GFP_KERNEL); 215 if (!ricoh_rtc) 216 return -ENOMEM; 217 218 platform_set_drvdata(pdev, ricoh_rtc); 219 220 /* Clear pending interrupts */ 221 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0); 222 if (ret < 0) 223 return ret; 224 225 /* clear RTC Adjust register */ 226 ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0); 227 if (ret < 0) { 228 dev_err(&pdev->dev, "unable to program rtc_adjust reg\n"); 229 return -EBUSY; 230 } 231 232 pmic_plat_data = dev_get_platdata(rc5t583->dev); 233 irq = pmic_plat_data->irq_base; 234 if (irq <= 0) { 235 dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", 236 irq); 237 return ret; 238 } 239 240 irq += RC5T583_IRQ_YALE; 241 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 242 rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW, 243 "rtc-rc5t583", &pdev->dev); 244 if (ret < 0) { 245 dev_err(&pdev->dev, "IRQ is not free.\n"); 246 return ret; 247 } 248 device_init_wakeup(&pdev->dev, 1); 249 250 ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 251 &rc5t583_rtc_ops, THIS_MODULE); 252 if (IS_ERR(ricoh_rtc->rtc)) { 253 ret = PTR_ERR(ricoh_rtc->rtc); 254 dev_err(&pdev->dev, "RTC device register: err %d\n", ret); 255 return ret; 256 } 257 258 return 0; 259} 260 261/* 262 * Disable rc5t583 RTC interrupts. 263 * Sets status flag to free. 264 */ 265static int rc5t583_rtc_remove(struct platform_device *pdev) 266{ 267 struct rc5t583_rtc *rc5t583_rtc = platform_get_drvdata(pdev); 268 269 rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0); 270 return 0; 271} 272 273#ifdef CONFIG_PM_SLEEP 274static int rc5t583_rtc_suspend(struct device *dev) 275{ 276 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 277 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 278 int ret; 279 280 /* Store current list of enabled interrupts*/ 281 ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, 282 &rc5t583_rtc->irqen); 283 return ret; 284} 285 286static int rc5t583_rtc_resume(struct device *dev) 287{ 288 struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); 289 struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); 290 291 /* Restore list of enabled interrupts before suspend */ 292 return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1, 293 rc5t583_rtc->irqen); 294} 295#endif 296 297static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend, 298 rc5t583_rtc_resume); 299 300static struct platform_driver rc5t583_rtc_driver = { 301 .probe = rc5t583_rtc_probe, 302 .remove = rc5t583_rtc_remove, 303 .driver = { 304 .name = "rtc-rc5t583", 305 .pm = &rc5t583_rtc_pm_ops, 306 }, 307}; 308 309module_platform_driver(rc5t583_rtc_driver); 310MODULE_ALIAS("platform:rtc-rc5t583"); 311MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); 312MODULE_LICENSE("GPL v2");