summaryrefslogtreecommitdiff
path: root/include/linux/sipc.h
blob: 5c7c3c3c349d3b5b0de6e094dcdb97f6f8cddba5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
/*
 * Copyright (C) 2012 Spreadtrum Communications Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.
 */

#ifndef __SIPC_H
#define __SIPC_H

#include <linux/poll.h>

/* ****************************************************************** */
/* SMSG interfaces */

/* sipc processor ID definition */
enum {
	SIPC_ID_AP = 0,		/* Application Processor */
	SIPC_ID_CPT,		/* TD processor */
	SIPC_ID_CPW,		/* WCDMA processor */
	SIPC_ID_WCN,		/* Wireless Connectivity */
	SIPC_ID_GGE, 		/* Gsm Gprs Edge processor */
	SIPC_ID_LTE, 		/* LTE processor */
	SIPC_ID_PM_SYS,		/* Power management processor */
	SIPC_ID_NR,		/* total processor number */
};

/* share-mem ring buffer short message */
struct smsg {
	uint8_t			channel;	/* channel index */
	uint8_t			type;		/* msg type */
	uint16_t		flag;		/* msg flag */
	uint32_t		value;		/* msg value */
};

/* smsg channel definition */
enum {
	SMSG_CH_CTRL = 0,	/* some emergency control */
	SMSG_CH_COMM,		/* general communication channel */
	SMSG_CH_RPC_AP,		/* RPC server channel in AP side */
	SMSG_CH_RPC_CP,		/* RPC server channel in CP side */
	SMSG_CH_PIPE,		/* general pipe channel */
	SMSG_CH_PLOG,		/* pipe for debug log/dump */
	SMSG_CH_TTY,		/* virtual serial for telephony */
	SMSG_CH_DATA0,		/* 2G/3G wirleless data */
	SMSG_CH_DATA1,		/* 2G/3G wirleless data */
	SMSG_CH_DATA2,		/* 2G/3G wirleless data */
	SMSG_CH_VBC,		/* audio conrol channel */
	SMSG_CH_PLAYBACK, 	/* audio playback channel */
	SMSG_CH_CAPTURE,	/* audio capture channel */
	SMSG_CH_MONITOR_AUDIO,	/* audio monitor channel */
	SMSG_CH_CTRL_VOIP,	/* audio voip conrol channel */
	SMSG_CH_PLAYBACK_VOIP, 	/* audio voip playback channel */
	SMSG_CH_CAPTURE_VOIP,	/* audio voip capture channel */
	SMSG_CH_MONITOR_VOIP,	/* audio voip monitor channel */
	SMSG_CH_DATA3,		/* 2G/3G wirleless data */
	SMSG_CH_DATA4,		/* 2G/3G wirleless data */
	SMSG_CH_DATA5,		/* 2G/3G wirleless data */
	SMSG_CH_DIAG,		/* pipe for debug log/dump */
	SMSG_CH_PM_CTRL, 	/* power management control */
	SMSG_CH_DUAL_SIM_PLUG,	/* dual sim plug channel */
	SMSG_CH_NR,		/* total channel number */
};

/* smsg type definition */
enum {
	SMSG_TYPE_NONE = 0,
	SMSG_TYPE_OPEN,		/* first msg to open a channel */
	SMSG_TYPE_CLOSE,	/* last msg to close a channel */
	SMSG_TYPE_DATA,		/* data, value=addr, no ack */
	SMSG_TYPE_EVENT,	/* event with value, no ack */
	SMSG_TYPE_CMD,		/* command, value=cmd */
	SMSG_TYPE_DONE,		/* return of command */
	SMSG_TYPE_SMEM_ALLOC,	/* allocate smem, flag=order */
	SMSG_TYPE_SMEM_FREE,	/* free smem, flag=order, value=addr */
	SMSG_TYPE_SMEM_DONE,	/* return of alloc/free smem */
	SMSG_TYPE_FUNC_CALL,	/* RPC func, value=addr */
	SMSG_TYPE_FUNC_RETURN,	/* return of RPC func */
	SMSG_TYPE_DIE,
	SMSG_TYPE_DFS,
	SMSG_TYPE_DFS_RSP,
	SMSG_TYPE_ASS_TRG,
	SMSG_TYPE_NR,		/* total type number */
};

/* flag for OPEN/CLOSE msg type */
#define	SMSG_OPEN_MAGIC		0xBEEE
#define	SMSG_CLOSE_MAGIC	0xEDDD

/**
 * smsg_ch_open -- open a channel for smsg
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int smsg_ch_open(uint8_t dst, uint8_t channel, int timeout);

/**
 * smsg_ch_close -- close a channel for smsg
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int smsg_ch_close(uint8_t dst, uint8_t channel, int timeout);

/**
 * smsg_send -- send smsg
 *
 * @dst: dest processor ID
 * @msg: smsg body to be sent
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int smsg_send(uint8_t dst, struct smsg *msg, int timeout);

/**
 * smsg_recv -- poll and recv smsg
 *
 * @dst: dest processor ID
 * @msg: smsg body to be received, channel should be filled as input
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int smsg_recv(uint8_t dst, struct smsg *msg, int timeout);

/* quickly fill a smsg body */
static inline void smsg_set(struct smsg *msg, uint8_t channel,
		uint8_t type, uint16_t flag, uint32_t value)
{
	msg->channel = channel;
	msg->type = type;
	msg->flag = flag;
	msg->value = value;
}

/* ack an open msg for modem recovery */
static inline void smsg_open_ack(uint8_t dst, uint16_t channel)
{
	struct smsg mopen;
	smsg_set(&mopen, channel, SMSG_TYPE_OPEN, SMSG_OPEN_MAGIC, 0);
	smsg_send(dst, &mopen, -1);
}

/* ack an close msg for modem recovery */
static inline void smsg_close_ack(uint8_t dst, uint16_t channel)
{
	struct smsg mclose;
	smsg_set(&mclose, channel, SMSG_TYPE_CLOSE, SMSG_CLOSE_MAGIC, 0);
	smsg_send(dst, &mclose, -1);
}
/* ****************************************************************** */
/* SMEM interfaces */

/**
 * smem_alloc -- allocate shared memory block
 *
 * @size: size to be allocated, page-aligned
 * @return: phys addr or 0 if failed
 */
uint32_t smem_alloc(uint32_t size);

/**
 * smem_free -- free shared memory block
 *
 * @addr: smem phys addr to be freed
 * @order: size to be freed
 */
void smem_free(uint32_t addr, uint32_t size);

/* ****************************************************************** */
/* SBUF Interfaces */

/**
 * sbuf_create -- create pipe ring buffers on a channel
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @txbufsize: tx buffer size
 * @rxbufsize: rx buffer size
 * @bufnum: how many buffers to be created
 * @return: 0 on success, <0 on failue
 */
int sbuf_create(uint8_t dst, uint8_t channel, uint32_t bufnum,
		uint32_t txbufsize, uint32_t rxbufsize);

/**
 * sbuf_destroy -- destroy the pipe ring buffers on a channel
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: 0 on success, <0 on failue
 */
void sbuf_destroy(uint8_t dst, uint8_t channel);

/**
 * sbuf_write -- write data to a sbuf
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @bufid: buffer ID
 * @buf: data to be written
 * @len: data length
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: written bytes on success, <0 on failue
 */
int sbuf_write(uint8_t dst, uint8_t channel, uint32_t bufid,
		void *buf, uint32_t len, int timeout);

/**
 * sbuf_read -- write data to a sbuf
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @bufid: buffer ID
 * @buf: data to be written
 * @len: data length
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: read bytes on success, <0 on failue
 */
int sbuf_read(uint8_t dst, uint8_t channel, uint32_t bufid,
		void *buf, uint32_t len, int timeout);

/**
 * sbuf_poll_wait -- poll sbuf read/write, used in spipe driver
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @bufid: buffer ID
 * @file: struct file handler
 * @wait: poll table
 * @return: POLLIN or POLLOUT
 */
int sbuf_poll_wait(uint8_t dst, uint8_t channel, uint32_t bufid,
		struct file *file, poll_table *wait);

/**
 * sbuf_status -- get sbuf status
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: 0 when ready, <0 when broken
 */
int sbuf_status(uint8_t dst, uint8_t channel);

#define	SBUF_NOTIFY_READ	0x01
#define	SBUF_NOTIFY_WRITE	0x02
/**
 * sbuf_register_notifier -- register a callback that's called
 * 		when a tx sbuf is available or a rx sbuf is received.
 * 		non-blocked sbuf_read can be called.
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @bufid: buf ID
 * @handler: a callback handler
 * @event: NOTIFY_READ, NOTIFY_WRITE, or both
 * @data: opaque data passed to the receiver
 * @return: 0 on success, <0 on failue
 */
int sbuf_register_notifier(uint8_t dst, uint8_t channel, uint32_t bufid,
		void (*handler)(int event, void *data), void *data);

/* ****************************************************************** */
/* SBLOCK interfaces */

/* sblock structure: addr is the uncached virtual address */
struct sblock {
	void		*addr;
	uint32_t	length;
};

/**
 * sblock_create -- create sblock manager on a channel
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @txblocknum: tx block number
 * @txblocksize: tx block size
 * @rxblocknum: rx block number
 * @rxblocksize: rx block size
 * @return: 0 on success, <0 on failue
 */
int sblock_create(uint8_t dst, uint8_t channel,
		uint32_t txblocknum, uint32_t txblocksize,
		uint32_t rxblocknum, uint32_t rxblocksize);

/**
 * sblock_destroy -- destroy sblock manager on a channel
 *
 * @dst: dest processor ID
 * @channel: channel ID
 */
void sblock_destroy(uint8_t dst, uint8_t channel);

#define	SBLOCK_NOTIFY_GET	0x01
#define	SBLOCK_NOTIFY_RECV	0x02
#define	SBLOCK_NOTIFY_STATUS	0x04
#define	SBLOCK_NOTIFY_OPEN	0x08
#define	SBLOCK_NOTIFY_CLOSE	0x10
/**
 * sblock_register_notifier -- register a callback that's called
 * 		when a tx sblock is available or a rx block is received.
 * 		non-blocked sblock_get or sblock_receive can be called.
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @handler: a callback handler
 * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both
 * @data: opaque data passed to the receiver
 * @return: 0 on success, <0 on failue
 */
int sblock_register_notifier(uint8_t dst, uint8_t channel,
		void (*handler)(int event, void *data), void *data);

/**
 * sblock_get  -- get a free sblock for sender
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @blk: return a gotten sblock pointer
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int sblock_get(uint8_t dst, uint8_t channel, struct sblock *blk, int timeout);

/**
 * sblock_send  -- send a sblock with smsg, it should be from sblock_get
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @blk: the sblock to be sent
 * @return: 0 on success, <0 on failue
 */
int sblock_send(uint8_t dst, uint8_t channel, struct sblock *blk);

/**
 * sblock_send_prepare  -- send a sblock without smsg, it should be from sblock_get
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @blk: the sblock to be sent
 * @return: 0 on success, <0 on failue
 */
int sblock_send_prepare(uint8_t dst, uint8_t channel, struct sblock *blk);

/**
 * sblock_send_finish  -- trigger an smsg to notify that sblock has been sent
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: 0 on success, <0 on failue
 */
int sblock_send_finish(uint8_t dst, uint8_t channel);

/**
 * sblock_receive  -- receive a sblock, it should be released after it's handled
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @blk: return a received sblock pointer
 * @timeout: milliseconds, 0 means no wait, -1 means unlimited
 * @return: 0 on success, <0 on failue
 */
int sblock_receive(uint8_t dst, uint8_t channel, struct sblock *blk, int timeout);

/**
 * sblock_release  -- release a sblock from reveiver
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: 0 on success, <0 on failue
 */
int sblock_release(uint8_t dst, uint8_t channel, struct sblock *blk);

/**
 * sblock_get_arrived_count  -- get the count of sblock(s) arrived at AP (sblock_send on CP)
 *                              but not received (sblock_receive on AP).
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: >=0  the count of blocks
 */
int sblock_get_arrived_count(uint8_t dst, uint8_t channel);



/**
 * sblock_get_free_count  -- get the count of available sblock(s) resident in sblock pool on AP.
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @return: >=0  the count of blocks
 */
int sblock_get_free_count(uint8_t dst, uint8_t channel);


/**
 * sblock_put  -- put a free sblock for sender
 *
 * @dst: dest processor ID
 * @channel: channel ID
 * @blk: sblock pointer
 * @return: void
 */
void sblock_put(uint8_t dst, uint8_t channel, struct sblock *blk);

/* ****************************************************************** */
/* TODO: SRPC interfaces */

enum {
	SPRC_ID_NONE = 0,
	SPRC_ID_XXX,
	SPRC_ID_NR,
};

struct srpc_server {
	uint32_t		id;
	/* TODO */
};

struct srpc_client {
	uint32_t		id;
	/* TODO */
};

int srpc_init(uint8_t dst);
int srpc_server_register(uint8_t dst, struct srpc_server *server);
int srpc_client_call(uint8_t dst, struct srpc_client *client);
int sctrl_send_sync(uint32_t type, uint32_t target_id, uint32_t value);
#ifdef CONFIG_64BIT
static inline unsigned long unalign_copy_to_user(void __user *to, const void *from, unsigned long n)
{
	unsigned long rval = 0;

	while (((unsigned long)from & 7) && n) {
		rval |= copy_to_user(to++, from++, 1);
		n--;
	}
	rval = copy_to_user(to, from, n);

	return rval;
}
static inline unsigned long unalign_copy_from_user(void *to, const void __user *from, unsigned long n)
{
	unsigned long rval = 0;

	while (((unsigned long)to & 7) && n) {
		rval |= copy_from_user(to++, from++, 1);
		n--;
	}
	rval = copy_from_user(to, from, n);

	return rval;
}
static inline void *unalign_memcpy(void *to, const void *from, size_t n)
{
	if (((unsigned long)to & 7) == ((unsigned long)from & 7)) {
		while (((unsigned long)from & 7) && n) {
			*(char *)(to++) = *(char*)(from++);
			n--;
		}
		memcpy(to, from, n);
	} else {
		while (n) {
			*(char *)(to++) = *(char*)(from++);
			n--;
		}
	}
}
#else
static inline unsigned long unalign_copy_to_user(void __user *to, const void *from, unsigned long n)
{
	return copy_to_user(to, from, n);
}
static inline unsigned long unalign_copy_from_user(void *to, const void __user *from, unsigned long n)
{
	return copy_from_user(to, from, n);
}
static inline void *unalign_memcpy(void *to, const void *from, size_t n)
{
	return memcpy(to, from, n);
}
#endif


#endif