From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/staging/octeon-usb/octeon-hcd.c | 1094 +++++++++++++++---------------- 1 file changed, 527 insertions(+), 567 deletions(-) (limited to 'drivers/staging/octeon-usb/octeon-hcd.c') diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6f2871784..17442b3ed 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -43,29 +43,15 @@ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. */ -#include + +#include +#include #include -#include -#include +#include #include -#include #include -#include - -#include -#include - -#include -#include - -#include - -#include #include -#include -#include -#include #include "octeon-hcd.h" @@ -113,35 +99,35 @@ enum cvmx_usb_direction { }; /** - * enum cvmx_usb_complete - possible callback function status codes + * enum cvmx_usb_status - possible callback function status codes * - * @CVMX_USB_COMPLETE_SUCCESS: The transaction / operation finished without + * @CVMX_USB_STATUS_OK: The transaction / operation finished without * any errors - * @CVMX_USB_COMPLETE_SHORT: FIXME: This is currently not implemented - * @CVMX_USB_COMPLETE_CANCEL: The transaction was canceled while in flight + * @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_COMPLETE_ERROR: The transaction aborted with an unexpected + * @CVMX_USB_STATUS_ERROR: The transaction aborted with an unexpected * error status - * @CVMX_USB_COMPLETE_STALL: The transaction received a USB STALL response + * @CVMX_USB_STATUS_STALL: The transaction received a USB STALL response * from the device - * @CVMX_USB_COMPLETE_XACTERR: The transaction failed with an error from the + * @CVMX_USB_STATUS_XACTERR: The transaction failed with an error from the * device even after a number of retries - * @CVMX_USB_COMPLETE_DATATGLERR: The transaction failed with a data toggle + * @CVMX_USB_STATUS_DATATGLERR: The transaction failed with a data toggle * error even after a number of retries - * @CVMX_USB_COMPLETE_BABBLEERR: The transaction failed with a babble error - * @CVMX_USB_COMPLETE_FRAMEERR: The transaction failed with a frame error + * @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_complete { - CVMX_USB_COMPLETE_SUCCESS, - CVMX_USB_COMPLETE_SHORT, - CVMX_USB_COMPLETE_CANCEL, - CVMX_USB_COMPLETE_ERROR, - CVMX_USB_COMPLETE_STALL, - CVMX_USB_COMPLETE_XACTERR, - CVMX_USB_COMPLETE_DATATGLERR, - CVMX_USB_COMPLETE_BABBLEERR, - CVMX_USB_COMPLETE_FRAMEERR, +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, }; /** @@ -160,13 +146,13 @@ enum cvmx_usb_complete { * status call. */ struct cvmx_usb_port_status { - uint32_t reserved : 25; - uint32_t port_enabled : 1; - uint32_t port_over_current : 1; - uint32_t port_powered : 1; + u32 reserved : 25; + u32 port_enabled : 1; + u32 port_over_current : 1; + u32 port_powered : 1; enum cvmx_usb_speed port_speed : 2; - uint32_t connected : 1; - uint32_t connect_change : 1; + u32 connected : 1; + u32 connect_change : 1; }; /** @@ -180,7 +166,7 @@ struct cvmx_usb_port_status { struct cvmx_usb_iso_packet { int offset; int length; - enum cvmx_usb_complete status; + enum cvmx_usb_status status; }; /** @@ -234,13 +220,13 @@ enum cvmx_usb_pipe_flags { * 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) +#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) +#define MAX_TRANSFER_PACKETS ((1 << 10) - 1) /** * Logical transactions may take numerous low level @@ -284,9 +270,9 @@ enum cvmx_usb_stage { struct cvmx_usb_transaction { struct list_head node; enum cvmx_usb_transfer type; - uint64_t buffer; + u64 buffer; int buffer_length; - uint64_t control_header; + u64 control_header; int iso_start_frame; int iso_number_packets; struct cvmx_usb_iso_packet *iso_packets; @@ -328,36 +314,37 @@ struct cvmx_usb_transaction { struct cvmx_usb_pipe { struct list_head node; struct list_head transactions; - uint64_t interval; - uint64_t next_tx_frame; + 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; - uint16_t max_packet; - uint8_t device_addr; - uint8_t endpoint_num; - uint8_t hub_device_addr; - uint8_t hub_port; - uint8_t pid_toggle; - uint8_t channel; - int8_t split_sc_frame; + 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; - uint64_t address; - } entry[MAX_CHANNELS+1]; + u64 address; + } entry[MAX_CHANNELS + 1]; int head; int tail; }; /** - * struct cvmx_usb_state - the state of the USB block + * 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. @@ -372,7 +359,8 @@ struct cvmx_usb_tx_fifo { * frame_number: Increments every SOF interrupt for time keeping. * active_split: Points to the current active split, or NULL. */ -struct cvmx_usb_state { +struct octeon_hcd { + spinlock_t lock; /* serialization lock */ int init_flags; int index; int idle_hardware_channels; @@ -382,23 +370,18 @@ struct cvmx_usb_state { struct cvmx_usb_port_status port_status; struct list_head idle_pipes; struct list_head active_pipes[4]; - uint64_t frame_number; + u64 frame_number; struct cvmx_usb_transaction *active_split; struct cvmx_usb_tx_fifo periodic; struct cvmx_usb_tx_fifo nonperiodic; }; -struct octeon_hcd { - spinlock_t lock; - struct cvmx_usb_state usb; -}; - /* This macro spins on a register waiting for it to reach a condition. */ #define CVMX_WAIT_FOR_FIELD32(address, _union, cond, timeout_usec) \ ({int result; \ do { \ - uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \ - octeon_get_clock_rate() / 1000000; \ + u64 done = cvmx_get_cycle() + (u64)timeout_usec * \ + octeon_get_clock_rate() / 1000000; \ union _union c; \ \ while (1) { \ @@ -431,7 +414,7 @@ struct octeon_hcd { /* 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) + (CVMX_USBCX_GOTGCTL(usb_index) + ((channel) + 1) * 0x1000) /** * struct octeon_temp_buffer - a bounce buffer for USB transfers @@ -447,11 +430,6 @@ struct octeon_temp_buffer { u8 data[0]; }; -static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) -{ - return container_of(p, struct octeon_hcd, usb); -} - static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) { return container_of((void *)p, struct usb_hcd, hcd_priv); @@ -562,14 +540,12 @@ static void octeon_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) * * Returns: Result of the read */ -static inline uint32_t cvmx_usb_read_csr32(struct cvmx_usb_state *usb, - uint64_t address) +static inline u32 cvmx_usb_read_csr32(struct octeon_hcd *usb, u64 address) { - uint32_t result = cvmx_read64_uint32(address ^ 4); + u32 result = cvmx_read64_uint32(address ^ 4); return result; } - /** * Write a USB 32bit CSR. It performs the necessary address * swizzle for 32bit CSRs and logs the value in a readable format @@ -579,8 +555,8 @@ static inline uint32_t cvmx_usb_read_csr32(struct cvmx_usb_state *usb, * @address: 64bit address to write * @value: Value to write */ -static inline void cvmx_usb_write_csr32(struct cvmx_usb_state *usb, - uint64_t address, uint32_t value) +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)); @@ -595,14 +571,13 @@ static inline void cvmx_usb_write_csr32(struct cvmx_usb_state *usb, * * Returns: Non zero if we need to do split transactions */ -static inline int cvmx_usb_pipe_needs_split(struct cvmx_usb_state *usb, +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 * @@ -617,7 +592,7 @@ static inline int cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe) return 0; /* Data0 */ } -static void cvmx_fifo_setup(struct cvmx_usb_state *usb) +static void cvmx_fifo_setup(struct octeon_hcd *usb) { union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3; union cvmx_usbcx_gnptxfsiz npsiz; @@ -675,7 +650,7 @@ static void cvmx_fifo_setup(struct cvmx_usb_state *usb) * * Returns: 0 or a negative error code. */ -static int cvmx_usb_shutdown(struct cvmx_usb_state *usb) +static int cvmx_usb_shutdown(struct octeon_hcd *usb) { union cvmx_usbnx_clk_ctl usbn_clk_ctl; @@ -704,12 +679,12 @@ static int cvmx_usb_shutdown(struct cvmx_usb_state *usb) * off in the disabled state. * * @dev: Pointer to struct device for logging purposes. - * @usb: Pointer to struct cvmx_usb_state. + * @usb: Pointer to struct octeon_hcd. * * Returns: 0 or a negative error code. */ static int cvmx_usb_initialize(struct device *dev, - struct cvmx_usb_state *usb) + struct octeon_hcd *usb) { int channel; int divisor; @@ -975,7 +950,7 @@ retry: * * @usb: USB device state populated by cvmx_usb_initialize(). */ -static void cvmx_usb_reset_port(struct cvmx_usb_state *usb) +static void cvmx_usb_reset_port(struct octeon_hcd *usb) { usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); @@ -1002,7 +977,6 @@ static void cvmx_usb_reset_port(struct cvmx_usb_state *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. @@ -1013,7 +987,7 @@ static void cvmx_usb_reset_port(struct cvmx_usb_state *usb) * * Returns: 0 or a negative error code. */ -static int cvmx_usb_disable(struct cvmx_usb_state *usb) +static int cvmx_usb_disable(struct octeon_hcd *usb) { /* Disable the port */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt, @@ -1021,7 +995,6 @@ static int cvmx_usb_disable(struct cvmx_usb_state *usb) return 0; } - /** * Get the current state of the USB port. Use this call to * determine if the usb port has anything connected, is enabled, @@ -1033,8 +1006,7 @@ static int cvmx_usb_disable(struct cvmx_usb_state *usb) * * Returns: Port status information */ -static struct cvmx_usb_port_status cvmx_usb_get_status( - struct cvmx_usb_state *usb) +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; @@ -1048,7 +1020,7 @@ static struct cvmx_usb_port_status cvmx_usb_get_status( result.port_speed = usbc_hprt.s.prtspd; result.connected = usbc_hprt.s.prtconnsts; result.connect_change = - (result.connected != usb->port_status.connected); + result.connected != usb->port_status.connected; return result; } @@ -1105,7 +1077,7 @@ static struct cvmx_usb_port_status cvmx_usb_get_status( * * Returns: A non-NULL value is a pipe. NULL means an error. */ -static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, +static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct octeon_hcd *usb, int device_addr, int endpoint_num, enum cvmx_usb_speed @@ -1125,8 +1097,8 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, if (!pipe) return NULL; if ((device_speed == CVMX_USB_SPEED_HIGH) && - (transfer_dir == CVMX_USB_DIRECTION_OUT) && - (transfer_type == CVMX_USB_TRANSFER_BULK)) + (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; @@ -1143,9 +1115,9 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, if (!interval) interval = 1; if (cvmx_usb_pipe_needs_split(usb, pipe)) { - pipe->interval = interval*8; + pipe->interval = interval * 8; /* Force start splits to be schedule on uFrame 0 */ - pipe->next_tx_frame = ((usb->frame_number+7)&~7) + + pipe->next_tx_frame = ((usb->frame_number + 7) & ~7) + pipe->interval; } else { pipe->interval = interval; @@ -1166,7 +1138,6 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, 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 @@ -1174,13 +1145,13 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, * * @usb: USB device state populated by cvmx_usb_initialize(). */ -static void cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb) +static void cvmx_usb_poll_rx_fifo(struct octeon_hcd *usb) { union cvmx_usbcx_grxstsph rx_status; int channel; int bytes; - uint64_t address; - uint32_t *ptr; + u64 address; + u32 *ptr; rx_status.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index)); @@ -1213,7 +1184,6 @@ static void cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb) CVMX_SYNCW; } - /** * Fill the TX hardware fifo with data out of the software * fifos @@ -1225,7 +1195,7 @@ static void cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb) * Returns: Non zero if the hardware fifo was too small and needs * to be serviced again. */ -static int cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb, +static int cvmx_usb_fill_tx_hw(struct octeon_hcd *usb, struct cvmx_usb_tx_fifo *fifo, int available) { /* @@ -1234,9 +1204,9 @@ static int cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb, */ while (available && (fifo->head != fifo->tail)) { int i = fifo->tail; - const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address); - uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, - usb->index) ^ 4; + 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 */ @@ -1275,13 +1245,12 @@ static int cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb, 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 cvmx_usb_state *usb) +static void cvmx_usb_poll_tx_fifo(struct octeon_hcd *usb) { if (usb->periodic.head != usb->periodic.tail) { union cvmx_usbcx_hptxsts tx_status; @@ -1312,14 +1281,13 @@ static void cvmx_usb_poll_tx_fifo(struct cvmx_usb_state *usb) } } - /** * 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 cvmx_usb_state *usb, int channel) +static void cvmx_usb_fill_tx_fifo(struct octeon_hcd *usb, int channel) { union cvmx_usbcx_hccharx hcchar; union cvmx_usbcx_hcspltx usbc_hcsplt; @@ -1348,7 +1316,7 @@ static void cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel) return; if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) || - (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) + (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) fifo = &usb->periodic; else fifo = &usb->nonperiodic; @@ -1357,7 +1325,7 @@ static void cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int 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->entry[fifo->head].size = (usbc_hctsiz.s.xfersize + 3) >> 2; fifo->head++; if (fifo->head > MAX_CHANNELS) fifo->head = 0; @@ -1373,12 +1341,11 @@ static void cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel) * @channel: Channel to setup * @pipe: Pipe for control transaction */ -static void cvmx_usb_start_channel_control(struct cvmx_usb_state *usb, +static void cvmx_usb_start_channel_control(struct octeon_hcd *usb, int channel, struct cvmx_usb_pipe *pipe) { - struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); - struct usb_hcd *hcd = octeon_to_hcd(priv); + 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), @@ -1488,9 +1455,9 @@ static void cvmx_usb_start_channel_control(struct cvmx_usb_state *usb, */ packets_to_transfer = DIV_ROUND_UP(bytes_to_transfer, pipe->max_packet); - if (packets_to_transfer == 0) + if (packets_to_transfer == 0) { packets_to_transfer = 1; - else if ((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 @@ -1515,7 +1482,6 @@ static void cvmx_usb_start_channel_control(struct cvmx_usb_state *usb, usbc_hctsiz.u32); } - /** * Start a channel to perform the pipe's head transaction * @@ -1523,7 +1489,7 @@ static void cvmx_usb_start_channel_control(struct cvmx_usb_state *usb, * @channel: Channel to setup * @pipe: Pipe to start */ -static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, +static void cvmx_usb_start_channel(struct octeon_hcd *usb, int channel, struct cvmx_usb_pipe *pipe) { struct cvmx_usb_transaction *transaction = @@ -1539,7 +1505,7 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, pipe->flags |= CVMX_USB_PIPE_FLAGS_SCHEDULED; /* Mark this channel as in use */ - usb->idle_hardware_channels &= ~(1<idle_hardware_channels &= ~(1 << channel); /* Enable the channel interrupt bits */ { @@ -1579,22 +1545,22 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, usbc_hcintmsk.s.xfercomplmsk = 1; } cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, usb->index), - usbc_hcintmsk.u32); + 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<index), usbc_haintmsk.u32); } /* Setup the location the DMA engine uses. */ { - uint64_t reg; - uint64_t dma_address = transaction->buffer + - transaction->actual_bytes; + u64 reg; + u64 dma_address = transaction->buffer + + transaction->actual_bytes; if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) dma_address = transaction->buffer + @@ -1636,15 +1602,16 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, * We only store the lower two bits since the time ahead * can only be two frames */ - if ((transaction->stage&1) == 0) { + 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 + } else { pipe->split_sc_frame = -1; + } usbc_hcsplt.s.spltena = 1; usbc_hcsplt.s.hubaddr = pipe->hub_device_addr; @@ -1666,10 +1633,9 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, * 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)) { + (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 @@ -1732,11 +1698,11 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, */ packets_to_transfer = DIV_ROUND_UP(bytes_to_transfer, pipe->max_packet); - if (packets_to_transfer == 0) + if (packets_to_transfer == 0) { packets_to_transfer = 1; - else if ((packets_to_transfer > 1) && - (usb->init_flags & - CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { + } 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 @@ -1783,7 +1749,7 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, * Set the startframe odd/even properly. This is only used for * periodic */ - usbc_hcchar.s.oddfrm = usb->frame_number&1; + usbc_hcchar.s.oddfrm = usb->frame_number & 1; /* * Set the number of back to back packets allowed by this @@ -1843,9 +1809,11 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, break; } { - union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = + union cvmx_usbcx_hctsizx usbc_hctsiz = { .u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, usb->index))}; + CVMX_USBCX_HCTSIZX(channel, + usb->index)) + }; transaction->xfersize = usbc_hctsiz.s.xfersize; transaction->pktcnt = usbc_hctsiz.s.pktcnt; } @@ -1858,21 +1826,19 @@ static void cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, 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(). - * @list: Pipe list to search - * @current_frame: - * Frame counter to use as a time reference. + * @xfer_type: Transfer type * * Returns: Pipe or NULL if none are ready */ static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe( - struct cvmx_usb_state *usb, - struct list_head *list, - uint64_t current_frame) + 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) { @@ -1880,11 +1846,11 @@ static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe( 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 - (int)pipe->split_sc_frame) - & 0x7f) < 0x40)) && - (!usb->active_split || (usb->active_split == 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; } @@ -1892,6 +1858,32 @@ static struct cvmx_usb_pipe *cvmx_usb_find_ready_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 @@ -1900,7 +1892,7 @@ static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe( * @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 cvmx_usb_state *usb, int is_sof) +static void cvmx_usb_schedule(struct octeon_hcd *usb, int is_sof) { int channel; struct cvmx_usb_pipe *pipe; @@ -1922,7 +1914,7 @@ static void cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof) CVMX_USBCX_HFIR(usb->index)) }; - if (hfnum.s.frrem < hfir.s.frint/4) + if (hfnum.s.frrem < hfir.s.frint / 4) goto done; } @@ -1932,35 +1924,7 @@ static void cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof) if (unlikely(channel > 7)) break; - /* Find a pipe needing service */ - pipe = NULL; - 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, - usb->active_pipes + - CVMX_USB_TRANSFER_ISOCHRONOUS, - usb->frame_number); - if (likely(!pipe)) - pipe = cvmx_usb_find_ready_pipe(usb, - usb->active_pipes + - CVMX_USB_TRANSFER_INTERRUPT, - usb->frame_number); - } - if (likely(!pipe)) { - pipe = cvmx_usb_find_ready_pipe(usb, - usb->active_pipes + - CVMX_USB_TRANSFER_CONTROL, - usb->frame_number); - if (likely(!pipe)) - pipe = cvmx_usb_find_ready_pipe(usb, - usb->active_pipes + - CVMX_USB_TRANSFER_BULK, - usb->frame_number); - } + pipe = cvmx_usb_next_pipe(usb, is_sof); if (!pipe) break; @@ -1974,7 +1938,7 @@ done: */ need_sof = 0; for (ttype = CVMX_USB_TRANSFER_CONTROL; - ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) { + 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; @@ -1986,19 +1950,18 @@ done: cvmx_usbcx_gintmsk, sofmsk, need_sof); } -static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, - enum cvmx_usb_complete status, +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 octeon_hcd *priv = cvmx_usb_to_octeon(usb); - struct usb_hcd *hcd = octeon_to_hcd(priv); + struct usb_hcd *hcd = octeon_to_hcd(usb); struct device *dev = hcd->self.controller; - if (likely(status == CVMX_USB_COMPLETE_SUCCESS)) + if (likely(status == CVMX_USB_STATUS_OK)) urb->actual_length = bytes_transferred; else urb->actual_length = 0; @@ -2006,7 +1969,8 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, urb->hcpriv = NULL; /* For Isochronous transactions we need to update the URB packet status - list from data in our private copy */ + * list from data in our private copy + */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* @@ -2014,12 +1978,11 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, * field. */ struct cvmx_usb_iso_packet *iso_packet = - (struct cvmx_usb_iso_packet *) urb->setup_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_COMPLETE_SUCCESS) { + 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; @@ -2039,41 +2002,41 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, } switch (status) { - case CVMX_USB_COMPLETE_SUCCESS: + case CVMX_USB_STATUS_OK: urb->status = 0; break; - case CVMX_USB_COMPLETE_CANCEL: + case CVMX_USB_STATUS_CANCEL: if (urb->status == 0) urb->status = -ENOENT; break; - case CVMX_USB_COMPLETE_STALL: + 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_COMPLETE_BABBLEERR: + 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_COMPLETE_SHORT: + 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_COMPLETE_ERROR: - case CVMX_USB_COMPLETE_XACTERR: - case CVMX_USB_COMPLETE_DATATGLERR: - case CVMX_USB_COMPLETE_FRAMEERR: + 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(priv), urb); - spin_unlock(&priv->lock); - usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status); - spin_lock(&priv->lock); + 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); } /** @@ -2087,10 +2050,10 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, * @complete_code: * Completion code */ -static void cvmx_usb_perform_complete(struct cvmx_usb_state *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - enum cvmx_usb_complete complete_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) @@ -2110,7 +2073,7 @@ static void cvmx_usb_perform_complete(struct cvmx_usb_state *usb, * next one */ if ((transaction->iso_number_packets > 1) && - (complete_code == CVMX_USB_COMPLETE_SUCCESS)) { + (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 */ @@ -2133,7 +2096,6 @@ static void cvmx_usb_perform_complete(struct cvmx_usb_state *usb, kfree(transaction); } - /** * Submit a usb transaction to a pipe. Called for all types * of transactions. @@ -2157,12 +2119,12 @@ static void cvmx_usb_perform_complete(struct cvmx_usb_state *usb, * Returns: Transaction or NULL on failure. */ static struct cvmx_usb_transaction *cvmx_usb_submit_transaction( - struct cvmx_usb_state *usb, + struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe, enum cvmx_usb_transfer type, - uint64_t buffer, + u64 buffer, int buffer_length, - uint64_t control_header, + u64 control_header, int iso_start_frame, int iso_number_packets, struct cvmx_usb_iso_packet *iso_packets, @@ -2208,7 +2170,6 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_transaction( return transaction; } - /** * Call to submit a USB Bulk transfer to a pipe. * @@ -2219,7 +2180,7 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_transaction( * Returns: A submitted transaction or NULL on failure. */ static struct cvmx_usb_transaction *cvmx_usb_submit_bulk( - struct cvmx_usb_state *usb, + struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe, struct urb *urb) { @@ -2233,7 +2194,6 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_bulk( urb); } - /** * Call to submit a USB Interrupt transfer to a pipe. * @@ -2244,7 +2204,7 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_bulk( * Returns: A submitted transaction or NULL on failure. */ static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt( - struct cvmx_usb_state *usb, + struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe, struct urb *urb) { @@ -2259,7 +2219,6 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt( urb); } - /** * Call to submit a USB Control transfer to a pipe. * @@ -2270,12 +2229,12 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt( * Returns: A submitted transaction or NULL on failure. */ static struct cvmx_usb_transaction *cvmx_usb_submit_control( - struct cvmx_usb_state *usb, + struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe, struct urb *urb) { int buffer_length = urb->transfer_buffer_length; - uint64_t control_header = urb->setup_dma; + u64 control_header = urb->setup_dma; struct usb_ctrlrequest *header = cvmx_phys_to_ptr(control_header); if ((header->bRequestType & USB_DIR_IN) == 0) @@ -2291,7 +2250,6 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_control( urb); } - /** * Call to submit a USB Isochronous transfer to a pipe. * @@ -2302,13 +2260,13 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_control( * Returns: A submitted transaction or NULL on failure. */ static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous( - struct cvmx_usb_state *usb, + 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; + packets = (struct cvmx_usb_iso_packet *)urb->setup_packet; return cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_ISOCHRONOUS, urb->transfer_dma, @@ -2319,7 +2277,6 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous( packets, urb); } - /** * Cancel one outstanding request in a pipe. Canceling a request * can fail if the transaction has already completed before cancel @@ -2333,7 +2290,7 @@ static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous( * * Returns: 0 or a negative error code. */ -static int cvmx_usb_cancel(struct cvmx_usb_state *usb, +static int cvmx_usb_cancel(struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction) { @@ -2359,17 +2316,15 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb, 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_USBCX_HCCHARX(pipe->channel, + usb->index), + usbc_hcchar.u32); } } - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_CANCEL); + 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. @@ -2379,7 +2334,7 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb, * * Returns: 0 or a negative error code. */ -static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb, +static int cvmx_usb_cancel_all(struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe) { struct cvmx_usb_transaction *transaction, *next; @@ -2394,7 +2349,6 @@ static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb, return 0; } - /** * Close a pipe created with cvmx_usb_open_pipe(). * @@ -2404,7 +2358,7 @@ static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb, * Returns: 0 or a negative error code. EBUSY is returned if the pipe has * outstanding transfers. */ -static int cvmx_usb_close_pipe(struct cvmx_usb_state *usb, +static int cvmx_usb_close_pipe(struct octeon_hcd *usb, struct cvmx_usb_pipe *pipe) { /* Fail if the pipe has pending transactions */ @@ -2425,7 +2379,7 @@ static int cvmx_usb_close_pipe(struct cvmx_usb_state *usb, * * Returns: USB frame number */ -static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb) +static int cvmx_usb_get_frame_number(struct octeon_hcd *usb) { int frame_number; union cvmx_usbcx_hfnum usbc_hfnum; @@ -2436,6 +2390,197 @@ static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb) return frame_number; } +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 @@ -2445,10 +2590,9 @@ static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb) * * Returns: Zero on success */ -static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) +static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel) { - struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); - struct usb_hcd *hcd = octeon_to_hcd(priv); + 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; @@ -2475,9 +2619,9 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * write of HCCHARX without changing things */ cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(channel, - usb->index), - usbc_hcchar.u32); + CVMX_USBCX_HCCHARX(channel, + usb->index), + usbc_hcchar.u32); return 0; } @@ -2492,14 +2636,12 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) hcintmsk.u32 = 0; hcintmsk.s.chhltdmsk = 1; cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, - usb->index), - hcintmsk.u32); + 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); + CVMX_USBCX_HCCHARX(channel, usb->index), + usbc_hcchar.u32); return 0; } else if (usbc_hcint.s.xfercompl) { /* @@ -2523,7 +2665,7 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) /* 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<idle_hardware_channels |= (1 << channel); /* Make sure this channel is tied to a valid pipe */ pipe = usb->pipe_for_channel[channel]; @@ -2593,7 +2735,7 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * transferred */ if ((transaction->stage == CVMX_USB_STAGE_SETUP) || - (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) + (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) bytes_this_transfer = 0; /* @@ -2621,8 +2763,8 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * 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->transfer_type == CVMX_USB_TRANSFER_BULK) && + (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)) pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING; if (unlikely(WARN_ON_ONCE(bytes_this_transfer < 0))) { @@ -2631,8 +2773,8 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * keeps substracting same byte count over and over again. In * such case we just need to fail every transaction. */ - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_ERROR); + cvmx_usb_complete(usb, pipe, transaction, + CVMX_USB_STATUS_ERROR); return 0; } @@ -2644,24 +2786,24 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * the actual bytes transferred */ pipe->pid_toggle = 0; - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_STALL); + 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_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_XACTERR); + cvmx_usb_complete(usb, pipe, transaction, + CVMX_USB_STATUS_XACTERR); } else if (usbc_hcint.s.bblerr) { /* Babble Error (BblErr) */ - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_BABBLEERR); + cvmx_usb_complete(usb, pipe, transaction, + CVMX_USB_STATUS_BABBLEERR); } else if (usbc_hcint.s.datatglerr) { /* Data toggle error */ - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_DATATGLERR); + 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 @@ -2676,10 +2818,10 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * again. Otherwise this transaction is complete */ if ((buffer_space_left == 0) || - (bytes_in_last_packet < pipe->max_packet)) - cvmx_usb_perform_complete(usb, pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); + (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 @@ -2713,205 +2855,26 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) switch (transaction->type) { case CVMX_USB_TRANSFER_CONTROL: - switch (transaction->stage) { - case CVMX_USB_STAGE_NON_CONTROL: - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: - /* This should be impossible */ - cvmx_usb_perform_complete(usb, pipe, - transaction, CVMX_USB_COMPLETE_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_perform_complete(usb, pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - break; - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: - cvmx_usb_perform_complete(usb, pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - break; - } + 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: - /* - * 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 { - if (transaction->type == - CVMX_USB_TRANSFER_INTERRUPT) - pipe->next_tx_frame += - pipe->interval; - cvmx_usb_perform_complete( - usb, - pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - } - } - } else { - if ((pipe->device_speed == - CVMX_USB_SPEED_HIGH) && - (pipe->transfer_type == - CVMX_USB_TRANSFER_BULK) && - (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)) { - if (transaction->type == - CVMX_USB_TRANSFER_INTERRUPT) - pipe->next_tx_frame += - pipe->interval; - cvmx_usb_perform_complete(usb, pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - } - } + cvmx_usb_transfer_intr(usb, pipe, transaction, + buffer_space_left, + bytes_in_last_packet); break; case CVMX_USB_TRANSFER_ISOCHRONOUS: - 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_perform_complete(usb, - pipe, transaction, - CVMX_USB_COMPLETE_SUCCESS); - } - } else { - 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_perform_complete( - usb, - pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - } - } else - transaction->stage = - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - } - } else { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_perform_complete(usb, pipe, - transaction, - CVMX_USB_COMPLETE_SUCCESS); - } + cvmx_usb_transfer_isoc(usb, pipe, transaction, + buffer_space_left, + bytes_in_last_packet, + bytes_this_transfer); break; } } else if (usbc_hcint.s.nak) { @@ -2946,20 +2909,18 @@ static int cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) * We get channel halted interrupts with no result bits * sets when the cable is unplugged */ - cvmx_usb_perform_complete(usb, pipe, transaction, - CVMX_USB_COMPLETE_ERROR); + cvmx_usb_complete(usb, pipe, transaction, + CVMX_USB_STATUS_ERROR); } } return 0; } -static void octeon_usb_port_callback(struct cvmx_usb_state *usb) +static void octeon_usb_port_callback(struct octeon_hcd *usb) { - struct octeon_hcd *priv = cvmx_usb_to_octeon(usb); - - spin_unlock(&priv->lock); - usb_hcd_poll_rh_status(octeon_to_hcd(priv)); - spin_lock(&priv->lock); + spin_unlock(&usb->lock); + usb_hcd_poll_rh_status(octeon_to_hcd(usb)); + spin_lock(&usb->lock); } /** @@ -2972,7 +2933,7 @@ static void octeon_usb_port_callback(struct cvmx_usb_state *usb) * * Returns: 0 or a negative error code. */ -static int cvmx_usb_poll(struct cvmx_usb_state *usb) +static int cvmx_usb_poll(struct octeon_hcd *usb) { union cvmx_usbcx_hfnum usbc_hfnum; union cvmx_usbcx_gintsts usbc_gintsts; @@ -2981,7 +2942,7 @@ static int cvmx_usb_poll(struct cvmx_usb_state *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) + if ((usb->frame_number & 0x3fff) > usbc_hfnum.s.frnum) usb->frame_number += 0x4000; usb->frame_number &= ~0x3fffull; usb->frame_number |= usbc_hfnum.s.frnum; @@ -3028,8 +2989,8 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb) */ 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.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); @@ -3056,7 +3017,7 @@ static int cvmx_usb_poll(struct cvmx_usb_state *usb) channel = __fls(usbc_haint.u32); cvmx_usb_poll_channel(usb, channel); - usbc_haint.u32 ^= 1<lock, flags); - cvmx_usb_poll(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&usb->lock, flags); + cvmx_usb_poll(usb); + spin_unlock_irqrestore(&usb->lock, flags); return IRQ_HANDLED; } @@ -3095,16 +3056,16 @@ static void octeon_usb_stop(struct usb_hcd *hcd) static int octeon_usb_get_frame_number(struct usb_hcd *hcd) { - struct octeon_hcd *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); - return cvmx_usb_get_frame_number(&priv->usb); + 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 *priv = hcd_to_octeon(hcd); + 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; @@ -3114,11 +3075,11 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, int rc; urb->status = 0; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&usb->lock, flags); rc = usb_hcd_link_urb_to_ep(hcd, urb); if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); return rc; } @@ -3184,7 +3145,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, dev = dev->parent; } } - pipe = cvmx_usb_open_pipe(&priv->usb, usb_pipedevice(urb->pipe), + pipe = cvmx_usb_open_pipe(usb, usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe), speed, le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff, @@ -3198,7 +3159,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, split_device, split_port); if (!pipe) { usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); dev_dbg(dev, "Failed to create pipe\n"); return -ENOMEM; } @@ -3227,8 +3188,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, urb->iso_frame_desc[i].offset; iso_packet[i].length = urb->iso_frame_desc[i].length; - iso_packet[i].status = - CVMX_USB_COMPLETE_ERROR; + iso_packet[i].status = CVMX_USB_STATUS_ERROR; } /* * Store a pointer to the list in the URB setup_packet @@ -3236,7 +3196,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, * this saves us a bunch of logic. */ urb->setup_packet = (char *)iso_packet; - transaction = cvmx_usb_submit_isochronous(&priv->usb, + transaction = cvmx_usb_submit_isochronous(usb, pipe, urb); /* * If submit failed we need to free our private packet @@ -3252,29 +3212,29 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, dev_dbg(dev, "Submit interrupt to %d.%d\n", usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe)); - transaction = cvmx_usb_submit_interrupt(&priv->usb, pipe, urb); + 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(&priv->usb, pipe, urb); + 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(&priv->usb, pipe, urb); + transaction = cvmx_usb_submit_bulk(usb, pipe, urb); break; } if (!transaction) { usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); dev_dbg(dev, "Failed to submit\n"); return -ENOMEM; } urb->hcpriv = transaction; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); return 0; } @@ -3282,24 +3242,24 @@ static int octeon_usb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { - struct octeon_hcd *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); unsigned long flags; int rc; if (!urb->dev) return -EINVAL; - spin_lock_irqsave(&priv->lock, flags); + 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(&priv->usb, urb->ep->hcpriv, urb->hcpriv); + cvmx_usb_cancel(usb, urb->ep->hcpriv, urb->hcpriv); out: - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); return rc; } @@ -3310,28 +3270,28 @@ static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct device *dev = hcd->self.controller; if (ep->hcpriv) { - struct octeon_hcd *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); struct cvmx_usb_pipe *pipe = ep->hcpriv; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - cvmx_usb_cancel_all(&priv->usb, pipe); - if (cvmx_usb_close_pipe(&priv->usb, pipe)) + 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(&priv->lock, flags); + 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 *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); struct cvmx_usb_port_status port_status; unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - port_status = cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + spin_lock_irqsave(&usb->lock, flags); + port_status = cvmx_usb_get_status(usb); + spin_unlock_irqrestore(&usb->lock, flags); buf[0] = 0; buf[0] = port_status.connect_change << 1; @@ -3339,12 +3299,11 @@ static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) } static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, char *buf, u16 wLength) + u16 wIndex, char *buf, u16 wLength) { - struct octeon_hcd *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); struct device *dev = hcd->self.controller; struct cvmx_usb_port_status usb_port_status; - struct cvmx_usb_state *usb = &priv->usb; int port_status; struct usb_hub_descriptor *desc; unsigned long flags; @@ -3371,9 +3330,9 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_ENABLE: dev_dbg(dev, " ENABLE\n"); - spin_lock_irqsave(&priv->lock, flags); - cvmx_usb_disable(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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"); @@ -3390,20 +3349,18 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_C_CONNECTION: dev_dbg(dev, " C_CONNECTION\n"); /* Clears drivers internal connect status change flag */ - spin_lock_irqsave(&priv->lock, flags); - priv->usb.port_status = - cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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(&priv->lock, flags); - priv->usb.port_status = - cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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"); @@ -3411,10 +3368,9 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, * Clears the driver's internal Port Enable/Disable * Change flag. */ - spin_lock_irqsave(&priv->lock, flags); - priv->usb.port_status = - cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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"); @@ -3427,10 +3383,9 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(dev, " C_OVER_CURRENT\n"); /* Clears the driver's overcurrent Change flag */ - spin_lock_irqsave(&priv->lock, flags); - priv->usb.port_status = - cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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"); @@ -3451,7 +3406,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case GetHubStatus: dev_dbg(dev, "GetHubStatus\n"); - *(__le32 *) buf = 0; + *(__le32 *)buf = 0; break; case GetPortStatus: dev_dbg(dev, "GetPortStatus\n"); @@ -3460,9 +3415,9 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, return -EINVAL; } - spin_lock_irqsave(&priv->lock, flags); - usb_port_status = cvmx_usb_get_status(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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) { @@ -3503,7 +3458,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dev_dbg(dev, " LOWSPEED\n"); } - *((__le32 *) buf) = cpu_to_le32(port_status); + *((__le32 *)buf) = cpu_to_le32(port_status); break; case SetHubFeature: dev_dbg(dev, "SetHubFeature\n"); @@ -3525,16 +3480,16 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* * Program the port power bit to drive VBUS on the USB. */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&usb->lock, flags); USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt, prtpwr, 1); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&usb->lock, flags); return 0; case USB_PORT_FEAT_RESET: dev_dbg(dev, " RESET\n"); - spin_lock_irqsave(&priv->lock, flags); - cvmx_usb_reset_port(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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"); @@ -3579,23 +3534,26 @@ static int octeon_usb_probe(struct platform_device *pdev) struct device_node *usbn_node; int irq = platform_get_irq(pdev, 0); struct device *dev = &pdev->dev; - struct octeon_hcd *priv; + 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 == NULL) { + 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, - "refclk-frequency", &clock_rate); + "clock-frequency", &clock_rate); + if (i) + i = of_property_read_u32(usbn_node, + "refclk-frequency", &clock_rate); if (i) { - dev_err(dev, "No USBN \"refclk-frequency\"\n"); + dev_err(dev, "No USBN \"clock-frequency\"\n"); return -ENXIO; } switch (clock_rate) { @@ -3609,14 +3567,16 @@ static int octeon_usb_probe(struct platform_device *pdev) initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; break; default: - dev_err(dev, "Illebal USBN \"refclk-frequency\" %u\n", - clock_rate); + dev_err(dev, "Illegal USBN \"clock-frequency\" %u\n", + clock_rate); return -ENXIO; - } i = of_property_read_string(usbn_node, - "refclk-type", &clock_type); + "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; @@ -3627,7 +3587,7 @@ static int octeon_usb_probe(struct platform_device *pdev) initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem == NULL) { + if (!res_mem) { dev_err(dev, "found no memory resource\n"); return -ENXIO; } @@ -3673,31 +3633,31 @@ static int octeon_usb_probe(struct platform_device *pdev) return -1; } hcd->uses_new_polling = 1; - priv = (struct octeon_hcd *)hcd->hcd_priv; + usb = (struct octeon_hcd *)hcd->hcd_priv; - spin_lock_init(&priv->lock); + spin_lock_init(&usb->lock); - priv->usb.init_flags = initialize_flags; + usb->init_flags = initialize_flags; /* Initialize the USB state structure */ - priv->usb.index = usb_num; - INIT_LIST_HEAD(&priv->usb.idle_pipes); - for (i = 0; i < ARRAY_SIZE(priv->usb.active_pipes); i++) - INIT_LIST_HEAD(&priv->usb.active_pipes[i]); + 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)) { - priv->usb.init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; + usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; /* Only use one channel with non DMA */ - priv->usb.idle_hardware_channels = 0x1; + usb->idle_hardware_channels = 0x1; } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) { /* CN5XXX have an errata with channel 3 */ - priv->usb.idle_hardware_channels = 0xf7; + usb->idle_hardware_channels = 0xf7; } else { - priv->usb.idle_hardware_channels = 0xff; + usb->idle_hardware_channels = 0xff; } - status = cvmx_usb_initialize(dev, &priv->usb); + status = cvmx_usb_initialize(dev, usb); if (status) { dev_dbg(dev, "USB initialization failed with %d\n", status); kfree(hcd); @@ -3722,13 +3682,13 @@ 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 *priv = hcd_to_octeon(hcd); + struct octeon_hcd *usb = hcd_to_octeon(hcd); unsigned long flags; usb_remove_hcd(hcd); - spin_lock_irqsave(&priv->lock, flags); - status = cvmx_usb_shutdown(&priv->usb); - spin_unlock_irqrestore(&priv->lock, flags); + 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); @@ -3747,7 +3707,7 @@ MODULE_DEVICE_TABLE(of, octeon_usb_match); static struct platform_driver octeon_usb_driver = { .driver = { - .name = "OcteonUSB", + .name = "octeon-hcd", .of_match_table = octeon_usb_match, }, .probe = octeon_usb_probe, -- cgit v1.2.3-54-g00ecf