Re: [PATCH 2/2] staging: octeon-usb: delete the octeon usb host controller driver

Chris Packham
2020-02-04T04:06:58Z

On Tue, 2019-12-10 at 10:15 +0100, Greg Kroah-Hartman wrote:
> This driver was merged back in 2013 and shows no progress toward every
> being merged into the "correct" part of the kernel. The code doesn't
> even build for anyone unless you have the specific hardware platform
> selected, so odds are it doesn't even work anymore.
>
> Remove it for now and is someone comes along that has the hardware and
> is willing to fix it up, it can be reverted.
>
> Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
> Cc: David Daney <ddaney.cavm@gmail.com>
> Cc: Nishka Dasgupta <nishkadg.linux@gmail.com>
> Cc: Himadri Pandya <himadri18.07@gmail.com>
> Cc: "Frank A. Cancio Bello" <frank@generalsoftwareinc.com>
> Cc: Sumit Pundir <pundirsumit11@gmail.com>
> Cc: Laura Lazzati <laura.lazzati.15@gmail.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---

Similarly we'd really like to keep this too.

> drivers/staging/Kconfig | 2 -
> drivers/staging/Makefile | 1 -
> drivers/staging/octeon-usb/Kconfig | 11 -
> drivers/staging/octeon-usb/Makefile | 2 -
> drivers/staging/octeon-usb/TODO | 8 -
> drivers/staging/octeon-usb/octeon-hcd.c | 3737 -----------------------
> drivers/staging/octeon-usb/octeon-hcd.h | 1847 -----------
> 7 files changed, 5608 deletions(-)
> delete mode 100644 drivers/staging/octeon-usb/Kconfig
> delete mode 100644 drivers/staging/octeon-usb/Makefile
> delete mode 100644 drivers/staging/octeon-usb/TODO
> delete mode 100644 drivers/staging/octeon-usb/octeon-hcd.c
> delete mode 100644 drivers/staging/octeon-usb/octeon-hcd.h
>
> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
> index 15d3549e7cc7..198bf59bc1e6 100644
> --- a/drivers/staging/Kconfig
> +++ b/drivers/staging/Kconfig
> @@ -42,8 +42,6 @@ source "drivers/staging/rtl8188eu/Kconfig"
>
> source "drivers/staging/rts5208/Kconfig"
>
> -source "drivers/staging/octeon-usb/Kconfig"
> -
> source "drivers/staging/vt6655/Kconfig"
>
> source "drivers/staging/vt6656/Kconfig"
> diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
> index c521204220b5..bf230a830338 100644
> --- a/drivers/staging/Makefile
> +++ b/drivers/staging/Makefile
> @@ -12,7 +12,6 @@ obj-$(CONFIG_R8712U) += rtl8712/
> obj-$(CONFIG_R8188EU) += rtl8188eu/
> obj-$(CONFIG_RTS5208) += rts5208/
> obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/
> -obj-$(CONFIG_OCTEON_USB) += octeon-usb/
> obj-$(CONFIG_VT6655) += vt6655/
> obj-$(CONFIG_VT6656) += vt6656/
> obj-$(CONFIG_VME_BUS) += vme/
> diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig
> deleted file mode 100644
> index 6a5d842ee0f2..000000000000
> --- a/drivers/staging/octeon-usb/Kconfig
> +++ /dev/null
> @@ -1,11 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -config OCTEON_USB
> - tristate "Cavium Networks Octeon USB support"
> - depends on CAVIUM_OCTEON_SOC && USB
> - help
> - This driver supports USB host controller on some Cavium
> - Networks' products in the Octeon family.
> -
> - To compile this driver as a module, choose M here. The module
> - will be called octeon-hcd.
> -
> diff --git a/drivers/staging/octeon-usb/Makefile b/drivers/staging/octeon-usb/Makefile
> deleted file mode 100644
> index 9873a0130ad5..000000000000
> --- a/drivers/staging/octeon-usb/Makefile
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0
> -obj-${CONFIG_OCTEON_USB} := octeon-hcd.o
> diff --git a/drivers/staging/octeon-usb/TODO b/drivers/staging/octeon-usb/TODO
> deleted file mode 100644
> index 2b29acca5caa..000000000000
> --- a/drivers/staging/octeon-usb/TODO
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -This driver is functional and has been tested on EdgeRouter Lite,
> -D-Link DSR-1000N and EBH5600 evaluation board with USB mass storage.
> -
> -TODO:
> - - kernel coding style
> - - checkpatch warnings
> -
> -Contact: Aaro Koskinen <aaro.koskinen@iki.fi>
> diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
> deleted file mode 100644
> index 582c9187559d..000000000000
> --- a/drivers/staging/octeon-usb/octeon-hcd.c
> +++ /dev/null
> @@ -1,3737 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * This file is subject to the terms and conditions of the GNU General Public
> - * License. See the file "COPYING" in the main directory of this archive
> - * for more details.
> - *
> - * Copyright (C) 2008 Cavium Networks
> - *
> - * Some parts of the code were originally released under BSD license:
> - *
> - * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
> - * reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions are
> - * met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - *
> - * * Redistributions in binary form must reproduce the above
> - * copyright notice, this list of conditions and the following
> - * disclaimer in the documentation and/or other materials provided
> - * with the distribution.
> - *
> - * * Neither the name of Cavium Networks nor the names of
> - * its contributors may be used to endorse or promote products
> - * derived from this software without specific prior written
> - * permission.
> - *
> - * This Software, including technical data, may be subject to U.S. export
> - * control laws, including the U.S. Export Administration Act and its associated
> - * regulations, and may be subject to export or import regulations in other
> - * countries.
> - *
> - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
> - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
> - * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
> - * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
> - * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
> - * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
> - * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
> - * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
> - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
> - * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
> - */
> -
> -#include <linux/usb.h>
> -#include <linux/slab.h>
> -#include <linux/module.h>
> -#include <linux/usb/hcd.h>
> -#include <linux/prefetch.h>
> -#include <linux/dma-mapping.h>
> -#include <linux/platform_device.h>
> -
> -#include <asm/octeon/octeon.h>
> -
> -#include "octeon-hcd.h"
> -
> -/**
> - * enum cvmx_usb_speed - the possible USB device speeds
> - *
> - * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps
> - * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps
> - * @CVMX_USB_SPEED_LOW: Device is operation at 1.5Mbps
> - */
> -enum cvmx_usb_speed {
> - CVMX_USB_SPEED_HIGH = 0,
> - CVMX_USB_SPEED_FULL = 1,
> - CVMX_USB_SPEED_LOW = 2,
> -};
> -
> -/**
> - * enum cvmx_usb_transfer - the possible USB transfer types
> - *
> - * @CVMX_USB_TRANSFER_CONTROL: USB transfer type control for hub and status
> - * transfers
> - * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low
> - * priority periodic transfers
> - * @CVMX_USB_TRANSFER_BULK: USB transfer type bulk for large low priority
> - * transfers
> - * @CVMX_USB_TRANSFER_INTERRUPT: USB transfer type interrupt for high priority
> - * periodic transfers
> - */
> -enum cvmx_usb_transfer {
> - CVMX_USB_TRANSFER_CONTROL = 0,
> - CVMX_USB_TRANSFER_ISOCHRONOUS = 1,
> - CVMX_USB_TRANSFER_BULK = 2,
> - CVMX_USB_TRANSFER_INTERRUPT = 3,
> -};
> -
> -/**
> - * enum cvmx_usb_direction - the transfer directions
> - *
> - * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host
> - * @CVMX_USB_DIRECTION_IN: Data is transferring from the device/host to Octeon
> - */
> -enum cvmx_usb_direction {
> - CVMX_USB_DIRECTION_OUT,
> - CVMX_USB_DIRECTION_IN,
> -};
> -
> -/**
> - * enum cvmx_usb_status - possible callback function status codes
> - *
> - * @CVMX_USB_STATUS_OK: The transaction / operation finished without
> - * any errors
> - * @CVMX_USB_STATUS_SHORT: FIXME: This is currently not implemented
> - * @CVMX_USB_STATUS_CANCEL: The transaction was canceled while in flight
> - * by a user call to cvmx_usb_cancel
> - * @CVMX_USB_STATUS_ERROR: The transaction aborted with an unexpected
> - * error status
> - * @CVMX_USB_STATUS_STALL: The transaction received a USB STALL response
> - * from the device
> - * @CVMX_USB_STATUS_XACTERR: The transaction failed with an error from the
> - * device even after a number of retries
> - * @CVMX_USB_STATUS_DATATGLERR: The transaction failed with a data toggle
> - * error even after a number of retries
> - * @CVMX_USB_STATUS_BABBLEERR: The transaction failed with a babble error
> - * @CVMX_USB_STATUS_FRAMEERR: The transaction failed with a frame error
> - * even after a number of retries
> - */
> -enum cvmx_usb_status {
> - CVMX_USB_STATUS_OK,
> - CVMX_USB_STATUS_SHORT,
> - CVMX_USB_STATUS_CANCEL,
> - CVMX_USB_STATUS_ERROR,
> - CVMX_USB_STATUS_STALL,
> - CVMX_USB_STATUS_XACTERR,
> - CVMX_USB_STATUS_DATATGLERR,
> - CVMX_USB_STATUS_BABBLEERR,
> - CVMX_USB_STATUS_FRAMEERR,
> -};
> -
> -/**
> - * struct cvmx_usb_port_status - the USB port status information
> - *
> - * @port_enabled: 1 = Usb port is enabled, 0 = disabled
> - * @port_over_current: 1 = Over current detected, 0 = Over current not
> - * detected. Octeon doesn't support over current detection.
> - * @port_powered: 1 = Port power is being supplied to the device, 0 =
> - * power is off. Octeon doesn't support turning port power
> - * off.
> - * @port_speed: Current port speed.
> - * @connected: 1 = A device is connected to the port, 0 = No device is
> - * connected.
> - * @connect_change: 1 = Device connected state changed since the last set
> - * status call.
> - */
> -struct cvmx_usb_port_status {
> - u32 reserved : 25;
> - u32 port_enabled : 1;
> - u32 port_over_current : 1;
> - u32 port_powered : 1;
> - enum cvmx_usb_speed port_speed : 2;
> - u32 connected : 1;
> - u32 connect_change : 1;
> -};
> -
> -/**
> - * struct cvmx_usb_iso_packet - descriptor for Isochronous packets
> - *
> - * @offset: This is the offset in bytes into the main buffer where this data
> - * is stored.
> - * @length: This is the length in bytes of the data.
> - * @status: This is the status of this individual packet transfer.
> - */
> -struct cvmx_usb_iso_packet {
> - int offset;
> - int length;
> - enum cvmx_usb_status status;
> -};
> -
> -/**
> - * enum cvmx_usb_initialize_flags - flags used by the initialization function
> - *
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI: The USB port uses a 12MHz crystal
> - * as clock source at USB_XO and
> - * USB_XI.
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND: The USB port uses 12/24/48MHz 2.5V
> - * board clock source at USB_XO.
> - * USB_XI should be tied to GND.
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: Speed of reference clock or
> - * crystal
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: Speed of reference clock
> - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: Speed of reference clock
> - * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA: Disable DMA and used polled IO for
> - * data transfer use for the USB
> - */
> -enum cvmx_usb_initialize_flags {
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1 << 0,
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1 << 1,
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3 << 3,
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1 << 3,
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2 << 3,
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3 << 3,
> - /* Bits 3-4 used to encode the clock frequency */
> - CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1 << 5,
> -};
> -
> -/**
> - * enum cvmx_usb_pipe_flags - internal flags for a pipe.
> - *
> - * @CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
> - * actively using hardware.
> - * @CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high speed
> - * pipe is in the ping state.
> - */
> -enum cvmx_usb_pipe_flags {
> - CVMX_USB_PIPE_FLAGS_SCHEDULED = 1 << 17,
> - CVMX_USB_PIPE_FLAGS_NEED_PING = 1 << 18,
> -};
> -
> -/* Maximum number of times to retry failed transactions */
> -#define MAX_RETRIES 3
> -
> -/* Maximum number of hardware channels supported by the USB block */
> -#define MAX_CHANNELS 8
> -
> -/*
> - * The low level hardware can transfer a maximum of this number of bytes in each
> - * transfer. The field is 19 bits wide
> - */
> -#define MAX_TRANSFER_BYTES ((1 << 19) - 1)
> -
> -/*
> - * The low level hardware can transfer a maximum of this number of packets in
> - * each transfer. The field is 10 bits wide
> - */
> -#define MAX_TRANSFER_PACKETS ((1 << 10) - 1)
> -
> -/**
> - * Logical transactions may take numerous low level
> - * transactions, especially when splits are concerned. This
> - * enum represents all of the possible stages a transaction can
> - * be in. Note that split completes are always even. This is so
> - * the NAK handler can backup to the previous low level
> - * transaction with a simple clearing of bit 0.
> - */
> -enum cvmx_usb_stage {
> - CVMX_USB_STAGE_NON_CONTROL,
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE,
> - CVMX_USB_STAGE_SETUP,
> - CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE,
> - CVMX_USB_STAGE_DATA,
> - CVMX_USB_STAGE_DATA_SPLIT_COMPLETE,
> - CVMX_USB_STAGE_STATUS,
> - CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE,
> -};
> -
> -/**
> - * struct cvmx_usb_transaction - describes each pending USB transaction
> - * regardless of type. These are linked together
> - * to form a list of pending requests for a pipe.
> - *
> - * @node: List node for transactions in the pipe.
> - * @type: Type of transaction, duplicated of the pipe.
> - * @flags: State flags for this transaction.
> - * @buffer: User's physical buffer address to read/write.
> - * @buffer_length: Size of the user's buffer in bytes.
> - * @control_header: For control transactions, physical address of the 8
> - * byte standard header.
> - * @iso_start_frame: For ISO transactions, the starting frame number.
> - * @iso_number_packets: For ISO transactions, the number of packets in the
> - * request.
> - * @iso_packets: For ISO transactions, the sub packets in the request.
> - * @actual_bytes: Actual bytes transfer for this transaction.
> - * @stage: For control transactions, the current stage.
> - * @urb: URB.
> - */
> -struct cvmx_usb_transaction {
> - struct list_head node;
> - enum cvmx_usb_transfer type;
> - u64 buffer;
> - int buffer_length;
> - u64 control_header;
> - int iso_start_frame;
> - int iso_number_packets;
> - struct cvmx_usb_iso_packet *iso_packets;
> - int xfersize;
> - int pktcnt;
> - int retries;
> - int actual_bytes;
> - enum cvmx_usb_stage stage;
> - struct urb *urb;
> -};
> -
> -/**
> - * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon
> - * and some USB device. It contains a list of pending
> - * request to the device.
> - *
> - * @node: List node for pipe list
> - * @next: Pipe after this one in the list
> - * @transactions: List of pending transactions
> - * @interval: For periodic pipes, the interval between packets in
> - * frames
> - * @next_tx_frame: The next frame this pipe is allowed to transmit on
> - * @flags: State flags for this pipe
> - * @device_speed: Speed of device connected to this pipe
> - * @transfer_type: Type of transaction supported by this pipe
> - * @transfer_dir: IN or OUT. Ignored for Control
> - * @multi_count: Max packet in a row for the device
> - * @max_packet: The device's maximum packet size in bytes
> - * @device_addr: USB device address at other end of pipe
> - * @endpoint_num: USB endpoint number at other end of pipe
> - * @hub_device_addr: Hub address this device is connected to
> - * @hub_port: Hub port this device is connected to
> - * @pid_toggle: This toggles between 0/1 on every packet send to track
> - * the data pid needed
> - * @channel: Hardware DMA channel for this pipe
> - * @split_sc_frame: The low order bits of the frame number the split
> - * complete should be sent on
> - */
> -struct cvmx_usb_pipe {
> - struct list_head node;
> - struct list_head transactions;
> - u64 interval;
> - u64 next_tx_frame;
> - enum cvmx_usb_pipe_flags flags;
> - enum cvmx_usb_speed device_speed;
> - enum cvmx_usb_transfer transfer_type;
> - enum cvmx_usb_direction transfer_dir;
> - int multi_count;
> - u16 max_packet;
> - u8 device_addr;
> - u8 endpoint_num;
> - u8 hub_device_addr;
> - u8 hub_port;
> - u8 pid_toggle;
> - u8 channel;
> - s8 split_sc_frame;
> -};
> -
> -struct cvmx_usb_tx_fifo {
> - struct {
> - int channel;
> - int size;
> - u64 address;
> - } entry[MAX_CHANNELS + 1];
> - int head;
> - int tail;
> -};
> -
> -/**
> - * struct octeon_hcd - the state of the USB block
> - *
> - * lock: Serialization lock.
> - * init_flags: Flags passed to initialize.
> - * index: Which USB block this is for.
> - * idle_hardware_channels: Bit set for every idle hardware channel.
> - * usbcx_hprt: Stored port status so we don't need to read a CSR to
> - * determine splits.
> - * pipe_for_channel: Map channels to pipes.
> - * pipe: Storage for pipes.
> - * indent: Used by debug output to indent functions.
> - * port_status: Last port status used for change notification.
> - * idle_pipes: List of open pipes that have no transactions.
> - * active_pipes: Active pipes indexed by transfer type.
> - * frame_number: Increments every SOF interrupt for time keeping.
> - * active_split: Points to the current active split, or NULL.
> - */
> -struct octeon_hcd {
> - spinlock_t lock; /* serialization lock */
> - int init_flags;
> - int index;
> - int idle_hardware_channels;
> - union cvmx_usbcx_hprt usbcx_hprt;
> - struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS];
> - int indent;
> - struct cvmx_usb_port_status port_status;
> - struct list_head idle_pipes;
> - struct list_head active_pipes[4];
> - u64 frame_number;
> - struct cvmx_usb_transaction *active_split;
> - struct cvmx_usb_tx_fifo periodic;
> - struct cvmx_usb_tx_fifo nonperiodic;
> -};
> -
> -/*
> - * This macro logically sets a single field in a CSR. It does the sequence
> - * read, modify, and write
> - */
> -#define USB_SET_FIELD32(address, _union, field, value) \
> - do { \
> - union _union c; \
> - \
> - c.u32 = cvmx_usb_read_csr32(usb, address); \
> - c.s.field = value; \
> - cvmx_usb_write_csr32(usb, address, c.u32); \
> - } while (0)
> -
> -/* Returns the IO address to push/pop stuff data from the FIFOs */
> -#define USB_FIFO_ADDRESS(channel, usb_index) \
> - (CVMX_USBCX_GOTGCTL(usb_index) + ((channel) + 1) * 0x1000)
> -
> -/**
> - * struct octeon_temp_buffer - a bounce buffer for USB transfers
> - * @orig_buffer: the original buffer passed by the USB stack
> - * @data: the newly allocated temporary buffer (excluding meta-data)
> - *
> - * Both the DMA engine and FIFO mode will always transfer full 32-bit words. If
> - * the buffer is too short, we need to allocate a temporary one, and this struct
> - * represents it.
> - */
> -struct octeon_temp_buffer {
> - void *orig_buffer;
> - u8 data[0];
> -};
> -
> -static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
> -{
> - return container_of((void *)p, struct usb_hcd, hcd_priv);
> -}
> -
> -/**
> - * octeon_alloc_temp_buffer - allocate a temporary buffer for USB transfer
> - * (if needed)
> - * @urb: URB.
> - * @mem_flags: Memory allocation flags.
> - *
> - * This function allocates a temporary bounce buffer whenever it's needed
> - * due to HW limitations.
> - */
> -static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
> -{
> - struct octeon_temp_buffer *temp;
> -
> - if (urb->num_sgs || urb->sg ||
> - (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) ||
> - !(urb->transfer_buffer_length % sizeof(u32)))
> - return 0;
> -
> - temp = kmalloc(ALIGN(urb->transfer_buffer_length, sizeof(u32)) +
> - sizeof(*temp), mem_flags);
> - if (!temp)
> - return -ENOMEM;
> -
> - temp->orig_buffer = urb->transfer_buffer;
> - if (usb_urb_dir_out(urb))
> - memcpy(temp->data, urb->transfer_buffer,
> - urb->transfer_buffer_length);
> - urb->transfer_buffer = temp->data;
> - urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
> -
> - return 0;
> -}
> -
> -/**
> - * octeon_free_temp_buffer - free a temporary buffer used by USB transfers.
> - * @urb: URB.
> - *
> - * Frees a buffer allocated by octeon_alloc_temp_buffer().
> - */
> -static void octeon_free_temp_buffer(struct urb *urb)
> -{
> - struct octeon_temp_buffer *temp;
> - size_t length;
> -
> - if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
> - return;
> -
> - temp = container_of(urb->transfer_buffer, struct octeon_temp_buffer,
> - data);
> - if (usb_urb_dir_in(urb)) {
> - if (usb_pipeisoc(urb->pipe))
> - length = urb->transfer_buffer_length;
> - else
> - length = urb->actual_length;
> -
> - memcpy(temp->orig_buffer, urb->transfer_buffer, length);
> - }
> - urb->transfer_buffer = temp->orig_buffer;
> - urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
> - kfree(temp);
> -}
> -
> -/**
> - * octeon_map_urb_for_dma - Octeon-specific map_urb_for_dma().
> - * @hcd: USB HCD structure.
> - * @urb: URB.
> - * @mem_flags: Memory allocation flags.
> - */
> -static int octeon_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
> - gfp_t mem_flags)
> -{
> - int ret;
> -
> - ret = octeon_alloc_temp_buffer(urb, mem_flags);
> - if (ret)
> - return ret;
> -
> - ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
> - if (ret)
> - octeon_free_temp_buffer(urb);
> -
> - return ret;
> -}
> -
> -/**
> - * octeon_unmap_urb_for_dma - Octeon-specific unmap_urb_for_dma()
> - * @hcd: USB HCD structure.
> - * @urb: URB.
> - */
> -static void octeon_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
> -{
> - usb_hcd_unmap_urb_for_dma(hcd, urb);
> - octeon_free_temp_buffer(urb);
> -}
> -
> -/**
> - * Read a USB 32bit CSR. It performs the necessary address swizzle
> - * for 32bit CSRs and logs the value in a readable format if
> - * debugging is on.
> - *
> - * @usb: USB block this access is for
> - * @address: 64bit address to read
> - *
> - * Returns: Result of the read
> - */
> -static inline u32 cvmx_usb_read_csr32(struct octeon_hcd *usb, u64 address)
> -{
> - return cvmx_read64_uint32(address ^ 4);
> -}
> -
> -/**
> - * Write a USB 32bit CSR. It performs the necessary address
> - * swizzle for 32bit CSRs and logs the value in a readable format
> - * if debugging is on.
> - *
> - * @usb: USB block this access is for
> - * @address: 64bit address to write
> - * @value: Value to write
> - */
> -static inline void cvmx_usb_write_csr32(struct octeon_hcd *usb,
> - u64 address, u32 value)
> -{
> - cvmx_write64_uint32(address ^ 4, value);
> - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
> -}
> -
> -/**
> - * Return non zero if this pipe connects to a non HIGH speed
> - * device through a high speed hub.
> - *
> - * @usb: USB block this access is for
> - * @pipe: Pipe to check
> - *
> - * Returns: Non zero if we need to do split transactions
> - */
> -static inline int cvmx_usb_pipe_needs_split(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe)
> -{
> - return pipe->device_speed != CVMX_USB_SPEED_HIGH &&
> - usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH;
> -}
> -
> -/**
> - * Trivial utility function to return the correct PID for a pipe
> - *
> - * @pipe: pipe to check
> - *
> - * Returns: PID for pipe
> - */
> -static inline int cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
> -{
> - if (pipe->pid_toggle)
> - return 2; /* Data1 */
> - return 0; /* Data0 */
> -}
> -
> -/* Loops through register until txfflsh or rxfflsh become zero.*/
> -static int cvmx_wait_tx_rx(struct octeon_hcd *usb, int fflsh_type)
> -{
> - int result;
> - u64 address = CVMX_USBCX_GRSTCTL(usb->index);
> - u64 done = cvmx_get_cycle() + 100 *
> - (u64)octeon_get_clock_rate / 1000000;
> - union cvmx_usbcx_grstctl c;
> -
> - while (1) {
> - c.u32 = cvmx_usb_read_csr32(usb, address);
> - if (fflsh_type == 0 && c.s.txfflsh == 0) {
> - result = 0;
> - break;
> - } else if (fflsh_type == 1 && c.s.rxfflsh == 0) {
> - result = 0;
> - break;
> - } else if (cvmx_get_cycle() > done) {
> - result = -1;
> - break;
> - }
> -
> - __delay(100);
> - }
> - return result;
> -}
> -
> -static void cvmx_fifo_setup(struct octeon_hcd *usb)
> -{
> - union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
> - union cvmx_usbcx_gnptxfsiz npsiz;
> - union cvmx_usbcx_hptxfsiz psiz;
> -
> - usbcx_ghwcfg3.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GHWCFG3(usb->index));
> -
> - /*
> - * Program the USBC_GRXFSIZ register to select the size of the receive
> - * FIFO (25%).
> - */
> - USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz,
> - rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
> -
> - /*
> - * Program the USBC_GNPTXFSIZ register to select the size and the start
> - * address of the non-periodic transmit FIFO for nonperiodic
> - * transactions (50%).
> - */
> - npsiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
> - npsiz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
> - npsiz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), npsiz.u32);
> -
> - /*
> - * Program the USBC_HPTXFSIZ register to select the size and start
> - * address of the periodic transmit FIFO for periodic transactions
> - * (25%).
> - */
> - psiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
> - psiz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
> - psiz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), psiz.u32);
> -
> - /* Flush all FIFOs */
> - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
> - cvmx_usbcx_grstctl, txfnum, 0x10);
> - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
> - cvmx_usbcx_grstctl, txfflsh, 1);
> - cvmx_wait_tx_rx(usb, 0);
> - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index),
> - cvmx_usbcx_grstctl, rxfflsh, 1);
> - cvmx_wait_tx_rx(usb, 1);
> -}
> -
> -/**
> - * Shutdown a USB port after a call to cvmx_usb_initialize().
> - * The port should be disabled with all pipes closed when this
> - * function is called.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_shutdown(struct octeon_hcd *usb)
> -{
> - union cvmx_usbnx_clk_ctl usbn_clk_ctl;
> -
> - /* Make sure all pipes are closed */
> - if (!list_empty(&usb->idle_pipes) ||
> - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) ||
> - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) ||
> - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) ||
> - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK]))
> - return -EBUSY;
> -
> - /* Disable the clocks and put them in power on reset */
> - usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index));
> - usbn_clk_ctl.s.enable = 1;
> - usbn_clk_ctl.s.por = 1;
> - usbn_clk_ctl.s.hclk_rst = 1;
> - usbn_clk_ctl.s.prst = 0;
> - usbn_clk_ctl.s.hrst = 0;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - return 0;
> -}
> -
> -/**
> - * Initialize a USB port for use. This must be called before any
> - * other access to the Octeon USB port is made. The port starts
> - * off in the disabled state.
> - *
> - * @dev: Pointer to struct device for logging purposes.
> - * @usb: Pointer to struct octeon_hcd.
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_initialize(struct device *dev,
> - struct octeon_hcd *usb)
> -{
> - int channel;
> - int divisor;
> - int retries = 0;
> - union cvmx_usbcx_hcfg usbcx_hcfg;
> - union cvmx_usbnx_clk_ctl usbn_clk_ctl;
> - union cvmx_usbcx_gintsts usbc_gintsts;
> - union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
> - union cvmx_usbcx_gintmsk usbcx_gintmsk;
> - union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
> - union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
> -
> -retry:
> - /*
> - * Power On Reset and PHY Initialization
> - *
> - * 1. Wait for DCOK to assert (nothing to do)
> - *
> - * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
> - * USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0
> - */
> - usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index));
> - usbn_clk_ctl.s.por = 1;
> - usbn_clk_ctl.s.hrst = 0;
> - usbn_clk_ctl.s.prst = 0;
> - usbn_clk_ctl.s.hclk_rst = 0;
> - usbn_clk_ctl.s.enable = 0;
> - /*
> - * 2b. Select the USB reference clock/crystal parameters by writing
> - * appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON]
> - */
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
> - /*
> - * The USB port uses 12/24/48MHz 2.5V board clock
> - * source at USB_XO. USB_XI should be tied to GND.
> - * Most Octeon evaluation boards require this setting
> - */
> - if (OCTEON_IS_MODEL(OCTEON_CN3XXX) ||
> - OCTEON_IS_MODEL(OCTEON_CN56XX) ||
> - OCTEON_IS_MODEL(OCTEON_CN50XX))
> - /* From CN56XX,CN50XX,CN31XX,CN30XX manuals */
> - usbn_clk_ctl.s.p_rtype = 2; /* p_rclk=1 & p_xenbn=0 */
> - else
> - /* From CN52XX manual */
> - usbn_clk_ctl.s.p_rtype = 1;
> -
> - switch (usb->init_flags &
> - CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
> - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
> - usbn_clk_ctl.s.p_c_sel = 0;
> - break;
> - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:
> - usbn_clk_ctl.s.p_c_sel = 1;
> - break;
> - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:
> - usbn_clk_ctl.s.p_c_sel = 2;
> - break;
> - }
> - } else {
> - /*
> - * The USB port uses a 12MHz crystal as clock source
> - * at USB_XO and USB_XI
> - */
> - if (OCTEON_IS_MODEL(OCTEON_CN3XXX))
> - /* From CN31XX,CN30XX manual */
> - usbn_clk_ctl.s.p_rtype = 3; /* p_rclk=1 & p_xenbn=1 */
> - else
> - /* From CN56XX,CN52XX,CN50XX manuals. */
> - usbn_clk_ctl.s.p_rtype = 0;
> -
> - usbn_clk_ctl.s.p_c_sel = 0;
> - }
> - /*
> - * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and
> - * setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down
> - * such that USB is as close as possible to 125Mhz
> - */
> - divisor = DIV_ROUND_UP(octeon_get_clock_rate(), 125000000);
> - /* Lower than 4 doesn't seem to work properly */
> - if (divisor < 4)
> - divisor = 4;
> - usbn_clk_ctl.s.divide = divisor;
> - usbn_clk_ctl.s.divide2 = 0;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> -
> - /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
> - usbn_clk_ctl.s.hclk_rst = 1;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */
> - __delay(64);
> - /*
> - * 3. Program the power-on reset field in the USBN clock-control
> - * register:
> - * USBN_CLK_CTL[POR] = 0
> - */
> - usbn_clk_ctl.s.por = 0;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - /* 4. Wait 1 ms for PHY clock to start */
> - mdelay(1);
> - /*
> - * 5. Program the Reset input from automatic test equipment field in the
> - * USBP control and status register:
> - * USBN_USBP_CTL_STATUS[ATE_RESET] = 1
> - */
> - usbn_usbp_ctl_status.u64 =
> - cvmx_read64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index));
> - usbn_usbp_ctl_status.s.ate_reset = 1;
> - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
> - usbn_usbp_ctl_status.u64);
> - /* 6. Wait 10 cycles */
> - __delay(10);
> - /*
> - * 7. Clear ATE_RESET field in the USBN clock-control register:
> - * USBN_USBP_CTL_STATUS[ATE_RESET] = 0
> - */
> - usbn_usbp_ctl_status.s.ate_reset = 0;
> - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
> - usbn_usbp_ctl_status.u64);
> - /*
> - * 8. Program the PHY reset field in the USBN clock-control register:
> - * USBN_CLK_CTL[PRST] = 1
> - */
> - usbn_clk_ctl.s.prst = 1;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - /*
> - * 9. Program the USBP control and status register to select host or
> - * device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
> - * device
> - */
> - usbn_usbp_ctl_status.s.hst_mode = 0;
> - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index),
> - usbn_usbp_ctl_status.u64);
> - /* 10. Wait 1 us */
> - udelay(1);
> - /*
> - * 11. Program the hreset_n field in the USBN clock-control register:
> - * USBN_CLK_CTL[HRST] = 1
> - */
> - usbn_clk_ctl.s.hrst = 1;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - /* 12. Proceed to USB core initialization */
> - usbn_clk_ctl.s.enable = 1;
> - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64);
> - udelay(1);
> -
> - /*
> - * USB Core Initialization
> - *
> - * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to
> - * determine USB core configuration parameters.
> - *
> - * Nothing needed
> - *
> - * 2. Program the following fields in the global AHB configuration
> - * register (USBC_GAHBCFG)
> - * DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode
> - * Burst length, USBC_GAHBCFG[HBSTLEN] = 0
> - * Nonperiodic TxFIFO empty level (slave mode only),
> - * USBC_GAHBCFG[NPTXFEMPLVL]
> - * Periodic TxFIFO empty level (slave mode only),
> - * USBC_GAHBCFG[PTXFEMPLVL]
> - * Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1
> - */
> - usbcx_gahbcfg.u32 = 0;
> - usbcx_gahbcfg.s.dmaen = !(usb->init_flags &
> - CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
> - usbcx_gahbcfg.s.hbstlen = 0;
> - usbcx_gahbcfg.s.nptxfemplvl = 1;
> - usbcx_gahbcfg.s.ptxfemplvl = 1;
> - usbcx_gahbcfg.s.glblintrmsk = 1;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
> - usbcx_gahbcfg.u32);
> -
> - /*
> - * 3. Program the following fields in USBC_GUSBCFG register.
> - * HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
> - * ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0
> - * USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
> - * PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0
> - */
> - usbcx_gusbcfg.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GUSBCFG(usb->index));
> - usbcx_gusbcfg.s.toutcal = 0;
> - usbcx_gusbcfg.s.ddrsel = 0;
> - usbcx_gusbcfg.s.usbtrdtim = 0x5;
> - usbcx_gusbcfg.s.phylpwrclksel = 0;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
> - usbcx_gusbcfg.u32);
> -
> - /*
> - * 4. The software must unmask the following bits in the USBC_GINTMSK
> - * register.
> - * OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
> - * Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1
> - */
> - usbcx_gintmsk.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GINTMSK(usb->index));
> - usbcx_gintmsk.s.otgintmsk = 1;
> - usbcx_gintmsk.s.modemismsk = 1;
> - usbcx_gintmsk.s.hchintmsk = 1;
> - usbcx_gintmsk.s.sofmsk = 0;
> - /* We need RX FIFO interrupts if we don't have DMA */
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
> - usbcx_gintmsk.s.rxflvlmsk = 1;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
> - usbcx_gintmsk.u32);
> -
> - /*
> - * Disable all channel interrupts. We'll enable them per channel later.
> - */
> - for (channel = 0; channel < 8; channel++)
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCINTMSKX(channel, usb->index),
> - 0);
> -
> - /*
> - * Host Port Initialization
> - *
> - * 1. Program the host-port interrupt-mask field to unmask,
> - * USBC_GINTMSK[PRTINT] = 1
> - */
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, prtintmsk, 1);
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, disconnintmsk, 1);
> -
> - /*
> - * 2. Program the USBC_HCFG register to select full-speed host
> - * or high-speed host.
> - */
> - usbcx_hcfg.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
> - usbcx_hcfg.s.fslssupp = 0;
> - usbcx_hcfg.s.fslspclksel = 0;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
> -
> - cvmx_fifo_setup(usb);
> -
> - /*
> - * If the controller is getting port events right after the reset, it
> - * means the initialization failed. Try resetting the controller again
> - * in such case. This is seen to happen after cold boot on DSR-1000N.
> - */
> - usbc_gintsts.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GINTSTS(usb->index));
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index),
> - usbc_gintsts.u32);
> - dev_dbg(dev, "gintsts after reset: 0x%x\n", (int)usbc_gintsts.u32);
> - if (!usbc_gintsts.s.disconnint && !usbc_gintsts.s.prtint)
> - return 0;
> - if (retries++ >= 5)
> - return -EAGAIN;
> - dev_info(dev, "controller reset failed (gintsts=0x%x) - retrying\n",
> - (int)usbc_gintsts.u32);
> - msleep(50);
> - cvmx_usb_shutdown(usb);
> - msleep(50);
> - goto retry;
> -}
> -
> -/**
> - * Reset a USB port. After this call succeeds, the USB port is
> - * online and servicing requests.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - */
> -static void cvmx_usb_reset_port(struct octeon_hcd *usb)
> -{
> - usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HPRT(usb->index));
> -
> - /* Program the port reset bit to start the reset process */
> - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
> - prtrst, 1);
> -
> - /*
> - * Wait at least 50ms (high speed), or 10ms (full speed) for the reset
> - * process to complete.
> - */
> - mdelay(50);
> -
> - /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
> - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
> - prtrst, 0);
> -
> - /*
> - * Read the port speed field to get the enumerated speed,
> - * USBC_HPRT[PRTSPD].
> - */
> - usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HPRT(usb->index));
> -}
> -
> -/**
> - * Disable a USB port. After this call the USB port will not
> - * generate data transfers and will not generate events.
> - * Transactions in process will fail and call their
> - * associated callbacks.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_disable(struct octeon_hcd *usb)
> -{
> - /* Disable the port */
> - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt,
> - prtena, 1);
> - return 0;
> -}
> -
> -/**
> - * Get the current state of the USB port. Use this call to
> - * determine if the usb port has anything connected, is enabled,
> - * or has some sort of error condition. The return value of this
> - * call has "changed" bits to signal of the value of some fields
> - * have changed between calls.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - *
> - * Returns: Port status information
> - */
> -static struct cvmx_usb_port_status cvmx_usb_get_status(struct octeon_hcd *usb)
> -{
> - union cvmx_usbcx_hprt usbc_hprt;
> - struct cvmx_usb_port_status result;
> -
> - memset(&result, 0, sizeof(result));
> -
> - usbc_hprt.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
> - result.port_enabled = usbc_hprt.s.prtena;
> - result.port_over_current = usbc_hprt.s.prtovrcurract;
> - result.port_powered = usbc_hprt.s.prtpwr;
> - result.port_speed = usbc_hprt.s.prtspd;
> - result.connected = usbc_hprt.s.prtconnsts;
> - result.connect_change =
> - result.connected != usb->port_status.connected;
> -
> - return result;
> -}
> -
> -/**
> - * Open a virtual pipe between the host and a USB device. A pipe
> - * must be opened before data can be transferred between a device
> - * and Octeon.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @device_addr:
> - * USB device address to open the pipe to
> - * (0-127).
> - * @endpoint_num:
> - * USB endpoint number to open the pipe to
> - * (0-15).
> - * @device_speed:
> - * The speed of the device the pipe is going
> - * to. This must match the device's speed,
> - * which may be different than the port speed.
> - * @max_packet: The maximum packet length the device can
> - * transmit/receive (low speed=0-8, full
> - * speed=0-1023, high speed=0-1024). This value
> - * comes from the standard endpoint descriptor
> - * field wMaxPacketSize bits <10:0>.
> - * @transfer_type:
> - * The type of transfer this pipe is for.
> - * @transfer_dir:
> - * The direction the pipe is in. This is not
> - * used for control pipes.
> - * @interval: For ISOCHRONOUS and INTERRUPT transfers,
> - * this is how often the transfer is scheduled
> - * for. All other transfers should specify
> - * zero. The units are in frames (8000/sec at
> - * high speed, 1000/sec for full speed).
> - * @multi_count:
> - * For high speed devices, this is the maximum
> - * allowed number of packet per microframe.
> - * Specify zero for non high speed devices. This
> - * value comes from the standard endpoint descriptor
> - * field wMaxPacketSize bits <12:11>.
> - * @hub_device_addr:
> - * Hub device address this device is connected
> - * to. Devices connected directly to Octeon
> - * use zero. This is only used when the device
> - * is full/low speed behind a high speed hub.
> - * The address will be of the high speed hub,
> - * not and full speed hubs after it.
> - * @hub_port: Which port on the hub the device is
> - * connected. Use zero for devices connected
> - * directly to Octeon. Like hub_device_addr,
> - * this is only used for full/low speed
> - * devices behind a high speed hub.
> - *
> - * Returns: A non-NULL value is a pipe. NULL means an error.
> - */
> -static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct octeon_hcd *usb,
> - int device_addr,
> - int endpoint_num,
> - enum cvmx_usb_speed
> - device_speed,
> - int max_packet,
> - enum cvmx_usb_transfer
> - transfer_type,
> - enum cvmx_usb_direction
> - transfer_dir,
> - int interval, int multi_count,
> - int hub_device_addr,
> - int hub_port)
> -{
> - struct cvmx_usb_pipe *pipe;
> -
> - pipe = kzalloc(sizeof(*pipe), GFP_ATOMIC);
> - if (!pipe)
> - return NULL;
> - if ((device_speed == CVMX_USB_SPEED_HIGH) &&
> - (transfer_dir == CVMX_USB_DIRECTION_OUT) &&
> - (transfer_type == CVMX_USB_TRANSFER_BULK))
> - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING;
> - pipe->device_addr = device_addr;
> - pipe->endpoint_num = endpoint_num;
> - pipe->device_speed = device_speed;
> - pipe->max_packet = max_packet;
> - pipe->transfer_type = transfer_type;
> - pipe->transfer_dir = transfer_dir;
> - INIT_LIST_HEAD(&pipe->transactions);
> -
> - /*
> - * All pipes use interval to rate limit NAK processing. Force an
> - * interval if one wasn't supplied
> - */
> - if (!interval)
> - interval = 1;
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - pipe->interval = interval * 8;
> - /* Force start splits to be schedule on uFrame 0 */
> - pipe->next_tx_frame = ((usb->frame_number + 7) & ~7) +
> - pipe->interval;
> - } else {
> - pipe->interval = interval;
> - pipe->next_tx_frame = usb->frame_number + pipe->interval;
> - }
> - pipe->multi_count = multi_count;
> - pipe->hub_device_addr = hub_device_addr;
> - pipe->hub_port = hub_port;
> - pipe->pid_toggle = 0;
> - pipe->split_sc_frame = -1;
> - list_add_tail(&pipe->node, &usb->idle_pipes);
> -
> - /*
> - * We don't need to tell the hardware about this pipe yet since
> - * it doesn't have any submitted requests
> - */
> -
> - return pipe;
> -}
> -
> -/**
> - * Poll the RX FIFOs and remove data as needed. This function is only used
> - * in non DMA mode. It is very important that this function be called quickly
> - * enough to prevent FIFO overflow.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - */
> -static void cvmx_usb_poll_rx_fifo(struct octeon_hcd *usb)
> -{
> - union cvmx_usbcx_grxstsph rx_status;
> - int channel;
> - int bytes;
> - u64 address;
> - u32 *ptr;
> -
> - rx_status.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GRXSTSPH(usb->index));
> - /* Only read data if IN data is there */
> - if (rx_status.s.pktsts != 2)
> - return;
> - /* Check if no data is available */
> - if (!rx_status.s.bcnt)
> - return;
> -
> - channel = rx_status.s.chnum;
> - bytes = rx_status.s.bcnt;
> - if (!bytes)
> - return;
> -
> - /* Get where the DMA engine would have written this data */
> - address = cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) +
> - channel * 8);
> -
> - ptr = cvmx_phys_to_ptr(address);
> - cvmx_write64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel * 8,
> - address + bytes);
> -
> - /* Loop writing the FIFO data for this packet into memory */
> - while (bytes > 0) {
> - *ptr++ = cvmx_usb_read_csr32(usb,
> - USB_FIFO_ADDRESS(channel, usb->index));
> - bytes -= 4;
> - }
> - CVMX_SYNCW;
> -}
> -
> -/**
> - * Fill the TX hardware fifo with data out of the software
> - * fifos
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @fifo: Software fifo to use
> - * @available: Amount of space in the hardware fifo
> - *
> - * Returns: Non zero if the hardware fifo was too small and needs
> - * to be serviced again.
> - */
> -static int cvmx_usb_fill_tx_hw(struct octeon_hcd *usb,
> - struct cvmx_usb_tx_fifo *fifo, int available)
> -{
> - /*
> - * We're done either when there isn't anymore space or the software FIFO
> - * is empty
> - */
> - while (available && (fifo->head != fifo->tail)) {
> - int i = fifo->tail;
> - const u32 *ptr = cvmx_phys_to_ptr(fifo->entry[i].address);
> - u64 csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel,
> - usb->index) ^ 4;
> - int words = available;
> -
> - /* Limit the amount of data to what the SW fifo has */
> - if (fifo->entry[i].size <= available) {
> - words = fifo->entry[i].size;
> - fifo->tail++;
> - if (fifo->tail > MAX_CHANNELS)
> - fifo->tail = 0;
> - }
> -
> - /* Update the next locations and counts */
> - available -= words;
> - fifo->entry[i].address += words * 4;
> - fifo->entry[i].size -= words;
> -
> - /*
> - * Write the HW fifo data. The read every three writes is due
> - * to an errata on CN3XXX chips
> - */
> - while (words > 3) {
> - cvmx_write64_uint32(csr_address, *ptr++);
> - cvmx_write64_uint32(csr_address, *ptr++);
> - cvmx_write64_uint32(csr_address, *ptr++);
> - cvmx_read64_uint64(
> - CVMX_USBNX_DMA0_INB_CHN0(usb->index));
> - words -= 3;
> - }
> - cvmx_write64_uint32(csr_address, *ptr++);
> - if (--words) {
> - cvmx_write64_uint32(csr_address, *ptr++);
> - if (--words)
> - cvmx_write64_uint32(csr_address, *ptr++);
> - }
> - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
> - }
> - return fifo->head != fifo->tail;
> -}
> -
> -/**
> - * Check the hardware FIFOs and fill them as needed
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - */
> -static void cvmx_usb_poll_tx_fifo(struct octeon_hcd *usb)
> -{
> - if (usb->periodic.head != usb->periodic.tail) {
> - union cvmx_usbcx_hptxsts tx_status;
> -
> - tx_status.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HPTXSTS(usb->index));
> - if (cvmx_usb_fill_tx_hw(usb, &usb->periodic,
> - tx_status.s.ptxfspcavail))
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, ptxfempmsk, 1);
> - else
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, ptxfempmsk, 0);
> - }
> -
> - if (usb->nonperiodic.head != usb->nonperiodic.tail) {
> - union cvmx_usbcx_gnptxsts tx_status;
> -
> - tx_status.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GNPTXSTS(usb->index));
> - if (cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic,
> - tx_status.s.nptxfspcavail))
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, nptxfempmsk, 1);
> - else
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, nptxfempmsk, 0);
> - }
> -}
> -
> -/**
> - * Fill the TX FIFO with an outgoing packet
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @channel: Channel number to get packet from
> - */
> -static void cvmx_usb_fill_tx_fifo(struct octeon_hcd *usb, int channel)
> -{
> - union cvmx_usbcx_hccharx hcchar;
> - union cvmx_usbcx_hcspltx usbc_hcsplt;
> - union cvmx_usbcx_hctsizx usbc_hctsiz;
> - struct cvmx_usb_tx_fifo *fifo;
> -
> - /* We only need to fill data on outbound channels */
> - hcchar.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel, usb->index));
> - if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
> - return;
> -
> - /* OUT Splits only have data on the start and not the complete */
> - usbc_hcsplt.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCSPLTX(channel, usb->index));
> - if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
> - return;
> -
> - /*
> - * Find out how many bytes we need to fill and convert it into 32bit
> - * words.
> - */
> - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCTSIZX(channel, usb->index));
> - if (!usbc_hctsiz.s.xfersize)
> - return;
> -
> - if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) ||
> - (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS))
> - fifo = &usb->periodic;
> - else
> - fifo = &usb->nonperiodic;
> -
> - fifo->entry[fifo->head].channel = channel;
> - fifo->entry[fifo->head].address =
> - cvmx_read64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) +
> - channel * 8);
> - fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize + 3) >> 2;
> - fifo->head++;
> - if (fifo->head > MAX_CHANNELS)
> - fifo->head = 0;
> -
> - cvmx_usb_poll_tx_fifo(usb);
> -}
> -
> -/**
> - * Perform channel specific setup for Control transactions. All
> - * the generic stuff will already have been done in cvmx_usb_start_channel().
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @channel: Channel to setup
> - * @pipe: Pipe for control transaction
> - */
> -static void cvmx_usb_start_channel_control(struct octeon_hcd *usb,
> - int channel,
> - struct cvmx_usb_pipe *pipe)
> -{
> - struct usb_hcd *hcd = octeon_to_hcd(usb);
> - struct device *dev = hcd->self.controller;
> - struct cvmx_usb_transaction *transaction =
> - list_first_entry(&pipe->transactions, typeof(*transaction),
> - node);
> - struct usb_ctrlrequest *header =
> - cvmx_phys_to_ptr(transaction->control_header);
> - int bytes_to_transfer = transaction->buffer_length -
> - transaction->actual_bytes;
> - int packets_to_transfer;
> - union cvmx_usbcx_hctsizx usbc_hctsiz;
> -
> - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCTSIZX(channel, usb->index));
> -
> - switch (transaction->stage) {
> - case CVMX_USB_STAGE_NON_CONTROL:
> - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
> - dev_err(dev, "%s: ERROR - Non control stage\n", __func__);
> - break;
> - case CVMX_USB_STAGE_SETUP:
> - usbc_hctsiz.s.pid = 3; /* Setup */
> - bytes_to_transfer = sizeof(*header);
> - /* All Control operations start with a setup going OUT */
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - CVMX_USB_DIRECTION_OUT);
> - /*
> - * Setup send the control header instead of the buffer data. The
> - * buffer data will be used in the next stage
> - */
> - cvmx_write64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) +
> - channel * 8,
> - transaction->control_header);
> - break;
> - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
> - usbc_hctsiz.s.pid = 3; /* Setup */
> - bytes_to_transfer = 0;
> - /* All Control operations start with a setup going OUT */
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - CVMX_USB_DIRECTION_OUT);
> -
> - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
> - cvmx_usbcx_hcspltx, compsplt, 1);
> - break;
> - case CVMX_USB_STAGE_DATA:
> - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - if (header->bRequestType & USB_DIR_IN)
> - bytes_to_transfer = 0;
> - else if (bytes_to_transfer > pipe->max_packet)
> - bytes_to_transfer = pipe->max_packet;
> - }
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - ((header->bRequestType & USB_DIR_IN) ?
> - CVMX_USB_DIRECTION_IN :
> - CVMX_USB_DIRECTION_OUT));
> - break;
> - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
> - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
> - if (!(header->bRequestType & USB_DIR_IN))
> - bytes_to_transfer = 0;
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - ((header->bRequestType & USB_DIR_IN) ?
> - CVMX_USB_DIRECTION_IN :
> - CVMX_USB_DIRECTION_OUT));
> - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
> - cvmx_usbcx_hcspltx, compsplt, 1);
> - break;
> - case CVMX_USB_STAGE_STATUS:
> - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
> - bytes_to_transfer = 0;
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - ((header->bRequestType & USB_DIR_IN) ?
> - CVMX_USB_DIRECTION_OUT :
> - CVMX_USB_DIRECTION_IN));
> - break;
> - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
> - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
> - bytes_to_transfer = 0;
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, epdir,
> - ((header->bRequestType & USB_DIR_IN) ?
> - CVMX_USB_DIRECTION_OUT :
> - CVMX_USB_DIRECTION_IN));
> - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index),
> - cvmx_usbcx_hcspltx, compsplt, 1);
> - break;
> - }
> -
> - /*
> - * Make sure the transfer never exceeds the byte limit of the hardware.
> - * Further bytes will be sent as continued transactions
> - */
> - if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
> - /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
> - bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
> - bytes_to_transfer *= pipe->max_packet;
> - }
> -
> - /*
> - * Calculate the number of packets to transfer. If the length is zero
> - * we still need to transfer one packet
> - */
> - packets_to_transfer = DIV_ROUND_UP(bytes_to_transfer,
> - pipe->max_packet);
> - if (packets_to_transfer == 0) {
> - packets_to_transfer = 1;
> - } else if ((packets_to_transfer > 1) &&
> - (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
> - /*
> - * Limit to one packet when not using DMA. Channels must be
> - * restarted between every packet for IN transactions, so there
> - * is no reason to do multiple packets in a row
> - */
> - packets_to_transfer = 1;
> - bytes_to_transfer = packets_to_transfer * pipe->max_packet;
> - } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
> - /*
> - * Limit the number of packet and data transferred to what the
> - * hardware can handle
> - */
> - packets_to_transfer = MAX_TRANSFER_PACKETS;
> - bytes_to_transfer = packets_to_transfer * pipe->max_packet;
> - }
> -
> - usbc_hctsiz.s.xfersize = bytes_to_transfer;
> - usbc_hctsiz.s.pktcnt = packets_to_transfer;
> -
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index),
> - usbc_hctsiz.u32);
> -}
> -
> -/**
> - * Start a channel to perform the pipe's head transaction
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @channel: Channel to setup
> - * @pipe: Pipe to start
> - */
> -static void cvmx_usb_start_channel(struct octeon_hcd *usb, int channel,
> - struct cvmx_usb_pipe *pipe)
> -{
> - struct cvmx_usb_transaction *transaction =
> - list_first_entry(&pipe->transactions, typeof(*transaction),
> - node);
> -
> - /* Make sure all writes to the DMA region get flushed */
> - CVMX_SYNCW;
> -
> - /* Attach the channel to the pipe */
> - usb->pipe_for_channel[channel] = pipe;
> - pipe->channel = channel;
> - pipe->flags |= CVMX_USB_PIPE_FLAGS_SCHEDULED;
> -
> - /* Mark this channel as in use */
> - usb->idle_hardware_channels &= ~(1 << channel);
> -
> - /* Enable the channel interrupt bits */
> - {
> - union cvmx_usbcx_hcintx usbc_hcint;
> - union cvmx_usbcx_hcintmskx usbc_hcintmsk;
> - union cvmx_usbcx_haintmsk usbc_haintmsk;
> -
> - /* Clear all channel status bits */
> - usbc_hcint.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCINTX(channel, usb->index));
> -
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCINTX(channel, usb->index),
> - usbc_hcint.u32);
> -
> - usbc_hcintmsk.u32 = 0;
> - usbc_hcintmsk.s.chhltdmsk = 1;
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
> - /*
> - * Channels need these extra interrupts when we aren't
> - * in DMA mode.
> - */
> - usbc_hcintmsk.s.datatglerrmsk = 1;
> - usbc_hcintmsk.s.frmovrunmsk = 1;
> - usbc_hcintmsk.s.bblerrmsk = 1;
> - usbc_hcintmsk.s.xacterrmsk = 1;
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - /*
> - * Splits don't generate xfercompl, so we need
> - * ACK and NYET.
> - */
> - usbc_hcintmsk.s.nyetmsk = 1;
> - usbc_hcintmsk.s.ackmsk = 1;
> - }
> - usbc_hcintmsk.s.nakmsk = 1;
> - usbc_hcintmsk.s.stallmsk = 1;
> - usbc_hcintmsk.s.xfercomplmsk = 1;
> - }
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCINTMSKX(channel, usb->index),
> - usbc_hcintmsk.u32);
> -
> - /* Enable the channel interrupt to propagate */
> - usbc_haintmsk.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HAINTMSK(usb->index));
> - usbc_haintmsk.s.haintmsk |= 1 << channel;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index),
> - usbc_haintmsk.u32);
> - }
> -
> - /* Setup the location the DMA engine uses. */
> - {
> - u64 reg;
> - u64 dma_address = transaction->buffer +
> - transaction->actual_bytes;
> -
> - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
> - dma_address = transaction->buffer +
> - transaction->iso_packets[0].offset +
> - transaction->actual_bytes;
> -
> - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)
> - reg = CVMX_USBNX_DMA0_OUTB_CHN0(usb->index);
> - else
> - reg = CVMX_USBNX_DMA0_INB_CHN0(usb->index);
> - cvmx_write64_uint64(reg + channel * 8, dma_address);
> - }
> -
> - /* Setup both the size of the transfer and the SPLIT characteristics */
> - {
> - union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0};
> - union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0};
> - int packets_to_transfer;
> - int bytes_to_transfer = transaction->buffer_length -
> - transaction->actual_bytes;
> -
> - /*
> - * ISOCHRONOUS transactions store each individual transfer size
> - * in the packet structure, not the global buffer_length
> - */
> - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
> - bytes_to_transfer =
> - transaction->iso_packets[0].length -
> - transaction->actual_bytes;
> -
> - /*
> - * We need to do split transactions when we are talking to non
> - * high speed devices that are behind a high speed hub
> - */
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - /*
> - * On the start split phase (stage is even) record the
> - * frame number we will need to send the split complete.
> - * We only store the lower two bits since the time ahead
> - * can only be two frames
> - */
> - if ((transaction->stage & 1) == 0) {
> - if (transaction->type == CVMX_USB_TRANSFER_BULK)
> - pipe->split_sc_frame =
> - (usb->frame_number + 1) & 0x7f;
> - else
> - pipe->split_sc_frame =
> - (usb->frame_number + 2) & 0x7f;
> - } else {
> - pipe->split_sc_frame = -1;
> - }
> -
> - usbc_hcsplt.s.spltena = 1;
> - usbc_hcsplt.s.hubaddr = pipe->hub_device_addr;
> - usbc_hcsplt.s.prtaddr = pipe->hub_port;
> - usbc_hcsplt.s.compsplt = (transaction->stage ==
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE);
> -
> - /*
> - * SPLIT transactions can only ever transmit one data
> - * packet so limit the transfer size to the max packet
> - * size
> - */
> - if (bytes_to_transfer > pipe->max_packet)
> - bytes_to_transfer = pipe->max_packet;
> -
> - /*
> - * ISOCHRONOUS OUT splits are unique in that they limit
> - * data transfers to 188 byte chunks representing the
> - * begin/middle/end of the data or all
> - */
> - if (!usbc_hcsplt.s.compsplt &&
> - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
> - (pipe->transfer_type ==
> - CVMX_USB_TRANSFER_ISOCHRONOUS)) {
> - /*
> - * Clear the split complete frame number as
> - * there isn't going to be a split complete
> - */
> - pipe->split_sc_frame = -1;
> - /*
> - * See if we've started this transfer and sent
> - * data
> - */
> - if (transaction->actual_bytes == 0) {
> - /*
> - * Nothing sent yet, this is either a
> - * begin or the entire payload
> - */
> - if (bytes_to_transfer <= 188)
> - /* Entire payload in one go */
> - usbc_hcsplt.s.xactpos = 3;
> - else
> - /* First part of payload */
> - usbc_hcsplt.s.xactpos = 2;
> - } else {
> - /*
> - * Continuing the previous data, we must
> - * either be in the middle or at the end
> - */
> - if (bytes_to_transfer <= 188)
> - /* End of payload */
> - usbc_hcsplt.s.xactpos = 1;
> - else
> - /* Middle of payload */
> - usbc_hcsplt.s.xactpos = 0;
> - }
> - /*
> - * Again, the transfer size is limited to 188
> - * bytes
> - */
> - if (bytes_to_transfer > 188)
> - bytes_to_transfer = 188;
> - }
> - }
> -
> - /*
> - * Make sure the transfer never exceeds the byte limit of the
> - * hardware. Further bytes will be sent as continued
> - * transactions
> - */
> - if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
> - /*
> - * Round MAX_TRANSFER_BYTES to a multiple of out packet
> - * size
> - */
> - bytes_to_transfer = MAX_TRANSFER_BYTES /
> - pipe->max_packet;
> - bytes_to_transfer *= pipe->max_packet;
> - }
> -
> - /*
> - * Calculate the number of packets to transfer. If the length is
> - * zero we still need to transfer one packet
> - */
> - packets_to_transfer =
> - DIV_ROUND_UP(bytes_to_transfer, pipe->max_packet);
> - if (packets_to_transfer == 0) {
> - packets_to_transfer = 1;
> - } else if ((packets_to_transfer > 1) &&
> - (usb->init_flags &
> - CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
> - /*
> - * Limit to one packet when not using DMA. Channels must
> - * be restarted between every packet for IN
> - * transactions, so there is no reason to do multiple
> - * packets in a row
> - */
> - packets_to_transfer = 1;
> - bytes_to_transfer = packets_to_transfer *
> - pipe->max_packet;
> - } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
> - /*
> - * Limit the number of packet and data transferred to
> - * what the hardware can handle
> - */
> - packets_to_transfer = MAX_TRANSFER_PACKETS;
> - bytes_to_transfer = packets_to_transfer *
> - pipe->max_packet;
> - }
> -
> - usbc_hctsiz.s.xfersize = bytes_to_transfer;
> - usbc_hctsiz.s.pktcnt = packets_to_transfer;
> -
> - /* Update the DATA0/DATA1 toggle */
> - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe);
> - /*
> - * High speed pipes may need a hardware ping before they start
> - */
> - if (pipe->flags & CVMX_USB_PIPE_FLAGS_NEED_PING)
> - usbc_hctsiz.s.dopng = 1;
> -
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCSPLTX(channel, usb->index),
> - usbc_hcsplt.u32);
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCTSIZX(channel, usb->index),
> - usbc_hctsiz.u32);
> - }
> -
> - /* Setup the Host Channel Characteristics Register */
> - {
> - union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0};
> -
> - /*
> - * Set the startframe odd/even properly. This is only used for
> - * periodic
> - */
> - usbc_hcchar.s.oddfrm = usb->frame_number & 1;
> -
> - /*
> - * Set the number of back to back packets allowed by this
> - * endpoint. Split transactions interpret "ec" as the number of
> - * immediate retries of failure. These retries happen too
> - * quickly, so we disable these entirely for splits
> - */
> - if (cvmx_usb_pipe_needs_split(usb, pipe))
> - usbc_hcchar.s.ec = 1;
> - else if (pipe->multi_count < 1)
> - usbc_hcchar.s.ec = 1;
> - else if (pipe->multi_count > 3)
> - usbc_hcchar.s.ec = 3;
> - else
> - usbc_hcchar.s.ec = pipe->multi_count;
> -
> - /* Set the rest of the endpoint specific settings */
> - usbc_hcchar.s.devaddr = pipe->device_addr;
> - usbc_hcchar.s.eptype = transaction->type;
> - usbc_hcchar.s.lspddev =
> - (pipe->device_speed == CVMX_USB_SPEED_LOW);
> - usbc_hcchar.s.epdir = pipe->transfer_dir;
> - usbc_hcchar.s.epnum = pipe->endpoint_num;
> - usbc_hcchar.s.mps = pipe->max_packet;
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel, usb->index),
> - usbc_hcchar.u32);
> - }
> -
> - /* Do transaction type specific fixups as needed */
> - switch (transaction->type) {
> - case CVMX_USB_TRANSFER_CONTROL:
> - cvmx_usb_start_channel_control(usb, channel, pipe);
> - break;
> - case CVMX_USB_TRANSFER_BULK:
> - case CVMX_USB_TRANSFER_INTERRUPT:
> - break;
> - case CVMX_USB_TRANSFER_ISOCHRONOUS:
> - if (!cvmx_usb_pipe_needs_split(usb, pipe)) {
> - /*
> - * ISO transactions require different PIDs depending on
> - * direction and how many packets are needed
> - */
> - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
> - if (pipe->multi_count < 2) /* Need DATA0 */
> - USB_SET_FIELD32(
> - CVMX_USBCX_HCTSIZX(channel,
> - usb->index),
> - cvmx_usbcx_hctsizx, pid, 0);
> - else /* Need MDATA */
> - USB_SET_FIELD32(
> - CVMX_USBCX_HCTSIZX(channel,
> - usb->index),
> - cvmx_usbcx_hctsizx, pid, 3);
> - }
> - }
> - break;
> - }
> - {
> - union cvmx_usbcx_hctsizx usbc_hctsiz = { .u32 =
> - cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCTSIZX(channel,
> - usb->index))
> - };
> - transaction->xfersize = usbc_hctsiz.s.xfersize;
> - transaction->pktcnt = usbc_hctsiz.s.pktcnt;
> - }
> - /* Remember when we start a split transaction */
> - if (cvmx_usb_pipe_needs_split(usb, pipe))
> - usb->active_split = transaction;
> - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
> - cvmx_usbcx_hccharx, chena, 1);
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
> - cvmx_usb_fill_tx_fifo(usb, channel);
> -}
> -
> -/**
> - * Find a pipe that is ready to be scheduled to hardware.
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @xfer_type: Transfer type
> - *
> - * Returns: Pipe or NULL if none are ready
> - */
> -static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe(struct octeon_hcd *usb,
> - enum cvmx_usb_transfer xfer_type)
> -{
> - struct list_head *list = usb->active_pipes + xfer_type;
> - u64 current_frame = usb->frame_number;
> - struct cvmx_usb_pipe *pipe;
> -
> - list_for_each_entry(pipe, list, node) {
> - struct cvmx_usb_transaction *t =
> - list_first_entry(&pipe->transactions, typeof(*t),
> - node);
> - if (!(pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED) && t &&
> - (pipe->next_tx_frame <= current_frame) &&
> - ((pipe->split_sc_frame == -1) ||
> - ((((int)current_frame - pipe->split_sc_frame) & 0x7f) <
> - 0x40)) &&
> - (!usb->active_split || (usb->active_split == t))) {
> - prefetch(t);
> - return pipe;
> - }
> - }
> - return NULL;
> -}
> -
> -static struct cvmx_usb_pipe *cvmx_usb_next_pipe(struct octeon_hcd *usb,
> - int is_sof)
> -{
> - struct cvmx_usb_pipe *pipe;
> -
> - /* Find a pipe needing service. */
> - if (is_sof) {
> - /*
> - * Only process periodic pipes on SOF interrupts. This way we
> - * are sure that the periodic data is sent in the beginning of
> - * the frame.
> - */
> - pipe = cvmx_usb_find_ready_pipe(usb,
> - CVMX_USB_TRANSFER_ISOCHRONOUS);
> - if (pipe)
> - return pipe;
> - pipe = cvmx_usb_find_ready_pipe(usb,
> - CVMX_USB_TRANSFER_INTERRUPT);
> - if (pipe)
> - return pipe;
> - }
> - pipe = cvmx_usb_find_ready_pipe(usb, CVMX_USB_TRANSFER_CONTROL);
> - if (pipe)
> - return pipe;
> - return cvmx_usb_find_ready_pipe(usb, CVMX_USB_TRANSFER_BULK);
> -}
> -
> -/**
> - * Called whenever a pipe might need to be scheduled to the
> - * hardware.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @is_sof: True if this schedule was called on a SOF interrupt.
> - */
> -static void cvmx_usb_schedule(struct octeon_hcd *usb, int is_sof)
> -{
> - int channel;
> - struct cvmx_usb_pipe *pipe;
> - int need_sof;
> - enum cvmx_usb_transfer ttype;
> -
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
> - /*
> - * Without DMA we need to be careful to not schedule something
> - * at the end of a frame and cause an overrun.
> - */
> - union cvmx_usbcx_hfnum hfnum = {
> - .u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HFNUM(usb->index))
> - };
> -
> - union cvmx_usbcx_hfir hfir = {
> - .u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HFIR(usb->index))
> - };
> -
> - if (hfnum.s.frrem < hfir.s.frint / 4)
> - goto done;
> - }
> -
> - while (usb->idle_hardware_channels) {
> - /* Find an idle channel */
> - channel = __fls(usb->idle_hardware_channels);
> - if (unlikely(channel > 7))
> - break;
> -
> - pipe = cvmx_usb_next_pipe(usb, is_sof);
> - if (!pipe)
> - break;
> -
> - cvmx_usb_start_channel(usb, channel, pipe);
> - }
> -
> -done:
> - /*
> - * Only enable SOF interrupts when we have transactions pending in the
> - * future that might need to be scheduled
> - */
> - need_sof = 0;
> - for (ttype = CVMX_USB_TRANSFER_CONTROL;
> - ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
> - list_for_each_entry(pipe, &usb->active_pipes[ttype], node) {
> - if (pipe->next_tx_frame > usb->frame_number) {
> - need_sof = 1;
> - break;
> - }
> - }
> - }
> - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index),
> - cvmx_usbcx_gintmsk, sofmsk, need_sof);
> -}
> -
> -static void octeon_usb_urb_complete_callback(struct octeon_hcd *usb,
> - enum cvmx_usb_status status,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction
> - *transaction,
> - int bytes_transferred,
> - struct urb *urb)
> -{
> - struct usb_hcd *hcd = octeon_to_hcd(usb);
> - struct device *dev = hcd->self.controller;
> -
> - if (likely(status == CVMX_USB_STATUS_OK))
> - urb->actual_length = bytes_transferred;
> - else
> - urb->actual_length = 0;
> -
> - urb->hcpriv = NULL;
> -
> - /* For Isochronous transactions we need to update the URB packet status
> - * list from data in our private copy
> - */
> - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
> - int i;
> - /*
> - * The pointer to the private list is stored in the setup_packet
> - * field.
> - */
> - struct cvmx_usb_iso_packet *iso_packet =
> - (struct cvmx_usb_iso_packet *)urb->setup_packet;
> - /* Recalculate the transfer size by adding up each packet */
> - urb->actual_length = 0;
> - for (i = 0; i < urb->number_of_packets; i++) {
> - if (iso_packet[i].status == CVMX_USB_STATUS_OK) {
> - urb->iso_frame_desc[i].status = 0;
> - urb->iso_frame_desc[i].actual_length =
> - iso_packet[i].length;
> - urb->actual_length +=
> - urb->iso_frame_desc[i].actual_length;
> - } else {
> - dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%p transaction=%p size=%d\n",
> - i, urb->number_of_packets,
> - iso_packet[i].status, pipe,
> - transaction, iso_packet[i].length);
> - urb->iso_frame_desc[i].status = -EREMOTEIO;
> - }
> - }
> - /* Free the private list now that we don't need it anymore */
> - kfree(iso_packet);
> - urb->setup_packet = NULL;
> - }
> -
> - switch (status) {
> - case CVMX_USB_STATUS_OK:
> - urb->status = 0;
> - break;
> - case CVMX_USB_STATUS_CANCEL:
> - if (urb->status == 0)
> - urb->status = -ENOENT;
> - break;
> - case CVMX_USB_STATUS_STALL:
> - dev_dbg(dev, "status=stall pipe=%p transaction=%p size=%d\n",
> - pipe, transaction, bytes_transferred);
> - urb->status = -EPIPE;
> - break;
> - case CVMX_USB_STATUS_BABBLEERR:
> - dev_dbg(dev, "status=babble pipe=%p transaction=%p size=%d\n",
> - pipe, transaction, bytes_transferred);
> - urb->status = -EPIPE;
> - break;
> - case CVMX_USB_STATUS_SHORT:
> - dev_dbg(dev, "status=short pipe=%p transaction=%p size=%d\n",
> - pipe, transaction, bytes_transferred);
> - urb->status = -EREMOTEIO;
> - break;
> - case CVMX_USB_STATUS_ERROR:
> - case CVMX_USB_STATUS_XACTERR:
> - case CVMX_USB_STATUS_DATATGLERR:
> - case CVMX_USB_STATUS_FRAMEERR:
> - dev_dbg(dev, "status=%d pipe=%p transaction=%p size=%d\n",
> - status, pipe, transaction, bytes_transferred);
> - urb->status = -EPROTO;
> - break;
> - }
> - usb_hcd_unlink_urb_from_ep(octeon_to_hcd(usb), urb);
> - spin_unlock(&usb->lock);
> - usb_hcd_giveback_urb(octeon_to_hcd(usb), urb, urb->status);
> - spin_lock(&usb->lock);
> -}
> -
> -/**
> - * Signal the completion of a transaction and free it. The
> - * transaction will be removed from the pipe transaction list.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Pipe the transaction is on
> - * @transaction:
> - * Transaction that completed
> - * @complete_code:
> - * Completion code
> - */
> -static void cvmx_usb_complete(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction,
> - enum cvmx_usb_status complete_code)
> -{
> - /* If this was a split then clear our split in progress marker */
> - if (usb->active_split == transaction)
> - usb->active_split = NULL;
> -
> - /*
> - * Isochronous transactions need extra processing as they might not be
> - * done after a single data transfer
> - */
> - if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
> - /* Update the number of bytes transferred in this ISO packet */
> - transaction->iso_packets[0].length = transaction->actual_bytes;
> - transaction->iso_packets[0].status = complete_code;
> -
> - /*
> - * If there are more ISOs pending and we succeeded, schedule the
> - * next one
> - */
> - if ((transaction->iso_number_packets > 1) &&
> - (complete_code == CVMX_USB_STATUS_OK)) {
> - /* No bytes transferred for this packet as of yet */
> - transaction->actual_bytes = 0;
> - /* One less ISO waiting to transfer */
> - transaction->iso_number_packets--;
> - /* Increment to the next location in our packet array */
> - transaction->iso_packets++;
> - transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
> - return;
> - }
> - }
> -
> - /* Remove the transaction from the pipe list */
> - list_del(&transaction->node);
> - if (list_empty(&pipe->transactions))
> - list_move_tail(&pipe->node, &usb->idle_pipes);
> - octeon_usb_urb_complete_callback(usb, complete_code, pipe,
> - transaction,
> - transaction->actual_bytes,
> - transaction->urb);
> - kfree(transaction);
> -}
> -
> -/**
> - * Submit a usb transaction to a pipe. Called for all types
> - * of transactions.
> - *
> - * @usb:
> - * @pipe: Which pipe to submit to.
> - * @type: Transaction type
> - * @buffer: User buffer for the transaction
> - * @buffer_length:
> - * User buffer's length in bytes
> - * @control_header:
> - * For control transactions, the 8 byte standard header
> - * @iso_start_frame:
> - * For ISO transactions, the start frame
> - * @iso_number_packets:
> - * For ISO, the number of packet in the transaction.
> - * @iso_packets:
> - * A description of each ISO packet
> - * @urb: URB for the callback
> - *
> - * Returns: Transaction or NULL on failure.
> - */
> -static struct cvmx_usb_transaction *cvmx_usb_submit_transaction(
> - struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - enum cvmx_usb_transfer type,
> - u64 buffer,
> - int buffer_length,
> - u64 control_header,
> - int iso_start_frame,
> - int iso_number_packets,
> - struct cvmx_usb_iso_packet *iso_packets,
> - struct urb *urb)
> -{
> - struct cvmx_usb_transaction *transaction;
> -
> - if (unlikely(pipe->transfer_type != type))
> - return NULL;
> -
> - transaction = kzalloc(sizeof(*transaction), GFP_ATOMIC);
> - if (unlikely(!transaction))
> - return NULL;
> -
> - transaction->type = type;
> - transaction->buffer = buffer;
> - transaction->buffer_length = buffer_length;
> - transaction->control_header = control_header;
> - /* FIXME: This is not used, implement it. */
> - transaction->iso_start_frame = iso_start_frame;
> - transaction->iso_number_packets = iso_number_packets;
> - transaction->iso_packets = iso_packets;
> - transaction->urb = urb;
> - if (transaction->type == CVMX_USB_TRANSFER_CONTROL)
> - transaction->stage = CVMX_USB_STAGE_SETUP;
> - else
> - transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
> -
> - if (!list_empty(&pipe->transactions)) {
> - list_add_tail(&transaction->node, &pipe->transactions);
> - } else {
> - list_add_tail(&transaction->node, &pipe->transactions);
> - list_move_tail(&pipe->node,
> - &usb->active_pipes[pipe->transfer_type]);
> -
> - /*
> - * We may need to schedule the pipe if this was the head of the
> - * pipe.
> - */
> - cvmx_usb_schedule(usb, 0);
> - }
> -
> - return transaction;
> -}
> -
> -/**
> - * Call to submit a USB Bulk transfer to a pipe.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Handle to the pipe for the transfer.
> - * @urb: URB.
> - *
> - * Returns: A submitted transaction or NULL on failure.
> - */
> -static struct cvmx_usb_transaction *cvmx_usb_submit_bulk(
> - struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct urb *urb)
> -{
> - return cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_BULK,
> - urb->transfer_dma,
> - urb->transfer_buffer_length,
> - 0, /* control_header */
> - 0, /* iso_start_frame */
> - 0, /* iso_number_packets */
> - NULL, /* iso_packets */
> - urb);
> -}
> -
> -/**
> - * Call to submit a USB Interrupt transfer to a pipe.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Handle to the pipe for the transfer.
> - * @urb: URB returned when the callback is called.
> - *
> - * Returns: A submitted transaction or NULL on failure.
> - */
> -static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt(
> - struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct urb *urb)
> -{
> - return cvmx_usb_submit_transaction(usb, pipe,
> - CVMX_USB_TRANSFER_INTERRUPT,
> - urb->transfer_dma,
> - urb->transfer_buffer_length,
> - 0, /* control_header */
> - 0, /* iso_start_frame */
> - 0, /* iso_number_packets */
> - NULL, /* iso_packets */
> - urb);
> -}
> -
> -/**
> - * Call to submit a USB Control transfer to a pipe.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Handle to the pipe for the transfer.
> - * @urb: URB.
> - *
> - * Returns: A submitted transaction or NULL on failure.
> - */
> -static struct cvmx_usb_transaction *cvmx_usb_submit_control(
> - struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct urb *urb)
> -{
> - int buffer_length = urb->transfer_buffer_length;
> - u64 control_header = urb->setup_dma;
> - struct usb_ctrlrequest *header = cvmx_phys_to_ptr(control_header);
> -
> - if ((header->bRequestType & USB_DIR_IN) == 0)
> - buffer_length = le16_to_cpu(header->wLength);
> -
> - return cvmx_usb_submit_transaction(usb, pipe,
> - CVMX_USB_TRANSFER_CONTROL,
> - urb->transfer_dma, buffer_length,
> - control_header,
> - 0, /* iso_start_frame */
> - 0, /* iso_number_packets */
> - NULL, /* iso_packets */
> - urb);
> -}
> -
> -/**
> - * Call to submit a USB Isochronous transfer to a pipe.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Handle to the pipe for the transfer.
> - * @urb: URB returned when the callback is called.
> - *
> - * Returns: A submitted transaction or NULL on failure.
> - */
> -static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous(
> - struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct urb *urb)
> -{
> - struct cvmx_usb_iso_packet *packets;
> -
> - packets = (struct cvmx_usb_iso_packet *)urb->setup_packet;
> - return cvmx_usb_submit_transaction(usb, pipe,
> - CVMX_USB_TRANSFER_ISOCHRONOUS,
> - urb->transfer_dma,
> - urb->transfer_buffer_length,
> - 0, /* control_header */
> - urb->start_frame,
> - urb->number_of_packets,
> - packets, urb);
> -}
> -
> -/**
> - * Cancel one outstanding request in a pipe. Canceling a request
> - * can fail if the transaction has already completed before cancel
> - * is called. Even after a successful cancel call, it may take
> - * a frame or two for the cvmx_usb_poll() function to call the
> - * associated callback.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Pipe to cancel requests in.
> - * @transaction: Transaction to cancel, returned by the submit function.
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_cancel(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction)
> -{
> - /*
> - * If the transaction is the HEAD of the queue and scheduled. We need to
> - * treat it special
> - */
> - if (list_first_entry(&pipe->transactions, typeof(*transaction), node) ==
> - transaction && (pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
> - union cvmx_usbcx_hccharx usbc_hcchar;
> -
> - usb->pipe_for_channel[pipe->channel] = NULL;
> - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED;
> -
> - CVMX_SYNCW;
> -
> - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
> - /*
> - * If the channel isn't enabled then the transaction already
> - * completed.
> - */
> - if (usbc_hcchar.s.chena) {
> - usbc_hcchar.s.chdis = 1;
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCCHARX(pipe->channel,
> - usb->index),
> - usbc_hcchar.u32);
> - }
> - }
> - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_CANCEL);
> - return 0;
> -}
> -
> -/**
> - * Cancel all outstanding requests in a pipe. Logically all this
> - * does is call cvmx_usb_cancel() in a loop.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Pipe to cancel requests in.
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_cancel_all(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe)
> -{
> - struct cvmx_usb_transaction *transaction, *next;
> -
> - /* Simply loop through and attempt to cancel each transaction */
> - list_for_each_entry_safe(transaction, next, &pipe->transactions, node) {
> - int result = cvmx_usb_cancel(usb, pipe, transaction);
> -
> - if (unlikely(result != 0))
> - return result;
> - }
> - return 0;
> -}
> -
> -/**
> - * Close a pipe created with cvmx_usb_open_pipe().
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - * @pipe: Pipe to close.
> - *
> - * Returns: 0 or a negative error code. EBUSY is returned if the pipe has
> - * outstanding transfers.
> - */
> -static int cvmx_usb_close_pipe(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe)
> -{
> - /* Fail if the pipe has pending transactions */
> - if (!list_empty(&pipe->transactions))
> - return -EBUSY;
> -
> - list_del(&pipe->node);
> - kfree(pipe);
> -
> - return 0;
> -}
> -
> -/**
> - * Get the current USB protocol level frame number. The frame
> - * number is always in the range of 0-0x7ff.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - *
> - * Returns: USB frame number
> - */
> -static int cvmx_usb_get_frame_number(struct octeon_hcd *usb)
> -{
> - union cvmx_usbcx_hfnum usbc_hfnum;
> -
> - usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
> -
> - return usbc_hfnum.s.frnum;
> -}
> -
> -static void cvmx_usb_transfer_control(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction,
> - union cvmx_usbcx_hccharx usbc_hcchar,
> - int buffer_space_left,
> - int bytes_in_last_packet)
> -{
> - switch (transaction->stage) {
> - case CVMX_USB_STAGE_NON_CONTROL:
> - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
> - /* This should be impossible */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_ERROR);
> - break;
> - case CVMX_USB_STAGE_SETUP:
> - pipe->pid_toggle = 1;
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - transaction->stage =
> - CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
> - } else {
> - struct usb_ctrlrequest *header =
> - cvmx_phys_to_ptr(transaction->control_header);
> - if (header->wLength)
> - transaction->stage = CVMX_USB_STAGE_DATA;
> - else
> - transaction->stage = CVMX_USB_STAGE_STATUS;
> - }
> - break;
> - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
> - {
> - struct usb_ctrlrequest *header =
> - cvmx_phys_to_ptr(transaction->control_header);
> - if (header->wLength)
> - transaction->stage = CVMX_USB_STAGE_DATA;
> - else
> - transaction->stage = CVMX_USB_STAGE_STATUS;
> - }
> - break;
> - case CVMX_USB_STAGE_DATA:
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
> - /*
> - * For setup OUT data that are splits,
> - * the hardware doesn't appear to count
> - * transferred data. Here we manually
> - * update the data transferred
> - */
> - if (!usbc_hcchar.s.epdir) {
> - if (buffer_space_left < pipe->max_packet)
> - transaction->actual_bytes +=
> - buffer_space_left;
> - else
> - transaction->actual_bytes +=
> - pipe->max_packet;
> - }
> - } else if ((buffer_space_left == 0) ||
> - (bytes_in_last_packet < pipe->max_packet)) {
> - pipe->pid_toggle = 1;
> - transaction->stage = CVMX_USB_STAGE_STATUS;
> - }
> - break;
> - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
> - if ((buffer_space_left == 0) ||
> - (bytes_in_last_packet < pipe->max_packet)) {
> - pipe->pid_toggle = 1;
> - transaction->stage = CVMX_USB_STAGE_STATUS;
> - } else {
> - transaction->stage = CVMX_USB_STAGE_DATA;
> - }
> - break;
> - case CVMX_USB_STAGE_STATUS:
> - if (cvmx_usb_pipe_needs_split(usb, pipe))
> - transaction->stage =
> - CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
> - else
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - break;
> - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
> - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK);
> - break;
> - }
> -}
> -
> -static void cvmx_usb_transfer_bulk(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction,
> - union cvmx_usbcx_hcintx usbc_hcint,
> - int buffer_space_left,
> - int bytes_in_last_packet)
> -{
> - /*
> - * The only time a bulk transfer isn't complete when it finishes with
> - * an ACK is during a split transaction. For splits we need to continue
> - * the transfer if more data is needed.
> - */
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL)
> - transaction->stage =
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
> - else if (buffer_space_left &&
> - (bytes_in_last_packet == pipe->max_packet))
> - transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
> - else
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - } else {
> - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
> - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
> - (usbc_hcint.s.nak))
> - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING;
> - if (!buffer_space_left ||
> - (bytes_in_last_packet < pipe->max_packet))
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - }
> -}
> -
> -static void cvmx_usb_transfer_intr(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction,
> - int buffer_space_left,
> - int bytes_in_last_packet)
> -{
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) {
> - transaction->stage =
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
> - } else if (buffer_space_left &&
> - (bytes_in_last_packet == pipe->max_packet)) {
> - transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
> - } else {
> - pipe->next_tx_frame += pipe->interval;
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - }
> - } else if (!buffer_space_left ||
> - (bytes_in_last_packet < pipe->max_packet)) {
> - pipe->next_tx_frame += pipe->interval;
> - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK);
> - }
> -}
> -
> -static void cvmx_usb_transfer_isoc(struct octeon_hcd *usb,
> - struct cvmx_usb_pipe *pipe,
> - struct cvmx_usb_transaction *transaction,
> - int buffer_space_left,
> - int bytes_in_last_packet,
> - int bytes_this_transfer)
> -{
> - if (cvmx_usb_pipe_needs_split(usb, pipe)) {
> - /*
> - * ISOCHRONOUS OUT splits don't require a complete split stage.
> - * Instead they use a sequence of begin OUT splits to transfer
> - * the data 188 bytes at a time. Once the transfer is complete,
> - * the pipe sleeps until the next schedule interval.
> - */
> - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
> - /*
> - * If no space left or this wasn't a max size packet
> - * then this transfer is complete. Otherwise start it
> - * again to send the next 188 bytes
> - */
> - if (!buffer_space_left || (bytes_this_transfer < 188)) {
> - pipe->next_tx_frame += pipe->interval;
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - }
> - return;
> - }
> - if (transaction->stage ==
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) {
> - /*
> - * We are in the incoming data phase. Keep getting data
> - * until we run out of space or get a small packet
> - */
> - if ((buffer_space_left == 0) ||
> - (bytes_in_last_packet < pipe->max_packet)) {
> - pipe->next_tx_frame += pipe->interval;
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_OK);
> - }
> - } else {
> - transaction->stage =
> - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
> - }
> - } else {
> - pipe->next_tx_frame += pipe->interval;
> - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK);
> - }
> -}
> -
> -/**
> - * Poll a channel for status
> - *
> - * @usb: USB device
> - * @channel: Channel to poll
> - *
> - * Returns: Zero on success
> - */
> -static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel)
> -{
> - struct usb_hcd *hcd = octeon_to_hcd(usb);
> - struct device *dev = hcd->self.controller;
> - union cvmx_usbcx_hcintx usbc_hcint;
> - union cvmx_usbcx_hctsizx usbc_hctsiz;
> - union cvmx_usbcx_hccharx usbc_hcchar;
> - struct cvmx_usb_pipe *pipe;
> - struct cvmx_usb_transaction *transaction;
> - int bytes_this_transfer;
> - int bytes_in_last_packet;
> - int packets_processed;
> - int buffer_space_left;
> -
> - /* Read the interrupt status bits for the channel */
> - usbc_hcint.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCINTX(channel, usb->index));
> -
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
> - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel, usb->index));
> -
> - if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
> - /*
> - * There seems to be a bug in CN31XX which can cause
> - * interrupt IN transfers to get stuck until we do a
> - * write of HCCHARX without changing things
> - */
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel,
> - usb->index),
> - usbc_hcchar.u32);
> - return 0;
> - }
> -
> - /*
> - * In non DMA mode the channels don't halt themselves. We need
> - * to manually disable channels that are left running
> - */
> - if (!usbc_hcint.s.chhltd) {
> - if (usbc_hcchar.s.chena) {
> - union cvmx_usbcx_hcintmskx hcintmsk;
> - /* Disable all interrupts except CHHLTD */
> - hcintmsk.u32 = 0;
> - hcintmsk.s.chhltdmsk = 1;
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCINTMSKX(channel, usb->index),
> - hcintmsk.u32);
> - usbc_hcchar.s.chdis = 1;
> - cvmx_usb_write_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel, usb->index),
> - usbc_hcchar.u32);
> - return 0;
> - } else if (usbc_hcint.s.xfercompl) {
> - /*
> - * Successful IN/OUT with transfer complete.
> - * Channel halt isn't needed.
> - */
> - } else {
> - dev_err(dev, "USB%d: Channel %d interrupt without halt\n",
> - usb->index, channel);
> - return 0;
> - }
> - }
> - } else {
> - /*
> - * There is are no interrupts that we need to process when the
> - * channel is still running
> - */
> - if (!usbc_hcint.s.chhltd)
> - return 0;
> - }
> -
> - /* Disable the channel interrupts now that it is done */
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
> - usb->idle_hardware_channels |= (1 << channel);
> -
> - /* Make sure this channel is tied to a valid pipe */
> - pipe = usb->pipe_for_channel[channel];
> - prefetch(pipe);
> - if (!pipe)
> - return 0;
> - transaction = list_first_entry(&pipe->transactions,
> - typeof(*transaction),
> - node);
> - prefetch(transaction);
> -
> - /*
> - * Disconnect this pipe from the HW channel. Later the schedule
> - * function will figure out which pipe needs to go
> - */
> - usb->pipe_for_channel[channel] = NULL;
> - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED;
> -
> - /*
> - * Read the channel config info so we can figure out how much data
> - * transferred
> - */
> - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCCHARX(channel, usb->index));
> - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HCTSIZX(channel, usb->index));
> -
> - /*
> - * Calculating the number of bytes successfully transferred is dependent
> - * on the transfer direction
> - */
> - packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt;
> - if (usbc_hcchar.s.epdir) {
> - /*
> - * IN transactions are easy. For every byte received the
> - * hardware decrements xfersize. All we need to do is subtract
> - * the current value of xfersize from its starting value and we
> - * know how many bytes were written to the buffer
> - */
> - bytes_this_transfer = transaction->xfersize -
> - usbc_hctsiz.s.xfersize;
> - } else {
> - /*
> - * OUT transaction don't decrement xfersize. Instead pktcnt is
> - * decremented on every successful packet send. The hardware
> - * does this when it receives an ACK, or NYET. If it doesn't
> - * receive one of these responses pktcnt doesn't change
> - */
> - bytes_this_transfer = packets_processed * usbc_hcchar.s.mps;
> - /*
> - * The last packet may not be a full transfer if we didn't have
> - * enough data
> - */
> - if (bytes_this_transfer > transaction->xfersize)
> - bytes_this_transfer = transaction->xfersize;
> - }
> - /* Figure out how many bytes were in the last packet of the transfer */
> - if (packets_processed)
> - bytes_in_last_packet = bytes_this_transfer -
> - (packets_processed - 1) * usbc_hcchar.s.mps;
> - else
> - bytes_in_last_packet = bytes_this_transfer;
> -
> - /*
> - * As a special case, setup transactions output the setup header, not
> - * the user's data. For this reason we don't count setup data as bytes
> - * transferred
> - */
> - if ((transaction->stage == CVMX_USB_STAGE_SETUP) ||
> - (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE))
> - bytes_this_transfer = 0;
> -
> - /*
> - * Add the bytes transferred to the running total. It is important that
> - * bytes_this_transfer doesn't count any data that needs to be
> - * retransmitted
> - */
> - transaction->actual_bytes += bytes_this_transfer;
> - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
> - buffer_space_left = transaction->iso_packets[0].length -
> - transaction->actual_bytes;
> - else
> - buffer_space_left = transaction->buffer_length -
> - transaction->actual_bytes;
> -
> - /*
> - * We need to remember the PID toggle state for the next transaction.
> - * The hardware already updated it for the next transaction
> - */
> - pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0);
> -
> - /*
> - * For high speed bulk out, assume the next transaction will need to do
> - * a ping before proceeding. If this isn't true the ACK processing below
> - * will clear this flag
> - */
> - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
> - (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
> - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
> - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING;
> -
> - if (WARN_ON_ONCE(bytes_this_transfer < 0)) {
> - /*
> - * In some rare cases the DMA engine seems to get stuck and
> - * keeps substracting same byte count over and over again. In
> - * such case we just need to fail every transaction.
> - */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_ERROR);
> - return 0;
> - }
> -
> - if (usbc_hcint.s.stall) {
> - /*
> - * STALL as a response means this transaction cannot be
> - * completed because the device can't process transactions. Tell
> - * the user. Any data that was transferred will be counted on
> - * the actual bytes transferred
> - */
> - pipe->pid_toggle = 0;
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_STALL);
> - } else if (usbc_hcint.s.xacterr) {
> - /*
> - * XactErr as a response means the device signaled
> - * something wrong with the transfer. For example, PID
> - * toggle errors cause these.
> - */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_XACTERR);
> - } else if (usbc_hcint.s.bblerr) {
> - /* Babble Error (BblErr) */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_BABBLEERR);
> - } else if (usbc_hcint.s.datatglerr) {
> - /* Data toggle error */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_DATATGLERR);
> - } else if (usbc_hcint.s.nyet) {
> - /*
> - * NYET as a response is only allowed in three cases: as a
> - * response to a ping, as a response to a split transaction, and
> - * as a response to a bulk out. The ping case is handled by
> - * hardware, so we only have splits and bulk out
> - */
> - if (!cvmx_usb_pipe_needs_split(usb, pipe)) {
> - transaction->retries = 0;
> - /*
> - * If there is more data to go then we need to try
> - * again. Otherwise this transaction is complete
> - */
> - if ((buffer_space_left == 0) ||
> - (bytes_in_last_packet < pipe->max_packet))
> - cvmx_usb_complete(usb, pipe,
> - transaction,
> - CVMX_USB_STATUS_OK);
> - } else {
> - /*
> - * Split transactions retry the split complete 4 times
> - * then rewind to the start split and do the entire
> - * transactions again
> - */
> - transaction->retries++;
> - if ((transaction->retries & 0x3) == 0) {
> - /*
> - * Rewind to the beginning of the transaction by
> - * anding off the split complete bit
> - */
> - transaction->stage &= ~1;
> - pipe->split_sc_frame = -1;
> - }
> - }
> - } else if (usbc_hcint.s.ack) {
> - transaction->retries = 0;
> - /*
> - * The ACK bit can only be checked after the other error bits.
> - * This is because a multi packet transfer may succeed in a
> - * number of packets and then get a different response on the
> - * last packet. In this case both ACK and the last response bit
> - * will be set. If none of the other response bits is set, then
> - * the last packet must have been an ACK
> - *
> - * Since we got an ACK, we know we don't need to do a ping on
> - * this pipe
> - */
> - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_NEED_PING;
> -
> - switch (transaction->type) {
> - case CVMX_USB_TRANSFER_CONTROL:
> - cvmx_usb_transfer_control(usb, pipe, transaction,
> - usbc_hcchar,
> - buffer_space_left,
> - bytes_in_last_packet);
> - break;
> - case CVMX_USB_TRANSFER_BULK:
> - cvmx_usb_transfer_bulk(usb, pipe, transaction,
> - usbc_hcint, buffer_space_left,
> - bytes_in_last_packet);
> - break;
> - case CVMX_USB_TRANSFER_INTERRUPT:
> - cvmx_usb_transfer_intr(usb, pipe, transaction,
> - buffer_space_left,
> - bytes_in_last_packet);
> - break;
> - case CVMX_USB_TRANSFER_ISOCHRONOUS:
> - cvmx_usb_transfer_isoc(usb, pipe, transaction,
> - buffer_space_left,
> - bytes_in_last_packet,
> - bytes_this_transfer);
> - break;
> - }
> - } else if (usbc_hcint.s.nak) {
> - /*
> - * If this was a split then clear our split in progress marker.
> - */
> - if (usb->active_split == transaction)
> - usb->active_split = NULL;
> - /*
> - * NAK as a response means the device couldn't accept the
> - * transaction, but it should be retried in the future. Rewind
> - * to the beginning of the transaction by anding off the split
> - * complete bit. Retry in the next interval
> - */
> - transaction->retries = 0;
> - transaction->stage &= ~1;
> - pipe->next_tx_frame += pipe->interval;
> - if (pipe->next_tx_frame < usb->frame_number)
> - pipe->next_tx_frame = usb->frame_number +
> - pipe->interval -
> - (usb->frame_number - pipe->next_tx_frame) %
> - pipe->interval;
> - } else {
> - struct cvmx_usb_port_status port;
> -
> - port = cvmx_usb_get_status(usb);
> - if (port.port_enabled) {
> - /* We'll retry the exact same transaction again */
> - transaction->retries++;
> - } else {
> - /*
> - * We get channel halted interrupts with no result bits
> - * sets when the cable is unplugged
> - */
> - cvmx_usb_complete(usb, pipe, transaction,
> - CVMX_USB_STATUS_ERROR);
> - }
> - }
> - return 0;
> -}
> -
> -static void octeon_usb_port_callback(struct octeon_hcd *usb)
> -{
> - spin_unlock(&usb->lock);
> - usb_hcd_poll_rh_status(octeon_to_hcd(usb));
> - spin_lock(&usb->lock);
> -}
> -
> -/**
> - * Poll the USB block for status and call all needed callback
> - * handlers. This function is meant to be called in the interrupt
> - * handler for the USB controller. It can also be called
> - * periodically in a loop for non-interrupt based operation.
> - *
> - * @usb: USB device state populated by cvmx_usb_initialize().
> - *
> - * Returns: 0 or a negative error code.
> - */
> -static int cvmx_usb_poll(struct octeon_hcd *usb)
> -{
> - union cvmx_usbcx_hfnum usbc_hfnum;
> - union cvmx_usbcx_gintsts usbc_gintsts;
> -
> - prefetch_range(usb, sizeof(*usb));
> -
> - /* Update the frame counter */
> - usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
> - if ((usb->frame_number & 0x3fff) > usbc_hfnum.s.frnum)
> - usb->frame_number += 0x4000;
> - usb->frame_number &= ~0x3fffull;
> - usb->frame_number |= usbc_hfnum.s.frnum;
> -
> - /* Read the pending interrupts */
> - usbc_gintsts.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_GINTSTS(usb->index));
> -
> - /* Clear the interrupts now that we know about them */
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index),
> - usbc_gintsts.u32);
> -
> - if (usbc_gintsts.s.rxflvl) {
> - /*
> - * RxFIFO Non-Empty (RxFLvl)
> - * Indicates that there is at least one packet pending to be
> - * read from the RxFIFO.
> - *
> - * In DMA mode this is handled by hardware
> - */
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
> - cvmx_usb_poll_rx_fifo(usb);
> - }
> - if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
> - /* Fill the Tx FIFOs when not in DMA mode */
> - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
> - cvmx_usb_poll_tx_fifo(usb);
> - }
> - if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
> - union cvmx_usbcx_hprt usbc_hprt;
> - /*
> - * Disconnect Detected Interrupt (DisconnInt)
> - * Asserted when a device disconnect is detected.
> - *
> - * Host Port Interrupt (PrtInt)
> - * The core sets this bit to indicate a change in port status of
> - * one of the O2P USB core ports in Host mode. The application
> - * must read the Host Port Control and Status (HPRT) register to
> - * determine the exact event that caused this interrupt. The
> - * application must clear the appropriate status bit in the Host
> - * Port Control and Status register to clear this bit.
> - *
> - * Call the user's port callback
> - */
> - octeon_usb_port_callback(usb);
> - /* Clear the port change bits */
> - usbc_hprt.u32 =
> - cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
> - usbc_hprt.s.prtena = 0;
> - cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index),
> - usbc_hprt.u32);
> - }
> - if (usbc_gintsts.s.hchint) {
> - /*
> - * Host Channels Interrupt (HChInt)
> - * The core sets this bit to indicate that an interrupt is
> - * pending on one of the channels of the core (in Host mode).
> - * The application must read the Host All Channels Interrupt
> - * (HAINT) register to determine the exact number of the channel
> - * on which the interrupt occurred, and then read the
> - * corresponding Host Channel-n Interrupt (HCINTn) register to
> - * determine the exact cause of the interrupt. The application
> - * must clear the appropriate status bit in the HCINTn register
> - * to clear this bit.
> - */
> - union cvmx_usbcx_haint usbc_haint;
> -
> - usbc_haint.u32 = cvmx_usb_read_csr32(usb,
> - CVMX_USBCX_HAINT(usb->index));
> - while (usbc_haint.u32) {
> - int channel;
> -
> - channel = __fls(usbc_haint.u32);
> - cvmx_usb_poll_channel(usb, channel);
> - usbc_haint.u32 ^= 1 << channel;
> - }
> - }
> -
> - cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
> -
> - return 0;
> -}
> -
> -/* convert between an HCD pointer and the corresponding struct octeon_hcd */
> -static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd)
> -{
> - return (struct octeon_hcd *)(hcd->hcd_priv);
> -}
> -
> -static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - unsigned long flags;
> -
> - spin_lock_irqsave(&usb->lock, flags);
> - cvmx_usb_poll(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - return IRQ_HANDLED;
> -}
> -
> -static int octeon_usb_start(struct usb_hcd *hcd)
> -{
> - hcd->state = HC_STATE_RUNNING;
> - return 0;
> -}
> -
> -static void octeon_usb_stop(struct usb_hcd *hcd)
> -{
> - hcd->state = HC_STATE_HALT;
> -}
> -
> -static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> -
> - return cvmx_usb_get_frame_number(usb);
> -}
> -
> -static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
> - struct urb *urb,
> - gfp_t mem_flags)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - struct device *dev = hcd->self.controller;
> - struct cvmx_usb_transaction *transaction = NULL;
> - struct cvmx_usb_pipe *pipe;
> - unsigned long flags;
> - struct cvmx_usb_iso_packet *iso_packet;
> - struct usb_host_endpoint *ep = urb->ep;
> - int rc;
> -
> - urb->status = 0;
> - spin_lock_irqsave(&usb->lock, flags);
> -
> - rc = usb_hcd_link_urb_to_ep(hcd, urb);
> - if (rc) {
> - spin_unlock_irqrestore(&usb->lock, flags);
> - return rc;
> - }
> -
> - if (!ep->hcpriv) {
> - enum cvmx_usb_transfer transfer_type;
> - enum cvmx_usb_speed speed;
> - int split_device = 0;
> - int split_port = 0;
> -
> - switch (usb_pipetype(urb->pipe)) {
> - case PIPE_ISOCHRONOUS:
> - transfer_type = CVMX_USB_TRANSFER_ISOCHRONOUS;
> - break;
> - case PIPE_INTERRUPT:
> - transfer_type = CVMX_USB_TRANSFER_INTERRUPT;
> - break;
> - case PIPE_CONTROL:
> - transfer_type = CVMX_USB_TRANSFER_CONTROL;
> - break;
> - default:
> - transfer_type = CVMX_USB_TRANSFER_BULK;
> - break;
> - }
> - switch (urb->dev->speed) {
> - case USB_SPEED_LOW:
> - speed = CVMX_USB_SPEED_LOW;
> - break;
> - case USB_SPEED_FULL:
> - speed = CVMX_USB_SPEED_FULL;
> - break;
> - default:
> - speed = CVMX_USB_SPEED_HIGH;
> - break;
> - }
> - /*
> - * For slow devices on high speed ports we need to find the hub
> - * that does the speed translation so we know where to send the
> - * split transactions.
> - */
> - if (speed != CVMX_USB_SPEED_HIGH) {
> - /*
> - * Start at this device and work our way up the usb
> - * tree.
> - */
> - struct usb_device *dev = urb->dev;
> -
> - while (dev->parent) {
> - /*
> - * If our parent is high speed then he'll
> - * receive the splits.
> - */
> - if (dev->parent->speed == USB_SPEED_HIGH) {
> - split_device = dev->parent->devnum;
> - split_port = dev->portnum;
> - break;
> - }
> - /*
> - * Move up the tree one level. If we make it all
> - * the way up the tree, then the port must not
> - * be in high speed mode and we don't need a
> - * split.
> - */
> - dev = dev->parent;
> - }
> - }
> - pipe = cvmx_usb_open_pipe(usb, usb_pipedevice(urb->pipe),
> - usb_pipeendpoint(urb->pipe), speed,
> - le16_to_cpu(ep->desc.wMaxPacketSize)
> - & 0x7ff,
> - transfer_type,
> - usb_pipein(urb->pipe) ?
> - CVMX_USB_DIRECTION_IN :
> - CVMX_USB_DIRECTION_OUT,
> - urb->interval,
> - (le16_to_cpu(ep->desc.wMaxPacketSize)
> - >> 11) & 0x3,
> - split_device, split_port);
> - if (!pipe) {
> - usb_hcd_unlink_urb_from_ep(hcd, urb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - dev_dbg(dev, "Failed to create pipe\n");
> - return -ENOMEM;
> - }
> - ep->hcpriv = pipe;
> - } else {
> - pipe = ep->hcpriv;
> - }
> -
> - switch (usb_pipetype(urb->pipe)) {
> - case PIPE_ISOCHRONOUS:
> - dev_dbg(dev, "Submit isochronous to %d.%d\n",
> - usb_pipedevice(urb->pipe),
> - usb_pipeendpoint(urb->pipe));
> - /*
> - * Allocate a structure to use for our private list of
> - * isochronous packets.
> - */
> - iso_packet = kmalloc_array(urb->number_of_packets,
> - sizeof(struct cvmx_usb_iso_packet),
> - GFP_ATOMIC);
> - if (iso_packet) {
> - int i;
> - /* Fill the list with the data from the URB */
> - for (i = 0; i < urb->number_of_packets; i++) {
> - iso_packet[i].offset =
> - urb->iso_frame_desc[i].offset;
> - iso_packet[i].length =
> - urb->iso_frame_desc[i].length;
> - iso_packet[i].status = CVMX_USB_STATUS_ERROR;
> - }
> - /*
> - * Store a pointer to the list in the URB setup_packet
> - * field. We know this currently isn't being used and
> - * this saves us a bunch of logic.
> - */
> - urb->setup_packet = (char *)iso_packet;
> - transaction = cvmx_usb_submit_isochronous(usb,
> - pipe, urb);
> - /*
> - * If submit failed we need to free our private packet
> - * list.
> - */
> - if (!transaction) {
> - urb->setup_packet = NULL;
> - kfree(iso_packet);
> - }
> - }
> - break;
> - case PIPE_INTERRUPT:
> - dev_dbg(dev, "Submit interrupt to %d.%d\n",
> - usb_pipedevice(urb->pipe),
> - usb_pipeendpoint(urb->pipe));
> - transaction = cvmx_usb_submit_interrupt(usb, pipe, urb);
> - break;
> - case PIPE_CONTROL:
> - dev_dbg(dev, "Submit control to %d.%d\n",
> - usb_pipedevice(urb->pipe),
> - usb_pipeendpoint(urb->pipe));
> - transaction = cvmx_usb_submit_control(usb, pipe, urb);
> - break;
> - case PIPE_BULK:
> - dev_dbg(dev, "Submit bulk to %d.%d\n",
> - usb_pipedevice(urb->pipe),
> - usb_pipeendpoint(urb->pipe));
> - transaction = cvmx_usb_submit_bulk(usb, pipe, urb);
> - break;
> - }
> - if (!transaction) {
> - usb_hcd_unlink_urb_from_ep(hcd, urb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - dev_dbg(dev, "Failed to submit\n");
> - return -ENOMEM;
> - }
> - urb->hcpriv = transaction;
> - spin_unlock_irqrestore(&usb->lock, flags);
> - return 0;
> -}
> -
> -static int octeon_usb_urb_dequeue(struct usb_hcd *hcd,
> - struct urb *urb,
> - int status)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - unsigned long flags;
> - int rc;
> -
> - if (!urb->dev)
> - return -EINVAL;
> -
> - spin_lock_irqsave(&usb->lock, flags);
> -
> - rc = usb_hcd_check_unlink_urb(hcd, urb, status);
> - if (rc)
> - goto out;
> -
> - urb->status = status;
> - cvmx_usb_cancel(usb, urb->ep->hcpriv, urb->hcpriv);
> -
> -out:
> - spin_unlock_irqrestore(&usb->lock, flags);
> -
> - return rc;
> -}
> -
> -static void octeon_usb_endpoint_disable(struct usb_hcd *hcd,
> - struct usb_host_endpoint *ep)
> -{
> - struct device *dev = hcd->self.controller;
> -
> - if (ep->hcpriv) {
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - struct cvmx_usb_pipe *pipe = ep->hcpriv;
> - unsigned long flags;
> -
> - spin_lock_irqsave(&usb->lock, flags);
> - cvmx_usb_cancel_all(usb, pipe);
> - if (cvmx_usb_close_pipe(usb, pipe))
> - dev_dbg(dev, "Closing pipe %p failed\n", pipe);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - ep->hcpriv = NULL;
> - }
> -}
> -
> -static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - struct cvmx_usb_port_status port_status;
> - unsigned long flags;
> -
> - spin_lock_irqsave(&usb->lock, flags);
> - port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - buf[0] = port_status.connect_change << 1;
> -
> - return buf[0] != 0;
> -}
> -
> -static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
> - u16 wIndex, char *buf, u16 wLength)
> -{
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - struct device *dev = hcd->self.controller;
> - struct cvmx_usb_port_status usb_port_status;
> - int port_status;
> - struct usb_hub_descriptor *desc;
> - unsigned long flags;
> -
> - switch (typeReq) {
> - case ClearHubFeature:
> - dev_dbg(dev, "ClearHubFeature\n");
> - switch (wValue) {
> - case C_HUB_LOCAL_POWER:
> - case C_HUB_OVER_CURRENT:
> - /* Nothing required here */
> - break;
> - default:
> - return -EINVAL;
> - }
> - break;
> - case ClearPortFeature:
> - dev_dbg(dev, "ClearPortFeature\n");
> - if (wIndex != 1) {
> - dev_dbg(dev, " INVALID\n");
> - return -EINVAL;
> - }
> -
> - switch (wValue) {
> - case USB_PORT_FEAT_ENABLE:
> - dev_dbg(dev, " ENABLE\n");
> - spin_lock_irqsave(&usb->lock, flags);
> - cvmx_usb_disable(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - break;
> - case USB_PORT_FEAT_SUSPEND:
> - dev_dbg(dev, " SUSPEND\n");
> - /* Not supported on Octeon */
> - break;
> - case USB_PORT_FEAT_POWER:
> - dev_dbg(dev, " POWER\n");
> - /* Not supported on Octeon */
> - break;
> - case USB_PORT_FEAT_INDICATOR:
> - dev_dbg(dev, " INDICATOR\n");
> - /* Port inidicator not supported */
> - break;
> - case USB_PORT_FEAT_C_CONNECTION:
> - dev_dbg(dev, " C_CONNECTION\n");
> - /* Clears drivers internal connect status change flag */
> - spin_lock_irqsave(&usb->lock, flags);
> - usb->port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - break;
> - case USB_PORT_FEAT_C_RESET:
> - dev_dbg(dev, " C_RESET\n");
> - /*
> - * Clears the driver's internal Port Reset Change flag.
> - */
> - spin_lock_irqsave(&usb->lock, flags);
> - usb->port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - break;
> - case USB_PORT_FEAT_C_ENABLE:
> - dev_dbg(dev, " C_ENABLE\n");
> - /*
> - * Clears the driver's internal Port Enable/Disable
> - * Change flag.
> - */
> - spin_lock_irqsave(&usb->lock, flags);
> - usb->port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - break;
> - case USB_PORT_FEAT_C_SUSPEND:
> - dev_dbg(dev, " C_SUSPEND\n");
> - /*
> - * Clears the driver's internal Port Suspend Change
> - * flag, which is set when resume signaling on the host
> - * port is complete.
> - */
> - break;
> - case USB_PORT_FEAT_C_OVER_CURRENT:
> - dev_dbg(dev, " C_OVER_CURRENT\n");
> - /* Clears the driver's overcurrent Change flag */
> - spin_lock_irqsave(&usb->lock, flags);
> - usb->port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - break;
> - default:
> - dev_dbg(dev, " UNKNOWN\n");
> - return -EINVAL;
> - }
> - break;
> - case GetHubDescriptor:
> - dev_dbg(dev, "GetHubDescriptor\n");
> - desc = (struct usb_hub_descriptor *)buf;
> - desc->bDescLength = 9;
> - desc->bDescriptorType = 0x29;
> - desc->bNbrPorts = 1;
> - desc->wHubCharacteristics = cpu_to_le16(0x08);
> - desc->bPwrOn2PwrGood = 1;
> - desc->bHubContrCurrent = 0;
> - desc->u.hs.DeviceRemovable[0] = 0;
> - desc->u.hs.DeviceRemovable[1] = 0xff;
> - break;
> - case GetHubStatus:
> - dev_dbg(dev, "GetHubStatus\n");
> - *(__le32 *)buf = 0;
> - break;
> - case GetPortStatus:
> - dev_dbg(dev, "GetPortStatus\n");
> - if (wIndex != 1) {
> - dev_dbg(dev, " INVALID\n");
> - return -EINVAL;
> - }
> -
> - spin_lock_irqsave(&usb->lock, flags);
> - usb_port_status = cvmx_usb_get_status(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - port_status = 0;
> -
> - if (usb_port_status.connect_change) {
> - port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
> - dev_dbg(dev, " C_CONNECTION\n");
> - }
> -
> - if (usb_port_status.port_enabled) {
> - port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
> - dev_dbg(dev, " C_ENABLE\n");
> - }
> -
> - if (usb_port_status.connected) {
> - port_status |= (1 << USB_PORT_FEAT_CONNECTION);
> - dev_dbg(dev, " CONNECTION\n");
> - }
> -
> - if (usb_port_status.port_enabled) {
> - port_status |= (1 << USB_PORT_FEAT_ENABLE);
> - dev_dbg(dev, " ENABLE\n");
> - }
> -
> - if (usb_port_status.port_over_current) {
> - port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
> - dev_dbg(dev, " OVER_CURRENT\n");
> - }
> -
> - if (usb_port_status.port_powered) {
> - port_status |= (1 << USB_PORT_FEAT_POWER);
> - dev_dbg(dev, " POWER\n");
> - }
> -
> - if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) {
> - port_status |= USB_PORT_STAT_HIGH_SPEED;
> - dev_dbg(dev, " HIGHSPEED\n");
> - } else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) {
> - port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
> - dev_dbg(dev, " LOWSPEED\n");
> - }
> -
> - *((__le32 *)buf) = cpu_to_le32(port_status);
> - break;
> - case SetHubFeature:
> - dev_dbg(dev, "SetHubFeature\n");
> - /* No HUB features supported */
> - break;
> - case SetPortFeature:
> - dev_dbg(dev, "SetPortFeature\n");
> - if (wIndex != 1) {
> - dev_dbg(dev, " INVALID\n");
> - return -EINVAL;
> - }
> -
> - switch (wValue) {
> - case USB_PORT_FEAT_SUSPEND:
> - dev_dbg(dev, " SUSPEND\n");
> - return -EINVAL;
> - case USB_PORT_FEAT_POWER:
> - dev_dbg(dev, " POWER\n");
> - /*
> - * Program the port power bit to drive VBUS on the USB.
> - */
> - spin_lock_irqsave(&usb->lock, flags);
> - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index),
> - cvmx_usbcx_hprt, prtpwr, 1);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - return 0;
> - case USB_PORT_FEAT_RESET:
> - dev_dbg(dev, " RESET\n");
> - spin_lock_irqsave(&usb->lock, flags);
> - cvmx_usb_reset_port(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - return 0;
> - case USB_PORT_FEAT_INDICATOR:
> - dev_dbg(dev, " INDICATOR\n");
> - /* Not supported */
> - break;
> - default:
> - dev_dbg(dev, " UNKNOWN\n");
> - return -EINVAL;
> - }
> - break;
> - default:
> - dev_dbg(dev, "Unknown root hub request\n");
> - return -EINVAL;
> - }
> - return 0;
> -}
> -
> -static const struct hc_driver octeon_hc_driver = {
> - .description = "Octeon USB",
> - .product_desc = "Octeon Host Controller",
> - .hcd_priv_size = sizeof(struct octeon_hcd),
> - .irq = octeon_usb_irq,
> - .flags = HCD_MEMORY | HCD_DMA | HCD_USB2,
> - .start = octeon_usb_start,
> - .stop = octeon_usb_stop,
> - .urb_enqueue = octeon_usb_urb_enqueue,
> - .urb_dequeue = octeon_usb_urb_dequeue,
> - .endpoint_disable = octeon_usb_endpoint_disable,
> - .get_frame_number = octeon_usb_get_frame_number,
> - .hub_status_data = octeon_usb_hub_status_data,
> - .hub_control = octeon_usb_hub_control,
> - .map_urb_for_dma = octeon_map_urb_for_dma,
> - .unmap_urb_for_dma = octeon_unmap_urb_for_dma,
> -};
> -
> -static int octeon_usb_probe(struct platform_device *pdev)
> -{
> - int status;
> - int initialize_flags;
> - int usb_num;
> - struct resource *res_mem;
> - struct device_node *usbn_node;
> - int irq = platform_get_irq(pdev, 0);
> - struct device *dev = &pdev->dev;
> - struct octeon_hcd *usb;
> - struct usb_hcd *hcd;
> - u32 clock_rate = 48000000;
> - bool is_crystal_clock = false;
> - const char *clock_type;
> - int i;
> -
> - if (!dev->of_node) {
> - dev_err(dev, "Error: empty of_node\n");
> - return -ENXIO;
> - }
> - usbn_node = dev->of_node->parent;
> -
> - i = of_property_read_u32(usbn_node,
> - "clock-frequency", &clock_rate);
> - if (i)
> - i = of_property_read_u32(usbn_node,
> - "refclk-frequency", &clock_rate);
> - if (i) {
> - dev_err(dev, "No USBN \"clock-frequency\"\n");
> - return -ENXIO;
> - }
> - switch (clock_rate) {
> - case 12000000:
> - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
> - break;
> - case 24000000:
> - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
> - break;
> - case 48000000:
> - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
> - break;
> - default:
> - dev_err(dev, "Illegal USBN \"clock-frequency\" %u\n",
> - clock_rate);
> - return -ENXIO;
> - }
> -
> - i = of_property_read_string(usbn_node,
> - "cavium,refclk-type", &clock_type);
> - if (i)
> - i = of_property_read_string(usbn_node,
> - "refclk-type", &clock_type);
> -
> - if (!i && strcmp("crystal", clock_type) == 0)
> - is_crystal_clock = true;
> -
> - if (is_crystal_clock)
> - initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;
> - else
> - initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
> -
> - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> - if (!res_mem) {
> - dev_err(dev, "found no memory resource\n");
> - return -ENXIO;
> - }
> - usb_num = (res_mem->start >> 44) & 1;
> -
> - if (irq < 0) {
> - /* Defective device tree, but we know how to fix it. */
> - irq_hw_number_t hwirq = usb_num ? (1 << 6) + 17 : 56;
> -
> - irq = irq_create_mapping(NULL, hwirq);
> - }
> -
> - /*
> - * Set the DMA mask to 64bits so we get buffers already translated for
> - * DMA.
> - */
> - i = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
> - if (i)
> - return i;
> -
> - /*
> - * Only cn52XX and cn56XX have DWC_OTG USB hardware and the
> - * IOB priority registers. Under heavy network load USB
> - * hardware can be starved by the IOB causing a crash. Give
> - * it a priority boost if it has been waiting more than 400
> - * cycles to avoid this situation.
> - *
> - * Testing indicates that a cnt_val of 8192 is not sufficient,
> - * but no failures are seen with 4096. We choose a value of
> - * 400 to give a safety factor of 10.
> - */
> - if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
> - union cvmx_iob_n2c_l2c_pri_cnt pri_cnt;
> -
> - pri_cnt.u64 = 0;
> - pri_cnt.s.cnt_enb = 1;
> - pri_cnt.s.cnt_val = 400;
> - cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
> - }
> -
> - hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev));
> - if (!hcd) {
> - dev_dbg(dev, "Failed to allocate memory for HCD\n");
> - return -1;
> - }
> - hcd->uses_new_polling = 1;
> - usb = (struct octeon_hcd *)hcd->hcd_priv;
> -
> - spin_lock_init(&usb->lock);
> -
> - usb->init_flags = initialize_flags;
> -
> - /* Initialize the USB state structure */
> - usb->index = usb_num;
> - INIT_LIST_HEAD(&usb->idle_pipes);
> - for (i = 0; i < ARRAY_SIZE(usb->active_pipes); i++)
> - INIT_LIST_HEAD(&usb->active_pipes[i]);
> -
> - /* Due to an errata, CN31XX doesn't support DMA */
> - if (OCTEON_IS_MODEL(OCTEON_CN31XX)) {
> - usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
> - /* Only use one channel with non DMA */
> - usb->idle_hardware_channels = 0x1;
> - } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) {
> - /* CN5XXX have an errata with channel 3 */
> - usb->idle_hardware_channels = 0xf7;
> - } else {
> - usb->idle_hardware_channels = 0xff;
> - }
> -
> - status = cvmx_usb_initialize(dev, usb);
> - if (status) {
> - dev_dbg(dev, "USB initialization failed with %d\n", status);
> - usb_put_hcd(hcd);
> - return -1;
> - }
> -
> - status = usb_add_hcd(hcd, irq, 0);
> - if (status) {
> - dev_dbg(dev, "USB add HCD failed with %d\n", status);
> - usb_put_hcd(hcd);
> - return -1;
> - }
> - device_wakeup_enable(hcd->self.controller);
> -
> - dev_info(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
> -
> - return 0;
> -}
> -
> -static int octeon_usb_remove(struct platform_device *pdev)
> -{
> - int status;
> - struct device *dev = &pdev->dev;
> - struct usb_hcd *hcd = dev_get_drvdata(dev);
> - struct octeon_hcd *usb = hcd_to_octeon(hcd);
> - unsigned long flags;
> -
> - usb_remove_hcd(hcd);
> - spin_lock_irqsave(&usb->lock, flags);
> - status = cvmx_usb_shutdown(usb);
> - spin_unlock_irqrestore(&usb->lock, flags);
> - if (status)
> - dev_dbg(dev, "USB shutdown failed with %d\n", status);
> -
> - usb_put_hcd(hcd);
> -
> - return 0;
> -}
> -
> -static const struct of_device_id octeon_usb_match[] = {
> - {
> - .compatible = "cavium,octeon-5750-usbc",
> - },
> - {},
> -};
> -MODULE_DEVICE_TABLE(of, octeon_usb_match);
> -
> -static struct platform_driver octeon_usb_driver = {
> - .driver = {
> - .name = "octeon-hcd",
> - .of_match_table = octeon_usb_match,
> - },
> - .probe = octeon_usb_probe,
> - .remove = octeon_usb_remove,
> -};
> -
> -static int __init octeon_usb_driver_init(void)
> -{
> - if (usb_disabled())
> - return 0;
> -
> - return platform_driver_register(&octeon_usb_driver);
> -}
> -module_init(octeon_usb_driver_init);
> -
> -static void __exit octeon_usb_driver_exit(void)
> -{
> - if (usb_disabled())
> - return;
> -
> - platform_driver_unregister(&octeon_usb_driver);
> -}
> -module_exit(octeon_usb_driver_exit);
> -
> -MODULE_LICENSE("GPL");
> -MODULE_AUTHOR("Cavium, Inc. <support@cavium.com>");
> -MODULE_DESCRIPTION("Cavium Inc. OCTEON USB Host driver.");
> diff --git a/drivers/staging/octeon-usb/octeon-hcd.h b/drivers/staging/octeon-usb/octeon-hcd.h
> deleted file mode 100644
> index 9ed619c93a4e..000000000000
> --- a/drivers/staging/octeon-usb/octeon-hcd.h
> +++ /dev/null
> @@ -1,1847 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * Octeon HCD hardware register definitions.
> - *
> - * This file is subject to the terms and conditions of the GNU General Public
> - * License. See the file "COPYING" in the main directory of this archive
> - * for more details.
> - *
> - * Some parts of the code were originally released under BSD license:
> - *
> - * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
> - * reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions are
> - * met:
> - *
> - * * Redistributions of source code must retain the above copyright
> - * notice, this list of conditions and the following disclaimer.
> - *
> - * * Redistributions in binary form must reproduce the above
> - * copyright notice, this list of conditions and the following
> - * disclaimer in the documentation and/or other materials provided
> - * with the distribution.
> - *
> - * * Neither the name of Cavium Networks nor the names of
> - * its contributors may be used to endorse or promote products
> - * derived from this software without specific prior written
> - * permission.
> - *
> - * This Software, including technical data, may be subject to U.S. export
> - * control laws, including the U.S. Export Administration Act and its associated
> - * regulations, and may be subject to export or import regulations in other
> - * countries.
> - *
> - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
> - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
> - * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
> - * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
> - * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
> - * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
> - * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
> - * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
> - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
> - * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
> - */
> -
> -#ifndef __OCTEON_HCD_H__
> -#define __OCTEON_HCD_H__
> -
> -#include <asm/bitfield.h>
> -
> -#define CVMX_USBCXBASE 0x00016F0010000000ull
> -#define CVMX_USBCXREG1(reg, bid) \
> - (CVMX_ADD_IO_SEG(CVMX_USBCXBASE | reg) + \
> - ((bid) & 1) * 0x100000000000ull)
> -#define CVMX_USBCXREG2(reg, bid, off) \
> - (CVMX_ADD_IO_SEG(CVMX_USBCXBASE | reg) + \
> - (((off) & 7) + ((bid) & 1) * 0x8000000000ull) * 32)
> -
> -#define CVMX_USBCX_GAHBCFG(bid) CVMX_USBCXREG1(0x008, bid)
> -#define CVMX_USBCX_GHWCFG3(bid) CVMX_USBCXREG1(0x04c, bid)
> -#define CVMX_USBCX_GINTMSK(bid) CVMX_USBCXREG1(0x018, bid)
> -#define CVMX_USBCX_GINTSTS(bid) CVMX_USBCXREG1(0x014, bid)
> -#define CVMX_USBCX_GNPTXFSIZ(bid) CVMX_USBCXREG1(0x028, bid)
> -#define CVMX_USBCX_GNPTXSTS(bid) CVMX_USBCXREG1(0x02c, bid)
> -#define CVMX_USBCX_GOTGCTL(bid) CVMX_USBCXREG1(0x000, bid)
> -#define CVMX_USBCX_GRSTCTL(bid) CVMX_USBCXREG1(0x010, bid)
> -#define CVMX_USBCX_GRXFSIZ(bid) CVMX_USBCXREG1(0x024, bid)
> -#define CVMX_USBCX_GRXSTSPH(bid) CVMX_USBCXREG1(0x020, bid)
> -#define CVMX_USBCX_GUSBCFG(bid) CVMX_USBCXREG1(0x00c, bid)
> -#define CVMX_USBCX_HAINT(bid) CVMX_USBCXREG1(0x414, bid)
> -#define CVMX_USBCX_HAINTMSK(bid) CVMX_USBCXREG1(0x418, bid)
> -#define CVMX_USBCX_HCCHARX(off, bid) CVMX_USBCXREG2(0x500, bid, off)
> -#define CVMX_USBCX_HCFG(bid) CVMX_USBCXREG1(0x400, bid)
> -#define CVMX_USBCX_HCINTMSKX(off, bid) CVMX_USBCXREG2(0x50c, bid, off)
> -#define CVMX_USBCX_HCINTX(off, bid) CVMX_USBCXREG2(0x508, bid, off)
> -#define CVMX_USBCX_HCSPLTX(off, bid) CVMX_USBCXREG2(0x504, bid, off)
> -#define CVMX_USBCX_HCTSIZX(off, bid) CVMX_USBCXREG2(0x510, bid, off)
> -#define CVMX_USBCX_HFIR(bid) CVMX_USBCXREG1(0x404, bid)
> -#define CVMX_USBCX_HFNUM(bid) CVMX_USBCXREG1(0x408, bid)
> -#define CVMX_USBCX_HPRT(bid) CVMX_USBCXREG1(0x440, bid)
> -#define CVMX_USBCX_HPTXFSIZ(bid) CVMX_USBCXREG1(0x100, bid)
> -#define CVMX_USBCX_HPTXSTS(bid) CVMX_USBCXREG1(0x410, bid)
> -
> -#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull)
> -#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull)
> -
> -#define CVMX_USBNXREG1(reg, bid) \
> - (CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid))
> -#define CVMX_USBNXREG2(reg, bid) \
> - (CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid))
> -
> -#define CVMX_USBNX_CLK_CTL(bid) CVMX_USBNXREG1(0x10, bid)
> -#define CVMX_USBNX_DMA0_INB_CHN0(bid) CVMX_USBNXREG2(0x818, bid)
> -#define CVMX_USBNX_DMA0_OUTB_CHN0(bid) CVMX_USBNXREG2(0x858, bid)
> -#define CVMX_USBNX_USBP_CTL_STATUS(bid) CVMX_USBNXREG1(0x18, bid)
> -
> -/**
> - * cvmx_usbc#_gahbcfg
> - *
> - * Core AHB Configuration Register (GAHBCFG)
> - *
> - * This register can be used to configure the core after power-on or a change in
> - * mode of operation. This register mainly contains AHB system-related
> - * configuration parameters. The AHB is the processor interface to the O2P USB
> - * core. In general, software need not know about this interface except to
> - * program the values as specified.
> - *
> - * The application must program this register as part of the O2P USB core
> - * initialization. Do not change this register after the initial programming.
> - */
> -union cvmx_usbcx_gahbcfg {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gahbcfg_s
> - * @ptxfemplvl: Periodic TxFIFO Empty Level (PTxFEmpLvl)
> - * Software should set this bit to 0x1.
> - * Indicates when the Periodic TxFIFO Empty Interrupt bit in the
> - * Core Interrupt register (GINTSTS.PTxFEmp) is triggered. This
> - * bit is used only in Slave mode.
> - * * 1'b0: GINTSTS.PTxFEmp interrupt indicates that the Periodic
> - * TxFIFO is half empty
> - * * 1'b1: GINTSTS.PTxFEmp interrupt indicates that the Periodic
> - * TxFIFO is completely empty
> - * @nptxfemplvl: Non-Periodic TxFIFO Empty Level (NPTxFEmpLvl)
> - * Software should set this bit to 0x1.
> - * Indicates when the Non-Periodic TxFIFO Empty Interrupt bit in
> - * the Core Interrupt register (GINTSTS.NPTxFEmp) is triggered.
> - * This bit is used only in Slave mode.
> - * * 1'b0: GINTSTS.NPTxFEmp interrupt indicates that the Non-
> - * Periodic TxFIFO is half empty
> - * * 1'b1: GINTSTS.NPTxFEmp interrupt indicates that the Non-
> - * Periodic TxFIFO is completely empty
> - * @dmaen: DMA Enable (DMAEn)
> - * * 1'b0: Core operates in Slave mode
> - * * 1'b1: Core operates in a DMA mode
> - * @hbstlen: Burst Length/Type (HBstLen)
> - * This field has not effect and should be left as 0x0.
> - * @glblintrmsk: Global Interrupt Mask (GlblIntrMsk)
> - * Software should set this field to 0x1.
> - * The application uses this bit to mask or unmask the interrupt
> - * line assertion to itself. Irrespective of this bit's setting,
> - * the interrupt status registers are updated by the core.
> - * * 1'b0: Mask the interrupt assertion to the application.
> - * * 1'b1: Unmask the interrupt assertion to the application.
> - */
> - struct cvmx_usbcx_gahbcfg_s {
> - __BITFIELD_FIELD(u32 reserved_9_31 : 23,
> - __BITFIELD_FIELD(u32 ptxfemplvl : 1,
> - __BITFIELD_FIELD(u32 nptxfemplvl : 1,
> - __BITFIELD_FIELD(u32 reserved_6_6 : 1,
> - __BITFIELD_FIELD(u32 dmaen : 1,
> - __BITFIELD_FIELD(u32 hbstlen : 4,
> - __BITFIELD_FIELD(u32 glblintrmsk : 1,
> - ;)))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_ghwcfg3
> - *
> - * User HW Config3 Register (GHWCFG3)
> - *
> - * This register contains the configuration options of the O2P USB core.
> - */
> -union cvmx_usbcx_ghwcfg3 {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_ghwcfg3_s
> - * @dfifodepth: DFIFO Depth (DfifoDepth)
> - * This value is in terms of 32-bit words.
> - * * Minimum value is 32
> - * * Maximum value is 32768
> - * @ahbphysync: AHB and PHY Synchronous (AhbPhySync)
> - * Indicates whether AHB and PHY clocks are synchronous to
> - * each other.
> - * * 1'b0: No
> - * * 1'b1: Yes
> - * This bit is tied to 1.
> - * @rsttype: Reset Style for Clocked always Blocks in RTL (RstType)
> - * * 1'b0: Asynchronous reset is used in the core
> - * * 1'b1: Synchronous reset is used in the core
> - * @optfeature: Optional Features Removed (OptFeature)
> - * Indicates whether the User ID register, GPIO interface ports,
> - * and SOF toggle and counter ports were removed for gate count
> - * optimization.
> - * @vendor_control_interface_support: Vendor Control Interface Support
> - * * 1'b0: Vendor Control Interface is not available on the core.
> - * * 1'b1: Vendor Control Interface is available.
> - * @i2c_selection: I2C Selection
> - * * 1'b0: I2C Interface is not available on the core.
> - * * 1'b1: I2C Interface is available on the core.
> - * @otgen: OTG Function Enabled (OtgEn)
> - * The application uses this bit to indicate the O2P USB core's
> - * OTG capabilities.
> - * * 1'b0: Not OTG capable
> - * * 1'b1: OTG Capable
> - * @pktsizewidth: Width of Packet Size Counters (PktSizeWidth)
> - * * 3'b000: 4 bits
> - * * 3'b001: 5 bits
> - * * 3'b010: 6 bits
> - * * 3'b011: 7 bits
> - * * 3'b100: 8 bits
> - * * 3'b101: 9 bits
> - * * 3'b110: 10 bits
> - * * Others: Reserved
> - * @xfersizewidth: Width of Transfer Size Counters (XferSizeWidth)
> - * * 4'b0000: 11 bits
> - * * 4'b0001: 12 bits
> - * - ...
> - * * 4'b1000: 19 bits
> - * * Others: Reserved
> - */
> - struct cvmx_usbcx_ghwcfg3_s {
> - __BITFIELD_FIELD(u32 dfifodepth : 16,
> - __BITFIELD_FIELD(u32 reserved_13_15 : 3,
> - __BITFIELD_FIELD(u32 ahbphysync : 1,
> - __BITFIELD_FIELD(u32 rsttype : 1,
> - __BITFIELD_FIELD(u32 optfeature : 1,
> - __BITFIELD_FIELD(u32 vendor_control_interface_support : 1,
> - __BITFIELD_FIELD(u32 i2c_selection : 1,
> - __BITFIELD_FIELD(u32 otgen : 1,
> - __BITFIELD_FIELD(u32 pktsizewidth : 3,
> - __BITFIELD_FIELD(u32 xfersizewidth : 4,
> - ;))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_gintmsk
> - *
> - * Core Interrupt Mask Register (GINTMSK)
> - *
> - * This register works with the Core Interrupt register to interrupt the
> - * application. When an interrupt bit is masked, the interrupt associated with
> - * that bit will not be generated. However, the Core Interrupt (GINTSTS)
> - * register bit corresponding to that interrupt will still be set.
> - * Mask interrupt: 1'b0, Unmask interrupt: 1'b1
> - */
> -union cvmx_usbcx_gintmsk {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gintmsk_s
> - * @wkupintmsk: Resume/Remote Wakeup Detected Interrupt Mask
> - * (WkUpIntMsk)
> - * @sessreqintmsk: Session Request/New Session Detected Interrupt Mask
> - * (SessReqIntMsk)
> - * @disconnintmsk: Disconnect Detected Interrupt Mask (DisconnIntMsk)
> - * @conidstschngmsk: Connector ID Status Change Mask (ConIDStsChngMsk)
> - * @ptxfempmsk: Periodic TxFIFO Empty Mask (PTxFEmpMsk)
> - * @hchintmsk: Host Channels Interrupt Mask (HChIntMsk)
> - * @prtintmsk: Host Port Interrupt Mask (PrtIntMsk)
> - * @fetsuspmsk: Data Fetch Suspended Mask (FetSuspMsk)
> - * @incomplpmsk: Incomplete Periodic Transfer Mask (incomplPMsk)
> - * Incomplete Isochronous OUT Transfer Mask
> - * (incompISOOUTMsk)
> - * @incompisoinmsk: Incomplete Isochronous IN Transfer Mask
> - * (incompISOINMsk)
> - * @oepintmsk: OUT Endpoints Interrupt Mask (OEPIntMsk)
> - * @inepintmsk: IN Endpoints Interrupt Mask (INEPIntMsk)
> - * @epmismsk: Endpoint Mismatch Interrupt Mask (EPMisMsk)
> - * @eopfmsk: End of Periodic Frame Interrupt Mask (EOPFMsk)
> - * @isooutdropmsk: Isochronous OUT Packet Dropped Interrupt Mask
> - * (ISOOutDropMsk)
> - * @enumdonemsk: Enumeration Done Mask (EnumDoneMsk)
> - * @usbrstmsk: USB Reset Mask (USBRstMsk)
> - * @usbsuspmsk: USB Suspend Mask (USBSuspMsk)
> - * @erlysuspmsk: Early Suspend Mask (ErlySuspMsk)
> - * @i2cint: I2C Interrupt Mask (I2CINT)
> - * @ulpickintmsk: ULPI Carkit Interrupt Mask (ULPICKINTMsk)
> - * I2C Carkit Interrupt Mask (I2CCKINTMsk)
> - * @goutnakeffmsk: Global OUT NAK Effective Mask (GOUTNakEffMsk)
> - * @ginnakeffmsk: Global Non-Periodic IN NAK Effective Mask
> - * (GINNakEffMsk)
> - * @nptxfempmsk: Non-Periodic TxFIFO Empty Mask (NPTxFEmpMsk)
> - * @rxflvlmsk: Receive FIFO Non-Empty Mask (RxFLvlMsk)
> - * @sofmsk: Start of (micro)Frame Mask (SofMsk)
> - * @otgintmsk: OTG Interrupt Mask (OTGIntMsk)
> - * @modemismsk: Mode Mismatch Interrupt Mask (ModeMisMsk)
> - */
> - struct cvmx_usbcx_gintmsk_s {
> - __BITFIELD_FIELD(u32 wkupintmsk : 1,
> - __BITFIELD_FIELD(u32 sessreqintmsk : 1,
> - __BITFIELD_FIELD(u32 disconnintmsk : 1,
> - __BITFIELD_FIELD(u32 conidstschngmsk : 1,
> - __BITFIELD_FIELD(u32 reserved_27_27 : 1,
> - __BITFIELD_FIELD(u32 ptxfempmsk : 1,
> - __BITFIELD_FIELD(u32 hchintmsk : 1,
> - __BITFIELD_FIELD(u32 prtintmsk : 1,
> - __BITFIELD_FIELD(u32 reserved_23_23 : 1,
> - __BITFIELD_FIELD(u32 fetsuspmsk : 1,
> - __BITFIELD_FIELD(u32 incomplpmsk : 1,
> - __BITFIELD_FIELD(u32 incompisoinmsk : 1,
> - __BITFIELD_FIELD(u32 oepintmsk : 1,
> - __BITFIELD_FIELD(u32 inepintmsk : 1,
> - __BITFIELD_FIELD(u32 epmismsk : 1,
> - __BITFIELD_FIELD(u32 reserved_16_16 : 1,
> - __BITFIELD_FIELD(u32 eopfmsk : 1,
> - __BITFIELD_FIELD(u32 isooutdropmsk : 1,
> - __BITFIELD_FIELD(u32 enumdonemsk : 1,
> - __BITFIELD_FIELD(u32 usbrstmsk : 1,
> - __BITFIELD_FIELD(u32 usbsuspmsk : 1,
> - __BITFIELD_FIELD(u32 erlysuspmsk : 1,
> - __BITFIELD_FIELD(u32 i2cint : 1,
> - __BITFIELD_FIELD(u32 ulpickintmsk : 1,
> - __BITFIELD_FIELD(u32 goutnakeffmsk : 1,
> - __BITFIELD_FIELD(u32 ginnakeffmsk : 1,
> - __BITFIELD_FIELD(u32 nptxfempmsk : 1,
> - __BITFIELD_FIELD(u32 rxflvlmsk : 1,
> - __BITFIELD_FIELD(u32 sofmsk : 1,
> - __BITFIELD_FIELD(u32 otgintmsk : 1,
> - __BITFIELD_FIELD(u32 modemismsk : 1,
> - __BITFIELD_FIELD(u32 reserved_0_0 : 1,
> - ;))))))))))))))))))))))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_gintsts
> - *
> - * Core Interrupt Register (GINTSTS)
> - *
> - * This register interrupts the application for system-level events in the
> - * current mode of operation (Device mode or Host mode). It is shown in
> - * Interrupt. Some of the bits in this register are valid only in Host mode,
> - * while others are valid in Device mode only. This register also indicates the
> - * current mode of operation. In order to clear the interrupt status bits of
> - * type R_SS_WC, the application must write 1'b1 into the bit. The FIFO status
> - * interrupts are read only; once software reads from or writes to the FIFO
> - * while servicing these interrupts, FIFO interrupt conditions are cleared
> - * automatically.
> - */
> -union cvmx_usbcx_gintsts {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gintsts_s
> - * @wkupint: Resume/Remote Wakeup Detected Interrupt (WkUpInt)
> - * In Device mode, this interrupt is asserted when a resume is
> - * detected on the USB. In Host mode, this interrupt is asserted
> - * when a remote wakeup is detected on the USB.
> - * For more information on how to use this interrupt, see "Partial
> - * Power-Down and Clock Gating Programming Model" on
> - * page 353.
> - * @sessreqint: Session Request/New Session Detected Interrupt
> - * (SessReqInt)
> - * In Host mode, this interrupt is asserted when a session request
> - * is detected from the device. In Device mode, this interrupt is
> - * asserted when the utmiotg_bvalid signal goes high.
> - * For more information on how to use this interrupt, see "Partial
> - * Power-Down and Clock Gating Programming Model" on
> - * page 353.
> - * @disconnint: Disconnect Detected Interrupt (DisconnInt)
> - * Asserted when a device disconnect is detected.
> - * @conidstschng: Connector ID Status Change (ConIDStsChng)
> - * The core sets this bit when there is a change in connector ID
> - * status.
> - * @ptxfemp: Periodic TxFIFO Empty (PTxFEmp)
> - * Asserted when the Periodic Transmit FIFO is either half or
> - * completely empty and there is space for at least one entry to be
> - * written in the Periodic Request Queue. The half or completely
> - * empty status is determined by the Periodic TxFIFO Empty Level
> - * bit in the Core AHB Configuration register
> - * (GAHBCFG.PTxFEmpLvl).
> - * @hchint: Host Channels Interrupt (HChInt)
> - * The core sets this bit to indicate that an interrupt is pending
> - * on one of the channels of the core (in Host mode). The
> - * application must read the Host All Channels Interrupt (HAINT)
> - * register to determine the exact number of the channel on which
> - * the interrupt occurred, and then read the corresponding Host
> - * Channel-n Interrupt (HCINTn) register to determine the exact
> - * cause of the interrupt. The application must clear the
> - * appropriate status bit in the HCINTn register to clear this bit.
> - * @prtint: Host Port Interrupt (PrtInt)
> - * The core sets this bit to indicate a change in port status of
> - * one of the O2P USB core ports in Host mode. The application must
> - * read the Host Port Control and Status (HPRT) register to
> - * determine the exact event that caused this interrupt. The
> - * application must clear the appropriate status bit in the Host
> - * Port Control and Status register to clear this bit.
> - * @fetsusp: Data Fetch Suspended (FetSusp)
> - * This interrupt is valid only in DMA mode. This interrupt
> - * indicates that the core has stopped fetching data for IN
> - * endpoints due to the unavailability of TxFIFO space or Request
> - * Queue space. This interrupt is used by the application for an
> - * endpoint mismatch algorithm.
> - * @incomplp: Incomplete Periodic Transfer (incomplP)
> - * In Host mode, the core sets this interrupt bit when there are
> - * incomplete periodic transactions still pending which are
> - * scheduled for the current microframe.
> - * Incomplete Isochronous OUT Transfer (incompISOOUT)
> - * The Device mode, the core sets this interrupt to indicate that
> - * there is at least one isochronous OUT endpoint on which the
> - * transfer is not completed in the current microframe. This
> - * interrupt is asserted along with the End of Periodic Frame
> - * Interrupt (EOPF) bit in this register.
> - * @incompisoin: Incomplete Isochronous IN Transfer (incompISOIN)
> - * The core sets this interrupt to indicate that there is at least
> - * one isochronous IN endpoint on which the transfer is not
> - * completed in the current microframe. This interrupt is asserted
> - * along with the End of Periodic Frame Interrupt (EOPF) bit in
> - * this register.
> - * @oepint: OUT Endpoints Interrupt (OEPInt)
> - * The core sets this bit to indicate that an interrupt is pending
> - * on one of the OUT endpoints of the core (in Device mode). The
> - * application must read the Device All Endpoints Interrupt
> - * (DAINT) register to determine the exact number of the OUT
> - * endpoint on which the interrupt occurred, and then read the
> - * corresponding Device OUT Endpoint-n Interrupt (DOEPINTn)
> - * register to determine the exact cause of the interrupt. The
> - * application must clear the appropriate status bit in the
> - * corresponding DOEPINTn register to clear this bit.
> - * @iepint: IN Endpoints Interrupt (IEPInt)
> - * The core sets this bit to indicate that an interrupt is pending
> - * on one of the IN endpoints of the core (in Device mode). The
> - * application must read the Device All Endpoints Interrupt
> - * (DAINT) register to determine the exact number of the IN
> - * endpoint on which the interrupt occurred, and then read the
> - * corresponding Device IN Endpoint-n Interrupt (DIEPINTn)
> - * register to determine the exact cause of the interrupt. The
> - * application must clear the appropriate status bit in the
> - * corresponding DIEPINTn register to clear this bit.
> - * @epmis: Endpoint Mismatch Interrupt (EPMis)
> - * Indicates that an IN token has been received for a non-periodic
> - * endpoint, but the data for another endpoint is present in the
> - * top of the Non-Periodic Transmit FIFO and the IN endpoint
> - * mismatch count programmed by the application has expired.
> - * @eopf: End of Periodic Frame Interrupt (EOPF)
> - * Indicates that the period specified in the Periodic Frame
> - * Interval field of the Device Configuration register
> - * (DCFG.PerFrInt) has been reached in the current microframe.
> - * @isooutdrop: Isochronous OUT Packet Dropped Interrupt (ISOOutDrop)
> - * The core sets this bit when it fails to write an isochronous OUT
> - * packet into the RxFIFO because the RxFIFO doesn't have
> - * enough space to accommodate a maximum packet size packet
> - * for the isochronous OUT endpoint.
> - * @enumdone: Enumeration Done (EnumDone)
> - * The core sets this bit to indicate that speed enumeration is
> - * complete. The application must read the Device Status (DSTS)
> - * register to obtain the enumerated speed.
> - * @usbrst: USB Reset (USBRst)
> - * The core sets this bit to indicate that a reset is detected on
> - * the USB.
> - * @usbsusp: USB Suspend (USBSusp)
> - * The core sets this bit to indicate that a suspend was detected
> - * on the USB. The core enters the Suspended state when there
> - * is no activity on the phy_line_state_i signal for an extended
> - * period of time.
> - * @erlysusp: Early Suspend (ErlySusp)
> - * The core sets this bit to indicate that an Idle state has been
> - * detected on the USB for 3 ms.
> - * @i2cint: I2C Interrupt (I2CINT)
> - * This bit is always 0x0.
> - * @ulpickint: ULPI Carkit Interrupt (ULPICKINT)
> - * This bit is always 0x0.
> - * @goutnakeff: Global OUT NAK Effective (GOUTNakEff)
> - * Indicates that the Set Global OUT NAK bit in the Device Control
> - * register (DCTL.SGOUTNak), set by the application, has taken
> - * effect in the core. This bit can be cleared by writing the Clear
> - * Global OUT NAK bit in the Device Control register
> - * (DCTL.CGOUTNak).
> - * @ginnakeff: Global IN Non-Periodic NAK Effective (GINNakEff)
> - * Indicates that the Set Global Non-Periodic IN NAK bit in the
> - * Device Control register (DCTL.SGNPInNak), set by the
> - * application, has taken effect in the core. That is, the core has
> - * sampled the Global IN NAK bit set by the application. This bit
> - * can be cleared by clearing the Clear Global Non-Periodic IN
> - * NAK bit in the Device Control register (DCTL.CGNPInNak).
> - * This interrupt does not necessarily mean that a NAK handshake
> - * is sent out on the USB. The STALL bit takes precedence over
> - * the NAK bit.
> - * @nptxfemp: Non-Periodic TxFIFO Empty (NPTxFEmp)
> - * This interrupt is asserted when the Non-Periodic TxFIFO is
> - * either half or completely empty, and there is space for at least
> - * one entry to be written to the Non-Periodic Transmit Request
> - * Queue. The half or completely empty status is determined by
> - * the Non-Periodic TxFIFO Empty Level bit in the Core AHB
> - * Configuration register (GAHBCFG.NPTxFEmpLvl).
> - * @rxflvl: RxFIFO Non-Empty (RxFLvl)
> - * Indicates that there is at least one packet pending to be read
> - * from the RxFIFO.
> - * @sof: Start of (micro)Frame (Sof)
> - * In Host mode, the core sets this bit to indicate that an SOF
> - * (FS), micro-SOF (HS), or Keep-Alive (LS) is transmitted on the
> - * USB. The application must write a 1 to this bit to clear the
> - * interrupt.
> - * In Device mode, in the core sets this bit to indicate that an
> - * SOF token has been received on the USB. The application can read
> - * the Device Status register to get the current (micro)frame
> - * number. This interrupt is seen only when the core is operating
> - * at either HS or FS.
> - * @otgint: OTG Interrupt (OTGInt)
> - * The core sets this bit to indicate an OTG protocol event. The
> - * application must read the OTG Interrupt Status (GOTGINT)
> - * register to determine the exact event that caused this
> - * interrupt. The application must clear the appropriate status bit
> - * in the GOTGINT register to clear this bit.
> - * @modemis: Mode Mismatch Interrupt (ModeMis)
> - * The core sets this bit when the application is trying to access:
> - * * A Host mode register, when the core is operating in Device
> - * mode
> - * * A Device mode register, when the core is operating in Host
> - * mode
> - * The register access is completed on the AHB with an OKAY
> - * response, but is ignored by the core internally and doesn't
> - * affect the operation of the core.
> - * @curmod: Current Mode of Operation (CurMod)
> - * Indicates the current mode of operation.
> - * * 1'b0: Device mode
> - * * 1'b1: Host mode
> - */
> - struct cvmx_usbcx_gintsts_s {
> - __BITFIELD_FIELD(u32 wkupint : 1,
> - __BITFIELD_FIELD(u32 sessreqint : 1,
> - __BITFIELD_FIELD(u32 disconnint : 1,
> - __BITFIELD_FIELD(u32 conidstschng : 1,
> - __BITFIELD_FIELD(u32 reserved_27_27 : 1,
> - __BITFIELD_FIELD(u32 ptxfemp : 1,
> - __BITFIELD_FIELD(u32 hchint : 1,
> - __BITFIELD_FIELD(u32 prtint : 1,
> - __BITFIELD_FIELD(u32 reserved_23_23 : 1,
> - __BITFIELD_FIELD(u32 fetsusp : 1,
> - __BITFIELD_FIELD(u32 incomplp : 1,
> - __BITFIELD_FIELD(u32 incompisoin : 1,
> - __BITFIELD_FIELD(u32 oepint : 1,
> - __BITFIELD_FIELD(u32 iepint : 1,
> - __BITFIELD_FIELD(u32 epmis : 1,
> - __BITFIELD_FIELD(u32 reserved_16_16 : 1,
> - __BITFIELD_FIELD(u32 eopf : 1,
> - __BITFIELD_FIELD(u32 isooutdrop : 1,
> - __BITFIELD_FIELD(u32 enumdone : 1,
> - __BITFIELD_FIELD(u32 usbrst : 1,
> - __BITFIELD_FIELD(u32 usbsusp : 1,
> - __BITFIELD_FIELD(u32 erlysusp : 1,
> - __BITFIELD_FIELD(u32 i2cint : 1,
> - __BITFIELD_FIELD(u32 ulpickint : 1,
> - __BITFIELD_FIELD(u32 goutnakeff : 1,
> - __BITFIELD_FIELD(u32 ginnakeff : 1,
> - __BITFIELD_FIELD(u32 nptxfemp : 1,
> - __BITFIELD_FIELD(u32 rxflvl : 1,
> - __BITFIELD_FIELD(u32 sof : 1,
> - __BITFIELD_FIELD(u32 otgint : 1,
> - __BITFIELD_FIELD(u32 modemis : 1,
> - __BITFIELD_FIELD(u32 curmod : 1,
> - ;))))))))))))))))))))))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_gnptxfsiz
> - *
> - * Non-Periodic Transmit FIFO Size Register (GNPTXFSIZ)
> - *
> - * The application can program the RAM size and the memory start address for the
> - * Non-Periodic TxFIFO.
> - */
> -union cvmx_usbcx_gnptxfsiz {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gnptxfsiz_s
> - * @nptxfdep: Non-Periodic TxFIFO Depth (NPTxFDep)
> - * This value is in terms of 32-bit words.
> - * Minimum value is 16
> - * Maximum value is 32768
> - * @nptxfstaddr: Non-Periodic Transmit RAM Start Address (NPTxFStAddr)
> - * This field contains the memory start address for Non-Periodic
> - * Transmit FIFO RAM.
> - */
> - struct cvmx_usbcx_gnptxfsiz_s {
> - __BITFIELD_FIELD(u32 nptxfdep : 16,
> - __BITFIELD_FIELD(u32 nptxfstaddr : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_gnptxsts
> - *
> - * Non-Periodic Transmit FIFO/Queue Status Register (GNPTXSTS)
> - *
> - * This read-only register contains the free space information for the
> - * Non-Periodic TxFIFO and the Non-Periodic Transmit Request Queue.
> - */
> -union cvmx_usbcx_gnptxsts {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gnptxsts_s
> - * @nptxqtop: Top of the Non-Periodic Transmit Request Queue (NPTxQTop)
> - * Entry in the Non-Periodic Tx Request Queue that is currently
> - * being processed by the MAC.
> - * * Bits [30:27]: Channel/endpoint number
> - * * Bits [26:25]:
> - * - 2'b00: IN/OUT token
> - * - 2'b01: Zero-length transmit packet (device IN/host OUT)
> - * - 2'b10: PING/CSPLIT token
> - * - 2'b11: Channel halt command
> - * * Bit [24]: Terminate (last entry for selected channel/endpoint)
> - * @nptxqspcavail: Non-Periodic Transmit Request Queue Space Available
> - * (NPTxQSpcAvail)
> - * Indicates the amount of free space available in the Non-
> - * Periodic Transmit Request Queue. This queue holds both IN
> - * and OUT requests in Host mode. Device mode has only IN
> - * requests.
> - * * 8'h0: Non-Periodic Transmit Request Queue is full
> - * * 8'h1: 1 location available
> - * * 8'h2: 2 locations available
> - * * n: n locations available (0..8)
> - * * Others: Reserved
> - * @nptxfspcavail: Non-Periodic TxFIFO Space Avail (NPTxFSpcAvail)
> - * Indicates the amount of free space available in the Non-
> - * Periodic TxFIFO.
> - * Values are in terms of 32-bit words.
> - * * 16'h0: Non-Periodic TxFIFO is full
> - * * 16'h1: 1 word available
> - * * 16'h2: 2 words available
> - * * 16'hn: n words available (where 0..32768)
> - * * 16'h8000: 32768 words available
> - * * Others: Reserved
> - */
> - struct cvmx_usbcx_gnptxsts_s {
> - __BITFIELD_FIELD(u32 reserved_31_31 : 1,
> - __BITFIELD_FIELD(u32 nptxqtop : 7,
> - __BITFIELD_FIELD(u32 nptxqspcavail : 8,
> - __BITFIELD_FIELD(u32 nptxfspcavail : 16,
> - ;))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_grstctl
> - *
> - * Core Reset Register (GRSTCTL)
> - *
> - * The application uses this register to reset various hardware features inside
> - * the core.
> - */
> -union cvmx_usbcx_grstctl {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_grstctl_s
> - * @ahbidle: AHB Master Idle (AHBIdle)
> - * Indicates that the AHB Master State Machine is in the IDLE
> - * condition.
> - * @dmareq: DMA Request Signal (DMAReq)
> - * Indicates that the DMA request is in progress. Used for debug.
> - * @txfnum: TxFIFO Number (TxFNum)
> - * This is the FIFO number that must be flushed using the TxFIFO
> - * Flush bit. This field must not be changed until the core clears
> - * the TxFIFO Flush bit.
> - * * 5'h0: Non-Periodic TxFIFO flush
> - * * 5'h1: Periodic TxFIFO 1 flush in Device mode or Periodic
> - * TxFIFO flush in Host mode
> - * * 5'h2: Periodic TxFIFO 2 flush in Device mode
> - * - ...
> - * * 5'hF: Periodic TxFIFO 15 flush in Device mode
> - * * 5'h10: Flush all the Periodic and Non-Periodic TxFIFOs in the
> - * core
> - * @txfflsh: TxFIFO Flush (TxFFlsh)
> - * This bit selectively flushes a single or all transmit FIFOs, but
> - * cannot do so if the core is in the midst of a transaction.
> - * The application must only write this bit after checking that the
> - * core is neither writing to the TxFIFO nor reading from the
> - * TxFIFO.
> - * The application must wait until the core clears this bit before
> - * performing any operations. This bit takes 8 clocks (of phy_clk
> - * or hclk, whichever is slower) to clear.
> - * @rxfflsh: RxFIFO Flush (RxFFlsh)
> - * The application can flush the entire RxFIFO using this bit, but
> - * must first ensure that the core is not in the middle of a
> - * transaction.
> - * The application must only write to this bit after checking that
> - * the core is neither reading from the RxFIFO nor writing to the
> - * RxFIFO.
> - * The application must wait until the bit is cleared before
> - * performing any other operations. This bit will take 8 clocks
> - * (slowest of PHY or AHB clock) to clear.
> - * @intknqflsh: IN Token Sequence Learning Queue Flush (INTknQFlsh)
> - * The application writes this bit to flush the IN Token Sequence
> - * Learning Queue.
> - * @frmcntrrst: Host Frame Counter Reset (FrmCntrRst)
> - * The application writes this bit to reset the (micro)frame number
> - * counter inside the core. When the (micro)frame counter is reset,
> - * the subsequent SOF sent out by the core will have a
> - * (micro)frame number of 0.
> - * @hsftrst: HClk Soft Reset (HSftRst)
> - * The application uses this bit to flush the control logic in the
> - * AHB Clock domain. Only AHB Clock Domain pipelines are reset.
> - * * FIFOs are not flushed with this bit.
> - * * All state machines in the AHB clock domain are reset to the
> - * Idle state after terminating the transactions on the AHB,
> - * following the protocol.
> - * * CSR control bits used by the AHB clock domain state
> - * machines are cleared.
> - * * To clear this interrupt, status mask bits that control the
> - * interrupt status and are generated by the AHB clock domain
> - * state machine are cleared.
> - * * Because interrupt status bits are not cleared, the application
> - * can get the status of any core events that occurred after it set
> - * this bit.
> - * This is a self-clearing bit that the core clears after all
> - * necessary logic is reset in the core. This may take several
> - * clocks, depending on the core's current state.
> - * @csftrst: Core Soft Reset (CSftRst)
> - * Resets the hclk and phy_clock domains as follows:
> - * * Clears the interrupts and all the CSR registers except the
> - * following register bits:
> - * - PCGCCTL.RstPdwnModule
> - * - PCGCCTL.GateHclk
> - * - PCGCCTL.PwrClmp
> - * - PCGCCTL.StopPPhyLPwrClkSelclk
> - * - GUSBCFG.PhyLPwrClkSel
> - * - GUSBCFG.DDRSel
> - * - GUSBCFG.PHYSel
> - * - GUSBCFG.FSIntf
> - * - GUSBCFG.ULPI_UTMI_Sel
> - * - GUSBCFG.PHYIf
> - * - HCFG.FSLSPclkSel
> - * - DCFG.DevSpd
> - * * All module state machines (except the AHB Slave Unit) are
> - * reset to the IDLE state, and all the transmit FIFOs and the
> - * receive FIFO are flushed.
> - * * Any transactions on the AHB Master are terminated as soon
> - * as possible, after gracefully completing the last data phase of
> - * an AHB transfer. Any transactions on the USB are terminated
> - * immediately.
> - * The application can write to this bit any time it wants to reset
> - * the core. This is a self-clearing bit and the core clears this
> - * bit after all the necessary logic is reset in the core, which
> - * may take several clocks, depending on the current state of the
> - * core. Once this bit is cleared software should wait at least 3
> - * PHY clocks before doing any access to the PHY domain
> - * (synchronization delay). Software should also should check that
> - * bit 31 of this register is 1 (AHB Master is IDLE) before
> - * starting any operation.
> - * Typically software reset is used during software development
> - * and also when you dynamically change the PHY selection bits
> - * in the USB configuration registers listed above. When you
> - * change the PHY, the corresponding clock for the PHY is
> - * selected and used in the PHY domain. Once a new clock is
> - * selected, the PHY domain has to be reset for proper operation.
> - */
> - struct cvmx_usbcx_grstctl_s {
> - __BITFIELD_FIELD(u32 ahbidle : 1,
> - __BITFIELD_FIELD(u32 dmareq : 1,
> - __BITFIELD_FIELD(u32 reserved_11_29 : 19,
> - __BITFIELD_FIELD(u32 txfnum : 5,
> - __BITFIELD_FIELD(u32 txfflsh : 1,
> - __BITFIELD_FIELD(u32 rxfflsh : 1,
> - __BITFIELD_FIELD(u32 intknqflsh : 1,
> - __BITFIELD_FIELD(u32 frmcntrrst : 1,
> - __BITFIELD_FIELD(u32 hsftrst : 1,
> - __BITFIELD_FIELD(u32 csftrst : 1,
> - ;))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_grxfsiz
> - *
> - * Receive FIFO Size Register (GRXFSIZ)
> - *
> - * The application can program the RAM size that must be allocated to the
> - * RxFIFO.
> - */
> -union cvmx_usbcx_grxfsiz {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_grxfsiz_s
> - * @rxfdep: RxFIFO Depth (RxFDep)
> - * This value is in terms of 32-bit words.
> - * * Minimum value is 16
> - * * Maximum value is 32768
> - */
> - struct cvmx_usbcx_grxfsiz_s {
> - __BITFIELD_FIELD(u32 reserved_16_31 : 16,
> - __BITFIELD_FIELD(u32 rxfdep : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_grxstsph
> - *
> - * Receive Status Read and Pop Register, Host Mode (GRXSTSPH)
> - *
> - * A read to the Receive Status Read and Pop register returns and additionally
> - * pops the top data entry out of the RxFIFO.
> - * This Description is only valid when the core is in Host Mode. For Device Mode
> - * use USBC_GRXSTSPD instead.
> - * NOTE: GRXSTSPH and GRXSTSPD are physically the same register and share the
> - * same offset in the O2P USB core. The offset difference shown in this
> - * document is for software clarity and is actually ignored by the
> - * hardware.
> - */
> -union cvmx_usbcx_grxstsph {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_grxstsph_s
> - * @pktsts: Packet Status (PktSts)
> - * Indicates the status of the received packet
> - * * 4'b0010: IN data packet received
> - * * 4'b0011: IN transfer completed (triggers an interrupt)
> - * * 4'b0101: Data toggle error (triggers an interrupt)
> - * * 4'b0111: Channel halted (triggers an interrupt)
> - * * Others: Reserved
> - * @dpid: Data PID (DPID)
> - * * 2'b00: DATA0
> - * * 2'b10: DATA1
> - * * 2'b01: DATA2
> - * * 2'b11: MDATA
> - * @bcnt: Byte Count (BCnt)
> - * Indicates the byte count of the received IN data packet
> - * @chnum: Channel Number (ChNum)
> - * Indicates the channel number to which the current received
> - * packet belongs.
> - */
> - struct cvmx_usbcx_grxstsph_s {
> - __BITFIELD_FIELD(u32 reserved_21_31 : 11,
> - __BITFIELD_FIELD(u32 pktsts : 4,
> - __BITFIELD_FIELD(u32 dpid : 2,
> - __BITFIELD_FIELD(u32 bcnt : 11,
> - __BITFIELD_FIELD(u32 chnum : 4,
> - ;)))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_gusbcfg
> - *
> - * Core USB Configuration Register (GUSBCFG)
> - *
> - * This register can be used to configure the core after power-on or a changing
> - * to Host mode or Device mode. It contains USB and USB-PHY related
> - * configuration parameters. The application must program this register before
> - * starting any transactions on either the AHB or the USB. Do not make changes
> - * to this register after the initial programming.
> - */
> -union cvmx_usbcx_gusbcfg {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_gusbcfg_s
> - * @otgi2csel: UTMIFS or I2C Interface Select (OtgI2CSel)
> - * This bit is always 0x0.
> - * @phylpwrclksel: PHY Low-Power Clock Select (PhyLPwrClkSel)
> - * Software should set this bit to 0x0.
> - * Selects either 480-MHz or 48-MHz (low-power) PHY mode. In
> - * FS and LS modes, the PHY can usually operate on a 48-MHz
> - * clock to save power.
> - * * 1'b0: 480-MHz Internal PLL clock
> - * * 1'b1: 48-MHz External Clock
> - * In 480 MHz mode, the UTMI interface operates at either 60 or
> - * 30-MHz, depending upon whether 8- or 16-bit data width is
> - * selected. In 48-MHz mode, the UTMI interface operates at 48
> - * MHz in FS mode and at either 48 or 6 MHz in LS mode
> - * (depending on the PHY vendor).
> - * This bit drives the utmi_fsls_low_power core output signal, and
> - * is valid only for UTMI+ PHYs.
> - * @usbtrdtim: USB Turnaround Time (USBTrdTim)
> - * Sets the turnaround time in PHY clocks.
> - * Specifies the response time for a MAC request to the Packet
> - * FIFO Controller (PFC) to fetch data from the DFIFO (SPRAM).
> - * This must be programmed to 0x5.
> - * @hnpcap: HNP-Capable (HNPCap)
> - * This bit is always 0x0.
> - * @srpcap: SRP-Capable (SRPCap)
> - * This bit is always 0x0.
> - * @ddrsel: ULPI DDR Select (DDRSel)
> - * Software should set this bit to 0x0.
> - * @physel: USB 2.0 High-Speed PHY or USB 1.1 Full-Speed Serial
> - * Software should set this bit to 0x0.
> - * @fsintf: Full-Speed Serial Interface Select (FSIntf)
> - * Software should set this bit to 0x0.
> - * @ulpi_utmi_sel: ULPI or UTMI+ Select (ULPI_UTMI_Sel)
> - * This bit is always 0x0.
> - * @phyif: PHY Interface (PHYIf)
> - * This bit is always 0x1.
> - * @toutcal: HS/FS Timeout Calibration (TOutCal)
> - * The number of PHY clocks that the application programs in this
> - * field is added to the high-speed/full-speed interpacket timeout
> - * duration in the core to account for any additional delays
> - * introduced by the PHY. This may be required, since the delay
> - * introduced by the PHY in generating the linestate condition may
> - * vary from one PHY to another.
> - * The USB standard timeout value for high-speed operation is
> - * 736 to 816 (inclusive) bit times. The USB standard timeout
> - * value for full-speed operation is 16 to 18 (inclusive) bit
> - * times. The application must program this field based on the
> - * speed of enumeration. The number of bit times added per PHY
> - * clock are:
> - * High-speed operation:
> - * * One 30-MHz PHY clock = 16 bit times
> - * * One 60-MHz PHY clock = 8 bit times
> - * Full-speed operation:
> - * * One 30-MHz PHY clock = 0.4 bit times
> - * * One 60-MHz PHY clock = 0.2 bit times
> - * * One 48-MHz PHY clock = 0.25 bit times
> - */
> - struct cvmx_usbcx_gusbcfg_s {
> - __BITFIELD_FIELD(u32 reserved_17_31 : 15,
> - __BITFIELD_FIELD(u32 otgi2csel : 1,
> - __BITFIELD_FIELD(u32 phylpwrclksel : 1,
> - __BITFIELD_FIELD(u32 reserved_14_14 : 1,
> - __BITFIELD_FIELD(u32 usbtrdtim : 4,
> - __BITFIELD_FIELD(u32 hnpcap : 1,
> - __BITFIELD_FIELD(u32 srpcap : 1,
> - __BITFIELD_FIELD(u32 ddrsel : 1,
> - __BITFIELD_FIELD(u32 physel : 1,
> - __BITFIELD_FIELD(u32 fsintf : 1,
> - __BITFIELD_FIELD(u32 ulpi_utmi_sel : 1,
> - __BITFIELD_FIELD(u32 phyif : 1,
> - __BITFIELD_FIELD(u32 toutcal : 3,
> - ;)))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_haint
> - *
> - * Host All Channels Interrupt Register (HAINT)
> - *
> - * When a significant event occurs on a channel, the Host All Channels Interrupt
> - * register interrupts the application using the Host Channels Interrupt bit of
> - * the Core Interrupt register (GINTSTS.HChInt). This is shown in Interrupt.
> - * There is one interrupt bit per channel, up to a maximum of 16 bits. Bits in
> - * this register are set and cleared when the application sets and clears bits
> - * in the corresponding Host Channel-n Interrupt register.
> - */
> -union cvmx_usbcx_haint {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_haint_s
> - * @haint: Channel Interrupts (HAINT)
> - * One bit per channel: Bit 0 for Channel 0, bit 15 for Channel 15
> - */
> - struct cvmx_usbcx_haint_s {
> - __BITFIELD_FIELD(u32 reserved_16_31 : 16,
> - __BITFIELD_FIELD(u32 haint : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_haintmsk
> - *
> - * Host All Channels Interrupt Mask Register (HAINTMSK)
> - *
> - * The Host All Channel Interrupt Mask register works with the Host All Channel
> - * Interrupt register to interrupt the application when an event occurs on a
> - * channel. There is one interrupt mask bit per channel, up to a maximum of 16
> - * bits.
> - * Mask interrupt: 1'b0 Unmask interrupt: 1'b1
> - */
> -union cvmx_usbcx_haintmsk {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_haintmsk_s
> - * @haintmsk: Channel Interrupt Mask (HAINTMsk)
> - * One bit per channel: Bit 0 for channel 0, bit 15 for channel 15
> - */
> - struct cvmx_usbcx_haintmsk_s {
> - __BITFIELD_FIELD(u32 reserved_16_31 : 16,
> - __BITFIELD_FIELD(u32 haintmsk : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hcchar#
> - *
> - * Host Channel-n Characteristics Register (HCCHAR)
> - *
> - */
> -union cvmx_usbcx_hccharx {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hccharx_s
> - * @chena: Channel Enable (ChEna)
> - * This field is set by the application and cleared by the OTG
> - * host.
> - * * 1'b0: Channel disabled
> - * * 1'b1: Channel enabled
> - * @chdis: Channel Disable (ChDis)
> - * The application sets this bit to stop transmitting/receiving
> - * data on a channel, even before the transfer for that channel is
> - * complete. The application must wait for the Channel Disabled
> - * interrupt before treating the channel as disabled.
> - * @oddfrm: Odd Frame (OddFrm)
> - * This field is set (reset) by the application to indicate that
> - * the OTG host must perform a transfer in an odd (micro)frame.
> - * This field is applicable for only periodic (isochronous and
> - * interrupt) transactions.
> - * * 1'b0: Even (micro)frame
> - * * 1'b1: Odd (micro)frame
> - * @devaddr: Device Address (DevAddr)
> - * This field selects the specific device serving as the data
> - * source or sink.
> - * @ec: Multi Count (MC) / Error Count (EC)
> - * When the Split Enable bit of the Host Channel-n Split Control
> - * register (HCSPLTn.SpltEna) is reset (1'b0), this field indicates
> - * to the host the number of transactions that should be executed
> - * per microframe for this endpoint.
> - * * 2'b00: Reserved. This field yields undefined results.
> - * * 2'b01: 1 transaction
> - * * 2'b10: 2 transactions to be issued for this endpoint per
> - * microframe
> - * * 2'b11: 3 transactions to be issued for this endpoint per
> - * microframe
> - * When HCSPLTn.SpltEna is set (1'b1), this field indicates the
> - * number of immediate retries to be performed for a periodic split
> - * transactions on transaction errors. This field must be set to at
> - * least 2'b01.
> - * @eptype: Endpoint Type (EPType)
> - * Indicates the transfer type selected.
> - * * 2'b00: Control
> - * * 2'b01: Isochronous
> - * * 2'b10: Bulk
> - * * 2'b11: Interrupt
> - * @lspddev: Low-Speed Device (LSpdDev)
> - * This field is set by the application to indicate that this
> - * channel is communicating to a low-speed device.
> - * @epdir: Endpoint Direction (EPDir)
> - * Indicates whether the transaction is IN or OUT.
> - * * 1'b0: OUT
> - * * 1'b1: IN
> - * @epnum: Endpoint Number (EPNum)
> - * Indicates the endpoint number on the device serving as the
> - * data source or sink.
> - * @mps: Maximum Packet Size (MPS)
> - * Indicates the maximum packet size of the associated endpoint.
> - */
> - struct cvmx_usbcx_hccharx_s {
> - __BITFIELD_FIELD(u32 chena : 1,
> - __BITFIELD_FIELD(u32 chdis : 1,
> - __BITFIELD_FIELD(u32 oddfrm : 1,
> - __BITFIELD_FIELD(u32 devaddr : 7,
> - __BITFIELD_FIELD(u32 ec : 2,
> - __BITFIELD_FIELD(u32 eptype : 2,
> - __BITFIELD_FIELD(u32 lspddev : 1,
> - __BITFIELD_FIELD(u32 reserved_16_16 : 1,
> - __BITFIELD_FIELD(u32 epdir : 1,
> - __BITFIELD_FIELD(u32 epnum : 4,
> - __BITFIELD_FIELD(u32 mps : 11,
> - ;)))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hcfg
> - *
> - * Host Configuration Register (HCFG)
> - *
> - * This register configures the core after power-on. Do not make changes to this
> - * register after initializing the host.
> - */
> -union cvmx_usbcx_hcfg {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hcfg_s
> - * @fslssupp: FS- and LS-Only Support (FSLSSupp)
> - * The application uses this bit to control the core's enumeration
> - * speed. Using this bit, the application can make the core
> - * enumerate as a FS host, even if the connected device supports
> - * HS traffic. Do not make changes to this field after initial
> - * programming.
> - * * 1'b0: HS/FS/LS, based on the maximum speed supported by
> - * the connected device
> - * * 1'b1: FS/LS-only, even if the connected device can support HS
> - * @fslspclksel: FS/LS PHY Clock Select (FSLSPclkSel)
> - * When the core is in FS Host mode
> - * * 2'b00: PHY clock is running at 30/60 MHz
> - * * 2'b01: PHY clock is running at 48 MHz
> - * * Others: Reserved
> - * When the core is in LS Host mode
> - * * 2'b00: PHY clock is running at 30/60 MHz. When the
> - * UTMI+/ULPI PHY Low Power mode is not selected, use
> - * 30/60 MHz.
> - * * 2'b01: PHY clock is running at 48 MHz. When the UTMI+
> - * PHY Low Power mode is selected, use 48MHz if the PHY
> - * supplies a 48 MHz clock during LS mode.
> - * * 2'b10: PHY clock is running at 6 MHz. In USB 1.1 FS mode,
> - * use 6 MHz when the UTMI+ PHY Low Power mode is
> - * selected and the PHY supplies a 6 MHz clock during LS
> - * mode. If you select a 6 MHz clock during LS mode, you must
> - * do a soft reset.
> - * * 2'b11: Reserved
> - */
> - struct cvmx_usbcx_hcfg_s {
> - __BITFIELD_FIELD(u32 reserved_3_31 : 29,
> - __BITFIELD_FIELD(u32 fslssupp : 1,
> - __BITFIELD_FIELD(u32 fslspclksel : 2,
> - ;)))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hcint#
> - *
> - * Host Channel-n Interrupt Register (HCINT)
> - *
> - * This register indicates the status of a channel with respect to USB- and
> - * AHB-related events. The application must read this register when the Host
> - * Channels Interrupt bit of the Core Interrupt register (GINTSTS.HChInt) is
> - * set. Before the application can read this register, it must first read
> - * the Host All Channels Interrupt (HAINT) register to get the exact channel
> - * number for the Host Channel-n Interrupt register. The application must clear
> - * the appropriate bit in this register to clear the corresponding bits in the
> - * HAINT and GINTSTS registers.
> - */
> -union cvmx_usbcx_hcintx {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hcintx_s
> - * @datatglerr: Data Toggle Error (DataTglErr)
> - * @frmovrun: Frame Overrun (FrmOvrun)
> - * @bblerr: Babble Error (BblErr)
> - * @xacterr: Transaction Error (XactErr)
> - * @nyet: NYET Response Received Interrupt (NYET)
> - * @ack: ACK Response Received Interrupt (ACK)
> - * @nak: NAK Response Received Interrupt (NAK)
> - * @stall: STALL Response Received Interrupt (STALL)
> - * @ahberr: This bit is always 0x0.
> - * @chhltd: Channel Halted (ChHltd)
> - * Indicates the transfer completed abnormally either because of
> - * any USB transaction error or in response to disable request by
> - * the application.
> - * @xfercompl: Transfer Completed (XferCompl)
> - * Transfer completed normally without any errors.
> - */
> - struct cvmx_usbcx_hcintx_s {
> - __BITFIELD_FIELD(u32 reserved_11_31 : 21,
> - __BITFIELD_FIELD(u32 datatglerr : 1,
> - __BITFIELD_FIELD(u32 frmovrun : 1,
> - __BITFIELD_FIELD(u32 bblerr : 1,
> - __BITFIELD_FIELD(u32 xacterr : 1,
> - __BITFIELD_FIELD(u32 nyet : 1,
> - __BITFIELD_FIELD(u32 ack : 1,
> - __BITFIELD_FIELD(u32 nak : 1,
> - __BITFIELD_FIELD(u32 stall : 1,
> - __BITFIELD_FIELD(u32 ahberr : 1,
> - __BITFIELD_FIELD(u32 chhltd : 1,
> - __BITFIELD_FIELD(u32 xfercompl : 1,
> - ;))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hcintmsk#
> - *
> - * Host Channel-n Interrupt Mask Register (HCINTMSKn)
> - *
> - * This register reflects the mask for each channel status described in the
> - * previous section.
> - * Mask interrupt: 1'b0 Unmask interrupt: 1'b1
> - */
> -union cvmx_usbcx_hcintmskx {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hcintmskx_s
> - * @datatglerrmsk: Data Toggle Error Mask (DataTglErrMsk)
> - * @frmovrunmsk: Frame Overrun Mask (FrmOvrunMsk)
> - * @bblerrmsk: Babble Error Mask (BblErrMsk)
> - * @xacterrmsk: Transaction Error Mask (XactErrMsk)
> - * @nyetmsk: NYET Response Received Interrupt Mask (NyetMsk)
> - * @ackmsk: ACK Response Received Interrupt Mask (AckMsk)
> - * @nakmsk: NAK Response Received Interrupt Mask (NakMsk)
> - * @stallmsk: STALL Response Received Interrupt Mask (StallMsk)
> - * @ahberrmsk: AHB Error Mask (AHBErrMsk)
> - * @chhltdmsk: Channel Halted Mask (ChHltdMsk)
> - * @xfercomplmsk: Transfer Completed Mask (XferComplMsk)
> - */
> - struct cvmx_usbcx_hcintmskx_s {
> - __BITFIELD_FIELD(u32 reserved_11_31 : 21,
> - __BITFIELD_FIELD(u32 datatglerrmsk : 1,
> - __BITFIELD_FIELD(u32 frmovrunmsk : 1,
> - __BITFIELD_FIELD(u32 bblerrmsk : 1,
> - __BITFIELD_FIELD(u32 xacterrmsk : 1,
> - __BITFIELD_FIELD(u32 nyetmsk : 1,
> - __BITFIELD_FIELD(u32 ackmsk : 1,
> - __BITFIELD_FIELD(u32 nakmsk : 1,
> - __BITFIELD_FIELD(u32 stallmsk : 1,
> - __BITFIELD_FIELD(u32 ahberrmsk : 1,
> - __BITFIELD_FIELD(u32 chhltdmsk : 1,
> - __BITFIELD_FIELD(u32 xfercomplmsk : 1,
> - ;))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hcsplt#
> - *
> - * Host Channel-n Split Control Register (HCSPLT)
> - *
> - */
> -union cvmx_usbcx_hcspltx {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hcspltx_s
> - * @spltena: Split Enable (SpltEna)
> - * The application sets this field to indicate that this channel is
> - * enabled to perform split transactions.
> - * @compsplt: Do Complete Split (CompSplt)
> - * The application sets this field to request the OTG host to
> - * perform a complete split transaction.
> - * @xactpos: Transaction Position (XactPos)
> - * This field is used to determine whether to send all, first,
> - * middle, or last payloads with each OUT transaction.
> - * * 2'b11: All. This is the entire data payload is of this
> - * transaction (which is less than or equal to 188 bytes).
> - * * 2'b10: Begin. This is the first data payload of this
> - * transaction (which is larger than 188 bytes).
> - * * 2'b00: Mid. This is the middle payload of this transaction
> - * (which is larger than 188 bytes).
> - * * 2'b01: End. This is the last payload of this transaction
> - * (which is larger than 188 bytes).
> - * @hubaddr: Hub Address (HubAddr)
> - * This field holds the device address of the transaction
> - * translator's hub.
> - * @prtaddr: Port Address (PrtAddr)
> - * This field is the port number of the recipient transaction
> - * translator.
> - */
> - struct cvmx_usbcx_hcspltx_s {
> - __BITFIELD_FIELD(u32 spltena : 1,
> - __BITFIELD_FIELD(u32 reserved_17_30 : 14,
> - __BITFIELD_FIELD(u32 compsplt : 1,
> - __BITFIELD_FIELD(u32 xactpos : 2,
> - __BITFIELD_FIELD(u32 hubaddr : 7,
> - __BITFIELD_FIELD(u32 prtaddr : 7,
> - ;))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hctsiz#
> - *
> - * Host Channel-n Transfer Size Register (HCTSIZ)
> - *
> - */
> -union cvmx_usbcx_hctsizx {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hctsizx_s
> - * @dopng: Do Ping (DoPng)
> - * Setting this field to 1 directs the host to do PING protocol.
> - * @pid: PID (Pid)
> - * The application programs this field with the type of PID to use
> - * for the initial transaction. The host will maintain this field
> - * for the rest of the transfer.
> - * * 2'b00: DATA0
> - * * 2'b01: DATA2
> - * * 2'b10: DATA1
> - * * 2'b11: MDATA (non-control)/SETUP (control)
> - * @pktcnt: Packet Count (PktCnt)
> - * This field is programmed by the application with the expected
> - * number of packets to be transmitted (OUT) or received (IN).
> - * The host decrements this count on every successful
> - * transmission or reception of an OUT/IN packet. Once this count
> - * reaches zero, the application is interrupted to indicate normal
> - * completion.
> - * @xfersize: Transfer Size (XferSize)
> - * For an OUT, this field is the number of data bytes the host will
> - * send during the transfer.
> - * For an IN, this field is the buffer size that the application
> - * has reserved for the transfer. The application is expected to
> - * program this field as an integer multiple of the maximum packet
> - * size for IN transactions (periodic and non-periodic).
> - */
> - struct cvmx_usbcx_hctsizx_s {
> - __BITFIELD_FIELD(u32 dopng : 1,
> - __BITFIELD_FIELD(u32 pid : 2,
> - __BITFIELD_FIELD(u32 pktcnt : 10,
> - __BITFIELD_FIELD(u32 xfersize : 19,
> - ;))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hfir
> - *
> - * Host Frame Interval Register (HFIR)
> - *
> - * This register stores the frame interval information for the current speed to
> - * which the O2P USB core has enumerated.
> - */
> -union cvmx_usbcx_hfir {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hfir_s
> - * @frint: Frame Interval (FrInt)
> - * The value that the application programs to this field specifies
> - * the interval between two consecutive SOFs (FS) or micro-
> - * SOFs (HS) or Keep-Alive tokens (HS). This field contains the
> - * number of PHY clocks that constitute the required frame
> - * interval. The default value set in this field for a FS operation
> - * when the PHY clock frequency is 60 MHz. The application can
> - * write a value to this register only after the Port Enable bit of
> - * the Host Port Control and Status register (HPRT.PrtEnaPort)
> - * has been set. If no value is programmed, the core calculates
> - * the value based on the PHY clock specified in the FS/LS PHY
> - * Clock Select field of the Host Configuration register
> - * (HCFG.FSLSPclkSel). Do not change the value of this field
> - * after the initial configuration.
> - * * 125 us (PHY clock frequency for HS)
> - * * 1 ms (PHY clock frequency for FS/LS)
> - */
> - struct cvmx_usbcx_hfir_s {
> - __BITFIELD_FIELD(u32 reserved_16_31 : 16,
> - __BITFIELD_FIELD(u32 frint : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hfnum
> - *
> - * Host Frame Number/Frame Time Remaining Register (HFNUM)
> - *
> - * This register indicates the current frame number.
> - * It also indicates the time remaining (in terms of the number of PHY clocks)
> - * in the current (micro)frame.
> - */
> -union cvmx_usbcx_hfnum {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hfnum_s
> - * @frrem: Frame Time Remaining (FrRem)
> - * Indicates the amount of time remaining in the current
> - * microframe (HS) or frame (FS/LS), in terms of PHY clocks.
> - * This field decrements on each PHY clock. When it reaches
> - * zero, this field is reloaded with the value in the Frame
> - * Interval register and a new SOF is transmitted on the USB.
> - * @frnum: Frame Number (FrNum)
> - * This field increments when a new SOF is transmitted on the
> - * USB, and is reset to 0 when it reaches 16'h3FFF.
> - */
> - struct cvmx_usbcx_hfnum_s {
> - __BITFIELD_FIELD(u32 frrem : 16,
> - __BITFIELD_FIELD(u32 frnum : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hprt
> - *
> - * Host Port Control and Status Register (HPRT)
> - *
> - * This register is available in both Host and Device modes.
> - * Currently, the OTG Host supports only one port.
> - * A single register holds USB port-related information such as USB reset,
> - * enable, suspend, resume, connect status, and test mode for each port. The
> - * R_SS_WC bits in this register can trigger an interrupt to the application
> - * through the Host Port Interrupt bit of the Core Interrupt register
> - * (GINTSTS.PrtInt). On a Port Interrupt, the application must read this
> - * register and clear the bit that caused the interrupt. For the R_SS_WC bits,
> - * the application must write a 1 to the bit to clear the interrupt.
> - */
> -union cvmx_usbcx_hprt {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hprt_s
> - * @prtspd: Port Speed (PrtSpd)
> - * Indicates the speed of the device attached to this port.
> - * * 2'b00: High speed
> - * * 2'b01: Full speed
> - * * 2'b10: Low speed
> - * * 2'b11: Reserved
> - * @prttstctl: Port Test Control (PrtTstCtl)
> - * The application writes a nonzero value to this field to put
> - * the port into a Test mode, and the corresponding pattern is
> - * signaled on the port.
> - * * 4'b0000: Test mode disabled
> - * * 4'b0001: Test_J mode
> - * * 4'b0010: Test_K mode
> - * * 4'b0011: Test_SE0_NAK mode
> - * * 4'b0100: Test_Packet mode
> - * * 4'b0101: Test_Force_Enable
> - * * Others: Reserved
> - * PrtSpd must be zero (i.e. the interface must be in high-speed
> - * mode) to use the PrtTstCtl test modes.
> - * @prtpwr: Port Power (PrtPwr)
> - * The application uses this field to control power to this port,
> - * and the core clears this bit on an overcurrent condition.
> - * * 1'b0: Power off
> - * * 1'b1: Power on
> - * @prtlnsts: Port Line Status (PrtLnSts)
> - * Indicates the current logic level USB data lines
> - * * Bit [10]: Logic level of D-
> - * * Bit [11]: Logic level of D+
> - * @prtrst: Port Reset (PrtRst)
> - * When the application sets this bit, a reset sequence is
> - * started on this port. The application must time the reset
> - * period and clear this bit after the reset sequence is
> - * complete.
> - * * 1'b0: Port not in reset
> - * * 1'b1: Port in reset
> - * The application must leave this bit set for at least a
> - * minimum duration mentioned below to start a reset on the
> - * port. The application can leave it set for another 10 ms in
> - * addition to the required minimum duration, before clearing
> - * the bit, even though there is no maximum limit set by the
> - * USB standard.
> - * * High speed: 50 ms
> - * * Full speed/Low speed: 10 ms
> - * @prtsusp: Port Suspend (PrtSusp)
> - * The application sets this bit to put this port in Suspend
> - * mode. The core only stops sending SOFs when this is set.
> - * To stop the PHY clock, the application must set the Port
> - * Clock Stop bit, which will assert the suspend input pin of
> - * the PHY.
> - * The read value of this bit reflects the current suspend
> - * status of the port. This bit is cleared by the core after a
> - * remote wakeup signal is detected or the application sets
> - * the Port Reset bit or Port Resume bit in this register or the
> - * Resume/Remote Wakeup Detected Interrupt bit or
> - * Disconnect Detected Interrupt bit in the Core Interrupt
> - * register (GINTSTS.WkUpInt or GINTSTS.DisconnInt,
> - * respectively).
> - * * 1'b0: Port not in Suspend mode
> - * * 1'b1: Port in Suspend mode
> - * @prtres: Port Resume (PrtRes)
> - * The application sets this bit to drive resume signaling on
> - * the port. The core continues to drive the resume signal
> - * until the application clears this bit.
> - * If the core detects a USB remote wakeup sequence, as
> - * indicated by the Port Resume/Remote Wakeup Detected
> - * Interrupt bit of the Core Interrupt register
> - * (GINTSTS.WkUpInt), the core starts driving resume
> - * signaling without application intervention and clears this bit
> - * when it detects a disconnect condition. The read value of
> - * this bit indicates whether the core is currently driving
> - * resume signaling.
> - * * 1'b0: No resume driven
> - * * 1'b1: Resume driven
> - * @prtovrcurrchng: Port Overcurrent Change (PrtOvrCurrChng)
> - * The core sets this bit when the status of the Port
> - * Overcurrent Active bit (bit 4) in this register changes.
> - * @prtovrcurract: Port Overcurrent Active (PrtOvrCurrAct)
> - * Indicates the overcurrent condition of the port.
> - * * 1'b0: No overcurrent condition
> - * * 1'b1: Overcurrent condition
> - * @prtenchng: Port Enable/Disable Change (PrtEnChng)
> - * The core sets this bit when the status of the Port Enable bit
> - * [2] of this register changes.
> - * @prtena: Port Enable (PrtEna)
> - * A port is enabled only by the core after a reset sequence,
> - * and is disabled by an overcurrent condition, a disconnect
> - * condition, or by the application clearing this bit. The
> - * application cannot set this bit by a register write. It can only
> - * clear it to disable the port. This bit does not trigger any
> - * interrupt to the application.
> - * * 1'b0: Port disabled
> - * * 1'b1: Port enabled
> - * @prtconndet: Port Connect Detected (PrtConnDet)
> - * The core sets this bit when a device connection is detected
> - * to trigger an interrupt to the application using the Host Port
> - * Interrupt bit of the Core Interrupt register (GINTSTS.PrtInt).
> - * The application must write a 1 to this bit to clear the
> - * interrupt.
> - * @prtconnsts: Port Connect Status (PrtConnSts)
> - * * 0: No device is attached to the port.
> - * * 1: A device is attached to the port.
> - */
> - struct cvmx_usbcx_hprt_s {
> - __BITFIELD_FIELD(u32 reserved_19_31 : 13,
> - __BITFIELD_FIELD(u32 prtspd : 2,
> - __BITFIELD_FIELD(u32 prttstctl : 4,
> - __BITFIELD_FIELD(u32 prtpwr : 1,
> - __BITFIELD_FIELD(u32 prtlnsts : 2,
> - __BITFIELD_FIELD(u32 reserved_9_9 : 1,
> - __BITFIELD_FIELD(u32 prtrst : 1,
> - __BITFIELD_FIELD(u32 prtsusp : 1,
> - __BITFIELD_FIELD(u32 prtres : 1,
> - __BITFIELD_FIELD(u32 prtovrcurrchng : 1,
> - __BITFIELD_FIELD(u32 prtovrcurract : 1,
> - __BITFIELD_FIELD(u32 prtenchng : 1,
> - __BITFIELD_FIELD(u32 prtena : 1,
> - __BITFIELD_FIELD(u32 prtconndet : 1,
> - __BITFIELD_FIELD(u32 prtconnsts : 1,
> - ;)))))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hptxfsiz
> - *
> - * Host Periodic Transmit FIFO Size Register (HPTXFSIZ)
> - *
> - * This register holds the size and the memory start address of the Periodic
> - * TxFIFO, as shown in Figures 310 and 311.
> - */
> -union cvmx_usbcx_hptxfsiz {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hptxfsiz_s
> - * @ptxfsize: Host Periodic TxFIFO Depth (PTxFSize)
> - * This value is in terms of 32-bit words.
> - * * Minimum value is 16
> - * * Maximum value is 32768
> - * @ptxfstaddr: Host Periodic TxFIFO Start Address (PTxFStAddr)
> - */
> - struct cvmx_usbcx_hptxfsiz_s {
> - __BITFIELD_FIELD(u32 ptxfsize : 16,
> - __BITFIELD_FIELD(u32 ptxfstaddr : 16,
> - ;))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbc#_hptxsts
> - *
> - * Host Periodic Transmit FIFO/Queue Status Register (HPTXSTS)
> - *
> - * This read-only register contains the free space information for the Periodic
> - * TxFIFO and the Periodic Transmit Request Queue
> - */
> -union cvmx_usbcx_hptxsts {
> - u32 u32;
> - /**
> - * struct cvmx_usbcx_hptxsts_s
> - * @ptxqtop: Top of the Periodic Transmit Request Queue (PTxQTop)
> - * This indicates the entry in the Periodic Tx Request Queue that
> - * is currently being processes by the MAC.
> - * This register is used for debugging.
> - * * Bit [31]: Odd/Even (micro)frame
> - * - 1'b0: send in even (micro)frame
> - * - 1'b1: send in odd (micro)frame
> - * * Bits [30:27]: Channel/endpoint number
> - * * Bits [26:25]: Type
> - * - 2'b00: IN/OUT
> - * - 2'b01: Zero-length packet
> - * - 2'b10: CSPLIT
> - * - 2'b11: Disable channel command
> - * * Bit [24]: Terminate (last entry for the selected
> - * channel/endpoint)
> - * @ptxqspcavail: Periodic Transmit Request Queue Space Available
> - * (PTxQSpcAvail)
> - * Indicates the number of free locations available to be written
> - * in the Periodic Transmit Request Queue. This queue holds both
> - * IN and OUT requests.
> - * * 8'h0: Periodic Transmit Request Queue is full
> - * * 8'h1: 1 location available
> - * * 8'h2: 2 locations available
> - * * n: n locations available (0..8)
> - * * Others: Reserved
> - * @ptxfspcavail: Periodic Transmit Data FIFO Space Available
> - * (PTxFSpcAvail)
> - * Indicates the number of free locations available to be written
> - * to in the Periodic TxFIFO.
> - * Values are in terms of 32-bit words
> - * * 16'h0: Periodic TxFIFO is full
> - * * 16'h1: 1 word available
> - * * 16'h2: 2 words available
> - * * 16'hn: n words available (where 0..32768)
> - * * 16'h8000: 32768 words available
> - * * Others: Reserved
> - */
> - struct cvmx_usbcx_hptxsts_s {
> - __BITFIELD_FIELD(u32 ptxqtop : 8,
> - __BITFIELD_FIELD(u32 ptxqspcavail : 8,
> - __BITFIELD_FIELD(u32 ptxfspcavail : 16,
> - ;)))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbn#_clk_ctl
> - *
> - * USBN_CLK_CTL = USBN's Clock Control
> - *
> - * This register is used to control the frequency of the hclk and the
> - * hreset and phy_rst signals.
> - */
> -union cvmx_usbnx_clk_ctl {
> - u64 u64;
> - /**
> - * struct cvmx_usbnx_clk_ctl_s
> - * @divide2: The 'hclk' used by the USB subsystem is derived
> - * from the eclk.
> - * Also see the field DIVIDE. DIVIDE2<1> must currently
> - * be zero because it is not implemented, so the maximum
> - * ratio of eclk/hclk is currently 16.
> - * The actual divide number for hclk is:
> - * (DIVIDE2 + 1) * (DIVIDE + 1)
> - * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to
> - * generate the hclk in the USB Subsystem is held
> - * in reset. This bit must be set to '0' before
> - * changing the value os DIVIDE in this register.
> - * The reset to the HCLK_DIVIDERis also asserted
> - * when core reset is asserted.
> - * @p_x_on: Force USB-PHY on during suspend.
> - * '1' USB-PHY XO block is powered-down during
> - * suspend.
> - * '0' USB-PHY XO block is powered-up during
> - * suspend.
> - * The value of this field must be set while POR is
> - * active.
> - * @p_rtype: PHY reference clock type
> - * On CN50XX/CN52XX/CN56XX the values are:
> - * '0' The USB-PHY uses a 12MHz crystal as a clock source
> - * at the USB_XO and USB_XI pins.
> - * '1' Reserved.
> - * '2' The USB_PHY uses 12/24/48MHz 2.5V board clock at the
> - * USB_XO pin. USB_XI should be tied to ground in this
> - * case.
> - * '3' Reserved.
> - * On CN3xxx bits 14 and 15 are p_xenbn and p_rclk and values are:
> - * '0' Reserved.
> - * '1' Reserved.
> - * '2' The PHY PLL uses the XO block output as a reference.
> - * The XO block uses an external clock supplied on the
> - * XO pin. USB_XI should be tied to ground for this
> - * usage.
> - * '3' The XO block uses the clock from a crystal.
> - * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to
> - * remain powered in Suspend Mode.
> - * '1' The USB-PHY XO Bias, Bandgap and PLL are
> - * powered down in suspend mode.
> - * The value of this field must be set while POR is
> - * active.
> - * @p_c_sel: Phy clock speed select.
> - * Selects the reference clock / crystal frequency.
> - * '11': Reserved
> - * '10': 48 MHz (reserved when a crystal is used)
> - * '01': 24 MHz (reserved when a crystal is used)
> - * '00': 12 MHz
> - * The value of this field must be set while POR is
> - * active.
> - * NOTE: if a crystal is used as a reference clock,
> - * this field must be set to 12 MHz.
> - * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV.
> - * @sd_mode: Scaledown mode for the USBC. Control timing events
> - * in the USBC, for normal operation this must be '0'.
> - * @s_bist: Starts bist on the hclk memories, during the '0'
> - * to '1' transition.
> - * @por: Power On Reset for the PHY.
> - * Resets all the PHYS registers and state machines.
> - * @enable: When '1' allows the generation of the hclk. When
> - * '0' the hclk will not be generated. SEE DIVIDE
> - * field of this register.
> - * @prst: When this field is '0' the reset associated with
> - * the phy_clk functionality in the USB Subsystem is
> - * help in reset. This bit should not be set to '1'
> - * until the time it takes 6 clocks (hclk or phy_clk,
> - * whichever is slower) has passed. Under normal
> - * operation once this bit is set to '1' it should not
> - * be set to '0'.
> - * @hrst: When this field is '0' the reset associated with
> - * the hclk functioanlity in the USB Subsystem is
> - * held in reset.This bit should not be set to '1'
> - * until 12ms after phy_clk is stable. Under normal
> - * operation, once this bit is set to '1' it should
> - * not be set to '0'.
> - * @divide: The frequency of 'hclk' used by the USB subsystem
> - * is the eclk frequency divided by the value of
> - * (DIVIDE2 + 1) * (DIVIDE + 1), also see the field
> - * DIVIDE2 of this register.
> - * The hclk frequency should be less than 125Mhz.
> - * After writing a value to this field the SW should
> - * read the field for the value written.
> - * The ENABLE field of this register should not be set
> - * until AFTER this field is set and then read.
> - */
> - struct cvmx_usbnx_clk_ctl_s {
> - __BITFIELD_FIELD(u64 reserved_20_63 : 44,
> - __BITFIELD_FIELD(u64 divide2 : 2,
> - __BITFIELD_FIELD(u64 hclk_rst : 1,
> - __BITFIELD_FIELD(u64 p_x_on : 1,
> - __BITFIELD_FIELD(u64 p_rtype : 2,
> - __BITFIELD_FIELD(u64 p_com_on : 1,
> - __BITFIELD_FIELD(u64 p_c_sel : 2,
> - __BITFIELD_FIELD(u64 cdiv_byp : 1,
> - __BITFIELD_FIELD(u64 sd_mode : 2,
> - __BITFIELD_FIELD(u64 s_bist : 1,
> - __BITFIELD_FIELD(u64 por : 1,
> - __BITFIELD_FIELD(u64 enable : 1,
> - __BITFIELD_FIELD(u64 prst : 1,
> - __BITFIELD_FIELD(u64 hrst : 1,
> - __BITFIELD_FIELD(u64 divide : 3,
> - ;)))))))))))))))
> - } s;
> -};
> -
> -/**
> - * cvmx_usbn#_usbp_ctl_status
> - *
> - * USBN_USBP_CTL_STATUS = USBP Control And Status Register
> - *
> - * Contains general control and status information for the USBN block.
> - */
> -union cvmx_usbnx_usbp_ctl_status {
> - u64 u64;
> - /**
> - * struct cvmx_usbnx_usbp_ctl_status_s
> - * @txrisetune: HS Transmitter Rise/Fall Time Adjustment
> - * @txvreftune: HS DC Voltage Level Adjustment
> - * @txfslstune: FS/LS Source Impedance Adjustment
> - * @txhsxvtune: Transmitter High-Speed Crossover Adjustment
> - * @sqrxtune: Squelch Threshold Adjustment
> - * @compdistune: Disconnect Threshold Adjustment
> - * @otgtune: VBUS Valid Threshold Adjustment
> - * @otgdisable: OTG Block Disable
> - * @portreset: Per_Port Reset
> - * @drvvbus: Drive VBUS
> - * @lsbist: Low-Speed BIST Enable.
> - * @fsbist: Full-Speed BIST Enable.
> - * @hsbist: High-Speed BIST Enable.
> - * @bist_done: PHY Bist Done.
> - * Asserted at the end of the PHY BIST sequence.
> - * @bist_err: PHY Bist Error.
> - * Indicates an internal error was detected during
> - * the BIST sequence.
> - * @tdata_out: PHY Test Data Out.
> - * Presents either internally generated signals or
> - * test register contents, based upon the value of
> - * test_data_out_sel.
> - * @siddq: Drives the USBP (USB-PHY) SIDDQ input.
> - * Normally should be set to zero.
> - * When customers have no intent to use USB PHY
> - * interface, they should:
> - * - still provide 3.3V to USB_VDD33, and
> - * - tie USB_REXT to 3.3V supply, and
> - * - set USBN*_USBP_CTL_STATUS[SIDDQ]=1
> - * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable
> - * @dma_bmode: When set to 1 the L2C DMA address will be updated
> - * with byte-counts between packets. When set to 0
> - * the L2C DMA address is incremented to the next
> - * 4-byte aligned address after adding byte-count.
> - * @usbc_end: Bigendian input to the USB Core. This should be
> - * set to '0' for operation.
> - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
> - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
> - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
> - * This signal enables the pull-down resistance on
> - * the D+ line. '1' pull down-resistance is connected
> - * to D+/ '0' pull down resistance is not connected
> - * to D+. When an A/B device is acting as a host
> - * (downstream-facing port), dp_pulldown and
> - * dm_pulldown are enabled. This must not toggle
> - * during normal operation.
> - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
> - * This signal enables the pull-down resistance on
> - * the D- line. '1' pull down-resistance is connected
> - * to D-. '0' pull down resistance is not connected
> - * to D-. When an A/B device is acting as a host
> - * (downstream-facing port), dp_pulldown and
> - * dm_pulldown are enabled. This must not toggle
> - * during normal operation.
> - * @hst_mode: When '0' the USB is acting as HOST, when '1'
> - * USB is acting as device. This field needs to be
> - * set while the USB is in reset.
> - * @tuning: Transmitter Tuning for High-Speed Operation.
> - * Tunes the current supply and rise/fall output
> - * times for high-speed operation.
> - * [20:19] == 11: Current supply increased
> - * approximately 9%
> - * [20:19] == 10: Current supply increased
> - * approximately 4.5%
> - * [20:19] == 01: Design default.
> - * [20:19] == 00: Current supply decreased
> - * approximately 4.5%
> - * [22:21] == 11: Rise and fall times are increased.
> - * [22:21] == 10: Design default.
> - * [22:21] == 01: Rise and fall times are decreased.
> - * [22:21] == 00: Rise and fall times are decreased
> - * further as compared to the 01 setting.
> - * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
> - * Enables or disables bit stuffing on data[15:8]
> - * when bit-stuffing is enabled.
> - * @tx_bs_en: Transmit Bit Stuffing on [7:0].
> - * Enables or disables bit stuffing on data[7:0]
> - * when bit-stuffing is enabled.
> - * @loop_enb: PHY Loopback Test Enable.
> - * '1': During data transmission the receive is
> - * enabled.
> - * '0': During data transmission the receive is
> - * disabled.
> - * Must be '0' for normal operation.
> - * @vtest_enb: Analog Test Pin Enable.
> - * '1' The PHY's analog_test pin is enabled for the
> - * input and output of applicable analog test signals.
> - * '0' THe analog_test pin is disabled.
> - * @bist_enb: Built-In Self Test Enable.
> - * Used to activate BIST in the PHY.
> - * @tdata_sel: Test Data Out Select.
> - * '1' test_data_out[3:0] (PHY) register contents
> - * are output. '0' internally generated signals are
> - * output.
> - * @taddr_in: Mode Address for Test Interface.
> - * Specifies the register address for writing to or
> - * reading from the PHY test interface register.
> - * @tdata_in: Internal Testing Register Input Data and Select
> - * This is a test bus. Data is present on [3:0],
> - * and its corresponding select (enable) is present
> - * on bits [7:4].
> - * @ate_reset: Reset input from automatic test equipment.
> - * This is a test signal. When the USB Core is
> - * powered up (not in Susned Mode), an automatic
> - * tester can use this to disable phy_clock and
> - * free_clk, then re-enable them with an aligned
> - * phase.
> - * '1': The phy_clk and free_clk outputs are
> - * disabled. "0": The phy_clock and free_clk outputs
> - * are available within a specific period after the
> - * de-assertion.
> - */
> - struct cvmx_usbnx_usbp_ctl_status_s {
> - __BITFIELD_FIELD(u64 txrisetune : 1,
> - __BITFIELD_FIELD(u64 txvreftune : 4,
> - __BITFIELD_FIELD(u64 txfslstune : 4,
> - __BITFIELD_FIELD(u64 txhsxvtune : 2,
> - __BITFIELD_FIELD(u64 sqrxtune : 3,
> - __BITFIELD_FIELD(u64 compdistune : 3,
> - __BITFIELD_FIELD(u64 otgtune : 3,
> - __BITFIELD_FIELD(u64 otgdisable : 1,
> - __BITFIELD_FIELD(u64 portreset : 1,
> - __BITFIELD_FIELD(u64 drvvbus : 1,
> - __BITFIELD_FIELD(u64 lsbist : 1,
> - __BITFIELD_FIELD(u64 fsbist : 1,
> - __BITFIELD_FIELD(u64 hsbist : 1,
> - __BITFIELD_FIELD(u64 bist_done : 1,
> - __BITFIELD_FIELD(u64 bist_err : 1,
> - __BITFIELD_FIELD(u64 tdata_out : 4,
> - __BITFIELD_FIELD(u64 siddq : 1,
> - __BITFIELD_FIELD(u64 txpreemphasistune : 1,
> - __BITFIELD_FIELD(u64 dma_bmode : 1,
> - __BITFIELD_FIELD(u64 usbc_end : 1,
> - __BITFIELD_FIELD(u64 usbp_bist : 1,
> - __BITFIELD_FIELD(u64 tclk : 1,
> - __BITFIELD_FIELD(u64 dp_pulld : 1,
> - __BITFIELD_FIELD(u64 dm_pulld : 1,
> - __BITFIELD_FIELD(u64 hst_mode : 1,
> - __BITFIELD_FIELD(u64 tuning : 4,
> - __BITFIELD_FIELD(u64 tx_bs_enh : 1,
> - __BITFIELD_FIELD(u64 tx_bs_en : 1,
> - __BITFIELD_FIELD(u64 loop_enb : 1,
> - __BITFIELD_FIELD(u64 vtest_enb : 1,
> - __BITFIELD_FIELD(u64 bist_enb : 1,
> - __BITFIELD_FIELD(u64 tdata_sel : 1,
> - __BITFIELD_FIELD(u64 taddr_in : 4,
> - __BITFIELD_FIELD(u64 tdata_in : 8,
> - __BITFIELD_FIELD(u64 ate_reset : 1,
> - ;)))))))))))))))))))))))))))))))))))
> - } s;
> -};
> -
> -#endif /* __OCTEON_HCD_H__ */