2 * Copyright (C) 2012 Spreadtrum Communications Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/wait.h>
17 #include <linux/spinlock.h>
18 #include <linux/interrupt.h>
19 #include <linux/sched.h>
21 #include <linux/slab.h>
22 #include <linux/debugfs.h>
23 #include <linux/platform_device.h>
24 #include <linux/of_device.h>
25 #include <linux/of_address.h>
26 #include <linux/of_irq.h>
27 #include <soc/sprd/sci_glb_regs.h>
29 #ifdef CONFIG_SPRD_MAILBOX
30 #include <soc/sprd/mailbox.h>
33 #include <linux/sipc.h>
34 #include <linux/sipc_priv.h>
36 #define SMSG_TXBUF_ADDR (0)
37 #define SMSG_TXBUF_SIZE (SZ_1K)
38 #define SMSG_RXBUF_ADDR (SMSG_TXBUF_SIZE)
39 #define SMSG_RXBUF_SIZE (SZ_1K)
41 #define SMSG_RINGHDR (SMSG_TXBUF_SIZE + SMSG_RXBUF_SIZE)
42 #define SMSG_TXBUF_RDPTR (SMSG_RINGHDR + 0)
43 #define SMSG_TXBUF_WRPTR (SMSG_RINGHDR + 4)
44 #define SMSG_RXBUF_RDPTR (SMSG_RINGHDR + 8)
45 #define SMSG_RXBUF_WRPTR (SMSG_RINGHDR + 12)
47 /* if it's upon mailbox arch, overwrite the implementation*/
48 #ifdef CONFIG_SPRD_MAILBOX
50 #define DEFINE_SIPC_RXIRQ_STATUS_FN(id) \
51 static int sipc_rxirq_status##id(void) \
56 #define DEFINE_SIPC_RXIRQ_CLEAR_FN(id) \
57 static void sipc_rxirq_clear##id(void) \
62 #define DEFINE_SIPC_TXIRQ_TRIGGER_FN(id) \
63 static void sipc_txirq_trigger##id(void) \
65 struct sipc_child_node_info *info = &sipc_dev->pdata->info_table[id];\
66 mbox_raw_sent(info->core_id, 0);\
71 #define DEFINE_SIPC_RXIRQ_STATUS_FN(id) \
72 static int sipc_rxirq_status##id(void) \
77 #define DEFINE_SIPC_RXIRQ_CLEAR_FN(id) \
78 static void sipc_rxirq_clear##id(void) \
80 struct sipc_child_node_info *info = &sipc_dev->pdata->info_table[id];\
81 __raw_writel(info->ap2cp_bit_clr, (volatile void *)info->cp2ap_int_ctrl);\
84 #define DEFINE_SIPC_TXIRQ_TRIGGER_FN(id) \
85 static void sipc_txirq_trigger##id(void) \
87 struct sipc_child_node_info *info = &sipc_dev->pdata->info_table[id];\
88 __raw_writel(info->ap2cp_bit_trig, (volatile void *)info->ap2cp_int_ctrl);\
93 #define __GET_SIPC_FN_NAME(fn, id) fn##id
95 #define __GET_SIPC_FN(fn, id) \
100 ret = __GET_SIPC_FN_NAME(fn, 0);\
103 ret = __GET_SIPC_FN_NAME(fn, 1);\
106 ret = __GET_SIPC_FN_NAME(fn, 2);\
114 #define GET_SIPC_RXIRQ_STATUS_FN(id) __GET_SIPC_FN(sipc_rxirq_status, id)
115 #define GET_SIPC_RXIRQ_CLEAR_FN(id) __GET_SIPC_FN(sipc_rxirq_clear, id)
116 #define GET_SIPC_TXIRQ_TRIGGER_FN(id) __GET_SIPC_FN(sipc_txirq_trigger, id)
118 struct sipc_child_node_info {
131 #ifdef CONFIG_SPRD_MAILBOX
134 uint32_t ap2cp_int_ctrl;
135 uint32_t cp2ap_int_ctrl;
136 uint32_t ap2cp_bit_trig;
137 uint32_t ap2cp_bit_clr;
143 struct sipc_init_data {
148 struct sipc_child_node_info info_table[0];
154 struct sipc_init_data *pdata;
155 struct smsg_ipc *smsg_inst;
158 struct sipc_device *sipc_dev;
160 DEFINE_SIPC_TXIRQ_TRIGGER_FN(0)
161 DEFINE_SIPC_TXIRQ_TRIGGER_FN(1)
162 DEFINE_SIPC_TXIRQ_TRIGGER_FN(2)
164 DEFINE_SIPC_RXIRQ_CLEAR_FN(0)
165 DEFINE_SIPC_RXIRQ_CLEAR_FN(1)
166 DEFINE_SIPC_RXIRQ_CLEAR_FN(2)
168 DEFINE_SIPC_RXIRQ_STATUS_FN(0)
169 DEFINE_SIPC_RXIRQ_STATUS_FN(1)
170 DEFINE_SIPC_RXIRQ_STATUS_FN(2)
173 static int sipc_create(struct sipc_device *sipc)
175 struct sipc_init_data *pdata = sipc->pdata;
176 struct smsg_ipc *inst;
177 struct sipc_child_node_info *info;
187 inst = sipc->smsg_inst;
188 info = pdata->info_table;
190 for (i = 0; i < num; i++) {
191 base = (size_t)ioremap_nocache((uint32_t)info[i].ring_base, info[i].ring_size);
193 pr_info("sipc:[%d] ioremap return NULL\n");
196 pr_info("sipc:[%d] after ioremap vbase=0x%lx, pbase=0x%x, size=0x%x\n",
197 i, base, info[i].ring_base, info[i].ring_size);
198 inst[i].txbuf_size = SMSG_TXBUF_SIZE / sizeof(struct smsg);
199 inst[i].txbuf_addr = base + SMSG_TXBUF_ADDR;
200 inst[i].txbuf_rdptr = base + SMSG_TXBUF_RDPTR;
201 inst[i].txbuf_wrptr = base + SMSG_TXBUF_WRPTR;
203 inst[i].rxbuf_size = SMSG_RXBUF_SIZE / sizeof(struct smsg);
204 inst[i].rxbuf_addr = base + SMSG_RXBUF_ADDR;
205 inst[i].rxbuf_rdptr = base + SMSG_RXBUF_RDPTR;
206 inst[i].rxbuf_wrptr = base + SMSG_RXBUF_WRPTR;
208 ret = smsg_ipc_create(inst[i].dst, &inst[i]);
210 pr_info("sipc:[%d] created\n", i);
219 static int sipc_parse_dt(struct sipc_init_data **init, struct device *dev)
221 struct device_node *np = dev->of_node, *nchd;
222 struct sipc_init_data *pdata;
223 struct sipc_child_node_info *info;
225 uint32_t data, nr, int_ctrl_phy[2];
228 nr = of_get_child_count(np);
229 if (nr == 0 || nr >= SIPC_ID_NR) {
230 return (!nr ? -ENODEV : -EINVAL);
232 pdata = kzalloc(sizeof(struct sipc_init_data) + nr*sizeof(struct sipc_child_node_info), GFP_KERNEL);
234 pr_err("sipc: failed to alloc mem for pdata\n");
239 ret = of_address_to_resource(np, 0, &res);
244 pdata->smem_base = (uint32_t)res.start;
245 pdata->smem_size = (uint32_t)(res.end - res.start + 1);
246 pr_info("sipc: chd_nr=%d smem_base=0x%x, smem_size=0x%x\n", pdata->chd_nr, pdata->smem_base, pdata->smem_size);
249 info = pdata->info_table;
251 for_each_child_of_node(np, nchd) {
252 ret = of_property_read_string(nchd, "sprd,name", (const char **)&info[i].name);
256 pr_info("sipc:[%d] name=%s\n", i, info[i].name);
258 ret = of_property_read_u32(nchd, "sprd,dst", &data);
262 info[i].dst = (uint8_t)data;
263 pr_info("sipc:[%d] dst=%u\n", i, info[i].dst);
265 #ifndef CONFIG_SPRD_MAILBOX
266 /* get ipi base addr */
267 ret = of_property_read_u32(nchd, "sprd,ap2cp", &int_ctrl_phy[0]);
271 info[i].ap2cp_int_ctrl = SPRD_DEV_P2V(int_ctrl_phy[0]);
273 ret = of_property_read_u32(nchd, "sprd,cp2ap", &int_ctrl_phy[1]);
277 info[i].cp2ap_int_ctrl = SPRD_DEV_P2V(int_ctrl_phy[1]);
279 pr_info("sipc:[%d] ap2cp_int_ctrl=0x%lx, ap2cp_ctrl_phy=0x%x, cp2ap_int_ctrl=0x%lx, cp2ap_ctrl_phy=0x%x\n",
280 i, info[i].ap2cp_int_ctrl, int_ctrl_phy[0], info[i].cp2ap_int_ctrl, int_ctrl_phy[1]);
282 ret = of_property_read_u32(nchd, "sprd,trig", &info[i].ap2cp_bit_trig);
287 ret = of_property_read_u32(nchd, "sprd,clr", &info[i].ap2cp_bit_clr);
291 pr_info("sipc:[%d] ap2cp_bit_trig=0x%x, ap2cp_bit_clr=0x%x\n",
292 i, info[i].ap2cp_bit_trig, info[i].ap2cp_bit_clr);
294 /* get cp base addr */
295 ret = of_address_to_resource(nchd, 0, &res);
299 info[i].cp_base = (uint32_t)res.start;
300 info[i].cp_size = (uint32_t)(res.end - res.start + 1);
301 pr_info("sipc:[%d] cp_base=0x%x, cp_size=0x%x\n",
302 i, info[i].cp_base, info[i].cp_size);
304 /* get smem base addr */
305 ret = of_address_to_resource(nchd, 1, &res);
309 info[i].smem_base = (uint32_t)res.start;
310 info[i].smem_size = (uint32_t)(res.end - res.start + 1);
311 pr_info("sipc:[%d] smem_base=0x%x, smem_size=0x%x\n", i, info[i].smem_base, info[i].smem_size);
313 /* get ring base addr */
314 ret = of_address_to_resource(nchd, 2, &res);
318 info[i].ring_base = (uint32_t)res.start;
319 info[i].ring_size = (uint32_t)(res.end - res.start + 1);
320 pr_info("sipc:[%d] ring_base=0x%x, ring_size=0x%x\n", i, info[i].ring_base, info[i].ring_size);
322 #ifdef CONFIG_SPRD_MAILBOX
323 ret = of_property_read_u32(nchd, "mailbox,core", &info[i].core_id);
327 pr_info("sipc:[%d] core_id=%u\n", i, info[i].core_id);
330 info[i].irq = irq_of_parse_and_map(nchd, 0);
335 pr_info("sipc:[%d] irq=%d\n", i, info[i].irq);
346 static void sipc_destroy_pdata(struct sipc_init_data **ppdata)
348 struct sipc_init_data *pdata = ppdata;
349 if (pdata && pdata->is_alloc) {
355 static int sipc_probe(struct platform_device *pdev)
357 struct sipc_init_data *pdata = pdev->dev.platform_data;
358 struct sipc_device *sipc;
359 struct sipc_child_node_info *info;
360 struct smsg_ipc *smsg;
364 pr_info("sipc:[0] define status=0x%x, clear=0x%x, trigger=0x%x\n",
365 (uint32_t)sipc_rxirq_status0, (uint32_t)sipc_rxirq_clear0, (uint32_t)sipc_txirq_trigger0);
367 pr_info("sipc:[1] define status=0x%x, clear=0x%x, trigger=0x%x\n",
368 (uint32_t)sipc_rxirq_status1, (uint32_t)sipc_rxirq_clear1, (uint32_t)sipc_txirq_trigger1);
370 pr_info("sipc:[2] define status=0x%x, clear=0x%x, trigger=0x%x\n",
371 (uint32_t)sipc_rxirq_status2, (uint32_t)sipc_rxirq_clear2, (uint32_t)sipc_txirq_trigger2);
373 if (!pdata && pdev->dev.of_node) {
374 ret = sipc_parse_dt(&pdata, &pdev->dev);
376 pr_err("sipc: failed to parse dt, ret=%d\n", ret);
381 sipc = kzalloc(sizeof(struct sipc_device), GFP_KERNEL);
383 sipc_destroy_pdata(&pdata);
388 smsg = kzalloc(num * sizeof(struct smsg_ipc), GFP_KERNEL);
391 sipc_destroy_pdata(&pdata);
395 pr_info("sipc: num=%d\n", num);
396 info = pdata->info_table;
397 for (i = 0; i < num; i++) {
398 smsg[i].name = info[i].name;
399 smsg[i].dst = info[i].dst;
400 #ifdef CONFIG_SPRD_MAILBOX
401 smsg[i].core_id = info[i].core_id;
403 smsg[i].irq = info[i].irq;
405 smsg[i].rxirq_status = GET_SIPC_RXIRQ_STATUS_FN(i);
406 smsg[i].rxirq_clear = GET_SIPC_RXIRQ_CLEAR_FN(i);
407 smsg[i].txirq_trigger = GET_SIPC_TXIRQ_TRIGGER_FN(i);
409 pr_info("sipc: [%d] fn status=0x%x, clear=0x%x, trigger=0x%x\n",
410 i, (uint32_t)smsg[i].rxirq_status, (uint32_t)smsg[i].rxirq_clear,
411 (uint32_t)smsg[i].txirq_trigger);
412 #ifdef CONFIG_SPRD_MAILBOX
413 pr_info("sipc:[%d] smsg name=%s, dst=%u, core_id=%d\n",
414 i, smsg[i].name, smsg[i].dst, smsg[i].core_id);
416 pr_info("sipc:[%d] smsg name=%s, dst=%u, irq=%d\n",
417 i, smsg[i].name, smsg[i].dst, smsg[i].irq);
422 sipc->smsg_inst = smsg;
429 pr_info("sipc: smem_base=0x%x, smem_size=0x%x\n", pdata->smem_base, pdata->smem_size);
430 smem_init(pdata->smem_base, pdata->smem_size);
432 platform_set_drvdata(pdev, sipc);
436 static int sipc_remove(struct platform_device *pdev)
438 struct sipc_device *sipc = platform_get_drvdata(pdev);
440 sipc_destroy_pdata(&sipc->pdata);
441 kfree(sipc->smsg_inst);
447 static const struct of_device_id sipc_match_table[] = {
448 {.compatible = "sprd,sipc", },
452 static struct platform_driver sipc_driver = {
454 .owner = THIS_MODULE,
456 .of_match_table = sipc_match_table,
459 .remove = sipc_remove,
462 static int __init sipc_init(void)
464 return platform_driver_register(&sipc_driver);
467 static void __exit sipc_exit(void)
469 platform_driver_unregister(&sipc_driver);
472 arch_initcall(sipc_init);
473 module_exit(sipc_exit);
475 MODULE_AUTHOR("Qiu Yi");
476 MODULE_DESCRIPTION("SIPC module driver");
477 MODULE_LICENSE("GPL");