1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Intel XHCI (Cherry Trail, Broxton and others) USB OTG role switch driver 4 * 5 * Copyright (c) 2016-2017 Hans de Goede <hdegoede@redhat.com> 6 * 7 * Loosely based on android x86 kernel code which is: 8 * 9 * Copyright (C) 2014 Intel Corp. 10 * 11 * Author: Wu, Hao 12 */ 13 14 #include <linux/acpi.h> 15 #include <linux/delay.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/usb/role.h> 22 23 /* register definition */ 24 #define DUAL_ROLE_CFG0 0x68 25 #define SW_VBUS_VALID BIT(24) 26 #define SW_IDPIN_EN BIT(21) 27 #define SW_IDPIN BIT(20) 28 29 #define DUAL_ROLE_CFG1 0x6c 30 #define HOST_MODE BIT(29) 31 32 #define DUAL_ROLE_CFG1_POLL_TIMEOUT 1000 33 34 #define DRV_NAME "intel_xhci_usb_sw" 35 36 struct intel_xhci_usb_data { 37 struct usb_role_switch *role_sw; 38 void __iomem *base; 39 }; 40 41 struct intel_xhci_acpi_match { 42 const char *hid; 43 int hrv; 44 }; 45 46 /* 47 * ACPI IDs for PMICs which do not support separate data and power role 48 * detection (USB ACA detection for micro USB OTG), we allow userspace to 49 * change the role manually on these. 50 */ 51 static const struct intel_xhci_acpi_match allow_userspace_ctrl_ids[] = { 52 { "INT33F4", 3 }, /* X-Powers AXP288 PMIC */ 53 }; 54 55 static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) 56 { 57 struct intel_xhci_usb_data *data = dev_get_drvdata(dev); 58 unsigned long timeout; 59 acpi_status status; 60 u32 glk, val; 61 62 /* 63 * On many CHT devices ACPI event (_AEI) handlers read / modify / 64 * write the cfg0 register, just like we do. Take the ACPI lock 65 * to avoid us racing with the AML code. 66 */ 67 status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk); 68 if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) { 69 dev_err(dev, "Error could not acquire lock\n"); 70 return -EIO; 71 } 72 73 /* Set idpin value as requested */ 74 val = readl(data->base + DUAL_ROLE_CFG0); 75 switch (role) { 76 case USB_ROLE_NONE: 77 val |= SW_IDPIN; 78 val &= ~SW_VBUS_VALID; 79 break; 80 case USB_ROLE_HOST: 81 val &= ~SW_IDPIN; 82 val &= ~SW_VBUS_VALID; 83 break; 84 case USB_ROLE_DEVICE: 85 val |= SW_IDPIN; 86 val |= SW_VBUS_VALID; 87 break; 88 } 89 val |= SW_IDPIN_EN; 90 91 writel(val, data->base + DUAL_ROLE_CFG0); 92 93 acpi_release_global_lock(glk); 94 95 /* In most case it takes about 600ms to finish mode switching */ 96 timeout = jiffies + msecs_to_jiffies(DUAL_ROLE_CFG1_POLL_TIMEOUT); 97 98 /* Polling on CFG1 register to confirm mode switch.*/ 99 do { 100 val = readl(data->base + DUAL_ROLE_CFG1); 101 if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) 102 return 0; 103 104 /* Interval for polling is set to about 5 - 10 ms */ 105 usleep_range(5000, 10000); 106 } while (time_before(jiffies, timeout)); 107 108 dev_warn(dev, "Timeout waiting for role-switch\n"); 109 return -ETIMEDOUT; 110 } 111 112 static enum usb_role intel_xhci_usb_get_role(struct device *dev) 113 { 114 struct intel_xhci_usb_data *data = dev_get_drvdata(dev); 115 enum usb_role role; 116 u32 val; 117 118 val = readl(data->base + DUAL_ROLE_CFG0); 119 120 if (!(val & SW_IDPIN)) 121 role = USB_ROLE_HOST; 122 else if (val & SW_VBUS_VALID) 123 role = USB_ROLE_DEVICE; 124 else 125 role = USB_ROLE_NONE; 126 127 return role; 128 } 129 130 static struct usb_role_switch_desc sw_desc = { 131 .set = intel_xhci_usb_set_role, 132 .get = intel_xhci_usb_get_role, 133 }; 134 135 static int intel_xhci_usb_probe(struct platform_device *pdev) 136 { 137 struct device *dev = &pdev->dev; 138 struct intel_xhci_usb_data *data; 139 struct resource *res; 140 int i; 141 142 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 143 if (!data) 144 return -ENOMEM; 145 146 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 147 data->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); 148 if (!data->base) 149 return -ENOMEM; 150 151 for (i = 0; i < ARRAY_SIZE(allow_userspace_ctrl_ids); i++) 152 if (acpi_dev_present(allow_userspace_ctrl_ids[i].hid, "1", 153 allow_userspace_ctrl_ids[i].hrv)) 154 sw_desc.allow_userspace_control = true; 155 156 platform_set_drvdata(pdev, data); 157 158 data->role_sw = usb_role_switch_register(dev, &sw_desc); 159 if (IS_ERR(data->role_sw)) 160 return PTR_ERR(data->role_sw); 161 162 return 0; 163 } 164 165 static int intel_xhci_usb_remove(struct platform_device *pdev) 166 { 167 struct intel_xhci_usb_data *data = platform_get_drvdata(pdev); 168 169 usb_role_switch_unregister(data->role_sw); 170 return 0; 171 } 172 173 static const struct platform_device_id intel_xhci_usb_table[] = { 174 { .name = DRV_NAME }, 175 {} 176 }; 177 MODULE_DEVICE_TABLE(platform, intel_xhci_usb_table); 178 179 static struct platform_driver intel_xhci_usb_driver = { 180 .driver = { 181 .name = DRV_NAME, 182 }, 183 .id_table = intel_xhci_usb_table, 184 .probe = intel_xhci_usb_probe, 185 .remove = intel_xhci_usb_remove, 186 }; 187 188 module_platform_driver(intel_xhci_usb_driver); 189 190 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 191 MODULE_DESCRIPTION("Intel XHCI USB role switch driver"); 192 MODULE_LICENSE("GPL"); 193