rtc-as3722.c (6727B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * rtc-as3722.c - Real Time Clock driver for ams AS3722 PMICs 4 * 5 * Copyright (C) 2013 ams AG 6 * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. 7 * 8 * Author: Florian Lobmaier <florian.lobmaier@ams.com> 9 * Author: Laxman Dewangan <ldewangan@nvidia.com> 10 */ 11 12#include <linux/bcd.h> 13#include <linux/completion.h> 14#include <linux/delay.h> 15#include <linux/interrupt.h> 16#include <linux/ioctl.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/mfd/as3722.h> 20#include <linux/platform_device.h> 21#include <linux/rtc.h> 22#include <linux/time.h> 23 24#define AS3722_RTC_START_YEAR 2000 25struct as3722_rtc { 26 struct rtc_device *rtc; 27 struct device *dev; 28 struct as3722 *as3722; 29 int alarm_irq; 30 bool irq_enable; 31}; 32 33static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm) 34{ 35 rbuff[0] = bin2bcd(tm->tm_sec); 36 rbuff[1] = bin2bcd(tm->tm_min); 37 rbuff[2] = bin2bcd(tm->tm_hour); 38 rbuff[3] = bin2bcd(tm->tm_mday); 39 rbuff[4] = bin2bcd(tm->tm_mon + 1); 40 rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900)); 41} 42 43static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm) 44{ 45 tm->tm_sec = bcd2bin(rbuff[0] & 0x7F); 46 tm->tm_min = bcd2bin(rbuff[1] & 0x7F); 47 tm->tm_hour = bcd2bin(rbuff[2] & 0x3F); 48 tm->tm_mday = bcd2bin(rbuff[3] & 0x3F); 49 tm->tm_mon = bcd2bin(rbuff[4] & 0x1F) - 1; 50 tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F); 51 return; 52} 53 54static int as3722_rtc_read_time(struct device *dev, struct rtc_time *tm) 55{ 56 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 57 struct as3722 *as3722 = as3722_rtc->as3722; 58 u8 as_time_array[6]; 59 int ret; 60 61 ret = as3722_block_read(as3722, AS3722_RTC_SECOND_REG, 62 6, as_time_array); 63 if (ret < 0) { 64 dev_err(dev, "RTC_SECOND reg block read failed %d\n", ret); 65 return ret; 66 } 67 as3722_reg_to_time(as_time_array, tm); 68 return 0; 69} 70 71static int as3722_rtc_set_time(struct device *dev, struct rtc_time *tm) 72{ 73 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 74 struct as3722 *as3722 = as3722_rtc->as3722; 75 u8 as_time_array[6]; 76 int ret; 77 78 if (tm->tm_year < (AS3722_RTC_START_YEAR - 1900)) 79 return -EINVAL; 80 81 as3722_time_to_reg(as_time_array, tm); 82 ret = as3722_block_write(as3722, AS3722_RTC_SECOND_REG, 6, 83 as_time_array); 84 if (ret < 0) 85 dev_err(dev, "RTC_SECOND reg block write failed %d\n", ret); 86 return ret; 87} 88 89static int as3722_rtc_alarm_irq_enable(struct device *dev, 90 unsigned int enabled) 91{ 92 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 93 94 if (enabled && !as3722_rtc->irq_enable) { 95 enable_irq(as3722_rtc->alarm_irq); 96 as3722_rtc->irq_enable = true; 97 } else if (!enabled && as3722_rtc->irq_enable) { 98 disable_irq(as3722_rtc->alarm_irq); 99 as3722_rtc->irq_enable = false; 100 } 101 return 0; 102} 103 104static int as3722_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 105{ 106 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 107 struct as3722 *as3722 = as3722_rtc->as3722; 108 u8 as_time_array[6]; 109 int ret; 110 111 ret = as3722_block_read(as3722, AS3722_RTC_ALARM_SECOND_REG, 6, 112 as_time_array); 113 if (ret < 0) { 114 dev_err(dev, "RTC_ALARM_SECOND block read failed %d\n", ret); 115 return ret; 116 } 117 118 as3722_reg_to_time(as_time_array, &alrm->time); 119 return 0; 120} 121 122static int as3722_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 123{ 124 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 125 struct as3722 *as3722 = as3722_rtc->as3722; 126 u8 as_time_array[6]; 127 int ret; 128 129 if (alrm->time.tm_year < (AS3722_RTC_START_YEAR - 1900)) 130 return -EINVAL; 131 132 ret = as3722_rtc_alarm_irq_enable(dev, 0); 133 if (ret < 0) { 134 dev_err(dev, "Disable RTC alarm failed\n"); 135 return ret; 136 } 137 138 as3722_time_to_reg(as_time_array, &alrm->time); 139 ret = as3722_block_write(as3722, AS3722_RTC_ALARM_SECOND_REG, 6, 140 as_time_array); 141 if (ret < 0) { 142 dev_err(dev, "RTC_ALARM_SECOND block write failed %d\n", ret); 143 return ret; 144 } 145 146 if (alrm->enabled) 147 ret = as3722_rtc_alarm_irq_enable(dev, alrm->enabled); 148 return ret; 149} 150 151static irqreturn_t as3722_alarm_irq(int irq, void *data) 152{ 153 struct as3722_rtc *as3722_rtc = data; 154 155 rtc_update_irq(as3722_rtc->rtc, 1, RTC_IRQF | RTC_AF); 156 return IRQ_HANDLED; 157} 158 159static const struct rtc_class_ops as3722_rtc_ops = { 160 .read_time = as3722_rtc_read_time, 161 .set_time = as3722_rtc_set_time, 162 .read_alarm = as3722_rtc_read_alarm, 163 .set_alarm = as3722_rtc_set_alarm, 164 .alarm_irq_enable = as3722_rtc_alarm_irq_enable, 165}; 166 167static int as3722_rtc_probe(struct platform_device *pdev) 168{ 169 struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent); 170 struct as3722_rtc *as3722_rtc; 171 int ret; 172 173 as3722_rtc = devm_kzalloc(&pdev->dev, sizeof(*as3722_rtc), GFP_KERNEL); 174 if (!as3722_rtc) 175 return -ENOMEM; 176 177 as3722_rtc->as3722 = as3722; 178 as3722_rtc->dev = &pdev->dev; 179 platform_set_drvdata(pdev, as3722_rtc); 180 181 /* Enable the RTC to make sure it is running. */ 182 ret = as3722_update_bits(as3722, AS3722_RTC_CONTROL_REG, 183 AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN, 184 AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN); 185 if (ret < 0) { 186 dev_err(&pdev->dev, "RTC_CONTROL reg write failed: %d\n", ret); 187 return ret; 188 } 189 190 device_init_wakeup(&pdev->dev, 1); 191 192 as3722_rtc->rtc = devm_rtc_device_register(&pdev->dev, "as3722-rtc", 193 &as3722_rtc_ops, THIS_MODULE); 194 if (IS_ERR(as3722_rtc->rtc)) { 195 ret = PTR_ERR(as3722_rtc->rtc); 196 dev_err(&pdev->dev, "RTC register failed: %d\n", ret); 197 return ret; 198 } 199 200 as3722_rtc->alarm_irq = platform_get_irq(pdev, 0); 201 dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq); 202 203 ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL, 204 as3722_alarm_irq, IRQF_ONESHOT, 205 "rtc-alarm", as3722_rtc); 206 if (ret < 0) { 207 dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", 208 as3722_rtc->alarm_irq, ret); 209 return ret; 210 } 211 disable_irq(as3722_rtc->alarm_irq); 212 return 0; 213} 214 215#ifdef CONFIG_PM_SLEEP 216static int as3722_rtc_suspend(struct device *dev) 217{ 218 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 219 220 if (device_may_wakeup(dev)) 221 enable_irq_wake(as3722_rtc->alarm_irq); 222 223 return 0; 224} 225 226static int as3722_rtc_resume(struct device *dev) 227{ 228 struct as3722_rtc *as3722_rtc = dev_get_drvdata(dev); 229 230 if (device_may_wakeup(dev)) 231 disable_irq_wake(as3722_rtc->alarm_irq); 232 return 0; 233} 234#endif 235 236static SIMPLE_DEV_PM_OPS(as3722_rtc_pm_ops, as3722_rtc_suspend, 237 as3722_rtc_resume); 238 239static struct platform_driver as3722_rtc_driver = { 240 .probe = as3722_rtc_probe, 241 .driver = { 242 .name = "as3722-rtc", 243 .pm = &as3722_rtc_pm_ops, 244 }, 245}; 246module_platform_driver(as3722_rtc_driver); 247 248MODULE_DESCRIPTION("RTC driver for AS3722 PMICs"); 249MODULE_ALIAS("platform:as3722-rtc"); 250MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>"); 251MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 252MODULE_LICENSE("GPL");