rtc-palmas.c (9776B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * rtc-palmas.c -- Palmas Real Time Clock driver. 4 5 * RTC driver for TI Palma series devices like TPS65913, 6 * TPS65914 power management IC. 7 * 8 * Copyright (c) 2012, NVIDIA Corporation. 9 * 10 * Author: Laxman Dewangan <ldewangan@nvidia.com> 11 */ 12 13#include <linux/bcd.h> 14#include <linux/errno.h> 15#include <linux/init.h> 16#include <linux/interrupt.h> 17#include <linux/kernel.h> 18#include <linux/mfd/palmas.h> 19#include <linux/module.h> 20#include <linux/of.h> 21#include <linux/rtc.h> 22#include <linux/types.h> 23#include <linux/platform_device.h> 24#include <linux/pm.h> 25 26struct palmas_rtc { 27 struct rtc_device *rtc; 28 struct device *dev; 29 unsigned int irq; 30}; 31 32/* Total number of RTC registers needed to set time*/ 33#define PALMAS_NUM_TIME_REGS (PALMAS_YEARS_REG - PALMAS_SECONDS_REG + 1) 34 35static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm) 36{ 37 unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; 38 struct palmas *palmas = dev_get_drvdata(dev->parent); 39 int ret; 40 41 /* Copy RTC counting registers to static registers or latches */ 42 ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, 43 PALMAS_RTC_CTRL_REG_GET_TIME, PALMAS_RTC_CTRL_REG_GET_TIME); 44 if (ret < 0) { 45 dev_err(dev, "RTC CTRL reg update failed, err: %d\n", ret); 46 return ret; 47 } 48 49 ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, 50 rtc_data, PALMAS_NUM_TIME_REGS); 51 if (ret < 0) { 52 dev_err(dev, "RTC_SECONDS reg read failed, err = %d\n", ret); 53 return ret; 54 } 55 56 tm->tm_sec = bcd2bin(rtc_data[0]); 57 tm->tm_min = bcd2bin(rtc_data[1]); 58 tm->tm_hour = bcd2bin(rtc_data[2]); 59 tm->tm_mday = bcd2bin(rtc_data[3]); 60 tm->tm_mon = bcd2bin(rtc_data[4]) - 1; 61 tm->tm_year = bcd2bin(rtc_data[5]) + 100; 62 63 return ret; 64} 65 66static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm) 67{ 68 unsigned char rtc_data[PALMAS_NUM_TIME_REGS]; 69 struct palmas *palmas = dev_get_drvdata(dev->parent); 70 int ret; 71 72 rtc_data[0] = bin2bcd(tm->tm_sec); 73 rtc_data[1] = bin2bcd(tm->tm_min); 74 rtc_data[2] = bin2bcd(tm->tm_hour); 75 rtc_data[3] = bin2bcd(tm->tm_mday); 76 rtc_data[4] = bin2bcd(tm->tm_mon + 1); 77 rtc_data[5] = bin2bcd(tm->tm_year - 100); 78 79 /* Stop RTC while updating the RTC time registers */ 80 ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, 81 PALMAS_RTC_CTRL_REG_STOP_RTC, 0); 82 if (ret < 0) { 83 dev_err(dev, "RTC stop failed, err = %d\n", ret); 84 return ret; 85 } 86 87 ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, PALMAS_SECONDS_REG, 88 rtc_data, PALMAS_NUM_TIME_REGS); 89 if (ret < 0) { 90 dev_err(dev, "RTC_SECONDS reg write failed, err = %d\n", ret); 91 return ret; 92 } 93 94 /* Start back RTC */ 95 ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, 96 PALMAS_RTC_CTRL_REG_STOP_RTC, PALMAS_RTC_CTRL_REG_STOP_RTC); 97 if (ret < 0) 98 dev_err(dev, "RTC start failed, err = %d\n", ret); 99 return ret; 100} 101 102static int palmas_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) 103{ 104 struct palmas *palmas = dev_get_drvdata(dev->parent); 105 u8 val; 106 107 val = enabled ? PALMAS_RTC_INTERRUPTS_REG_IT_ALARM : 0; 108 return palmas_write(palmas, PALMAS_RTC_BASE, 109 PALMAS_RTC_INTERRUPTS_REG, val); 110} 111 112static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 113{ 114 unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; 115 u32 int_val; 116 struct palmas *palmas = dev_get_drvdata(dev->parent); 117 int ret; 118 119 ret = palmas_bulk_read(palmas, PALMAS_RTC_BASE, 120 PALMAS_ALARM_SECONDS_REG, 121 alarm_data, PALMAS_NUM_TIME_REGS); 122 if (ret < 0) { 123 dev_err(dev, "RTC_ALARM_SECONDS read failed, err = %d\n", ret); 124 return ret; 125 } 126 127 alm->time.tm_sec = bcd2bin(alarm_data[0]); 128 alm->time.tm_min = bcd2bin(alarm_data[1]); 129 alm->time.tm_hour = bcd2bin(alarm_data[2]); 130 alm->time.tm_mday = bcd2bin(alarm_data[3]); 131 alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; 132 alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; 133 134 ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_INTERRUPTS_REG, 135 &int_val); 136 if (ret < 0) { 137 dev_err(dev, "RTC_INTERRUPTS reg read failed, err = %d\n", ret); 138 return ret; 139 } 140 141 if (int_val & PALMAS_RTC_INTERRUPTS_REG_IT_ALARM) 142 alm->enabled = 1; 143 return ret; 144} 145 146static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 147{ 148 unsigned char alarm_data[PALMAS_NUM_TIME_REGS]; 149 struct palmas *palmas = dev_get_drvdata(dev->parent); 150 int ret; 151 152 ret = palmas_rtc_alarm_irq_enable(dev, 0); 153 if (ret < 0) { 154 dev_err(dev, "Disable RTC alarm failed\n"); 155 return ret; 156 } 157 158 alarm_data[0] = bin2bcd(alm->time.tm_sec); 159 alarm_data[1] = bin2bcd(alm->time.tm_min); 160 alarm_data[2] = bin2bcd(alm->time.tm_hour); 161 alarm_data[3] = bin2bcd(alm->time.tm_mday); 162 alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); 163 alarm_data[5] = bin2bcd(alm->time.tm_year - 100); 164 165 ret = palmas_bulk_write(palmas, PALMAS_RTC_BASE, 166 PALMAS_ALARM_SECONDS_REG, alarm_data, PALMAS_NUM_TIME_REGS); 167 if (ret < 0) { 168 dev_err(dev, "ALARM_SECONDS_REG write failed, err = %d\n", ret); 169 return ret; 170 } 171 172 if (alm->enabled) 173 ret = palmas_rtc_alarm_irq_enable(dev, 1); 174 return ret; 175} 176 177static int palmas_clear_interrupts(struct device *dev) 178{ 179 struct palmas *palmas = dev_get_drvdata(dev->parent); 180 unsigned int rtc_reg; 181 int ret; 182 183 ret = palmas_read(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, 184 &rtc_reg); 185 if (ret < 0) { 186 dev_err(dev, "RTC_STATUS read failed, err = %d\n", ret); 187 return ret; 188 } 189 190 ret = palmas_write(palmas, PALMAS_RTC_BASE, PALMAS_RTC_STATUS_REG, 191 rtc_reg); 192 if (ret < 0) { 193 dev_err(dev, "RTC_STATUS write failed, err = %d\n", ret); 194 return ret; 195 } 196 return 0; 197} 198 199static irqreturn_t palmas_rtc_interrupt(int irq, void *context) 200{ 201 struct palmas_rtc *palmas_rtc = context; 202 struct device *dev = palmas_rtc->dev; 203 int ret; 204 205 ret = palmas_clear_interrupts(dev); 206 if (ret < 0) { 207 dev_err(dev, "RTC interrupt clear failed, err = %d\n", ret); 208 return IRQ_NONE; 209 } 210 211 rtc_update_irq(palmas_rtc->rtc, 1, RTC_IRQF | RTC_AF); 212 return IRQ_HANDLED; 213} 214 215static const struct rtc_class_ops palmas_rtc_ops = { 216 .read_time = palmas_rtc_read_time, 217 .set_time = palmas_rtc_set_time, 218 .read_alarm = palmas_rtc_read_alarm, 219 .set_alarm = palmas_rtc_set_alarm, 220 .alarm_irq_enable = palmas_rtc_alarm_irq_enable, 221}; 222 223static int palmas_rtc_probe(struct platform_device *pdev) 224{ 225 struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); 226 struct palmas_rtc *palmas_rtc = NULL; 227 int ret; 228 bool enable_bb_charging = false; 229 bool high_bb_charging = false; 230 231 if (pdev->dev.of_node) { 232 enable_bb_charging = of_property_read_bool(pdev->dev.of_node, 233 "ti,backup-battery-chargeable"); 234 high_bb_charging = of_property_read_bool(pdev->dev.of_node, 235 "ti,backup-battery-charge-high-current"); 236 } 237 238 palmas_rtc = devm_kzalloc(&pdev->dev, sizeof(struct palmas_rtc), 239 GFP_KERNEL); 240 if (!palmas_rtc) 241 return -ENOMEM; 242 243 /* Clear pending interrupts */ 244 ret = palmas_clear_interrupts(&pdev->dev); 245 if (ret < 0) { 246 dev_err(&pdev->dev, "clear RTC int failed, err = %d\n", ret); 247 return ret; 248 } 249 250 palmas_rtc->dev = &pdev->dev; 251 platform_set_drvdata(pdev, palmas_rtc); 252 253 if (enable_bb_charging) { 254 unsigned reg = PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG; 255 256 if (high_bb_charging) 257 reg = 0; 258 259 ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, 260 PALMAS_BACKUP_BATTERY_CTRL, 261 PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG, reg); 262 if (ret < 0) { 263 dev_err(&pdev->dev, 264 "BACKUP_BATTERY_CTRL update failed, %d\n", ret); 265 return ret; 266 } 267 268 ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, 269 PALMAS_BACKUP_BATTERY_CTRL, 270 PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN, 271 PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN); 272 if (ret < 0) { 273 dev_err(&pdev->dev, 274 "BACKUP_BATTERY_CTRL update failed, %d\n", ret); 275 return ret; 276 } 277 } 278 279 /* Start RTC */ 280 ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG, 281 PALMAS_RTC_CTRL_REG_STOP_RTC, 282 PALMAS_RTC_CTRL_REG_STOP_RTC); 283 if (ret < 0) { 284 dev_err(&pdev->dev, "RTC_CTRL write failed, err = %d\n", ret); 285 return ret; 286 } 287 288 palmas_rtc->irq = platform_get_irq(pdev, 0); 289 290 device_init_wakeup(&pdev->dev, 1); 291 palmas_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 292 &palmas_rtc_ops, THIS_MODULE); 293 if (IS_ERR(palmas_rtc->rtc)) { 294 ret = PTR_ERR(palmas_rtc->rtc); 295 dev_err(&pdev->dev, "RTC register failed, err = %d\n", ret); 296 return ret; 297 } 298 299 ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL, 300 palmas_rtc_interrupt, 301 IRQF_TRIGGER_LOW | IRQF_ONESHOT, 302 dev_name(&pdev->dev), palmas_rtc); 303 if (ret < 0) { 304 dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret); 305 return ret; 306 } 307 308 return 0; 309} 310 311static int palmas_rtc_remove(struct platform_device *pdev) 312{ 313 palmas_rtc_alarm_irq_enable(&pdev->dev, 0); 314 return 0; 315} 316 317#ifdef CONFIG_PM_SLEEP 318static int palmas_rtc_suspend(struct device *dev) 319{ 320 struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); 321 322 if (device_may_wakeup(dev)) 323 enable_irq_wake(palmas_rtc->irq); 324 return 0; 325} 326 327static int palmas_rtc_resume(struct device *dev) 328{ 329 struct palmas_rtc *palmas_rtc = dev_get_drvdata(dev); 330 331 if (device_may_wakeup(dev)) 332 disable_irq_wake(palmas_rtc->irq); 333 return 0; 334} 335#endif 336 337static SIMPLE_DEV_PM_OPS(palmas_rtc_pm_ops, palmas_rtc_suspend, 338 palmas_rtc_resume); 339 340#ifdef CONFIG_OF 341static const struct of_device_id of_palmas_rtc_match[] = { 342 { .compatible = "ti,palmas-rtc"}, 343 { }, 344}; 345MODULE_DEVICE_TABLE(of, of_palmas_rtc_match); 346#endif 347 348static struct platform_driver palmas_rtc_driver = { 349 .probe = palmas_rtc_probe, 350 .remove = palmas_rtc_remove, 351 .driver = { 352 .name = "palmas-rtc", 353 .pm = &palmas_rtc_pm_ops, 354 .of_match_table = of_match_ptr(of_palmas_rtc_match), 355 }, 356}; 357 358module_platform_driver(palmas_rtc_driver); 359 360MODULE_ALIAS("platform:palmas_rtc"); 361MODULE_DESCRIPTION("TI PALMAS series RTC driver"); 362MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 363MODULE_LICENSE("GPL v2");