2 * System Control and Power Interface (SCPI) Message Protocol driver
4 * Copyright (C) 2014 ARM Ltd.
5 * Copyright (c) 2014, 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/scpi_protocol.h>
28 #include <linux/slab.h>
29 #include <linux/rockchip-mailbox.h>
30 #include <linux/rockchip/common.h>
34 #define CMD_ID_SHIFT 0
35 #define CMD_ID_MASK 0xff
36 #define CMD_SENDER_ID_SHIFT 8
37 #define CMD_SENDER_ID_MASK 0xff
38 #define CMD_DATA_SIZE_SHIFT 20
39 #define CMD_DATA_SIZE_MASK 0x1ff
40 #define PACK_SCPI_CMD(cmd, sender, txsz) \
41 ((((cmd) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
42 (((sender) & CMD_SENDER_ID_MASK) << CMD_SENDER_ID_SHIFT) | \
43 (((txsz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
44 #define SCPI_CMD_DEFAULT_TIMEOUT_MS 1000
46 #define MAX_DVFS_DOMAINS 3
47 #define MAX_DVFS_OPPS 8
48 #define DVFS_LATENCY(hdr) ((hdr) >> 16)
49 #define DVFS_OPP_COUNT(hdr) (((hdr) >> 8) & 0xff)
51 static int max_chan_num = 0;
52 static DECLARE_BITMAP(bm_mbox_chans, 4);
53 static DEFINE_MUTEX(scpi_mtx);
55 struct scpi_data_buf {
57 struct rockchip_mbox_msg *data;
58 struct completion complete;
67 static int high_priority_cmds[] = {
68 SCPI_CMD_GET_CSS_PWR_STATE,
69 SCPI_CMD_CFG_PWR_STATE_STAT,
70 SCPI_CMD_GET_PWR_STATE_STAT,
75 SCPI_CMD_SET_CLOCK_INDEX,
76 SCPI_CMD_SET_CLOCK_VALUE,
77 SCPI_CMD_GET_CLOCK_VALUE,
80 SCPI_CMD_SENSOR_CFG_PERIODIC,
81 SCPI_CMD_SENSOR_CFG_BOUNDS,
84 static struct scpi_opp *scpi_opps[MAX_DVFS_DOMAINS];
86 static struct device *the_scpi_device;
88 static int scpi_linux_errmap[SCPI_ERR_MAX] = {
89 0, -EINVAL, -ENOEXEC, -EMSGSIZE,
90 -EINVAL, -EACCES, -ERANGE, -ETIMEDOUT,
91 -ENOMEM, -EINVAL, -EOPNOTSUPP, -EIO,
94 static inline int scpi_to_linux_errno(int errno)
96 if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
97 return scpi_linux_errmap[errno];
101 static bool __maybe_unused high_priority_chan_supported(int cmd)
105 for (idx = 0; idx < ARRAY_SIZE(high_priority_cmds); idx++)
106 if (cmd == high_priority_cmds[idx])
111 static int scpi_alloc_mbox_chan(void)
115 mutex_lock(&scpi_mtx);
117 index = find_first_zero_bit(bm_mbox_chans, max_chan_num);
118 if (index >= max_chan_num) {
119 pr_err("alloc mailbox channel failed\n");
120 mutex_unlock(&scpi_mtx);
124 set_bit(index, bm_mbox_chans);
126 mutex_unlock(&scpi_mtx);
130 static void scpi_free_mbox_chan(int chan)
134 mutex_lock(&scpi_mtx);
136 if (index < max_chan_num && index >= 0)
137 clear_bit(index, bm_mbox_chans);
139 mutex_unlock(&scpi_mtx);
142 static void scpi_rx_callback(struct mbox_client *cl, void *msg)
144 struct rockchip_mbox_msg *data = (struct rockchip_mbox_msg *)msg;
145 struct scpi_data_buf *scpi_buf = data->cl_data;
147 complete(&scpi_buf->complete);
150 static int send_scpi_cmd(struct scpi_data_buf *scpi_buf, int index)
152 struct mbox_chan *chan;
153 struct mbox_client cl;
154 struct rockchip_mbox_msg *data = scpi_buf->data;
157 int timeout = msecs_to_jiffies(scpi_buf->timeout_ms);
159 if (!the_scpi_device) {
160 pr_err("Scpi initializes unsuccessfully\n");
164 cl.dev = the_scpi_device;
165 cl.rx_callback = scpi_rx_callback;
168 cl.knows_txdone = false;
170 chan = mbox_request_channel(&cl, index);
172 scpi_free_mbox_chan(index);
173 return PTR_ERR(chan);
176 init_completion(&scpi_buf->complete);
177 if (mbox_send_message(chan, (void *)data) < 0) {
178 status = SCPI_ERR_TIMEOUT;
182 ret = wait_for_completion_timeout(&scpi_buf->complete, timeout);
184 status = SCPI_ERR_TIMEOUT;
187 status = *(u32 *)(data->rx_buf); /* read first word */
190 mbox_free_channel(chan);
191 scpi_free_mbox_chan(index);
193 return scpi_to_linux_errno(status);
196 #define SCPI_SETUP_DBUF(scpi_buf, mbox_buf, _client_id,\
197 _cmd, _tx_buf, _rx_buf) \
199 struct rockchip_mbox_msg *pdata = &mbox_buf; \
201 pdata->tx_buf = &_tx_buf; \
202 pdata->tx_size = sizeof(_tx_buf); \
203 pdata->rx_buf = &_rx_buf; \
204 pdata->rx_size = sizeof(_rx_buf); \
205 scpi_buf.client_id = _client_id; \
206 scpi_buf.data = pdata; \
207 scpi_buf.timeout_ms = SCPI_CMD_DEFAULT_TIMEOUT_MS; \
210 #define SCPI_SETUP_DBUF_BY_SIZE(scpi_buf, mbox_buf, _client_id, \
211 _cmd, _tx_buf, _tx_size, _rx_buf) \
213 struct rockchip_mbox_msg *pdata = &mbox_buf; \
215 pdata->tx_buf = _tx_buf; \
216 pdata->tx_size = _tx_size; \
217 pdata->rx_buf = &_rx_buf; \
218 pdata->rx_size = sizeof(_rx_buf); \
219 scpi_buf.client_id = _client_id; \
220 scpi_buf.data = pdata; \
221 scpi_buf.timeout_ms = SCPI_CMD_DEFAULT_TIMEOUT_MS; \
224 static int scpi_execute_cmd(struct scpi_data_buf *scpi_buf)
226 struct rockchip_mbox_msg *data;
229 if (!scpi_buf || !scpi_buf->data)
232 index = scpi_alloc_mbox_chan();
236 data = scpi_buf->data;
237 data->cmd = PACK_SCPI_CMD(data->cmd, scpi_buf->client_id,
239 data->cl_data = scpi_buf;
241 return send_scpi_cmd(scpi_buf, index);
244 unsigned long scpi_clk_get_val(u16 clk_id)
246 struct scpi_data_buf sdata;
247 struct rockchip_mbox_msg mdata;
253 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
254 SCPI_CMD_GET_CLOCK_VALUE, clk_id, buf);
255 if (scpi_execute_cmd(&sdata))
260 EXPORT_SYMBOL_GPL(scpi_clk_get_val);
262 int scpi_clk_set_val(u16 clk_id, unsigned long rate)
264 struct scpi_data_buf sdata;
265 struct rockchip_mbox_msg mdata;
272 buf.clk_rate = (u32)rate;
275 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
276 SCPI_CMD_SET_CLOCK_VALUE, buf, stat);
277 return scpi_execute_cmd(&sdata);
279 EXPORT_SYMBOL_GPL(scpi_clk_set_val);
281 struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
283 struct scpi_data_buf sdata;
284 struct rockchip_mbox_msg mdata;
288 struct scpi_opp_entry opp[MAX_DVFS_OPPS];
290 struct scpi_opp *opps;
294 if (domain >= MAX_DVFS_DOMAINS)
295 return ERR_PTR(-EINVAL);
297 if (scpi_opps[domain]) /* data already populated */
298 return scpi_opps[domain];
300 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
301 SCPI_CMD_GET_DVFS_INFO, domain, buf);
302 ret = scpi_execute_cmd(&sdata);
306 opps = kmalloc(sizeof(*opps), GFP_KERNEL);
308 return ERR_PTR(-ENOMEM);
310 count = DVFS_OPP_COUNT(buf.header);
311 opps_sz = count * sizeof(*(opps->opp));
314 opps->latency = DVFS_LATENCY(buf.header);
315 opps->opp = kmalloc(opps_sz, GFP_KERNEL);
318 return ERR_PTR(-ENOMEM);
321 memcpy(opps->opp, &buf.opp[0], opps_sz);
322 scpi_opps[domain] = opps;
326 EXPORT_SYMBOL_GPL(scpi_dvfs_get_opps);
328 int scpi_dvfs_get_idx(u8 domain)
330 struct scpi_data_buf sdata;
331 struct rockchip_mbox_msg mdata;
338 if (domain >= MAX_DVFS_DOMAINS)
341 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
342 SCPI_CMD_GET_DVFS, domain, buf);
343 ret = scpi_execute_cmd(&sdata);
349 EXPORT_SYMBOL_GPL(scpi_dvfs_get_idx);
351 int scpi_dvfs_set_idx(u8 domain, u8 idx)
353 struct scpi_data_buf sdata;
354 struct rockchip_mbox_msg mdata;
362 buf.dvfs_domain = domain;
364 if (domain >= MAX_DVFS_DOMAINS)
367 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
368 SCPI_CMD_SET_DVFS, buf, stat);
369 return scpi_execute_cmd(&sdata);
371 EXPORT_SYMBOL_GPL(scpi_dvfs_set_idx);
373 int scpi_get_sensor(char *name)
375 struct scpi_data_buf sdata;
376 struct rockchip_mbox_msg mdata;
391 /* This should be handled by a generic macro */
393 struct rockchip_mbox_msg *pdata = &mdata;
395 pdata->cmd = SCPI_CMD_SENSOR_CAPABILITIES;
397 pdata->rx_buf = &cap_buf;
398 pdata->rx_size = sizeof(cap_buf);
399 sdata.client_id = SCPI_CL_THERMAL;
403 ret = scpi_execute_cmd(&sdata);
408 for (sensor_id = 0; sensor_id < cap_buf.sensors; sensor_id++) {
409 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
410 SCPI_CMD_SENSOR_INFO, sensor_id, info_buf);
411 ret = scpi_execute_cmd(&sdata);
415 if (!strcmp(name, info_buf.name)) {
423 EXPORT_SYMBOL_GPL(scpi_get_sensor);
425 int scpi_get_sensor_value(u16 sensor, u32 *val)
427 struct scpi_data_buf sdata;
428 struct rockchip_mbox_msg mdata;
435 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL, SCPI_CMD_SENSOR_VALUE,
438 ret = scpi_execute_cmd(&sdata);
444 EXPORT_SYMBOL_GPL(scpi_get_sensor_value);
446 static int scpi_get_version(u32 old, struct scpi_mcu_ver *ver)
449 struct scpi_data_buf sdata;
450 struct rockchip_mbox_msg mdata;
453 struct scpi_mcu_ver version;
456 memset(&buf, 0, sizeof(buf));
457 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS, SCPI_SYS_GET_VERSION,
460 ret = scpi_execute_cmd(&sdata);
462 pr_err("get scpi version from MCU failed, ret=%d\n", ret);
466 memcpy(ver, &(buf.version), sizeof(*ver));
472 int scpi_sys_set_mcu_state_suspend(void)
474 struct scpi_data_buf sdata;
475 struct rockchip_mbox_msg mdata;
484 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
485 SCPI_SYS_SET_MCU_STATE_SUSPEND, tx_buf, rx_buf);
486 return scpi_execute_cmd(&sdata);
488 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_suspend);
490 int scpi_sys_set_mcu_state_resume(void)
492 struct scpi_data_buf sdata;
493 struct rockchip_mbox_msg mdata;
503 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
504 SCPI_SYS_SET_MCU_STATE_RESUME, tx_buf, rx_buf);
505 return scpi_execute_cmd(&sdata);
507 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_resume);
509 int scpi_ddr_init(u32 dram_speed_bin, u32 freq, u32 lcdc_type, u32 addr_mcu_el3)
511 struct scpi_data_buf sdata;
512 struct rockchip_mbox_msg mdata;
523 tx_buf.dram_speed_bin = (u32)dram_speed_bin;
524 tx_buf.freq = (u32)freq;
525 tx_buf.lcdc_type = (u32)lcdc_type;
526 tx_buf.addr_mcu_el3 = addr_mcu_el3;
527 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
528 SCPI_DDR_INIT, tx_buf, rx_buf);
529 return scpi_execute_cmd(&sdata);
531 EXPORT_SYMBOL_GPL(scpi_ddr_init);
533 int scpi_ddr_set_clk_rate(u32 rate, u32 lcdc_type)
535 struct scpi_data_buf sdata;
536 struct rockchip_mbox_msg mdata;
545 tx_buf.clk_rate = (u32)rate;
546 tx_buf.lcdc_type = (u32)lcdc_type;
547 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
548 SCPI_DDR_SET_FREQ, tx_buf, rx_buf);
549 return scpi_execute_cmd(&sdata);
551 EXPORT_SYMBOL_GPL(scpi_ddr_set_clk_rate);
553 int scpi_ddr_send_timing(u32 *p, u32 size)
555 struct scpi_data_buf sdata;
556 struct rockchip_mbox_msg mdata;
560 SCPI_SETUP_DBUF_BY_SIZE(sdata, mdata, SCPI_CL_DDR,
561 SCPI_DDR_SEND_TIMING, p, size, rx_buf);
562 return scpi_execute_cmd(&sdata);
564 EXPORT_SYMBOL_GPL(scpi_ddr_send_timing);
566 int scpi_ddr_round_rate(u32 m_hz)
568 struct scpi_data_buf sdata;
569 struct rockchip_mbox_msg mdata;
578 tx_buf.clk_rate = (u32)m_hz;
580 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
581 SCPI_DDR_ROUND_RATE, tx_buf, rx_buf);
582 if (scpi_execute_cmd(&sdata))
585 return rx_buf.round_rate;
587 EXPORT_SYMBOL_GPL(scpi_ddr_round_rate);
589 int scpi_ddr_set_auto_self_refresh(u32 en)
591 struct scpi_data_buf sdata;
592 struct rockchip_mbox_msg mdata;
600 tx_buf.enable = (u32)en;
602 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
603 SCPI_DDR_AUTO_SELF_REFRESH, tx_buf, rx_buf);
604 return scpi_execute_cmd(&sdata);
606 EXPORT_SYMBOL_GPL(scpi_ddr_set_auto_self_refresh);
608 int scpi_ddr_bandwidth_get(struct ddr_bw_info *ddr_bw_ch0,
609 struct ddr_bw_info *ddr_bw_ch1)
611 struct scpi_data_buf sdata;
612 struct rockchip_mbox_msg mdata;
618 struct ddr_bw_info ddr_bw_ch0;
619 struct ddr_bw_info ddr_bw_ch1;
624 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
625 SCPI_DDR_BANDWIDTH_GET, tx_buf, rx_buf);
626 if (scpi_execute_cmd(&sdata))
629 memcpy(ddr_bw_ch0, &(rx_buf.ddr_bw_ch0), sizeof(rx_buf.ddr_bw_ch0));
630 memcpy(ddr_bw_ch1, &(rx_buf.ddr_bw_ch1), sizeof(rx_buf.ddr_bw_ch1));
634 EXPORT_SYMBOL_GPL(scpi_ddr_bandwidth_get);
636 int scpi_ddr_get_clk_rate(void)
638 struct scpi_data_buf sdata;
639 struct rockchip_mbox_msg mdata;
649 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
650 SCPI_DDR_GET_FREQ, tx_buf, rx_buf);
651 if (scpi_execute_cmd(&sdata))
654 return rx_buf.clk_rate;
656 EXPORT_SYMBOL_GPL(scpi_ddr_get_clk_rate);
658 int scpi_thermal_get_temperature(void)
661 struct scpi_data_buf sdata;
662 struct rockchip_mbox_msg mdata;
673 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
674 SCPI_THERMAL_GET_TSADC_DATA, tx_buf, rx_buf);
676 ret = scpi_execute_cmd(&sdata);
678 pr_err("get temperature from MCU failed, ret=%d\n", ret);
682 return rx_buf.tsadc_data;
684 EXPORT_SYMBOL_GPL(scpi_thermal_get_temperature);
686 int scpi_thermal_set_clk_cycle(u32 cycle)
688 struct scpi_data_buf sdata;
689 struct rockchip_mbox_msg mdata;
698 tx_buf.clk_cycle = cycle;
699 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
700 SCPI_THERMAL_SET_TSADC_CYCLE, tx_buf, rx_buf);
702 return scpi_execute_cmd(&sdata);
704 EXPORT_SYMBOL_GPL(scpi_thermal_set_clk_cycle);
706 static struct of_device_id mobx_scpi_of_match[] = {
707 { .compatible = "rockchip,mbox-scpi"},
710 MODULE_DEVICE_TABLE(of, mobx_scpi_of_match);
712 static int mobx_scpi_probe(struct platform_device *pdev)
717 struct scpi_mcu_ver mcu_ver;
718 int check_version = 1; /*0: not check version, 1: check version*/
720 the_scpi_device = &pdev->dev;
722 /* try to get mboxes chan nums from DT */
723 if (of_property_read_u32((&pdev->dev)->of_node, "chan-nums", &val)) {
724 dev_err(&pdev->dev, "parse mboxes chan-nums failed\n");
731 /* try to check up with SCPI version from MCU */
732 while ((retry--) && (check_version != 0)) {
733 memset(&mcu_ver, 0, sizeof(mcu_ver));
735 ret = scpi_get_version(SCPI_VERSION, &mcu_ver);
736 if ((ret == 0) && (mcu_ver.scpi_ver == SCPI_VERSION))
740 if ((retry <= 0) && (check_version != 0)) {
742 "Scpi verison not match:kernel ver:0x%x, MCU ver:0x%x, ret=%d\n",
743 SCPI_VERSION, mcu_ver.scpi_ver, ret);
748 dev_info(&pdev->dev, "Scpi initialize, version: 0x%x, chan nums: %d\n",
749 mcu_ver.scpi_ver, val);
750 dev_info(&pdev->dev, "MCU version: %s\n", mcu_ver.mcu_ver);
754 the_scpi_device = NULL;
758 static struct platform_driver mbox_scpi_driver = {
759 .probe = mobx_scpi_probe,
762 .of_match_table = of_match_ptr(mobx_scpi_of_match),
766 static int __init rockchip_mbox_scpi_init(void)
768 return platform_driver_register(&mbox_scpi_driver);
770 subsys_initcall(rockchip_mbox_scpi_init);