summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/pxa25x_udc.h
blob: f543b2d588e22321132f770458ae56f0ec407d5d (plain)
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
/*
 * Intel PXA25x on-chip full speed USB device controller
 *
 * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
 * Copyright (C) 2003 David Brownell
 * Copyright (C) 2012 Lukasz Dalek <luk0104@gmail.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef __LINUX_USB_GADGET_PXA25X_H
#define __LINUX_USB_GADGET_PXA25X_H

#include <linux/types.h>
#include <asm/arch/regs-usb.h>

/*
 * Prefetching support - only ARMv5.
 */

#ifdef ARCH_HAS_PREFETCH
static inline void prefetch(const void *ptr)
{
	__asm__ __volatile__(
		"pld\t%a0"
		:
		: "p" (ptr)
		: "cc");
}

#define prefetchw(ptr)	prefetch(ptr)
#endif /* ARCH_HAS_PREFETCH */

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

#define UDC_REGS	((struct pxa25x_udc_regs *)PXA25X_UDC_BASE)

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

struct pxa2xx_udc_mach_info {
	int  (*udc_is_connected)(void);		/* do we see host? */
	void (*udc_command)(int cmd);
#define	PXA2XX_UDC_CMD_CONNECT		0	/* let host see us */
#define	PXA2XX_UDC_CMD_DISCONNECT	1	/* so host won't see us */
};

struct pxa25x_udc;

struct pxa25x_ep {
	struct usb_ep				ep;
	struct pxa25x_udc			*dev;

	const struct usb_endpoint_descriptor	*desc;
	struct list_head			queue;
	unsigned long				pio_irqs;

	unsigned short				fifo_size;
	u8					bEndpointAddress;
	u8					bmAttributes;

	unsigned				stopped:1;

	/* UDCCS = UDC Control/Status for this EP
	 * UBCR = UDC Byte Count Remaining (contents of OUT fifo)
	 * UDDR = UDC Endpoint Data Register (the fifo)
	 * DRCM = DMA Request Channel Map
	 */
	u32					*reg_udccs;
	u32					*reg_ubcr;
	u32					*reg_uddr;
};

struct pxa25x_request {
	struct usb_request			req;
	struct list_head			queue;
};

enum ep0_state {
	EP0_IDLE,
	EP0_IN_DATA_PHASE,
	EP0_OUT_DATA_PHASE,
	EP0_END_XFER,
	EP0_STALL,
};

#define EP0_FIFO_SIZE	16U
#define BULK_FIFO_SIZE	64U
#define ISO_FIFO_SIZE	256U
#define INT_FIFO_SIZE	8U

struct udc_stats {
	struct ep0stats {
		unsigned long		ops;
		unsigned long		bytes;
	} read, write;
	unsigned long			irqs;
};

#ifdef CONFIG_USB_PXA25X_SMALL
/* when memory's tight, SMALL config saves code+data.  */
#define	PXA_UDC_NUM_ENDPOINTS	3
#endif

#ifndef	PXA_UDC_NUM_ENDPOINTS
#define	PXA_UDC_NUM_ENDPOINTS	16
#endif

struct pxa25x_watchdog {
	unsigned				running:1;
	ulong					period;
	ulong					base;
	struct pxa25x_udc			*udc;

	void (*function)(struct pxa25x_udc *udc);
};

struct pxa25x_udc {
	struct usb_gadget			gadget;
	struct usb_gadget_driver		*driver;
	struct pxa25x_udc_regs			*regs;

	enum ep0_state				ep0state;
	struct udc_stats			stats;
	unsigned				got_irq:1,
						pullup:1,
						has_cfr:1,
						req_pending:1,
						req_std:1,
						req_config:1,
						active:1;

	struct clk				*clk;
	struct pxa2xx_udc_mach_info		*mach;
	u64					dma_mask;
	struct pxa25x_ep			ep[PXA_UDC_NUM_ENDPOINTS];

	struct pxa25x_watchdog			watchdog;
};

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

static struct pxa25x_udc *the_controller;

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

#ifndef DEBUG
# define NOISY 0
#endif

#endif /* __LINUX_USB_GADGET_PXA25X_H */
OpenPOWER on IntegriCloud