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

usb: ohci-platform: Enable optional use of reset controller

The OHCI controllers used in the Allwinner A31 are asserted in reset using a
global reset controller.

Add optional support for such a controller in the OHCI platform driver.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Maxime Ripard and committed by
Greg Kroah-Hartman
4615f3bd 38e0c109

+25 -3
+1
Documentation/devicetree/bindings/usb/usb-ohci.txt
··· 12 12 - clocks : a list of phandle + clock specifier pairs 13 13 - phys : phandle + phy specifier pair 14 14 - phy-names : "usb" 15 + - resets : phandle + reset specifier pair 15 16 16 17 Example: 17 18
+24 -3
drivers/usb/host/ohci-platform.c
··· 24 24 #include <linux/err.h> 25 25 #include <linux/phy/phy.h> 26 26 #include <linux/platform_device.h> 27 + #include <linux/reset.h> 27 28 #include <linux/usb/ohci_pdriver.h> 28 29 #include <linux/usb.h> 29 30 #include <linux/usb/hcd.h> ··· 37 36 38 37 struct ohci_platform_priv { 39 38 struct clk *clks[OHCI_MAX_CLKS]; 39 + struct reset_control *rst; 40 40 struct phy *phy; 41 41 }; 42 42 ··· 193 191 break; 194 192 } 195 193 } 194 + 195 + } 196 + 197 + priv->rst = devm_reset_control_get_optional(&dev->dev, NULL); 198 + if (IS_ERR(priv->rst)) { 199 + err = PTR_ERR(priv->rst); 200 + if (err == -EPROBE_DEFER) 201 + goto err_put_clks; 202 + priv->rst = NULL; 203 + } else { 204 + err = reset_control_deassert(priv->rst); 205 + if (err) 206 + goto err_put_clks; 196 207 } 197 208 198 209 if (pdata->big_endian_desc) ··· 218 203 dev_err(&dev->dev, 219 204 "Error: CONFIG_USB_OHCI_BIG_ENDIAN_MMIO not set\n"); 220 205 err = -EINVAL; 221 - goto err_put_clks; 206 + goto err_reset; 222 207 } 223 208 #endif 224 209 #ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC ··· 226 211 dev_err(&dev->dev, 227 212 "Error: CONFIG_USB_OHCI_BIG_ENDIAN_DESC not set\n"); 228 213 err = -EINVAL; 229 - goto err_put_clks; 214 + goto err_reset; 230 215 } 231 216 #endif 232 217 233 218 if (pdata->power_on) { 234 219 err = pdata->power_on(dev); 235 220 if (err < 0) 236 - goto err_put_clks; 221 + goto err_reset; 237 222 } 238 223 239 224 hcd->rsrc_start = res_mem->start; ··· 257 242 err_power: 258 243 if (pdata->power_off) 259 244 pdata->power_off(dev); 245 + err_reset: 246 + if (priv->rst) 247 + reset_control_assert(priv->rst); 260 248 err_put_clks: 261 249 while (--clk >= 0) 262 250 clk_put(priv->clks[clk]); ··· 283 265 284 266 if (pdata->power_off) 285 267 pdata->power_off(dev); 268 + 269 + if (priv->rst) 270 + reset_control_assert(priv->rst); 286 271 287 272 for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) 288 273 clk_put(priv->clks[clk]);