GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
|
||||
menuconfig LOTUS_USB
|
||||
bool "LOTUS USB support"
|
||||
default y
|
||||
select CMD_USB
|
||||
select USB
|
||||
help
|
||||
LOTUS USB support.
|
||||
|
||||
if LOTUS_USB
|
||||
config USB_PWREN_OFF_DELAY
|
||||
int "usb port power off delay(ms)"
|
||||
default 100
|
||||
help
|
||||
Some usb device can't be recognize in U-boot because of error state, so
|
||||
we power off them and wait a delay to restart them, we call the delay
|
||||
as USB_PWREN_OFF_DELAY.
|
||||
|
||||
config USB_DUAL_PORT_SUPPORT
|
||||
bool "support dual-usb-port(U2 & U3) in host mode"
|
||||
default n
|
||||
help
|
||||
Some lotus chips support 2 usb host ports, contains U2 and U3. If your
|
||||
chip support 2 ports, enable this config could recognize U3 and U2 dev
|
||||
meanwhile, but cause to U3 couldn't be recognized sometimes.
|
||||
endif
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
obj-y += phy/
|
||||
|
||||
ccflags-y += -I$(srctree)/cmd
|
||||
|
||||
obj-$(CONFIG_USB_GADGET)+= udc3/
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_TARGET_XMFALCON) += phy-xmfalcon-usb.o
|
||||
obj-$(CONFIG_TARGET_XMORCA) += phy-xmorca-usb.o
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef PHY_LOTUS_USB
|
||||
#define PHY_LOTUS_USB
|
||||
|
||||
#define U_LEVEL1 10
|
||||
#define U_LEVEL2 20
|
||||
#define U_LEVEL3 30
|
||||
#define U_LEVEL4 50
|
||||
#define U_LEVEL5 100
|
||||
#define U_LEVEL6 200
|
||||
#define U_LEVEL7 300
|
||||
#define U_LEVEL8 500
|
||||
#define U_LEVEL9 1000
|
||||
#define U_LEVEL10 2000
|
||||
|
||||
enum usb_phy_width_mode {
|
||||
PHY_WIDTH_8BIT = 0,
|
||||
PHY_WIDTH_16BIT,
|
||||
};
|
||||
|
||||
enum usb_scenes {
|
||||
/* U3 CTRL connect U3/U2 PHY */
|
||||
LOTUS_USB_SCENE2 = 0,
|
||||
/* U3 CTRL connect U3 PHY, U2 CTRL connect U2 PHY */
|
||||
LOTUS_USB_SCENE1 = 1,
|
||||
};
|
||||
|
||||
#endif // PHY_LOTUS_USB
|
||||
@@ -0,0 +1,699 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
#include <asm/arch/platform.h>
|
||||
#include <dm.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
#include <usb.h>
|
||||
#include <usb/xhci.h>
|
||||
#include <linux/lotus/chip.h>
|
||||
|
||||
#include "phy-usb.h"
|
||||
|
||||
#ifdef __USB_DEBUG
|
||||
#define USB_DEBUG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define USB_DEBUG(...)
|
||||
#endif
|
||||
|
||||
/* CRG PERI_CRG80: usb clk & reset, offset 0x140 */
|
||||
#define USB2_CTRL 0x140
|
||||
#define OUTER_PHY_CRG_DEF_VAL 0x130d
|
||||
#define LOTUS_PHY_CRG_DEF_VAL 0x3130d
|
||||
#define LOTUS_PHY_REF_CKEN (0x1 << 17)
|
||||
#define LOTUS_PHY_APB_CKEN (0x1 << 16)
|
||||
#define USB2_UTMI_CKEN (0x1 << 12)
|
||||
#define USB2_PHY_APB_CKEN (0x1 << 11)
|
||||
#define USB2_REF_CKEN (0x1 << 9)
|
||||
#define USB2_BUS_CKEN (0x1 << 8)
|
||||
#define USB2_PHY_PLL_CKEN (0x1 << 4)
|
||||
#define USB2_PHY_XTAL_CKEN (0x1 << 2)
|
||||
#define USB2_FREECLK_CKSEL (0x1 << 13)
|
||||
#define USB2_PHY_APB_RST (0x1 << 10)
|
||||
#define USB2_VCC_SRST_REQ (0x1 << 3)
|
||||
#define USB2_PHY_REQ (0x1 << 0)
|
||||
#define USB2_PHY_PORT_TREQ (0x1 << 1)
|
||||
|
||||
#define USB3_CTRL 0x13c
|
||||
#define USB3_PHY_SRST (0x1 << 8)
|
||||
#define USB3_PHY_XTAL_CKEN (0x1 << 7)
|
||||
#define USB3_VCC_SRST (0x1 << 6)
|
||||
#define USB3_PIPE3_RX_CKEN (0x1 << 5)
|
||||
#define USB3_PIPE3_TX_CKEN (0x1 << 4)
|
||||
#define USB3_UTMI_CKEN (0x1 << 3)
|
||||
#define USB3_SUSPEND_CKEN (0x1 << 2)
|
||||
#define USB3_REF_CKEN (0x1 << 1)
|
||||
#define USB3_BUS_CKEN (0x1 << 0)
|
||||
|
||||
#define GTXTHRCFG 0xc108
|
||||
#define GRXTHRCFG 0xc10c
|
||||
#define REG_GCTL 0xc110
|
||||
#define GUSB2PHYCFG 0xc200
|
||||
#define REG_GUSB3PIPECTL0 0xc2c0
|
||||
#define PCS_SSP_SOFT_RESET (0x1 << 31)
|
||||
#define USBTRDTIM_MASK 0x00003c00
|
||||
#define USBTRDTIM_16BIT (0x5 << 10)
|
||||
#define USBTRDTIM_8BIT (0x9 << 10)
|
||||
#define PHYIF (0x1 << 3)
|
||||
#define SUSPENDUSB20 (0x1 << 6)
|
||||
#define ENBLSLPM (0x1 << 8)
|
||||
#define LSIPD_MASK (0x7 << 19)
|
||||
#define LSIPD_3_BIT (0x2 << 19)
|
||||
#define U2_FREECLK_EXISTS (0x1 << 30)
|
||||
|
||||
#define PORT_CAP_DIR (0x3 << 12)
|
||||
#define PORT_SET_HOST (0x1 << 12)
|
||||
#define PORT_DISABLE_SUSPEND (0x1 << 17)
|
||||
|
||||
#define USB2_G_TXTHRCFG 0x23100000
|
||||
#define USB2_G_RXTHRCFG 0x23100000
|
||||
|
||||
/* Lotus phy use reg, reg's misc_base=0x12028000 */
|
||||
#define MISC_LOTUS_PHY2_CTRL_REG 0x28
|
||||
#define MISC_USB_SEL_SCENE1 (0x0 << 0)
|
||||
#define MISC_USB_SEL_SCENE2 (0x1 << 0)
|
||||
#define MISC_USB_SCENE_MASK (0x1 << 0)
|
||||
#define USB2_UTMI_REG_PROTECT1 (0x1 << 8)
|
||||
#define USB2_UTMI_REG_PROTECT2 (0x1 << 9)
|
||||
#define USB2_UTMI_REG_PROTECT3 (0x1 << 10)
|
||||
#define USB2_HW_CHIRP (0x1 << 14)
|
||||
#define USB2_UTMI_IDPULLUP (0x1 << 15)
|
||||
|
||||
/* Outer phy use reg, reg's misc_base=0x12028000 */
|
||||
#define MISC_OUT_PHY2_CTRL_REG 0x2C
|
||||
#define USB2_OSCOUTEN (0x1 << 8)
|
||||
#define USB2_PLL_EN (0x1 << 12)
|
||||
#define USB2_UTMI_DATABUS16_8 (0x1 << 16)
|
||||
#define MISC_OUT_PHY2_XCFGI_63TO32 0x988
|
||||
#define CFG_OUT_PHY2_EYE_VAL (0x1 << 5)
|
||||
|
||||
/* reg base(misc_base): 0x12028000 */
|
||||
#define MISC_USB2_CTRL_REG 0x24
|
||||
#define U2_BUS_FILTER_BYPASS (0xf << 0)
|
||||
#define U2_PWREN_MODE_MASK (0x1 << 4)
|
||||
#define U2_PWREN_MODE_MISC (0x0 << 4)
|
||||
#define U2_PWREN_MODE_CTRL (0x1 << 4)
|
||||
#define U2_OVERCURR_MODE_MASK (0x1 << 5)
|
||||
#define U2_OVERCURR_MODE_DISABLE (0x0 << 5)
|
||||
#define U2_OVERCURR_MODE_ENABLE (0x1 << 5)
|
||||
#define U2_PWREN_MASK (0x1 << 6)
|
||||
#define U2_PWREN_ON (0x0 << 6)
|
||||
#define U2_PWREN_OFF (0x1 << 6)
|
||||
#define U2_OVERCURR_MASK (0x1 << 7)
|
||||
#define U2_OVERCURR_ON (0x0 << 7)
|
||||
#define U2_OVERCURR_OFF (0x1 << 7)
|
||||
#define U2_FLADJ_30MHZ (0x20 << 13)
|
||||
|
||||
#define MISC_USB3_CTRL_REG 0x1110
|
||||
#define U3_BUS_FILTER_BYPASS (0xf << 0)
|
||||
#define U3_FLADJ_30MHZ (0x20 << 4)
|
||||
#define U3_PWREN_MODE_MASK (0x1 << 11)
|
||||
#define U3_PWREN_MODE_MISC (0x0 << 11)
|
||||
#define U3_PWREN_MODE_CTRL (0x1 << 11)
|
||||
#define U3_OVERCURR_MODE_MASK (0x1 << 12)
|
||||
#define U3_OVERCURR_MODE_DISABLE (0x0 << 12)
|
||||
#define U3_OVERCURR_MODE_ENABLE (0x1 << 12)
|
||||
#define U3_PWREN_MASK (0x1 << 13)
|
||||
#define U3_PWREN_ON (0x0 << 13)
|
||||
#define U3_PWREN_OFF (0x1 << 13)
|
||||
#define U3_OVERCURR_MASK (0x1 << 14)
|
||||
#define U3_OVERCURR_ON (0x0 << 14)
|
||||
#define U3_OVERCURR_OFF (0x1 << 14)
|
||||
#define HOST_U2_PORT_MASK (0xf << 20)
|
||||
#define HOST_U2_PORT(n) (n << 20)
|
||||
#define HOST_U3_PORT_MASK (0xf << 24)
|
||||
#define HOST_U3_PORT(n) (n << 24)
|
||||
#define USB2_HOST_VBUS_EN (0x1 << 30)
|
||||
#define USB3_HOST_VBUS_EN (0x1 << 31)
|
||||
|
||||
#define MISC_USB3_PHY_REG 0x112c
|
||||
|
||||
/* SYSBOOT1[2:2]: usb scene select */
|
||||
#define SYSBOOT1 0x12020134
|
||||
#define SYSBOOT1_SEL_USB_SCENE_MASK (1 << 2)
|
||||
|
||||
static uintptr_t xhci_base;
|
||||
|
||||
/**
|
||||
* lotus_chip_u3_ability - whether current chip support u3.
|
||||
*
|
||||
* @return:
|
||||
* 1: support u3.
|
||||
* 0: only support u2.
|
||||
*/
|
||||
static int lotus_chip_u3_ability(void)
|
||||
{
|
||||
u32 id = get_chipid();
|
||||
|
||||
USB_DEBUG("%s: chid id 0x%x\n", __func__, id);
|
||||
|
||||
if (id == 0x76050110 || id == 0x06050110)
|
||||
return 0;
|
||||
|
||||
/* if id == 0, consider chip support U3. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
|
||||
{
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(MISC_REG_BASE + MISC_LOTUS_PHY2_CTRL_REG);
|
||||
reg &= MISC_USB_SCENE_MASK;
|
||||
|
||||
if (index >= LOTUS_USB_CTRL_UNKNOWN)
|
||||
return -ENODEV;
|
||||
/* 7605v11 only support u2 host */
|
||||
if (!lotus_chip_u3_ability() && index == LOTUS_DWC_U3)
|
||||
return -ENODEV;
|
||||
|
||||
/* Scene2 don't init U2 host. */
|
||||
if (index == LOTUS_DWC_U2 && reg)
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
if ((hccr == NULL) || (hcor == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
if (index == LOTUS_DWC_U3)
|
||||
xhci_base = USB3_CTRL_REG_BASE;
|
||||
else if (index == LOTUS_DWC_U2)
|
||||
xhci_base = USB2_CTRL_REG_BASE;
|
||||
#else
|
||||
/* single usb port, U3 is default */
|
||||
if (index == LOTUS_DWC_U3) {
|
||||
/* 7605v11 only support U2 host */
|
||||
if (!lotus_chip_u3_ability())
|
||||
xhci_base = USB2_CTRL_REG_BASE;
|
||||
else
|
||||
xhci_base = USB3_CTRL_REG_BASE;
|
||||
} else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
*hccr = (struct xhci_hccr *)(xhci_base);
|
||||
*hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
|
||||
HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
|
||||
|
||||
USB_DEBUG("hccr:0x%x, hcor:0x%x.\n", (unsigned int)*hccr, (unsigned int)*hcor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get usb scene from SYSBOOT1 and config to MISC
|
||||
* usb_scene: 0-scene1, 1-scene2.
|
||||
* scene1:U3 only + U2.
|
||||
* scene2:U3(compatible to U2).
|
||||
*/
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
static void usb_scene_select(int index, int type)
|
||||
#else
|
||||
static void usb_scene_select(int index)
|
||||
#endif
|
||||
{
|
||||
unsigned int reg, usb_scene = LOTUS_USB_SCENE2;
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
reg = readl(SYSBOOT1);
|
||||
if (reg & SYSBOOT1_SEL_USB_SCENE_MASK)
|
||||
usb_scene = LOTUS_USB_SCENE1;
|
||||
|
||||
/* used by usb download */
|
||||
if (index == LOTUS_DWC_U2 && type == USB_INIT_DEVICE)
|
||||
usb_scene = LOTUS_USB_SCENE1;
|
||||
#else
|
||||
/* used by usb download */
|
||||
if ((index == LOTUS_DWC_U2) ||
|
||||
(index == LOTUS_DWC_U3 && !lotus_chip_u3_ability()))
|
||||
usb_scene = LOTUS_USB_SCENE1;
|
||||
#endif
|
||||
|
||||
reg = 0;
|
||||
if (usb_scene == LOTUS_USB_SCENE1) {
|
||||
/* u3 ctrl connect u3 phy, u2 ctrl connect u2 phy */
|
||||
reg |= MISC_USB_SEL_SCENE1;
|
||||
printf("%s:select U3 only + U2.\n", __func__);
|
||||
} else if (usb_scene == LOTUS_USB_SCENE2) {
|
||||
/* u3 ctrl connect u3 phy and u2 phy */
|
||||
reg |= MISC_USB_SEL_SCENE2;
|
||||
printf("%s:select U3(compatible to U2).\n", __func__);
|
||||
}
|
||||
writel(reg, MISC_REG_BASE + MISC_LOTUS_PHY2_CTRL_REG);
|
||||
|
||||
USB_DEBUG("MISC_LOTUS_PHY2_CTRL_REG(0x12028028):0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_LOTUS_PHY2_CTRL_REG));
|
||||
}
|
||||
|
||||
static void lotus_u2_phy_eye_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* outer phy eye diagram config */
|
||||
reg = readl(MISC_REG_BASE + MISC_OUT_PHY2_XCFGI_63TO32);
|
||||
reg |= CFG_OUT_PHY2_EYE_VAL;
|
||||
writel(reg, MISC_REG_BASE + MISC_OUT_PHY2_XCFGI_63TO32);
|
||||
}
|
||||
|
||||
static void lotus_dwc_data_width_config(int index,
|
||||
enum usb_phy_width_mode mode)
|
||||
{
|
||||
unsigned int reg, base = 0;
|
||||
|
||||
/* GUSB2PHYCFG register: config val 0x40001548(HS/FS) or
|
||||
* 0x00381548(LS) according to IC.
|
||||
*
|
||||
* USBTRDTIM: USB 2.0 Turnaround Time in PHY clocks.
|
||||
* PHYIF: 1 UTMI+ PHY is 16-bit, 0 UTMI+ PHY is 8-bit.
|
||||
*/
|
||||
reg = 0;
|
||||
switch (mode) {
|
||||
case PHY_WIDTH_8BIT:
|
||||
/* 8-bits usb phy configure */
|
||||
reg |= USBTRDTIM_8BIT;
|
||||
reg &= ~PHYIF;
|
||||
break;
|
||||
case PHY_WIDTH_16BIT:
|
||||
/* 16-bits usb phy configure */
|
||||
reg |= (USBTRDTIM_16BIT | PHYIF);
|
||||
break;
|
||||
default:
|
||||
printf("usb phy width config val error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
if (index == LOTUS_DWC_U3)
|
||||
base = USB3_CTRL_REG_BASE;
|
||||
else
|
||||
base = USB2_CTRL_REG_BASE;
|
||||
#else
|
||||
if (index == LOTUS_DWC_U3 && lotus_chip_u3_ability())
|
||||
base = USB3_CTRL_REG_BASE;
|
||||
else
|
||||
base = USB2_CTRL_REG_BASE;
|
||||
#endif
|
||||
writel(reg, base + GUSB2PHYCFG);
|
||||
}
|
||||
|
||||
static inline void lotus_usb2_vbus_valid_en(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable U2 vbus valid */
|
||||
reg = readl(MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
reg |= USB2_HOST_VBUS_EN;
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
}
|
||||
|
||||
static inline void lotus_usb3_vbus_valid_en(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable U3 vbus valid */
|
||||
reg = readl(MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
reg |= USB3_HOST_VBUS_EN;
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
}
|
||||
|
||||
static void lotus_u2_phy_clk_init(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable u2 phy clk and do reset */
|
||||
reg = (USB2_PHY_REQ | USB2_PHY_XTAL_CKEN);
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* undo phy reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x4,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_u2_ctrl_clk_init(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable u2 ctrl clk and do reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= (USB2_VCC_SRST_REQ | USB2_BUS_CKEN | USB2_REF_CKEN |
|
||||
USB2_UTMI_CKEN);
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* undo ctrl vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
}
|
||||
|
||||
static void inline lotus_usb2_clk_init(void)
|
||||
{
|
||||
/* write CRG default value 0x130d, including:
|
||||
*
|
||||
* USB2_PHY_REQ: reset PHY UTMI
|
||||
* USB2_PHY_XTAL_CKEN: open phy xtal clk
|
||||
* USB2_VCC_SRST_REQ: reset ctrl VCC
|
||||
* USB2_BUS_CKEN: open bus clk
|
||||
* USB2_REF_CKEN: open ctrl ref clk
|
||||
* USB2_UTMI_CKEN: open UTMI clk
|
||||
* LOTUS_PHY_APB_CKEN: open LOTUS phy apb clk
|
||||
* USB2_UTMI_CKEN: open LOTUS phy ref clk
|
||||
*/
|
||||
lotus_u2_phy_clk_init();
|
||||
lotus_u2_ctrl_clk_init();
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x1304,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
}
|
||||
|
||||
static void inline lotus_usb2_clk_exit(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* disable usb2 clk and do reset */
|
||||
reg = 0;
|
||||
reg |= (USB2_VCC_SRST_REQ | USB2_PHY_REQ);
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x9,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_usb3_clk_init(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* write CRG default value 0x1ff, including:
|
||||
*
|
||||
* USB3_PHY_SRST: reset U3 PHY UTMI
|
||||
* USB3_PHY_XTAL_CKEN: open U3 phy xtal clk
|
||||
* USB3_VCC_SRST: reset U3 ctrl VCC
|
||||
* USB3_PIPE3_RX_CKEN: open PIPE3 RX clk
|
||||
* USB3_PIPE3_TX_CKEN: open PIPE3 TX clk
|
||||
* USB3_UTMI_CKEN: open UTMI clk
|
||||
* USB3_SUSPEND_CKEN: open U3 ctrl suspend clk
|
||||
* USB3_REF_CKEN: open U3 ctrl ref clk
|
||||
* USB3_BUS_CKEN: open U3 ctrl bus clk
|
||||
*/
|
||||
|
||||
reg = 0;
|
||||
reg |= (USB3_PHY_SRST | USB3_PHY_XTAL_CKEN | USB3_VCC_SRST |
|
||||
USB3_PIPE3_RX_CKEN | USB3_PIPE3_TX_CKEN | USB3_UTMI_CKEN |
|
||||
USB3_SUSPEND_CKEN | USB3_REF_CKEN | USB3_BUS_CKEN);
|
||||
writel(reg, CRG_REG_BASE + USB3_CTRL);
|
||||
USB_DEBUG("USB3_CRG(0x1201013c), expext:0x1ff,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB3_CTRL));
|
||||
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* undo usb phy and ctrl reset */
|
||||
reg = readl(CRG_REG_BASE + USB3_CTRL);
|
||||
reg &= ~USB3_PHY_SRST;
|
||||
reg &= ~USB3_VCC_SRST;
|
||||
writel(reg, CRG_REG_BASE + USB3_CTRL);
|
||||
USB_DEBUG("USB3_CRG(0x1201013c), expext:0xbf,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB3_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_usb3_clk_exit(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* disable usb3 clk and do reset */
|
||||
reg = 0;
|
||||
reg |= (USB3_PHY_SRST | USB3_VCC_SRST);
|
||||
writel(reg, CRG_REG_BASE + USB3_CTRL);
|
||||
USB_DEBUG("USB3_CRG(0x1201013c), expext:0x140,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB3_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_u2_phy_misc_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* MISC_OUT_PHY2_CTRL: config 0x11100 according to IC. */
|
||||
reg = 0;
|
||||
reg |= (USB2_OSCOUTEN | USB2_PLL_EN | USB2_UTMI_DATABUS16_8);
|
||||
writel(reg, MISC_REG_BASE + MISC_OUT_PHY2_CTRL_REG);
|
||||
USB_DEBUG("MISC_OUT_PHY2_CTRL_REG(0x1202802c),"
|
||||
"expext:0x11100, acutal:0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_OUT_PHY2_CTRL_REG));
|
||||
}
|
||||
|
||||
static void lotus_u2_ctrl_misc_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* MISC_USB2_CTRL_REG: config 0x400ff according to IC. */
|
||||
reg = 0;
|
||||
reg |= (U2_BUS_FILTER_BYPASS | U2_PWREN_MODE_CTRL | U2_OVERCURR_MODE_ENABLE |\
|
||||
U2_PWREN_OFF | U2_OVERCURR_OFF | U2_FLADJ_30MHZ);
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
USB_DEBUG("MISC_USB2_CTRL_REG(0x12028024),"
|
||||
"expext:0x400ff, acutal:0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB2_CTRL_REG));
|
||||
}
|
||||
|
||||
static void lotus_u3_ctrl_misc_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* MISC_USB3_CTRL_REG: config 0xc1107a0f according to IC. */
|
||||
reg = 0;
|
||||
reg |= HOST_U3_PORT(1);
|
||||
reg |= HOST_U2_PORT(1);
|
||||
reg |= (U3_OVERCURR_OFF | U3_PWREN_OFF | U3_OVERCURR_MODE_ENABLE |\
|
||||
U3_PWREN_MODE_CTRL | U3_FLADJ_30MHZ | U3_BUS_FILTER_BYPASS);
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
USB_DEBUG("MISC_USB3_CTRL_REG(0x12029110), acutal:0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB3_CTRL_REG));
|
||||
}
|
||||
|
||||
/* config U3 phy inner reg, insure U3 phy CRG already open. */
|
||||
static void lotus_u3_phy_misc_config(void)
|
||||
{
|
||||
/* adjust pi_current_trim */
|
||||
writel(0x11, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1); /* asic say delay 10ns, we delay 1us */
|
||||
writel(0x4211, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1);
|
||||
writel(0x11, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1);
|
||||
|
||||
/* close slew_assist_dis */
|
||||
writel(0x2, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1);
|
||||
writel(0x100202, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1);
|
||||
writel(0x2, MISC_REG_BASE + MISC_USB3_PHY_REG);
|
||||
udelay(1);
|
||||
USB_DEBUG("MISC_USB3_PHY_REG(0x1202912c):0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB3_PHY_REG));
|
||||
}
|
||||
|
||||
static void lotus_dwc_usb_config(int index)
|
||||
{
|
||||
unsigned int reg, base = 0;
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
if (index == LOTUS_DWC_U2)
|
||||
base = USB2_CTRL_REG_BASE;
|
||||
else
|
||||
base = USB3_CTRL_REG_BASE;
|
||||
#else
|
||||
if (index == LOTUS_DWC_U2 ||
|
||||
(index == LOTUS_DWC_U3 && !lotus_chip_u3_ability())) {
|
||||
/* USB2 Controller configs */
|
||||
base = USB2_CTRL_REG_BASE;
|
||||
}
|
||||
|
||||
if ((index == LOTUS_DWC_U3 && lotus_chip_u3_ability())) {
|
||||
/* USB3 Controller configs */
|
||||
base = USB3_CTRL_REG_BASE;
|
||||
}
|
||||
#endif
|
||||
|
||||
reg = readl(base + REG_GUSB3PIPECTL0);
|
||||
reg |= PCS_SSP_SOFT_RESET;
|
||||
writel(reg, base + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(base + REG_GCTL);
|
||||
reg &= ~PORT_CAP_DIR;
|
||||
reg |= PORT_SET_HOST; /* [13:12] 01: Host; 10: Device; 11: OTG */
|
||||
writel(reg, base + REG_GCTL);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(base + REG_GUSB3PIPECTL0);
|
||||
reg &= ~PCS_SSP_SOFT_RESET;
|
||||
reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
|
||||
writel(reg, base + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
writel(USB2_G_TXTHRCFG, base + GTXTHRCFG);
|
||||
writel(USB2_G_RXTHRCFG, base + GRXTHRCFG);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
lotus_dwc_data_width_config(index, PHY_WIDTH_16BIT);
|
||||
|
||||
reg = readl(base + GUSB2PHYCFG);
|
||||
reg &= ~SUSPENDUSB20; /* disable suspend */
|
||||
reg &= ~ENBLSLPM; /* suspend not transfer to external PHY */
|
||||
reg &= ~U2_FREECLK_EXISTS;
|
||||
reg &= ~LSIPD_MASK;
|
||||
reg |= LSIPD_3_BIT;
|
||||
writel(reg, base + GUSB2PHYCFG);
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
if (index == LOTUS_DWC_U2) {
|
||||
#else
|
||||
if (index == LOTUS_DWC_U2 ||
|
||||
(index == LOTUS_DWC_U3 && !lotus_chip_u3_ability())) {
|
||||
#endif
|
||||
USB_DEBUG("U2 GUSB2PHYCFG(0xc200):0x%X\n",
|
||||
readl(base + GUSB2PHYCFG));
|
||||
USB_DEBUG("U2 GUSB3PIPECTL0(0xc2c0):0x%X\n",
|
||||
readl(base + REG_GUSB3PIPECTL0));
|
||||
USB_DEBUG("U2 GCTL(0xc110):0x%X\n",
|
||||
readl(base + REG_GCTL));
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
} else if (index == LOTUS_DWC_U3) {
|
||||
#else
|
||||
} else if ((index == LOTUS_DWC_U3 && lotus_chip_u3_ability())) {
|
||||
#endif
|
||||
USB_DEBUG("U3 GUSB2PHYCFG(0xc200):0x%X\n",
|
||||
readl(base + GUSB2PHYCFG));
|
||||
USB_DEBUG("U3 GUSB3PIPECTL0(0xc2c0):0x%X\n",
|
||||
readl(base + REG_GUSB3PIPECTL0));
|
||||
USB_DEBUG("U3 GCTL(0xc110):0x%X\n",
|
||||
readl(base + REG_GCTL));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
void phy_usb_init(int index, int type)
|
||||
#else
|
||||
void phy_usb_init(int index)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
unsigned int reg;
|
||||
|
||||
/* 7605v11 only support u2 host */
|
||||
if (!lotus_chip_u3_ability() && index == LOTUS_DWC_U3)
|
||||
return;
|
||||
usb_scene_select(index, type);
|
||||
#else
|
||||
usb_scene_select(index);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
reg = readl(MISC_REG_BASE + MISC_LOTUS_PHY2_CTRL_REG);
|
||||
reg &= MISC_USB_SCENE_MASK;
|
||||
|
||||
/* Scene2 don't init U2 host. */
|
||||
if (index == LOTUS_DWC_U2 && reg)
|
||||
return;
|
||||
|
||||
if (index == LOTUS_DWC_U3) {
|
||||
#else
|
||||
if (index == LOTUS_DWC_U3 && lotus_chip_u3_ability()) {
|
||||
#endif
|
||||
printf("USB3 init...\n");
|
||||
/* config u3 ctrl/u3 phy/u2 phy */
|
||||
lotus_u3_ctrl_misc_config();
|
||||
lotus_usb3_vbus_valid_en();
|
||||
lotus_u2_phy_misc_config();
|
||||
lotus_usb3_clk_init();
|
||||
lotus_u3_phy_misc_config();
|
||||
lotus_u2_phy_clk_init();
|
||||
lotus_dwc_usb_config(index);
|
||||
#ifdef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
} else if (index == LOTUS_DWC_U2) {
|
||||
#else
|
||||
} else if ((index == LOTUS_DWC_U2) ||
|
||||
(index == LOTUS_DWC_U3 && !lotus_chip_u3_ability())) {
|
||||
#endif
|
||||
printf("USB2 init...\n");
|
||||
/* config u2 ctrl and u2 phy */
|
||||
lotus_u2_ctrl_misc_config();
|
||||
lotus_usb2_vbus_valid_en();
|
||||
lotus_u2_phy_misc_config();
|
||||
lotus_usb2_clk_init();
|
||||
lotus_dwc_usb_config(index);
|
||||
/* u2 phy eye diagram config */
|
||||
lotus_u2_phy_eye_config();
|
||||
}
|
||||
/* According to IC, usb phy clk init need 1ms delay */
|
||||
mdelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL(phy_usb_init);
|
||||
|
||||
void xhci_hcd_stop(int index)
|
||||
{
|
||||
if (index == LOTUS_DWC_U3 && lotus_chip_u3_ability())
|
||||
lotus_usb3_clk_exit();
|
||||
else if ((index == LOTUS_DWC_U2) ||
|
||||
(index == LOTUS_DWC_U3 && !lotus_chip_u3_ability()))
|
||||
lotus_usb2_clk_exit();
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_hcd_stop);
|
||||
|
||||
/* Some usb device can't be recognize in U-boot because
|
||||
* of error state, so we power off them and wait a delay
|
||||
* to restart them, similar to unplug and then insert.
|
||||
*/
|
||||
void lotus_usb_pwren_control(void)
|
||||
{
|
||||
u32 reg, default_val;
|
||||
int delay __attribute__((unused));
|
||||
|
||||
#ifndef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
delay = CONFIG_USB_PWREN_OFF_DELAY ?
|
||||
CONFIG_USB_PWREN_OFF_DELAY : 100;
|
||||
#endif
|
||||
reg = readl(MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
default_val = reg;
|
||||
reg &= ~U2_PWREN_MODE_MASK; /* set PWREN_MISC mode */
|
||||
reg |= U2_PWREN_OFF; /* turn off PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
|
||||
#ifndef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
mdelay(delay);
|
||||
#endif
|
||||
|
||||
reg = readl(MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
reg &= ~U2_PWREN_MASK; /* turn on PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
|
||||
reg = default_val; /* set PWREN_CTRL mode(default val) */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
|
||||
/* U3 CTRL PWREN control */
|
||||
reg = readl(MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
default_val = reg;
|
||||
reg &= ~U3_PWREN_MODE_MASK;
|
||||
reg |= U3_PWREN_OFF; /* turn off PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
USB_DEBUG("U3 MISC GCTL(0x1110):0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB3_CTRL_REG));
|
||||
|
||||
#ifndef CONFIG_USB_DUAL_PORT_SUPPORT
|
||||
mdelay(delay);
|
||||
#endif
|
||||
|
||||
reg = readl(MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
reg &= ~U3_PWREN_MASK; /* turn on PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
USB_DEBUG("U3 MISC GCTL(0x1110):0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB3_CTRL_REG));
|
||||
|
||||
reg = default_val; /* set PWREN_CTRL mode(default val) */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB3_CTRL_REG);
|
||||
USB_DEBUG("U3 MISC GCTL(0x1110):0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_USB3_CTRL_REG));
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PHY_LOTUS_USB
|
||||
#include <asm/arch/platform.h>
|
||||
#include <dm.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
#include <usb/xhci.h>
|
||||
#include "phy-usb.h"
|
||||
|
||||
/* offset 0x140 */
|
||||
#define USB2_CTRL 0x140
|
||||
#define USB2_CRG_DEFAULT_VAL 0x3b2f
|
||||
#define USB2_UTMI_CKEN (0x1 << 12)
|
||||
#define USB2_PHY_APB_CKEN (0x1 << 11)
|
||||
#define USB2_REF_CKEN (0x1 << 9)
|
||||
#define USB2_BUS_CKEN (0x1 << 8)
|
||||
#define USB2_PHY_PLL_CKEN (0x1 << 4)
|
||||
#define USB2_PHY_XTAL_CKEN (0x1 << 2)
|
||||
#define USB2_FREECLK_CKSEL (0x1 << 13)
|
||||
#define USB2_PHY_APB_RST (0x1 << 10)
|
||||
#define USB2_VCC_SRST_REQ (0x1 << 3)
|
||||
#define USB2_PHY_REQ (0x1 << 0)
|
||||
#define USB2_PHY_PORT_TREQ (0x1 << 1)
|
||||
|
||||
#define GTXTHRCFG 0xc108
|
||||
#define GRXTHRCFG 0xc10c
|
||||
#define REG_GCTL 0xc110
|
||||
#define REG_GUSB3PIPECTL0 0xc2c0
|
||||
#define PCS_SSP_SOFT_RESET (0x1 << 31)
|
||||
|
||||
#define PORT_CAP_DIR (0x3 << 12)
|
||||
#define PORT_SET_HOST (0x1 << 12)
|
||||
#define PORT_DISABLE_SUSPEND (0x1 << 17)
|
||||
|
||||
#define USB2_G_TXTHRCFG 0x23100000
|
||||
#define USB2_G_RXTHRCFG 0x23100000
|
||||
|
||||
/* PHY base register */
|
||||
#define USB2_PHY_BASE_REG 0x100D0000
|
||||
#define RG_PLL_EN_MASK 0x0003
|
||||
#define RG_PLL_EN_VAL 0x0003
|
||||
#define PHY_PLL_OFFSET 0x0014
|
||||
|
||||
#define USB_VBUS_IO_CONFIG_REG 0x100c007C
|
||||
#define USB_VBUS_IO_CONFIG_VAL 0x0531
|
||||
|
||||
#define USB_PWREN_CONFIG_REG 0x100c0080
|
||||
#define USB_PWREN_CONFIG_VAL 0x1
|
||||
|
||||
/* PHY eye config */
|
||||
#define PHY_ANA_CFG_0_OFFSET 0x00
|
||||
#define PHY_PRE_DRIVE_MASK (0xf << 24)
|
||||
#define PHY_PRE_DRIVE_VAL (0x4 << 24)
|
||||
#define PHY_HSTX_DE_MASK (0xf << 8)
|
||||
#define PHY_HSTX_DE_VAL (0xc << 8)
|
||||
#define PHY_HSTX_DEEN_BIT (0x1 << 5)
|
||||
#define PHY_ANA_CFG_2_OFFSET 0x08
|
||||
#define PHY_TX_TEST_BIT (0x1 << 20)
|
||||
#define PHY_HALF_DEEM_BIT (0x1 << 21)
|
||||
#define PHY_DISCONNECT_REFERENCE_MASK (0x7 << 16)
|
||||
#define PHY_DISCONNECT_REFERENCE_VAL (0x2 << 16)
|
||||
#define PHY_ANA_CFG_4_OFFSET 0x10
|
||||
#define PHY_TX_REFERENCE_MASK (0x7 << 4)
|
||||
#define PHY_TX_REFERENCE_VAL (0x5 << 4)
|
||||
#define PHY_SQUELCH_REFERENCE_MASK (0x7 << 0)
|
||||
#define PHY_SQUELCH_REFERENCE_VAL (0x5 << 0)
|
||||
|
||||
/* PHY trim config */
|
||||
#define USB_TRIM_BASE_REG 0x12028004
|
||||
#define USB_TRIM_VAL_MASK 0x001F
|
||||
#define USB_TRIM_VAL_MIN 0x0009
|
||||
#define USB_TRIM_VAL_MAX 0x001D
|
||||
#define USB2_TRIM_OFFSET 0x0008
|
||||
#define USB2_TRIM_MASK 0x1f00
|
||||
#define usb2_trim_val(a) (((a) << 8) & USB2_TRIM_MASK)
|
||||
#define USB2_TRIM_DEFAULT_VAL 0x000F
|
||||
|
||||
static uintptr_t xhci_base = 0;
|
||||
|
||||
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
|
||||
{
|
||||
if ((hccr == NULL) || (hcor == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
xhci_base = USB3_CTRL_REG_BASE;
|
||||
|
||||
*hccr = (struct xhci_hccr *)(xhci_base);
|
||||
*hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
|
||||
HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb2_eye_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
/* HSTX pre-drive strength */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg &= ~PHY_PRE_DRIVE_MASK;
|
||||
reg |= PHY_PRE_DRIVE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* HSTX de-emphasis strength */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg &= ~PHY_HSTX_DE_MASK;
|
||||
reg |= PHY_HSTX_DE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* HSTX de-emphasis enable */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg |= PHY_HSTX_DEEN_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* TX test bit */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg |= PHY_TX_TEST_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* TX half de-emphasis bit */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg |= PHY_HALF_DEEM_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* Disconnect reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg &= ~PHY_DISCONNECT_REFERENCE_MASK;
|
||||
reg |= PHY_DISCONNECT_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* TX reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
reg &= ~PHY_TX_REFERENCE_MASK;
|
||||
reg |= PHY_TX_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
|
||||
/* Squlech reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
reg &= ~PHY_SQUELCH_REFERENCE_MASK;
|
||||
reg |= PHY_SQUELCH_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
}
|
||||
|
||||
void usb2_trim_config(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
unsigned int reg;
|
||||
unsigned int trim_val;
|
||||
|
||||
ret = readl(USB_TRIM_BASE_REG);
|
||||
trim_val = (ret & USB_TRIM_VAL_MASK); /* get usb trim value */
|
||||
reg = readl(USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
|
||||
reg &= ~USB2_TRIM_MASK;
|
||||
if ((trim_val >= USB_TRIM_VAL_MIN) && (trim_val <= USB_TRIM_VAL_MAX))
|
||||
reg |= usb2_trim_val(trim_val);
|
||||
else
|
||||
reg |= usb2_trim_val(USB2_TRIM_DEFAULT_VAL);
|
||||
|
||||
writel(reg, USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
|
||||
}
|
||||
|
||||
void phy_usb_init_crg_clk(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* set usb2 CRG default val */
|
||||
reg = USB2_CRG_DEFAULT_VAL;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* open UTMI clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_UTMI_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy apb clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_APB_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open ctrl ref clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_REF_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open bus clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_BUS_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy pll clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_PLL_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy xtal clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_XTAL_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* freeclk_cksel_free */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_FREECLK_CKSEL;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL5);
|
||||
}
|
||||
|
||||
void phy_usb_init(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* VBUS config */
|
||||
reg = USB_VBUS_IO_CONFIG_VAL;
|
||||
writel(reg, USB_VBUS_IO_CONFIG_REG);
|
||||
|
||||
reg = USB_PWREN_CONFIG_VAL;
|
||||
writel(reg, USB_PWREN_CONFIG_REG);
|
||||
|
||||
/* init crg and clk */
|
||||
phy_usb_init_crg_clk(index);
|
||||
|
||||
/* release phy apb */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_APB_RST;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL5);
|
||||
|
||||
/* por noreset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
|
||||
reg &= ~RG_PLL_EN_MASK;
|
||||
reg |= RG_PLL_EN_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
|
||||
|
||||
udelay(U_LEVEL10);
|
||||
|
||||
/* cancel TPOR */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_PORT_TREQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* USB2 Controller configs */
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
reg |= PCS_SSP_SOFT_RESET;
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GCTL);
|
||||
reg &= ~PORT_CAP_DIR;
|
||||
reg |= PORT_SET_HOST; /* [13:12] 01: Host; 10: Device; 11: OTG */
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GCTL);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
reg &= ~PCS_SSP_SOFT_RESET;
|
||||
reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
writel(USB2_G_TXTHRCFG, USB3_CTRL_REG_BASE + GTXTHRCFG);
|
||||
writel(USB2_G_RXTHRCFG, USB3_CTRL_REG_BASE + GRXTHRCFG);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
/* USB2 eye config */
|
||||
usb2_eye_config();
|
||||
|
||||
/* USB2 trim config */
|
||||
usb2_trim_config();
|
||||
}
|
||||
EXPORT_SYMBOL(phy_usb_init);
|
||||
|
||||
void xhci_hcd_stop(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* por noreset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL10);
|
||||
|
||||
/* cancel TPOR */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_PORT_TREQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_hcd_stop);
|
||||
#endif
|
||||
@@ -0,0 +1,313 @@
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
#include <asm/arch/platform.h>
|
||||
#include <dm.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
#include <usb.h>
|
||||
#include <usb/xhci.h>
|
||||
#include "phy-usb.h"
|
||||
|
||||
#ifdef __USB_DEBUG
|
||||
#define USB_DEBUG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define USB_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#define GTXTHRCFG 0xc108
|
||||
#define GRXTHRCFG 0xc10c
|
||||
#define REG_GCTL 0xc110
|
||||
#define GUSB2PHYCFG 0xc200
|
||||
#define REG_GUSB3PIPECTL0 0xc2c0
|
||||
#define PCS_SSP_SOFT_RESET (0x1 << 31)
|
||||
#define USBTRDTIM_MASK 0x00003c00
|
||||
#define USBTRDTIM_16BIT (0x5 << 10)
|
||||
#define USBTRDTIM_8BIT (0x9 << 10)
|
||||
#define PHYIF (0x1 << 3)
|
||||
#define SUSPENDUSB20 (0x1 << 6)
|
||||
#define ENBLSLPM (0x1 << 8)
|
||||
#define LSIPD_MASK (0x7 << 19)
|
||||
#define LSIPD_3_BIT (0x2 << 19)
|
||||
#define U2_FREECLK_EXISTS (0x1 << 30)
|
||||
|
||||
#define PORT_CAP_DIR (0x3 << 12)
|
||||
#define PORT_SET_HOST (0x1 << 12)
|
||||
#define PORT_DISABLE_SUSPEND (0x1 << 17)
|
||||
|
||||
#define USB2_G_TXTHRCFG 0x23100000
|
||||
#define USB2_G_RXTHRCFG 0x23100000
|
||||
|
||||
/* CRG PERI_CRG80: usb clk & reset, offset 0x140 */
|
||||
#define USB2_CTRL 0x140
|
||||
#define USB2_CRG_DEF_VAL 0x1307
|
||||
#define USB2_PHY_CFG_REQ (0x1 << 0)
|
||||
#define USB2_PHY_PORT_SRST (0x1 << 1)
|
||||
#define USB2_PHY_XTAL_CKEN (0x1 << 2)
|
||||
#define USB2_VCC_SRST_REQ (0x1 << 3)
|
||||
#define USB2_BUS_CKEN (0x1 << 8)
|
||||
#define USB2_REF_CKEN (0x1 << 9)
|
||||
#define USB2_UTMI_CKEN (0x1 << 12)
|
||||
#define USB2_FREECLK_CKSEL (0x1 << 13)
|
||||
|
||||
/* u2 ctrl use reg, reg's misc_base=0x12028000 */
|
||||
#define MISC_USB2_CTRL_REG 0x24
|
||||
#define U2_BUS_FILTER_BYPASS (0xf << 0)
|
||||
#define U2_PWREN_MODE_MASK (0x1 << 4)
|
||||
#define U2_PWREN_MODE_MISC (0x0 << 4)
|
||||
#define U2_PWREN_MODE_CTRL (0x1 << 4)
|
||||
#define U2_OVERCURR_MODE_MASK (0x1 << 5)
|
||||
#define U2_OVERCURR_MODE_DISABLE (0x0 << 5)
|
||||
#define U2_OVERCURR_MODE_ENABLE (0x1 << 5)
|
||||
#define U2_PWREN_MASK (0x1 << 6)
|
||||
#define U2_PWREN_ON (0x0 << 6)
|
||||
#define U2_PWREN_OFF (0x1 << 6)
|
||||
#define U2_OVERCURR_MASK (0x1 << 7)
|
||||
#define U2_OVERCURR_ON (0x0 << 7)
|
||||
#define U2_OVERCURR_OFF (0x1 << 7)
|
||||
#define U2_FLADJ_30MHZ (0x20 << 13)
|
||||
|
||||
/* Outer phy use reg, reg's misc_base=0x12028000 */
|
||||
#define MISC_OUT_PHY2_CTRL_REG 0x2C
|
||||
#define USB2_PLL_EN (0x1 << 0)
|
||||
#define USB2_UTMI_DATABUS16_8 (0x1 << 1)
|
||||
|
||||
#define MISC_USB2_VBUS_REG 0x980
|
||||
#define U2_VBUS_EN (0x1 << 0)
|
||||
|
||||
static uintptr_t xhci_base;
|
||||
|
||||
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
|
||||
{
|
||||
if ((hccr == NULL) || (hcor == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
xhci_base = USB2_CTRL_REG_BASE;
|
||||
|
||||
*hccr = (struct xhci_hccr *)(xhci_base);
|
||||
*hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
|
||||
HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xhci_hcd_stop(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* por reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_CFG_REQ;
|
||||
reg |= USB2_PHY_PORT_SRST;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL10);
|
||||
|
||||
/* vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_hcd_stop);
|
||||
|
||||
static void usb2_eye_config(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void usb2_trim_config(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void lotus_u2_phy_clk_init(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable u2 phy clk and do reset */
|
||||
reg = (USB2_PHY_CFG_REQ | USB2_PHY_PORT_SRST | \
|
||||
USB2_PHY_XTAL_CKEN);
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x7,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* undo phy reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_CFG_REQ;
|
||||
reg &= ~USB2_PHY_PORT_SRST;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x4,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_u2_ctrl_clk_init(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable u2 ctrl clk and do reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= (USB2_VCC_SRST_REQ | USB2_BUS_CKEN | USB2_REF_CKEN |
|
||||
USB2_UTMI_CKEN);
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x130c,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* undo ctrl vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
USB_DEBUG("USB2_CRG(0x12010140), expext:0x1304,"
|
||||
"acutal:0x%X\n", readl(CRG_REG_BASE + USB2_CTRL));
|
||||
}
|
||||
|
||||
static void lotus_usb2_clk_init(void)
|
||||
{
|
||||
lotus_u2_phy_clk_init();
|
||||
lotus_u2_ctrl_clk_init();
|
||||
}
|
||||
|
||||
static void lotus_u2_phy_misc_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* MISC_CTRL11: config 0x3 according to IC. */
|
||||
reg = 0;
|
||||
reg |= (USB2_PLL_EN | USB2_UTMI_DATABUS16_8);
|
||||
writel(reg, MISC_REG_BASE + MISC_OUT_PHY2_CTRL_REG);
|
||||
USB_DEBUG("MISC_OUT_PHY2_CTRL_REG(0x1202802c),"
|
||||
"expext:0x3, acutal:0x%X\n",
|
||||
readl(MISC_REG_BASE + MISC_OUT_PHY2_CTRL_REG));
|
||||
}
|
||||
|
||||
static inline void lotus_usb2_vbus_valid_en(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* enable U2 vbus valid */
|
||||
reg = readl(MISC_REG_BASE + MISC_USB2_VBUS_REG);
|
||||
reg |= U2_VBUS_EN;
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_VBUS_REG);
|
||||
}
|
||||
|
||||
static void lotus_dwc_data_width_config(enum usb_phy_width_mode mode)
|
||||
{
|
||||
unsigned int reg, base = USB2_CTRL_REG_BASE;
|
||||
|
||||
/* GUSB2PHYCFG register: config val 0x40001548(HS/FS) or
|
||||
* 0x00381548(LS) according to IC.
|
||||
*
|
||||
* USBTRDTIM: USB 2.0 Turnaround Time in PHY clocks.
|
||||
* PHYIF: 1 UTMI+ PHY is 16-bit, 0 UTMI+ PHY is 8-bit.
|
||||
*/
|
||||
reg = 0;
|
||||
switch (mode) {
|
||||
case PHY_WIDTH_8BIT:
|
||||
/* 8-bits usb phy configure */
|
||||
reg |= USBTRDTIM_8BIT;
|
||||
reg &= ~PHYIF;
|
||||
break;
|
||||
case PHY_WIDTH_16BIT:
|
||||
/* 16-bits usb phy configure */
|
||||
reg |= (USBTRDTIM_16BIT | PHYIF);
|
||||
break;
|
||||
default:
|
||||
printf("usb phy width config val error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
writel(reg, base + GUSB2PHYCFG);
|
||||
}
|
||||
|
||||
static void lotus_dwc_usb_config(void)
|
||||
{
|
||||
unsigned int reg, base = USB2_CTRL_REG_BASE;
|
||||
|
||||
reg = readl(base + REG_GUSB3PIPECTL0);
|
||||
reg |= PCS_SSP_SOFT_RESET;
|
||||
writel(reg, base + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(base + REG_GCTL);
|
||||
reg &= ~PORT_CAP_DIR;
|
||||
reg |= PORT_SET_HOST; /* host mode is default. */
|
||||
writel(reg, base + REG_GCTL);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(base + REG_GUSB3PIPECTL0);
|
||||
reg &= ~PCS_SSP_SOFT_RESET;
|
||||
reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
|
||||
writel(reg, base + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
writel(USB2_G_TXTHRCFG, base + GTXTHRCFG);
|
||||
writel(USB2_G_RXTHRCFG, base + GRXTHRCFG);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
lotus_dwc_data_width_config(PHY_WIDTH_16BIT);
|
||||
|
||||
reg = readl(base + GUSB2PHYCFG);
|
||||
reg &= ~SUSPENDUSB20; /* disable suspend */
|
||||
reg &= ~ENBLSLPM; /* suspend not transfer to external PHY */
|
||||
reg &= ~U2_FREECLK_EXISTS;
|
||||
reg &= ~LSIPD_MASK;
|
||||
reg |= LSIPD_3_BIT;
|
||||
writel(reg, base + GUSB2PHYCFG);
|
||||
|
||||
USB_DEBUG("GUSB2PHYCFG(0xc200):0x%X\n",
|
||||
readl(base + GUSB2PHYCFG));
|
||||
USB_DEBUG("GUSB3PIPECTL0(0xc2c0):0x%X\n",
|
||||
readl(base + REG_GUSB3PIPECTL0));
|
||||
USB_DEBUG("GCTL(0xc110):0x%X\n",
|
||||
readl(base + REG_GCTL));
|
||||
}
|
||||
|
||||
void phy_usb_init(int index)
|
||||
{
|
||||
/* u2 utmi data bus config, u2 phy pll en */
|
||||
lotus_u2_phy_misc_config();
|
||||
|
||||
/* init crg and clk */
|
||||
lotus_usb2_clk_init();
|
||||
|
||||
/* enable u2 vbusvalid */
|
||||
lotus_usb2_vbus_valid_en();
|
||||
|
||||
/* USB2 Controller configs */
|
||||
lotus_dwc_usb_config();
|
||||
|
||||
/* lotus phy eye diagram config */
|
||||
usb2_eye_config();
|
||||
|
||||
/* lotus phy trim config */
|
||||
usb2_trim_config();
|
||||
}
|
||||
EXPORT_SYMBOL(phy_usb_init);
|
||||
|
||||
/* Some usb device can't be recognize in U-boot because
|
||||
* of error state, so we power off them and wait a delay
|
||||
* to restart them, similar to unplug and then insert.
|
||||
*/
|
||||
void lotus_usb_pwren_control(void)
|
||||
{
|
||||
u32 reg, default_val, delay;
|
||||
|
||||
delay = CONFIG_USB_PWREN_OFF_DELAY ?
|
||||
CONFIG_USB_PWREN_OFF_DELAY : 100;
|
||||
|
||||
reg = readl(MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
default_val = reg;
|
||||
reg &= ~U2_PWREN_MODE_MASK; /* set PWREN_MISC mode */
|
||||
reg |= U2_PWREN_OFF; /* turn off PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
|
||||
mdelay(delay);
|
||||
|
||||
reg = readl(MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
reg &= ~U2_PWREN_MASK; /* turn on PWREN */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
|
||||
reg = default_val; /* set PWREN_CTRL mode(default val) */
|
||||
writel(reg, MISC_REG_BASE + MISC_USB2_CTRL_REG);
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PHY_LOTUS_USB
|
||||
#include <asm/arch/platform.h>
|
||||
#include <dm.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
#include <usb/xhci.h>
|
||||
#include "phy-usb.h"
|
||||
|
||||
/* offset 0x140 */
|
||||
#define USB2_CTRL 0x140
|
||||
#define USB2_CRG_DEFAULT_VAL 0x3b2f
|
||||
#define USB2_UTMI_CKEN (0x1 << 12)
|
||||
#define USB2_PHY_APB_CKEN (0x1 << 11)
|
||||
#define USB2_REF_CKEN (0x1 << 9)
|
||||
#define USB2_BUS_CKEN (0x1 << 8)
|
||||
#define USB2_PHY_PLL_CKEN (0x1 << 4)
|
||||
#define USB2_PHY_XTAL_CKEN (0x1 << 2)
|
||||
#define USB2_FREECLK_CKSEL (0x1 << 13)
|
||||
#define USB2_PHY_APB_RST (0x1 << 10)
|
||||
#define USB2_VCC_SRST_REQ (0x1 << 3)
|
||||
#define USB2_PHY_REQ (0x1 << 0)
|
||||
#define USB2_PHY_PORT_TREQ (0x1 << 1)
|
||||
|
||||
#define GTXTHRCFG 0xc108
|
||||
#define GRXTHRCFG 0xc10c
|
||||
#define REG_GCTL 0xc110
|
||||
#define REG_GUSB3PIPECTL0 0xc2c0
|
||||
#define PCS_SSP_SOFT_RESET (0x1 << 31)
|
||||
|
||||
#define PORT_CAP_DIR (0x3 << 12)
|
||||
#define PORT_SET_HOST (0x1 << 12)
|
||||
#define PORT_DISABLE_SUSPEND (0x1 << 17)
|
||||
|
||||
#define USB2_G_TXTHRCFG 0x23100000
|
||||
#define USB2_G_RXTHRCFG 0x23100000
|
||||
|
||||
/* PHY base register */
|
||||
#define USB2_PHY_BASE_REG 0x100D0000
|
||||
#define RG_PLL_EN_MASK 0x0003
|
||||
#define RG_PLL_EN_VAL 0x0003
|
||||
#define PHY_PLL_OFFSET 0x0014
|
||||
|
||||
#define USB_VBUS_IO_CONFIG_REG 0x100c007C
|
||||
#define USB_VBUS_IO_CONFIG_VAL 0x0531
|
||||
|
||||
#define USB_PWREN_CONFIG_REG 0x100c0080
|
||||
#define USB_PWREN_CONFIG_VAL 0x1
|
||||
|
||||
/* PHY eye config */
|
||||
#define PHY_ANA_CFG_0_OFFSET 0x00
|
||||
#define PHY_PRE_DRIVE_MASK (0xf << 24)
|
||||
#define PHY_PRE_DRIVE_VAL (0x4 << 24)
|
||||
#define PHY_HSTX_DE_MASK (0xf << 8)
|
||||
#define PHY_HSTX_DE_VAL (0xc << 8)
|
||||
#define PHY_HSTX_DEEN_BIT (0x1 << 5)
|
||||
#define PHY_ANA_CFG_2_OFFSET 0x08
|
||||
#define PHY_TX_TEST_BIT (0x1 << 20)
|
||||
#define PHY_HALF_DEEM_BIT (0x1 << 21)
|
||||
#define PHY_DISCONNECT_REFERENCE_MASK (0x7 << 16)
|
||||
#define PHY_DISCONNECT_REFERENCE_VAL (0x2 << 16)
|
||||
#define PHY_ANA_CFG_4_OFFSET 0x10
|
||||
#define PHY_TX_REFERENCE_MASK (0x7 << 4)
|
||||
#define PHY_TX_REFERENCE_VAL (0x5 << 4)
|
||||
#define PHY_SQUELCH_REFERENCE_MASK (0x7 << 0)
|
||||
#define PHY_SQUELCH_REFERENCE_VAL (0x5 << 0)
|
||||
|
||||
/* PHY trim config */
|
||||
#define USB_TRIM_BASE_REG 0x12028004
|
||||
#define USB_TRIM_VAL_MASK 0x001F
|
||||
#define USB_TRIM_VAL_MIN 0x0009
|
||||
#define USB_TRIM_VAL_MAX 0x001D
|
||||
#define USB2_TRIM_OFFSET 0x0008
|
||||
#define USB2_TRIM_MASK 0x1f00
|
||||
#define usb2_trim_val(a) (((a) << 8) & USB2_TRIM_MASK)
|
||||
#define USB2_TRIM_DEFAULT_VAL 0x000F
|
||||
|
||||
static uintptr_t xhci_base = 0;
|
||||
|
||||
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
|
||||
{
|
||||
if ((hccr == NULL) || (hcor == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
xhci_base = USB3_CTRL_REG_BASE;
|
||||
|
||||
*hccr = (struct xhci_hccr *)(xhci_base);
|
||||
*hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
|
||||
HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb2_eye_config(void)
|
||||
{
|
||||
unsigned int reg;
|
||||
/* HSTX pre-drive strength */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg &= ~PHY_PRE_DRIVE_MASK;
|
||||
reg |= PHY_PRE_DRIVE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* HSTX de-emphasis strength */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg &= ~PHY_HSTX_DE_MASK;
|
||||
reg |= PHY_HSTX_DE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* HSTX de-emphasis enable */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
reg |= PHY_HSTX_DEEN_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_0_OFFSET);
|
||||
|
||||
/* TX test bit */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg |= PHY_TX_TEST_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* TX half de-emphasis bit */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg |= PHY_HALF_DEEM_BIT;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* Disconnect reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
reg &= ~PHY_DISCONNECT_REFERENCE_MASK;
|
||||
reg |= PHY_DISCONNECT_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_2_OFFSET);
|
||||
|
||||
/* TX reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
reg &= ~PHY_TX_REFERENCE_MASK;
|
||||
reg |= PHY_TX_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
|
||||
/* Squlech reference voltage sel */
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
reg &= ~PHY_SQUELCH_REFERENCE_MASK;
|
||||
reg |= PHY_SQUELCH_REFERENCE_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_ANA_CFG_4_OFFSET);
|
||||
}
|
||||
|
||||
void usb2_trim_config(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
unsigned int reg;
|
||||
unsigned int trim_val;
|
||||
|
||||
ret = readl(USB_TRIM_BASE_REG);
|
||||
trim_val = (ret & USB_TRIM_VAL_MASK); /* get usb trim value */
|
||||
reg = readl(USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
|
||||
reg &= ~USB2_TRIM_MASK;
|
||||
if ((trim_val >= USB_TRIM_VAL_MIN) && (trim_val <= USB_TRIM_VAL_MAX))
|
||||
reg |= usb2_trim_val(trim_val);
|
||||
else
|
||||
reg |= usb2_trim_val(USB2_TRIM_DEFAULT_VAL);
|
||||
|
||||
writel(reg, USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
|
||||
}
|
||||
|
||||
void phy_usb_init_crg_clk(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* set usb2 CRG default val */
|
||||
reg = USB2_CRG_DEFAULT_VAL;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* open UTMI clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_UTMI_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy apb clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_APB_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open ctrl ref clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_REF_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open bus clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_BUS_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy pll clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_PLL_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* open phy xtal clk */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_XTAL_CKEN;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* freeclk_cksel_free */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_FREECLK_CKSEL;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL5);
|
||||
}
|
||||
|
||||
void phy_usb_init(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* VBUS config */
|
||||
reg = USB_VBUS_IO_CONFIG_VAL;
|
||||
writel(reg, USB_VBUS_IO_CONFIG_REG);
|
||||
|
||||
reg = USB_PWREN_CONFIG_VAL;
|
||||
writel(reg, USB_PWREN_CONFIG_REG);
|
||||
|
||||
/* init crg and clk */
|
||||
phy_usb_init_crg_clk(index);
|
||||
|
||||
/* release phy apb */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_APB_RST;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL5);
|
||||
|
||||
/* por noreset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
reg = readl(USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
|
||||
reg &= ~RG_PLL_EN_MASK;
|
||||
reg |= RG_PLL_EN_VAL;
|
||||
writel(reg, USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
|
||||
|
||||
udelay(U_LEVEL10);
|
||||
|
||||
/* cancel TPOR */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_PHY_PORT_TREQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg &= ~USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
/* USB2 Controller configs */
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
reg |= PCS_SSP_SOFT_RESET;
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GCTL);
|
||||
reg &= ~PORT_CAP_DIR;
|
||||
reg |= PORT_SET_HOST; /* [13:12] 01: Host; 10: Device; 11: OTG */
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GCTL);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
reg &= ~PCS_SSP_SOFT_RESET;
|
||||
reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
|
||||
writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
writel(USB2_G_TXTHRCFG, USB3_CTRL_REG_BASE + GTXTHRCFG);
|
||||
writel(USB2_G_RXTHRCFG, USB3_CTRL_REG_BASE + GRXTHRCFG);
|
||||
udelay(U_LEVEL2);
|
||||
|
||||
/* USB2 eye config */
|
||||
usb2_eye_config();
|
||||
|
||||
/* USB2 trim config */
|
||||
usb2_trim_config();
|
||||
}
|
||||
EXPORT_SYMBOL(phy_usb_init);
|
||||
|
||||
void xhci_hcd_stop(int index)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
/* por noreset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
|
||||
udelay(U_LEVEL10);
|
||||
|
||||
/* cancel TPOR */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_PHY_PORT_TREQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
udelay(U_LEVEL6);
|
||||
|
||||
/* vcc reset */
|
||||
reg = readl(CRG_REG_BASE + USB2_CTRL);
|
||||
reg |= USB2_VCC_SRST_REQ;
|
||||
writel(reg, CRG_REG_BASE + USB2_CTRL);
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_hcd_stop);
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
obj-y += usb3_drv.o usb3_pcd.o usb3_intr.o usb3_pcd_intr.o usb3_prot.o
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "platform.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define MHZ (1000 * 1000)
|
||||
|
||||
#define CFG_CLK_OTHER (19200000)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* Serial Configuration
|
||||
*/
|
||||
#define CONFIG_PL011_CLOCK CFG_CLK_OTHER
|
||||
|
||||
#define CONFIG_CONS_INDEX 0 /* select the default console */
|
||||
#define CONFIG_BAUDRATE 115200
|
||||
#define CFG_SERIAL0 REG_BASE_UART6
|
||||
|
||||
/*
|
||||
* ARM PrimeCell UART's (PL010 & PL011)
|
||||
* ------------------------------------
|
||||
*
|
||||
* Definitions common to both PL010 & PL011
|
||||
*
|
||||
*/
|
||||
#define UART_PL01X_DR 0x00 /* Data read or written from the interface. */
|
||||
#define UART_PL01X_RSR 0x04 /* Receive status register (Read). */
|
||||
#define UART_PL01X_ECR 0x04 /* Error clear register (Write). */
|
||||
#define UART_PL01X_ECR 0x18 /* Flag register (Read only). */
|
||||
|
||||
#define UART_PL01X_RSR_OE 0x08
|
||||
#define UART_PL01X_RSR_BE 0x04
|
||||
#define UART_PL01X_RSR_PE 0x02
|
||||
#define UART_PL01X_RSR_FE 0x01
|
||||
|
||||
#define UART_PL01X_FR_TXFE 0x80
|
||||
#define UART_PL01X_FR_RXFF 0x40
|
||||
#define UART_PL01X_FR_TXFF 0x20
|
||||
#define UART_PL01X_FR_RXFE 0x10
|
||||
#define UART_PL01X_FR_BUSY 0x08
|
||||
#define UART_PL01X_FR_TMSK (UART_PL01X_FR_TXFF + UART_PL01X_FR_BUSY)
|
||||
|
||||
/*
|
||||
* PL010 definitions
|
||||
*
|
||||
*/
|
||||
#define UART_PL010_LCRH 0x08 /* Line control register, high byte. */
|
||||
#define UART_PL010_LCRM 0x0C /* Line control register, middle byte. */
|
||||
#define UART_PL010_LCRL 0x10 /* Line control register, low byte. */
|
||||
#define UART_PL010_CR 0x14 /* Control register. */
|
||||
#define UART_PL010_IIR 0x1C /* Interrupt indentification register (Read). */
|
||||
#define UART_PL010_ICR 0x1C /* Interrupt clear register (Write). */
|
||||
#define UART_PL010_ILPR 0x20 /* IrDA low power counter register. */
|
||||
|
||||
#define UART_PL010_CR_LPE (1 << 7)
|
||||
#define UART_PL010_CR_RTIE (1 << 6)
|
||||
#define UART_PL010_CR_TIE (1 << 5)
|
||||
#define UART_PL010_CR_RIE (1 << 4)
|
||||
#define UART_PL010_CR_MSIE (1 << 3)
|
||||
#define UART_PL010_CR_IIRLP (1 << 2)
|
||||
#define UART_PL010_CR_SIREN (1 << 1)
|
||||
#define UART_PL010_CR_UARTEN (1 << 0)
|
||||
|
||||
#define UART_PL010_LCRH_WLEN_8 (3 << 5)
|
||||
#define UART_PL010_LCRH_WLEN_7 (2 << 5)
|
||||
#define UART_PL010_LCRH_WLEN_6 (1 << 5)
|
||||
#define UART_PL010_LCRH_WLEN_5 (0 << 5)
|
||||
#define UART_PL010_LCRH_FEN (1 << 4)
|
||||
#define UART_PL010_LCRH_STP2 (1 << 3)
|
||||
#define UART_PL010_LCRH_EPS (1 << 2)
|
||||
#define UART_PL010_LCRH_PEN (1 << 1)
|
||||
#define UART_PL010_LCRH_BRK (1 << 0)
|
||||
|
||||
#define UART_PL010_BAUD_460800 1
|
||||
#define UART_PL010_BAUD_230400 3
|
||||
#define UART_PL010_BAUD_115200 7
|
||||
#define UART_PL010_BAUD_57600 15
|
||||
#define UART_PL010_BAUD_38400 23
|
||||
#define UART_PL010_BAUD_19200 47
|
||||
#define UART_PL010_BAUD_14400 63
|
||||
#define UART_PL010_BAUD_9600 95
|
||||
#define UART_PL010_BAUD_4800 191
|
||||
#define UART_PL010_BAUD_2400 383
|
||||
#define UART_PL010_BAUD_1200 767
|
||||
/*
|
||||
* PL011 definitions
|
||||
*
|
||||
*/
|
||||
#define UART_PL011_IBRD 0x24
|
||||
#define UART_PL011_FBRD 0x28
|
||||
#define UART_PL011_LCRH 0x2C
|
||||
#define UART_PL011_CR 0x30
|
||||
#define UART_PL011_IMSC 0x38
|
||||
#define UART_PL011_PERIPH_ID0 0xFE0
|
||||
|
||||
#define UART_PL011_LCRH_SPS (1 << 7)
|
||||
#define UART_PL011_LCRH_WLEN_8 (3 << 5)
|
||||
#define UART_PL011_LCRH_WLEN_7 (2 << 5)
|
||||
#define UART_PL011_LCRH_WLEN_6 (1 << 5)
|
||||
#define UART_PL011_LCRH_WLEN_5 (0 << 5)
|
||||
#define UART_PL011_LCRH_FEN (1 << 4)
|
||||
#define UART_PL011_LCRH_STP2 (1 << 3)
|
||||
#define UART_PL011_LCRH_EPS (1 << 2)
|
||||
#define UART_PL011_LCRH_PEN (1 << 1)
|
||||
#define UART_PL011_LCRH_BRK (1 << 0)
|
||||
|
||||
#define UART_PL011_CR_CTSEN (1 << 15)
|
||||
#define UART_PL011_CR_RTSEN (1 << 14)
|
||||
#define UART_PL011_CR_OUT2 (1 << 13)
|
||||
#define UART_PL011_CR_OUT1 (1 << 12)
|
||||
#define UART_PL011_CR_RTS (1 << 11)
|
||||
#define UART_PL011_CR_DTR (1 << 10)
|
||||
#define UART_PL011_CR_RXE (1 << 9)
|
||||
#define UART_PL011_CR_TXE (1 << 8)
|
||||
#define UART_PL011_CR_LPE (1 << 7)
|
||||
#define UART_PL011_CR_IIRLP (1 << 2)
|
||||
#define UART_PL011_CR_SIREN (1 << 1)
|
||||
#define UART_PL011_CR_UARTEN (1 << 0)
|
||||
|
||||
#define UART_PL011_IMSC_OEIM (1 << 10)
|
||||
#define UART_PL011_IMSC_BEIM (1 << 9)
|
||||
#define UART_PL011_IMSC_PEIM (1 << 8)
|
||||
#define UART_PL011_IMSC_FEIM (1 << 7)
|
||||
#define UART_PL011_IMSC_RTIM (1 << 6)
|
||||
#define UART_PL011_IMSC_TXIM (1 << 5)
|
||||
#define UART_PL011_IMSC_RXIM (1 << 4)
|
||||
#define UART_PL011_IMSC_DSRMIM (1 << 3)
|
||||
#define UART_PL011_IMSC_DCDMIM (1 << 2)
|
||||
#define UART_PL011_IMSC_CTSMIM (1 << 1)
|
||||
#define UART_PL011_IMSC_RIMIM (1 << 0)
|
||||
|
||||
void console_init();
|
||||
|
||||
void __xprintf(const char *fmt, va_list ap, void (*xputc)(unsigned n, void *cookie), void *cookie);
|
||||
void cprintf(const char *fmt, ...);
|
||||
|
||||
#define debug_init() console_init()
|
||||
#define DEBUG_PRINTF cprintf
|
||||
#define msglogstr(x) cprintf(x);
|
||||
|
||||
#else
|
||||
|
||||
#define debug_init()
|
||||
#define debug_printf(exp, ...)
|
||||
#define msglogstr(x)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* end of __DEBUG_H__ */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __ONCHIPROM_H__
|
||||
#define __ONCHIPROM_H__
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/* define vrl table of xloader loaded address & size */
|
||||
#define VRL_TABLE_LOAD_ADDRESS REG_BASE_LP_RAM
|
||||
#define VRL_TABLE_LOAD_SIZE (4 * 1024)
|
||||
|
||||
/* define xloader loaded address & size */
|
||||
#define XLOADER_IMAGE_LOAD_ADDRESS (VRL_TABLE_LOAD_ADDRESS + VRL_TABLE_LOAD_SIZE)
|
||||
#ifdef EDA_SPEEDUP
|
||||
#define XLOADER_IMAGE_LOAD_SIZE (4 * 1024)
|
||||
#else
|
||||
#define XLOADER_IMAGE_LOAD_SIZE (28 * 1024)
|
||||
#endif
|
||||
|
||||
#define ONCHIPROM_IMAGE_LOAD_MAX (100 * 1024)
|
||||
|
||||
/* define ufs work space area */
|
||||
#define UFS_STATIC_WORK_SPACE_ADDRESS (REG_BASE_LP_RAM + 0x1C000)
|
||||
#define UFS_STATIC_WORK_SPACE_SIZE (0xE00)
|
||||
|
||||
/* define onchiprom static area */
|
||||
#define ONCHIPROM_STATIC_AREA_ADDRESS (REG_BASE_LP_RAM + 0x1CE00)
|
||||
#define ONCHIPROM_STATIC_AREA_SIZE (0x100)
|
||||
|
||||
/* define secure engine static area */
|
||||
#define SECURE_ENGINE_STATIC_AREA_ADDRESS (REG_BASE_LP_RAM + 0x1CF00)
|
||||
#define SECURE_ENGINE_STATIC_AREA_SIZE (0x100)
|
||||
|
||||
/* define secure engine work space address & size */
|
||||
#define SECURE_ENGINE_WORK_SPACE_ADDRESS (REG_BASE_LP_RAM + 0x1D000)
|
||||
#define SECURE_ENGINE_WORK_SPACE_SIZE (0x1800)
|
||||
|
||||
/* define secure engine work space address & size */
|
||||
#define USB_STATIC_WORK_SPACE_ADDRESS (REG_BASE_LP_RAM + 0x1E800)
|
||||
#define USB_STATIC_WORK_SPACE_SIZE (0x1800)
|
||||
|
||||
/* xloader image length address */
|
||||
#define VRL_TABLE_IMAGE_LENGTH_OFFEST_ADDR (0xFFC)
|
||||
|
||||
#define LPRAM_MEMORY_MAP_OFFEST_ADDRESS SECURE_ENGINE_STATIC_AREA_ADDRESS
|
||||
#define LPRAM_MEMORY_MAP_OFFEST (REG_BASE_LP_RAM_ACORE - REG_BASE_LP_RAM)
|
||||
|
||||
/* static variable */
|
||||
#define STATIC_ERROR_CODE_ADDR (ONCHIPROM_STATIC_AREA_ADDRESS + 0x4)
|
||||
#define STATIC_TIMER_STATUS_ADDR (ONCHIPROM_STATIC_AREA_ADDRESS + 0x8)
|
||||
#define STATIC_TIMER_COUNT_ADDR (ONCHIPROM_STATIC_AREA_ADDRESS + 0xC)
|
||||
#define STATIC_UFS_TAG_ADDR (ONCHIPROM_STATIC_AREA_ADDRESS + 0x10)
|
||||
|
||||
/* define boot mode */
|
||||
#define BOOT_MODE_USB_DOWNLOAD 0
|
||||
#define BOOT_MODE_NORMAL_BOOT 1
|
||||
|
||||
#define BOOT_MODE_EMMC_BOOT 0
|
||||
#define BOOT_MODE_UFS_BOOT 1
|
||||
|
||||
typedef void (*PJUMPTOADDR)(void); /* addr of xloader */
|
||||
|
||||
#endif /* end of __ONCHIPROM_H__ */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_H__
|
||||
#define __PLATFORM_H__
|
||||
|
||||
/* fpga memory map */
|
||||
#define REG_BASE_EMMC0 0xBF3FB000
|
||||
|
||||
#define REG_BASE_USB_OTG 0x10180000
|
||||
#define REG_BASE_USB_OTG_BC 0XBF200000
|
||||
#define REG_BASE_LP_RAM 0x00020000
|
||||
|
||||
#define REG_BASE_UFS_SYS 0xBF3B1000
|
||||
#define REG_BASE_UFS 0xBF3B0000
|
||||
|
||||
#define REG_BASE_PCTRL 0xA8A09000
|
||||
#define REG_BASE_IOC 0xA896C000
|
||||
#define REG_BASE_PMC 0x40231000
|
||||
#define REG_BASE_UART6 0x40232000
|
||||
#define REG_BASE_PERI_CRG 0x40235000
|
||||
#define REG_BASE_LP_TIMER 0x4023E000
|
||||
#define REG_BASE_SCTRL 0x4020A000
|
||||
#define REG_BASE_AO_IOC 0x40211000
|
||||
|
||||
#define REG_BASE_GPIO 0xA8A0B000 /* GPIO0~21 */
|
||||
#define reg_gpio(x) (REG_BASE_GPIO + (0x1000 * (x)))
|
||||
#define REG_GPIO22 0x4020B000
|
||||
|
||||
#define LP_RAM_SIZE (96*1024)
|
||||
|
||||
#define REG_BASE_LP_RAM_ACORE 0xFFF50000
|
||||
|
||||
#endif /* end of __PLATFORM_H__ */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SYS_H__
|
||||
#define __SYS_H__
|
||||
#include "types.h"
|
||||
static inline void writel(unsigned int val, unsigned long int addr)
|
||||
{
|
||||
(*(volatile unsigned int *)(addr)) = (val);
|
||||
}
|
||||
|
||||
static inline void writew(unsigned short val, unsigned long int addr)
|
||||
{
|
||||
(*(volatile unsigned short *)(addr)) = (val);
|
||||
}
|
||||
|
||||
static inline void writeb(unsigned char val, unsigned long int addr)
|
||||
{
|
||||
(*(volatile unsigned char *)(addr)) = (val);
|
||||
}
|
||||
|
||||
static inline unsigned int readl(unsigned long int addr)
|
||||
{
|
||||
return (*(volatile unsigned int *)(addr));
|
||||
}
|
||||
|
||||
static inline unsigned short readw(unsigned long int addr)
|
||||
{
|
||||
return (*(volatile unsigned short *)(addr));
|
||||
}
|
||||
|
||||
static inline unsigned char readb(unsigned long int addr)
|
||||
{
|
||||
return (*(volatile unsigned char *)(addr));
|
||||
}
|
||||
|
||||
/* Set the bits of addr to 1, which in mask is 1 */
|
||||
static inline void set_bits(unsigned int mask, unsigned long int addr)
|
||||
{
|
||||
(*(volatile unsigned int *)(addr)) |= mask;
|
||||
}
|
||||
|
||||
/* Clear the bits of addr to 0, which in mask is 1 */
|
||||
static inline void clr_bits(unsigned int mask, unsigned long int addr)
|
||||
{
|
||||
(*(volatile unsigned int *)(addr)) &= ~(mask);
|
||||
}
|
||||
|
||||
/* Return True if all the bits of addr are 1, which is 1 in mask.
|
||||
Else, return False. */
|
||||
static inline unsigned int is_bits_set(unsigned int mask, unsigned long int addr)
|
||||
{
|
||||
return (((*(volatile unsigned int *)(addr)) & (mask)) == (mask));
|
||||
}
|
||||
#endif /* end of __SYS_H__ */
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#endif /* end of __TYPES_H__ */
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __USB3_H__
|
||||
#define __USB3_H__
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define STRING_LANGUAGE 0
|
||||
#define STRING_MANUFACTURER 1
|
||||
#define STRING_PRODUCT 2
|
||||
|
||||
#define USB_SPEED_UNKNOWN 0x00
|
||||
#define USB_SPEED_LOW 0x01
|
||||
#define USB_SPEED_FULL 0x02
|
||||
#define USB_SPEED_HIGH 0x03
|
||||
#define USB_SPEED_VARIABLE 0x04
|
||||
#define USB_SPEED_SUPER 0x05
|
||||
|
||||
#define UDESC_DEVICE 0x01
|
||||
#define UDESC_CONFIG 0x02
|
||||
#define UDESC_STRING 0x03
|
||||
#define UDESC_INTERFACE 0x04
|
||||
#define UDESC_ENDPOINT 0x05
|
||||
#define UDESC_SS_USB_COMPANION 0x30
|
||||
#define UDESC_DEVICE_QUALIFIER 0x06
|
||||
#define UDESC_BOS 0x0f
|
||||
#define UDESC_DEVICE_CAPABILITY 0x10
|
||||
|
||||
#define ut_get_dir(a) ((a)&0x80)
|
||||
#define UT_WRITE 0x00
|
||||
#define UT_READ 0x80
|
||||
|
||||
#define ut_get_type(a) ((a)&0x60)
|
||||
#define UT_STANDARD 0x00
|
||||
#define UT_CLASS 0x20
|
||||
#define UT_VENDOR 0x40
|
||||
|
||||
#define ut_get_recipient(a) ((a)&0x1f)
|
||||
#define UT_DEVICE 0x00
|
||||
#define UT_INTERFACE 0x01
|
||||
#define UT_ENDPOINT 0x02
|
||||
#define UT_OTHER 0x03
|
||||
|
||||
#define UR_GET_STATUS 0x00
|
||||
#define UR_CLEAR_FEATURE 0x01
|
||||
#define UR_SET_FEATURE 0x03
|
||||
#define UR_SET_ADDRESS 0x05
|
||||
#define UR_GET_DESCRIPTOR 0x06
|
||||
#define UR_SET_DESCRIPTOR 0x07
|
||||
#define UR_GET_CONFIG 0x08
|
||||
#define UR_SET_CONFIG 0x09
|
||||
#define UR_GET_INTERFACE 0x0a
|
||||
#define UR_SET_INTERFACE 0x0b
|
||||
#define UR_SYNCH_FRAME 0x0c
|
||||
#define UR_SET_SEL 0x30
|
||||
#define UR_SET_ISOC_DELAY 0x31
|
||||
|
||||
/* Feature numbers */
|
||||
#define UF_ENDPOINT_HALT 0
|
||||
#define UF_DEVICE_REMOTE_WAKEUP 1
|
||||
#define UF_TEST_MODE 2
|
||||
#define UF_DEVICE_B_HNP_ENABLE 3
|
||||
#define UF_DEVICE_A_HNP_SUPPORT 4
|
||||
#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
|
||||
#define UF_FUNCTION_SUSPEND 0
|
||||
#define UF_U1_ENABLE 48
|
||||
#define UF_U2_ENABLE 49
|
||||
#define UF_LTM_ENABLE 50
|
||||
|
||||
/* OTG feature selectors */
|
||||
#define UOTG_B_HNP_ENABLE 3
|
||||
#define UOTG_A_HNP_SUPPORT 4
|
||||
#define UOTG_A_ALT_HNP_SUPPORT 5
|
||||
#define UOTG_NTF_HOST_REL 51
|
||||
#define UOTG_B3_RSP_ENABLE 52
|
||||
|
||||
#define ue_get_dir(a) ((a)&0x80)
|
||||
#define ue_set_dir(a, d) ((a) | (((d)&1) << 7))
|
||||
#define UE_DIR_IN 0x80
|
||||
#define UE_DIR_OUT 0x00
|
||||
#define UE_ADDR 0x0f
|
||||
#define ue_get_addr(a) ((a)&UE_ADDR)
|
||||
|
||||
/* * Maxpacket size for EP0, defined by USB3 spec */
|
||||
#define USB3_MAX_EP0_SIZE 512
|
||||
|
||||
/* * Maxpacket size for any EP, defined by USB3 spec */
|
||||
#define USB3_MAX_PACKET_SIZE 1024
|
||||
#define USB2_HS_MAX_PACKET_SIZE 512
|
||||
#define USB2_FS_MAX_PACKET_SIZE 64
|
||||
|
||||
#define USB3_BULK_IN_EP 1
|
||||
#define USB3_BULK_OUT_EP 1
|
||||
|
||||
typedef struct usb_device_request {
|
||||
unsigned char bm_request_type;
|
||||
unsigned char b_request;
|
||||
unsigned short w_value;
|
||||
unsigned short w_index;
|
||||
unsigned short w_length;
|
||||
} usb_device_request_t;
|
||||
|
||||
#pragma pack(1)
|
||||
/* * USB_DT_DEVICE: Device descriptor */
|
||||
typedef struct usb_device_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned short bcd_usb;
|
||||
#define USB_CLASS_COMM 0x02
|
||||
#define USB_CLASS_VENDOR_SPEC 0xFF
|
||||
#define USB_SC_VENDOR_SPEC 0xFF
|
||||
#define USB_PR_VENDOR_SPEC 0xFF
|
||||
unsigned char b_device_class;
|
||||
unsigned char b_device_sub_class;
|
||||
unsigned char b_device_protocol;
|
||||
unsigned char b_max_packet_size0;
|
||||
unsigned short id_vendor;
|
||||
unsigned short id_product;
|
||||
unsigned short bcd_device;
|
||||
unsigned char i_manufacturer;
|
||||
unsigned char i_product;
|
||||
unsigned char i_serial_number;
|
||||
unsigned char b_num_configurations;
|
||||
} usb_device_descriptor_t;
|
||||
|
||||
/* USB_DT_CONFIG: Config descriptor */
|
||||
typedef struct usb_config_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned short w_total_length;
|
||||
unsigned char b_num_interfaces;
|
||||
#define CONFIG_VALUE 1
|
||||
unsigned char b_configuration_value;
|
||||
unsigned char i_configuration;
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7)
|
||||
unsigned char bm_attributes;
|
||||
#define USB_CONFIG_VBUS_DRAW (0xFA)
|
||||
unsigned char b_max_power;
|
||||
} usb_config_descriptor_t;
|
||||
|
||||
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
|
||||
typedef struct usb_qualifier_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned short bcd_usb;
|
||||
unsigned char b_device_class;
|
||||
unsigned char b_device_sub_class;
|
||||
unsigned char b_device_protocol;
|
||||
unsigned char b_max_packet_size0;
|
||||
unsigned char b_num_configurations;
|
||||
unsigned char b_reserved;
|
||||
} usb_qualifier_descriptor_t;
|
||||
|
||||
/* USB_DT_INTERFACE: Interface descriptor */
|
||||
typedef struct usb_interface_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned char b_interface_number;
|
||||
unsigned char b_alternate_setting;
|
||||
unsigned char b_num_endpoints;
|
||||
unsigned char b_interface_class;
|
||||
unsigned char b_interface_subclass;
|
||||
unsigned char b_interface_protocol;
|
||||
unsigned char i_interface;
|
||||
} usb_interface_descriptor_t;
|
||||
|
||||
/* USB_DT_ENDPOINT: Endpoint descriptor */
|
||||
typedef struct usb_endpoint_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned char b_endpoint_address;
|
||||
unsigned char bm_attributes;
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0x00
|
||||
#define USB_ENDPOINT_XFER_ISOC 0x01
|
||||
#define USB_ENDPOINT_XFER_BULK 0x02
|
||||
#define USB_ENDPOINT_XFER_INT 0x03
|
||||
unsigned short w_max_packet_size;
|
||||
unsigned char b_interval;
|
||||
} usb_endpoint_descriptor_t;
|
||||
|
||||
/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
|
||||
typedef struct usb_ss_ep_comp_descriptor {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
|
||||
unsigned char b_max_burst;
|
||||
unsigned char bm_attributes;
|
||||
unsigned short w_bytes_per_interval;
|
||||
} usb_ss_ep_comp_descriptor_t;
|
||||
|
||||
/* WUSB BOS Descriptor (Binary device Object Store) */
|
||||
typedef struct wusb_bos_desc {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
unsigned short w_total_length;
|
||||
unsigned char b_num_device_caps;
|
||||
} wusb_bos_desc_t;
|
||||
|
||||
#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02
|
||||
typedef struct usb_dev_cap_20_ext_desc {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
unsigned char b_devcapability_type;
|
||||
#define USB_20_EXT_LPM 0x02
|
||||
unsigned int bm_attributes;
|
||||
} usb_dev_cap_20_ext_desc_t;
|
||||
|
||||
#define USB_DEVICE_CAPABILITY_SS_USB 0x03
|
||||
typedef struct usb_dev_cap_ss_usb {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
unsigned char b_devcapability_type;
|
||||
#define USB_DC_SS_USB_LTM_CAPABLE 0x02
|
||||
unsigned char bm_attributes;
|
||||
#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01
|
||||
#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02
|
||||
#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04
|
||||
#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08
|
||||
unsigned int w_speeds_supported;
|
||||
unsigned char b_functionality_support;
|
||||
unsigned char b_u1dev_exit_lat;
|
||||
unsigned int w_u2dev_exit_lat;
|
||||
} usb_dev_cap_ss_usb_t;
|
||||
|
||||
#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04
|
||||
typedef struct usb_dev_cap_container_id {
|
||||
unsigned char b_length;
|
||||
unsigned char b_descriptor_type;
|
||||
unsigned char b_devcapability_type;
|
||||
unsigned char b_reserved;
|
||||
unsigned char container_id[16];
|
||||
} usb_dev_cap_container_id_t;
|
||||
#pragma pack()
|
||||
|
||||
#endif /* __USB3_H__ */
|
||||
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
#include "usb3_drv.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <cpu_func.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/lotus/usb.h>
|
||||
|
||||
unsigned int usb3_rd32(volatile unsigned int *addr)
|
||||
{
|
||||
return readl((unsigned int)addr);
|
||||
}
|
||||
|
||||
void usb3_wr32(volatile unsigned int *addr, unsigned int val)
|
||||
{
|
||||
writel(val, (unsigned int)addr);
|
||||
}
|
||||
|
||||
unsigned int usb3_is_host_mode(usb3_device_t *dev)
|
||||
{
|
||||
return usb3_rd32(&dev->core_global_regs->gsts) & 0x01;
|
||||
}
|
||||
|
||||
void pcd_epinit(usb3_pcd_t *pcd)
|
||||
{
|
||||
usb3_pcd_ep_t *ep;
|
||||
|
||||
/* Init EP0 */
|
||||
do {
|
||||
ep = &pcd->ep0;
|
||||
|
||||
ep->pcd = pcd;
|
||||
ep->stopped = 1;
|
||||
ep->is_in = 0;
|
||||
ep->active = 0;
|
||||
ep->phys = 0;
|
||||
ep->num = 0;
|
||||
ep->tx_fifo_num = 0;
|
||||
ep->out_ep_reg = &pcd->out_ep_regs[0];
|
||||
ep->in_ep_reg = &pcd->in_ep_regs[0];
|
||||
|
||||
ep->type = USB3_EP_TYPE_CONTROL;
|
||||
ep->maxburst = 0;
|
||||
ep->maxpacket = 64; /* 64 bytes */
|
||||
ep->send_zlp = 0;
|
||||
|
||||
ep->req.length = 0;
|
||||
ep->req.actual = 0;
|
||||
|
||||
pcd->ep0_req.length = 0;
|
||||
pcd->ep0_req.actual = 0;
|
||||
} while (0);
|
||||
|
||||
/* Init EP1-OUT */
|
||||
do {
|
||||
ep = &pcd->out_ep;
|
||||
|
||||
ep->pcd = pcd;
|
||||
ep->stopped = 1;
|
||||
ep->is_in = 0;
|
||||
ep->active = 0;
|
||||
ep->phys = USB3_BULK_OUT_EP << 1;
|
||||
ep->num = 1;
|
||||
ep->tx_fifo_num = 0;
|
||||
ep->out_ep_reg = &pcd->out_ep_regs[USB3_BULK_OUT_EP];
|
||||
|
||||
/* Bulk EP is activated */
|
||||
ep->type = USB3_EP_TYPE_BULK;
|
||||
ep->maxburst = 0;
|
||||
ep->maxpacket = USB2_FS_MAX_PACKET_SIZE;
|
||||
ep->send_zlp = 0;
|
||||
|
||||
ep->req.length = 0;
|
||||
ep->req.actual = 0;
|
||||
} while (0);
|
||||
|
||||
/* Init EP1-IN */
|
||||
do {
|
||||
ep = &pcd->in_ep;
|
||||
|
||||
ep->pcd = pcd;
|
||||
ep->stopped = 1;
|
||||
ep->is_in = 1;
|
||||
ep->active = 0;
|
||||
ep->phys = (USB3_BULK_IN_EP << 1) | 1;
|
||||
ep->num = 1;
|
||||
ep->tx_fifo_num = USB3_BULK_IN_EP;
|
||||
ep->in_ep_reg = &pcd->in_ep_regs[USB3_BULK_IN_EP];
|
||||
|
||||
/* Bulk EP is activated */
|
||||
ep->type = USB3_EP_TYPE_BULK;
|
||||
ep->maxburst = 0;
|
||||
ep->maxpacket = USB2_FS_MAX_PACKET_SIZE;
|
||||
ep->send_zlp = 0;
|
||||
|
||||
ep->req.length = 0;
|
||||
ep->req.actual = 0;
|
||||
} while (0);
|
||||
|
||||
pcd->ep0state = EP0_IDLE;
|
||||
}
|
||||
|
||||
void usb3_set_address(usb3_pcd_t *pcd, unsigned int addr)
|
||||
{
|
||||
unsigned int dcfg;
|
||||
|
||||
dcfg = usb3_rd32(&pcd->dev_global_regs->dcfg);
|
||||
dcfg &= ~USB3_DCFG_DEVADDR_BITS;
|
||||
dcfg |= addr << USB3_DCFG_DEVADDR_SHIFT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dcfg, dcfg);
|
||||
}
|
||||
|
||||
#define RAM_WIDTH 8
|
||||
#define RAM_RX_DEPTH 4096
|
||||
#define RAM_TX0_DEPTH 1024
|
||||
#define RAM_TX1_DEPTH 2048
|
||||
void usb3_set_tx_fifo_size(usb3_device_t *dev)
|
||||
{
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
unsigned int prev_start = 0;
|
||||
/* Set 1K for tx fifo0 */
|
||||
usb3_wr32(&global_regs->gtxfifosiz[0],
|
||||
((RAM_TX0_DEPTH / RAM_WIDTH) << USB3_FIFOSZ_DEPTH_SHIFT) |
|
||||
(prev_start << USB3_FIFOSZ_STARTADDR_SHIFT));
|
||||
|
||||
prev_start += RAM_TX0_DEPTH / RAM_WIDTH;
|
||||
/* Set 2K for tx fifo1 */
|
||||
usb3_wr32(&global_regs->gtxfifosiz[1],
|
||||
((RAM_TX1_DEPTH / RAM_WIDTH) << USB3_FIFOSZ_DEPTH_SHIFT) |
|
||||
(prev_start << USB3_FIFOSZ_STARTADDR_SHIFT));
|
||||
}
|
||||
|
||||
void usb3_set_rx_fifo_size(usb3_device_t *dev)
|
||||
{
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
/* Set 4K for rx fifo */
|
||||
usb3_wr32(&global_regs->grxfifosiz[0],
|
||||
((RAM_RX_DEPTH / RAM_WIDTH) << USB3_FIFOSZ_DEPTH_SHIFT));
|
||||
}
|
||||
|
||||
void usb3_resume_usb2_phy(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int usb2phycfg;
|
||||
usb3_device_t *dev = pcd->usb3_dev;
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
|
||||
usb2phycfg = usb3_rd32(&global_regs->gusb2phycfg[0]);
|
||||
usb2phycfg |= USB3_USB2PHYCFG_SUS_PHY_BIT;
|
||||
usb3_wr32(&global_regs->gusb2phycfg[0], usb2phycfg);
|
||||
}
|
||||
|
||||
void usb3_resume_usb3_phy(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int pipectl;
|
||||
usb3_device_t *dev = pcd->usb3_dev;
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
|
||||
pipectl = usb3_rd32(&global_regs->gusb3pipectl[0]);
|
||||
pipectl |= USB3_PIPECTL_SUS_PHY_BIT;
|
||||
usb3_wr32(&global_regs->gusb3pipectl[0], pipectl);
|
||||
}
|
||||
|
||||
void usb3_accept_u1(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int dctl;
|
||||
|
||||
dctl = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
dctl |= USB3_DCTL_ACCEPT_U1_EN_BIT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dctl, dctl);
|
||||
}
|
||||
|
||||
void usb3_accept_u2(usb3_pcd_t *pcd) {}
|
||||
|
||||
void usb3_enable_u1(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int dctl;
|
||||
|
||||
dctl = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
dctl |= USB3_DCTL_INIT_U1_EN_BIT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dctl, dctl);
|
||||
}
|
||||
|
||||
void usb3_enable_u2(usb3_pcd_t *pcd) {}
|
||||
|
||||
void usb3_disable_u1(usb3_pcd_t *pcd) {}
|
||||
|
||||
void usb3_disable_u2(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int dctl;
|
||||
|
||||
dctl = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
dctl &= ~USB3_DCTL_INIT_U2_EN_BIT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dctl, dctl);
|
||||
}
|
||||
|
||||
unsigned int usb3_u1_enabled(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int dctl;
|
||||
|
||||
dctl = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
return !!(dctl & USB3_DCTL_INIT_U1_EN_BIT);
|
||||
}
|
||||
|
||||
unsigned int usb3_u2_enabled(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int dctl;
|
||||
|
||||
dctl = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
return !!(dctl & USB3_DCTL_INIT_U2_EN_BIT);
|
||||
}
|
||||
|
||||
void usb3_dep_cstall(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg)
|
||||
{
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd, USB3_EPCMD_CLR_STALL | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
void usb3_dep_sstall(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg)
|
||||
{
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd, USB3_EPCMD_SET_STALL | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
unsigned int handshake(usb3_device_t *dev, volatile unsigned int *ptr,
|
||||
unsigned int mask, unsigned int done)
|
||||
{
|
||||
unsigned int usec = 1000;
|
||||
unsigned int result;
|
||||
|
||||
do {
|
||||
result = usb3_rd32(ptr);
|
||||
if ((result & mask) == done)
|
||||
return 1;
|
||||
|
||||
udelay(1);
|
||||
usec -= 1;
|
||||
} while (usec > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb3_fill_desc(usb3_dma_desc_t *desc, phys_addr_t dma_addr,
|
||||
unsigned int dma_len, unsigned int stream, unsigned int type,
|
||||
unsigned int ctrlbits, int own)
|
||||
{
|
||||
dma_addr = map_to_dma_addr(dma_addr);
|
||||
|
||||
desc->bptl = (phys_addr_t)(dma_addr & 0xffffffffU);
|
||||
desc->bpth = 0;
|
||||
desc->status &= ~USB3_DSCSTS_XFRCNT_BITS;
|
||||
desc->status |= ((dma_len << USB3_DSCSTS_XFRCNT_SHIFT) &
|
||||
USB3_DSCSTS_XFRCNT_BITS);
|
||||
/* Note: If type is 0, leave original control bits intact (for isoc) */
|
||||
if (type)
|
||||
desc->control = type << USB3_DSCCTL_TRBCTL_SHIFT;
|
||||
|
||||
desc->control |= (stream << USB3_DSCCTL_STRMID_SOFN_SHIFT) | ctrlbits;
|
||||
|
||||
/* Must do this last! */
|
||||
if (own)
|
||||
desc->control |= USB3_DSCCTL_HWO_BIT;
|
||||
flush_dcache_all();
|
||||
}
|
||||
|
||||
|
||||
void usb3_dep_startnewcfg(usb3_pcd_t *pcd,
|
||||
usb3_dev_ep_regs_t *ep_reg, unsigned int rsrcidx)
|
||||
{
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd,
|
||||
(rsrcidx << USB3_EPCMD_XFER_RSRC_IDX_SHIFT) |
|
||||
USB3_EPCMD_START_NEW_CFG | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
void usb3_dep_cfg(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int depcfg0, unsigned int depcfg1, unsigned int depcfg2)
|
||||
{
|
||||
/* Set param 2 */
|
||||
usb3_wr32(&ep_reg->depcmdpar2, depcfg2);
|
||||
|
||||
/* Set param 1 */
|
||||
usb3_wr32(&ep_reg->depcmdpar1, depcfg1);
|
||||
|
||||
/* Set param 0 */
|
||||
usb3_wr32(&ep_reg->depcmdpar0, depcfg0); /* mm 0x1018c808 0x200 */
|
||||
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd, USB3_EPCMD_SET_EP_CFG | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
void usb3_dep_xfercfg(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int depstrmcfg)
|
||||
{
|
||||
/* Set param 0 */
|
||||
usb3_wr32(&ep_reg->depcmdpar0, depstrmcfg);
|
||||
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd, USB3_EPCMD_SET_XFER_CFG |
|
||||
USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
unsigned char usb3_dep_startxfer(usb3_pcd_t *pcd,
|
||||
usb3_dev_ep_regs_t *ep_reg, phys_addr_t dma_addr,
|
||||
unsigned int stream_or_uf)
|
||||
{
|
||||
unsigned int depcmd;
|
||||
|
||||
dma_addr = map_to_dma_addr(dma_addr);
|
||||
|
||||
/* Set param 1 */
|
||||
usb3_wr32(&ep_reg->depcmdpar1, dma_addr & 0xffffffffU);
|
||||
|
||||
/* Set param 0 */
|
||||
usb3_wr32(&ep_reg->depcmdpar0, 0);
|
||||
|
||||
usb3_wr32(&ep_reg->depcmd,
|
||||
(stream_or_uf << USB3_EPCMD_STR_NUM_OR_UF_SHIFT) |
|
||||
USB3_EPCMD_START_XFER | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
|
||||
depcmd = usb3_rd32(&ep_reg->depcmd);
|
||||
|
||||
return (depcmd >> USB3_EPCMD_XFER_RSRC_IDX_SHIFT) &
|
||||
(USB3_EPCMD_XFER_RSRC_IDX_BITS >> USB3_EPCMD_XFER_RSRC_IDX_SHIFT);
|
||||
}
|
||||
|
||||
void usb3_dep_updatexfer(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int tri)
|
||||
{
|
||||
/* Start the command */
|
||||
usb3_wr32(&ep_reg->depcmd, (tri << USB3_EPCMD_XFER_RSRC_IDX_SHIFT) |
|
||||
USB3_EPCMD_UPDATE_XFER | USB3_EPCMD_ACT_BIT);
|
||||
|
||||
/* Wait for command completion */
|
||||
handshake(pcd->usb3_dev, &ep_reg->depcmd, USB3_EPCMD_ACT_BIT, 0);
|
||||
}
|
||||
|
||||
void usb3_enable_ep(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep)
|
||||
{
|
||||
unsigned int ep_index_num, dalepena;
|
||||
|
||||
ep_index_num = ep->num * 0x2;
|
||||
if (ep->is_in)
|
||||
ep_index_num += 1;
|
||||
|
||||
dalepena = usb3_rd32(&pcd->dev_global_regs->dalepena);
|
||||
/* If we have already enabled this EP, leave it alone
|
||||
* (shouldn't happen)
|
||||
*/
|
||||
if (dalepena & (1 << ep_index_num))
|
||||
return;
|
||||
|
||||
dalepena |= 1 << ep_index_num;
|
||||
usb3_wr32(&pcd->dev_global_regs->dalepena, dalepena);
|
||||
}
|
||||
|
||||
void usb3_dis_usb2_suspend(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int usb2phycfg;
|
||||
usb3_device_t *dev = pcd->usb3_dev;
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
|
||||
if (pcd->speed == USB_SPEED_SUPER)
|
||||
return;
|
||||
|
||||
usb2phycfg = usb3_rd32(&global_regs->gusb2phycfg[0]);
|
||||
usb2phycfg &= ~USB3_USB2PHYCFG_SUS_PHY_BIT;
|
||||
usb2phycfg &= ~USB3_USB2PHYCFG_ENBL_SLP_M_BIT;
|
||||
usb3_wr32(&global_regs->gusb2phycfg[0], usb2phycfg);
|
||||
}
|
||||
|
||||
void usb3_ep0_activate(usb3_pcd_t *pcd)
|
||||
{
|
||||
unsigned int diepcfg0, doepcfg0, diepcfg1, doepcfg1;
|
||||
unsigned int diepcfg2 = 0;
|
||||
unsigned int doepcfg2 = 0;
|
||||
usb3_dev_ep_regs_t *ep_reg;
|
||||
|
||||
diepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
diepcfg1 =
|
||||
USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT |
|
||||
USB3_EPCFG1_XFER_NRDY_BIT | USB3_EPCFG1_EP_DIR_BIT;
|
||||
|
||||
doepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
doepcfg1 = USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT |
|
||||
USB3_EPCFG1_XFER_NRDY_BIT;
|
||||
|
||||
/* Default to MPS of 512 (will reconfigure
|
||||
* after ConnectDone event)
|
||||
*/
|
||||
diepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT;
|
||||
/* Default to MPS of 512 (will reconfigure
|
||||
* after ConnectDone event)
|
||||
*/
|
||||
doepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT;
|
||||
|
||||
diepcfg0 |= pcd->ep0.tx_fifo_num << USB3_EPCFG0_TXFNUM_SHIFT;
|
||||
|
||||
/* Issue "DEPCFG" command to EP0-OUT */
|
||||
|
||||
ep_reg = &pcd->out_ep_regs[0];
|
||||
usb3_dis_usb2_suspend(pcd); /* mm 0x1018c200 0x102400 */
|
||||
/* If core is version 1.09a or later */
|
||||
/* Must issue DEPSTRTNEWCFG command first */
|
||||
usb3_dep_startnewcfg(pcd, ep_reg, 0);
|
||||
|
||||
usb3_dep_cfg(pcd, ep_reg, doepcfg0, doepcfg1, doepcfg2);
|
||||
|
||||
/* Issue "DEPSTRMCFG" command to EP0-OUT */
|
||||
|
||||
/* One stream */
|
||||
usb3_dep_xfercfg(pcd, ep_reg, 1);
|
||||
|
||||
/* Issue "DEPCFG" command to EP0-IN */
|
||||
|
||||
ep_reg = &pcd->in_ep_regs[0];
|
||||
usb3_dep_cfg(pcd, ep_reg, diepcfg0, diepcfg1, diepcfg2);
|
||||
|
||||
/* Issue "DEPSTRMCFG" command to EP0-IN */
|
||||
|
||||
/* One stream */
|
||||
usb3_dep_xfercfg(pcd, ep_reg, 1);
|
||||
|
||||
pcd->ep0.active = 1;
|
||||
}
|
||||
|
||||
void usb3_ep_activate(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep)
|
||||
{
|
||||
usb3_dev_ep_regs_t *ep_reg, *ep0_reg;
|
||||
unsigned int depcfg0;
|
||||
unsigned int depcfg1;
|
||||
unsigned int depcfg2 = 0;
|
||||
/*
|
||||
* Get the appropriate EP registers
|
||||
*/
|
||||
if (ep->is_in)
|
||||
ep_reg = ep->in_ep_reg;
|
||||
else
|
||||
ep_reg = ep->out_ep_reg;
|
||||
|
||||
/* If this is first EP enable (ie. start of a new configuration) */
|
||||
if (!pcd->eps_enabled) {
|
||||
pcd->eps_enabled = 1;
|
||||
|
||||
/* NOTE: When setting a new configuration, we must issue a
|
||||
* "DEPCFG" command to physical EP1 (logical EP0-IN) first.
|
||||
* This resets the core's Tx FIFO mapping table
|
||||
*/
|
||||
depcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
depcfg0 |= USB3_CFG_ACTION_MODIFY <<
|
||||
USB3_EPCFG0_CFG_ACTION_SHIFT;
|
||||
depcfg1 = USB3_EPCFG1_XFER_CMPL_BIT |
|
||||
USB3_EPCFG1_XFER_NRDY_BIT | USB3_EPCFG1_EP_DIR_BIT;
|
||||
|
||||
switch (pcd->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
/* Default to MPS of 512 (will reconfigure
|
||||
* after ConnectDone event)
|
||||
*/
|
||||
depcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT;
|
||||
break;
|
||||
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_FULL:
|
||||
/* Default to MPS of 64 (will reconfigure
|
||||
* after ConnectDone event)
|
||||
*/
|
||||
depcfg0 |= 64 << USB3_EPCFG0_MPS_SHIFT;
|
||||
break;
|
||||
|
||||
case USB_SPEED_LOW:
|
||||
/* Default to MPS of 8 (will reconfigure
|
||||
* after ConnectDone event)
|
||||
*/
|
||||
depcfg0 |= 8 << USB3_EPCFG0_MPS_SHIFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ep0_reg = &pcd->in_ep_regs[0];
|
||||
usb3_dep_cfg(pcd, ep0_reg, depcfg0, depcfg1, 0);
|
||||
|
||||
/* If core is version 1.09a or later */
|
||||
/* Must issue DEPSTRTNEWCFG command first */
|
||||
ep0_reg = &pcd->out_ep_regs[0];
|
||||
usb3_dep_startnewcfg(pcd, ep0_reg, 0x2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue "DEPCFG" command to EP
|
||||
*/
|
||||
depcfg0 = ep->type << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
depcfg0 |= ep->maxpacket << USB3_EPCFG0_MPS_SHIFT;
|
||||
|
||||
if (ep->is_in)
|
||||
depcfg0 |= ep->tx_fifo_num << USB3_EPCFG0_TXFNUM_SHIFT;
|
||||
|
||||
depcfg0 |= ep->maxburst << USB3_EPCFG0_BRSTSIZ_SHIFT;
|
||||
|
||||
depcfg1 = ep->num << USB3_EPCFG1_EP_NUM_SHIFT;
|
||||
|
||||
if (ep->is_in)
|
||||
depcfg1 |= USB3_EPCFG1_EP_DIR_BIT;
|
||||
|
||||
depcfg1 |= USB3_EPCFG1_XFER_CMPL_BIT;
|
||||
|
||||
usb3_dep_cfg(pcd, ep_reg, depcfg0, depcfg1, depcfg2);
|
||||
|
||||
/*
|
||||
* Issue "DEPSTRMCFG" command to EP
|
||||
*/
|
||||
/* Setting 1 stream resource */
|
||||
usb3_dep_xfercfg(pcd, ep_reg, 1);
|
||||
|
||||
/* Enable EP in DALEPENA reg */
|
||||
usb3_enable_ep(pcd, ep);
|
||||
|
||||
ep->active = 1;
|
||||
}
|
||||
|
||||
void usb3_ep0_out_start(usb3_pcd_t *pcd)
|
||||
{
|
||||
usb3_dev_ep_regs_t *ep_reg;
|
||||
usb3_dma_desc_t *desc;
|
||||
unsigned int desc_dma;
|
||||
unsigned char tri;
|
||||
|
||||
/* Get the SETUP packet DMA Descriptor (TRB) */
|
||||
desc = pcd->ep0_setup_desc;
|
||||
desc_dma = (phys_addr_t)pcd->ep0_setup_desc;
|
||||
|
||||
/* DMA Descriptor setup */
|
||||
usb3_fill_desc(desc, (phys_addr_t)pcd->ep0_setup_pkt,
|
||||
pcd->ep0.maxpacket, 0, USB3_DSCCTL_TRBCTL_SETUP,
|
||||
USB3_DSCCTL_IOC_BIT | USB3_DSCCTL_ISP_BIT |
|
||||
USB3_DSCCTL_LST_BIT, 1);
|
||||
|
||||
ep_reg = &pcd->out_ep_regs[0];
|
||||
|
||||
/* Issue "DEPSTRTXFER" command to EP0-OUT */
|
||||
tri = usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0);
|
||||
pcd->ep0.tri_out = tri;
|
||||
}
|
||||
|
||||
void usb3_core_dev_init(usb3_device_t *dev)
|
||||
{
|
||||
usb3_core_global_regs_t *global_regs = dev->core_global_regs;
|
||||
usb3_pcd_t *pcd = &dev->pcd;
|
||||
usb3_dev_global_regs_t *dev_global_regs = pcd->dev_global_regs;
|
||||
unsigned int temp_t;
|
||||
|
||||
/* Soft-reset the core */
|
||||
do {
|
||||
temp_t = usb3_rd32(&dev_global_regs->dctl);
|
||||
temp_t &= ~USB3_DCTL_RUN_STOP_BIT;
|
||||
temp_t |= USB3_DCTL_CSFT_RST_BIT;
|
||||
usb3_wr32(&dev_global_regs->dctl, temp_t);
|
||||
do {
|
||||
udelay(1);
|
||||
temp_t = usb3_rd32(&dev_global_regs->dctl);
|
||||
} while (temp_t & USB3_DCTL_CSFT_RST_BIT);
|
||||
|
||||
/* Wait for at least 3 PHY clocks */
|
||||
udelay(1);
|
||||
} while (0);
|
||||
|
||||
pcd->link_state = 0;
|
||||
|
||||
temp_t = 0x13802004;
|
||||
usb3_wr32(&global_regs->gctl, temp_t);
|
||||
|
||||
usb_info("evnt buffer addr: 0x%x\n", (u32)dev->event_buf);
|
||||
|
||||
usb3_init_eventbuf(dev, USB3_EVENT_BUF_SIZE,
|
||||
(phys_addr_t)dev->event_buf);
|
||||
dev->event_ptr = dev->event_buf;
|
||||
|
||||
/* Set speed to Super */
|
||||
temp_t = usb3_rd32(&pcd->dev_global_regs->dcfg);
|
||||
temp_t &= ~(USB3_DCFG_DEVSPD_BITS << USB3_DCFG_DEVSPD_SHIFT);
|
||||
temp_t |= USB3_SPEED_HS_PHY_30MHZ_OR_60MHZ << USB3_DCFG_DEVSPD_SHIFT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dcfg, temp_t);
|
||||
|
||||
/* If LPM enable was requested */
|
||||
temp_t = usb3_rd32(&pcd->dev_global_regs->dcfg);
|
||||
temp_t |= USB3_DCFG_LPM_CAP_BIT;
|
||||
/* mm 0x1018c700 0x480804 */
|
||||
usb3_wr32(&pcd->dev_global_regs->dcfg, temp_t);
|
||||
|
||||
/* Set Nump */
|
||||
temp_t = usb3_rd32(&pcd->dev_global_regs->dcfg);
|
||||
temp_t &= ~USB3_DCFG_NUM_RCV_BUF_BITS;
|
||||
temp_t |= 0x10 << USB3_DCFG_NUM_RCV_BUF_SHIFT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dcfg, temp_t);
|
||||
|
||||
usb3_set_address(pcd, 0);
|
||||
|
||||
/* disable Phy suspend */
|
||||
usb3_resume_usb3_phy(pcd);
|
||||
/* mm 0x1018c200 0x102540 */
|
||||
usb3_resume_usb2_phy(pcd);
|
||||
/* Enable Global and Device interrupts */
|
||||
usb3_enable_device_interrupts(dev);
|
||||
|
||||
/* Activate EP0 */
|
||||
usb3_ep0_activate(pcd);
|
||||
|
||||
/* Start EP0 to receive SETUP packets */
|
||||
usb3_ep0_out_start(pcd);
|
||||
|
||||
/* Enable EP0-OUT/IN in DALEPENA register */
|
||||
usb3_wr32(&pcd->dev_global_regs->dalepena, 0x3);
|
||||
|
||||
/* Set Run/Stop bit */
|
||||
temp_t = usb3_rd32(&pcd->dev_global_regs->dctl);
|
||||
temp_t |= USB3_DCTL_RUN_STOP_BIT;
|
||||
usb3_wr32(&pcd->dev_global_regs->dctl, temp_t);
|
||||
}
|
||||
|
||||
void usb3_pcd_init(usb3_device_t *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = &dev->pcd;
|
||||
|
||||
pcd->usb3_dev = dev;
|
||||
pcd->speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
/* Initialize EP structures */
|
||||
pcd_epinit(pcd);
|
||||
|
||||
/* Initialize the Core (also enables interrupts
|
||||
* and sets Run/Stop bit)
|
||||
*/
|
||||
usb3_core_dev_init(dev);
|
||||
}
|
||||
|
||||
void usb3_common_init(usb3_device_t *dev, volatile unsigned char *base)
|
||||
{
|
||||
usb3_pcd_t *pcd;
|
||||
|
||||
dev->core_global_regs =
|
||||
(usb3_core_global_regs_t *)(base + USB3_CORE_GLOBAL_REG_OFFSET);
|
||||
|
||||
pcd = &dev->pcd;
|
||||
|
||||
pcd->dev_global_regs =
|
||||
(usb3_dev_global_regs_t *)(base + USB3_DEV_GLOBAL_REG_OFFSET);
|
||||
pcd->out_ep_regs =
|
||||
(usb3_dev_ep_regs_t *)(base + USB3_DEV_OUT_EP_REG_OFFSET);
|
||||
pcd->in_ep_regs =
|
||||
(usb3_dev_ep_regs_t *)(base + USB3_DEV_IN_EP_REG_OFFSET);
|
||||
}
|
||||
|
||||
void usb3_init(usb3_device_t *dev)
|
||||
{
|
||||
/* Init the PCD (also enables interrupts and sets Run/Stop bit) */
|
||||
usb3_pcd_init(dev);
|
||||
}
|
||||
|
||||
static unsigned char string_manu[] = {'B', 0, 'o', 0, 'o', 0, 't', 0};
|
||||
static unsigned char string_prod[] = {'U', 0, 'S', 0, 'B', 0, 'B', 0,
|
||||
'u', 0, 'r', 0, 'n', 0};
|
||||
#define USB_INIT_DEVICE 1
|
||||
static int usb3_driver_init(const char *manu_suffix)
|
||||
{
|
||||
volatile unsigned char *reg;
|
||||
usb3_device_t *usb3_dev;
|
||||
struct usb_device_descriptor *usb3_dev_desc;
|
||||
|
||||
usb3_dev = malloc(sizeof(usb3_device_t));
|
||||
if (!usb3_dev) {
|
||||
debug("usb3_dev: out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset((void *)usb3_dev, 0, sizeof(usb3_device_t));
|
||||
usb3_dev_desc = malloc(sizeof(struct usb_device_descriptor));
|
||||
if (usb3_dev_desc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
usb3_pcd_t *pcd = &usb3_dev->pcd;
|
||||
usb3_pcd_ep_t *ep = &pcd->in_ep;
|
||||
usb3_pcd_req_t *req = &ep->req;
|
||||
|
||||
req->bufdma = (unsigned char *)malloc(512); /* 512 bytes */
|
||||
usb_info("size of usb3_dev %d\n", sizeof(*usb3_dev));
|
||||
usb3_dev->base = (volatile unsigned char *)USB2_CTRL_REG_BASE;
|
||||
usb3_dev->string_manu_len = sizeof(string_manu);
|
||||
usb3_dev->string_prod_len = sizeof(string_prod);
|
||||
usb3_dev->dev_desc = usb3_dev_desc;
|
||||
memcpy(usb3_dev->string_manu, string_manu, usb3_dev->string_manu_len);
|
||||
memcpy(usb3_dev->string_prod, string_prod, usb3_dev->string_prod_len);
|
||||
strncpy(usb3_dev->manu_suffix, manu_suffix,
|
||||
sizeof(usb3_dev->manu_suffix));
|
||||
usb3_dev->pcd.ep0_setup_desc = (usb3_dma_desc_t *)((phys_addr_t)
|
||||
(usb3_dev->pcd.ep0_setup + 0xf) & (unsigned int)(~0xf));
|
||||
usb3_dev->pcd.ep0_in_desc = (usb3_dma_desc_t *)
|
||||
((phys_addr_t)(usb3_dev->pcd.ep0_in + 0xf) &
|
||||
(unsigned int)(~0xf));
|
||||
usb3_dev->pcd.ep0_out_desc = (usb3_dma_desc_t *)
|
||||
((phys_addr_t)(usb3_dev->pcd.ep0_out + 0xf) &
|
||||
(unsigned int)(~0xf));
|
||||
usb3_dev->pcd.in_ep.ep_desc = (usb3_dma_desc_t *)
|
||||
((phys_addr_t)(usb3_dev->pcd.in_ep.epx_desc + 0xf) &
|
||||
(unsigned int)(~0xf));
|
||||
usb3_dev->pcd.out_ep.ep_desc = (usb3_dma_desc_t *)
|
||||
((phys_addr_t)(usb3_dev->pcd.out_ep.epx_desc + 0xf) &
|
||||
(unsigned int)(~0xf));
|
||||
|
||||
/* Release usb3.0 controller */
|
||||
phy_usb_init(USB_INIT_DEVICE);
|
||||
|
||||
/* Get usb3.0 version number */
|
||||
reg = usb3_dev->base + USB3_CORE_REG_BASE +
|
||||
USB3_CORE_GSNPSID_REG_OFFSET;
|
||||
usb3_dev->snpsid = usb3_rd32((volatile unsigned int *)reg);
|
||||
|
||||
/* Initialize usb3.0 core */
|
||||
usb3_common_init(usb3_dev, usb3_dev->base + USB3_CORE_REG_BASE);
|
||||
|
||||
/* Initialize usb3.0 pcd */
|
||||
usb3_init(usb3_dev);
|
||||
|
||||
usb_info("usb init done\n");
|
||||
for (;;)
|
||||
usb3_handle_event(usb3_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface func for download the mirror, address from return.
|
||||
*/
|
||||
void udc_connect(void)
|
||||
{
|
||||
dcache_disable();
|
||||
if (usb3_driver_init("") < 0)
|
||||
usb_info("usb3 driver init error\n");
|
||||
dcache_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(udc_connect);
|
||||
|
||||
|
||||
/*
|
||||
* Interface func for download the mirror, address from return.
|
||||
*/
|
||||
void usbburn_connect(const char *manu_suffix)
|
||||
{
|
||||
dcache_disable();
|
||||
if (usb3_driver_init(manu_suffix) < 0)
|
||||
usb_info("usb3 driver init error\n");
|
||||
dcache_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(usbburn_connect);
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __USB3_DRIVER_H__
|
||||
#define __USB3_DRIVER_H__
|
||||
|
||||
#include "sys.h"
|
||||
#include "usb3.h"
|
||||
#include "usb3_hw.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* time limit of waiting for key enents */
|
||||
#define USB_WAIT_FOR_ENUM_DONE_TIME_MS (300 * 1000)
|
||||
#define USB_WAIT_FOR_RX_NEXT_TIME_MS (60 * 1000)
|
||||
|
||||
enum usb_error_type {
|
||||
USB_RX_NEXT_TIMEOUT = -5,
|
||||
USB_ENUM_DONE_TIMEOUT = -3,
|
||||
USB_PROCESS_ERR = -1,
|
||||
USB_NO_ERR = 0,
|
||||
};
|
||||
|
||||
struct usb_data_handle {
|
||||
unsigned int u_file_type;
|
||||
unsigned int u_file_address;
|
||||
unsigned int u_file_length;
|
||||
|
||||
unsigned int is_rx_start;
|
||||
|
||||
unsigned int init_time_stamp;
|
||||
unsigned int rx_time_stamp;
|
||||
};
|
||||
|
||||
#define usb_info(format, arg...) debug_printf("[USBINFO]" format, ##arg)
|
||||
#define usb_err(format, arg...) debug_printf("[USBERR]" format, ##arg)
|
||||
|
||||
typedef enum pcd_state {
|
||||
USB3_STATE_UNCONNECTED, /* no host */
|
||||
USB3_STATE_DEFAULT,
|
||||
USB3_STATE_ADDRESSED,
|
||||
USB3_STATE_CONFIGURED,
|
||||
} pcdstate_e;
|
||||
|
||||
typedef enum ep0_state {
|
||||
EP0_IDLE,
|
||||
EP0_IN_DATA_PHASE,
|
||||
EP0_OUT_DATA_PHASE,
|
||||
EP0_IN_WAIT_NRDY,
|
||||
EP0_OUT_WAIT_NRDY,
|
||||
EP0_IN_STATUS_PHASE,
|
||||
EP0_OUT_STATUS_PHASE,
|
||||
EP0_STALL,
|
||||
} ep0state_e;
|
||||
|
||||
typedef union usb_setup_pkt {
|
||||
usb_device_request_t req;
|
||||
unsigned int d32[2];
|
||||
unsigned char d8[8];
|
||||
} usb_setup_pkt_t;
|
||||
|
||||
typedef struct usb3_pcd_req {
|
||||
usb3_dma_desc_t *trb;
|
||||
phys_addr_t trbdma;
|
||||
|
||||
unsigned int length;
|
||||
unsigned int actual;
|
||||
|
||||
unsigned char *bufdma;
|
||||
void (*complete)(void *dev);
|
||||
} usb3_pcd_req_t;
|
||||
|
||||
typedef struct usb3_pcd_ep {
|
||||
struct usb3_pcd *pcd;
|
||||
|
||||
usb3_dev_ep_regs_t *out_ep_reg;
|
||||
usb3_dev_ep_regs_t *in_ep_reg;
|
||||
|
||||
unsigned char phys;
|
||||
unsigned char num;
|
||||
unsigned char type;
|
||||
unsigned char maxburst;
|
||||
unsigned short maxpacket;
|
||||
/* Tx FIFO # for IN EPs */
|
||||
unsigned char tx_fifo_num;
|
||||
|
||||
/* The Transfer Resource Index from the Start Transfer command */
|
||||
unsigned char tri_out;
|
||||
unsigned char tri_in;
|
||||
|
||||
unsigned char stopped;
|
||||
/* Send ZLP */
|
||||
unsigned char send_zlp;
|
||||
/* True if 3-stage control transfer */
|
||||
unsigned char three_stage;
|
||||
/* True if transfer has been started on EP */
|
||||
unsigned char xfer_started;
|
||||
/* EP direction 0 = OUT */
|
||||
unsigned char is_in;
|
||||
/* True if endpoint is active */
|
||||
unsigned char active;
|
||||
/* Initial data pid of bulk endpoint */
|
||||
unsigned char data_pid_start;
|
||||
|
||||
/* ep_desc (excluding ep0) */
|
||||
usb3_dma_desc_t *ep_desc;
|
||||
|
||||
/* TRB descriptor must be aligned to 16 bytes */
|
||||
unsigned char epx_desc[32];
|
||||
|
||||
/* request (excluding ep0) */
|
||||
usb3_pcd_req_t req;
|
||||
} usb3_pcd_ep_t;
|
||||
|
||||
typedef struct usb3_pcd {
|
||||
struct usb3_device *usb3_dev;
|
||||
|
||||
signed int link_state;
|
||||
pcdstate_e state;
|
||||
unsigned char new_config;
|
||||
ep0state_e ep0state;
|
||||
|
||||
unsigned int eps_enabled;
|
||||
unsigned int ltm_enable;
|
||||
|
||||
usb3_pcd_ep_t ep0;
|
||||
usb3_pcd_ep_t out_ep;
|
||||
usb3_pcd_ep_t in_ep;
|
||||
|
||||
usb3_dev_global_regs_t *dev_global_regs;
|
||||
usb3_dev_ep_regs_t *out_ep_regs;
|
||||
usb3_dev_ep_regs_t *in_ep_regs;
|
||||
|
||||
usb3_pcd_req_t ep0_req;
|
||||
|
||||
unsigned char speed;
|
||||
|
||||
usb3_dma_desc_t *ep0_setup_desc;
|
||||
usb3_dma_desc_t *ep0_in_desc;
|
||||
usb3_dma_desc_t *ep0_out_desc;
|
||||
|
||||
/* TRB descriptor must be aligned to 16 bytes */
|
||||
unsigned char ep0_setup[32];
|
||||
unsigned char ep0_in[32];
|
||||
unsigned char ep0_out[32];
|
||||
|
||||
usb_setup_pkt_t ep0_setup_pkt[5];
|
||||
|
||||
#define USB3_STATUS_BUF_SIZE 512
|
||||
unsigned char ep0_status_buf[USB3_STATUS_BUF_SIZE];
|
||||
|
||||
#define USB3_BULK_BUF_SIZE 512
|
||||
unsigned char ss_bulk_buf[USB3_BULK_BUF_SIZE];
|
||||
|
||||
unsigned int file_type;
|
||||
unsigned int file_address;
|
||||
unsigned int file_capacity;
|
||||
unsigned int file_total_frame;
|
||||
unsigned int file_curr_frame;
|
||||
unsigned int file_next_frame;
|
||||
unsigned int file_received;
|
||||
unsigned int file_complete;
|
||||
} usb3_pcd_t;
|
||||
|
||||
#define usb3_pcd_ep_to_pcd(pcd_ep) ((pcd_ep)->usb3_pcd_ep_t.pcd)
|
||||
#define usb3_pcd_ep_num(pcd_ep) ((pcd_ep)->usb3_pcd_ep_t.num)
|
||||
#define usb3_pcd_ep_type(pcd_ep) ((pcd_ep)->usb3_pcd_ep_t.type)
|
||||
#define usb3_pcd_ep_is_in(pcd_ep) ((pcd_ep)->usb3_pcd_ep_t.is_in)
|
||||
|
||||
#define dwc_usb3_is_hwo(desc) ((desc)->control & USB3_DSCCTL_HWO_BIT)
|
||||
#define dwc_usb3_is_ioc(desc) ((desc)->control & USB3_DSCCTL_IOC_BIT)
|
||||
|
||||
#define usb3_get_xfercnt(desc) \
|
||||
(((desc)->status >> USB3_DSCSTS_XFRCNT_SHIFT) & \
|
||||
(USB3_DSCSTS_XFRCNT_BITS >> USB3_DSCSTS_XFRCNT_SHIFT))
|
||||
#define usb3_get_xfersts(desc) \
|
||||
(((desc)->status >> USB3_DSCSTS_TRBRSP_SHIFT) & \
|
||||
(USB3_DSCSTS_TRBRSP_BITS >> USB3_DSCSTS_TRBRSP_SHIFT))
|
||||
|
||||
#define map_to_dma_addr(addr) ((addr))
|
||||
//((addr) + (REG_BASE_LP_RAM_ACORE - REG_BASE_LP_RAM))
|
||||
|
||||
typedef struct usb3_device {
|
||||
volatile unsigned char *base;
|
||||
void *dev_desc;
|
||||
unsigned char string_manu[32];
|
||||
unsigned char string_prod[32];
|
||||
unsigned int string_manu_len;
|
||||
unsigned int string_prod_len;
|
||||
|
||||
char manu_suffix[16];
|
||||
|
||||
usb3_pcd_t pcd;
|
||||
unsigned int snpsid;
|
||||
usb3_core_global_regs_t *core_global_regs;
|
||||
|
||||
#define USB3_EVENT_BUF_SIZE 256
|
||||
unsigned int event_buf[USB3_EVENT_BUF_SIZE];
|
||||
unsigned int *event_ptr;
|
||||
struct usb_data_handle *p_handle;
|
||||
} usb3_device_t;
|
||||
|
||||
unsigned int usb3_rd32(volatile unsigned int *addr);
|
||||
void usb3_wr32(volatile unsigned int *addr, unsigned int val);
|
||||
void usb3_set_address(usb3_pcd_t *pcd, unsigned int addr);
|
||||
void usb3_accept_u1(usb3_pcd_t *pcd);
|
||||
void usb3_accept_u2(usb3_pcd_t *pcd);
|
||||
void usb3_enable_u1(usb3_pcd_t *pcd);
|
||||
void usb3_enable_u2(usb3_pcd_t *pcd);
|
||||
void usb3_disable_u1(usb3_pcd_t *pcd);
|
||||
void usb3_disable_u2(usb3_pcd_t *pcd);
|
||||
unsigned int usb3_u1_enabled(usb3_pcd_t *pcd);
|
||||
unsigned int usb3_u2_enabled(usb3_pcd_t *pcd);
|
||||
void usb3_dep_cstall(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg);
|
||||
void usb3_dep_sstall(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg);
|
||||
unsigned int handshake(usb3_device_t *dev, volatile unsigned int *ptr,
|
||||
unsigned int mask, unsigned int done);
|
||||
void usb3_fill_desc(usb3_dma_desc_t *desc, phys_addr_t dma_addr,
|
||||
unsigned int dma_len, unsigned int stream, unsigned int type,
|
||||
unsigned int ctrlbits, int own);
|
||||
void usb3_dep_startnewcfg(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int rsrcidx);
|
||||
void usb3_dep_cfg(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int depcfg0, unsigned int depcfg1, unsigned int depcfg2);
|
||||
void usb3_dep_xfercfg(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int depstrmcfg);
|
||||
unsigned char usb3_dep_startxfer(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
phys_addr_t dma_addr, unsigned int stream_or_uf);
|
||||
void usb3_dep_updatexfer(usb3_pcd_t *pcd, usb3_dev_ep_regs_t *ep_reg,
|
||||
unsigned int tri);
|
||||
void usb3_ep_activate(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep);
|
||||
void usb3_ep0_out_start(usb3_pcd_t *pcd);
|
||||
void usb3_ep0_start_transfer(usb3_pcd_t *pcd, usb3_pcd_req_t *req);
|
||||
void usb3_resume_usb2_phy(usb3_pcd_t *pcd);
|
||||
void usb3_handle_dev_intr(usb3_pcd_t *pcd, unsigned int event);
|
||||
int usb3_handle_ep_intr(usb3_pcd_t *pcd, unsigned int physep,
|
||||
unsigned int event);
|
||||
void usb3_handle_event(usb3_device_t *dev);
|
||||
void usb3_enable_device_interrupts(usb3_device_t *dev);
|
||||
void usb3_dis_flush_eventbuf_intr(usb3_device_t *dev);
|
||||
void usb3_init_eventbuf(usb3_device_t *dev, unsigned int size,
|
||||
phys_addr_t dma_addr);
|
||||
|
||||
#endif /* __USB3_DRIVER_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
#include "usb3_hw.h"
|
||||
#include "usb3_drv.h"
|
||||
#include <cpu_func.h>
|
||||
|
||||
void ena_eventbuf_intr(usb3_device_t *dev)
|
||||
{
|
||||
unsigned int eventsiz;
|
||||
|
||||
eventsiz = usb3_rd32(&dev->core_global_regs->geventbuf[0].geventsiz);
|
||||
eventsiz &= ~USB3_EVENTSIZ_INT_MSK_BIT;
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventsiz, eventsiz);
|
||||
}
|
||||
|
||||
void dis_eventbuf_intr(usb3_device_t *dev)
|
||||
{
|
||||
unsigned int eventsiz;
|
||||
|
||||
eventsiz = usb3_rd32(&dev->core_global_regs->geventbuf[0].geventsiz);
|
||||
eventsiz |= USB3_EVENTSIZ_INT_MSK_BIT;
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventsiz, eventsiz);
|
||||
}
|
||||
|
||||
void usb3_dis_flush_eventbuf_intr(usb3_device_t *dev)
|
||||
{
|
||||
unsigned int cnt;
|
||||
unsigned int gevntsize;
|
||||
|
||||
dis_eventbuf_intr(dev);
|
||||
cnt = usb3_rd32(&dev->core_global_regs->geventbuf[0].geventcnt);
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventcnt, cnt);
|
||||
|
||||
if (cnt != 0) {
|
||||
gevntsize = sizeof(dev->event_buf[0]) * USB3_EVENT_BUF_SIZE;
|
||||
usb_info("evnt count 0x%x, evnt buf size 0x%x\n", cnt, gevntsize);
|
||||
dev->event_ptr += cnt % gevntsize;
|
||||
}
|
||||
}
|
||||
|
||||
int get_eventbuf_count(usb3_device_t *dev)
|
||||
{
|
||||
unsigned int cnt;
|
||||
|
||||
cnt = usb3_rd32(&dev->core_global_regs->geventbuf[0].geventcnt);
|
||||
|
||||
return cnt & USB3_EVENTCNT_CNT_BITS;
|
||||
}
|
||||
|
||||
void update_eventbuf_count(usb3_device_t *dev, int cnt)
|
||||
{
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventcnt, cnt);
|
||||
}
|
||||
|
||||
unsigned int get_eventbuf_event(usb3_device_t *dev, int size)
|
||||
{
|
||||
unsigned int event;
|
||||
|
||||
event = *dev->event_ptr++;
|
||||
|
||||
if (dev->event_ptr >= dev->event_buf + size)
|
||||
dev->event_ptr = dev->event_buf;
|
||||
return event;
|
||||
}
|
||||
|
||||
void usb3_init_eventbuf(usb3_device_t *dev, unsigned int size, phys_addr_t dma_addr)
|
||||
{
|
||||
dma_addr = map_to_dma_addr(dma_addr);
|
||||
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventadr_lo, dma_addr & 0xffffffff);
|
||||
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventadr_hi, 0);
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventsiz, size << 2); /* left shift 2bit */
|
||||
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventcnt, 0);
|
||||
}
|
||||
|
||||
void usb3_enable_device_interrupts(usb3_device_t *dev)
|
||||
{
|
||||
unsigned int eventsiz;
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
usb3_dis_flush_eventbuf_intr(dev);
|
||||
/* *
|
||||
* This routine enables the Event Buffer interrupt.
|
||||
*/
|
||||
eventsiz = usb3_rd32(&dev->core_global_regs->geventbuf[0].geventsiz);
|
||||
eventsiz &= ~USB3_EVENTSIZ_INT_MSK_BIT;
|
||||
usb3_wr32(&dev->core_global_regs->geventbuf[0].geventsiz, eventsiz);
|
||||
/* Enable device interrupts */
|
||||
usb3_wr32(&dev->pcd.dev_global_regs->devten, USB3_DEVTEN_DISCONN_BIT | USB3_DEVTEN_CONNDONE_BIT |
|
||||
USB3_DEVTEN_USBRESET_BIT | USB3_DEVTEN_HIBER_REQ_EVT_BIT | USB3_DEVTEN_WKUP_BIT | USB3_DEVTEN_EOPF_BIT);
|
||||
}
|
||||
|
||||
void usb3_handle_event(usb3_device_t *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = &dev->pcd;
|
||||
unsigned int event, physep;
|
||||
int intr, count, i;
|
||||
intr = 0;
|
||||
|
||||
invalidate_dcache_all();
|
||||
count = get_eventbuf_count(dev);
|
||||
if ((count & USB3_EVENTCNT_CNT_BITS) == USB3_EVENTCNT_CNT_BITS || count >= USB3_EVENT_BUF_SIZE * 0x4) {
|
||||
update_eventbuf_count(dev, count);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i += 0x4) {
|
||||
event = get_eventbuf_event(dev, USB3_EVENT_BUF_SIZE);
|
||||
update_eventbuf_count(dev, 0x4);
|
||||
if (event == 0) {
|
||||
/* Ignore null events */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event & USB3_EVENT_NON_EP_BIT) {
|
||||
intr = event & USB3_EVENT_INTTYPE_BITS;
|
||||
|
||||
if (intr == (USB3_EVENT_DEV_INT << USB3_EVENT_INTTYPE_SHIFT)) {
|
||||
usb3_handle_dev_intr(pcd, event);
|
||||
} else {
|
||||
/* @todo Handle non-Device interrupts
|
||||
* (OTG, CarKit, I2C)
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
physep = (event >> USB3_DEPEVT_EPNUM_SHIFT) & (USB3_DEPEVT_EPNUM_BITS >> USB3_DEPEVT_EPNUM_SHIFT);
|
||||
usb3_handle_ep_intr(pcd, physep, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __USB3_PCD_H__
|
||||
#define __USB3_PCD_H__
|
||||
|
||||
usb3_pcd_ep_t *usb3_get_out_ep(usb3_pcd_t *pcd, unsigned int ep_num);
|
||||
usb3_pcd_ep_t *usb3_get_in_ep(usb3_pcd_t *pcd, unsigned int ep_num);
|
||||
usb3_pcd_ep_t *usb3_get_ep_by_addr(usb3_pcd_t *pcd, unsigned short index);
|
||||
void usb3_ep_clear_stall(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep);
|
||||
unsigned int usb3_get_device_speed(usb3_pcd_t *pcd);
|
||||
void usb3_pcd_set_speed(usb3_pcd_t *pcd, int speed);
|
||||
void usb3_ep_set_stall(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep);
|
||||
void usb3_bulk_in_transfer(void *dev, const char *status);
|
||||
void usb3_bulk_out_transfer_cmd(void *dev);
|
||||
int usb3_bulk_out_transfer_data(void *dev);
|
||||
void usb3_bulk_out_transfer(void *dev);
|
||||
void usb3_ep_start_transfer(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep);
|
||||
int usb3_ep_complete_request(usb3_pcd_t *pcd, usb3_pcd_ep_t *ep, unsigned int event);
|
||||
void usb3_os_handle_ep0(usb3_pcd_t *pcd, unsigned int event);
|
||||
void usb_tx_status_complete(void *dev);
|
||||
|
||||
#endif /* __USB3_PCD_H__ */
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
#include "usb3_drv.h"
|
||||
#include "usb3_pcd.h"
|
||||
|
||||
static void handle_usb_reset_intr(usb3_pcd_t *pcd)
|
||||
{
|
||||
usb3_pcd_ep_t *ep;
|
||||
|
||||
/* Clear stall on each EP */
|
||||
ep = &pcd->in_ep;
|
||||
if (ep->stopped)
|
||||
usb3_ep_clear_stall(pcd, ep);
|
||||
|
||||
ep = &pcd->out_ep;
|
||||
if (ep->stopped)
|
||||
usb3_ep_clear_stall(pcd, ep);
|
||||
|
||||
/* Set Device Address to 0 */
|
||||
usb3_set_address(pcd, 0);
|
||||
|
||||
pcd->ltm_enable = 0;
|
||||
}
|
||||
|
||||
static void handle_connect_done_intr(usb3_pcd_t *pcd)
|
||||
{
|
||||
usb3_pcd_ep_t *ep0 = &pcd->ep0;
|
||||
unsigned int diepcfg0, doepcfg0, diepcfg1, doepcfg1;
|
||||
usb3_dev_ep_regs_t *ep_reg;
|
||||
int speed;
|
||||
|
||||
ep0->stopped = 0;
|
||||
speed = usb3_get_device_speed(pcd);
|
||||
pcd->speed = speed;
|
||||
|
||||
usb3_pcd_set_speed(pcd, speed);
|
||||
|
||||
/*
|
||||
* Set the MPS of EP0 based on the connection speed
|
||||
*/
|
||||
diepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
diepcfg0 |= USB3_CFG_ACTION_MODIFY << USB3_EPCFG0_CFG_ACTION_SHIFT;
|
||||
diepcfg1 =
|
||||
USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT | USB3_EPCFG1_XFER_NRDY_BIT | USB3_EPCFG1_EP_DIR_BIT;
|
||||
|
||||
doepcfg0 = USB3_EP_TYPE_CONTROL << USB3_EPCFG0_EPTYPE_SHIFT;
|
||||
doepcfg0 |= USB3_CFG_ACTION_MODIFY << USB3_EPCFG0_CFG_ACTION_SHIFT;
|
||||
doepcfg1 = USB3_EPCFG1_XFER_CMPL_BIT | USB3_EPCFG1_XFER_IN_PROG_BIT | USB3_EPCFG1_XFER_NRDY_BIT;
|
||||
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
diepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT; /* 512 for super speed */
|
||||
doepcfg0 |= 512 << USB3_EPCFG0_MPS_SHIFT; /* 512 for super speed */
|
||||
break;
|
||||
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_FULL:
|
||||
diepcfg0 |= 64 << USB3_EPCFG0_MPS_SHIFT; /* 64 for high\full speed */
|
||||
doepcfg0 |= 64 << USB3_EPCFG0_MPS_SHIFT; /* 64 for high\full speed */
|
||||
break;
|
||||
|
||||
case USB_SPEED_LOW:
|
||||
diepcfg0 |= 8 << USB3_EPCFG0_MPS_SHIFT; /* 8 for low speed */
|
||||
doepcfg0 |= 8 << USB3_EPCFG0_MPS_SHIFT; /* 8 for low speed */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
diepcfg0 |= ep0->tx_fifo_num << USB3_EPCFG0_TXFNUM_SHIFT;
|
||||
|
||||
/* Issue "DEPCFG" command to EP0-OUT */
|
||||
ep_reg = &pcd->out_ep_regs[0];
|
||||
usb3_dep_cfg(pcd, ep_reg, doepcfg0, doepcfg1, 0);
|
||||
|
||||
/* Issue "DEPCFG" command to EP0-IN */
|
||||
ep_reg = &pcd->in_ep_regs[0];
|
||||
usb3_dep_cfg(pcd, ep_reg, diepcfg0, diepcfg1, 0);
|
||||
|
||||
pcd->state = USB3_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
int usb3_handle_ep_intr(usb3_pcd_t *pcd, unsigned int physep, unsigned int event)
|
||||
{
|
||||
usb3_pcd_ep_t *ep;
|
||||
int epnum, is_in;
|
||||
int error = USB_NO_ERR;
|
||||
|
||||
if (pcd == NULL)
|
||||
return USB_PROCESS_ERR;
|
||||
|
||||
/* Physical Out EPs are even, physical In EPs are odd */
|
||||
is_in = physep & 1;
|
||||
epnum = (physep >> 1) & 0xf;
|
||||
|
||||
/* Get EP pointer */
|
||||
if (is_in) {
|
||||
ep = usb3_get_in_ep(pcd, epnum);
|
||||
} else {
|
||||
ep = usb3_get_out_ep(pcd, epnum);
|
||||
}
|
||||
if (ep == NULL)
|
||||
return USB_PROCESS_ERR;
|
||||
|
||||
// printf("\n##########%s,%d,event=0x%x\n",__func__,__LINE__,event);
|
||||
switch (event & USB3_DEPEVT_INTTYPE_BITS) {
|
||||
case USB3_DEPEVT_XFER_CMPL << USB3_DEPEVT_INTTYPE_SHIFT:
|
||||
ep->xfer_started = 0;
|
||||
|
||||
/* Complete the transfer */
|
||||
if (epnum == 0) {
|
||||
usb3_os_handle_ep0(pcd, event);
|
||||
} else {
|
||||
// printf("\n##########%s,%d,event=0x%x\n",__func__,__LINE__,event);
|
||||
error = usb3_ep_complete_request(pcd, ep, event);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB3_DEPEVT_XFER_NRDY << USB3_DEPEVT_INTTYPE_SHIFT:
|
||||
if (epnum != 0)
|
||||
break;
|
||||
switch (pcd->ep0state) {
|
||||
case EP0_IN_WAIT_NRDY:
|
||||
if (is_in)
|
||||
usb3_os_handle_ep0(pcd, event);
|
||||
break;
|
||||
case EP0_OUT_WAIT_NRDY:
|
||||
if (!is_in)
|
||||
usb3_os_handle_ep0(pcd, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void usb3_handle_dev_intr(usb3_pcd_t *pcd, unsigned int event)
|
||||
{
|
||||
unsigned int dint = (event >> USB3_DEVT_SHIFT) & (USB3_DEVT_BITS >> USB3_DEVT_SHIFT);
|
||||
|
||||
switch (dint) {
|
||||
case USB3_DEVT_USBRESET:
|
||||
handle_usb_reset_intr(pcd);
|
||||
break;
|
||||
|
||||
case USB3_DEVT_CONNDONE:
|
||||
handle_connect_done_intr(pcd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "usb3_drv.h"
|
||||
#include "usb3_pcd.h"
|
||||
#include "usb3_prot.h"
|
||||
#include "onchiprom.h"
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define USTART 0xFA
|
||||
#define UHEAD 0xFE
|
||||
#define UDATA 0xDA
|
||||
#define UTAIL 0xED
|
||||
#define UCMD 0XAB
|
||||
#define UREQ 0XFB
|
||||
|
||||
#define TX_STATE_BUFFER 500
|
||||
#define TX_STATE_LIMIT 400
|
||||
#define BUFFER_SIZE 512
|
||||
|
||||
char u_ack[2] = {0xAA, '\0'};
|
||||
char u_nak[2] = {0x55, '\0'};
|
||||
char tx_state[TX_STATE_BUFFER] = {0, 0x55, 0};
|
||||
static phys_addr_t rx_addr;
|
||||
static unsigned int rx_length;
|
||||
int usb_connected;
|
||||
int usb_out_open = 0;
|
||||
|
||||
void usb3_bulk_out_transfer_cmd(void *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = (usb3_pcd_t *)dev;
|
||||
usb3_pcd_ep_t *ep = &pcd->out_ep;
|
||||
usb3_pcd_req_t *req = &ep->req;
|
||||
|
||||
memset(pcd->ss_bulk_buf, 0x0, USB3_BULK_BUF_SIZE);
|
||||
|
||||
req->length = ep->maxpacket;
|
||||
req->bufdma = pcd->ss_bulk_buf;
|
||||
req->complete = usb3_handle_protocol;
|
||||
usb3_ep_start_transfer(pcd, ep);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void usb3_handle_data(void *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = NULL;
|
||||
usb3_pcd_ep_t *ep = NULL;
|
||||
usb3_pcd_req_t *req = NULL;
|
||||
if (dev == NULL)
|
||||
return;
|
||||
|
||||
pcd = (usb3_pcd_t *)dev;
|
||||
ep = &pcd->out_ep;
|
||||
req = &ep->req;
|
||||
|
||||
if (req->actual > rx_length)
|
||||
req->actual = rx_length;
|
||||
|
||||
rx_addr += req->actual;
|
||||
rx_length -= req->actual;
|
||||
|
||||
if (rx_length > 0) {
|
||||
usb3_bulk_out_transfer_data(dev);
|
||||
} else {
|
||||
usb3_bulk_out_transfer_cmd(dev);
|
||||
}
|
||||
}
|
||||
|
||||
int usb3_bulk_out_transfer_data(void *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = NULL;
|
||||
usb3_pcd_ep_t *ep = NULL;
|
||||
usb3_pcd_req_t *req = NULL;
|
||||
if (dev == NULL)
|
||||
return USB_PROCESS_ERR;
|
||||
|
||||
pcd = (usb3_pcd_t *)dev;
|
||||
ep = &pcd->out_ep;
|
||||
req = &ep->req;
|
||||
|
||||
/* For DWC3 controller,If CHN=0 and HWO=0 for the TRB, this field represents the total remaining Buffer
|
||||
* Descriptor buffer size in bytes. Valid Range: 0 bytes to (16 MB - 1 byte).
|
||||
* The hardware decrements this field to represent the remaining buffer size after data is
|
||||
* transferred.
|
||||
* Note: for bulk transfer, max length = 16MB - maxpacket;
|
||||
* */
|
||||
if (rx_length >= (USB3_DSCSTS_XFRCNT_MAX - ep->maxpacket)) {
|
||||
req->length = USB3_DSCSTS_XFRCNT_MAX - ep->maxpacket;
|
||||
} else {
|
||||
req->length = rx_length;
|
||||
}
|
||||
|
||||
req->bufdma = (unsigned char *)rx_addr;
|
||||
req->complete = usb3_handle_data;
|
||||
|
||||
usb3_ep_start_transfer(pcd, ep);
|
||||
|
||||
return USB_NO_ERR;
|
||||
}
|
||||
|
||||
void udc_puts(const char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
if (strlen(tx_state) + strlen(s) > TX_STATE_LIMIT)
|
||||
(void)memset(tx_state, 0, TX_STATE_BUFFER);
|
||||
|
||||
if (strlen(s) > TX_STATE_BUFFER) {
|
||||
return;
|
||||
} else {
|
||||
if (usb_out_open == 1) {
|
||||
strcat(tx_state, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*USB3_HANDLE_REQUEST)(unsigned char * const buff, unsigned int *bufflen);
|
||||
USB3_HANDLE_REQUEST handle_request = NULL;
|
||||
void set_usb3_call_back_func(USB3_HANDLE_REQUEST func)
|
||||
{
|
||||
handle_request = func;
|
||||
}
|
||||
|
||||
void usb3_handle_protocol(void *dev)
|
||||
{
|
||||
usb3_pcd_t *pcd = (usb3_pcd_t *)dev;
|
||||
int ret;
|
||||
char *buf = (char *)pcd->ss_bulk_buf;
|
||||
|
||||
if (buf[0] == USTART) {
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
usb3_bulk_in_transfer(dev, u_ack);
|
||||
} else if (buf[0] == UHEAD) {
|
||||
/*left shift 8/16/24 bit [5][6][7][8]:buffer number */
|
||||
rx_addr = (buf[5] << 24) | (buf[6] << 16) | (buf[7] << 8) | (buf[8]);
|
||||
/*left shift 8/16/24 bit [1][2][3][4]:buffer number */
|
||||
rx_length = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | (buf[4]);
|
||||
if (rx_addr == rx_length) {
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
usb_connected = 1;
|
||||
usb_out_open = 1;
|
||||
} else {
|
||||
usb3_bulk_out_transfer_data(pcd);
|
||||
}
|
||||
usb3_bulk_in_transfer(dev, u_ack);
|
||||
return;
|
||||
} else if(buf[0]==UCMD) {
|
||||
strcat(tx_state, " ");
|
||||
|
||||
|
||||
usb_out_open = 1;
|
||||
ret = run_command(buf + 0x3, 0);
|
||||
if (ret) {
|
||||
usb3_bulk_in_transfer(dev, "[EOT](ERROR)\r\n");
|
||||
} else {
|
||||
strcat(tx_state, "[EOT](OK)\r\n");
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
usb3_bulk_in_transfer(dev, tx_state);
|
||||
memset(tx_state, 0, TX_STATE_BUFFER);
|
||||
}
|
||||
} else if (buf[0] == UTAIL) {
|
||||
if (rx_length > 0) {
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
usb3_bulk_in_transfer(dev, u_nak);
|
||||
} else {
|
||||
usb3_bulk_in_transfer(dev, u_ack);
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
}
|
||||
} else if (buf[0] == UREQ) {
|
||||
usb_out_open = 0;
|
||||
if (handle_request != NULL) {
|
||||
usb3_pcd_ep_t *ep = &pcd->in_ep;
|
||||
usb3_pcd_req_t *req = &ep->req;
|
||||
|
||||
memset(req->bufdma, 0, BUFFER_SIZE);
|
||||
req->length = 0;
|
||||
ret = (*handle_request)(req->bufdma, &req->length);
|
||||
|
||||
req->complete = usb_tx_status_complete;
|
||||
usb3_ep_start_transfer(pcd, ep);
|
||||
|
||||
usb3_bulk_out_transfer_cmd(pcd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) LOTUS. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __USB3_PROT_H__
|
||||
#define __USB3_PROT_H__
|
||||
|
||||
|
||||
/* FILE FRAME: TYPE(1)+SEQ(1)+CSEQ(1)+FILE(1)+LENGTH(4)+ADDRESS(4)+CRC(2) */
|
||||
/* DATA FRAME: TYPE(1)+SEQ(1)+CSEQ(1)+DATA(0~1024)+CRC(2) */
|
||||
/* EOT FRAME: TYPE(1)+SEQ(1)+CSEQ(1)+CRC(2) */
|
||||
#define FRAME_HEAD 0
|
||||
#define FRAME_SEQ 1
|
||||
#define FRAME_CSEQ 2
|
||||
#define FRAME_TYPE 3
|
||||
#define FRAME_DATA_START 3
|
||||
#define FRAME_LENGTH 4
|
||||
#define FRAME_ADDRESS 8
|
||||
|
||||
#define FRAME_FILE 0xFE
|
||||
#define FRAME_DATA 0xDA
|
||||
#define FRAME_EOT 0xED
|
||||
#define FRAME_INQUIRE 0xCD
|
||||
|
||||
#define USB3_RESPONSE_ACK 0xAA
|
||||
#define USB3_RESPONSE_NAK 0x55
|
||||
|
||||
#define FRAME_FILE_LEN 14
|
||||
#define FRAME_EOT_LEN 5
|
||||
|
||||
#define FRAME_HEAD_LEN 5
|
||||
#define FRAME_DATA_LEN 1024
|
||||
|
||||
#define FILE_RAMINIT 1
|
||||
#define FILE_USB 2
|
||||
|
||||
#define USB3_XFR_PROT_OK 0
|
||||
#define USB3_XFR_PROT_ERR 1
|
||||
#define USB3_XFR_PROT_SKIP 2
|
||||
#define USB3_XFR_PROT_COMPLETE 3
|
||||
#define USB3_XFR_PROT_INPROGRESS 4
|
||||
#define USB3_XFR_PROT_WAIT 0x05
|
||||
#define USB3_XFR_PROT_INQUIRE 0x06
|
||||
#define USB3_XFR_PROT_ADDR_ERROR 0x07
|
||||
|
||||
|
||||
void usb3_handle_protocol(void *dev);
|
||||
|
||||
#endif /* __USB3_PROT_H__ */
|
||||
Reference in New Issue
Block a user