/****************************************************************************/
/* Copyright 2010, © Bendor Research Pty. Ltd. All rights reserved.			*/
/* Permission is granted to use this software for any purpose whatsoever	*/
/* as long as this copyright notice is preserved. The code is provided		*/
/* "as is", with no explicit, implicit or implied warranty or guarantee		*/
/* of any kind and Bendor Research Pty. Ltd. can not be held liable for		*/
/* any loss or damages arising out of the use of this software.				*/
/****************************************************************************/
/*																			*/
/*	Include file describing the OHCI-USB specification						*/
/*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~						*/
/*																			*/
/*	This file contains the header generated from the document called		*/
/*	"OpenHCI Open Host Controller Interface Specification for USB"			*/
/*	Release 1.0a by Compaq, Microsoft and National Semiconductor.			*/
/*																			*/
/*	All register names and bitfields are as per that document, except that	*/
/*	the Hc prefix is removed from each register name and each bitfield is	*/
/*	prefixed with OHCI_.													*/
/*																			*/
/*	2010 May	ZK		Original											*/
/*																			*/
/****************************************************************************/

#ifndef _OHCI_USB
#define	_OHCI_USB

/*
*	General transfer descriptor (in memory)
*/

typedef struct ohci_td {

	unsigned		Control;
	void			*CBP;				// Current buffer pointer
	struct ohci_td	*NextTD;			// Next transfer descriptor
	void			*BE;				// Buffer end

} OHCI_TD;

#define	OHCI_TD_CC_M		0xf0000000	// Completion code mask
#define	OHCI_TD_CC_S		28			// Completion code shift
#define	OHCI_TD_EC_M		0x0c000000	// Error count mask
#define	OHCI_TD_EC_S		26			// Error count shift
#define	OHCI_TD_T			0x03000000
#define	OHCI_TD_DI(n)		((n)<<<21)	// Delay interrupt by n frames
#define	OHCI_TD_DI_NEVER	0x00600000	// No interrupt at all
#define	OHCI_TD_DP			0x00180000	// Direction/pid
#define	OHCI_TD_DP_SETUP	0x00000000	// Setup
#define	OHCI_TD_DP_OUT		0x00080000	// HC -> device
#define	OHCI_TD_DP_IN		0x00000000	// Device -> HC
#define	OHCI_TD_R			0x00040000	// Rounding

/*
*	Completion codes
*/

#define	OHCI_CC_NO_ERROR				0	// No error
#define	OHCI_CC_CRC						1	// CRC error
#define	OHCI_CC_BIT_STUFFING			2	// Bit stuffing violation
#define	OHCI_CC_DATA_TOGGLE_MISMATCH	3	// Data toggle in PID didn't match
#define	OHCI_CC_STALL					4	// The endpoint returned a STALL PID
#define	OHCI_CC_DEVICE_NOT_RESPONDING	5	// Device did not respond
#define	OHCI_CC_PID_CHECK_FAILURE		6	// EP PID check failure
#define	OHCI_CC_UNEXPECTED_PID			7	// Undefined or invalild PID
#define	OHCI_CC_DATA_OVERRUN			8	// More data than space available
#define	OHCI_CC_DATA_UNDERRUN			9	// Less data that space available
#define	OHCI_CC_BUFFER_OVERRUN			12	// During an IN the HC lost data
#define	OHCI_CC_BUFFER_UNDERRUN			13	// During an OUT the HC starved
#define	OHCI_CC_NOT_ACCESSED			15	// Set by SW

/*
*	Isochronous transfer descriptor (in memory)
*/

struct ohci_itd {

	unsigned		Control;			// Control word
	unsigned		BP0;				// Buffer page 0
	struct ohci_itd	*NextTD;			// Next descriptor
	void			*BE;				// Buffer end
	union
	{
		unsigned short Offset[ 8 ];		// Transfer offset
		unsigned short PSW[ 8 ];		// Packet status word
	};

} OHCI_ITD;

/*
*	Endpoint descriptor (in memory)
*/

typedef struct ohci_ed {

	unsigned		Control;			// Control word
	struct ohct_td	*TailP;				// Tail of the transfer list
	struct ohct_td	*HeadP;				// Head of the transfer list
	struct ohci_ed	*NextED;			// Next endpoint descriptor

} OHCI_ED;

#define	OHCI_ED_H		1			// Halted (in HeadP!)
#define	OHCI_ED_C		2			// Carry toggle (in HeadP!)
#define	OHCI_ED_FA(x)	(x)			// USB function address
#define	OHCT_ED_EN(x)	((x)<<7)	// USB endpoint number
#define	OHCT_ED_D		0x1800		// Direction mask
#define	OHCT_ED_D_TD	0x0000		// Get direction from TD
#define	OHCT_ED_D_OUT	0x0800		// HC -> device
#define	OHCT_ED_D_IN	0x1000		// Device -> HC
#define	OHCT_ED_S		0x2000		// Speed (0:full 1:low)
#define	OHCT_ED_K		0x4000		// Skip this endpoint
#define	OHCT_ED_F		0x8000		// Format (1:isochronous 0:anything else)
#define	OHCT_ED_MPS(x)	((x)<<16)

/*
*	Host controller communications are descriptor (in memory)
*	It must be *at least* on a 256 byte boundary, but the device might
*	ask for more. Write -1 to the HCCA register and read it back. The
*	number of 0 bits on the bottom reflects the address alignment.
*/

typedef struct ohci_hcca {

	struct ohci_ed	*InterruptTable[32];	// Interrupt EDs
	unsigned short	FrameNumber;			// Current farme number
	unsigned short	Pad1;					// The HC writes 0 to this field
	struct ohci_ed	*DoneHead;				// The queue of finished EDs
	unsigned		_[29];					// Reserved for HC use

} OHCI_HCCA;

/*
*	OHCI-USB registers
*/

struct ohci_usb {

	unsigned 	Revision;				// Revision code
	unsigned 	Control;				// Operating mode
	unsigned 	CommandStatus;			// Command and status
	unsigned 	InterruptStatus;		// Interrupt status bits
	unsigned 	InterruptEnable;		// Interrupt enable
	unsigned 	InterruptDisable;		// Interrupt disable
	OHCI_HCCA	*HCCA;					// Host controller communication area
	OHCI_ED		*PeriodCurrentED;		// Current periodic or isochr. endpoint
	OHCI_ED		*ControlHeadED;			// First control endpoint
	OHCI_ED		*ControlCurrentED;		// Current control endpoint
	OHCI_ED		*BulkHeadED;			// First bulk endpoint
	OHCI_ED		*BulkCurrentED;			// Current bulk endpoint
	OHCI_ED		*DoneHead;				// Last endpoint added to the done list
	unsigned	FmInterval;				// Frame interval and max. packet size
	unsigned	FmRemaining;			// Number of bits remaining in frame
	unsigned	FmNumber;				// Frame number
	unsigned	PeriodicStart;			// Bit count for periodic list start
	unsigned	LSThreshold;			// Last transfer commit threshold
	unsigned	RhDescriptorA;			// Root hub control descriptor
	unsigned	RhDescriptorB;			// Root hub control descriptor
	unsigned	RhStatus;				// Root hub status
	unsigned	RhPortStatus[];			// Root hub port(s) status
};

/*
*	Control register
*/

#define	OHCI_CBSR		0x001
#define	OHCI_PLE		0x004			// Periodic list enable
#define	OHCI_IE			0x008			// Isochronous enable
#define	OHCI_CLE		0x010			// Control list enable
#define	OHCI_BLE		0x020			// Bulk list enable
#define	OHCI_HCFS		0x0c0
#define	OHCI_IR			0x100			// Interrupt routing
#define	OHCI_RWC		0x200			// Remote wakeup connected
#define	OHCI_RWE		0x400			// Remote wakeup enable

/*
*	CommandStatus register
*/

#define	OHCI_HCR		0x00001			// Host controller reset
#define	OHCI_CLF		0x00002			// Control list filled
#define	OHCI_BLF		0x00004			// Bulk list filled
#define	OHCI_OCR		0x00008			// Ownership change request
#define	OHCI_SOC_M		0x30000			// Scheduling overrun count
#define	OHCI_SOC_S		16

/*
*	InterruptStatus, InterruptDisable and InterruptEnable registers
*/

#define	OHCI_SO			0x00000001		// Scheduling overrun
#define	OHCI_WDH		0x00000002		// Writeback done head
#define	OHCI_SF			0x00000004		// Start of frame
#define	OHCI_RD			0x00000008		// Resume detected
#define	OHCI_UE			0x00000010		// Unrecoverable error
#define	OHCI_FNO		0x00000020		// Frame number overflow
#define	OHCI_RHSC		0x00000040		// Root hub status change
#define	OHCI_OC			0x40000000		// Ownership change
#define	OHCI_MIE		0x80000000		// Master interrupt enable

/*
*	FmInterval register
*/

#define	OHCI_FI_M		0x00003fff		// Frame interval mask
#define	OHCI_FI_S		0
#define	OHCI_FSMPS_M	0x7fff0000		// FS largest data packet
#define	OHCI_FSMPS_S	16
#define	OHCI_FIT		0x80000000		// Frame interval toggle

/*
*	FmRemaining register
*/

#define	OHCI_FR			0x00003fff		// Frame remaining mask
#define	OHCI_FRT		0x80000000		// Frame remaining toggle

/*
*	RhDescriptoA register
*/

#define	OHCI_NDP_M		0x000000ff		// Number downstream ports mask
#define	OHCI_NDP_S		0				// Number downstream ports shift
#define	OHCI_PSM		0x00000100		// Power switching mode
#define	OHCI_NPS		0x00000200		// No power switching
#define	OHCI_DT			0x00000400		// Device type
#define	OHCI_OCPM		0x00000800		// Over-current protection mode
#define	OHCI_NOCP		0x00001000		// No over-current protection
#define	OHCI_POTPGT_M	0xff000000		// Power on to power good time mask
#define	OHCI_POTPGT_S	24				// Power on to power good time shift

/*
*	RhDescriptorB register
*/

#define	OHCI_DR(x)		(1<<(x))		// Device removable
#define	OHCI_PPCM(x)	(1<<((x)+16))	// Port power control mask

/*
*	RhStatus register
*/

#define	OHCI_LPS		0x00000001		// Local power status
#define	OHCI_OCI		0x00000002		// Over-current indicator
#define	OHCI_DRWE		0x00008000		// Device remote wakeup enable
#define	OHCI_LPSC		0x00010000		// Local power status change
#define	OHCI_OCIC		0x00020000		// Over-current indicator change
#define	OHCI_CRWE		0x80000000		// Clear remote wakeup enable

/*
*	RhPortStatus register(s)
*/

#define	OHCI_CCS		0x000001		// Current connect ststus
#define	OHCI_PES		0x000002		// Port enable status
#define	OHCI_PSS		0x000004		// Port suspend status
#define	OHCI_POCI		0x000008		// Port over-current indicator
#define	OHCI_PRS		0x000010		// Port reset status
#define	OHCI_PPS		0x000100		// Port power status
#define	OHCI_LSDA		0x000200		// Low speed device attached
#define	OHCI_CSC		0x001000		// Connect status change
#define	OHCI_PESC		0x002000		// Port enable sttau change
#define	OHCI_PSSC		0x004000		// Port suspend status change
#define	OHCI_POCIC		0x008000		// Port over-current indicator change
#define	OHCI_PRSC		0x010000		// Port reset status change

#endif

