Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Renesas USB driver R-Car Gen. 3 initialization and power control
0004  *
0005  * Copyright (C) 2016-2019 Renesas Electronics Corporation
0006  */
0007 
0008 #include <linux/delay.h>
0009 #include <linux/io.h>
0010 #include "common.h"
0011 #include "rcar3.h"
0012 
0013 #define LPSTS       0x102
0014 #define UGCTRL      0x180   /* 32-bit register */
0015 #define UGCTRL2     0x184   /* 32-bit register */
0016 #define UGSTS       0x188   /* 32-bit register */
0017 
0018 /* Low Power Status register (LPSTS) */
0019 #define LPSTS_SUSPM 0x4000
0020 
0021 /* R-Car D3 only: USB General control register (UGCTRL) */
0022 #define UGCTRL_PLLRESET     0x00000001
0023 #define UGCTRL_CONNECT      0x00000004
0024 
0025 /*
0026  * USB General control register 2 (UGCTRL2)
0027  * Remarks: bit[31:11] and bit[9:6] should be 0
0028  */
0029 #define UGCTRL2_RESERVED_3  0x00000001  /* bit[3:0] should be B'0001 */
0030 #define UGCTRL2_USB0SEL_HSUSB   0x00000020
0031 #define UGCTRL2_USB0SEL_OTG 0x00000030
0032 #define UGCTRL2_VBUSSEL     0x00000400
0033 
0034 /* R-Car D3 only: USB General status register (UGSTS) */
0035 #define UGSTS_LOCK      0x00000100
0036 
0037 static void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data)
0038 {
0039     iowrite32(data, priv->base + reg);
0040 }
0041 
0042 static u32 usbhs_read32(struct usbhs_priv *priv, u32 reg)
0043 {
0044     return ioread32(priv->base + reg);
0045 }
0046 
0047 static void usbhs_rcar3_set_ugctrl2(struct usbhs_priv *priv, u32 val)
0048 {
0049     usbhs_write32(priv, UGCTRL2, val | UGCTRL2_RESERVED_3);
0050 }
0051 
0052 static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
0053                 void __iomem *base, int enable)
0054 {
0055     struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
0056 
0057     usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL);
0058 
0059     if (enable) {
0060         usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
0061         /* The controller on R-Car Gen3 needs to wait up to 45 usec */
0062         usleep_range(45, 90);
0063     } else {
0064         usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
0065     }
0066 
0067     return 0;
0068 }
0069 
0070 /* R-Car D3 needs to release UGCTRL.PLLRESET */
0071 static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev,
0072                       void __iomem *base, int enable)
0073 {
0074     struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
0075     u32 val;
0076     int timeout = 1000;
0077 
0078     if (enable) {
0079         usbhs_write32(priv, UGCTRL, 0); /* release PLLRESET */
0080         usbhs_rcar3_set_ugctrl2(priv,
0081                     UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL);
0082 
0083         usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
0084         do {
0085             val = usbhs_read32(priv, UGSTS);
0086             udelay(1);
0087         } while (!(val & UGSTS_LOCK) && timeout--);
0088         usbhs_write32(priv, UGCTRL, UGCTRL_CONNECT);
0089     } else {
0090         usbhs_write32(priv, UGCTRL, 0);
0091         usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
0092         usbhs_write32(priv, UGCTRL, UGCTRL_PLLRESET);
0093     }
0094 
0095     return 0;
0096 }
0097 
0098 const struct renesas_usbhs_platform_info usbhs_rcar_gen3_plat_info = {
0099     .platform_callback = {
0100         .power_ctrl = usbhs_rcar3_power_ctrl,
0101         .get_id = usbhs_get_id_as_gadget,
0102     },
0103     .driver_param = {
0104         .has_usb_dmac = 1,
0105         .multi_clks = 1,
0106         .has_new_pipe_configs = 1,
0107     },
0108 };
0109 
0110 const struct renesas_usbhs_platform_info usbhs_rcar_gen3_with_pll_plat_info = {
0111     .platform_callback = {
0112         .power_ctrl = usbhs_rcar3_power_and_pll_ctrl,
0113         .get_id = usbhs_get_id_as_gadget,
0114     },
0115     .driver_param = {
0116         .has_usb_dmac = 1,
0117         .multi_clks = 1,
0118         .has_new_pipe_configs = 1,
0119     },
0120 };