1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP. 4 */ 5 6 #include <linux/arm-smccc.h> 7 #include <linux/firmware/imx/sci.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/platform_device.h> 11 #include <linux/rtc.h> 12 13 #define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9 14 #define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6 15 16 #define IMX_SIP_SRTC 0xC2000002 17 #define IMX_SIP_SRTC_SET_TIME 0x0 18 19 static struct imx_sc_ipc *rtc_ipc_handle; 20 static struct rtc_device *imx_sc_rtc; 21 22 struct imx_sc_msg_timer_get_rtc_time { 23 struct imx_sc_rpc_msg hdr; 24 u32 time; 25 } __packed; 26 27 static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm) 28 { 29 struct imx_sc_msg_timer_get_rtc_time msg; 30 struct imx_sc_rpc_msg *hdr = &msg.hdr; 31 int ret; 32 33 hdr->ver = IMX_SC_RPC_VERSION; 34 hdr->svc = IMX_SC_RPC_SVC_TIMER; 35 hdr->func = IMX_SC_TIMER_FUNC_GET_RTC_SEC1970; 36 hdr->size = 1; 37 38 ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true); 39 if (ret) { 40 dev_err(dev, "read rtc time failed, ret %d\n", ret); 41 return ret; 42 } 43 44 rtc_time64_to_tm(msg.time, tm); 45 46 return 0; 47 } 48 49 static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm) 50 { 51 struct arm_smccc_res res; 52 53 /* pack 2 time parameters into 1 register, 16 bits for each */ 54 arm_smccc_smc(IMX_SIP_SRTC, IMX_SIP_SRTC_SET_TIME, 55 ((tm->tm_year + 1900) << 16) | (tm->tm_mon + 1), 56 (tm->tm_mday << 16) | tm->tm_hour, 57 (tm->tm_min << 16) | tm->tm_sec, 58 0, 0, 0, &res); 59 60 return res.a0; 61 } 62 63 static const struct rtc_class_ops imx_sc_rtc_ops = { 64 .read_time = imx_sc_rtc_read_time, 65 .set_time = imx_sc_rtc_set_time, 66 }; 67 68 static int imx_sc_rtc_probe(struct platform_device *pdev) 69 { 70 int ret; 71 72 ret = imx_scu_get_handle(&rtc_ipc_handle); 73 if (ret) 74 return ret; 75 76 imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev); 77 if (IS_ERR(imx_sc_rtc)) 78 return PTR_ERR(imx_sc_rtc); 79 80 imx_sc_rtc->ops = &imx_sc_rtc_ops; 81 imx_sc_rtc->range_min = 0; 82 imx_sc_rtc->range_max = U32_MAX; 83 84 ret = rtc_register_device(imx_sc_rtc); 85 if (ret) { 86 dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); 87 return ret; 88 } 89 90 return 0; 91 } 92 93 static const struct of_device_id imx_sc_dt_ids[] = { 94 { .compatible = "fsl,imx8qxp-sc-rtc", }, 95 {} 96 }; 97 MODULE_DEVICE_TABLE(of, imx_sc_dt_ids); 98 99 static struct platform_driver imx_sc_rtc_driver = { 100 .driver = { 101 .name = "imx-sc-rtc", 102 .of_match_table = imx_sc_dt_ids, 103 }, 104 .probe = imx_sc_rtc_probe, 105 }; 106 module_platform_driver(imx_sc_rtc_driver); 107 108 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>"); 109 MODULE_DESCRIPTION("NXP i.MX System Controller RTC Driver"); 110 MODULE_LICENSE("GPL"); 111