blob: 720af180d277d012cce63e6959f844efad6d9f1c [file] [log] [blame]
b.liub17525e2025-05-14 17:22:29 +08001/*
2 * drivers/soc/zte/plat/plat-zx298501.c
3 *
4 * Copyright (C) 2021 ZTE-TSP
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <linux/clockchips.h>
21#include <linux/clk.h>
22#include <linux/clk-provider.h>
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/syscore_ops.h>
26#include <linux/gpio.h>
27#include <linux/of_device.h>
28#include <linux/pinctrl/consumer.h>
29#include <linux/io.h>
30#include <linux/of_gpio.h>
31#include <linux/platform_device.h>
32#include <linux/pm_domain.h>
33#include <linux/pm_runtime.h>
34#include <linux/delay.h>
35#include <linux/reset.h>
36#include <linux/io.h>
37#include <linux/amba/serial.h>
38#include <linux/serial_reg.h>
39#include <linux/of_device.h>
40#include <linux/of_irq.h>
41#include <linux/of_address.h>
42#include <linux/sched/clock.h>
43#include <linux/suspend.h>
44#include <linux/mfd/syscon.h>
45#include <linux/regmap.h>
46#include <linux/reboot.h>
47#include <linux/miscdevice.h>
48#include <dt-bindings/soc/mbtk_plat_irq.h>
49#include <uapi/linux/bsp_api.h>
50//#include <linux/soc/sc/common.h>
51/*#include <linux/soc/sc/pcu.h>
52#include <linux/soc/sc/spinlock.h>
53
54
55*/
56/*
57 * we use sysfs to test&debug some system funcs
58 *
59 */
60struct kobject *zx_root_kobj;
61struct kobject *zx_test_kobj;
62struct kobject *zx_pm_kobj;
63
64extern int __init zx_clk_test_init(void);
65extern int __init zx_dma_test_init(void);
66extern int __init zx_icp_test_init(void);
67extern int __init zx_timer_test_init(void);
68
69#define DOUBLE_EINT_DBG 0
70#define EINT_THREAD_TEST 0
71
72#define CONFIG_USE_DEBUG_LED 1
73#define ZX_RESET_TEST 1
74#define ZX_CLK_TEST 1
75#define ZX_PINCTRL_TEST 1
76#define ZX_GPIO_TEST 1
77#define ZX_EINT_TEST 1
78#define ZX_PM_TEST 1
79#if ZX_PM_TEST
80#define PM_RUNTIME_AUTO_TEST 1
81#endif
82#define ZX_SPINLOCK_TEST 0
83#define ZX_PM_QOS_TEST 0
84
85#define TRUE 1
86#define FALSE 0
87
88/*
89 *
90 * some test need device probe
91 */
92struct zx_drv_test
93{
94 struct device *dev;
95#if ZX_RESET_TEST
96 struct reset_control *rst;
97#endif
98
99#if ZX_PINCTRL_TEST
100 struct pinctrl *pctrl;
101 struct pinctrl_state *state0;
102 struct pinctrl_state *state1;
103 struct pinctrl_state *state2;
104#endif
105
106#if ZX_GPIO_TEST
107 int gpio;
108 int gpio2;
109 int gpio3;
110 struct gpio_desc *gd;
111
112#endif
113
114#if ZX_EINT_TEST
115 int eint_irq;
116 int eint_irq2;
117#endif
118
119#if ZX_CLK_TEST
120 struct clk *clk;
121#endif
122};
123
124struct zx_drv_test drv_test = {0};
125
126#define MAX_GPIO_NUM 4
127
128struct MbtkPlatIrq_dev
129{
130 struct device *dev;
131 struct pinctrl *pctrl;
132 int gpio_desc[MAX_GPIO_NUM] ;
133 int release_func_callback[MAX_GPIO_NUM] ;
134 //struct wakeup_source *WakeUp_ws;
135
136};
137
138struct MbtkPlatIrq_dev g_MbtkPlatIrq_dev = {0};
139
140
141
142
143
144
145#if 0//ZX_RESET_TEST
146static void drv_reset_test(struct reset_control *rstc)
147{
148 reset_control_assert(rstc);
149 udelay(10);
150 reset_control_deassert(rstc);
151}
152#endif
153
154#if ZX_EINT_TEST
155#if EINT_THREAD_TEST
156static irqreturn_t test_eint_pri_isr(int irq, void *p)
157{
158 disable_irq_nosync(irq);
159
160 return IRQ_WAKE_THREAD;
161}
162
163static irqreturn_t test_eint_isr(int irq, void *p)
164{
165 static int eint_cnt = 0;
166 if ( pinctrl_select_state(drv_test.pctrl, drv_test.state0) < 0) {
167 pr_err("setting state0 failed\n");
168 }
169
170 irq_set_irq_type(drv_test.eint_irq, gpio_get_value(drv_test.gpio)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
171
172 if ( pinctrl_select_state(drv_test.pctrl, drv_test.state1) < 0) {
173 pr_err("setting state0 failed\n");
174 }
175
176 enable_irq(irq);
177
178 pr_info("eint9 get = %d\n", ++eint_cnt);
179
180 return IRQ_HANDLED;
181}
182#else
183static irqreturn_t test_eint_isr(int irq, void *p)
184{
185 static int eint_cnt = 0;
186
187 irq_set_irq_type(drv_test.eint_irq, gpio_get_value(drv_test.gpio)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
188
189 //pr_info("eint9 get = %d\n", ++eint_cnt);
190
191 return IRQ_HANDLED;
192}
193#endif
194static irqreturn_t test_eint_isr2(int irq, void *p)
195{
196 static int eint_cnt1 = 0;
197
198 irq_set_irq_type(drv_test.eint_irq2, gpio_get_value(drv_test.gpio2)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
199
200 pr_info("eint12 get = %d\n", ++eint_cnt1);
201
202 return IRQ_HANDLED;
203}
204
205#endif
206
207
208
209/*-------------------------------------------------------------------*/
210#define MBTK_IRQ_MINOR (170)
211#define MBTK_LIBIRQ_MAX (4)
212
213/*
214 * line : request
215 * type : driver use
216 * wake_flag : for wait
217 *
218 */
219struct libirq_info {
220 unsigned int line;
221 unsigned int hirq;
222 unsigned int virq;
223 unsigned int type;
224 int wake;
225 unsigned int used;
226 bool wake_flag;
227 wait_queue_head_t wait;
228 char name[16];
229};
230
231struct libirq_context {
232 unsigned int pending;
233 spinlock_t lock;
234 struct pinctrl *pctrl;
235 struct pinctrl_state *state[MBTK_LIBIRQ_MAX];
236
237 struct device_node *np;
238 struct device_node *ext8in1_np;
239 struct libirq_info info[MBTK_LIBIRQ_MAX];
240};
241static struct libirq_context irq_ctx = {0};
242
243#define line_used(l) irq_ctx.info[l].used
244
245static int irq_line_convert(int line)
246{
247#if 0 //forbid by niening
248 if (line>=4)
249 return EX24_INT + line - 8;
250 else
251 return EX21_INT + line;
252
253
254#else
255 int irq;
256
257 irq = gpio_to_irq(g_MbtkPlatIrq_dev.gpio_desc[line]);
258 if (irq < 0)
259 {
260 pr_err("%s. gpio %d request irq %d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[line], irq);
261
262 }
263
264 return irq;
265
266#endif
267}
268
269static unsigned int irq_type_convert(unsigned int req_type)
270{
271 //printk("--->%s/L%d req_type = %d\n", __FUNCTION__, __LINE__, req_type);
272 if (req_type == 0)
273 return IRQ_TYPE_EDGE_RISING;
274 else if (req_type == 1)
275 return IRQ_TYPE_EDGE_FALLING;
276 else if (req_type == 2)
277 return IRQ_TYPE_LEVEL_HIGH;
278 else if (req_type == 3)
279 return IRQ_TYPE_LEVEL_LOW;
280 else
281 return IRQ_TYPE_NONE;
282}
283
284static int mbkt_irq_map_ext8in1(int hirq, unsigned int type)
285{
286 struct of_phandle_args args;
287
288 args.args_count = 2;
289 args.args[0] = hirq;
290 args.args[1] = type;
291 args.np = irq_ctx.ext8in1_np;
292
293 return irq_create_of_mapping(&args);
294}
295
296static int mbkt_irq_map(int hirq, unsigned int type, unsigned int line)
297{
298 struct of_phandle_args args;
299 int ret = 0;
300#if 0
301 char name[16];
302
303 //if (hirq>=EX8_INT && hirq<=EX15_INT)
304 // return mbkt_irq_map_ext8in1(hirq, type);
305
306 memset(name, 0, sizeof(name));
307 sprintf(name, "%s%d", "gpio_irq", line);
308
309 ret = gpio_request(g_MbtkPlatIrq_dev.gpio_desc[line], name);
310 if(ret < 0)
311 {
312 pr_err("%s. gpio_request for =%d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[line]);
313 }
314
315 gpio_direction_input(g_MbtkPlatIrq_dev.gpio_desc[line]);
316
317 hirq = gpio_to_irq(g_MbtkPlatIrq_dev.gpio_desc[line]);
318
319
320 pr_err("%s. %s=%d, hirq = %d\n", __func__, name, g_MbtkPlatIrq_dev.gpio_desc[line], hirq);
321 irq_ctx.info[line].hirq = hirq;
322#endif
323 args.args_count = 3;
324 args.args[0] = 0;
325 args.args[1] = hirq;
326 args.args[2] = type;
327 args.np = irq_ctx.np;
328
329 return hirq;
330 //return irq_create_of_mapping(&args);
331}
332
333static void mbtk_irq_wait(unsigned int line)
334{
335 struct libirq_info *info = &(irq_ctx.info[line]);
336
337 info->wake_flag = false;
338 wait_event_freezable(info->wait, info->wake_flag);
339}
340
341static void mbtk_irq_wakeup(unsigned int line)
342{
343 struct libirq_info *info = &(irq_ctx.info[line]);
344
345 info->wake_flag = true;
346 wake_up_interruptible(&info->wait);
347}
348
349static irqreturn_t mbtk_irq_isr(int irq, void *priv)
350{
351 struct libirq_info *info = (struct libirq_info *)priv;
352 unsigned int line = info->line;
353 int gpio_value = 0;
354
355 disable_irq_nosync(irq); //add by niening
356
357 gpio_value = gpio_get_value_cansleep(g_MbtkPlatIrq_dev.gpio_desc[line]) ;
358
359 printk("%s/L%d, gpio_value = %d \n", __FUNCTION__, __LINE__, gpio_value);
360 if(info->wake)
361 {
362 pm_wakeup_event(g_MbtkPlatIrq_dev.dev, 2000);
363 }
364
365
366 if(line_used(line)) {
367 irq_ctx.pending |= BIT(line);
368
369 mbtk_irq_wakeup(line);
370 }
371
372
373
374 pr_info("%s:eint get = %d\n", __func__, line);
375
376 enable_irq(irq);//add by niening
377
378 return IRQ_HANDLED;
379}
380
381static int mbtk_irq_open(struct inode *inode, struct file *filp)
382{
383 int error = 0;
384 unsigned int line;
385 struct libirq_info *info;
386
387 line = iminor(inode) - MBTK_IRQ_MINOR;
388
389 filp->private_data = &(irq_ctx.info[line]);
390
391
392 info = (struct libirq_info *)filp->private_data;
393
394 // add by niening for solve upper app restart send install cmd
395
396 if (g_MbtkPlatIrq_dev.release_func_callback[info->line] == TRUE)
397 {
398 pr_err("%s/L%d\n", __FUNCTION__, __LINE__);
399 free_irq(info->virq, info);
400 }
401
402
403 return error;
404}
405
406static int mbtk_irq_release(struct inode *inode, struct file *filp)
407{
408 struct libirq_info *info;
409
410 info = (struct libirq_info *)filp->private_data;
411
412 pr_err("%s/L%d\n", __FUNCTION__, __LINE__);
413
414 if(line_used(info->line)) {
415
416#if 0 // forbid by niening for upper app goto sleep will callback this function
417
418 //irq_set_irq_type(info->virq, IRQ_TYPE_NONE);
419 //free_irq(info->virq, info);
420#endif
421
422 line_used(info->line) = 0;
423 }
424
425 filp->private_data = NULL;
426
427
428 g_MbtkPlatIrq_dev.release_func_callback[info->line] = TRUE;
429 return 0;
430}
431
432static long mbtk_irq_ioctl(struct file *filp, unsigned int cmd,
433 unsigned long arg)
434{
435 int error = 0;
436 struct libirq_info *info;
437 int virq;
438 unsigned int type;
439 unsigned int en;
440 int ret = 0;
441 unsigned long flags;
442
443 info = (struct libirq_info *)filp->private_data;
444
445 switch (cmd) {
446
447 case SC_IRQ_INSTALL:
448
449 if(line_used(info->line))
450 return -EEXIST;
451
452 type = irq_type_convert((unsigned int)arg);
453
454 virq = mbkt_irq_map(info->hirq, type, info->line);
455 if (virq <= 0) {
456 pr_err("%s:mbkt_irq_map %d failed %d(%d)\n", __func__, info->line, virq, type);
457 return -ENOMEM;
458 }
459 /* pr_err("%s:mbkt_irq_map %d %d %d\n", __func__, info->line, virq, info->hirq);*/
460
461#if 1// niening_Test
462 /* if ( pinctrl_select_state(irq_ctx.pctrl, irq_ctx.state[info->line]) < 0) {
463 pr_err("%s:setting state%d failed\n", __func__, info->line);
464 return -ENODEV;
465 }
466*/
467 ret = request_irq(virq, mbtk_irq_isr, 0, info->name, info);
468 if(ret<0) {
469 pr_err("%s:request_irq %d failed %d\n", __func__, info->line, type);
470 return ret;
471 }
472#else
473 ret = devm_request_threaded_irq(g_MbtkPlatIrq_dev.dev, virq, mbtk_irq_isr,mbtk_irq_isr,0 , info->name, info);
474
475
476#endif
477 info->virq = virq;
478 info->type = type;
479
480 line_used(info->line) = 1;
481
482 pr_info("%s:install(%d) hirq(%d) virq(%d) type(%d)\n", __func__, info->line, info->hirq, info->virq, info->type);
483 break;
484
485 case SC_IRQ_UNINSTALL:
486
487
488 if(!line_used(info->line))
489 return -ENODEV;
490
491 irq_set_irq_type(info->virq, IRQ_TYPE_NONE);
492
493 free_irq(info->virq, info);
494
495 line_used(info->line) = 0;
496
497 pr_info("%s:uninstall(%d)\n", __func__, info->line);
498 break;
499
500 case SC_IRQ_SET_TYPE:
501
502 if(!line_used(info->line))
503 return -ENODEV;
504
505 type = irq_type_convert((unsigned int)arg);
506
507#if 0 //niening_test
508 ret = irq_set_irq_type(info->virq, type);
509#else
510
511 ret = irq_set_irq_type(info->virq, (type | IRQF_ONESHOT));
512#endif
513 if (ret)
514 return ret;
515
516 info->type = type;
517
518 pr_info("%s:set_type(%d) virq(%d) type(%d)\n", __func__, info->line, info->virq, info->type);
519
520 break;
521
522 case SC_IRQ_SET_WAKE:
523 if(!line_used(info->line))
524 return -ENODEV;
525
526 en = (unsigned int)arg;
527
528#if 0 //niening_test
529
530 ret = irq_set_irq_wake(info->virq, en);
531 if (ret)
532 return ret;
533#else
534 if(en)
535 enable_irq_wake(info->virq);
536 else
537 disable_irq_wake(info->virq);
538
539#endif
540
541 info->wake = en;
542 pr_info("%s:set_wake(%d) virq(%d) wake(%d)\n", __func__, info->line, info->virq, info->wake);
543
544 break;
545
546 case SC_IRQ_GET_WAKE:
547
548 if(!line_used(info->line))
549 return -ENODEV;
550 error = put_user(info->wake, (unsigned int __user *)arg);
551
552 pr_info("%s:get_wake(%d) virq(%d) wake(%d)\n", __func__, info->line, info->virq, info->wake);
553
554 break;
555
556
557 case SC_IRQ_GET_STATUS:
558 if(!line_used(info->line))
559 return -ENODEV;
560
561 mbtk_irq_wait(info->line);
562
563 spin_lock_irqsave(&irq_ctx.lock, flags);
564 error = put_user(irq_ctx.pending, (unsigned int __user *)arg);
565 spin_unlock_irqrestore(&irq_ctx.lock, flags);
566
567 pr_debug("%s:get_status(%d) virq(%d) wake(%d) pending(0x%x)\n",
568 __func__, info->line, info->virq, info->wake, irq_ctx.pending);
569
570 break;
571
572 case SC_IRQ_CLEAR_STATUS:
573 if(!line_used(info->line))
574 return -ENODEV;
575 spin_lock_irqsave(&irq_ctx.lock, flags);
576 irq_ctx.pending &= ~(1 << info->line);
577 spin_unlock_irqrestore(&irq_ctx.lock, flags);
578
579 pr_info("%s:clear_status(%d)\n", __func__, info->line);
580
581 break;
582
583 default:
584 error = -ENOTTY;
585 break;
586 }
587
588 return error;
589}
590
591#ifdef CONFIG_COMPAT
592
593static long
594mbtk_irq_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
595{
596 BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
597
598
599 if (_IOC_TYPE(cmd) != SC_IRQ_IOC_MAGIC)
600 return -ENOTTY;
601
602 if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
603 cmd &= ~IOCSIZE_MASK;
604 cmd |= sizeof(char *) << IOCSIZE_SHIFT;
605 }
606
607 return mbtk_irq_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
608}
609
610#endif /* CONFIG_COMPAT */
611
612static const struct file_operations mbtk_plat_irq_fops = {
613 .open = mbtk_irq_open,
614 .release = mbtk_irq_release,
615 .llseek = no_llseek,
616 .unlocked_ioctl = mbtk_irq_ioctl,
617#ifdef CONFIG_COMPAT
618 .compat_ioctl = mbtk_irq_compat_ioctl,
619#endif
620};
621
622static struct miscdevice mbtk_irq_device[MBTK_LIBIRQ_MAX] = {0};
623static int mbtk_plat_irq_device_init(struct platform_device *pdev)
624{
625 int i;
626 int ret = 0;
627 char name[16];
628 struct miscdevice *misc_dev = NULL;
629 struct device_node *np;
630 g_MbtkPlatIrq_dev.dev = &pdev->dev;
631
632
633 np = of_find_compatible_node(NULL, NULL, "mbtk,plat-irq");
634 if (NULL == np) {
635 pr_err("Can't find interrupt-controller \n");
636 return -ENODEV;
637 }
638 irq_ctx.np = np;
639
640 for(i= 0; i < MAX_GPIO_NUM; i++)
641 {
642 memset(name, 0, sizeof(name));
643 sprintf(name, "%s%d", "gpio_irq", i);
644 pr_err("%s. parse %s \n", __func__, name);
645
646 g_MbtkPlatIrq_dev.gpio_desc[i] = of_get_named_gpio(np, name, 0);
647 g_MbtkPlatIrq_dev.release_func_callback[i] = FALSE;
648
649 if (unlikely(g_MbtkPlatIrq_dev.gpio_desc[i] < 0))
650 {
651 pr_err("%s. parse %s failed\n", __func__, name);
652 }
653 else
654 {
655 pr_err("%s. %s=%d g_MbtkPlatIrq_dev.release_func_callback[i] =%d\n", __func__, name, g_MbtkPlatIrq_dev.gpio_desc[i], g_MbtkPlatIrq_dev.release_func_callback[i]);
656 }
657
658 ret = gpio_request(g_MbtkPlatIrq_dev.gpio_desc[i], name);
659 if(ret < 0)
660 {
661 pr_err("%s. gpio_request for =%d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[i]);
662 return ret;
663 }
664
665 gpio_direction_input(g_MbtkPlatIrq_dev.gpio_desc[i]);
666 }
667
668/*
669 irq_ctx.pctrl = devm_pinctrl_get(&pdev->dev);
670 if (IS_ERR(irq_ctx.pctrl)) {
671 dev_warn(&pdev->dev, "Failed to get sc_irq pins");
672 printk("--->%s/L%d\n", __FUNCTION__, __LINE__);
673 irq_ctx.pctrl = NULL;
674 return -ENODEV;
675 }
676*/
677 for (i=0; i<MBTK_LIBIRQ_MAX; i++) {
678 misc_dev = &mbtk_irq_device[i];
679 misc_dev->mode = 0666,
680 misc_dev->minor = MBTK_IRQ_MINOR + i,
681 memset(name, 0, sizeof(name));
682 sprintf(name, "%s%d", "sc_irq", i);
683 misc_dev->name = name;
684 misc_dev->fops = &mbtk_plat_irq_fops;
685
686 strcpy(irq_ctx.info[i].name, name);
687 irq_ctx.info[i].line = i;
688 irq_ctx.info[i].hirq = irq_line_convert(i);
689 init_waitqueue_head(&irq_ctx.info[i].wait);
690
691 while ((ret = misc_register(misc_dev)) < 0) {
692 if (ret != -EINTR)
693 break;
694 }
695 if (ret < 0) {
696
697 printk(KERN_ERR "misc_register failed with error %d\n", ret);
698 }
699
700
701 /* ret = misc_register(misc_dev);
702 if (ret) {
703 pr_err("%s:register dev(%d) failed:%d \n", __func__, i, ret);
704 return ret;
705 }*/
706
707#if 0 //niening_Test
708 irq_ctx.state[i] = pinctrl_lookup_state(irq_ctx.pctrl, name);
709 if (IS_ERR(irq_ctx.state[i])) {
710
711 dev_err(&pdev->dev, "TEST: missing state(%s)\n", name);
712 return -ENODEV;
713 }
714#endif
715 }
716
717
718 spin_lock_init(&irq_ctx.lock);
719
720 return ret;
721};
722
723static int mbtk_plat_irq_probe(struct platform_device *pdev)
724{
725 int ret = 0;
726
727 //ret = mbtk_plat_irq_device_init();
728 //if (ret)
729 // return ret;
730
731 ret = mbtk_plat_irq_device_init(pdev);
732
733 device_init_wakeup(&pdev->dev, true);
734
735 return ret;
736}
737
738static int mbtk_plat_irq_remove(struct platform_device *pdev)
739{
740 return 0;
741}
742
743static const struct of_device_id mbtk_plat_irq_match[] = {
744 { .compatible = "mbtk,plat-irq", },
745 { }
746};
747
748static struct platform_driver zx_bsp_driver = {
749 .probe = mbtk_plat_irq_probe,
750 .remove = mbtk_plat_irq_remove,
751 .driver = {
752 .name = "mbtk_PlatIrq",
753 .of_match_table = mbtk_plat_irq_match,
754 },
755};
756builtin_platform_driver(zx_bsp_driver)
757
758/*---------------------------------------------------------------*/
759#if 0
760
761static struct reset_control *reboot_rst;
762static int zx_restart(struct notifier_block *this,
763 unsigned long mode, void *cmd)
764{
765 if (reboot_rst) {
766 reset_control_assert(reboot_rst);
767 }
768
769 return NOTIFY_DONE;
770}
771
772static struct notifier_block zx_restart_handler = {
773 .notifier_call = zx_restart,
774 .priority = 129,
775};
776
777static int zx_reboot_probe(struct platform_device *pdev)
778{
779 int ret;
780 struct device_node *np = pdev->dev.of_node;
781
782 reboot_rst = of_reset_control_get_by_index(np, 0);
783 if (!reboot_rst) {
784 dev_err(&pdev->dev, "No reset handler found!");
785 return -EINVAL;
786 }
787
788 ret = register_restart_handler(&zx_restart_handler);
789 if (ret)
790 pr_warn("cannot register restart handler, %d\n", ret);
791
792 return 0;
793}
794
795static const struct of_device_id zx_reboot_match[] = {
796 { .compatible = "zte,reboot", },
797 { }
798};
799
800static struct platform_driver zx_reboot_driver = {
801 .probe = zx_reboot_probe,
802 .driver = {
803 .name = "zx_reboot",
804 .of_match_table = zx_reboot_match,
805 },
806};
807builtin_platform_driver(zx_reboot_driver)
808
809/*----------------------------------------------------------------*/
810#define CONFIG_RPMSG_LOG 1
811
812#ifdef CONFIG_RPMSG_LOG
813#define RPMSG_LOG_SIZE (20*1024)
814static char rpmsg_printk_buf[RPMSG_LOG_SIZE];
815static u32 rpmsg_log_point = 0;
816static u32 rpmsg_log_turn = 0;
817static u32 rpmsg_sram_inited = 0;
818//static char rpmsg_log_temp_buf[512] = {0};
819static spinlock_t rpmsg_log_lock;
820
821static void rpmsg_sram_cpy(char *s, unsigned len)
822{
823 unsigned long flags;
824
825 spin_lock_irqsave(&rpmsg_log_lock, flags);
826
827 if(rpmsg_log_point + len + 2 >= RPMSG_LOG_SIZE) {
828 rpmsg_log_point = 0;
829
830 if (!rpmsg_log_turn)
831 rpmsg_log_turn = 1;
832 }
833
834 memcpy(rpmsg_printk_buf+rpmsg_log_point, s, len);
835 rpmsg_log_point += len;
836 rpmsg_printk_buf[rpmsg_log_point]=0;
837
838 spin_unlock_irqrestore(&rpmsg_log_lock, flags);
839}
840#endif
841
842static ssize_t rpmsg_log_show(struct kobject *kobj, struct kobj_attribute *attr,
843 char *buf)
844{
845 char *s = buf;
846
847#ifdef CONFIG_RPMSG_LOG
848 unsigned long flags;
849
850 if (rpmsg_sram_inited) {
851 spin_lock_irqsave(&rpmsg_log_lock, flags);
852
853 if (!rpmsg_log_turn) {
854 s += sprintf(s, "%s", rpmsg_printk_buf);
855 }
856 else {
857 s += sprintf(s, "%s", rpmsg_printk_buf+rpmsg_log_point+2);
858 s += sprintf(s, "%s", rpmsg_printk_buf);
859 }
860
861 spin_unlock_irqrestore(&rpmsg_log_lock, flags);
862 }
863#endif
864
865 return (s - buf);
866}
867
868/**
869 * usage: like printk(...)
870 */
871void rpmsg_printk(const char *fmt, ...)
872{
873#ifdef CONFIG_RPMSG_LOG
874 va_list args;
875 unsigned long long t;
876 unsigned long nanosec_rem;
877 int tlen, len;
878 char rpmsg_log_temp_buf[512] = {0};
879
880 if(!rpmsg_sram_inited)
881 return;
882
883 va_start(args, fmt);
884
885 /* add time stamp */
886 t = cpu_clock(smp_processor_id());
887 nanosec_rem = do_div(t, 1000000000);
888 tlen = sprintf(rpmsg_log_temp_buf, ">%5lu.%06lu< ",
889 (unsigned long) t, nanosec_rem / 1000);
890
891 len = vsprintf(rpmsg_log_temp_buf+tlen, fmt, args);
892 len += tlen;
893
894 rpmsg_sram_cpy(rpmsg_log_temp_buf, len);
895
896 va_end(args);
897#endif
898}
899
900void rpmsg_sram_init(void)
901{
902#ifdef CONFIG_RPMSG_LOG
903 pr_info("[RPMSG] LOG_INIT \n");
904
905 memset(rpmsg_printk_buf, 0, RPMSG_LOG_SIZE);
906 rpmsg_log_point = 0;
907
908 spin_lock_init(&rpmsg_log_lock);
909
910 rpmsg_sram_inited = 1;
911#endif
912}
913
914#endif