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/phy/phy.h> 12 #include "common.h" 13 #include "rza.h" 14 15 static int usbhs_rza2_hardware_init(struct platform_device *pdev) 16 { 17 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 18 struct phy *phy = phy_get(&pdev->dev, "usb"); 19 20 if (IS_ERR(phy)) 21 return PTR_ERR(phy); 22 23 priv->phy = phy; 24 return 0; 25 } 26 27 static int usbhs_rza2_hardware_exit(struct platform_device *pdev) 28 { 29 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 30 31 phy_put(&pdev->dev, priv->phy); 32 priv->phy = NULL; 33 34 return 0; 35 } 36 37 static int usbhs_rza2_power_ctrl(struct platform_device *pdev, 38 void __iomem *base, int enable) 39 { 40 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 41 int retval = 0; 42 43 if (!priv->phy) 44 return -ENODEV; 45 46 if (enable) { 47 retval = phy_init(priv->phy); 48 usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); 49 udelay(100); /* Wait for PLL to become stable */ 50 if (!retval) 51 retval = phy_power_on(priv->phy); 52 } else { 53 usbhs_bset(priv, SUSPMODE, SUSPM, 0); 54 phy_power_off(priv->phy); 55 phy_exit(priv->phy); 56 } 57 58 return retval; 59 } 60 61 const struct renesas_usbhs_platform_info usbhs_rza2_plat_info = { 62 .platform_callback = { 63 .hardware_init = usbhs_rza2_hardware_init, 64 .hardware_exit = usbhs_rza2_hardware_exit, 65 .power_ctrl = usbhs_rza2_power_ctrl, 66 .get_id = usbhs_get_id_as_gadget, 67 }, 68 .driver_param = { 69 .has_cnen = 1, 70 .cfifo_byte_addr = 1, 71 .has_new_pipe_configs = 1, 72 }, 73 }; 74