From: Senchuan Zhang <zhangsenchuan@xxxxxxxxxxxxxxxxxx>
Add the eic7700 usb driver, which is responsible for
identifying,configuring and connecting usb devices,and
provides interfaces for accessing these devices.
Co-developed-by: Wei Yang <yangwei1@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Wei Yang <yangwei1@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Senchuan Zhang <zhangsenchuan@xxxxxxxxxxxxxxxxxx>
---
+static ssize_t dwc3_mode_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+ struct dwc3 *dwc = eswin->dwc;
+ int ret;
+
+ switch (dwc->current_dr_role) {
+ case USB_DR_MODE_HOST:
+ ret = sprintf(buf, "host\n");
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ ret = sprintf(buf, "peripheral\n");
+ break;
+ case USB_DR_MODE_OTG:
+ ret = sprintf(buf, "otg\n");
+ break;
+ default:
+ ret = sprintf(buf, "UNKNOWN\n");
+ }
+
+ return ret;
+}
+
+static ssize_t dwc3_mode_store(struct device *device,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+ struct dwc3 *dwc = eswin->dwc;
+ enum usb_role new_role;
+ struct usb_role_switch *role_sw = dwc->role_sw;
+
+ if (!strncmp(buf, "1", 1) || !strncmp(buf, "host", 4)) {
+ new_role = USB_ROLE_HOST;
+ } else if (!strncmp(buf, "0", 1) || !strncmp(buf, "peripheral", 10)) {
+ new_role = USB_ROLE_DEVICE;
+ } else {
+ dev_info(eswin->dev, "illegal dr_mode\n");
+ return count;
+ }
+ eswin->force_mode = true;
+
+ mutex_lock(&eswin->lock);
+ usb_role_switch_set_role(role_sw, new_role);
+ mutex_unlock(&eswin->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(dwc3_mode);
+
+static ssize_t dwc3_hub_rst_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+
+ if (!IS_ERR(eswin->hub_gpio))
+ return sprintf(buf, "%d", gpiod_get_raw_value(eswin->hub_gpio));
+
+ return sprintf(buf, "UNKONWN");
+}
+
+static ssize_t dwc3_hub_rst_store(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+
+ if (!IS_ERR(eswin->hub_gpio)) {
+ if (!strncmp(buf, "0", 1))
+ gpiod_set_raw_value(eswin->hub_gpio, 0);
+ else
+ gpiod_set_raw_value(eswin->hub_gpio, 1);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(dwc3_hub_rst);
+
+static struct attribute *dwc3_eswin_attrs[] = {
+ &dev_attr_dwc3_mode.attr,
+ &dev_attr_dwc3_hub_rst.attr,
+ NULL,
+};
+
+static struct attribute_group dwc3_eswin_attr_group = {
+ .name = NULL, /* we want them in the same directory */
+ .attrs = dwc3_eswin_attrs,
+};
+
+static int dwc3_eswin_probe(struct platform_device *pdev)
+{
+ struct dwc3_eswin *eswin;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node, *child;
+ struct platform_device *child_pdev;
+ unsigned int count;
+ int ret;
+ int i;
+ int err_desc = 0;
+
+ child = of_get_child_by_name(np, "dwc3");
+ if (!child) {
+ dev_err(dev, "failed to find dwc3 core node\n");
+ ret = -ENODEV;
+ goto err1;
+ }
+ /* Allocate and initialize the core */
+ ret = of_platform_populate(np, NULL, NULL, dev);
+ if (ret) {
+ dev_err(dev, "failed to create dwc3 core\n");
+ goto err1;
+ }
+
+ INIT_WORK(&eswin->otg_work, dwc3_eswin_otg_extcon_evt_work);
+ child_pdev = of_find_device_by_node(child);
+ if (!child_pdev) {
+ dev_err(dev, "failed to find dwc3 core device\n");
+ ret = -ENODEV;
+ goto err2;
+ }
+ eswin->dwc = platform_get_drvdata(child_pdev);
+ if (!eswin->dwc) {
+ dev_err(dev, "failed to get drvdata dwc3\n");
+ ret = -EPROBE_DEFER;
+ goto err2;
+ }