162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * ISP116x register declarations and HCD data structures
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
662306a36Sopenharmony_ci * Portions:
762306a36Sopenharmony_ci * Copyright (C) 2004 Lothar Wassmann
862306a36Sopenharmony_ci * Copyright (C) 2004 Psion Teklogix
962306a36Sopenharmony_ci * Copyright (C) 2004 David Brownell
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* us of 1ms frame */
1362306a36Sopenharmony_ci#define  MAX_LOAD_LIMIT		850
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* Full speed: max # of bytes to transfer for a single urb
1662306a36Sopenharmony_ci   at a time must be < 1024 && must be multiple of 64.
1762306a36Sopenharmony_ci   832 allows transferring 4kiB within 5 frames. */
1862306a36Sopenharmony_ci#define MAX_TRANSFER_SIZE_FULLSPEED	832
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Low speed: there is no reason to schedule in very big
2162306a36Sopenharmony_ci   chunks; often the requested long transfers are for
2262306a36Sopenharmony_ci   string descriptors containing short strings. */
2362306a36Sopenharmony_ci#define MAX_TRANSFER_SIZE_LOWSPEED	64
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* Bytetime (us), a rough indication of how much time it
2662306a36Sopenharmony_ci   would take to transfer a byte of useful data over USB */
2762306a36Sopenharmony_ci#define BYTE_TIME_FULLSPEED	1
2862306a36Sopenharmony_ci#define BYTE_TIME_LOWSPEED	20
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Buffer sizes */
3162306a36Sopenharmony_ci#define ISP116x_BUF_SIZE	4096
3262306a36Sopenharmony_ci#define ISP116x_ITL_BUFSIZE	0
3362306a36Sopenharmony_ci#define ISP116x_ATL_BUFSIZE	((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define ISP116x_WRITE_OFFSET	0x80
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*------------ ISP116x registers/bits ------------*/
3862306a36Sopenharmony_ci#define	HCREVISION	0x00
3962306a36Sopenharmony_ci#define	HCCONTROL	0x01
4062306a36Sopenharmony_ci#define		HCCONTROL_HCFS	(3 << 6)	/* host controller
4162306a36Sopenharmony_ci						   functional state */
4262306a36Sopenharmony_ci#define		HCCONTROL_USB_RESET	(0 << 6)
4362306a36Sopenharmony_ci#define		HCCONTROL_USB_RESUME	(1 << 6)
4462306a36Sopenharmony_ci#define		HCCONTROL_USB_OPER	(2 << 6)
4562306a36Sopenharmony_ci#define		HCCONTROL_USB_SUSPEND	(3 << 6)
4662306a36Sopenharmony_ci#define		HCCONTROL_RWC	(1 << 9)	/* remote wakeup connected */
4762306a36Sopenharmony_ci#define		HCCONTROL_RWE	(1 << 10)	/* remote wakeup enable */
4862306a36Sopenharmony_ci#define	HCCMDSTAT	0x02
4962306a36Sopenharmony_ci#define		HCCMDSTAT_HCR	(1 << 0)	/* host controller reset */
5062306a36Sopenharmony_ci#define		HCCMDSTAT_SOC	(3 << 16)	/* scheduling overrun count */
5162306a36Sopenharmony_ci#define	HCINTSTAT	0x03
5262306a36Sopenharmony_ci#define		HCINT_SO	(1 << 0)	/* scheduling overrun */
5362306a36Sopenharmony_ci#define		HCINT_WDH	(1 << 1)	/* writeback of done_head */
5462306a36Sopenharmony_ci#define		HCINT_SF	(1 << 2)	/* start frame */
5562306a36Sopenharmony_ci#define		HCINT_RD	(1 << 3)	/* resume detect */
5662306a36Sopenharmony_ci#define		HCINT_UE	(1 << 4)	/* unrecoverable error */
5762306a36Sopenharmony_ci#define		HCINT_FNO	(1 << 5)	/* frame number overflow */
5862306a36Sopenharmony_ci#define		HCINT_RHSC	(1 << 6)	/* root hub status change */
5962306a36Sopenharmony_ci#define		HCINT_OC	(1 << 30)	/* ownership change */
6062306a36Sopenharmony_ci#define		HCINT_MIE	(1 << 31)	/* master interrupt enable */
6162306a36Sopenharmony_ci#define	HCINTENB	0x04
6262306a36Sopenharmony_ci#define	HCINTDIS	0x05
6362306a36Sopenharmony_ci#define	HCFMINTVL	0x0d
6462306a36Sopenharmony_ci#define	HCFMREM		0x0e
6562306a36Sopenharmony_ci#define	HCFMNUM		0x0f
6662306a36Sopenharmony_ci#define	HCLSTHRESH	0x11
6762306a36Sopenharmony_ci#define	HCRHDESCA	0x12
6862306a36Sopenharmony_ci#define		RH_A_NDP	(0x3 << 0)	/* # downstream ports */
6962306a36Sopenharmony_ci#define		RH_A_PSM	(1 << 8)	/* power switching mode */
7062306a36Sopenharmony_ci#define		RH_A_NPS	(1 << 9)	/* no power switching */
7162306a36Sopenharmony_ci#define		RH_A_DT		(1 << 10)	/* device type (mbz) */
7262306a36Sopenharmony_ci#define		RH_A_OCPM	(1 << 11)	/* overcurrent protection
7362306a36Sopenharmony_ci						   mode */
7462306a36Sopenharmony_ci#define		RH_A_NOCP	(1 << 12)	/* no overcurrent protection */
7562306a36Sopenharmony_ci#define		RH_A_POTPGT	(0xff << 24)	/* power on -> power good
7662306a36Sopenharmony_ci						   time */
7762306a36Sopenharmony_ci#define	HCRHDESCB	0x13
7862306a36Sopenharmony_ci#define		RH_B_DR		(0xffff << 0)	/* device removable flags */
7962306a36Sopenharmony_ci#define		RH_B_PPCM	(0xffff << 16)	/* port power control mask */
8062306a36Sopenharmony_ci#define	HCRHSTATUS	0x14
8162306a36Sopenharmony_ci#define		RH_HS_LPS	(1 << 0)	/* local power status */
8262306a36Sopenharmony_ci#define		RH_HS_OCI	(1 << 1)	/* over current indicator */
8362306a36Sopenharmony_ci#define		RH_HS_DRWE	(1 << 15)	/* device remote wakeup
8462306a36Sopenharmony_ci						   enable */
8562306a36Sopenharmony_ci#define		RH_HS_LPSC	(1 << 16)	/* local power status change */
8662306a36Sopenharmony_ci#define		RH_HS_OCIC	(1 << 17)	/* over current indicator
8762306a36Sopenharmony_ci						   change */
8862306a36Sopenharmony_ci#define		RH_HS_CRWE	(1 << 31)	/* clear remote wakeup
8962306a36Sopenharmony_ci						   enable */
9062306a36Sopenharmony_ci#define	HCRHPORT1	0x15
9162306a36Sopenharmony_ci#define		RH_PS_CCS	(1 << 0)	/* current connect status */
9262306a36Sopenharmony_ci#define		RH_PS_PES	(1 << 1)	/* port enable status */
9362306a36Sopenharmony_ci#define		RH_PS_PSS	(1 << 2)	/* port suspend status */
9462306a36Sopenharmony_ci#define		RH_PS_POCI	(1 << 3)	/* port over current
9562306a36Sopenharmony_ci						   indicator */
9662306a36Sopenharmony_ci#define		RH_PS_PRS	(1 << 4)	/* port reset status */
9762306a36Sopenharmony_ci#define		RH_PS_PPS	(1 << 8)	/* port power status */
9862306a36Sopenharmony_ci#define		RH_PS_LSDA	(1 << 9)	/* low speed device attached */
9962306a36Sopenharmony_ci#define		RH_PS_CSC	(1 << 16)	/* connect status change */
10062306a36Sopenharmony_ci#define		RH_PS_PESC	(1 << 17)	/* port enable status change */
10162306a36Sopenharmony_ci#define		RH_PS_PSSC	(1 << 18)	/* port suspend status
10262306a36Sopenharmony_ci						   change */
10362306a36Sopenharmony_ci#define		RH_PS_OCIC	(1 << 19)	/* over current indicator
10462306a36Sopenharmony_ci						   change */
10562306a36Sopenharmony_ci#define		RH_PS_PRSC	(1 << 20)	/* port reset status change */
10662306a36Sopenharmony_ci#define		HCRHPORT_CLRMASK	(0x1f << 16)
10762306a36Sopenharmony_ci#define	HCRHPORT2	0x16
10862306a36Sopenharmony_ci#define	HCHWCFG		0x20
10962306a36Sopenharmony_ci#define		HCHWCFG_15KRSEL		(1 << 12)
11062306a36Sopenharmony_ci#define		HCHWCFG_CLKNOTSTOP	(1 << 11)
11162306a36Sopenharmony_ci#define		HCHWCFG_ANALOG_OC	(1 << 10)
11262306a36Sopenharmony_ci#define		HCHWCFG_DACK_MODE	(1 << 8)
11362306a36Sopenharmony_ci#define		HCHWCFG_EOT_POL		(1 << 7)
11462306a36Sopenharmony_ci#define		HCHWCFG_DACK_POL	(1 << 6)
11562306a36Sopenharmony_ci#define		HCHWCFG_DREQ_POL	(1 << 5)
11662306a36Sopenharmony_ci#define		HCHWCFG_DBWIDTH_MASK	(0x03 << 3)
11762306a36Sopenharmony_ci#define		HCHWCFG_DBWIDTH(n)	(((n) << 3) & HCHWCFG_DBWIDTH_MASK)
11862306a36Sopenharmony_ci#define		HCHWCFG_INT_POL		(1 << 2)
11962306a36Sopenharmony_ci#define		HCHWCFG_INT_TRIGGER	(1 << 1)
12062306a36Sopenharmony_ci#define		HCHWCFG_INT_ENABLE	(1 << 0)
12162306a36Sopenharmony_ci#define	HCDMACFG	0x21
12262306a36Sopenharmony_ci#define		HCDMACFG_BURST_LEN_MASK	(0x03 << 5)
12362306a36Sopenharmony_ci#define		HCDMACFG_BURST_LEN(n)	(((n) << 5) & HCDMACFG_BURST_LEN_MASK)
12462306a36Sopenharmony_ci#define		HCDMACFG_BURST_LEN_1	HCDMACFG_BURST_LEN(0)
12562306a36Sopenharmony_ci#define		HCDMACFG_BURST_LEN_4	HCDMACFG_BURST_LEN(1)
12662306a36Sopenharmony_ci#define		HCDMACFG_BURST_LEN_8	HCDMACFG_BURST_LEN(2)
12762306a36Sopenharmony_ci#define		HCDMACFG_DMA_ENABLE	(1 << 4)
12862306a36Sopenharmony_ci#define		HCDMACFG_BUF_TYPE_MASK	(0x07 << 1)
12962306a36Sopenharmony_ci#define		HCDMACFG_CTR_SEL	(1 << 2)
13062306a36Sopenharmony_ci#define		HCDMACFG_ITLATL_SEL	(1 << 1)
13162306a36Sopenharmony_ci#define		HCDMACFG_DMA_RW_SELECT	(1 << 0)
13262306a36Sopenharmony_ci#define	HCXFERCTR	0x22
13362306a36Sopenharmony_ci#define	HCuPINT		0x24
13462306a36Sopenharmony_ci#define		HCuPINT_SOF		(1 << 0)
13562306a36Sopenharmony_ci#define		HCuPINT_ATL		(1 << 1)
13662306a36Sopenharmony_ci#define		HCuPINT_AIIEOT		(1 << 2)
13762306a36Sopenharmony_ci#define		HCuPINT_OPR		(1 << 4)
13862306a36Sopenharmony_ci#define		HCuPINT_SUSP		(1 << 5)
13962306a36Sopenharmony_ci#define		HCuPINT_CLKRDY		(1 << 6)
14062306a36Sopenharmony_ci#define	HCuPINTENB	0x25
14162306a36Sopenharmony_ci#define	HCCHIPID	0x27
14262306a36Sopenharmony_ci#define		HCCHIPID_MASK		0xff00
14362306a36Sopenharmony_ci#define		HCCHIPID_MAGIC		0x6100
14462306a36Sopenharmony_ci#define	HCSCRATCH	0x28
14562306a36Sopenharmony_ci#define	HCSWRES		0x29
14662306a36Sopenharmony_ci#define		HCSWRES_MAGIC		0x00f6
14762306a36Sopenharmony_ci#define	HCITLBUFLEN	0x2a
14862306a36Sopenharmony_ci#define	HCATLBUFLEN	0x2b
14962306a36Sopenharmony_ci#define	HCBUFSTAT	0x2c
15062306a36Sopenharmony_ci#define		HCBUFSTAT_ITL0_FULL	(1 << 0)
15162306a36Sopenharmony_ci#define		HCBUFSTAT_ITL1_FULL	(1 << 1)
15262306a36Sopenharmony_ci#define		HCBUFSTAT_ATL_FULL	(1 << 2)
15362306a36Sopenharmony_ci#define		HCBUFSTAT_ITL0_DONE	(1 << 3)
15462306a36Sopenharmony_ci#define		HCBUFSTAT_ITL1_DONE	(1 << 4)
15562306a36Sopenharmony_ci#define		HCBUFSTAT_ATL_DONE	(1 << 5)
15662306a36Sopenharmony_ci#define	HCRDITL0LEN	0x2d
15762306a36Sopenharmony_ci#define	HCRDITL1LEN	0x2e
15862306a36Sopenharmony_ci#define	HCITLPORT	0x40
15962306a36Sopenharmony_ci#define	HCATLPORT	0x41
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* Philips transfer descriptor */
16262306a36Sopenharmony_cistruct ptd {
16362306a36Sopenharmony_ci	u16 count;
16462306a36Sopenharmony_ci#define	PTD_COUNT_MSK	(0x3ff << 0)
16562306a36Sopenharmony_ci#define	PTD_TOGGLE_MSK	(1 << 10)
16662306a36Sopenharmony_ci#define	PTD_ACTIVE_MSK	(1 << 11)
16762306a36Sopenharmony_ci#define	PTD_CC_MSK	(0xf << 12)
16862306a36Sopenharmony_ci	u16 mps;
16962306a36Sopenharmony_ci#define	PTD_MPS_MSK	(0x3ff << 0)
17062306a36Sopenharmony_ci#define	PTD_SPD_MSK	(1 << 10)
17162306a36Sopenharmony_ci#define	PTD_LAST_MSK	(1 << 11)
17262306a36Sopenharmony_ci#define	PTD_EP_MSK	(0xf << 12)
17362306a36Sopenharmony_ci	u16 len;
17462306a36Sopenharmony_ci#define	PTD_LEN_MSK	(0x3ff << 0)
17562306a36Sopenharmony_ci#define	PTD_DIR_MSK	(3 << 10)
17662306a36Sopenharmony_ci#define	PTD_DIR_SETUP	(0)
17762306a36Sopenharmony_ci#define	PTD_DIR_OUT	(1)
17862306a36Sopenharmony_ci#define	PTD_DIR_IN	(2)
17962306a36Sopenharmony_ci#define	PTD_B5_5_MSK	(1 << 13)
18062306a36Sopenharmony_ci	u16 faddr;
18162306a36Sopenharmony_ci#define	PTD_FA_MSK	(0x7f << 0)
18262306a36Sopenharmony_ci#define	PTD_FMT_MSK	(1 << 7)
18362306a36Sopenharmony_ci} __attribute__ ((packed, aligned(2)));
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* PTD accessor macros. */
18662306a36Sopenharmony_ci#define PTD_GET_COUNT(p)	(((p)->count & PTD_COUNT_MSK) >> 0)
18762306a36Sopenharmony_ci#define PTD_COUNT(v)		(((v) << 0) & PTD_COUNT_MSK)
18862306a36Sopenharmony_ci#define PTD_GET_TOGGLE(p)	(((p)->count & PTD_TOGGLE_MSK) >> 10)
18962306a36Sopenharmony_ci#define PTD_TOGGLE(v)		(((v) << 10) & PTD_TOGGLE_MSK)
19062306a36Sopenharmony_ci#define PTD_GET_ACTIVE(p)	(((p)->count & PTD_ACTIVE_MSK) >> 11)
19162306a36Sopenharmony_ci#define PTD_ACTIVE(v)		(((v) << 11) & PTD_ACTIVE_MSK)
19262306a36Sopenharmony_ci#define PTD_GET_CC(p)		(((p)->count & PTD_CC_MSK) >> 12)
19362306a36Sopenharmony_ci#define PTD_CC(v)		(((v) << 12) & PTD_CC_MSK)
19462306a36Sopenharmony_ci#define PTD_GET_MPS(p)		(((p)->mps & PTD_MPS_MSK) >> 0)
19562306a36Sopenharmony_ci#define PTD_MPS(v)		(((v) << 0) & PTD_MPS_MSK)
19662306a36Sopenharmony_ci#define PTD_GET_SPD(p)		(((p)->mps & PTD_SPD_MSK) >> 10)
19762306a36Sopenharmony_ci#define PTD_SPD(v)		(((v) << 10) & PTD_SPD_MSK)
19862306a36Sopenharmony_ci#define PTD_GET_LAST(p)		(((p)->mps & PTD_LAST_MSK) >> 11)
19962306a36Sopenharmony_ci#define PTD_LAST(v)		(((v) << 11) & PTD_LAST_MSK)
20062306a36Sopenharmony_ci#define PTD_GET_EP(p)		(((p)->mps & PTD_EP_MSK) >> 12)
20162306a36Sopenharmony_ci#define PTD_EP(v)		(((v) << 12) & PTD_EP_MSK)
20262306a36Sopenharmony_ci#define PTD_GET_LEN(p)		(((p)->len & PTD_LEN_MSK) >> 0)
20362306a36Sopenharmony_ci#define PTD_LEN(v)		(((v) << 0) & PTD_LEN_MSK)
20462306a36Sopenharmony_ci#define PTD_GET_DIR(p)		(((p)->len & PTD_DIR_MSK) >> 10)
20562306a36Sopenharmony_ci#define PTD_DIR(v)		(((v) << 10) & PTD_DIR_MSK)
20662306a36Sopenharmony_ci#define PTD_GET_B5_5(p)		(((p)->len & PTD_B5_5_MSK) >> 13)
20762306a36Sopenharmony_ci#define PTD_B5_5(v)		(((v) << 13) & PTD_B5_5_MSK)
20862306a36Sopenharmony_ci#define PTD_GET_FA(p)		(((p)->faddr & PTD_FA_MSK) >> 0)
20962306a36Sopenharmony_ci#define PTD_FA(v)		(((v) << 0) & PTD_FA_MSK)
21062306a36Sopenharmony_ci#define PTD_GET_FMT(p)		(((p)->faddr & PTD_FMT_MSK) >> 7)
21162306a36Sopenharmony_ci#define PTD_FMT(v)		(((v) << 7) & PTD_FMT_MSK)
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/*  Hardware transfer status codes -- CC from ptd->count */
21462306a36Sopenharmony_ci#define TD_CC_NOERROR      0x00
21562306a36Sopenharmony_ci#define TD_CC_CRC          0x01
21662306a36Sopenharmony_ci#define TD_CC_BITSTUFFING  0x02
21762306a36Sopenharmony_ci#define TD_CC_DATATOGGLEM  0x03
21862306a36Sopenharmony_ci#define TD_CC_STALL        0x04
21962306a36Sopenharmony_ci#define TD_DEVNOTRESP      0x05
22062306a36Sopenharmony_ci#define TD_PIDCHECKFAIL    0x06
22162306a36Sopenharmony_ci#define TD_UNEXPECTEDPID   0x07
22262306a36Sopenharmony_ci#define TD_DATAOVERRUN     0x08
22362306a36Sopenharmony_ci#define TD_DATAUNDERRUN    0x09
22462306a36Sopenharmony_ci    /* 0x0A, 0x0B reserved for hardware */
22562306a36Sopenharmony_ci#define TD_BUFFEROVERRUN   0x0C
22662306a36Sopenharmony_ci#define TD_BUFFERUNDERRUN  0x0D
22762306a36Sopenharmony_ci    /* 0x0E, 0x0F reserved for HCD */
22862306a36Sopenharmony_ci#define TD_NOTACCESSED     0x0F
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci/* map PTD status codes (CC) to errno values */
23162306a36Sopenharmony_cistatic const int cc_to_error[16] = {
23262306a36Sopenharmony_ci	/* No  Error  */ 0,
23362306a36Sopenharmony_ci	/* CRC Error  */ -EILSEQ,
23462306a36Sopenharmony_ci	/* Bit Stuff  */ -EPROTO,
23562306a36Sopenharmony_ci	/* Data Togg  */ -EILSEQ,
23662306a36Sopenharmony_ci	/* Stall      */ -EPIPE,
23762306a36Sopenharmony_ci	/* DevNotResp */ -ETIME,
23862306a36Sopenharmony_ci	/* PIDCheck   */ -EPROTO,
23962306a36Sopenharmony_ci	/* UnExpPID   */ -EPROTO,
24062306a36Sopenharmony_ci	/* DataOver   */ -EOVERFLOW,
24162306a36Sopenharmony_ci	/* DataUnder  */ -EREMOTEIO,
24262306a36Sopenharmony_ci	/* (for hw)   */ -EIO,
24362306a36Sopenharmony_ci	/* (for hw)   */ -EIO,
24462306a36Sopenharmony_ci	/* BufferOver */ -ECOMM,
24562306a36Sopenharmony_ci	/* BuffUnder  */ -ENOSR,
24662306a36Sopenharmony_ci	/* (for HCD)  */ -EALREADY,
24762306a36Sopenharmony_ci	/* (for HCD)  */ -EALREADY
24862306a36Sopenharmony_ci};
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/*--------------------------------------------------------------*/
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci#define	LOG2_PERIODIC_SIZE	5	/* arbitrary; this matches OHCI */
25362306a36Sopenharmony_ci#define	PERIODIC_SIZE		(1 << LOG2_PERIODIC_SIZE)
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistruct isp116x {
25662306a36Sopenharmony_ci	spinlock_t lock;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	void __iomem *addr_reg;
25962306a36Sopenharmony_ci	void __iomem *data_reg;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	struct isp116x_platform_data *board;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	unsigned long stat1, stat2, stat4, stat8, stat16;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	/* HC registers */
26662306a36Sopenharmony_ci	u32 intenb;		/* "OHCI" interrupts */
26762306a36Sopenharmony_ci	u16 irqenb;		/* uP interrupts */
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/* Root hub registers */
27062306a36Sopenharmony_ci	u32 rhdesca;
27162306a36Sopenharmony_ci	u32 rhdescb;
27262306a36Sopenharmony_ci	u32 rhstatus;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/* async schedule: control, bulk */
27562306a36Sopenharmony_ci	struct list_head async;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* periodic schedule: int */
27862306a36Sopenharmony_ci	u16 load[PERIODIC_SIZE];
27962306a36Sopenharmony_ci	struct isp116x_ep *periodic[PERIODIC_SIZE];
28062306a36Sopenharmony_ci	unsigned periodic_count;
28162306a36Sopenharmony_ci	u16 fmindex;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	/* Schedule for the current frame */
28462306a36Sopenharmony_ci	struct isp116x_ep *atl_active;
28562306a36Sopenharmony_ci	int atl_buflen;
28662306a36Sopenharmony_ci	int atl_bufshrt;
28762306a36Sopenharmony_ci	int atl_last_dir;
28862306a36Sopenharmony_ci	atomic_t atl_finishing;
28962306a36Sopenharmony_ci};
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic inline struct isp116x *hcd_to_isp116x(struct usb_hcd *hcd)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	return (struct isp116x *)(hcd->hcd_priv);
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic inline struct usb_hcd *isp116x_to_hcd(struct isp116x *isp116x)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	return container_of((void *)isp116x, struct usb_hcd, hcd_priv);
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistruct isp116x_ep {
30262306a36Sopenharmony_ci	struct usb_host_endpoint *hep;
30362306a36Sopenharmony_ci	struct usb_device *udev;
30462306a36Sopenharmony_ci	struct ptd ptd;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	u8 maxpacket;
30762306a36Sopenharmony_ci	u8 epnum;
30862306a36Sopenharmony_ci	u8 nextpid;
30962306a36Sopenharmony_ci	u16 error_count;
31062306a36Sopenharmony_ci	u16 length;		/* of current packet */
31162306a36Sopenharmony_ci	unsigned char *data;	/* to databuf */
31262306a36Sopenharmony_ci	/* queue of active EP's (the ones scheduled for the
31362306a36Sopenharmony_ci	   current frame) */
31462306a36Sopenharmony_ci	struct isp116x_ep *active;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* periodic schedule */
31762306a36Sopenharmony_ci	u16 period;
31862306a36Sopenharmony_ci	u16 branch;
31962306a36Sopenharmony_ci	u16 load;
32062306a36Sopenharmony_ci	struct isp116x_ep *next;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	/* async schedule */
32362306a36Sopenharmony_ci	struct list_head schedule;
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci#define DBG(stuff...)		pr_debug("116x: " stuff)
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci#ifdef VERBOSE
33162306a36Sopenharmony_ci#    define VDBG		DBG
33262306a36Sopenharmony_ci#else
33362306a36Sopenharmony_ci#    define VDBG(stuff...)	do{}while(0)
33462306a36Sopenharmony_ci#endif
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci#define ERR(stuff...)		printk(KERN_ERR "116x: " stuff)
33762306a36Sopenharmony_ci#define WARNING(stuff...)	printk(KERN_WARNING "116x: " stuff)
33862306a36Sopenharmony_ci#define INFO(stuff...)		printk(KERN_INFO "116x: " stuff)
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/* ------------------------------------------------- */
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci#if defined(USE_PLATFORM_DELAY)
34362306a36Sopenharmony_ci#if defined(USE_NDELAY)
34462306a36Sopenharmony_ci#error USE_PLATFORM_DELAY and USE_NDELAY simultaneously defined.
34562306a36Sopenharmony_ci#endif
34662306a36Sopenharmony_ci#define	isp116x_delay(h,d)	(h)->board->delay(	\
34762306a36Sopenharmony_ci				isp116x_to_hcd(h)->self.controller,d)
34862306a36Sopenharmony_ci#define isp116x_check_platform_delay(h)	((h)->board->delay == NULL)
34962306a36Sopenharmony_ci#elif defined(USE_NDELAY)
35062306a36Sopenharmony_ci#define	isp116x_delay(h,d)	ndelay(d)
35162306a36Sopenharmony_ci#define isp116x_check_platform_delay(h)	0
35262306a36Sopenharmony_ci#else
35362306a36Sopenharmony_ci#define	isp116x_delay(h,d)	do{}while(0)
35462306a36Sopenharmony_ci#define isp116x_check_platform_delay(h)	0
35562306a36Sopenharmony_ci#endif
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	writew(reg & 0xff, isp116x->addr_reg);
36062306a36Sopenharmony_ci	isp116x_delay(isp116x, 300);
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic inline void isp116x_write_data16(struct isp116x *isp116x, u16 val)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	writew(val, isp116x->data_reg);
36662306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	__raw_writew(val, isp116x->data_reg);
37262306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
37362306a36Sopenharmony_ci}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_cistatic inline u16 isp116x_read_data16(struct isp116x *isp116x)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	u16 val;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	val = readw(isp116x->data_reg);
38062306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
38162306a36Sopenharmony_ci	return val;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic inline u16 isp116x_raw_read_data16(struct isp116x *isp116x)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	u16 val;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	val = __raw_readw(isp116x->data_reg);
38962306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
39062306a36Sopenharmony_ci	return val;
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic inline void isp116x_write_data32(struct isp116x *isp116x, u32 val)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	writew(val & 0xffff, isp116x->data_reg);
39662306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
39762306a36Sopenharmony_ci	writew(val >> 16, isp116x->data_reg);
39862306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic inline u32 isp116x_read_data32(struct isp116x *isp116x)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	u32 val;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	val = (u32) readw(isp116x->data_reg);
40662306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
40762306a36Sopenharmony_ci	val |= ((u32) readw(isp116x->data_reg)) << 16;
40862306a36Sopenharmony_ci	isp116x_delay(isp116x, 150);
40962306a36Sopenharmony_ci	return val;
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci/* Let's keep register access functions out of line. Hint:
41362306a36Sopenharmony_ci   we wait at least 150 ns at every access.
41462306a36Sopenharmony_ci*/
41562306a36Sopenharmony_cistatic u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	isp116x_write_addr(isp116x, reg);
41862306a36Sopenharmony_ci	return isp116x_read_data16(isp116x);
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	isp116x_write_addr(isp116x, reg);
42462306a36Sopenharmony_ci	return isp116x_read_data32(isp116x);
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cistatic void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
42862306a36Sopenharmony_ci				unsigned val)
42962306a36Sopenharmony_ci{
43062306a36Sopenharmony_ci	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
43162306a36Sopenharmony_ci	isp116x_write_data16(isp116x, (u16) (val & 0xffff));
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
43562306a36Sopenharmony_ci				unsigned val)
43662306a36Sopenharmony_ci{
43762306a36Sopenharmony_ci	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
43862306a36Sopenharmony_ci	isp116x_write_data32(isp116x, (u32) val);
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci#define isp116x_show_reg_log(d,r,s) {				\
44262306a36Sopenharmony_ci	if ((r) < 0x20) {			                \
44362306a36Sopenharmony_ci		DBG("%-12s[%02x]: %08x\n", #r,			\
44462306a36Sopenharmony_ci			r, isp116x_read_reg32(d, r));		\
44562306a36Sopenharmony_ci	} else {						\
44662306a36Sopenharmony_ci		DBG("%-12s[%02x]:     %04x\n", #r,		\
44762306a36Sopenharmony_ci			r, isp116x_read_reg16(d, r));	    	\
44862306a36Sopenharmony_ci	}							\
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci#define isp116x_show_reg_seq(d,r,s) {				\
45162306a36Sopenharmony_ci	if ((r) < 0x20) {					\
45262306a36Sopenharmony_ci		seq_printf(s, "%-12s[%02x]: %08x\n", #r,	\
45362306a36Sopenharmony_ci			r, isp116x_read_reg32(d, r));		\
45462306a36Sopenharmony_ci	} else {						\
45562306a36Sopenharmony_ci		seq_printf(s, "%-12s[%02x]:     %04x\n", #r,	\
45662306a36Sopenharmony_ci			r, isp116x_read_reg16(d, r));		\
45762306a36Sopenharmony_ci	}							\
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci#define isp116x_show_regs(d,type,s) {			\
46162306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCREVISION, s);	\
46262306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCCONTROL, s);	\
46362306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCCMDSTAT, s);	\
46462306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCINTSTAT, s);	\
46562306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCINTENB, s);	\
46662306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCFMINTVL, s);	\
46762306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCFMREM, s);		\
46862306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCFMNUM, s);		\
46962306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCLSTHRESH, s);	\
47062306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRHDESCA, s);	\
47162306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRHDESCB, s);	\
47262306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRHSTATUS, s);	\
47362306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRHPORT1, s);	\
47462306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRHPORT2, s);	\
47562306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCHWCFG, s);		\
47662306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCDMACFG, s);	\
47762306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCXFERCTR, s);	\
47862306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCuPINT, s);		\
47962306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCuPINTENB, s);	\
48062306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCCHIPID, s);	\
48162306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCSCRATCH, s);	\
48262306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCITLBUFLEN, s);	\
48362306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCATLBUFLEN, s);	\
48462306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCBUFSTAT, s);	\
48562306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRDITL0LEN, s);	\
48662306a36Sopenharmony_ci	isp116x_show_reg_##type(d, HCRDITL1LEN, s);	\
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci/*
49062306a36Sopenharmony_ci   Dump registers for debugfs.
49162306a36Sopenharmony_ci*/
49262306a36Sopenharmony_cistatic inline void isp116x_show_regs_seq(struct isp116x *isp116x,
49362306a36Sopenharmony_ci					  struct seq_file *s)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	isp116x_show_regs(isp116x, seq, s);
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci/*
49962306a36Sopenharmony_ci   Dump registers to syslog.
50062306a36Sopenharmony_ci*/
50162306a36Sopenharmony_cistatic inline void isp116x_show_regs_log(struct isp116x *isp116x)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	isp116x_show_regs(isp116x, log, NULL);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci#if defined(URB_TRACE)
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci#define PIPETYPE(pipe)  ({ char *__s;			\
50962306a36Sopenharmony_ci	if (usb_pipecontrol(pipe))	__s = "ctrl";	\
51062306a36Sopenharmony_ci	else if (usb_pipeint(pipe))	__s = "int";	\
51162306a36Sopenharmony_ci	else if (usb_pipebulk(pipe))	__s = "bulk";	\
51262306a36Sopenharmony_ci	else				__s = "iso";	\
51362306a36Sopenharmony_ci	__s;})
51462306a36Sopenharmony_ci#define PIPEDIR(pipe)   ({ usb_pipein(pipe) ? "in" : "out"; })
51562306a36Sopenharmony_ci#define URB_NOTSHORT(urb) ({ (urb)->transfer_flags & URB_SHORT_NOT_OK ? \
51662306a36Sopenharmony_ci	"short_not_ok" : ""; })
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci/* print debug info about the URB */
51962306a36Sopenharmony_cistatic void urb_dbg(struct urb *urb, char *msg)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	unsigned int pipe;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	if (!urb) {
52462306a36Sopenharmony_ci		DBG("%s: zero urb\n", msg);
52562306a36Sopenharmony_ci		return;
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci	pipe = urb->pipe;
52862306a36Sopenharmony_ci	DBG("%s: FA %d ep%d%s %s: len %d/%d %s\n", msg,
52962306a36Sopenharmony_ci	    usb_pipedevice(pipe), usb_pipeendpoint(pipe),
53062306a36Sopenharmony_ci	    PIPEDIR(pipe), PIPETYPE(pipe),
53162306a36Sopenharmony_ci	    urb->transfer_buffer_length, urb->actual_length, URB_NOTSHORT(urb));
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci#else
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci#define  urb_dbg(urb,msg)   do{}while(0)
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci#endif				/* ! defined(URB_TRACE) */
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci#if defined(PTD_TRACE)
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci#define PTD_DIR_STR(ptd)  ({char __c;		\
54362306a36Sopenharmony_ci	switch(PTD_GET_DIR(ptd)){		\
54462306a36Sopenharmony_ci	case 0:  __c = 's'; break;		\
54562306a36Sopenharmony_ci	case 1:  __c = 'o'; break;		\
54662306a36Sopenharmony_ci	default: __c = 'i'; break;		\
54762306a36Sopenharmony_ci	}; __c;})
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci/*
55062306a36Sopenharmony_ci  Dump PTD info. The code documents the format
55162306a36Sopenharmony_ci  perfectly, right :)
55262306a36Sopenharmony_ci*/
55362306a36Sopenharmony_cistatic inline void dump_ptd(struct ptd *ptd)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d  %x %x%x%x\n",
55662306a36Sopenharmony_ci	       PTD_GET_CC(ptd), PTD_GET_FA(ptd),
55762306a36Sopenharmony_ci	       PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
55862306a36Sopenharmony_ci	       PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
55962306a36Sopenharmony_ci	       PTD_GET_TOGGLE(ptd), PTD_GET_ACTIVE(ptd),
56062306a36Sopenharmony_ci	       PTD_GET_SPD(ptd), PTD_GET_LAST(ptd));
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_cistatic inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	int k;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) {
56862306a36Sopenharmony_ci		printk(KERN_WARNING "-> ");
56962306a36Sopenharmony_ci		for (k = 0; k < PTD_GET_LEN(ptd); ++k)
57062306a36Sopenharmony_ci			printk("%02x ", ((u8 *) buf)[k]);
57162306a36Sopenharmony_ci		printk("\n");
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cistatic inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	int k;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) {
58062306a36Sopenharmony_ci		printk(KERN_WARNING "<- ");
58162306a36Sopenharmony_ci		for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
58262306a36Sopenharmony_ci			printk("%02x ", ((u8 *) buf)[k]);
58362306a36Sopenharmony_ci		printk("\n");
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci	if (PTD_GET_LAST(ptd))
58662306a36Sopenharmony_ci		printk(KERN_WARNING "-\n");
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci#else
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci#define dump_ptd(ptd)               do{}while(0)
59262306a36Sopenharmony_ci#define dump_ptd_in_data(ptd,buf)   do{}while(0)
59362306a36Sopenharmony_ci#define dump_ptd_out_data(ptd,buf)  do{}while(0)
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci#endif				/* ! defined(PTD_TRACE) */
596