Blame view

drivers/usb/musb-new/musb_uboot.c 5.2 KB
eb81955bf   Ilya Yanok   musb-new: port of...
1
  #include <common.h>
7a3427854   Heiko Schocher   usb, musb-new: ad...
2
  #include <watchdog.h>
eb81955bf   Ilya Yanok   musb-new: port of...
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
  #include <asm/errno.h>
  #include <linux/usb/ch9.h>
  #include <linux/usb/gadget.h>
  
  #define __UBOOT__
  #include <usb.h>
  #include "linux-compat.h"
  #include "usb-compat.h"
  #include "musb_core.h"
  #include "musb_host.h"
  #include "musb_gadget.h"
  
  #ifdef CONFIG_MUSB_HOST
  static struct musb *host;
  static struct usb_hcd hcd;
  static enum usb_device_speed host_speed;
  
  static void musb_host_complete_urb(struct urb *urb)
  {
  	urb->dev->status &= ~USB_ST_NOT_PROC;
  	urb->dev->act_len = urb->actual_length;
  }
  
  static struct usb_host_endpoint hep;
  static struct urb urb;
  
  static struct urb *construct_urb(struct usb_device *dev, int endpoint_type,
  				unsigned long pipe, void *buffer, int len,
  				struct devrequest *setup, int interval)
  {
  	int epnum = usb_pipeendpoint(pipe);
  	int is_in = usb_pipein(pipe);
  
  	memset(&urb, 0, sizeof(struct urb));
  	memset(&hep, 0, sizeof(struct usb_host_endpoint));
  	INIT_LIST_HEAD(&hep.urb_list);
  	INIT_LIST_HEAD(&urb.urb_list);
  	urb.ep = &hep;
  	urb.complete = musb_host_complete_urb;
  	urb.status = -EINPROGRESS;
  	urb.dev = dev;
  	urb.pipe = pipe;
  	urb.transfer_buffer = buffer;
  	urb.transfer_dma = (unsigned long)buffer;
  	urb.transfer_buffer_length = len;
  	urb.setup_packet = (unsigned char *)setup;
  
  	urb.ep->desc.wMaxPacketSize =
  		__cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
  				dev->epmaxpacketout[epnum]);
  	urb.ep->desc.bmAttributes = endpoint_type;
  	urb.ep->desc.bEndpointAddress =
  		(is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
  	urb.ep->desc.bInterval = interval;
  
  	return &urb;
  }
  
  #define MUSB_HOST_TIMEOUT	0x3ffffff
  
  static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
  {
  	struct musb *host = hcd->hcd_priv;
  	int ret;
  	int timeout;
  
  	ret = musb_urb_enqueue(hcd, urb, 0);
  	if (ret < 0) {
  		printf("Failed to enqueue URB to controller
  ");
  		return ret;
  	}
  
  	timeout = MUSB_HOST_TIMEOUT;
  	do {
  		if (ctrlc())
  			return -EIO;
  		host->isr(0, host);
  	} while ((urb->dev->status & USB_ST_NOT_PROC) && --timeout);
  
  	return urb->status;
  }
  
  int submit_control_msg(struct usb_device *dev, unsigned long pipe,
  			void *buffer, int len, struct devrequest *setup)
  {
  	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe,
  					buffer, len, setup, 0);
  
  	/* Fix speed for non hub-attached devices */
  	if (!dev->parent)
  		dev->speed = host_speed;
  
  	return submit_urb(&hcd, urb);
  }
  
  
  int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
  					void *buffer, int len)
  {
  	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe,
  					buffer, len, NULL, 0);
  	return submit_urb(&hcd, urb);
  }
  
  int submit_int_msg(struct usb_device *dev, unsigned long pipe,
  				void *buffer, int len, int interval)
  {
  	struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe,
  					buffer, len, NULL, interval);
  	return submit_urb(&hcd, urb);
  }
06d513ecb   Troy Kisky   usb: add enum usb...
115
  int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
eb81955bf   Ilya Yanok   musb-new: port of...
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
164
165
166
167
168
169
  {
  	u8 power;
  	void *mbase;
  	int timeout = MUSB_HOST_TIMEOUT;
  
  	if (!host) {
  		printf("MUSB host is not registered
  ");
  		return -ENODEV;
  	}
  
  	musb_start(host);
  	mbase = host->mregs;
  	do {
  		if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
  			break;
  	} while (--timeout);
  	if (!timeout)
  		return -ENODEV;
  
  	power = musb_readb(mbase, MUSB_POWER);
  	musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
  	udelay(30000);
  	power = musb_readb(mbase, MUSB_POWER);
  	musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
  	host->isr(0, host);
  	host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
  			USB_SPEED_HIGH :
  			(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
  			USB_SPEED_FULL : USB_SPEED_LOW;
  	host->is_active = 1;
  	hcd.hcd_priv = host;
  
  	return 0;
  }
  
  int usb_lowlevel_stop(int index)
  {
  	if (!host) {
  		printf("MUSB host is not registered
  ");
  		return -ENODEV;
  	}
  
  	musb_stop(host);
  	return 0;
  }
  #endif /* CONFIG_MUSB_HOST */
  
  #ifdef CONFIG_MUSB_GADGET
  static struct musb *gadget;
  
  int usb_gadget_handle_interrupts(void)
  {
7a3427854   Heiko Schocher   usb, musb-new: ad...
170
  	WATCHDOG_RESET();
eb81955bf   Ilya Yanok   musb-new: port of...
171
172
173
174
175
176
177
178
179
  	if (!gadget || !gadget->isr)
  		return -EINVAL;
  
  	return gadget->isr(0, gadget);
  }
  
  int usb_gadget_register_driver(struct usb_gadget_driver *driver)
  {
  	int ret;
76b09b856   Bin Liu   musb: set MUSB sp...
180
  	if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind ||
eb81955bf   Ilya Yanok   musb-new: port of...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  	    !driver->setup) {
  		printf("bad parameter.
  ");
  		return -EINVAL;
  	}
  
  	if (!gadget) {
  		printf("Controller uninitialized
  ");
  		return -ENXIO;
  	}
  
  	ret = musb_gadget_start(&gadget->g, driver);
  	if (ret < 0) {
  		printf("gadget_start failed with %d
  ", ret);
  		return ret;
  	}
  
  	ret = driver->bind(&gadget->g);
  	if (ret < 0) {
  		printf("bind failed with %d
  ", ret);
  		return ret;
  	}
  
  	return 0;
  }
  
  int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
  {
078d7302a   Rob Herring   usb: musb: fill i...
212
213
214
215
  	if (driver->disconnect)
  		driver->disconnect(&gadget->g);
  	if (driver->unbind)
  		driver->unbind(&gadget->g);
eb81955bf   Ilya Yanok   musb-new: port of...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  	return 0;
  }
  #endif /* CONFIG_MUSB_GADGET */
  
  int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
  			void *ctl_regs)
  {
  	struct musb **musbp;
  
  	switch (plat->mode) {
  #ifdef CONFIG_MUSB_HOST
  	case MUSB_HOST:
  		musbp = &host;
  		break;
  #endif
  #ifdef CONFIG_MUSB_GADGET
  	case MUSB_PERIPHERAL:
  		musbp = &gadget;
  		break;
  #endif
  	default:
  		return -EINVAL;
  	}
  
  	*musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs);
  	if (!musbp) {
  		printf("Failed to init the controller
  ");
  		return -EIO;
  	}
  
  	return 0;
  }