xref: /openbmc/linux/drivers/usb/host/max3421-hcd.c (revision 658e467b)
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 #define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
762d53139fSDavid Mosberger 
772d53139fSDavid Mosberger /* Port-change mask: */
782d53139fSDavid Mosberger #define PORT_C_MASK	((USB_PORT_STAT_C_CONNECTION |	\
792d53139fSDavid Mosberger 			  USB_PORT_STAT_C_ENABLE |	\
802d53139fSDavid Mosberger 			  USB_PORT_STAT_C_SUSPEND |	\
812d53139fSDavid Mosberger 			  USB_PORT_STAT_C_OVERCURRENT | \
822d53139fSDavid Mosberger 			  USB_PORT_STAT_C_RESET) << 16)
832d53139fSDavid Mosberger 
84721fdc83SJules Maselbas #define MAX3421_GPOUT_COUNT	8
85721fdc83SJules Maselbas 
862d53139fSDavid Mosberger enum max3421_rh_state {
872d53139fSDavid Mosberger 	MAX3421_RH_RESET,
882d53139fSDavid Mosberger 	MAX3421_RH_SUSPENDED,
892d53139fSDavid Mosberger 	MAX3421_RH_RUNNING
902d53139fSDavid Mosberger };
912d53139fSDavid Mosberger 
922d53139fSDavid Mosberger enum pkt_state {
932d53139fSDavid Mosberger 	PKT_STATE_SETUP,	/* waiting to send setup packet to ctrl pipe */
942d53139fSDavid Mosberger 	PKT_STATE_TRANSFER,	/* waiting to xfer transfer_buffer */
952d53139fSDavid Mosberger 	PKT_STATE_TERMINATE	/* waiting to terminate control transfer */
962d53139fSDavid Mosberger };
972d53139fSDavid Mosberger 
982d53139fSDavid Mosberger enum scheduling_pass {
992d53139fSDavid Mosberger 	SCHED_PASS_PERIODIC,
1002d53139fSDavid Mosberger 	SCHED_PASS_NON_PERIODIC,
1012d53139fSDavid Mosberger 	SCHED_PASS_DONE
1022d53139fSDavid Mosberger };
1032d53139fSDavid Mosberger 
1042eb5dbddSDavid Mosberger-Tang /* Bit numbers for max3421_hcd->todo: */
1052eb5dbddSDavid Mosberger-Tang enum {
1062eb5dbddSDavid Mosberger-Tang 	ENABLE_IRQ = 0,
1072eb5dbddSDavid Mosberger-Tang 	RESET_HCD,
1082eb5dbddSDavid Mosberger-Tang 	RESET_PORT,
1092eb5dbddSDavid Mosberger-Tang 	CHECK_UNLINK,
1102eb5dbddSDavid Mosberger-Tang 	IOPIN_UPDATE
1112eb5dbddSDavid Mosberger-Tang };
1122eb5dbddSDavid Mosberger-Tang 
11305dfa5c9SDavid Mosberger-Tang struct max3421_dma_buf {
11405dfa5c9SDavid Mosberger-Tang 	u8 data[2];
11505dfa5c9SDavid Mosberger-Tang };
11605dfa5c9SDavid Mosberger-Tang 
1172d53139fSDavid Mosberger struct max3421_hcd {
1182d53139fSDavid Mosberger 	spinlock_t lock;
1192d53139fSDavid Mosberger 
1202d53139fSDavid Mosberger 	struct task_struct *spi_thread;
1212d53139fSDavid Mosberger 
1222d53139fSDavid Mosberger 	enum max3421_rh_state rh_state;
1232d53139fSDavid Mosberger 	/* lower 16 bits contain port status, upper 16 bits the change mask: */
1242d53139fSDavid Mosberger 	u32 port_status;
1252d53139fSDavid Mosberger 
1262d53139fSDavid Mosberger 	unsigned active:1;
1272d53139fSDavid Mosberger 
1282d53139fSDavid Mosberger 	struct list_head ep_list;	/* list of EP's with work */
1292d53139fSDavid Mosberger 
1302d53139fSDavid Mosberger 	/*
1312d53139fSDavid Mosberger 	 * The following are owned by spi_thread (may be accessed by
1322d53139fSDavid Mosberger 	 * SPI-thread without acquiring the HCD lock:
1332d53139fSDavid Mosberger 	 */
1342d53139fSDavid Mosberger 	u8 rev;				/* chip revision */
1352d53139fSDavid Mosberger 	u16 frame_number;
1362d53139fSDavid Mosberger 	/*
13705dfa5c9SDavid Mosberger-Tang 	 * kmalloc'd buffers guaranteed to be in separate (DMA)
13805dfa5c9SDavid Mosberger-Tang 	 * cache-lines:
13905dfa5c9SDavid Mosberger-Tang 	 */
14005dfa5c9SDavid Mosberger-Tang 	struct max3421_dma_buf *tx;
14105dfa5c9SDavid Mosberger-Tang 	struct max3421_dma_buf *rx;
14205dfa5c9SDavid Mosberger-Tang 	/*
1432d53139fSDavid Mosberger 	 * URB we're currently processing.  Must not be reset to NULL
1442d53139fSDavid Mosberger 	 * unless MAX3421E chip is idle:
1452d53139fSDavid Mosberger 	 */
1462d53139fSDavid Mosberger 	struct urb *curr_urb;
1472d53139fSDavid Mosberger 	enum scheduling_pass sched_pass;
1482d53139fSDavid Mosberger 	int urb_done;			/* > 0 -> no errors, < 0: errno */
1492d53139fSDavid Mosberger 	size_t curr_len;
1502d53139fSDavid Mosberger 	u8 hien;
1512d53139fSDavid Mosberger 	u8 mode;
1522d53139fSDavid Mosberger 	u8 iopins[2];
1532eb5dbddSDavid Mosberger-Tang 	unsigned long todo;
1542d53139fSDavid Mosberger #ifdef DEBUG
1552d53139fSDavid Mosberger 	unsigned long err_stat[16];
1562d53139fSDavid Mosberger #endif
1572d53139fSDavid Mosberger };
1582d53139fSDavid Mosberger 
1592d53139fSDavid Mosberger struct max3421_ep {
1602d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
1612d53139fSDavid Mosberger 	struct list_head ep_list;
1622d53139fSDavid Mosberger 	u32 naks;
1632d53139fSDavid Mosberger 	u16 last_active;		/* frame # this ep was last active */
1642d53139fSDavid Mosberger 	enum pkt_state pkt_state;
1652d53139fSDavid Mosberger 	u8 retries;
1662d53139fSDavid Mosberger 	u8 retransmit;			/* packet needs retransmission */
1672d53139fSDavid Mosberger };
1682d53139fSDavid Mosberger 
1692d53139fSDavid Mosberger #define MAX3421_FIFO_SIZE	64
1702d53139fSDavid Mosberger 
1712d53139fSDavid Mosberger #define MAX3421_SPI_DIR_RD	0	/* read register from MAX3421 */
1722d53139fSDavid Mosberger #define MAX3421_SPI_DIR_WR	1	/* write register to MAX3421 */
1732d53139fSDavid Mosberger 
1742d53139fSDavid Mosberger /* SPI commands: */
1752d53139fSDavid Mosberger #define MAX3421_SPI_DIR_SHIFT	1
1762d53139fSDavid Mosberger #define MAX3421_SPI_REG_SHIFT	3
1772d53139fSDavid Mosberger 
1782d53139fSDavid Mosberger #define MAX3421_REG_RCVFIFO	1
1792d53139fSDavid Mosberger #define MAX3421_REG_SNDFIFO	2
1802d53139fSDavid Mosberger #define MAX3421_REG_SUDFIFO	4
1812d53139fSDavid Mosberger #define MAX3421_REG_RCVBC	6
1822d53139fSDavid Mosberger #define MAX3421_REG_SNDBC	7
1832d53139fSDavid Mosberger #define MAX3421_REG_USBIRQ	13
1842d53139fSDavid Mosberger #define MAX3421_REG_USBIEN	14
1852d53139fSDavid Mosberger #define MAX3421_REG_USBCTL	15
1862d53139fSDavid Mosberger #define MAX3421_REG_CPUCTL	16
1872d53139fSDavid Mosberger #define MAX3421_REG_PINCTL	17
1882d53139fSDavid Mosberger #define MAX3421_REG_REVISION	18
1892d53139fSDavid Mosberger #define MAX3421_REG_IOPINS1	20
1902d53139fSDavid Mosberger #define MAX3421_REG_IOPINS2	21
1912d53139fSDavid Mosberger #define MAX3421_REG_GPINIRQ	22
1922d53139fSDavid Mosberger #define MAX3421_REG_GPINIEN	23
1932d53139fSDavid Mosberger #define MAX3421_REG_GPINPOL	24
1942d53139fSDavid Mosberger #define MAX3421_REG_HIRQ	25
1952d53139fSDavid Mosberger #define MAX3421_REG_HIEN	26
1962d53139fSDavid Mosberger #define MAX3421_REG_MODE	27
1972d53139fSDavid Mosberger #define MAX3421_REG_PERADDR	28
1982d53139fSDavid Mosberger #define MAX3421_REG_HCTL	29
1992d53139fSDavid Mosberger #define MAX3421_REG_HXFR	30
2002d53139fSDavid Mosberger #define MAX3421_REG_HRSL	31
2012d53139fSDavid Mosberger 
2022d53139fSDavid Mosberger enum {
2032d53139fSDavid Mosberger 	MAX3421_USBIRQ_OSCOKIRQ_BIT = 0,
2042d53139fSDavid Mosberger 	MAX3421_USBIRQ_NOVBUSIRQ_BIT = 5,
2052d53139fSDavid Mosberger 	MAX3421_USBIRQ_VBUSIRQ_BIT
2062d53139fSDavid Mosberger };
2072d53139fSDavid Mosberger 
2082d53139fSDavid Mosberger enum {
2092d53139fSDavid Mosberger 	MAX3421_CPUCTL_IE_BIT = 0,
2102d53139fSDavid Mosberger 	MAX3421_CPUCTL_PULSEWID0_BIT = 6,
2112d53139fSDavid Mosberger 	MAX3421_CPUCTL_PULSEWID1_BIT
2122d53139fSDavid Mosberger };
2132d53139fSDavid Mosberger 
2142d53139fSDavid Mosberger enum {
2152d53139fSDavid Mosberger 	MAX3421_USBCTL_PWRDOWN_BIT = 4,
2162d53139fSDavid Mosberger 	MAX3421_USBCTL_CHIPRES_BIT
2172d53139fSDavid Mosberger };
2182d53139fSDavid Mosberger 
2192d53139fSDavid Mosberger enum {
2202d53139fSDavid Mosberger 	MAX3421_PINCTL_GPXA_BIT	= 0,
2212d53139fSDavid Mosberger 	MAX3421_PINCTL_GPXB_BIT,
2222d53139fSDavid Mosberger 	MAX3421_PINCTL_POSINT_BIT,
2232d53139fSDavid Mosberger 	MAX3421_PINCTL_INTLEVEL_BIT,
2242d53139fSDavid Mosberger 	MAX3421_PINCTL_FDUPSPI_BIT,
2252d53139fSDavid Mosberger 	MAX3421_PINCTL_EP0INAK_BIT,
2262d53139fSDavid Mosberger 	MAX3421_PINCTL_EP2INAK_BIT,
2272d53139fSDavid Mosberger 	MAX3421_PINCTL_EP3INAK_BIT,
2282d53139fSDavid Mosberger };
2292d53139fSDavid Mosberger 
2302d53139fSDavid Mosberger enum {
2312d53139fSDavid Mosberger 	MAX3421_HI_BUSEVENT_BIT = 0,	/* bus-reset/-resume */
2322d53139fSDavid Mosberger 	MAX3421_HI_RWU_BIT,		/* remote wakeup */
2332d53139fSDavid Mosberger 	MAX3421_HI_RCVDAV_BIT,		/* receive FIFO data available */
2342d53139fSDavid Mosberger 	MAX3421_HI_SNDBAV_BIT,		/* send buffer available */
2352d53139fSDavid Mosberger 	MAX3421_HI_SUSDN_BIT,		/* suspend operation done */
2362d53139fSDavid Mosberger 	MAX3421_HI_CONDET_BIT,		/* peripheral connect/disconnect */
2372d53139fSDavid Mosberger 	MAX3421_HI_FRAME_BIT,		/* frame generator */
2382d53139fSDavid Mosberger 	MAX3421_HI_HXFRDN_BIT,		/* host transfer done */
2392d53139fSDavid Mosberger };
2402d53139fSDavid Mosberger 
2412d53139fSDavid Mosberger enum {
2422d53139fSDavid Mosberger 	MAX3421_HCTL_BUSRST_BIT = 0,
2432d53139fSDavid Mosberger 	MAX3421_HCTL_FRMRST_BIT,
2442d53139fSDavid Mosberger 	MAX3421_HCTL_SAMPLEBUS_BIT,
2452d53139fSDavid Mosberger 	MAX3421_HCTL_SIGRSM_BIT,
2462d53139fSDavid Mosberger 	MAX3421_HCTL_RCVTOG0_BIT,
2472d53139fSDavid Mosberger 	MAX3421_HCTL_RCVTOG1_BIT,
2482d53139fSDavid Mosberger 	MAX3421_HCTL_SNDTOG0_BIT,
2492d53139fSDavid Mosberger 	MAX3421_HCTL_SNDTOG1_BIT
2502d53139fSDavid Mosberger };
2512d53139fSDavid Mosberger 
2522d53139fSDavid Mosberger enum {
2532d53139fSDavid Mosberger 	MAX3421_MODE_HOST_BIT = 0,
2542d53139fSDavid Mosberger 	MAX3421_MODE_LOWSPEED_BIT,
2552d53139fSDavid Mosberger 	MAX3421_MODE_HUBPRE_BIT,
2562d53139fSDavid Mosberger 	MAX3421_MODE_SOFKAENAB_BIT,
2572d53139fSDavid Mosberger 	MAX3421_MODE_SEPIRQ_BIT,
2582d53139fSDavid Mosberger 	MAX3421_MODE_DELAYISO_BIT,
2592d53139fSDavid Mosberger 	MAX3421_MODE_DMPULLDN_BIT,
2602d53139fSDavid Mosberger 	MAX3421_MODE_DPPULLDN_BIT
2612d53139fSDavid Mosberger };
2622d53139fSDavid Mosberger 
2632d53139fSDavid Mosberger enum {
2642d53139fSDavid Mosberger 	MAX3421_HRSL_OK = 0,
2652d53139fSDavid Mosberger 	MAX3421_HRSL_BUSY,
2662d53139fSDavid Mosberger 	MAX3421_HRSL_BADREQ,
2672d53139fSDavid Mosberger 	MAX3421_HRSL_UNDEF,
2682d53139fSDavid Mosberger 	MAX3421_HRSL_NAK,
2692d53139fSDavid Mosberger 	MAX3421_HRSL_STALL,
2702d53139fSDavid Mosberger 	MAX3421_HRSL_TOGERR,
2712d53139fSDavid Mosberger 	MAX3421_HRSL_WRONGPID,
2722d53139fSDavid Mosberger 	MAX3421_HRSL_BADBC,
2732d53139fSDavid Mosberger 	MAX3421_HRSL_PIDERR,
2742d53139fSDavid Mosberger 	MAX3421_HRSL_PKTERR,
2752d53139fSDavid Mosberger 	MAX3421_HRSL_CRCERR,
2762d53139fSDavid Mosberger 	MAX3421_HRSL_KERR,
2772d53139fSDavid Mosberger 	MAX3421_HRSL_JERR,
2782d53139fSDavid Mosberger 	MAX3421_HRSL_TIMEOUT,
2792d53139fSDavid Mosberger 	MAX3421_HRSL_BABBLE,
2802d53139fSDavid Mosberger 	MAX3421_HRSL_RESULT_MASK = 0xf,
2812d53139fSDavid Mosberger 	MAX3421_HRSL_RCVTOGRD_BIT = 4,
2822d53139fSDavid Mosberger 	MAX3421_HRSL_SNDTOGRD_BIT,
2832d53139fSDavid Mosberger 	MAX3421_HRSL_KSTATUS_BIT,
2842d53139fSDavid Mosberger 	MAX3421_HRSL_JSTATUS_BIT
2852d53139fSDavid Mosberger };
2862d53139fSDavid Mosberger 
2872d53139fSDavid Mosberger /* Return same error-codes as ohci.h:cc_to_error: */
2882d53139fSDavid Mosberger static const int hrsl_to_error[] = {
2892d53139fSDavid Mosberger 	[MAX3421_HRSL_OK] =		0,
2902d53139fSDavid Mosberger 	[MAX3421_HRSL_BUSY] =		-EINVAL,
2912d53139fSDavid Mosberger 	[MAX3421_HRSL_BADREQ] =		-EINVAL,
2922d53139fSDavid Mosberger 	[MAX3421_HRSL_UNDEF] =		-EINVAL,
2932d53139fSDavid Mosberger 	[MAX3421_HRSL_NAK] =		-EAGAIN,
2942d53139fSDavid Mosberger 	[MAX3421_HRSL_STALL] =		-EPIPE,
2952d53139fSDavid Mosberger 	[MAX3421_HRSL_TOGERR] =		-EILSEQ,
2962d53139fSDavid Mosberger 	[MAX3421_HRSL_WRONGPID] =	-EPROTO,
2972d53139fSDavid Mosberger 	[MAX3421_HRSL_BADBC] =		-EREMOTEIO,
2982d53139fSDavid Mosberger 	[MAX3421_HRSL_PIDERR] =		-EPROTO,
2992d53139fSDavid Mosberger 	[MAX3421_HRSL_PKTERR] =		-EPROTO,
3002d53139fSDavid Mosberger 	[MAX3421_HRSL_CRCERR] =		-EILSEQ,
3012d53139fSDavid Mosberger 	[MAX3421_HRSL_KERR] =		-EIO,
3022d53139fSDavid Mosberger 	[MAX3421_HRSL_JERR] =		-EIO,
3032d53139fSDavid Mosberger 	[MAX3421_HRSL_TIMEOUT] =	-ETIME,
3042d53139fSDavid Mosberger 	[MAX3421_HRSL_BABBLE] =		-EOVERFLOW
3052d53139fSDavid Mosberger };
3062d53139fSDavid Mosberger 
3072d53139fSDavid Mosberger /*
308ffeb1e9eSAlexander A. Klimov  * See https://www.beyondlogic.org/usbnutshell/usb4.shtml#Control for a
309d46b4343SJiang Jian  * reasonable overview of how control transfers use the IN/OUT
3102d53139fSDavid Mosberger  * tokens.
3112d53139fSDavid Mosberger  */
3122d53139fSDavid Mosberger #define MAX3421_HXFR_BULK_IN(ep)	(0x00 | (ep))	/* bulk or interrupt */
3132d53139fSDavid Mosberger #define MAX3421_HXFR_SETUP		 0x10
3142d53139fSDavid Mosberger #define MAX3421_HXFR_BULK_OUT(ep)	(0x20 | (ep))	/* bulk or interrupt */
3152d53139fSDavid Mosberger #define MAX3421_HXFR_ISO_IN(ep)		(0x40 | (ep))
3162d53139fSDavid Mosberger #define MAX3421_HXFR_ISO_OUT(ep)	(0x60 | (ep))
3172d53139fSDavid Mosberger #define MAX3421_HXFR_HS_IN		 0x80		/* handshake in */
3182d53139fSDavid Mosberger #define MAX3421_HXFR_HS_OUT		 0xa0		/* handshake out */
3192d53139fSDavid Mosberger 
3202d53139fSDavid Mosberger #define field(val, bit)	((val) << (bit))
3212d53139fSDavid Mosberger 
3222d53139fSDavid Mosberger static inline s16
frame_diff(u16 left,u16 right)3232d53139fSDavid Mosberger frame_diff(u16 left, u16 right)
3242d53139fSDavid Mosberger {
3252d53139fSDavid Mosberger 	return ((unsigned) (left - right)) % (USB_MAX_FRAME_NUMBER + 1);
3262d53139fSDavid Mosberger }
3272d53139fSDavid Mosberger 
3282d53139fSDavid Mosberger static inline struct max3421_hcd *
hcd_to_max3421(struct usb_hcd * hcd)3292d53139fSDavid Mosberger hcd_to_max3421(struct usb_hcd *hcd)
3302d53139fSDavid Mosberger {
3312d53139fSDavid Mosberger 	return (struct max3421_hcd *) hcd->hcd_priv;
3322d53139fSDavid Mosberger }
3332d53139fSDavid Mosberger 
3342d53139fSDavid Mosberger static inline struct usb_hcd *
max3421_to_hcd(struct max3421_hcd * max3421_hcd)3352d53139fSDavid Mosberger max3421_to_hcd(struct max3421_hcd *max3421_hcd)
3362d53139fSDavid Mosberger {
3372d53139fSDavid Mosberger 	return container_of((void *) max3421_hcd, struct usb_hcd, hcd_priv);
3382d53139fSDavid Mosberger }
3392d53139fSDavid Mosberger 
3402d53139fSDavid Mosberger static u8
spi_rd8(struct usb_hcd * hcd,unsigned int reg)3412d53139fSDavid Mosberger spi_rd8(struct usb_hcd *hcd, unsigned int reg)
3422d53139fSDavid Mosberger {
34305dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
3442d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
3452d53139fSDavid Mosberger 	struct spi_transfer transfer;
3462d53139fSDavid Mosberger 	struct spi_message msg;
3472d53139fSDavid Mosberger 
3482d53139fSDavid Mosberger 	memset(&transfer, 0, sizeof(transfer));
3492d53139fSDavid Mosberger 
3502d53139fSDavid Mosberger 	spi_message_init(&msg);
3512d53139fSDavid Mosberger 
35205dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
35305dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
3542d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_RD, MAX3421_SPI_DIR_SHIFT));
3552d53139fSDavid Mosberger 
35605dfa5c9SDavid Mosberger-Tang 	transfer.tx_buf = max3421_hcd->tx->data;
35705dfa5c9SDavid Mosberger-Tang 	transfer.rx_buf = max3421_hcd->rx->data;
3582d53139fSDavid Mosberger 	transfer.len = 2;
3592d53139fSDavid Mosberger 
3602d53139fSDavid Mosberger 	spi_message_add_tail(&transfer, &msg);
3612d53139fSDavid Mosberger 	spi_sync(spi, &msg);
3622d53139fSDavid Mosberger 
36305dfa5c9SDavid Mosberger-Tang 	return max3421_hcd->rx->data[1];
3642d53139fSDavid Mosberger }
3652d53139fSDavid Mosberger 
3662d53139fSDavid Mosberger static void
spi_wr8(struct usb_hcd * hcd,unsigned int reg,u8 val)3672d53139fSDavid Mosberger spi_wr8(struct usb_hcd *hcd, unsigned int reg, u8 val)
3682d53139fSDavid Mosberger {
3692d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
37005dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
3712d53139fSDavid Mosberger 	struct spi_transfer transfer;
3722d53139fSDavid Mosberger 	struct spi_message msg;
3732d53139fSDavid Mosberger 
3742d53139fSDavid Mosberger 	memset(&transfer, 0, sizeof(transfer));
3752d53139fSDavid Mosberger 
3762d53139fSDavid Mosberger 	spi_message_init(&msg);
3772d53139fSDavid Mosberger 
37805dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
37905dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
3802d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_WR, MAX3421_SPI_DIR_SHIFT));
38105dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[1] = val;
3822d53139fSDavid Mosberger 
38305dfa5c9SDavid Mosberger-Tang 	transfer.tx_buf = max3421_hcd->tx->data;
3842d53139fSDavid Mosberger 	transfer.len = 2;
3852d53139fSDavid Mosberger 
3862d53139fSDavid Mosberger 	spi_message_add_tail(&transfer, &msg);
3872d53139fSDavid Mosberger 	spi_sync(spi, &msg);
3882d53139fSDavid Mosberger }
3892d53139fSDavid Mosberger 
3902d53139fSDavid Mosberger static void
spi_rd_buf(struct usb_hcd * hcd,unsigned int reg,void * buf,size_t len)3912d53139fSDavid Mosberger spi_rd_buf(struct usb_hcd *hcd, unsigned int reg, void *buf, size_t len)
3922d53139fSDavid Mosberger {
3932d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
39405dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
3952d53139fSDavid Mosberger 	struct spi_transfer transfer[2];
3962d53139fSDavid Mosberger 	struct spi_message msg;
3972d53139fSDavid Mosberger 
3982d53139fSDavid Mosberger 	memset(transfer, 0, sizeof(transfer));
3992d53139fSDavid Mosberger 
4002d53139fSDavid Mosberger 	spi_message_init(&msg);
4012d53139fSDavid Mosberger 
40205dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
40305dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
4042d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_RD, MAX3421_SPI_DIR_SHIFT));
40505dfa5c9SDavid Mosberger-Tang 	transfer[0].tx_buf = max3421_hcd->tx->data;
4062d53139fSDavid Mosberger 	transfer[0].len = 1;
4072d53139fSDavid Mosberger 
4082d53139fSDavid Mosberger 	transfer[1].rx_buf = buf;
4092d53139fSDavid Mosberger 	transfer[1].len = len;
4102d53139fSDavid Mosberger 
4112d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[0], &msg);
4122d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[1], &msg);
4132d53139fSDavid Mosberger 	spi_sync(spi, &msg);
4142d53139fSDavid Mosberger }
4152d53139fSDavid Mosberger 
4162d53139fSDavid Mosberger static void
spi_wr_buf(struct usb_hcd * hcd,unsigned int reg,void * buf,size_t len)4172d53139fSDavid Mosberger spi_wr_buf(struct usb_hcd *hcd, unsigned int reg, void *buf, size_t len)
4182d53139fSDavid Mosberger {
4192d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
42005dfa5c9SDavid Mosberger-Tang 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4212d53139fSDavid Mosberger 	struct spi_transfer transfer[2];
4222d53139fSDavid Mosberger 	struct spi_message msg;
4232d53139fSDavid Mosberger 
4242d53139fSDavid Mosberger 	memset(transfer, 0, sizeof(transfer));
4252d53139fSDavid Mosberger 
4262d53139fSDavid Mosberger 	spi_message_init(&msg);
4272d53139fSDavid Mosberger 
42805dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx->data[0] =
42905dfa5c9SDavid Mosberger-Tang 		(field(reg, MAX3421_SPI_REG_SHIFT) |
4302d53139fSDavid Mosberger 		 field(MAX3421_SPI_DIR_WR, MAX3421_SPI_DIR_SHIFT));
4312d53139fSDavid Mosberger 
43205dfa5c9SDavid Mosberger-Tang 	transfer[0].tx_buf = max3421_hcd->tx->data;
4332d53139fSDavid Mosberger 	transfer[0].len = 1;
4342d53139fSDavid Mosberger 
4352d53139fSDavid Mosberger 	transfer[1].tx_buf = buf;
4362d53139fSDavid Mosberger 	transfer[1].len = len;
4372d53139fSDavid Mosberger 
4382d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[0], &msg);
4392d53139fSDavid Mosberger 	spi_message_add_tail(&transfer[1], &msg);
4402d53139fSDavid Mosberger 	spi_sync(spi, &msg);
4412d53139fSDavid Mosberger }
4422d53139fSDavid Mosberger 
4432d53139fSDavid Mosberger /*
4442d53139fSDavid Mosberger  * Figure out the correct setting for the LOWSPEED and HUBPRE mode
4452d53139fSDavid Mosberger  * bits.  The HUBPRE bit needs to be set when MAX3421E operates at
4462d53139fSDavid Mosberger  * full speed, but it's talking to a low-speed device (i.e., through a
4472d53139fSDavid Mosberger  * hub).  Setting that bit ensures that every low-speed packet is
4482d53139fSDavid Mosberger  * preceded by a full-speed PRE PID.  Possible configurations:
4492d53139fSDavid Mosberger  *
4502d53139fSDavid Mosberger  * Hub speed:	Device speed:	=>	LOWSPEED bit:	HUBPRE bit:
4512d53139fSDavid Mosberger  *	FULL	FULL		=>	0		0
4522d53139fSDavid Mosberger  *	FULL	LOW		=>	1		1
4532d53139fSDavid Mosberger  *	LOW	LOW		=>	1		0
4542d53139fSDavid Mosberger  *	LOW	FULL		=>	1		0
4552d53139fSDavid Mosberger  */
4562d53139fSDavid Mosberger static void
max3421_set_speed(struct usb_hcd * hcd,struct usb_device * dev)4572d53139fSDavid Mosberger max3421_set_speed(struct usb_hcd *hcd, struct usb_device *dev)
4582d53139fSDavid Mosberger {
4592d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
4602d53139fSDavid Mosberger 	u8 mode_lowspeed, mode_hubpre, mode = max3421_hcd->mode;
4612d53139fSDavid Mosberger 
4622d53139fSDavid Mosberger 	mode_lowspeed = BIT(MAX3421_MODE_LOWSPEED_BIT);
4632d53139fSDavid Mosberger 	mode_hubpre   = BIT(MAX3421_MODE_HUBPRE_BIT);
4642d53139fSDavid Mosberger 	if (max3421_hcd->port_status & USB_PORT_STAT_LOW_SPEED) {
4652d53139fSDavid Mosberger 		mode |=  mode_lowspeed;
4662d53139fSDavid Mosberger 		mode &= ~mode_hubpre;
4672d53139fSDavid Mosberger 	} else if (dev->speed == USB_SPEED_LOW) {
4682d53139fSDavid Mosberger 		mode |= mode_lowspeed | mode_hubpre;
4692d53139fSDavid Mosberger 	} else {
4702d53139fSDavid Mosberger 		mode &= ~(mode_lowspeed | mode_hubpre);
4712d53139fSDavid Mosberger 	}
4722d53139fSDavid Mosberger 	if (mode != max3421_hcd->mode) {
4732d53139fSDavid Mosberger 		max3421_hcd->mode = mode;
4742d53139fSDavid Mosberger 		spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
4752d53139fSDavid Mosberger 	}
4762d53139fSDavid Mosberger 
4772d53139fSDavid Mosberger }
4782d53139fSDavid Mosberger 
4792d53139fSDavid Mosberger /*
4802d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
4812d53139fSDavid Mosberger  */
4822d53139fSDavid Mosberger static void
max3421_set_address(struct usb_hcd * hcd,struct usb_device * dev,int epnum)483b5fdf5c6SMark Tomlinson max3421_set_address(struct usb_hcd *hcd, struct usb_device *dev, int epnum)
4842d53139fSDavid Mosberger {
485b5fdf5c6SMark Tomlinson 	int rcvtog, sndtog;
4862d53139fSDavid Mosberger 	u8 hctl;
4872d53139fSDavid Mosberger 
4882d53139fSDavid Mosberger 	/* setup new endpoint's toggle bits: */
4892d53139fSDavid Mosberger 	rcvtog = usb_gettoggle(dev, epnum, 0);
4902d53139fSDavid Mosberger 	sndtog = usb_gettoggle(dev, epnum, 1);
4912d53139fSDavid Mosberger 	hctl = (BIT(rcvtog + MAX3421_HCTL_RCVTOG0_BIT) |
4922d53139fSDavid Mosberger 		BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT));
4932d53139fSDavid Mosberger 
4942d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, hctl);
4952d53139fSDavid Mosberger 
4962d53139fSDavid Mosberger 	/*
4972d53139fSDavid Mosberger 	 * Note: devnum for one and the same device can change during
4982d53139fSDavid Mosberger 	 * address-assignment so it's best to just always load the
4992d53139fSDavid Mosberger 	 * address whenever the end-point changed/was forced.
5002d53139fSDavid Mosberger 	 */
5012d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_PERADDR, dev->devnum);
5022d53139fSDavid Mosberger }
5032d53139fSDavid Mosberger 
5042d53139fSDavid Mosberger static int
max3421_ctrl_setup(struct usb_hcd * hcd,struct urb * urb)5052d53139fSDavid Mosberger max3421_ctrl_setup(struct usb_hcd *hcd, struct urb *urb)
5062d53139fSDavid Mosberger {
5072d53139fSDavid Mosberger 	spi_wr_buf(hcd, MAX3421_REG_SUDFIFO, urb->setup_packet, 8);
5082d53139fSDavid Mosberger 	return MAX3421_HXFR_SETUP;
5092d53139fSDavid Mosberger }
5102d53139fSDavid Mosberger 
5112d53139fSDavid Mosberger static int
max3421_transfer_in(struct usb_hcd * hcd,struct urb * urb)5122d53139fSDavid Mosberger max3421_transfer_in(struct usb_hcd *hcd, struct urb *urb)
5132d53139fSDavid Mosberger {
5142d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
5152d53139fSDavid Mosberger 	int epnum = usb_pipeendpoint(urb->pipe);
5162d53139fSDavid Mosberger 
5172d53139fSDavid Mosberger 	max3421_hcd->curr_len = 0;
5182d53139fSDavid Mosberger 	max3421_hcd->hien |= BIT(MAX3421_HI_RCVDAV_BIT);
5192d53139fSDavid Mosberger 	return MAX3421_HXFR_BULK_IN(epnum);
5202d53139fSDavid Mosberger }
5212d53139fSDavid Mosberger 
5222d53139fSDavid Mosberger static int
max3421_transfer_out(struct usb_hcd * hcd,struct urb * urb,int fast_retransmit)5232d53139fSDavid Mosberger max3421_transfer_out(struct usb_hcd *hcd, struct urb *urb, int fast_retransmit)
5242d53139fSDavid Mosberger {
5252d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
5262d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
5272d53139fSDavid Mosberger 	int epnum = usb_pipeendpoint(urb->pipe);
5282d53139fSDavid Mosberger 	u32 max_packet;
5292d53139fSDavid Mosberger 	void *src;
5302d53139fSDavid Mosberger 
5312d53139fSDavid Mosberger 	src = urb->transfer_buffer + urb->actual_length;
5322d53139fSDavid Mosberger 
5332d53139fSDavid Mosberger 	if (fast_retransmit) {
5342d53139fSDavid Mosberger 		if (max3421_hcd->rev == 0x12) {
5352d53139fSDavid Mosberger 			/* work around rev 0x12 bug: */
5362d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDBC, 0);
5372d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDFIFO, ((u8 *) src)[0]);
5382d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_SNDBC, max3421_hcd->curr_len);
5392d53139fSDavid Mosberger 		}
5402d53139fSDavid Mosberger 		return MAX3421_HXFR_BULK_OUT(epnum);
5412d53139fSDavid Mosberger 	}
5422d53139fSDavid Mosberger 
543dcd2e49bSVincent Mailhol 	max_packet = usb_maxpacket(urb->dev, urb->pipe);
5442d53139fSDavid Mosberger 
5452d53139fSDavid Mosberger 	if (max_packet > MAX3421_FIFO_SIZE) {
5462d53139fSDavid Mosberger 		/*
5472d53139fSDavid Mosberger 		 * We do not support isochronous transfers at this
5482d53139fSDavid Mosberger 		 * time.
5492d53139fSDavid Mosberger 		 */
5502d53139fSDavid Mosberger 		dev_err(&spi->dev,
5512d53139fSDavid Mosberger 			"%s: packet-size of %u too big (limit is %u bytes)",
5522d53139fSDavid Mosberger 			__func__, max_packet, MAX3421_FIFO_SIZE);
5532d53139fSDavid Mosberger 		max3421_hcd->urb_done = -EMSGSIZE;
5542d53139fSDavid Mosberger 		return -EMSGSIZE;
5552d53139fSDavid Mosberger 	}
5562d53139fSDavid Mosberger 	max3421_hcd->curr_len = min((urb->transfer_buffer_length -
5572d53139fSDavid Mosberger 				     urb->actual_length), max_packet);
5582d53139fSDavid Mosberger 
5592d53139fSDavid Mosberger 	spi_wr_buf(hcd, MAX3421_REG_SNDFIFO, src, max3421_hcd->curr_len);
5602d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_SNDBC, max3421_hcd->curr_len);
5612d53139fSDavid Mosberger 	return MAX3421_HXFR_BULK_OUT(epnum);
5622d53139fSDavid Mosberger }
5632d53139fSDavid Mosberger 
5642d53139fSDavid Mosberger /*
5652d53139fSDavid Mosberger  * Issue the next host-transfer command.
5662d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
5672d53139fSDavid Mosberger  */
5682d53139fSDavid Mosberger static void
max3421_next_transfer(struct usb_hcd * hcd,int fast_retransmit)5692d53139fSDavid Mosberger max3421_next_transfer(struct usb_hcd *hcd, int fast_retransmit)
5702d53139fSDavid Mosberger {
5712d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
5722d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
573f9da25c7SDavid Mosberger-Tang 	struct max3421_ep *max3421_ep;
5742d53139fSDavid Mosberger 	int cmd = -EINVAL;
5752d53139fSDavid Mosberger 
5762d53139fSDavid Mosberger 	if (!urb)
5772d53139fSDavid Mosberger 		return;	/* nothing to do */
5782d53139fSDavid Mosberger 
579f9da25c7SDavid Mosberger-Tang 	max3421_ep = urb->ep->hcpriv;
580f9da25c7SDavid Mosberger-Tang 
5812d53139fSDavid Mosberger 	switch (max3421_ep->pkt_state) {
5822d53139fSDavid Mosberger 	case PKT_STATE_SETUP:
5832d53139fSDavid Mosberger 		cmd = max3421_ctrl_setup(hcd, urb);
5842d53139fSDavid Mosberger 		break;
5852d53139fSDavid Mosberger 
5862d53139fSDavid Mosberger 	case PKT_STATE_TRANSFER:
5872d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
5882d53139fSDavid Mosberger 			cmd = max3421_transfer_in(hcd, urb);
5892d53139fSDavid Mosberger 		else
5902d53139fSDavid Mosberger 			cmd = max3421_transfer_out(hcd, urb, fast_retransmit);
5912d53139fSDavid Mosberger 		break;
5922d53139fSDavid Mosberger 
5932d53139fSDavid Mosberger 	case PKT_STATE_TERMINATE:
5942d53139fSDavid Mosberger 		/*
5952d53139fSDavid Mosberger 		 * IN transfers are terminated with HS_OUT token,
5962d53139fSDavid Mosberger 		 * OUT transfers with HS_IN:
5972d53139fSDavid Mosberger 		 */
5982d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
5992d53139fSDavid Mosberger 			cmd = MAX3421_HXFR_HS_OUT;
6002d53139fSDavid Mosberger 		else
6012d53139fSDavid Mosberger 			cmd = MAX3421_HXFR_HS_IN;
6022d53139fSDavid Mosberger 		break;
6032d53139fSDavid Mosberger 	}
6042d53139fSDavid Mosberger 
6052d53139fSDavid Mosberger 	if (cmd < 0)
6062d53139fSDavid Mosberger 		return;
6072d53139fSDavid Mosberger 
6082d53139fSDavid Mosberger 	/* issue the command and wait for host-xfer-done interrupt: */
6092d53139fSDavid Mosberger 
6102d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HXFR, cmd);
6112d53139fSDavid Mosberger 	max3421_hcd->hien |= BIT(MAX3421_HI_HXFRDN_BIT);
6122d53139fSDavid Mosberger }
6132d53139fSDavid Mosberger 
6142d53139fSDavid Mosberger /*
6152d53139fSDavid Mosberger  * Find the next URB to process and start its execution.
6162d53139fSDavid Mosberger  *
6172d53139fSDavid Mosberger  * At this time, we do not anticipate ever connecting a USB hub to the
6182d53139fSDavid Mosberger  * MAX3421 chip, so at most USB device can be connected and we can use
6192d53139fSDavid Mosberger  * a simplistic scheduler: at the start of a frame, schedule all
6202d53139fSDavid Mosberger  * periodic transfers.  Once that is done, use the remainder of the
6212d53139fSDavid Mosberger  * frame to process non-periodic (bulk & control) transfers.
6222d53139fSDavid Mosberger  *
6232d53139fSDavid Mosberger  * Preconditions:
6242d53139fSDavid Mosberger  * o Caller must NOT hold HCD spinlock.
6252d53139fSDavid Mosberger  * o max3421_hcd->curr_urb MUST BE NULL.
6262d53139fSDavid Mosberger  * o MAX3421E chip must be idle.
6272d53139fSDavid Mosberger  */
6282d53139fSDavid Mosberger static int
max3421_select_and_start_urb(struct usb_hcd * hcd)6292d53139fSDavid Mosberger max3421_select_and_start_urb(struct usb_hcd *hcd)
6302d53139fSDavid Mosberger {
6312d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
6322d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
6332d53139fSDavid Mosberger 	struct urb *urb, *curr_urb = NULL;
6342d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
635b5fdf5c6SMark Tomlinson 	int epnum;
6362d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
6372d53139fSDavid Mosberger 	struct list_head *pos;
6382d53139fSDavid Mosberger 	unsigned long flags;
6392d53139fSDavid Mosberger 
6402d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
6412d53139fSDavid Mosberger 
6422d53139fSDavid Mosberger 	for (;
6432d53139fSDavid Mosberger 	     max3421_hcd->sched_pass < SCHED_PASS_DONE;
6442d53139fSDavid Mosberger 	     ++max3421_hcd->sched_pass)
6452d53139fSDavid Mosberger 		list_for_each(pos, &max3421_hcd->ep_list) {
6462d53139fSDavid Mosberger 			urb = NULL;
6472d53139fSDavid Mosberger 			max3421_ep = container_of(pos, struct max3421_ep,
6482d53139fSDavid Mosberger 						  ep_list);
6492d53139fSDavid Mosberger 			ep = max3421_ep->ep;
6502d53139fSDavid Mosberger 
6512d53139fSDavid Mosberger 			switch (usb_endpoint_type(&ep->desc)) {
6522d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_ISOC:
6532d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_INT:
6542d53139fSDavid Mosberger 				if (max3421_hcd->sched_pass !=
6552d53139fSDavid Mosberger 				    SCHED_PASS_PERIODIC)
6562d53139fSDavid Mosberger 					continue;
6572d53139fSDavid Mosberger 				break;
6582d53139fSDavid Mosberger 
6592d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_CONTROL:
6602d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_BULK:
6612d53139fSDavid Mosberger 				if (max3421_hcd->sched_pass !=
6622d53139fSDavid Mosberger 				    SCHED_PASS_NON_PERIODIC)
6632d53139fSDavid Mosberger 					continue;
6642d53139fSDavid Mosberger 				break;
6652d53139fSDavid Mosberger 			}
6662d53139fSDavid Mosberger 
6672d53139fSDavid Mosberger 			if (list_empty(&ep->urb_list))
6682d53139fSDavid Mosberger 				continue;	/* nothing to do */
6692d53139fSDavid Mosberger 			urb = list_first_entry(&ep->urb_list, struct urb,
6702d53139fSDavid Mosberger 					       urb_list);
6712d53139fSDavid Mosberger 			if (urb->unlinked) {
6722d53139fSDavid Mosberger 				dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
6732d53139fSDavid Mosberger 					__func__, urb, urb->unlinked);
6742d53139fSDavid Mosberger 				max3421_hcd->curr_urb = urb;
6752d53139fSDavid Mosberger 				max3421_hcd->urb_done = 1;
6762d53139fSDavid Mosberger 				spin_unlock_irqrestore(&max3421_hcd->lock,
6772d53139fSDavid Mosberger 						       flags);
6782d53139fSDavid Mosberger 				return 1;
6792d53139fSDavid Mosberger 			}
6802d53139fSDavid Mosberger 
6812d53139fSDavid Mosberger 			switch (usb_endpoint_type(&ep->desc)) {
6822d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_CONTROL:
6832d53139fSDavid Mosberger 				/*
6842d53139fSDavid Mosberger 				 * Allow one control transaction per
6852d53139fSDavid Mosberger 				 * frame per endpoint:
6862d53139fSDavid Mosberger 				 */
6872d53139fSDavid Mosberger 				if (frame_diff(max3421_ep->last_active,
6882d53139fSDavid Mosberger 					       max3421_hcd->frame_number) == 0)
6892d53139fSDavid Mosberger 					continue;
6902d53139fSDavid Mosberger 				break;
6912d53139fSDavid Mosberger 
6922d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_BULK:
6932d53139fSDavid Mosberger 				if (max3421_ep->retransmit
6942d53139fSDavid Mosberger 				    && (frame_diff(max3421_ep->last_active,
6952d53139fSDavid Mosberger 						   max3421_hcd->frame_number)
6962d53139fSDavid Mosberger 					== 0))
6972d53139fSDavid Mosberger 					/*
6982d53139fSDavid Mosberger 					 * We already tried this EP
6992d53139fSDavid Mosberger 					 * during this frame and got a
7002d53139fSDavid Mosberger 					 * NAK or error; wait for next frame
7012d53139fSDavid Mosberger 					 */
7022d53139fSDavid Mosberger 					continue;
7032d53139fSDavid Mosberger 				break;
7042d53139fSDavid Mosberger 
7052d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_ISOC:
7062d53139fSDavid Mosberger 			case USB_ENDPOINT_XFER_INT:
7072d53139fSDavid Mosberger 				if (frame_diff(max3421_hcd->frame_number,
7082d53139fSDavid Mosberger 					       max3421_ep->last_active)
7092d53139fSDavid Mosberger 				    < urb->interval)
7102d53139fSDavid Mosberger 					/*
7112d53139fSDavid Mosberger 					 * We already processed this
7122d53139fSDavid Mosberger 					 * end-point in the current
7132d53139fSDavid Mosberger 					 * frame
7142d53139fSDavid Mosberger 					 */
7152d53139fSDavid Mosberger 					continue;
7162d53139fSDavid Mosberger 				break;
7172d53139fSDavid Mosberger 			}
7182d53139fSDavid Mosberger 
7192d53139fSDavid Mosberger 			/* move current ep to tail: */
7202d53139fSDavid Mosberger 			list_move_tail(pos, &max3421_hcd->ep_list);
7212d53139fSDavid Mosberger 			curr_urb = urb;
7222d53139fSDavid Mosberger 			goto done;
7232d53139fSDavid Mosberger 		}
7242d53139fSDavid Mosberger done:
7252d53139fSDavid Mosberger 	if (!curr_urb) {
7262d53139fSDavid Mosberger 		spin_unlock_irqrestore(&max3421_hcd->lock, flags);
7272d53139fSDavid Mosberger 		return 0;
7282d53139fSDavid Mosberger 	}
7292d53139fSDavid Mosberger 
7302d53139fSDavid Mosberger 	urb = max3421_hcd->curr_urb = curr_urb;
7312d53139fSDavid Mosberger 	epnum = usb_endpoint_num(&urb->ep->desc);
7322d53139fSDavid Mosberger 	if (max3421_ep->retransmit)
7332d53139fSDavid Mosberger 		/* restart (part of) a USB transaction: */
7342d53139fSDavid Mosberger 		max3421_ep->retransmit = 0;
7352d53139fSDavid Mosberger 	else {
7362d53139fSDavid Mosberger 		/* start USB transaction: */
7372d53139fSDavid Mosberger 		if (usb_endpoint_xfer_control(&ep->desc)) {
7382d53139fSDavid Mosberger 			/*
7392d53139fSDavid Mosberger 			 * See USB 2.0 spec section 8.6.1
7402d53139fSDavid Mosberger 			 * Initialization via SETUP Token:
7412d53139fSDavid Mosberger 			 */
7422d53139fSDavid Mosberger 			usb_settoggle(urb->dev, epnum, 0, 1);
7432d53139fSDavid Mosberger 			usb_settoggle(urb->dev, epnum, 1, 1);
7442d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_SETUP;
7452d53139fSDavid Mosberger 		} else
7462d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TRANSFER;
7472d53139fSDavid Mosberger 	}
7482d53139fSDavid Mosberger 
7492d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
7502d53139fSDavid Mosberger 
7512d53139fSDavid Mosberger 	max3421_ep->last_active = max3421_hcd->frame_number;
752b5fdf5c6SMark Tomlinson 	max3421_set_address(hcd, urb->dev, epnum);
7532d53139fSDavid Mosberger 	max3421_set_speed(hcd, urb->dev);
7542d53139fSDavid Mosberger 	max3421_next_transfer(hcd, 0);
7552d53139fSDavid Mosberger 	return 1;
7562d53139fSDavid Mosberger }
7572d53139fSDavid Mosberger 
7582d53139fSDavid Mosberger /*
7592d53139fSDavid Mosberger  * Check all endpoints for URBs that got unlinked.
7602d53139fSDavid Mosberger  *
7612d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
7622d53139fSDavid Mosberger  */
7632d53139fSDavid Mosberger static int
max3421_check_unlink(struct usb_hcd * hcd)7642d53139fSDavid Mosberger max3421_check_unlink(struct usb_hcd *hcd)
7652d53139fSDavid Mosberger {
7662d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
7672d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
7682d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
7692d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
770553c2360SGeliang Tang 	struct urb *urb, *next;
7712d53139fSDavid Mosberger 	unsigned long flags;
7722d53139fSDavid Mosberger 	int retval = 0;
7732d53139fSDavid Mosberger 
7742d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
775553c2360SGeliang Tang 	list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) {
7762d53139fSDavid Mosberger 		ep = max3421_ep->ep;
777553c2360SGeliang Tang 		list_for_each_entry_safe(urb, next, &ep->urb_list, urb_list) {
7782d53139fSDavid Mosberger 			if (urb->unlinked) {
7792d53139fSDavid Mosberger 				retval = 1;
7802d53139fSDavid Mosberger 				dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
7812d53139fSDavid Mosberger 					__func__, urb, urb->unlinked);
7822d53139fSDavid Mosberger 				usb_hcd_unlink_urb_from_ep(hcd, urb);
7832d53139fSDavid Mosberger 				spin_unlock_irqrestore(&max3421_hcd->lock,
7842d53139fSDavid Mosberger 						       flags);
7852d53139fSDavid Mosberger 				usb_hcd_giveback_urb(hcd, urb, 0);
7862d53139fSDavid Mosberger 				spin_lock_irqsave(&max3421_hcd->lock, flags);
7872d53139fSDavid Mosberger 			}
7882d53139fSDavid Mosberger 		}
7892d53139fSDavid Mosberger 	}
7902d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
7912d53139fSDavid Mosberger 	return retval;
7922d53139fSDavid Mosberger }
7932d53139fSDavid Mosberger 
7942d53139fSDavid Mosberger /*
7952d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
7962d53139fSDavid Mosberger  */
7972d53139fSDavid Mosberger static void
max3421_slow_retransmit(struct usb_hcd * hcd)7982d53139fSDavid Mosberger max3421_slow_retransmit(struct usb_hcd *hcd)
7992d53139fSDavid Mosberger {
8002d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8012d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8022d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
8032d53139fSDavid Mosberger 
8042d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
8052d53139fSDavid Mosberger 	max3421_ep->retransmit = 1;
8062d53139fSDavid Mosberger 	max3421_hcd->curr_urb = NULL;
8072d53139fSDavid Mosberger }
8082d53139fSDavid Mosberger 
8092d53139fSDavid Mosberger /*
8102d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
8112d53139fSDavid Mosberger  */
8122d53139fSDavid Mosberger static void
max3421_recv_data_available(struct usb_hcd * hcd)8132d53139fSDavid Mosberger max3421_recv_data_available(struct usb_hcd *hcd)
8142d53139fSDavid Mosberger {
8152d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8162d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8172d53139fSDavid Mosberger 	size_t remaining, transfer_size;
8182d53139fSDavid Mosberger 	u8 rcvbc;
8192d53139fSDavid Mosberger 
8202d53139fSDavid Mosberger 	rcvbc = spi_rd8(hcd, MAX3421_REG_RCVBC);
8212d53139fSDavid Mosberger 
8222d53139fSDavid Mosberger 	if (rcvbc > MAX3421_FIFO_SIZE)
8232d53139fSDavid Mosberger 		rcvbc = MAX3421_FIFO_SIZE;
8242d53139fSDavid Mosberger 	if (urb->actual_length >= urb->transfer_buffer_length)
8252d53139fSDavid Mosberger 		remaining = 0;
8262d53139fSDavid Mosberger 	else
8272d53139fSDavid Mosberger 		remaining = urb->transfer_buffer_length - urb->actual_length;
8282d53139fSDavid Mosberger 	transfer_size = rcvbc;
8292d53139fSDavid Mosberger 	if (transfer_size > remaining)
8302d53139fSDavid Mosberger 		transfer_size = remaining;
8312d53139fSDavid Mosberger 	if (transfer_size > 0) {
8322d53139fSDavid Mosberger 		void *dst = urb->transfer_buffer + urb->actual_length;
8332d53139fSDavid Mosberger 
8342d53139fSDavid Mosberger 		spi_rd_buf(hcd, MAX3421_REG_RCVFIFO, dst, transfer_size);
8352d53139fSDavid Mosberger 		urb->actual_length += transfer_size;
8362d53139fSDavid Mosberger 		max3421_hcd->curr_len = transfer_size;
8372d53139fSDavid Mosberger 	}
8382d53139fSDavid Mosberger 
8392d53139fSDavid Mosberger 	/* ack the RCVDAV irq now that the FIFO has been read: */
8402d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIRQ, BIT(MAX3421_HI_RCVDAV_BIT));
8412d53139fSDavid Mosberger }
8422d53139fSDavid Mosberger 
8432d53139fSDavid Mosberger static void
max3421_handle_error(struct usb_hcd * hcd,u8 hrsl)8442d53139fSDavid Mosberger max3421_handle_error(struct usb_hcd *hcd, u8 hrsl)
8452d53139fSDavid Mosberger {
8462d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
8472d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
8482d53139fSDavid Mosberger 	u8 result_code = hrsl & MAX3421_HRSL_RESULT_MASK;
8492d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
8502d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep = urb->ep->hcpriv;
8512d53139fSDavid Mosberger 	int switch_sndfifo;
8522d53139fSDavid Mosberger 
8532d53139fSDavid Mosberger 	/*
8542d53139fSDavid Mosberger 	 * If an OUT command results in any response other than OK
8552d53139fSDavid Mosberger 	 * (i.e., error or NAK), we have to perform a dummy-write to
8562d53139fSDavid Mosberger 	 * SNDBC so the FIFO gets switched back to us.  Otherwise, we
8572d53139fSDavid Mosberger 	 * get out of sync with the SNDFIFO double buffer.
8582d53139fSDavid Mosberger 	 */
8592d53139fSDavid Mosberger 	switch_sndfifo = (max3421_ep->pkt_state == PKT_STATE_TRANSFER &&
8602d53139fSDavid Mosberger 			  usb_urb_dir_out(urb));
8612d53139fSDavid Mosberger 
8622d53139fSDavid Mosberger 	switch (result_code) {
8632d53139fSDavid Mosberger 	case MAX3421_HRSL_OK:
8642d53139fSDavid Mosberger 		return;			/* this shouldn't happen */
8652d53139fSDavid Mosberger 
8662d53139fSDavid Mosberger 	case MAX3421_HRSL_WRONGPID:	/* received wrong PID */
8672d53139fSDavid Mosberger 	case MAX3421_HRSL_BUSY:		/* SIE busy */
8682d53139fSDavid Mosberger 	case MAX3421_HRSL_BADREQ:	/* bad val in HXFR */
8692d53139fSDavid Mosberger 	case MAX3421_HRSL_UNDEF:	/* reserved */
8702d53139fSDavid Mosberger 	case MAX3421_HRSL_KERR:		/* K-state instead of response */
8712d53139fSDavid Mosberger 	case MAX3421_HRSL_JERR:		/* J-state instead of response */
8722d53139fSDavid Mosberger 		/*
8732d53139fSDavid Mosberger 		 * packet experienced an error that we cannot recover
8742d53139fSDavid Mosberger 		 * from; report error
8752d53139fSDavid Mosberger 		 */
8762d53139fSDavid Mosberger 		max3421_hcd->urb_done = hrsl_to_error[result_code];
8772d53139fSDavid Mosberger 		dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
8782d53139fSDavid Mosberger 			__func__, hrsl);
8792d53139fSDavid Mosberger 		break;
8802d53139fSDavid Mosberger 
8812d53139fSDavid Mosberger 	case MAX3421_HRSL_TOGERR:
8822d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
8832d53139fSDavid Mosberger 			; /* don't do anything (device will switch toggle) */
8842d53139fSDavid Mosberger 		else {
8852d53139fSDavid Mosberger 			/* flip the send toggle bit: */
8862d53139fSDavid Mosberger 			int sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
8872d53139fSDavid Mosberger 
8882d53139fSDavid Mosberger 			sndtog ^= 1;
8892d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HCTL,
8902d53139fSDavid Mosberger 				BIT(sndtog + MAX3421_HCTL_SNDTOG0_BIT));
8912d53139fSDavid Mosberger 		}
8920d9b6d49SGustavo A. R. Silva 		fallthrough;
8932d53139fSDavid Mosberger 	case MAX3421_HRSL_BADBC:	/* bad byte count */
8942d53139fSDavid Mosberger 	case MAX3421_HRSL_PIDERR:	/* received PID is corrupted */
8952d53139fSDavid Mosberger 	case MAX3421_HRSL_PKTERR:	/* packet error (stuff, EOP) */
8962d53139fSDavid Mosberger 	case MAX3421_HRSL_CRCERR:	/* CRC error */
8972d53139fSDavid Mosberger 	case MAX3421_HRSL_BABBLE:	/* device talked too long */
8982d53139fSDavid Mosberger 	case MAX3421_HRSL_TIMEOUT:
8992d53139fSDavid Mosberger 		if (max3421_ep->retries++ < USB_MAX_RETRIES)
9002d53139fSDavid Mosberger 			/* retry the packet again in the next frame */
9012d53139fSDavid Mosberger 			max3421_slow_retransmit(hcd);
9022d53139fSDavid Mosberger 		else {
9032d53139fSDavid Mosberger 			/* Based on ohci.h cc_to_err[]: */
9042d53139fSDavid Mosberger 			max3421_hcd->urb_done = hrsl_to_error[result_code];
9052d53139fSDavid Mosberger 			dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
9062d53139fSDavid Mosberger 				__func__, hrsl);
9072d53139fSDavid Mosberger 		}
9082d53139fSDavid Mosberger 		break;
9092d53139fSDavid Mosberger 
9102d53139fSDavid Mosberger 	case MAX3421_HRSL_STALL:
9112d53139fSDavid Mosberger 		dev_dbg(&spi->dev, "%s: unexpected error HRSL=0x%02x",
9122d53139fSDavid Mosberger 			__func__, hrsl);
9132d53139fSDavid Mosberger 		max3421_hcd->urb_done = hrsl_to_error[result_code];
9142d53139fSDavid Mosberger 		break;
9152d53139fSDavid Mosberger 
9162d53139fSDavid Mosberger 	case MAX3421_HRSL_NAK:
9172d53139fSDavid Mosberger 		/*
9182d53139fSDavid Mosberger 		 * Device wasn't ready for data or has no data
9192d53139fSDavid Mosberger 		 * available: retry the packet again.
9202d53139fSDavid Mosberger 		 */
9212d53139fSDavid Mosberger 		max3421_next_transfer(hcd, 1);
9222d53139fSDavid Mosberger 		switch_sndfifo = 0;
9232d53139fSDavid Mosberger 		break;
9242d53139fSDavid Mosberger 	}
9252d53139fSDavid Mosberger 	if (switch_sndfifo)
9262d53139fSDavid Mosberger 		spi_wr8(hcd, MAX3421_REG_SNDBC, 0);
9272d53139fSDavid Mosberger }
9282d53139fSDavid Mosberger 
9292d53139fSDavid Mosberger /*
9302d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
9312d53139fSDavid Mosberger  */
9322d53139fSDavid Mosberger static int
max3421_transfer_in_done(struct usb_hcd * hcd,struct urb * urb)9332d53139fSDavid Mosberger max3421_transfer_in_done(struct usb_hcd *hcd, struct urb *urb)
9342d53139fSDavid Mosberger {
9352d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
9362d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
9372d53139fSDavid Mosberger 	u32 max_packet;
9382d53139fSDavid Mosberger 
9392d53139fSDavid Mosberger 	if (urb->actual_length >= urb->transfer_buffer_length)
9402d53139fSDavid Mosberger 		return 1;	/* read is complete, so we're done */
9412d53139fSDavid Mosberger 
9422d53139fSDavid Mosberger 	/*
9432d53139fSDavid Mosberger 	 * USB 2.0 Section 5.3.2 Pipes: packets must be full size
9442d53139fSDavid Mosberger 	 * except for last one.
9452d53139fSDavid Mosberger 	 */
946dcd2e49bSVincent Mailhol 	max_packet = usb_maxpacket(urb->dev, urb->pipe);
9472d53139fSDavid Mosberger 	if (max_packet > MAX3421_FIFO_SIZE) {
9482d53139fSDavid Mosberger 		/*
9492d53139fSDavid Mosberger 		 * We do not support isochronous transfers at this
9502d53139fSDavid Mosberger 		 * time...
9512d53139fSDavid Mosberger 		 */
9522d53139fSDavid Mosberger 		dev_err(&spi->dev,
9532d53139fSDavid Mosberger 			"%s: packet-size of %u too big (limit is %u bytes)",
9542d53139fSDavid Mosberger 			__func__, max_packet, MAX3421_FIFO_SIZE);
9552d53139fSDavid Mosberger 		return -EINVAL;
9562d53139fSDavid Mosberger 	}
9572d53139fSDavid Mosberger 
9582d53139fSDavid Mosberger 	if (max3421_hcd->curr_len < max_packet) {
9592d53139fSDavid Mosberger 		if (urb->transfer_flags & URB_SHORT_NOT_OK) {
9602d53139fSDavid Mosberger 			/*
9612d53139fSDavid Mosberger 			 * remaining > 0 and received an
9622d53139fSDavid Mosberger 			 * unexpected partial packet ->
9632d53139fSDavid Mosberger 			 * error
9642d53139fSDavid Mosberger 			 */
9652d53139fSDavid Mosberger 			return -EREMOTEIO;
9662d53139fSDavid Mosberger 		} else
9672d53139fSDavid Mosberger 			/* short read, but it's OK */
9682d53139fSDavid Mosberger 			return 1;
9692d53139fSDavid Mosberger 	}
9702d53139fSDavid Mosberger 	return 0;	/* not done */
9712d53139fSDavid Mosberger }
9722d53139fSDavid Mosberger 
9732d53139fSDavid Mosberger /*
9742d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
9752d53139fSDavid Mosberger  */
9762d53139fSDavid Mosberger static int
max3421_transfer_out_done(struct usb_hcd * hcd,struct urb * urb)9772d53139fSDavid Mosberger max3421_transfer_out_done(struct usb_hcd *hcd, struct urb *urb)
9782d53139fSDavid Mosberger {
9792d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
9802d53139fSDavid Mosberger 
9812d53139fSDavid Mosberger 	urb->actual_length += max3421_hcd->curr_len;
9822d53139fSDavid Mosberger 	if (urb->actual_length < urb->transfer_buffer_length)
9832d53139fSDavid Mosberger 		return 0;
9842d53139fSDavid Mosberger 	if (urb->transfer_flags & URB_ZERO_PACKET) {
9852d53139fSDavid Mosberger 		/*
9862d53139fSDavid Mosberger 		 * Some hardware needs a zero-size packet at the end
9872d53139fSDavid Mosberger 		 * of a bulk-out transfer if the last transfer was a
9882d53139fSDavid Mosberger 		 * full-sized packet (i.e., such hardware use <
9892d53139fSDavid Mosberger 		 * max_packet as an indicator that the end of the
9902d53139fSDavid Mosberger 		 * packet has been reached).
9912d53139fSDavid Mosberger 		 */
992dcd2e49bSVincent Mailhol 		u32 max_packet = usb_maxpacket(urb->dev, urb->pipe);
9932d53139fSDavid Mosberger 
9942d53139fSDavid Mosberger 		if (max3421_hcd->curr_len == max_packet)
9952d53139fSDavid Mosberger 			return 0;
9962d53139fSDavid Mosberger 	}
9972d53139fSDavid Mosberger 	return 1;
9982d53139fSDavid Mosberger }
9992d53139fSDavid Mosberger 
10002d53139fSDavid Mosberger /*
10012d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
10022d53139fSDavid Mosberger  */
10032d53139fSDavid Mosberger static void
max3421_host_transfer_done(struct usb_hcd * hcd)10042d53139fSDavid Mosberger max3421_host_transfer_done(struct usb_hcd *hcd)
10052d53139fSDavid Mosberger {
10062d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
10072d53139fSDavid Mosberger 	struct urb *urb = max3421_hcd->curr_urb;
10082d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
10092d53139fSDavid Mosberger 	u8 result_code, hrsl;
10102d53139fSDavid Mosberger 	int urb_done = 0;
10112d53139fSDavid Mosberger 
10122d53139fSDavid Mosberger 	max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
10132d53139fSDavid Mosberger 			       BIT(MAX3421_HI_RCVDAV_BIT));
10142d53139fSDavid Mosberger 
10152d53139fSDavid Mosberger 	hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
10162d53139fSDavid Mosberger 	result_code = hrsl & MAX3421_HRSL_RESULT_MASK;
10172d53139fSDavid Mosberger 
10182d53139fSDavid Mosberger #ifdef DEBUG
10192d53139fSDavid Mosberger 	++max3421_hcd->err_stat[result_code];
10202d53139fSDavid Mosberger #endif
10212d53139fSDavid Mosberger 
10222d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
10232d53139fSDavid Mosberger 
10242d53139fSDavid Mosberger 	if (unlikely(result_code != MAX3421_HRSL_OK)) {
10252d53139fSDavid Mosberger 		max3421_handle_error(hcd, hrsl);
10262d53139fSDavid Mosberger 		return;
10272d53139fSDavid Mosberger 	}
10282d53139fSDavid Mosberger 
10292d53139fSDavid Mosberger 	max3421_ep->naks = 0;
10302d53139fSDavid Mosberger 	max3421_ep->retries = 0;
10312d53139fSDavid Mosberger 	switch (max3421_ep->pkt_state) {
10322d53139fSDavid Mosberger 
10332d53139fSDavid Mosberger 	case PKT_STATE_SETUP:
10342d53139fSDavid Mosberger 		if (urb->transfer_buffer_length > 0)
10352d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TRANSFER;
10362d53139fSDavid Mosberger 		else
10372d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TERMINATE;
10382d53139fSDavid Mosberger 		break;
10392d53139fSDavid Mosberger 
10402d53139fSDavid Mosberger 	case PKT_STATE_TRANSFER:
10412d53139fSDavid Mosberger 		if (usb_urb_dir_in(urb))
10422d53139fSDavid Mosberger 			urb_done = max3421_transfer_in_done(hcd, urb);
10432d53139fSDavid Mosberger 		else
10442d53139fSDavid Mosberger 			urb_done = max3421_transfer_out_done(hcd, urb);
10452d53139fSDavid Mosberger 		if (urb_done > 0 && usb_pipetype(urb->pipe) == PIPE_CONTROL) {
10462d53139fSDavid Mosberger 			/*
10472d53139fSDavid Mosberger 			 * We aren't really done - we still need to
10482d53139fSDavid Mosberger 			 * terminate the control transfer:
10492d53139fSDavid Mosberger 			 */
10502d53139fSDavid Mosberger 			max3421_hcd->urb_done = urb_done = 0;
10512d53139fSDavid Mosberger 			max3421_ep->pkt_state = PKT_STATE_TERMINATE;
10522d53139fSDavid Mosberger 		}
10532d53139fSDavid Mosberger 		break;
10542d53139fSDavid Mosberger 
10552d53139fSDavid Mosberger 	case PKT_STATE_TERMINATE:
10562d53139fSDavid Mosberger 		urb_done = 1;
10572d53139fSDavid Mosberger 		break;
10582d53139fSDavid Mosberger 	}
10592d53139fSDavid Mosberger 
10602d53139fSDavid Mosberger 	if (urb_done)
10612d53139fSDavid Mosberger 		max3421_hcd->urb_done = urb_done;
10622d53139fSDavid Mosberger 	else
10632d53139fSDavid Mosberger 		max3421_next_transfer(hcd, 0);
10642d53139fSDavid Mosberger }
10652d53139fSDavid Mosberger 
10662d53139fSDavid Mosberger /*
10672d53139fSDavid Mosberger  * Caller must NOT hold HCD spinlock.
10682d53139fSDavid Mosberger  */
10692d53139fSDavid Mosberger static void
max3421_detect_conn(struct usb_hcd * hcd)10702d53139fSDavid Mosberger max3421_detect_conn(struct usb_hcd *hcd)
10712d53139fSDavid Mosberger {
10722d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
10732d53139fSDavid Mosberger 	unsigned int jk, have_conn = 0;
10742d53139fSDavid Mosberger 	u32 old_port_status, chg;
10752d53139fSDavid Mosberger 	unsigned long flags;
10762d53139fSDavid Mosberger 	u8 hrsl, mode;
10772d53139fSDavid Mosberger 
10782d53139fSDavid Mosberger 	hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
10792d53139fSDavid Mosberger 
10802d53139fSDavid Mosberger 	jk = ((((hrsl >> MAX3421_HRSL_JSTATUS_BIT) & 1) << 0) |
10812d53139fSDavid Mosberger 	      (((hrsl >> MAX3421_HRSL_KSTATUS_BIT) & 1) << 1));
10822d53139fSDavid Mosberger 
10832d53139fSDavid Mosberger 	mode = max3421_hcd->mode;
10842d53139fSDavid Mosberger 
10852d53139fSDavid Mosberger 	switch (jk) {
10862d53139fSDavid Mosberger 	case 0x0: /* SE0: disconnect */
10872d53139fSDavid Mosberger 		/*
10882d53139fSDavid Mosberger 		 * Turn off SOFKAENAB bit to avoid getting interrupt
10892d53139fSDavid Mosberger 		 * every milli-second:
10902d53139fSDavid Mosberger 		 */
10912d53139fSDavid Mosberger 		mode &= ~BIT(MAX3421_MODE_SOFKAENAB_BIT);
10922d53139fSDavid Mosberger 		break;
10932d53139fSDavid Mosberger 
10942d53139fSDavid Mosberger 	case 0x1: /* J=0,K=1: low-speed (in full-speed or vice versa) */
10952d53139fSDavid Mosberger 	case 0x2: /* J=1,K=0: full-speed (in full-speed or vice versa) */
10962d53139fSDavid Mosberger 		if (jk == 0x2)
10972d53139fSDavid Mosberger 			/* need to switch to the other speed: */
10982d53139fSDavid Mosberger 			mode ^= BIT(MAX3421_MODE_LOWSPEED_BIT);
10992d53139fSDavid Mosberger 		/* turn on SOFKAENAB bit: */
11002d53139fSDavid Mosberger 		mode |= BIT(MAX3421_MODE_SOFKAENAB_BIT);
11012d53139fSDavid Mosberger 		have_conn = 1;
11022d53139fSDavid Mosberger 		break;
11032d53139fSDavid Mosberger 
11042d53139fSDavid Mosberger 	case 0x3: /* illegal */
11052d53139fSDavid Mosberger 		break;
11062d53139fSDavid Mosberger 	}
11072d53139fSDavid Mosberger 
11082d53139fSDavid Mosberger 	max3421_hcd->mode = mode;
11092d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
11102d53139fSDavid Mosberger 
11112d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
11122d53139fSDavid Mosberger 	old_port_status = max3421_hcd->port_status;
11132d53139fSDavid Mosberger 	if (have_conn)
11142d53139fSDavid Mosberger 		max3421_hcd->port_status |=  USB_PORT_STAT_CONNECTION;
11152d53139fSDavid Mosberger 	else
11162d53139fSDavid Mosberger 		max3421_hcd->port_status &= ~USB_PORT_STAT_CONNECTION;
11172d53139fSDavid Mosberger 	if (mode & BIT(MAX3421_MODE_LOWSPEED_BIT))
11182d53139fSDavid Mosberger 		max3421_hcd->port_status |=  USB_PORT_STAT_LOW_SPEED;
11192d53139fSDavid Mosberger 	else
11202d53139fSDavid Mosberger 		max3421_hcd->port_status &= ~USB_PORT_STAT_LOW_SPEED;
11212d53139fSDavid Mosberger 	chg = (old_port_status ^ max3421_hcd->port_status);
11222d53139fSDavid Mosberger 	max3421_hcd->port_status |= chg << 16;
11232d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
11242d53139fSDavid Mosberger }
11252d53139fSDavid Mosberger 
11262d53139fSDavid Mosberger static irqreturn_t
max3421_irq_handler(int irq,void * dev_id)11272d53139fSDavid Mosberger max3421_irq_handler(int irq, void *dev_id)
11282d53139fSDavid Mosberger {
11292d53139fSDavid Mosberger 	struct usb_hcd *hcd = dev_id;
11302d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
11312d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11322d53139fSDavid Mosberger 
113337aadc68SPeter Zijlstra 	if (max3421_hcd->spi_thread)
11342d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
11352eb5dbddSDavid Mosberger-Tang 	if (!test_and_set_bit(ENABLE_IRQ, &max3421_hcd->todo))
11362d53139fSDavid Mosberger 		disable_irq_nosync(spi->irq);
11372d53139fSDavid Mosberger 	return IRQ_HANDLED;
11382d53139fSDavid Mosberger }
11392d53139fSDavid Mosberger 
11402d53139fSDavid Mosberger #ifdef DEBUG
11412d53139fSDavid Mosberger 
11422d53139fSDavid Mosberger static void
dump_eps(struct usb_hcd * hcd)11432d53139fSDavid Mosberger dump_eps(struct usb_hcd *hcd)
11442d53139fSDavid Mosberger {
11452d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11462d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
11472d53139fSDavid Mosberger 	struct usb_host_endpoint *ep;
11482d53139fSDavid Mosberger 	char ubuf[512], *dp, *end;
11492d53139fSDavid Mosberger 	unsigned long flags;
11502d53139fSDavid Mosberger 	struct urb *urb;
11512d53139fSDavid Mosberger 	int epnum, ret;
11522d53139fSDavid Mosberger 
11532d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
1154553c2360SGeliang Tang 	list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) {
11552d53139fSDavid Mosberger 		ep = max3421_ep->ep;
11562d53139fSDavid Mosberger 
11572d53139fSDavid Mosberger 		dp = ubuf;
11582d53139fSDavid Mosberger 		end = dp + sizeof(ubuf);
11592d53139fSDavid Mosberger 		*dp = '\0';
1160553c2360SGeliang Tang 		list_for_each_entry(urb, &ep->urb_list, urb_list) {
11612d53139fSDavid Mosberger 			ret = snprintf(dp, end - dp, " %p(%d.%s %d/%d)", urb,
11622d53139fSDavid Mosberger 				       usb_pipetype(urb->pipe),
11632d53139fSDavid Mosberger 				       usb_urb_dir_in(urb) ? "IN" : "OUT",
11642d53139fSDavid Mosberger 				       urb->actual_length,
11652d53139fSDavid Mosberger 				       urb->transfer_buffer_length);
11662d53139fSDavid Mosberger 			if (ret < 0 || ret >= end - dp)
11672d53139fSDavid Mosberger 				break;	/* error or buffer full */
11682d53139fSDavid Mosberger 			dp += ret;
11692d53139fSDavid Mosberger 		}
11702d53139fSDavid Mosberger 
11712d53139fSDavid Mosberger 		epnum = usb_endpoint_num(&ep->desc);
11722d53139fSDavid Mosberger 		pr_info("EP%0u %u lst %04u rtr %u nak %6u rxmt %u: %s\n",
11732d53139fSDavid Mosberger 			epnum, max3421_ep->pkt_state, max3421_ep->last_active,
11742d53139fSDavid Mosberger 			max3421_ep->retries, max3421_ep->naks,
11752d53139fSDavid Mosberger 			max3421_ep->retransmit, ubuf);
11762d53139fSDavid Mosberger 	}
11772d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
11782d53139fSDavid Mosberger }
11792d53139fSDavid Mosberger 
11802d53139fSDavid Mosberger #endif /* DEBUG */
11812d53139fSDavid Mosberger 
11822d53139fSDavid Mosberger /* Return zero if no work was performed, 1 otherwise.  */
11832d53139fSDavid Mosberger static int
max3421_handle_irqs(struct usb_hcd * hcd)11842d53139fSDavid Mosberger max3421_handle_irqs(struct usb_hcd *hcd)
11852d53139fSDavid Mosberger {
11862d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
11872d53139fSDavid Mosberger 	u32 chg, old_port_status;
11882d53139fSDavid Mosberger 	unsigned long flags;
11892d53139fSDavid Mosberger 	u8 hirq;
11902d53139fSDavid Mosberger 
11912d53139fSDavid Mosberger 	/*
11922d53139fSDavid Mosberger 	 * Read and ack pending interrupts (CPU must never
11932d53139fSDavid Mosberger 	 * clear SNDBAV directly and RCVDAV must be cleared by
11942d53139fSDavid Mosberger 	 * max3421_recv_data_available()!):
11952d53139fSDavid Mosberger 	 */
11962d53139fSDavid Mosberger 	hirq = spi_rd8(hcd, MAX3421_REG_HIRQ);
11972d53139fSDavid Mosberger 	hirq &= max3421_hcd->hien;
11982d53139fSDavid Mosberger 	if (!hirq)
11992d53139fSDavid Mosberger 		return 0;
12002d53139fSDavid Mosberger 
12012d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIRQ,
12022d53139fSDavid Mosberger 		hirq & ~(BIT(MAX3421_HI_SNDBAV_BIT) |
12032d53139fSDavid Mosberger 			 BIT(MAX3421_HI_RCVDAV_BIT)));
12042d53139fSDavid Mosberger 
12052d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_FRAME_BIT)) {
12062d53139fSDavid Mosberger 		max3421_hcd->frame_number = ((max3421_hcd->frame_number + 1)
12072d53139fSDavid Mosberger 					     & USB_MAX_FRAME_NUMBER);
12082d53139fSDavid Mosberger 		max3421_hcd->sched_pass = SCHED_PASS_PERIODIC;
12092d53139fSDavid Mosberger 	}
12102d53139fSDavid Mosberger 
12112d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_RCVDAV_BIT))
12122d53139fSDavid Mosberger 		max3421_recv_data_available(hcd);
12132d53139fSDavid Mosberger 
12142d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_HXFRDN_BIT))
12152d53139fSDavid Mosberger 		max3421_host_transfer_done(hcd);
12162d53139fSDavid Mosberger 
12172d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_CONDET_BIT))
12182d53139fSDavid Mosberger 		max3421_detect_conn(hcd);
12192d53139fSDavid Mosberger 
12202d53139fSDavid Mosberger 	/*
12212d53139fSDavid Mosberger 	 * Now process interrupts that may affect HCD state
12222d53139fSDavid Mosberger 	 * other than the end-points:
12232d53139fSDavid Mosberger 	 */
12242d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
12252d53139fSDavid Mosberger 
12262d53139fSDavid Mosberger 	old_port_status = max3421_hcd->port_status;
12272d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_BUSEVENT_BIT)) {
12282d53139fSDavid Mosberger 		if (max3421_hcd->port_status & USB_PORT_STAT_RESET) {
12292d53139fSDavid Mosberger 			/* BUSEVENT due to completion of Bus Reset */
12302d53139fSDavid Mosberger 			max3421_hcd->port_status &= ~USB_PORT_STAT_RESET;
12312d53139fSDavid Mosberger 			max3421_hcd->port_status |=  USB_PORT_STAT_ENABLE;
12322d53139fSDavid Mosberger 		} else {
12332d53139fSDavid Mosberger 			/* BUSEVENT due to completion of Bus Resume */
12342d53139fSDavid Mosberger 			pr_info("%s: BUSEVENT Bus Resume Done\n", __func__);
12352d53139fSDavid Mosberger 		}
12362d53139fSDavid Mosberger 	}
12372d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_RWU_BIT))
12382d53139fSDavid Mosberger 		pr_info("%s: RWU\n", __func__);
12392d53139fSDavid Mosberger 	if (hirq & BIT(MAX3421_HI_SUSDN_BIT))
12402d53139fSDavid Mosberger 		pr_info("%s: SUSDN\n", __func__);
12412d53139fSDavid Mosberger 
12422d53139fSDavid Mosberger 	chg = (old_port_status ^ max3421_hcd->port_status);
12432d53139fSDavid Mosberger 	max3421_hcd->port_status |= chg << 16;
12442d53139fSDavid Mosberger 
12452d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
12462d53139fSDavid Mosberger 
12472d53139fSDavid Mosberger #ifdef DEBUG
12482d53139fSDavid Mosberger 	{
12492d53139fSDavid Mosberger 		static unsigned long last_time;
12502d53139fSDavid Mosberger 		char sbuf[16 * 16], *dp, *end;
12512d53139fSDavid Mosberger 		int i;
12522d53139fSDavid Mosberger 
1253788bfe88SAsaf Vertz 		if (time_after(jiffies, last_time + 5*HZ)) {
12542d53139fSDavid Mosberger 			dp = sbuf;
12552d53139fSDavid Mosberger 			end = sbuf + sizeof(sbuf);
12562d53139fSDavid Mosberger 			*dp = '\0';
12572d53139fSDavid Mosberger 			for (i = 0; i < 16; ++i) {
12582d53139fSDavid Mosberger 				int ret = snprintf(dp, end - dp, " %lu",
12592d53139fSDavid Mosberger 						   max3421_hcd->err_stat[i]);
12602d53139fSDavid Mosberger 				if (ret < 0 || ret >= end - dp)
12612d53139fSDavid Mosberger 					break;	/* error or buffer full */
12622d53139fSDavid Mosberger 				dp += ret;
12632d53139fSDavid Mosberger 			}
12642d53139fSDavid Mosberger 			pr_info("%s: hrsl_stats %s\n", __func__, sbuf);
12652d53139fSDavid Mosberger 			memset(max3421_hcd->err_stat, 0,
12662d53139fSDavid Mosberger 			       sizeof(max3421_hcd->err_stat));
12672d53139fSDavid Mosberger 			last_time = jiffies;
12682d53139fSDavid Mosberger 
12692d53139fSDavid Mosberger 			dump_eps(hcd);
12702d53139fSDavid Mosberger 		}
12712d53139fSDavid Mosberger 	}
12722d53139fSDavid Mosberger #endif
12732d53139fSDavid Mosberger 	return 1;
12742d53139fSDavid Mosberger }
12752d53139fSDavid Mosberger 
12762d53139fSDavid Mosberger static int
max3421_reset_hcd(struct usb_hcd * hcd)12772d53139fSDavid Mosberger max3421_reset_hcd(struct usb_hcd *hcd)
12782d53139fSDavid Mosberger {
12792d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
12802d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
12812d53139fSDavid Mosberger 	int timeout;
12822d53139fSDavid Mosberger 
12832d53139fSDavid Mosberger 	/* perform a chip reset and wait for OSCIRQ signal to appear: */
12842d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_USBCTL, BIT(MAX3421_USBCTL_CHIPRES_BIT));
12852d53139fSDavid Mosberger 	/* clear reset: */
12862d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_USBCTL, 0);
12872d53139fSDavid Mosberger 	timeout = 1000;
12882d53139fSDavid Mosberger 	while (1) {
12892d53139fSDavid Mosberger 		if (spi_rd8(hcd, MAX3421_REG_USBIRQ)
12902d53139fSDavid Mosberger 		    & BIT(MAX3421_USBIRQ_OSCOKIRQ_BIT))
12912d53139fSDavid Mosberger 			break;
12922d53139fSDavid Mosberger 		if (--timeout < 0) {
12932d53139fSDavid Mosberger 			dev_err(&spi->dev,
12942d53139fSDavid Mosberger 				"timed out waiting for oscillator OK signal");
12952d53139fSDavid Mosberger 			return 1;
12962d53139fSDavid Mosberger 		}
12972d53139fSDavid Mosberger 		cond_resched();
12982d53139fSDavid Mosberger 	}
12992d53139fSDavid Mosberger 
13002d53139fSDavid Mosberger 	/*
13012d53139fSDavid Mosberger 	 * Turn on host mode, automatic generation of SOF packets, and
13022d53139fSDavid Mosberger 	 * enable pull-down registers on DM/DP:
13032d53139fSDavid Mosberger 	 */
13042d53139fSDavid Mosberger 	max3421_hcd->mode = (BIT(MAX3421_MODE_HOST_BIT) |
13052d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_SOFKAENAB_BIT) |
13062d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_DMPULLDN_BIT) |
13072d53139fSDavid Mosberger 			     BIT(MAX3421_MODE_DPPULLDN_BIT));
13082d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_MODE, max3421_hcd->mode);
13092d53139fSDavid Mosberger 
13102d53139fSDavid Mosberger 	/* reset frame-number: */
13112d53139fSDavid Mosberger 	max3421_hcd->frame_number = USB_MAX_FRAME_NUMBER;
13122d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, BIT(MAX3421_HCTL_FRMRST_BIT));
13132d53139fSDavid Mosberger 
13142d53139fSDavid Mosberger 	/* sample the state of the D+ and D- lines */
13152d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HCTL, BIT(MAX3421_HCTL_SAMPLEBUS_BIT));
13162d53139fSDavid Mosberger 	max3421_detect_conn(hcd);
13172d53139fSDavid Mosberger 
13182d53139fSDavid Mosberger 	/* enable frame, connection-detected, and bus-event interrupts: */
13192d53139fSDavid Mosberger 	max3421_hcd->hien = (BIT(MAX3421_HI_FRAME_BIT) |
13202d53139fSDavid Mosberger 			     BIT(MAX3421_HI_CONDET_BIT) |
13212d53139fSDavid Mosberger 			     BIT(MAX3421_HI_BUSEVENT_BIT));
13222d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
13232d53139fSDavid Mosberger 
13242d53139fSDavid Mosberger 	/* enable interrupts: */
13252d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_CPUCTL, BIT(MAX3421_CPUCTL_IE_BIT));
13262d53139fSDavid Mosberger 	return 1;
13272d53139fSDavid Mosberger }
13282d53139fSDavid Mosberger 
13292d53139fSDavid Mosberger static int
max3421_urb_done(struct usb_hcd * hcd)13302d53139fSDavid Mosberger max3421_urb_done(struct usb_hcd *hcd)
13312d53139fSDavid Mosberger {
13322d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
13332d53139fSDavid Mosberger 	unsigned long flags;
13342d53139fSDavid Mosberger 	struct urb *urb;
13352d53139fSDavid Mosberger 	int status;
13362d53139fSDavid Mosberger 
13372d53139fSDavid Mosberger 	status = max3421_hcd->urb_done;
13382d53139fSDavid Mosberger 	max3421_hcd->urb_done = 0;
13392d53139fSDavid Mosberger 	if (status > 0)
13402d53139fSDavid Mosberger 		status = 0;
13412d53139fSDavid Mosberger 	urb = max3421_hcd->curr_urb;
13422d53139fSDavid Mosberger 	if (urb) {
1343b5fdf5c6SMark Tomlinson 		/* save the old end-points toggles: */
1344b5fdf5c6SMark Tomlinson 		u8 hrsl = spi_rd8(hcd, MAX3421_REG_HRSL);
1345b5fdf5c6SMark Tomlinson 		int rcvtog = (hrsl >> MAX3421_HRSL_RCVTOGRD_BIT) & 1;
1346b5fdf5c6SMark Tomlinson 		int sndtog = (hrsl >> MAX3421_HRSL_SNDTOGRD_BIT) & 1;
1347b5fdf5c6SMark Tomlinson 		int epnum = usb_endpoint_num(&urb->ep->desc);
1348b5fdf5c6SMark Tomlinson 
1349b5fdf5c6SMark Tomlinson 		/* no locking: HCD (i.e., we) own toggles, don't we? */
1350b5fdf5c6SMark Tomlinson 		usb_settoggle(urb->dev, epnum, 0, rcvtog);
1351b5fdf5c6SMark Tomlinson 		usb_settoggle(urb->dev, epnum, 1, sndtog);
1352b5fdf5c6SMark Tomlinson 
13532d53139fSDavid Mosberger 		max3421_hcd->curr_urb = NULL;
13542d53139fSDavid Mosberger 		spin_lock_irqsave(&max3421_hcd->lock, flags);
13552d53139fSDavid Mosberger 		usb_hcd_unlink_urb_from_ep(hcd, urb);
13562d53139fSDavid Mosberger 		spin_unlock_irqrestore(&max3421_hcd->lock, flags);
13572d53139fSDavid Mosberger 
13582d53139fSDavid Mosberger 		/* must be called without the HCD spinlock: */
13592d53139fSDavid Mosberger 		usb_hcd_giveback_urb(hcd, urb, status);
13602d53139fSDavid Mosberger 	}
13612d53139fSDavid Mosberger 	return 1;
13622d53139fSDavid Mosberger }
13632d53139fSDavid Mosberger 
13642d53139fSDavid Mosberger static int
max3421_spi_thread(void * dev_id)13652d53139fSDavid Mosberger max3421_spi_thread(void *dev_id)
13662d53139fSDavid Mosberger {
13672d53139fSDavid Mosberger 	struct usb_hcd *hcd = dev_id;
13682d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
13692d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
13702d53139fSDavid Mosberger 	int i, i_worked = 1;
13712d53139fSDavid Mosberger 
13722d53139fSDavid Mosberger 	/* set full-duplex SPI mode, low-active interrupt pin: */
13732d53139fSDavid Mosberger 	spi_wr8(hcd, MAX3421_REG_PINCTL,
13742d53139fSDavid Mosberger 		(BIT(MAX3421_PINCTL_FDUPSPI_BIT) |	/* full-duplex */
13752d53139fSDavid Mosberger 		 BIT(MAX3421_PINCTL_INTLEVEL_BIT)));	/* low-active irq */
13762d53139fSDavid Mosberger 
13772d53139fSDavid Mosberger 	while (!kthread_should_stop()) {
13782d53139fSDavid Mosberger 		max3421_hcd->rev = spi_rd8(hcd, MAX3421_REG_REVISION);
13792d53139fSDavid Mosberger 		if (max3421_hcd->rev == 0x12 || max3421_hcd->rev == 0x13)
13802d53139fSDavid Mosberger 			break;
13812d53139fSDavid Mosberger 		dev_err(&spi->dev, "bad rev 0x%02x", max3421_hcd->rev);
13822d53139fSDavid Mosberger 		msleep(10000);
13832d53139fSDavid Mosberger 	}
13842d53139fSDavid Mosberger 	dev_info(&spi->dev, "rev 0x%x, SPI clk %dHz, bpw %u, irq %d\n",
13852d53139fSDavid Mosberger 		 max3421_hcd->rev, spi->max_speed_hz, spi->bits_per_word,
13862d53139fSDavid Mosberger 		 spi->irq);
13872d53139fSDavid Mosberger 
13882d53139fSDavid Mosberger 	while (!kthread_should_stop()) {
13892d53139fSDavid Mosberger 		if (!i_worked) {
13902d53139fSDavid Mosberger 			/*
13912d53139fSDavid Mosberger 			 * We'll be waiting for wakeups from the hard
13922d53139fSDavid Mosberger 			 * interrupt handler, so now is a good time to
13932d53139fSDavid Mosberger 			 * sync our hien with the chip:
13942d53139fSDavid Mosberger 			 */
13952d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HIEN, max3421_hcd->hien);
13962d53139fSDavid Mosberger 
13972d53139fSDavid Mosberger 			set_current_state(TASK_INTERRUPTIBLE);
13982eb5dbddSDavid Mosberger-Tang 			if (test_and_clear_bit(ENABLE_IRQ, &max3421_hcd->todo))
13992d53139fSDavid Mosberger 				enable_irq(spi->irq);
14002d53139fSDavid Mosberger 			schedule();
14012d53139fSDavid Mosberger 			__set_current_state(TASK_RUNNING);
14022d53139fSDavid Mosberger 		}
14032d53139fSDavid Mosberger 
14042d53139fSDavid Mosberger 		i_worked = 0;
14052d53139fSDavid Mosberger 
14062d53139fSDavid Mosberger 		if (max3421_hcd->urb_done)
14072d53139fSDavid Mosberger 			i_worked |= max3421_urb_done(hcd);
14082d53139fSDavid Mosberger 		else if (max3421_handle_irqs(hcd))
14092d53139fSDavid Mosberger 			i_worked = 1;
14102d53139fSDavid Mosberger 		else if (!max3421_hcd->curr_urb)
14112d53139fSDavid Mosberger 			i_worked |= max3421_select_and_start_urb(hcd);
14122d53139fSDavid Mosberger 
14132eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(RESET_HCD, &max3421_hcd->todo))
14142d53139fSDavid Mosberger 			/* reset the HCD: */
14152d53139fSDavid Mosberger 			i_worked |= max3421_reset_hcd(hcd);
14162eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(RESET_PORT, &max3421_hcd->todo)) {
14172d53139fSDavid Mosberger 			/* perform a USB bus reset: */
14182d53139fSDavid Mosberger 			spi_wr8(hcd, MAX3421_REG_HCTL,
14192d53139fSDavid Mosberger 				BIT(MAX3421_HCTL_BUSRST_BIT));
14202d53139fSDavid Mosberger 			i_worked = 1;
14212d53139fSDavid Mosberger 		}
14222eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(CHECK_UNLINK, &max3421_hcd->todo))
14232d53139fSDavid Mosberger 			i_worked |= max3421_check_unlink(hcd);
14242eb5dbddSDavid Mosberger-Tang 		if (test_and_clear_bit(IOPIN_UPDATE, &max3421_hcd->todo)) {
14252d53139fSDavid Mosberger 			/*
14262d53139fSDavid Mosberger 			 * IOPINS1/IOPINS2 do not auto-increment, so we can't
14272d53139fSDavid Mosberger 			 * use spi_wr_buf().
14282d53139fSDavid Mosberger 			 */
14292d53139fSDavid Mosberger 			for (i = 0; i < ARRAY_SIZE(max3421_hcd->iopins); ++i) {
1430a7efe3fcSMark Tomlinson 				u8 val = spi_rd8(hcd, MAX3421_REG_IOPINS1 + i);
14312d53139fSDavid Mosberger 
14322d53139fSDavid Mosberger 				val = ((val & 0xf0) |
14332d53139fSDavid Mosberger 				       (max3421_hcd->iopins[i] & 0x0f));
14342d53139fSDavid Mosberger 				spi_wr8(hcd, MAX3421_REG_IOPINS1 + i, val);
14352d53139fSDavid Mosberger 				max3421_hcd->iopins[i] = val;
14362d53139fSDavid Mosberger 			}
14372d53139fSDavid Mosberger 			i_worked = 1;
14382d53139fSDavid Mosberger 		}
14392d53139fSDavid Mosberger 	}
14402d53139fSDavid Mosberger 	set_current_state(TASK_RUNNING);
14412d53139fSDavid Mosberger 	dev_info(&spi->dev, "SPI thread exiting");
14422d53139fSDavid Mosberger 	return 0;
14432d53139fSDavid Mosberger }
14442d53139fSDavid Mosberger 
14452d53139fSDavid Mosberger static int
max3421_reset_port(struct usb_hcd * hcd)14462d53139fSDavid Mosberger max3421_reset_port(struct usb_hcd *hcd)
14472d53139fSDavid Mosberger {
14482d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14492d53139fSDavid Mosberger 
14502d53139fSDavid Mosberger 	max3421_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |
14512d53139fSDavid Mosberger 				      USB_PORT_STAT_LOW_SPEED);
1452a2b63cb5SDavid Mosberger-Tang 	max3421_hcd->port_status |= USB_PORT_STAT_RESET;
14532eb5dbddSDavid Mosberger-Tang 	set_bit(RESET_PORT, &max3421_hcd->todo);
14542d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
14552d53139fSDavid Mosberger 	return 0;
14562d53139fSDavid Mosberger }
14572d53139fSDavid Mosberger 
14582d53139fSDavid Mosberger static int
max3421_reset(struct usb_hcd * hcd)14592d53139fSDavid Mosberger max3421_reset(struct usb_hcd *hcd)
14602d53139fSDavid Mosberger {
14612d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14622d53139fSDavid Mosberger 
14632d53139fSDavid Mosberger 	hcd->self.sg_tablesize = 0;
14642d53139fSDavid Mosberger 	hcd->speed = HCD_USB2;
14652d53139fSDavid Mosberger 	hcd->self.root_hub->speed = USB_SPEED_FULL;
14662eb5dbddSDavid Mosberger-Tang 	set_bit(RESET_HCD, &max3421_hcd->todo);
14672d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
14682d53139fSDavid Mosberger 	return 0;
14692d53139fSDavid Mosberger }
14702d53139fSDavid Mosberger 
14712d53139fSDavid Mosberger static int
max3421_start(struct usb_hcd * hcd)14722d53139fSDavid Mosberger max3421_start(struct usb_hcd *hcd)
14732d53139fSDavid Mosberger {
14742d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14752d53139fSDavid Mosberger 
14762d53139fSDavid Mosberger 	spin_lock_init(&max3421_hcd->lock);
14772d53139fSDavid Mosberger 	max3421_hcd->rh_state = MAX3421_RH_RUNNING;
14782d53139fSDavid Mosberger 
14792d53139fSDavid Mosberger 	INIT_LIST_HEAD(&max3421_hcd->ep_list);
14802d53139fSDavid Mosberger 
14812d53139fSDavid Mosberger 	hcd->power_budget = POWER_BUDGET;
14822d53139fSDavid Mosberger 	hcd->state = HC_STATE_RUNNING;
14832d53139fSDavid Mosberger 	hcd->uses_new_polling = 1;
14842d53139fSDavid Mosberger 	return 0;
14852d53139fSDavid Mosberger }
14862d53139fSDavid Mosberger 
14872d53139fSDavid Mosberger static void
max3421_stop(struct usb_hcd * hcd)14882d53139fSDavid Mosberger max3421_stop(struct usb_hcd *hcd)
14892d53139fSDavid Mosberger {
14902d53139fSDavid Mosberger }
14912d53139fSDavid Mosberger 
14922d53139fSDavid Mosberger static int
max3421_urb_enqueue(struct usb_hcd * hcd,struct urb * urb,gfp_t mem_flags)14932d53139fSDavid Mosberger max3421_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
14942d53139fSDavid Mosberger {
14952d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
14962d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
14972d53139fSDavid Mosberger 	struct max3421_ep *max3421_ep;
14982d53139fSDavid Mosberger 	unsigned long flags;
14992d53139fSDavid Mosberger 	int retval;
15002d53139fSDavid Mosberger 
15012d53139fSDavid Mosberger 	switch (usb_pipetype(urb->pipe)) {
15022d53139fSDavid Mosberger 	case PIPE_INTERRUPT:
15032d53139fSDavid Mosberger 	case PIPE_ISOCHRONOUS:
15042d53139fSDavid Mosberger 		if (urb->interval < 0) {
15052d53139fSDavid Mosberger 			dev_err(&spi->dev,
15062d53139fSDavid Mosberger 			  "%s: interval=%d for intr-/iso-pipe; expected > 0\n",
15072d53139fSDavid Mosberger 				__func__, urb->interval);
15082d53139fSDavid Mosberger 			return -EINVAL;
15092d53139fSDavid Mosberger 		}
151093c747edSGustavo A. R. Silva 		break;
15112d53139fSDavid Mosberger 	default:
15122d53139fSDavid Mosberger 		break;
15132d53139fSDavid Mosberger 	}
15142d53139fSDavid Mosberger 
15152d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
15162d53139fSDavid Mosberger 
15172d53139fSDavid Mosberger 	max3421_ep = urb->ep->hcpriv;
15182d53139fSDavid Mosberger 	if (!max3421_ep) {
15192d53139fSDavid Mosberger 		/* gets freed in max3421_endpoint_disable: */
15206c0f3695SAlexey Khoroshilov 		max3421_ep = kzalloc(sizeof(struct max3421_ep), GFP_ATOMIC);
152100c5aa17SDavid Mosberger-Tang 		if (!max3421_ep) {
152200c5aa17SDavid Mosberger-Tang 			retval = -ENOMEM;
152300c5aa17SDavid Mosberger-Tang 			goto out;
152400c5aa17SDavid Mosberger-Tang 		}
15252d53139fSDavid Mosberger 		max3421_ep->ep = urb->ep;
15262d53139fSDavid Mosberger 		max3421_ep->last_active = max3421_hcd->frame_number;
15272d53139fSDavid Mosberger 		urb->ep->hcpriv = max3421_ep;
15282d53139fSDavid Mosberger 
15292d53139fSDavid Mosberger 		list_add_tail(&max3421_ep->ep_list, &max3421_hcd->ep_list);
15302d53139fSDavid Mosberger 	}
15312d53139fSDavid Mosberger 
15322d53139fSDavid Mosberger 	retval = usb_hcd_link_urb_to_ep(hcd, urb);
15332d53139fSDavid Mosberger 	if (retval == 0) {
15342d53139fSDavid Mosberger 		/* Since we added to the queue, restart scheduling: */
15352d53139fSDavid Mosberger 		max3421_hcd->sched_pass = SCHED_PASS_PERIODIC;
15362d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
15372d53139fSDavid Mosberger 	}
15382d53139fSDavid Mosberger 
153900c5aa17SDavid Mosberger-Tang out:
15402d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
15412d53139fSDavid Mosberger 	return retval;
15422d53139fSDavid Mosberger }
15432d53139fSDavid Mosberger 
15442d53139fSDavid Mosberger static int
max3421_urb_dequeue(struct usb_hcd * hcd,struct urb * urb,int status)15452d53139fSDavid Mosberger max3421_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
15462d53139fSDavid Mosberger {
15472d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15482d53139fSDavid Mosberger 	unsigned long flags;
15492d53139fSDavid Mosberger 	int retval;
15502d53139fSDavid Mosberger 
15512d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
15522d53139fSDavid Mosberger 
15532d53139fSDavid Mosberger 	/*
15542d53139fSDavid Mosberger 	 * This will set urb->unlinked which in turn causes the entry
15552d53139fSDavid Mosberger 	 * to be dropped at the next opportunity.
15562d53139fSDavid Mosberger 	 */
15572d53139fSDavid Mosberger 	retval = usb_hcd_check_unlink_urb(hcd, urb, status);
15582d53139fSDavid Mosberger 	if (retval == 0) {
15592eb5dbddSDavid Mosberger-Tang 		set_bit(CHECK_UNLINK, &max3421_hcd->todo);
15602d53139fSDavid Mosberger 		wake_up_process(max3421_hcd->spi_thread);
15612d53139fSDavid Mosberger 	}
15622d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
15632d53139fSDavid Mosberger 	return retval;
15642d53139fSDavid Mosberger }
15652d53139fSDavid Mosberger 
15662d53139fSDavid Mosberger static void
max3421_endpoint_disable(struct usb_hcd * hcd,struct usb_host_endpoint * ep)15672d53139fSDavid Mosberger max3421_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
15682d53139fSDavid Mosberger {
15692d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15702d53139fSDavid Mosberger 	unsigned long flags;
15712d53139fSDavid Mosberger 
15722d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
15732d53139fSDavid Mosberger 
15742d53139fSDavid Mosberger 	if (ep->hcpriv) {
15752d53139fSDavid Mosberger 		struct max3421_ep *max3421_ep = ep->hcpriv;
15762d53139fSDavid Mosberger 
15772d53139fSDavid Mosberger 		/* remove myself from the ep_list: */
15782d53139fSDavid Mosberger 		if (!list_empty(&max3421_ep->ep_list))
15792d53139fSDavid Mosberger 			list_del(&max3421_ep->ep_list);
15802d53139fSDavid Mosberger 		kfree(max3421_ep);
15812d53139fSDavid Mosberger 		ep->hcpriv = NULL;
15822d53139fSDavid Mosberger 	}
15832d53139fSDavid Mosberger 
15842d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
15852d53139fSDavid Mosberger }
15862d53139fSDavid Mosberger 
15872d53139fSDavid Mosberger static int
max3421_get_frame_number(struct usb_hcd * hcd)15882d53139fSDavid Mosberger max3421_get_frame_number(struct usb_hcd *hcd)
15892d53139fSDavid Mosberger {
15902d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
15912d53139fSDavid Mosberger 	return max3421_hcd->frame_number;
15922d53139fSDavid Mosberger }
15932d53139fSDavid Mosberger 
15942d53139fSDavid Mosberger /*
15952d53139fSDavid Mosberger  * Should return a non-zero value when any port is undergoing a resume
15962d53139fSDavid Mosberger  * transition while the root hub is suspended.
15972d53139fSDavid Mosberger  */
15982d53139fSDavid Mosberger static int
max3421_hub_status_data(struct usb_hcd * hcd,char * buf)15992d53139fSDavid Mosberger max3421_hub_status_data(struct usb_hcd *hcd, char *buf)
16002d53139fSDavid Mosberger {
16012d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16022d53139fSDavid Mosberger 	unsigned long flags;
16032d53139fSDavid Mosberger 	int retval = 0;
16042d53139fSDavid Mosberger 
16052d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
16062d53139fSDavid Mosberger 	if (!HCD_HW_ACCESSIBLE(hcd))
16072d53139fSDavid Mosberger 		goto done;
16082d53139fSDavid Mosberger 
16092d53139fSDavid Mosberger 	*buf = 0;
16102d53139fSDavid Mosberger 	if ((max3421_hcd->port_status & PORT_C_MASK) != 0) {
16112d53139fSDavid Mosberger 		*buf = (1 << 1); /* a hub over-current condition exists */
16122d53139fSDavid Mosberger 		dev_dbg(hcd->self.controller,
16132d53139fSDavid Mosberger 			"port status 0x%08x has changes\n",
16142d53139fSDavid Mosberger 			max3421_hcd->port_status);
16152d53139fSDavid Mosberger 		retval = 1;
16162d53139fSDavid Mosberger 		if (max3421_hcd->rh_state == MAX3421_RH_SUSPENDED)
16172d53139fSDavid Mosberger 			usb_hcd_resume_root_hub(hcd);
16182d53139fSDavid Mosberger 	}
16192d53139fSDavid Mosberger done:
16202d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
16212d53139fSDavid Mosberger 	return retval;
16222d53139fSDavid Mosberger }
16232d53139fSDavid Mosberger 
16242d53139fSDavid Mosberger static inline void
hub_descriptor(struct usb_hub_descriptor * desc)16252d53139fSDavid Mosberger hub_descriptor(struct usb_hub_descriptor *desc)
16262d53139fSDavid Mosberger {
16272d53139fSDavid Mosberger 	memset(desc, 0, sizeof(*desc));
16282d53139fSDavid Mosberger 	/*
16292d53139fSDavid Mosberger 	 * See Table 11-13: Hub Descriptor in USB 2.0 spec.
16302d53139fSDavid Mosberger 	 */
1631e3d02e0eSSergei Shtylyov 	desc->bDescriptorType = USB_DT_HUB; /* hub descriptor */
16322d53139fSDavid Mosberger 	desc->bDescLength = 9;
16332e48c466SSergei Shtylyov 	desc->wHubCharacteristics = cpu_to_le16(HUB_CHAR_INDV_PORT_LPSM |
16342e48c466SSergei Shtylyov 						HUB_CHAR_COMMON_OCPM);
16352d53139fSDavid Mosberger 	desc->bNbrPorts = 1;
16362d53139fSDavid Mosberger }
16372d53139fSDavid Mosberger 
16382d53139fSDavid Mosberger /*
16392d53139fSDavid Mosberger  * Set the MAX3421E general-purpose output with number PIN_NUMBER to
16402d53139fSDavid Mosberger  * VALUE (0 or 1).  PIN_NUMBER may be in the range from 1-8.  For
16412d53139fSDavid Mosberger  * any other value, this function acts as a no-op.
16422d53139fSDavid Mosberger  */
16432d53139fSDavid Mosberger static void
max3421_gpout_set_value(struct usb_hcd * hcd,u8 pin_number,u8 value)16442d53139fSDavid Mosberger max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value)
16452d53139fSDavid Mosberger {
16462d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16472d53139fSDavid Mosberger 	u8 mask, idx;
16482d53139fSDavid Mosberger 
16492d53139fSDavid Mosberger 	--pin_number;
1650721fdc83SJules Maselbas 	if (pin_number >= MAX3421_GPOUT_COUNT)
16512d53139fSDavid Mosberger 		return;
16522d53139fSDavid Mosberger 
165359b71f77SJaewon Kim 	mask = 1u << (pin_number % 4);
16542d53139fSDavid Mosberger 	idx = pin_number / 4;
16552d53139fSDavid Mosberger 
16562d53139fSDavid Mosberger 	if (value)
16572d53139fSDavid Mosberger 		max3421_hcd->iopins[idx] |=  mask;
16582d53139fSDavid Mosberger 	else
16592d53139fSDavid Mosberger 		max3421_hcd->iopins[idx] &= ~mask;
16602eb5dbddSDavid Mosberger-Tang 	set_bit(IOPIN_UPDATE, &max3421_hcd->todo);
16612d53139fSDavid Mosberger 	wake_up_process(max3421_hcd->spi_thread);
16622d53139fSDavid Mosberger }
16632d53139fSDavid Mosberger 
16642d53139fSDavid Mosberger static int
max3421_hub_control(struct usb_hcd * hcd,u16 type_req,u16 value,u16 index,char * buf,u16 length)16652d53139fSDavid Mosberger max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index,
16662d53139fSDavid Mosberger 		    char *buf, u16 length)
16672d53139fSDavid Mosberger {
16682d53139fSDavid Mosberger 	struct spi_device *spi = to_spi_device(hcd->self.controller);
16692d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd);
16702d53139fSDavid Mosberger 	struct max3421_hcd_platform_data *pdata;
16712d53139fSDavid Mosberger 	unsigned long flags;
16722d53139fSDavid Mosberger 	int retval = 0;
16732d53139fSDavid Mosberger 
16742d53139fSDavid Mosberger 	pdata = spi->dev.platform_data;
1675892f6ebcSJules Maselbas 
1676892f6ebcSJules Maselbas 	spin_lock_irqsave(&max3421_hcd->lock, flags);
16772d53139fSDavid Mosberger 
16782d53139fSDavid Mosberger 	switch (type_req) {
16792d53139fSDavid Mosberger 	case ClearHubFeature:
16802d53139fSDavid Mosberger 		break;
16812d53139fSDavid Mosberger 	case ClearPortFeature:
16822d53139fSDavid Mosberger 		switch (value) {
16832d53139fSDavid Mosberger 		case USB_PORT_FEAT_SUSPEND:
16842d53139fSDavid Mosberger 			break;
16852d53139fSDavid Mosberger 		case USB_PORT_FEAT_POWER:
16862d53139fSDavid Mosberger 			dev_dbg(hcd->self.controller, "power-off\n");
16874055e5e5SDavid Mosberger-Tang 			max3421_gpout_set_value(hcd, pdata->vbus_gpout,
16884055e5e5SDavid Mosberger-Tang 						!pdata->vbus_active_level);
16890d9b6d49SGustavo A. R. Silva 			fallthrough;
16902d53139fSDavid Mosberger 		default:
16912d53139fSDavid Mosberger 			max3421_hcd->port_status &= ~(1 << value);
16922d53139fSDavid Mosberger 		}
16932d53139fSDavid Mosberger 		break;
16942d53139fSDavid Mosberger 	case GetHubDescriptor:
16952d53139fSDavid Mosberger 		hub_descriptor((struct usb_hub_descriptor *) buf);
16962d53139fSDavid Mosberger 		break;
16972d53139fSDavid Mosberger 
16982d53139fSDavid Mosberger 	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
16992d53139fSDavid Mosberger 	case GetPortErrorCount:
17002d53139fSDavid Mosberger 	case SetHubDepth:
17012d53139fSDavid Mosberger 		/* USB3 only */
17022d53139fSDavid Mosberger 		goto error;
17032d53139fSDavid Mosberger 
17042d53139fSDavid Mosberger 	case GetHubStatus:
17052d53139fSDavid Mosberger 		*(__le32 *) buf = cpu_to_le32(0);
17062d53139fSDavid Mosberger 		break;
17072d53139fSDavid Mosberger 
17082d53139fSDavid Mosberger 	case GetPortStatus:
17092d53139fSDavid Mosberger 		if (index != 1) {
17102d53139fSDavid Mosberger 			retval = -EPIPE;
17112d53139fSDavid Mosberger 			goto error;
17122d53139fSDavid Mosberger 		}
17132d53139fSDavid Mosberger 		((__le16 *) buf)[0] = cpu_to_le16(max3421_hcd->port_status);
17142d53139fSDavid Mosberger 		((__le16 *) buf)[1] =
17152d53139fSDavid Mosberger 			cpu_to_le16(max3421_hcd->port_status >> 16);
17162d53139fSDavid Mosberger 		break;
17172d53139fSDavid Mosberger 
17182d53139fSDavid Mosberger 	case SetHubFeature:
17192d53139fSDavid Mosberger 		retval = -EPIPE;
17202d53139fSDavid Mosberger 		break;
17212d53139fSDavid Mosberger 
17222d53139fSDavid Mosberger 	case SetPortFeature:
17232d53139fSDavid Mosberger 		switch (value) {
17242d53139fSDavid Mosberger 		case USB_PORT_FEAT_LINK_STATE:
17252d53139fSDavid Mosberger 		case USB_PORT_FEAT_U1_TIMEOUT:
17262d53139fSDavid Mosberger 		case USB_PORT_FEAT_U2_TIMEOUT:
17272d53139fSDavid Mosberger 		case USB_PORT_FEAT_BH_PORT_RESET:
17282d53139fSDavid Mosberger 			goto error;
17292d53139fSDavid Mosberger 		case USB_PORT_FEAT_SUSPEND:
17302d53139fSDavid Mosberger 			if (max3421_hcd->active)
17312d53139fSDavid Mosberger 				max3421_hcd->port_status |=
17322d53139fSDavid Mosberger 					USB_PORT_STAT_SUSPEND;
17332d53139fSDavid Mosberger 			break;
17342d53139fSDavid Mosberger 		case USB_PORT_FEAT_POWER:
17352d53139fSDavid Mosberger 			dev_dbg(hcd->self.controller, "power-on\n");
17362d53139fSDavid Mosberger 			max3421_hcd->port_status |= USB_PORT_STAT_POWER;
17374055e5e5SDavid Mosberger-Tang 			max3421_gpout_set_value(hcd, pdata->vbus_gpout,
17384055e5e5SDavid Mosberger-Tang 						pdata->vbus_active_level);
17392d53139fSDavid Mosberger 			break;
17402d53139fSDavid Mosberger 		case USB_PORT_FEAT_RESET:
17412d53139fSDavid Mosberger 			max3421_reset_port(hcd);
17420d9b6d49SGustavo A. R. Silva 			fallthrough;
17432d53139fSDavid Mosberger 		default:
17442d53139fSDavid Mosberger 			if ((max3421_hcd->port_status & USB_PORT_STAT_POWER)
17452d53139fSDavid Mosberger 			    != 0)
17462d53139fSDavid Mosberger 				max3421_hcd->port_status |= (1 << value);
17472d53139fSDavid Mosberger 		}
17482d53139fSDavid Mosberger 		break;
17492d53139fSDavid Mosberger 
17502d53139fSDavid Mosberger 	default:
17512d53139fSDavid Mosberger 		dev_dbg(hcd->self.controller,
17522d53139fSDavid Mosberger 			"hub control req%04x v%04x i%04x l%d\n",
17532d53139fSDavid Mosberger 			type_req, value, index, length);
17542d53139fSDavid Mosberger error:		/* "protocol stall" on error */
17552d53139fSDavid Mosberger 		retval = -EPIPE;
17562d53139fSDavid Mosberger 	}
17572d53139fSDavid Mosberger 
17582d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
17592d53139fSDavid Mosberger 	return retval;
17602d53139fSDavid Mosberger }
17612d53139fSDavid Mosberger 
17622d53139fSDavid Mosberger static int
max3421_bus_suspend(struct usb_hcd * hcd)17632d53139fSDavid Mosberger max3421_bus_suspend(struct usb_hcd *hcd)
17642d53139fSDavid Mosberger {
17652d53139fSDavid Mosberger 	return -1;
17662d53139fSDavid Mosberger }
17672d53139fSDavid Mosberger 
17682d53139fSDavid Mosberger static int
max3421_bus_resume(struct usb_hcd * hcd)17692d53139fSDavid Mosberger max3421_bus_resume(struct usb_hcd *hcd)
17702d53139fSDavid Mosberger {
17712d53139fSDavid Mosberger 	return -1;
17722d53139fSDavid Mosberger }
17732d53139fSDavid Mosberger 
1774887e2e0cSJulia Lawall static const struct hc_driver max3421_hcd_desc = {
17752d53139fSDavid Mosberger 	.description =		"max3421",
17762d53139fSDavid Mosberger 	.product_desc =		DRIVER_DESC,
17772d53139fSDavid Mosberger 	.hcd_priv_size =	sizeof(struct max3421_hcd),
17782d53139fSDavid Mosberger 	.flags =		HCD_USB11,
17792d53139fSDavid Mosberger 	.reset =		max3421_reset,
17802d53139fSDavid Mosberger 	.start =		max3421_start,
17812d53139fSDavid Mosberger 	.stop =			max3421_stop,
17822d53139fSDavid Mosberger 	.get_frame_number =	max3421_get_frame_number,
17832d53139fSDavid Mosberger 	.urb_enqueue =		max3421_urb_enqueue,
17842d53139fSDavid Mosberger 	.urb_dequeue =		max3421_urb_dequeue,
17852d53139fSDavid Mosberger 	.endpoint_disable =	max3421_endpoint_disable,
17862d53139fSDavid Mosberger 	.hub_status_data =	max3421_hub_status_data,
17872d53139fSDavid Mosberger 	.hub_control =		max3421_hub_control,
17882d53139fSDavid Mosberger 	.bus_suspend =		max3421_bus_suspend,
17892d53139fSDavid Mosberger 	.bus_resume =		max3421_bus_resume,
17902d53139fSDavid Mosberger };
17912d53139fSDavid Mosberger 
17922d53139fSDavid Mosberger static int
max3421_of_vbus_en_pin(struct device * dev,struct max3421_hcd_platform_data * pdata)1793721fdc83SJules Maselbas max3421_of_vbus_en_pin(struct device *dev, struct max3421_hcd_platform_data *pdata)
1794721fdc83SJules Maselbas {
1795721fdc83SJules Maselbas 	int retval;
1796721fdc83SJules Maselbas 	uint32_t value[2];
1797721fdc83SJules Maselbas 
1798721fdc83SJules Maselbas 	if (!pdata)
1799721fdc83SJules Maselbas 		return -EINVAL;
1800721fdc83SJules Maselbas 
1801721fdc83SJules Maselbas 	retval = of_property_read_u32_array(dev->of_node, "maxim,vbus-en-pin", value, 2);
1802721fdc83SJules Maselbas 	if (retval) {
1803721fdc83SJules Maselbas 		dev_err(dev, "device tree node property 'maxim,vbus-en-pin' is missing\n");
1804721fdc83SJules Maselbas 		return retval;
1805721fdc83SJules Maselbas 	}
1806721fdc83SJules Maselbas 	dev_info(dev, "property 'maxim,vbus-en-pin' value is <%d %d>\n", value[0], value[1]);
1807721fdc83SJules Maselbas 
1808721fdc83SJules Maselbas 	pdata->vbus_gpout = value[0];
1809721fdc83SJules Maselbas 	pdata->vbus_active_level = value[1];
1810721fdc83SJules Maselbas 
1811721fdc83SJules Maselbas 	return 0;
1812721fdc83SJules Maselbas }
1813721fdc83SJules Maselbas 
1814721fdc83SJules Maselbas static int
max3421_probe(struct spi_device * spi)18152d53139fSDavid Mosberger max3421_probe(struct spi_device *spi)
18162d53139fSDavid Mosberger {
1817721fdc83SJules Maselbas 	struct device *dev = &spi->dev;
18182d53139fSDavid Mosberger 	struct max3421_hcd *max3421_hcd;
181905dfa5c9SDavid Mosberger-Tang 	struct usb_hcd *hcd = NULL;
1820721fdc83SJules Maselbas 	struct max3421_hcd_platform_data *pdata = NULL;
18215a569343SYang Yingliang 	int retval;
18222d53139fSDavid Mosberger 
18232d53139fSDavid Mosberger 	if (spi_setup(spi) < 0) {
18242d53139fSDavid Mosberger 		dev_err(&spi->dev, "Unable to setup SPI bus");
18252d53139fSDavid Mosberger 		return -EFAULT;
18262d53139fSDavid Mosberger 	}
18272d53139fSDavid Mosberger 
1828721fdc83SJules Maselbas 	if (!spi->irq) {
1829721fdc83SJules Maselbas 		dev_err(dev, "Failed to get SPI IRQ");
1830721fdc83SJules Maselbas 		return -EFAULT;
1831721fdc83SJules Maselbas 	}
1832721fdc83SJules Maselbas 
1833721fdc83SJules Maselbas 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
1834721fdc83SJules Maselbas 		pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL);
1835721fdc83SJules Maselbas 		if (!pdata) {
1836721fdc83SJules Maselbas 			retval = -ENOMEM;
1837721fdc83SJules Maselbas 			goto error;
1838721fdc83SJules Maselbas 		}
1839721fdc83SJules Maselbas 		retval = max3421_of_vbus_en_pin(dev, pdata);
1840721fdc83SJules Maselbas 		if (retval)
1841721fdc83SJules Maselbas 			goto error;
1842721fdc83SJules Maselbas 
1843721fdc83SJules Maselbas 		spi->dev.platform_data = pdata;
1844721fdc83SJules Maselbas 	}
1845721fdc83SJules Maselbas 
1846721fdc83SJules Maselbas 	pdata = spi->dev.platform_data;
1847721fdc83SJules Maselbas 	if (!pdata) {
1848721fdc83SJules Maselbas 		dev_err(&spi->dev, "driver configuration data is not provided\n");
1849721fdc83SJules Maselbas 		retval = -EFAULT;
1850721fdc83SJules Maselbas 		goto error;
1851721fdc83SJules Maselbas 	}
1852721fdc83SJules Maselbas 	if (pdata->vbus_active_level > 1) {
1853721fdc83SJules Maselbas 		dev_err(&spi->dev, "vbus active level value %d is out of range (0/1)\n", pdata->vbus_active_level);
1854721fdc83SJules Maselbas 		retval = -EINVAL;
1855721fdc83SJules Maselbas 		goto error;
1856721fdc83SJules Maselbas 	}
1857721fdc83SJules Maselbas 	if (pdata->vbus_gpout < 1 || pdata->vbus_gpout > MAX3421_GPOUT_COUNT) {
1858721fdc83SJules Maselbas 		dev_err(&spi->dev, "vbus gpout value %d is out of range (1..8)\n", pdata->vbus_gpout);
1859721fdc83SJules Maselbas 		retval = -EINVAL;
1860721fdc83SJules Maselbas 		goto error;
1861721fdc83SJules Maselbas 	}
1862721fdc83SJules Maselbas 
18635a569343SYang Yingliang 	retval = -ENOMEM;
18642d53139fSDavid Mosberger 	hcd = usb_create_hcd(&max3421_hcd_desc, &spi->dev,
18652d53139fSDavid Mosberger 			     dev_name(&spi->dev));
18662d53139fSDavid Mosberger 	if (!hcd) {
18672d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to create HCD structure\n");
186805dfa5c9SDavid Mosberger-Tang 		goto error;
18692d53139fSDavid Mosberger 	}
18702d53139fSDavid Mosberger 	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
18712d53139fSDavid Mosberger 	max3421_hcd = hcd_to_max3421(hcd);
18722d53139fSDavid Mosberger 	INIT_LIST_HEAD(&max3421_hcd->ep_list);
1873fc153abaSUwe Kleine-König 	spi_set_drvdata(spi, max3421_hcd);
18742d53139fSDavid Mosberger 
187505dfa5c9SDavid Mosberger-Tang 	max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL);
187613dcf780SWolfram Sang 	if (!max3421_hcd->tx)
187705dfa5c9SDavid Mosberger-Tang 		goto error;
187805dfa5c9SDavid Mosberger-Tang 	max3421_hcd->rx = kmalloc(sizeof(*max3421_hcd->rx), GFP_KERNEL);
187913dcf780SWolfram Sang 	if (!max3421_hcd->rx)
188005dfa5c9SDavid Mosberger-Tang 		goto error;
188105dfa5c9SDavid Mosberger-Tang 
18822d53139fSDavid Mosberger 	max3421_hcd->spi_thread = kthread_run(max3421_spi_thread, hcd,
18832d53139fSDavid Mosberger 					      "max3421_spi_thread");
18842d53139fSDavid Mosberger 	if (max3421_hcd->spi_thread == ERR_PTR(-ENOMEM)) {
18852d53139fSDavid Mosberger 		dev_err(&spi->dev,
18862d53139fSDavid Mosberger 			"failed to create SPI thread (out of memory)\n");
188705dfa5c9SDavid Mosberger-Tang 		goto error;
18882d53139fSDavid Mosberger 	}
18892d53139fSDavid Mosberger 
18902d53139fSDavid Mosberger 	retval = usb_add_hcd(hcd, 0, 0);
18912d53139fSDavid Mosberger 	if (retval) {
18922d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to add HCD\n");
189305dfa5c9SDavid Mosberger-Tang 		goto error;
18942d53139fSDavid Mosberger 	}
18952d53139fSDavid Mosberger 
18962d53139fSDavid Mosberger 	retval = request_irq(spi->irq, max3421_irq_handler,
18972d53139fSDavid Mosberger 			     IRQF_TRIGGER_LOW, "max3421", hcd);
18982d53139fSDavid Mosberger 	if (retval < 0) {
18992d53139fSDavid Mosberger 		dev_err(&spi->dev, "failed to request irq %d\n", spi->irq);
190005dfa5c9SDavid Mosberger-Tang 		goto error;
19012d53139fSDavid Mosberger 	}
19022d53139fSDavid Mosberger 	return 0;
190305dfa5c9SDavid Mosberger-Tang 
190405dfa5c9SDavid Mosberger-Tang error:
1905721fdc83SJules Maselbas 	if (IS_ENABLED(CONFIG_OF) && dev->of_node && pdata) {
1906721fdc83SJules Maselbas 		devm_kfree(&spi->dev, pdata);
1907721fdc83SJules Maselbas 		spi->dev.platform_data = NULL;
1908721fdc83SJules Maselbas 	}
1909721fdc83SJules Maselbas 
191005dfa5c9SDavid Mosberger-Tang 	if (hcd) {
191105dfa5c9SDavid Mosberger-Tang 		kfree(max3421_hcd->tx);
191205dfa5c9SDavid Mosberger-Tang 		kfree(max3421_hcd->rx);
191305dfa5c9SDavid Mosberger-Tang 		if (max3421_hcd->spi_thread)
191405dfa5c9SDavid Mosberger-Tang 			kthread_stop(max3421_hcd->spi_thread);
191505dfa5c9SDavid Mosberger-Tang 		usb_put_hcd(hcd);
191605dfa5c9SDavid Mosberger-Tang 	}
191705dfa5c9SDavid Mosberger-Tang 	return retval;
19182d53139fSDavid Mosberger }
19192d53139fSDavid Mosberger 
1920a0386bbaSUwe Kleine-König static void
max3421_remove(struct spi_device * spi)19212d53139fSDavid Mosberger max3421_remove(struct spi_device *spi)
19222d53139fSDavid Mosberger {
1923fc153abaSUwe Kleine-König 	struct max3421_hcd *max3421_hcd;
1924fc153abaSUwe Kleine-König 	struct usb_hcd *hcd;
19252d53139fSDavid Mosberger 	unsigned long flags;
19262d53139fSDavid Mosberger 
1927fc153abaSUwe Kleine-König 	max3421_hcd = spi_get_drvdata(spi);
19282d53139fSDavid Mosberger 	hcd = max3421_to_hcd(max3421_hcd);
19292d53139fSDavid Mosberger 
19302d53139fSDavid Mosberger 	usb_remove_hcd(hcd);
19312d53139fSDavid Mosberger 
19322d53139fSDavid Mosberger 	spin_lock_irqsave(&max3421_hcd->lock, flags);
19332d53139fSDavid Mosberger 
19342d53139fSDavid Mosberger 	kthread_stop(max3421_hcd->spi_thread);
19352d53139fSDavid Mosberger 
19362d53139fSDavid Mosberger 	spin_unlock_irqrestore(&max3421_hcd->lock, flags);
19372d53139fSDavid Mosberger 
19382d53139fSDavid Mosberger 	free_irq(spi->irq, hcd);
19392d53139fSDavid Mosberger 
19402d53139fSDavid Mosberger 	usb_put_hcd(hcd);
19412d53139fSDavid Mosberger }
19422d53139fSDavid Mosberger 
1943721fdc83SJules Maselbas static const struct of_device_id max3421_of_match_table[] = {
1944721fdc83SJules Maselbas 	{ .compatible = "maxim,max3421", },
1945721fdc83SJules Maselbas 	{},
1946721fdc83SJules Maselbas };
1947721fdc83SJules Maselbas MODULE_DEVICE_TABLE(of, max3421_of_match_table);
1948721fdc83SJules Maselbas 
19492d53139fSDavid Mosberger static struct spi_driver max3421_driver = {
19502d53139fSDavid Mosberger 	.probe		= max3421_probe,
19512d53139fSDavid Mosberger 	.remove		= max3421_remove,
19522d53139fSDavid Mosberger 	.driver		= {
19532d53139fSDavid Mosberger 		.name	= "max3421-hcd",
1954*658e467bSKrzysztof Kozlowski 		.of_match_table = max3421_of_match_table,
19552d53139fSDavid Mosberger 	},
19562d53139fSDavid Mosberger };
19572d53139fSDavid Mosberger 
19587df45d5fSSachin Kamat module_spi_driver(max3421_driver);
19592d53139fSDavid Mosberger 
19602d53139fSDavid Mosberger MODULE_DESCRIPTION(DRIVER_DESC);
19612d53139fSDavid Mosberger MODULE_AUTHOR("David Mosberger <davidm@egauge.net>");
19622d53139fSDavid Mosberger MODULE_LICENSE("GPL");
1963