[PATCH] usb: add Freescale QE/CPM USB peripheral controller driver

Anton Vorontsov avorontsov at ru.mvista.com
Thu Aug 7 01:15:38 EST 2008


On Wed, Aug 06, 2008 at 03:16:40PM +0800, Li Yang wrote:
> Some of Freescale SoC chips have a QE or CPM co-processor which
> supports full speed USB.  The driver adds device mode support
> of both QE and CPM USB controller to Linux USB gadget.  The
> driver is tested with MPC8360 and MPC8272, and should work with
> other models having QE/CPM given minor tweaks.
> 
> Signed-off-by: Xie Xiaobo <X.Xie at freescale.com>
> Signed-off-by: Li Yang <leoli at freescale.com>

Hi,

Few (mostly cosmetic) comments below. I didn't look into locking and
other stuff, just few general questions: did you try this driver
with CONFIG_SMP (even on UP machine), CONFIG_PREEMPT,
CONFIG_DEBUG_SPINLOCK and CONFIG_DEBUG_SPINLOCK_SLEEP?
These options will trigger most obvious bugs.

Also, I think sparse tool will be very unhappy about this driver,
there are lots of unnecessary and dubious casts...

Also surprisingly, checkpatch reports just few warnings though there
are a lot of cosmetic issues...

> ---
>  drivers/usb/gadget/Kconfig        |   19 +
>  drivers/usb/gadget/Makefile       |    1 +
>  drivers/usb/gadget/fsl_qe_udc.c   | 2729 +++++++++++++++++++++++++++++++++++++
>  drivers/usb/gadget/fsl_qe_udc.h   |  458 +++++++
>  drivers/usb/gadget/gadget_chips.h |    9 +
>  5 files changed, 3216 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/fsl_qe_udc.c
>  create mode 100644 drivers/usb/gadget/fsl_qe_udc.h
> 
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index c6a8c6b..fba8305 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -150,6 +150,25 @@ config USB_FSL_USB2
>  	default USB_GADGET
>  	select USB_GADGET_SELECTED
>  
> +config USB_GADGET_FSL_QE
> +    boolean "Freescale QE/CPM USB Device Controller"

no depends on? Without depends, this driver will break build for arches
other than powerpc && (qe || cpm)

> +    help
> +       Some of Freescale PowerPC processors have a Full Speed
> +       QE/CPM2 USB controller, which support device mode with 4
> +       programmable endpoints. This driver supports the
> +       controller in the MPC8360 and MPC8272, and should work with
> +       controllers having QE or CPM2, given minor tweaks.
> +
> +       Say "y" to link the driver statically, or "m" to build a
> +       dynamically linked module called "fsl_qe_udc" and force all
> +       gadget drivers to also be dynamically linked.
> +
> +config USB_FSL_QE
> +    tristate
> +    depends on USB_GADGET_FSL_QE
> +    default USB_GADGET
> +    select USB_GADGET_SELECTED
> +
>  config USB_GADGET_NET2280
>  	boolean "NetChip 228x"
>  	depends on PCI
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index fcb5cb9..4871554 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_USB_AT91)		+= at91_udc.o
>  obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
>  obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
>  obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
> +obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
>  
>  #
>  # USB gadget drivers
> diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
> new file mode 100644
> index 0000000..52790f7
> --- /dev/null
> +++ b/drivers/usb/gadget/fsl_qe_udc.c
> @@ -0,0 +1,2729 @@
> +/*
> + * driver/usb/gadget/fsl_qe_udc.c
> + *
> + * Copyright (c) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Xie Xiaobo <X.Xie at freescale.com>
> + * Li Yang <leoli at freescale.com>
> + * Based on bareboard code from Shlomi Gridish.
> + *
> + * Description:
> + * Freescle QE/CPM USB Pheripheral Controller Driver
> + * The controller can be found on MPC8360, MPC8272, and etc.
> + * MPC8360 Rev 1.1 may need QE mircocode update
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation;  either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#undef USB_TRACE

Nobody seem to use this.

> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/ioport.h>
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/delay.h>

Don't see any calls to sleep or delay.

> +#include <linux/slab.h>
> +#include <linux/timer.h>
> +#include <linux/list.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>

Do you really need irq.h? This is somewhat internal header.

> +#include <linux/io.h>
> +#include <linux/proc_fs.h>

Seems spurious also.

> +#include <linux/mm.h>
> +#include <linux/uaccess.h>

Not sure about this one.

> +#include <linux/moduleparam.h>
> +
> +#include <linux/of_platform.h>
> +
> +#include <asm/qe.h>
> +#include <asm/dma.h>
> +#include <asm/reg.h>
> +
> +#include <linux/usb/ch9.h>
> +#include <linux/usb/gadget.h>
> +#include <linux/usb/otg.h>
> +#include <linux/dma-mapping.h>
> +#include "fsl_qe_udc.h"
> +
> +#ifdef CONFIG_CPM2
> +extern int cpm_command(u32 command, u8 opcode);
> +extern unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
> +extern int cpm_muram_free(unsigned long offset);

These are externed in the include/asm-powerpc/cpm.h.

> +#define qe_muram_alloc cpm_muram_alloc
> +#define qe_muram_free cpm_muram_free

qe_muarm_* calls are cpm_muram_* calls, see
include/asm-powerpc/qe.h in the recent kernels.
So, you can just switch to cpm_*.

> +#endif
> +
> +#define DRIVER_DESC     "Freescale QE/CPM USB Device Controller driver"
> +#define DRIVER_AUTHOR   "Xie XiaoBo"
> +#define DRIVER_VERSION  "1.0"
> +
> +#define DMA_ADDR_INVALID        (~(dma_addr_t)0)
> +
> +static const char driver_name[] = "fsl_qe_udc";
> +static const char driver_desc[] = DRIVER_DESC;
> +
> +/*ep name is important in gadget, it should obey the convention of ep_match()*/
> +static const char *const ep_name[] = {
> +	"ep0-control", /* everyone has ep0 */
> +	/* 3 configurable endpoints */
> +	"ep1",
> +	"ep2",
> +	"ep3",
> +};
> +
> +static struct usb_endpoint_descriptor
> +qe_ep0_desc = {

This seem to fit into one line perfectly well.

> +	.bLength =		USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType =	USB_DT_ENDPOINT,
> +
> +	.bEndpointAddress =	0,
> +	.bmAttributes =		USB_ENDPOINT_XFER_CONTROL,
> +	.wMaxPacketSize =	USB_MAX_CTRL_PAYLOAD,
> +};
> +
> +/* it is initialized in probe()  */
> +static struct qe_udc *udc_controller;
> +
> +/********************************************************************
> + *      Internal Used Function Start
> +********************************************************************/
> +/*-----------------------------------------------------------------
> + * done() - retire a request; caller blocked irqs
> + *--------------------------------------------------------------*/
> +static void done(struct qe_ep *ep, struct qe_req *req, int status)
> +{
> +	struct qe_udc *udc = NULL;
> +	unsigned char stopped = ep->stopped;
> +	udc = (struct qe_udc *) ep->udc;
> +
> +	/* the req->queue pointer is used by ep_queue() func, in which
> +	* the request will be added into a udc_ep->queue 'd tail

The comments are broken this way all over the place.
Can we stick with

/*
 * Multiline
 * comment.
 */

? This is orthodox style.

> +	* so here the req will be dropped from the ep->queue
> +	*/
> +	list_del_init(&req->queue);
> +
> +	/* req.status should be set as -EINPROGRESS in ep_queue() */
> +	if (req->req.status == -EINPROGRESS)
> +		req->req.status = status;
> +	else
> +		status = req->req.status;
> +
> +	if (req->mapped) {
> +		dma_unmap_single(ep->udc->gadget.dev.parent,
> +			req->req.dma, req->req.length,
> +			ep_is_in(ep)
> +				? DMA_TO_DEVICE
> +				: DMA_FROM_DEVICE);
> +		req->req.dma = DMA_ADDR_INVALID;
> +		req->mapped = 0;
> +	} else

if () {
	multi;
	statement;
} else { <- brace
	single statement;
}

> +		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
> +			req->req.dma, req->req.length,
> +			ep_is_in(ep)
> +				? DMA_TO_DEVICE
> +				: DMA_FROM_DEVICE);
> +
> +	if (status && (status != -ESHUTDOWN))
> +		VDBG("complete %s req %p stat %d len %u/%u",
> +			ep->ep.name, &req->req, status,
> +			req->req.actual, req->req.length);

please use dev_vdbg().

> +
> +	/* don't modify queue heads during completion callback */
> +	ep->stopped = 1;
> +	spin_unlock(&ep->udc->lock);
> +
> +	/* this complete() should a func implemented by gadget layer,
> +	* eg fsg->bulk_in_complete() */
> +	if (req->req.complete)
> +		req->req.complete(&ep->ep, &req->req);
> +
> +	spin_lock(&ep->udc->lock);
> +
> +	ep->stopped = stopped;
> +}
> +
> +/*-----------------------------------------------------------------
> + * nuke(): delete all requests related to this ep
> + *--------------------------------------------------------------*/
> +static void nuke(struct qe_ep *ep, int status)
> +{
> +	/* Whether this eq has request linked */
> +	while (!list_empty(&ep->queue)) {
> +		struct qe_req *req = NULL;

No need to = NULL.

> +		req = list_entry(ep->queue.next, struct qe_req, queue);
> +
> +		done(ep, req, status);
> +	}
> +}
> +
> +/*---------------------------------------------------------------------------*
> + * USB and Endpoint manipulate process, include parameter and register       *
> + *---------------------------------------------------------------------------*/
> +/* @value: 1--set stall 0--clean stall */
> +static int qe_eprx_stall_change(struct qe_ep *ep, int value)
> +{
> +	u16 tem_usep;
> +	u8 epnum = ep->epnum;
> +	struct qe_udc *udc = ep->udc;
> +
> +	tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
> +	tem_usep = tem_usep & ~USB_RHS_MASK;
> +	if (value == 1)
> +		tem_usep |= USB_RHS_STALL;
> +	else if (ep->dir == USB_DIR_IN)
> +		tem_usep |= USB_RHS_IGNORE_OUT;
> +
> +	out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
> +	return 0;
> +}
> +
> +static int qe_eptx_stall_change(struct qe_ep *ep, int value)
> +{
> +	u16 tem_usep;
> +	u8 epnum = ep->epnum;
> +	struct qe_udc *udc = ep->udc;
> +
> +	tem_usep = in_be16(&udc->usb_regs->usb_usep[epnum]);
> +	tem_usep = tem_usep & ~USB_THS_MASK;
> +	if (value == 1)
> +		tem_usep |= USB_THS_STALL;
> +	else if (ep->dir == USB_DIR_OUT)
> +		tem_usep |= USB_THS_IGNORE_IN;
> +
> +	out_be16(&udc->usb_regs->usb_usep[epnum], tem_usep);
> +
> +	return 0;
> +}
> +
> +static int qe_ep0_stall(struct qe_udc *udc)
> +{
> +	qe_eptx_stall_change(&udc->eps[0], 1);
> +	qe_eprx_stall_change(&udc->eps[0], 1);
> +	udc_controller->ep0_state = WAIT_FOR_SETUP;
> +	udc_controller->ep0_dir = 0;
> +	return 0;
> +}
> +
> +static int qe_eprx_nack(struct qe_ep *ep)
> +{
> +	u8 epnum = ep->epnum;
> +	struct qe_udc *udc = ep->udc;
> +
> +	if (ep->state == EP_STATE_IDLE) {
> +		/* Set the ep's nack */
> +		clrsetbits_be16(&udc->usb_regs->usb_usep[epnum],
> +				USB_RHS_MASK, USB_RHS_NACK);
> +
> +		/* Mask Rx and Busy interrupts */
> +		clrbits16(&udc->usb_regs->usb_usbmr,
> +				(USB_E_RXB_MASK | USB_E_BSY_MASK));
> +
> +		ep->state = EP_STATE_NACK;
> +	}
> +	return 0;
> +}
> +
> +static int qe_eprx_normal(struct qe_ep *ep)
> +{
> +	struct qe_udc *udc = ep->udc;
> +
> +	if (ep->state == EP_STATE_NACK) {
> +		clrsetbits_be16(&udc->usb_regs->usb_usep[ep->epnum],
> +				USB_RTHS_MASK, USB_THS_IGNORE_IN);
> +
> +		/* Unmask RX interrupts */
> +		out_be16(&udc->usb_regs->usb_usber,
> +				USB_E_BSY_MASK|USB_E_RXB_MASK);

Not sure why checkpatch does not complain about missing spaces
around "|"...

> +		setbits16(&udc->usb_regs->usb_usbmr,
> +				(USB_E_RXB_MASK | USB_E_BSY_MASK));
> +
> +		ep->state = EP_STATE_IDLE;
> +		ep->has_data = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +static int qe_ep_cmd_stoptx(struct qe_ep *ep)
> +{
> +	u8 ep_num;
> +#ifdef CONFIG_CPM2
> +	u32 command;
> +	u8 opcode;
> +
> +	ep_num = ep->epnum << CPM_USB_EP_SHIFT;
> +	command = CPM_USB_STOP_TX | (u32)ep_num;
> +	opcode = CPM_USB_STOP_TX_OPCODE;
> +	cpm_command(command, opcode);
> +#else
> +	ep_num = ep->epnum;
> +	qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, ep_num, 0);
> +#endif
> +	return 0;
> +}
> +
> +static int qe_ep_cmd_restarttx(struct qe_ep *ep)
> +{
> +	u8 ep_num;
> +#ifdef CONFIG_CPM2
> +	u32 command;
> +	u8 opcode;
> +
> +	ep_num = ep->epnum << CPM_USB_EP_SHIFT;
> +	command = CPM_USB_RESTART_TX | (u32)ep_num;
> +	opcode = CPM_USB_RESTART_TX_OPCODE;
> +	cpm_command(command, opcode);
> +#else
> +	ep_num = ep->epnum;
> +	qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB, ep_num, 0);
> +#endif
> +	return 0;
> +}
> +
> +static int qe_ep_flushtxfifo(struct qe_ep *ep)
> +{
> +	struct qe_ep *tmp_ep;
> +	struct qe_udc *udc = ep->udc;
> +	int i;
> +
> +	tmp_ep = ep;
> +	i = (int)tmp_ep->epnum;
> +
> +	qe_ep_cmd_stoptx(tmp_ep);
> +	out_8(&udc->usb_regs->usb_uscom,
> +		USB_CMD_FLUSH_FIFO | (USB_CMD_EP_MASK & (tmp_ep->epnum)));
> +	udc->ep_param[i]->tbptr = udc->ep_param[i]->tbase;
> +	udc->ep_param[i]->tstate = 0;
> +	udc->ep_param[i]->tbcnt = 0;
> +
> +	tmp_ep->c_txbd = tmp_ep->txbase;
> +	tmp_ep->n_txbd = tmp_ep->txbase;
> +	qe_ep_cmd_restarttx(tmp_ep);
> +	return 0;
> +}
> +
> +static int qe_ep_filltxfifo(struct qe_ep *ep)
> +{
> +	struct qe_udc *udc = ep->udc;
> +
> +	out_8(&udc->usb_regs->usb_uscom,
> +			USB_CMD_STR_FIFO | (USB_CMD_EP_MASK & (ep->epnum)));
> +	return 0;
> +}
> +
> +static int qe_epbds_reset(struct qe_udc *udc, int pipe_num)
> +{
> +	struct qe_ep *ep;
> +	u32 bdring_len;
> +	u8 *bd;
> +	int i;
> +
> +	ep = &(udc->eps[pipe_num]);

No need for parentheses.

> +
> +	if (ep->dir == USB_DIR_OUT)
> +		bdring_len = USB_BDRING_LEN_RX;
> +	else
> +		bdring_len = USB_BDRING_LEN;
> +
> +	bd = (u8 *)ep->rxbase;
> +	for (i = 0; i < bdring_len; i++) {
> +		BD_STATUS_AND_LENGTH_SET(bd, (R_E|R_I));

I would put spaces around "|".

> +		bd += QE_SIZEOF_BD;
> +	}
> +	bd -= QE_SIZEOF_BD;
> +	BD_STATUS_AND_LENGTH_SET(bd, (R_E|R_I|R_W));

ditto.

> +
> +	bd = (u8 *)(ep->txbase);
> +	for (i = 0; i < USB_BDRING_LEN_TX; i++) {
> +		BD_BUFFER_CLEAR(bd);
> +		BD_STATUS_AND_LENGTH_SET(bd, 0);
> +		bd += QE_SIZEOF_BD;
> +	}
> +	bd -= QE_SIZEOF_BD;
> +	BD_STATUS_AND_LENGTH_SET(bd, T_W);
> +
> +	return 0;
> +}
> +
> +static int qe_ep_reset(struct qe_udc *udc, int pipe_num)
> +{
> +	struct qe_ep *ep;
> +	u16 tmpusep;
> +
> +	ep = &(udc->eps[pipe_num]);

Parentheses.

> +	tmpusep = in_be16(&udc->usb_regs->usb_usep[pipe_num]);
> +	tmpusep &= ~USB_RTHS_MASK;
> +
> +	switch (ep->dir) {
> +	case USB_DIR_BOTH:
> +		qe_ep_flushtxfifo(ep);
> +		break;
> +	case USB_DIR_OUT:
> +		tmpusep |= USB_THS_IGNORE_IN;
> +		break;
> +	case USB_DIR_IN:
> +		qe_ep_flushtxfifo(ep);
> +		tmpusep |= USB_RHS_IGNORE_OUT;
> +		break;
> +	default:
> +		break;
> +	}
> +	out_be16(&udc->usb_regs->usb_usep[pipe_num], tmpusep);
> +
> +	qe_epbds_reset(udc, pipe_num);
> +
> +	return 0;
> +}
> +
> +static int qe_ep_toggledata01(struct qe_ep *ep)
> +{
> +	struct qe_ep *tmpep = ep;
> +
> +	tmpep->data01 ^= 0x1;
> +	return 0;
> +}
> +
> +static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num)
> +{
> +	struct qe_ep *ep = &(udc->eps[pipe_num]);

Ditto.

> +	unsigned long tmp_addr = 0;
> +	struct usb_ep_para __iomem *epparam;
> +	int i;
> +	u8 *bd;
> +	int bdring_len;
> +
> +	if (ep->dir == USB_DIR_OUT)
> +		bdring_len = USB_BDRING_LEN_RX;
> +	else
> +		bdring_len = USB_BDRING_LEN;
> +
> +	epparam = udc->ep_param[pipe_num];
> +	/* alloc multi-ram for BD rings and set the ep parameters */
> +	tmp_addr = qe_muram_alloc(QE_SIZEOF_BD * (bdring_len +
> +				USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD);
> +	out_be16(&epparam->rbase, (u16)tmp_addr);
> +	out_be16(&epparam->tbase, (u16)(tmp_addr +
> +				(QE_SIZEOF_BD * bdring_len)));
> +
> +	out_be16(&epparam->rbptr, in_be16(&epparam->rbase));
> +	out_be16(&epparam->tbptr, in_be16(&epparam->tbase));
> +
> +	ep->rxbase = (struct qe_bd *)muram_addr(tmp_addr);
> +	ep->txbase = (struct qe_bd *)muram_addr(tmp_addr +
> +						(QE_SIZEOF_BD * bdring_len));
> +	ep->n_rxbd = ep->rxbase;
> +	ep->e_rxbd = ep->rxbase;
> +	ep->n_txbd = ep->txbase;
> +	ep->c_txbd = ep->txbase;
> +	ep->data01 = 0; /* data0 */
> +
> +	/* Init TX and RX bds */
> +	bd = (u8 *)(ep->rxbase);
> +	for (i = 0; i < bdring_len; i++) {
> +		BD_BUFFER_CLEAR(bd);
> +		BD_STATUS_AND_LENGTH_SET(bd, 0);
> +		bd += QE_SIZEOF_BD;
> +	}
> +	bd -= QE_SIZEOF_BD;
> +	BD_STATUS_AND_LENGTH_SET(bd, R_W);
> +
> +	bd = (u8 *)(ep->txbase);
> +	for (i = 0; i < USB_BDRING_LEN_TX; i++) {
> +		BD_BUFFER_CLEAR(bd);
> +		BD_STATUS_AND_LENGTH_SET(bd, 0);
> +		bd += QE_SIZEOF_BD;
> +	}
> +	bd -= QE_SIZEOF_BD;
> +	BD_STATUS_AND_LENGTH_SET(bd, T_W);
> +
> +	return 0;
> +}
> +
> +static int qe_ep_rxbd_update(struct qe_ep *ep)
> +{
> +	unsigned int size;
> +	int i;
> +	unsigned int tmp;
> +	struct qe_bd *bd;
> +	unsigned int bdring_len;
> +
> +	if (ep->rxbase == NULL)
> +		return -EINVAL;
> +
> +	bd = ep->rxbase;
> +
> +	ep->rxframe = kmalloc(sizeof(struct qe_frame), GFP_KERNEL);
> +	if (ep->rxframe == NULL) {
> +		dev_err(ep->udc->dev, "malloc rxframe failed\n");
> +		return -ENOMEM;
> +	}
> +
> +	qe_frame_init(ep->rxframe);
> +
> +	if (ep->dir == USB_DIR_OUT)
> +		bdring_len = USB_BDRING_LEN_RX;
> +	else
> +		bdring_len = USB_BDRING_LEN;
> +
> +	size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) * (bdring_len + 1);
> +	ep->rxbuffer = kzalloc(size, GFP_KERNEL);
> +	if (ep->rxbuffer == NULL) {
> +		dev_err(ep->udc->dev, "malloc rxbuffer failed,size=%d\n",
> +				size);
> +		return -ENOMEM;
> +	}
> +
> +	ep->rxbuf_d = virt_to_phys((void *)ep->rxbuffer);
> +	if (ep->rxbuf_d == DMA_ADDR_INVALID) {
> +		ep->rxbuf_d = dma_map_single(udc_controller->gadget.dev.parent,
> +					ep->rxbuffer,
> +					size,
> +					DMA_FROM_DEVICE);
> +		ep->rxbufmap = 1;
> +	} else {
> +		dma_sync_single_for_device(udc_controller->gadget.dev.parent,
> +					ep->rxbuf_d, size,
> +					DMA_FROM_DEVICE);
> +		ep->rxbufmap = 0;
> +	}
> +
> +	size = ep->ep.maxpacket + USB_CRC_SIZE + 2;
> +	tmp = ep->rxbuf_d;
> +	tmp = (u32)(((tmp>>2)<<2) + 4);
> +
> +	for (i = 0; i < bdring_len; i++) {
> +		BD_BUFFER_SET(bd, tmp);
> +		BD_STATUS_AND_LENGTH_SET(bd, (R_E|R_I));
> +		tmp = tmp + size;
> +		bd++;
> +	}
> +	bd--;
> +	BD_STATUS_AND_LENGTH_SET(bd, (R_E|R_I|R_W));
> +
> +	return 0;
> +}
> +
> +static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
> +{
> +	struct qe_ep *ep = &(udc->eps[pipe_num]);
> +	struct usb_ep_para __iomem *epparam;
> +	u16 usep, logepnum;
> +	u16 tmp;
> +	u8 rtfcr = 0;
> +
> +	epparam = udc->ep_param[pipe_num];
> +
> +	usep = 0;
> +	logepnum = (ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
> +	usep |= (logepnum << USB_EPNUM_SHIFT);
> +
> +	switch (ep->desc->bmAttributes & 0x03) {
> +	case USB_ENDPOINT_XFER_BULK:
> +		usep |= USB_TRANS_BULK;
> +		break;
> +	case USB_ENDPOINT_XFER_ISOC:
> +		usep |=  USB_TRANS_ISO;
> +		break;
> +	case USB_ENDPOINT_XFER_INT:
> +		usep |= USB_TRANS_INT;
> +		break;
> +	default:
> +		usep |= USB_TRANS_CTR;
> +		break;
> +	}
> +
> +	switch (ep->dir) {
> +	case USB_DIR_OUT:
> +		usep |= USB_THS_IGNORE_IN;
> +		break;
> +	case USB_DIR_IN:
> +		usep |= USB_RHS_IGNORE_OUT;
> +		break;
> +	default:
> +		break;
> +	}
> +	out_be16(&udc->usb_regs->usb_usep[pipe_num], usep);
> +
> +	rtfcr = 0x30;
> +	out_8(&epparam->rbmr, rtfcr);
> +	out_8(&epparam->tbmr, rtfcr);
> +
> +	tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
> +	/* MRBLR must be divisble by 4 */
> +	tmp = (u16)(((tmp >> 2) << 2) + 4);
> +	out_be16(&epparam->mrblr, tmp);
> +
> +	return 0;
> +}
> +
> +static int qe_ep_init(struct qe_udc *udc,
> +		      unsigned char pipe_num,
> +		      const struct usb_endpoint_descriptor *desc)
> +{
> +	struct qe_ep *ep = &(udc->eps[pipe_num]);
> +	unsigned long flags = 0;
> +	int reval = 0;
> +	u16 max = 0;
> +
> +	max = le16_to_cpu(desc->wMaxPacketSize);
> +
> +	/* check the max package size validate for this endpoint */
> +	/* Refer to USB2.0 spec table 9-13,
> +	*/
> +	if (pipe_num != 0) {
> +		switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
> +		case USB_ENDPOINT_XFER_BULK:
> +			if (strstr(ep->ep.name, "-iso")
> +				|| strstr(ep->ep.name, "-int"))
> +			goto en_done;
> +			switch (udc->gadget.speed) {
> +			case USB_SPEED_HIGH:
> +			if ((max == 128) || (max == 256) || (max == 512))
> +				break;
> +			default:
> +				switch (max) {
> +				case 4:
> +				case 8:
> +				case 16:
> +				case 32:
> +				case 64:
> +					break;
> +				default:
> +				case USB_SPEED_LOW:
> +					goto en_done;
> +				}
> +			}
> +			break;
> +		case USB_ENDPOINT_XFER_INT:
> +			if (strstr(ep->ep.name, "-iso"))	/* bulk is ok */
> +				goto en_done;
> +			switch (udc->gadget.speed) {
> +			case USB_SPEED_HIGH:
> +				if (max <= 1024)
> +					break;
> +			case USB_SPEED_FULL:
> +				if (max <= 64)
> +					break;
> +			default:
> +				if (max <= 8)
> +					break;
> +				goto en_done;
> +			}
> +			break;
> +		case USB_ENDPOINT_XFER_ISOC:
> +			if (strstr(ep->ep.name, "-bulk")
> +				|| strstr(ep->ep.name, "-int"))
> +				goto en_done;
> +			switch (udc->gadget.speed) {
> +			case USB_SPEED_HIGH:
> +				if (max <= 1024)
> +					break;
> +			case USB_SPEED_FULL:
> +				if (max <= 1023)
> +					break;
> +			default:
> +				goto en_done;
> +			}
> +			break;
> +		case USB_ENDPOINT_XFER_CONTROL:
> +			if (strstr(ep->ep.name, "-iso")
> +				|| strstr(ep->ep.name, "-int"))
> +				goto en_done;
> +			switch (udc->gadget.speed) {
> +			case USB_SPEED_HIGH:
> +			case USB_SPEED_FULL:
> +				switch (max) {
> +				case 1:
> +				case 2:
> +				case 4:
> +				case 8:
> +				case 16:
> +				case 32:
> +				case 64:
> +					break;
> +				default:
> +					goto en_done;
> +				}
> +			case USB_SPEED_LOW:
> +				switch (max) {
> +				case 1:
> +				case 2:
> +				case 4:
> +				case 8:
> +					break;
> +				default:
> +					goto en_done;
> +				}
> +			default:
> +				goto en_done;
> +			}
> +			break;
> +
> +		default:
> +			goto en_done;
> +		}
> +	} /* if ep0*/
> +
> +	/* here initialize variable of ep */
> +	ep->ep.maxpacket = max;
> +	ep->tm = (u8)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
> +	ep->desc = desc;
> +	ep->stopped = 0;
> +	ep->init = 1;
> +
> +	if (pipe_num == 0) {
> +		ep->dir = USB_DIR_BOTH;
> +		udc->ep0_dir = USB_DIR_OUT;
> +		udc->ep0_state = WAIT_FOR_SETUP;
> +	} else	{
> +		switch ((desc->bEndpointAddress)&USB_ENDPOINT_DIR_MASK) {

This *looks* like a cast. But actually it is "a & b". It took me
quite some time to parse this. Just remove parentheses to avoid
the confusion.

> +		case USB_DIR_OUT:
> +			ep->dir = USB_DIR_OUT;
> +			break;
> +		case USB_DIR_IN:
> +			ep->dir = USB_DIR_IN;
> +		default:
> +			break;
> +		}
> +	}
> +
> +	spin_lock_irqsave(&udc->lock, flags);
> +
> +	/* hardware special operation */
> +	qe_ep_bd_init((void *)udc, pipe_num);

Unneeded cast.

> +	if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_OUT)) {
> +		reval = qe_ep_rxbd_update(ep);
> +		if (reval)
> +			goto en_done;
> +	}
> +
> +	if ((ep->tm == USBP_TM_CTL) || (ep->dir == USB_DIR_IN)) {
> +		ep->txframe = kmalloc(sizeof(struct qe_frame), GFP_KERNEL);
> +		if (ep->txframe == NULL) {
> +			dev_err(udc->dev, "malloc txframe failed\n");
> +			goto en_done;
> +		}
> +		qe_frame_init(ep->txframe);
> +	}
> +	qe_ep_register_init((void *)udc, pipe_num);

Unneeded cast.

> +
> +	/* Now HW will be NAKing transfers to that EP,
> +	 * until a buffer is queued to it. */
> +
> +	/* should have stop the lock */
> +	spin_unlock_irqrestore(&udc->lock, flags);
> +	return 0;
> +
> +en_done:
> +	VDBG("init %s failed!", ep->ep.name);
> +	return -ENODEV;
> +}
> +
> +static int qe_usb_enable(void)
> +{
> +	setbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
> +
> +	return 0;

You don't need, neither check any return value for this function.
Return type of void will work here.

> +}
> +
> +static int qe_usb_disable(void)
> +{
> +	clrbits8(&udc_controller->usb_regs->usb_usmod, USB_MODE_EN);
> +
> +	return 0;

Ditto.

> +}
> +
> +/*----------------------------------------------------------------------------*
> + *		USB and EP basic manipulate function end		      *
> + *----------------------------------------------------------------------------*/
> +
> +
> +/******************************************************************************
> +		UDC transmit and receive process
> + ******************************************************************************/
> +static void recycle_one_rxbd(struct qe_ep *ep)
> +{
> +	u32 bdstatus;
> +
> +	bdstatus = (u32)BD_STATUS_AND_LENGTH(ep->e_rxbd);
> +	bdstatus = R_I | R_E | (bdstatus & R_W);
> +	BD_STATUS_AND_LENGTH_SET(ep->e_rxbd, bdstatus);
> +
> +	if (bdstatus & R_W)
> +		ep->e_rxbd = ep->rxbase;
> +	else
> +		ep->e_rxbd++;
> +}
> +
> +static void recycle_rxbds(struct qe_ep *ep, unsigned char stopatnext)
> +{
> +	u32 bdstatus;
> +	struct qe_bd *bd, *nextbd;

struct qe_bd *bd;
struct qe_bd *nextbd;

> +	unsigned char stop = 0;
> +
> +	nextbd = ep->n_rxbd;
> +	bd = ep->e_rxbd;
> +	bdstatus = (u32)BD_STATUS_AND_LENGTH(bd);
> +
> +	while (!(bdstatus & R_E) && !(bdstatus&BD_LENGTH_MASK) && !stop) {
> +		bdstatus = R_E | R_I | (bdstatus & R_W);
> +		BD_STATUS_AND_LENGTH_SET(bd, bdstatus);
> +
> +		if (bdstatus & R_W)
> +			bd = ep->rxbase;
> +		else
> +			bd++;
> +
> +		bdstatus = (u32)BD_STATUS_AND_LENGTH(bd);
> +		if (stopatnext && (bd == nextbd))
> +			stop = 1;
> +	}
> +
> +	ep->e_rxbd = (struct qe_bd *)bd;
> +}
> +
> +static void ep_recycle_rxbds(struct qe_ep *ep)
> +{
> +	struct qe_bd *bd = NULL;
> +	u32 bdstatus;
> +	u8 epnum;
> +	struct qe_udc *udc = NULL;

No need to = NULL.

> +
> +	udc = ep->udc;
> +	epnum = ep->epnum;
> +
> +	bd = ep->n_rxbd;
> +	bdstatus = (u32)BD_STATUS_AND_LENGTH(bd);
> +	if (!(bdstatus & R_E) && !(bdstatus & BD_LENGTH_MASK)) {
> +		bd = (struct qe_bd *)(ep->rxbase +
> +				((in_be16(&udc->ep_param[epnum]->rbptr) -
> +				  in_be16(&udc->ep_param[epnum]->rbase))
> +				 >> 3));
> +		bdstatus = (u32)BD_STATUS_AND_LENGTH(bd);
> +
> +		if (bdstatus & R_W)
> +			bd = ep->rxbase;
> +		else
> +			bd++;
> +
> +		ep->e_rxbd = (struct qe_bd *)bd;
> +		VDBG("The QE completed full bd cycle");
> +		recycle_rxbds(ep, 0);
> +		ep->e_rxbd = ep->n_rxbd;
> +	} else
> +		recycle_rxbds(ep, 1);
> +
> +	if (in_be16(&udc->usb_regs->usb_usber) & USB_E_BSY_MASK)
> +		out_be16(&udc->usb_regs->usb_usber, USB_E_BSY_MASK);
> +
> +	if (ep->has_data <= 0 && (!list_empty(&ep->queue)))
> +		qe_eprx_normal(ep);
> +
> +	ep->localnack = 0;
> +}
> +
> +static void setup_received_handle(struct qe_udc *udc,
> +					struct usb_ctrlrequest *setup);
> +static int qe_ep_rxframe_handle(struct qe_ep *ep);
> +static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req);
> +/* when BD PID is setup, handle the packet */
> +static int ep0_setup_handle(struct qe_udc *udc)
> +{
> +	struct qe_ep *ep = &(udc->eps[0]);
> +	struct qe_frame *pframe = NULL;
> +	unsigned int fsize;
> +	u8 *cp;
> +
> +	pframe = (struct qe_frame *)ep->rxframe;

No need to case here.

> +	if ((frame_get_info(pframe) & PID_SETUP)
> +		&& (udc->ep0_state == WAIT_FOR_SETUP)) {
> +		fsize = (int)frame_get_length(pframe);
> +		if (unlikely(fsize != 8))
> +			return -EINVAL;
> +		cp = (u8 *)&(udc->local_setup_buff);
> +		memcpy(cp, pframe->data, fsize);
> +		ep->data01 = 1;
> +
> +		/* handle the usb command base on the usb_ctrlrequest */
> +		setup_received_handle(udc, &udc->local_setup_buff);
> +		return 0;
> +	}
> +	return -EINVAL;
> +}
> +
> +static int qe_ep0_rx(struct qe_udc *udc)
> +{
> +	struct qe_ep *ep = &(udc->eps[0]);
> +	struct qe_frame *pframe = NULL;
> +	struct qe_bd *bd;
> +	u32 bdstatus, length;
> +	u32 vaddr;
> +
> +	pframe = (struct qe_frame *)ep->rxframe;
> +
> +	if (ep->dir == USB_DIR_IN) {
> +		VDBG("error:This is a transmit ep!");
> +		return -EINVAL;
> +	}
> +
> +	bd = (struct qe_bd *)(ep->n_rxbd);
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	length = bdstatus & BD_LENGTH_MASK;
> +
> +	while (!(bdstatus&R_E) && length) {

Spaces around &.

> +		if ((bdstatus & R_F) && (bdstatus & R_L)
> +			&& !(bdstatus & R_ERROR)) {

I would add one more tab here.

> +			if (length == USB_CRC_SIZE) {
> +				udc->ep0_state = WAIT_FOR_SETUP;
> +				VDBG("receive a ZLP in status phase");
> +			} else {
> +				qe_frame_clean(pframe);
> +				vaddr = (u32)phys_to_virt(BD_BUFFER(bd));
> +				frame_set_data(pframe, (u8 *)vaddr);
> +				frame_set_length(pframe,
> +						(length - USB_CRC_SIZE));
> +				frame_set_status(pframe, FRAME_OK);
> +				switch (bdstatus & R_PID) {
> +				case R_PID_SETUP:
> +					frame_set_info(pframe, PID_SETUP);
> +					break;
> +				case R_PID_DATA1:
> +					frame_set_info(pframe, PID_DATA1);
> +					break;
> +				default:
> +					frame_set_info(pframe, PID_DATA0);
> +					break;
> +				}
> +
> +				if ((bdstatus & R_PID) == R_PID_SETUP)
> +					ep0_setup_handle(udc);
> +				else
> +					qe_ep_rxframe_handle(ep);
> +			}
> +		} else {
> +			dev_err(udc->dev, "The receive frame with error!\n");
> +		}
> +
> +		/* note: don't clear the rxbd's buffer address */
> +		recycle_one_rxbd(ep);
> +
> +		/* Get next BD */
> +		if (bdstatus & R_W)
> +			bd = ep->rxbase;
> +		else
> +			bd++;
> +
> +		bdstatus = BD_STATUS_AND_LENGTH(bd);
> +		length = bdstatus & BD_LENGTH_MASK;
> +
> +	}
> +
> +	ep->n_rxbd = (struct qe_bd *)bd;
> +
> +	return 0;
> +}
> +
> +static int qe_ep_rxframe_handle(struct qe_ep *ep)
> +{
> +	struct qe_frame *pframe = NULL;

No need for = NULL.

> +	u8 framepid = 0;
> +	unsigned int fsize;
> +	u8 *cp = NULL;
> +	struct qe_req *req = NULL;

You can move this variable to } else { branch down in this
function. And no need for = NULL.

> +
> +	pframe = (struct qe_frame *)ep->rxframe;
> +
> +	if (frame_get_info(pframe) & PID_DATA1)
> +		framepid = 0x1;
> +
> +	if (framepid != ep->data01) {
> +		dev_err(ep->udc->dev, "the data01 error!\n");
> +		return -EIO;
> +	}
> +
> +	fsize = frame_get_length(pframe);
> +	if (list_empty(&ep->queue)) {
> +		dev_err(ep->udc->dev, "the %s have no requeue!\n", ep->name);
> +	} else {
> +		req = list_entry(ep->queue.next, struct qe_req, queue);
> +
> +		cp = (u8 *)(req->req.buf) + req->req.actual;
> +		if (cp) {
> +			memcpy(cp, pframe->data, fsize);
> +			req->req.actual += fsize;
> +			if ((fsize < ep->ep.maxpacket) ||
> +					(req->req.actual >= req->req.length)) {
> +				if (ep->epnum == 0)
> +					ep0_req_complete(ep->udc, req);
> +				else
> +					done(ep, req, 0);
> +				if (list_empty(&ep->queue) && ep->epnum != 0)
> +					qe_eprx_nack(ep);
> +			}
> +		}
> +	}
> +
> +	qe_ep_toggledata01(ep);
> +
> +	return 0;
> +}
> +
> +static void ep_rx_tasklet(unsigned long data)
> +{
> +	struct qe_udc *udc = (struct qe_udc *)data;
> +	struct qe_ep *ep = NULL;
> +	struct qe_frame *pframe = NULL;

These NULLs are not needed.

> +	struct qe_bd *bd;
> +	u32 bdstatus, length;
> +	u32 vaddr, i;
> +
> +	for (i = 1; i < USB_MAX_ENDPOINTS; i++) {
> +		ep = (struct qe_ep *)&(udc->eps[i]);

Cast unneeded, I think.

> +
> +		if (ep->dir == USB_DIR_IN || ep->enable_tasklet == 0) {
> +			VDBG("This is a transmit ep or disable tasklet!");
> +			continue;
> +		}
> +
> +		pframe = (struct qe_frame *)ep->rxframe;
> +		bd = (struct qe_bd *)(ep->n_rxbd);
> +		bdstatus = BD_STATUS_AND_LENGTH(bd);
> +		length = bdstatus & BD_LENGTH_MASK;
> +
> +		while (!(bdstatus&R_E) && length) {

Spaces around &.

> +			if (list_empty(&ep->queue)) {
> +				qe_eprx_nack(ep);
> +				VDBG("The rxep have noreq %d", ep->has_data);
> +				break;
> +			}
> +
> +			if ((bdstatus & R_F) && (bdstatus & R_L)
> +				&& !(bdstatus & R_ERROR)) {
> +				qe_frame_clean(pframe);
> +				vaddr = (u32)phys_to_virt(BD_BUFFER(bd));
> +				frame_set_data(pframe, (u8 *)vaddr);
> +				frame_set_length(pframe,
> +						(length - USB_CRC_SIZE));
> +				frame_set_status(pframe, FRAME_OK);
> +				switch (bdstatus & R_PID) {
> +				case R_PID_DATA1:
> +					frame_set_info(pframe, PID_DATA1);
> +					break;
> +				case R_PID_SETUP:
> +					frame_set_info(pframe, PID_SETUP);
> +					break;
> +				default:
> +					frame_set_info(pframe, PID_DATA0);
> +					break;
> +				}
> +				/* handle the rx frame */
> +				qe_ep_rxframe_handle(ep);
> +			} else {
> +				dev_err(udc->dev,
> +					"error in received frame\n");
> +			}
> +			/* note: don't clear the rxbd's buffer address */
> +			/*clear the length */
> +			BD_STATUS_AND_LENGTH_SET(bd, (bdstatus&BD_STATUS_MASK));
> +			ep->has_data--;
> +			if (!(ep->localnack))
> +				recycle_one_rxbd(ep);
> +
> +			/* Get next BD */
> +			if (bdstatus & R_W)
> +				bd = ep->rxbase;
> +			else
> +				bd++;
> +
> +			bdstatus = BD_STATUS_AND_LENGTH(bd);
> +			length = bdstatus & BD_LENGTH_MASK;
> +		}
> +
> +		ep->n_rxbd = (struct qe_bd *)bd;
> +
> +		if (ep->localnack)
> +			ep_recycle_rxbds(ep);
> +
> +		ep->enable_tasklet = 0;
> +	} /* for i=1 */
> +}
> +
> +static int qe_ep_rx(struct qe_ep *ep)
> +{
> +	struct qe_udc *udc = NULL;
> +	struct qe_frame *pframe = NULL;
> +	struct qe_bd *bd;
> +	u16 swoffs, ucoffs, emptybds;
> +	u32 bdstatus, length;
> +
> +	udc = (struct qe_udc *)ep->udc;
> +	pframe = (struct qe_frame *)ep->rxframe;
> +
> +	if (ep->dir == USB_DIR_IN) {
> +		VDBG("error:This is a transmit ep!");
> +		return -EINVAL;
> +	}
> +
> +	bd = (struct qe_bd *)(ep->n_rxbd);
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	length = bdstatus & BD_LENGTH_MASK;
> +
> +	swoffs = (u16)(((u8 *)bd - (u8 *)ep->rxbase) >> 3);
> +	ucoffs = (u16)((in_be16(&udc->ep_param[ep->epnum]->rbptr) -
> +			in_be16(&udc->ep_param[ep->epnum]->rbase)) >> 3);
> +	if (swoffs < ucoffs)
> +		emptybds = USB_BDRING_LEN_RX - ucoffs + swoffs;
> +	else
> +		emptybds = swoffs - ucoffs;
> +
> +	if (emptybds < MIN_EMPTY_BDS) {
> +		qe_eprx_nack(ep);
> +		ep->localnack = 1;
> +		VDBG("The rx ep have a nack!%d", emptybds);
> +	}
> +	ep->has_data = USB_BDRING_LEN_RX - emptybds;
> +
> +	if (list_empty(&ep->queue)) {
> +		qe_eprx_nack(ep);
> +		VDBG("The rxep have noreq %d", ep->has_data);
> +		return 0;
> +	}
> +
> +	tasklet_schedule(&udc->rx_tasklet);
> +	ep->enable_tasklet = 1;
> +
> +	return 0;
> +}
> +
> +/* send data from a frame, no matter what tx_req */
> +static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame)
> +{
> +	struct qe_udc *udc = NULL;
> +
> +	struct qe_bd *bd = NULL;

Nulls, spurious empty line.

> +	u16 saveusbmr;
> +	u32 bdstatus, pidmask;
> +	u32 paddr;
> +
> +	udc = (struct qe_udc *)ep->udc;
> +
> +	if (ep->dir == USB_DIR_OUT) {
> +		VDBG("error:this is a receive ep!");
> +		return -EINVAL;
> +	}
> +
> +	/* Disable the Tx interrupt */
> +	saveusbmr = in_be16(&udc->usb_regs->usb_usbmr);
> +	out_be16(&udc->usb_regs->usb_usbmr,
> +			saveusbmr & ~(USB_E_TXB_MASK | USB_E_TXE_MASK));
> +
> +	bd = ep->n_txbd;
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +
> +	if (!(bdstatus & (T_R|BD_LENGTH_MASK))) {
> +		if (frame_get_length(frame) == 0) {
> +			frame_set_data(frame, udc->nullbuf);
> +			frame_set_length(frame, 2);
> +			frame->info |= (ZLP|NO_CRC);
> +			VDBG("the frame size = 0");
> +		}
> +		paddr = virt_to_phys((void *)frame->data);
> +		BD_BUFFER_SET(bd, paddr);
> +		bdstatus = (bdstatus&T_W);
> +		if (!(frame_get_info(frame) & NO_CRC))
> +			bdstatus |= T_R | T_I | T_L | T_TC
> +					| frame_get_length(frame);
> +		else
> +			bdstatus |= T_R | T_I | T_L | frame_get_length(frame);
> +
> +		/* if the packet is a ZLP in status phase */
> +		if ((ep->epnum == 0) && (udc->ep0_state == DATA_STATE_NEED_ZLP))
> +			ep->data01 = 0x1;
> +
> +		if (ep->data01) {
> +			pidmask = T_PID_DATA1;
> +			frame->info |= PID_DATA1;
> +		} else {
> +			pidmask = T_PID_DATA0;
> +			frame->info |= PID_DATA0;
> +		}
> +		bdstatus |= T_CNF;
> +		bdstatus |= pidmask;
> +		BD_STATUS_AND_LENGTH_SET(bd, bdstatus);
> +		qe_ep_filltxfifo(ep);
> +
> +		/* enable the TX interrupt */
> +		out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
> +
> +		qe_ep_toggledata01(ep);
> +		if (bdstatus & T_W)
> +			ep->n_txbd = ep->txbase;
> +		else
> +			ep->n_txbd++;
> +
> +		return 0;
> +	} else {
> +		out_be16(&udc->usb_regs->usb_usbmr, saveusbmr);
> +		VDBG("The tx bd is not ready!");
> +		return -EBUSY;
> +	}
> +}
> +
> +/* when an bd was transmitted, the function can *
> + * handle the tx_req, not include ep0           */
> +static int txcomplete(struct qe_ep *ep, unsigned char restart)
> +{
> +	struct qe_req *tx_req = NULL;
> +
> +	tx_req = ep->tx_req;
> +	if (tx_req != NULL) {
> +		if (!restart) {
> +			int asent = ep->last;
> +			ep->sent += asent;
> +			ep->last -= asent;
> +		} else {
> +			ep->last = 0;
> +		}
> +
> +		/* a request already were transmitted completely */
> +		if ((ep->tx_req->req.length - ep->sent) <= 0) {
> +			ep->tx_req->req.actual = (unsigned int)ep->sent;
> +			done(ep, ep->tx_req, 0);
> +			ep->tx_req = NULL;
> +			ep->last = 0;
> +			ep->sent = 0;
> +		}
> +	}
> +
> +	/* we should gain a new tx_req fot this endpoint */
> +	if (ep->tx_req == NULL) {
> +		if (!list_empty(&ep->queue)) {
> +			ep->tx_req = list_entry(ep->queue.next,	struct qe_req,
> +							queue);
> +			ep->last = 0;
> +			ep->sent = 0;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/* give a frame and a tx_req,send some data */
> +static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame)
> +{
> +	unsigned int size;
> +	u8 *buf;
> +
> +	qe_frame_clean(frame);
> +	size = min_t(u32, (ep->tx_req->req.length - ep->sent),
> +				ep->ep.maxpacket);
> +	buf = (u8 *)ep->tx_req->req.buf + ep->sent;
> +	if (buf && size) {
> +		ep->last = size;
> +		frame_set_data(frame, buf);
> +		frame_set_length(frame, size);
> +		frame_set_status(frame, FRAME_OK);
> +		frame_set_info(frame, 0);
> +		return qe_ep_tx(ep, frame);
> +	}
> +	return -EIO;
> +}
> +
> +/* give a frame struct,send a ZLP */
> +static int sendnulldata(struct qe_ep *ep, struct qe_frame *frame, uint infor)
> +{
> +	struct qe_udc *udc = ep->udc;
> +
> +	if (frame == NULL)
> +		return -ENODEV;
> +
> +	qe_frame_clean(frame);
> +	frame_set_data(frame, (u8 *)udc->nullbuf);
> +	frame_set_length(frame, 2);
> +	frame_set_status(frame, FRAME_OK);
> +	frame_set_info(frame, (ZLP|NO_CRC|infor));
> +
> +	return qe_ep_tx(ep, frame);
> +}
> +
> +static int frame_create_tx(struct qe_ep *ep, struct qe_frame *frame)
> +{
> +	struct qe_req *req;
> +	int reval;
> +	if (ep->tx_req == NULL)
> +		return -ENODEV;
> +
> +	req = ep->tx_req;
> +
> +	if ((req->req.length - ep->sent) > 0)
> +		reval = qe_usb_senddata(ep, frame);
> +	else
> +		reval = sendnulldata(ep, frame, 0);
> +
> +	return reval;
> +}
> +
> +/* if direction is DIR_IN, the status is Device->Host
> + * if direction is DIR_OUT, the status transaction is Device<-Host
> + * in status phase, udc create a request and gain status */
> +static int ep0_prime_status(struct qe_udc *udc, int direction)
> +{
> +
> +	struct qe_ep *ep = &udc->eps[0];
> +
> +	if (direction == USB_DIR_IN) {
> +		udc->ep0_state = DATA_STATE_NEED_ZLP;
> +		udc->ep0_dir = USB_DIR_IN;
> +		sendnulldata(ep, ep->txframe, SETUP_STATUS|NO_REQ);
> +	} else {
> +		udc->ep0_dir = USB_DIR_OUT;
> +		udc->ep0_state = WAIT_FOR_OUT_STATUS;
> +	}
> +
> +	return 0;
> +}
> +
> +/* a request complete in ep0, whether gadget request or udc request */
> +static void ep0_req_complete(struct qe_udc *udc, struct qe_req *req)
> +{
> +	struct qe_ep *ep = &(udc->eps[0]);
> +	/* because usb and ep's status already been set in ch9setaddress() */
> +
> +	switch (udc->ep0_state) {
> +	case DATA_STATE_XMIT:
> +		done(ep, req, 0);
> +		/* receive status phase */
> +		if (ep0_prime_status(udc, USB_DIR_OUT))
> +			qe_ep0_stall(udc);
> +		break;
> +
> +	case DATA_STATE_NEED_ZLP:
> +		done(ep, req, 0);
> +		udc->ep0_state = WAIT_FOR_SETUP;
> +		break;
> +
> +	case DATA_STATE_RECV:
> +		done(ep, req, 0);
> +		/* send status phase */
> +		if (ep0_prime_status(udc, USB_DIR_IN))
> +			qe_ep0_stall(udc);
> +		break;
> +
> +	case WAIT_FOR_OUT_STATUS:
> +		done(ep, req, 0);
> +		udc->ep0_state = WAIT_FOR_SETUP;
> +		break;
> +
> +	case WAIT_FOR_SETUP:
> +		VDBG("Unexpected interrupt");
> +		break;
> +
> +	default:
> +		qe_ep0_stall(udc);
> +		break;
> +	}
> +}
> +
> +static int ep0_txcomplete(struct qe_ep *ep, unsigned char restart)
> +{
> +	struct qe_req *tx_req = NULL;
> +	struct qe_frame *frame = ep->txframe;
> +
> +	if ((frame_get_info(frame)&(ZLP|NO_REQ)) == (ZLP|NO_REQ)) {
> +		if (!restart)
> +			ep->udc->ep0_state = WAIT_FOR_SETUP;
> +		else
> +			sendnulldata(ep, ep->txframe, SETUP_STATUS|NO_REQ);
> +		return 0;
> +	}
> +
> +	tx_req = ep->tx_req;
> +	if (tx_req != NULL) {
> +		if (!restart) {
> +			int asent = ep->last;
> +			ep->sent += asent;
> +			ep->last -= asent;
> +		} else {
> +			ep->last = 0;
> +		}
> +
> +		/* a request already were transmitted completely */
> +		if ((ep->tx_req->req.length - ep->sent) <= 0) {
> +			ep->tx_req->req.actual = (unsigned int)ep->sent;
> +			ep0_req_complete(ep->udc, ep->tx_req);
> +			ep->tx_req = NULL;
> +			ep->last = 0;
> +			ep->sent = 0;
> +		}
> +	} else {
> +		VDBG("the ep0_controller have no req");
> +	}
> +
> +	return 0;
> +}
> +
> +static int ep0_txframe_handle(struct qe_ep *ep)
> +{
> +	/* if have error, transmit again */
> +	if (frame_get_status(ep->txframe)&FRAME_ERROR) {
> +		qe_ep_flushtxfifo(ep);
> +		VDBG("The EP0 transmit data have error!");
> +		if (frame_get_info(ep->txframe)&PID_DATA0)
> +			ep->data01 = 0;
> +		else
> +			ep->data01 = 1;
> +
> +		ep0_txcomplete(ep, 1);
> +	} else
> +		ep0_txcomplete(ep, 0);
> +
> +	frame_create_tx(ep, ep->txframe);
> +	return 0;
> +}
> +
> +static int qe_ep0_txconf(struct qe_ep *ep)
> +{
> +	struct qe_bd *bd = NULL;
> +	struct qe_frame *pframe = NULL;
> +	u32 bdstatus;
> +
> +	bd = ep->c_txbd;
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
> +		pframe = ep->txframe;
> +
> +		/* clear and recycle the BD */
> +		BD_STATUS_AND_LENGTH_SET(bd, (bdstatus&T_W));
> +		BD_BUFFER_CLEAR(bd);
> +		if (bdstatus&T_W)
> +			ep->c_txbd = ep->txbase;
> +		else
> +			ep->c_txbd++;
> +
> +		if (ep->c_txbd == ep->n_txbd) {
> +			if (bdstatus & DEVICE_T_ERROR) {
> +				frame_set_status(pframe, FRAME_ERROR);
> +				if (bdstatus & T_TO)
> +					pframe->status |= TX_ER_TIMEOUT;
> +				if (bdstatus & T_UN)
> +					pframe->status |= TX_ER_UNDERUN;
> +			}
> +			ep0_txframe_handle(ep);
> +		}
> +
> +		bd = ep->c_txbd;
> +		bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ep_txframe_handle(struct qe_ep *ep)
> +{
> +	if (frame_get_status(ep->txframe)&FRAME_ERROR) {
> +		qe_ep_flushtxfifo(ep);
> +		VDBG("The EP0 transmit data have error!");
> +		if (frame_get_info(ep->txframe)&PID_DATA0)
> +			ep->data01 = 0;
> +		else
> +			ep->data01 = 1;
> +
> +		txcomplete(ep, 1);
> +	} else
> +		txcomplete(ep, 0);
> +
> +	frame_create_tx(ep, ep->txframe); /* send the data */
> +	return 0;
> +}
> +
> +/* confirm the already trainsmited bd */
> +static int qe_ep_txconf(struct qe_ep *ep)
> +{
> +	struct qe_bd *bd = NULL;
> +	struct qe_frame *pframe = NULL;
> +	u32 bdstatus;
> +	unsigned char breakonrxinterrupt = 0;
> +
> +	bd = ep->c_txbd;
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	while (!(bdstatus & T_R) && (bdstatus & ~T_W)) {
> +		pframe = ep->txframe;
> +		if (bdstatus & DEVICE_T_ERROR) {
> +			frame_set_status(pframe, FRAME_ERROR);
> +			if (bdstatus & T_TO)
> +				pframe->status |= TX_ER_TIMEOUT;
> +			if (bdstatus & T_UN)
> +				pframe->status |= TX_ER_UNDERUN;
> +		}
> +
> +		/* clear and recycle the BD */
> +		BD_STATUS_AND_LENGTH_SET(bd, (bdstatus&T_W));
> +		BD_BUFFER_CLEAR(bd);
> +		if (bdstatus&T_W)
> +			ep->c_txbd = ep->txbase;
> +		else
> +			ep->c_txbd++;
> +
> +		/* handle the tx frame */
> +		ep_txframe_handle(ep);
> +		bd = ep->c_txbd;
> +		bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	}
> +	if (breakonrxinterrupt)
> +		return -EIO;
> +	else
> +		return 0;
> +}
> +
> +/* Add a request in queue, and try to transmit a packet */
> +static int ep_req_send(struct qe_ep *ep, struct qe_req *req)
> +{
> +	int reval = 0;
> +
> +	if (ep->tx_req == NULL) {
> +		ep->sent = 0;
> +		ep->last = 0;
> +		txcomplete(ep, 0); /* can gain a new tx_req */
> +		reval = frame_create_tx(ep, ep->txframe);
> +	}
> +	return reval;
> +}
> +
> +/* Maybe this is a good ideal */
> +static int ep_req_rx(struct qe_ep *ep, struct qe_req *req)
> +{
> +	struct qe_udc *udc = NULL;
> +	struct qe_frame *pframe = NULL;
> +	struct qe_bd *bd;
> +	u32 bdstatus, length;
> +	u32 vaddr, fsize;
> +	u8 *cp;
> +	u8 finish_req = 0;
> +	u8 framepid;
> +
> +	if (list_empty(&ep->queue)) {
> +		VDBG("the req already finish!");
> +		return 0;
> +	}
> +	udc = (struct qe_udc *)ep->udc;
> +	pframe = (struct qe_frame *)ep->rxframe;
> +
> +	bd = (struct qe_bd *)(ep->n_rxbd);
> +	bdstatus = BD_STATUS_AND_LENGTH(bd);
> +	length = bdstatus & BD_LENGTH_MASK;
> +
> +	while (!(bdstatus&R_E) && length) {
> +		if (finish_req)
> +			break;
> +		if ((bdstatus & R_F) && (bdstatus & R_L)
> +					&& !(bdstatus & R_ERROR)) {
> +			qe_frame_clean(pframe);
> +			vaddr = (u32)phys_to_virt(BD_BUFFER(bd));
> +			frame_set_data(pframe, (u8 *)vaddr);
> +			frame_set_length(pframe, (length - USB_CRC_SIZE));
> +			frame_set_status(pframe, FRAME_OK);
> +			switch (bdstatus & R_PID) {
> +			case R_PID_DATA1:
> +				frame_set_info(pframe, PID_DATA1); break;
> +			default:
> +				frame_set_info(pframe, PID_DATA0); break;
> +			}
> +			/* handle the rx frame */
> +
> +			if (frame_get_info(pframe)&PID_DATA1)
> +				framepid = 0x1;
> +			else
> +				framepid = 0;
> +
> +			if (framepid != ep->data01) {
> +				VDBG("the data01 error!");
> +			} else {
> +				fsize = frame_get_length(pframe);
> +
> +				cp = (u8 *)(req->req.buf) + req->req.actual;
> +				if (cp) {
> +					memcpy(cp, pframe->data, fsize);
> +					req->req.actual += fsize;
> +					if ((fsize < ep->ep.maxpacket)
> +						|| (req->req.actual >=
> +							req->req.length)) {
> +						finish_req = 1;
> +						done(ep, req, 0);
> +						if (list_empty(&ep->queue))
> +							qe_eprx_nack(ep);
> +					}
> +				}
> +				qe_ep_toggledata01(ep);
> +			}
> +		} else {
> +			dev_err(udc->dev, "The receive frame with error!\n");
> +		}
> +
> +		/* note: don't clear the rxbd's buffer address *
> +		 * only Clear the length */
> +		BD_STATUS_AND_LENGTH_SET(bd, (bdstatus & BD_STATUS_MASK));
> +		ep->has_data--;
> +
> +		/* Get next BD */
> +		if (bdstatus & R_W)
> +			bd = ep->rxbase;
> +		else
> +			bd++;
> +
> +		bdstatus = BD_STATUS_AND_LENGTH(bd);
> +		length = bdstatus & BD_LENGTH_MASK;
> +	}
> +
> +	ep->n_rxbd = (struct qe_bd *)bd;
> +	ep_recycle_rxbds(ep);
> +
> +	return 0;
> +}
> +
> +/* only add the request in queue */
> +static int ep_req_receive(struct qe_ep *ep, struct qe_req *req)
> +{
> +	if (ep->state == EP_STATE_NACK) {
> +		if (ep->has_data <= 0) {
> +			/* Enable rx and unmask rx interrupt */
> +			qe_eprx_normal(ep);
> +		} else {
> +			/* Copy the exist BD data */
> +			ep_req_rx(ep, req);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/********************************************************************
> +	Internal Used Function End
> +********************************************************************/
> +
> +/*-----------------------------------------------------------------------
> +	Endpoint Management Functions For Gadget
> + -----------------------------------------------------------------------*/
> +static int qe_ep_enable(struct usb_ep *_ep,
> +			 const struct usb_endpoint_descriptor *desc)
> +{
> +	struct qe_udc *udc = NULL;
> +	struct qe_ep *ep = NULL;
> +	int retval = 0;
> +	unsigned char epnum;
> +	unsigned long flags = 0;
> +
> +	ep = container_of(_ep, struct qe_ep, ep);
> +
> +	/* catch various bogus parameters */
> +	if (!_ep || !desc || ep->desc || _ep->name == ep_name[0] ||
> +		(desc->bDescriptorType != USB_DT_ENDPOINT))
> +		/* FIXME: add judge for ep->bEndpointAddress */
> +		return -EINVAL;
> +
> +	udc = ep->udc;
> +	if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN))
> +		return -ESHUTDOWN;
> +
> +	epnum = (u8)desc->bEndpointAddress&0xF;
> +
> +	spin_lock_irqsave(&udc->lock, flags);
> +	retval = qe_ep_init((void *)udc, epnum, desc);
> +	spin_unlock_irqrestore(&udc->lock, flags);
> +	if (retval != 0) {
> +		qe_muram_free(muram_offset(ep->rxbase));
> +		VDBG("enable ep%d fail", ep->epnum);
> +		return -EINVAL;
> +	}
> +	VDBG("enable ep%d ok", ep->epnum);
> +	return 0;
> +}
> +
> +static int qe_ep_disable(struct usb_ep *_ep)
> +{
> +	struct qe_udc *udc = NULL;
> +	struct qe_ep *ep = NULL;
> +	unsigned long flags = 0;
> +	unsigned int size;
> +
> +	ep = container_of(_ep, struct qe_ep, ep);
> +
> +	if (!_ep || !ep->desc) {
> +		VDBG("%s not enabled", _ep ? ep->ep.name : NULL);
> +		return -EINVAL;
> +	}
> +
> +	udc = (struct qe_udc *) ep->udc;
> +
> +	spin_lock_irqsave(&udc->lock, flags);
> +	/* Nuke all pending requests (does flush) */
> +	nuke(ep, -ESHUTDOWN);
> +	ep->desc = NULL;
> +	ep->stopped = 1;
> +	spin_unlock_irqrestore(&udc->lock, flags);
> +
> +	qe_muram_free(muram_offset(ep->rxbase));
> +
> +	if (ep->dir == USB_DIR_OUT)
> +		size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
> +				(USB_BDRING_LEN_RX + 1);
> +	else
> +		size = (ep->ep.maxpacket + USB_CRC_SIZE + 2) *
> +				(USB_BDRING_LEN + 1);
> +
> +	if (ep->dir != USB_DIR_IN) {
> +		kfree(ep->rxframe);
> +		if (ep->rxbufmap) {
> +			dma_unmap_single(udc_controller->gadget.dev.parent,
> +					ep->rxbuf_d, size,
> +					DMA_FROM_DEVICE);
> +				ep->rxbuf_d = DMA_ADDR_INVALID;
> +		} else
> +			dma_sync_single_for_cpu(
> +					udc_controller->gadget.dev.parent,
> +					ep->rxbuf_d, size,
> +					DMA_FROM_DEVICE);
> +		kfree(ep->rxbuffer);
> +	}
> +
> +	if (ep->dir != USB_DIR_OUT)
> +		kfree(ep->txframe);
> +
> +	VDBG("disabled %s OK", _ep->name);
> +	return 0;
> +}
> +
> +static struct usb_request *qe_alloc_request(struct usb_ep *_ep,	gfp_t gfp_flags)
> +{
> +	struct qe_req *req = NULL;
> +
> +	req = kzalloc(sizeof *req, gfp_flags);

sizeof(*reg)

> +	if (!req)
> +		return NULL;
> +
> +	req->req.dma = DMA_ADDR_INVALID;
> +
> +	INIT_LIST_HEAD(&req->queue);
> +
> +	return &req->req;
> +}
> +
> +static void qe_free_request(struct usb_ep *_ep, struct usb_request *_req)
> +{
> +	struct qe_req *req = NULL;
> +
> +	req = container_of(_req, struct qe_req, req);
> +
> +	if (_req)
> +		kfree(req);
> +}
> +
> +/* queues (submits) an I/O request to an endpoint */
> +static int qe_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
> +				gfp_t gfp_flags)
> +{
> +	struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
> +	struct qe_req *req = container_of(_req, struct qe_req, req);
> +	struct qe_udc *udc;
> +	unsigned long flags;
> +	int reval;
> +
> +	/* catch various bogus parameters */
> +	if (!_req || !req->req.complete || !req->req.buf
> +	|| !list_empty(&req->queue)) {
> +		VDBG("bad params");
> +		return -EINVAL;
> +	}
> +	if (!_ep || (!ep->desc && ep_index(ep))) {
> +		VDBG("bad ep");
> +		return -EINVAL;
> +	}
> +
> +	udc = ep->udc;
> +	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
> +		return -ESHUTDOWN;
> +
> +	req->ep = ep;
> +
> +	/* map virtual address to hardware */
> +	if (req->req.dma == DMA_ADDR_INVALID) {
> +		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
> +					req->req.buf,
> +					req->req.length,
> +					ep_is_in(ep)
> +					? DMA_TO_DEVICE :
> +					DMA_FROM_DEVICE);
> +		req->mapped = 1;
> +	} else {
> +		dma_sync_single_for_device(ep->udc->gadget.dev.parent,
> +					req->req.dma, req->req.length,
> +					ep_is_in(ep)
> +					? DMA_TO_DEVICE :
> +					DMA_FROM_DEVICE);
> +		req->mapped = 0;
> +	}
> +
> +	req->req.status = -EINPROGRESS;
> +	req->req.actual = 0;
> +
> +	list_add_tail(&req->queue, &ep->queue);
> +	VDBG("gadget have request in %s! %d", ep->name, req->req.length);
> +	spin_lock_irqsave(&udc->lock, flags);
> +	/* push the request to device */
> +	if (ep_is_in(ep))
> +		reval = ep_req_send(ep, req);
> +
> +	/* EP0 */
> +	if (ep_index(ep) == 0 && req->req.length > 0) {
> +		if (ep_is_in(ep))
> +			udc->ep0_state = DATA_STATE_XMIT;
> +		else
> +			udc->ep0_state = DATA_STATE_RECV;
> +	}
> +
> +	if (ep->dir == USB_DIR_OUT)
> +		reval = ep_req_receive(ep, req);
> +
> +	spin_unlock_irqrestore(&udc->lock, flags);
> +
> +	return 0;
> +}
> +
> +/* dequeues (cancels, unlinks) an I/O request from an endpoint */
> +static int qe_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
> +{
> +	struct qe_ep *ep = container_of(_ep, struct qe_ep, ep);
> +	struct qe_req *req;
> +	unsigned long flags;
> +
> +	if (!_ep || !_req)
> +		return -EINVAL;
> +
> +	spin_lock_irqsave(&ep->udc->lock, flags);
> +
> +	/* make sure it's actually queued on this endpoint */
> +	list_for_each_entry(req, &ep->queue, queue) {
> +		if (&req->req == _req)
> +			break;
> +	}
> +
> +	if (&req->req != _req) {
> +		spin_unlock_irqrestore(&ep->udc->lock, flags);
> +		return -EINVAL;
> +	}
> +
> +	done(ep, req, -ECONNRESET);
> +
> +	spin_unlock_irqrestore(&ep->udc->lock, flags);
> +	return 0;
> +}
> +
> +/*-----------------------------------------------------------------
> + * modify the endpoint halt feature
> + * @ep: the non-isochronous endpoint being stalled
> + * @value: 1--set halt  0--clear halt
> + * Returns zero, or a negative error code.
> +*----------------------------------------------------------------*/
> +static int qe_ep_set_halt(struct usb_ep *_ep, int value)
> +{
> +	struct qe_ep *ep = NULL;
> +	unsigned long flags = 0;
> +	int status = -EOPNOTSUPP;
> +	struct qe_udc *udc = NULL;
> +
> +	ep = container_of(_ep, struct qe_ep, ep);
> +	udc = ep->udc;
> +	if (!_ep || !ep->desc) {
> +		status = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (ep->epnum != 0) {
> +		status = 0;
> +		goto out;
> +	}
> +
> +	/* Attempt to halt IN ep will fail if any transfer requests
> +	 * are still queue */
> +	if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
> +		status = -EAGAIN;
> +		goto out;
> +	}
> +
> +	status = 0;
> +	spin_lock_irqsave(&ep->udc->lock, flags);
> +	qe_eptx_stall_change(ep, value);
> +	qe_eprx_stall_change(ep, value);
> +	spin_unlock_irqrestore(&ep->udc->lock, flags);
> +
> +	if (ep->epnum == 0) {
> +		udc->ep0_state = WAIT_FOR_SETUP;
> +		udc->ep0_dir = 0;
> +	}
> +out:
> +	VDBG(" %s %s halt stat %d", ep->ep.name,
> +			value ?  "set" : "clear", status);
> +
> +	return status;
> +}
> +
> +static struct usb_ep_ops qe_ep_ops = {
> +	.enable = qe_ep_enable,
> +	.disable = qe_ep_disable,
> +
> +	.alloc_request = qe_alloc_request,
> +	.free_request = qe_free_request,
> +
> +	.queue = qe_ep_queue,
> +	.dequeue = qe_ep_dequeue,
> +
> +	.set_halt = qe_ep_set_halt,
> +};
> +
> +/*------------------------------------------------------------------------
> +	Gadget Driver Layer Operations
> + ------------------------------------------------------------------------*/
> +
> +/* Get the current frame number */
> +static int qe_get_frame(struct usb_gadget *gadget)
> +{
> +	u16 tmp;
> +
> +	tmp = in_be16(&udc_controller->usb_param->frame_n);
> +	if (tmp & 0x8000)
> +		tmp = tmp & 0x07ff;
> +	else
> +		tmp = -EINVAL;
> +
> +	return (int)tmp;
> +}
> +
> +/* Tries to wake up the host connected to this gadget
> + *
> + * Return : 0-success
> + * Negative-this feature not enabled by host or not supported by device hw
> + */
> +static int qe_wakeup(struct usb_gadget *gadget)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +/* Notify controller that VBUS is powered, Called by whatever
> +   detects VBUS sessions */
> +static int qe_vbus_session(struct usb_gadget *gadget, int is_active)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +/* constrain controller's VBUS power usage
> + * This call is used by gadget drivers during SET_CONFIGURATION calls,
> + * reporting how much power the device may consume.  For example, this
> + * could affect how quickly batteries are recharged.
> + *
> + * Returns zero on success, else negative errno.
> + */
> +static int qe_vbus_draw(struct usb_gadget *gadget, unsigned mA)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +/* Change Data+ pullup status
> + * this func is used by usb_gadget_connect/disconnet
> + */
> +static int qe_pullup(struct usb_gadget *gadget, int is_on)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +/* defined in usb_gadget.h */
> +static struct usb_gadget_ops qe_gadget_ops = {
> +	.get_frame = qe_get_frame,
> +	.wakeup = qe_wakeup,
> +/*	.set_selfpowered = qe_set_selfpowered,*/ /* always selfpowered */
> +	.vbus_session = qe_vbus_session,
> +	.vbus_draw = qe_vbus_draw,
> +	.pullup = qe_pullup,
> +};
> +
> +/*-------------------------------------------------------------------------
> +	USB ep0 Setup process in BUS Enumeration
> + -------------------------------------------------------------------------*/
> +static int udc_reset_ep_queue(struct qe_udc *udc, u8 pipe)
> +{
> +	struct qe_ep *ep = &udc->eps[pipe];
> +
> +	nuke(ep, -ECONNRESET);
> +	ep->tx_req = NULL;
> +	return 0;
> +}
> +
> +static int reset_queues(struct qe_udc *udc)
> +{
> +	u8 pipe;
> +
> +	for (pipe = 0; pipe < USB_MAX_ENDPOINTS; pipe++)
> +		udc_reset_ep_queue(udc, pipe);
> +
> +	/* report disconnect; the driver is already quiesced */
> +	udc->driver->disconnect(&udc->gadget);
> +
> +	return 0;
> +}
> +
> +static void ch9setaddress(struct qe_udc *udc, u16 value, u16 index,
> +			u16 length)
> +{
> +	/* Save the new address to device struct */
> +	udc->device_address = (u8) value;
> +	/* Update usb state */
> +	udc->usb_state = USB_STATE_ADDRESS;
> +
> +	/* Status phase , send a ZLP */
> +	if (ep0_prime_status(udc, USB_DIR_IN))
> +		qe_ep0_stall(udc);
> +}
> +
> +static void ownercomplete(struct usb_ep *_ep, struct usb_request *_req)
> +{
> +	struct qe_req *req = container_of(_req, struct qe_req, req);
> +
> +	req->req.buf = 0;
> +	kfree(req);
> +}
> +
> +static void ch9getstatus(struct qe_udc *udc, u16 value, u16 index,
> +			 u16 length)
> +{
> +	u16 usb_status = 0;	/* fix me to give correct status */
> +
> +	struct qe_req *req;
> +	struct qe_ep *ep;
> +	int status = 0;
> +
> +	ep = &udc->eps[0];
> +
> +	req = container_of(qe_alloc_request(&ep->ep, GFP_KERNEL),
> +					struct qe_req, req);
> +	req->req.length = 2;
> +	req->req.buf = udc->nullbuf;
> +	memcpy(req->req.buf, (u8 *)&usb_status, 2);
> +	req->req.status = -EINPROGRESS;
> +	req->req.actual = 0;
> +	req->req.complete = ownercomplete;
> +
> +	udc->ep0_dir = USB_DIR_IN;
> +
> +	/* data phase */
> +	status = qe_ep_queue(&(ep->ep), &(req->req), GFP_ATOMIC);
> +
> +	if (status) {
> +		dev_err(udc->dev, "Can't respond to getstatus request \n");
> +		qe_ep0_stall(udc);
> +	}
> +}
> +
> +/* only handle the setup request, suppose the device in normal status */
> +static void setup_received_handle(struct qe_udc *udc,
> +				struct usb_ctrlrequest *setup)
> +{
> +	/* Fix Endian (udc->local_setup_buff is cpu Endian now)*/
> +	u16 wValue = le16_to_cpu(setup->wValue);
> +	u16 wIndex = le16_to_cpu(setup->wIndex);
> +	u16 wLength = le16_to_cpu(setup->wLength);
> +
> +	/* clear the previous request in the ep0 */
> +	udc_reset_ep_queue(udc, 0);
> +
> +	if (setup->bRequestType & USB_DIR_IN)
> +		udc->ep0_dir = USB_DIR_IN;
> +	else
> +		udc->ep0_dir = USB_DIR_OUT;
> +
> +	switch (setup->bRequest) {
> +	case USB_REQ_GET_STATUS:
> +		/* Data+Status phase form udc */
> +		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
> +					!= (USB_DIR_IN | USB_TYPE_STANDARD))
> +			break;
> +		ch9getstatus(udc, wValue, wIndex, wLength);
> +		return;
> +
> +	case USB_REQ_SET_ADDRESS:
> +		/* Status phase from udc */
> +		if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
> +						USB_RECIP_DEVICE))
> +			break;
> +		ch9setaddress(udc, wValue, wIndex, wLength);
> +		return;
> +
> +	case USB_REQ_CLEAR_FEATURE:
> +	case USB_REQ_SET_FEATURE:
> +		/* Requests with no data phase, status phase from udc */
> +		if ((setup->bRequestType &  USB_TYPE_MASK)
> +					!= USB_TYPE_STANDARD)
> +			break;
> +
> +		if ((setup->bRequestType & USB_RECIP_MASK)
> +				== USB_RECIP_ENDPOINT) {
> +			int pipe = wIndex & USB_ENDPOINT_NUMBER_MASK;
> +			struct qe_ep *ep;
> +
> +			if (wValue != 0 || wLength != 0
> +				|| pipe > USB_MAX_ENDPOINTS)
> +				break;
> +			ep = &udc->eps[pipe];
> +
> +			spin_unlock(&udc->lock);
> +			qe_ep_set_halt(&ep->ep,
> +					(setup->bRequest == USB_REQ_SET_FEATURE)
> +						? 1 : 0);
> +			spin_lock(&udc->lock);
> +		}
> +
> +		ep0_prime_status(udc, USB_DIR_IN);
> +
> +		return;
> +
> +	default:
> +		break;
> +	}
> +
> +	if (wLength) {
> +		/* Data phase from gadget, status phase from udc */
> +		if (setup->bRequestType & USB_DIR_IN) {
> +			udc->ep0_state = DATA_STATE_XMIT;
> +			udc->ep0_dir = USB_DIR_IN;
> +		} else{
> +			udc->ep0_state = DATA_STATE_RECV;
> +			udc->ep0_dir = USB_DIR_OUT;
> +		}
> +		spin_unlock(&udc->lock);
> +		if (udc->driver->setup(&udc->gadget,
> +					&udc->local_setup_buff) < 0)
> +			qe_ep0_stall(udc);
> +		spin_lock(&udc->lock);
> +	} else {
> +		/* No data phase, IN status from gadget */
> +		udc->ep0_dir = USB_DIR_IN;
> +		spin_unlock(&udc->lock);
> +		if (udc->driver->setup(&udc->gadget,
> +					&udc->local_setup_buff) < 0)
> +			qe_ep0_stall(udc);
> +		spin_lock(&udc->lock);
> +		udc->ep0_state = DATA_STATE_NEED_ZLP;
> +	}
> +}
> +
> +/*-------------------------------------------------------------------------
> +	USB Interrupt handlers
> + -------------------------------------------------------------------------*/
> +static void suspend_irq(struct qe_udc *udc)
> +{
> +	udc->resume_state = udc->usb_state;
> +	udc->usb_state = USB_STATE_SUSPENDED;
> +
> +	/* report suspend to the driver ,serial.c not support this*/
> +	if (udc->driver->suspend)
> +		udc->driver->suspend(&udc->gadget);
> +}
> +
> +static void resume_irq(struct qe_udc *udc)
> +{
> +	udc->usb_state = udc->resume_state;
> +	udc->resume_state = 0;
> +
> +	/* report resume to the driver , serial.c not support this*/
> +	if (udc->driver->resume)
> +		udc->driver->resume(&udc->gadget);
> +}
> +
> +static void idle_irq(struct qe_udc *udc)
> +{
> +	u8 usbs;
> +
> +	usbs = in_8(&udc->usb_regs->usb_usbs);
> +	if (usbs & USB_IDLE_STATUS_MASK) {
> +		if ((udc->usb_state) != USB_STATE_SUSPENDED)
> +			suspend_irq(udc);
> +	} else {
> +		if (udc->usb_state == USB_STATE_SUSPENDED)
> +			resume_irq(udc);
> +	}
> +}
> +
> +static int reset_irq(struct qe_udc *udc)
> +{
> +	unsigned char i;
> +
> +	qe_usb_disable();
> +	out_8(&udc->usb_regs->usb_usadr, 0);
> +
> +	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
> +		if (udc->eps[i].init)
> +			qe_ep_reset(udc, i);
> +	}
> +
> +	reset_queues(udc);
> +	udc->usb_state = USB_STATE_DEFAULT;
> +	udc->ep0_state = WAIT_FOR_SETUP;
> +	udc->ep0_dir = USB_DIR_OUT;
> +	qe_usb_enable();
> +	return 0;
> +}
> +
> +static int bsy_irq(struct qe_udc *udc)
> +{
> +	return 0;
> +}
> +
> +static int txe_irq(struct qe_udc *udc)
> +{
> +	return 0;
> +}
> +
> +/* ep0 tx interrupt also in here */
> +static int tx_irq(struct qe_udc *udc)
> +{
> +	struct qe_ep *ep;
> +	int i, res = 0;
> +	struct qe_bd *bd;
> +
> +	if ((udc->usb_state == USB_STATE_ADDRESS)
> +		&& (in_8(&udc->usb_regs->usb_usadr) == 0))
> +		out_8(&udc->usb_regs->usb_usadr, udc->device_address);
> +
> +	for (i = (USB_MAX_ENDPOINTS-1); ((i >= 0) && (res == 0)); i--) {
> +		ep = &(udc->eps[i]);
> +		if (ep && ep->init && (ep->dir != USB_DIR_OUT)) {
> +			bd = ep->c_txbd;
> +			if (!(BD_STATUS_AND_LENGTH(bd)&T_R)
> +						&& (BD_BUFFER(bd))) {
> +				/* Disable the TX Interrupt */
> +				/*confirm the transmitted bd*/
> +				if (ep->epnum == 0)
> +					res = qe_ep0_txconf(ep);
> +				else
> +					res = qe_ep_txconf(ep);
> +				/* Enable the TX Interrupt */
> +			}
> +		}
> +	}
> +	return res;
> +}
> +
> +
> +/* setup packect's rx is handle in the function too */
> +static void rx_irq(struct qe_udc *udc)
> +{
> +	struct qe_ep *ep;
> +	int i;
> +	struct qe_bd *bd;
> +
> +	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
> +		ep = &(udc->eps[i]);
> +		if (ep && ep->init && (ep->dir != USB_DIR_IN)) {
> +			bd = ep->n_rxbd;
> +			if (!(BD_STATUS_AND_LENGTH(bd)&R_E)
> +						&& (BD_BUFFER(bd))) {
> +				if (ep->epnum == 0) {
> +					qe_ep0_rx(udc);
> +				} else {
> +					/*non-setup package receive*/
> +					qe_ep_rx(ep);
> +				}
> +			}
> +		}
> +	}
> +}
> +
> +static irqreturn_t qe_udc_irq(int irq, void *_udc)
> +{
> +	struct qe_udc *udc = (struct qe_udc *)_udc;
> +	u16 irq_src;
> +	irqreturn_t status = IRQ_NONE;
> +	unsigned long flags;
> +
> +
> +	spin_lock_irqsave(&udc->lock, flags);
> +
> +	irq_src = in_be16(&udc->usb_regs->usb_usber) &
> +		in_be16(&udc->usb_regs->usb_usbmr);
> +	/* Clear notification bits */
> +	out_be16(&udc->usb_regs->usb_usber, irq_src);
> +	/* USB Interrupt */
> +	if (irq_src & USB_E_IDLE_MASK) {
> +		idle_irq(udc);
> +		irq_src &= ~USB_E_IDLE_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	if (irq_src & USB_E_TXB_MASK) {
> +		tx_irq(udc);
> +		irq_src &= ~USB_E_TXB_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	if (irq_src & USB_E_RXB_MASK) {
> +		rx_irq(udc);
> +		irq_src &= ~USB_E_RXB_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	if (irq_src & USB_E_RESET_MASK) {
> +		reset_irq(udc);
> +		irq_src &= ~USB_E_RESET_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	if (irq_src & USB_E_BSY_MASK) {
> +		bsy_irq(udc);
> +		irq_src &= ~USB_E_BSY_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	if (irq_src & USB_E_TXE_MASK) {
> +		txe_irq(udc);
> +		irq_src &= ~USB_E_TXE_MASK;
> +		status = IRQ_HANDLED;
> +	}
> +
> +	spin_unlock_irqrestore(&udc->lock, flags);
> +
> +	return status;
> +}
> +
> +/*-------------------------------------------------------------------------
> +	Gadget driver register and unregister.
> + --------------------------------------------------------------------------*/
> +int usb_gadget_register_driver(struct usb_gadget_driver *driver)
> +{
> +	int retval;
> +	unsigned long flags = 0;
> +
> +	/* standard operations */
> +	if (!udc_controller)
> +		return -ENODEV;
> +
> +	if (!driver || (driver->speed != USB_SPEED_FULL
> +			&& driver->speed != USB_SPEED_HIGH)
> +			|| !driver->bind || !driver->unbind ||
> +			!driver->disconnect || !driver->setup)
> +		return -EINVAL;
> +
> +	if (udc_controller->driver)
> +		return -EBUSY;
> +
> +	/* lock is needed but whether should use this lock or another */
> +	spin_lock_irqsave(&udc_controller->lock, flags);
> +
> +	driver->driver.bus = 0;
> +	/* hook up the driver */
> +	udc_controller->driver = driver;
> +	udc_controller->gadget.dev.driver = &driver->driver;
> +	udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
> +	spin_unlock_irqrestore(&udc_controller->lock, flags);
> +
> +	retval = driver->bind(&udc_controller->gadget);
> +	if (retval) {
> +		dev_err(udc_controller->dev, "bind to %s --> %d",
> +				driver->driver.name, retval);
> +		udc_controller->gadget.dev.driver = 0;
> +		udc_controller->driver = 0;
> +		return retval;
> +	}
> +
> +	/* Enable IRQ reg and Set usbcmd reg EN bit */
> +	qe_usb_enable();
> +
> +	out_be16(&udc_controller->usb_regs->usb_usber, 0xffff);
> +	out_be16(&udc_controller->usb_regs->usb_usbmr, USB_E_DEFAULT_DEVICE);
> +	udc_controller->usb_state = USB_STATE_ATTACHED;
> +	udc_controller->ep0_state = WAIT_FOR_SETUP;
> +	udc_controller->ep0_dir = USB_DIR_OUT;
> +	dev_info(udc_controller->dev, "%s bind to driver %s \n",
> +		udc_controller->gadget.name, driver->driver.name);
> +	return 0;
> +}
> +EXPORT_SYMBOL(usb_gadget_register_driver);
> +
> +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
> +{
> +	struct qe_ep *loop_ep;
> +	unsigned long flags;
> +
> +	if (!udc_controller)
> +		return -ENODEV;
> +
> +	if (!driver || driver != udc_controller->driver)
> +		return -EINVAL;
> +
> +	/* stop usb controller, disable intr */
> +	qe_usb_disable();
> +
> +	/* in fact, no needed */
> +	udc_controller->usb_state = USB_STATE_ATTACHED;
> +	udc_controller->ep0_state = WAIT_FOR_SETUP;
> +	udc_controller->ep0_dir = 0;
> +
> +	/* stand operation */
> +	spin_lock_irqsave(&udc_controller->lock, flags);
> +	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
> +	nuke(&udc_controller->eps[0], -ESHUTDOWN);
> +	list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list,
> +				ep.ep_list)
> +		nuke(loop_ep, -ESHUTDOWN);
> +	spin_unlock_irqrestore(&udc_controller->lock, flags);
> +
> +	/* unbind gadget and unhook driver. */
> +	driver->unbind(&udc_controller->gadget);
> +	udc_controller->gadget.dev.driver = NULL;
> +	udc_controller->driver = NULL;
> +
> +	dev_info(udc_controller->dev, "unregistered gadget driver '%s'\r\n",
> +			driver->driver.name);
> +	return 0;
> +}
> +EXPORT_SYMBOL(usb_gadget_unregister_driver);
> +
> +/* udc structure's alloc and setup, include ep-param alloc */
> +static void *qe_udc_config(struct of_device *ofdev)
> +{
> +	struct qe_udc *udc = NULL;
> +	struct device_node *np = ofdev->node;
> +	unsigned int tmp_addr = 0;
> +	struct usb_device_para __iomem *usbpram = NULL;
> +	unsigned int i;
> +	u64 size;
> +	u32 offset;
> +	unsigned int nsize;
> +	const unsigned int *prop;
> +
> +	udc = kzalloc(sizeof(struct qe_udc), GFP_KERNEL);

sizeof(*udc)

> +	if (udc == NULL) {
> +		dev_err(&ofdev->dev, "malloc udc failed\n");
> +		goto cleanup;
> +	}
> +
> +	udc->dev = &ofdev->dev;
> +
> +	/* use the default address for the usb parameter */
> +	prop = of_get_property(np, "reg", &nsize);
> +	offset = of_read_number(prop + 2, 1);
> +	size = of_read_number(prop + 3, 1);
> +
> +	udc->usb_param = muram_addr(offset);
> +
> +	memset_io(udc->usb_param, 0, size);
> +
> +	usbpram = udc->usb_param;
> +
> +	out_be16(&usbpram->frame_n, 0);
> +	out_be32(&usbpram->rstate, 0);
> +
> +	tmp_addr = qe_muram_alloc((USB_MAX_ENDPOINTS *
> +					sizeof(struct usb_ep_para)),
> +					   USB_EP_PARA_ALIGNMENT);
> +
> +	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
> +		usbpram->epptr[i] = (u16)tmp_addr;
> +		udc->ep_param[i] = (struct usb_ep_para *)muram_addr(tmp_addr);
> +		tmp_addr += 32;
> +	}
> +
> +	memset_io(udc->ep_param[0], 0,
> +			USB_MAX_ENDPOINTS * sizeof(struct usb_ep_para));
> +
> +	udc->resume_state = USB_STATE_NOTATTACHED;
> +	udc->usb_state = USB_STATE_POWERED;
> +	udc->ep0_dir = 0;
> +
> +	/* initliaze the qe_udc lock */
> +	spin_lock_init(&udc->lock);
> +	return udc;
> +
> +cleanup:
> +	kfree(udc);
> +	return NULL;
> +}
> +
> +/* USB Controller register init */
> +static int qe_udc_reg_init(struct qe_udc *udc)
> +{
> +	struct usb_ctlr __iomem *qe_usbregs;
> +	qe_usbregs = udc->usb_regs;
> +
> +	/* Init the usb register */
> +	out_8(&qe_usbregs->usb_usmod, 0x01); /* FIXME if need enable in here */
> +	out_be16(&qe_usbregs->usb_usbmr, 0);
> +	out_8(&qe_usbregs->usb_uscom, 0);
> +	out_be16(&qe_usbregs->usb_usber, USBER_ALL_CLEAR);
> +
> +	return 0;
> +}
> +
> +static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
> +{
> +	struct qe_ep *ep = &(udc->eps[pipe_num]);
> +
> +	ep->udc = udc;
> +	strcpy(ep->name, ep_name[pipe_num]);
> +	ep->ep.name = ep_name[pipe_num];
> +
> +	ep->ep.ops = &qe_ep_ops;
> +	ep->stopped = 1;
> +	ep->ep.maxpacket = (unsigned short) ~0;
> +	ep->desc = NULL;
> +	ep->dir = 0xff;
> +	ep->epnum = (u8)pipe_num;
> +	ep->sent = 0;
> +	ep->last = 0;
> +	ep->init = 0;
> +	ep->rxframe = NULL;
> +	ep->txframe = NULL;
> +	ep->tx_req = NULL;
> +	ep->state = EP_STATE_IDLE;
> +	ep->has_data = 0;
> +
> +	/* the queue lists any req for this ep */
> +	INIT_LIST_HEAD(&ep->queue);
> +
> +	/* gagdet.ep_list used for ep_autoconfig so no ep0*/
> +	if (pipe_num != 0)
> +		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
> +
> +	ep->gadget = &udc->gadget;
> +
> +	return 0;
> +}
> +
> +/*-----------------------------------------------------------------------
> + *	UDC device Driver operation functions				*
> + *----------------------------------------------------------------------*/
> +static void qe_udc_release(struct device *dev)
> +{
> +	int i = 0;
> +
> +	complete(udc_controller->done);
> +	qe_muram_free(muram_offset(&udc_controller->ep_param[0]));
> +	for (i = 0; i < USB_MAX_ENDPOINTS; i++)
> +		udc_controller->ep_param[i] = NULL;
> +
> +	kfree(udc_controller);
> +	udc_controller = NULL;
> +}
> +
> +/* Driver probe functions */
> +static int qe_udc_probe(struct of_device *ofdev,
> +			const struct of_device_id *match)
> +{
> +	struct device_node *np = ofdev->node;
> +	unsigned int tmp_status = -ENODEV;
> +	unsigned int i;
> +
> +	/* Initialize the udc structure including QH member and other member */
> +	udc_controller = (struct qe_udc *)qe_udc_config(ofdev);

You don't need the cast here. But also it is good idea to change
return type of qe_udc_config() from void * to struct qe_udc *.

> +	if (!udc_controller) {
> +		VDBG("udc_controll is NULL");
> +		return -ENOMEM;
> +	}
> +
> +	udc_controller->usb_regs = of_iomap(np, 0);

Can't fail?

> +
> +	/* initialize usb hw reg except for regs for EP,
> +	 * leave usbintr reg untouched*/
> +	qe_udc_reg_init(udc_controller);
> +
> +	/* here comes the stand operations for probe
> +	 * set the qe_udc->gadget.xxx */
> +	udc_controller->gadget.ops = &qe_gadget_ops;
> +
> +	/* gadget.ep0 is a pointer */
> +	udc_controller->gadget.ep0 = &(udc_controller->eps[0].ep);

Parentheses.

> +
> +	INIT_LIST_HEAD(&udc_controller->gadget.ep_list);
> +
> +	/* modify in register gadget process */
> +	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;
> +
> +	/* name: Identifies the controller hardware type. */
> +	udc_controller->gadget.name = driver_name;
> +
> +	device_initialize(&udc_controller->gadget.dev);
> +
> +	strcpy(udc_controller->gadget.dev.bus_id, "gadget");
> +
> +	udc_controller->gadget.dev.release = qe_udc_release;
> +	udc_controller->gadget.dev.parent = &ofdev->dev;
> +
> +
> +	/* EP:intialization qe_ep struct */
> +	for (i = 0; i < USB_MAX_ENDPOINTS ; i++) {
> +		/*because the ep type isn't decide here so
> +		 * qe_ep_init() should be called in ep_enable() */
> +
> +		/* setup the qe_ep struct and link ep.ep.list
> +		 * into gadget.ep_list */
> +		qe_ep_config(udc_controller, (unsigned char)i);
> +	}
> +
> +	/* ep0 initialization in here */
> +	qe_ep_init(udc_controller, 0, &qe_ep0_desc);
> +
> +	/* create a buf for ZLP send */
> +	udc_controller->nullbuf = kzalloc(256, GFP_KERNEL);
> +	if (udc_controller->nullbuf == NULL) {
> +		VDBG("cannot alloc nullbuf");
> +		return -ENOMEM;
> +	}
> +
> +	udc_controller->nullp = virt_to_phys((void *)udc_controller->nullbuf);
> +	if (udc_controller->nullp == DMA_ADDR_INVALID) {
> +		udc_controller->nullp = dma_map_single(
> +					udc_controller->gadget.dev.parent,
> +					udc_controller->nullbuf,
> +					256,
> +					DMA_TO_DEVICE);
> +		udc_controller->nullmap = 1;
> +	} else {
> +		dma_sync_single_for_device(udc_controller->gadget.dev.parent,
> +					udc_controller->nullp, 256,
> +					DMA_TO_DEVICE);
> +		udc_controller->nullmap = 1;
> +	}
> +
> +	tasklet_init(&udc_controller->rx_tasklet, ep_rx_tasklet,
> +			(unsigned long)udc_controller);
> +	/* request irq and disable DR  */
> +	udc_controller->usb_irq = irq_of_parse_and_map(np, 0);
> +
> +	tmp_status = request_irq(udc_controller->usb_irq, qe_udc_irq, 0,
> +				driver_name, udc_controller);
> +	if (tmp_status != 0) {
> +		dev_err(udc_controller->dev, "cannot request irq %d err %d \n",
> +			udc_controller->usb_irq, tmp_status);
> +		return tmp_status;
> +	}
> +
> +	tmp_status = device_add(&udc_controller->gadget.dev);
> +	if (tmp_status != 0)
> +		return tmp_status;
> +
> +	dev_info(udc_controller->dev,
> +			"QE/CPM USB controller initialized as device\n");
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int qe_udc_suspend(struct of_device *dev, pm_message_t state)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +static int qe_udc_resume(struct of_device *dev)
> +{
> +	return -ENOTSUPP;
> +}
> +#endif
> +
> +static int qe_udc_remove(struct of_device *ofdev)
> +{
> +	struct qe_ep *ep = NULL;
> +	unsigned int size;
> +
> +	DECLARE_COMPLETION(done);
> +
> +	if (!udc_controller)
> +		return -ENODEV;
> +
> +	udc_controller->done = &done;
> +	tasklet_disable(&udc_controller->rx_tasklet);
> +
> +	if (udc_controller->nullmap) {
> +		dma_unmap_single(udc_controller->gadget.dev.parent,
> +			udc_controller->nullp, 256,
> +				DMA_TO_DEVICE);
> +			udc_controller->nullp = DMA_ADDR_INVALID;
> +	} else
> +		dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
> +			udc_controller->nullp, 256,
> +				DMA_TO_DEVICE);
> +	kfree(udc_controller->nullbuf);
> +
> +	ep = &(udc_controller->eps[0]);
> +	qe_muram_free(muram_offset(ep->rxbase));
> +	size = (ep->ep.maxpacket + USB_CRC_SIZE + 2)*(USB_BDRING_LEN + 1);
> +
> +	kfree(ep->rxframe);
> +	if (ep->rxbufmap) {
> +		dma_unmap_single(udc_controller->gadget.dev.parent,
> +				ep->rxbuf_d, size,
> +				DMA_FROM_DEVICE);
> +		ep->rxbuf_d = DMA_ADDR_INVALID;
> +	} else
> +		dma_sync_single_for_cpu(udc_controller->gadget.dev.parent,
> +				ep->rxbuf_d, size,
> +				DMA_FROM_DEVICE);
> +
> +	kfree(ep->rxbuffer);
> +	kfree(ep->txframe);
> +
> +	/* free irq */
> +	free_irq(udc_controller->usb_irq, udc_controller);
> +
> +	tasklet_kill(&udc_controller->rx_tasklet);
> +
> +	device_unregister(&udc_controller->gadget.dev);
> +	if (udc_controller != NULL)
> +		kfree(udc_controller);
> +
> +	/* free udc --wait for the release() finished */
> +	wait_for_completion(&done);
> +
> +	return 0;
> +}
> +
> +/*-------------------------------------------------------------------------*/
> +static struct of_device_id qe_udc_match[] = {
> +	{
> +		.compatible = "fsl,qe_udc",
> +	},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, qe_udc_match);
> +
> +static struct of_platform_driver udc_driver = {
> +	.name           = (char *) driver_name,
> +	.match_table    = qe_udc_match,
> +	.probe          = qe_udc_probe,
> +	.remove         = qe_udc_remove,
> +#ifdef CONFIG_PM
> +	.suspend        = qe_udc_suspend,
> +	.resume         = qe_udc_resume,
> +#endif
> +};
> +
> +static int __init qe_udc_init(void)
> +{
> +	printk(KERN_INFO "%s: %s, %s\n", driver_name, driver_desc,
> +			DRIVER_VERSION);
> +	return of_register_platform_driver(&udc_driver);
> +}
> +
> +static void __exit qe_udc_exit(void)
> +{
> +	of_unregister_platform_driver(&udc_driver);
> +}
> +
> +module_init(qe_udc_init);
> +module_exit(qe_udc_exit);
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_AUTHOR(DRIVER_AUTHOR);
> +MODULE_LICENSE("GPL");
> +
> diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h
> new file mode 100644
> index 0000000..8b333f9
> --- /dev/null
> +++ b/drivers/usb/gadget/fsl_qe_udc.h
> @@ -0,0 +1,458 @@
> +/*
> + * drivers/usb/gadget/qe_udc.h
> + *
> + * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Xiaobo Xie <X.Xie at freescale.com>
> + *
> + * Description:
> + * Freescale USB device/endpoint management registers
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +
> +#ifndef __FSL_QE_UDC_H
> +#define __FSL_QE_UDC_H
> +
> +#ifdef CONFIG_CPM2
> +extern unsigned long cpm2_immr;
> +
> +static inline void __iomem *muram_addr(unsigned long offset)
> +{
> +	return (void __iomem *)cpm2_immr + offset;
> +}
> +
> +static inline unsigned long muram_offset(void __iomem *addr)
> +{
> +	return addr - (void __iomem *)cpm2_immr;
> +}
> +#else
> +#define muram_addr	qe_muram_addr
> +#define muram_offset	qe_muram_offset
> +#endif

In the recent kernels we have both cpm_muram_addr and cpm_muram_offset.
No need to duplicate them.

> +
> +#define USB_MAX_ENDPOINTS               4
> +#define USB_MAX_PIPES                   USB_MAX_ENDPOINTS
> +#define USB_EP0_MAX_SIZE		64
> +#define USB_MAX_CTRL_PAYLOAD            0x4000
> +#define USB_BDRING_LEN			16
> +#define USB_BDRING_LEN_RX		256
> +#define USB_BDRING_LEN_TX		16
> +#define MIN_EMPTY_BDS			128
> +#define MAX_DATA_BDS			8
> +#define USB_CRC_SIZE			2
> +#define USB_DIR_BOTH			0x88
> +#define R_BUF_MAXSIZE			0x800
> +#define USB_EP_PARA_ALIGNMENT		32
> +
> +/* USB Mode Register bit define */
> +#define USB_MODE_EN		0x01
> +#define USB_MODE_HOST		0x02
> +#define USB_MODE_TEST		0x04
> +#define USB_MODE_SFTE		0x08
> +#define USB_MODE_RESUME		0x40
> +#define USB_MODE_LSS		0x80
> +
> +/* USB Slave Address Register Mask */
> +#define USB_SLVADDR_MASK	0x7F
> +
> +/* USB Endpoint register define */
> +#define USB_EPNUM_MASK		0xF000
> +#define USB_EPNUM_SHIFT		12
> +
> +#define USB_TRANS_MODE_SHIFT	8
> +#define USB_TRANS_CTR		0x0000
> +#define USB_TRANS_INT		0x0100
> +#define USB_TRANS_BULK		0x0200
> +#define USB_TRANS_ISO		0x0300
> +
> +#define USB_EP_MF		0x0020
> +#define USB_EP_RTE		0x0010
> +
> +#define USB_THS_SHIFT		2
> +#define USB_THS_MASK		0x000c
> +#define USB_THS_NORMAL		0x0
> +#define USB_THS_IGNORE_IN	0x0004
> +#define USB_THS_NACK		0x0008
> +#define USB_THS_STALL		0x000c
> +
> +#define USB_RHS_SHIFT   	0
> +#define USB_RHS_MASK		0x0003
> +#define USB_RHS_NORMAL  	0x0
> +#define USB_RHS_IGNORE_OUT	0x0001
> +#define USB_RHS_NACK		0x0002
> +#define USB_RHS_STALL		0x0003
> +
> +#define USB_RTHS_MASK		0x000f
> +
> +/* USB Command Register define */
> +#define USB_CMD_STR_FIFO	0x80
> +#define USB_CMD_FLUSH_FIFO	0x40
> +#define USB_CMD_ISFT		0x20
> +#define USB_CMD_DSFT		0x10
> +#define USB_CMD_EP_MASK		0x03
> +
> +/* USB Event and Mask Register define */
> +#define USB_E_MSF_MASK		0x0800
> +#define USB_E_SFT_MASK		0x0400
> +#define USB_E_RESET_MASK	0x0200
> +#define USB_E_IDLE_MASK		0x0100
> +#define USB_E_TXE4_MASK		0x0080
> +#define USB_E_TXE3_MASK		0x0040
> +#define USB_E_TXE2_MASK		0x0020
> +#define USB_E_TXE1_MASK		0x0010
> +#define USB_E_SOF_MASK		0x0008
> +#define USB_E_BSY_MASK		0x0004
> +#define USB_E_TXB_MASK		0x0002
> +#define USB_E_RXB_MASK		0x0001
> +#define USBER_ALL_CLEAR 	0x0fff
> +
> +#define USB_E_DEFAULT_DEVICE   (USB_E_RESET_MASK | USB_E_TXE4_MASK | \
> +				USB_E_TXE3_MASK | USB_E_TXE2_MASK | \
> +				USB_E_TXE1_MASK | USB_E_BSY_MASK | \
> +				USB_E_TXB_MASK | USB_E_RXB_MASK)
> +
> +#define USB_E_TXE_MASK         (USB_E_TXE4_MASK | USB_E_TXE3_MASK|\
> +				 USB_E_TXE2_MASK | USB_E_TXE1_MASK)
> +/* USB Status Register define */
> +#define USB_IDLE_STATUS_MASK	0x01
> +
> +/* USB Start of Frame Timer */
> +#define USB_USSFT_MASK		0x3FFF
> +
> +/* USB Frame Number Register */
> +#define USB_USFRN_MASK		0xFFFF
> +
> +struct usb_device_para{
> +	u16	epptr[4];
> +	u32	rstate;
> +	u32	rptr;
> +	u16	frame_n;
> +	u16	rbcnt;
> +	u32	rtemp;
> +	u32	rxusb_data;
> +	u16	rxuptr;
> +	u8	reso[2];
> +	u32	softbl;
> +	u8	sofucrctemp;
> +};
> +
> +struct usb_ep_para{
> +	u16	rbase;
> +	u16	tbase;
> +	u8	rbmr;
> +	u8	tbmr;
> +	u16	mrblr;
> +	u16	rbptr;
> +	u16	tbptr;
> +	u32	tstate;
> +	u32	tptr;
> +	u16	tcrc;
> +	u16	tbcnt;
> +	u32	ttemp;
> +	u16	txusbu_ptr;
> +	u8	reserve[2];
> +};
> +
> +#define USB_BUSMODE_GBL		0x20
> +#define USB_BUSMODE_BO_MASK	0x18
> +#define USB_BUSMODE_BO_SHIFT	0x3
> +#define USB_BUSMODE_BE		0x2
> +#define USB_BUSMODE_CETM	0x04
> +#define USB_BUSMODE_DTB		0x02
> +
> +/* Endpoint basic handle */
> +#define ep_index(EP)		((EP)->desc->bEndpointAddress&0xF)

Missing spaces around &, also..

> +#define ep_maxpacket(EP)	((EP)->ep.maxpacket)
> +#define ep_is_in(EP)	((ep_index(EP) == 0) ? (EP->udc->ep0_dir == \
> +			USB_DIR_IN):((EP)->desc->bEndpointAddress \
> +			& USB_DIR_IN) == USB_DIR_IN)

I'd turn this into static inlines. But since there are no casts,
this seems to be fine...

> +
> +/* ep0 transfer state */
> +#define WAIT_FOR_SETUP          0
> +#define DATA_STATE_XMIT         1
> +#define DATA_STATE_NEED_ZLP     2
> +#define WAIT_FOR_OUT_STATUS     3
> +#define DATA_STATE_RECV         4
> +
> +/* ep tramsfer mode */
> +#define USBP_TM_CTL	0
> +#define USBP_TM_ISO	1
> +#define USBP_TM_BULK	2
> +#define USBP_TM_INT	3
> +
> +/*-----------------------------------------------------------------------------
> +	USB RX And TX DATA Frame
> + -----------------------------------------------------------------------------*/
> +struct qe_frame{
> +	u8 *data;
> +	u32 len;
> +	u32 status;
> +	u32 info;
> +
> +	void *privdata;
> +	struct list_head node;
> +};
> +
> +/* Frame structure, info field. */
> +#define PID_DATA0              0x80000000 /* Data toggle zero */
> +#define PID_DATA1              0x40000000 /* Data toggle one  */
> +#define PID_SETUP              0x20000000 /* setup bit */
> +#define SETUP_STATUS           0x10000000 /* setup status bit */
> +#define SETADDR_STATUS         0x08000000 /* setupup address status bit */
> +#define NO_REQ                 0x04000000 /* Frame without request */
> +#define HOST_DATA              0x02000000 /* Host data frame */
> +#define FIRST_PACKET_IN_FRAME  0x01000000 /* first packet in the frame */
> +#define TOKEN_FRAME            0x00800000 /* Host token frame */
> +#define ZLP                    0x00400000 /* Zero length packet */
> +#define IN_TOKEN_FRAME         0x00200000 /* In token package */
> +#define OUT_TOKEN_FRAME        0x00100000 /* Out token package */
> +#define SETUP_TOKEN_FRAME      0x00080000 /* Setup token package */
> +#define STALL_FRAME            0x00040000 /* Stall handshake */
> +#define NACK_FRAME             0x00020000 /* Nack handshake */
> +#define NO_PID                 0x00010000 /* No send PID */
> +#define NO_CRC                 0x00008000 /* No send CRC */
> +#define HOST_COMMAND           0x00004000 /* Host command frame   */
> +
> +/* Frame status field */
> +/* Receive side */
> +#define FRAME_OK               0x00000000 /* Frame tranmitted or received OK */
> +#define FRAME_ERROR            0x80000000 /* Error occured on frame */
> +#define START_FRAME_LOST       0x40000000 /* START_FRAME_LOST */
> +#define END_FRAME_LOST         0x20000000 /* END_FRAME_LOST */
> +#define RX_ER_NONOCT           0x10000000 /* Rx Non Octet Aligned Packet */
> +#define RX_ER_BITSTUFF         0x08000000 /* Frame Aborted --Received packet
> +						with bit stuff error */
> +#define RX_ER_CRC              0x04000000 /* Received packet with CRC error */
> +#define RX_ER_OVERUN           0x02000000 /* Over-run occured on reception */
> +#define RX_ER_PID              0x01000000 /* Wrong PID received */
> +/* Tranmit side */
> +#define TX_ER_NAK              0x00800000 /* Received NAK handshake */
> +#define TX_ER_STALL            0x00400000 /* Received STALL handshake */
> +#define TX_ER_TIMEOUT          0x00200000 /* Transmit time out */
> +#define TX_ER_UNDERUN          0x00100000 /* Transmit underrun */
> +#define FRAME_INPROGRESS       0x00080000 /* Frame is being transmitted */
> +#define ER_DATA_UNDERUN        0x00040000 /* Frame is shorter then expected */
> +#define ER_DATA_OVERUN         0x00020000 /* Frame is longer then expected */
> +
> +/* QE USB frame operation functions */
> +#define frame_get_length(frm) (((struct qe_frame *)frm)->len)
> +#define frame_set_length(frm, leng) (((struct qe_frame *)frm)->len = leng)
> +#define frame_get_data(frm) (((struct qe_frame *)frm)->data)
> +#define frame_set_data(frm, dat) (((struct qe_frame *)frm)->data = dat)
> +#define frame_get_info(frm) (((struct qe_frame *)frm)->info)
> +#define frame_set_info(frm, inf) (((struct qe_frame *)frm)->info = inf)
> +#define frame_get_status(frm) (((struct qe_frame *)frm)->status)
> +#define frame_set_status(frm, stat) (((struct qe_frame *)frm)->status = stat)
> +#define frame_get_privdata(frm) (((struct qe_frame *)frm)->privdata)
> +#define frame_set_privdata(frm, dat) (((struct qe_frame *)frm)->privdata = dat)

Please turn these macros into `static inline' functions. The benefit of
using functions is type checking.

> +
> +#define qe_frame_clean(frm)                     \
> +	do {                                  \
> +		frame_set_data(frm, NULL);         \
> +		frame_set_length(frm, 0);          \
> +		frame_set_status(frm, FRAME_OK);   \
> +		frame_set_info(frm, 0);            \
> +		frame_set_privdata(frm, 0);        \
> +	} while (0)
> +
> +#define qe_frame_init(frm)                                   \
> +	do {                                               \
> +		qe_frame_clean(frm);                         \
> +		INIT_LIST_HEAD(&(((struct qe_frame *)frm)->node)); \
> +	} while (0)

Ditto.

> +struct qe_req {
> +	struct usb_request req;
> +	struct list_head queue;
> +	/* ep_queue() func will add
> +	 a request->queue into a udc_ep->queue 'd tail */
> +	struct qe_ep *ep;
> +	unsigned mapped:1;
> +};
> +
> +struct qe_ep {
> +	struct usb_ep ep;
> +	struct list_head queue;
> +	struct qe_udc *udc;
> +	const struct usb_endpoint_descriptor *desc;
> +	struct usb_gadget *gadget;
> +
> +	u8 state;
> +
> +	struct qe_bd *rxbase;
> +	struct qe_bd *n_rxbd;
> +	struct qe_bd *e_rxbd;
> +
> +	struct qe_bd *txbase;
> +	struct qe_bd *n_txbd;
> +	struct qe_bd *c_txbd;
> +
> +	struct qe_frame *rxframe;
> +	u8 *rxbuffer;
> +	dma_addr_t rxbuf_d;
> +	u8 rxbufmap;
> +	unsigned char localnack;
> +	int has_data;
> +
> +	struct qe_frame *txframe;
> +	struct qe_req *tx_req;
> +	int sent;  /*data already sent */
> +	int last;  /*data sent in the last time*/
> +
> +	u8 dir;
> +	u8 epnum;
> +	u8 tm; /* transfer mode */
> +	u8 data01;
> +	u8 init;
> +
> +	u8 already_seen;
> +	u8 enable_tasklet;
> +	u8 setup_stage;
> +	u32 last_io;            /* timestamp */
> +
> +	char name[14];
> +
> +	unsigned double_buf:1;
> +	unsigned stopped:1;
> +	unsigned fnf:1;
> +	unsigned has_dma:1;
> +
> +	u8 ackwait;
> +	u8 dma_channel;
> +	u16 dma_counter;
> +	int lch;
> +
> +	struct timer_list timer;
> +};
> +
> +struct qe_udc {
> +	struct usb_gadget gadget;
> +	struct usb_gadget_driver *driver;
> +	struct device *dev;
> +	struct qe_ep eps[USB_MAX_ENDPOINTS];
> +	struct usb_ctrlrequest local_setup_buff;
> +	spinlock_t lock;	/* lock for set/config qe_udc */
> +
> +	struct qe_req *status_req;     /* ep0 status request */
> +
> +	/* USB and EP Parameter Block pointer */
> +	struct usb_device_para __iomem *usb_param;
> +	struct usb_ep_para __iomem *ep_param[4];
> +
> +	u32 max_pipes;          /* Device max pipes */
> +	u32 max_use_endpts;     /* Max endpointes to be used */
> +	u32 bus_reset;          /* Device is bus reseting */
> +	u32 resume_state;       /* USB state to resume*/
> +	u32 usb_state;          /* USB current state */
> +	u32 usb_next_state;     /* USB next state */
> +	u32 ep0_state;          /* Enpoint zero state */
> +	u32 ep0_dir;            /* Enpoint zero direction: can be
> +				USB_DIR_IN or USB_DIR_OUT*/
> +	u32 usb_sof_count;      /* SOF count */
> +	u32 errors;             /* USB ERRORs count */
> +
> +	u8 *tmpbuf;
> +	u32 c_start;
> +	u32 c_end;
> +
> +	u8 *nullbuf;
> +	dma_addr_t nullp;
> +	u8 nullmap;
> +	u8 device_address;	/* Device USB address */
> +
> +	unsigned int usb_clock;
> +	unsigned int usb_irq;
> +	struct usb_ctlr __iomem *usb_regs;
> +
> +	struct tasklet_struct rx_tasklet;
> +
> +	struct completion *done;	/* to make sure release() is done */
> +};
> +
> +#define EP_STATE_IDLE	0
> +#define EP_STATE_NACK	1
> +#define EP_STATE_STALL	2
> +
> +/*---------------------------------------------------------------------
> + * 		Mask definitions for usb BD                           *
> + *--------------------------------------------------------------------*/
> +#define QE_SIZEOF_BD       sizeof(struct qe_bd)
> +
> +#define BD_BUFFER_ARG(bd)                   (((struct qe_bd *)bd)->buf)
> +#define BD_BUFFER_CLEAR(bd)                 out_be32(&(BD_BUFFER_ARG(bd)), 0);
> +#define BD_BUFFER(bd)                       in_be32(&(BD_BUFFER_ARG(bd)))
> +#define BD_STATUS_AND_LENGTH_SET(bd, val)   out_be32((u32 *)bd, val)
> +#define BD_STATUS_AND_LENGTH(bd)            in_be32((u32 *)bd)
> +#define BD_BUFFER_SET(bd, buffer)           out_be32(&(BD_BUFFER_ARG(bd)), \
> +							(u32)(buffer))
> +
> +/*
> + * transmit BD's status
> + */
> +#define T_R           0x80000000         /* ready bit */
> +#define T_W           0x20000000         /* wrap bit */
> +#define T_I           0x10000000         /* interrupt on completion */
> +#define T_L           0x08000000         /* last */
> +#define T_TC          0x04000000         /* transmit CRC */
> +#define T_CNF         0x02000000         /* wait for  transmit confirm */
> +#define T_LSP         0x01000000         /* Low-speed transaction */
> +#define T_PID         0x00c00000         /* packet id */
> +#define T_NAK         0x00100000         /* No ack. */
> +#define T_STAL        0x00080000         /* Stall recieved */
> +#define T_TO          0x00040000         /* time out */
> +#define T_UN          0x00020000         /* underrun */
> +
> +#define DEVICE_T_ERROR    (T_UN | T_TO)
> +#define HOST_T_ERROR      (T_UN | T_TO | T_NAK | T_STAL)
> +#define DEVICE_T_BD_MASK  DEVICE_T_ERROR
> +#define HOST_T_BD_MASK    HOST_T_ERROR
> +
> +#define T_PID_SHIFT   6
> +#define T_PID_DATA0   0x00800000         /* Data 0 toggle */
> +#define T_PID_DATA1   0x00c00000         /* Data 1 toggle */
> +
> +/*
> + * receive BD's status
> + */
> +#define R_E           0x80000000         /* buffer empty */
> +#define R_W           0x20000000         /* wrap bit */
> +#define R_I           0x10000000         /* interrupt on reception */
> +#define R_L           0x08000000         /* last */
> +#define R_F           0x04000000         /* first */
> +#define R_PID         0x00c00000         /* packet id */
> +#define R_NO          0x00100000         /* Rx Non Octet Aligned Packet */
> +#define R_AB          0x00080000         /* Frame Aborted */
> +#define R_CR          0x00040000         /* CRC Error */
> +#define R_OV          0x00020000         /* Overrun */
> +
> +#define R_ERROR       (R_NO | R_AB | R_CR | R_OV)
> +#define R_BD_MASK     R_ERROR
> +
> +#define R_PID_DATA0   0x00000000
> +#define R_PID_DATA1   0x00400000
> +#define R_PID_SETUP   0x00800000
> +
> +/* Bulk only class request */
> +#define USB_BULK_RESET_REQUEST          0xff
> +
> +extern int par_io_config_pin(u8  port, u8  pin, int dir, int open_drain,
> +				int assignment, int has_irq);
> +
> +#ifdef DEBUG
> +#define VDBG(fmt, args...)	printk(KERN_DEBUG "[%s]  " fmt "\n", \
> +				__func__, ## args)
> +#else
> +#define VDBG(fmt, args...)       do {} while (0)
> +#endif
> +
> +#define CPM_USB_STOP_TX 0x2e600000
> +#define CPM_USB_RESTART_TX 0x2e600000
> +#define CPM_USB_STOP_TX_OPCODE 0x0a
> +#define CPM_USB_RESTART_TX_OPCODE 0x0b
> +#define CPM_USB_EP_SHIFT 5
> +
> +#endif
> diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
> index 5246e8f..7e5be52 100644
> --- a/drivers/usb/gadget/gadget_chips.h
> +++ b/drivers/usb/gadget/gadget_chips.h
> @@ -147,6 +147,13 @@
>  #define	gadget_is_m66592(g)	0
>  #endif
>  
> +/* Freescale CPM/QE UDC SUPPORT */
> +#ifdef CONFIG_USB_GADGET_FSL_QE
> +#define gadget_is_fsl_qe(g)	!strcmp("fsl_qe_udc", (g)->name)
> +#else
> +#define gadget_is_fsl_qe(g)	0
> +#endif
> +
>  
>  // CONFIG_USB_GADGET_SX2
>  // CONFIG_USB_GADGET_AU1X00
> @@ -212,6 +219,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
>  		return 0x20;
>  	else if (gadget_is_m66592(gadget))
>  		return 0x21;
> +	else if (gadget_is_fsl_qe(gadget))
> +		return 0x22;
>  	return -ENOENT;
>  }
>  
> -- 
> 1.5.5.1.248.g4b17

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2



More information about the Linuxppc-dev mailing list