Lines Matching +full:max +full:- +full:speed

1 // SPDX-License-Identifier: GPL-2.0+
3 * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
5 * dev.c - Individual device/gadget management (ie, a port = a gadget)
25 #include <linux/dma-mapping.h>
33 u32 istat = readl(d->regs + AST_VHUB_DEV_ISR); in ast_vhub_dev_irq()
35 writel(istat, d->regs + AST_VHUB_DEV_ISR); in ast_vhub_dev_irq()
38 ast_vhub_ep0_handle_ack(&d->ep0, true); in ast_vhub_dev_irq()
40 ast_vhub_ep0_handle_ack(&d->ep0, false); in ast_vhub_dev_irq()
42 ast_vhub_ep0_handle_setup(&d->ep0); in ast_vhub_dev_irq()
49 if (d->enabled) in ast_vhub_dev_enable()
60 if (d->gadget.speed == USB_SPEED_HIGH) in ast_vhub_dev_enable()
62 writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL); in ast_vhub_dev_enable()
65 hmsk = VHUB_IRQ_DEVICE1 << d->index; in ast_vhub_dev_enable()
66 reg = readl(d->vhub->regs + AST_VHUB_IER); in ast_vhub_dev_enable()
68 writel(reg, d->vhub->regs + AST_VHUB_IER); in ast_vhub_dev_enable()
71 writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA); in ast_vhub_dev_enable()
74 for (i = 0; i < d->max_epns; i++) { in ast_vhub_dev_enable()
75 struct ast_vhub_ep *ep = d->epns[i]; in ast_vhub_dev_enable()
77 if (ep && (ep->epn.stalled || ep->epn.wedged)) { in ast_vhub_dev_enable()
78 ep->epn.stalled = false; in ast_vhub_dev_enable()
79 ep->epn.wedged = false; in ast_vhub_dev_enable()
85 d->wakeup_en = false; in ast_vhub_dev_enable()
86 d->enabled = true; in ast_vhub_dev_enable()
93 if (!d->enabled) in ast_vhub_dev_disable()
97 hmsk = VHUB_IRQ_DEVICE1 << d->index; in ast_vhub_dev_disable()
98 reg = readl(d->vhub->regs + AST_VHUB_IER); in ast_vhub_dev_disable()
100 writel(reg, d->vhub->regs + AST_VHUB_IER); in ast_vhub_dev_disable()
103 writel(0, d->regs + AST_VHUB_DEV_EN_CTRL); in ast_vhub_dev_disable()
104 d->gadget.speed = USB_SPEED_UNKNOWN; in ast_vhub_dev_disable()
105 d->enabled = false; in ast_vhub_dev_disable()
118 d->wakeup_en = is_set; in ast_vhub_dev_feature()
123 val = readl(d->vhub->regs + AST_VHUB_CTRL); in ast_vhub_dev_feature()
126 writel(val, d->vhub->regs + AST_VHUB_CTRL); in ast_vhub_dev_feature()
145 if (ep_num >= d->max_epns || !d->epns[ep_num - 1]) in ast_vhub_ep_feature()
150 ep = d->epns[ep_num - 1]; in ast_vhub_ep_feature()
154 if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso || in ast_vhub_ep_feature()
155 ep->epn.is_in != !!(wIndex & USB_DIR_IN)) in ast_vhub_ep_feature()
160 ep->epn.stalled = is_set; in ast_vhub_ep_feature()
173 st0 = d->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED; in ast_vhub_dev_status()
174 if (d->wakeup_en) in ast_vhub_dev_status()
177 return ast_vhub_simple_reply(&d->ep0, st0, 0); in ast_vhub_dev_status()
189 if (ep_num >= d->max_epns) in ast_vhub_ep_status()
192 ep = d->epns[ep_num - 1]; in ast_vhub_ep_status()
195 if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso || in ast_vhub_ep_status()
196 ep->epn.is_in != !!(wIndex & USB_DIR_IN)) in ast_vhub_ep_status()
198 if (ep->epn.stalled) in ast_vhub_ep_status()
202 return ast_vhub_simple_reply(&d->ep0, st0, 0); in ast_vhub_ep_status()
211 reg = readl(d->regs + AST_VHUB_DEV_EN_CTRL); in ast_vhub_dev_set_address()
214 writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL); in ast_vhub_dev_set_address()
220 struct ast_vhub_dev *d = ep->dev; in ast_vhub_std_dev_request()
224 if (!d->driver || !d->enabled) { in ast_vhub_std_dev_request()
227 d->driver, d->enabled); in ast_vhub_std_dev_request()
237 /* First packet, grab speed */ in ast_vhub_std_dev_request()
238 if (d->gadget.speed == USB_SPEED_UNKNOWN) { in ast_vhub_std_dev_request()
239 d->gadget.speed = ep->vhub->speed; in ast_vhub_std_dev_request()
240 if (d->gadget.speed > d->driver->max_speed) in ast_vhub_std_dev_request()
241 d->gadget.speed = d->driver->max_speed; in ast_vhub_std_dev_request()
242 DDBG(d, "fist packet, captured speed %d\n", in ast_vhub_std_dev_request()
243 d->gadget.speed); in ast_vhub_std_dev_request()
246 wValue = le16_to_cpu(crq->wValue); in ast_vhub_std_dev_request()
247 wIndex = le16_to_cpu(crq->wIndex); in ast_vhub_std_dev_request()
249 switch ((crq->bRequestType << 8) | crq->bRequest) { in ast_vhub_std_dev_request()
280 int rc = -EINVAL; in ast_vhub_udc_wakeup()
282 spin_lock_irqsave(&d->vhub->lock, flags); in ast_vhub_udc_wakeup()
283 if (!d->wakeup_en) in ast_vhub_udc_wakeup()
289 ast_vhub_hub_wake_all(d->vhub); in ast_vhub_udc_wakeup()
292 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_udc_wakeup()
300 return (readl(d->vhub->regs + AST_VHUB_USBSTS) >> 16) & 0x7ff; in ast_vhub_udc_get_frame()
307 for (i = 0; i < d->max_epns; i++) { in ast_vhub_dev_nuke()
308 if (!d->epns[i]) in ast_vhub_dev_nuke()
310 ast_vhub_nuke(d->epns[i], -ESHUTDOWN); in ast_vhub_dev_nuke()
319 spin_lock_irqsave(&d->vhub->lock, flags); in ast_vhub_udc_pullup()
324 ast_vhub_device_connect(d->vhub, d->index, on); in ast_vhub_udc_pullup()
330 if (d->enabled) { in ast_vhub_udc_pullup()
335 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_udc_pullup()
346 spin_lock_irqsave(&d->vhub->lock, flags); in ast_vhub_udc_start()
351 d->driver = driver; in ast_vhub_udc_start()
352 d->gadget.is_selfpowered = 1; in ast_vhub_udc_start()
354 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_udc_start()
366 unsigned int max, addr, i; in ast_vhub_udc_match_ep() local
376 list_for_each_entry(u_ep, &gadget->ep_list, ep_list) { in ast_vhub_udc_match_ep()
378 DDBG(d, " -> using existing EP%d\n", in ast_vhub_udc_match_ep()
379 to_ast_ep(u_ep)->d_idx); in ast_vhub_udc_match_ep()
394 /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ in ast_vhub_udc_match_ep()
396 max = 1024; in ast_vhub_udc_match_ep()
398 max = 1023; in ast_vhub_udc_match_ep()
402 max = 512; in ast_vhub_udc_match_ep()
404 max = 64; in ast_vhub_udc_match_ep()
408 max = 1024; in ast_vhub_udc_match_ep()
410 max = 64; in ast_vhub_udc_match_ep()
413 if (usb_endpoint_maxp(desc) > max) in ast_vhub_udc_match_ep()
424 for (i = 0; i < d->max_epns; i++) in ast_vhub_udc_match_ep()
425 if (d->epns[i] == NULL) in ast_vhub_udc_match_ep()
427 if (i >= d->max_epns) in ast_vhub_udc_match_ep()
439 ep->epn.g_idx, addr); in ast_vhub_udc_match_ep()
441 return &ep->ep; in ast_vhub_udc_match_ep()
449 spin_lock_irqsave(&d->vhub->lock, flags); in ast_vhub_udc_stop()
453 d->driver = NULL; in ast_vhub_udc_stop()
454 d->gadget.speed = USB_SPEED_UNKNOWN; in ast_vhub_udc_stop()
458 if (d->enabled) in ast_vhub_udc_stop()
461 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_udc_stop()
477 if (d->driver && d->driver->suspend) { in ast_vhub_dev_suspend()
478 spin_unlock(&d->vhub->lock); in ast_vhub_dev_suspend()
479 d->driver->suspend(&d->gadget); in ast_vhub_dev_suspend()
480 spin_lock(&d->vhub->lock); in ast_vhub_dev_suspend()
486 if (d->driver && d->driver->resume) { in ast_vhub_dev_resume()
487 spin_unlock(&d->vhub->lock); in ast_vhub_dev_resume()
488 d->driver->resume(&d->gadget); in ast_vhub_dev_resume()
489 spin_lock(&d->vhub->lock); in ast_vhub_dev_resume()
496 if (!d->driver) { in ast_vhub_dev_reset()
502 if (!d->enabled) { in ast_vhub_dev_reset()
507 spin_unlock(&d->vhub->lock); in ast_vhub_dev_reset()
508 usb_gadget_udc_reset(&d->gadget, d->driver); in ast_vhub_dev_reset()
509 spin_lock(&d->vhub->lock); in ast_vhub_dev_reset()
512 * Disable and maybe re-enable HW, this will clear the address in ast_vhub_dev_reset()
513 * and speed setting. in ast_vhub_dev_reset()
524 spin_lock_irqsave(&d->vhub->lock, flags); in ast_vhub_del_dev()
525 if (!d->registered) { in ast_vhub_del_dev()
526 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_del_dev()
529 d->registered = false; in ast_vhub_del_dev()
530 spin_unlock_irqrestore(&d->vhub->lock, flags); in ast_vhub_del_dev()
532 usb_del_gadget_udc(&d->gadget); in ast_vhub_del_dev()
533 device_unregister(d->port_dev); in ast_vhub_del_dev()
534 kfree(d->epns); in ast_vhub_del_dev()
544 struct ast_vhub_dev *d = &vhub->ports[idx].dev; in ast_vhub_init_dev()
545 struct device *parent = &vhub->pdev->dev; in ast_vhub_init_dev()
548 d->vhub = vhub; in ast_vhub_init_dev()
549 d->index = idx; in ast_vhub_init_dev()
550 d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1); in ast_vhub_init_dev()
551 d->regs = vhub->regs + 0x100 + 0x10 * idx; in ast_vhub_init_dev()
553 ast_vhub_init_ep0(vhub, &d->ep0, d); in ast_vhub_init_dev()
559 d->max_epns = min_t(u32, vhub->max_epns, 30); in ast_vhub_init_dev()
560 d->epns = kcalloc(d->max_epns, sizeof(*d->epns), GFP_KERNEL); in ast_vhub_init_dev()
561 if (!d->epns) in ast_vhub_init_dev()
562 return -ENOMEM; in ast_vhub_init_dev()
569 d->port_dev = kzalloc(sizeof(struct device), GFP_KERNEL); in ast_vhub_init_dev()
570 if (!d->port_dev) { in ast_vhub_init_dev()
571 rc = -ENOMEM; in ast_vhub_init_dev()
574 device_initialize(d->port_dev); in ast_vhub_init_dev()
575 d->port_dev->release = ast_vhub_dev_release; in ast_vhub_init_dev()
576 d->port_dev->parent = parent; in ast_vhub_init_dev()
577 dev_set_name(d->port_dev, "%s:p%d", dev_name(parent), idx + 1); in ast_vhub_init_dev()
578 rc = device_add(d->port_dev); in ast_vhub_init_dev()
583 INIT_LIST_HEAD(&d->gadget.ep_list); in ast_vhub_init_dev()
584 d->gadget.ops = &ast_vhub_udc_ops; in ast_vhub_init_dev()
585 d->gadget.ep0 = &d->ep0.ep; in ast_vhub_init_dev()
586 d->gadget.name = KBUILD_MODNAME; in ast_vhub_init_dev()
587 if (vhub->force_usb1) in ast_vhub_init_dev()
588 d->gadget.max_speed = USB_SPEED_FULL; in ast_vhub_init_dev()
590 d->gadget.max_speed = USB_SPEED_HIGH; in ast_vhub_init_dev()
591 d->gadget.speed = USB_SPEED_UNKNOWN; in ast_vhub_init_dev()
592 d->gadget.dev.of_node = vhub->pdev->dev.of_node; in ast_vhub_init_dev()
593 d->gadget.dev.of_node_reused = true; in ast_vhub_init_dev()
595 rc = usb_add_gadget_udc(d->port_dev, &d->gadget); in ast_vhub_init_dev()
598 d->registered = true; in ast_vhub_init_dev()
602 device_del(d->port_dev); in ast_vhub_init_dev()
604 put_device(d->port_dev); in ast_vhub_init_dev()
606 kfree(d->epns); in ast_vhub_init_dev()