0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/acpi.h>
0015 #include <linux/delay.h>
0016 #include <linux/err.h>
0017 #include <linux/io.h>
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/pm_runtime.h>
0022 #include <linux/property.h>
0023 #include <linux/usb/role.h>
0024
0025
0026 #define DUAL_ROLE_CFG0 0x68
0027 #define SW_VBUS_VALID BIT(24)
0028 #define SW_IDPIN_EN BIT(21)
0029 #define SW_IDPIN BIT(20)
0030 #define SW_SWITCH_EN BIT(16)
0031
0032 #define DRD_CONFIG_DYNAMIC 0
0033 #define DRD_CONFIG_STATIC_HOST 1
0034 #define DRD_CONFIG_STATIC_DEVICE 2
0035 #define DRD_CONFIG_MASK 3
0036
0037 #define DUAL_ROLE_CFG1 0x6c
0038 #define HOST_MODE BIT(29)
0039
0040 #define DUAL_ROLE_CFG1_POLL_TIMEOUT 1000
0041
0042 #define DRV_NAME "intel_xhci_usb_sw"
0043
0044 struct intel_xhci_usb_data {
0045 struct device *dev;
0046 struct usb_role_switch *role_sw;
0047 void __iomem *base;
0048 bool enable_sw_switch;
0049 };
0050
0051 static const struct software_node intel_xhci_usb_node = {
0052 "intel-xhci-usb-sw",
0053 };
0054
0055 static int intel_xhci_usb_set_role(struct usb_role_switch *sw,
0056 enum usb_role role)
0057 {
0058 struct intel_xhci_usb_data *data = usb_role_switch_get_drvdata(sw);
0059 unsigned long timeout;
0060 acpi_status status;
0061 u32 glk, val;
0062 u32 drd_config = DRD_CONFIG_DYNAMIC;
0063
0064
0065
0066
0067
0068
0069 status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);
0070 if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
0071 dev_err(data->dev, "Error could not acquire lock\n");
0072 return -EIO;
0073 }
0074
0075 pm_runtime_get_sync(data->dev);
0076
0077
0078
0079
0080
0081
0082
0083 val = readl(data->base + DUAL_ROLE_CFG0);
0084 switch (role) {
0085 case USB_ROLE_NONE:
0086 val |= SW_IDPIN;
0087 val &= ~SW_VBUS_VALID;
0088 drd_config = DRD_CONFIG_DYNAMIC;
0089 break;
0090 case USB_ROLE_HOST:
0091 val &= ~SW_IDPIN;
0092 val &= ~SW_VBUS_VALID;
0093 drd_config = DRD_CONFIG_STATIC_HOST;
0094 break;
0095 case USB_ROLE_DEVICE:
0096 val |= SW_IDPIN;
0097 val |= SW_VBUS_VALID;
0098 drd_config = DRD_CONFIG_STATIC_DEVICE;
0099 break;
0100 }
0101 val |= SW_IDPIN_EN;
0102 if (data->enable_sw_switch) {
0103 val &= ~DRD_CONFIG_MASK;
0104 val |= SW_SWITCH_EN | drd_config;
0105 }
0106 writel(val, data->base + DUAL_ROLE_CFG0);
0107
0108 acpi_release_global_lock(glk);
0109
0110
0111 timeout = jiffies + msecs_to_jiffies(DUAL_ROLE_CFG1_POLL_TIMEOUT);
0112
0113
0114 do {
0115 val = readl(data->base + DUAL_ROLE_CFG1);
0116 if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) {
0117 pm_runtime_put(data->dev);
0118 return 0;
0119 }
0120
0121
0122 usleep_range(5000, 10000);
0123 } while (time_before(jiffies, timeout));
0124
0125 pm_runtime_put(data->dev);
0126
0127 dev_warn(data->dev, "Timeout waiting for role-switch\n");
0128 return -ETIMEDOUT;
0129 }
0130
0131 static enum usb_role intel_xhci_usb_get_role(struct usb_role_switch *sw)
0132 {
0133 struct intel_xhci_usb_data *data = usb_role_switch_get_drvdata(sw);
0134 enum usb_role role;
0135 u32 val;
0136
0137 pm_runtime_get_sync(data->dev);
0138 val = readl(data->base + DUAL_ROLE_CFG0);
0139 pm_runtime_put(data->dev);
0140
0141 if (!(val & SW_IDPIN))
0142 role = USB_ROLE_HOST;
0143 else if (val & SW_VBUS_VALID)
0144 role = USB_ROLE_DEVICE;
0145 else
0146 role = USB_ROLE_NONE;
0147
0148 return role;
0149 }
0150
0151 static int intel_xhci_usb_probe(struct platform_device *pdev)
0152 {
0153 struct usb_role_switch_desc sw_desc = { };
0154 struct device *dev = &pdev->dev;
0155 struct intel_xhci_usb_data *data;
0156 struct resource *res;
0157 int ret;
0158
0159 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0160 if (!data)
0161 return -ENOMEM;
0162
0163 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0164 if (!res)
0165 return -EINVAL;
0166 data->base = devm_ioremap(dev, res->start, resource_size(res));
0167 if (!data->base)
0168 return -ENOMEM;
0169
0170 platform_set_drvdata(pdev, data);
0171
0172 ret = software_node_register(&intel_xhci_usb_node);
0173 if (ret)
0174 return ret;
0175
0176 sw_desc.set = intel_xhci_usb_set_role,
0177 sw_desc.get = intel_xhci_usb_get_role,
0178 sw_desc.allow_userspace_control = true,
0179 sw_desc.fwnode = software_node_fwnode(&intel_xhci_usb_node);
0180 sw_desc.driver_data = data;
0181
0182 data->dev = dev;
0183 data->enable_sw_switch = !device_property_read_bool(dev,
0184 "sw_switch_disable");
0185
0186 data->role_sw = usb_role_switch_register(dev, &sw_desc);
0187 if (IS_ERR(data->role_sw)) {
0188 fwnode_handle_put(sw_desc.fwnode);
0189 return PTR_ERR(data->role_sw);
0190 }
0191
0192 pm_runtime_set_active(dev);
0193 pm_runtime_enable(dev);
0194
0195 return 0;
0196 }
0197
0198 static int intel_xhci_usb_remove(struct platform_device *pdev)
0199 {
0200 struct intel_xhci_usb_data *data = platform_get_drvdata(pdev);
0201
0202 pm_runtime_disable(&pdev->dev);
0203
0204 usb_role_switch_unregister(data->role_sw);
0205 fwnode_handle_put(software_node_fwnode(&intel_xhci_usb_node));
0206
0207 return 0;
0208 }
0209
0210 static const struct platform_device_id intel_xhci_usb_table[] = {
0211 { .name = DRV_NAME },
0212 {}
0213 };
0214 MODULE_DEVICE_TABLE(platform, intel_xhci_usb_table);
0215
0216 static struct platform_driver intel_xhci_usb_driver = {
0217 .driver = {
0218 .name = DRV_NAME,
0219 },
0220 .id_table = intel_xhci_usb_table,
0221 .probe = intel_xhci_usb_probe,
0222 .remove = intel_xhci_usb_remove,
0223 };
0224
0225 module_platform_driver(intel_xhci_usb_driver);
0226
0227 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0228 MODULE_DESCRIPTION("Intel XHCI USB role switch driver");
0229 MODULE_LICENSE("GPL");