Blame view

drivers/usb/renesas_usbhs/pipe.c 17.2 KB
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Renesas USB driver
   *
   * Copyright (C) 2011 Renesas Solutions Corp.
   * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   *
   * 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.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   */
  #include <linux/delay.h>
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
18
  #include <linux/slab.h>
cc502bb74   Paul Bolle   renesas_usbhs: cl...
19
20
  #include "common.h"
  #include "pipe.h"
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
21
22
23
24
  
  /*
   *		macros
   */
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
25
  #define usbhsp_addr_offset(p)	((usbhs_pipe_number(p) - 1) * 2)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
26
27
28
29
  #define usbhsp_flags_set(p, f)	((p)->flags |=  USBHS_PIPE_FLAGS_##f)
  #define usbhsp_flags_clr(p, f)	((p)->flags &= ~USBHS_PIPE_FLAGS_##f)
  #define usbhsp_flags_has(p, f)	((p)->flags &   USBHS_PIPE_FLAGS_##f)
  #define usbhsp_flags_init(p)	do {(p)->flags = 0; } while (0)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
30
31
32
33
34
35
36
37
38
  /*
   * for debug
   */
  static char *usbhsp_pipe_name[] = {
  	[USB_ENDPOINT_XFER_CONTROL]	= "DCP",
  	[USB_ENDPOINT_XFER_BULK]	= "BULK",
  	[USB_ENDPOINT_XFER_INT]		= "INT",
  	[USB_ENDPOINT_XFER_ISOC]	= "ISO",
  };
3cf8ed128   Kuninori Morimoto   usb: gadget: rene...
39
40
41
42
  char *usbhs_pipe_name(struct usbhs_pipe *pipe)
  {
  	return usbhsp_pipe_name[usbhs_pipe_type(pipe)];
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
43
  /*
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
44
45
46
47
   *		DCPCTR/PIPEnCTR functions
   */
  static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
48
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
49
  	int offset = usbhsp_addr_offset(pipe);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
50
  	if (usbhs_pipe_is_dcp(pipe))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
51
52
53
54
55
56
57
  		usbhs_bset(priv, DCPCTR, mask, val);
  	else
  		usbhs_bset(priv, PIPEnCTR + offset, mask, val);
  }
  
  static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
58
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
59
  	int offset = usbhsp_addr_offset(pipe);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
60
  	if (usbhs_pipe_is_dcp(pipe))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
61
62
63
64
65
66
67
68
69
70
71
72
  		return usbhs_read(priv, DCPCTR);
  	else
  		return usbhs_read(priv, PIPEnCTR + offset);
  }
  
  /*
   *		DCP/PIPE functions
   */
  static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
  				  u16 dcp_reg, u16 pipe_reg,
  				  u16 mask, u16 val)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
73
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
74

e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
75
  	if (usbhs_pipe_is_dcp(pipe))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
76
77
78
79
  		usbhs_bset(priv, dcp_reg, mask, val);
  	else
  		usbhs_bset(priv, pipe_reg, mask, val);
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
80
81
82
83
84
85
86
87
88
  /*
   *		DCPCFG/PIPECFG functions
   */
  static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
  	__usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val);
  }
  
  /*
1c90ee0b3   Kuninori Morimoto   usb: renesas_usbh...
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
   *		PIPEnTRN/PIPEnTRE functions
   */
  static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  	struct device *dev = usbhs_priv_to_dev(priv);
  	int num = usbhs_pipe_number(pipe);
  	u16 reg;
  
  	/*
  	 * It is impossible to calculate address,
  	 * since PIPEnTRN addresses were mapped randomly.
  	 */
  #define CASE_PIPExTRN(a)		\
  	case 0x ## a:			\
  		reg = PIPE ## a ## TRN;	\
  		break;
  
  	switch (num) {
  	CASE_PIPExTRN(1);
  	CASE_PIPExTRN(2);
  	CASE_PIPExTRN(3);
  	CASE_PIPExTRN(4);
  	CASE_PIPExTRN(5);
  	CASE_PIPExTRN(B);
  	CASE_PIPExTRN(C);
  	CASE_PIPExTRN(D);
  	CASE_PIPExTRN(E);
  	CASE_PIPExTRN(F);
  	CASE_PIPExTRN(9);
  	CASE_PIPExTRN(A);
  	default:
  		dev_err(dev, "unknown pipe (%d)
  ", num);
  		return;
  	}
  	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
  }
  
  static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  	struct device *dev = usbhs_priv_to_dev(priv);
  	int num = usbhs_pipe_number(pipe);
  	u16 reg;
  
  	/*
  	 * It is impossible to calculate address,
  	 * since PIPEnTRE addresses were mapped randomly.
  	 */
  #define CASE_PIPExTRE(a)			\
  	case 0x ## a:				\
  		reg = PIPE ## a ## TRE;		\
  		break;
  
  	switch (num) {
  	CASE_PIPExTRE(1);
  	CASE_PIPExTRE(2);
  	CASE_PIPExTRE(3);
  	CASE_PIPExTRE(4);
  	CASE_PIPExTRE(5);
  	CASE_PIPExTRE(B);
  	CASE_PIPExTRE(C);
  	CASE_PIPExTRE(D);
  	CASE_PIPExTRE(E);
  	CASE_PIPExTRE(F);
  	CASE_PIPExTRE(9);
  	CASE_PIPExTRE(A);
  	default:
  		dev_err(dev, "unknown pipe (%d)
  ", num);
  		return;
  	}
  
  	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
  }
  
  /*
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
167
168
169
170
   *		PIPEBUF
   */
  static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
171
  	if (usbhs_pipe_is_dcp(pipe))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
172
173
174
175
176
177
178
179
180
181
182
183
  		return;
  
  	__usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val);
  }
  
  /*
   *		DCPMAXP/PIPEMAXP
   */
  static void usbhsp_pipe_maxp_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
  {
  	__usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val);
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
184
185
186
187
188
  /*
   *		pipe control functions
   */
  static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
189
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  
  	/*
  	 * On pipe, this is necessary before
  	 * accesses to below registers.
  	 *
  	 * PIPESEL	: usbhsp_pipe_select
  	 * PIPECFG	: usbhsp_pipe_cfg_xxx
  	 * PIPEBUF	: usbhsp_pipe_buf_xxx
  	 * PIPEMAXP	: usbhsp_pipe_maxp_xxx
  	 * PIPEPERI
  	 */
  
  	/*
  	 * if pipe is dcp, no pipe is selected.
  	 * it is no problem, because dcp have its register
  	 */
  	usbhs_write(priv, PIPESEL, 0xF & usbhs_pipe_number(pipe));
  }
  
  static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
211
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  	int timeout = 1024;
  	u16 val;
  
  	/*
  	 * make sure....
  	 *
  	 * Modify these bits when CSSTS = 0, PID = NAK, and no pipe number is
  	 * specified by the CURPIPE bits.
  	 * When changing the setting of this bit after changing
  	 * the PID bits for the selected pipe from BUF to NAK,
  	 * check that CSSTS = 0 and PBUSY = 0.
  	 */
  
  	/*
  	 * CURPIPE bit = 0
  	 *
  	 * see also
  	 *  "Operation"
  	 *  - "Pipe Control"
  	 *   - "Pipe Control Registers Switching Procedure"
  	 */
  	usbhs_write(priv, CFIFOSEL, 0);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
234
  	usbhs_pipe_disable(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
235
236
237
238
239
240
241
242
243
244
  
  	do {
  		val  = usbhsp_pipectrl_get(pipe);
  		val &= CSSTS | PID_MASK;
  		if (!val)
  			return 0;
  
  		udelay(10);
  
  	} while (timeout--);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
245
246
  	return -EBUSY;
  }
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
247
  int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
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
  {
  	u16 val;
  
  	val = usbhsp_pipectrl_get(pipe);
  	if (val & BSTS)
  		return 0;
  
  	return -EBUSY;
  }
  
  /*
   *		PID ctrl
   */
  static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe)
  {
  	u16 pid = usbhsp_pipectrl_get(pipe);
  
  	pid &= PID_MASK;
  
  	/*
  	 * see
  	 * "Pipe n Control Register" - "PID"
  	 */
  	switch (pid) {
  	case PID_STALL11:
  		usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10);
  		/* fall-through */
  	case PID_STALL10:
  		usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK);
  	}
  }
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
279
  void usbhs_pipe_disable(struct usbhs_pipe *pipe)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
280
  {
c786e09c3   Kuninori Morimoto   usb: renesas_usbh...
281
282
  	int timeout = 1024;
  	u16 val;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
283
284
285
286
  	/* see "Pipe n Control Register" - "PID" */
  	__usbhsp_pid_try_nak_if_stall(pipe);
  
  	usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK);
c786e09c3   Kuninori Morimoto   usb: renesas_usbh...
287
288
289
290
291
292
293
294
295
  
  	do {
  		val  = usbhsp_pipectrl_get(pipe);
  		val &= PBUSY;
  		if (!val)
  			break;
  
  		udelay(10);
  	} while (timeout--);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
296
  }
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
297
  void usbhs_pipe_enable(struct usbhs_pipe *pipe)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
298
299
300
301
302
303
  {
  	/* see "Pipe n Control Register" - "PID" */
  	__usbhsp_pid_try_nak_if_stall(pipe);
  
  	usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF);
  }
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
304
  void usbhs_pipe_stall(struct usbhs_pipe *pipe)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  {
  	u16 pid = usbhsp_pipectrl_get(pipe);
  
  	pid &= PID_MASK;
  
  	/*
  	 * see
  	 * "Pipe n Control Register" - "PID"
  	 */
  	switch (pid) {
  	case PID_NAK:
  		usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10);
  		break;
  	case PID_BUF:
  		usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL11);
  		break;
  	}
  }
9cf1b06e9   Kuninori Morimoto   usb: renesas_usbh...
323
324
325
326
327
328
  int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
  {
  	u16 pid = usbhsp_pipectrl_get(pipe) & PID_MASK;
  
  	return (int)(pid == PID_STALL10 || pid == PID_STALL11);
  }
1c90ee0b3   Kuninori Morimoto   usb: renesas_usbh...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
  {
  	if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
  		return;
  
  	/*
  	 * clear and disable transfer counter for IN/OUT pipe
  	 */
  	usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);
  
  	/*
  	 * Only IN direction bulk pipe can use transfer count.
  	 * Without using this function,
  	 * received data will break if it was large data size.
  	 * see PIPEnTRN/PIPEnTRE for detail
  	 */
  	if (usbhs_pipe_is_dir_in(pipe)) {
  		int maxp = usbhs_pipe_get_maxpacket(pipe);
  
  		usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
  		usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
  	}
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
352
  /*
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
353
354
355
356
357
358
359
   *		pipe setup
   */
  static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe)
  {
  	/*
  	 * only ISO / BULK pipe can use double buffer
  	 */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
360
361
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) ||
  	    usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
362
363
364
365
366
367
  		return 1;
  
  	return 0;
  }
  
  static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
368
369
  				int is_host,
  				int dir_in)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  {
  	u16 type = 0;
  	u16 bfre = 0;
  	u16 dblb = 0;
  	u16 cntmd = 0;
  	u16 dir = 0;
  	u16 epnum = 0;
  	u16 shtnak = 0;
  	u16 type_array[] = {
  		[USB_ENDPOINT_XFER_BULK] = TYPE_BULK,
  		[USB_ENDPOINT_XFER_INT]  = TYPE_INT,
  		[USB_ENDPOINT_XFER_ISOC] = TYPE_ISO,
  	};
  	int is_double = usbhsp_possible_double_buffer(pipe);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
384
  	if (usbhs_pipe_is_dcp(pipe))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
385
386
387
388
389
390
391
392
393
394
395
396
  		return -EINVAL;
  
  	/*
  	 * PIPECFG
  	 *
  	 * see
  	 *  - "Register Descriptions" - "PIPECFG" register
  	 *  - "Features"  - "Pipe configuration"
  	 *  - "Operation" - "Pipe Control"
  	 */
  
  	/* TYPE */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
397
  	type = type_array[usbhs_pipe_type(pipe)];
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
398
399
  
  	/* BFRE */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
400
401
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
  	    usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
402
403
404
  		bfre = 0; /* FIXME */
  
  	/* DBLB */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
405
406
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
  	    usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
407
408
409
  		dblb = (is_double) ? DBLB : 0;
  
  	/* CNTMD */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
410
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
411
412
413
  		cntmd = 0; /* FIXME */
  
  	/* DIR */
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
414
  	if (dir_in)
ad6f2a8bc   Kuninori Morimoto   usb: renesas_usbh...
415
  		usbhsp_flags_set(pipe, IS_DIR_HOST);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
416

14ff96e04   Felipe Balbi   usb: renesas: pip...
417
  	if (!!is_host ^ !!dir_in)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
418
  		dir |= DIR_OUT;
ad6f2a8bc   Kuninori Morimoto   usb: renesas_usbh...
419
420
  	if (!dir)
  		usbhsp_flags_set(pipe, IS_DIR_IN);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
421
  	/* SHTNAK */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
422
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) &&
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
423
424
425
426
  	    !dir)
  		shtnak = SHTNAK;
  
  	/* EPNUM */
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
427
  	epnum = 0; /* see usbhs_pipe_config_update() */
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
428
429
430
431
432
433
434
435
436
  
  	return	type	|
  		bfre	|
  		dblb	|
  		cntmd	|
  		dir	|
  		shtnak	|
  		epnum;
  }
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
437
  static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
438
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
439
440
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
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
  	struct device *dev = usbhs_priv_to_dev(priv);
  	int pipe_num = usbhs_pipe_number(pipe);
  	int is_double = usbhsp_possible_double_buffer(pipe);
  	u16 buff_size;
  	u16 bufnmb;
  	u16 bufnmb_cnt;
  
  	/*
  	 * PIPEBUF
  	 *
  	 * see
  	 *  - "Register Descriptions" - "PIPEBUF" register
  	 *  - "Features"  - "Pipe configuration"
  	 *  - "Operation" - "FIFO Buffer Memory"
  	 *  - "Operation" - "Pipe Control"
  	 *
  	 * ex) if pipe6 - pipe9 are USB_ENDPOINT_XFER_INT (SH7724)
  	 *
  	 * BUFNMB:	PIPE
  	 * 0:		pipe0 (DCP 256byte)
  	 * 1:		-
  	 * 2:		-
  	 * 3:		-
  	 * 4:		pipe6 (INT 64byte)
  	 * 5:		pipe7 (INT 64byte)
  	 * 6:		pipe8 (INT 64byte)
  	 * 7:		pipe9 (INT 64byte)
  	 * 8 - xx:	free (for BULK, ISOC)
  	 */
  
  	/*
  	 * FIXME
  	 *
  	 * it doesn't have good buffer allocator
  	 *
  	 * DCP : 256 byte
  	 * BULK: 512 byte
  	 * INT :  64 byte
  	 * ISOC: 512 byte
  	 */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
481
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_CONTROL))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
482
  		buff_size = 256;
356db7eda   Kuninori Morimoto   usb: gadget: rene...
483
  	else if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
484
485
486
487
488
489
490
491
492
  		buff_size = 64;
  	else
  		buff_size = 512;
  
  	/* change buff_size to register value */
  	bufnmb_cnt = (buff_size / 64) - 1;
  
  	/* BUFNMB has been reserved for INT pipe
  	 * see above */
356db7eda   Kuninori Morimoto   usb: gadget: rene...
493
  	if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) {
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  		bufnmb = pipe_num - 2;
  	} else {
  		bufnmb = info->bufnmb_last;
  		info->bufnmb_last += bufnmb_cnt + 1;
  
  		/*
  		 * double buffer
  		 */
  		if (is_double)
  			info->bufnmb_last += bufnmb_cnt + 1;
  	}
  
  	dev_dbg(dev, "pipe : %d : buff_size 0x%x: bufnmb 0x%x
  ",
  		pipe_num, buff_size, bufnmb);
  
  	return	(0x1f & bufnmb_cnt)	<< 10 |
  		(0xff & bufnmb)		<<  0;
  }
bc6fbf59d   Kuninori Morimoto   usb: gadget: rene...
513
514
  void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
  			      u16 epnum, u16 maxp)
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
515
  {
bc6fbf59d   Kuninori Morimoto   usb: gadget: rene...
516
517
518
519
520
521
522
523
524
  	if (devsel > 0xA) {
  		struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
  		struct device *dev = usbhs_priv_to_dev(priv);
  
  		dev_err(dev, "devsel error %d
  ", devsel);
  
  		devsel = 0;
  	}
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
525
  	usbhsp_pipe_barrier(pipe);
7fd097e72   Kuninori Morimoto   usb: gadget: rene...
526
  	pipe->maxp = maxp;
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
527
  	usbhsp_pipe_select(pipe);
bc6fbf59d   Kuninori Morimoto   usb: gadget: rene...
528
529
530
  	usbhsp_pipe_maxp_set(pipe, 0xFFFF,
  			     (devsel << 12) |
  			     maxp);
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
531
532
533
534
  
  	if (!usbhs_pipe_is_dcp(pipe))
  		usbhsp_pipe_cfg_set(pipe,  0x000F, epnum);
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
535
536
537
538
539
  /*
   *		pipe control
   */
  int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe)
  {
7fd097e72   Kuninori Morimoto   usb: gadget: rene...
540
541
542
543
544
545
  	/*
  	 * see
  	 *	usbhs_pipe_config_update()
  	 *	usbhs_dcp_malloc()
  	 */
  	return pipe->maxp;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
546
547
548
549
550
551
  }
  
  int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe)
  {
  	return usbhsp_flags_has(pipe, IS_DIR_IN);
  }
ad6f2a8bc   Kuninori Morimoto   usb: renesas_usbh...
552
553
554
555
  int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
  {
  	return usbhsp_flags_has(pipe, IS_DIR_HOST);
  }
8355b2b30   Yoshihiro Shimoda   usb: renesas_usbh...
556
557
558
559
560
561
562
563
564
565
566
567
  int usbhs_pipe_is_running(struct usbhs_pipe *pipe)
  {
  	return usbhsp_flags_has(pipe, IS_RUNNING);
  }
  
  void usbhs_pipe_running(struct usbhs_pipe *pipe, int running)
  {
  	if (running)
  		usbhsp_flags_set(pipe, IS_RUNNING);
  	else
  		usbhsp_flags_clr(pipe, IS_RUNNING);
  }
3edeee389   Kuninori Morimoto   usb: renesas_usbh...
568
  void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
569
  {
6e6db82ba   Kuninori Morimoto   usb: gadget: rene...
570
  	u16 mask = (SQCLR | SQSET);
3edeee389   Kuninori Morimoto   usb: renesas_usbh...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
  	u16 val;
  
  	/*
  	 * sequence
  	 *  0  : data0
  	 *  1  : data1
  	 *  -1 : no change
  	 */
  	switch (sequence) {
  	case 0:
  		val = SQCLR;
  		break;
  	case 1:
  		val = SQSET;
  		break;
  	default:
  		return;
  	}
6e6db82ba   Kuninori Morimoto   usb: gadget: rene...
589
590
  
  	usbhsp_pipectrl_set(pipe, mask, val);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
591
  }
08e6c6111   Kuninori Morimoto   usb: renesas_usbh...
592
593
594
595
596
  void usbhs_pipe_clear(struct usbhs_pipe *pipe)
  {
  	usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
  	usbhsp_pipectrl_set(pipe, ACLRM, 0);
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
597
598
599
600
601
602
603
604
605
606
  static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
  {
  	struct usbhs_pipe *pos, *pipe;
  	int i;
  
  	/*
  	 * find target pipe
  	 */
  	pipe = NULL;
  	usbhs_for_each_pipe_with_dcp(pos, priv, i) {
356db7eda   Kuninori Morimoto   usb: gadget: rene...
607
  		if (!usbhs_pipe_type_is(pos, type))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  			continue;
  		if (usbhsp_flags_has(pos, IS_USED))
  			continue;
  
  		pipe = pos;
  		break;
  	}
  
  	if (!pipe)
  		return NULL;
  
  	/*
  	 * initialize pipe flags
  	 */
  	usbhsp_flags_init(pipe);
  	usbhsp_flags_set(pipe, IS_USED);
  
  	return pipe;
  }
dfb87b8bf   Yoshihiro Shimoda   usb: renesas_usbh...
627
628
629
630
  static void usbhsp_put_pipe(struct usbhs_pipe *pipe)
  {
  	usbhsp_flags_init(pipe);
  }
4bd048115   Kuninori Morimoto   usb: renesas_usbh...
631
  void usbhs_pipe_init(struct usbhs_priv *priv,
e73a9891b   Kuninori Morimoto   usb: renesas_usbh...
632
  		     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
633
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
634
  	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  	struct usbhs_pipe *pipe;
  	int i;
  
  	/*
  	 * FIXME
  	 *
  	 * driver needs good allocator.
  	 *
  	 * find first free buffer area (BULK, ISOC)
  	 * (DCP, INT area is fixed)
  	 *
  	 * buffer number 0 - 3 have been reserved for DCP
  	 * see
  	 *	usbhsp_to_bufnmb
  	 */
  	info->bufnmb_last = 4;
  	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
356db7eda   Kuninori Morimoto   usb: gadget: rene...
652
  		if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
653
654
655
  			info->bufnmb_last++;
  
  		usbhsp_flags_init(pipe);
d77e3f4e1   Kuninori Morimoto   usb: renesas_usbh...
656
  		pipe->fifo = NULL;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
657
  		pipe->mod_private = NULL;
6acb95d4e   Kuninori Morimoto   usb: renesas_usbh...
658
  		INIT_LIST_HEAD(&pipe->list);
45e13e6e0   Kuninori Morimoto   usb: renesas_usbh...
659

e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
660
  		/* pipe force init */
08e6c6111   Kuninori Morimoto   usb: renesas_usbh...
661
  		usbhs_pipe_clear(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
662
  	}
4bd048115   Kuninori Morimoto   usb: renesas_usbh...
663

e73a9891b   Kuninori Morimoto   usb: renesas_usbh...
664
  	info->dma_map_ctrl = dma_map_ctrl;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
665
666
667
  }
  
  struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
668
669
  				     int endpoint_type,
  				     int dir_in)
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
670
671
  {
  	struct device *dev = usbhs_priv_to_dev(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
672
  	struct usbhs_pipe *pipe;
0deb3e770   Kuninori Morimoto   usb: gadget: rene...
673
  	int is_host = usbhs_mod_is_host(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
674
  	int ret;
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
675
  	u16 pipecfg, pipebuf;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
676

f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
677
  	pipe = usbhsp_get_pipe(priv, endpoint_type);
f429ea3f3   Kuninori Morimoto   usb: renesas_usbh...
678
679
680
  	if (!pipe) {
  		dev_err(dev, "can't get pipe (%s)
  ",
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
681
  			usbhsp_pipe_name[endpoint_type]);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
682
  		return NULL;
f429ea3f3   Kuninori Morimoto   usb: renesas_usbh...
683
  	}
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
684

6acb95d4e   Kuninori Morimoto   usb: renesas_usbh...
685
  	INIT_LIST_HEAD(&pipe->list);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
686
  	usbhs_pipe_disable(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
687
688
689
690
691
692
693
694
  
  	/* make sure pipe is not busy */
  	ret = usbhsp_pipe_barrier(pipe);
  	if (ret < 0) {
  		dev_err(dev, "pipe setup failed %d
  ", usbhs_pipe_number(pipe));
  		return NULL;
  	}
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
695
696
  	pipecfg  = usbhsp_setup_pipecfg(pipe, is_host, dir_in);
  	pipebuf  = usbhsp_setup_pipebuff(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
697

f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
698
699
700
  	usbhsp_pipe_select(pipe);
  	usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
  	usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
6a0541599   Yoshihiro Shimoda   usb: renesas_usbh...
701
  	usbhs_pipe_clear(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
702

6e6db82ba   Kuninori Morimoto   usb: gadget: rene...
703
  	usbhs_pipe_sequence_data0(pipe);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
704
705
706
707
  
  	dev_dbg(dev, "enable pipe %d : %s (%s)
  ",
  		usbhs_pipe_number(pipe),
3cf8ed128   Kuninori Morimoto   usb: gadget: rene...
708
  		usbhs_pipe_name(pipe),
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
709
  		usbhs_pipe_is_dir_in(pipe) ? "in" : "out");
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
710
711
712
713
  	/*
  	 * epnum / maxp are still not set to this pipe.
  	 * call usbhs_pipe_config_update() after this function !!
  	 */
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
714
715
  	return pipe;
  }
dfb87b8bf   Yoshihiro Shimoda   usb: renesas_usbh...
716
717
718
719
  void usbhs_pipe_free(struct usbhs_pipe *pipe)
  {
  	usbhsp_put_pipe(pipe);
  }
d77e3f4e1   Kuninori Morimoto   usb: renesas_usbh...
720
721
722
723
724
725
726
727
728
729
  void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
  {
  	if (pipe->fifo)
  		pipe->fifo->pipe = NULL;
  
  	pipe->fifo = fifo;
  
  	if (fifo)
  		fifo->pipe = pipe;
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
730
731
732
733
734
735
736
737
738
739
  /*
   *		dcp control
   */
  struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv)
  {
  	struct usbhs_pipe *pipe;
  
  	pipe = usbhsp_get_pipe(priv, USB_ENDPOINT_XFER_CONTROL);
  	if (!pipe)
  		return NULL;
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
740
  	INIT_LIST_HEAD(&pipe->list);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
741
  	/*
f5aa889f7   Kuninori Morimoto   usb: gadget: rene...
742
  	 * call usbhs_pipe_config_update() after this function !!
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
743
  	 */
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
744
745
746
747
748
  	return pipe;
  }
  
  void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
  {
e2eddc610   Kuninori Morimoto   usb: gadget: rene...
749
  	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
750
  	WARN_ON(!usbhs_pipe_is_dcp(pipe));
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
751

e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
752
  	usbhs_pipe_enable(pipe);
e2eddc610   Kuninori Morimoto   usb: gadget: rene...
753
754
755
  
  	if (!usbhs_mod_is_host(priv)) /* funconly */
  		usbhsp_pipectrl_set(pipe, CCPL, CCPL);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
756
  }
923520715   Kuninori Morimoto   usb: gadget: rene...
757
758
759
760
761
  void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out)
  {
  	usbhsp_pipe_cfg_set(pipe, DIR_OUT,
  			    dir_out ? DIR_OUT : 0);
  }
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
762
763
764
765
766
  /*
   *		pipe module function
   */
  int usbhs_pipe_probe(struct usbhs_priv *priv)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
767
  	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  	struct usbhs_pipe *pipe;
  	struct device *dev = usbhs_priv_to_dev(priv);
  	u32 *pipe_type = usbhs_get_dparam(priv, pipe_type);
  	int pipe_size = usbhs_get_dparam(priv, pipe_size);
  	int i;
  
  	/* This driver expects 1st pipe is DCP */
  	if (pipe_type[0] != USB_ENDPOINT_XFER_CONTROL) {
  		dev_err(dev, "1st PIPE is not DCP
  ");
  		return -EINVAL;
  	}
  
  	info->pipe = kzalloc(sizeof(struct usbhs_pipe) * pipe_size, GFP_KERNEL);
  	if (!info->pipe) {
  		dev_err(dev, "Could not allocate pipe
  ");
  		return -ENOMEM;
  	}
  
  	info->size = pipe_size;
  
  	/*
  	 * init pipe
  	 */
  	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
  		pipe->priv = priv;
356db7eda   Kuninori Morimoto   usb: gadget: rene...
795
796
797
  
  		usbhs_pipe_type(pipe) =
  			pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK;
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
798
799
800
801
802
803
804
805
806
807
808
  
  		dev_dbg(dev, "pipe %x\t: %s
  ",
  			i, usbhsp_pipe_name[pipe_type[i]]);
  	}
  
  	return 0;
  }
  
  void usbhs_pipe_remove(struct usbhs_priv *priv)
  {
e8d548d54   Kuninori Morimoto   usb: renesas_usbh...
809
  	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c6   Kuninori Morimoto   usb: renesas_usbh...
810
811
812
  
  	kfree(info->pipe);
  }