Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // RTC driver for ChromeOS Embedded Controller.
0003 //
0004 // Copyright (C) 2017 Google, Inc.
0005 // Author: Stephen Barber <smbarber@chromium.org>
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_data/cros_ec_commands.h>
0010 #include <linux/platform_data/cros_ec_proto.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/rtc.h>
0013 #include <linux/slab.h>
0014 
0015 #define DRV_NAME    "cros-ec-rtc"
0016 
0017 /**
0018  * struct cros_ec_rtc - Driver data for EC RTC
0019  *
0020  * @cros_ec: Pointer to EC device
0021  * @rtc: Pointer to RTC device
0022  * @notifier: Notifier info for responding to EC events
0023  * @saved_alarm: Alarm to restore when interrupts are reenabled
0024  */
0025 struct cros_ec_rtc {
0026     struct cros_ec_device *cros_ec;
0027     struct rtc_device *rtc;
0028     struct notifier_block notifier;
0029     u32 saved_alarm;
0030 };
0031 
0032 static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command,
0033                u32 *response)
0034 {
0035     int ret;
0036     struct {
0037         struct cros_ec_command msg;
0038         struct ec_response_rtc data;
0039     } __packed msg;
0040 
0041     memset(&msg, 0, sizeof(msg));
0042     msg.msg.command = command;
0043     msg.msg.insize = sizeof(msg.data);
0044 
0045     ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
0046     if (ret < 0) {
0047         dev_err(cros_ec->dev,
0048             "error getting %s from EC: %d\n",
0049             command == EC_CMD_RTC_GET_VALUE ? "time" : "alarm",
0050             ret);
0051         return ret;
0052     }
0053 
0054     *response = msg.data.time;
0055 
0056     return 0;
0057 }
0058 
0059 static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command,
0060                u32 param)
0061 {
0062     int ret = 0;
0063     struct {
0064         struct cros_ec_command msg;
0065         struct ec_response_rtc data;
0066     } __packed msg;
0067 
0068     memset(&msg, 0, sizeof(msg));
0069     msg.msg.command = command;
0070     msg.msg.outsize = sizeof(msg.data);
0071     msg.data.time = param;
0072 
0073     ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
0074     if (ret < 0) {
0075         dev_err(cros_ec->dev, "error setting %s on EC: %d\n",
0076             command == EC_CMD_RTC_SET_VALUE ? "time" : "alarm",
0077             ret);
0078         return ret;
0079     }
0080 
0081     return 0;
0082 }
0083 
0084 /* Read the current time from the EC. */
0085 static int cros_ec_rtc_read_time(struct device *dev, struct rtc_time *tm)
0086 {
0087     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
0088     struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
0089     int ret;
0090     u32 time;
0091 
0092     ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &time);
0093     if (ret) {
0094         dev_err(dev, "error getting time: %d\n", ret);
0095         return ret;
0096     }
0097 
0098     rtc_time64_to_tm(time, tm);
0099 
0100     return 0;
0101 }
0102 
0103 /* Set the current EC time. */
0104 static int cros_ec_rtc_set_time(struct device *dev, struct rtc_time *tm)
0105 {
0106     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
0107     struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
0108     int ret;
0109     time64_t time = rtc_tm_to_time64(tm);
0110 
0111     ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_VALUE, (u32)time);
0112     if (ret < 0) {
0113         dev_err(dev, "error setting time: %d\n", ret);
0114         return ret;
0115     }
0116 
0117     return 0;
0118 }
0119 
0120 /* Read alarm time from RTC. */
0121 static int cros_ec_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0122 {
0123     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
0124     struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
0125     int ret;
0126     u32 current_time, alarm_offset;
0127 
0128     /*
0129      * The EC host command for getting the alarm is relative (i.e. 5
0130      * seconds from now) whereas rtc_wkalrm is absolute. Get the current
0131      * RTC time first so we can calculate the relative time.
0132      */
0133     ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
0134     if (ret < 0) {
0135         dev_err(dev, "error getting time: %d\n", ret);
0136         return ret;
0137     }
0138 
0139     ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM, &alarm_offset);
0140     if (ret < 0) {
0141         dev_err(dev, "error getting alarm: %d\n", ret);
0142         return ret;
0143     }
0144 
0145     rtc_time64_to_tm(current_time + alarm_offset, &alrm->time);
0146 
0147     return 0;
0148 }
0149 
0150 /* Set the EC's RTC alarm. */
0151 static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0152 {
0153     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
0154     struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
0155     int ret;
0156     time64_t alarm_time;
0157     u32 current_time, alarm_offset;
0158 
0159     /*
0160      * The EC host command for setting the alarm is relative
0161      * (i.e. 5 seconds from now) whereas rtc_wkalrm is absolute.
0162      * Get the current RTC time first so we can calculate the
0163      * relative time.
0164      */
0165     ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
0166     if (ret < 0) {
0167         dev_err(dev, "error getting time: %d\n", ret);
0168         return ret;
0169     }
0170 
0171     alarm_time = rtc_tm_to_time64(&alrm->time);
0172 
0173     if (alarm_time < 0 || alarm_time > U32_MAX)
0174         return -EINVAL;
0175 
0176     if (!alrm->enabled) {
0177         /*
0178          * If the alarm is being disabled, send an alarm
0179          * clear command.
0180          */
0181         alarm_offset = EC_RTC_ALARM_CLEAR;
0182         cros_ec_rtc->saved_alarm = (u32)alarm_time;
0183     } else {
0184         /* Don't set an alarm in the past. */
0185         if ((u32)alarm_time <= current_time)
0186             return -ETIME;
0187 
0188         alarm_offset = (u32)alarm_time - current_time;
0189     }
0190 
0191     ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);
0192     if (ret < 0) {
0193         dev_err(dev, "error setting alarm: %d\n", ret);
0194         return ret;
0195     }
0196 
0197     return 0;
0198 }
0199 
0200 static int cros_ec_rtc_alarm_irq_enable(struct device *dev,
0201                     unsigned int enabled)
0202 {
0203     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
0204     struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
0205     int ret;
0206     u32 current_time, alarm_offset, alarm_value;
0207 
0208     ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
0209     if (ret < 0) {
0210         dev_err(dev, "error getting time: %d\n", ret);
0211         return ret;
0212     }
0213 
0214     if (enabled) {
0215         /* Restore saved alarm if it's still in the future. */
0216         if (cros_ec_rtc->saved_alarm < current_time)
0217             alarm_offset = EC_RTC_ALARM_CLEAR;
0218         else
0219             alarm_offset = cros_ec_rtc->saved_alarm - current_time;
0220 
0221         ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
0222                       alarm_offset);
0223         if (ret < 0) {
0224             dev_err(dev, "error restoring alarm: %d\n", ret);
0225             return ret;
0226         }
0227     } else {
0228         /* Disable alarm, saving the old alarm value. */
0229         ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM,
0230                       &alarm_offset);
0231         if (ret < 0) {
0232             dev_err(dev, "error saving alarm: %d\n", ret);
0233             return ret;
0234         }
0235 
0236         alarm_value = current_time + alarm_offset;
0237 
0238         /*
0239          * If the current EC alarm is already past, we don't want
0240          * to set an alarm when we go through the alarm irq enable
0241          * path.
0242          */
0243         if (alarm_value < current_time)
0244             cros_ec_rtc->saved_alarm = EC_RTC_ALARM_CLEAR;
0245         else
0246             cros_ec_rtc->saved_alarm = alarm_value;
0247 
0248         alarm_offset = EC_RTC_ALARM_CLEAR;
0249         ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
0250                       alarm_offset);
0251         if (ret < 0) {
0252             dev_err(dev, "error disabling alarm: %d\n", ret);
0253             return ret;
0254         }
0255     }
0256 
0257     return 0;
0258 }
0259 
0260 static int cros_ec_rtc_event(struct notifier_block *nb,
0261                  unsigned long queued_during_suspend,
0262                  void *_notify)
0263 {
0264     struct cros_ec_rtc *cros_ec_rtc;
0265     struct rtc_device *rtc;
0266     struct cros_ec_device *cros_ec;
0267     u32 host_event;
0268 
0269     cros_ec_rtc = container_of(nb, struct cros_ec_rtc, notifier);
0270     rtc = cros_ec_rtc->rtc;
0271     cros_ec = cros_ec_rtc->cros_ec;
0272 
0273     host_event = cros_ec_get_host_event(cros_ec);
0274     if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) {
0275         rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
0276         return NOTIFY_OK;
0277     } else {
0278         return NOTIFY_DONE;
0279     }
0280 }
0281 
0282 static const struct rtc_class_ops cros_ec_rtc_ops = {
0283     .read_time = cros_ec_rtc_read_time,
0284     .set_time = cros_ec_rtc_set_time,
0285     .read_alarm = cros_ec_rtc_read_alarm,
0286     .set_alarm = cros_ec_rtc_set_alarm,
0287     .alarm_irq_enable = cros_ec_rtc_alarm_irq_enable,
0288 };
0289 
0290 #ifdef CONFIG_PM_SLEEP
0291 static int cros_ec_rtc_suspend(struct device *dev)
0292 {
0293     struct platform_device *pdev = to_platform_device(dev);
0294     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
0295 
0296     if (device_may_wakeup(dev))
0297         return enable_irq_wake(cros_ec_rtc->cros_ec->irq);
0298 
0299     return 0;
0300 }
0301 
0302 static int cros_ec_rtc_resume(struct device *dev)
0303 {
0304     struct platform_device *pdev = to_platform_device(dev);
0305     struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
0306 
0307     if (device_may_wakeup(dev))
0308         return disable_irq_wake(cros_ec_rtc->cros_ec->irq);
0309 
0310     return 0;
0311 }
0312 #endif
0313 
0314 static SIMPLE_DEV_PM_OPS(cros_ec_rtc_pm_ops, cros_ec_rtc_suspend,
0315              cros_ec_rtc_resume);
0316 
0317 static int cros_ec_rtc_probe(struct platform_device *pdev)
0318 {
0319     struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
0320     struct cros_ec_device *cros_ec = ec_dev->ec_dev;
0321     struct cros_ec_rtc *cros_ec_rtc;
0322     struct rtc_time tm;
0323     int ret;
0324 
0325     cros_ec_rtc = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_rtc),
0326                    GFP_KERNEL);
0327     if (!cros_ec_rtc)
0328         return -ENOMEM;
0329 
0330     platform_set_drvdata(pdev, cros_ec_rtc);
0331     cros_ec_rtc->cros_ec = cros_ec;
0332 
0333     /* Get initial time */
0334     ret = cros_ec_rtc_read_time(&pdev->dev, &tm);
0335     if (ret) {
0336         dev_err(&pdev->dev, "failed to read RTC time\n");
0337         return ret;
0338     }
0339 
0340     ret = device_init_wakeup(&pdev->dev, 1);
0341     if (ret) {
0342         dev_err(&pdev->dev, "failed to initialize wakeup\n");
0343         return ret;
0344     }
0345 
0346     cros_ec_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
0347     if (IS_ERR(cros_ec_rtc->rtc))
0348         return PTR_ERR(cros_ec_rtc->rtc);
0349 
0350     cros_ec_rtc->rtc->ops = &cros_ec_rtc_ops;
0351     cros_ec_rtc->rtc->range_max = U32_MAX;
0352 
0353     ret = devm_rtc_register_device(cros_ec_rtc->rtc);
0354     if (ret)
0355         return ret;
0356 
0357     /* Get RTC events from the EC. */
0358     cros_ec_rtc->notifier.notifier_call = cros_ec_rtc_event;
0359     ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
0360                            &cros_ec_rtc->notifier);
0361     if (ret) {
0362         dev_err(&pdev->dev, "failed to register notifier\n");
0363         return ret;
0364     }
0365 
0366     return 0;
0367 }
0368 
0369 static int cros_ec_rtc_remove(struct platform_device *pdev)
0370 {
0371     struct cros_ec_rtc *cros_ec_rtc = platform_get_drvdata(pdev);
0372     struct device *dev = &pdev->dev;
0373     int ret;
0374 
0375     ret = blocking_notifier_chain_unregister(
0376                 &cros_ec_rtc->cros_ec->event_notifier,
0377                 &cros_ec_rtc->notifier);
0378     if (ret)
0379         dev_err(dev, "failed to unregister notifier\n");
0380 
0381     return 0;
0382 }
0383 
0384 static struct platform_driver cros_ec_rtc_driver = {
0385     .probe = cros_ec_rtc_probe,
0386     .remove = cros_ec_rtc_remove,
0387     .driver = {
0388         .name = DRV_NAME,
0389         .pm = &cros_ec_rtc_pm_ops,
0390     },
0391 };
0392 
0393 module_platform_driver(cros_ec_rtc_driver);
0394 
0395 MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
0396 MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
0397 MODULE_LICENSE("GPL v2");
0398 MODULE_ALIAS("platform:" DRV_NAME);