1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Driver for onboard USB hubs 4 * 5 * Copyright (c) 2022, Google LLC 6 */ 7 8#include <linux/clk.h> 9#include <linux/device.h> 10#include <linux/export.h> 11#include <linux/err.h> 12#include <linux/gpio/consumer.h> 13#include <linux/init.h> 14#include <linux/kernel.h> 15#include <linux/list.h> 16#include <linux/module.h> 17#include <linux/mutex.h> 18#include <linux/of.h> 19#include <linux/of_platform.h> 20#include <linux/platform_device.h> 21#include <linux/regulator/consumer.h> 22#include <linux/slab.h> 23#include <linux/suspend.h> 24#include <linux/sysfs.h> 25#include <linux/usb.h> 26#include <linux/usb/hcd.h> 27#include <linux/usb/onboard_hub.h> 28#include <linux/workqueue.h> 29 30#include "onboard_usb_hub.h" 31 32/* 33 * Use generic names, as the actual names might differ between hubs. If a new 34 * hub requires more than the currently supported supplies, add a new one here. 35 */ 36static const char * const supply_names[] = { 37 "vdd", 38 "vdd2", 39}; 40 41#define MAX_SUPPLIES ARRAY_SIZE(supply_names) 42 43static void onboard_hub_attach_usb_driver(struct work_struct *work); 44 45static struct usb_device_driver onboard_hub_usbdev_driver; 46static DECLARE_WORK(attach_usb_driver_work, onboard_hub_attach_usb_driver); 47 48/************************** Platform driver **************************/ 49 50struct usbdev_node { 51 struct usb_device *udev; 52 struct list_head list; 53}; 54 55struct onboard_hub { 56 struct regulator_bulk_data supplies[MAX_SUPPLIES]; 57 struct device *dev; 58 const struct onboard_hub_pdata *pdata; 59 struct gpio_desc *reset_gpio; 60 bool always_powered_in_suspend; 61 bool is_powered_on; 62 bool going_away; 63 struct list_head udev_list; 64 struct mutex lock; 65 struct clk *clk; 66}; 67 68static int onboard_hub_power_on(struct onboard_hub *hub) 69{ 70 int err; 71 72 err = clk_prepare_enable(hub->clk); 73 if (err) { 74 dev_err(hub->dev, "failed to enable clock: %pe\n", ERR_PTR(err)); 75 return err; 76 } 77 78 err = regulator_bulk_enable(hub->pdata->num_supplies, hub->supplies); 79 if (err) { 80 dev_err(hub->dev, "failed to enable supplies: %pe\n", ERR_PTR(err)); 81 goto disable_clk; 82 } 83 84 fsleep(hub->pdata->reset_us); 85 gpiod_set_value_cansleep(hub->reset_gpio, 0); 86 87 hub->is_powered_on = true; 88 89 return 0; 90 91disable_clk: 92 clk_disable_unprepare(hub->clk); 93 return err; 94} 95 96static int onboard_hub_power_off(struct onboard_hub *hub) 97{ 98 int err; 99 100 gpiod_set_value_cansleep(hub->reset_gpio, 1); 101 102 err = regulator_bulk_disable(hub->pdata->num_supplies, hub->supplies); 103 if (err) { 104 dev_err(hub->dev, "failed to disable supplies: %pe\n", ERR_PTR(err)); 105 return err; 106 } 107 108 clk_disable_unprepare(hub->clk); 109 110 hub->is_powered_on = false; 111 112 return 0; 113} 114 115static int __maybe_unused onboard_hub_suspend(struct device *dev) 116{ 117 struct onboard_hub *hub = dev_get_drvdata(dev); 118 struct usbdev_node *node; 119 bool power_off = true; 120 121 if (hub->always_powered_in_suspend) 122 return 0; 123 124 mutex_lock(&hub->lock); 125 126 list_for_each_entry(node, &hub->udev_list, list) { 127 if (!device_may_wakeup(node->udev->bus->controller)) 128 continue; 129 130 if (usb_wakeup_enabled_descendants(node->udev)) { 131 power_off = false; 132 break; 133 } 134 } 135 136 mutex_unlock(&hub->lock); 137 138 if (!power_off) 139 return 0; 140 141 return onboard_hub_power_off(hub); 142} 143 144static int __maybe_unused onboard_hub_resume(struct device *dev) 145{ 146 struct onboard_hub *hub = dev_get_drvdata(dev); 147 148 if (hub->is_powered_on) 149 return 0; 150 151 return onboard_hub_power_on(hub); 152} 153 154static inline void get_udev_link_name(const struct usb_device *udev, char *buf, size_t size) 155{ 156 snprintf(buf, size, "usb_dev.%s", dev_name(&udev->dev)); 157} 158 159static int onboard_hub_add_usbdev(struct onboard_hub *hub, struct usb_device *udev) 160{ 161 struct usbdev_node *node; 162 char link_name[64]; 163 int err; 164 165 mutex_lock(&hub->lock); 166 167 if (hub->going_away) { 168 err = -EINVAL; 169 goto error; 170 } 171 172 node = kzalloc(sizeof(*node), GFP_KERNEL); 173 if (!node) { 174 err = -ENOMEM; 175 goto error; 176 } 177 178 node->udev = udev; 179 180 list_add(&node->list, &hub->udev_list); 181 182 mutex_unlock(&hub->lock); 183 184 get_udev_link_name(udev, link_name, sizeof(link_name)); 185 WARN_ON(sysfs_create_link(&hub->dev->kobj, &udev->dev.kobj, link_name)); 186 187 return 0; 188 189error: 190 mutex_unlock(&hub->lock); 191 192 return err; 193} 194 195static void onboard_hub_remove_usbdev(struct onboard_hub *hub, const struct usb_device *udev) 196{ 197 struct usbdev_node *node; 198 char link_name[64]; 199 200 get_udev_link_name(udev, link_name, sizeof(link_name)); 201 sysfs_remove_link(&hub->dev->kobj, link_name); 202 203 mutex_lock(&hub->lock); 204 205 list_for_each_entry(node, &hub->udev_list, list) { 206 if (node->udev == udev) { 207 list_del(&node->list); 208 kfree(node); 209 break; 210 } 211 } 212 213 mutex_unlock(&hub->lock); 214} 215 216static ssize_t always_powered_in_suspend_show(struct device *dev, struct device_attribute *attr, 217 char *buf) 218{ 219 const struct onboard_hub *hub = dev_get_drvdata(dev); 220 221 return sysfs_emit(buf, "%d\n", hub->always_powered_in_suspend); 222} 223 224static ssize_t always_powered_in_suspend_store(struct device *dev, struct device_attribute *attr, 225 const char *buf, size_t count) 226{ 227 struct onboard_hub *hub = dev_get_drvdata(dev); 228 bool val; 229 int ret; 230 231 ret = kstrtobool(buf, &val); 232 if (ret < 0) 233 return ret; 234 235 hub->always_powered_in_suspend = val; 236 237 return count; 238} 239static DEVICE_ATTR_RW(always_powered_in_suspend); 240 241static struct attribute *onboard_hub_attrs[] = { 242 &dev_attr_always_powered_in_suspend.attr, 243 NULL, 244}; 245ATTRIBUTE_GROUPS(onboard_hub); 246 247static void onboard_hub_attach_usb_driver(struct work_struct *work) 248{ 249 int err; 250 251 err = driver_attach(&onboard_hub_usbdev_driver.driver); 252 if (err) 253 pr_err("Failed to attach USB driver: %pe\n", ERR_PTR(err)); 254} 255 256static int onboard_hub_probe(struct platform_device *pdev) 257{ 258 struct device *dev = &pdev->dev; 259 struct onboard_hub *hub; 260 unsigned int i; 261 int err; 262 263 hub = devm_kzalloc(dev, sizeof(*hub), GFP_KERNEL); 264 if (!hub) 265 return -ENOMEM; 266 267 hub->pdata = device_get_match_data(dev); 268 if (!hub->pdata) 269 return -EINVAL; 270 271 if (hub->pdata->num_supplies > MAX_SUPPLIES) 272 return dev_err_probe(dev, -EINVAL, "max %zu supplies supported!\n", 273 MAX_SUPPLIES); 274 275 for (i = 0; i < hub->pdata->num_supplies; i++) 276 hub->supplies[i].supply = supply_names[i]; 277 278 err = devm_regulator_bulk_get(dev, hub->pdata->num_supplies, hub->supplies); 279 if (err) { 280 dev_err(dev, "Failed to get regulator supplies: %pe\n", ERR_PTR(err)); 281 return err; 282 } 283 284 hub->clk = devm_clk_get_optional(dev, NULL); 285 if (IS_ERR(hub->clk)) 286 return dev_err_probe(dev, PTR_ERR(hub->clk), "failed to get clock\n"); 287 288 hub->reset_gpio = devm_gpiod_get_optional(dev, "reset", 289 GPIOD_OUT_HIGH); 290 if (IS_ERR(hub->reset_gpio)) 291 return dev_err_probe(dev, PTR_ERR(hub->reset_gpio), "failed to get reset GPIO\n"); 292 293 hub->dev = dev; 294 mutex_init(&hub->lock); 295 INIT_LIST_HEAD(&hub->udev_list); 296 297 dev_set_drvdata(dev, hub); 298 299 err = onboard_hub_power_on(hub); 300 if (err) 301 return err; 302 303 /* 304 * The USB driver might have been detached from the USB devices by 305 * onboard_hub_remove() (e.g. through an 'unbind' by userspace), 306 * make sure to re-attach it if needed. 307 * 308 * This needs to be done deferred to avoid self-deadlocks on systems 309 * with nested onboard hubs. 310 */ 311 schedule_work(&attach_usb_driver_work); 312 313 return 0; 314} 315 316static void onboard_hub_remove(struct platform_device *pdev) 317{ 318 struct onboard_hub *hub = dev_get_drvdata(&pdev->dev); 319 struct usbdev_node *node; 320 struct usb_device *udev; 321 322 hub->going_away = true; 323 324 mutex_lock(&hub->lock); 325 326 /* unbind the USB devices to avoid dangling references to this device */ 327 while (!list_empty(&hub->udev_list)) { 328 node = list_first_entry(&hub->udev_list, struct usbdev_node, list); 329 udev = node->udev; 330 331 /* 332 * Unbinding the driver will call onboard_hub_remove_usbdev(), 333 * which acquires hub->lock. We must release the lock first. 334 */ 335 get_device(&udev->dev); 336 mutex_unlock(&hub->lock); 337 device_release_driver(&udev->dev); 338 put_device(&udev->dev); 339 mutex_lock(&hub->lock); 340 } 341 342 mutex_unlock(&hub->lock); 343 344 onboard_hub_power_off(hub); 345} 346 347MODULE_DEVICE_TABLE(of, onboard_hub_match); 348 349static const struct dev_pm_ops __maybe_unused onboard_hub_pm_ops = { 350 SET_LATE_SYSTEM_SLEEP_PM_OPS(onboard_hub_suspend, onboard_hub_resume) 351}; 352 353static struct platform_driver onboard_hub_driver = { 354 .probe = onboard_hub_probe, 355 .remove_new = onboard_hub_remove, 356 357 .driver = { 358 .name = "onboard-usb-hub", 359 .of_match_table = onboard_hub_match, 360 .pm = pm_ptr(&onboard_hub_pm_ops), 361 .dev_groups = onboard_hub_groups, 362 }, 363}; 364 365/************************** USB driver **************************/ 366 367#define VENDOR_ID_CYPRESS 0x04b4 368#define VENDOR_ID_GENESYS 0x05e3 369#define VENDOR_ID_MICROCHIP 0x0424 370#define VENDOR_ID_REALTEK 0x0bda 371#define VENDOR_ID_TI 0x0451 372#define VENDOR_ID_VIA 0x2109 373 374/* 375 * Returns the onboard_hub platform device that is associated with the USB 376 * device passed as parameter. 377 */ 378static struct onboard_hub *_find_onboard_hub(struct device *dev) 379{ 380 struct platform_device *pdev; 381 struct device_node *np; 382 struct onboard_hub *hub; 383 384 pdev = of_find_device_by_node(dev->of_node); 385 if (!pdev) { 386 np = of_parse_phandle(dev->of_node, "peer-hub", 0); 387 if (!np) { 388 dev_err(dev, "failed to find device node for peer hub\n"); 389 return ERR_PTR(-EINVAL); 390 } 391 392 pdev = of_find_device_by_node(np); 393 of_node_put(np); 394 395 if (!pdev) 396 return ERR_PTR(-ENODEV); 397 } 398 399 hub = dev_get_drvdata(&pdev->dev); 400 put_device(&pdev->dev); 401 402 /* 403 * The presence of drvdata ('hub') indicates that the platform driver 404 * finished probing. This handles the case where (conceivably) we could 405 * be running at the exact same time as the platform driver's probe. If 406 * we detect the race we request probe deferral and we'll come back and 407 * try again. 408 */ 409 if (!hub) 410 return ERR_PTR(-EPROBE_DEFER); 411 412 return hub; 413} 414 415static int onboard_hub_usbdev_probe(struct usb_device *udev) 416{ 417 struct device *dev = &udev->dev; 418 struct onboard_hub *hub; 419 int err; 420 421 /* ignore supported hubs without device tree node */ 422 if (!dev->of_node) 423 return -ENODEV; 424 425 hub = _find_onboard_hub(dev); 426 if (IS_ERR(hub)) 427 return PTR_ERR(hub); 428 429 dev_set_drvdata(dev, hub); 430 431 err = onboard_hub_add_usbdev(hub, udev); 432 if (err) 433 return err; 434 435 return 0; 436} 437 438static void onboard_hub_usbdev_disconnect(struct usb_device *udev) 439{ 440 struct onboard_hub *hub = dev_get_drvdata(&udev->dev); 441 442 onboard_hub_remove_usbdev(hub, udev); 443} 444 445static const struct usb_device_id onboard_hub_id_table[] = { 446 { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6504) }, /* CYUSB33{0,1,2}x/CYUSB230x 3.0 */ 447 { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6506) }, /* CYUSB33{0,1,2}x/CYUSB230x 2.0 */ 448 { USB_DEVICE(VENDOR_ID_CYPRESS, 0x6570) }, /* CY7C6563x 2.0 */ 449 { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */ 450 { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */ 451 { USB_DEVICE(VENDOR_ID_GENESYS, 0x0620) }, /* Genesys Logic GL3523 USB 3.1 */ 452 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */ 453 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ 454 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ 455 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */ 456 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */ 457 { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */ 458 { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */ 459 { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */ 460 { USB_DEVICE(VENDOR_ID_REALTEK, 0x5414) }, /* RTS5414 USB 2.1 */ 461 { USB_DEVICE(VENDOR_ID_TI, 0x8025) }, /* TI USB8020B 3.0 */ 462 { USB_DEVICE(VENDOR_ID_TI, 0x8027) }, /* TI USB8020B 2.0 */ 463 { USB_DEVICE(VENDOR_ID_TI, 0x8140) }, /* TI USB8041 3.0 */ 464 { USB_DEVICE(VENDOR_ID_TI, 0x8142) }, /* TI USB8041 2.0 */ 465 { USB_DEVICE(VENDOR_ID_VIA, 0x0817) }, /* VIA VL817 3.1 */ 466 { USB_DEVICE(VENDOR_ID_VIA, 0x2817) }, /* VIA VL817 2.0 */ 467 {} 468}; 469MODULE_DEVICE_TABLE(usb, onboard_hub_id_table); 470 471static struct usb_device_driver onboard_hub_usbdev_driver = { 472 .name = "onboard-usb-hub", 473 .probe = onboard_hub_usbdev_probe, 474 .disconnect = onboard_hub_usbdev_disconnect, 475 .generic_subclass = 1, 476 .supports_autosuspend = 1, 477 .id_table = onboard_hub_id_table, 478}; 479 480static int __init onboard_hub_init(void) 481{ 482 int ret; 483 484 ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE); 485 if (ret) 486 return ret; 487 488 ret = platform_driver_register(&onboard_hub_driver); 489 if (ret) 490 usb_deregister_device_driver(&onboard_hub_usbdev_driver); 491 492 return ret; 493} 494module_init(onboard_hub_init); 495 496static void __exit onboard_hub_exit(void) 497{ 498 usb_deregister_device_driver(&onboard_hub_usbdev_driver); 499 platform_driver_unregister(&onboard_hub_driver); 500 501 cancel_work_sync(&attach_usb_driver_work); 502} 503module_exit(onboard_hub_exit); 504 505MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>"); 506MODULE_DESCRIPTION("Driver for discrete onboard USB hubs"); 507MODULE_LICENSE("GPL v2"); 508