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/cdev.h>
17 #include <linux/poll.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
21 #include <linux/of_device.h>
23 #include "soc/sprd/mailbox.h"
24 #include <linux/sched.h>
25 #include <linux/kthread.h>
26 #include <linux/delay.h>
27 #include <linux/sizes.h>
28 #include <soc/sprd/sci_glb_regs.h>
29 #include <linux/sipc.h>
30 #include <linux/spipe.h>
31 #include <linux/sipc_priv.h>
34 #define SMSG_TXBUF_ADDR (0)
35 #define SMSG_TXBUF_SIZE (SZ_1K)
36 #define SMSG_RXBUF_ADDR (SMSG_TXBUF_SIZE)
37 #define SMSG_RXBUF_SIZE (SZ_1K)
39 #define SMSG_RINGHDR (SMSG_TXBUF_SIZE + SMSG_RXBUF_SIZE)
40 #define SMSG_TXBUF_RDPTR (SMSG_RINGHDR + 0)
41 #define SMSG_TXBUF_WRPTR (SMSG_RINGHDR + 4)
42 #define SMSG_RXBUF_RDPTR (SMSG_RINGHDR + 8)
43 #define SMSG_RXBUF_WRPTR (SMSG_RINGHDR + 12)
46 static struct class *sctrl_class;
47 static struct sctrl_mgr strcl_mgr_val;
48 //#define SCTRL_LOOPBACK_DEBUG
49 #ifdef SCTRL_LOOPBACK_DEBUG
50 struct timer_list sctrl_ti;
51 static void sctrl_tx(void)
54 smsg_set(&mrevt, 1, 0, 0, 0);
55 smsg_send(SIPC_ID_PMIC, &mrevt, -1);
57 void sctrl_timer_func(unsigned long arg)
59 struct timer_list *timer=(struct timer_list *)arg;
60 unsigned long j = jiffies;
61 mod_timer(timer,j+8*HZ);
62 pr_err(" sctrl_timer_func expired at jif=%lx\n", j);
66 static int sctrl_thread(void *data)
68 struct sctrl_mgr *strcl_mgr_ptr= data;
71 struct sched_param param = {.sched_priority = 90};
73 /*set the thread as a real time thread, and its priority is 90*/
74 sched_setscheduler(current, SCHED_RR, ¶m);
76 /* since the channel open may hang, we call it in the sctrl thread */
77 rval = smsg_ch_open(strcl_mgr_ptr->dst, strcl_mgr_ptr->channel, -1);
79 pr_err("Failed to open channel %d, rval=%d\n", strcl_mgr_ptr->channel,rval);
80 /* assign NULL to thread poniter as failed to open channel */
81 strcl_mgr_ptr->thread = NULL;
85 #ifdef SCTRL_LOOPBACK_DEBUG
86 /*initiated a timer to send smsg to arm7*/
87 init_timer(&sctrl_ti);
88 sctrl_ti.data=(unsigned long)&sctrl_ti;
89 sctrl_ti.function=sctrl_timer_func;
90 sctrl_ti.expires = jiffies + HZ;
94 while (!kthread_should_stop()) {
95 /* monitor sctrl rdptr/wrptr update smsg */
96 smsg_set(&mrecv, strcl_mgr_ptr->channel, 0, 0, 0);
97 rval = smsg_recv(strcl_mgr_ptr->dst, &mrecv, -1);
100 /* channel state is free */
104 printk(KERN_ERR "sctrl thread recv msg: dst=%d, channel=%d, "
105 "type=%d, flag=0x%04x, value=0x%08x\n",
106 strcl_mgr_ptr->dst, strcl_mgr_ptr->channel,
107 mrecv.type, mrecv.flag, mrecv.value);
108 switch (mrecv.type) {
109 case SMSG_TYPE_DFS_RSP:
112 strcl_mgr_ptr->state = SCTL_STATE_REV_CMPT;
116 strcl_mgr_ptr->state = SCTL_STATE_READY;
118 wake_up_interruptible_all(&strcl_mgr_ptr->rx_pending);
124 case SMSG_TYPE_CLOSE:
125 /* handle channel recovery */
126 smsg_close_ack(strcl_mgr_ptr->dst, strcl_mgr_ptr->channel);
127 strcl_mgr_ptr->state = SCTL_STATE_IDLE;
131 /* respond cmd done for sctrl init */
132 smsg_set(&mcmd, strcl_mgr_ptr->channel, SMSG_TYPE_DONE,SMSG_DONE_SBUF_INIT, 0);
133 smsg_send(strcl_mgr_ptr->dst, &mcmd, -1);
134 strcl_mgr_ptr->state = SCTL_STATE_READY;
140 void sctrl_send_async(uint32_t type, uint32_t target_id, uint32_t value)
143 smsg_set(&mevt, 1, type, target_id ,value);
144 smsg_send(SIPC_ID_PMIC, &mevt, -1);
146 int sctrl_send_sync(uint32_t type, uint32_t target_id, uint32_t value)
150 int timeout =msecs_to_jiffies(50000);
151 smsg_set(&mrecv, 1, type, target_id ,value);
152 smsg_send(SIPC_ID_PMIC, &mrecv, -1);
153 if(type ==SMSG_TYPE_DFS)
155 rval = wait_event_interruptible_timeout(strcl_mgr_val.rx_pending,\
156 strcl_mgr_val.state != SCTL_STATE_IDLE, timeout);
158 pr_warning(" sctrl_send_sync wait interrupted!\n");
159 } else if (rval == 0) {
160 pr_err(" sctrl_send_sync wait timeout!\n");
163 if (strcl_mgr_val.state == SCTL_STATE_REV_CMPT)
165 strcl_mgr_val.state = SCTL_STATE_IDLE;
166 pr_info(" sctrl_send_sync DFS Response!\n");
178 strcl_mgr_val.state = SCTL_STATE_IDLE;
181 int sctrl_create(uint8_t dst, uint8_t channel, uint32_t bufnum)
184 strcl_mgr_val.state = SCTL_STATE_IDLE;
185 strcl_mgr_val.dst = dst;
186 strcl_mgr_val.channel = channel;
187 init_waitqueue_head(&strcl_mgr_val.tx_pending);
188 init_waitqueue_head(&strcl_mgr_val.rx_pending);
189 strcl_mgr_val.thread = kthread_create(sctrl_thread, &strcl_mgr_val, "sctrl-%d-%d", dst, channel);
190 if (IS_ERR(strcl_mgr_val.thread)) {
191 printk(KERN_ERR "Failed to create kthread: sctrl-%d-%d\n", dst, channel);
192 result = PTR_ERR(strcl_mgr_val.thread);
195 pr_err(" sctrl create strcl_mgr_val.thread %p\n", strcl_mgr_val.thread);
196 wake_up_process(strcl_mgr_val.thread);
199 static int sctrl_open(struct inode *inode, struct file *filp)
201 int minor = iminor(filp->f_path.dentry->d_inode);
202 struct sctrl_device *sctrl;
203 struct sctrl_buf *sbuf;
205 sctrl = container_of(inode->i_cdev, struct sctrl_device, cdev);
206 sbuf = kmalloc(sizeof(struct sctrl_buf), GFP_KERNEL);
208 pr_err(" sctrl open malloc sbuf fail\n");
211 filp->private_data = sbuf;
213 sbuf->dst = sctrl->init->dst;
214 sbuf->channel = sctrl->init->channel;
215 sbuf->bufid = minor - sctrl->minor;
216 pr_info("sctrl open sucess\n");
220 static int sctrl_release(struct inode *inode, struct file *filp)
222 struct sctrl_buf *sbuf = filp->private_data;
231 static ssize_t sctrl_read(struct file *filp,
232 char __user *buf, size_t count, loff_t *ppos)
234 struct sctrl_buf *sbuf = filp->private_data;
235 struct smsg mevt = {0};
238 if (filp->f_flags & O_NONBLOCK) {
241 if(smsg_recv(sbuf->dst,&mevt,timeout) == 0)
243 if(copy_to_user((void __user *)buf, (void *)&mevt, sizeof(struct smsg)))
253 static ssize_t sctrl_write(struct file *filp,
254 const char __user *buf, size_t count, loff_t *ppos)
256 struct sctrl_buf *sbuf = filp->private_data;
257 struct smsg mevt = {0};
260 if (filp->f_flags & O_NONBLOCK) {
263 pr_info("sctrl open sucess\n");
265 sctrl_send_sync(SMSG_TYPE_DFS, SIPC_ID_PMIC,0xfe);
269 static unsigned int sctrl_poll(struct file *filp, poll_table *wait)
271 struct sctrl_buf *sbuf = filp->private_data;
272 unsigned int mask = 0;
279 static long sctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
283 uint32_t pmic_rxirq_status(void)
287 void pmic_rxirq_clear(void)
290 void pmic_txirq_trigger(void)
292 mbox_raw_sent(ARM7, 0);
295 static struct smsg_ipc smsg_ipc_pmic = {
299 .rxirq_status = pmic_rxirq_status,
300 .rxirq_clear = pmic_rxirq_clear,
301 .txirq_trigger = pmic_txirq_trigger,
304 static int __init sipc_pmic_init(ssize_t base)
307 smsg_ipc_pmic.txbuf_size = SMSG_TXBUF_SIZE / sizeof(struct smsg);
308 smsg_ipc_pmic.txbuf_addr = base + SMSG_TXBUF_ADDR;
309 smsg_ipc_pmic.txbuf_rdptr =base+0x1c00+ 0;
310 smsg_ipc_pmic.txbuf_wrptr = base+0x1c00+ 8;
312 smsg_ipc_pmic.rxbuf_size = SMSG_RXBUF_SIZE / sizeof(struct smsg);
313 smsg_ipc_pmic.rxbuf_addr = base + SMSG_RXBUF_ADDR;
314 smsg_ipc_pmic.rxbuf_rdptr = base+0x1c00+ 16;
315 smsg_ipc_pmic.rxbuf_wrptr = base+0x1c00+ 24;
317 return smsg_ipc_create(SIPC_ID_PMIC, &smsg_ipc_pmic);
319 static const struct file_operations sctrl_fops = {
321 .release = sctrl_release,
323 .write = sctrl_write,
325 .unlocked_ioctl = sctrl_ioctl,
326 .owner = THIS_MODULE,
327 .llseek = default_llseek,
330 static int sctrl_parse_dt(struct spipe_init_data **init, struct device *dev)
333 struct device_node *np = dev->of_node;
334 struct spipe_init_data *pdata = NULL;
335 ssize_t ring_base = 0;
337 uint32_t rxbuf_size = 0;
338 uint32_t txbuf_size = 0;
342 pdata = kzalloc(sizeof(struct spipe_init_data), GFP_KERNEL);
344 printk(KERN_ERR "Failed to allocate pdata memory\n");
348 ret = of_property_read_string(np, "sprd,name", (const char**)&pdata->name);
350 printk(KERN_ERR "Failed to read sprd name\n");
354 ret = of_property_read_u32(np, "sprd,dst", (uint32_t *)&data);
356 printk(KERN_ERR "Failed to read sprd dst\n");
359 pdata->dst = (uint8_t)data;
361 ret = of_property_read_u32(np, "sprd,channel", (uint32_t *)&data);
363 printk(KERN_ERR "Failed to read sprd channel\n");
366 pdata->channel = (uint8_t)data;
367 ret = of_property_read_u32(np, "sprd,ringnr", (uint32_t *)&data);
369 printk(KERN_ERR "Failed to read sprd ringnr, ret=%d\n", ret);
373 ret = of_property_read_u32(np, "sprd,ringbase", (uint32_t *)&vm_base);
377 ring_base = (unsigned long)ioremap_nocache(vm_base,SZ_8K);
379 printk(KERN_ERR "Unable to map ring base\n");
383 ret = of_property_read_u32(np, "sprd,size-rxbuf", &rxbuf_size);
388 ret = of_property_read_u32(np, "sprd,size-txbuf", &txbuf_size);
392 pr_info("sipc_pmic_init with base=0x%lx\n", ring_base);
393 sipc_pmic_init(ring_base);
405 static inline void sctrl_destroy_pdata(struct spipe_init_data **init)
408 struct spipe_init_data *pdata = *init;
420 static int sctrl_probe(struct platform_device *pdev)
422 struct spipe_init_data *init = pdev->dev.platform_data;
423 struct sctrl_device *sctrl;
427 if (pdev->dev.of_node && !init) {
428 rval = sctrl_parse_dt(&init, &pdev->dev);
430 printk(KERN_ERR "Failed to parse sctrl device tree, ret=%d\n", rval);
434 pr_info("sctrl: after parse device tree, name=%s, dst=%u, channel=%u, ringnr=%u, rxbuf_size=%u, txbuf_size=%u\n",
435 init->name, init->dst, init->channel, init->ringnr, init->rxbuf_size, init->txbuf_size);
438 rval = sctrl_create(init->dst, init->channel, init->ringnr);
440 printk(KERN_ERR "Failed to create sctrl device: %d\n", rval);
441 sctrl_destroy_pdata(&init);
445 sctrl = kzalloc(sizeof(struct sctrl_device), GFP_KERNEL);
447 sctrl_destroy_pdata(&init);
448 printk(KERN_ERR "Failed to allocate sctrl_device\n");
451 rval = alloc_chrdev_region(&devid, 0, init->ringnr, init->name);
454 sctrl_destroy_pdata(&init);
455 printk(KERN_ERR "Failed to alloc sctrl chrdev\n");
459 cdev_init(&(sctrl->cdev), &sctrl_fops);
460 rval = cdev_add(&(sctrl->cdev), devid, init->ringnr);
463 unregister_chrdev_region(devid, init->ringnr);
464 sctrl_destroy_pdata(&init);
465 printk(KERN_ERR "Failed to add sctrl cdev\n");
469 sctrl->major = MAJOR(devid);
470 sctrl->minor = MINOR(devid);
471 if (init->ringnr > 1) {
472 for (i = 0; i < init->ringnr; i++) {
473 device_create(sctrl_class, NULL,
474 MKDEV(sctrl->major, sctrl->minor + i),
475 NULL, "%s%d", init->name, i);
478 device_create(sctrl_class, NULL,
479 MKDEV(sctrl->major, sctrl->minor),
480 NULL, "%s", init->name);
484 platform_set_drvdata(pdev, sctrl);
488 static int sctrl_remove(struct platform_device *pdev)
490 struct sctrl_device *sctrl = platform_get_drvdata(pdev);
493 for (i = 0; i < sctrl->init->ringnr; i++) {
494 device_destroy(sctrl_class,
495 MKDEV(sctrl->major, sctrl->minor + i));
497 cdev_del(&(sctrl->cdev));
498 unregister_chrdev_region(
499 MKDEV(sctrl->major, sctrl->minor), sctrl->init->ringnr);
501 sctrl_destroy_pdata(&sctrl->init);
505 platform_set_drvdata(pdev, NULL);
510 static const struct of_device_id sctrl_match_table[] = {
511 {.compatible = "sprd,sctrl", },
515 static struct platform_driver sctrl_driver = {
517 .owner = THIS_MODULE,
519 .of_match_table = sctrl_match_table,
521 .probe = sctrl_probe,
522 .remove = sctrl_remove,
525 static int __init sctrl_init(void)
527 sctrl_class = class_create(THIS_MODULE, "sctrl");
528 if (IS_ERR(sctrl_class))
529 return PTR_ERR(sctrl_class);
531 return platform_driver_register(&sctrl_driver);
534 static void __exit sctrl_exit(void)
536 class_destroy(sctrl_class);
537 platform_driver_unregister(&sctrl_driver);
540 module_init(sctrl_init);
541 module_exit(sctrl_exit);
543 MODULE_AUTHOR("Andrew Yang");
544 MODULE_DESCRIPTION("SIPC/SCTRL driver");
545 MODULE_LICENSE("GPL");