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);
+
+