1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas USB driver RZ/A2 initialization and power control 4 * 5 * Copyright (C) 2019 Chris Brandt 6 * Copyright (C) 2019 Renesas Electronics Corporation 7 */ 8 9 #include <linux/delay.h> 10 #include <linux/io.h> 11 #include <linux/of_device.h> 12 #include <linux/phy/phy.h> 13 #include "common.h" 14 #include "rza.h" 15 16 static int usbhs_rza2_hardware_init(struct platform_device *pdev) 17 { 18 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 19 struct phy *phy = phy_get(&pdev->dev, "usb"); 20 21 if (IS_ERR(phy)) 22 return PTR_ERR(phy); 23 24 priv->phy = phy; 25 return 0; 26 } 27 28 static int usbhs_rza2_hardware_exit(struct platform_device *pdev) 29 { 30 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 31 32 phy_put(&pdev->dev, priv->phy); 33 priv->phy = NULL; 34 35 return 0; 36 } 37 38 static int usbhs_rza2_power_ctrl(struct platform_device *pdev, 39 void __iomem *base, int enable) 40 { 41 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 42 int retval = 0; 43 44 if (!priv->phy) 45 return -ENODEV; 46 47 if (enable) { 48 retval = phy_init(priv->phy); 49 usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); 50 udelay(100); /* Wait for PLL to become stable */ 51 if (!retval) 52 retval = phy_power_on(priv->phy); 53 } else { 54 usbhs_bset(priv, SUSPMODE, SUSPM, 0); 55 phy_power_off(priv->phy); 56 phy_exit(priv->phy); 57 } 58 59 return retval; 60 } 61 62 const struct renesas_usbhs_platform_info usbhs_rza2_plat_info = { 63 .platform_callback = { 64 .hardware_init = usbhs_rza2_hardware_init, 65 .hardware_exit = usbhs_rza2_hardware_exit, 66 .power_ctrl = usbhs_rza2_power_ctrl, 67 .get_id = usbhs_get_id_as_gadget, 68 }, 69 .driver_param = { 70 .has_cnen = 1, 71 .cfifo_byte_addr = 1, 72 .has_new_pipe_configs = 1, 73 }, 74 }; 75