aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/modem_if_u1/modem_link_device_spi.h
blob: 3e2456e1a15838aa3892f010f6075cfef07e0504 (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
/*
 * Copyright (C) 2011 Google, Inc.
 * Copyright (C) 2010 Samsung Electronics.
 *
 * 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 __MODEM_LINK_DEVICE_SPI_H__
#define __MODEM_LINK_DEVICE_SPI_H__

#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/platform_data/modem.h>


#define SPI_TIMER_TX_WAIT_TIME 60 /* ms */
#define SPI_TIMER_RX_WAIT_TIME 500 /* ms */

#define SPI_MAX_PACKET_SIZE (2048 * 6)
#define SPI_TASK_EVENT_COUNT	64
#define SPI_DATA_BOF			0x7F
#define SPI_DATA_EOF			0x7E
#define SPI_DATA_FF_PADDING_HEADER 0xFFFFFFFF

#define SPI_DATA_MUX_NORMAL_MASK	0x0F
#define SPI_DATA_MUX_MORE_H			0x10
#define SPI_DATA_MUX_MORE_M			0x20
#define SPI_DATA_MUX_MORE_T			0x30

#define SPI_DATA_MUX_SIZE		2
#define SPI_DATA_LENGTH_SIZE	4
#define SPI_DATA_BOF_SIZE		1
#define SPI_DATA_INNER_LENGTH_SIZE	4
#define SPI_DATA_IPC_INNER_LENGTH_SIZE	2
#define SPI_DATA_IPC_INNER_CONTROL_SIZE	1
#define SPI_DATA_EOF_SIZE		1
#define SPI_DATA_HEADER_SIZE	(SPI_DATA_MUX_SIZE+ \
		SPI_DATA_LENGTH_SIZE+SPI_DATA_BOF_SIZE+SPI_DATA_EOF_SIZE)
#define SPI_DATA_HEADER_SIZE_FRONT	(SPI_DATA_MUX_SIZE+ \
		SPI_DATA_LENGTH_SIZE+SPI_DATA_BOF_SIZE)
#define SPI_DATA_IPC_INNER_HEADER_SIZE	\
		(SPI_DATA_IPC_INNER_LENGTH_SIZE+ \
		SPI_DATA_IPC_INNER_CONTROL_SIZE)
#define SPI_DATA_SIZE(X)				(SPI_DATA_HEADER_SIZE+X)

#define SPI_DATA_LENGTH_OFFSET	SPI_DATA_MUX_SIZE
#define SPI_DATA_BOF_OFFSET		(SPI_DATA_LENGTH_OFFSET+ \
		SPI_DATA_LENGTH_SIZE)
#define SPI_DATA_DATA_OFFSET		(SPI_DATA_BOF_OFFSET+ \
		SPI_DATA_BOF_SIZE)
#define SPI_DATA_EOF_OFFSET(X)		(SPI_DATA_DATA_OFFSET+X)

#define SPI_DATA_PACKET_HEADER_SIZE	                 4
#define SPI_DATA_PACKET_MUX_ERROR_SPARE_SIZE		 4
#define SPI_DATA_PACKET_MAX_PACKET_BODY_SIZE \
		(SPI_MAX_PACKET_SIZE-SPI_DATA_PACKET_HEADER_SIZE- \
		SPI_DATA_PACKET_MUX_ERROR_SPARE_SIZE)

#define SPI_DATA_MIN_SIZE		(SPI_DATA_HEADER_SIZE*2)
#define SPI_DATA_MAX_SIZE_PER_PACKET (SPI_MAX_PACKET_SIZE- \
		SPI_DATA_PACKET_HEADER_SIZE-SPI_DATA_HEADER_SIZE- \
		SPI_DATA_PACKET_MUX_ERROR_SPARE_SIZE)

#define SPI_DATA_DIVIDE_BUFFER_SIZE SPI_MAX_PACKET_SIZE

struct spi_work_type {
	struct work_struct work;
	int signal_code;
};

enum spi_msg_t {
	SPI_WORK_SEND,
	SPI_WORK_RECEIVE
};

enum spi_work_t {
	SPI_WORK,
	SPI_WORK_FRONT
};

enum spi_state_t {
	SPI_STATE_START,		/* before init complete */
	SPI_STATE_INIT,		/* initialising */
	SPI_STATE_IDLE,		/* suspend. Waiting for event */
	/* state to start tx. Become from idle */
	SPI_STATE_TX_START,
	SPI_STATE_TX_CONFIRM,
	/* (in case of master) */
	/* wait srdy rising interrupt to check slave preparing */
	/* (in case of slave) */
	/* wait submrdy rising interrupt to check sync complete */
	SPI_STATE_TX_WAIT,
	SPI_STATE_TX_SENDING,	/* tx data sending  */
	SPI_STATE_TX_TERMINATE,
	SPI_STATE_TX_MORE,

	/* in case of slave, wait submrdy rising interrupt to */
	SPI_STATE_RX_WAIT,

	/* check sync complete then it starts to read buffer */
	SPI_STATE_RX_MORE,
	SPI_STATE_RX_TERMINATE,
	SPI_STATE_END			/* spi task is stopped */
};

enum spi_timer_state_t {
	SPI_STATE_TIME_START,
	SPI_STATE_TIME_OVER
};

enum spi_gpiolevel_t {
	SPI_GPIOLEVEL_LOW	= 0,
	SPI_GPIOLEVEL_HIGH
};

enum spi_data_type_t {
	SPI_DATA_MUX_IPC			= 0x01,
	SPI_DATA_MUX_RAW			= 0x02,
	SPI_DATA_MUX_RFS			= 0x03,
	SPI_DATA_MUX_CMD			= 0x04,
};

struct spi_data_packet_header {
	/* 12bit : packet size less than SPI_DEV_PACKET_SIZE */
	unsigned long current_data_size:31;
	/* 1bit : packet division flag */
	unsigned long more:1;
};

struct link_pm_data {
	struct miscdevice miscdev;
	struct spi_link_device *spild;

	struct notifier_block pm_notifier;
};

struct spi_link_device {
	struct link_device ld;

	/* Link to SPI control functions dependent on each platform */
	int max_ipc_dev;

	/* Wakelock for SPI device */
	struct wake_lock spi_wake_lock;
	/* Workqueue for modem bin transfers */
	struct workqueue_struct *ipc_spi_wq;

	/* SPI state */
	int spi_state;

	/* SPI Timer state */
	int spi_timer_tx_state;
	int spi_timer_rx_state;

	/* SPI GPIO pins */
	unsigned int gpio_ipc_mrdy;
	unsigned int gpio_ipc_srdy;
	unsigned int gpio_ipc_sub_mrdy;
	unsigned int gpio_ipc_sub_srdy;

	unsigned int gpio_modem_bin_srdy;

	unsigned int gpio_ap_cp_int1;
	unsigned int gpio_ap_cp_int2;

	/* value for checking spi pin status */
	unsigned long mrdy_low_time_save;
	unsigned long mrdy_high_time_save;

	/* SPI Wait Timer */
	struct timer_list spi_tx_timer;
	struct timer_list spi_rx_timer;

	struct workqueue_struct *spi_wq;
	struct spi_work_type spi_work;

	/* For send modem bin */
	struct work_struct send_modem_w;

	struct io_device    *iod[MAX_DEV_FORMAT];
	struct sk_buff_head  skb_rxq[MAX_DEV_FORMAT];

	/* LINK PM DEVICE DATA */
	struct link_pm_data *link_pm_data;

	/* Multi-purpose miscellaneous buffer */
	u8 *buff;
	u8 *sync_buff;

	struct semaphore srdy_sem;

	int send_modem_spi;
	int is_cp_reset;
	int boot_done;
	int ril_send_modem_img;
	unsigned long ril_send_cnt;

	void __iomem *p_virtual_buff;
};

/* converts from struct link_device* to struct xxx_link_device* */
#define to_spi_link_device(linkdev) \
			container_of(linkdev, struct spi_link_device, ld)

struct spi_v_buff {
	unsigned long base;
	unsigned long size;
	void __iomem *mmio;
};

extern unsigned int lpcharge;
extern int get_console_suspended(void);
static void spi_work(struct work_struct *work);

/* Send SPRD main image through SPI */
#define SPRD_BLOCK_SIZE	32768

enum image_type {
	MODEM_MAIN,
	MODEM_DSP,
	MODEM_NV,
	MODEM_EFS,
	MODEM_RUN,
};

struct image_buf {
	unsigned int length;
	unsigned int offset;
	unsigned int address;
	unsigned char *buf;
};

struct sprd_image_buf {
	u8 *tx_b;
	u8 *rx_b;
	u8 *encoded_tx_b;
	u8 *decoded_rx_b;

	int tx_size;
	int rx_size;
	int encoded_tx_size;
	int decoded_rx_size;
};

/* CRC */
#define CRC_16_L_OK	0x0
#define HDLC_FLAG	0x7E
#define HDLC_ESCAPE	0x7D
#define HDLC_ESCAPE_MASK 0x20
#define CRC_CHECK_SIZE	0x02

#define M_32_SWAP(a) {					\
		u32 _tmp;				\
		_tmp = a;					\
		((u8 *)&a)[0] = ((u8 *)&_tmp)[3]; \
		((u8 *)&a)[1] = ((u8 *)&_tmp)[2]; \
		((u8 *)&a)[2] = ((u8 *)&_tmp)[1]; \
		((u8 *)&a)[3] = ((u8 *)&_tmp)[0]; \
		}

#define M_16_SWAP(a) {					\
		u16 _tmp;					\
		_tmp = (u16)a;			\
		((u8 *)&a)[0] = ((u8 *)&_tmp)[1];	\
		((u8 *)&a)[1] = ((u8 *)&_tmp)[0];	\
		}

#endif