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

usb: musb: jz4740: Support the generic PHY framework

Support PHYs implemented using the generic PHY framework instead of the
deprecated USB-PHY framework.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20221026182657.146630-7-paul@crapouillou.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Paul Cercueil and committed by
Greg Kroah-Hartman
9cd07479 d9b32430

+54 -8
+54 -8
drivers/usb/musb/jz4740.c
··· 11 11 #include <linux/kernel.h> 12 12 #include <linux/module.h> 13 13 #include <linux/of_device.h> 14 + #include <linux/phy/phy.h> 14 15 #include <linux/platform_device.h> 15 16 #include <linux/usb/role.h> 16 17 #include <linux/usb/usb_phy_generic.h> ··· 82 81 struct jz4740_glue *glue = usb_role_switch_get_drvdata(sw); 83 82 struct usb_phy *phy = glue->musb->xceiv; 84 83 84 + if (!phy) 85 + return 0; 86 + 85 87 switch (role) { 86 88 case USB_ROLE_NONE: 87 89 atomic_notifier_call_chain(&phy->notifier, USB_EVENT_NONE, phy); ··· 109 105 .driver_data = glue, 110 106 .fwnode = dev_fwnode(dev), 111 107 }; 108 + int err; 112 109 113 110 glue->musb = musb; 114 111 115 - if (dev->of_node) 116 - musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0); 117 - else 118 - musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 119 - if (IS_ERR(musb->xceiv)) 120 - return dev_err_probe(dev, PTR_ERR(musb->xceiv), 121 - "No transceiver configured\n"); 112 + if (IS_ENABLED(CONFIG_GENERIC_PHY)) { 113 + musb->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0); 114 + if (IS_ERR(musb->phy)) { 115 + err = PTR_ERR(musb->phy); 116 + if (err != -ENODEV) { 117 + dev_err(dev, "Unable to get PHY\n"); 118 + return err; 119 + } 120 + 121 + musb->phy = NULL; 122 + } 123 + } 124 + 125 + if (musb->phy) { 126 + err = phy_init(musb->phy); 127 + if (err) { 128 + dev_err(dev, "Failed to init PHY\n"); 129 + return err; 130 + } 131 + 132 + err = phy_power_on(musb->phy); 133 + if (err) { 134 + dev_err(dev, "Unable to power on PHY\n"); 135 + goto err_phy_shutdown; 136 + } 137 + } else { 138 + if (dev->of_node) 139 + musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0); 140 + else 141 + musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 142 + if (IS_ERR(musb->xceiv)) { 143 + dev_err(dev, "No transceiver configured\n"); 144 + return PTR_ERR(musb->xceiv); 145 + } 146 + } 122 147 123 148 glue->role_sw = usb_role_switch_register(dev, &role_sw_desc); 124 149 if (IS_ERR(glue->role_sw)) { 125 150 dev_err(dev, "Failed to register USB role switch\n"); 126 - return PTR_ERR(glue->role_sw); 151 + err = PTR_ERR(glue->role_sw); 152 + goto err_phy_power_down; 127 153 } 128 154 129 155 /* ··· 165 131 musb->isr = jz4740_musb_interrupt; 166 132 167 133 return 0; 134 + 135 + err_phy_power_down: 136 + if (musb->phy) 137 + phy_power_off(musb->phy); 138 + err_phy_shutdown: 139 + if (musb->phy) 140 + phy_exit(musb->phy); 141 + return err; 168 142 } 169 143 170 144 static int jz4740_musb_exit(struct musb *musb) ··· 180 138 struct jz4740_glue *glue = dev_get_drvdata(musb->controller->parent); 181 139 182 140 usb_role_switch_unregister(glue->role_sw); 141 + if (musb->phy) { 142 + phy_power_off(musb->phy); 143 + phy_exit(musb->phy); 144 + } 183 145 184 146 return 0; 185 147 }