xref: /openbmc/linux/drivers/usb/host/max3421-hcd.c (revision 37aadc68)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
22d53139fSDavid Mosberger /*
32d53139fSDavid Mosberger  * MAX3421 Host Controller driver for USB.
42d53139fSDavid Mosberger  *
52d53139fSDavid Mosberger  * Author: David Mosberger-Tang <davidm@egauge.net>
62d53139fSDavid Mosberger  *
72d53139fSDavid Mosberger  * (C) Copyright 2014 David Mosberger-Tang <davidm@egauge.net>
82d53139fSDavid Mosberger  *
92d53139fSDavid Mosberger  * MAX3421 is a chip implementing a USB 2.0 Full-/Low-Speed host
102d53139fSDavid Mosberger  * controller on a SPI bus.
112d53139fSDavid Mosberger  *
122d53139fSDavid Mosberger  * Based on:
132d53139fSDavid Mosberger  *	o MAX3421E datasheet
14ffeb1e9eSAlexander A. Klimov  *		https://datasheets.maximintegrated.com/en/ds/MAX3421E.pdf
152d53139fSDavid Mosberger  *	o MAX3421E Programming Guide
16ffeb1e9eSAlexander A. Klimov  *		https://www.hdl.co.jp/ftpdata/utl-001/AN3785.pdf
172d53139fSDavid Mosberger  *	o gadget/dummy_hcd.c
182d53139fSDavid Mosberger  *		For USB HCD implementation.
192d53139fSDavid Mosberger  *	o Arduino MAX3421 driver
202d53139fSDavid Mosberger  *	     https://github.com/felis/USB_Host_Shield_2.0/blob/master/Usb.cpp
212d53139fSDavid Mosberger  *
222d53139fSDavid Mosberger  * This file is licenced under the GPL v2.
232d53139fSDavid Mosberger  *
242d53139fSDavid Mosberger  * Important note on worst-case (full-speed) packet size constraints
252d53139fSDavid Mosberger  * (See USB 2.0 Section 5.6.3 and following):
262d53139fSDavid Mosberger  *
272d53139fSDavid Mosberger  *	- control:	  64 bytes
282d53139fSDavid Mosberger  *	- isochronous:	1023 bytes
292d53139fSDavid Mosberger  *	- interrupt:	  64 bytes
302d53139fSDavid Mosberger  *	- bulk:		  64 bytes
312d53139fSDavid Mosberger  *
322d53139fSDavid Mosberger  * Since the MAX3421 FIFO size is 64 bytes, we do not have to work about
332d53139fSDavid Mosberger  * multi-FIFO writes/reads for a single USB packet *except* for isochronous
342d53139fSDavid Mosberger  * transfers.  We don't support isochronous transfers at this time, so we
352d53139fSDavid Mosberger  * just assume that a USB packet always fits into a single FIFO buffer.
362d53139fSDavid Mosberger  *
372d53139fSDavid Mosberger  * NOTE: The June 2006 version of "MAX3421E Programming Guide"
382d53139fSDavid Mosberger  * (AN3785) has conflicting info for the RCVDAVIRQ bit:
392d53139fSDavid Mosberger  *
402d53139fSDavid Mosberger  *	The description of RCVDAVIRQ says "The CPU *must* clear
412d53139fSDavid Mosberger  *	this IRQ bit (by writing a 1 to it) before reading the
422d53139fSDavid Mosberger  *	RCVFIFO data.
432d53139fSDavid Mosberger  *
442d53139fSDavid Mosberger  * However, the earlier section on "Programming BULK-IN
452d53139fSDavid Mosberger  * Transfers" says * that:
462d53139fSDavid Mosberger  *
472d53139fSDavid Mosberger  *	After the CPU retrieves the data, it clears the
482d53139fSDavid Mosberger  *	RCVDAVIRQ bit.
492d53139fSDavid Mosberger  *
502d53139fSDavid Mosberger  * The December 2006 version has been corrected and it consistently
512d53139fSDavid Mosberger  * states the second behavior is the correct one.
522d53139fSDavid Mosberger  *
532d53139fSDavid Mosberger  * Synchronous SPI transactions sleep so we can't perform any such
542d53139fSDavid Mosberger  * transactions while holding a spin-lock (and/or while interrupts are
552d53139fSDavid Mosberger  * masked).  To achieve this, all SPI transactions are issued from a
562d53139fSDavid Mosberger  * single thread (max3421_spi_thread).
572d53139fSDavid Mosberger  */
582d53139fSDavid Mosberger 
59788bfe88SAsaf Vertz #include <linux/jiffies.h>
602d53139fSDavid Mosberger #include <linux/module.h>
612d53139fSDavid Mosberger #include <linux/spi/spi.h>
622d53139fSDavid Mosberger #include <linux/usb.h>
632d53139fSDavid Mosberger #include <linux/usb/hcd.h>
64721fdc83SJules Maselbas #include <linux/of.h>
652d53139fSDavid Mosberger 
662d53139fSDavid Mosberger #include <linux/platform_data/max3421-hcd.h>
672d53139fSDavid Mosberger 
682d53139fSDavid Mosberger #define DRIVER_DESC	"MAX3421 USB Host-Controller Driver"
692d53139fSDavid Mosberger #define DRIVER_VERSION	"1.0"
702d53139fSDavid Mosberger 
712d53139fSDavid Mosberger /* 11-bit counter that wraps around (USB 2.0 Section 8.3.3): */
722d53139fSDavid Mosberger #define USB_MAX_FRAME_NUMBER	0x7ff
732d53139fSDavid Mosberger #define USB_MAX_RETRIES		3 /* # of retries before error is reported */
742d53139fSDavid Mosberger 
752d53139fSDavid Mosberger /*
762d53139fSDavid Mosberger  * Max. # of times we're willing to retransmit a request immediately in
772d53139fSDavid Mosberger  * resposne to a NAK.  Afterwards, we fall back on trying once a frame.
782d53139fSDavid Mosberger  */
792d53139fSDavid Mosberger #define NAK_MAX_FAST_RETRANSMITS	2
802d53139fSDavid Mosberger 
812d53139fSDavid Mosberger #define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
822d53139fSDavid Mosberger 
832d53139fSDavid Mosberger /* Port-change mask: */
842d53139fSDavid Mosberger #define PORT_C_MASK	((USB_PORT_STAT_C_CONNECTION |	\
852d53139fSDavid Mosberger 			  USB_PORT_STAT_C_ENABLE |	\
862d53139fSDavid Mosberger 			  USB_PORT_STAT_C_SUSPEND |	\
872d53139fSDavid Mosberger 			  USB_PORT_STAT_C_OVERCURRENT | \
882d53139fSDavid Mosberger 			  USB_PORT_STAT_C_RESET) << 16)
892d53139fSDavid Mosberger 
90721fdc83SJules Maselbas #define MAX3421_GPOUT_COUNT	8
91721fdc83SJules Maselbas 
922d53139fSDavid Mosberger enum max3421_rh_state {
932d53139fSDavid Mosberger 	MAX3421_RH_RESET,
942d53139fSDavid Mosberger 	MAX3421_RH_SUSPENDED,
952d53139fSDavid Mosberger 	MAX3421_RH_RUNNING
962d53139fSDavid Mosberger };
972d53139fSDavid Mosberger 
982d53139fSDavid Mosberger enum pkt_state {
992d53139fSDavid Mosberger 	PKT_STATE_SETUP,	/* waiting to send setup packet to ctrl pipe */
1002d53139fSDavid Mosberger 	PKT_STATE_TRANSFER,	/* waiting to xfer transfer_buffer */
1012d53139fSDavid Mosberger 	PKT_STATE_TERMINATE	/* waiting to terminate control transfer */
1022d53139fSDavid Mosberger };
1032d53139fSDavid Mosberger 
1042d53139fSDavid Mosberger enum scheduling_pass {
1052d53139fSDavid Mosberger 	SCHED_PASS_PERIODIC,
1062d53139fSDavid Mosberger 	SCHED_PASS_NON_PERIODIC,
1072d53139fSDavid Mosberger 	SCHED_PASS_DONE
1082d53139fSDavid Mosberger };
1092d53139fSDavid Mosberger 
1102eb5dbddSDavid Mosberger-Tang /* Bit numbers for max3421_hcd->todo: */
1112eb5dbddSDavid Mosberger-Tang enum {
1122eb5dbddSDavid Mosberger-Tang 	ENABLE_IRQ = 0,
1132eb5dbddSDavid Mosberger-Tang 	RESET_HCD,
1142eb5dbddSDavid Mosberger-Tang 	RESET_PORT,
1152eb5dbddSDavid Mosberger-Tang 	CHECK_UNLINK,
1162eb5dbddSDavid Mosberger-Tang 	IOPIN_UPDATE
1172eb5dbddSDavid Mosberger-Tang };
1182eb5dbddSDavid Mosberger-Tang 
11905dfa5c9SDavid Mosberger-Tang struct max3421_dma_buf {
12005dfa5c9SDavid Mosberger-Tang 	u8 data[2];
12105dfa5c9SDavid Mosberger-Tang };
12205dfa5c9SDavid Mosberger-Tang 
1232d53139fSDavid Mosberger struct max3421_hcd {
1242d53139fSDavid Mosberger 	spinlock_t lock;
1252d53139fSDavid Mosberger 
1262d53139fSDavid Mosberger 	struct task_struct *spi_thread;
1272d53139fSDavid Mosberger 
1282d53139fSDavid Mosberger 	struct max3421_hcd *next;
1292d53139fSDavid Mosberger 
1302d53139fSDavid Mosberger 	enum max3421_rh_state rh_state;
1312d53139fSDavid Mosberger 	/* lower 16 bits contain port status, upper 16 bits the change mask: */
1322d53139fSDavid Mosberger 	u32 port_status;
1332d53139fSDavid Mosberger 
1342d53139fSDavid Mosberger 	unsigned active:1;
1352d53139fSDavid Mosberger 
1362d53139fSDavid Mosberger 	struct list_head ep_list;	/* list of EP's with work */
1372d53139fSDavid Mosberger 
1382d53139fSDavid Mosberger 	/*
1392d53139fSDavid Mosberger 	 * The following are owned by spi_thread (may be accessed by
1402d53139fSDavid Mosberger 	 * SPI-thread without acquiring the HCD lock:
1412d53139fSDavid Mosberger 	 */
1422d53139fSDavid Mosberger 	u8 rev;				/* chip revision */
1432d53139fSDavid Mosberger 	u16 frame_number;
1442d53139fSDavid Mosberger 	/*
14505dfa5c9SDavid Mosberger-Tang 	 * kmalloc'd buffers guaranteed to be in separate (DMA)
14605dfa5c9SDavid Mosberger-Tang 	 * cache-lines:
14705dfa5c9SDavid Mosberger-Tang 	 */
14805dfa5c9SDavid Mosberger-Tang 	struct max3421_dma_buf *tx;
14905dfa5c9SDavid Mosberger-Tang 	struct max3421_dma_buf *rx;
15005dfa5c9SDavid Mosberger-Tang 	/*
1512d53139fSDavid Mosberger 	 * URB we're currently processing.  Must not be reset to NULL
1522d53139fSDavid Mosberger 	 * unless MAX3421E chip is idle:
1532d53139fSDavid Mosberger 	 */
1542d53139fSDavid Mosberger 	struct urb *curr_urb;
1552d53139fSDavid Mosberger 	enum scheduling_pass sched_pass;
1562d53139fSDavid Mosberger 	struct usb_device *loaded_dev;	/* dev that's loaded into the chip */
1572d53139fSDavid Mosberger 	int loaded_epnum;		/* epnum whose toggles are loaded */
1582d53139fSDavid Mosberger 	int urb_done;			/* > 0 -> no errors, < 0: errno */
1592d53139fSDavid Mosberger 	size_t curr_len;
1602d53139fSDavid Mosberger 	u8 hien;
1612d53139fSDavid Mosberger 	u8 mode;
1622d53139fSDavid Mosberger 	u8 iopins[2];
1632eb5dbddSDavid Mosberger-Tang 	unsigned long todo;
1642d53139fSDavid Mosberger #ifdef DEBUG
1652d53139fSDavid Mosberger 	unsigned long err_stat[16];
1662d53139fSDavid Mosberger #endif
1672d53139fSDavid Mosberger };
1682d53139fSDavid Mosberger 
1692d53139fSDavid Mosberger struct max3421_ep {
1702d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
1712d53139fSDavid Mosberger 	struct list_head ep_list;
1722d53139fSDavid Mosberger 	u32 naks;
1732d53139fSDavid Mosberger 	u16 last_active;		/* frame # this ep was last active */
1742d53139fSDavid Mosberger 	enum pkt_state pkt_state;
1752d53139fSDavid Mosberger 	u8 retries;
1762d53139fSDavid Mosberger 	u8 retransmit;			/* packet needs retransmission */
1772d53139fSDavid Mosberger };
1782d53139fSDavid Mosberger 
1792d53139fSDavid Mosberger static struct max3421_hcd *max3421_hcd_list;
1802d53139fSDavid Mosberger 
1812d53139fSDavid Mosberger #define MAX3421_FIFO_SIZE	64
1822d53139fSDavid Mosberger 
1832d53139fSDavid Mosberger #define MAX3421_SPI_DIR_RD	0	/* read register from MAX3421 */
1842d53139fSDavid Mosberger #define MAX3421_SPI_DIR_WR	1	/* write register to MAX3421 */
1852d53139fSDavid Mosberger 
1862d53139fSDavid Mosberger /* SPI commands: */
1872d53139fSDavid Mosberger #define MAX3421_SPI_DIR_SHIFT	1
1882d53139fSDavid Mosberger #define MAX3421_SPI_REG_SHIFT	3
1892d53139fSDavid Mosberger 
1902d53139fSDavid Mosberger #define MAX3421_REG_RCVFIFO	1
1912d53139fSDavid Mosberger #define MAX3421_REG_SNDFIFO	2
1922d53139fSDavid Mosberger #define MAX3421_REG_SUDFIFO	4
1932d53139fSDavid Mosberger #define MAX3421_REG_RCVBC	6
1942d53139fSDavid Mosberger #define MAX3421_REG_SNDBC	7
1952d53139fSDavid Mosberger #define MAX3421_REG_USBIRQ	13
1962d53139fSDavid Mosberger #define MAX3421_REG_USBIEN	14
1972d53139fSDavid Mosberger #define MAX3421_REG_USBCTL	15
1982d53139fSDavid Mosberger #define MAX3421_REG_CPUCTL	16
1992d53139fSDavid Mosberger #define MAX3421_REG_PINCTL	17
2002d53139fSDavid Mosberger #define MAX3421_REG_REVISION	18
2012d53139fSDavid Mosberger #define MAX3421_REG_IOPINS1	20
2022d53139fSDavid Mosberger #define MAX3421_REG_IOPINS2	21
2032d53139fSDavid Mosberger #define MAX3421_REG_GPINIRQ	22
2042d53139fSDavid Mosberger #define MAX3421_REG_GPINIEN	23
2052d53139fSDavid Mosberger #define MAX3421_REG_GPINPOL	24
2062d53139fSDavid Mosberger #define MAX3421_REG_HIRQ	25
2072d53139fSDavid Mosberger #define MAX3421_REG_HIEN	26
2082d53139fSDavid Mosberger #define MAX3421_REG_MODE	27
2092d53139fSDavid Mosberger #define MAX3421_REG_PERADDR	28
2102d53139fSDavid Mosberger #define MAX3421_REG_HCTL	29
2112d53139fSDavid Mosberger #define MAX3421_REG_HXFR	30
2122d53139fSDavid Mosberger #define MAX3421_REG_HRSL	31
2132d53139fSDavid Mosberger 
2142d53139fSDavid Mosberger enum {
2152d53139fSDavid Mosberger 	MAX3421_USBIRQ_OSCOKIRQ_BIT = 0,
2162d53139fSDavid Mosberger 	MAX3421_USBIRQ_NOVBUSIRQ_BIT = 5,
2172d53139fSDavid Mosberger 	MAX3421_USBIRQ_VBUSIRQ_BIT
2182d53139fSDavid Mosberger };
2192d53139fSDavid Mosberger 
2202d53139fSDavid Mosberger enum {
2212d53139fSDavid Mosberger 	MAX3421_CPUCTL_IE_BIT = 0,
2222d53139fSDavid Mosberger 	MAX3421_CPUCTL_PULSEWID0_BIT = 6,
2232d53139fSDavid Mosberger 	MAX3421_CPUCTL_PULSEWID1_BIT
2242d53139fSDavid Mosberger };
2252d53139fSDavid Mosberger 
2262d53139fSDavid Mosberger enum {
2272d53139fSDavid Mosberger 	MAX3421_USBCTL_PWRDOWN_BIT = 4,
2282d53139fSDavid Mosberger 	MAX3421_USBCTL_CHIPRES_BIT
2292d53139fSDavid Mosberger };
2302d53139fSDavid Mosberger 
2312d53139fSDavid Mosberger enum {
2322d53139fSDavid Mosberger 	MAX3421_PINCTL_GPXA_BIT	= 0,
2332d53139fSDavid Mosberger 	MAX3421_PINCTL_GPXB_BIT,
2342d53139fSDavid Mosberger 	MAX3421_PINCTL_POSINT_BIT,
2352d53139fSDavid Mosberger 	MAX3421_PINCTL_INTLEVEL_BIT,
2362d53139fSDavid Mosberger 	MAX3421_PINCTL_FDUPSPI_BIT,
2372d53139fSDavid Mosberger 	MAX3421_PINCTL_EP0INAK_BIT,
2382d53139fSDavid Mosberger 	MAX3421_PINCTL_EP2INAK_BIT,
2392d53139fSDavid Mosberger 	MAX3421_PINCTL_EP3INAK_BIT,
2402d53139fSDavid Mosberger };
2412d53139fSDavid Mosberger 
2422d53139fSDavid Mosberger enum {
2432d53139fSDavid Mosberger 	MAX3421_HI_BUSEVENT_BIT = 0,	/* bus-reset/-resume */
2442d53139fSDavid Mosberger 	MAX3421_HI_RWU_BIT,		/* remote wakeup */
2452d53139fSDavid Mosberger 	MAX3421_HI_RCVDAV_BIT,		/* receive FIFO data available */
2462d53139fSDavid Mosberger 	MAX3421_HI_SNDBAV_BIT,		/* send buffer available */
2472d53139fSDavid Mosberger 	MAX3421_HI_SUSDN_BIT,		/* suspend operation done */
2482d53139fSDavid Mosberger 	MAX3421_HI_CONDET_BIT,		/* peripheral connect/disconnect */
2492d53139fSDavid Mosberger 	MAX3421_HI_FRAME_BIT,		/* frame generator */
2502d53139fSDavid Mosberger 	MAX3421_HI_HXFRDN_BIT,		/* host transfer done */
2512d53139fSDavid Mosberger };
2522d53139fSDavid Mosberger 
2532d53139fSDavid Mosberger enum {
2542d53139fSDavid Mosberger 	MAX3421_HCTL_BUSRST_BIT = 0,
2552d53139fSDavid Mosberger 	MAX3421_HCTL_FRMRST_BIT,
2562d53139fSDavid Mosberger 	MAX3421_HCTL_SAMPLEBUS_BIT,
2572d53139fSDavid Mosberger 	MAX3421_HCTL_SIGRSM_BIT,
2582d53139fSDavid Mosberger 	MAX3421_HCTL_RCVTOG0_BIT,
2592d53139fSDavid Mosberger 	MAX3421_HCTL_RCVTOG1_BIT,
2602d53139fSDavid Mosberger 	MAX3421_HCTL_SNDTOG0_BIT,
2612d53139fSDavid Mosberger 	MAX3421_HCTL_SNDTOG1_BIT
2622d53139fSDavid Mosberger };
2632d53139fSDavid Mosberger 
2642d53139fSDavid Mosberger enum {
2652d53139fSDavid Mosberger 	MAX3421_MODE_HOST_BIT = 0,
2662d53139fSDavid Mosberger 	MAX3421_MODE_LOWSPEED_BIT,
2672d53139fSDavid Mosberger 	MAX3421_MODE_HUBPRE_BIT,
2682d53139fSDavid Mosberger 	MAX3421_MODE_SOFKAENAB_BIT,
2692d53139fSDavid Mosberger 	MAX3421_MODE_SEPIRQ_BIT,
2702d53139fSDavid Mosberger 	MAX3421_MODE_DELAYISO_BIT,
2712d53139fSDavid Mosberger 	MAX3421_MODE_DMPULLDN_BIT,
2722d53139fSDavid Mosberger 	MAX3421_MODE_DPPULLDN_BIT
2732d53139fSDavid Mosberger };
2742d53139fSDavid Mosberger 
2752d53139fSDavid Mosberger enum {
2762d53139fSDavid Mosberger 	MAX3421_HRSL_OK = 0,
2772d53139fSDavid Mosberger 	MAX3421_HRSL_BUSY,
2782d53139fSDavid Mosberger 	MAX3421_HRSL_BADREQ,
2792d53139fSDavid Mosberger 	MAX3421_HRSL_UNDEF,
2802d53139fSDavid Mosberger 	MAX3421_HRSL_NAK,
2812d53139fSDavid Mosberger 	MAX3421_HRSL_STALL,
2822d53139fSDavid Mosberger 	MAX3421_HRSL_TOGERR,
2832d53139fSDavid Mosberger 	MAX3421_HRSL_WRONGPID,
2842d53139fSDavid Mosberger 	MAX3421_HRSL_BADBC,
2852d53139fSDavid Mosberger 	MAX3421_HRSL_PIDERR,
2862d53139fSDavid Mosberger 	MAX3421_HRSL_PKTERR,
2872d53139fSDavid Mosberger 	MAX3421_HRSL_CRCERR,
2882d53139fSDavid Mosberger 	MAX3421_HRSL_KERR,
2892d53139fSDavid Mosberger 	MAX3421_HRSL_JERR,
2902d53139fSDavid Mosberger 	MAX3421_HRSL_TIMEOUT,
2912d53139fSDavid Mosberger 	MAX3421_HRSL_BABBLE,
2922d53139fSDavid Mosberger 	MAX3421_HRSL_RESULT_MASK = 0xf,
2932d53139fSDavid Mosberger 	MAX3421_HRSL_RCVTOGRD_BIT = 4,
2942d53139fSDavid Mosberger 	MAX3421_HRSL_SNDTOGRD_BIT,
2952d53139fSDavid Mosberger 	MAX3421_HRSL_KSTATUS_BIT,
2962d53139fSDavid Mosberger 	MAX3421_HRSL_JSTATUS_BIT
2972d53139fSDavid Mosberger };
2982d53139fSDavid Mosberger 
2992d53139fSDavid Mosberger /* Return same error-codes as ohci.h:cc_to_error: */
3002d53139fSDavid Mosberger static const int hrsl_to_error[] = {
3012d53139fSDavid Mosberger 	[MAX3421_HRSL_OK] =		0,
3022d53139fSDavid Mosberger 	[MAX3421_HRSL_BUSY] =		-EINVAL,
3032d53139fSDavid Mosberger 	[MAX3421_HRSL_BADREQ] =		-EINVAL,
3042d53139fSDavid Mosberger 	[MAX3421_HRSL_UNDEF] =		-EINVAL,
3052d53139fSDavid Mosberger 	[MAX3421_HRSL_NAK] =		-EAGAIN,
3062d53139fSDavid Mosberger 	[MAX3421_HRSL_STALL] =		-EPIPE,
3072d53139fSDavid Mosberger 	[MAX3421_HRSL_TOGERR] =		-EILSEQ,
3082d53139fSDavid Mosberger 	[MAX3421_HRSL_WRONGPID] =	-EPROTO,
3092d53139fSDavid Mosberger 	[MAX3421_HRSL_BADBC] =		-EREMOTEIO,
3102d53139fSDavid Mosberger 	[MAX3421_HRSL_PIDERR] =		-EPROTO,
3112d53139fSDavid Mosberger 	[MAX3421_HRSL_PKTERR] =		-EPROTO,
3122d53139fSDavid Mosberger 	[MAX3421_HRSL_CRCERR] =		-EILSEQ,
3132d53139fSDavid Mosberger 	[MAX3421_HRSL_KERR] =		-EIO,
3142d53139fSDavid Mosberger 	[MAX3421_HRSL_JERR] =		-EIO,
3152d53139fSDavid Mosberger 	[MAX3421_HRSL_TIMEOUT] =	-ETIME,
3162d53139fSDavid Mosberger 	[MAX3421_HRSL_BABBLE] =		-EOVERFLOW
3172d53139fSDavid Mosberger };
3182d53139fSDavid Mosberger 
3192d53139fSDavid Mosberger /*
320ffeb1e9eSAlexander A. Klimov  * See https://www.beyondlogic.org/usbnutshell/usb4.shtml#Control for a
3212d53139fSDavid Mosberger  * reasonable overview of how control transfers use the the IN/OUT
3222d53139fSDavid Mosberger  * tokens.
3232d53139fSDavid Mosberger  */
3242d53139fSDavid Mosberger #define MAX3421_HXFR_BULK_IN(ep)	(0x00 | (ep))	/* bulk or interrupt */
3252d53139fSDavid Mosberger #define MAX3421_HXFR_SETUP		 0x10
3262d53139fSDavid Mosberger #define MAX3421_HXFR_BULK_OUT(ep)	(0x20 | (ep))	/* bulk or interrupt */
3272d53139fSDavid Mosberger #define MAX3421_HXFR_ISO_IN(ep)		(0x40 | (ep))
3282d53139fSDavid Mosberger #define MAX3421_HXFR_ISO_OUT(ep)	(0x60 | (ep))
3292d53139fSDavid Mosberger #define MAX3421_HXFR_HS_IN		 0x80		/* handshake in */
3302d53139fSDavid Mosberger #define MAX3421_HXFR_HS_OUT		 0xa0		/* handshake out */
3312d53139fSDavid Mosberger 
3322d53139fSDavid Mosberger #define field(val, bit)	((val) << (bit))
3332d53139fSDavid Mosberger 
3342d53139fSDavid Mosberger static inline s16
3352d53139fSDavid Mosberger frame_diff(u16 left, u16 right)
3362d53139fSDavid Mosberger {
3372d53139fSDavid Mosberger 	return ((unsigned) (left - right)) % (USB_MAX_FRAME_NUMBER + 1);
3382d53139fSDavid Mosberger }
3392d53139fSDavid Mosberger 
3402d53139fSDavid Mosberger static inline struct max3421_hcd *
3412d53139fSDavid Mosberger hcd_to_max3421(struct usb_hcd *hcd)
3422d53139fSDavid Mosberger {
3432d53139fSDavid Mosberger 	return (struct max3421_hcd *) hcd->hcd_priv;
3442d53139fSDavid Mosberger }
3452d53139fSDavid Mosberger 
3462d53139fSDavid Mosberger static inline struct usb_hcd *
3472d53139fSDavid Mosberger max3421_to_hcd(struct max3421_hcd *max3421_hcd)
3482d53139fSDavid Mosberger {
3492d53139fSDavid Mosberger 	return container_of((void *) max3421_hcd, struct usb_hcd, hcd_priv);
3502d53139fSDavid Mosberger }
3512d53139fSDavid Mosberger 
3522d53139fSDavid Mosberger static u8
3532d53139fSDavid Mosberger spi_rd8(struct usb_hcd *hcd, unsigned int reg)
3542d53139fSDavid Mosberger {
35505dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
3562d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
3572d53139fSDavid Mosberger 	struct spi_transfer transfer;
3582d53139fSDavid Mosberger 	struct spi_message msg;
3592d53139fSDavid Mosberger 
3602d53139fSDavid Mosberger 	memset(&transfer, 0, sizeof(transfer));
3612d53139fSDavid Mosberger 
3622d53139fSDavid Mosberger 	spi_message_init(&msg);
3632d53139fSDavid Mosberger 
36405dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
36505dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
3662d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_RD, MAX3421_SPI_DIR_SHIFT));
3672d53139fSDavid Mosberger 
36805dfa5c9SDavid Mosberger-Tang 	transfer.tx_buf = max3421_hcd->tx->data;
36905dfa5c9SDavid Mosberger-Tang 	transfer.rx_buf = max3421_hcd->rx->data;
3702d53139fSDavid Mosberger 	transfer.len = 2;
3712d53139fSDavid Mosberger 
3722d53139fSDavid Mosberger 	spi_message_add_tail(&transfer, &msg);
3732d53139fSDavid Mosberger 	spi_sync(spi, &msg);
3742d53139fSDavid Mosberger 
37505dfa5c9SDavid Mosberger-Tang 	return max3421_hcd->rx->data[1];
3762d53139fSDavid Mosberger }
3772d53139fSDavid Mosberger 
3782d53139fSDavid Mosberger static void
3792d53139fSDavid Mosberger spi_wr8(struct usb_hcd *hcd, unsigned int reg, u8 val)
3802d53139fSDavid Mosberger {
3812d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
38205dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
3832d53139fSDavid Mosberger 	struct spi_transfer transfer;
3842d53139fSDavid Mosberger 	struct spi_message msg;
3852d53139fSDavid Mosberger 
3862d53139fSDavid Mosberger 	memset(&transfer, 0, sizeof(transfer));
3872d53139fSDavid Mosberger 
3882d53139fSDavid Mosberger 	spi_message_init(&msg);
3892d53139fSDavid Mosberger 
39005dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
39105dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
3922d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_WR, MAX3421_SPI_DIR_SHIFT));
39305dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[1] = val;
3942d53139fSDavid Mosberger 
39505dfa5c9SDavid Mosberger-Tang 	transfer.tx_buf = max3421_hcd->tx->data;
3962d53139fSDavid Mosberger 	transfer.len = 2;
3972d53139fSDavid Mosberger 
3982d53139fSDavid Mosberger 	spi_message_add_tail(&transfer, &msg);
3992d53139fSDavid Mosberger 	spi_sync(spi, &msg);
4002d53139fSDavid Mosberger }
4012d53139fSDavid Mosberger 
4022d53139fSDavid Mosberger static void
4032d53139fSDavid Mosberger spi_rd_buf(struct usb_hcd *hcd, unsigned int reg, void *buf, size_t len)
4042d53139fSDavid Mosberger {
4052d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
40605dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4072d53139fSDavid Mosberger 	struct spi_transfer transfer[2];
4082d53139fSDavid Mosberger 	struct spi_message msg;
4092d53139fSDavid Mosberger 
4102d53139fSDavid Mosberger 	memset(transfer, 0, sizeof(transfer));
4112d53139fSDavid Mosberger 
4122d53139fSDavid Mosberger 	spi_message_init(&msg);
4132d53139fSDavid Mosberger 
41405dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
41505dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
4162d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_RD, MAX3421_SPI_DIR_SHIFT));
41705dfa5c9SDavid Mosberger-Tang 	transfer[0].tx_buf = max3421_hcd->tx->data;
4182d53139fSDavid Mosberger 	transfer[0].len = 1;
4192d53139fSDavid Mosberger 
4202d53139fSDavid Mosberger 	transfer[1].rx_buf = buf;
4212d53139fSDavid Mosberger 	transfer[1].len = len;
4222d53139fSDavid Mosberger 
4232d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[0], &msg);
4242d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[1], &msg);
4252d53139fSDavid Mosberger 	spi_sync(spi, &msg);
4262d53139fSDavid Mosberger }
4272d53139fSDavid Mosberger 
4282d53139fSDavid Mosberger static void
4292d53139fSDavid Mosberger spi_wr_buf(struct usb_hcd *hcd, unsigned int reg, void *buf, size_t len)
4302d53139fSDavid Mosberger {
4312d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
43205dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4332d53139fSDavid Mosberger 	struct spi_transfer transfer[2];
4342d53139fSDavid Mosberger 	struct spi_message msg;
4352d53139fSDavid Mosberger 
4362d53139fSDavid Mosberger 	memset(transfer, 0, sizeof(transfer));
4372d53139fSDavid Mosberger 
4382d53139fSDavid Mosberger 	spi_message_init(&msg);
4392d53139fSDavid Mosberger 
44005dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
44105dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
4422d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_WR, MAX3421_SPI_DIR_SHIFT));
4432d53139fSDavid Mosberger 
44405dfa5c9SDavid Mosberger-Tang 	transfer[0].tx_buf = max3421_hcd->tx->data;
4452d53139fSDavid Mosberger 	transfer[0].len = 1;
4462d53139fSDavid Mosberger 
4472d53139fSDavid Mosberger 	transfer[1].tx_buf = buf;
4482d53139fSDavid Mosberger 	transfer[1].len = len;
4492d53139fSDavid Mosberger 
4502d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[0], &msg);
4512d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[1], &msg);
4522d53139fSDavid Mosberger 	spi_sync(spi, &msg);
4532d53139fSDavid Mosberger }
4542d53139fSDavid Mosberger 
4552d53139fSDavid Mosberger /*
4562d53139fSDavid Mosberger  * Figure out the correct setting for the LOWSPEED and HUBPRE mode
4572d53139fSDavid Mosberger  * bits.  The HUBPRE bit needs to be set when MAX3421E operates at
4582d53139fSDavid Mosberger  * full speed, but it's talking to a low-speed device (i.e., through a
4592d53139fSDavid Mosberger  * hub).  Setting that bit ensures that every low-speed packet is
4602d53139fSDavid Mosberger  * preceded by a full-speed PRE PID.  Possible configurations:
4612d53139fSDavid Mosberger  *
4622d53139fSDavid Mosberger  * Hub speed:	Device speed:	=>	LOWSPEED bit:	HUBPRE bit:
4632d53139fSDavid Mosberger  *	FULL	FULL		=>	0		0
4642d53139fSDavid Mosberger  *	FULL	LOW		=>	1		1
4652d53139fSDavid Mosberger  *	LOW	LOW		=>	1		0
4662d53139fSDavid Mosberger  *	LOW	FULL		=>	1		0
4672d53139fSDavid Mosberger  */
4682d53139fSDavid Mosberger static void
4692d53139fSDavid Mosberger max3421_set_speed(struct usb_hcd *hcd, struct usb_device *dev)
4702d53139fSDavid Mosberger {
4712d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4722d53139fSDavid Mosberger 	u8 mode_lowspeed, mode_hubpre, mode = max3421_hcd->mode;
4732d53139fSDavid Mosberger 
4742d53139fSDavid Mosberger 	mode_lowspeed = BIT(MAX3421_MODE_LOWSPEED_BIT);
4752d53139fSDavid Mosberger 	mode_hubpre   = BIT(MAX3421_MODE_HUBPRE_BIT);
4762d53139fSDavid Mosberger 	if (max3421_hcd->port_status & USB_PORT_STAT_LOW_SPEED) {
4772d53139fSDavid Mosberger 		mode |=  mode_lowspeed;
4782d53139fSDavid Mosberger 		mode &= ~mode_hubpre;
4792d53139fSDavid Mosberger 	} else if (dev->speed == USB_SPEED_LOW) {
4802d53139fSDavid Mosberger 		mode |= mode_lowspeed | mode_hubpre;
4812d53139fSDavid Mosberger 	} else {
4822d53139fSDavid Mosberger 		mode &= ~(mode_lowspeed | mode_hubpre);
4832d53139fSDavid Mosberger 	}
4842d53139fSDavid Mosberger 	if (mode != max3421_hcd->mode) {
4852d53139fSDavid Mosberger 		max3421_hcd->mode = mode;
4862d53139fSDavid Mosberger 		spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
4872d53139fSDavid Mosberger 	}
4882d53139fSDavid Mosberger 
4892d53139fSDavid Mosberger }
4902d53139fSDavid Mosberger 
4912d53139fSDavid Mosberger /*
4922d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
4932d53139fSDavid Mosberger  */
4942d53139fSDavid Mosberger static void
4952d53139fSDavid Mosberger max3421_set_address(struct usb_hcd *hcd, struct usb_device *dev, int epnum,
4962d53139fSDavid Mosberger 		    int force_toggles)
4972d53139fSDavid Mosberger {
4982d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4992d53139fSDavid Mosberger 	int old_epnum, same_ep, rcvtog, sndtog;
5002d53139fSDavid Mosberger 	struct usb_device *old_dev;
5012d53139fSDavid Mosberger 	u8 hctl;
5022d53139fSDavid Mosberger 
5032d53139fSDavid Mosberger 	old_dev = max3421_hcd->loaded_dev;
5042d53139fSDavid Mosberger 	old_epnum = max3421_hcd->loaded_epnum;
5052d53139fSDavid Mosberger 
5062d53139fSDavid Mosberger 	same_ep = (dev == old_dev && epnum == old_epnum);
5072d53139fSDavid Mosberger 	if (same_ep && !force_toggles)
5082d53139fSDavid Mosberger 		return;
5092d53139fSDavid Mosberger 
5102d53139fSDavid Mosberger 	if (old_dev && !same_ep) {
5112d53139fSDavid Mosberger 		/* save the old end-points toggles: */
5122d53139fSDavid Mosberger 		u8 hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
5132d53139fSDavid Mosberger 
5142d53139fSDavid Mosberger 		rcvtog = (hrsl >> MAX3421_HRSL_RCVTOGRD_BIT) & 1;
5152d53139fSDavid Mosberger 		sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
5162d53139fSDavid Mosberger 
5172d53139fSDavid Mosberger 		/* no locking: HCD (i.e., we) own toggles, don't we? */
5182d53139fSDavid Mosberger 		usb_settoggle(old_dev, old_epnum, 0, rcvtog);
5192d53139fSDavid Mosberger 		usb_settoggle(old_dev, old_epnum, 1, sndtog);
5202d53139fSDavid Mosberger 	}
5212d53139fSDavid Mosberger 	/* setup new endpoint's toggle bits: */
5222d53139fSDavid Mosberger 	rcvtog = usb_gettoggle(dev, epnum, 0);
5232d53139fSDavid Mosberger 	sndtog = usb_gettoggle(dev, epnum, 1);
5242d53139fSDavid Mosberger 	hctl = (BIT(rcvtog + MAX3421_HCTL_RCVTOG0_BIT) |
5252d53139fSDavid Mosberger 		BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT));
5262d53139fSDavid Mosberger 
5272d53139fSDavid Mosberger 	max3421_hcd->loaded_epnum = epnum;
5282d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, hctl);
5292d53139fSDavid Mosberger 
5302d53139fSDavid Mosberger 	/*
5312d53139fSDavid Mosberger 	 * Note: devnum for one and the same device can change during
5322d53139fSDavid Mosberger 	 * address-assignment so it's best to just always load the
5332d53139fSDavid Mosberger 	 * address whenever the end-point changed/was forced.
5342d53139fSDavid Mosberger 	 */
5352d53139fSDavid Mosberger 	max3421_hcd->loaded_dev = dev;
5362d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_PERADDR, dev->devnum);
5372d53139fSDavid Mosberger }
5382d53139fSDavid Mosberger 
5392d53139fSDavid Mosberger static int
5402d53139fSDavid Mosberger max3421_ctrl_setup(struct usb_hcd *hcd, struct urb *urb)
5412d53139fSDavid Mosberger {
5422d53139fSDavid Mosberger 	spi_wr_buf(hcd, MAX3421_REG_SUDFIFO, urb->setup_packet, 8);
5432d53139fSDavid Mosberger 	return MAX3421_HXFR_SETUP;
5442d53139fSDavid Mosberger }
5452d53139fSDavid Mosberger 
5462d53139fSDavid Mosberger static int
5472d53139fSDavid Mosberger max3421_transfer_in(struct usb_hcd *hcd, struct urb *urb)
5482d53139fSDavid Mosberger {
5492d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
5502d53139fSDavid Mosberger 	int epnum = usb_pipeendpoint(urb->pipe);
5512d53139fSDavid Mosberger 
5522d53139fSDavid Mosberger 	max3421_hcd->curr_len = 0;
5532d53139fSDavid Mosberger 	max3421_hcd->hien |= BIT(MAX3421_HI_RCVDAV_BIT);
5542d53139fSDavid Mosberger 	return MAX3421_HXFR_BULK_IN(epnum);
5552d53139fSDavid Mosberger }
5562d53139fSDavid Mosberger 
5572d53139fSDavid Mosberger static int
5582d53139fSDavid Mosberger max3421_transfer_out(struct usb_hcd *hcd, struct urb *urb, int fast_retransmit)
5592d53139fSDavid Mosberger {
5602d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
5612d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
5622d53139fSDavid Mosberger 	int epnum = usb_pipeendpoint(urb->pipe);
5632d53139fSDavid Mosberger 	u32 max_packet;
5642d53139fSDavid Mosberger 	void *src;
5652d53139fSDavid Mosberger 
5662d53139fSDavid Mosberger 	src = urb->transfer_buffer + urb->actual_length;
5672d53139fSDavid Mosberger 
5682d53139fSDavid Mosberger 	if (fast_retransmit) {
5692d53139fSDavid Mosberger 		if (max3421_hcd->rev == 0x12) {
5702d53139fSDavid Mosberger 			/* work around rev 0x12 bug: */
5712d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDBC, 0);
5722d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDFIFO, ((u8 *) src)[0]);
5732d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDBC, max3421_hcd->curr_len);
5742d53139fSDavid Mosberger 		}
5752d53139fSDavid Mosberger 		return MAX3421_HXFR_BULK_OUT(epnum);
5762d53139fSDavid Mosberger 	}
5772d53139fSDavid Mosberger 
5782d53139fSDavid Mosberger 	max_packet = usb_maxpacket(urb->dev, urb->pipe, 1);
5792d53139fSDavid Mosberger 
5802d53139fSDavid Mosberger 	if (max_packet > MAX3421_FIFO_SIZE) {
5812d53139fSDavid Mosberger 		/*
5822d53139fSDavid Mosberger 		 * We do not support isochronous transfers at this
5832d53139fSDavid Mosberger 		 * time.
5842d53139fSDavid Mosberger 		 */
5852d53139fSDavid Mosberger 		dev_err(&spi->dev,
5862d53139fSDavid Mosberger 			"%s: packet-size of %u too big (limit is %u bytes)",
5872d53139fSDavid Mosberger 			__func__, max_packet, MAX3421_FIFO_SIZE);
5882d53139fSDavid Mosberger 		max3421_hcd->urb_done = -EMSGSIZE;
5892d53139fSDavid Mosberger 		return -EMSGSIZE;
5902d53139fSDavid Mosberger 	}
5912d53139fSDavid Mosberger 	max3421_hcd->curr_len = min((urb->transfer_buffer_length -
5922d53139fSDavid Mosberger 				     urb->actual_length), max_packet);
5932d53139fSDavid Mosberger 
5942d53139fSDavid Mosberger 	spi_wr_buf(hcd, MAX3421_REG_SNDFIFO, src, max3421_hcd->curr_len);
5952d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_SNDBC, max3421_hcd->curr_len);
5962d53139fSDavid Mosberger 	return MAX3421_HXFR_BULK_OUT(epnum);
5972d53139fSDavid Mosberger }
5982d53139fSDavid Mosberger 
5992d53139fSDavid Mosberger /*
6002d53139fSDavid Mosberger  * Issue the next host-transfer command.
6012d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
6022d53139fSDavid Mosberger  */
6032d53139fSDavid Mosberger static void
6042d53139fSDavid Mosberger max3421_next_transfer(struct usb_hcd *hcd, int fast_retransmit)
6052d53139fSDavid Mosberger {
6062d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
6072d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
608f9da25c7SDavid Mosberger-Tang 	struct max3421_ep *max3421_ep;
6092d53139fSDavid Mosberger 	int cmd = -EINVAL;
6102d53139fSDavid Mosberger 
6112d53139fSDavid Mosberger 	if (!urb)
6122d53139fSDavid Mosberger 		return;	/* nothing to do */
6132d53139fSDavid Mosberger 
614f9da25c7SDavid Mosberger-Tang 	max3421_ep = urb->ep->hcpriv;
615f9da25c7SDavid Mosberger-Tang 
6162d53139fSDavid Mosberger 	switch (max3421_ep->pkt_state) {
6172d53139fSDavid Mosberger 	case PKT_STATE_SETUP:
6182d53139fSDavid Mosberger 		cmd = max3421_ctrl_setup(hcd, urb);
6192d53139fSDavid Mosberger 		break;
6202d53139fSDavid Mosberger 
6212d53139fSDavid Mosberger 	case PKT_STATE_TRANSFER:
6222d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
6232d53139fSDavid Mosberger 			cmd = max3421_transfer_in(hcd, urb);
6242d53139fSDavid Mosberger 		else
6252d53139fSDavid Mosberger 			cmd = max3421_transfer_out(hcd, urb, fast_retransmit);
6262d53139fSDavid Mosberger 		break;
6272d53139fSDavid Mosberger 
6282d53139fSDavid Mosberger 	case PKT_STATE_TERMINATE:
6292d53139fSDavid Mosberger 		/*
6302d53139fSDavid Mosberger 		 * IN transfers are terminated with HS_OUT token,
6312d53139fSDavid Mosberger 		 * OUT transfers with HS_IN:
6322d53139fSDavid Mosberger 		 */
6332d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
6342d53139fSDavid Mosberger 			cmd = MAX3421_HXFR_HS_OUT;
6352d53139fSDavid Mosberger 		else
6362d53139fSDavid Mosberger 			cmd = MAX3421_HXFR_HS_IN;
6372d53139fSDavid Mosberger 		break;
6382d53139fSDavid Mosberger 	}
6392d53139fSDavid Mosberger 
6402d53139fSDavid Mosberger 	if (cmd < 0)
6412d53139fSDavid Mosberger 		return;
6422d53139fSDavid Mosberger 
6432d53139fSDavid Mosberger 	/* issue the command and wait for host-xfer-done interrupt: */
6442d53139fSDavid Mosberger 
6452d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HXFR, cmd);
6462d53139fSDavid Mosberger 	max3421_hcd->hien |= BIT(MAX3421_HI_HXFRDN_BIT);
6472d53139fSDavid Mosberger }
6482d53139fSDavid Mosberger 
6492d53139fSDavid Mosberger /*
6502d53139fSDavid Mosberger  * Find the next URB to process and start its execution.
6512d53139fSDavid Mosberger  *
6522d53139fSDavid Mosberger  * At this time, we do not anticipate ever connecting a USB hub to the
6532d53139fSDavid Mosberger  * MAX3421 chip, so at most USB device can be connected and we can use
6542d53139fSDavid Mosberger  * a simplistic scheduler: at the start of a frame, schedule all
6552d53139fSDavid Mosberger  * periodic transfers.  Once that is done, use the remainder of the
6562d53139fSDavid Mosberger  * frame to process non-periodic (bulk & control) transfers.
6572d53139fSDavid Mosberger  *
6582d53139fSDavid Mosberger  * Preconditions:
6592d53139fSDavid Mosberger  * o Caller must NOT hold HCD spinlock.
6602d53139fSDavid Mosberger  * o max3421_hcd->curr_urb MUST BE NULL.
6612d53139fSDavid Mosberger  * o MAX3421E chip must be idle.
6622d53139fSDavid Mosberger  */
6632d53139fSDavid Mosberger static int
6642d53139fSDavid Mosberger max3421_select_and_start_urb(struct usb_hcd *hcd)
6652d53139fSDavid Mosberger {
6662d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
6672d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
6682d53139fSDavid Mosberger 	struct urb *urb, *curr_urb = NULL;
6692d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
6702d53139fSDavid Mosberger 	int epnum, force_toggles = 0;
6712d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
6722d53139fSDavid Mosberger 	struct list_head *pos;
6732d53139fSDavid Mosberger 	unsigned long flags;
6742d53139fSDavid Mosberger 
6752d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
6762d53139fSDavid Mosberger 
6772d53139fSDavid Mosberger 	for (;
6782d53139fSDavid Mosberger 	     max3421_hcd->sched_pass < SCHED_PASS_DONE;
6792d53139fSDavid Mosberger 	     ++max3421_hcd->sched_pass)
6802d53139fSDavid Mosberger 		list_for_each(pos, &max3421_hcd->ep_list) {
6812d53139fSDavid Mosberger 			urb = NULL;
6822d53139fSDavid Mosberger 			max3421_ep = container_of(pos, struct max3421_ep,
6832d53139fSDavid Mosberger 						  ep_list);
6842d53139fSDavid Mosberger 			ep = max3421_ep->ep;
6852d53139fSDavid Mosberger 
6862d53139fSDavid Mosberger 			switch (usb_endpoint_type(&ep->desc)) {
6872d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_ISOC:
6882d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_INT:
6892d53139fSDavid Mosberger 				if (max3421_hcd->sched_pass !=
6902d53139fSDavid Mosberger 				    SCHED_PASS_PERIODIC)
6912d53139fSDavid Mosberger 					continue;
6922d53139fSDavid Mosberger 				break;
6932d53139fSDavid Mosberger 
6942d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_CONTROL:
6952d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_BULK:
6962d53139fSDavid Mosberger 				if (max3421_hcd->sched_pass !=
6972d53139fSDavid Mosberger 				    SCHED_PASS_NON_PERIODIC)
6982d53139fSDavid Mosberger 					continue;
6992d53139fSDavid Mosberger 				break;
7002d53139fSDavid Mosberger 			}
7012d53139fSDavid Mosberger 
7022d53139fSDavid Mosberger 			if (list_empty(&ep->urb_list))
7032d53139fSDavid Mosberger 				continue;	/* nothing to do */
7042d53139fSDavid Mosberger 			urb = list_first_entry(&ep->urb_list, struct urb,
7052d53139fSDavid Mosberger 					       urb_list);
7062d53139fSDavid Mosberger 			if (urb->unlinked) {
7072d53139fSDavid Mosberger 				dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
7082d53139fSDavid Mosberger 					__func__, urb, urb->unlinked);
7092d53139fSDavid Mosberger 				max3421_hcd->curr_urb = urb;
7102d53139fSDavid Mosberger 				max3421_hcd->urb_done = 1;
7112d53139fSDavid Mosberger 				spin_unlock_irqrestore(&max3421_hcd->lock,
7122d53139fSDavid Mosberger 						       flags);
7132d53139fSDavid Mosberger 				return 1;
7142d53139fSDavid Mosberger 			}
7152d53139fSDavid Mosberger 
7162d53139fSDavid Mosberger 			switch (usb_endpoint_type(&ep->desc)) {
7172d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_CONTROL:
7182d53139fSDavid Mosberger 				/*
7192d53139fSDavid Mosberger 				 * Allow one control transaction per
7202d53139fSDavid Mosberger 				 * frame per endpoint:
7212d53139fSDavid Mosberger 				 */
7222d53139fSDavid Mosberger 				if (frame_diff(max3421_ep->last_active,
7232d53139fSDavid Mosberger 					       max3421_hcd->frame_number) == 0)
7242d53139fSDavid Mosberger 					continue;
7252d53139fSDavid Mosberger 				break;
7262d53139fSDavid Mosberger 
7272d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_BULK:
7282d53139fSDavid Mosberger 				if (max3421_ep->retransmit
7292d53139fSDavid Mosberger 				    && (frame_diff(max3421_ep->last_active,
7302d53139fSDavid Mosberger 						   max3421_hcd->frame_number)
7312d53139fSDavid Mosberger 					== 0))
7322d53139fSDavid Mosberger 					/*
7332d53139fSDavid Mosberger 					 * We already tried this EP
7342d53139fSDavid Mosberger 					 * during this frame and got a
7352d53139fSDavid Mosberger 					 * NAK or error; wait for next frame
7362d53139fSDavid Mosberger 					 */
7372d53139fSDavid Mosberger 					continue;
7382d53139fSDavid Mosberger 				break;
7392d53139fSDavid Mosberger 
7402d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_ISOC:
7412d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_INT:
7422d53139fSDavid Mosberger 				if (frame_diff(max3421_hcd->frame_number,
7432d53139fSDavid Mosberger 					       max3421_ep->last_active)
7442d53139fSDavid Mosberger 				    < urb->interval)
7452d53139fSDavid Mosberger 					/*
7462d53139fSDavid Mosberger 					 * We already processed this
7472d53139fSDavid Mosberger 					 * end-point in the current
7482d53139fSDavid Mosberger 					 * frame
7492d53139fSDavid Mosberger 					 */
7502d53139fSDavid Mosberger 					continue;
7512d53139fSDavid Mosberger 				break;
7522d53139fSDavid Mosberger 			}
7532d53139fSDavid Mosberger 
7542d53139fSDavid Mosberger 			/* move current ep to tail: */
7552d53139fSDavid Mosberger 			list_move_tail(pos, &max3421_hcd->ep_list);
7562d53139fSDavid Mosberger 			curr_urb = urb;
7572d53139fSDavid Mosberger 			goto done;
7582d53139fSDavid Mosberger 		}
7592d53139fSDavid Mosberger done:
7602d53139fSDavid Mosberger 	if (!curr_urb) {
7612d53139fSDavid Mosberger 		spin_unlock_irqrestore(&max3421_hcd->lock, flags);
7622d53139fSDavid Mosberger 		return 0;
7632d53139fSDavid Mosberger 	}
7642d53139fSDavid Mosberger 
7652d53139fSDavid Mosberger 	urb = max3421_hcd->curr_urb = curr_urb;
7662d53139fSDavid Mosberger 	epnum = usb_endpoint_num(&urb->ep->desc);
7672d53139fSDavid Mosberger 	if (max3421_ep->retransmit)
7682d53139fSDavid Mosberger 		/* restart (part of) a USB transaction: */
7692d53139fSDavid Mosberger 		max3421_ep->retransmit = 0;
7702d53139fSDavid Mosberger 	else {
7712d53139fSDavid Mosberger 		/* start USB transaction: */
7722d53139fSDavid Mosberger 		if (usb_endpoint_xfer_control(&ep->desc)) {
7732d53139fSDavid Mosberger 			/*
7742d53139fSDavid Mosberger 			 * See USB 2.0 spec section 8.6.1
7752d53139fSDavid Mosberger 			 * Initialization via SETUP Token:
7762d53139fSDavid Mosberger 			 */
7772d53139fSDavid Mosberger 			usb_settoggle(urb->dev, epnum, 0, 1);
7782d53139fSDavid Mosberger 			usb_settoggle(urb->dev, epnum, 1, 1);
7792d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_SETUP;
7802d53139fSDavid Mosberger 			force_toggles = 1;
7812d53139fSDavid Mosberger 		} else
7822d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TRANSFER;
7832d53139fSDavid Mosberger 	}
7842d53139fSDavid Mosberger 
7852d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
7862d53139fSDavid Mosberger 
7872d53139fSDavid Mosberger 	max3421_ep->last_active = max3421_hcd->frame_number;
7882d53139fSDavid Mosberger 	max3421_set_address(hcd, urb->dev, epnum, force_toggles);
7892d53139fSDavid Mosberger 	max3421_set_speed(hcd, urb->dev);
7902d53139fSDavid Mosberger 	max3421_next_transfer(hcd, 0);
7912d53139fSDavid Mosberger 	return 1;
7922d53139fSDavid Mosberger }
7932d53139fSDavid Mosberger 
7942d53139fSDavid Mosberger /*
7952d53139fSDavid Mosberger  * Check all endpoints for URBs that got unlinked.
7962d53139fSDavid Mosberger  *
7972d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
7982d53139fSDavid Mosberger  */
7992d53139fSDavid Mosberger static int
8002d53139fSDavid Mosberger max3421_check_unlink(struct usb_hcd *hcd)
8012d53139fSDavid Mosberger {
8022d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
8032d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8042d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
8052d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
806553c2360SGeliang Tang 	struct urb *urb, *next;
8072d53139fSDavid Mosberger 	unsigned long flags;
8082d53139fSDavid Mosberger 	int retval = 0;
8092d53139fSDavid Mosberger 
8102d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
811553c2360SGeliang Tang 	list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) {
8122d53139fSDavid Mosberger 		ep = max3421_ep->ep;
813553c2360SGeliang Tang 		list_for_each_entry_safe(urb, next, &ep->urb_list, urb_list) {
8142d53139fSDavid Mosberger 			if (urb->unlinked) {
8152d53139fSDavid Mosberger 				retval = 1;
8162d53139fSDavid Mosberger 				dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
8172d53139fSDavid Mosberger 					__func__, urb, urb->unlinked);
8182d53139fSDavid Mosberger 				usb_hcd_unlink_urb_from_ep(hcd, urb);
8192d53139fSDavid Mosberger 				spin_unlock_irqrestore(&max3421_hcd->lock,
8202d53139fSDavid Mosberger 						       flags);
8212d53139fSDavid Mosberger 				usb_hcd_giveback_urb(hcd, urb, 0);
8222d53139fSDavid Mosberger 				spin_lock_irqsave(&max3421_hcd->lock, flags);
8232d53139fSDavid Mosberger 			}
8242d53139fSDavid Mosberger 		}
8252d53139fSDavid Mosberger 	}
8262d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
8272d53139fSDavid Mosberger 	return retval;
8282d53139fSDavid Mosberger }
8292d53139fSDavid Mosberger 
8302d53139fSDavid Mosberger /*
8312d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
8322d53139fSDavid Mosberger  */
8332d53139fSDavid Mosberger static void
8342d53139fSDavid Mosberger max3421_slow_retransmit(struct usb_hcd *hcd)
8352d53139fSDavid Mosberger {
8362d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8372d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8382d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
8392d53139fSDavid Mosberger 
8402d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
8412d53139fSDavid Mosberger 	max3421_ep->retransmit = 1;
8422d53139fSDavid Mosberger 	max3421_hcd->curr_urb = NULL;
8432d53139fSDavid Mosberger }
8442d53139fSDavid Mosberger 
8452d53139fSDavid Mosberger /*
8462d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
8472d53139fSDavid Mosberger  */
8482d53139fSDavid Mosberger static void
8492d53139fSDavid Mosberger max3421_recv_data_available(struct usb_hcd *hcd)
8502d53139fSDavid Mosberger {
8512d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8522d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8532d53139fSDavid Mosberger 	size_t remaining, transfer_size;
8542d53139fSDavid Mosberger 	u8 rcvbc;
8552d53139fSDavid Mosberger 
8562d53139fSDavid Mosberger 	rcvbc = spi_rd8(hcd, MAX3421_REG_RCVBC);
8572d53139fSDavid Mosberger 
8582d53139fSDavid Mosberger 	if (rcvbc > MAX3421_FIFO_SIZE)
8592d53139fSDavid Mosberger 		rcvbc = MAX3421_FIFO_SIZE;
8602d53139fSDavid Mosberger 	if (urb->actual_length >= urb->transfer_buffer_length)
8612d53139fSDavid Mosberger 		remaining = 0;
8622d53139fSDavid Mosberger 	else
8632d53139fSDavid Mosberger 		remaining = urb->transfer_buffer_length - urb->actual_length;
8642d53139fSDavid Mosberger 	transfer_size = rcvbc;
8652d53139fSDavid Mosberger 	if (transfer_size > remaining)
8662d53139fSDavid Mosberger 		transfer_size = remaining;
8672d53139fSDavid Mosberger 	if (transfer_size > 0) {
8682d53139fSDavid Mosberger 		void *dst = urb->transfer_buffer + urb->actual_length;
8692d53139fSDavid Mosberger 
8702d53139fSDavid Mosberger 		spi_rd_buf(hcd, MAX3421_REG_RCVFIFO, dst, transfer_size);
8712d53139fSDavid Mosberger 		urb->actual_length += transfer_size;
8722d53139fSDavid Mosberger 		max3421_hcd->curr_len = transfer_size;
8732d53139fSDavid Mosberger 	}
8742d53139fSDavid Mosberger 
8752d53139fSDavid Mosberger 	/* ack the RCVDAV irq now that the FIFO has been read: */
8762d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIRQ, BIT(MAX3421_HI_RCVDAV_BIT));
8772d53139fSDavid Mosberger }
8782d53139fSDavid Mosberger 
8792d53139fSDavid Mosberger static void
8802d53139fSDavid Mosberger max3421_handle_error(struct usb_hcd *hcd, u8 hrsl)
8812d53139fSDavid Mosberger {
8822d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
8832d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8842d53139fSDavid Mosberger 	u8 result_code = hrsl & MAX3421_HRSL_RESULT_MASK;
8852d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8862d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep = urb->ep->hcpriv;
8872d53139fSDavid Mosberger 	int switch_sndfifo;
8882d53139fSDavid Mosberger 
8892d53139fSDavid Mosberger 	/*
8902d53139fSDavid Mosberger 	 * If an OUT command results in any response other than OK
8912d53139fSDavid Mosberger 	 * (i.e., error or NAK), we have to perform a dummy-write to
8922d53139fSDavid Mosberger 	 * SNDBC so the FIFO gets switched back to us.  Otherwise, we
8932d53139fSDavid Mosberger 	 * get out of sync with the SNDFIFO double buffer.
8942d53139fSDavid Mosberger 	 */
8952d53139fSDavid Mosberger 	switch_sndfifo = (max3421_ep->pkt_state == PKT_STATE_TRANSFER &&
8962d53139fSDavid Mosberger 			  usb_urb_dir_out(urb));
8972d53139fSDavid Mosberger 
8982d53139fSDavid Mosberger 	switch (result_code) {
8992d53139fSDavid Mosberger 	case MAX3421_HRSL_OK:
9002d53139fSDavid Mosberger 		return;			/* this shouldn't happen */
9012d53139fSDavid Mosberger 
9022d53139fSDavid Mosberger 	case MAX3421_HRSL_WRONGPID:	/* received wrong PID */
9032d53139fSDavid Mosberger 	case MAX3421_HRSL_BUSY:		/* SIE busy */
9042d53139fSDavid Mosberger 	case MAX3421_HRSL_BADREQ:	/* bad val in HXFR */
9052d53139fSDavid Mosberger 	case MAX3421_HRSL_UNDEF:	/* reserved */
9062d53139fSDavid Mosberger 	case MAX3421_HRSL_KERR:		/* K-state instead of response */
9072d53139fSDavid Mosberger 	case MAX3421_HRSL_JERR:		/* J-state instead of response */
9082d53139fSDavid Mosberger 		/*
9092d53139fSDavid Mosberger 		 * packet experienced an error that we cannot recover
9102d53139fSDavid Mosberger 		 * from; report error
9112d53139fSDavid Mosberger 		 */
9122d53139fSDavid Mosberger 		max3421_hcd->urb_done = hrsl_to_error[result_code];
9132d53139fSDavid Mosberger 		dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
9142d53139fSDavid Mosberger 			__func__, hrsl);
9152d53139fSDavid Mosberger 		break;
9162d53139fSDavid Mosberger 
9172d53139fSDavid Mosberger 	case MAX3421_HRSL_TOGERR:
9182d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
9192d53139fSDavid Mosberger 			; /* don't do anything (device will switch toggle) */
9202d53139fSDavid Mosberger 		else {
9212d53139fSDavid Mosberger 			/* flip the send toggle bit: */
9222d53139fSDavid Mosberger 			int sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
9232d53139fSDavid Mosberger 
9242d53139fSDavid Mosberger 			sndtog ^= 1;
9252d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HCTL,
9262d53139fSDavid Mosberger 				BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT));
9272d53139fSDavid Mosberger 		}
9280d9b6d49SGustavo A. R. Silva 		fallthrough;
9292d53139fSDavid Mosberger 	case MAX3421_HRSL_BADBC:	/* bad byte count */
9302d53139fSDavid Mosberger 	case MAX3421_HRSL_PIDERR:	/* received PID is corrupted */
9312d53139fSDavid Mosberger 	case MAX3421_HRSL_PKTERR:	/* packet error (stuff, EOP) */
9322d53139fSDavid Mosberger 	case MAX3421_HRSL_CRCERR:	/* CRC error */
9332d53139fSDavid Mosberger 	case MAX3421_HRSL_BABBLE:	/* device talked too long */
9342d53139fSDavid Mosberger 	case MAX3421_HRSL_TIMEOUT:
9352d53139fSDavid Mosberger 		if (max3421_ep->retries++ < USB_MAX_RETRIES)
9362d53139fSDavid Mosberger 			/* retry the packet again in the next frame */
9372d53139fSDavid Mosberger 			max3421_slow_retransmit(hcd);
9382d53139fSDavid Mosberger 		else {
9392d53139fSDavid Mosberger 			/* Based on ohci.h cc_to_err[]: */
9402d53139fSDavid Mosberger 			max3421_hcd->urb_done = hrsl_to_error[result_code];
9412d53139fSDavid Mosberger 			dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
9422d53139fSDavid Mosberger 				__func__, hrsl);
9432d53139fSDavid Mosberger 		}
9442d53139fSDavid Mosberger 		break;
9452d53139fSDavid Mosberger 
9462d53139fSDavid Mosberger 	case MAX3421_HRSL_STALL:
9472d53139fSDavid Mosberger 		dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
9482d53139fSDavid Mosberger 			__func__, hrsl);
9492d53139fSDavid Mosberger 		max3421_hcd->urb_done = hrsl_to_error[result_code];
9502d53139fSDavid Mosberger 		break;
9512d53139fSDavid Mosberger 
9522d53139fSDavid Mosberger 	case MAX3421_HRSL_NAK:
9532d53139fSDavid Mosberger 		/*
9542d53139fSDavid Mosberger 		 * Device wasn't ready for data or has no data
9552d53139fSDavid Mosberger 		 * available: retry the packet again.
9562d53139fSDavid Mosberger 		 */
9572d53139fSDavid Mosberger 		if (max3421_ep->naks++ < NAK_MAX_FAST_RETRANSMITS) {
9582d53139fSDavid Mosberger 			max3421_next_transfer(hcd, 1);
9592d53139fSDavid Mosberger 			switch_sndfifo = 0;
9602d53139fSDavid Mosberger 		} else
9612d53139fSDavid Mosberger 			max3421_slow_retransmit(hcd);
9622d53139fSDavid Mosberger 		break;
9632d53139fSDavid Mosberger 	}
9642d53139fSDavid Mosberger 	if (switch_sndfifo)
9652d53139fSDavid Mosberger 		spi_wr8(hcd, MAX3421_REG_SNDBC, 0);
9662d53139fSDavid Mosberger }
9672d53139fSDavid Mosberger 
9682d53139fSDavid Mosberger /*
9692d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
9702d53139fSDavid Mosberger  */
9712d53139fSDavid Mosberger static int
9722d53139fSDavid Mosberger max3421_transfer_in_done(struct usb_hcd *hcd, struct urb *urb)
9732d53139fSDavid Mosberger {
9742d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
9752d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
9762d53139fSDavid Mosberger 	u32 max_packet;
9772d53139fSDavid Mosberger 
9782d53139fSDavid Mosberger 	if (urb->actual_length >= urb->transfer_buffer_length)
9792d53139fSDavid Mosberger 		return 1;	/* read is complete, so we're done */
9802d53139fSDavid Mosberger 
9812d53139fSDavid Mosberger 	/*
9822d53139fSDavid Mosberger 	 * USB 2.0 Section 5.3.2 Pipes: packets must be full size
9832d53139fSDavid Mosberger 	 * except for last one.
9842d53139fSDavid Mosberger 	 */
9852d53139fSDavid Mosberger 	max_packet = usb_maxpacket(urb->dev, urb->pipe, 0);
9862d53139fSDavid Mosberger 	if (max_packet > MAX3421_FIFO_SIZE) {
9872d53139fSDavid Mosberger 		/*
9882d53139fSDavid Mosberger 		 * We do not support isochronous transfers at this
9892d53139fSDavid Mosberger 		 * time...
9902d53139fSDavid Mosberger 		 */
9912d53139fSDavid Mosberger 		dev_err(&spi->dev,
9922d53139fSDavid Mosberger 			"%s: packet-size of %u too big (limit is %u bytes)",
9932d53139fSDavid Mosberger 			__func__, max_packet, MAX3421_FIFO_SIZE);
9942d53139fSDavid Mosberger 		return -EINVAL;
9952d53139fSDavid Mosberger 	}
9962d53139fSDavid Mosberger 
9972d53139fSDavid Mosberger 	if (max3421_hcd->curr_len < max_packet) {
9982d53139fSDavid Mosberger 		if (urb->transfer_flags & URB_SHORT_NOT_OK) {
9992d53139fSDavid Mosberger 			/*
10002d53139fSDavid Mosberger 			 * remaining > 0 and received an
10012d53139fSDavid Mosberger 			 * unexpected partial packet ->
10022d53139fSDavid Mosberger 			 * error
10032d53139fSDavid Mosberger 			 */
10042d53139fSDavid Mosberger 			return -EREMOTEIO;
10052d53139fSDavid Mosberger 		} else
10062d53139fSDavid Mosberger 			/* short read, but it's OK */
10072d53139fSDavid Mosberger 			return 1;
10082d53139fSDavid Mosberger 	}
10092d53139fSDavid Mosberger 	return 0;	/* not done */
10102d53139fSDavid Mosberger }
10112d53139fSDavid Mosberger 
10122d53139fSDavid Mosberger /*
10132d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
10142d53139fSDavid Mosberger  */
10152d53139fSDavid Mosberger static int
10162d53139fSDavid Mosberger max3421_transfer_out_done(struct usb_hcd *hcd, struct urb *urb)
10172d53139fSDavid Mosberger {
10182d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
10192d53139fSDavid Mosberger 
10202d53139fSDavid Mosberger 	urb->actual_length += max3421_hcd->curr_len;
10212d53139fSDavid Mosberger 	if (urb->actual_length < urb->transfer_buffer_length)
10222d53139fSDavid Mosberger 		return 0;
10232d53139fSDavid Mosberger 	if (urb->transfer_flags & URB_ZERO_PACKET) {
10242d53139fSDavid Mosberger 		/*
10252d53139fSDavid Mosberger 		 * Some hardware needs a zero-size packet at the end
10262d53139fSDavid Mosberger 		 * of a bulk-out transfer if the last transfer was a
10272d53139fSDavid Mosberger 		 * full-sized packet (i.e., such hardware use <
10282d53139fSDavid Mosberger 		 * max_packet as an indicator that the end of the
10292d53139fSDavid Mosberger 		 * packet has been reached).
10302d53139fSDavid Mosberger 		 */
10312d53139fSDavid Mosberger 		u32 max_packet = usb_maxpacket(urb->dev, urb->pipe, 1);
10322d53139fSDavid Mosberger 
10332d53139fSDavid Mosberger 		if (max3421_hcd->curr_len == max_packet)
10342d53139fSDavid Mosberger 			return 0;
10352d53139fSDavid Mosberger 	}
10362d53139fSDavid Mosberger 	return 1;
10372d53139fSDavid Mosberger }
10382d53139fSDavid Mosberger 
10392d53139fSDavid Mosberger /*
10402d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
10412d53139fSDavid Mosberger  */
10422d53139fSDavid Mosberger static void
10432d53139fSDavid Mosberger max3421_host_transfer_done(struct usb_hcd *hcd)
10442d53139fSDavid Mosberger {
10452d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
10462d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
10472d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
10482d53139fSDavid Mosberger 	u8 result_code, hrsl;
10492d53139fSDavid Mosberger 	int urb_done = 0;
10502d53139fSDavid Mosberger 
10512d53139fSDavid Mosberger 	max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
10522d53139fSDavid Mosberger 			       BIT(MAX3421_HI_RCVDAV_BIT));
10532d53139fSDavid Mosberger 
10542d53139fSDavid Mosberger 	hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
10552d53139fSDavid Mosberger 	result_code = hrsl & MAX3421_HRSL_RESULT_MASK;
10562d53139fSDavid Mosberger 
10572d53139fSDavid Mosberger #ifdef DEBUG
10582d53139fSDavid Mosberger 	++max3421_hcd->err_stat[result_code];
10592d53139fSDavid Mosberger #endif
10602d53139fSDavid Mosberger 
10612d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
10622d53139fSDavid Mosberger 
10632d53139fSDavid Mosberger 	if (unlikely(result_code != MAX3421_HRSL_OK)) {
10642d53139fSDavid Mosberger 		max3421_handle_error(hcd, hrsl);
10652d53139fSDavid Mosberger 		return;
10662d53139fSDavid Mosberger 	}
10672d53139fSDavid Mosberger 
10682d53139fSDavid Mosberger 	max3421_ep->naks = 0;
10692d53139fSDavid Mosberger 	max3421_ep->retries = 0;
10702d53139fSDavid Mosberger 	switch (max3421_ep->pkt_state) {
10712d53139fSDavid Mosberger 
10722d53139fSDavid Mosberger 	case PKT_STATE_SETUP:
10732d53139fSDavid Mosberger 		if (urb->transfer_buffer_length > 0)
10742d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TRANSFER;
10752d53139fSDavid Mosberger 		else
10762d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TERMINATE;
10772d53139fSDavid Mosberger 		break;
10782d53139fSDavid Mosberger 
10792d53139fSDavid Mosberger 	case PKT_STATE_TRANSFER:
10802d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
10812d53139fSDavid Mosberger 			urb_done = max3421_transfer_in_done(hcd, urb);
10822d53139fSDavid Mosberger 		else
10832d53139fSDavid Mosberger 			urb_done = max3421_transfer_out_done(hcd, urb);
10842d53139fSDavid Mosberger 		if (urb_done > 0 && usb_pipetype(urb->pipe) == PIPE_CONTROL) {
10852d53139fSDavid Mosberger 			/*
10862d53139fSDavid Mosberger 			 * We aren't really done - we still need to
10872d53139fSDavid Mosberger 			 * terminate the control transfer:
10882d53139fSDavid Mosberger 			 */
10892d53139fSDavid Mosberger 			max3421_hcd->urb_done = urb_done = 0;
10902d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TERMINATE;
10912d53139fSDavid Mosberger 		}
10922d53139fSDavid Mosberger 		break;
10932d53139fSDavid Mosberger 
10942d53139fSDavid Mosberger 	case PKT_STATE_TERMINATE:
10952d53139fSDavid Mosberger 		urb_done = 1;
10962d53139fSDavid Mosberger 		break;
10972d53139fSDavid Mosberger 	}
10982d53139fSDavid Mosberger 
10992d53139fSDavid Mosberger 	if (urb_done)
11002d53139fSDavid Mosberger 		max3421_hcd->urb_done = urb_done;
11012d53139fSDavid Mosberger 	else
11022d53139fSDavid Mosberger 		max3421_next_transfer(hcd, 0);
11032d53139fSDavid Mosberger }
11042d53139fSDavid Mosberger 
11052d53139fSDavid Mosberger /*
11062d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
11072d53139fSDavid Mosberger  */
11082d53139fSDavid Mosberger static void
11092d53139fSDavid Mosberger max3421_detect_conn(struct usb_hcd *hcd)
11102d53139fSDavid Mosberger {
11112d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11122d53139fSDavid Mosberger 	unsigned int jk, have_conn = 0;
11132d53139fSDavid Mosberger 	u32 old_port_status, chg;
11142d53139fSDavid Mosberger 	unsigned long flags;
11152d53139fSDavid Mosberger 	u8 hrsl, mode;
11162d53139fSDavid Mosberger 
11172d53139fSDavid Mosberger 	hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
11182d53139fSDavid Mosberger 
11192d53139fSDavid Mosberger 	jk = ((((hrsl >> MAX3421_HRSL_JSTATUS_BIT) & 1) << 0) |
11202d53139fSDavid Mosberger 	      (((hrsl >> MAX3421_HRSL_KSTATUS_BIT) & 1) << 1));
11212d53139fSDavid Mosberger 
11222d53139fSDavid Mosberger 	mode = max3421_hcd->mode;
11232d53139fSDavid Mosberger 
11242d53139fSDavid Mosberger 	switch (jk) {
11252d53139fSDavid Mosberger 	case 0x0: /* SE0: disconnect */
11262d53139fSDavid Mosberger 		/*
11272d53139fSDavid Mosberger 		 * Turn off SOFKAENAB bit to avoid getting interrupt
11282d53139fSDavid Mosberger 		 * every milli-second:
11292d53139fSDavid Mosberger 		 */
11302d53139fSDavid Mosberger 		mode &= ~BIT(MAX3421_MODE_SOFKAENAB_BIT);
11312d53139fSDavid Mosberger 		break;
11322d53139fSDavid Mosberger 
11332d53139fSDavid Mosberger 	case 0x1: /* J=0,K=1: low-speed (in full-speed or vice versa) */
11342d53139fSDavid Mosberger 	case 0x2: /* J=1,K=0: full-speed (in full-speed or vice versa) */
11352d53139fSDavid Mosberger 		if (jk == 0x2)
11362d53139fSDavid Mosberger 			/* need to switch to the other speed: */
11372d53139fSDavid Mosberger 			mode ^= BIT(MAX3421_MODE_LOWSPEED_BIT);
11382d53139fSDavid Mosberger 		/* turn on SOFKAENAB bit: */
11392d53139fSDavid Mosberger 		mode |= BIT(MAX3421_MODE_SOFKAENAB_BIT);
11402d53139fSDavid Mosberger 		have_conn = 1;
11412d53139fSDavid Mosberger 		break;
11422d53139fSDavid Mosberger 
11432d53139fSDavid Mosberger 	case 0x3: /* illegal */
11442d53139fSDavid Mosberger 		break;
11452d53139fSDavid Mosberger 	}
11462d53139fSDavid Mosberger 
11472d53139fSDavid Mosberger 	max3421_hcd->mode = mode;
11482d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
11492d53139fSDavid Mosberger 
11502d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
11512d53139fSDavid Mosberger 	old_port_status = max3421_hcd->port_status;
11522d53139fSDavid Mosberger 	if (have_conn)
11532d53139fSDavid Mosberger 		max3421_hcd->port_status |=  USB_PORT_STAT_CONNECTION;
11542d53139fSDavid Mosberger 	else
11552d53139fSDavid Mosberger 		max3421_hcd->port_status &= ~USB_PORT_STAT_CONNECTION;
11562d53139fSDavid Mosberger 	if (mode & BIT(MAX3421_MODE_LOWSPEED_BIT))
11572d53139fSDavid Mosberger 		max3421_hcd->port_status |=  USB_PORT_STAT_LOW_SPEED;
11582d53139fSDavid Mosberger 	else
11592d53139fSDavid Mosberger 		max3421_hcd->port_status &= ~USB_PORT_STAT_LOW_SPEED;
11602d53139fSDavid Mosberger 	chg = (old_port_status ^ max3421_hcd->port_status);
11612d53139fSDavid Mosberger 	max3421_hcd->port_status |= chg << 16;
11622d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
11632d53139fSDavid Mosberger }
11642d53139fSDavid Mosberger 
11652d53139fSDavid Mosberger static irqreturn_t
11662d53139fSDavid Mosberger max3421_irq_handler(int irq, void *dev_id)
11672d53139fSDavid Mosberger {
11682d53139fSDavid Mosberger 	struct usb_hcd *hcd = dev_id;
11692d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
11702d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11712d53139fSDavid Mosberger 
1172*37aadc68SPeter Zijlstra 	if (max3421_hcd->spi_thread)
11732d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
11742eb5dbddSDavid Mosberger-Tang 	if (!test_and_set_bit(ENABLE_IRQ, &max3421_hcd->todo))
11752d53139fSDavid Mosberger 		disable_irq_nosync(spi->irq);
11762d53139fSDavid Mosberger 	return IRQ_HANDLED;
11772d53139fSDavid Mosberger }
11782d53139fSDavid Mosberger 
11792d53139fSDavid Mosberger #ifdef DEBUG
11802d53139fSDavid Mosberger 
11812d53139fSDavid Mosberger static void
11822d53139fSDavid Mosberger dump_eps(struct usb_hcd *hcd)
11832d53139fSDavid Mosberger {
11842d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11852d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
11862d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
11872d53139fSDavid Mosberger 	char ubuf[512], *dp, *end;
11882d53139fSDavid Mosberger 	unsigned long flags;
11892d53139fSDavid Mosberger 	struct urb *urb;
11902d53139fSDavid Mosberger 	int epnum, ret;
11912d53139fSDavid Mosberger 
11922d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
1193553c2360SGeliang Tang 	list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) {
11942d53139fSDavid Mosberger 		ep = max3421_ep->ep;
11952d53139fSDavid Mosberger 
11962d53139fSDavid Mosberger 		dp = ubuf;
11972d53139fSDavid Mosberger 		end = dp + sizeof(ubuf);
11982d53139fSDavid Mosberger 		*dp = '\0';
1199553c2360SGeliang Tang 		list_for_each_entry(urb, &ep->urb_list, urb_list) {
12002d53139fSDavid Mosberger 			ret = snprintf(dp, end - dp, " %p(%d.%s %d/%d)", urb,
12012d53139fSDavid Mosberger 				       usb_pipetype(urb->pipe),
12022d53139fSDavid Mosberger 				       usb_urb_dir_in(urb) ? "IN" : "OUT",
12032d53139fSDavid Mosberger 				       urb->actual_length,
12042d53139fSDavid Mosberger 				       urb->transfer_buffer_length);
12052d53139fSDavid Mosberger 			if (ret < 0 || ret >= end - dp)
12062d53139fSDavid Mosberger 				break;	/* error or buffer full */
12072d53139fSDavid Mosberger 			dp += ret;
12082d53139fSDavid Mosberger 		}
12092d53139fSDavid Mosberger 
12102d53139fSDavid Mosberger 		epnum = usb_endpoint_num(&ep->desc);
12112d53139fSDavid Mosberger 		pr_info("EP%0u %u lst %04u rtr %u nak %6u rxmt %u: %s\n",
12122d53139fSDavid Mosberger 			epnum, max3421_ep->pkt_state, max3421_ep->last_active,
12132d53139fSDavid Mosberger 			max3421_ep->retries, max3421_ep->naks,
12142d53139fSDavid Mosberger 			max3421_ep->retransmit, ubuf);
12152d53139fSDavid Mosberger 	}
12162d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
12172d53139fSDavid Mosberger }
12182d53139fSDavid Mosberger 
12192d53139fSDavid Mosberger #endif /* DEBUG */
12202d53139fSDavid Mosberger 
12212d53139fSDavid Mosberger /* Return zero if no work was performed, 1 otherwise.  */
12222d53139fSDavid Mosberger static int
12232d53139fSDavid Mosberger max3421_handle_irqs(struct usb_hcd *hcd)
12242d53139fSDavid Mosberger {
12252d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
12262d53139fSDavid Mosberger 	u32 chg, old_port_status;
12272d53139fSDavid Mosberger 	unsigned long flags;
12282d53139fSDavid Mosberger 	u8 hirq;
12292d53139fSDavid Mosberger 
12302d53139fSDavid Mosberger 	/*
12312d53139fSDavid Mosberger 	 * Read and ack pending interrupts (CPU must never
12322d53139fSDavid Mosberger 	 * clear SNDBAV directly and RCVDAV must be cleared by
12332d53139fSDavid Mosberger 	 * max3421_recv_data_available()!):
12342d53139fSDavid Mosberger 	 */
12352d53139fSDavid Mosberger 	hirq = spi_rd8(hcd, MAX3421_REG_HIRQ);
12362d53139fSDavid Mosberger 	hirq &= max3421_hcd->hien;
12372d53139fSDavid Mosberger 	if (!hirq)
12382d53139fSDavid Mosberger 		return 0;
12392d53139fSDavid Mosberger 
12402d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIRQ,
12412d53139fSDavid Mosberger 		hirq & ~(BIT(MAX3421_HI_SNDBAV_BIT) |
12422d53139fSDavid Mosberger 			 BIT(MAX3421_HI_RCVDAV_BIT)));
12432d53139fSDavid Mosberger 
12442d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_FRAME_BIT)) {
12452d53139fSDavid Mosberger 		max3421_hcd->frame_number = ((max3421_hcd->frame_number + 1)
12462d53139fSDavid Mosberger 					     & USB_MAX_FRAME_NUMBER);
12472d53139fSDavid Mosberger 		max3421_hcd->sched_pass = SCHED_PASS_PERIODIC;
12482d53139fSDavid Mosberger 	}
12492d53139fSDavid Mosberger 
12502d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_RCVDAV_BIT))
12512d53139fSDavid Mosberger 		max3421_recv_data_available(hcd);
12522d53139fSDavid Mosberger 
12532d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_HXFRDN_BIT))
12542d53139fSDavid Mosberger 		max3421_host_transfer_done(hcd);
12552d53139fSDavid Mosberger 
12562d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_CONDET_BIT))
12572d53139fSDavid Mosberger 		max3421_detect_conn(hcd);
12582d53139fSDavid Mosberger 
12592d53139fSDavid Mosberger 	/*
12602d53139fSDavid Mosberger 	 * Now process interrupts that may affect HCD state
12612d53139fSDavid Mosberger 	 * other than the end-points:
12622d53139fSDavid Mosberger 	 */
12632d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
12642d53139fSDavid Mosberger 
12652d53139fSDavid Mosberger 	old_port_status = max3421_hcd->port_status;
12662d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_BUSEVENT_BIT)) {
12672d53139fSDavid Mosberger 		if (max3421_hcd->port_status & USB_PORT_STAT_RESET) {
12682d53139fSDavid Mosberger 			/* BUSEVENT due to completion of Bus Reset */
12692d53139fSDavid Mosberger 			max3421_hcd->port_status &= ~USB_PORT_STAT_RESET;
12702d53139fSDavid Mosberger 			max3421_hcd->port_status |=  USB_PORT_STAT_ENABLE;
12712d53139fSDavid Mosberger 		} else {
12722d53139fSDavid Mosberger 			/* BUSEVENT due to completion of Bus Resume */
12732d53139fSDavid Mosberger 			pr_info("%s: BUSEVENT Bus Resume Done\n", __func__);
12742d53139fSDavid Mosberger 		}
12752d53139fSDavid Mosberger 	}
12762d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_RWU_BIT))
12772d53139fSDavid Mosberger 		pr_info("%s: RWU\n", __func__);
12782d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_SUSDN_BIT))
12792d53139fSDavid Mosberger 		pr_info("%s: SUSDN\n", __func__);
12802d53139fSDavid Mosberger 
12812d53139fSDavid Mosberger 	chg = (old_port_status ^ max3421_hcd->port_status);
12822d53139fSDavid Mosberger 	max3421_hcd->port_status |= chg << 16;
12832d53139fSDavid Mosberger 
12842d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
12852d53139fSDavid Mosberger 
12862d53139fSDavid Mosberger #ifdef DEBUG
12872d53139fSDavid Mosberger 	{
12882d53139fSDavid Mosberger 		static unsigned long last_time;
12892d53139fSDavid Mosberger 		char sbuf[16 * 16], *dp, *end;
12902d53139fSDavid Mosberger 		int i;
12912d53139fSDavid Mosberger 
1292788bfe88SAsaf Vertz 		if (time_after(jiffies, last_time + 5*HZ)) {
12932d53139fSDavid Mosberger 			dp = sbuf;
12942d53139fSDavid Mosberger 			end = sbuf + sizeof(sbuf);
12952d53139fSDavid Mosberger 			*dp = '\0';
12962d53139fSDavid Mosberger 			for (i = 0; i < 16; ++i) {
12972d53139fSDavid Mosberger 				int ret = snprintf(dp, end - dp, " %lu",
12982d53139fSDavid Mosberger 						   max3421_hcd->err_stat[i]);
12992d53139fSDavid Mosberger 				if (ret < 0 || ret >= end - dp)
13002d53139fSDavid Mosberger 					break;	/* error or buffer full */
13012d53139fSDavid Mosberger 				dp += ret;
13022d53139fSDavid Mosberger 			}
13032d53139fSDavid Mosberger 			pr_info("%s: hrsl_stats %s\n", __func__, sbuf);
13042d53139fSDavid Mosberger 			memset(max3421_hcd->err_stat, 0,
13052d53139fSDavid Mosberger 			       sizeof(max3421_hcd->err_stat));
13062d53139fSDavid Mosberger 			last_time = jiffies;
13072d53139fSDavid Mosberger 
13082d53139fSDavid Mosberger 			dump_eps(hcd);
13092d53139fSDavid Mosberger 		}
13102d53139fSDavid Mosberger 	}
13112d53139fSDavid Mosberger #endif
13122d53139fSDavid Mosberger 	return 1;
13132d53139fSDavid Mosberger }
13142d53139fSDavid Mosberger 
13152d53139fSDavid Mosberger static int
13162d53139fSDavid Mosberger max3421_reset_hcd(struct usb_hcd *hcd)
13172d53139fSDavid Mosberger {
13182d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
13192d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
13202d53139fSDavid Mosberger 	int timeout;
13212d53139fSDavid Mosberger 
13222d53139fSDavid Mosberger 	/* perform a chip reset and wait for OSCIRQ signal to appear: */
13232d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_USBCTL, BIT(MAX3421_USBCTL_CHIPRES_BIT));
13242d53139fSDavid Mosberger 	/* clear reset: */
13252d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_USBCTL, 0);
13262d53139fSDavid Mosberger 	timeout = 1000;
13272d53139fSDavid Mosberger 	while (1) {
13282d53139fSDavid Mosberger 		if (spi_rd8(hcd, MAX3421_REG_USBIRQ)
13292d53139fSDavid Mosberger 		    & BIT(MAX3421_USBIRQ_OSCOKIRQ_BIT))
13302d53139fSDavid Mosberger 			break;
13312d53139fSDavid Mosberger 		if (--timeout < 0) {
13322d53139fSDavid Mosberger 			dev_err(&spi->dev,
13332d53139fSDavid Mosberger 				"timed out waiting for oscillator OK signal");
13342d53139fSDavid Mosberger 			return 1;
13352d53139fSDavid Mosberger 		}
13362d53139fSDavid Mosberger 		cond_resched();
13372d53139fSDavid Mosberger 	}
13382d53139fSDavid Mosberger 
13392d53139fSDavid Mosberger 	/*
13402d53139fSDavid Mosberger 	 * Turn on host mode, automatic generation of SOF packets, and
13412d53139fSDavid Mosberger 	 * enable pull-down registers on DM/DP:
13422d53139fSDavid Mosberger 	 */
13432d53139fSDavid Mosberger 	max3421_hcd->mode = (BIT(MAX3421_MODE_HOST_BIT) |
13442d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_SOFKAENAB_BIT) |
13452d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_DMPULLDN_BIT) |
13462d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_DPPULLDN_BIT));
13472d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
13482d53139fSDavid Mosberger 
13492d53139fSDavid Mosberger 	/* reset frame-number: */
13502d53139fSDavid Mosberger 	max3421_hcd->frame_number = USB_MAX_FRAME_NUMBER;
13512d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, BIT(MAX3421_HCTL_FRMRST_BIT));
13522d53139fSDavid Mosberger 
13532d53139fSDavid Mosberger 	/* sample the state of the D+ and D- lines */
13542d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, BIT(MAX3421_HCTL_SAMPLEBUS_BIT));
13552d53139fSDavid Mosberger 	max3421_detect_conn(hcd);
13562d53139fSDavid Mosberger 
13572d53139fSDavid Mosberger 	/* enable frame, connection-detected, and bus-event interrupts: */
13582d53139fSDavid Mosberger 	max3421_hcd->hien = (BIT(MAX3421_HI_FRAME_BIT) |
13592d53139fSDavid Mosberger 			     BIT(MAX3421_HI_CONDET_BIT) |
13602d53139fSDavid Mosberger 			     BIT(MAX3421_HI_BUSEVENT_BIT));
13612d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
13622d53139fSDavid Mosberger 
13632d53139fSDavid Mosberger 	/* enable interrupts: */
13642d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_CPUCTL, BIT(MAX3421_CPUCTL_IE_BIT));
13652d53139fSDavid Mosberger 	return 1;
13662d53139fSDavid Mosberger }
13672d53139fSDavid Mosberger 
13682d53139fSDavid Mosberger static int
13692d53139fSDavid Mosberger max3421_urb_done(struct usb_hcd *hcd)
13702d53139fSDavid Mosberger {
13712d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
13722d53139fSDavid Mosberger 	unsigned long flags;
13732d53139fSDavid Mosberger 	struct urb *urb;
13742d53139fSDavid Mosberger 	int status;
13752d53139fSDavid Mosberger 
13762d53139fSDavid Mosberger 	status = max3421_hcd->urb_done;
13772d53139fSDavid Mosberger 	max3421_hcd->urb_done = 0;
13782d53139fSDavid Mosberger 	if (status > 0)
13792d53139fSDavid Mosberger 		status = 0;
13802d53139fSDavid Mosberger 	urb = max3421_hcd->curr_urb;
13812d53139fSDavid Mosberger 	if (urb) {
13822d53139fSDavid Mosberger 		max3421_hcd->curr_urb = NULL;
13832d53139fSDavid Mosberger 		spin_lock_irqsave(&max3421_hcd->lock, flags);
13842d53139fSDavid Mosberger 		usb_hcd_unlink_urb_from_ep(hcd, urb);
13852d53139fSDavid Mosberger 		spin_unlock_irqrestore(&max3421_hcd->lock, flags);
13862d53139fSDavid Mosberger 
13872d53139fSDavid Mosberger 		/* must be called without the HCD spinlock: */
13882d53139fSDavid Mosberger 		usb_hcd_giveback_urb(hcd, urb, status);
13892d53139fSDavid Mosberger 	}
13902d53139fSDavid Mosberger 	return 1;
13912d53139fSDavid Mosberger }
13922d53139fSDavid Mosberger 
13932d53139fSDavid Mosberger static int
13942d53139fSDavid Mosberger max3421_spi_thread(void *dev_id)
13952d53139fSDavid Mosberger {
13962d53139fSDavid Mosberger 	struct usb_hcd *hcd = dev_id;
13972d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
13982d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
13992d53139fSDavid Mosberger 	int i, i_worked = 1;
14002d53139fSDavid Mosberger 
14012d53139fSDavid Mosberger 	/* set full-duplex SPI mode, low-active interrupt pin: */
14022d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_PINCTL,
14032d53139fSDavid Mosberger 		(BIT(MAX3421_PINCTL_FDUPSPI_BIT) |	/* full-duplex */
14042d53139fSDavid Mosberger 		 BIT(MAX3421_PINCTL_INTLEVEL_BIT)));	/* low-active irq */
14052d53139fSDavid Mosberger 
14062d53139fSDavid Mosberger 	while (!kthread_should_stop()) {
14072d53139fSDavid Mosberger 		max3421_hcd->rev = spi_rd8(hcd, MAX3421_REG_REVISION);
14082d53139fSDavid Mosberger 		if (max3421_hcd->rev == 0x12 || max3421_hcd->rev == 0x13)
14092d53139fSDavid Mosberger 			break;
14102d53139fSDavid Mosberger 		dev_err(&spi->dev, "bad rev 0x%02x", max3421_hcd->rev);
14112d53139fSDavid Mosberger 		msleep(10000);
14122d53139fSDavid Mosberger 	}
14132d53139fSDavid Mosberger 	dev_info(&spi->dev, "rev 0x%x, SPI clk %dHz, bpw %u, irq %d\n",
14142d53139fSDavid Mosberger 		 max3421_hcd->rev, spi->max_speed_hz, spi->bits_per_word,
14152d53139fSDavid Mosberger 		 spi->irq);
14162d53139fSDavid Mosberger 
14172d53139fSDavid Mosberger 	while (!kthread_should_stop()) {
14182d53139fSDavid Mosberger 		if (!i_worked) {
14192d53139fSDavid Mosberger 			/*
14202d53139fSDavid Mosberger 			 * We'll be waiting for wakeups from the hard
14212d53139fSDavid Mosberger 			 * interrupt handler, so now is a good time to
14222d53139fSDavid Mosberger 			 * sync our hien with the chip:
14232d53139fSDavid Mosberger 			 */
14242d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
14252d53139fSDavid Mosberger 
14262d53139fSDavid Mosberger 			set_current_state(TASK_INTERRUPTIBLE);
14272eb5dbddSDavid Mosberger-Tang 			if (test_and_clear_bit(ENABLE_IRQ, &max3421_hcd->todo))
14282d53139fSDavid Mosberger 				enable_irq(spi->irq);
14292d53139fSDavid Mosberger 			schedule();
14302d53139fSDavid Mosberger 			__set_current_state(TASK_RUNNING);
14312d53139fSDavid Mosberger 		}
14322d53139fSDavid Mosberger 
14332d53139fSDavid Mosberger 		i_worked = 0;
14342d53139fSDavid Mosberger 
14352d53139fSDavid Mosberger 		if (max3421_hcd->urb_done)
14362d53139fSDavid Mosberger 			i_worked |= max3421_urb_done(hcd);
14372d53139fSDavid Mosberger 		else if (max3421_handle_irqs(hcd))
14382d53139fSDavid Mosberger 			i_worked = 1;
14392d53139fSDavid Mosberger 		else if (!max3421_hcd->curr_urb)
14402d53139fSDavid Mosberger 			i_worked |= max3421_select_and_start_urb(hcd);
14412d53139fSDavid Mosberger 
14422eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(RESET_HCD, &max3421_hcd->todo))
14432d53139fSDavid Mosberger 			/* reset the HCD: */
14442d53139fSDavid Mosberger 			i_worked |= max3421_reset_hcd(hcd);
14452eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(RESET_PORT, &max3421_hcd->todo)) {
14462d53139fSDavid Mosberger 			/* perform a USB bus reset: */
14472d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HCTL,
14482d53139fSDavid Mosberger 				BIT(MAX3421_HCTL_BUSRST_BIT));
14492d53139fSDavid Mosberger 			i_worked = 1;
14502d53139fSDavid Mosberger 		}
14512eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(CHECK_UNLINK, &max3421_hcd->todo))
14522d53139fSDavid Mosberger 			i_worked |= max3421_check_unlink(hcd);
14532eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(IOPIN_UPDATE, &max3421_hcd->todo)) {
14542d53139fSDavid Mosberger 			/*
14552d53139fSDavid Mosberger 			 * IOPINS1/IOPINS2 do not auto-increment, so we can't
14562d53139fSDavid Mosberger 			 * use spi_wr_buf().
14572d53139fSDavid Mosberger 			 */
14582d53139fSDavid Mosberger 			for (i = 0; i < ARRAY_SIZE(max3421_hcd->iopins); ++i) {
14592d53139fSDavid Mosberger 				u8 val = spi_rd8(hcd, MAX3421_REG_IOPINS1);
14602d53139fSDavid Mosberger 
14612d53139fSDavid Mosberger 				val = ((val & 0xf0) |
14622d53139fSDavid Mosberger 				       (max3421_hcd->iopins[i] & 0x0f));
14632d53139fSDavid Mosberger 				spi_wr8(hcd, MAX3421_REG_IOPINS1 + i, val);
14642d53139fSDavid Mosberger 				max3421_hcd->iopins[i] = val;
14652d53139fSDavid Mosberger 			}
14662d53139fSDavid Mosberger 			i_worked = 1;
14672d53139fSDavid Mosberger 		}
14682d53139fSDavid Mosberger 	}
14692d53139fSDavid Mosberger 	set_current_state(TASK_RUNNING);
14702d53139fSDavid Mosberger 	dev_info(&spi->dev, "SPI thread exiting");
14712d53139fSDavid Mosberger 	return 0;
14722d53139fSDavid Mosberger }
14732d53139fSDavid Mosberger 
14742d53139fSDavid Mosberger static int
14752d53139fSDavid Mosberger max3421_reset_port(struct usb_hcd *hcd)
14762d53139fSDavid Mosberger {
14772d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14782d53139fSDavid Mosberger 
14792d53139fSDavid Mosberger 	max3421_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |
14802d53139fSDavid Mosberger 				      USB_PORT_STAT_LOW_SPEED);
1481a2b63cb5SDavid Mosberger-Tang 	max3421_hcd->port_status |= USB_PORT_STAT_RESET;
14822eb5dbddSDavid Mosberger-Tang 	set_bit(RESET_PORT, &max3421_hcd->todo);
14832d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
14842d53139fSDavid Mosberger 	return 0;
14852d53139fSDavid Mosberger }
14862d53139fSDavid Mosberger 
14872d53139fSDavid Mosberger static int
14882d53139fSDavid Mosberger max3421_reset(struct usb_hcd *hcd)
14892d53139fSDavid Mosberger {
14902d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14912d53139fSDavid Mosberger 
14922d53139fSDavid Mosberger 	hcd->self.sg_tablesize = 0;
14932d53139fSDavid Mosberger 	hcd->speed = HCD_USB2;
14942d53139fSDavid Mosberger 	hcd->self.root_hub->speed = USB_SPEED_FULL;
14952eb5dbddSDavid Mosberger-Tang 	set_bit(RESET_HCD, &max3421_hcd->todo);
14962d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
14972d53139fSDavid Mosberger 	return 0;
14982d53139fSDavid Mosberger }
14992d53139fSDavid Mosberger 
15002d53139fSDavid Mosberger static int
15012d53139fSDavid Mosberger max3421_start(struct usb_hcd *hcd)
15022d53139fSDavid Mosberger {
15032d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15042d53139fSDavid Mosberger 
15052d53139fSDavid Mosberger 	spin_lock_init(&max3421_hcd->lock);
15062d53139fSDavid Mosberger 	max3421_hcd->rh_state = MAX3421_RH_RUNNING;
15072d53139fSDavid Mosberger 
15082d53139fSDavid Mosberger 	INIT_LIST_HEAD(&max3421_hcd->ep_list);
15092d53139fSDavid Mosberger 
15102d53139fSDavid Mosberger 	hcd->power_budget = POWER_BUDGET;
15112d53139fSDavid Mosberger 	hcd->state = HC_STATE_RUNNING;
15122d53139fSDavid Mosberger 	hcd->uses_new_polling = 1;
15132d53139fSDavid Mosberger 	return 0;
15142d53139fSDavid Mosberger }
15152d53139fSDavid Mosberger 
15162d53139fSDavid Mosberger static void
15172d53139fSDavid Mosberger max3421_stop(struct usb_hcd *hcd)
15182d53139fSDavid Mosberger {
15192d53139fSDavid Mosberger }
15202d53139fSDavid Mosberger 
15212d53139fSDavid Mosberger static int
15222d53139fSDavid Mosberger max3421_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
15232d53139fSDavid Mosberger {
15242d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
15252d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15262d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
15272d53139fSDavid Mosberger 	unsigned long flags;
15282d53139fSDavid Mosberger 	int retval;
15292d53139fSDavid Mosberger 
15302d53139fSDavid Mosberger 	switch (usb_pipetype(urb->pipe)) {
15312d53139fSDavid Mosberger 	case PIPE_INTERRUPT:
15322d53139fSDavid Mosberger 	case PIPE_ISOCHRONOUS:
15332d53139fSDavid Mosberger 		if (urb->interval < 0) {
15342d53139fSDavid Mosberger 			dev_err(&spi->dev,
15352d53139fSDavid Mosberger 			  "%s: interval=%d for intr-/iso-pipe; expected > 0\n",
15362d53139fSDavid Mosberger 				__func__, urb->interval);
15372d53139fSDavid Mosberger 			return -EINVAL;
15382d53139fSDavid Mosberger 		}
153993c747edSGustavo A. R. Silva 		break;
15402d53139fSDavid Mosberger 	default:
15412d53139fSDavid Mosberger 		break;
15422d53139fSDavid Mosberger 	}
15432d53139fSDavid Mosberger 
15442d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
15452d53139fSDavid Mosberger 
15462d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
15472d53139fSDavid Mosberger 	if (!max3421_ep) {
15482d53139fSDavid Mosberger 		/* gets freed in max3421_endpoint_disable: */
15496c0f3695SAlexey Khoroshilov 		max3421_ep = kzalloc(sizeof(struct max3421_ep), GFP_ATOMIC);
155000c5aa17SDavid Mosberger-Tang 		if (!max3421_ep) {
155100c5aa17SDavid Mosberger-Tang 			retval = -ENOMEM;
155200c5aa17SDavid Mosberger-Tang 			goto out;
155300c5aa17SDavid Mosberger-Tang 		}
15542d53139fSDavid Mosberger 		max3421_ep->ep = urb->ep;
15552d53139fSDavid Mosberger 		max3421_ep->last_active = max3421_hcd->frame_number;
15562d53139fSDavid Mosberger 		urb->ep->hcpriv = max3421_ep;
15572d53139fSDavid Mosberger 
15582d53139fSDavid Mosberger 		list_add_tail(&max3421_ep->ep_list, &max3421_hcd->ep_list);
15592d53139fSDavid Mosberger 	}
15602d53139fSDavid Mosberger 
15612d53139fSDavid Mosberger 	retval = usb_hcd_link_urb_to_ep(hcd, urb);
15622d53139fSDavid Mosberger 	if (retval == 0) {
15632d53139fSDavid Mosberger 		/* Since we added to the queue, restart scheduling: */
15642d53139fSDavid Mosberger 		max3421_hcd->sched_pass = SCHED_PASS_PERIODIC;
15652d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
15662d53139fSDavid Mosberger 	}
15672d53139fSDavid Mosberger 
156800c5aa17SDavid Mosberger-Tang out:
15692d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
15702d53139fSDavid Mosberger 	return retval;
15712d53139fSDavid Mosberger }
15722d53139fSDavid Mosberger 
15732d53139fSDavid Mosberger static int
15742d53139fSDavid Mosberger max3421_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
15752d53139fSDavid Mosberger {
15762d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15772d53139fSDavid Mosberger 	unsigned long flags;
15782d53139fSDavid Mosberger 	int retval;
15792d53139fSDavid Mosberger 
15802d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
15812d53139fSDavid Mosberger 
15822d53139fSDavid Mosberger 	/*
15832d53139fSDavid Mosberger 	 * This will set urb->unlinked which in turn causes the entry
15842d53139fSDavid Mosberger 	 * to be dropped at the next opportunity.
15852d53139fSDavid Mosberger 	 */
15862d53139fSDavid Mosberger 	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
15872d53139fSDavid Mosberger 	if (retval == 0) {
15882eb5dbddSDavid Mosberger-Tang 		set_bit(CHECK_UNLINK, &max3421_hcd->todo);
15892d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
15902d53139fSDavid Mosberger 	}
15912d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
15922d53139fSDavid Mosberger 	return retval;
15932d53139fSDavid Mosberger }
15942d53139fSDavid Mosberger 
15952d53139fSDavid Mosberger static void
15962d53139fSDavid Mosberger max3421_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
15972d53139fSDavid Mosberger {
15982d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15992d53139fSDavid Mosberger 	unsigned long flags;
16002d53139fSDavid Mosberger 
16012d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
16022d53139fSDavid Mosberger 
16032d53139fSDavid Mosberger 	if (ep->hcpriv) {
16042d53139fSDavid Mosberger 		struct max3421_ep *max3421_ep = ep->hcpriv;
16052d53139fSDavid Mosberger 
16062d53139fSDavid Mosberger 		/* remove myself from the ep_list: */
16072d53139fSDavid Mosberger 		if (!list_empty(&max3421_ep->ep_list))
16082d53139fSDavid Mosberger 			list_del(&max3421_ep->ep_list);
16092d53139fSDavid Mosberger 		kfree(max3421_ep);
16102d53139fSDavid Mosberger 		ep->hcpriv = NULL;
16112d53139fSDavid Mosberger 	}
16122d53139fSDavid Mosberger 
16132d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
16142d53139fSDavid Mosberger }
16152d53139fSDavid Mosberger 
16162d53139fSDavid Mosberger static int
16172d53139fSDavid Mosberger max3421_get_frame_number(struct usb_hcd *hcd)
16182d53139fSDavid Mosberger {
16192d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16202d53139fSDavid Mosberger 	return max3421_hcd->frame_number;
16212d53139fSDavid Mosberger }
16222d53139fSDavid Mosberger 
16232d53139fSDavid Mosberger /*
16242d53139fSDavid Mosberger  * Should return a non-zero value when any port is undergoing a resume
16252d53139fSDavid Mosberger  * transition while the root hub is suspended.
16262d53139fSDavid Mosberger  */
16272d53139fSDavid Mosberger static int
16282d53139fSDavid Mosberger max3421_hub_status_data(struct usb_hcd *hcd, char *buf)
16292d53139fSDavid Mosberger {
16302d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16312d53139fSDavid Mosberger 	unsigned long flags;
16322d53139fSDavid Mosberger 	int retval = 0;
16332d53139fSDavid Mosberger 
16342d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
16352d53139fSDavid Mosberger 	if (!HCD_HW_ACCESSIBLE(hcd))
16362d53139fSDavid Mosberger 		goto done;
16372d53139fSDavid Mosberger 
16382d53139fSDavid Mosberger 	*buf = 0;
16392d53139fSDavid Mosberger 	if ((max3421_hcd->port_status & PORT_C_MASK) != 0) {
16402d53139fSDavid Mosberger 		*buf = (1 << 1); /* a hub over-current condition exists */
16412d53139fSDavid Mosberger 		dev_dbg(hcd->self.controller,
16422d53139fSDavid Mosberger 			"port status 0x%08x has changes\n",
16432d53139fSDavid Mosberger 			max3421_hcd->port_status);
16442d53139fSDavid Mosberger 		retval = 1;
16452d53139fSDavid Mosberger 		if (max3421_hcd->rh_state == MAX3421_RH_SUSPENDED)
16462d53139fSDavid Mosberger 			usb_hcd_resume_root_hub(hcd);
16472d53139fSDavid Mosberger 	}
16482d53139fSDavid Mosberger done:
16492d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
16502d53139fSDavid Mosberger 	return retval;
16512d53139fSDavid Mosberger }
16522d53139fSDavid Mosberger 
16532d53139fSDavid Mosberger static inline void
16542d53139fSDavid Mosberger hub_descriptor(struct usb_hub_descriptor *desc)
16552d53139fSDavid Mosberger {
16562d53139fSDavid Mosberger 	memset(desc, 0, sizeof(*desc));
16572d53139fSDavid Mosberger 	/*
16582d53139fSDavid Mosberger 	 * See Table 11-13: Hub Descriptor in USB 2.0 spec.
16592d53139fSDavid Mosberger 	 */
1660e3d02e0eSSergei Shtylyov 	desc->bDescriptorType = USB_DT_HUB; /* hub descriptor */
16612d53139fSDavid Mosberger 	desc->bDescLength = 9;
16622e48c466SSergei Shtylyov 	desc->wHubCharacteristics = cpu_to_le16(HUB_CHAR_INDV_PORT_LPSM |
16632e48c466SSergei Shtylyov 						HUB_CHAR_COMMON_OCPM);
16642d53139fSDavid Mosberger 	desc->bNbrPorts = 1;
16652d53139fSDavid Mosberger }
16662d53139fSDavid Mosberger 
16672d53139fSDavid Mosberger /*
16682d53139fSDavid Mosberger  * Set the MAX3421E general-purpose output with number PIN_NUMBER to
16692d53139fSDavid Mosberger  * VALUE (0 or 1).  PIN_NUMBER may be in the range from 1-8.  For
16702d53139fSDavid Mosberger  * any other value, this function acts as a no-op.
16712d53139fSDavid Mosberger  */
16722d53139fSDavid Mosberger static void
16732d53139fSDavid Mosberger max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value)
16742d53139fSDavid Mosberger {
16752d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16762d53139fSDavid Mosberger 	u8 mask, idx;
16772d53139fSDavid Mosberger 
16782d53139fSDavid Mosberger 	--pin_number;
1679721fdc83SJules Maselbas 	if (pin_number >= MAX3421_GPOUT_COUNT)
16802d53139fSDavid Mosberger 		return;
16812d53139fSDavid Mosberger 
168259b71f77SJaewon Kim 	mask = 1u << (pin_number % 4);
16832d53139fSDavid Mosberger 	idx = pin_number / 4;
16842d53139fSDavid Mosberger 
16852d53139fSDavid Mosberger 	if (value)
16862d53139fSDavid Mosberger 		max3421_hcd->iopins[idx] |=  mask;
16872d53139fSDavid Mosberger 	else
16882d53139fSDavid Mosberger 		max3421_hcd->iopins[idx] &= ~mask;
16892eb5dbddSDavid Mosberger-Tang 	set_bit(IOPIN_UPDATE, &max3421_hcd->todo);
16902d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
16912d53139fSDavid Mosberger }
16922d53139fSDavid Mosberger 
16932d53139fSDavid Mosberger static int
16942d53139fSDavid Mosberger max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index,
16952d53139fSDavid Mosberger 		    char *buf, u16 length)
16962d53139fSDavid Mosberger {
16972d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
16982d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16992d53139fSDavid Mosberger 	struct max3421_hcd_platform_data *pdata;
17002d53139fSDavid Mosberger 	unsigned long flags;
17012d53139fSDavid Mosberger 	int retval = 0;
17022d53139fSDavid Mosberger 
17032d53139fSDavid Mosberger 	pdata = spi->dev.platform_data;
1704892f6ebcSJules Maselbas 
1705892f6ebcSJules Maselbas 	spin_lock_irqsave(&max3421_hcd->lock, flags);
17062d53139fSDavid Mosberger 
17072d53139fSDavid Mosberger 	switch (type_req) {
17082d53139fSDavid Mosberger 	case ClearHubFeature:
17092d53139fSDavid Mosberger 		break;
17102d53139fSDavid Mosberger 	case ClearPortFeature:
17112d53139fSDavid Mosberger 		switch (value) {
17122d53139fSDavid Mosberger 		case USB_PORT_FEAT_SUSPEND:
17132d53139fSDavid Mosberger 			break;
17142d53139fSDavid Mosberger 		case USB_PORT_FEAT_POWER:
17152d53139fSDavid Mosberger 			dev_dbg(hcd->self.controller, "power-off\n");
17164055e5e5SDavid Mosberger-Tang 			max3421_gpout_set_value(hcd, pdata->vbus_gpout,
17174055e5e5SDavid Mosberger-Tang 						!pdata->vbus_active_level);
17180d9b6d49SGustavo A. R. Silva 			fallthrough;
17192d53139fSDavid Mosberger 		default:
17202d53139fSDavid Mosberger 			max3421_hcd->port_status &= ~(1 << value);
17212d53139fSDavid Mosberger 		}
17222d53139fSDavid Mosberger 		break;
17232d53139fSDavid Mosberger 	case GetHubDescriptor:
17242d53139fSDavid Mosberger 		hub_descriptor((struct usb_hub_descriptor *) buf);
17252d53139fSDavid Mosberger 		break;
17262d53139fSDavid Mosberger 
17272d53139fSDavid Mosberger 	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
17282d53139fSDavid Mosberger 	case GetPortErrorCount:
17292d53139fSDavid Mosberger 	case SetHubDepth:
17302d53139fSDavid Mosberger 		/* USB3 only */
17312d53139fSDavid Mosberger 		goto error;
17322d53139fSDavid Mosberger 
17332d53139fSDavid Mosberger 	case GetHubStatus:
17342d53139fSDavid Mosberger 		*(__le32 *) buf = cpu_to_le32(0);
17352d53139fSDavid Mosberger 		break;
17362d53139fSDavid Mosberger 
17372d53139fSDavid Mosberger 	case GetPortStatus:
17382d53139fSDavid Mosberger 		if (index != 1) {
17392d53139fSDavid Mosberger 			retval = -EPIPE;
17402d53139fSDavid Mosberger 			goto error;
17412d53139fSDavid Mosberger 		}
17422d53139fSDavid Mosberger 		((__le16 *) buf)[0] = cpu_to_le16(max3421_hcd->port_status);
17432d53139fSDavid Mosberger 		((__le16 *) buf)[1] =
17442d53139fSDavid Mosberger 			cpu_to_le16(max3421_hcd->port_status >> 16);
17452d53139fSDavid Mosberger 		break;
17462d53139fSDavid Mosberger 
17472d53139fSDavid Mosberger 	case SetHubFeature:
17482d53139fSDavid Mosberger 		retval = -EPIPE;
17492d53139fSDavid Mosberger 		break;
17502d53139fSDavid Mosberger 
17512d53139fSDavid Mosberger 	case SetPortFeature:
17522d53139fSDavid Mosberger 		switch (value) {
17532d53139fSDavid Mosberger 		case USB_PORT_FEAT_LINK_STATE:
17542d53139fSDavid Mosberger 		case USB_PORT_FEAT_U1_TIMEOUT:
17552d53139fSDavid Mosberger 		case USB_PORT_FEAT_U2_TIMEOUT:
17562d53139fSDavid Mosberger 		case USB_PORT_FEAT_BH_PORT_RESET:
17572d53139fSDavid Mosberger 			goto error;
17582d53139fSDavid Mosberger 		case USB_PORT_FEAT_SUSPEND:
17592d53139fSDavid Mosberger 			if (max3421_hcd->active)
17602d53139fSDavid Mosberger 				max3421_hcd->port_status |=
17612d53139fSDavid Mosberger 					USB_PORT_STAT_SUSPEND;
17622d53139fSDavid Mosberger 			break;
17632d53139fSDavid Mosberger 		case USB_PORT_FEAT_POWER:
17642d53139fSDavid Mosberger 			dev_dbg(hcd->self.controller, "power-on\n");
17652d53139fSDavid Mosberger 			max3421_hcd->port_status |= USB_PORT_STAT_POWER;
17664055e5e5SDavid Mosberger-Tang 			max3421_gpout_set_value(hcd, pdata->vbus_gpout,
17674055e5e5SDavid Mosberger-Tang 						pdata->vbus_active_level);
17682d53139fSDavid Mosberger 			break;
17692d53139fSDavid Mosberger 		case USB_PORT_FEAT_RESET:
17702d53139fSDavid Mosberger 			max3421_reset_port(hcd);
17710d9b6d49SGustavo A. R. Silva 			fallthrough;
17722d53139fSDavid Mosberger 		default:
17732d53139fSDavid Mosberger 			if ((max3421_hcd->port_status & USB_PORT_STAT_POWER)
17742d53139fSDavid Mosberger 			    != 0)
17752d53139fSDavid Mosberger 				max3421_hcd->port_status |= (1 << value);
17762d53139fSDavid Mosberger 		}
17772d53139fSDavid Mosberger 		break;
17782d53139fSDavid Mosberger 
17792d53139fSDavid Mosberger 	default:
17802d53139fSDavid Mosberger 		dev_dbg(hcd->self.controller,
17812d53139fSDavid Mosberger 			"hub control req%04x v%04x i%04x l%d\n",
17822d53139fSDavid Mosberger 			type_req, value, index, length);
17832d53139fSDavid Mosberger error:		/* "protocol stall" on error */
17842d53139fSDavid Mosberger 		retval = -EPIPE;
17852d53139fSDavid Mosberger 	}
17862d53139fSDavid Mosberger 
17872d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
17882d53139fSDavid Mosberger 	return retval;
17892d53139fSDavid Mosberger }
17902d53139fSDavid Mosberger 
17912d53139fSDavid Mosberger static int
17922d53139fSDavid Mosberger max3421_bus_suspend(struct usb_hcd *hcd)
17932d53139fSDavid Mosberger {
17942d53139fSDavid Mosberger 	return -1;
17952d53139fSDavid Mosberger }
17962d53139fSDavid Mosberger 
17972d53139fSDavid Mosberger static int
17982d53139fSDavid Mosberger max3421_bus_resume(struct usb_hcd *hcd)
17992d53139fSDavid Mosberger {
18002d53139fSDavid Mosberger 	return -1;
18012d53139fSDavid Mosberger }
18022d53139fSDavid Mosberger 
1803887e2e0cSJulia Lawall static const struct hc_driver max3421_hcd_desc = {
18042d53139fSDavid Mosberger 	.description =		"max3421",
18052d53139fSDavid Mosberger 	.product_desc =		DRIVER_DESC,
18062d53139fSDavid Mosberger 	.hcd_priv_size =	sizeof(struct max3421_hcd),
18072d53139fSDavid Mosberger 	.flags =		HCD_USB11,
18082d53139fSDavid Mosberger 	.reset =		max3421_reset,
18092d53139fSDavid Mosberger 	.start =		max3421_start,
18102d53139fSDavid Mosberger 	.stop =			max3421_stop,
18112d53139fSDavid Mosberger 	.get_frame_number =	max3421_get_frame_number,
18122d53139fSDavid Mosberger 	.urb_enqueue =		max3421_urb_enqueue,
18132d53139fSDavid Mosberger 	.urb_dequeue =		max3421_urb_dequeue,
18142d53139fSDavid Mosberger 	.endpoint_disable =	max3421_endpoint_disable,
18152d53139fSDavid Mosberger 	.hub_status_data =	max3421_hub_status_data,
18162d53139fSDavid Mosberger 	.hub_control =		max3421_hub_control,
18172d53139fSDavid Mosberger 	.bus_suspend =		max3421_bus_suspend,
18182d53139fSDavid Mosberger 	.bus_resume =		max3421_bus_resume,
18192d53139fSDavid Mosberger };
18202d53139fSDavid Mosberger 
18212d53139fSDavid Mosberger static int
1822721fdc83SJules Maselbas max3421_of_vbus_en_pin(struct device *dev, struct max3421_hcd_platform_data *pdata)
1823721fdc83SJules Maselbas {
1824721fdc83SJules Maselbas 	int retval;
1825721fdc83SJules Maselbas 	uint32_t value[2];
1826721fdc83SJules Maselbas 
1827721fdc83SJules Maselbas 	if (!pdata)
1828721fdc83SJules Maselbas 		return -EINVAL;
1829721fdc83SJules Maselbas 
1830721fdc83SJules Maselbas 	retval = of_property_read_u32_array(dev->of_node, "maxim,vbus-en-pin", value, 2);
1831721fdc83SJules Maselbas 	if (retval) {
1832721fdc83SJules Maselbas 		dev_err(dev, "device tree node property 'maxim,vbus-en-pin' is missing\n");
1833721fdc83SJules Maselbas 		return retval;
1834721fdc83SJules Maselbas 	}
1835721fdc83SJules Maselbas 	dev_info(dev, "property 'maxim,vbus-en-pin' value is <%d %d>\n", value[0], value[1]);
1836721fdc83SJules Maselbas 
1837721fdc83SJules Maselbas 	pdata->vbus_gpout = value[0];
1838721fdc83SJules Maselbas 	pdata->vbus_active_level = value[1];
1839721fdc83SJules Maselbas 
1840721fdc83SJules Maselbas 	return 0;
1841721fdc83SJules Maselbas }
1842721fdc83SJules Maselbas 
1843721fdc83SJules Maselbas static int
18442d53139fSDavid Mosberger max3421_probe(struct spi_device *spi)
18452d53139fSDavid Mosberger {
1846721fdc83SJules Maselbas 	struct device *dev = &spi->dev;
18472d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd;
184805dfa5c9SDavid Mosberger-Tang 	struct usb_hcd *hcd = NULL;
1849721fdc83SJules Maselbas 	struct max3421_hcd_platform_data *pdata = NULL;
18505a569343SYang Yingliang 	int retval;
18512d53139fSDavid Mosberger 
18522d53139fSDavid Mosberger 	if (spi_setup(spi) < 0) {
18532d53139fSDavid Mosberger 		dev_err(&spi->dev, "Unable to setup SPI bus");
18542d53139fSDavid Mosberger 		return -EFAULT;
18552d53139fSDavid Mosberger 	}
18562d53139fSDavid Mosberger 
1857721fdc83SJules Maselbas 	if (!spi->irq) {
1858721fdc83SJules Maselbas 		dev_err(dev, "Failed to get SPI IRQ");
1859721fdc83SJules Maselbas 		return -EFAULT;
1860721fdc83SJules Maselbas 	}
1861721fdc83SJules Maselbas 
1862721fdc83SJules Maselbas 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
1863721fdc83SJules Maselbas 		pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL);
1864721fdc83SJules Maselbas 		if (!pdata) {
1865721fdc83SJules Maselbas 			retval = -ENOMEM;
1866721fdc83SJules Maselbas 			goto error;
1867721fdc83SJules Maselbas 		}
1868721fdc83SJules Maselbas 		retval = max3421_of_vbus_en_pin(dev, pdata);
1869721fdc83SJules Maselbas 		if (retval)
1870721fdc83SJules Maselbas 			goto error;
1871721fdc83SJules Maselbas 
1872721fdc83SJules Maselbas 		spi->dev.platform_data = pdata;
1873721fdc83SJules Maselbas 	}
1874721fdc83SJules Maselbas 
1875721fdc83SJules Maselbas 	pdata = spi->dev.platform_data;
1876721fdc83SJules Maselbas 	if (!pdata) {
1877721fdc83SJules Maselbas 		dev_err(&spi->dev, "driver configuration data is not provided\n");
1878721fdc83SJules Maselbas 		retval = -EFAULT;
1879721fdc83SJules Maselbas 		goto error;
1880721fdc83SJules Maselbas 	}
1881721fdc83SJules Maselbas 	if (pdata->vbus_active_level > 1) {
1882721fdc83SJules Maselbas 		dev_err(&spi->dev, "vbus active level value %d is out of range (0/1)\n", pdata->vbus_active_level);
1883721fdc83SJules Maselbas 		retval = -EINVAL;
1884721fdc83SJules Maselbas 		goto error;
1885721fdc83SJules Maselbas 	}
1886721fdc83SJules Maselbas 	if (pdata->vbus_gpout < 1 || pdata->vbus_gpout > MAX3421_GPOUT_COUNT) {
1887721fdc83SJules Maselbas 		dev_err(&spi->dev, "vbus gpout value %d is out of range (1..8)\n", pdata->vbus_gpout);
1888721fdc83SJules Maselbas 		retval = -EINVAL;
1889721fdc83SJules Maselbas 		goto error;
1890721fdc83SJules Maselbas 	}
1891721fdc83SJules Maselbas 
18925a569343SYang Yingliang 	retval = -ENOMEM;
18932d53139fSDavid Mosberger 	hcd = usb_create_hcd(&max3421_hcd_desc, &spi->dev,
18942d53139fSDavid Mosberger 			     dev_name(&spi->dev));
18952d53139fSDavid Mosberger 	if (!hcd) {
18962d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to create HCD structure\n");
189705dfa5c9SDavid Mosberger-Tang 		goto error;
18982d53139fSDavid Mosberger 	}
18992d53139fSDavid Mosberger 	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
19002d53139fSDavid Mosberger 	max3421_hcd = hcd_to_max3421(hcd);
19012d53139fSDavid Mosberger 	max3421_hcd->next = max3421_hcd_list;
19022d53139fSDavid Mosberger 	max3421_hcd_list = max3421_hcd;
19032d53139fSDavid Mosberger 	INIT_LIST_HEAD(&max3421_hcd->ep_list);
19042d53139fSDavid Mosberger 
190505dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL);
190613dcf780SWolfram Sang 	if (!max3421_hcd->tx)
190705dfa5c9SDavid Mosberger-Tang 		goto error;
190805dfa5c9SDavid Mosberger-Tang 	max3421_hcd->rx = kmalloc(sizeof(*max3421_hcd->rx), GFP_KERNEL);
190913dcf780SWolfram Sang 	if (!max3421_hcd->rx)
191005dfa5c9SDavid Mosberger-Tang 		goto error;
191105dfa5c9SDavid Mosberger-Tang 
19122d53139fSDavid Mosberger 	max3421_hcd->spi_thread = kthread_run(max3421_spi_thread, hcd,
19132d53139fSDavid Mosberger 					      "max3421_spi_thread");
19142d53139fSDavid Mosberger 	if (max3421_hcd->spi_thread == ERR_PTR(-ENOMEM)) {
19152d53139fSDavid Mosberger 		dev_err(&spi->dev,
19162d53139fSDavid Mosberger 			"failed to create SPI thread (out of memory)\n");
191705dfa5c9SDavid Mosberger-Tang 		goto error;
19182d53139fSDavid Mosberger 	}
19192d53139fSDavid Mosberger 
19202d53139fSDavid Mosberger 	retval = usb_add_hcd(hcd, 0, 0);
19212d53139fSDavid Mosberger 	if (retval) {
19222d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to add HCD\n");
192305dfa5c9SDavid Mosberger-Tang 		goto error;
19242d53139fSDavid Mosberger 	}
19252d53139fSDavid Mosberger 
19262d53139fSDavid Mosberger 	retval = request_irq(spi->irq, max3421_irq_handler,
19272d53139fSDavid Mosberger 			     IRQF_TRIGGER_LOW, "max3421", hcd);
19282d53139fSDavid Mosberger 	if (retval < 0) {
19292d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to request irq %d\n", spi->irq);
193005dfa5c9SDavid Mosberger-Tang 		goto error;
19312d53139fSDavid Mosberger 	}
19322d53139fSDavid Mosberger 	return 0;
193305dfa5c9SDavid Mosberger-Tang 
193405dfa5c9SDavid Mosberger-Tang error:
1935721fdc83SJules Maselbas 	if (IS_ENABLED(CONFIG_OF) && dev->of_node && pdata) {
1936721fdc83SJules Maselbas 		devm_kfree(&spi->dev, pdata);
1937721fdc83SJules Maselbas 		spi->dev.platform_data = NULL;
1938721fdc83SJules Maselbas 	}
1939721fdc83SJules Maselbas 
194005dfa5c9SDavid Mosberger-Tang 	if (hcd) {
194105dfa5c9SDavid Mosberger-Tang 		kfree(max3421_hcd->tx);
194205dfa5c9SDavid Mosberger-Tang 		kfree(max3421_hcd->rx);
194305dfa5c9SDavid Mosberger-Tang 		if (max3421_hcd->spi_thread)
194405dfa5c9SDavid Mosberger-Tang 			kthread_stop(max3421_hcd->spi_thread);
194505dfa5c9SDavid Mosberger-Tang 		usb_put_hcd(hcd);
194605dfa5c9SDavid Mosberger-Tang 	}
194705dfa5c9SDavid Mosberger-Tang 	return retval;
19482d53139fSDavid Mosberger }
19492d53139fSDavid Mosberger 
19502d53139fSDavid Mosberger static int
19512d53139fSDavid Mosberger max3421_remove(struct spi_device *spi)
19522d53139fSDavid Mosberger {
19532d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = NULL, **prev;
19542d53139fSDavid Mosberger 	struct usb_hcd *hcd = NULL;
19552d53139fSDavid Mosberger 	unsigned long flags;
19562d53139fSDavid Mosberger 
19572d53139fSDavid Mosberger 	for (prev = &max3421_hcd_list; *prev; prev = &(*prev)->next) {
19582d53139fSDavid Mosberger 		max3421_hcd = *prev;
19592d53139fSDavid Mosberger 		hcd = max3421_to_hcd(max3421_hcd);
19602d53139fSDavid Mosberger 		if (hcd->self.controller == &spi->dev)
19612d53139fSDavid Mosberger 			break;
19622d53139fSDavid Mosberger 	}
19632d53139fSDavid Mosberger 	if (!max3421_hcd) {
19642d53139fSDavid Mosberger 		dev_err(&spi->dev, "no MAX3421 HCD found for SPI device %p\n",
19652d53139fSDavid Mosberger 			spi);
19662d53139fSDavid Mosberger 		return -ENODEV;
19672d53139fSDavid Mosberger 	}
19682d53139fSDavid Mosberger 
19692d53139fSDavid Mosberger 	usb_remove_hcd(hcd);
19702d53139fSDavid Mosberger 
19712d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
19722d53139fSDavid Mosberger 
19732d53139fSDavid Mosberger 	kthread_stop(max3421_hcd->spi_thread);
19742d53139fSDavid Mosberger 	*prev = max3421_hcd->next;
19752d53139fSDavid Mosberger 
19762d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
19772d53139fSDavid Mosberger 
19782d53139fSDavid Mosberger 	free_irq(spi->irq, hcd);
19792d53139fSDavid Mosberger 
19802d53139fSDavid Mosberger 	usb_put_hcd(hcd);
19812d53139fSDavid Mosberger 	return 0;
19822d53139fSDavid Mosberger }
19832d53139fSDavid Mosberger 
1984721fdc83SJules Maselbas static const struct of_device_id max3421_of_match_table[] = {
1985721fdc83SJules Maselbas 	{ .compatible = "maxim,max3421", },
1986721fdc83SJules Maselbas 	{},
1987721fdc83SJules Maselbas };
1988721fdc83SJules Maselbas MODULE_DEVICE_TABLE(of, max3421_of_match_table);
1989721fdc83SJules Maselbas 
19902d53139fSDavid Mosberger static struct spi_driver max3421_driver = {
19912d53139fSDavid Mosberger 	.probe		= max3421_probe,
19922d53139fSDavid Mosberger 	.remove		= max3421_remove,
19932d53139fSDavid Mosberger 	.driver		= {
19942d53139fSDavid Mosberger 		.name	= "max3421-hcd",
1995721fdc83SJules Maselbas 		.of_match_table = of_match_ptr(max3421_of_match_table),
19962d53139fSDavid Mosberger 	},
19972d53139fSDavid Mosberger };
19982d53139fSDavid Mosberger 
19997df45d5fSSachin Kamat module_spi_driver(max3421_driver);
20002d53139fSDavid Mosberger 
20012d53139fSDavid Mosberger MODULE_DESCRIPTION(DRIVER_DESC);
20022d53139fSDavid Mosberger MODULE_AUTHOR("David Mosberger <davidm@egauge.net>");
20032d53139fSDavid Mosberger MODULE_LICENSE("GPL");
2004