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