Baseline update from LYNQ_SDK_ASR_T108_V05.03.01.00(kernel build error.)

Change-Id: I56fc72cd096e82c589920026553170e5cb9692eb
diff --git a/marvell/linux/drivers/misc/mbtk_plat_irq.c b/marvell/linux/drivers/misc/mbtk_plat_irq.c
new file mode 100755
index 0000000..720af18
--- /dev/null
+++ b/marvell/linux/drivers/misc/mbtk_plat_irq.c
@@ -0,0 +1,914 @@
+/*
+ * drivers/soc/zte/plat/plat-zx298501.c
+ *
+ *  Copyright (C) 2021 ZTE-TSP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/syscore_ops.h>
+#include <linux/gpio.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/amba/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/sched/clock.h>
+#include <linux/suspend.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/reboot.h>
+#include <linux/miscdevice.h>
+#include <dt-bindings/soc/mbtk_plat_irq.h>
+#include <uapi/linux/bsp_api.h>
+//#include <linux/soc/sc/common.h>
+/*#include <linux/soc/sc/pcu.h>
+#include <linux/soc/sc/spinlock.h>
+
+
+*/
+/*
+ *  we use sysfs to test&debug some system funcs
+ *
+ */
+struct kobject *zx_root_kobj; 
+struct kobject *zx_test_kobj;
+struct kobject *zx_pm_kobj;
+
+extern int __init zx_clk_test_init(void);
+extern int __init zx_dma_test_init(void);
+extern int __init zx_icp_test_init(void);
+extern int __init zx_timer_test_init(void);
+
+#define DOUBLE_EINT_DBG     0
+#define EINT_THREAD_TEST    0
+
+#define	CONFIG_USE_DEBUG_LED		1
+#define ZX_RESET_TEST		1
+#define ZX_CLK_TEST			1
+#define ZX_PINCTRL_TEST		1
+#define ZX_GPIO_TEST		1
+#define ZX_EINT_TEST		1
+#define ZX_PM_TEST			1
+#if ZX_PM_TEST
+#define PM_RUNTIME_AUTO_TEST	1
+#endif
+#define ZX_SPINLOCK_TEST	0
+#define ZX_PM_QOS_TEST		0
+
+#define TRUE 1
+#define FALSE 0
+
+/* 
+ * 
+ * some test need device probe
+ */
+struct zx_drv_test
+{
+	struct device	*dev;
+#if ZX_RESET_TEST	
+	struct reset_control *rst;
+#endif
+
+#if ZX_PINCTRL_TEST
+	struct pinctrl		  *pctrl;
+	struct pinctrl_state  *state0;
+	struct pinctrl_state  *state1;
+	struct pinctrl_state  *state2;
+#endif
+
+#if ZX_GPIO_TEST
+	int						gpio;
+	int						gpio2;
+	int						gpio3;
+	struct gpio_desc 		*gd;
+
+#endif
+
+#if ZX_EINT_TEST
+	int						eint_irq;
+	int 					eint_irq2;
+#endif
+
+#if	ZX_CLK_TEST
+	struct clk 				*clk;
+#endif
+};
+
+struct zx_drv_test drv_test = {0};
+
+#define MAX_GPIO_NUM 4
+
+struct MbtkPlatIrq_dev
+{
+	struct device	*dev;
+	struct pinctrl		  *pctrl;
+	int gpio_desc[MAX_GPIO_NUM] ;
+	int release_func_callback[MAX_GPIO_NUM] ;
+	//struct wakeup_source *WakeUp_ws;
+	
+};	
+
+struct MbtkPlatIrq_dev g_MbtkPlatIrq_dev = {0};
+
+
+
+
+
+
+#if 0//ZX_RESET_TEST
+static void drv_reset_test(struct reset_control *rstc)
+{
+	reset_control_assert(rstc);
+	udelay(10);
+	reset_control_deassert(rstc);	
+}
+#endif
+
+#if ZX_EINT_TEST
+#if EINT_THREAD_TEST
+static irqreturn_t test_eint_pri_isr(int irq, void *p)
+{
+	disable_irq_nosync(irq);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t test_eint_isr(int irq, void *p)
+{
+	static int eint_cnt = 0;
+	if ( pinctrl_select_state(drv_test.pctrl, drv_test.state0) < 0) {
+		pr_err("setting state0 failed\n");
+	}
+
+	irq_set_irq_type(drv_test.eint_irq, gpio_get_value(drv_test.gpio)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
+
+	if ( pinctrl_select_state(drv_test.pctrl, drv_test.state1) < 0) {
+		pr_err("setting state0 failed\n");
+	}
+
+	enable_irq(irq);
+
+	pr_info("eint9 get = %d\n", ++eint_cnt);
+
+	return IRQ_HANDLED;
+}
+#else
+static irqreturn_t test_eint_isr(int irq, void *p)
+{
+	static int eint_cnt = 0;
+
+	irq_set_irq_type(drv_test.eint_irq, gpio_get_value(drv_test.gpio)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
+
+	//pr_info("eint9 get = %d\n", ++eint_cnt);
+
+	return IRQ_HANDLED;
+}
+#endif
+static irqreturn_t test_eint_isr2(int irq, void *p)
+{
+	static int eint_cnt1 = 0;
+
+	irq_set_irq_type(drv_test.eint_irq2, gpio_get_value(drv_test.gpio2)?IRQ_TYPE_LEVEL_LOW:IRQ_TYPE_LEVEL_HIGH);
+
+	pr_info("eint12 get = %d\n", ++eint_cnt1);
+
+	return IRQ_HANDLED;
+}
+
+#endif
+
+
+
+/*-------------------------------------------------------------------*/
+#define MBTK_IRQ_MINOR			(170)
+#define MBTK_LIBIRQ_MAX			(4)
+
+/*
+ * line 		: request
+ * type 		: driver use
+ * wake_flag	: for wait
+ *
+ */
+struct libirq_info {
+	unsigned int 		line;
+	unsigned int 		hirq;
+	unsigned int 		virq;
+	unsigned int 		type;
+	int 				wake;
+	unsigned int 		used;
+	bool				wake_flag;
+	wait_queue_head_t 	wait;
+	char				name[16];
+};
+
+struct libirq_context {
+	unsigned int 			pending;
+	spinlock_t 				lock;
+	struct pinctrl			*pctrl;
+	struct pinctrl_state	*state[MBTK_LIBIRQ_MAX];
+
+	struct device_node 		*np;
+	struct device_node 		*ext8in1_np;
+	struct libirq_info		info[MBTK_LIBIRQ_MAX];
+};
+static struct libirq_context irq_ctx = {0};
+
+#define line_used(l)		irq_ctx.info[l].used
+
+static int irq_line_convert(int line)
+{
+#if 0  //forbid by niening
+	if (line>=4)
+		return EX24_INT + line - 8;
+	else
+		return EX21_INT + line;
+ 
+
+#else
+    int irq;
+  	
+    irq = gpio_to_irq(g_MbtkPlatIrq_dev.gpio_desc[line]);
+    if (irq  < 0) 
+		{
+			pr_err("%s. gpio %d request  irq  %d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[line], irq);
+			
+		}
+	
+	return irq;
+
+#endif
+}
+
+static unsigned int irq_type_convert(unsigned int req_type)
+{
+	//printk("--->%s/L%d req_type = %d\n", __FUNCTION__, __LINE__, req_type);
+	if (req_type == 0)
+		return IRQ_TYPE_EDGE_RISING;
+	else if (req_type == 1)
+		return IRQ_TYPE_EDGE_FALLING;
+	else if (req_type == 2)
+		return IRQ_TYPE_LEVEL_HIGH;
+	else if (req_type == 3)
+		return IRQ_TYPE_LEVEL_LOW;
+	else
+		return IRQ_TYPE_NONE;
+}
+
+static int mbkt_irq_map_ext8in1(int hirq, unsigned int type)
+{
+	struct of_phandle_args args;
+
+	args.args_count = 2;
+	args.args[0] = hirq;
+	args.args[1] = type;
+	args.np = irq_ctx.ext8in1_np;
+
+	return irq_create_of_mapping(&args);
+}
+
+static int mbkt_irq_map(int hirq, unsigned int type,  unsigned int line)
+{
+	struct of_phandle_args args;
+	int ret = 0;
+#if 0
+	char name[16];
+
+	//if (hirq>=EX8_INT && hirq<=EX15_INT)
+	//	return mbkt_irq_map_ext8in1(hirq, type);
+
+	memset(name, 0, sizeof(name));
+	sprintf(name, "%s%d", "gpio_irq", line);
+
+	ret = gpio_request(g_MbtkPlatIrq_dev.gpio_desc[line], name);
+	if(ret < 0) 
+	{
+	    pr_err("%s. gpio_request for =%d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[line]);
+	}
+
+	gpio_direction_input(g_MbtkPlatIrq_dev.gpio_desc[line]);
+	
+	hirq = gpio_to_irq(g_MbtkPlatIrq_dev.gpio_desc[line]);
+
+
+	pr_err("%s. %s=%d, hirq = %d\n", __func__,  name, g_MbtkPlatIrq_dev.gpio_desc[line], hirq);
+	irq_ctx.info[line].hirq  = hirq;
+#endif
+	args.args_count = 3;
+	args.args[0] = 0;
+	args.args[1] = hirq;
+	args.args[2] = type;
+	args.np = irq_ctx.np;
+	
+	return hirq;
+	//return irq_create_of_mapping(&args);
+}
+
+static void mbtk_irq_wait(unsigned int line)
+{
+	struct libirq_info *info = &(irq_ctx.info[line]);
+
+	info->wake_flag = false;
+	wait_event_freezable(info->wait, info->wake_flag);
+}
+
+static void mbtk_irq_wakeup(unsigned int line)
+{
+	struct libirq_info *info = &(irq_ctx.info[line]);
+
+	info->wake_flag = true;
+	wake_up_interruptible(&info->wait);
+}
+
+static irqreturn_t mbtk_irq_isr(int irq, void *priv)
+{
+	struct libirq_info *info = (struct libirq_info *)priv;
+	unsigned int line = info->line;
+	int gpio_value = 0;
+
+	disable_irq_nosync(irq); //add by niening
+	
+	gpio_value = gpio_get_value_cansleep(g_MbtkPlatIrq_dev.gpio_desc[line]) ;
+
+	printk("%s/L%d, gpio_value = %d \n", __FUNCTION__, __LINE__, gpio_value);
+	 if(info->wake)
+	 {
+	 	pm_wakeup_event(g_MbtkPlatIrq_dev.dev, 2000);
+	 }
+
+
+	if(line_used(line)) {
+		irq_ctx.pending |= BIT(line);
+
+		mbtk_irq_wakeup(line);
+	}
+
+
+
+	pr_info("%s:eint get = %d\n", __func__, line); 
+	
+	enable_irq(irq);//add by niening
+	
+	return IRQ_HANDLED;
+}
+
+static int mbtk_irq_open(struct inode *inode, struct file *filp)
+{
+	int error = 0;
+	unsigned int line;
+	struct libirq_info *info;
+
+	line = iminor(inode) - MBTK_IRQ_MINOR;
+
+	filp->private_data = &(irq_ctx.info[line]);
+
+
+	info = (struct libirq_info *)filp->private_data;
+
+ // add  by niening for solve upper app restart send install cmd
+
+	   if (g_MbtkPlatIrq_dev.release_func_callback[info->line] == TRUE)
+		{
+			pr_err("%s/L%d\n", __FUNCTION__, __LINE__);
+			free_irq(info->virq, info);
+		}
+
+
+	return error;
+}
+
+static int mbtk_irq_release(struct inode *inode, struct file *filp)
+{
+	struct libirq_info *info;
+
+	info = (struct libirq_info *)filp->private_data;
+	
+	pr_err("%s/L%d\n", __FUNCTION__, __LINE__);
+	
+	if(line_used(info->line)) {
+
+#if 0  // forbid by niening for upper app goto sleep  will callback this function
+
+	    //irq_set_irq_type(info->virq, IRQ_TYPE_NONE);
+		//free_irq(info->virq, info);
+#endif	
+
+		line_used(info->line) = 0;
+	}
+
+	filp->private_data = NULL;
+
+ 
+	g_MbtkPlatIrq_dev.release_func_callback[info->line] = TRUE;
+	return 0;
+}
+
+static long mbtk_irq_ioctl(struct file *filp, unsigned int cmd,
+							unsigned long arg)
+{
+	int error = 0;
+	struct libirq_info *info;
+	int virq;
+	unsigned int type;
+	unsigned int en;
+	int ret = 0;
+	unsigned long flags;
+
+	info = (struct libirq_info *)filp->private_data;
+ 
+	switch (cmd) {
+
+	case SC_IRQ_INSTALL:
+
+		if(line_used(info->line))
+			return -EEXIST;
+		
+		type = irq_type_convert((unsigned int)arg);
+	
+		virq = mbkt_irq_map(info->hirq, type, info->line);
+		if (virq <= 0) {
+			pr_err("%s:mbkt_irq_map %d failed %d(%d)\n", __func__, info->line, virq, type);
+			return -ENOMEM;
+		}
+		/* pr_err("%s:mbkt_irq_map %d %d %d\n", __func__, info->line, virq, info->hirq);*/
+
+#if 1// niening_Test
+	/*	if ( pinctrl_select_state(irq_ctx.pctrl, irq_ctx.state[info->line]) < 0) {
+		pr_err("%s:setting state%d failed\n", __func__, info->line);
+			return -ENODEV;
+		}
+*/
+		ret = request_irq(virq, mbtk_irq_isr, 0, info->name, info);
+		if(ret<0) {
+			pr_err("%s:request_irq %d failed %d\n", __func__, info->line, type);
+			return ret;
+		}
+#else
+		ret = devm_request_threaded_irq(g_MbtkPlatIrq_dev.dev, virq, mbtk_irq_isr,mbtk_irq_isr,0 , info->name, info);
+
+
+#endif		
+		info->virq = virq;
+		info->type = type;
+
+		line_used(info->line) = 1;
+	
+		 pr_info("%s:install(%d) hirq(%d) virq(%d) type(%d)\n", __func__, info->line, info->hirq, info->virq, info->type);
+		break;
+
+	case SC_IRQ_UNINSTALL:
+		
+		
+		if(!line_used(info->line))
+			return -ENODEV;
+
+		irq_set_irq_type(info->virq, IRQ_TYPE_NONE);
+
+		free_irq(info->virq, info);
+
+		line_used(info->line) = 0;
+
+		pr_info("%s:uninstall(%d)\n", __func__, info->line);
+		break;
+
+	case SC_IRQ_SET_TYPE:
+
+		if(!line_used(info->line))
+			return -ENODEV;
+			
+		type = irq_type_convert((unsigned int)arg);
+		
+#if 0  //niening_test
+		ret = irq_set_irq_type(info->virq, type);
+#else
+
+		ret = irq_set_irq_type(info->virq, (type | IRQF_ONESHOT));
+#endif
+		if (ret)
+			return ret;
+
+		info->type = type;
+	
+		pr_info("%s:set_type(%d) virq(%d) type(%d)\n", __func__, info->line, info->virq, info->type); 
+
+		break;
+
+	case SC_IRQ_SET_WAKE:
+		if(!line_used(info->line))
+			return -ENODEV;
+
+		en = (unsigned int)arg;
+
+#if 0  //niening_test
+		
+		ret = irq_set_irq_wake(info->virq, en);
+		if (ret)
+			return ret;
+#else
+		if(en)
+			enable_irq_wake(info->virq);
+		else
+			disable_irq_wake(info->virq);
+		
+#endif
+
+		info->wake = en;
+		pr_info("%s:set_wake(%d) virq(%d) wake(%d)\n", __func__, info->line, info->virq, info->wake); 
+
+		break;
+
+	case SC_IRQ_GET_WAKE:
+			
+		if(!line_used(info->line))
+			return -ENODEV;
+		error = put_user(info->wake, (unsigned int __user *)arg);
+
+		 pr_info("%s:get_wake(%d) virq(%d) wake(%d)\n", __func__, info->line, info->virq, info->wake); 
+
+		break;
+
+
+	case SC_IRQ_GET_STATUS:
+		if(!line_used(info->line))
+			return -ENODEV;
+
+		mbtk_irq_wait(info->line);
+
+		spin_lock_irqsave(&irq_ctx.lock, flags);
+		error = put_user(irq_ctx.pending, (unsigned int __user *)arg);
+		spin_unlock_irqrestore(&irq_ctx.lock, flags);
+
+		 pr_debug("%s:get_status(%d) virq(%d) wake(%d) pending(0x%x)\n",
+			__func__, info->line, info->virq, info->wake, irq_ctx.pending); 
+
+		break;
+
+	case SC_IRQ_CLEAR_STATUS:
+		if(!line_used(info->line))
+			return -ENODEV;
+		spin_lock_irqsave(&irq_ctx.lock, flags);
+		irq_ctx.pending &= ~(1 << info->line);
+		spin_unlock_irqrestore(&irq_ctx.lock, flags);
+
+		 pr_info("%s:clear_status(%d)\n", __func__, info->line); 
+
+		break;
+
+	default:
+		error = -ENOTTY;
+		break;
+	}
+
+	return error;
+}
+
+#ifdef CONFIG_COMPAT
+
+static long
+mbtk_irq_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
+
+
+	if (_IOC_TYPE(cmd) != SC_IRQ_IOC_MAGIC)
+		return -ENOTTY;
+
+	if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
+		cmd &= ~IOCSIZE_MASK;
+		cmd |= sizeof(char *) << IOCSIZE_SHIFT;
+	}
+
+	return mbtk_irq_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+
+#endif /* CONFIG_COMPAT */
+
+static const struct file_operations mbtk_plat_irq_fops = {
+	.open = mbtk_irq_open,
+	.release = mbtk_irq_release,
+	.llseek = no_llseek,
+	.unlocked_ioctl = mbtk_irq_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = mbtk_irq_compat_ioctl,
+#endif
+};
+
+static struct miscdevice mbtk_irq_device[MBTK_LIBIRQ_MAX] = {0};
+static int mbtk_plat_irq_device_init(struct platform_device *pdev)
+{
+	int i;
+	int ret = 0;
+	char name[16];
+	struct miscdevice *misc_dev = NULL;
+	struct device_node *np;
+	g_MbtkPlatIrq_dev.dev = &pdev->dev;
+	
+
+	np = of_find_compatible_node(NULL, NULL, "mbtk,plat-irq");
+	if (NULL == np)	{
+		pr_err("Can't find interrupt-controller \n");
+		return -ENODEV;
+	}
+	irq_ctx.np = np;
+
+	for(i= 0; i < MAX_GPIO_NUM; i++)
+	{
+		memset(name, 0, sizeof(name));
+		sprintf(name, "%s%d", "gpio_irq", i);
+		pr_err("%s. parse %s \n", __func__, name); 
+		
+		g_MbtkPlatIrq_dev.gpio_desc[i] = of_get_named_gpio(np, name, 0);
+		g_MbtkPlatIrq_dev.release_func_callback[i] = FALSE;
+
+		if (unlikely(g_MbtkPlatIrq_dev.gpio_desc[i] < 0)) 
+		{
+			pr_err("%s. parse %s failed\n", __func__, name); 
+		} 
+		else 
+		{
+			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]);
+		}
+
+		ret = gpio_request(g_MbtkPlatIrq_dev.gpio_desc[i], name);
+		if(ret < 0) 
+		{
+			pr_err("%s. gpio_request for =%d failed\n", __func__,g_MbtkPlatIrq_dev.gpio_desc[i]);
+			return ret;
+		}
+
+		gpio_direction_input(g_MbtkPlatIrq_dev.gpio_desc[i]);
+	}
+	
+/*
+	irq_ctx.pctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(irq_ctx.pctrl)) {
+		dev_warn(&pdev->dev, "Failed to get sc_irq pins");
+		printk("--->%s/L%d\n", __FUNCTION__, __LINE__);
+		irq_ctx.pctrl = NULL;
+		return -ENODEV;
+	}
+*/
+	for (i=0; i<MBTK_LIBIRQ_MAX; i++) {
+		misc_dev = &mbtk_irq_device[i];
+		misc_dev->mode = 0666,
+		misc_dev->minor = MBTK_IRQ_MINOR + i,
+		memset(name, 0, sizeof(name));
+		sprintf(name, "%s%d", "sc_irq", i);
+		misc_dev->name = name;
+		misc_dev->fops = &mbtk_plat_irq_fops;
+
+		strcpy(irq_ctx.info[i].name, name);
+		irq_ctx.info[i].line = i;
+		irq_ctx.info[i].hirq = irq_line_convert(i);
+		init_waitqueue_head(&irq_ctx.info[i].wait);
+
+		while ((ret = misc_register(misc_dev)) < 0) {
+    		if (ret != -EINTR)
+        	break; 		
+		}
+		if (ret < 0) {
+    		
+    		printk(KERN_ERR "misc_register failed with error %d\n", ret);
+		}
+
+	
+	/*	ret = misc_register(misc_dev);
+		if (ret) {
+			pr_err("%s:register dev(%d) failed:%d \n", __func__, i, ret);
+			return ret;
+		}*/
+
+#if 0  //niening_Test
+ 		irq_ctx.state[i] = pinctrl_lookup_state(irq_ctx.pctrl, name);
+		if (IS_ERR(irq_ctx.state[i])) {
+
+			dev_err(&pdev->dev, "TEST: missing state(%s)\n", name);
+			return -ENODEV;
+		}
+#endif
+	}
+
+
+	spin_lock_init(&irq_ctx.lock);
+
+	return ret;
+};
+
+static int mbtk_plat_irq_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	//ret = mbtk_plat_irq_device_init();
+	//if (ret)
+	//	return ret;
+
+	ret = mbtk_plat_irq_device_init(pdev);
+
+	device_init_wakeup(&pdev->dev, true);
+
+	return ret;
+}
+
+static int mbtk_plat_irq_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id mbtk_plat_irq_match[] = {
+	{ .compatible = "mbtk,plat-irq", },
+	{ }
+};
+
+static struct platform_driver zx_bsp_driver = {
+	.probe = mbtk_plat_irq_probe,
+	.remove = mbtk_plat_irq_remove,
+	.driver = {
+		.name = "mbtk_PlatIrq",
+		.of_match_table = mbtk_plat_irq_match,
+	},
+};
+builtin_platform_driver(zx_bsp_driver)
+
+/*---------------------------------------------------------------*/
+#if 0
+
+static struct reset_control *reboot_rst;
+static int zx_restart(struct notifier_block *this,
+			   unsigned long mode, void *cmd)
+{
+	if (reboot_rst) {
+		reset_control_assert(reboot_rst);		
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block zx_restart_handler = {
+	.notifier_call = zx_restart,
+	.priority = 129,
+};
+
+static int zx_reboot_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device_node *np = pdev->dev.of_node;
+
+	reboot_rst = of_reset_control_get_by_index(np, 0);
+	if (!reboot_rst) {
+		dev_err(&pdev->dev, "No reset handler found!");
+		return -EINVAL;
+	}
+
+	ret = register_restart_handler(&zx_restart_handler);
+	if (ret)
+		pr_warn("cannot register restart handler, %d\n", ret);
+
+	return 0;
+}
+
+static const struct of_device_id zx_reboot_match[] = {
+	{ .compatible = "zte,reboot", },
+	{ }
+};
+
+static struct platform_driver zx_reboot_driver = {
+	.probe = zx_reboot_probe,
+	.driver = {
+		.name = "zx_reboot",
+		.of_match_table = zx_reboot_match,
+	},
+};
+builtin_platform_driver(zx_reboot_driver)
+
+/*----------------------------------------------------------------*/
+#define CONFIG_RPMSG_LOG	1
+
+#ifdef CONFIG_RPMSG_LOG
+#define	 RPMSG_LOG_SIZE	(20*1024)
+static char rpmsg_printk_buf[RPMSG_LOG_SIZE];
+static u32  rpmsg_log_point = 0;
+static u32  rpmsg_log_turn = 0;
+static u32  rpmsg_sram_inited = 0;
+//static char rpmsg_log_temp_buf[512] = {0};
+static spinlock_t	rpmsg_log_lock;
+
+static void rpmsg_sram_cpy(char *s, unsigned len)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rpmsg_log_lock, flags);
+
+	if(rpmsg_log_point + len + 2 >= RPMSG_LOG_SIZE) {
+		rpmsg_log_point = 0;
+
+		if (!rpmsg_log_turn)
+			rpmsg_log_turn = 1;
+	}
+
+	memcpy(rpmsg_printk_buf+rpmsg_log_point, s, len);
+	rpmsg_log_point += len;
+	rpmsg_printk_buf[rpmsg_log_point]=0;
+
+	spin_unlock_irqrestore(&rpmsg_log_lock, flags);
+}
+#endif
+
+static ssize_t rpmsg_log_show(struct kobject *kobj, struct kobj_attribute *attr,
+			  char *buf)
+{
+	char *s = buf;
+
+#ifdef CONFIG_RPMSG_LOG
+	unsigned long flags;
+
+	if (rpmsg_sram_inited) {
+		spin_lock_irqsave(&rpmsg_log_lock, flags);
+
+		if (!rpmsg_log_turn) {
+			s += sprintf(s, "%s", rpmsg_printk_buf);
+		}
+		else {
+			s += sprintf(s, "%s", rpmsg_printk_buf+rpmsg_log_point+2);
+			s += sprintf(s, "%s", rpmsg_printk_buf);
+		}
+
+		spin_unlock_irqrestore(&rpmsg_log_lock, flags);
+	}
+#endif
+
+	return (s - buf);
+}
+
+/**
+ * usage: like printk(...)
+ */
+void rpmsg_printk(const char *fmt, ...)
+{
+#ifdef CONFIG_RPMSG_LOG
+	va_list args;
+	unsigned long long t;
+	unsigned long nanosec_rem;
+	int tlen, len;
+	char rpmsg_log_temp_buf[512] = {0};
+
+	if(!rpmsg_sram_inited)
+		return;
+
+	va_start(args, fmt);
+
+	/* add time stamp */
+	t = cpu_clock(smp_processor_id());
+	nanosec_rem = do_div(t, 1000000000);
+	tlen = sprintf(rpmsg_log_temp_buf, ">%5lu.%06lu< ",
+		       (unsigned long) t, nanosec_rem / 1000);
+
+	len = vsprintf(rpmsg_log_temp_buf+tlen, fmt, args);
+	len += tlen;
+
+	rpmsg_sram_cpy(rpmsg_log_temp_buf, len);
+
+	va_end(args);
+#endif
+}
+
+void rpmsg_sram_init(void)
+{
+#ifdef CONFIG_RPMSG_LOG
+    pr_info("[RPMSG] LOG_INIT \n");
+
+	memset(rpmsg_printk_buf, 0, RPMSG_LOG_SIZE);
+	rpmsg_log_point = 0;
+
+	spin_lock_init(&rpmsg_log_lock);
+
+	rpmsg_sram_inited = 1;
+#endif
+}
+
+#endif
\ No newline at end of file