/* * module start/stop */ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usbhs_pipe *pipe; struct renesas_usbhs_driver_pipe_config *pipe_configs = usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int old_type, dir_in, i; /* init all pipe */ old_type = USB_ENDPOINT_XFER_CONTROL; for (i = 0; i < pipe_size; i++) { /* * data "output" will be finished as soon as possible, * but there is no guaranty at data "input" case. * * "input" needs "standby" pipe. * So, "input" direction pipe > "output" direction pipe * is good idea. * * 1st USB_ENDPOINT_XFER_xxx will be output direction, * and the other will be input direction here. * * ex) * ... * USB_ENDPOINT_XFER_ISOC -> dir out * USB_ENDPOINT_XFER_ISOC -> dir in * USB_ENDPOINT_XFER_BULK -> dir out * USB_ENDPOINT_XFER_BULK -> dir in * USB_ENDPOINT_XFER_BULK -> dir in * ... */ dir_in = (pipe_configs[i].type == old_type); old_type = pipe_configs[i].type; if (USB_ENDPOINT_XFER_CONTROL == pipe_configs[i].type) { pipe = usbhs_dcp_malloc(priv); usbhsh_hpriv_to_dcp(hpriv) = pipe; } else { pipe = usbhs_pipe_malloc(priv, pipe_configs[i].type, dir_in); } pipe->mod_private = NULL; } }
/* * local functions */ static void usbhsc_set_buswait(struct usbhs_priv *priv) { int wait = usbhs_get_dparam(priv, buswait_bwait); /* set bus wait if platform have */ if (wait) usbhs_bset(priv, BUSWAIT, 0x000F, wait); }
static struct renesas_usbhs_driver_pipe_config *usbhsp_get_pipe_config(struct usbhs_priv *priv, int pipe_num) { struct renesas_usbhs_driver_pipe_config *pipe_configs = usbhs_get_dparam(priv, pipe_configs); return &pipe_configs[pipe_num]; }
/* * local functions */ static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable) { int wait = usbhs_get_dparam(priv, buswait_bwait); u16 data = 0; if (enable) { /* set bus wait if platform have */ if (wait) usbhs_bset(priv, BUSWAIT, 0x000F, wait); } usbhs_write(priv, DVSTCTR, data); }
int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); int delay = usbhs_get_dparam(priv, detection_delay); /* * This functions will be called in interrupt. * To make sure safety context, * use workqueue for usbhs_notify_hotplug */ schedule_delayed_work(&priv->notify_hotplug_work, delay); return 0; }
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable) { u16 mask = DCFM | DRPD | DPRPU | HSE | USBE; u16 val = DCFM | DRPD | HSE | USBE; int has_otg = usbhs_get_dparam(priv, has_otg); if (has_otg) usbhs_bset(priv, DVSTCTR, (EXTLP | PWEN), (EXTLP | PWEN)); /* * if enable * * - select Host mode * - D+ Line/D- Line Pull-down */ usbhs_bset(priv, SYSCFG, mask, enable ? val : 0); }
static int usbhsf_fifo_select(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo, int write) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct device *dev = usbhs_priv_to_dev(priv); int timeout = 1024; u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ if (usbhs_pipe_is_busy(pipe) || usbhsf_fifo_is_busy(fifo)) return -EBUSY; if (usbhs_pipe_is_dcp(pipe)) { base |= (1 == write) << 5; /* ISEL */ if (usbhs_mod_is_host(priv)) usbhs_dcp_dir_for_host(pipe, write); } /* "base" will be used below */ if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo)) usbhs_write(priv, fifo->sel, base); else usbhs_write(priv, fifo->sel, base | MBW_32); /* check ISEL and CURPIPE value */ while (timeout--) { if (base == (mask & usbhs_read(priv, fifo->sel))) { usbhs_pipe_select_fifo(pipe, fifo); return 0; } udelay(10); } dev_err(dev, "fifo select error\n"); return -EIO; }
/* * interrupt functions */ void usbhs_xxxsts_clear(struct usbhs_priv *priv, u16 sts_reg, u16 bit) { u16 pipe_mask = (u16)GENMASK(usbhs_get_dparam(priv, pipe_size), 0); usbhs_write(priv, sts_reg, ~(1 << bit) & pipe_mask); }
int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv; struct usbhsg_uep *uep; struct device *dev = usbhs_priv_to_dev(priv); int pipe_size = usbhs_get_dparam(priv, pipe_size); int i; int ret; gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); if (!gpriv) { dev_err(dev, "Could not allocate gadget priv\n"); return -ENOMEM; } uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); if (!uep) { dev_err(dev, "Could not allocate ep\n"); ret = -ENOMEM; goto usbhs_mod_gadget_probe_err_gpriv; } /* * 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 "usbhsg_start" */ /* * register itself */ usbhs_mod_register(priv, &gpriv->mod, USBHS_GADGET); /* init gpriv */ gpriv->mod.name = "gadget"; gpriv->mod.start = usbhsg_start; gpriv->mod.stop = usbhsg_stop; gpriv->uep = uep; gpriv->uep_size = pipe_size; usbhsg_status_init(gpriv); /* * init gadget */ device_initialize(&gpriv->gadget.dev); dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.is_dualspeed = 1; INIT_LIST_HEAD(&gpriv->gadget.ep_list); /* * init usb_ep */ usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { uep->gpriv = gpriv; snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); uep->ep.name = uep->ep_name; uep->ep.ops = &usbhsg_ep_ops; INIT_LIST_HEAD(&uep->ep.ep_list); INIT_LIST_HEAD(&uep->list); /* init DCP */ if (usbhsg_is_dcp(uep)) { gpriv->gadget.ep0 = &uep->ep; uep->ep.maxpacket = 64; } /* init normal pipe */ else { uep->ep.maxpacket = 512; list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); } }
int usbhs_mod_gadget_probe(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv; struct usbhsg_uep *uep; struct device *dev = usbhs_priv_to_dev(priv); struct renesas_usbhs_driver_pipe_config *pipe_configs = usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int i; int ret; gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); if (!gpriv) return -ENOMEM; uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); if (!uep) { ret = -ENOMEM; goto usbhs_mod_gadget_probe_err_gpriv; } gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); dev_info(dev, "%stransceiver found\n", !IS_ERR(gpriv->transceiver) ? "" : "no "); /* * 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 "usbhsg_start" */ /* * register itself */ usbhs_mod_register(priv, &gpriv->mod, USBHS_GADGET); /* init gpriv */ gpriv->mod.name = "gadget"; gpriv->mod.start = usbhsg_start; gpriv->mod.stop = usbhsg_stop; gpriv->uep = uep; gpriv->uep_size = pipe_size; usbhsg_status_init(gpriv); /* * init gadget */ gpriv->gadget.dev.parent = dev; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; gpriv->gadget.quirk_avoids_skb_reserve = usbhs_get_dparam(priv, has_usb_dmac); INIT_LIST_HEAD(&gpriv->gadget.ep_list); /* * init usb_ep */ usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { uep->gpriv = gpriv; uep->pipe = NULL; snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); uep->ep.name = uep->ep_name; uep->ep.ops = &usbhsg_ep_ops; INIT_LIST_HEAD(&uep->ep.ep_list); spin_lock_init(&uep->lock); /* init DCP */ if (usbhsg_is_dcp(uep)) { gpriv->gadget.ep0 = &uep->ep; usb_ep_set_maxpacket_limit(&uep->ep, 64); uep->ep.caps.type_control = true; } else { /* init normal pipe */ if (pipe_configs[i].type == USB_ENDPOINT_XFER_ISOC) uep->ep.caps.type_iso = true; if (pipe_configs[i].type == USB_ENDPOINT_XFER_BULK) uep->ep.caps.type_bulk = true; if (pipe_configs[i].type == USB_ENDPOINT_XFER_INT) uep->ep.caps.type_int = true; usb_ep_set_maxpacket_limit(&uep->ep, pipe_configs[i].bufsize); list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); } uep->ep.caps.dir_in = true; uep->ep.caps.dir_out = true; }