Lines Matching +full:vhub +full:- +full:strings

1 // SPDX-License-Identifier: GPL-2.0+
3 * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
5 * hub.c - virtual hub handling
26 #include <linux/dma-mapping.h>
32 #include "vhub.h"
38 * - We may need to indicate TT support
39 * - We may need a device qualifier descriptor
41 * - Make vid/did overridable
42 * - make it look like usb1 if usb1 mode forced
145 * These strings converted to UTF-16 must be smaller than
166 .strings = (struct usb_string *)ast_vhub_str_array
177 * Mark it as self-powered, I doubt the BMC is powered off in ast_vhub_hub_dev_status()
186 if (ep->vhub->wakeup_en) in ast_vhub_hub_dev_status()
203 if (ep->vhub->ep1_stalled) in ast_vhub_hub_ep_status()
221 ep->vhub->wakeup_en = is_set; in ast_vhub_hub_dev_feature()
228 val = readl(ep->vhub->regs + AST_VHUB_CTRL); in ast_vhub_hub_dev_feature()
231 writel(val, ep->vhub->regs + AST_VHUB_CTRL); in ast_vhub_hub_dev_feature()
260 ep->vhub->ep1_stalled = is_set; in ast_vhub_hub_ep_feature()
261 reg = readl(ep->vhub->regs + AST_VHUB_EP1_CTRL); in ast_vhub_hub_ep_feature()
268 writel(reg, ep->vhub->regs + AST_VHUB_EP1_CTRL); in ast_vhub_hub_ep_feature()
277 struct ast_vhub *vhub = ep->vhub; in ast_vhub_rep_desc() local
283 * we can do some in-place patching if needed. We know in ast_vhub_rep_desc()
293 memcpy(ep->buf, &vhub->vhub_dev_desc, dsize); in ast_vhub_rep_desc()
294 BUILD_BUG_ON(dsize > sizeof(vhub->vhub_dev_desc)); in ast_vhub_rep_desc()
300 memcpy(ep->buf, &vhub->vhub_conf_desc, dsize); in ast_vhub_rep_desc()
301 ((u8 *)ep->buf)[1] = desc_type; in ast_vhub_rep_desc()
302 BUILD_BUG_ON(dsize > sizeof(vhub->vhub_conf_desc)); in ast_vhub_rep_desc()
307 memcpy(ep->buf, &vhub->vhub_hub_desc, dsize); in ast_vhub_rep_desc()
308 BUILD_BUG_ON(dsize > sizeof(vhub->vhub_hub_desc)); in ast_vhub_rep_desc()
312 dsize = sizeof(vhub->vhub_qual_desc); in ast_vhub_rep_desc()
313 memcpy(ep->buf, &vhub->vhub_qual_desc, dsize); in ast_vhub_rep_desc()
330 return (struct usb_gadget_strings *)container->stash; in ast_vhub_str_of_container()
333 static int ast_vhub_collect_languages(struct ast_vhub *vhub, void *buf, in ast_vhub_collect_languages() argument
343 max_langs = (size - hdr_len) / sizeof(sdesc->wData[0]); in ast_vhub_collect_languages()
344 list_for_each_entry(container, &vhub->vhub_str_desc, list) { in ast_vhub_collect_languages()
349 sdesc->wData[nlangs++] = cpu_to_le16(lang_str->language); in ast_vhub_collect_languages()
352 rc = hdr_len + nlangs * sizeof(sdesc->wData[0]); in ast_vhub_collect_languages()
353 sdesc->bLength = rc; in ast_vhub_collect_languages()
354 sdesc->bDescriptorType = USB_DT_STRING; in ast_vhub_collect_languages()
359 static struct usb_gadget_strings *ast_vhub_lookup_string(struct ast_vhub *vhub, in ast_vhub_lookup_string() argument
365 list_for_each_entry(container, &vhub->vhub_str_desc, list) { in ast_vhub_lookup_string()
367 if (lang_str->language == lang_id) in ast_vhub_lookup_string()
380 struct ast_vhub *vhub = ep->vhub; in ast_vhub_rep_string() local
384 rc = ast_vhub_collect_languages(vhub, buf, sizeof(buf)); in ast_vhub_rep_string()
386 lang_str = ast_vhub_lookup_string(vhub, lang_id); in ast_vhub_rep_string()
397 memcpy(ep->buf, buf, rc); in ast_vhub_rep_string()
404 struct ast_vhub *vhub = ep->vhub; in ast_vhub_std_hub_request() local
407 wValue = le16_to_cpu(crq->wValue); in ast_vhub_std_hub_request()
408 wIndex = le16_to_cpu(crq->wIndex); in ast_vhub_std_hub_request()
409 wLength = le16_to_cpu(crq->wLength); in ast_vhub_std_hub_request()
412 if (vhub->speed == USB_SPEED_UNKNOWN) { in ast_vhub_std_hub_request()
413 u32 ustat = readl(vhub->regs + AST_VHUB_USBSTS); in ast_vhub_std_hub_request()
415 vhub->speed = USB_SPEED_HIGH; in ast_vhub_std_hub_request()
417 vhub->speed = USB_SPEED_FULL; in ast_vhub_std_hub_request()
418 UDCDBG(vhub, "USB status=%08x speed=%s\n", ustat, in ast_vhub_std_hub_request()
419 vhub->speed == USB_SPEED_HIGH ? "high" : "full"); in ast_vhub_std_hub_request()
422 switch ((crq->bRequestType << 8) | crq->bRequest) { in ast_vhub_std_hub_request()
426 writel(wValue, vhub->regs + AST_VHUB_CONF); in ast_vhub_std_hub_request()
481 static void ast_vhub_update_hub_ep1(struct ast_vhub *vhub, in ast_vhub_update_hub_ep1() argument
485 u32 reg = readl(vhub->regs + AST_VHUB_EP1_STS_CHG); in ast_vhub_update_hub_ep1()
487 if (vhub->ports[port].change) in ast_vhub_update_hub_ep1()
491 writel(reg, vhub->regs + AST_VHUB_EP1_STS_CHG); in ast_vhub_update_hub_ep1()
494 static void ast_vhub_change_port_stat(struct ast_vhub *vhub, in ast_vhub_change_port_stat() argument
500 struct ast_vhub_port *p = &vhub->ports[port]; in ast_vhub_change_port_stat()
504 prev = p->status; in ast_vhub_change_port_stat()
505 p->status = (prev & ~clr_flags) | set_flags; in ast_vhub_change_port_stat()
506 DDBG(&p->dev, "port %d status %04x -> %04x (C=%d)\n", in ast_vhub_change_port_stat()
507 port + 1, prev, p->status, set_c); in ast_vhub_change_port_stat()
511 u16 chg = p->status ^ prev; in ast_vhub_change_port_stat()
525 if (p->status & USB_PORT_STAT_ENABLE) in ast_vhub_change_port_stat()
528 p->change = chg; in ast_vhub_change_port_stat()
529 ast_vhub_update_hub_ep1(vhub, port); in ast_vhub_change_port_stat()
533 static void ast_vhub_send_host_wakeup(struct ast_vhub *vhub) in ast_vhub_send_host_wakeup() argument
535 u32 reg = readl(vhub->regs + AST_VHUB_CTRL); in ast_vhub_send_host_wakeup()
536 UDCDBG(vhub, "Waking up host !\n"); in ast_vhub_send_host_wakeup()
538 writel(reg, vhub->regs + AST_VHUB_CTRL); in ast_vhub_send_host_wakeup()
541 void ast_vhub_device_connect(struct ast_vhub *vhub, in ast_vhub_device_connect() argument
545 ast_vhub_change_port_stat(vhub, port, 0, in ast_vhub_device_connect()
548 ast_vhub_change_port_stat(vhub, port, in ast_vhub_device_connect()
557 if (vhub->wakeup_en) in ast_vhub_device_connect()
558 ast_vhub_send_host_wakeup(vhub); in ast_vhub_device_connect()
563 struct ast_vhub *vhub = container_of(work, in ast_vhub_wake_work() local
574 spin_lock_irqsave(&vhub->lock, flags); in ast_vhub_wake_work()
575 for (i = 0; i < vhub->max_ports; i++) { in ast_vhub_wake_work()
576 struct ast_vhub_port *p = &vhub->ports[i]; in ast_vhub_wake_work()
578 if (!(p->status & USB_PORT_STAT_SUSPEND)) in ast_vhub_wake_work()
580 ast_vhub_change_port_stat(vhub, i, in ast_vhub_wake_work()
583 ast_vhub_dev_resume(&p->dev); in ast_vhub_wake_work()
585 ast_vhub_send_host_wakeup(vhub); in ast_vhub_wake_work()
586 spin_unlock_irqrestore(&vhub->lock, flags); in ast_vhub_wake_work()
589 void ast_vhub_hub_wake_all(struct ast_vhub *vhub) in ast_vhub_hub_wake_all() argument
596 schedule_work(&vhub->wake_work); in ast_vhub_hub_wake_all()
599 static void ast_vhub_port_reset(struct ast_vhub *vhub, u8 port) in ast_vhub_port_reset() argument
601 struct ast_vhub_port *p = &vhub->ports[port]; in ast_vhub_port_reset()
605 ast_vhub_change_port_stat(vhub, port, in ast_vhub_port_reset()
611 if (!p->dev.driver) in ast_vhub_port_reset()
618 ast_vhub_dev_reset(&p->dev); in ast_vhub_port_reset()
621 speed = p->dev.driver->max_speed; in ast_vhub_port_reset()
622 if (speed == USB_SPEED_UNKNOWN || speed > vhub->speed) in ast_vhub_port_reset()
623 speed = vhub->speed; in ast_vhub_port_reset()
640 UDCDBG(vhub, "Unsupported speed %d when" in ast_vhub_port_reset()
649 ast_vhub_change_port_stat(vhub, port, clr, set, true); in ast_vhub_port_reset()
655 struct ast_vhub *vhub = ep->vhub; in ast_vhub_set_port_feature() local
658 if (port == 0 || port > vhub->max_ports) in ast_vhub_set_port_feature()
660 port--; in ast_vhub_set_port_feature()
661 p = &vhub->ports[port]; in ast_vhub_set_port_feature()
665 if (!(p->status & USB_PORT_STAT_ENABLE)) in ast_vhub_set_port_feature()
667 ast_vhub_change_port_stat(vhub, port, in ast_vhub_set_port_feature()
670 ast_vhub_dev_suspend(&p->dev); in ast_vhub_set_port_feature()
674 ast_vhub_port_reset(vhub, port); in ast_vhub_set_port_feature()
678 * On Power-on, we mark the connected flag changed, in ast_vhub_set_port_feature()
682 if (p->status & USB_PORT_STAT_CONNECTION) { in ast_vhub_set_port_feature()
683 p->change |= USB_PORT_STAT_C_CONNECTION; in ast_vhub_set_port_feature()
684 ast_vhub_update_hub_ep1(vhub, port); in ast_vhub_set_port_feature()
698 struct ast_vhub *vhub = ep->vhub; in ast_vhub_clr_port_feature() local
701 if (port == 0 || port > vhub->max_ports) in ast_vhub_clr_port_feature()
703 port--; in ast_vhub_clr_port_feature()
704 p = &vhub->ports[port]; in ast_vhub_clr_port_feature()
708 ast_vhub_change_port_stat(vhub, port, in ast_vhub_clr_port_feature()
712 ast_vhub_dev_suspend(&p->dev); in ast_vhub_clr_port_feature()
715 if (!(p->status & USB_PORT_STAT_SUSPEND)) in ast_vhub_clr_port_feature()
717 ast_vhub_change_port_stat(vhub, port, in ast_vhub_clr_port_feature()
720 ast_vhub_dev_resume(&p->dev); in ast_vhub_clr_port_feature()
733 /* Clear state-change feature */ in ast_vhub_clr_port_feature()
734 p->change &= ~(1u << (feat - 16)); in ast_vhub_clr_port_feature()
735 ast_vhub_update_hub_ep1(vhub, port); in ast_vhub_clr_port_feature()
744 struct ast_vhub *vhub = ep->vhub; in ast_vhub_get_port_stat() local
747 if (port == 0 || port > vhub->max_ports) in ast_vhub_get_port_stat()
749 port--; in ast_vhub_get_port_stat()
751 stat = vhub->ports[port].status; in ast_vhub_get_port_stat()
752 chg = vhub->ports[port].change; in ast_vhub_get_port_stat()
771 wValue = le16_to_cpu(crq->wValue); in ast_vhub_class_hub_request()
772 wIndex = le16_to_cpu(crq->wIndex); in ast_vhub_class_hub_request()
773 wLength = le16_to_cpu(crq->wLength); in ast_vhub_class_hub_request()
775 switch ((crq->bRequestType << 8) | crq->bRequest) { in ast_vhub_class_hub_request()
813 void ast_vhub_hub_suspend(struct ast_vhub *vhub) in ast_vhub_hub_suspend() argument
817 UDCDBG(vhub, "USB bus suspend\n"); in ast_vhub_hub_suspend()
819 if (vhub->suspended) in ast_vhub_hub_suspend()
822 vhub->suspended = true; in ast_vhub_hub_suspend()
828 for (i = 0; i < vhub->max_ports; i++) { in ast_vhub_hub_suspend()
829 struct ast_vhub_port *p = &vhub->ports[i]; in ast_vhub_hub_suspend()
831 if (!(p->status & USB_PORT_STAT_SUSPEND)) in ast_vhub_hub_suspend()
832 ast_vhub_dev_suspend(&p->dev); in ast_vhub_hub_suspend()
836 void ast_vhub_hub_resume(struct ast_vhub *vhub) in ast_vhub_hub_resume() argument
840 UDCDBG(vhub, "USB bus resume\n"); in ast_vhub_hub_resume()
842 if (!vhub->suspended) in ast_vhub_hub_resume()
845 vhub->suspended = false; in ast_vhub_hub_resume()
851 for (i = 0; i < vhub->max_ports; i++) { in ast_vhub_hub_resume()
852 struct ast_vhub_port *p = &vhub->ports[i]; in ast_vhub_hub_resume()
854 if (!(p->status & USB_PORT_STAT_SUSPEND)) in ast_vhub_hub_resume()
855 ast_vhub_dev_resume(&p->dev); in ast_vhub_hub_resume()
859 void ast_vhub_hub_reset(struct ast_vhub *vhub) in ast_vhub_hub_reset() argument
863 UDCDBG(vhub, "USB bus reset\n"); in ast_vhub_hub_reset()
869 if (vhub->speed == USB_SPEED_UNKNOWN) in ast_vhub_hub_reset()
873 vhub->suspended = false; in ast_vhub_hub_reset()
876 vhub->speed = USB_SPEED_UNKNOWN; in ast_vhub_hub_reset()
879 vhub->wakeup_en = false; in ast_vhub_hub_reset()
885 for (i = 0; i < vhub->max_ports; i++) { in ast_vhub_hub_reset()
886 struct ast_vhub_port *p = &vhub->ports[i]; in ast_vhub_hub_reset()
889 p->status &= USB_PORT_STAT_CONNECTION; in ast_vhub_hub_reset()
890 p->change = 0; in ast_vhub_hub_reset()
893 ast_vhub_dev_suspend(&p->dev); in ast_vhub_hub_reset()
897 writel(0, vhub->regs + AST_VHUB_CONF); in ast_vhub_hub_reset()
898 writel(0, vhub->regs + AST_VHUB_EP0_CTRL); in ast_vhub_hub_reset()
901 vhub->regs + AST_VHUB_EP1_CTRL); in ast_vhub_hub_reset()
902 writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG); in ast_vhub_hub_reset()
905 static void ast_vhub_of_parse_dev_desc(struct ast_vhub *vhub, in ast_vhub_of_parse_dev_desc() argument
911 if (!of_property_read_u32(vhub_np, "vhub-vendor-id", &data)) { in ast_vhub_of_parse_dev_desc()
913 vhub->vhub_dev_desc.idVendor = cpu_to_le16(id); in ast_vhub_of_parse_dev_desc()
915 if (!of_property_read_u32(vhub_np, "vhub-product-id", &data)) { in ast_vhub_of_parse_dev_desc()
917 vhub->vhub_dev_desc.idProduct = cpu_to_le16(id); in ast_vhub_of_parse_dev_desc()
919 if (!of_property_read_u32(vhub_np, "vhub-device-revision", &data)) { in ast_vhub_of_parse_dev_desc()
921 vhub->vhub_dev_desc.bcdDevice = cpu_to_le16(id); in ast_vhub_of_parse_dev_desc()
925 static void ast_vhub_fixup_usb1_dev_desc(struct ast_vhub *vhub) in ast_vhub_fixup_usb1_dev_desc() argument
927 vhub->vhub_dev_desc.bcdUSB = cpu_to_le16(0x0100); in ast_vhub_fixup_usb1_dev_desc()
928 vhub->vhub_dev_desc.bDeviceProtocol = 0; in ast_vhub_fixup_usb1_dev_desc()
932 ast_vhub_str_container_alloc(struct ast_vhub *vhub) in ast_vhub_str_container_alloc() argument
942 container = devm_kzalloc(&vhub->pdev->dev, size, GFP_KERNEL); in ast_vhub_str_container_alloc()
944 return ERR_PTR(-ENOMEM); in ast_vhub_str_container_alloc()
948 lang_str->strings = str_array; in ast_vhub_str_container_alloc()
955 struct usb_string *src_array = src->strings; in ast_vhub_str_deep_copy()
956 struct usb_string *dest_array = dest->strings; in ast_vhub_str_deep_copy()
958 dest->language = src->language; in ast_vhub_str_deep_copy()
964 } while (src_array->s); in ast_vhub_str_deep_copy()
968 static int ast_vhub_str_alloc_add(struct ast_vhub *vhub, in ast_vhub_str_alloc_add() argument
974 container = ast_vhub_str_container_alloc(vhub); in ast_vhub_str_alloc_add()
980 list_add_tail(&container->list, &vhub->vhub_str_desc); in ast_vhub_str_alloc_add()
991 {"serial-number", AST_VHUB_STR_SERIAL},
995 static int ast_vhub_of_parse_str_desc(struct ast_vhub *vhub, in ast_vhub_of_parse_str_desc() argument
1005 .strings = (struct usb_string *)str_array, in ast_vhub_of_parse_str_desc()
1027 ret = ast_vhub_str_alloc_add(vhub, &lang_str); in ast_vhub_of_parse_str_desc()
1037 static int ast_vhub_init_desc(struct ast_vhub *vhub) in ast_vhub_init_desc() argument
1041 const struct device_node *vhub_np = vhub->pdev->dev.of_node; in ast_vhub_init_desc()
1043 /* Initialize vhub Device Descriptor. */ in ast_vhub_init_desc()
1044 memcpy(&vhub->vhub_dev_desc, &ast_vhub_dev_desc, in ast_vhub_init_desc()
1045 sizeof(vhub->vhub_dev_desc)); in ast_vhub_init_desc()
1046 ast_vhub_of_parse_dev_desc(vhub, vhub_np); in ast_vhub_init_desc()
1047 if (vhub->force_usb1) in ast_vhub_init_desc()
1048 ast_vhub_fixup_usb1_dev_desc(vhub); in ast_vhub_init_desc()
1050 /* Initialize vhub Configuration Descriptor. */ in ast_vhub_init_desc()
1051 memcpy(&vhub->vhub_conf_desc, &ast_vhub_conf_desc, in ast_vhub_init_desc()
1052 sizeof(vhub->vhub_conf_desc)); in ast_vhub_init_desc()
1054 /* Initialize vhub Hub Descriptor. */ in ast_vhub_init_desc()
1055 memcpy(&vhub->vhub_hub_desc, &ast_vhub_hub_desc, in ast_vhub_init_desc()
1056 sizeof(vhub->vhub_hub_desc)); in ast_vhub_init_desc()
1057 vhub->vhub_hub_desc.bNbrPorts = vhub->max_ports; in ast_vhub_init_desc()
1059 /* Initialize vhub String Descriptors. */ in ast_vhub_init_desc()
1060 INIT_LIST_HEAD(&vhub->vhub_str_desc); in ast_vhub_init_desc()
1061 desc_np = of_get_child_by_name(vhub_np, "vhub-strings"); in ast_vhub_init_desc()
1063 ret = ast_vhub_of_parse_str_desc(vhub, desc_np); in ast_vhub_init_desc()
1067 ret = ast_vhub_str_alloc_add(vhub, &ast_vhub_strings); in ast_vhub_init_desc()
1069 /* Initialize vhub Qualifier Descriptor. */ in ast_vhub_init_desc()
1070 memcpy(&vhub->vhub_qual_desc, &ast_vhub_qual_desc, in ast_vhub_init_desc()
1071 sizeof(vhub->vhub_qual_desc)); in ast_vhub_init_desc()
1076 int ast_vhub_init_hub(struct ast_vhub *vhub) in ast_vhub_init_hub() argument
1078 vhub->speed = USB_SPEED_UNKNOWN; in ast_vhub_init_hub()
1079 INIT_WORK(&vhub->wake_work, ast_vhub_wake_work); in ast_vhub_init_hub()
1081 return ast_vhub_init_desc(vhub); in ast_vhub_init_hub()