51d8feb8b782cd871f9d6c9c9cd6e81ed4d9ec64
[firefly-linux-kernel-4.4.55.git] / drivers / mailbox / scpi_protocol.c
1 /*
2  * System Control and Power Interface (SCPI) Message Protocol driver
3  *
4  * Copyright (C) 2014 ARM Ltd.
5  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
6  *
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.
10  *
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
14  * more details.
15  *
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/>.
18  */
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>
31
32 #include "scpi_cmd.h"
33
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
45
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)
50
51 struct scpi_data_buf {
52         int client_id;
53         struct rockchip_mbox_msg *data;
54         struct completion complete;
55         int timeout_ms;
56 };
57
58 static int high_priority_cmds[] = {
59         SCPI_CMD_GET_CSS_PWR_STATE,
60         SCPI_CMD_CFG_PWR_STATE_STAT,
61         SCPI_CMD_GET_PWR_STATE_STAT,
62         SCPI_CMD_SET_DVFS,
63         SCPI_CMD_GET_DVFS,
64         SCPI_CMD_SET_RTC,
65         SCPI_CMD_GET_RTC,
66         SCPI_CMD_SET_CLOCK_INDEX,
67         SCPI_CMD_SET_CLOCK_VALUE,
68         SCPI_CMD_GET_CLOCK_VALUE,
69         SCPI_CMD_SET_PSU,
70         SCPI_CMD_GET_PSU,
71         SCPI_CMD_SENSOR_CFG_PERIODIC,
72         SCPI_CMD_SENSOR_CFG_BOUNDS,
73 };
74
75 static struct scpi_opp *scpi_opps[MAX_DVFS_DOMAINS];
76
77 static struct device *the_scpi_device;
78
79 static int scpi_linux_errmap[SCPI_ERR_MAX] = {
80         0, -EINVAL, -ENOEXEC, -EMSGSIZE,
81         -EINVAL, -EACCES, -ERANGE, -ETIMEDOUT,
82         -ENOMEM, -EINVAL, -EOPNOTSUPP, -EIO,
83 };
84
85 static inline int scpi_to_linux_errno(int errno)
86 {
87         if (errno >= SCPI_SUCCESS && errno < SCPI_ERR_MAX)
88                 return scpi_linux_errmap[errno];
89         return -EIO;
90 }
91
92 static bool high_priority_chan_supported(int cmd)
93 {
94         int idx;
95
96         for (idx = 0; idx < ARRAY_SIZE(high_priority_cmds); idx++)
97                 if (cmd == high_priority_cmds[idx])
98                         return true;
99         return false;
100 }
101
102 static void scpi_rx_callback(struct mbox_client *cl, void *msg)
103 {
104         struct rockchip_mbox_msg *data = (struct rockchip_mbox_msg *)msg;
105         struct scpi_data_buf *scpi_buf = data->cl_data;
106
107         complete(&scpi_buf->complete);
108 }
109
110 static int send_scpi_cmd(struct scpi_data_buf *scpi_buf, bool high_priority)
111 {
112         struct mbox_chan *chan;
113         struct mbox_client cl;
114         struct rockchip_mbox_msg *data = scpi_buf->data;
115         u32 status;
116         int ret;
117         int timeout = msecs_to_jiffies(scpi_buf->timeout_ms);
118
119         if (!the_scpi_device) {
120                 pr_err("Scpi initializes unsuccessfully\n");
121                 return -EIO;
122         }
123
124         cl.dev = the_scpi_device;
125         cl.rx_callback = scpi_rx_callback;
126         cl.tx_done = NULL;
127         cl.tx_block = false;
128         cl.knows_txdone = false;
129
130         chan = mbox_request_channel(&cl, high_priority);
131         if (IS_ERR(chan))
132                 return PTR_ERR(chan);
133
134         init_completion(&scpi_buf->complete);
135         if (mbox_send_message(chan, (void *)data) < 0) {
136                 status = SCPI_ERR_TIMEOUT;
137                 goto free_channel;
138         }
139
140         ret = wait_for_completion_timeout(&scpi_buf->complete, timeout);
141         if (ret == 0) {
142                 status = SCPI_ERR_TIMEOUT;
143                 goto free_channel;
144         }
145         status = *(u32 *)(data->rx_buf); /* read first word */
146
147 free_channel:
148         mbox_free_channel(chan);
149
150         return scpi_to_linux_errno(status);
151 }
152
153 #define SCPI_SETUP_DBUF(scpi_buf, mbox_buf, _client_id,\
154                         _cmd, _tx_buf, _rx_buf) \
155 do {                                            \
156         struct rockchip_mbox_msg *pdata = &mbox_buf;    \
157         pdata->cmd = _cmd;                      \
158         pdata->tx_buf = &_tx_buf;               \
159         pdata->tx_size = sizeof(_tx_buf);       \
160         pdata->rx_buf = &_rx_buf;               \
161         pdata->rx_size = sizeof(_rx_buf);       \
162         scpi_buf.client_id = _client_id;        \
163         scpi_buf.data = pdata;                  \
164         scpi_buf.timeout_ms = SCPI_CMD_DEFAULT_TIMEOUT_MS; \
165 } while (0)
166
167 static int scpi_execute_cmd(struct scpi_data_buf *scpi_buf)
168 {
169         struct rockchip_mbox_msg *data;
170         bool high_priority;
171
172         if (!scpi_buf || !scpi_buf->data)
173                 return -EINVAL;
174
175         data = scpi_buf->data;
176         high_priority = high_priority_chan_supported(data->cmd);
177         data->cmd = PACK_SCPI_CMD(data->cmd, scpi_buf->client_id,
178                                   data->tx_size);
179         data->cl_data = scpi_buf;
180
181         return send_scpi_cmd(scpi_buf, high_priority);
182 }
183
184 unsigned long scpi_clk_get_val(u16 clk_id)
185 {
186         struct scpi_data_buf sdata;
187         struct rockchip_mbox_msg mdata;
188         struct __packed {
189                 u32 status;
190                 u32 clk_rate;
191         } buf;
192
193         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
194                         SCPI_CMD_GET_CLOCK_VALUE, clk_id, buf);
195         if (scpi_execute_cmd(&sdata))
196                 return 0;
197
198         return buf.clk_rate;
199 }
200 EXPORT_SYMBOL_GPL(scpi_clk_get_val);
201
202 int scpi_clk_set_val(u16 clk_id, unsigned long rate)
203 {
204         struct scpi_data_buf sdata;
205         struct rockchip_mbox_msg mdata;
206         int stat;
207         struct __packed {
208                 u32 clk_rate;
209                 u16 clk_id;
210         } buf;
211
212         buf.clk_rate = (u32)rate;
213         buf.clk_id = clk_id;
214
215         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_CLOCKS,
216                         SCPI_CMD_SET_CLOCK_VALUE, buf, stat);
217         return scpi_execute_cmd(&sdata);
218 }
219 EXPORT_SYMBOL_GPL(scpi_clk_set_val);
220
221 struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
222 {
223         struct scpi_data_buf sdata;
224         struct rockchip_mbox_msg mdata;
225         struct __packed {
226                 u32 status;
227                 u32 header;
228                 struct scpi_opp_entry opp[MAX_DVFS_OPPS];
229         } buf;
230         struct scpi_opp *opps;
231         size_t opps_sz;
232         int count, ret;
233
234         if (domain >= MAX_DVFS_DOMAINS)
235                 return ERR_PTR(-EINVAL);
236
237         if (scpi_opps[domain])  /* data already populated */
238                 return scpi_opps[domain];
239
240         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
241                         SCPI_CMD_GET_DVFS_INFO, domain, buf);
242         ret = scpi_execute_cmd(&sdata);
243         if (ret)
244                 return ERR_PTR(ret);
245
246         opps = kmalloc(sizeof(*opps), GFP_KERNEL);
247         if (!opps)
248                 return ERR_PTR(-ENOMEM);
249
250         count = DVFS_OPP_COUNT(buf.header);
251         opps_sz = count * sizeof(*(opps->opp));
252
253         opps->count = count;
254         opps->latency = DVFS_LATENCY(buf.header);
255         opps->opp = kmalloc(opps_sz, GFP_KERNEL);
256         if (!opps->opp) {
257                 kfree(opps);
258                 return ERR_PTR(-ENOMEM);
259         }
260
261         memcpy(opps->opp, &buf.opp[0], opps_sz);
262         scpi_opps[domain] = opps;
263
264         return opps;
265 }
266 EXPORT_SYMBOL_GPL(scpi_dvfs_get_opps);
267
268 int scpi_dvfs_get_idx(u8 domain)
269 {
270         struct scpi_data_buf sdata;
271         struct rockchip_mbox_msg mdata;
272         struct __packed {
273                 u32 status;
274                 u8 dvfs_idx;
275         } buf;
276         int ret;
277
278         if (domain >= MAX_DVFS_DOMAINS)
279                 return -EINVAL;
280
281         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
282                         SCPI_CMD_GET_DVFS, domain, buf);
283         ret = scpi_execute_cmd(&sdata);
284
285         if (!ret)
286                 ret = buf.dvfs_idx;
287         return ret;
288 }
289 EXPORT_SYMBOL_GPL(scpi_dvfs_get_idx);
290
291 int scpi_dvfs_set_idx(u8 domain, u8 idx)
292 {
293         struct scpi_data_buf sdata;
294         struct rockchip_mbox_msg mdata;
295         struct __packed {
296                 u8 dvfs_domain;
297                 u8 dvfs_idx;
298         } buf;
299         int stat;
300
301         buf.dvfs_idx = idx;
302         buf.dvfs_domain = domain;
303
304         if (domain >= MAX_DVFS_DOMAINS)
305                 return -EINVAL;
306
307         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DVFS,
308                         SCPI_CMD_SET_DVFS, buf, stat);
309         return scpi_execute_cmd(&sdata);
310 }
311 EXPORT_SYMBOL_GPL(scpi_dvfs_set_idx);
312
313 int scpi_get_sensor(char *name)
314 {
315         struct scpi_data_buf sdata;
316         struct rockchip_mbox_msg mdata;
317         struct __packed {
318                 u32 status;
319                 u16 sensors;
320         } cap_buf;
321         struct __packed {
322                 u32 status;
323                 u16 sensor;
324                 u8 class;
325                 u8 trigger;
326                 char name[20];
327         } info_buf;
328         int ret;
329         u16 sensor_id;
330
331         /* This should be handled by a generic macro */
332         do {
333                 struct rockchip_mbox_msg *pdata = &mdata;
334
335                 pdata->cmd = SCPI_CMD_SENSOR_CAPABILITIES;
336                 pdata->tx_size = 0;
337                 pdata->rx_buf = &cap_buf;
338                 pdata->rx_size = sizeof(cap_buf);
339                 sdata.client_id = SCPI_CL_THERMAL;
340                 sdata.data = pdata;
341         } while (0);
342
343         ret = scpi_execute_cmd(&sdata);
344         if (ret)
345                 goto out;
346
347         ret = -ENODEV;
348         for (sensor_id = 0; sensor_id < cap_buf.sensors; sensor_id++) {
349                 SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
350                                 SCPI_CMD_SENSOR_INFO, sensor_id, info_buf);
351                 ret = scpi_execute_cmd(&sdata);
352                 if (ret)
353                         break;
354
355                 if (!strcmp(name, info_buf.name)) {
356                         ret = sensor_id;
357                         break;
358                 }
359         }
360 out:
361         return ret;
362 }
363 EXPORT_SYMBOL_GPL(scpi_get_sensor);
364
365 int scpi_get_sensor_value(u16 sensor, u32 *val)
366 {
367         struct scpi_data_buf sdata;
368         struct rockchip_mbox_msg mdata;
369         struct __packed {
370                 u32 status;
371                 u32 val;
372         } buf;
373         int ret;
374
375         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL, SCPI_CMD_SENSOR_VALUE,
376                         sensor, buf);
377
378         ret = scpi_execute_cmd(&sdata);
379         if (ret)
380                 *val = buf.val;
381
382         return ret;
383 }
384 EXPORT_SYMBOL_GPL(scpi_get_sensor_value);
385
386 static int scpi_get_version(u32 old, u32 *ver)
387 {
388         struct scpi_data_buf sdata;
389         struct rockchip_mbox_msg mdata;
390         struct __packed {
391                 u32 status;
392                 u32 ver;
393         } buf;
394         int ret;
395
396         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS, SCPI_SYS_GET_VERSION,
397                         old, buf);
398
399         ret = scpi_execute_cmd(&sdata);
400         if (ret)
401                 *ver = buf.ver;
402
403         return ret;
404 }
405
406 int scpi_sys_set_mcu_state_suspend(void)
407 {
408         struct scpi_data_buf sdata;
409         struct rockchip_mbox_msg mdata;
410         struct __packed1 {
411                 u32 status;
412         } tx_buf;
413         struct __packed2 {
414                 u32 status;
415         } rx_buf;
416
417         tx_buf.status = 0;
418         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
419                         SCPI_SYS_SET_MCU_STATE_SUSPEND, tx_buf, rx_buf);
420         return scpi_execute_cmd(&sdata);
421 }
422 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_suspend);
423
424 int scpi_sys_set_mcu_state_resume(void)
425 {
426         struct scpi_data_buf sdata;
427         struct rockchip_mbox_msg mdata;
428         struct __packed1 {
429                 u32 status;
430         } tx_buf;
431         struct __packed2 {
432                 u32 status;
433         } rx_buf;
434
435         tx_buf.status = 0;
436
437         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_SYS,
438                         SCPI_SYS_SET_MCU_STATE_RESUME, tx_buf, rx_buf);
439         return scpi_execute_cmd(&sdata);
440 }
441 EXPORT_SYMBOL_GPL(scpi_sys_set_mcu_state_resume);
442
443 int scpi_ddr_init(u32 dram_speed_bin, u32 freq, u32 lcdc_type)
444 {
445         struct scpi_data_buf sdata;
446         struct rockchip_mbox_msg mdata;
447         struct __packed1 {
448                 u32 dram_speed_bin;
449                 u32 freq;
450                 u32 lcdc_type;
451         } tx_buf;
452         struct __packed2 {
453                 u32 status;
454         } rx_buf;
455
456         tx_buf.dram_speed_bin = (u32)dram_speed_bin;
457         tx_buf.freq = (u32)freq;
458         tx_buf.lcdc_type = (u32)lcdc_type;
459
460         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
461                         SCPI_DDR_INIT, tx_buf, rx_buf);
462         return scpi_execute_cmd(&sdata);
463 }
464 EXPORT_SYMBOL_GPL(scpi_ddr_init);
465
466 int scpi_ddr_set_clk_rate(u32 rate, u32 lcdc_type)
467 {
468         struct scpi_data_buf sdata;
469         struct rockchip_mbox_msg mdata;
470         struct __packed1 {
471                 u32 clk_rate;
472                 u32 lcdc_type;
473         } tx_buf;
474         struct __packed2 {
475                 u32 status;
476         } rx_buf;
477
478         tx_buf.clk_rate = (u32)rate;
479         tx_buf.lcdc_type = (u32)lcdc_type;
480         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
481                         SCPI_DDR_SET_FREQ, tx_buf, rx_buf);
482         return scpi_execute_cmd(&sdata);
483 }
484 EXPORT_SYMBOL_GPL(scpi_ddr_set_clk_rate);
485
486 int scpi_ddr_round_rate(u32 m_hz)
487 {
488         struct scpi_data_buf sdata;
489         struct rockchip_mbox_msg mdata;
490         struct __packed1 {
491                 u32 clk_rate;
492         } tx_buf;
493         struct __packed2 {
494                 u32 status;
495                 u32 round_rate;
496         } rx_buf;
497
498         tx_buf.clk_rate = (u32)m_hz;
499
500         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
501                         SCPI_DDR_ROUND_RATE, tx_buf, rx_buf);
502         if (scpi_execute_cmd(&sdata))
503                 return 0;
504
505         return rx_buf.round_rate;
506 }
507 EXPORT_SYMBOL_GPL(scpi_ddr_round_rate);
508
509 int scpi_ddr_set_auto_self_refresh(u32 en)
510 {
511         struct scpi_data_buf sdata;
512         struct rockchip_mbox_msg mdata;
513         struct __packed1 {
514                 u32 enable;
515         } tx_buf;
516         struct __packed2 {
517                 u32 status;
518         } rx_buf;
519
520         tx_buf.enable = (u32)en;
521
522         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
523                         SCPI_DDR_AUTO_SELF_REFRESH, tx_buf, rx_buf);
524         return scpi_execute_cmd(&sdata);
525 }
526 EXPORT_SYMBOL_GPL(scpi_ddr_set_auto_self_refresh);
527
528 int scpi_ddr_bandwidth_get(struct ddr_bw_info *ddr_bw_ch0,
529                            struct ddr_bw_info *ddr_bw_ch1)
530 {
531         struct scpi_data_buf sdata;
532         struct rockchip_mbox_msg mdata;
533         struct __packed1 {
534                 u32 status;
535         } tx_buf;
536         struct __packed2 {
537                 u32 status;
538                 struct ddr_bw_info ddr_bw_ch0;
539                 struct ddr_bw_info ddr_bw_ch1;
540         } rx_buf;
541
542         tx_buf.status = 0;
543
544         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
545                         SCPI_DDR_BANDWIDTH_GET, tx_buf, rx_buf);
546         if (scpi_execute_cmd(&sdata))
547                 return 0;
548
549         memcpy(ddr_bw_ch0, &(rx_buf.ddr_bw_ch0), sizeof(rx_buf.ddr_bw_ch0));
550         memcpy(ddr_bw_ch1, &(rx_buf.ddr_bw_ch1), sizeof(rx_buf.ddr_bw_ch1));
551
552         return 0;
553 }
554 EXPORT_SYMBOL_GPL(scpi_ddr_bandwidth_get);
555
556 int scpi_ddr_get_clk_rate(void)
557 {
558         struct scpi_data_buf sdata;
559         struct rockchip_mbox_msg mdata;
560         struct __packed1 {
561                 u32 status;
562         } tx_buf;
563         struct __packed2 {
564                 u32 status;
565                 u32 clk_rate;
566         } rx_buf;
567
568         tx_buf.status = 0;
569         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_DDR,
570                         SCPI_DDR_GET_FREQ, tx_buf, rx_buf);
571         if (scpi_execute_cmd(&sdata))
572                 return 0;
573
574         return rx_buf.clk_rate;
575 }
576 EXPORT_SYMBOL_GPL(scpi_ddr_get_clk_rate);
577
578 int scpi_thermal_get_temperature(void)
579 {
580         struct scpi_data_buf sdata;
581         struct rockchip_mbox_msg mdata;
582         struct __packed1 {
583                 u32 status;
584         } tx_buf;
585
586         struct __packed2 {
587                 u32 status;
588                 u32 tsadc_data;
589         } rx_buf;
590
591         tx_buf.status = 0;
592         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
593                         SCPI_THERMAL_GET_TSADC_DATA, tx_buf, rx_buf);
594         if (scpi_execute_cmd(&sdata))
595                 return 0;
596
597         return rx_buf.tsadc_data;
598 }
599 EXPORT_SYMBOL_GPL(scpi_thermal_get_temperature);
600
601 int scpi_thermal_set_clk_cycle(u32 cycle)
602 {
603         struct scpi_data_buf sdata;
604         struct rockchip_mbox_msg mdata;
605         struct __packed1 {
606                 u32 clk_cycle;
607         } tx_buf;
608
609         struct __packed2 {
610                 u32 status;
611         } rx_buf;
612
613         tx_buf.clk_cycle = cycle;
614         SCPI_SETUP_DBUF(sdata, mdata, SCPI_CL_THERMAL,
615                         SCPI_THERMAL_SET_TSADC_CYCLE, tx_buf, rx_buf);
616
617         return scpi_execute_cmd(&sdata);
618 }
619 EXPORT_SYMBOL_GPL(scpi_thermal_set_clk_cycle);
620
621 static struct of_device_id mobx_scpi_of_match[] = {
622         { .compatible = "rockchip,mbox-scpi"},
623         { },
624 };
625 MODULE_DEVICE_TABLE(of, mobx_scpi_of_match);
626
627 static int mobx_scpi_probe(struct platform_device *pdev)
628 {
629         int ret = 0;
630         int retry = 3;
631         u32 ver = 0;
632         int check_version = 0; /*0: not check version, 1: check version*/
633
634         the_scpi_device = &pdev->dev;
635
636         while ((retry--) && (check_version != 0)) {
637                 ret = scpi_get_version(SCPI_VERSION, &ver);
638                 if ((ret == 0) && (ver == SCPI_VERSION))
639                         break;
640         }
641
642         if ((retry <= 0) && (check_version != 0)) {
643                 dev_err(&pdev->dev, "Failed to get scpi version\n");
644                 ret = -EIO;
645                 goto exit;
646         }
647
648         dev_info(&pdev->dev,
649                  "Scpi initialize, version: 0x%x\n", ver);
650         return 0;
651 exit:
652         the_scpi_device = NULL;
653         return ret;
654 }
655
656 static struct platform_driver mbox_scpi_driver = {
657         .probe  = mobx_scpi_probe,
658         .driver = {
659                 .name = "mbox-scpi",
660                 .of_match_table = of_match_ptr(mobx_scpi_of_match),
661         },
662 };
663
664 static int __init rockchip_mbox_scpi_init(void)
665 {
666         return platform_driver_register(&mbox_scpi_driver);
667 }
668 subsys_initcall(rockchip_mbox_scpi_init);