18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * RTC driver for Maxim MAX8925 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009-2010 Marvell International Ltd. 68c2ecf20Sopenharmony_ci * Haojian Zhuang <haojian.zhuang@marvell.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/i2c.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/rtc.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/max8925.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cienum { 178c2ecf20Sopenharmony_ci RTC_SEC = 0, 188c2ecf20Sopenharmony_ci RTC_MIN, 198c2ecf20Sopenharmony_ci RTC_HOUR, 208c2ecf20Sopenharmony_ci RTC_WEEKDAY, 218c2ecf20Sopenharmony_ci RTC_DATE, 228c2ecf20Sopenharmony_ci RTC_MONTH, 238c2ecf20Sopenharmony_ci RTC_YEAR1, 248c2ecf20Sopenharmony_ci RTC_YEAR2, 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define MAX8925_RTC_SEC 0x00 288c2ecf20Sopenharmony_ci#define MAX8925_RTC_MIN 0x01 298c2ecf20Sopenharmony_ci#define MAX8925_RTC_HOUR 0x02 308c2ecf20Sopenharmony_ci#define MAX8925_RTC_WEEKDAY 0x03 318c2ecf20Sopenharmony_ci#define MAX8925_RTC_DATE 0x04 328c2ecf20Sopenharmony_ci#define MAX8925_RTC_MONTH 0x05 338c2ecf20Sopenharmony_ci#define MAX8925_RTC_YEAR1 0x06 348c2ecf20Sopenharmony_ci#define MAX8925_RTC_YEAR2 0x07 358c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_SEC 0x08 368c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_MIN 0x09 378c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_HOUR 0x0a 388c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_WEEKDAY 0x0b 398c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_DATE 0x0c 408c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_MON 0x0d 418c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_YEAR1 0x0e 428c2ecf20Sopenharmony_ci#define MAX8925_ALARM0_YEAR2 0x0f 438c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_SEC 0x10 448c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_MIN 0x11 458c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_HOUR 0x12 468c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_WEEKDAY 0x13 478c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_DATE 0x14 488c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_MON 0x15 498c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_YEAR1 0x16 508c2ecf20Sopenharmony_ci#define MAX8925_ALARM1_YEAR2 0x17 518c2ecf20Sopenharmony_ci#define MAX8925_RTC_CNTL 0x1b 528c2ecf20Sopenharmony_ci#define MAX8925_RTC_STATUS 0x20 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define TIME_NUM 8 558c2ecf20Sopenharmony_ci#define ALARM_1SEC (1 << 7) 568c2ecf20Sopenharmony_ci#define HOUR_12 (1 << 7) 578c2ecf20Sopenharmony_ci#define HOUR_AM_PM (1 << 5) 588c2ecf20Sopenharmony_ci#define ALARM0_IRQ (1 << 3) 598c2ecf20Sopenharmony_ci#define ALARM1_IRQ (1 << 2) 608c2ecf20Sopenharmony_ci#define ALARM0_STATUS (1 << 2) 618c2ecf20Sopenharmony_ci#define ALARM1_STATUS (1 << 1) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistruct max8925_rtc_info { 658c2ecf20Sopenharmony_ci struct rtc_device *rtc_dev; 668c2ecf20Sopenharmony_ci struct max8925_chip *chip; 678c2ecf20Sopenharmony_ci struct i2c_client *rtc; 688c2ecf20Sopenharmony_ci struct device *dev; 698c2ecf20Sopenharmony_ci int irq; 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic irqreturn_t rtc_update_handler(int irq, void *data) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci struct max8925_rtc_info *info = (struct max8925_rtc_info *)data; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* disable ALARM0 except for 1SEC alarm */ 778c2ecf20Sopenharmony_ci max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0); 788c2ecf20Sopenharmony_ci rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); 798c2ecf20Sopenharmony_ci return IRQ_HANDLED; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic int tm_calc(struct rtc_time *tm, unsigned char *buf, int len) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci if (len < TIME_NUM) 858c2ecf20Sopenharmony_ci return -EINVAL; 868c2ecf20Sopenharmony_ci tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000 878c2ecf20Sopenharmony_ci + (buf[RTC_YEAR2] & 0xf) * 100 888c2ecf20Sopenharmony_ci + (buf[RTC_YEAR1] >> 4) * 10 898c2ecf20Sopenharmony_ci + (buf[RTC_YEAR1] & 0xf); 908c2ecf20Sopenharmony_ci tm->tm_year -= 1900; 918c2ecf20Sopenharmony_ci tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10 928c2ecf20Sopenharmony_ci + (buf[RTC_MONTH] & 0x0f); 938c2ecf20Sopenharmony_ci tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10 948c2ecf20Sopenharmony_ci + (buf[RTC_DATE] & 0x0f); 958c2ecf20Sopenharmony_ci tm->tm_wday = buf[RTC_WEEKDAY] & 0x07; 968c2ecf20Sopenharmony_ci if (buf[RTC_HOUR] & HOUR_12) { 978c2ecf20Sopenharmony_ci tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10 988c2ecf20Sopenharmony_ci + (buf[RTC_HOUR] & 0x0f); 998c2ecf20Sopenharmony_ci if (buf[RTC_HOUR] & HOUR_AM_PM) 1008c2ecf20Sopenharmony_ci tm->tm_hour += 12; 1018c2ecf20Sopenharmony_ci } else 1028c2ecf20Sopenharmony_ci tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10 1038c2ecf20Sopenharmony_ci + (buf[RTC_HOUR] & 0x0f); 1048c2ecf20Sopenharmony_ci tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10 1058c2ecf20Sopenharmony_ci + (buf[RTC_MIN] & 0x0f); 1068c2ecf20Sopenharmony_ci tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10 1078c2ecf20Sopenharmony_ci + (buf[RTC_SEC] & 0x0f); 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic int data_calc(unsigned char *buf, struct rtc_time *tm, int len) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci unsigned char high, low; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (len < TIME_NUM) 1168c2ecf20Sopenharmony_ci return -EINVAL; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci high = (tm->tm_year + 1900) / 1000; 1198c2ecf20Sopenharmony_ci low = (tm->tm_year + 1900) / 100; 1208c2ecf20Sopenharmony_ci low = low - high * 10; 1218c2ecf20Sopenharmony_ci buf[RTC_YEAR2] = (high << 4) + low; 1228c2ecf20Sopenharmony_ci high = (tm->tm_year + 1900) / 10; 1238c2ecf20Sopenharmony_ci low = tm->tm_year + 1900; 1248c2ecf20Sopenharmony_ci low = low - high * 10; 1258c2ecf20Sopenharmony_ci high = high - (high / 10) * 10; 1268c2ecf20Sopenharmony_ci buf[RTC_YEAR1] = (high << 4) + low; 1278c2ecf20Sopenharmony_ci high = tm->tm_mon / 10; 1288c2ecf20Sopenharmony_ci low = tm->tm_mon; 1298c2ecf20Sopenharmony_ci low = low - high * 10; 1308c2ecf20Sopenharmony_ci buf[RTC_MONTH] = (high << 4) + low; 1318c2ecf20Sopenharmony_ci high = tm->tm_mday / 10; 1328c2ecf20Sopenharmony_ci low = tm->tm_mday; 1338c2ecf20Sopenharmony_ci low = low - high * 10; 1348c2ecf20Sopenharmony_ci buf[RTC_DATE] = (high << 4) + low; 1358c2ecf20Sopenharmony_ci buf[RTC_WEEKDAY] = tm->tm_wday; 1368c2ecf20Sopenharmony_ci high = tm->tm_hour / 10; 1378c2ecf20Sopenharmony_ci low = tm->tm_hour; 1388c2ecf20Sopenharmony_ci low = low - high * 10; 1398c2ecf20Sopenharmony_ci buf[RTC_HOUR] = (high << 4) + low; 1408c2ecf20Sopenharmony_ci high = tm->tm_min / 10; 1418c2ecf20Sopenharmony_ci low = tm->tm_min; 1428c2ecf20Sopenharmony_ci low = low - high * 10; 1438c2ecf20Sopenharmony_ci buf[RTC_MIN] = (high << 4) + low; 1448c2ecf20Sopenharmony_ci high = tm->tm_sec / 10; 1458c2ecf20Sopenharmony_ci low = tm->tm_sec; 1468c2ecf20Sopenharmony_ci low = low - high * 10; 1478c2ecf20Sopenharmony_ci buf[RTC_SEC] = (high << 4) + low; 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct max8925_rtc_info *info = dev_get_drvdata(dev); 1548c2ecf20Sopenharmony_ci unsigned char buf[TIME_NUM]; 1558c2ecf20Sopenharmony_ci int ret; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); 1588c2ecf20Sopenharmony_ci if (ret < 0) 1598c2ecf20Sopenharmony_ci goto out; 1608c2ecf20Sopenharmony_ci ret = tm_calc(tm, buf, TIME_NUM); 1618c2ecf20Sopenharmony_ciout: 1628c2ecf20Sopenharmony_ci return ret; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci struct max8925_rtc_info *info = dev_get_drvdata(dev); 1688c2ecf20Sopenharmony_ci unsigned char buf[TIME_NUM]; 1698c2ecf20Sopenharmony_ci int ret; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci ret = data_calc(buf, tm, TIME_NUM); 1728c2ecf20Sopenharmony_ci if (ret < 0) 1738c2ecf20Sopenharmony_ci goto out; 1748c2ecf20Sopenharmony_ci ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf); 1758c2ecf20Sopenharmony_ciout: 1768c2ecf20Sopenharmony_ci return ret; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct max8925_rtc_info *info = dev_get_drvdata(dev); 1828c2ecf20Sopenharmony_ci unsigned char buf[TIME_NUM]; 1838c2ecf20Sopenharmony_ci int ret; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); 1868c2ecf20Sopenharmony_ci if (ret < 0) 1878c2ecf20Sopenharmony_ci goto out; 1888c2ecf20Sopenharmony_ci ret = tm_calc(&alrm->time, buf, TIME_NUM); 1898c2ecf20Sopenharmony_ci if (ret < 0) 1908c2ecf20Sopenharmony_ci goto out; 1918c2ecf20Sopenharmony_ci ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK); 1928c2ecf20Sopenharmony_ci if (ret < 0) 1938c2ecf20Sopenharmony_ci goto out; 1948c2ecf20Sopenharmony_ci if (ret & ALARM0_IRQ) { 1958c2ecf20Sopenharmony_ci alrm->enabled = 0; 1968c2ecf20Sopenharmony_ci } else { 1978c2ecf20Sopenharmony_ci ret = max8925_reg_read(info->rtc, MAX8925_ALARM0_CNTL); 1988c2ecf20Sopenharmony_ci if (ret < 0) 1998c2ecf20Sopenharmony_ci goto out; 2008c2ecf20Sopenharmony_ci if (!ret) 2018c2ecf20Sopenharmony_ci alrm->enabled = 0; 2028c2ecf20Sopenharmony_ci else 2038c2ecf20Sopenharmony_ci alrm->enabled = 1; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS); 2068c2ecf20Sopenharmony_ci if (ret < 0) 2078c2ecf20Sopenharmony_ci goto out; 2088c2ecf20Sopenharmony_ci if (ret & ALARM0_STATUS) 2098c2ecf20Sopenharmony_ci alrm->pending = 1; 2108c2ecf20Sopenharmony_ci else 2118c2ecf20Sopenharmony_ci alrm->pending = 0; 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ciout: 2148c2ecf20Sopenharmony_ci return ret; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci struct max8925_rtc_info *info = dev_get_drvdata(dev); 2208c2ecf20Sopenharmony_ci unsigned char buf[TIME_NUM]; 2218c2ecf20Sopenharmony_ci int ret; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ret = data_calc(buf, &alrm->time, TIME_NUM); 2248c2ecf20Sopenharmony_ci if (ret < 0) 2258c2ecf20Sopenharmony_ci goto out; 2268c2ecf20Sopenharmony_ci ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf); 2278c2ecf20Sopenharmony_ci if (ret < 0) 2288c2ecf20Sopenharmony_ci goto out; 2298c2ecf20Sopenharmony_ci if (alrm->enabled) 2308c2ecf20Sopenharmony_ci /* only enable alarm on year/month/day/hour/min/sec */ 2318c2ecf20Sopenharmony_ci ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77); 2328c2ecf20Sopenharmony_ci else 2338c2ecf20Sopenharmony_ci ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x0); 2348c2ecf20Sopenharmony_ciout: 2358c2ecf20Sopenharmony_ci return ret; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic const struct rtc_class_ops max8925_rtc_ops = { 2398c2ecf20Sopenharmony_ci .read_time = max8925_rtc_read_time, 2408c2ecf20Sopenharmony_ci .set_time = max8925_rtc_set_time, 2418c2ecf20Sopenharmony_ci .read_alarm = max8925_rtc_read_alarm, 2428c2ecf20Sopenharmony_ci .set_alarm = max8925_rtc_set_alarm, 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int max8925_rtc_probe(struct platform_device *pdev) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 2488c2ecf20Sopenharmony_ci struct max8925_rtc_info *info; 2498c2ecf20Sopenharmony_ci int ret; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_rtc_info), 2528c2ecf20Sopenharmony_ci GFP_KERNEL); 2538c2ecf20Sopenharmony_ci if (!info) 2548c2ecf20Sopenharmony_ci return -ENOMEM; 2558c2ecf20Sopenharmony_ci info->chip = chip; 2568c2ecf20Sopenharmony_ci info->rtc = chip->rtc; 2578c2ecf20Sopenharmony_ci info->dev = &pdev->dev; 2588c2ecf20Sopenharmony_ci info->irq = platform_get_irq(pdev, 0); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, 2618c2ecf20Sopenharmony_ci rtc_update_handler, IRQF_ONESHOT, 2628c2ecf20Sopenharmony_ci "rtc-alarm0", info); 2638c2ecf20Sopenharmony_ci if (ret < 0) { 2648c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", 2658c2ecf20Sopenharmony_ci info->irq, ret); 2668c2ecf20Sopenharmony_ci return ret; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci dev_set_drvdata(&pdev->dev, info); 2708c2ecf20Sopenharmony_ci /* XXX - isn't this redundant? */ 2718c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, info); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci device_init_wakeup(&pdev->dev, 1); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8925-rtc", 2768c2ecf20Sopenharmony_ci &max8925_rtc_ops, THIS_MODULE); 2778c2ecf20Sopenharmony_ci ret = PTR_ERR(info->rtc_dev); 2788c2ecf20Sopenharmony_ci if (IS_ERR(info->rtc_dev)) { 2798c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); 2808c2ecf20Sopenharmony_ci return ret; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci return 0; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 2878c2ecf20Sopenharmony_cistatic int max8925_rtc_suspend(struct device *dev) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 2908c2ecf20Sopenharmony_ci struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (device_may_wakeup(dev)) 2938c2ecf20Sopenharmony_ci chip->wakeup_flag |= 1 << MAX8925_IRQ_RTC_ALARM0; 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_cistatic int max8925_rtc_resume(struct device *dev) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 2998c2ecf20Sopenharmony_ci struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (device_may_wakeup(dev)) 3028c2ecf20Sopenharmony_ci chip->wakeup_flag &= ~(1 << MAX8925_IRQ_RTC_ALARM0); 3038c2ecf20Sopenharmony_ci return 0; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci#endif 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(max8925_rtc_pm_ops, max8925_rtc_suspend, max8925_rtc_resume); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic struct platform_driver max8925_rtc_driver = { 3108c2ecf20Sopenharmony_ci .driver = { 3118c2ecf20Sopenharmony_ci .name = "max8925-rtc", 3128c2ecf20Sopenharmony_ci .pm = &max8925_rtc_pm_ops, 3138c2ecf20Sopenharmony_ci }, 3148c2ecf20Sopenharmony_ci .probe = max8925_rtc_probe, 3158c2ecf20Sopenharmony_ci}; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cimodule_platform_driver(max8925_rtc_driver); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); 3208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 3218c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3228c2ecf20Sopenharmony_ci 323