zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297510/icp.c b/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297510/icp.c
new file mode 100644
index 0000000..8ff797d
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/arch/arm/mach-zx297510/icp.c
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (C) 2013, ZTE Corporation.
+ *
+ * File Name: icp.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       V0.1
+ * Author:        ShiDeYou
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+ ******************************************************************************/
+
+/*******************************************************************************
+*                                  Include files                               *
+*******************************************************************************/
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+#include <asm/mach/map.h>
+#include <mach/rpmsg.h>
+#include <linux/kthread.h>
+
+
+/*******************************************************************************
+*                                    Macro                                     *
+*******************************************************************************/
+
+
+/*******************************************************************************
+*                           Global  Variable                                   *
+*******************************************************************************/
+ 
+static Icp_rpmsg_drv icp_arm0_info = {
+	.name	= "icp_arm0",	
+	.Channel_config =
+		{
+			.ChConfig = {CH_IRAM, CH_IRAM, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,CH_DDR,\
+					    CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
+					    CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
+					    CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
+					    CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
+						CH_DDR},
+		},
+};
+
+static Icp_rpmsg_drv icp_m0_info = {
+	.name	= "icp_m0",
+	.Channel_config =
+		{
+			.ChConfig = {CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
+					    CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,\
+					    CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
+					    CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
+					    CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,
+					    CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM},
+		},
+};
+
+Icp_rpmsg_drv *IcpRpMsgInfo[] = { &icp_m0_info, &icp_arm0_info, NULL };
+
+T_HalRpMsg_RWP ap2cp_chinfo[ACTOR_MAXID][CHANNEL_MAXID];
+T_HalRpMsg_RWP cp2ap_chinfo[ACTOR_MAXID][CHANNEL_MAXID];
+
+/*******************************************************************************
+* Function: zx29_Icp_SetInt
+* Description: This function is used for generating icp interrupt to inform remote cpu;
+* Parameters:
+*   Input:
+           actorID: id of remote cpu
+           chID: id of channel
+*   Output:None
+*
+* Returns:None
+*
+*
+* Others:
+********************************************************************************/
+int icp_set_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
+{
+    T_HalRpMsg_ChInfo *channel_send = IcpRpMsgInfo[actorID]->ChInfo_Send_Base + chID;
+
+    if(!(channel_send->flag & CHANNEL_FLAG))
+	return RPMSG_CHANNEL_INEXISTANCE;
+	
+    if(chID<32)
+    {
+        iowrite32((1<<chID), &(IcpRpMsgInfo[actorID]->IcpReg->control.low_word)) ;
+    }
+    else
+    {
+       iowrite32((1<<(chID - 32)),&(IcpRpMsgInfo[actorID]->IcpReg->control.high_word));
+    }   
+	return RPMSG_SUCCESS;
+}
+  
+/*******************************************************************************
+* Function: zx29_Icp_ClearInt
+* Description: This function is used for clear icp interrupt from remote cpu;
+* Parameters:
+*   Input:
+           actorID: id of remote cpu
+           chID: id of channel
+*   Output:None
+*
+* Returns:None
+*
+*
+* Others:
+********************************************************************************/
+ void icp_clear_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
+{
+    if(chID<32)
+    {	
+        iowrite32((1<<chID), &(IcpRpMsgInfo[actorID]->IcpReg->clear.low_word));
+    }
+    else
+    {
+       iowrite32(1<<(chID - 32), &(IcpRpMsgInfo[actorID]->IcpReg->clear.high_word)) ;
+    }   
+}
+
+/*******************************************************************************
+* Function: zx29_Icp_GetInt
+* Description: This function is used for get icp interrupt from remote cpu;
+* Parameters:
+*   Input:
+*           actorID: id of remote cpu
+*           chID: id of channel
+*   Output:None
+*
+* Returns:None
+*
+*
+* Others:
+********************************************************************************/
+ T_HalIcp_Dword icp_get_int(T_ZDrvRpMsg_ActorID actorID)
+{
+	void __iomem *tmp = NULL;
+	T_HalIcp_Dword IcpState = {0};
+	tmp = &(IcpRpMsgInfo[actorID]->IcpReg->state.high_word);
+	IcpState.high_word = ioread32(tmp);
+	tmp = &(IcpRpMsgInfo[actorID]->IcpReg->state.low_word);
+	IcpState.low_word = ioread32(tmp);
+	
+	return IcpState;
+}
+
+/*******************************************************************************
+* Function: zx29_Icp_GetIntState
+* Description: This function is used for get the state of icp interruptting  of remote cpu;
+* Parameters:
+*   Input:
+           actorID: id of remote cpu
+           chID: id of channel
+*   Output:None
+*
+* Returns:None
+*
+*
+* Others:
+********************************************************************************/
+int icp_get_intstate(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
+{
+	if(chID < 32)
+	{
+		if(ioread32(&(IcpRpMsgInfo[actorID]->IcpReg->in_state.low_word)) & (0x1 << chID))
+			return TRUE;
+		else
+			return FALSE;
+	}
+	else
+	{
+		if(ioread32(&(IcpRpMsgInfo[actorID]->IcpReg->in_state.high_word)) & (0x1 << (chID - 32)))
+			return TRUE;
+		else
+			return FALSE;
+	}
+}
+	
+/*******************************************************************************
+* Function: zx29_Icp_Mask
+* Description: This function is used for Mask interrupt of channel;
+* Parameters:
+*   Input:
+*   Output:
+*
+* Returns:  NONE
+*
+*
+* Others:
+********************************************************************************/
+void icp_mask_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
+{
+    if(chID < 32)
+    {
+        IcpRpMsgInfo[actorID]->IcpReg->mask.low_word |=(0x1<<chID);
+    }
+    else
+    {
+        IcpRpMsgInfo[actorID]->IcpReg->mask.high_word |= (0x1<<(chID-32));
+    }
+}
+
+/*******************************************************************************
+* Function: zx29_Icp_UnMask
+* Description: This function is used for unmask interrupt of channel;
+* Parameters:
+*   Input:
+*   Output:
+*
+* Returns:
+*            NONE
+*
+*
+* Others:
+********************************************************************************/
+void icp_unmask_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
+{
+     if(chID < 32)
+    {
+        IcpRpMsgInfo[actorID]->IcpReg->mask.low_word &= ~(0x1<<chID);
+    }
+    else
+    {
+        IcpRpMsgInfo[actorID]->IcpReg->mask.high_word &= ~(0x1<<(chID-32));
+    }
+     
+}
+
+static icp_operations icp_ops = {
+	.Icp_SetInt = icp_set_int,
+	.Icp_ClearInt = icp_clear_int,
+	.Icp_GetInt = icp_get_int,
+	.Icp_GetIntState = icp_get_intstate,
+	.Icp_Mask = icp_mask_int,
+	.Icp_UnMask = icp_unmask_int,
+};
+
+
+
+
+static int __devinit icp_probe(struct platform_device *pdev)
+{
+	struct resource *icp_mem;
+	struct resource *icp_iram_send;
+	struct resource *icp_iram_recv;
+	struct resource *icp_ddr_send;
+	struct resource *icp_ddr_recv;
+	
+	int ret;
+	Icp_rpmsg_drv *list;
+	unsigned int i;
+	
+	list = IcpRpMsgInfo[pdev->id];
+	list->actorID = pdev->id;
+	
+	list->intline = platform_get_irq(pdev, 0 );
+
+	icp_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp");
+	icp_iram_send = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_iram_send");
+	icp_iram_recv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_iram_recv");
+	icp_ddr_send = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_ddr_send");
+	icp_ddr_recv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_ddr_recv");
+
+	if (!icp_mem || !icp_iram_send || !icp_iram_recv)
+		return -ENOMEM;
+
+	list->IcpReg = (T_HalIcp_Reg *)ioremap(icp_mem->start, resource_size(icp_mem));
+	list->ChInfo_Send_Base = (T_HalRpMsg_ChInfo *)ioremap(icp_iram_send->start, resource_size(icp_iram_send));
+	list->ChInfo_Recv_Base = (T_HalRpMsg_ChInfo *)ioremap(icp_iram_recv->start, resource_size(icp_iram_recv));
+	list->ChInfo_SendBase_offset= (unsigned int)(list->ChInfo_Send_Base) - (unsigned int)(icp_iram_send->start);
+	list->ChInfo_RecvBase_offset= (unsigned int)(list->ChInfo_Recv_Base) - (unsigned int)(icp_iram_recv->start);
+
+	memset(list->ChInfo_Send_Base, 0, (CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo)));
+  
+	list->Ddr_SendBase = (unsigned int)(icp_ddr_send->start);
+	list->Ddr_RecvBase = (unsigned int)(icp_ddr_recv->start);
+	list->Ddr_SendBase_offset =  (unsigned int)ioremap(icp_ddr_send->start, resource_size(icp_ddr_send)) - list->Ddr_SendBase;
+	list->Ddr_RecvBase_offset = (unsigned int)ioremap(icp_ddr_recv->start, resource_size(icp_ddr_recv)) - list->Ddr_RecvBase;
+
+	list->IcpReg->mask.high_word=0xffffffff;
+	list->IcpReg->mask.low_word=0xffffffff;
+
+	list->Channel_config.CurIramAddr = (unsigned int)(icp_iram_send->start + CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo));	
+	list->Channel_config.CurIramSpace_Size = icp_iram_send->end - icp_iram_send->start - CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo);
+	list->Channel_config.CurDdrAddr = (unsigned int)(icp_ddr_send->start);
+	list->Channel_config.CurDdrSpace_Size = icp_ddr_send->end - icp_ddr_send->start;
+	
+	if (!list->IcpReg && !list->Channel_config.CurIramAddr && !list->Channel_config.CurDdrAddr)
+		return -ENODEV;
+
+	list->ops = &icp_ops;
+
+	for(i = 0; i<CHANNEL_MAXID; i++)
+	{
+		ap2cp_chinfo[pdev->id][i].writep = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->SendPos);
+		ap2cp_chinfo[pdev->id][i].readp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->RecvPos);
+		ap2cp_chinfo[pdev->id][i].endp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->EndAddr);
+		cp2ap_chinfo[pdev->id][i].writep = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->SendPos);
+		cp2ap_chinfo[pdev->id][i].readp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->RecvPos);
+		cp2ap_chinfo[pdev->id][i].endp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->EndAddr);
+	}
+	
+	ret = icp_rpmsg_register(list);
+  
+	if (ret)
+		goto unmap_base;
+
+	printk("rpmsg: icp_probe actorID = %d, success!\n", list->actorID);
+	
+	return 0;
+
+unmap_base:
+	iounmap(list->IcpReg);
+	iounmap(list->ChInfo_Send_Base);
+	iounmap(list->ChInfo_Recv_Base);
+	//iounmap((unsigned int *)(list->Ddr_SendBase_map));
+	//iounmap((unsigned int *)(list->Ddr_RecvBase_map));
+
+    
+	
+	return ret;
+}
+
+static int __devexit icp_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	ret = icp_rpmsg_unregister(IcpRpMsgInfo[pdev->id]);
+	return ret;
+}
+
+static struct platform_driver icp_driver = {
+	.probe = icp_probe,
+	.remove = __devexit_p(icp_remove),
+	.driver = {
+		.name = "icp",
+	},
+};
+
+static int __init icp_init(void)
+{
+	return platform_driver_register(&icp_driver);
+}
+  
+subsys_initcall(icp_init);
+
+static void __exit icp_exit(void)
+{
+	platform_driver_unregister(&icp_driver);
+}
+    
+module_exit(icp_exit);
+
+