Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: usb251xb: support usage case without I2C control

Currently, the usb251xb assumes i2c control. But from HW point of
view, the hub supports usage case without any i2c, we only want the
gpio controls.

Refactor the code so that register writes for configuration are only
performed if the device has a i2c_client provided and also register as
a platform driver. This allows the driver to be used to manage GPIO
based control of the device.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Link: https://lore.kernel.org/r/20250825234509.1041-4-jszhang@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Jisheng Zhang and committed by
Greg Kroah-Hartman
2cf8ecd0 22fbedf9

+95 -13
+95 -13
drivers/usb/misc/usb251xb.c
··· 17 17 #include <linux/module.h> 18 18 #include <linux/nls.h> 19 19 #include <linux/of.h> 20 + #include <linux/platform_device.h> 20 21 #include <linux/regulator/consumer.h> 21 22 #include <linux/slab.h> 22 23 ··· 243 242 static int usb251x_check_gpio_chip(struct usb251xb *hub) 244 243 { 245 244 struct gpio_chip *gc = gpiod_to_chip(hub->gpio_reset); 246 - struct i2c_adapter *adap = hub->i2c->adapter; 245 + struct i2c_adapter *adap; 247 246 int ret; 247 + 248 + if (!hub->i2c) 249 + return 0; 248 250 249 251 if (!hub->gpio_reset) 250 252 return 0; ··· 255 251 if (!gc) 256 252 return -EINVAL; 257 253 254 + adap = hub->i2c->adapter; 258 255 ret = usb251xb_check_dev_children(&adap->dev, gc->parent); 259 256 if (ret) { 260 257 dev_err(hub->dev, "Reset GPIO chip is at the same i2c-bus\n"); ··· 276 271 if (!hub->gpio_reset) 277 272 return; 278 273 279 - i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); 274 + if (hub->i2c) 275 + i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); 280 276 281 277 gpiod_set_value_cansleep(hub->gpio_reset, 1); 282 278 usleep_range(1, 10); /* >=1us RESET_N asserted */ ··· 286 280 /* wait for hub recovery/stabilization */ 287 281 usleep_range(500, 750); /* >=500us after RESET_N deasserted */ 288 282 289 - i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); 283 + if (hub->i2c) 284 + i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); 290 285 } 291 286 292 287 static int usb251xb_connect(struct usb251xb *hub) ··· 295 288 struct device *dev = hub->dev; 296 289 int err, i; 297 290 char i2c_wb[USB251XB_I2C_REG_SZ]; 291 + 292 + if (!hub->i2c) { 293 + usb251xb_reset(hub); 294 + dev_info(dev, "hub is put in default configuration.\n"); 295 + return 0; 296 + } 298 297 299 298 memset(i2c_wb, 0, USB251XB_I2C_REG_SZ); 300 299 ··· 711 698 return usb251xb_probe(hub); 712 699 } 713 700 714 - static int usb251xb_suspend(struct device *dev) 701 + static int usb251xb_suspend(struct usb251xb *hub) 715 702 { 716 - struct i2c_client *client = to_i2c_client(dev); 717 - struct usb251xb *hub = i2c_get_clientdata(client); 718 - 719 703 return regulator_disable(hub->vdd); 720 704 } 721 705 722 - static int usb251xb_resume(struct device *dev) 706 + static int usb251xb_resume(struct usb251xb *hub) 723 707 { 724 - struct i2c_client *client = to_i2c_client(dev); 725 - struct usb251xb *hub = i2c_get_clientdata(client); 726 708 int err; 727 709 728 710 err = regulator_enable(hub->vdd); ··· 727 719 return usb251xb_connect(hub); 728 720 } 729 721 730 - static DEFINE_SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume); 722 + static int usb251xb_i2c_suspend(struct device *dev) 723 + { 724 + struct i2c_client *client = to_i2c_client(dev); 725 + struct usb251xb *hub = i2c_get_clientdata(client); 726 + 727 + return usb251xb_suspend(hub); 728 + } 729 + 730 + static int usb251xb_i2c_resume(struct device *dev) 731 + { 732 + struct i2c_client *client = to_i2c_client(dev); 733 + struct usb251xb *hub = i2c_get_clientdata(client); 734 + 735 + return usb251xb_resume(hub); 736 + } 737 + 738 + static DEFINE_SIMPLE_DEV_PM_OPS(usb251xb_i2c_pm_ops, usb251xb_i2c_suspend, usb251xb_i2c_resume); 731 739 732 740 static const struct i2c_device_id usb251xb_id[] = { 733 741 { "usb2422" }, ··· 763 739 .driver = { 764 740 .name = DRIVER_NAME, 765 741 .of_match_table = usb251xb_of_match, 766 - .pm = pm_sleep_ptr(&usb251xb_pm_ops), 742 + .pm = pm_sleep_ptr(&usb251xb_i2c_pm_ops), 767 743 }, 768 744 .probe = usb251xb_i2c_probe, 769 745 .id_table = usb251xb_id, 770 746 }; 771 747 772 - module_i2c_driver(usb251xb_i2c_driver); 748 + static int usb251xb_plat_probe(struct platform_device *pdev) 749 + { 750 + struct usb251xb *hub; 751 + 752 + hub = devm_kzalloc(&pdev->dev, sizeof(*hub), GFP_KERNEL); 753 + if (!hub) 754 + return -ENOMEM; 755 + 756 + platform_set_drvdata(pdev, hub); 757 + hub->dev = &pdev->dev; 758 + 759 + return usb251xb_probe(hub); 760 + } 761 + 762 + static int usb251xb_plat_suspend(struct device *dev) 763 + { 764 + return usb251xb_suspend(dev_get_drvdata(dev)); 765 + } 766 + 767 + static int usb251xb_plat_resume(struct device *dev) 768 + { 769 + return usb251xb_resume(dev_get_drvdata(dev)); 770 + } 771 + 772 + static DEFINE_SIMPLE_DEV_PM_OPS(usb251xb_plat_pm_ops, usb251xb_plat_suspend, usb251xb_plat_resume); 773 + 774 + static struct platform_driver usb251xb_plat_driver = { 775 + .driver = { 776 + .name = DRIVER_NAME, 777 + .of_match_table = usb251xb_of_match, 778 + .pm = pm_sleep_ptr(&usb251xb_plat_pm_ops), 779 + }, 780 + .probe = usb251xb_plat_probe, 781 + }; 782 + 783 + static int __init usb251xb_init(void) 784 + { 785 + int err; 786 + 787 + err = i2c_add_driver(&usb251xb_i2c_driver); 788 + if (err) 789 + return err; 790 + 791 + err = platform_driver_register(&usb251xb_plat_driver); 792 + if (err) { 793 + i2c_del_driver(&usb251xb_i2c_driver); 794 + return err; 795 + } 796 + 797 + return 0; 798 + } 799 + module_init(usb251xb_init); 800 + 801 + static void __exit usb251xb_exit(void) 802 + { 803 + platform_driver_unregister(&usb251xb_plat_driver); 804 + i2c_del_driver(&usb251xb_i2c_driver); 805 + } 806 + module_exit(usb251xb_exit); 773 807 774 808 MODULE_AUTHOR("Richard Leitner <richard.leitner@skidata.com>"); 775 809 MODULE_DESCRIPTION("USB251x/xBi USB 2.0 Hub Controller Driver");