1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP. 4 */ 5 6 #include <dt-bindings/firmware/imx/rsrc.h> 7 #include <linux/arm-smccc.h> 8 #include <linux/firmware/imx/sci.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/rtc.h> 13 14 #define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9 15 #define IMX_SC_TIMER_FUNC_SET_RTC_ALARM 8 16 #define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6 17 18 #define IMX_SIP_SRTC 0xC2000002 19 #define IMX_SIP_SRTC_SET_TIME 0x0 20 21 #define SC_IRQ_GROUP_RTC 2 22 #define SC_IRQ_RTC 1 23 24 static struct imx_sc_ipc *rtc_ipc_handle; 25 static struct rtc_device *imx_sc_rtc; 26 27 struct imx_sc_msg_timer_get_rtc_time { 28 struct imx_sc_rpc_msg hdr; 29 u32 time; 30 } __packed; 31 32 struct imx_sc_msg_timer_rtc_set_alarm { 33 struct imx_sc_rpc_msg hdr; 34 u16 year; 35 u8 mon; 36 u8 day; 37 u8 hour; 38 u8 min; 39 u8 sec; 40 } __packed; 41 42 static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm) 43 { 44 struct imx_sc_msg_timer_get_rtc_time msg; 45 struct imx_sc_rpc_msg *hdr = &msg.hdr; 46 int ret; 47 48 hdr->ver = IMX_SC_RPC_VERSION; 49 hdr->svc = IMX_SC_RPC_SVC_TIMER; 50 hdr->func = IMX_SC_TIMER_FUNC_GET_RTC_SEC1970; 51 hdr->size = 1; 52 53 ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true); 54 if (ret) { 55 dev_err(dev, "read rtc time failed, ret %d\n", ret); 56 return ret; 57 } 58 59 rtc_time64_to_tm(msg.time, tm); 60 61 return 0; 62 } 63 64 static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm) 65 { 66 struct arm_smccc_res res; 67 68 /* pack 2 time parameters into 1 register, 16 bits for each */ 69 arm_smccc_smc(IMX_SIP_SRTC, IMX_SIP_SRTC_SET_TIME, 70 ((tm->tm_year + 1900) << 16) | (tm->tm_mon + 1), 71 (tm->tm_mday << 16) | tm->tm_hour, 72 (tm->tm_min << 16) | tm->tm_sec, 73 0, 0, 0, &res); 74 75 return res.a0; 76 } 77 78 static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) 79 { 80 return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable); 81 } 82 83 static int imx_sc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 84 { 85 /* 86 * SCU firmware does NOT provide read alarm API, but .read_alarm 87 * callback is required by RTC framework to support alarm function, 88 * so just return here. 89 */ 90 return 0; 91 } 92 93 static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 94 { 95 struct imx_sc_msg_timer_rtc_set_alarm msg; 96 struct imx_sc_rpc_msg *hdr = &msg.hdr; 97 int ret; 98 struct rtc_time *alrm_tm = &alrm->time; 99 100 hdr->ver = IMX_SC_RPC_VERSION; 101 hdr->svc = IMX_SC_RPC_SVC_TIMER; 102 hdr->func = IMX_SC_TIMER_FUNC_SET_RTC_ALARM; 103 hdr->size = 3; 104 105 msg.year = alrm_tm->tm_year + 1900; 106 msg.mon = alrm_tm->tm_mon + 1; 107 msg.day = alrm_tm->tm_mday; 108 msg.hour = alrm_tm->tm_hour; 109 msg.min = alrm_tm->tm_min; 110 msg.sec = alrm_tm->tm_sec; 111 112 ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true); 113 if (ret) { 114 dev_err(dev, "set rtc alarm failed, ret %d\n", ret); 115 return ret; 116 } 117 118 ret = imx_sc_rtc_alarm_irq_enable(dev, alrm->enabled); 119 if (ret) { 120 dev_err(dev, "enable rtc alarm failed, ret %d\n", ret); 121 return ret; 122 } 123 124 return 0; 125 } 126 127 static const struct rtc_class_ops imx_sc_rtc_ops = { 128 .read_time = imx_sc_rtc_read_time, 129 .set_time = imx_sc_rtc_set_time, 130 .read_alarm = imx_sc_rtc_read_alarm, 131 .set_alarm = imx_sc_rtc_set_alarm, 132 .alarm_irq_enable = imx_sc_rtc_alarm_irq_enable, 133 }; 134 135 static int imx_sc_rtc_alarm_notify(struct notifier_block *nb, 136 unsigned long event, void *group) 137 { 138 /* ignore non-rtc irq */ 139 if (!((event & SC_IRQ_RTC) && (*(u8 *)group == SC_IRQ_GROUP_RTC))) 140 return 0; 141 142 rtc_update_irq(imx_sc_rtc, 1, RTC_IRQF | RTC_AF); 143 144 return 0; 145 } 146 147 static struct notifier_block imx_sc_rtc_alarm_sc_notifier = { 148 .notifier_call = imx_sc_rtc_alarm_notify, 149 }; 150 151 static int imx_sc_rtc_probe(struct platform_device *pdev) 152 { 153 int ret; 154 155 ret = imx_scu_get_handle(&rtc_ipc_handle); 156 if (ret) 157 return ret; 158 159 device_init_wakeup(&pdev->dev, true); 160 161 imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev); 162 if (IS_ERR(imx_sc_rtc)) 163 return PTR_ERR(imx_sc_rtc); 164 165 imx_sc_rtc->ops = &imx_sc_rtc_ops; 166 imx_sc_rtc->range_min = 0; 167 imx_sc_rtc->range_max = U32_MAX; 168 169 ret = rtc_register_device(imx_sc_rtc); 170 if (ret) 171 return ret; 172 173 imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier); 174 175 return 0; 176 } 177 178 static const struct of_device_id imx_sc_dt_ids[] = { 179 { .compatible = "fsl,imx8qxp-sc-rtc", }, 180 {} 181 }; 182 MODULE_DEVICE_TABLE(of, imx_sc_dt_ids); 183 184 static struct platform_driver imx_sc_rtc_driver = { 185 .driver = { 186 .name = "imx-sc-rtc", 187 .of_match_table = imx_sc_dt_ids, 188 }, 189 .probe = imx_sc_rtc_probe, 190 }; 191 module_platform_driver(imx_sc_rtc_driver); 192 193 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>"); 194 MODULE_DESCRIPTION("NXP i.MX System Controller RTC Driver"); 195 MODULE_LICENSE("GPL"); 196