brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · daa472b Raw
163 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Copyright 2024 NXP.4 */5 6#include <linux/jiffies.h>7#include <linux/module.h>8#include <linux/platform_device.h>9#include <linux/rtc.h>10#include <linux/scmi_protocol.h>11#include <linux/scmi_imx_protocol.h>12 13struct scmi_imx_bbm {14	const struct scmi_imx_bbm_proto_ops *ops;15	struct rtc_device *rtc_dev;16	struct scmi_protocol_handle *ph;17	struct notifier_block nb;18};19 20static int scmi_imx_bbm_read_time(struct device *dev, struct rtc_time *tm)21{22	struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);23	struct scmi_protocol_handle *ph = bbnsm->ph;24	u64 val;25	int ret;26 27	ret = bbnsm->ops->rtc_time_get(ph, 0, &val);28	if (ret)29		return ret;30 31	rtc_time64_to_tm(val, tm);32 33	return 0;34}35 36static int scmi_imx_bbm_set_time(struct device *dev, struct rtc_time *tm)37{38	struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);39	struct scmi_protocol_handle *ph = bbnsm->ph;40	u64 val;41 42	val = rtc_tm_to_time64(tm);43 44	return bbnsm->ops->rtc_time_set(ph, 0, val);45}46 47static int scmi_imx_bbm_alarm_irq_enable(struct device *dev, unsigned int enable)48{49	struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);50	struct scmi_protocol_handle *ph = bbnsm->ph;51 52	/* scmi_imx_bbm_set_alarm enables the irq, just handle disable here */53	if (!enable)54		return bbnsm->ops->rtc_alarm_set(ph, 0, false, 0);55 56	return 0;57}58 59static int scmi_imx_bbm_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)60{61	struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);62	struct scmi_protocol_handle *ph = bbnsm->ph;63	struct rtc_time *alrm_tm = &alrm->time;64	u64 val;65 66	val = rtc_tm_to_time64(alrm_tm);67 68	return bbnsm->ops->rtc_alarm_set(ph, 0, true, val);69}70 71static const struct rtc_class_ops smci_imx_bbm_rtc_ops = {72	.read_time = scmi_imx_bbm_read_time,73	.set_time = scmi_imx_bbm_set_time,74	.set_alarm = scmi_imx_bbm_set_alarm,75	.alarm_irq_enable = scmi_imx_bbm_alarm_irq_enable,76};77 78static int scmi_imx_bbm_rtc_notifier(struct notifier_block *nb, unsigned long event, void *data)79{80	struct scmi_imx_bbm *bbnsm = container_of(nb, struct scmi_imx_bbm, nb);81	struct scmi_imx_bbm_notif_report *r = data;82 83	if (r->is_rtc)84		rtc_update_irq(bbnsm->rtc_dev, 1, RTC_AF | RTC_IRQF);85	else86		pr_err("Unexpected bbm event: %s\n", __func__);87 88	return 0;89}90 91static int scmi_imx_bbm_rtc_init(struct scmi_device *sdev)92{93	const struct scmi_handle *handle = sdev->handle;94	struct device *dev = &sdev->dev;95	struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev);96	int ret;97 98	bbnsm->rtc_dev = devm_rtc_allocate_device(dev);99	if (IS_ERR(bbnsm->rtc_dev))100		return PTR_ERR(bbnsm->rtc_dev);101 102	bbnsm->rtc_dev->ops = &smci_imx_bbm_rtc_ops;103	bbnsm->rtc_dev->range_max = U32_MAX;104 105	bbnsm->nb.notifier_call = &scmi_imx_bbm_rtc_notifier;106	ret = handle->notify_ops->devm_event_notifier_register(sdev, SCMI_PROTOCOL_IMX_BBM,107							       SCMI_EVENT_IMX_BBM_RTC,108							       NULL, &bbnsm->nb);109	if (ret)110		return ret;111 112	return devm_rtc_register_device(bbnsm->rtc_dev);113}114 115static int scmi_imx_bbm_rtc_probe(struct scmi_device *sdev)116{117	const struct scmi_handle *handle = sdev->handle;118	struct device *dev = &sdev->dev;119	struct scmi_protocol_handle *ph;120	struct scmi_imx_bbm *bbnsm;121	int ret;122 123	if (!handle)124		return -ENODEV;125 126	bbnsm = devm_kzalloc(dev, sizeof(*bbnsm), GFP_KERNEL);127	if (!bbnsm)128		return -ENOMEM;129 130	bbnsm->ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_BBM, &ph);131	if (IS_ERR(bbnsm->ops))132		return PTR_ERR(bbnsm->ops);133 134	bbnsm->ph = ph;135 136	device_init_wakeup(dev, true);137 138	dev_set_drvdata(dev, bbnsm);139 140	ret = scmi_imx_bbm_rtc_init(sdev);141	if (ret)142		device_init_wakeup(dev, false);143 144	return ret;145}146 147static const struct scmi_device_id scmi_id_table[] = {148	{ SCMI_PROTOCOL_IMX_BBM, "imx-bbm-rtc" },149	{ },150};151MODULE_DEVICE_TABLE(scmi, scmi_id_table);152 153static struct scmi_driver scmi_imx_bbm_rtc_driver = {154	.name = "scmi-imx-bbm-rtc",155	.probe = scmi_imx_bbm_rtc_probe,156	.id_table = scmi_id_table,157};158module_scmi_driver(scmi_imx_bbm_rtc_driver);159 160MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");161MODULE_DESCRIPTION("IMX SM BBM RTC driver");162MODULE_LICENSE("GPL");163