2 * System Control and Power Interface (SCPI) Message Protocol driver
4 * Copyright (C) 2014 ARM Ltd.
5 * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/of_device.h>
20 #include <linux/platform_device.h>
21 #include <linux/err.h>
22 #include <linux/export.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/printk.h>
26 #include <linux/mailbox_client.h>
27 #include <linux/slab.h>
28 #include <soc/rockchip/scpi.h>
29 #include <soc/rockchip/rk3368-mailbox.h>
31 #define SCPI_VERSION 0x01000002 /* version: 1.0.0.2 */
33 #define CMD_ID_SHIFT 0
34 #define CMD_ID_MASK 0xff
35 #define CMD_SENDER_ID_SHIFT 8
36 #define CMD_SENDER_ID_MASK 0xff
37 #define CMD_DATA_SIZE_SHIFT 20
38 #define CMD_DATA_SIZE_MASK 0x1ff
39 #define PACK_SCPI_CMD(cmd, sender, txsz) \
40 ((((cmd) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
41 (((sender) & CMD_SENDER_ID_MASK) << CMD_SENDER_ID_SHIFT) | \
42 (((txsz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
43 #define SCPI_CMD_DEFAULT_TIMEOUT_MS 1000
45 #define MAX_DVFS_DOMAINS 3
46 #define MAX_DVFS_OPPS 8
47 #define DVFS_LATENCY(hdr) ((hdr) >> 16)
48 #define DVFS_OPP_COUNT(hdr) (((hdr) >> 8) & 0xff)
50 static int max_chan_num = 0;
51 static DECLARE_BITMAP(bm_mbox_chans, 4);
52 static DEFINE_MUTEX(scpi_mtx);
54 enum scpi_error_codes {
55 SCPI_SUCCESS = 0, /* Success */
56 SCPI_ERR_PARAM = 1, /* Invalid parameter(s) */
57 SCPI_ERR_ALIGN = 2, /* Invalid alignment */
58 SCPI_ERR_SIZE = 3, /* Invalid size */
59 SCPI_ERR_HANDLER = 4, /* Invalid handler/callback */
60 SCPI_ERR_ACCESS = 5, /* Invalid access/permission denied */
61 SCPI_ERR_RANGE = 6, /* Value out of range */
62 SCPI_ERR_TIMEOUT = 7, /* Timeout has occurred */
63 SCPI_ERR_NOMEM = 8, /* Invalid memory area or pointer */
64 SCPI_ERR_PWRSTATE = 9, /* Invalid power state */
65 SCPI_ERR_SUPPORT = 10, /* Not supported or disabled */
66 SCPI_ERR_DEVICE = 11, /* Device error */
85 SCPI_DDR_AUTO_SELF_REFRESH,
86 SCPI_DDR_BANDWIDTH_GET,
94 SCPI_SYS_REFRESH_MCU_FREQ,
95 SCPI_SYS_SET_MCU_STATE_SUSPEND,
96 SCPI_SYS_SET_MCU_STATE_RESUME,
97 SCPI_SYS_SET_JTAGMUX_ON_OFF,
101 SCPI_CMD_INVALID = 0x00,
102 SCPI_CMD_SCPI_READY = 0x01,
103 SCPI_CMD_SCPI_CAPABILITIES = 0x02,
104 SCPI_CMD_EVENT = 0x03,
105 SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
106 SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
107 SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
108 SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
109 SCPI_CMD_SYS_PWR_STATE = 0x08,
110 SCPI_CMD_L2_READY = 0x09,
111 SCPI_CMD_SET_AP_TIMER = 0x0a,
112 SCPI_CMD_CANCEL_AP_TIME = 0x0b,
113 SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
114 SCPI_CMD_GET_DVFS_INFO = 0x0d,
115 SCPI_CMD_SET_DVFS = 0x0e,
116 SCPI_CMD_GET_DVFS = 0x0f,
117 SCPI_CMD_GET_DVFS_STAT = 0x10,
118 SCPI_CMD_SET_RTC = 0x11,
119 SCPI_CMD_GET_RTC = 0x12,
120 SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
121 SCPI_CMD_SET_CLOCK_INDEX = 0x14,
122 SCPI_CMD_SET_CLOCK_VALUE = 0x15,
123 SCPI_CMD_GET_CLOCK_VALUE = 0x16,
124 SCPI_CMD_PSU_CAPABILITIES = 0x17,
125 SCPI_CMD_SET_PSU = 0x18,
126 SCPI_CMD_GET_PSU = 0x19,
127 SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
128 SCPI_CMD_SENSOR_INFO = 0x1b,
129 SCPI_CMD_SENSOR_VALUE = 0x1c,
130 SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
131 SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
132 SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
136 enum scpi_thermal_cmd {
137 SCPI_THERMAL_GET_TSADC_DATA,
138 SCPI_THERMAL_SET_TSADC_CYCLE,
142 static int high_priority_cmds[] = {
143 SCPI_CMD_GET_CSS_PWR_STATE,
144 SCPI_CMD_CFG_PWR_STATE_STAT,
145 SCPI_CMD_GET_PWR_STATE_STAT,
150 SCPI_CMD_SET_CLOCK_INDEX,
151 SCPI_CMD_SET_CLOCK_VALUE,
152 SCPI_CMD_GET_CLOCK_VALUE,
155 SCPI_CMD_SENSOR_CFG_PERIODIC,
156 SCPI_CMD_SENSOR_CFG_BOUNDS,
159 struct scpi_data_buf {
161 struct rk3368_mbox_msg *data;
162 struct completion complete;
166 struct scpi_mcu_ver {
171 static struct scpi_opp *scpi_opps[MAX_DVFS_DOMAINS];
173 static struct device *the_scpi_device;
175 static int scpi_linux_errmap[SCPI_ERR_MAX] = {
176 0, -EINVAL, -ENOEXEC, -EMSGSIZE,
177 -EINVAL, -EACCES, -ERANGE, -ETIMEDOUT,
178 -ENOMEM, -EINVAL, -EOPNOTSUPP, -EIO,
181 static inline int scpi_to_linux_errno(int errno)
183 if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
184 return scpi_linux_errmap[errno];
188 static bool __maybe_unused high_priority_chan_supported(int cmd)
192 for (idx = 0; idx < ARRAY_SIZE(high_priority_cmds); idx++)
193 if (cmd == high_priority_cmds[idx])
198 static int scpi_alloc_mbox_chan(void)
202 mutex_lock(&scpi_mtx);
204 index = find_first_zero_bit(bm_mbox_chans, max_chan_num);
205 if (index >= max_chan_num) {
206 pr_err("alloc mailbox channel failed\n");
207 mutex_unlock(&scpi_mtx);
211 set_bit(index, bm_mbox_chans);
213 mutex_unlock(&scpi_mtx);
217 static void scpi_free_mbox_chan(int chan)
221 mutex_lock(&scpi_mtx);
223 if (index < max_chan_num && index >= 0)
224 clear_bit(index, bm_mbox_chans);
226 mutex_unlock(&scpi_mtx);
229 static void scpi_rx_callback(struct mbox_client *cl, void *msg)
231 struct rk3368_mbox_msg *data = (struct rk3368_mbox_msg *)msg;
232 struct scpi_data_buf *scpi_buf = data->cl_data;
234 complete(&scpi_buf->complete);
237 static int send_scpi_cmd(struct scpi_data_buf *scpi_buf, int index)
239 struct mbox_chan *chan;
240 struct mbox_client cl;
241 struct rk3368_mbox_msg *data = scpi_buf->data;
244 int timeout = msecs_to_jiffies(scpi_buf->timeout_ms);
246 if (!the_scpi_device) {
247 pr_err("Scpi initializes unsuccessfully\n");
251 cl.dev = the_scpi_device;
252 cl.rx_callback = scpi_rx_callback;
254 cl.tx_prepare = NULL;
256 cl.knows_txdone = false;
258 chan = mbox_request_channel(&cl, index);
260 scpi_free_mbox_chan(index);
261 return PTR_ERR(chan);
264 init_completion(&scpi_buf->complete);
265 if (mbox_send_message(chan, (void *)data) < 0) {
266 status = SCPI_ERR_TIMEOUT;
270 ret = wait_for_completion_timeout(&scpi_buf->complete, timeout);
272 status = SCPI_ERR_TIMEOUT;
275 status = *(u32 *)(data->rx_buf); /* read first word */
278 mbox_free_channel(chan);
279 scpi_free_mbox_chan(index);
281 return scpi_to_linux_errno(status);
284 #define SCPI_SETUP_DBUF(scpi_buf, mbox_buf, _client_id,\
285 _cmd, _tx_buf, _rx_buf) \
287 struct rk3368_mbox_msg *pdata = &mbox_buf; \
289 pdata->tx_buf = &_tx_buf; \
290 pdata->tx_size = sizeof(_tx_buf); \
291 pdata->rx_buf = &_rx_buf; \
292 pdata->rx_size = sizeof(_rx_buf); \
293 scpi_buf.client_id = _client_id; \
294 scpi_buf.data = pdata; \
295 scpi_buf.timeout_ms = SCPI_CMD_DEFAULT_TIMEOUT_MS; \
298 #define SCPI_SETUP_DBUF_BY_SIZE(scpi_buf, mbox_buf, _client_id, \
299 _cmd, _tx_buf, _tx_size, _rx_buf) \
301 struct rk3368_mbox_msg *pdata = &mbox_buf; \
303 pdata->tx_buf = _tx_buf; \
304 pdata->tx_size = _tx_size; \
305 pdata->rx_buf = &_rx_buf; \
306 pdata->rx_size = sizeof(_rx_buf); \
307 scpi_buf.client_id = _client_id; \
308 scpi_buf.data = pdata; \
309 scpi_buf.timeout_ms = SCPI_CMD_DEFAULT_TIMEOUT_MS; \
312 static int scpi_execute_cmd(struct scpi_data_buf *scpi_buf)
314 struct rk3368_mbox_msg *data;
317 if (!scpi_buf || !scpi_buf->data)
320 index = scpi_alloc_mbox_chan();
324 data = scpi_buf->data;
325 data->cmd = PACK_SCPI_CMD(data->cmd, scpi_buf->client_id,
327 data->cl_data = scpi_buf;
329 return send_scpi_cmd(scpi_buf, index);
332 unsigned long scpi_clk_get_val(u16 clk_id)
334 struct scpi_data_buf sdata;
335 struct rk3368_mbox_msg mdata;
341 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
342 SCPI_CMD_GET_CLOCK_VALUE, clk_id, buf);
343 if (scpi_execute_cmd(&sdata))
348 EXPORT_SYMBOL_GPL(scpi_clk_get_val);
350 int scpi_clk_set_val(u16 clk_id, unsigned long rate)
352 struct scpi_data_buf sdata;
353 struct rk3368_mbox_msg mdata;
360 buf.clk_rate = (u32)rate;
363 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
364 SCPI_CMD_SET_CLOCK_VALUE, buf, stat);
365 return scpi_execute_cmd(&sdata);
367 EXPORT_SYMBOL_GPL(scpi_clk_set_val);
369 struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
371 struct scpi_data_buf sdata;
372 struct rk3368_mbox_msg mdata;
376 struct scpi_opp_entry opp[MAX_DVFS_OPPS];
378 struct scpi_opp *opps;
382 if (domain >= MAX_DVFS_DOMAINS)
383 return ERR_PTR(-EINVAL);
385 if (scpi_opps[domain]) /* data already populated */
386 return scpi_opps[domain];
388 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
389 SCPI_CMD_GET_DVFS_INFO, domain, buf);
390 ret = scpi_execute_cmd(&sdata);
394 opps = kmalloc(sizeof(*opps), GFP_KERNEL);
396 return ERR_PTR(-ENOMEM);
398 count = DVFS_OPP_COUNT(buf.header);
399 opps_sz = count * sizeof(*(opps->opp));
402 opps->latency = DVFS_LATENCY(buf.header);
403 opps->opp = kmalloc(opps_sz, GFP_KERNEL);
406 return ERR_PTR(-ENOMEM);
409 memcpy(opps->opp, &buf.opp[0], opps_sz);
410 scpi_opps[domain] = opps;
414 EXPORT_SYMBOL_GPL(scpi_dvfs_get_opps);
416 int scpi_dvfs_get_idx(u8 domain)
418 struct scpi_data_buf sdata;
419 struct rk3368_mbox_msg mdata;
426 if (domain >= MAX_DVFS_DOMAINS)
429 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
430 SCPI_CMD_GET_DVFS, domain, buf);
431 ret = scpi_execute_cmd(&sdata);
437 EXPORT_SYMBOL_GPL(scpi_dvfs_get_idx);
439 int scpi_dvfs_set_idx(u8 domain, u8 idx)
441 struct scpi_data_buf sdata;
442 struct rk3368_mbox_msg mdata;
450 buf.dvfs_domain = domain;
452 if (domain >= MAX_DVFS_DOMAINS)
455 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
456 SCPI_CMD_SET_DVFS, buf, stat);
457 return scpi_execute_cmd(&sdata);
459 EXPORT_SYMBOL_GPL(scpi_dvfs_set_idx);
461 int scpi_get_sensor(char *name)
463 struct scpi_data_buf sdata;
464 struct rk3368_mbox_msg mdata;
479 /* This should be handled by a generic macro */
481 struct rk3368_mbox_msg *pdata = &mdata;
483 pdata->cmd = SCPI_CMD_SENSOR_CAPABILITIES;
485 pdata->rx_buf = &cap_buf;
486 pdata->rx_size = sizeof(cap_buf);
487 sdata.client_id = SCPI_CL_THERMAL;
491 ret = scpi_execute_cmd(&sdata);
496 for (sensor_id = 0; sensor_id < cap_buf.sensors; sensor_id++) {
497 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
498 SCPI_CMD_SENSOR_INFO, sensor_id, info_buf);
499 ret = scpi_execute_cmd(&sdata);
503 if (!strcmp(name, info_buf.name)) {
511 EXPORT_SYMBOL_GPL(scpi_get_sensor);
513 int scpi_get_sensor_value(u16 sensor, u32 *val)
515 struct scpi_data_buf sdata;
516 struct rk3368_mbox_msg mdata;
523 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL, SCPI_CMD_SENSOR_VALUE,
526 ret = scpi_execute_cmd(&sdata);
532 EXPORT_SYMBOL_GPL(scpi_get_sensor_value);
534 static int scpi_get_version(u32 old, struct scpi_mcu_ver *ver)
537 struct scpi_data_buf sdata;
538 struct rk3368_mbox_msg mdata;
541 struct scpi_mcu_ver version;
544 memset(&buf, 0, sizeof(buf));
545 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS, SCPI_SYS_GET_VERSION,
548 ret = scpi_execute_cmd(&sdata);
550 pr_err("get scpi version from MCU failed, ret=%d\n", ret);
554 memcpy(ver, &(buf.version), sizeof(*ver));
560 int scpi_sys_set_mcu_state_suspend(void)
562 struct scpi_data_buf sdata;
563 struct rk3368_mbox_msg mdata;
572 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
573 SCPI_SYS_SET_MCU_STATE_SUSPEND, tx_buf, rx_buf);
574 return scpi_execute_cmd(&sdata);
576 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_suspend);
578 int scpi_sys_set_mcu_state_resume(void)
580 struct scpi_data_buf sdata;
581 struct rk3368_mbox_msg mdata;
591 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
592 SCPI_SYS_SET_MCU_STATE_RESUME, tx_buf, rx_buf);
593 return scpi_execute_cmd(&sdata);
595 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_resume);
597 int scpi_sys_set_jtagmux_on_off(u32 en)
600 struct scpi_data_buf sdata;
601 struct rk3368_mbox_msg mdata;
611 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
612 SCPI_SYS_SET_JTAGMUX_ON_OFF, tx_buf, rx_buf);
614 ret = scpi_execute_cmd(&sdata);
616 pr_err("set jtagmux on-off failed, ret=%d\n", ret);
622 EXPORT_SYMBOL_GPL(scpi_sys_set_jtagmux_on_off);
624 int scpi_ddr_dclk_mode(u32 dclk_mode)
626 struct scpi_data_buf sdata;
627 struct rk3368_mbox_msg mdata;
635 tx_buf.dclk_mode = (u32)dclk_mode;
636 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
637 SCPI_DDR_DCLK_MODE, tx_buf, rx_buf);
638 return scpi_execute_cmd(&sdata);
640 EXPORT_SYMBOL_GPL(scpi_ddr_dclk_mode);
642 int scpi_ddr_init(u32 dram_speed_bin, u32 freq, u32 lcdc_type, u32 addr_mcu_el3)
644 struct scpi_data_buf sdata;
645 struct rk3368_mbox_msg mdata;
656 tx_buf.dram_speed_bin = (u32)dram_speed_bin;
657 tx_buf.freq = (u32)freq;
658 tx_buf.lcdc_type = (u32)lcdc_type;
659 tx_buf.addr_mcu_el3 = addr_mcu_el3;
660 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
661 SCPI_DDR_INIT, tx_buf, rx_buf);
662 return scpi_execute_cmd(&sdata);
664 EXPORT_SYMBOL_GPL(scpi_ddr_init);
666 int scpi_ddr_set_clk_rate(u32 rate, u32 lcdc_type)
670 struct scpi_data_buf sdata;
671 struct rk3368_mbox_msg mdata;
681 tx_buf.clk_rate = (u32)rate;
682 tx_buf.lcdc_type = (u32)lcdc_type;
683 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
684 SCPI_DDR_SET_FREQ, tx_buf, rx_buf);
685 ret = scpi_execute_cmd(&sdata);
687 if ((!ret) && (!rx_buf.status))
694 EXPORT_SYMBOL_GPL(scpi_ddr_set_clk_rate);
696 int scpi_ddr_send_timing(u32 *p, u32 size)
698 struct scpi_data_buf sdata;
699 struct rk3368_mbox_msg mdata;
703 SCPI_SETUP_DBUF_BY_SIZE(sdata, mdata, SCPI_CL_DDR,
704 SCPI_DDR_SEND_TIMING, p, size, rx_buf);
705 return scpi_execute_cmd(&sdata);
707 EXPORT_SYMBOL_GPL(scpi_ddr_send_timing);
709 int scpi_ddr_round_rate(u32 m_hz)
711 struct scpi_data_buf sdata;
712 struct rk3368_mbox_msg mdata;
721 tx_buf.clk_rate = (u32)m_hz;
723 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
724 SCPI_DDR_ROUND_RATE, tx_buf, rx_buf);
725 if (scpi_execute_cmd(&sdata))
728 return rx_buf.round_rate;
730 EXPORT_SYMBOL_GPL(scpi_ddr_round_rate);
732 int scpi_ddr_set_auto_self_refresh(u32 en)
734 struct scpi_data_buf sdata;
735 struct rk3368_mbox_msg mdata;
743 tx_buf.enable = (u32)en;
745 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
746 SCPI_DDR_AUTO_SELF_REFRESH, tx_buf, rx_buf);
747 return scpi_execute_cmd(&sdata);
749 EXPORT_SYMBOL_GPL(scpi_ddr_set_auto_self_refresh);
751 int scpi_ddr_bandwidth_get(struct ddr_bw_info *ddr_bw_ch0,
752 struct ddr_bw_info *ddr_bw_ch1)
754 struct scpi_data_buf sdata;
755 struct rk3368_mbox_msg mdata;
761 struct ddr_bw_info ddr_bw_ch0;
762 struct ddr_bw_info ddr_bw_ch1;
767 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
768 SCPI_DDR_BANDWIDTH_GET, tx_buf, rx_buf);
769 if (scpi_execute_cmd(&sdata))
772 memcpy(ddr_bw_ch0, &(rx_buf.ddr_bw_ch0), sizeof(rx_buf.ddr_bw_ch0));
773 memcpy(ddr_bw_ch1, &(rx_buf.ddr_bw_ch1), sizeof(rx_buf.ddr_bw_ch1));
777 EXPORT_SYMBOL_GPL(scpi_ddr_bandwidth_get);
779 int scpi_ddr_get_clk_rate(void)
781 struct scpi_data_buf sdata;
782 struct rk3368_mbox_msg mdata;
792 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
793 SCPI_DDR_GET_FREQ, tx_buf, rx_buf);
794 if (scpi_execute_cmd(&sdata))
797 return rx_buf.clk_rate;
799 EXPORT_SYMBOL_GPL(scpi_ddr_get_clk_rate);
801 int scpi_thermal_get_temperature(void)
804 struct scpi_data_buf sdata;
805 struct rk3368_mbox_msg mdata;
816 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
817 SCPI_THERMAL_GET_TSADC_DATA, tx_buf, rx_buf);
819 ret = scpi_execute_cmd(&sdata);
821 pr_err("get temperature from MCU failed, ret=%d\n", ret);
825 return rx_buf.tsadc_data;
827 EXPORT_SYMBOL_GPL(scpi_thermal_get_temperature);
829 int scpi_thermal_set_clk_cycle(u32 cycle)
831 struct scpi_data_buf sdata;
832 struct rk3368_mbox_msg mdata;
841 tx_buf.clk_cycle = cycle;
842 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
843 SCPI_THERMAL_SET_TSADC_CYCLE, tx_buf, rx_buf);
845 return scpi_execute_cmd(&sdata);
847 EXPORT_SYMBOL_GPL(scpi_thermal_set_clk_cycle);
849 static struct of_device_id mobx_scpi_of_match[] = {
850 { .compatible = "rockchip,rk3368-scpi-legacy"},
853 MODULE_DEVICE_TABLE(of, mobx_scpi_of_match);
855 static int mobx_scpi_probe(struct platform_device *pdev)
860 struct scpi_mcu_ver mcu_ver;
861 int check_version = 1; /*0: not check version, 1: check version*/
863 the_scpi_device = &pdev->dev;
865 /* try to get mboxes chan nums from DT */
866 if (of_property_read_u32((&pdev->dev)->of_node, "chan-nums", &val)) {
867 dev_err(&pdev->dev, "parse mboxes chan-nums failed\n");
874 /* try to check up with SCPI version from MCU */
875 while ((retry--) && (check_version != 0)) {
876 memset(&mcu_ver, 0, sizeof(mcu_ver));
878 ret = scpi_get_version(SCPI_VERSION, &mcu_ver);
879 if ((ret == 0) && (mcu_ver.scpi_ver == SCPI_VERSION))
883 if ((retry <= 0) && (check_version != 0)) {
885 "Scpi verison not match:kernel ver:0x%x, MCU ver:0x%x, ret=%d\n",
886 SCPI_VERSION, mcu_ver.scpi_ver, ret);
891 dev_info(&pdev->dev, "Scpi initialize, version: 0x%x, chan nums: %d\n",
895 dev_info(&pdev->dev, "MCU version: %s\n", mcu_ver.mcu_ver);
899 the_scpi_device = NULL;
903 static struct platform_driver mbox_scpi_driver = {
904 .probe = mobx_scpi_probe,
907 .of_match_table = of_match_ptr(mobx_scpi_of_match),
911 static int __init rockchip_mbox_scpi_init(void)
913 return platform_driver_register(&mbox_scpi_driver);
915 subsys_initcall(rockchip_mbox_scpi_init);