linux/drivers/usb/renesas_usbhs/rcar3.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Renesas USB driver R-Car Gen. 3 initialization and power control
   4 *
   5 * Copyright (C) 2016-2019 Renesas Electronics Corporation
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/io.h>
  10#include "common.h"
  11#include "rcar3.h"
  12
  13#define LPSTS           0x102
  14#define UGCTRL          0x180   /* 32-bit register */
  15#define UGCTRL2         0x184   /* 32-bit register */
  16#define UGSTS           0x188   /* 32-bit register */
  17
  18/* Low Power Status register (LPSTS) */
  19#define LPSTS_SUSPM     0x4000
  20
  21/* R-Car D3 only: USB General control register (UGCTRL) */
  22#define UGCTRL_PLLRESET         0x00000001
  23#define UGCTRL_CONNECT          0x00000004
  24
  25/*
  26 * USB General control register 2 (UGCTRL2)
  27 * Remarks: bit[31:11] and bit[9:6] should be 0
  28 */
  29#define UGCTRL2_RESERVED_3      0x00000001      /* bit[3:0] should be B'0001 */
  30#define UGCTRL2_USB0SEL_HSUSB   0x00000020
  31#define UGCTRL2_USB0SEL_OTG     0x00000030
  32#define UGCTRL2_VBUSSEL         0x00000400
  33
  34/* R-Car D3 only: USB General status register (UGSTS) */
  35#define UGSTS_LOCK              0x00000100
  36
  37static void usbhs_write32(struct usbhs_priv *priv, u32 reg, u32 data)
  38{
  39        iowrite32(data, priv->base + reg);
  40}
  41
  42static u32 usbhs_read32(struct usbhs_priv *priv, u32 reg)
  43{
  44        return ioread32(priv->base + reg);
  45}
  46
  47static void usbhs_rcar3_set_ugctrl2(struct usbhs_priv *priv, u32 val)
  48{
  49        usbhs_write32(priv, UGCTRL2, val | UGCTRL2_RESERVED_3);
  50}
  51
  52static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
  53                                void __iomem *base, int enable)
  54{
  55        struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
  56
  57        usbhs_rcar3_set_ugctrl2(priv, UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL);
  58
  59        if (enable) {
  60                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
  61                /* The controller on R-Car Gen3 needs to wait up to 45 usec */
  62                usleep_range(45, 90);
  63        } else {
  64                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
  65        }
  66
  67        return 0;
  68}
  69
  70/* R-Car D3 needs to release UGCTRL.PLLRESET */
  71static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev,
  72                                          void __iomem *base, int enable)
  73{
  74        struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
  75        u32 val;
  76        int timeout = 1000;
  77
  78        if (enable) {
  79                usbhs_write32(priv, UGCTRL, 0); /* release PLLRESET */
  80                usbhs_rcar3_set_ugctrl2(priv,
  81                                        UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL);
  82
  83                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
  84                do {
  85                        val = usbhs_read32(priv, UGSTS);
  86                        udelay(1);
  87                } while (!(val & UGSTS_LOCK) && timeout--);
  88                usbhs_write32(priv, UGCTRL, UGCTRL_CONNECT);
  89        } else {
  90                usbhs_write32(priv, UGCTRL, 0);
  91                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
  92                usbhs_write32(priv, UGCTRL, UGCTRL_PLLRESET);
  93        }
  94
  95        return 0;
  96}
  97
  98const struct renesas_usbhs_platform_info usbhs_rcar_gen3_plat_info = {
  99        .platform_callback = {
 100                .power_ctrl = usbhs_rcar3_power_ctrl,
 101                .get_id = usbhs_get_id_as_gadget,
 102        },
 103        .driver_param = {
 104                .has_usb_dmac = 1,
 105                .multi_clks = 1,
 106                .has_new_pipe_configs = 1,
 107        },
 108};
 109
 110const struct renesas_usbhs_platform_info usbhs_rcar_gen3_with_pll_plat_info = {
 111        .platform_callback = {
 112                .power_ctrl = usbhs_rcar3_power_and_pll_ctrl,
 113                .get_id = usbhs_get_id_as_gadget,
 114        },
 115        .driver_param = {
 116                .has_usb_dmac = 1,
 117                .multi_clks = 1,
 118                .has_new_pipe_configs = 1,
 119        },
 120};
 121