1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
42 * "cvmx-usb.h" defines a set of low level USB functions to help
43 * developers create Octeon USB drivers for various operating
44 * systems. These functions provide a generic API to the Octeon
45 * USB blocks, hiding the internal hardware specific
48 * At a high level the device driver needs to:
50 * - Call cvmx_usb_get_num_ports() to get the number of
52 * - Call cvmx_usb_initialize() for each Octeon USB port.
53 * - Enable the port using cvmx_usb_enable().
54 * - Either periodically, or in an interrupt handler, call
55 * cvmx_usb_poll() to service USB events.
56 * - Manage pipes using cvmx_usb_open_pipe() and
57 * cvmx_usb_close_pipe().
58 * - Manage transfers using cvmx_usb_submit_*() and
60 * - Shutdown USB on unload using cvmx_usb_shutdown().
62 * To monitor USB status changes, the device driver must use
63 * cvmx_usb_register_callback() to register for events that it
64 * is interested in. Below are a few hints on successfully
65 * implementing a driver on top of this API.
67 * == Initialization ==
69 * When a driver is first loaded, it is normally not necessary
70 * to bring up the USB port completely. Most operating systems
71 * expect to initialize and enable the port in two independent
72 * steps. Normally an operating system will probe hardware,
73 * initialize anything found, and then enable the hardware.
75 * In the probe phase you should:
76 * - Use cvmx_usb_get_num_ports() to determine the number of
77 * USB port to be supported.
78 * - Allocate space for a cvmx_usb_state_t structure for each
80 * - Tell the operating system about each port
82 * In the initialization phase you should:
83 * - Use cvmx_usb_initialize() on each port.
84 * - Do not call cvmx_usb_enable(). This leaves the USB port in
85 * the disabled state until the operating system is ready.
87 * Finally, in the enable phase you should:
88 * - Call cvmx_usb_enable() on the appropriate port.
89 * - Note that some operating system use a RESET instead of an
90 * enable call. To implement RESET, you should call
91 * cvmx_usb_disable() followed by cvmx_usb_enable().
95 * All of the functions in the cvmx-usb API assume exclusive
96 * access to the USB hardware and internal data structures. This
97 * means that the driver must provide locking as necessary.
99 * In the single CPU state it is normally enough to disable
100 * interrupts before every call to cvmx_usb*() and enable them
101 * again after the call is complete. Keep in mind that it is
102 * very common for the callback handlers to make additional
103 * calls into cvmx-usb, so the disable/enable must be protected
104 * against recursion. As an example, the Linux kernel
105 * local_irq_save() and local_irq_restore() are perfect for this
106 * in the non SMP case.
108 * In the SMP case, locking is more complicated. For SMP you not
109 * only need to disable interrupts on the local core, but also
110 * take a lock to make sure that another core cannot call
113 * == Port callback ==
115 * The port callback prototype needs to look as follows:
117 * void port_callback(cvmx_usb_state_t *usb,
118 * cvmx_usb_callback_t reason,
119 * cvmx_usb_complete_t status,
122 * int bytes_transferred,
124 * - "usb" is the cvmx_usb_state_t for the port.
125 * - "reason" will always be CVMX_USB_CALLBACK_PORT_CHANGED.
126 * - "status" will always be CVMX_USB_COMPLETE_SUCCESS.
127 * - "pipe_handle" will always be -1.
128 * - "submit_handle" will always be -1.
129 * - "bytes_transferred" will always be 0.
130 * - "user_data" is the void pointer originally passed along
131 * with the callback. Use this for any state information you
134 * The port callback will be called whenever the user plugs /
135 * unplugs a device from the port. It will not be called when a
136 * device is plugged / unplugged from a hub connected to the
137 * root port. Normally all the callback needs to do is tell the
138 * operating system to poll the root hub for status. Under
139 * Linux, this is performed by calling usb_hcd_poll_rh_status().
140 * In the Linux driver we use "user_data". to pass around the
141 * Linux "hcd" structure. Once the port callback completes,
142 * Linux automatically calls octeon_usb_hub_status_data() which
143 * uses cvmx_usb_get_status() to determine the root port status.
145 * == Complete callback ==
147 * The completion callback prototype needs to look as follows:
149 * void complete_callback(cvmx_usb_state_t *usb,
150 * cvmx_usb_callback_t reason,
151 * cvmx_usb_complete_t status,
154 * int bytes_transferred,
156 * - "usb" is the cvmx_usb_state_t for the port.
157 * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE.
158 * - "status" will be one of the cvmx_usb_complete_t enumerations.
159 * - "pipe_handle" is the handle to the pipe the transaction
160 * was originally submitted on.
161 * - "submit_handle" is the handle returned by the original
162 * cvmx_usb_submit_* call.
163 * - "bytes_transferred" is the number of bytes successfully
164 * transferred in the transaction. This will be zero on most
166 * - "user_data" is the void pointer originally passed along
167 * with the callback. Use this for any state information you
168 * need. For example, the Linux "urb" is stored in here in the
171 * In general your callback handler should use "status" and
172 * "bytes_transferred" to tell the operating system the how the
173 * transaction completed. Normally the pipe is not changed in
176 * == Canceling transactions ==
178 * When a transaction is cancelled using cvmx_usb_cancel*(), the
179 * actual length of time until the complete callback is called
180 * can vary greatly. It may be called before cvmx_usb_cancel*()
181 * returns, or it may be called a number of usb frames in the
182 * future once the hardware frees the transaction. In either of
183 * these cases, the complete handler will receive
184 * CVMX_USB_COMPLETE_CANCEL.
186 * == Handling pipes ==
188 * USB "pipes" is a software construct created by this API to
189 * enable the ordering of usb transactions to a device endpoint.
190 * Octeon's underlying hardware doesn't have any concept
191 * equivalent to "pipes". The hardware instead has eight
192 * channels that can be used simultaneously to have up to eight
193 * transaction in process at the same time. In order to maintain
194 * ordering in a pipe, the transactions for a pipe will only be
195 * active in one hardware channel at a time. From an API user's
196 * perspective, this doesn't matter but it can be helpful to
197 * keep this in mind when you are probing hardware while
200 * Also keep in mind that usb transactions contain state
201 * information about the previous transaction to the same
202 * endpoint. Each transaction has a PID toggle that changes 0/1
203 * between each sub packet. This is maintained in the pipe data
204 * structures. For this reason, you generally cannot create and
205 * destroy a pipe for every transaction. A sequence of
206 * transaction to the same endpoint must use the same pipe.
210 * Some operating systems view the usb root port as a normal usb
211 * hub. These systems attempt to control the root hub with
212 * messages similar to the usb 2.0 spec for hub control and
213 * status. For these systems it may be necessary to write
214 * function to decode standard usb control messages into
215 * equivalent cvmx-usb API calls.
219 * If you plan on using usb interrupts, cvmx_usb_poll() must be
220 * called on every usb interrupt. It will read the usb state,
221 * call any needed callbacks, and schedule transactions as
222 * needed. Your device driver needs only to hookup an interrupt
223 * handler and call cvmx_usb_poll(). Octeon's usb port 0 causes
224 * CIU bit CIU_INT*_SUM0[USB] to be set (bit 56). For port 1,
225 * CIU bit CIU_INT_SUM1[USB1] is set (bit 17). How these bits
226 * are turned into interrupt numbers is operating system
227 * specific. For Linux, there are the convenient defines
228 * OCTEON_IRQ_USB0 and OCTEON_IRQ_USB1 for the IRQ numbers.
230 * If you aren't using interrupts, simple call cvmx_usb_poll()
231 * in your main processing loop.
234 #ifndef __CVMX_USB_H__
235 #define __CVMX_USB_H__
238 * Enumerations representing the possible USB device speeds
242 CVMX_USB_SPEED_HIGH = 0, /**< Device is operation at 480Mbps */
243 CVMX_USB_SPEED_FULL = 1, /**< Device is operation at 12Mbps */
244 CVMX_USB_SPEED_LOW = 2, /**< Device is operation at 1.5Mbps */
248 * Enumeration representing the possible USB transfer types.
252 CVMX_USB_TRANSFER_CONTROL = 0, /**< USB transfer type control for hub and status transfers */
253 CVMX_USB_TRANSFER_ISOCHRONOUS = 1, /**< USB transfer type isochronous for low priority periodic transfers */
254 CVMX_USB_TRANSFER_BULK = 2, /**< USB transfer type bulk for large low priority transfers */
255 CVMX_USB_TRANSFER_INTERRUPT = 3, /**< USB transfer type interrupt for high priority periodic transfers */
256 } cvmx_usb_transfer_t;
259 * Enumeration of the transfer directions
263 CVMX_USB_DIRECTION_OUT, /**< Data is transferring from Octeon to the device/host */
264 CVMX_USB_DIRECTION_IN, /**< Data is transferring from the device/host to Octeon */
265 } cvmx_usb_direction_t;
268 * Enumeration of all possible status codes passed to callback
273 CVMX_USB_COMPLETE_SUCCESS, /**< The transaction / operation finished without any errors */
274 CVMX_USB_COMPLETE_SHORT, /**< FIXME: This is currently not implemented */
275 CVMX_USB_COMPLETE_CANCEL, /**< The transaction was canceled while in flight by a user call to cvmx_usb_cancel* */
276 CVMX_USB_COMPLETE_ERROR, /**< The transaction aborted with an unexpected error status */
277 CVMX_USB_COMPLETE_STALL, /**< The transaction received a USB STALL response from the device */
278 CVMX_USB_COMPLETE_XACTERR, /**< The transaction failed with an error from the device even after a number of retries */
279 CVMX_USB_COMPLETE_DATATGLERR, /**< The transaction failed with a data toggle error even after a number of retries */
280 CVMX_USB_COMPLETE_BABBLEERR, /**< The transaction failed with a babble error */
281 CVMX_USB_COMPLETE_FRAMEERR, /**< The transaction failed with a frame error even after a number of retries */
282 } cvmx_usb_complete_t;
285 * Structure returned containing the USB port status information.
289 uint32_t reserved : 25;
290 uint32_t port_enabled : 1; /**< 1 = Usb port is enabled, 0 = disabled */
291 uint32_t port_over_current : 1; /**< 1 = Over current detected, 0 = Over current not detected. Octeon doesn't support over current detection */
292 uint32_t port_powered : 1; /**< 1 = Port power is being supplied to the device, 0 = power is off. Octeon doesn't support turning port power off */
293 cvmx_usb_speed_t port_speed : 2; /**< Current port speed */
294 uint32_t connected : 1; /**< 1 = A device is connected to the port, 0 = No device is connected */
295 uint32_t connect_change : 1; /**< 1 = Device connected state changed since the last set status call */
296 } cvmx_usb_port_status_t;
299 * This is the structure of a Control packet header
306 uint64_t request_type : 8; /**< Bit 7 tells the direction: 1=IN, 0=OUT */
307 uint64_t request : 8; /**< The standard usb request to make */
308 uint64_t value : 16; /**< Value parameter for the request in little endian format */
309 uint64_t index : 16; /**< Index for the request in little endian format */
310 uint64_t length : 16; /**< Length of the data associated with this request in little endian format */
312 } cvmx_usb_control_header_t;
315 * Descriptor for Isochronous packets
319 int offset; /**< This is the offset in bytes into the main buffer where this data is stored */
320 int length; /**< This is the length in bytes of the data */
321 cvmx_usb_complete_t status; /**< This is the status of this individual packet transfer */
322 } cvmx_usb_iso_packet_t;
325 * Possible callback reasons for the USB API.
329 CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
330 /**< A callback of this type is called when a submitted transfer
331 completes. The completion callback will be called even if the
332 transfer fails or is canceled. The status parameter will
333 contain details of why he callback was called. */
334 CVMX_USB_CALLBACK_PORT_CHANGED, /**< The status of the port changed. For example, someone may have
335 plugged a device in. The status parameter contains
336 CVMX_USB_COMPLETE_SUCCESS. Use cvmx_usb_get_status() to get
337 the new port status. */
338 __CVMX_USB_CALLBACK_END /**< Do not use. Used internally for array bounds */
339 } cvmx_usb_callback_t;
342 * USB state internal data. The contents of this structure
343 * may change in future SDKs. No data in it should be referenced
344 * by user's of this API.
352 * USB callback functions are always of the following type.
353 * The parameters are as follows:
354 * - state = USB device state populated by
355 * cvmx_usb_initialize().
356 * - reason = The cvmx_usb_callback_t used to register
358 * - status = The cvmx_usb_complete_t representing the
359 * status code of a transaction.
360 * - pipe_handle = The Pipe that caused this callback, or
361 * -1 if this callback wasn't associated with a pipe.
362 * - submit_handle = Transfer submit handle causing this
363 * callback, or -1 if this callback wasn't associated
365 * - Actual number of bytes transfer.
366 * - user_data = The user pointer supplied to the
367 * function cvmx_usb_submit() or
368 * cvmx_usb_register_callback() */
369 typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state,
370 cvmx_usb_callback_t reason,
371 cvmx_usb_complete_t status,
372 int pipe_handle, int submit_handle,
373 int bytes_transferred, void *user_data);
376 * Flags to pass the initialization function.
380 CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1<<0, /**< The USB port uses a 12MHz crystal as clock source
381 at USB_XO and USB_XI. */
382 CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1<<1, /**< The USB port uses 12/24/48MHz 2.5V board clock
383 source at USB_XO. USB_XI should be tied to GND.*/
384 CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0, /**< Automatically determine clock type based on function
385 in cvmx-helper-board.c. */
386 CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3<<3, /**< Mask for clock speed field */
387 CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1<<3, /**< Speed of reference clock or crystal */
388 CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2<<3, /**< Speed of reference clock */
389 CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3<<3, /**< Speed of reference clock */
390 /* Bits 3-4 used to encode the clock frequency */
391 CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1<<5, /**< Disable DMA and used polled IO for data transfer use for the USB */
392 } cvmx_usb_initialize_flags_t;
395 * Flags for passing when a pipe is created. Currently no flags
400 __CVMX_USB_PIPE_FLAGS_OPEN = 1<<16, /**< Used internally to determine if a pipe is open. Do not use */
401 __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1<<17, /**< Used internally to determine if a pipe is actively using hardware. Do not use */
402 __CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18, /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */
403 } cvmx_usb_pipe_flags_t;
405 extern int cvmx_usb_get_num_ports(void);
406 extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number,
407 cvmx_usb_initialize_flags_t flags);
408 extern int cvmx_usb_shutdown(cvmx_usb_state_t *state);
409 extern int cvmx_usb_enable(cvmx_usb_state_t *state);
410 extern int cvmx_usb_disable(cvmx_usb_state_t *state);
411 extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state);
412 extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status);
413 extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state,
414 cvmx_usb_pipe_flags_t flags,
415 int device_addr, int endpoint_num,
416 cvmx_usb_speed_t device_speed, int max_packet,
417 cvmx_usb_transfer_t transfer_type,
418 cvmx_usb_direction_t transfer_dir, int interval,
419 int multi_count, int hub_device_addr,
421 extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle,
422 uint64_t buffer, int buffer_length,
423 cvmx_usb_callback_func_t callback,
425 extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle,
426 uint64_t buffer, int buffer_length,
427 cvmx_usb_callback_func_t callback,
429 extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle,
430 uint64_t control_header,
431 uint64_t buffer, int buffer_length,
432 cvmx_usb_callback_func_t callback,
436 * Flags to pass the cvmx_usb_submit_isochronous() function.
440 CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1<<0, /**< Do not return an error if a transfer is less than the maximum packet size of the device */
441 CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1<<1, /**< Schedule the transaction as soon as possible */
442 } cvmx_usb_isochronous_flags_t;
444 extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle,
445 int start_frame, int flags,
447 cvmx_usb_iso_packet_t packets[],
448 uint64_t buffer, int buffer_length,
449 cvmx_usb_callback_func_t callback,
451 extern int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle,
453 extern int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle);
454 extern int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle);
455 extern int cvmx_usb_register_callback(cvmx_usb_state_t *state,
456 cvmx_usb_callback_t reason,
457 cvmx_usb_callback_func_t callback,
459 extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state);
460 extern int cvmx_usb_poll(cvmx_usb_state_t *state);
462 #endif /* __CVMX_USB_H__ */