langwell_udc.h 5.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
/*
 * Intel Langwell USB Device Controller driver
 * Copyright (C) 2008-2009, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 */

#include <linux/usb/langwell_udc.h>

/*-------------------------------------------------------------------------*/

/* driver data structures and utilities */

/*
 * dTD: Device Endpoint Transfer Descriptor
 * describe to the device controller the location and quantity of
 * data to be send/received for given transfer
 */
struct langwell_dtd {
	u32	dtd_next;
/* bits 31:5, next transfer element pointer */
#define	DTD_NEXT(d)	(((d)>>5)&0x7ffffff)
#define	DTD_NEXT_MASK	(0x7ffffff << 5)
/* terminate */
#define	DTD_TERM	BIT(0)
	/* bits 7:0, execution back states */
	u32	dtd_status:8;
#define	DTD_STATUS(d)	(((d)>>0)&0xff)
#define	DTD_STS_ACTIVE	BIT(7)	/* active */
#define	DTD_STS_HALTED	BIT(6)	/* halted */
#define	DTD_STS_DBE	BIT(5)	/* data buffer error */
#define	DTD_STS_TRE	BIT(3)	/* transaction error  */
	/* bits 9:8 */
	u32	dtd_res0:2;
	/* bits 11:10, multipier override */
	u32	dtd_multo:2;
#define	DTD_MULTO	(BIT(11) | BIT(10))
	/* bits 14:12 */
	u32	dtd_res1:3;
	/* bit 15, interrupt on complete */
	u32	dtd_ioc:1;
#define	DTD_IOC		BIT(15)
	/* bits 30:16, total bytes */
	u32	dtd_total:15;
#define	DTD_TOTAL(d)	(((d)>>16)&0x7fff)
#define	DTD_MAX_TRANSFER_LENGTH	0x4000
	/* bit 31 */
	u32	dtd_res2:1;
	/* dTD buffer pointer page 0 to 4 */
	u32	dtd_buf[5];
#define	DTD_OFFSET_MASK	0xfff
/* bits 31:12, buffer pointer */
#define	DTD_BUFFER(d)	(((d)>>12)&0x3ff)
/* bits 11:0, current offset */
#define	DTD_C_OFFSET(d)	(((d)>>0)&0xfff)
/* bits 10:0, frame number */
#define	DTD_FRAME(d)	(((d)>>0)&0x7ff)

	/* driver-private parts */

	/* dtd dma address */
	dma_addr_t		dtd_dma;
	/* next dtd virtual address */
	struct langwell_dtd	*next_dtd_virt;
};


/*
 * dQH: Device Endpoint Queue Head
 * describe where all transfers are managed
 * 48-byte data structure, aligned on 64-byte boundary
 *
 * These are associated with dTD structure
 */
struct langwell_dqh {
	/* endpoint capabilities and characteristics */
	u32	dqh_res0:15;	/* bits 14:0 */
	u32	dqh_ios:1;	/* bit 15, interrupt on setup */
#define	DQH_IOS		BIT(15)
	u32	dqh_mpl:11;	/* bits 26:16, maximum packet length */
#define	DQH_MPL		(0x7ff << 16)
	u32	dqh_res1:2;	/* bits 28:27 */
	u32	dqh_zlt:1;	/* bit 29, zero length termination */
#define	DQH_ZLT		BIT(29)
	u32	dqh_mult:2;	/* bits 31:30 */
#define	DQH_MULT	(BIT(30) | BIT(31))

	/* current dTD pointer */
	u32	dqh_current;	/* locate the transfer in progress */
#define DQH_C_DTD(e)	\
	(((e)>>5)&0x7ffffff)	/* bits 31:5, current dTD pointer */

	/* transfer overlay, hardware parts of a struct langwell_dtd */
	u32	dtd_next;
	u32	dtd_status:8;	/* bits 7:0, execution back states */
	u32	dtd_res0:2;	/* bits 9:8 */
	u32	dtd_multo:2;	/* bits 11:10, multipier override */
	u32	dtd_res1:3;	/* bits 14:12 */
	u32	dtd_ioc:1;	/* bit 15, interrupt on complete */
	u32	dtd_total:15;	/* bits 30:16, total bytes */
	u32	dtd_res2:1;	/* bit 31 */
	u32	dtd_buf[5];	/* dTD buffer pointer page 0 to 4 */

	u32	dqh_res2;
	struct usb_ctrlrequest	dqh_setup;	/* setup packet buffer */
} __attribute__ ((aligned(64)));


/* endpoint data structure */
struct langwell_ep {
	struct usb_ep		ep;
	dma_addr_t		dma;
	struct langwell_udc	*dev;
	unsigned long		irqs;
	struct list_head	queue;
	struct langwell_dqh	*dqh;
	char			name[14];
	unsigned		stopped:1,
				ep_type:2,
				ep_num:8;
};


/* request data structure */
struct langwell_request {
	struct usb_request	req;
	struct langwell_dtd	*dtd, *head, *tail;
	struct langwell_ep	*ep;
	dma_addr_t		dtd_dma;
	struct list_head	queue;
	unsigned		dtd_count;
	unsigned		mapped:1;
};


/* ep0 transfer state */
enum ep0_state {
	WAIT_FOR_SETUP,
	DATA_STATE_XMIT,
	DATA_STATE_NEED_ZLP,
	WAIT_FOR_OUT_STATUS,
	DATA_STATE_RECV,
};


/* device suspend state */
enum lpm_state {
	LPM_L0,	/* on */
	LPM_L1,	/* LPM L1 sleep */
	LPM_L2,	/* suspend */
	LPM_L3,	/* off */
};


/* device data structure */
struct langwell_udc {
	/* each pci device provides one gadget, several endpoints */
	struct usb_gadget	gadget;
	spinlock_t		lock;	/* device lock */
	struct langwell_ep	*ep;
	struct usb_gadget_driver	*driver;
164
	struct usb_phy		*transceiver;
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
	u8			dev_addr;
	u32			usb_state;
	u32			resume_state;
	u32			bus_reset;
	enum lpm_state		lpm_state;
	enum ep0_state		ep0_state;
	u32			ep0_dir;
	u16			dciversion;
	unsigned		ep_max;
	unsigned		devcap:1,
				enabled:1,
				region:1,
				got_irq:1,
				powered:1,
				remote_wakeup:1,
				rate:1,
				is_reset:1,
				softconnected:1,
				vbus_active:1,
				suspended:1,
				stopped:1,
186 187 188
				lpm:1,		/* LPM capability */
				has_sram:1,	/* SRAM caching */
				got_sram:1;
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

	/* pci state used to access those endpoints */
	struct pci_dev		*pdev;

	/* Langwell otg transceiver */
	struct langwell_otg	*lotg;

	/* control registers */
	struct langwell_cap_regs	__iomem	*cap_regs;
	struct langwell_op_regs		__iomem	*op_regs;

	struct usb_ctrlrequest	local_setup_buff;
	struct langwell_dqh	*ep_dqh;
	size_t			ep_dqh_size;
	dma_addr_t		ep_dqh_dma;

	/* ep0 status request */
	struct langwell_request	*status_req;

	/* dma pool */
	struct dma_pool		*dtd_pool;

	/* make sure release() is done */
	struct completion	*done;
213

214 215 216 217
	/* for private SRAM caching */
	unsigned int		sram_addr;
	unsigned int		sram_size;

218 219
	/* device status data for get_status request */
	u16			dev_status;
220 221
};

222 223
#define gadget_to_langwell(g)	container_of((g), struct langwell_udc, gadget)