Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock
0004  *
0005  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
0006  * Author: Venu Byravarasu <vbyravarasu@nvidia.com>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/errno.h>
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/types.h>
0014 #include <linux/rtc.h>
0015 #include <linux/bcd.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/mfd/rc5t583.h>
0019 
0020 struct rc5t583_rtc {
0021     struct rtc_device   *rtc;
0022     /* To store the list of enabled interrupts, during system suspend */
0023     u32 irqen;
0024 };
0025 
0026 /* Total number of RTC registers needed to set time*/
0027 #define NUM_TIME_REGS   (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1)
0028 
0029 /* Total number of RTC registers needed to set Y-Alarm*/
0030 #define NUM_YAL_REGS    (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1)
0031 
0032 /* Set Y-Alarm interrupt */
0033 #define SET_YAL BIT(5)
0034 
0035 /* Get Y-Alarm interrupt status*/
0036 #define GET_YAL_STATUS BIT(3)
0037 
0038 static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
0039 {
0040     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0041     u8 val;
0042 
0043     /* Set Y-Alarm, based on 'enabled' */
0044     val = enabled ? SET_YAL : 0;
0045 
0046     return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL,
0047         val);
0048 }
0049 
0050 /*
0051  * Gets current rc5t583 RTC time and date parameters.
0052  *
0053  * The RTC's time/alarm representation is not what gmtime(3) requires
0054  * Linux to use:
0055  *
0056  *  - Months are 1..12 vs Linux 0-11
0057  *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
0058  */
0059 static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm)
0060 {
0061     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0062     u8 rtc_data[NUM_TIME_REGS];
0063     int ret;
0064 
0065     ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
0066         NUM_TIME_REGS);
0067     if (ret < 0) {
0068         dev_err(dev, "RTC read time failed with err:%d\n", ret);
0069         return ret;
0070     }
0071 
0072     tm->tm_sec = bcd2bin(rtc_data[0]);
0073     tm->tm_min = bcd2bin(rtc_data[1]);
0074     tm->tm_hour = bcd2bin(rtc_data[2]);
0075     tm->tm_wday = bcd2bin(rtc_data[3]);
0076     tm->tm_mday = bcd2bin(rtc_data[4]);
0077     tm->tm_mon = bcd2bin(rtc_data[5]) - 1;
0078     tm->tm_year = bcd2bin(rtc_data[6]) + 100;
0079 
0080     return ret;
0081 }
0082 
0083 static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm)
0084 {
0085     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0086     unsigned char rtc_data[NUM_TIME_REGS];
0087     int ret;
0088 
0089     rtc_data[0] = bin2bcd(tm->tm_sec);
0090     rtc_data[1] = bin2bcd(tm->tm_min);
0091     rtc_data[2] = bin2bcd(tm->tm_hour);
0092     rtc_data[3] = bin2bcd(tm->tm_wday);
0093     rtc_data[4] = bin2bcd(tm->tm_mday);
0094     rtc_data[5] = bin2bcd(tm->tm_mon + 1);
0095     rtc_data[6] = bin2bcd(tm->tm_year - 100);
0096 
0097     ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
0098         NUM_TIME_REGS);
0099     if (ret < 0) {
0100         dev_err(dev, "RTC set time failed with error %d\n", ret);
0101         return ret;
0102     }
0103 
0104     return ret;
0105 }
0106 
0107 static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
0108 {
0109     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0110     unsigned char alarm_data[NUM_YAL_REGS];
0111     u32 interrupt_enable;
0112     int ret;
0113 
0114     ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
0115         NUM_YAL_REGS);
0116     if (ret < 0) {
0117         dev_err(dev, "rtc_read_alarm error %d\n", ret);
0118         return ret;
0119     }
0120 
0121     alm->time.tm_sec = 0;
0122     alm->time.tm_min = bcd2bin(alarm_data[0]);
0123     alm->time.tm_hour = bcd2bin(alarm_data[1]);
0124     alm->time.tm_mday = bcd2bin(alarm_data[2]);
0125     alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1;
0126     alm->time.tm_year = bcd2bin(alarm_data[4]) + 100;
0127 
0128     ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable);
0129     if (ret < 0)
0130         return ret;
0131 
0132     /* check if YALE is set */
0133     if (interrupt_enable & SET_YAL)
0134         alm->enabled = 1;
0135 
0136     return ret;
0137 }
0138 
0139 static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
0140 {
0141     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0142     unsigned char alarm_data[NUM_YAL_REGS];
0143     int ret;
0144 
0145     ret = rc5t583_rtc_alarm_irq_enable(dev, 0);
0146     if (ret)
0147         return ret;
0148 
0149     alarm_data[0] = bin2bcd(alm->time.tm_min);
0150     alarm_data[1] = bin2bcd(alm->time.tm_hour);
0151     alarm_data[2] = bin2bcd(alm->time.tm_mday);
0152     alarm_data[3] = bin2bcd(alm->time.tm_mon + 1);
0153     alarm_data[4] = bin2bcd(alm->time.tm_year - 100);
0154 
0155     ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
0156         NUM_YAL_REGS);
0157     if (ret) {
0158         dev_err(dev, "rtc_set_alarm error %d\n", ret);
0159         return ret;
0160     }
0161 
0162     if (alm->enabled)
0163         ret = rc5t583_rtc_alarm_irq_enable(dev, 1);
0164 
0165     return ret;
0166 }
0167 
0168 static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc)
0169 {
0170     struct device *dev = rtc;
0171     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0172     struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0173     unsigned long events = 0;
0174     int ret;
0175     u32 rtc_reg;
0176 
0177     ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg);
0178     if (ret < 0)
0179         return IRQ_NONE;
0180 
0181     if (rtc_reg & GET_YAL_STATUS) {
0182         events = RTC_IRQF | RTC_AF;
0183         /* clear pending Y-alarm interrupt bit */
0184         rtc_reg &= ~GET_YAL_STATUS;
0185     }
0186 
0187     ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg);
0188     if (ret)
0189         return IRQ_NONE;
0190 
0191     /* Notify RTC core on event */
0192     rtc_update_irq(rc5t583_rtc->rtc, 1, events);
0193 
0194     return IRQ_HANDLED;
0195 }
0196 
0197 static const struct rtc_class_ops rc5t583_rtc_ops = {
0198     .read_time  = rc5t583_rtc_read_time,
0199     .set_time   = rc5t583_rtc_set_time,
0200     .read_alarm = rc5t583_rtc_read_alarm,
0201     .set_alarm  = rc5t583_rtc_set_alarm,
0202     .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,
0203 };
0204 
0205 static int rc5t583_rtc_probe(struct platform_device *pdev)
0206 {
0207     struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
0208     struct rc5t583_rtc *ricoh_rtc;
0209     struct rc5t583_platform_data *pmic_plat_data;
0210     int ret;
0211     int irq;
0212 
0213     ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc),
0214             GFP_KERNEL);
0215     if (!ricoh_rtc)
0216         return -ENOMEM;
0217 
0218     platform_set_drvdata(pdev, ricoh_rtc);
0219 
0220     /* Clear pending interrupts */
0221     ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0);
0222     if (ret < 0)
0223         return ret;
0224 
0225     /* clear RTC Adjust register */
0226     ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0);
0227     if (ret < 0) {
0228         dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
0229         return -EBUSY;
0230     }
0231 
0232     pmic_plat_data = dev_get_platdata(rc5t583->dev);
0233     irq = pmic_plat_data->irq_base;
0234     if (irq <= 0) {
0235         dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
0236             irq);
0237         return ret;
0238     }
0239 
0240     irq += RC5T583_IRQ_YALE;
0241     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0242         rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW,
0243         "rtc-rc5t583", &pdev->dev);
0244     if (ret < 0) {
0245         dev_err(&pdev->dev, "IRQ is not free.\n");
0246         return ret;
0247     }
0248     device_init_wakeup(&pdev->dev, 1);
0249 
0250     ricoh_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
0251         &rc5t583_rtc_ops, THIS_MODULE);
0252     if (IS_ERR(ricoh_rtc->rtc)) {
0253         ret = PTR_ERR(ricoh_rtc->rtc);
0254         dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
0255         return ret;
0256     }
0257 
0258     return 0;
0259 }
0260 
0261 /*
0262  * Disable rc5t583 RTC interrupts.
0263  * Sets status flag to free.
0264  */
0265 static int rc5t583_rtc_remove(struct platform_device *pdev)
0266 {
0267     struct rc5t583_rtc *rc5t583_rtc = platform_get_drvdata(pdev);
0268 
0269     rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0);
0270     return 0;
0271 }
0272 
0273 #ifdef CONFIG_PM_SLEEP
0274 static int rc5t583_rtc_suspend(struct device *dev)
0275 {
0276     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0277     struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0278     int ret;
0279 
0280     /* Store current list of enabled interrupts*/
0281     ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1,
0282         &rc5t583_rtc->irqen);
0283     return ret;
0284 }
0285 
0286 static int rc5t583_rtc_resume(struct device *dev)
0287 {
0288     struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
0289     struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
0290 
0291     /* Restore list of enabled interrupts before suspend */
0292     return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1,
0293         rc5t583_rtc->irqen);
0294 }
0295 #endif
0296 
0297 static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
0298             rc5t583_rtc_resume);
0299 
0300 static struct platform_driver rc5t583_rtc_driver = {
0301     .probe      = rc5t583_rtc_probe,
0302     .remove     = rc5t583_rtc_remove,
0303     .driver     = {
0304         .name   = "rtc-rc5t583",
0305         .pm = &rc5t583_rtc_pm_ops,
0306     },
0307 };
0308 
0309 module_platform_driver(rc5t583_rtc_driver);
0310 MODULE_ALIAS("platform:rtc-rc5t583");
0311 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
0312 MODULE_LICENSE("GPL v2");