diff options
Diffstat (limited to 'drivers/usb/gadget')
| -rw-r--r-- | drivers/usb/gadget/Makefile | 8 | ||||
| -rw-r--r-- | drivers/usb/gadget/f_dfu.c | 43 | ||||
| -rw-r--r-- | drivers/usb/gadget/f_dfu.h | 2 | ||||
| -rw-r--r-- | drivers/usb/gadget/fotg210.c | 15 | 
4 files changed, 57 insertions, 11 deletions
| diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f52d3f450..f13b172a6 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,12 +5,8 @@  # SPDX-License-Identifier:	GPL-2.0+  # -# if defined(CONFIG_USB_GADGET) || defined(CONFIG_USB_ETHER) -#   Everytime you forget how crufty makefiles can get things like -#   this remind you... -ifneq (,$(CONFIG_USB_GADGET)$(CONFIG_USB_ETHER)) -obj-y += epautoconf.o config.o usbstring.o -endif +obj-$(CONFIG_USB_GADGET) += epautoconf.o config.o usbstring.o +obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o  # new USB gadget layer dependencies  ifdef CONFIG_USB_GADGET diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 37d04a192..a045864d7 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -40,6 +40,7 @@ struct f_dfu {  	/* Send/received block number is handy for data integrity check */  	int                             blk_seq_num; +	unsigned int                    poll_timeout;  };  typedef int (*dfu_state_fn) (struct f_dfu *, @@ -128,6 +129,33 @@ static struct usb_gadget_strings *dfu_strings[] = {  	NULL,  }; +static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms) +{ +	/* +	 * The bwPollTimeout DFU_GETSTATUS request payload provides information +	 * about minimum time, in milliseconds, that the host should wait before +	 * sending a subsequent DFU_GETSTATUS request +	 * +	 * This permits the device to vary the delay depending on its need to +	 * erase or program the memory +	 * +	 */ + +	unsigned char *p = (unsigned char *)&ms; + +	if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) { +		dstat->bwPollTimeout[0] = 0; +		dstat->bwPollTimeout[1] = 0; +		dstat->bwPollTimeout[2] = 0; + +		return; +	} + +	dstat->bwPollTimeout[0] = *p++; +	dstat->bwPollTimeout[1] = *p++; +	dstat->bwPollTimeout[2] = *p; +} +  /*-------------------------------------------------------------------------*/  static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) @@ -157,11 +185,15 @@ static void handle_getstatus(struct usb_request *req)  		break;  	} +	dfu_set_poll_timeout(dstat, 0); + +	if (f_dfu->poll_timeout) +		if (!(f_dfu->blk_seq_num % +		      (dfu_get_buf_size() / DFU_USB_BUFSIZ))) +			dfu_set_poll_timeout(dstat, f_dfu->poll_timeout); +  	/* send status response */  	dstat->bStatus = f_dfu->dfu_status; -	dstat->bwPollTimeout[0] = 0; -	dstat->bwPollTimeout[1] = 0; -	dstat->bwPollTimeout[2] = 0;  	dstat->bState = f_dfu->dfu_state;  	dstat->iString = 0;  } @@ -723,8 +755,9 @@ static int dfu_bind_config(struct usb_configuration *c)  	f_dfu->usb_function.unbind = dfu_unbind;  	f_dfu->usb_function.set_alt = dfu_set_alt;  	f_dfu->usb_function.disable = dfu_disable; -	f_dfu->usb_function.strings = dfu_generic_strings, -	f_dfu->usb_function.setup = dfu_handle, +	f_dfu->usb_function.strings = dfu_generic_strings; +	f_dfu->usb_function.setup = dfu_handle; +	f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT;  	status = usb_add_function(c, &f_dfu->usb_function);  	if (status) diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h index cc2c45567..0c29954ad 100644 --- a/drivers/usb/gadget/f_dfu.h +++ b/drivers/usb/gadget/f_dfu.h @@ -82,4 +82,6 @@ struct dfu_function_descriptor {  	__le16				wTransferSize;  	__le16				bcdDFUVersion;  } __packed; + +#define DFU_POLL_TIMEOUT_MASK           (0xFFFFFFUL)  #endif /* __F_DFU_H_ */ diff --git a/drivers/usb/gadget/fotg210.c b/drivers/usb/gadget/fotg210.c index 6e19db15f..3acf6a1f4 100644 --- a/drivers/usb/gadget/fotg210.c +++ b/drivers/usb/gadget/fotg210.c @@ -245,6 +245,7 @@ static int fotg210_dma(struct fotg210_ep *ep, struct fotg210_request *req)  		if (ep->id == 0) {  			/* Wait until cx/ep0 fifo empty */  			fotg210_cxwait(chip, CXFIFO_CXFIFOE); +			udelay(1);  			writel(DMAFIFO_CX, ®s->dma_fifo);  		} else {  			/* Wait until epx fifo empty */ @@ -847,6 +848,13 @@ int usb_gadget_handle_interrupts(void)  	/* CX interrupts */  	if (gisr & GISR_GRP0) {  		st = readl(®s->gisr0); +		/* +		 * Write 1 and then 0 works for both W1C & RW. +		 * +		 * HW v1.11.0+: It's a W1C register (write 1 clear) +		 * HW v1.10.0-: It's a R/W register (write 0 clear) +		 */ +		writel(st & GISR0_CXABORT, ®s->gisr0);  		writel(0, ®s->gisr0);  		if (st & GISR0_CXERR) @@ -873,6 +881,13 @@ int usb_gadget_handle_interrupts(void)  	/* Device Status Interrupts */  	if (gisr & GISR_GRP2) {  		st = readl(®s->gisr2); +		/* +		 * Write 1 and then 0 works for both W1C & RW. +		 * +		 * HW v1.11.0+: It's a W1C register (write 1 clear) +		 * HW v1.10.0-: It's a R/W register (write 0 clear) +		 */ +		writel(st, ®s->gisr2);  		writel(0, ®s->gisr2);  		if (st & GISR2_RESET) |