/** * ipa_data_resume() - Initiate USB resume functionality * @gp: Gadget IPA port * @port_num: port number used by function * * It is being used to initiate USB resume functionality * for USB bus resume case. */ void ipa_data_resume(struct gadget_ipa_port *gp, u8 port_num) { struct ipa_data_ch_info *port; unsigned long flags; struct usb_gadget *gadget = NULL; int ret; pr_debug("dev:%p port number:%d\n", gp, port_num); if (port_num >= n_ipa_ports) { pr_err("invalid ipa portno#%d\n", port_num); return; } if (!gp) { pr_err("data port is null\n"); return; } port = ipa_data_ports[port_num]; if (!port) { pr_err("port %u is NULL", port_num); return; } pr_debug("%s: resume started\n", __func__); spin_lock_irqsave(&port->port_lock, flags); gadget = port->port_usb->cdev->gadget; if (!gadget) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s(): Gadget is NULL.\n", __func__); return; } ret = usb_bam_register_wake_cb(port->dst_connection_idx, NULL, NULL); if (ret) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s(): Failed to register BAM wake callback.\n", __func__); return; } if (msm_dwc3_reset_ep_after_lpm(gadget)) { configure_fifo(port->src_bam_idx, port->port_usb->out); configure_fifo(port->dst_bam_idx, port->port_usb->in); spin_unlock_irqrestore(&port->port_lock, flags); msm_dwc3_reset_dbm_ep(port->port_usb->in); spin_lock_irqsave(&port->port_lock, flags); usb_bam_resume(&port->ipa_params); } spin_unlock_irqrestore(&port->port_lock, flags); }
/** * ipa_data_start() - Restart USB endless transfer * @param: IPA data channel information * @dir: USB BAM pipe direction * * It is being used to restart USB endless transfer for USB bus resume. * For USB consumer case, it restarts USB endless RX transfer, whereas * for USB producer case, it resets DBM endpoint and restart USB endless * TX transfer. */ static void ipa_data_start(void *param, enum usb_bam_pipe_dir dir) { struct ipa_data_ch_info *port = param; struct usb_gadget *gadget = NULL; if (!port || !port->port_usb || !port->port_usb->cdev->gadget) { pr_err("%s:port,cdev or gadget is NULL\n", __func__); return; } gadget = port->port_usb->cdev->gadget; if (dir == USB_TO_PEER_PERIPHERAL) { pr_debug("%s(): start endless RX\n", __func__); ipa_data_start_endless_xfer(port, false); } else { pr_debug("%s(): start endless TX\n", __func__); if (msm_dwc3_reset_ep_after_lpm(gadget)) { u8 idx; idx = usb_bam_get_connection_idx(gadget->name, IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 1); if (idx < 0) { pr_err("%s: get_connection_idx failed\n", __func__); return; } configure_fifo(idx, port->port_usb->in); } ipa_data_start_endless_xfer(port, true); } }
void main_init() { REVCTL = 0x03; SYNCDELAY(); SETIF48MHZ(); SYNCDELAY(); // Configure port PORTACFG = 0x00; SYNCDELAY(); PORTCCFG = 0x00; SYNCDELAY(); PORTECFG = 0x00; SYNCDELAY(); // set IFCONFIG EP1INCFG &= ~bmVALID; SYNCDELAY(); EP1OUTCFG &= ~bmVALID; SYNCDELAY(); EP2CFG = (bmVALID | bmBULK | bmBUF4X /*| bmBUF1024*/ | bmDIR); SYNCDELAY(); EP4CFG &= ~bmVALID; /* = (bmVALID | bmISO | bmBUF2X | bmDIR);*/ SYNCDELAY(); EP6CFG = (bmVALID | bmBULK | bmBUF2X | bmDIR); SYNCDELAY(); EP8CFG &= ~bmVALID; SYNCDELAY(); reset(); #ifndef SIMULATION configure_fifo(); #endif }
/** * ipa_data_connect_work() - Perform USB IPA BAM connect * @w: connect work * * It is being schedule from ipa_data_connect() API when particular function * which is using USB IPA accelerated path. This API performs allocating request * for USB endpoint (tx/rx) for endless purpose, configure USB endpoint to be * used in accelerated path, connect of USB BAM pipe, IPA BAM pipe and also * initiate USB IPA BAM pipe handshake for connect sequence. */ static void ipa_data_connect_work(struct work_struct *w) { struct ipa_data_ch_info *port = container_of(w, struct ipa_data_ch_info, connect_w); struct gadget_ipa_port *gport; struct usb_gadget *gadget = NULL; u32 sps_params; int ret; unsigned long flags; bool is_ipa_disconnected = true; pr_debug("%s: Connect workqueue started", __func__); spin_lock_irqsave(&port->port_lock, flags); if (!port->port_usb) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s(): port_usb is NULL.\n", __func__); return; } gport = port->port_usb; if (gport && gport->cdev) gadget = gport->cdev->gadget; if (!gadget) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s: gport is NULL.\n", __func__); return; } gport->ipa_consumer_ep = -1; gport->ipa_producer_ep = -1; if (gport->out) { port->rx_req = usb_ep_alloc_request(gport->out, GFP_ATOMIC); if (!port->rx_req) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s: failed to allocate rx_req\n", __func__); return; } port->rx_req->context = port; port->rx_req->complete = ipa_data_endless_complete; port->rx_req->length = 0; port->rx_req->no_interrupt = 1; } if (gport->in) { port->tx_req = usb_ep_alloc_request(gport->in, GFP_ATOMIC); if (!port->tx_req) { spin_unlock_irqrestore(&port->port_lock, flags); pr_err("%s: failed to allocate tx_req\n", __func__); goto free_rx_req; } port->tx_req->context = port; port->tx_req->complete = ipa_data_endless_complete; port->tx_req->length = 0; port->tx_req->no_interrupt = 1; } port->is_connected = true; spin_unlock_irqrestore(&port->port_lock, flags); /* update IPA Parameteres here. */ port->ipa_params.usb_connection_speed = gadget->speed; if (gadget_is_dwc3(gadget)) port->ipa_params.reset_pipe_after_lpm = msm_dwc3_reset_ep_after_lpm(gadget); port->ipa_params.skip_ep_cfg = true; port->ipa_params.keep_ipa_awake = true; port->ipa_params.cons_clnt_hdl = -1; port->ipa_params.prod_clnt_hdl = -1; /* * Perform below operations for Tx from Device (OUT transfer) * 1. Connect with pipe of USB BAM with IPA BAM pipe * 2. Update USB Endpoint related information using SPS Param. * 3. Configure USB Endpoint/DBM for the same. * 4. Override USB ep queue functionality for endless transfer. */ if (gport->out) { pr_debug("configure bam ipa connect for USB OUT\n"); port->ipa_params.dir = USB_TO_PEER_PERIPHERAL; ret = usb_bam_connect_ipa(&port->ipa_params); if (ret) { pr_err("usb_bam_connect_ipa out failed err:%d\n", ret); goto free_rx_tx_req; } gadget->bam2bam_func_enabled = true; gport->ipa_consumer_ep = port->ipa_params.ipa_cons_ep_idx; if (gadget_is_dwc3(gadget)) { sps_params = MSM_SPS_MODE | MSM_DISABLE_WB | MSM_PRODUCER | port->src_pipe_idx; port->rx_req->length = 32*1024; } else { sps_params = (MSM_SPS_MODE | port->src_pipe_idx | MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER; } port->rx_req->udc_priv = sps_params; port->src_bam_idx = usb_bam_get_connection_idx( gadget->name, IPA_P_BAM, USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE, 1); if (port->src_bam_idx < 0) { pr_err("src_bam: get_connection_idx failed\n"); goto disconnect_usb_bam_ipa_out; } if (gadget_is_dwc3(gadget)) { configure_fifo(port->src_bam_idx, port->port_usb->out); ret = msm_ep_config(port->port_usb->out); if (ret) { pr_err("msm_ep_config() failed for OUT EP\n"); goto disconnect_usb_bam_ipa_out; } } is_ipa_disconnected = false; } if (gport->in) { pr_debug("configure bam ipa connect for USB IN\n"); port->ipa_params.dir = PEER_PERIPHERAL_TO_USB; port->ipa_params.dst_client = IPA_CLIENT_USB_DPL_CONS; ret = usb_bam_connect_ipa(&port->ipa_params); if (ret) { pr_err("usb_bam_connect_ipa IN failed err:%d\n", ret); goto unconfig_msm_ep_out; } gadget->bam2bam_func_enabled = true; gport->ipa_producer_ep = port->ipa_params.ipa_prod_ep_idx; if (gadget_is_dwc3(gadget)) { sps_params = MSM_SPS_MODE | MSM_DISABLE_WB | port->dst_pipe_idx; port->tx_req->length = 32*1024; } else { sps_params = (MSM_SPS_MODE | port->dst_pipe_idx | MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER; } port->tx_req->udc_priv = sps_params; port->dst_bam_idx = usb_bam_get_connection_idx(gadget->name, IPA_P_BAM, PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 1); if (port->dst_bam_idx < 0) { pr_err("dst_bam: get_connection_idx failed\n"); goto disconnect_usb_bam_ipa_in; } if (gadget_is_dwc3(gadget)) { configure_fifo(port->dst_bam_idx, gport->in); ret = msm_ep_config(gport->in); if (ret) { pr_err("msm_ep_config() failed for IN EP\n"); goto disconnect_usb_bam_ipa_in; } } is_ipa_disconnected = false; } pr_debug("ipa_producer_ep:%d ipa_consumer_ep:%d\n", gport->ipa_producer_ep, gport->ipa_consumer_ep); gqti_ctrl_update_ipa_pipes(NULL, DPL_QTI_CTRL_PORT_NO, gport->ipa_producer_ep, gport->ipa_consumer_ep); pr_debug("src_bam_idx:%d dst_bam_idx:%d\n", port->src_bam_idx, port->dst_bam_idx); if (gport->out) ipa_data_start_endless_xfer(port, false); if (gport->in) ipa_data_start_endless_xfer(port, true); pr_debug("Connect workqueue done (port %p)", port); return; disconnect_usb_bam_ipa_in: if (!is_ipa_disconnected) { usb_bam_disconnect_ipa(&port->ipa_params); is_ipa_disconnected = true; } unconfig_msm_ep_out: if (gport->out) msm_ep_unconfig(port->port_usb->out); disconnect_usb_bam_ipa_out: if (!is_ipa_disconnected) { usb_bam_disconnect_ipa(&port->ipa_params); is_ipa_disconnected = true; } free_rx_tx_req: spin_lock_irqsave(&port->port_lock, flags); port->is_connected = false; spin_unlock_irqrestore(&port->port_lock, flags); if (gport->in && port->tx_req) usb_ep_free_request(gport->in, port->tx_req); free_rx_req: if (gport->out && port->rx_req) usb_ep_free_request(gport->out, port->rx_req); }