blob: 8ff797dca59bbad032ed10303055baa9784aab1b [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*******************************************************************************
2 * Copyright (C) 2013, ZTE Corporation.
3 *
4 * File Name: icp.c
5 * File Mark:
6 * Description:
7 * Others:
8 * Version: V0.1
9 * Author: ShiDeYou
10 * Date: 2013-3-13
11 * History 1:
12 * Date:
13 * Version:
14 * Author:
15 * Modification:
16 * History 2:
17 ******************************************************************************/
18
19/*******************************************************************************
20* Include files *
21*******************************************************************************/
22#include <linux/clk.h>
23#include <linux/err.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26#include <linux/slab.h>
27#include <linux/delay.h>
28#include <linux/pm_runtime.h>
29#include <mach/irqs.h>
30#include <mach/iomap.h>
31#include <asm/mach/map.h>
32#include <mach/rpmsg.h>
33#include <linux/kthread.h>
34
35
36/*******************************************************************************
37* Macro *
38*******************************************************************************/
39
40
41/*******************************************************************************
42* Global Variable *
43*******************************************************************************/
44
45static Icp_rpmsg_drv icp_arm0_info = {
46 .name = "icp_arm0",
47 .Channel_config =
48 {
49 .ChConfig = {CH_IRAM, CH_IRAM, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,CH_DDR,\
50 CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
51 CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
52 CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
53 CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR, CH_DDR,CH_DDR,\
54 CH_DDR},
55 },
56};
57
58static Icp_rpmsg_drv icp_m0_info = {
59 .name = "icp_m0",
60 .Channel_config =
61 {
62 .ChConfig = {CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
63 CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,\
64 CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
65 CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,\
66 CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM,CH_IRAM,
67 CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM, CH_IRAM},
68 },
69};
70
71Icp_rpmsg_drv *IcpRpMsgInfo[] = { &icp_m0_info, &icp_arm0_info, NULL };
72
73T_HalRpMsg_RWP ap2cp_chinfo[ACTOR_MAXID][CHANNEL_MAXID];
74T_HalRpMsg_RWP cp2ap_chinfo[ACTOR_MAXID][CHANNEL_MAXID];
75
76/*******************************************************************************
77* Function: zx29_Icp_SetInt
78* Description: This function is used for generating icp interrupt to inform remote cpu;
79* Parameters:
80* Input:
81 actorID: id of remote cpu
82 chID: id of channel
83* Output:None
84*
85* Returns:None
86*
87*
88* Others:
89********************************************************************************/
90int icp_set_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
91{
92 T_HalRpMsg_ChInfo *channel_send = IcpRpMsgInfo[actorID]->ChInfo_Send_Base + chID;
93
94 if(!(channel_send->flag & CHANNEL_FLAG))
95 return RPMSG_CHANNEL_INEXISTANCE;
96
97 if(chID<32)
98 {
99 iowrite32((1<<chID), &(IcpRpMsgInfo[actorID]->IcpReg->control.low_word)) ;
100 }
101 else
102 {
103 iowrite32((1<<(chID - 32)),&(IcpRpMsgInfo[actorID]->IcpReg->control.high_word));
104 }
105 return RPMSG_SUCCESS;
106}
107
108/*******************************************************************************
109* Function: zx29_Icp_ClearInt
110* Description: This function is used for clear icp interrupt from remote cpu;
111* Parameters:
112* Input:
113 actorID: id of remote cpu
114 chID: id of channel
115* Output:None
116*
117* Returns:None
118*
119*
120* Others:
121********************************************************************************/
122 void icp_clear_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
123{
124 if(chID<32)
125 {
126 iowrite32((1<<chID), &(IcpRpMsgInfo[actorID]->IcpReg->clear.low_word));
127 }
128 else
129 {
130 iowrite32(1<<(chID - 32), &(IcpRpMsgInfo[actorID]->IcpReg->clear.high_word)) ;
131 }
132}
133
134/*******************************************************************************
135* Function: zx29_Icp_GetInt
136* Description: This function is used for get icp interrupt from remote cpu;
137* Parameters:
138* Input:
139* actorID: id of remote cpu
140* chID: id of channel
141* Output:None
142*
143* Returns:None
144*
145*
146* Others:
147********************************************************************************/
148 T_HalIcp_Dword icp_get_int(T_ZDrvRpMsg_ActorID actorID)
149{
150 void __iomem *tmp = NULL;
151 T_HalIcp_Dword IcpState = {0};
152 tmp = &(IcpRpMsgInfo[actorID]->IcpReg->state.high_word);
153 IcpState.high_word = ioread32(tmp);
154 tmp = &(IcpRpMsgInfo[actorID]->IcpReg->state.low_word);
155 IcpState.low_word = ioread32(tmp);
156
157 return IcpState;
158}
159
160/*******************************************************************************
161* Function: zx29_Icp_GetIntState
162* Description: This function is used for get the state of icp interruptting of remote cpu;
163* Parameters:
164* Input:
165 actorID: id of remote cpu
166 chID: id of channel
167* Output:None
168*
169* Returns:None
170*
171*
172* Others:
173********************************************************************************/
174int icp_get_intstate(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
175{
176 if(chID < 32)
177 {
178 if(ioread32(&(IcpRpMsgInfo[actorID]->IcpReg->in_state.low_word)) & (0x1 << chID))
179 return TRUE;
180 else
181 return FALSE;
182 }
183 else
184 {
185 if(ioread32(&(IcpRpMsgInfo[actorID]->IcpReg->in_state.high_word)) & (0x1 << (chID - 32)))
186 return TRUE;
187 else
188 return FALSE;
189 }
190}
191
192/*******************************************************************************
193* Function: zx29_Icp_Mask
194* Description: This function is used for Mask interrupt of channel;
195* Parameters:
196* Input:
197* Output:
198*
199* Returns: NONE
200*
201*
202* Others:
203********************************************************************************/
204void icp_mask_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
205{
206 if(chID < 32)
207 {
208 IcpRpMsgInfo[actorID]->IcpReg->mask.low_word |=(0x1<<chID);
209 }
210 else
211 {
212 IcpRpMsgInfo[actorID]->IcpReg->mask.high_word |= (0x1<<(chID-32));
213 }
214}
215
216/*******************************************************************************
217* Function: zx29_Icp_UnMask
218* Description: This function is used for unmask interrupt of channel;
219* Parameters:
220* Input:
221* Output:
222*
223* Returns:
224* NONE
225*
226*
227* Others:
228********************************************************************************/
229void icp_unmask_int(T_ZDrvRpMsg_ActorID actorID, T_ZDrvRpMsg_ChID chID)
230{
231 if(chID < 32)
232 {
233 IcpRpMsgInfo[actorID]->IcpReg->mask.low_word &= ~(0x1<<chID);
234 }
235 else
236 {
237 IcpRpMsgInfo[actorID]->IcpReg->mask.high_word &= ~(0x1<<(chID-32));
238 }
239
240}
241
242static icp_operations icp_ops = {
243 .Icp_SetInt = icp_set_int,
244 .Icp_ClearInt = icp_clear_int,
245 .Icp_GetInt = icp_get_int,
246 .Icp_GetIntState = icp_get_intstate,
247 .Icp_Mask = icp_mask_int,
248 .Icp_UnMask = icp_unmask_int,
249};
250
251
252
253
254static int __devinit icp_probe(struct platform_device *pdev)
255{
256 struct resource *icp_mem;
257 struct resource *icp_iram_send;
258 struct resource *icp_iram_recv;
259 struct resource *icp_ddr_send;
260 struct resource *icp_ddr_recv;
261
262 int ret;
263 Icp_rpmsg_drv *list;
264 unsigned int i;
265
266 list = IcpRpMsgInfo[pdev->id];
267 list->actorID = pdev->id;
268
269 list->intline = platform_get_irq(pdev, 0 );
270
271 icp_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp");
272 icp_iram_send = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_iram_send");
273 icp_iram_recv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_iram_recv");
274 icp_ddr_send = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_ddr_send");
275 icp_ddr_recv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icp_ddr_recv");
276
277 if (!icp_mem || !icp_iram_send || !icp_iram_recv)
278 return -ENOMEM;
279
280 list->IcpReg = (T_HalIcp_Reg *)ioremap(icp_mem->start, resource_size(icp_mem));
281 list->ChInfo_Send_Base = (T_HalRpMsg_ChInfo *)ioremap(icp_iram_send->start, resource_size(icp_iram_send));
282 list->ChInfo_Recv_Base = (T_HalRpMsg_ChInfo *)ioremap(icp_iram_recv->start, resource_size(icp_iram_recv));
283 list->ChInfo_SendBase_offset= (unsigned int)(list->ChInfo_Send_Base) - (unsigned int)(icp_iram_send->start);
284 list->ChInfo_RecvBase_offset= (unsigned int)(list->ChInfo_Recv_Base) - (unsigned int)(icp_iram_recv->start);
285
286 memset(list->ChInfo_Send_Base, 0, (CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo)));
287
288 list->Ddr_SendBase = (unsigned int)(icp_ddr_send->start);
289 list->Ddr_RecvBase = (unsigned int)(icp_ddr_recv->start);
290 list->Ddr_SendBase_offset = (unsigned int)ioremap(icp_ddr_send->start, resource_size(icp_ddr_send)) - list->Ddr_SendBase;
291 list->Ddr_RecvBase_offset = (unsigned int)ioremap(icp_ddr_recv->start, resource_size(icp_ddr_recv)) - list->Ddr_RecvBase;
292
293 list->IcpReg->mask.high_word=0xffffffff;
294 list->IcpReg->mask.low_word=0xffffffff;
295
296 list->Channel_config.CurIramAddr = (unsigned int)(icp_iram_send->start + CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo));
297 list->Channel_config.CurIramSpace_Size = icp_iram_send->end - icp_iram_send->start - CHANNEL_MAXID * sizeof(T_HalRpMsg_ChInfo);
298 list->Channel_config.CurDdrAddr = (unsigned int)(icp_ddr_send->start);
299 list->Channel_config.CurDdrSpace_Size = icp_ddr_send->end - icp_ddr_send->start;
300
301 if (!list->IcpReg && !list->Channel_config.CurIramAddr && !list->Channel_config.CurDdrAddr)
302 return -ENODEV;
303
304 list->ops = &icp_ops;
305
306 for(i = 0; i<CHANNEL_MAXID; i++)
307 {
308 ap2cp_chinfo[pdev->id][i].writep = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->SendPos);
309 ap2cp_chinfo[pdev->id][i].readp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->RecvPos);
310 ap2cp_chinfo[pdev->id][i].endp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->EndAddr);
311 cp2ap_chinfo[pdev->id][i].writep = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->SendPos);
312 cp2ap_chinfo[pdev->id][i].readp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Send_Base + i))->RecvPos);
313 cp2ap_chinfo[pdev->id][i].endp = &(((T_HalRpMsg_ChInfo *)(list->ChInfo_Recv_Base + i))->EndAddr);
314 }
315
316 ret = icp_rpmsg_register(list);
317
318 if (ret)
319 goto unmap_base;
320
321 printk("rpmsg: icp_probe actorID = %d, success!\n", list->actorID);
322
323 return 0;
324
325unmap_base:
326 iounmap(list->IcpReg);
327 iounmap(list->ChInfo_Send_Base);
328 iounmap(list->ChInfo_Recv_Base);
329 //iounmap((unsigned int *)(list->Ddr_SendBase_map));
330 //iounmap((unsigned int *)(list->Ddr_RecvBase_map));
331
332
333
334 return ret;
335}
336
337static int __devexit icp_remove(struct platform_device *pdev)
338{
339 int ret = 0;
340 ret = icp_rpmsg_unregister(IcpRpMsgInfo[pdev->id]);
341 return ret;
342}
343
344static struct platform_driver icp_driver = {
345 .probe = icp_probe,
346 .remove = __devexit_p(icp_remove),
347 .driver = {
348 .name = "icp",
349 },
350};
351
352static int __init icp_init(void)
353{
354 return platform_driver_register(&icp_driver);
355}
356
357subsys_initcall(icp_init);
358
359static void __exit icp_exit(void)
360{
361 platform_driver_unregister(&icp_driver);
362}
363
364module_exit(icp_exit);
365
366