int usbhs_mod_probe(struct usbhs_priv *priv) { struct device *dev = usbhs_priv_to_dev(priv); int ret; /* * install host/gadget driver */ ret = usbhs_mod_host_probe(priv); if (ret < 0) return ret; ret = usbhs_mod_gadget_probe(priv); if (ret < 0) goto mod_init_host_err; /* irq settings */ ret = request_irq(priv->irq, usbhs_interrupt, 0, dev_name(dev), priv); if (ret) { dev_err(dev, "irq request err\n"); goto mod_init_gadget_err; } return ret; mod_init_gadget_err: usbhs_mod_gadget_remove(priv); mod_init_host_err: usbhs_mod_host_remove(priv); return ret; }
static void usbhsh_endpoint_detach(struct usbhsh_hpriv *hpriv, struct usb_host_endpoint *ep) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct device *dev = usbhs_priv_to_dev(priv); struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep); unsigned long flags; if (!uep) return; dev_dbg(dev, "%s [%d-%d]\n", __func__, usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)), usb_endpoint_num(&ep->desc)); if (usbhsh_uep_to_pipe(uep)) usbhsh_pipe_detach(hpriv, uep); /******************** spin lock ********************/ usbhs_lock(priv, flags); /* remove this endpoint from udev */ list_del_init(&uep->ep_list); usbhsh_uep_to_udev(uep) = NULL; usbhsh_uep_to_ep(uep) = NULL; usbhsh_ep_to_uep(ep) = NULL; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ kfree(uep); }
/* * queue push/pop */ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) { struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt); struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct urb *urb = ureq->urb; struct device *dev = usbhs_priv_to_dev(priv); int status = 0; dev_dbg(dev, "%s\n", __func__); if (!urb) { dev_warn(dev, "pkt doesn't have urb\n"); return; } if (!usbhsh_is_running(hpriv)) status = -ESHUTDOWN; urb->actual_length = pkt->actual; usbhsh_endpoint_sequence_save(hpriv, urb, pkt); usbhsh_ureq_free(hpriv, ureq); usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); usb_hcd_unlink_urb_from_ep(hcd, urb); usb_hcd_giveback_urb(hcd, urb, status); }
static int usbhsh_stop(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); /* * disable irq callback */ mod->irq_attch = NULL; mod->irq_dtch = NULL; mod->irq_sack = NULL; mod->irq_sign = NULL; usbhs_irq_callback_update(priv, mod); usb_remove_hcd(hcd); /* disable sys */ usbhs_sys_host_ctrl(priv, 0); dev_dbg(dev, "quit host\n"); return 0; }
static int usbhsh_irq_dtch(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct device *dev = usbhs_priv_to_dev(priv); dev_dbg(dev, "device detached\n"); usbhsh_port_stat_clear(hpriv, USB_PORT_STAT_CONNECTION); usbhsh_port_stat_set(hpriv, USB_PORT_STAT_C_CONNECTION << 16); /* * enable attch interrupt again * * usbhsh_is_running() becomes invalid * according to this process. * see * usbhsh_is_running() * usbhsh_urb_enqueue() */ hpriv->mod.irq_attch = usbhsh_irq_attch; usbhs_irq_callback_update(priv, &hpriv->mod); /* * usbhsh_queue_force_pop_all() should be called * after usbhsh_is_running() becomes invalid. */ usbhsh_queue_force_pop_all(priv); return 0; }
/* * * linux usb function * */ static int usbhsg_gadget_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); struct device *dev = usbhs_priv_to_dev(priv); int ret; if (!driver || !driver->setup || driver->max_speed < USB_SPEED_FULL) return -EINVAL; /* connect to bus through transceiver */ if (!IS_ERR_OR_NULL(gpriv->transceiver)) { ret = otg_set_peripheral(gpriv->transceiver->otg, &gpriv->gadget); if (ret) { dev_err(dev, "%s: can't bind to transceiver\n", gpriv->gadget.name); return ret; } /* get vbus using phy versions */ usbhs_mod_phy_mode(priv); } /* first hook up the driver ... */ gpriv->driver = driver; return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); }
/* * PIPEnTRN/PIPEnTRE functions */ static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct device *dev = usbhs_priv_to_dev(priv); int num = usbhs_pipe_number(pipe); u16 reg; /* * It is impossible to calculate address, * since PIPEnTRN addresses were mapped randomly. */ #define CASE_PIPExTRN(a) \ case 0x ## a: \ reg = PIPE ## a ## TRN; \ break; switch (num) { CASE_PIPExTRN(1); CASE_PIPExTRN(2); CASE_PIPExTRN(3); CASE_PIPExTRN(4); CASE_PIPExTRN(5); CASE_PIPExTRN(B); CASE_PIPExTRN(C); CASE_PIPExTRN(D); CASE_PIPExTRN(E); CASE_PIPExTRN(F); CASE_PIPExTRN(9); CASE_PIPExTRN(A); default: dev_err(dev, "unknown pipe (%d)\n", num); return; } __usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val); }
/* * interrupt functions */ static int usbhsh_irq_attch(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct device *dev = usbhs_priv_to_dev(priv); dev_dbg(dev, "device attached\n"); usbhsh_port_stat_set(hpriv, USB_PORT_STAT_CONNECTION); usbhsh_port_stat_set(hpriv, USB_PORT_STAT_C_CONNECTION << 16); /* * attch interrupt might happen infinitely on some device * (on self power USB hub ?) * disable it here. * * usbhsh_is_running() becomes effective * according to this process. * see * usbhsh_is_running() * usbhsh_urb_enqueue() */ hpriv->mod.irq_attch = NULL; usbhs_irq_callback_update(priv, &hpriv->mod); return 0; }
/* * usb module start/end */ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int ret = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); usbhsg_status_set(gpriv, status); if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) ret = -1; /* not ready */ usbhs_unlock(priv, flags); /******************** spin unlock ********************/ if (ret < 0) return 0; /* not ready is not error */ /* * enable interrupt and systems if ready */ dev_dbg(dev, "start gadget\n"); /* * pipe initialize and enable DCP */ usbhs_pipe_init(priv, usbhsg_queue_done, usbhsg_dma_map_ctrl); usbhs_fifo_init(priv); usbhsg_uep_init(gpriv); /* dcp init */ dcp->pipe = usbhs_dcp_malloc(priv); dcp->pipe->mod_private = dcp; /* * system config enble * - HI speed * - function * - usb module */ usbhs_sys_hispeed_ctrl(priv, 1); usbhs_sys_function_ctrl(priv, 1); usbhs_sys_usb_ctrl(priv, 1); /* * enable irq callback */ mod->irq_dev_state = usbhsg_irq_dev_state; mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; usbhs_irq_callback_update(priv, mod); return 0; }
int usbhs_mod_probe(struct usbhs_priv *priv) { struct device *dev = usbhs_priv_to_dev(priv); int ret; ret = usbhs_mod_host_probe(priv); if (ret < 0) return ret; ret = usbhs_mod_gadget_probe(priv); if (ret < 0) goto mod_init_host_err; ret = request_irq(priv->irq, usbhs_interrupt, priv->irqflags, dev_name(dev), priv); if (ret) { dev_err(dev, "irq request err\n"); goto mod_init_gadget_err; } return ret; mod_init_gadget_err: usbhs_mod_gadget_remove(priv); mod_init_host_err: usbhs_mod_host_remove(priv); return ret; }
static int usbhs_rza1_hardware_init(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); struct device_node *usb_x1_clk, *extal_clk; u32 freq_usb = 0, freq_extal = 0; /* Input Clock Selection (NOTE: ch0 controls both ch0 and ch1) */ usb_x1_clk = of_find_node_by_name(NULL, "usb_x1"); extal_clk = of_find_node_by_name(NULL, "extal"); of_property_read_u32(usb_x1_clk, "clock-frequency", &freq_usb); of_property_read_u32(extal_clk, "clock-frequency", &freq_extal); if (freq_usb == 0) { if (freq_extal == 12000000) { /* Select 12MHz XTAL */ usbhs_bset(priv, SYSCFG, UCKSEL, UCKSEL); } else { dev_err(usbhs_priv_to_dev(priv), "A 48MHz USB clock or 12MHz main clock is required.\n"); return -EIO; } } /* Enable USB PLL (NOTE: ch0 controls both ch0 and ch1) */ usbhs_bset(priv, SYSCFG, UPLLE, UPLLE); udelay(1000); usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); return 0; }
static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, struct usbhsh_ep *uep) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhs_pipe *pipe; struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; /******************** spin lock ********************/ usbhs_lock(priv, flags); pipe = usbhsh_uep_to_pipe(uep); if (unlikely(!pipe)) { dev_err(dev, "uep doens't have pipe\n"); } else { struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep); struct usbhsh_device *udev = usbhsh_uep_to_udev(uep); /* detach pipe from uep */ usbhsh_uep_to_pipe(uep) = NULL; usbhsh_pipe_to_uep(pipe) = NULL; dev_dbg(dev, "%s [%d-%d(%s)]\n", __func__, usbhsh_device_number(hpriv, udev), usb_endpoint_num(&ep->desc), usbhs_pipe_name(pipe)); } usbhs_unlock(priv, flags); /******************** spin unlock ******************/ }
/* * power control */ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) { struct platform_device *pdev = usbhs_priv_to_pdev(priv); struct device *dev = usbhs_priv_to_dev(priv); if (enable) { /* enable PM */ pm_runtime_get_sync(dev); /* enable platform power */ usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable); /* USB on */ usbhs_sys_clock_ctrl(priv, enable); } else { /* USB off */ usbhs_sys_clock_ctrl(priv, enable); /* disable platform power */ usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable); /* disable PM */ pm_runtime_put_sync(dev); } }
/* * packet control function */ static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); struct device *dev = usbhs_priv_to_dev(priv); dev_err(dev, "null handler\n"); return -EINVAL; }
/* * usb module start/end */ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); spinlock_t *lock; unsigned long flags; /******************** spin lock ********************/ lock = usbhsg_trylock(gpriv, &flags); /* * enable interrupt and systems if ready */ usbhsg_status_set(gpriv, status); if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) goto usbhsg_try_start_unlock; dev_dbg(dev, "start gadget\n"); /* * pipe initialize and enable DCP */ usbhs_pipe_init(priv); usbhsg_uep_init(gpriv); usbhsg_dcp_enable(dcp); /* * system config enble * - HI speed * - function * - usb module */ usbhs_sys_hispeed_ctrl(priv, 1); usbhs_sys_function_ctrl(priv, 1); usbhs_sys_usb_ctrl(priv, 1); /* * enable irq callback */ mod->irq_dev_state = usbhsg_irq_dev_state; mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; mod->irq_empty = usbhsg_irq_empty; mod->irq_ready = usbhsg_irq_ready; mod->irq_bempsts = 0; mod->irq_brdysts = 0; usbhs_irq_callback_update(priv, mod); usbhsg_try_start_unlock: usbhsg_unlock(lock, &flags); /******************** spin unlock ********************/ return 0; }
static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct device *dev = usbhs_priv_to_dev(priv); spinlock_t *lock; unsigned long flags; /******************** spin lock ********************/ lock = usbhsg_trylock(gpriv, &flags); /* * disable interrupt and systems if 1st try */ usbhsg_status_clr(gpriv, status); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) goto usbhsg_try_stop_unlock; /* disable all irq */ mod->irq_dev_state = NULL; mod->irq_ctrl_stage = NULL; mod->irq_empty = NULL; mod->irq_ready = NULL; mod->irq_bempsts = 0; mod->irq_brdysts = 0; usbhs_irq_callback_update(priv, mod); usbhsg_dcp_disable(dcp); gpriv->gadget.speed = USB_SPEED_UNKNOWN; /* disable sys */ usbhs_sys_hispeed_ctrl(priv, 0); usbhs_sys_function_ctrl(priv, 0); usbhs_sys_usb_ctrl(priv, 0); usbhsg_unlock(lock, &flags); /******************** spin unlock ********************/ if (gpriv->driver && gpriv->driver->disconnect) gpriv->driver->disconnect(&gpriv->gadget); dev_dbg(dev, "stop gadget\n"); return 0; usbhsg_try_stop_unlock: usbhsg_unlock(lock, &flags); return 0; }
/* * bus/vbus functions */ void usbhs_bus_send_sof_enable(struct usbhs_priv *priv) { u16 status = usbhs_read(priv, DVSTCTR) & (USBRST | UACT); if (status != USBRST) { struct device *dev = usbhs_priv_to_dev(priv); dev_err(dev, "usbhs should be reset\n"); } usbhs_bset(priv, DVSTCTR, (USBRST | UACT), UACT); }
static int usbhsh_irq_setup_err(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct device *dev = usbhs_priv_to_dev(priv); dev_dbg(dev, "setup packet Err\n"); complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */ return 0; }
/* * DCP status stage */ static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done) { struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ struct device *dev = usbhs_priv_to_dev(priv); int ret; usbhs_pipe_disable(pipe); ret = usbhsf_fifo_select(pipe, fifo, 1); if (ret < 0) { dev_err(dev, "%s() faile\n",
static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int ret = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); usbhsg_status_clr(gpriv, status); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) ret = -1; /* already done */ usbhs_unlock(priv, flags); /******************** spin unlock ********************/ if (ret < 0) return 0; /* already done is not error */ /* * disable interrupt and systems if 1st try */ usbhs_fifo_quit(priv); /* disable all irq */ mod->irq_dev_state = NULL; mod->irq_ctrl_stage = NULL; usbhs_irq_callback_update(priv, mod); gpriv->gadget.speed = USB_SPEED_UNKNOWN; /* disable sys */ usbhs_sys_hispeed_ctrl(priv, 0); usbhs_sys_function_ctrl(priv, 0); usbhs_sys_usb_ctrl(priv, 0); usbhsg_pipe_disable(dcp); if (gpriv->driver && gpriv->driver->disconnect) gpriv->driver->disconnect(&gpriv->gadget); dev_dbg(dev, "stop gadget\n"); return 0; }
static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_pkt *pkt; struct device *dev = usbhs_priv_to_dev(priv); int (*func)(struct usbhs_pkt *pkt, int *is_done); unsigned long flags; int ret = 0; int is_done = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); pkt = __usbhsf_pkt_get(pipe); if (!pkt) goto __usbhs_pkt_handler_end; switch (type) { case USBHSF_PKT_PREPARE: func = pkt->handler->prepare; break; case USBHSF_PKT_TRY_RUN: func = pkt->handler->try_run; break; case USBHSF_PKT_DMA_DONE: func = pkt->handler->dma_done; break; default: dev_err(dev, "unknown pkt hander\n"); goto __usbhs_pkt_handler_end; } ret = func(pkt, &is_done); if (is_done) __usbhsf_pkt_del(pkt); __usbhs_pkt_handler_end: usbhs_unlock(priv, flags); /******************** spin unlock ******************/ if (is_done) { pkt->done(priv, pkt); usbhs_pkt_start(pipe); } return ret; }
static int __usbhsh_hub_hub_feature(struct usbhsh_hpriv *hpriv, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct device *dev = usbhs_priv_to_dev(priv); switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: dev_dbg(dev, "%s :: C_HUB_xx\n", __func__); return 0; } return -EPIPE; }
static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv, struct urb *urb, struct usbhs_pipe *pipe) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usb_ctrlrequest req; struct device *dev = usbhs_priv_to_dev(priv); /* * wait setup packet ACK * see * usbhsh_irq_setup_ack() * usbhsh_irq_setup_err() */ init_completion(&hpriv->setup_ack_done); /* copy original request */ memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest)); /* * renesas_usbhs can not use original usb address. * see HARDWARE LIMITATION. * modify usb address here to use attached device. * see usbhsh_device_attach() */ if (usbhsh_is_request_address(urb)) { struct usb_device *usbv = usbhsh_urb_to_usbv(urb); struct usbhsh_device *udev = usbhsh_usbv_to_udev(usbv); /* udev is a attached device */ req.wValue = usbhsh_device_number(hpriv, udev); dev_dbg(dev, "create new address - %d\n", req.wValue); } /* set request */ usbhs_usbreq_set_val(priv, &req); /* * wait setup packet ACK */ wait_for_completion(&hpriv->setup_ack_done); dev_dbg(dev, "%s done\n", __func__); }
static int usbhsh_start(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); int ret; /* add hcd */ ret = usb_add_hcd(hcd, 0, 0); if (ret < 0) return 0; device_wakeup_enable(hcd->self.controller); /* * pipe initialize and enable DCP */ usbhs_fifo_init(priv); usbhs_pipe_init(priv, usbhsh_dma_map_ctrl); usbhsh_pipe_init_for_host(priv); /* * system config enble * - HI speed * - host * - usb module */ usbhs_sys_host_ctrl(priv, 1); /* * enable irq callback */ mod->irq_attch = usbhsh_irq_attch; mod->irq_dtch = usbhsh_irq_dtch; mod->irq_sack = usbhsh_irq_setup_ack; mod->irq_sign = usbhsh_irq_setup_err; usbhs_irq_callback_update(priv, mod); dev_dbg(dev, "start host\n"); return ret; }
int usbhs_mod_host_probe(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv; struct usb_hcd *hcd; struct usbhsh_device *udev; struct device *dev = usbhs_priv_to_dev(priv); int i; /* initialize hcd */ hcd = usb_create_hcd(&usbhsh_driver, dev, usbhsh_hcd_name); if (!hcd) { dev_err(dev, "Failed to create hcd\n"); return -ENOMEM; } hcd->has_tt = 1; /* for low/full speed */ /* * CAUTION * * There is no guarantee that it is possible to access usb module here. * Don't accesses to it. * The accesse will be enable after "usbhsh_start" */ hpriv = usbhsh_hcd_to_hpriv(hcd); /* * register itself */ usbhs_mod_register(priv, &hpriv->mod, USBHS_HOST); /* init hpriv */ hpriv->mod.name = "host"; hpriv->mod.start = usbhsh_start; hpriv->mod.stop = usbhsh_stop; usbhsh_port_stat_init(hpriv); /* init all device */ usbhsh_for_each_udev_with_dev0(udev, hpriv, i) { udev->usbv = NULL; INIT_LIST_HEAD(&udev->ep_list_head); }
/* * power control */ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) { struct device *dev = usbhs_priv_to_dev(priv); if (enable) { /* enable PM */ pm_runtime_get_sync(dev); /* USB on */ usbhs_sys_clock_ctrl(priv, enable); usbhsc_bus_ctrl(priv, enable); } else { /* USB off */ usbhsc_bus_ctrl(priv, enable); usbhs_sys_clock_ctrl(priv, enable); /* disable PM */ pm_runtime_put_sync(dev); } }
/* * req alloc/free */ static struct usbhsh_request *usbhsh_ureq_alloc(struct usbhsh_hpriv *hpriv, struct urb *urb, gfp_t mem_flags) { struct usbhsh_request *ureq; struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct device *dev = usbhs_priv_to_dev(priv); ureq = kzalloc(sizeof(struct usbhsh_request), mem_flags); if (!ureq) { dev_err(dev, "ureq alloc fail\n"); return NULL; } usbhs_pkt_init(&ureq->pkt); ureq->urb = urb; usbhsh_urb_to_ureq(urb) = ureq; return ureq; }
static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf) { struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct device *dev = usbhs_priv_to_dev(priv); int roothub_id = 1; /* only 1 root hub */ /* * does port stat was changed ? * check USB_PORT_STAT_C_xxx << 16 */ if (usbhsh_port_stat_get(hpriv) & 0xFFFF0000) *buf = (1 << roothub_id); else *buf = 0; dev_dbg(dev, "%s (%02x)\n", __func__, *buf); return !!(*buf); }
/* * endpoint control */ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv, struct urb *urb, gfp_t mem_flags) { struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb); struct usb_host_endpoint *ep = urb->ep; struct usbhsh_ep *uep; struct device *dev = usbhs_priv_to_dev(priv); struct usb_endpoint_descriptor *desc = &ep->desc; unsigned long flags; uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags); if (!uep) { dev_err(dev, "usbhsh_ep alloc fail\n"); return -ENOMEM; } /******************** spin lock ********************/ usbhs_lock(priv, flags); /* * init endpoint */ uep->counter = 0; INIT_LIST_HEAD(&uep->ep_list); list_add_tail(&uep->ep_list, &udev->ep_list_head); usbhsh_uep_to_udev(uep) = udev; usbhsh_uep_to_ep(uep) = ep; usbhsh_ep_to_uep(ep) = uep; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ dev_dbg(dev, "%s [%d-%d]\n", __func__, usbhsh_device_number(hpriv, udev), usb_endpoint_num(desc)); return 0; }
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt), void *buf, int len, int zero, int sequence) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; if (!done) { dev_err(dev, "no done function\n"); return; } /******************** spin lock ********************/ usbhs_lock(priv, flags); if (!pipe->handler) { dev_err(dev, "no handler function\n"); pipe->handler = &usbhsf_null_handler; } list_move_tail(&pkt->node, &pipe->list); /* * each pkt must hold own handler. * because handler might be changed by its situation. * dma handler -> pio handler. */ pkt->pipe = pipe; pkt->buf = buf; pkt->handler = pipe->handler; pkt->length = len; pkt->zero = zero; pkt->actual = 0; pkt->done = done; pkt->sequence = sequence; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ }