0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/export.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/list.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/of.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/regulator/consumer.h>
0020 #include <linux/slab.h>
0021 #include <linux/suspend.h>
0022 #include <linux/sysfs.h>
0023 #include <linux/usb.h>
0024 #include <linux/usb/hcd.h>
0025 #include <linux/usb/onboard_hub.h>
0026 #include <linux/workqueue.h>
0027
0028 #include "onboard_usb_hub.h"
0029
0030 static struct usb_device_driver onboard_hub_usbdev_driver;
0031
0032
0033
0034 struct usbdev_node {
0035 struct usb_device *udev;
0036 struct list_head list;
0037 };
0038
0039 struct onboard_hub {
0040 struct regulator *vdd;
0041 struct device *dev;
0042 const struct onboard_hub_pdata *pdata;
0043 struct gpio_desc *reset_gpio;
0044 bool always_powered_in_suspend;
0045 bool is_powered_on;
0046 bool going_away;
0047 struct list_head udev_list;
0048 struct work_struct attach_usb_driver_work;
0049 struct mutex lock;
0050 };
0051
0052 static int onboard_hub_power_on(struct onboard_hub *hub)
0053 {
0054 int err;
0055
0056 err = regulator_enable(hub->vdd);
0057 if (err) {
0058 dev_err(hub->dev, "failed to enable regulator: %d\n", err);
0059 return err;
0060 }
0061
0062 fsleep(hub->pdata->reset_us);
0063 gpiod_set_value_cansleep(hub->reset_gpio, 0);
0064
0065 hub->is_powered_on = true;
0066
0067 return 0;
0068 }
0069
0070 static int onboard_hub_power_off(struct onboard_hub *hub)
0071 {
0072 int err;
0073
0074 gpiod_set_value_cansleep(hub->reset_gpio, 1);
0075
0076 err = regulator_disable(hub->vdd);
0077 if (err) {
0078 dev_err(hub->dev, "failed to disable regulator: %d\n", err);
0079 return err;
0080 }
0081
0082 hub->is_powered_on = false;
0083
0084 return 0;
0085 }
0086
0087 static int __maybe_unused onboard_hub_suspend(struct device *dev)
0088 {
0089 struct onboard_hub *hub = dev_get_drvdata(dev);
0090 struct usbdev_node *node;
0091 bool power_off = true;
0092
0093 if (hub->always_powered_in_suspend)
0094 return 0;
0095
0096 mutex_lock(&hub->lock);
0097
0098 list_for_each_entry(node, &hub->udev_list, list) {
0099 if (!device_may_wakeup(node->udev->bus->controller))
0100 continue;
0101
0102 if (usb_wakeup_enabled_descendants(node->udev)) {
0103 power_off = false;
0104 break;
0105 }
0106 }
0107
0108 mutex_unlock(&hub->lock);
0109
0110 if (!power_off)
0111 return 0;
0112
0113 return onboard_hub_power_off(hub);
0114 }
0115
0116 static int __maybe_unused onboard_hub_resume(struct device *dev)
0117 {
0118 struct onboard_hub *hub = dev_get_drvdata(dev);
0119
0120 if (hub->is_powered_on)
0121 return 0;
0122
0123 return onboard_hub_power_on(hub);
0124 }
0125
0126 static inline void get_udev_link_name(const struct usb_device *udev, char *buf, size_t size)
0127 {
0128 snprintf(buf, size, "usb_dev.%s", dev_name(&udev->dev));
0129 }
0130
0131 static int onboard_hub_add_usbdev(struct onboard_hub *hub, struct usb_device *udev)
0132 {
0133 struct usbdev_node *node;
0134 char link_name[64];
0135 int err;
0136
0137 mutex_lock(&hub->lock);
0138
0139 if (hub->going_away) {
0140 err = -EINVAL;
0141 goto error;
0142 }
0143
0144 node = kzalloc(sizeof(*node), GFP_KERNEL);
0145 if (!node) {
0146 err = -ENOMEM;
0147 goto error;
0148 }
0149
0150 node->udev = udev;
0151
0152 list_add(&node->list, &hub->udev_list);
0153
0154 mutex_unlock(&hub->lock);
0155
0156 get_udev_link_name(udev, link_name, sizeof(link_name));
0157 WARN_ON(sysfs_create_link(&hub->dev->kobj, &udev->dev.kobj, link_name));
0158
0159 return 0;
0160
0161 error:
0162 mutex_unlock(&hub->lock);
0163
0164 return err;
0165 }
0166
0167 static void onboard_hub_remove_usbdev(struct onboard_hub *hub, const struct usb_device *udev)
0168 {
0169 struct usbdev_node *node;
0170 char link_name[64];
0171
0172 get_udev_link_name(udev, link_name, sizeof(link_name));
0173 sysfs_remove_link(&hub->dev->kobj, link_name);
0174
0175 mutex_lock(&hub->lock);
0176
0177 list_for_each_entry(node, &hub->udev_list, list) {
0178 if (node->udev == udev) {
0179 list_del(&node->list);
0180 kfree(node);
0181 break;
0182 }
0183 }
0184
0185 mutex_unlock(&hub->lock);
0186 }
0187
0188 static ssize_t always_powered_in_suspend_show(struct device *dev, struct device_attribute *attr,
0189 char *buf)
0190 {
0191 const struct onboard_hub *hub = dev_get_drvdata(dev);
0192
0193 return sysfs_emit(buf, "%d\n", hub->always_powered_in_suspend);
0194 }
0195
0196 static ssize_t always_powered_in_suspend_store(struct device *dev, struct device_attribute *attr,
0197 const char *buf, size_t count)
0198 {
0199 struct onboard_hub *hub = dev_get_drvdata(dev);
0200 bool val;
0201 int ret;
0202
0203 ret = kstrtobool(buf, &val);
0204 if (ret < 0)
0205 return ret;
0206
0207 hub->always_powered_in_suspend = val;
0208
0209 return count;
0210 }
0211 static DEVICE_ATTR_RW(always_powered_in_suspend);
0212
0213 static struct attribute *onboard_hub_attrs[] = {
0214 &dev_attr_always_powered_in_suspend.attr,
0215 NULL,
0216 };
0217 ATTRIBUTE_GROUPS(onboard_hub);
0218
0219 static void onboard_hub_attach_usb_driver(struct work_struct *work)
0220 {
0221 int err;
0222
0223 err = driver_attach(&onboard_hub_usbdev_driver.drvwrap.driver);
0224 if (err)
0225 pr_err("Failed to attach USB driver: %d\n", err);
0226 }
0227
0228 static int onboard_hub_probe(struct platform_device *pdev)
0229 {
0230 const struct of_device_id *of_id;
0231 struct device *dev = &pdev->dev;
0232 struct onboard_hub *hub;
0233 int err;
0234
0235 hub = devm_kzalloc(dev, sizeof(*hub), GFP_KERNEL);
0236 if (!hub)
0237 return -ENOMEM;
0238
0239 of_id = of_match_device(onboard_hub_match, &pdev->dev);
0240 if (!of_id)
0241 return -ENODEV;
0242
0243 hub->pdata = of_id->data;
0244 if (!hub->pdata)
0245 return -EINVAL;
0246
0247 hub->vdd = devm_regulator_get(dev, "vdd");
0248 if (IS_ERR(hub->vdd))
0249 return PTR_ERR(hub->vdd);
0250
0251 hub->reset_gpio = devm_gpiod_get_optional(dev, "reset",
0252 GPIOD_OUT_HIGH);
0253 if (IS_ERR(hub->reset_gpio))
0254 return dev_err_probe(dev, PTR_ERR(hub->reset_gpio), "failed to get reset GPIO\n");
0255
0256 hub->dev = dev;
0257 mutex_init(&hub->lock);
0258 INIT_LIST_HEAD(&hub->udev_list);
0259
0260 dev_set_drvdata(dev, hub);
0261
0262 err = onboard_hub_power_on(hub);
0263 if (err)
0264 return err;
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 INIT_WORK(&hub->attach_usb_driver_work, onboard_hub_attach_usb_driver);
0275 schedule_work(&hub->attach_usb_driver_work);
0276
0277 return 0;
0278 }
0279
0280 static int onboard_hub_remove(struct platform_device *pdev)
0281 {
0282 struct onboard_hub *hub = dev_get_drvdata(&pdev->dev);
0283 struct usbdev_node *node;
0284 struct usb_device *udev;
0285
0286 hub->going_away = true;
0287
0288 if (&hub->attach_usb_driver_work != current_work())
0289 cancel_work_sync(&hub->attach_usb_driver_work);
0290
0291 mutex_lock(&hub->lock);
0292
0293
0294 while (!list_empty(&hub->udev_list)) {
0295 node = list_first_entry(&hub->udev_list, struct usbdev_node, list);
0296 udev = node->udev;
0297
0298
0299
0300
0301
0302 get_device(&udev->dev);
0303 mutex_unlock(&hub->lock);
0304 device_release_driver(&udev->dev);
0305 put_device(&udev->dev);
0306 mutex_lock(&hub->lock);
0307 }
0308
0309 mutex_unlock(&hub->lock);
0310
0311 return onboard_hub_power_off(hub);
0312 }
0313
0314 MODULE_DEVICE_TABLE(of, onboard_hub_match);
0315
0316 static const struct dev_pm_ops __maybe_unused onboard_hub_pm_ops = {
0317 SET_LATE_SYSTEM_SLEEP_PM_OPS(onboard_hub_suspend, onboard_hub_resume)
0318 };
0319
0320 static struct platform_driver onboard_hub_driver = {
0321 .probe = onboard_hub_probe,
0322 .remove = onboard_hub_remove,
0323
0324 .driver = {
0325 .name = "onboard-usb-hub",
0326 .of_match_table = onboard_hub_match,
0327 .pm = pm_ptr(&onboard_hub_pm_ops),
0328 .dev_groups = onboard_hub_groups,
0329 },
0330 };
0331
0332
0333
0334 #define VENDOR_ID_MICROCHIP 0x0424
0335 #define VENDOR_ID_REALTEK 0x0bda
0336 #define VENDOR_ID_TI 0x0451
0337
0338
0339
0340
0341
0342 static struct onboard_hub *_find_onboard_hub(struct device *dev)
0343 {
0344 struct platform_device *pdev;
0345 struct device_node *np;
0346 struct onboard_hub *hub;
0347
0348 pdev = of_find_device_by_node(dev->of_node);
0349 if (!pdev) {
0350 np = of_parse_phandle(dev->of_node, "peer-hub", 0);
0351 if (!np) {
0352 dev_err(dev, "failed to find device node for peer hub\n");
0353 return ERR_PTR(-EINVAL);
0354 }
0355
0356 pdev = of_find_device_by_node(np);
0357 of_node_put(np);
0358
0359 if (!pdev)
0360 return ERR_PTR(-ENODEV);
0361 }
0362
0363 hub = dev_get_drvdata(&pdev->dev);
0364 put_device(&pdev->dev);
0365
0366
0367
0368
0369
0370
0371
0372
0373 if (!hub)
0374 return ERR_PTR(-EPROBE_DEFER);
0375
0376 return hub;
0377 }
0378
0379 static int onboard_hub_usbdev_probe(struct usb_device *udev)
0380 {
0381 struct device *dev = &udev->dev;
0382 struct onboard_hub *hub;
0383 int err;
0384
0385
0386 if (!dev->of_node)
0387 return -ENODEV;
0388
0389 hub = _find_onboard_hub(dev);
0390 if (IS_ERR(hub))
0391 return PTR_ERR(hub);
0392
0393 dev_set_drvdata(dev, hub);
0394
0395 err = onboard_hub_add_usbdev(hub, udev);
0396 if (err)
0397 return err;
0398
0399 return 0;
0400 }
0401
0402 static void onboard_hub_usbdev_disconnect(struct usb_device *udev)
0403 {
0404 struct onboard_hub *hub = dev_get_drvdata(&udev->dev);
0405
0406 onboard_hub_remove_usbdev(hub, udev);
0407 }
0408
0409 static const struct usb_device_id onboard_hub_id_table[] = {
0410 { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) },
0411 { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) },
0412 { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) },
0413 { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) },
0414 { USB_DEVICE(VENDOR_ID_REALTEK, 0x5414) },
0415 { USB_DEVICE(VENDOR_ID_TI, 0x8140) },
0416 { USB_DEVICE(VENDOR_ID_TI, 0x8142) },
0417 {}
0418 };
0419 MODULE_DEVICE_TABLE(usb, onboard_hub_id_table);
0420
0421 static struct usb_device_driver onboard_hub_usbdev_driver = {
0422 .name = "onboard-usb-hub",
0423 .probe = onboard_hub_usbdev_probe,
0424 .disconnect = onboard_hub_usbdev_disconnect,
0425 .generic_subclass = 1,
0426 .supports_autosuspend = 1,
0427 .id_table = onboard_hub_id_table,
0428 };
0429
0430 static int __init onboard_hub_init(void)
0431 {
0432 int ret;
0433
0434 ret = platform_driver_register(&onboard_hub_driver);
0435 if (ret)
0436 return ret;
0437
0438 ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
0439 if (ret)
0440 platform_driver_unregister(&onboard_hub_driver);
0441
0442 return ret;
0443 }
0444 module_init(onboard_hub_init);
0445
0446 static void __exit onboard_hub_exit(void)
0447 {
0448 usb_deregister_device_driver(&onboard_hub_usbdev_driver);
0449 platform_driver_unregister(&onboard_hub_driver);
0450 }
0451 module_exit(onboard_hub_exit);
0452
0453 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
0454 MODULE_DESCRIPTION("Driver for discrete onboard USB hubs");
0455 MODULE_LICENSE("GPL v2");