fifo.c 13.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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>
#include <linux/io.h>
#include "./common.h"
#include "./pipe.h"

22 23
#define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))

24 25
#define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */

26 27 28
/*
 *		packet info function
 */
29
static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done)
30 31 32 33 34 35 36 37 38 39 40 41 42 43
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe);
	struct device *dev = usbhs_priv_to_dev(priv);

	dev_err(dev, "null handler\n");

	return -EINVAL;
}

static struct usbhs_pkt_handle usbhsf_null_handler = {
	.prepare = usbhsf_null_handle,
	.try_run = usbhsf_null_handle,
};

44 45 46 47 48
void usbhs_pkt_init(struct usbhs_pkt *pkt)
{
	INIT_LIST_HEAD(&pkt->node);
}

49
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
50
		    struct usbhs_pkt_handle *handler,
51
		    void *buf, int len, int zero)
52
{
53 54
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
	struct device *dev = usbhs_priv_to_dev(priv);
55 56 57 58
	unsigned long flags;

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);
59 60 61 62 63 64

	if (!handler) {
		dev_err(dev, "no handler function\n");
		handler = &usbhsf_null_handler;
	}

65 66 67
	list_del_init(&pkt->node);
	list_add_tail(&pkt->node, &pipe->list);

68 69
	pkt->pipe	= pipe;
	pkt->buf	= buf;
70
	pkt->handler	= handler;
71 72 73
	pkt->length	= len;
	pkt->zero	= zero;
	pkt->actual	= 0;
74 75 76

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/
77 78
}

79
static void __usbhsf_pkt_del(struct usbhs_pkt *pkt)
80 81 82 83
{
	list_del_init(&pkt->node);
}

84
static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
85 86 87 88 89 90 91
{
	if (list_empty(&pipe->list))
		return NULL;

	return list_entry(pipe->list.next, struct usbhs_pkt, node);
}

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
struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
	unsigned long flags;

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);

	if (!pkt)
		pkt = __usbhsf_pkt_get(pipe);

	if (pkt)
		__usbhsf_pkt_del(pkt);

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/

	return pkt;
}

int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type)
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
	struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
	struct usbhs_pkt *pkt;
	struct device *dev = usbhs_priv_to_dev(priv);
	int (*func)(struct usbhs_pkt *pkt, int *is_done);
	unsigned long flags;
	int ret = 0;
	int is_done = 0;

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);

	pkt = __usbhsf_pkt_get(pipe);
	if (!pkt)
		goto __usbhs_pkt_handler_end;

	switch (type) {
	case USBHSF_PKT_PREPARE:
		func = pkt->handler->prepare;
		break;
	case USBHSF_PKT_TRY_RUN:
		func = pkt->handler->try_run;
		break;
	default:
		dev_err(dev, "unknown pkt hander\n");
		goto __usbhs_pkt_handler_end;
	}

	ret = func(pkt, &is_done);

	if (is_done)
		__usbhsf_pkt_del(pkt);

__usbhs_pkt_handler_end:
	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/

	if (is_done)
		info->done(pkt);

	return ret;
}

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
/*
 *		irq enable/disable function
 */
#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
#define usbhsf_irq_callback_ctrl(pipe, status, enable)			\
	({								\
		struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);	\
		struct usbhs_mod *mod = usbhs_mod_get_current(priv);	\
		u16 status = (1 << usbhs_pipe_number(pipe));		\
		if (!mod)						\
			return;						\
		if (enable)						\
			mod->irq_##status |= status;			\
		else							\
			mod->irq_##status &= ~status;			\
		usbhs_irq_callback_update(priv, mod);			\
	})

static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
{
	/*
	 * And DCP pipe can NOT use "ready interrupt" for "send"
	 * it should use "empty" interrupt.
	 * see
	 *   "Operation" - "Interrupt Function" - "BRDY Interrupt"
	 *
	 * on the other hand, normal pipe can use "ready interrupt" for "send"
	 * even though it is single/double buffer
	 */
	if (usbhs_pipe_is_dcp(pipe))
		usbhsf_irq_empty_ctrl(pipe, enable);
	else
		usbhsf_irq_ready_ctrl(pipe, enable);
}

static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
{
	usbhsf_irq_ready_ctrl(pipe, enable);
}

198 199 200
/*
 *		FIFO ctrl
 */
201 202
static void usbhsf_send_terminator(struct usbhs_pipe *pipe,
				   struct usbhs_fifo *fifo)
203 204 205
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);

206
	usbhs_bset(priv, fifo->ctr, BVAL, BVAL);
207 208
}

209 210
static int usbhsf_fifo_barrier(struct usbhs_priv *priv,
			       struct usbhs_fifo *fifo)
211 212 213 214 215
{
	int timeout = 1024;

	do {
		/* The FIFO port is accessible */
216
		if (usbhs_read(priv, fifo->ctr) & FRDY)
217 218 219 220 221 222 223 224
			return 0;

		udelay(10);
	} while (timeout--);

	return -EBUSY;
}

225 226
static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
			      struct usbhs_fifo *fifo)
227 228 229 230
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);

	if (!usbhs_pipe_is_dcp(pipe))
231
		usbhsf_fifo_barrier(priv, fifo);
232

233
	usbhs_write(priv, fifo->ctr, BCLR);
234 235
}

236 237
static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
			       struct usbhs_fifo *fifo)
238
{
239
	return usbhs_read(priv, fifo->ctr) & DTLN_MASK;
240 241
}

242 243 244 245 246 247 248 249 250
static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
				 struct usbhs_fifo *fifo)
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);

	usbhs_pipe_select_fifo(pipe, NULL);
	usbhs_write(priv, fifo->sel, 0);
}

251 252 253
static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
			      struct usbhs_fifo *fifo,
			      int write)
254 255 256 257 258 259 260
{
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
	struct device *dev = usbhs_priv_to_dev(priv);
	int timeout = 1024;
	u16 mask = ((1 << 5) | 0xF);		/* mask of ISEL | CURPIPE */
	u16 base = usbhs_pipe_number(pipe);	/* CURPIPE */

261 262 263 264
	if (usbhs_pipe_is_busy(pipe) ||
	    usbhsf_fifo_is_busy(fifo))
		return -EBUSY;

265 266 267 268
	if (usbhs_pipe_is_dcp(pipe))
		base |= (1 == write) << 5;	/* ISEL */

	/* "base" will be used below  */
269
	usbhs_write(priv, fifo->sel, base | MBW_32);
270 271 272

	/* check ISEL and CURPIPE value */
	while (timeout--) {
273 274
		if (base == (mask & usbhs_read(priv, fifo->sel))) {
			usbhs_pipe_select_fifo(pipe, fifo);
275
			return 0;
276
		}
277 278 279 280 281 282 283 284 285 286 287
		udelay(10);
	}

	dev_err(dev, "fifo select error\n");

	return -EIO;
}

/*
 *		PIO fifo functions
 */
288
static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
289
{
290
	struct usbhs_pipe *pipe = pkt->pipe;
291
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
292
	struct device *dev = usbhs_priv_to_dev(priv);
293 294
	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
	void __iomem *addr = priv->base + fifo->port;
295
	u8 *buf;
296 297
	int maxp = usbhs_pipe_get_maxpacket(pipe);
	int total_len;
298
	int i, ret, len;
299
	int is_short;
300

301
	ret = usbhsf_fifo_select(pipe, fifo, 1);
302
	if (ret < 0)
303
		return 0;
304

305
	ret = usbhs_pipe_is_accessible(pipe);
306
	if (ret < 0)
307
		goto usbhs_fifo_write_busy;
308

309
	ret = usbhsf_fifo_barrier(priv, fifo);
310
	if (ret < 0)
311
		goto usbhs_fifo_write_busy;
312

313 314 315 316 317
	buf		= pkt->buf    + pkt->actual;
	len		= pkt->length - pkt->actual;
	len		= min(len, maxp);
	total_len	= len;
	is_short	= total_len < maxp;
318 319 320 321 322 323

	/*
	 * FIXME
	 *
	 * 32-bit access only
	 */
324
	if (len >= 4 && !((unsigned long)buf & 0x03)) {
325 326 327 328 329 330 331 332 333
		iowrite32_rep(addr, buf, len / 4);
		len %= 4;
		buf += total_len - len;
	}

	/* the rest operation */
	for (i = 0; i < len; i++)
		iowrite8(buf[i], addr + (0x03 - (i & 0x03)));

334 335 336 337 338 339
	/*
	 * variable update
	 */
	pkt->actual += total_len;

	if (pkt->actual < pkt->length)
340
		*is_done = 0;		/* there are remainder data */
341
	else if (is_short)
342
		*is_done = 1;		/* short packet */
343
	else
344
		*is_done = !pkt->zero;	/* send zero packet ? */
345 346 347 348 349

	/*
	 * pipe/irq handling
	 */
	if (is_short)
350
		usbhsf_send_terminator(pipe, fifo);
351

352
	usbhsf_tx_irq_ctrl(pipe, !*is_done);
353 354
	usbhs_pipe_enable(pipe);

355 356
	dev_dbg(dev, "  send %d (%d/ %d/ %d/ %d)\n",
		usbhs_pipe_number(pipe),
357
		pkt->length, pkt->actual, *is_done, pkt->zero);
358 359 360 361

	/*
	 * Transmission end
	 */
362
	if (*is_done) {
363 364
		if (usbhs_pipe_is_dcp(pipe))
			usbhs_dcp_control_transfer_done(pipe);
365 366
	}

367 368
	usbhsf_fifo_unselect(pipe, fifo);

369
	return 0;
370 371

usbhs_fifo_write_busy:
372 373
	usbhsf_fifo_unselect(pipe, fifo);

374 375 376 377 378 379 380
	/*
	 * pipe is busy.
	 * retry in interrupt
	 */
	usbhsf_tx_irq_ctrl(pipe, 1);

	return ret;
381 382
}

383 384 385 386 387
struct usbhs_pkt_handle usbhs_fifo_push_handler = {
	.prepare = usbhsf_try_push,
	.try_run = usbhsf_try_push,
};

388
static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
389
{
390
	struct usbhs_pipe *pipe = pkt->pipe;
391 392 393

	if (usbhs_pipe_is_busy(pipe))
		return 0;
394 395

	/*
396
	 * pipe enable to prepare packet receive
397 398 399
	 */

	usbhs_pipe_enable(pipe);
400
	usbhsf_rx_irq_ctrl(pipe, 1);
401

402
	return 0;
403 404
}

405
static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
406
{
407
	struct usbhs_pipe *pipe = pkt->pipe;
408
	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
409
	struct device *dev = usbhs_priv_to_dev(priv);
410 411
	struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
	void __iomem *addr = priv->base + fifo->port;
412 413 414
	u8 *buf;
	u32 data = 0;
	int maxp = usbhs_pipe_get_maxpacket(pipe);
415
	int rcv_len, len;
416
	int i, ret;
417
	int total_len = 0;
418

419
	ret = usbhsf_fifo_select(pipe, fifo, 0);
420
	if (ret < 0)
421
		return 0;
422

423
	ret = usbhsf_fifo_barrier(priv, fifo);
424
	if (ret < 0)
425
		goto usbhs_fifo_read_busy;
426

427
	rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
428

429 430 431 432 433
	buf		= pkt->buf    + pkt->actual;
	len		= pkt->length - pkt->actual;
	len		= min(len, rcv_len);
	total_len	= len;

434 435 436 437 438 439 440
	/*
	 * Buffer clear if Zero-Length packet
	 *
	 * see
	 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
	 */
	if (0 == rcv_len) {
441
		usbhsf_fifo_clear(pipe, fifo);
442
		goto usbhs_fifo_read_end;
443 444 445 446 447 448 449
	}

	/*
	 * FIXME
	 *
	 * 32-bit access only
	 */
450
	if (len >= 4 && !((unsigned long)buf & 0x03)) {
451 452
		ioread32_rep(addr, buf, len / 4);
		len %= 4;
453
		buf += total_len - len;
454 455 456 457 458 459 460 461 462 463
	}

	/* the rest operation */
	for (i = 0; i < len; i++) {
		if (!(i & 0x03))
			data = ioread32(addr);

		buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
	}

464 465
	pkt->actual += total_len;

466
usbhs_fifo_read_end:
467
	if ((pkt->actual == pkt->length) ||	/* receive all data */
468 469
	    (total_len < maxp)) {		/* short packet */
		*is_done = 1;
470 471
		usbhsf_rx_irq_ctrl(pipe, 0);
		usbhs_pipe_disable(pipe);
472 473
	}

474 475 476 477
	dev_dbg(dev, "  recv %d (%d/ %d/ %d/ %d)\n",
		usbhs_pipe_number(pipe),
		pkt->length, pkt->actual, *is_done, pkt->zero);

478 479 480 481
usbhs_fifo_read_busy:
	usbhsf_fifo_unselect(pipe, fifo);

	return ret;
482
}
483 484 485 486 487 488 489 490 491

struct usbhs_pkt_handle usbhs_fifo_pop_handler = {
	.prepare = usbhsf_prepare_pop,
	.try_run = usbhsf_try_pop,
};

/*
 *		handler function
 */
492
static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done)
493
{
494
	usbhs_dcp_control_transfer_done(pkt->pipe);
495

496
	*is_done = 1;
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530

	return 0;
}

struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = {
	.prepare = usbhsf_ctrl_stage_end,
	.try_run = usbhsf_ctrl_stage_end,
};

/*
 *		irq functions
 */
static int usbhsf_irq_empty(struct usbhs_priv *priv,
			    struct usbhs_irq_state *irq_state)
{
	struct usbhs_pipe *pipe;
	struct device *dev = usbhs_priv_to_dev(priv);
	int i, ret;

	if (!irq_state->bempsts) {
		dev_err(dev, "debug %s !!\n", __func__);
		return -EIO;
	}

	dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts);

	/*
	 * search interrupted "pipe"
	 * not "uep".
	 */
	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
		if (!(irq_state->bempsts & (1 << i)))
			continue;

531
		ret = usbhs_pkt_run(pipe);
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
		if (ret < 0)
			dev_err(dev, "irq_empty run_error %d : %d\n", i, ret);
	}

	return 0;
}

static int usbhsf_irq_ready(struct usbhs_priv *priv,
			    struct usbhs_irq_state *irq_state)
{
	struct usbhs_pipe *pipe;
	struct device *dev = usbhs_priv_to_dev(priv);
	int i, ret;

	if (!irq_state->brdysts) {
		dev_err(dev, "debug %s !!\n", __func__);
		return -EIO;
	}

	dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts);

	/*
	 * search interrupted "pipe"
	 * not "uep".
	 */
	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
		if (!(irq_state->brdysts & (1 << i)))
			continue;

561
		ret = usbhs_pkt_run(pipe);
562 563 564 565 566 567 568 569 570 571 572 573 574
		if (ret < 0)
			dev_err(dev, "irq_ready run_error %d : %d\n", i, ret);
	}

	return 0;
}

/*
 *		fifo init
 */
void usbhs_fifo_init(struct usbhs_priv *priv)
{
	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
575
	struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv);
576 577 578 579 580

	mod->irq_empty		= usbhsf_irq_empty;
	mod->irq_ready		= usbhsf_irq_ready;
	mod->irq_bempsts	= 0;
	mod->irq_brdysts	= 0;
581 582

	cfifo->pipe	= NULL;
583 584 585 586 587 588 589 590 591 592 593
}

void usbhs_fifo_quit(struct usbhs_priv *priv)
{
	struct usbhs_mod *mod = usbhs_mod_get_current(priv);

	mod->irq_empty		= NULL;
	mod->irq_ready		= NULL;
	mod->irq_bempsts	= 0;
	mod->irq_brdysts	= 0;
}
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610

int usbhs_fifo_probe(struct usbhs_priv *priv)
{
	struct usbhs_fifo *fifo;

	/* CFIFO */
	fifo = usbhsf_get_cfifo(priv);
	fifo->port	= CFIFO;
	fifo->sel	= CFIFOSEL;
	fifo->ctr	= CFIFOCTR;

	return 0;
}

void usbhs_fifo_remove(struct usbhs_priv *priv)
{
}