326 lines
10 KiB
C
326 lines
10 KiB
C
/*
|
|
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
|
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
* conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
* provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "hisoc/usb3.h"
|
|
#include "los_atomic.h"
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
#endif /* __cplusplus */
|
|
|
|
#define USB3_CTRL_REG_BASE IO_DEVICE_ADDR(CONFIG_HIUSB_XHCI_IOBASE)
|
|
#define REG_USB2_CTRL 0x0140
|
|
|
|
/* offset 0x140 */
|
|
#define USB2_UTMI_PCTRL (0x1U << 15)
|
|
#define USB2_PHY_TEST_SRST_REQ (0x1U << 14)
|
|
#define USB2_UTMI_CKSEL (0x1U << 13)
|
|
#define USB2_UTMI_CKEN (0x1U << 12)
|
|
#define USB2_REF_CKEN (0x1U << 9)
|
|
#define USB2_BUS_CKEN (0x1U << 8)
|
|
#define USB2_VCC_SRST_REQ (0x1U << 3)
|
|
#define USB2_PHY_CKEN (0x1U << 2)
|
|
#define USB2_PHY_PORT_TREQ (0x1U << 1)
|
|
#define USB2_PHY_REQ (0x1U << 0)
|
|
|
|
#define REG_GUSB3PIPECTL0 0xC2C0
|
|
#define PCS_SSP_SOFT_RESET (0x1U << 31)
|
|
#define PORT_DISABLE_SUSPEND (0x1U << 17)
|
|
|
|
#define REG_GCTL 0xC110
|
|
#define PORT_CAP_DIR (0x3U << 12)
|
|
#define PORT_SET_HOST (0x1U << 12)
|
|
#define PORT_SET_DEVICE (0x1U << 13)
|
|
|
|
#define GTXTHRCFG 0xC108
|
|
#define USB2_G_TXTHRCFG IO_DEVICE_ADDR(0x23100000)
|
|
|
|
#define GRXTHRCFG 0xC10C
|
|
#define USB2_G_RXTHRCFG IO_DEVICE_ADDR(0x23100000)
|
|
|
|
#define USB2_INNO_PHY_BASE_REG IO_DEVICE_ADDR(0x10110000)
|
|
#define USB2_PHY_CLK_OUTPUT_REG 0x18
|
|
#define USB2_PHY_CLK_OUTPUT_VAL 0x0C
|
|
|
|
#define USB2_VBUS_IO_BASE_REG IO_DEVICE_ADDR(0x10FF0000)
|
|
#define USB2_VBUS_IO_OFFSET 0x40
|
|
#define USB2_VBUS_IO_VAL 0x431
|
|
|
|
#define HS_HIGH_HEIGHT_TUNING_OFFSET 0x8
|
|
#define HS_HIGH_HEIGHT_TUNING_MASK (0x7U << 4)
|
|
#define HS_HIGH_HEIGHT_TUNING_VAL (0x5U << 4)
|
|
|
|
#define PRE_EMPHASIS_TUNING_OFFSET 0x0
|
|
#define PRE_EMPHASIS_TUNING_MASK (0x7U << 0)
|
|
#define PRE_EMPHASIS_TUNING_VAL (0x7U << 0)
|
|
|
|
#define PRE_EMPHASIS_STRENGTH_OFFSET 0x14
|
|
#define PRE_EMPHASIS_STRENGTH_MASK (0x7U << 2)
|
|
#define PRE_EMPHASIS_STRENGTH_VAL (0x3U << 2)
|
|
|
|
#define HS_SLEW_RATE_TUNING_OFFSET 0x74
|
|
#define HS_SLEW_RATE_TUNING_MASK (0x7U << 1)
|
|
#define HS_SLEW_RATE_TUNING_VAL (0x7U << 1)
|
|
|
|
#define DISCONNECT_TRIGGER_OFFSET 0x10
|
|
#define DISCONNECT_TRIGGER_MASK (0xfU << 4)
|
|
#define DISCONNECT_TRIGGER_VAL (0xdU << 4)
|
|
|
|
STATIC BOOL g_otgUsbdevStat = FALSE;
|
|
STATIC Atomic g_devOpenCnt = 0;
|
|
|
|
STATIC VOID OpenUtmi(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
/* open utmi pctrl */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_UTMI_PCTRL;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
|
|
/* open utmi cksel */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_UTMI_CKSEL;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
|
|
/* open utmi cken */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_UTMI_CKEN;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
}
|
|
|
|
STATIC VOID CancelReset(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
/* cancel POR reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_PHY_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
|
|
/* cancel TPOR reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_PHY_PORT_TREQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
|
|
/* cancel vcc reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_VCC_SRST_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
}
|
|
|
|
STATIC VOID Usb2ControllerConfig(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
reg = GET_UINT32(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
|
reg |= PCS_SSP_SOFT_RESET;
|
|
WRITE_UINT32(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
|
|
reg = GET_UINT32(USB3_CTRL_REG_BASE + REG_GCTL);
|
|
reg &= ~PORT_CAP_DIR;
|
|
reg |= PORT_SET_HOST; /* [13:12] 01: Host; 10: Device; 11: OTG */
|
|
WRITE_UINT32(reg, USB3_CTRL_REG_BASE + REG_GCTL);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
|
|
reg = GET_UINT32(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
|
reg &= ~PCS_SSP_SOFT_RESET;
|
|
reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
|
|
WRITE_UINT32(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
|
|
WRITE_UINT32(USB2_G_TXTHRCFG, USB3_CTRL_REG_BASE + GTXTHRCFG);
|
|
WRITE_UINT32(USB2_G_RXTHRCFG, USB3_CTRL_REG_BASE + GRXTHRCFG);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
}
|
|
|
|
VOID Usb2EyeConfig(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
/* HS eye height tuning */
|
|
reg = GET_UINT32(USB2_INNO_PHY_BASE_REG + HS_HIGH_HEIGHT_TUNING_OFFSET);
|
|
reg &= ~HS_HIGH_HEIGHT_TUNING_MASK;
|
|
reg |= HS_HIGH_HEIGHT_TUNING_VAL;
|
|
WRITE_UINT32(reg, USB2_INNO_PHY_BASE_REG + HS_HIGH_HEIGHT_TUNING_OFFSET);
|
|
|
|
/* Pre-emphasis tuning */
|
|
reg = GET_UINT32(USB2_INNO_PHY_BASE_REG + PRE_EMPHASIS_TUNING_OFFSET);
|
|
reg &= ~PRE_EMPHASIS_TUNING_MASK;
|
|
reg |= PRE_EMPHASIS_TUNING_VAL;
|
|
WRITE_UINT32(reg, USB2_INNO_PHY_BASE_REG + PRE_EMPHASIS_TUNING_OFFSET);
|
|
|
|
/* Pre-emphasis strength */
|
|
reg = GET_UINT32(USB2_INNO_PHY_BASE_REG + PRE_EMPHASIS_STRENGTH_OFFSET);
|
|
reg &= ~PRE_EMPHASIS_STRENGTH_MASK;
|
|
reg |= PRE_EMPHASIS_STRENGTH_VAL;
|
|
WRITE_UINT32(reg, USB2_INNO_PHY_BASE_REG + PRE_EMPHASIS_STRENGTH_OFFSET);
|
|
|
|
/* HS driver slew rate tunning */
|
|
reg = GET_UINT32(USB2_INNO_PHY_BASE_REG + HS_SLEW_RATE_TUNING_OFFSET);
|
|
reg &= ~HS_SLEW_RATE_TUNING_MASK;
|
|
reg |= HS_SLEW_RATE_TUNING_VAL;
|
|
WRITE_UINT32(reg, USB2_INNO_PHY_BASE_REG + HS_SLEW_RATE_TUNING_OFFSET);
|
|
|
|
/* HOST disconnects detection trigger point */
|
|
reg = GET_UINT32(USB2_INNO_PHY_BASE_REG + DISCONNECT_TRIGGER_OFFSET);
|
|
reg &= ~DISCONNECT_TRIGGER_MASK;
|
|
reg |= DISCONNECT_TRIGGER_VAL;
|
|
WRITE_UINT32(reg, USB2_INNO_PHY_BASE_REG + DISCONNECT_TRIGGER_OFFSET);
|
|
}
|
|
|
|
STATIC VOID HisiUsb3PhyPowerOn(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
if (LOS_AtomicIncRet(&g_devOpenCnt) == 1) {
|
|
/* usb phy reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_PHY_TEST_SRST_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(100); /* Delay 100us */
|
|
|
|
/* cancel usb phy srst */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg &= ~USB2_PHY_TEST_SRST_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
|
|
/* usb2 vcc reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_VCC_SRST_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
|
|
/* set inno phy output clock */
|
|
WRITE_UINT32(USB2_PHY_CLK_OUTPUT_VAL, USB2_INNO_PHY_BASE_REG +
|
|
USB2_PHY_CLK_OUTPUT_REG);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
|
|
/* open phy ref cken */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_PHY_CKEN;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
|
|
/* open utmi */
|
|
OpenUtmi();
|
|
|
|
/* open controller ref cken */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_REF_CKEN;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(10); /* Delay 10us */
|
|
|
|
/* open bus cken */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_BUS_CKEN;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
|
|
/* cancel reset */
|
|
CancelReset();
|
|
|
|
/* usb2 test vbus using gpio */
|
|
WRITE_UINT32(USB2_VBUS_IO_VAL, USB2_VBUS_IO_BASE_REG + USB2_VBUS_IO_OFFSET);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
|
|
/* USB2 Controller configs */
|
|
Usb2ControllerConfig();
|
|
|
|
/* USB2 eye config */
|
|
Usb2EyeConfig();
|
|
}
|
|
}
|
|
|
|
STATIC VOID HisiUsb3PhyPowerOff(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
if (LOS_AtomicDecRet(&g_devOpenCnt) == 0) {
|
|
/* usb2 vcc reset */
|
|
reg = GET_UINT32(CRG_REG_BASE + REG_USB2_CTRL);
|
|
reg |= USB2_VCC_SRST_REQ;
|
|
WRITE_UINT32(reg, CRG_REG_BASE + REG_USB2_CTRL);
|
|
LOS_Udelay(200); /* Delay 200us */
|
|
}
|
|
}
|
|
|
|
VOID HiUsb3StartHcd(VOID)
|
|
{
|
|
HisiUsb3PhyPowerOn();
|
|
}
|
|
VOID HiUsb3StopHcd(VOID)
|
|
{
|
|
HisiUsb3PhyPowerOff();
|
|
}
|
|
|
|
VOID HiUsb3Host2Device(VOID)
|
|
{
|
|
UINT32 reg;
|
|
|
|
reg = GET_UINT32(USB3_CTRL_REG_BASE + REG_GCTL);
|
|
reg &= ~PORT_CAP_DIR;
|
|
reg |= PORT_SET_DEVICE; /* [13:12] 01: Host; 10: Device; 11: OTG */
|
|
WRITE_UINT32(reg, USB3_CTRL_REG_BASE + REG_GCTL);
|
|
LOS_Udelay(20); /* Delay 20us */
|
|
}
|
|
|
|
BOOL HiUsbIsDeviceMode(VOID)
|
|
{
|
|
return g_otgUsbdevStat;
|
|
}
|
|
|
|
VOID UsbOtgSwSetDeviceState(VOID)
|
|
{
|
|
g_otgUsbdevStat = TRUE;
|
|
}
|
|
|
|
VOID UsbOtgSwClearDeviceState(VOID)
|
|
{
|
|
g_otgUsbdevStat = FALSE;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|