rtc-bd70528.c (8960B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2// 3// Copyright (C) 2018 ROHM Semiconductors 4// 5// RTC driver for ROHM BD71828 and BD71815 PMIC 6 7#include <linux/bcd.h> 8#include <linux/mfd/rohm-bd71815.h> 9#include <linux/mfd/rohm-bd71828.h> 10#include <linux/module.h> 11#include <linux/of.h> 12#include <linux/platform_device.h> 13#include <linux/regmap.h> 14#include <linux/rtc.h> 15 16/* 17 * On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0 18 * block start 19 */ 20#define BD718XX_ALM_EN_OFFSET 14 21 22/* 23 * We read regs RTC_SEC => RTC_YEAR 24 * this struct is ordered according to chip registers. 25 * Keep it u8 only (or packed) to avoid padding issues. 26 */ 27struct bd70528_rtc_day { 28 u8 sec; 29 u8 min; 30 u8 hour; 31} __packed; 32 33struct bd70528_rtc_data { 34 struct bd70528_rtc_day time; 35 u8 week; 36 u8 day; 37 u8 month; 38 u8 year; 39} __packed; 40 41struct bd71828_rtc_alm { 42 struct bd70528_rtc_data alm0; 43 struct bd70528_rtc_data alm1; 44 u8 alm_mask; 45 u8 alm1_mask; 46} __packed; 47 48struct bd70528_rtc { 49 struct rohm_regmap_dev *parent; 50 struct regmap *regmap; 51 struct device *dev; 52 u8 reg_time_start; 53 u8 bd718xx_alm_block_start; 54}; 55 56static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d) 57{ 58 d->sec &= ~BD70528_MASK_RTC_SEC; 59 d->min &= ~BD70528_MASK_RTC_MINUTE; 60 d->hour &= ~BD70528_MASK_RTC_HOUR; 61 d->sec |= bin2bcd(t->tm_sec); 62 d->min |= bin2bcd(t->tm_min); 63 d->hour |= bin2bcd(t->tm_hour); 64} 65 66static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r) 67{ 68 r->day &= ~BD70528_MASK_RTC_DAY; 69 r->week &= ~BD70528_MASK_RTC_WEEK; 70 r->month &= ~BD70528_MASK_RTC_MONTH; 71 /* 72 * PM and 24H bits are not used by Wake - thus we clear them 73 * here and not in tmday2rtc() which is also used by wake. 74 */ 75 r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H); 76 77 tmday2rtc(t, &r->time); 78 /* 79 * We do always set time in 24H mode. 80 */ 81 r->time.hour |= BD70528_MASK_RTC_HOUR_24H; 82 r->day |= bin2bcd(t->tm_mday); 83 r->week |= bin2bcd(t->tm_wday); 84 r->month |= bin2bcd(t->tm_mon + 1); 85 r->year = bin2bcd(t->tm_year - 100); 86} 87 88static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t) 89{ 90 t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC); 91 t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE); 92 t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR); 93 /* 94 * If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM 95 * is not BCD value but tells whether it is AM or PM 96 */ 97 if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) { 98 t->tm_hour %= 12; 99 if (r->time.hour & BD70528_MASK_RTC_HOUR_PM) 100 t->tm_hour += 12; 101 } 102 t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY); 103 t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1; 104 t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR); 105 t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK); 106} 107 108static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a) 109{ 110 int ret; 111 struct bd71828_rtc_alm alm; 112 struct bd70528_rtc *r = dev_get_drvdata(dev); 113 114 ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, 115 sizeof(alm)); 116 if (ret) { 117 dev_err(dev, "Failed to read alarm regs\n"); 118 return ret; 119 } 120 121 tm2rtc(&a->time, &alm.alm0); 122 123 if (!a->enabled) 124 alm.alm_mask &= ~BD70528_MASK_ALM_EN; 125 else 126 alm.alm_mask |= BD70528_MASK_ALM_EN; 127 128 ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm, 129 sizeof(alm)); 130 if (ret) 131 dev_err(dev, "Failed to set alarm time\n"); 132 133 return ret; 134 135} 136 137static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a) 138{ 139 int ret; 140 struct bd71828_rtc_alm alm; 141 struct bd70528_rtc *r = dev_get_drvdata(dev); 142 143 ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm, 144 sizeof(alm)); 145 if (ret) { 146 dev_err(dev, "Failed to read alarm regs\n"); 147 return ret; 148 } 149 150 rtc2tm(&alm.alm0, &a->time); 151 a->time.tm_mday = -1; 152 a->time.tm_mon = -1; 153 a->time.tm_year = -1; 154 a->enabled = !!(alm.alm_mask & BD70528_MASK_ALM_EN); 155 a->pending = 0; 156 157 return 0; 158} 159 160static int bd71828_set_time(struct device *dev, struct rtc_time *t) 161{ 162 int ret; 163 struct bd70528_rtc_data rtc_data; 164 struct bd70528_rtc *r = dev_get_drvdata(dev); 165 166 ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data, 167 sizeof(rtc_data)); 168 if (ret) { 169 dev_err(dev, "Failed to read RTC time registers\n"); 170 return ret; 171 } 172 tm2rtc(t, &rtc_data); 173 174 ret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data, 175 sizeof(rtc_data)); 176 if (ret) 177 dev_err(dev, "Failed to set RTC time\n"); 178 179 return ret; 180} 181 182static int bd70528_get_time(struct device *dev, struct rtc_time *t) 183{ 184 struct bd70528_rtc *r = dev_get_drvdata(dev); 185 struct bd70528_rtc_data rtc_data; 186 int ret; 187 188 /* read the RTC date and time registers all at once */ 189 ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data, 190 sizeof(rtc_data)); 191 if (ret) { 192 dev_err(dev, "Failed to read RTC time (err %d)\n", ret); 193 return ret; 194 } 195 196 rtc2tm(&rtc_data, t); 197 198 return 0; 199} 200 201static int bd71828_alm_enable(struct device *dev, unsigned int enabled) 202{ 203 int ret; 204 struct bd70528_rtc *r = dev_get_drvdata(dev); 205 unsigned int enableval = BD70528_MASK_ALM_EN; 206 207 if (!enabled) 208 enableval = 0; 209 210 ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start + 211 BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN, 212 enableval); 213 if (ret) 214 dev_err(dev, "Failed to change alarm state\n"); 215 216 return ret; 217} 218 219static const struct rtc_class_ops bd71828_rtc_ops = { 220 .read_time = bd70528_get_time, 221 .set_time = bd71828_set_time, 222 .read_alarm = bd71828_read_alarm, 223 .set_alarm = bd71828_set_alarm, 224 .alarm_irq_enable = bd71828_alm_enable, 225}; 226 227static irqreturn_t alm_hndlr(int irq, void *data) 228{ 229 struct rtc_device *rtc = data; 230 231 rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF); 232 return IRQ_HANDLED; 233} 234 235static int bd70528_probe(struct platform_device *pdev) 236{ 237 struct bd70528_rtc *bd_rtc; 238 const struct rtc_class_ops *rtc_ops; 239 const char *irq_name; 240 int ret; 241 struct rtc_device *rtc; 242 int irq; 243 unsigned int hr; 244 u8 hour_reg; 245 enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; 246 247 bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL); 248 if (!bd_rtc) 249 return -ENOMEM; 250 251 bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL); 252 if (!bd_rtc->regmap) { 253 dev_err(&pdev->dev, "No regmap\n"); 254 return -EINVAL; 255 } 256 257 bd_rtc->dev = &pdev->dev; 258 rtc_ops = &bd71828_rtc_ops; 259 260 switch (chip) { 261 case ROHM_CHIP_TYPE_BD71815: 262 irq_name = "bd71815-rtc-alm-0"; 263 bd_rtc->reg_time_start = BD71815_REG_RTC_START; 264 265 /* 266 * See also BD718XX_ALM_EN_OFFSET: 267 * This works for BD71828 and BD71815 as they have same offset 268 * between ALM0 start and ALM0_MASK. If new ICs are to be 269 * added this requires proper check as ALM0_MASK is not located 270 * at the end of ALM0 block - but after all ALM blocks so if 271 * amount of ALMs differ the offset to enable/disable is likely 272 * to be incorrect and enable/disable must be given as own 273 * reg address here. 274 */ 275 bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START; 276 hour_reg = BD71815_REG_HOUR; 277 break; 278 case ROHM_CHIP_TYPE_BD71828: 279 irq_name = "bd71828-rtc-alm-0"; 280 bd_rtc->reg_time_start = BD71828_REG_RTC_START; 281 bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START; 282 hour_reg = BD71828_REG_RTC_HOUR; 283 break; 284 default: 285 dev_err(&pdev->dev, "Unknown chip\n"); 286 return -ENOENT; 287 } 288 289 irq = platform_get_irq_byname(pdev, irq_name); 290 291 if (irq < 0) 292 return irq; 293 294 platform_set_drvdata(pdev, bd_rtc); 295 296 ret = regmap_read(bd_rtc->regmap, hour_reg, &hr); 297 298 if (ret) { 299 dev_err(&pdev->dev, "Failed to reag RTC clock\n"); 300 return ret; 301 } 302 303 if (!(hr & BD70528_MASK_RTC_HOUR_24H)) { 304 struct rtc_time t; 305 306 ret = rtc_ops->read_time(&pdev->dev, &t); 307 308 if (!ret) 309 ret = rtc_ops->set_time(&pdev->dev, &t); 310 311 if (ret) { 312 dev_err(&pdev->dev, 313 "Setting 24H clock for RTC failed\n"); 314 return ret; 315 } 316 } 317 318 device_set_wakeup_capable(&pdev->dev, true); 319 device_wakeup_enable(&pdev->dev); 320 321 rtc = devm_rtc_allocate_device(&pdev->dev); 322 if (IS_ERR(rtc)) { 323 dev_err(&pdev->dev, "RTC device creation failed\n"); 324 return PTR_ERR(rtc); 325 } 326 327 rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 328 rtc->range_max = RTC_TIMESTAMP_END_2099; 329 rtc->ops = rtc_ops; 330 331 /* Request alarm IRQ prior to registerig the RTC */ 332 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr, 333 IRQF_ONESHOT, "bd70528-rtc", rtc); 334 if (ret) 335 return ret; 336 337 return devm_rtc_register_device(rtc); 338} 339 340static const struct platform_device_id bd718x7_rtc_id[] = { 341 { "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 }, 342 { "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 }, 343 { }, 344}; 345MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id); 346 347static struct platform_driver bd70528_rtc = { 348 .driver = { 349 .name = "bd70528-rtc" 350 }, 351 .probe = bd70528_probe, 352 .id_table = bd718x7_rtc_id, 353}; 354 355module_platform_driver(bd70528_rtc); 356 357MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 358MODULE_DESCRIPTION("ROHM BD71828 and BD71815 PMIC RTC driver"); 359MODULE_LICENSE("GPL"); 360MODULE_ALIAS("platform:bd70528-rtc");