summaryrefslogtreecommitdiff
path: root/drivers/slimbus/slim-msm.h
blob: 15c12ff580e480b23e282be9deb3f46bb353d907 (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
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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 _SLIM_MSM_H
#define _SLIM_MSM_H

#include <linux/irq.h>
#include <linux/kthread.h>
#include <soc/qcom/msm_qmi_interface.h>
#include <soc/qcom/subsystem_notif.h>
#include <linux/ipc_logging.h>

/* Per spec.max 40 bytes per received message */
#define SLIM_MSGQ_BUF_LEN	40

#define MSM_TX_BUFS		32

#define SLIM_USR_MC_GENERIC_ACK		0x25
#define SLIM_USR_MC_MASTER_CAPABILITY	0x0
#define SLIM_USR_MC_REPORT_SATELLITE	0x1
#define SLIM_USR_MC_ADDR_QUERY		0xD
#define SLIM_USR_MC_ADDR_REPLY		0xE
#define SLIM_USR_MC_DEFINE_CHAN		0x20
#define SLIM_USR_MC_DEF_ACT_CHAN	0x21
#define SLIM_USR_MC_CHAN_CTRL		0x23
#define SLIM_USR_MC_RECONFIG_NOW	0x24
#define SLIM_USR_MC_REQ_BW		0x28
#define SLIM_USR_MC_CONNECT_SRC		0x2C
#define SLIM_USR_MC_CONNECT_SINK	0x2D
#define SLIM_USR_MC_DISCONNECT_PORT	0x2E

#define SLIM_USR_MC_REPEAT_CHANGE_VALUE	0x0
#define MSM_SLIM_VE_MAX_MAP_ADDR	0xFFF
#define SLIM_MAX_VE_SLC_BYTES		16

#define MSM_SLIM_AUTOSUSPEND		MSEC_PER_SEC

#define SLIM_RX_MSGQ_TIMEOUT_VAL	0x10000
/*
 * Messages that can be received simultaneously:
 * Client reads, LPASS master responses, announcement messages
 * Receive upto 10 messages simultaneously.
 */
#define MSM_SLIM_DESC_NUM		32

/* MSM Slimbus peripheral settings */
#define MSM_SLIM_PERF_SUMM_THRESHOLD	0x8000
#define MSM_SLIM_NPORTS			24
#define MSM_SLIM_NCHANS			32

#define QC_MFGID_LSB	0x2
#define QC_MFGID_MSB	0x17
#define QC_CHIPID_SL	0x10
#define QC_DEVID_SAT1	0x3
#define QC_DEVID_SAT2	0x4
#define QC_DEVID_PGD	0x5

#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))

#define INIT_MX_RETRIES 10
#define DEF_RETRY_MS	10
#define MSM_CONCUR_MSG	8
#define SAT_CONCUR_MSG	8

#define DEF_WATERMARK	(8 << 1)
#define DEF_ALIGN_LSB	0
#define DEF_ALIGN_MSB	(1 << 7)
#define DEF_PACK	(1 << 6)
#define DEF_NO_PACK	0
#define ENABLE_PORT	1

#define DEF_BLKSZ	0
#define DEF_TRANSZ	0

#define SAT_MAGIC_LSB	0xD9
#define SAT_MAGIC_MSB	0xC5
#define SAT_MSG_VER	0x1
#define SAT_MSG_PROT	0x1
#define MSM_SAT_SUCCSS	0x20
#define MSM_MAX_NSATS	2
#define MSM_MAX_SATCH	32

/* Slimbus QMI service */
#define SLIMBUS_QMI_SVC_ID 0x0301
#define SLIMBUS_QMI_SVC_V1 1
#define SLIMBUS_QMI_INS_ID 0

/* QMI response timeout of 500ms */
#define SLIM_QMI_RESP_TOUT 500

#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))

#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
#define CFG_PORT_V2(r) ((r ## _V2))
/* Component registers */
enum comp_reg_v2 {
	COMP_CFG_V2		= 4,
	COMP_TRUST_CFG_V2	= 0x3000,
};

/* Manager PGD registers */
enum pgd_reg_v2 {
	PGD_CFG_V2		= 0x800,
	PGD_STAT_V2		= 0x804,
	PGD_INT_EN_V2		= 0x810,
	PGD_INT_STAT_V2		= 0x814,
	PGD_INT_CLR_V2		= 0x818,
	PGD_OWN_EEn_V2		= 0x300C,
	PGD_PORT_INT_EN_EEn_V2	= 0x5000,
	PGD_PORT_INT_ST_EEn_V2	= 0x5004,
	PGD_PORT_INT_CL_EEn_V2	= 0x5008,
	PGD_PORT_CFGn_V2	= 0x14000,
	PGD_PORT_STATn_V2	= 0x14004,
	PGD_PORT_PARAMn_V2	= 0x14008,
	PGD_PORT_BLKn_V2	= 0x1400C,
	PGD_PORT_TRANn_V2	= 0x14010,
	PGD_PORT_MCHANn_V2	= 0x14014,
	PGD_PORT_PSHPLLn_V2	= 0x14018,
	PGD_PORT_PC_CFGn_V2	= 0x8000,
	PGD_PORT_PC_VALn_V2	= 0x8004,
	PGD_PORT_PC_VFR_TSn_V2	= 0x8008,
	PGD_PORT_PC_VFR_STn_V2	= 0x800C,
	PGD_PORT_PC_VFR_CLn_V2	= 0x8010,
	PGD_IE_STAT_V2		= 0x820,
	PGD_VE_STAT_V2		= 0x830,
};

#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
#define CFG_PORT_V1(r) ((r ## _V1))
/* Component registers */
enum comp_reg_v1 {
	COMP_CFG_V1		= 0,
	COMP_TRUST_CFG_V1	= 0x14,
};

/* Manager PGD registers */
enum pgd_reg_v1 {
	PGD_CFG_V1		= 0x1000,
	PGD_STAT_V1		= 0x1004,
	PGD_INT_EN_V1		= 0x1010,
	PGD_INT_STAT_V1		= 0x1014,
	PGD_INT_CLR_V1		= 0x1018,
	PGD_OWN_EEn_V1		= 0x1020,
	PGD_PORT_INT_EN_EEn_V1	= 0x1030,
	PGD_PORT_INT_ST_EEn_V1	= 0x1034,
	PGD_PORT_INT_CL_EEn_V1	= 0x1038,
	PGD_PORT_CFGn_V1	= 0x1080,
	PGD_PORT_STATn_V1	= 0x1084,
	PGD_PORT_PARAMn_V1	= 0x1088,
	PGD_PORT_BLKn_V1	= 0x108C,
	PGD_PORT_TRANn_V1	= 0x1090,
	PGD_PORT_MCHANn_V1	= 0x1094,
	PGD_PORT_PSHPLLn_V1	= 0x1098,
	PGD_PORT_PC_CFGn_V1	= 0x1600,
	PGD_PORT_PC_VALn_V1	= 0x1604,
	PGD_PORT_PC_VFR_TSn_V1	= 0x1608,
	PGD_PORT_PC_VFR_STn_V1	= 0x160C,
	PGD_PORT_PC_VFR_CLn_V1	= 0x1610,
	PGD_IE_STAT_V1		= 0x1700,
	PGD_VE_STAT_V1		= 0x1710,
};

enum msm_slim_port_status {
	MSM_PORT_OVERFLOW	= 1 << 2,
	MSM_PORT_UNDERFLOW	= 1 << 3,
	MSM_PORT_DISCONNECT	= 1 << 19,
};

enum msm_ctrl_state {
	MSM_CTRL_AWAKE,
	MSM_CTRL_IDLE,
	MSM_CTRL_ASLEEP,
	MSM_CTRL_DOWN,
};

enum msm_slim_msgq {
	MSM_MSGQ_DISABLED,
	MSM_MSGQ_RESET,
	MSM_MSGQ_ENABLED,
	MSM_MSGQ_DOWN,
};

struct msm_slim_sps_bam {
	unsigned long		hdl;
	void __iomem		*base;
	int			irq;
};

/*
 * struct slim_pshpull_parm: Structure to store push pull protocol parameters
 * @num_samples: Number of samples in a period
 * @rpt_period: Repeat period value
 */
struct msm_slim_pshpull_parm {
	int		num_samples;
	int		rpt_period;
};

struct msm_slim_endp {
	struct sps_pipe			*sps;
	struct sps_connect		config;
	struct sps_register_event	event;
	struct sps_mem_buffer		buf;
	bool				connected;
	int				port_b;
	struct msm_slim_pshpull_parm	psh_pull;
};

struct msm_slim_qmi {
	struct qmi_handle		*handle;
	struct task_struct		*task;
	struct task_struct		*slave_thread;
	struct completion		slave_notify;
	struct kthread_work		kwork;
	struct kthread_worker		kworker;
	struct completion		qmi_comp;
	struct notifier_block		nb;
	struct work_struct		ssr_down;
	struct work_struct		ssr_up;
};

struct msm_slim_ss {
	struct notifier_block nb;
	void *ssr;
	enum msm_ctrl_state state;
};

struct msm_slim_pdata {
	u32 apps_pipes;
	u32 eapc;
};

struct msm_slim_bulk_wr {
	dma_addr_t	wr_dma;
	void		*base;
	int		size;
	int		buf_sz;
	int		(*cb)(void *ctx, int err);
	void		*ctx;
	bool		in_progress;
};

struct msm_slim_ctrl {
	struct slim_controller  ctrl;
	struct slim_framer	framer;
	struct device		*dev;
	void __iomem		*base;
	struct resource		*slew_mem;
	struct resource		*bam_mem;
	u32			curr_bw;
	u8			msg_cnt;
	u32			tx_buf[10];
	u8			rx_msgs[MSM_CONCUR_MSG][SLIM_MSGQ_BUF_LEN];
	int			tx_tail;
	int			tx_head;
	spinlock_t		rx_lock;
	int			head;
	int			tail;
	int			irq;
	int			err;
	int			ee;
	struct completion	**wr_comp;
	struct msm_slim_sat	*satd[MSM_MAX_NSATS];
	struct msm_slim_endp	*pipes;
	struct msm_slim_sps_bam	bam;
	struct msm_slim_endp	tx_msgq;
	struct msm_slim_endp	rx_msgq;
	struct completion	rx_msgq_notify;
	struct task_struct	*rx_msgq_thread;
	struct clk		*rclk;
	struct clk		*hclk;
	struct mutex		tx_lock;
	spinlock_t		tx_buf_lock;
	u8			pgdla;
	enum msm_slim_msgq	use_rx_msgqs;
	enum msm_slim_msgq	use_tx_msgqs;
	int			port_nums;
	struct completion	reconf;
	bool			reconf_busy;
	bool			chan_active;
	enum msm_ctrl_state	state;
	struct completion	ctrl_up;
	int			nsats;
	u32			ver;
	struct msm_slim_qmi	qmi;
	struct msm_slim_pdata	pdata;
	struct msm_slim_ss	ext_mdm;
	struct msm_slim_ss	dsp;
	struct msm_slim_bulk_wr	bulk;
	int			default_ipc_log_mask;
	int			ipc_log_mask;
	bool			sysfs_created;
	void			*ipc_slimbus_log;
	void (*rx_slim)(struct msm_slim_ctrl *dev, u8 *buf);
	u32			current_rx_buf[10];
	int			current_count;
};

struct msm_sat_chan {
	u8 chan;
	u16 chanh;
	int req_rem;
	int req_def;
	bool reconf;
};

struct msm_slim_sat {
	struct slim_device	satcl;
	struct msm_slim_ctrl	*dev;
	struct workqueue_struct *wq;
	struct work_struct	wd;
	u8			sat_msgs[SAT_CONCUR_MSG][40];
	struct msm_sat_chan	*satch;
	u8			nsatch;
	bool			sent_capability;
	bool			pending_reconf;
	bool			pending_capability;
	int			shead;
	int			stail;
	spinlock_t lock;
};

enum rsc_grp {
	EE_MGR_RSC_GRP	= 1 << 10,
	EE_NGD_2	= 2 << 6,
	EE_NGD_1	= 0,
};


/* IPC logging stuff */
#define IPC_SLIMBUS_LOG_PAGES 5

/* Log levels */
enum {
	FATAL_LEV = 0U,
	ERR_LEV = 1U,
	WARN_LEV = 2U,
	INFO_LEV = 3U,
	DBG_LEV = 4U,
};

/* Default IPC log level INFO */
#define SLIM_DBG(dev, x...) do { \
	pr_debug(x); \
	if (dev->ipc_slimbus_log && dev->ipc_log_mask >= DBG_LEV) { \
		ipc_log_string(dev->ipc_slimbus_log, x); \
	} \
} while (0)

#define SLIM_INFO(dev, x...) do { \
	pr_debug(x); \
	if (dev->ipc_slimbus_log && dev->ipc_log_mask >= INFO_LEV) {\
		ipc_log_string(dev->ipc_slimbus_log, x); \
	} \
} while (0)

/* warnings and errors show up on console always */
#define SLIM_WARN(dev, x...) do { \
	pr_warn(x); \
	if (dev->ipc_slimbus_log && dev->ipc_log_mask >= WARN_LEV) \
		ipc_log_string(dev->ipc_slimbus_log, x); \
} while (0)

/* ERROR condition in the driver sets the hs_serial_debug_mask
 * to ERR_FATAL level, so that this message can be seen
 * in IPC logging. Further errors continue to log on the console
 */
#define SLIM_ERR(dev, x...) do { \
	pr_err(x); \
	if (dev->ipc_slimbus_log && dev->ipc_log_mask >= ERR_LEV) { \
		ipc_log_string(dev->ipc_slimbus_log, x); \
		dev->default_ipc_log_mask = dev->ipc_log_mask; \
		dev->ipc_log_mask = FATAL_LEV; \
	} \
} while (0)

#define SLIM_RST_LOGLVL(dev) { \
	dev->ipc_log_mask = dev->default_ipc_log_mask; \
}

int msm_slim_rx_enqueue(struct msm_slim_ctrl *dev, u32 *buf, u8 len);
int msm_slim_rx_dequeue(struct msm_slim_ctrl *dev, u8 *buf);
int msm_slim_get_ctrl(struct msm_slim_ctrl *dev);
void msm_slim_put_ctrl(struct msm_slim_ctrl *dev);
irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat);
int msm_slim_init_endpoint(struct msm_slim_ctrl *dev, struct msm_slim_endp *ep);
void msm_slim_free_endpoint(struct msm_slim_endp *ep);
void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pipenum, u8 portnum);
int msm_alloc_port(struct slim_controller *ctrl, u8 pn);
void msm_dealloc_port(struct slim_controller *ctrl, u8 pn);
int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn);
enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
				u8 pn, phys_addr_t *done_buf, u32 *done_len);
int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf,
			u32 len, struct completion *comp);
int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
			struct completion *comp);
u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf,
			struct completion *comp, int err);
int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset);
int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
			u32 pipe_reg, bool remote);
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg);

int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint);
void msm_slim_disconnect_endp(struct msm_slim_ctrl *dev,
					struct msm_slim_endp *endpoint,
					enum msm_slim_msgq *msgq_flag);
void msm_slim_deinit_ep(struct msm_slim_ctrl *dev,
				struct msm_slim_endp *endpoint,
				enum msm_slim_msgq *msgq_flag);

void msm_slim_qmi_exit(struct msm_slim_ctrl *dev);
int msm_slim_qmi_init(struct msm_slim_ctrl *dev, bool apps_is_master);
int msm_slim_qmi_power_request(struct msm_slim_ctrl *dev, bool active);
int msm_slim_qmi_check_framer_request(struct msm_slim_ctrl *dev);
#endif