]> Git Repo - J-linux.git/blob - drivers/firmware/imx/sm-misc.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / firmware / imx / sm-misc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2024 NXP
4  */
5
6 #include <linux/firmware/imx/sm.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/platform_device.h>
10 #include <linux/scmi_protocol.h>
11 #include <linux/scmi_imx_protocol.h>
12
13 static const struct scmi_imx_misc_proto_ops *imx_misc_ctrl_ops;
14 static struct scmi_protocol_handle *ph;
15 struct notifier_block scmi_imx_misc_ctrl_nb;
16
17 int scmi_imx_misc_ctrl_set(u32 id, u32 val)
18 {
19         if (!ph)
20                 return -EPROBE_DEFER;
21
22         return imx_misc_ctrl_ops->misc_ctrl_set(ph, id, 1, &val);
23 };
24 EXPORT_SYMBOL(scmi_imx_misc_ctrl_set);
25
26 int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val)
27 {
28         if (!ph)
29                 return -EPROBE_DEFER;
30
31         return imx_misc_ctrl_ops->misc_ctrl_get(ph, id, num, val);
32 }
33 EXPORT_SYMBOL(scmi_imx_misc_ctrl_get);
34
35 static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
36                                        unsigned long event, void *data)
37 {
38         /*
39          * notifier_chain_register requires a valid notifier_block and
40          * valid notifier_call. SCMI_EVENT_IMX_MISC_CONTROL is needed
41          * to let SCMI firmware enable control events, but the hook here
42          * is just a dummy function to avoid kernel panic as of now.
43          */
44         return 0;
45 }
46
47 static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev)
48 {
49         const struct scmi_handle *handle = sdev->handle;
50         struct device_node *np = sdev->dev.of_node;
51         u32 src_id, flags;
52         int ret, i, num;
53
54         if (!handle)
55                 return -ENODEV;
56
57         if (imx_misc_ctrl_ops) {
58                 dev_err(&sdev->dev, "misc ctrl already initialized\n");
59                 return -EEXIST;
60         }
61
62         imx_misc_ctrl_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_MISC, &ph);
63         if (IS_ERR(imx_misc_ctrl_ops))
64                 return PTR_ERR(imx_misc_ctrl_ops);
65
66         num = of_property_count_u32_elems(np, "nxp,ctrl-ids");
67         if (num % 2) {
68                 dev_err(&sdev->dev, "Invalid wakeup-sources\n");
69                 return -EINVAL;
70         }
71
72         scmi_imx_misc_ctrl_nb.notifier_call = &scmi_imx_misc_ctrl_notifier;
73         for (i = 0; i < num; i += 2) {
74                 ret = of_property_read_u32_index(np, "nxp,ctrl-ids", i, &src_id);
75                 if (ret) {
76                         dev_err(&sdev->dev, "Failed to read ctrl-id: %i\n", i);
77                         continue;
78                 }
79
80                 ret = of_property_read_u32_index(np, "nxp,ctrl-ids", i + 1, &flags);
81                 if (ret) {
82                         dev_err(&sdev->dev, "Failed to read ctrl-id value: %d\n", i + 1);
83                         continue;
84                 }
85
86                 ret = handle->notify_ops->devm_event_notifier_register(sdev, SCMI_PROTOCOL_IMX_MISC,
87                                                                        SCMI_EVENT_IMX_MISC_CONTROL,
88                                                                        &src_id,
89                                                                        &scmi_imx_misc_ctrl_nb);
90                 if (ret) {
91                         dev_err(&sdev->dev, "Failed to register scmi misc event: %d\n", src_id);
92                 } else {
93                         ret = imx_misc_ctrl_ops->misc_ctrl_req_notify(ph, src_id,
94                                                                       SCMI_EVENT_IMX_MISC_CONTROL,
95                                                                       flags);
96                         if (ret)
97                                 dev_err(&sdev->dev, "Failed to req notify: %d\n", src_id);
98                 }
99         }
100
101         return 0;
102 }
103
104 static const struct scmi_device_id scmi_id_table[] = {
105         { SCMI_PROTOCOL_IMX_MISC, "imx-misc-ctrl" },
106         { },
107 };
108 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
109
110 static struct scmi_driver scmi_imx_misc_ctrl_driver = {
111         .name = "scmi-imx-misc-ctrl",
112         .probe = scmi_imx_misc_ctrl_probe,
113         .id_table = scmi_id_table,
114 };
115 module_scmi_driver(scmi_imx_misc_ctrl_driver);
116
117 MODULE_AUTHOR("Peng Fan <[email protected]>");
118 MODULE_DESCRIPTION("IMX SM MISC driver");
119 MODULE_LICENSE("GPL");
This page took 0.031862 seconds and 4 git commands to generate.