Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2018 NXP.
0004  */
0005 
0006 #include <dt-bindings/firmware/imx/rsrc.h>
0007 #include <linux/arm-smccc.h>
0008 #include <linux/firmware/imx/sci.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/rtc.h>
0013 
0014 #define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970   9
0015 #define IMX_SC_TIMER_FUNC_SET_RTC_ALARM     8
0016 #define IMX_SC_TIMER_FUNC_SET_RTC_TIME      6
0017 
0018 #define IMX_SIP_SRTC            0xC2000002
0019 #define IMX_SIP_SRTC_SET_TIME       0x0
0020 
0021 #define SC_IRQ_GROUP_RTC    2
0022 #define SC_IRQ_RTC          1
0023 
0024 static struct imx_sc_ipc *rtc_ipc_handle;
0025 static struct rtc_device *imx_sc_rtc;
0026 
0027 struct imx_sc_msg_timer_get_rtc_time {
0028     struct imx_sc_rpc_msg hdr;
0029     u32 time;
0030 } __packed;
0031 
0032 struct imx_sc_msg_timer_rtc_set_alarm {
0033     struct imx_sc_rpc_msg hdr;
0034     u16 year;
0035     u8 mon;
0036     u8 day;
0037     u8 hour;
0038     u8 min;
0039     u8 sec;
0040 } __packed __aligned(4);
0041 
0042 static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm)
0043 {
0044     struct imx_sc_msg_timer_get_rtc_time msg;
0045     struct imx_sc_rpc_msg *hdr = &msg.hdr;
0046     int ret;
0047 
0048     hdr->ver = IMX_SC_RPC_VERSION;
0049     hdr->svc = IMX_SC_RPC_SVC_TIMER;
0050     hdr->func = IMX_SC_TIMER_FUNC_GET_RTC_SEC1970;
0051     hdr->size = 1;
0052 
0053     ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true);
0054     if (ret) {
0055         dev_err(dev, "read rtc time failed, ret %d\n", ret);
0056         return ret;
0057     }
0058 
0059     rtc_time64_to_tm(msg.time, tm);
0060 
0061     return 0;
0062 }
0063 
0064 static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm)
0065 {
0066     struct arm_smccc_res res;
0067 
0068     /* pack 2 time parameters into 1 register, 16 bits for each */
0069     arm_smccc_smc(IMX_SIP_SRTC, IMX_SIP_SRTC_SET_TIME,
0070               ((tm->tm_year + 1900) << 16) | (tm->tm_mon + 1),
0071               (tm->tm_mday << 16) | tm->tm_hour,
0072               (tm->tm_min << 16) | tm->tm_sec,
0073               0, 0, 0, &res);
0074 
0075     return res.a0;
0076 }
0077 
0078 static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
0079 {
0080     return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable);
0081 }
0082 
0083 static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0084 {
0085     struct imx_sc_msg_timer_rtc_set_alarm msg;
0086     struct imx_sc_rpc_msg *hdr = &msg.hdr;
0087     int ret;
0088     struct rtc_time *alrm_tm = &alrm->time;
0089 
0090     hdr->ver = IMX_SC_RPC_VERSION;
0091     hdr->svc = IMX_SC_RPC_SVC_TIMER;
0092     hdr->func = IMX_SC_TIMER_FUNC_SET_RTC_ALARM;
0093     hdr->size = 3;
0094 
0095     msg.year = alrm_tm->tm_year + 1900;
0096     msg.mon = alrm_tm->tm_mon + 1;
0097     msg.day = alrm_tm->tm_mday;
0098     msg.hour = alrm_tm->tm_hour;
0099     msg.min = alrm_tm->tm_min;
0100     msg.sec = alrm_tm->tm_sec;
0101 
0102     ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true);
0103     if (ret) {
0104         dev_err(dev, "set rtc alarm failed, ret %d\n", ret);
0105         return ret;
0106     }
0107 
0108     ret = imx_sc_rtc_alarm_irq_enable(dev, alrm->enabled);
0109     if (ret) {
0110         dev_err(dev, "enable rtc alarm failed, ret %d\n", ret);
0111         return ret;
0112     }
0113 
0114     return 0;
0115 }
0116 
0117 static const struct rtc_class_ops imx_sc_rtc_ops = {
0118     .read_time = imx_sc_rtc_read_time,
0119     .set_time = imx_sc_rtc_set_time,
0120     .set_alarm = imx_sc_rtc_set_alarm,
0121     .alarm_irq_enable = imx_sc_rtc_alarm_irq_enable,
0122 };
0123 
0124 static int imx_sc_rtc_alarm_notify(struct notifier_block *nb,
0125                     unsigned long event, void *group)
0126 {
0127     /* ignore non-rtc irq */
0128     if (!((event & SC_IRQ_RTC) && (*(u8 *)group == SC_IRQ_GROUP_RTC)))
0129         return 0;
0130 
0131     rtc_update_irq(imx_sc_rtc, 1, RTC_IRQF | RTC_AF);
0132 
0133     return 0;
0134 }
0135 
0136 static struct notifier_block imx_sc_rtc_alarm_sc_notifier = {
0137     .notifier_call = imx_sc_rtc_alarm_notify,
0138 };
0139 
0140 static int imx_sc_rtc_probe(struct platform_device *pdev)
0141 {
0142     int ret;
0143 
0144     ret = imx_scu_get_handle(&rtc_ipc_handle);
0145     if (ret)
0146         return ret;
0147 
0148     device_init_wakeup(&pdev->dev, true);
0149 
0150     imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev);
0151     if (IS_ERR(imx_sc_rtc))
0152         return PTR_ERR(imx_sc_rtc);
0153 
0154     imx_sc_rtc->ops = &imx_sc_rtc_ops;
0155     imx_sc_rtc->range_min = 0;
0156     imx_sc_rtc->range_max = U32_MAX;
0157 
0158     ret = devm_rtc_register_device(imx_sc_rtc);
0159     if (ret)
0160         return ret;
0161 
0162     imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier);
0163 
0164     return 0;
0165 }
0166 
0167 static const struct of_device_id imx_sc_dt_ids[] = {
0168     { .compatible = "fsl,imx8qxp-sc-rtc", },
0169     {}
0170 };
0171 MODULE_DEVICE_TABLE(of, imx_sc_dt_ids);
0172 
0173 static struct platform_driver imx_sc_rtc_driver = {
0174     .driver = {
0175         .name   = "imx-sc-rtc",
0176         .of_match_table = imx_sc_dt_ids,
0177     },
0178     .probe      = imx_sc_rtc_probe,
0179 };
0180 module_platform_driver(imx_sc_rtc_driver);
0181 
0182 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
0183 MODULE_DESCRIPTION("NXP i.MX System Controller RTC Driver");
0184 MODULE_LICENSE("GPL");