diff --git a/arch/arm/dts/ipq806x-soc.dtsi b/arch/arm/dts/ipq806x-soc.dtsi index f2dc976934..0410f84355 100644 --- a/arch/arm/dts/ipq806x-soc.dtsi +++ b/arch/arm/dts/ipq806x-soc.dtsi @@ -453,6 +453,20 @@ perst_gpio = <63>; }; + xhci@11000000 { + compatible = "qca,dwc3-ipq"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x11000000 0xcd00>; + }; + + xhci@10000000 { + compatible = "qca,dwc3-ipq"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x10000000 0xcd00>; + }; + spi { spi0 { mosi_miso_clk { diff --git a/arch/arm/include/asm/arch-ipq806x/clk.h b/arch/arm/include/asm/arch-ipq806x/clk.h index 35e5ca4f09..c6acbafe1a 100644 --- a/arch/arm/include/asm/arch-ipq806x/clk.h +++ b/arch/arm/include/asm/arch-ipq806x/clk.h @@ -113,6 +113,23 @@ typedef struct { unsigned int parf_phy_refclk; } pci_clk_offset_t; +#define USB30_MASTER_CLK_CTL REG(0x3B24) +#define USB30_MASTER_1_CLK_CTL REG(0x3B34) +#define USB30_MASTER_CLK_MD REG(0x3B28) +#define USB30_MASTER_CLK_NS REG(0x3B2C) +#define USB30_MOC_UTMI_CLK_MD REG(0x3B40) +#define USB30_MOC_UTMI_CLK_NS REG(0x3B44) +#define USB30_MOC_UTMI_CLK_CTL REG(0x3B48) +#define USB30_MOC_1_UTMI_CLK_CTL REG(0x3B4C) + +#define USB_clk_ns_mask (BM(BIT_POS_23, BIT_POS_16) | BM(BIT_POS_6, BIT_POS_0)) +#define USB_en_mask BIT(11) + +void usb_ss_core_clock_config(unsigned int usb_port, unsigned int m, + unsigned int n, unsigned int d); +void usb_ss_utmi_clock_config(unsigned int usb_port, unsigned int m, + unsigned int n, unsigned int d); + void i2c_clock_config(void); /* Uart specific clock settings */ diff --git a/board/qca/arm/ipq806x/ipq806x.c b/board/qca/arm/ipq806x/ipq806x.c index 2a44dc58c0..49bab45a9e 100644 --- a/board/qca/arm/ipq806x/ipq806x.c +++ b/board/qca/arm/ipq806x/ipq806x.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "ipq806x.h" #include "qca_common.h" #include @@ -493,3 +495,299 @@ int switch_ce_channel_buf(unsigned int channel_id) return ret; } + +#ifdef CONFIG_USB_XHCI_IPQ +__weak void ipq_reset_usb_phy(void *data) +{ + return; +} + +static u16 dwc3_ipq_ssusb_read_phy_reg(unsigned int addr, unsigned int ipq_base) +{ + u16 tmp_phy[3], i; + do { + for (i = 0; i < 3; i++) { + writel(addr, ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_IN); + writel(0x1, ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_ADDR); + while (0 != readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_ADDR)); + writel(0x1, ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_READ); + while (0 != readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_READ)); + tmp_phy[i] = (u16)readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_OUT); + } + } while (tmp_phy[1] != tmp_phy[2]); + return tmp_phy[2]; +} + +static void dwc3_ipq_ssusb_write_phy_reg(u32 addr, u16 data, unsigned int ipq_base) +{ + writel(addr, ipq_base + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_IN); + writel(0x1, ipq_base + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_ADDR); + while (0 != readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_ADDR)); + writel(data, ipq_base + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_IN); + writel(0x1, ipq_base + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_DATA); + while (0 != readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_DATA)); + writel(0x1, ipq_base + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_WRITE); + while (0 != readl(ipq_base + + IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_WRITE)); +} + +static void ipq_ssusb_clear_bits32(u32 offset, u32 bits, unsigned int ipq_base) +{ + u32 data; + data = readl(ipq_base+offset); + data = data & ~bits; + writel(data, ipq_base + offset); +} + +static void ipq_ssusb_clear_and_set_bits32(u32 offset, u32 clear_bits, u32 set_bits, unsigned int ipq_base) +{ + u32 data; + data = readl(ipq_base + offset); + data = (data & ~clear_bits) | set_bits; + writel(data, ipq_base + offset); +} + +static void partial_rx_reset_init(unsigned int ipq_base) +{ + u32 addr = DWC3_SSUSB_PHY_TX_ALT_BLOCK_REG; + u16 data = dwc3_ipq_ssusb_read_phy_reg(addr, ipq_base); + data |= DWC3_SSUSB_PHY_TX_ALT_BLOCK_EN_ALT_BUS; + dwc3_ipq_ssusb_write_phy_reg(addr, data, ipq_base); + return; +} + +static void uw_ssusb_pre_init(unsigned int ipq_base) +{ + u32 set_bits, tmp; + + /* GCTL Reset ON */ + writel(0x800, ipq_base + DWC3_SSUSB_REG_GCTL); + /* Config SS PHY CTRL */ + set_bits = 0; + writel(0x80, ipq_base + IPQ_SS_PHY_CTRL_REG); + udelay(5); + ipq_ssusb_clear_bits32(IPQ_SS_PHY_CTRL_REG, 0x80, ipq_base); + udelay(5); + /* REF_USE_PAD */ + set_bits = 0x0000000; /* USE Internal clock */ + set_bits |= IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_LANE0_PWR_PRESENT; + set_bits |= IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_SS_PHY_EN; + writel(set_bits, ipq_base + IPQ_SS_PHY_CTRL_REG); + /* Config HS PHY CTRL */ + set_bits = IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_UTMI_OTG_VBUS_VALID; + /* + * COMMONONN forces xo, bias and pll to stay on during suspend; + * Allowing suspend (writing 1) kills Aragorn V1 + */ + set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_COMMONONN; + set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_USE_CLKCORE; + set_bits |= IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_FSEL_VAL; + /* + * If the configuration of clocks is not bypassed in Host mode, + * HS PHY suspend needs to be prohibited, otherwise - SS connection fails + */ + ipq_ssusb_clear_and_set_bits32(IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL, 0, + set_bits, ipq_base); + /* USB2 PHY Reset ON */ + writel(DWC3_SSUSB_REG_GUSB2PHYCFG_PHYSOFTRST, ipq_base + + DWC3_SSUSB_REG_GUSB2PHYCFG(0)); + /* USB3 PHY Reset ON */ + writel(DWC3_SSUSB_REG_GUSB3PIPECTL_PHYSOFTRST, ipq_base + + DWC3_SSUSB_REG_GUSB3PIPECTL(0)); + udelay(5); + /* USB3 PHY Reset OFF */ + ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GUSB3PIPECTL(0), + DWC3_SSUSB_REG_GUSB3PIPECTL_PHYSOFTRST, ipq_base); + ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GUSB2PHYCFG(0), + DWC3_GUSB2PHYCFG_PHYSOFTRST, ipq_base); + udelay(5); + /* GCTL Reset OFF */ + ipq_ssusb_clear_bits32(DWC3_SSUSB_REG_GCTL, DWC3_GCTL_CORESOFTRESET, + ipq_base); + udelay(5); + if (RX_TERM_VALUE) { + dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_RTUNE_CTRL_REG, + 0, ipq_base); + dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_DEBUG_REG, + 0x0448, ipq_base); + dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RTUNE_DEBUG_REG, + RX_TERM_VALUE, ipq_base); + } + if (0 != RX_EQ_VALUE) { /* Values from 1 to 7 */ + tmp =0; + /* + * 1. Fixed EQ setting. This can be achieved as follows: + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 - address 1006 bit 6 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 0- address 1006 bit 7 + * LANE0.RX_OVRD_IN_HI.RX_EQ set to 4 (also try setting 3 if possible) - + * address 1006 bits 10:8 - please make this a variable, if unchanged the section is not executed + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 - address 1006 bit 11 + */ + tmp = dwc3_ipq_ssusb_read_phy_reg(DWC3_SSUSB_PHY_RX_OVRD_IN_HI_REG, + ipq_base); + tmp &= ~((u16)1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN); + tmp |= ((u16)1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN_OVRD); + tmp &= ~((u16) DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_MASK << + DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ); + tmp |= RX_EQ_VALUE << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ; + tmp |= 1 << DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_OVRD; + dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_RX_OVRD_IN_HI_REG, + tmp, ipq_base); + } + if ((113 != AMPLITUDE_VALUE) || (21 != TX_DEEMPH_3_5DB)) { + tmp = dwc3_ipq_ssusb_read_phy_reg(DWC3_SSUSB_PHY_TX_OVRD_DRV_LO_REG, + ipq_base); + tmp &= ~DWC3_SSUSB_PHY_TX_DEEMPH_MASK; + tmp |= (TX_DEEMPH_3_5DB << DWC3_SSUSB_PHY_TX_DEEMPH_SHIFT); + tmp &= ~DWC3_SSUSB_PHY_AMP_MASK; + tmp |= AMPLITUDE_VALUE; + tmp |= DWC3_SSUSB_PHY_AMP_EN; + dwc3_ipq_ssusb_write_phy_reg(DWC3_SSUSB_PHY_TX_OVRD_DRV_LO_REG, + tmp, ipq_base); + } + ipq_ssusb_clear_and_set_bits32(IPQ_SS_PHY_PARAM_CTRL_1_REG, + 0x7, 0x5, ipq_base); + /* XHCI REV */ + writel((1 << 2), ipq_base + IPQ_QSCRATCH_GENERAL_CFG); + writel(0x0c80c010, ipq_base + DWC3_SSUSB_REG_GUCTL); + partial_rx_reset_init(ipq_base); + set_bits = 0; + /* Test U2EXIT_LFPS */ + set_bits |= IPQ_SSUSB_REG_GCTL_U2EXIT_LFPS; + ipq_ssusb_clear_and_set_bits32(DWC3_SSUSB_REG_GCTL, 0, + set_bits, ipq_base); + set_bits = 0; + set_bits |= IPQ_SSUSB_REG_GCTL_U2RSTECN; + set_bits |= IPQ_SSUSB_REG_GCTL_U2EXIT_LFPS; + ipq_ssusb_clear_and_set_bits32(DWC3_SSUSB_REG_GCTL, 0, + set_bits, ipq_base); + writel(DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_SOFITPSYNC | + DWC3_GCTL_PRTCAPDIR(1) | + DWC3_GCTL_U2RSTECN | DWC3_GCTL_PWRDNSCALE(2), + ipq_base + DWC3_GCTL); + writel((IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_MPLL_MULTI(0x19) | + IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_SS_PHY_EN | + IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_LANE0_PWR_PRESENT), + ipq_base + IPQ_SS_PHY_CTRL_REG); + writel((DWC3_SSUSB_REG_GUSB2PHYCFG_SUSPENDUSB20 | + DWC3_SSUSB_REG_GUSB2PHYCFG_ENBLSLPM | + DWC3_SSUSB_REG_GUSB2PHYCFG_USBTRDTIM(9)), + ipq_base + DWC3_SSUSB_REG_GUSB2PHYCFG(0)); + writel(DWC3_SSUSB_REG_GUSB3PIPECTL_ELASTIC_BUFFER_MODE | + DWC3_SSUSB_REG_GUSB3PIPECTL_TX_DE_EPPHASIS(1) | + DWC3_SSUSB_REG_GUSB3PIPECTL_TX_MARGIN(0)| + DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1TRANS | + DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1P2P3(1) | + DWC3_SSUSB_REG_GUSB3PIPECTL_U1U2EXITFAIL_TO_RECOV | + DWC3_SSUSB_REG_GUSB3PIPECTL_REQUEST_P1P2P3, + ipq_base + DWC3_SSUSB_REG_GUSB3PIPECTL(0)); + writel(IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_LOS_LEVEL(0x9) | + IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_3_5DB(0x17) | + IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_6DB(0x20) | + IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_SWING_FULL(0x6E), + ipq_base + IPQ_SS_PHY_PARAM_CTRL_1_REG); + writel(IPQ_SSUSB_REG_QSCRATCH_GENERAL_CFG_XHCI_REV(DWC3_SSUSB_XHCI_REV_10), + ipq_base + IPQ_QSCRATCH_GENERAL_CFG); +} + +static void usb30_common_pre_init(int id, unsigned int ipq_base) +{ + unsigned int reg; + + if (id == 0) + reg = USB30_RESET; + else + reg = USB30_1_RESET; + + writel(IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + writel(IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + writel(IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + writel(IPQ_USB30_RESET_SLEEP_ASYNC_RESET | + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + writel(IPQ_USB30_RESET_MASTER_ASYNC_RESET | + IPQ_USB30_RESET_SLEEP_ASYNC_RESET | + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + if (id == 0) { + writel(IPQ_USB30_RESET_PORT2_HS_PHY_ASYNC_RESET | + IPQ_USB30_RESET_MASTER_ASYNC_RESET | + IPQ_USB30_RESET_SLEEP_ASYNC_RESET | + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET, reg); + } + udelay(5); + writel(IPQ_USB30_RESET_MASK & ~(IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + writel(IPQ_USB30_RESET_MASK & ~(IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + writel(IPQ_USB30_RESET_MASK & ~(IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + writel(IPQ_USB30_RESET_MASK & ~(IPQ_USB30_RESET_SLEEP_ASYNC_RESET | + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + writel(IPQ_USB30_RESET_MASK & ~(IPQ_USB30_RESET_MASTER_ASYNC_RESET | + IPQ_USB30_RESET_SLEEP_ASYNC_RESET| + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + if (id == 0) { + writel(IPQ_USB30_RESET_MASK & + ~(IPQ_USB30_RESET_PORT2_HS_PHY_ASYNC_RESET | + IPQ_USB30_RESET_MASTER_ASYNC_RESET | + IPQ_USB30_RESET_SLEEP_ASYNC_RESET | + IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET | + IPQ_USB30_RESET_POWERON_ASYNC_RESET | + IPQ_USB30_RESET_PHY_ASYNC_RESET), reg); + reg = IPQ_TCSR_USB_CONTROLLER_TYPE_SEL; + if (reg) { + writel(0x3, reg); + } + } + writel((IPQ_SSUSB_REG_QSCRATCH_CGCTL_RAM1112_EN | + IPQ_SSUSB_REG_QSCRATCH_CGCTL_RAM13_EN), + ipq_base + IPQ_SSUSB_REG_QSCRATCH_CGCTL); + writel((IPQ_SSUSB_REG_QSCRATCH_RAM1_RAM13_EN | + IPQ_SSUSB_REG_QSCRATCH_RAM1RAM12_EN | + IPQ_SSUSB_REG_QSCRATCH_RAM1_RAM11_EN), + ipq_base + IPQ_SSUSB_REG_QSCRATCH_RAM1); +} + +int ipq_board_usb_init(void) +{ + int i; + unsigned int ipq_base; + + /* Configure the usb core clock */ + usb_ss_core_clock_config(0, 1, 5, 32); + /* Configure the usb core clock */ + usb_ss_utmi_clock_config(0, 1, 40, 1); + + for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { + + if (i == 0) + ipq_base = IPQ_XHCI_BASE_1; + else + ipq_base = IPQ_XHCI_BASE_2; + + usb30_common_pre_init(0, ipq_base); + uw_ssusb_pre_init(ipq_base); + } + return 0; +} +#endif /* CONFIG_USB_XHCI_IPQ */ diff --git a/board/qca/arm/ipq806x/ipq806x.h b/board/qca/arm/ipq806x/ipq806x.h index d044655289..6f7cb7965c 100644 --- a/board/qca/arm/ipq806x/ipq806x.h +++ b/board/qca/arm/ipq806x/ipq806x.h @@ -46,6 +46,50 @@ #define CE1_ADM_USAGE (1) #define CE1_RESOURCE (1) +#define IPQ_XHCI_BASE_1 0x11000000 +#define IPQ_XHCI_BASE_2 0x10000000 +#define USB30_RESET 0x00903B50 +#define USB30_1_RESET 0x00903B58 +#define DWC3_SSUSB_REG_GCTL 0xC110 +#define DWC3_SSUSB_REG_GUSB2PHYCFG_PHYSOFTRST (1 << 31) +#define DWC3_SSUSB_REG_GUSB2PHYCFG(n) (0xC200 + ((n) * 0x16)) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_PHYSOFTRST (1 << 31) +#define DWC3_SSUSB_REG_GUSB3PIPECTL(n) (0xC2C0 + ((n) * 0x16)) +#define DWC3_SSUSB_PHY_RTUNE_RTUNE_CTRL_REG 0x34 +#define DWC3_SSUSB_PHY_RTUNE_DEBUG_REG 0x3 +#define RX_TERM_VALUE 0 +#define RX_EQ_VALUE 4 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_REG 0x1006 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN 6 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_EN_OVRD 7 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_MASK 0x7 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ 8 +#define DWC3_SSUSB_PHY_RX_OVRD_IN_HI_RX_EQ_OVRD 11 +#define AMPLITUDE_VALUE 110 +#define TX_DEEMPH_3_5DB 23 +#define DWC3_SSUSB_PHY_TX_OVRD_DRV_LO_REG 0x1002 +#define DWC3_SSUSB_PHY_TX_DEEMPH_MASK 0x3F80 +#define DWC3_SSUSB_PHY_AMP_MASK 0x7F +#define DWC3_SSUSB_PHY_AMP_EN (1 << 14) +#define DWC3_SSUSB_REG_GUCTL 0xC12C +#define DWC3_SSUSB_PHY_TX_ALT_BLOCK_REG 0x102D +#define DWC3_SSUSB_PHY_TX_ALT_BLOCK_EN_ALT_BUS (1 << 7) +#define DWC3_GCTL_U2EXIT_LFPS (1 << 2) +#define DWC3_GCTL_SOFITPSYNC (1 << 10) +#define DWC3_GCTL 0xc110 +#define DWC3_SSUSB_REG_GUSB2PHYCFG_SUSPENDUSB20 (1 << 6) +#define DWC3_SSUSB_REG_GUSB2PHYCFG_ENBLSLPM (1 << 8) +#define DWC3_SSUSB_REG_GUSB2PHYCFG_USBTRDTIM(n) ((n) << 10) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_ELASTIC_BUFFER_MODE (1 << 0) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_TX_DE_EPPHASIS(n) ((n) << 1) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_TX_MARGIN(n) ((n) << 3) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1TRANS (1 << 18) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_DELAYP1P2P3(n) ((n) << 19) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_U1U2EXITFAIL_TO_RECOV (1 << 25) +#define DWC3_SSUSB_REG_GUSB3PIPECTL_REQUEST_P1P2P3 (1 << 24) +#define DWC3_SSUSB_PHY_TX_DEEMPH_SHIFT 7 +#define DWC3_SSUSB_XHCI_REV_10 1 + typedef struct { uint count; u8 addr[7]; diff --git a/configs/ipq806x_defconfig b/configs/ipq806x_defconfig index 58562ac164..229e80ab0d 100644 --- a/configs/ipq806x_defconfig +++ b/configs/ipq806x_defconfig @@ -248,9 +248,10 @@ CONFIG_REQUIRE_SERIAL_CONSOLE=y # CONFIG_DM_THERMAL is not set # -# TPM support +# USB support # -# CONFIG_USB is not set +CONFIG_USB=y +CONFIG_DM_USB=y # # Graphics support diff --git a/drivers/clk/ipq806x_clk.c b/drivers/clk/ipq806x_clk.c index ce9ca240ef..f801bd2d90 100644 --- a/drivers/clk/ipq806x_clk.c +++ b/drivers/clk/ipq806x_clk.c @@ -54,7 +54,7 @@ void uart_pll_vote_clk_enable(void) while((readl(PLL_LOCK_DET_STATUS_REG) & BIT(8)) == 0); } -#ifdef CONFIG_IPQ806X_USB +#ifdef CONFIG_USB_XHCI_IPQ /** * usb_pll_vote_clk_enable - enables PLL8 */ @@ -82,7 +82,7 @@ static void uart_set_rate_mnd(unsigned int gsbi_port, unsigned int m, clrbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(7)); } -#ifdef CONFIG_IPQ806X_USB +#ifdef CONFIG_USB_XHCI_IPQ /** * usb_set_rate_mnd - configures divider M and D values * @@ -121,7 +121,7 @@ static void uart_branch_clk_enable_reg(unsigned int gsbi_port) setbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(9)); } -#ifdef CONFIG_IPQ806X_USB +#ifdef CONFIG_USB_XHCI_IPQ /** * usb_local_clock_enable - configures N value and enables root clocks * @@ -280,7 +280,7 @@ static void uart_set_gsbi_clk(unsigned int gsbi_port) setbits_le32(GSBIn_HCLK_CTL_REG(gsbi_port), BIT(4)); } -#ifdef CONFIG_IPQ806X_USB +#ifdef CONFIG_USB_XHCI_IPQ /** * * USB_clock_config - configures USB3.0 clocks diff --git a/drivers/usb/host/xhci-ipq.c b/drivers/usb/host/xhci-ipq.c index ea79063272..fabf5b5957 100644 --- a/drivers/usb/host/xhci-ipq.c +++ b/drivers/usb/host/xhci-ipq.c @@ -44,10 +44,11 @@ struct ipq_xhci { struct dwc3 *dwc3_reg; }; -void ipq_reset_usb_phy(struct ipq_xhci *ipq) +void ipq_reset_usb_phy(void *data) { unsigned int gcc_rst_ctrl; struct ipq_xhci_platdata *platdata; + struct ipq_xhci *ipq = (struct ipq_xhci *)data; platdata = dev_get_platdata(ipq->dev); if (platdata == NULL) { @@ -89,7 +90,7 @@ static int ipq_xhci_core_init(struct ipq_xhci *ipq) { int ret = 0; - ipq_reset_usb_phy(ipq); + ipq_reset_usb_phy((void *)ipq); ret = dwc3_core_init(ipq->dwc3_reg); if (ret) { diff --git a/include/configs/ipq806x.h b/include/configs/ipq806x.h index ee8d604ef3..815c7fe237 100644 --- a/include/configs/ipq806x.h +++ b/include/configs/ipq806x.h @@ -47,9 +47,10 @@ #define CONFIG_MBN_HEADER #define CONFIG_IPQ_APPSBL_IMG_TYPE 0x5 -#undef CONFIG_IPQ806X_USB -#ifdef CONFIG_IPQ806X_USB +#define CONFIG_USB_XHCI_IPQ +#ifdef CONFIG_USB_XHCI_IPQ #define CONFIG_USB_XHCI +#define CONFIG_USB_XHCI_DWC3 #define CONFIG_CMD_USB #define CONFIG_DOS_PARTITION #define CONFIG_USB_STORAGE diff --git a/include/linux/usb/ipq_usb30.h b/include/linux/usb/ipq_usb30.h new file mode 100644 index 0000000000..9228cc5c3c --- /dev/null +++ b/include/linux/usb/ipq_usb30.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014, 2017 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MSM_USB30_H +#define __MSM_USB30_H + +/* + * QSCRATCH registers + */ +#define IPQ_SSUSB_REG_QSCRATCH_REV 0xF8800 +#define IPQ_SSUSB_REG_QSCRATCH_CTRL 0xF8804 +#define IPQ_SSUSB_REG_QSCRATCH_RAM1 0xF880C +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL 0xF8810 +#define IPQ_SSUSB_REG_QSCRATCH_PARAMETER_OVERRIDE_X 0xF8814 +#define IPQ_SSUSB_REG_QSCRATCH_CHARGING_DET_CTRL 0xF8818 +#define IPQ_SSUSB_REG_QSCRATCH_CHARGING_DET_OUTPUT 0xF881C +#define IPQ_SSUSB_REG_QSCRATCH_ALT_INTERRUPT_EN 0xF8820 +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_IRQ_STAT 0xF8824 +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL 0xF8828 +#define IPQ_SSUSB_REG_QSCRATCH_DBG_BUS 0xF882C +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1 0xF8834 +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_2 0xF8838 +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_IN 0xF883C +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_DATA_OUT 0xF8840 +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_ADDR 0xF8844 +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_CAP_DATA 0xF8848 +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_READ 0xF884C +#define IPQ_SSUSB_REG_QSCRATCH_SS_CR_PROTOCOL_WRITE 0xF8850 +#define IPQ_SSUSB_REG_QSCRATCH_SS_STATUS_READ_ONLY 0xF8854 +#define IPQ_SSUSB_REG_QSCRATCH_PWR_EVNT_IRQ_STAT 0xF8858 +#define IPQ_SSUSB_REG_QSCRATCH_PWR_EVNT_IRQ_MASK 0xF885C +#define IPQ_SSUSB_REG_QSCRATCH_HW_SW_EVT_CTRL 0xF8860 +#define IPQ_SSUSB_REG_QSCRATCH_VMIDMT_AMEMTYPE_CTRL 0xF8864 +#define IPQ_SSUSB_REG_QSCRATCH_QSCRTCH(n) 0xF8868 + ((n) * 0x4) + +/* + * Global config registers + */ + +#define IPQ_SSUSB_REG_GCTL_U2RSTECN (1 << 16) +#define IPQ_SSUSB_REG_GCTL_U2EXIT_LFPS (1 << 2) + +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL_RAM13_EN (1 << 4) +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL_RAM1112_EN (1 << 3) +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL_BAM_NDP_EN (1 << 2) +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL_DBM_FSM_EN (1 << 1) +#define IPQ_SSUSB_REG_QSCRATCH_CGCTL_DBM_REG_EN (1 << 0) + +#define IPQ_SSUSB_REG_QSCRATCH_RAM1_RAM13_EN (1 << 2) +#define IPQ_SSUSB_REG_QSCRATCH_RAM1RAM12_EN (1 << 1) +#define IPQ_SSUSB_REG_QSCRATCH_RAM1_RAM11_EN (1 << 0) + +#define IPQ_GPIO_IN_OUTn(n) (MSM_TLMM_BASE + \ + 0x00001004 + 0x10 * (n)) +#define IPQ_GPIO_IN_OUTn_GPIO_OUT_SHFT 1 + +/* + * USB Reset control register + */ +#define IPQ_USB30_RESET_PORT2_HS_PHY_ASYNC_RESET (1 << 5) +#define IPQ_USB30_RESET_MASTER_ASYNC_RESET (1 << 4) +#define IPQ_USB30_RESET_SLEEP_ASYNC_RESET (1 << 3) +#define IPQ_USB30_RESET_MOC_UTMI_ASYNC_RESET (1 << 2) +#define IPQ_USB30_RESET_POWERON_ASYNC_RESET (1 << 1) +#define IPQ_USB30_RESET_PHY_ASYNC_RESET (1 << 0) +#define IPQ_USB30_RESET_MASK 0x3F + +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_COMMONONN (1 << 11) +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_USE_CLKCORE (1 << 18) +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_FSEL_VAL 0x70 +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_AUTORESUME (1 << 19) +#define IPQ_SSUSB_REG_QSCRATCH_HS_PHY_CTRL_UTMI_OTG_VBUS_VALID (1 << 20) + +#define IPQ_QSCRATCH_REG_OFFSET (0x000F8800) +#define IPQ_QSCRATCH_GENERAL_CFG (IPQ_QSCRATCH_REG_OFFSET + 0x08) +#define IPQ_CHARGING_DET_CTRL_REG (IPQ_QSCRATCH_REG_OFFSET + 0x18) +#define IPQ_CHARGING_DET_OUTPUT_REG (IPQ_QSCRATCH_REG_OFFSET + 0x1C) +#define IPQ_ALT_INTERRUPT_EN_REG (IPQ_QSCRATCH_REG_OFFSET + 0x20) +#define IPQ_HS_PHY_IRQ_STAT_REG (IPQ_QSCRATCH_REG_OFFSET + 0x24) +#define IPQ_SS_PHY_CTRL_REG (IPQ_QSCRATCH_REG_OFFSET + 0x30) +#define IPQ_SS_PHY_PARAM_CTRL_1_REG (IPQ_QSCRATCH_REG_OFFSET + 0x34) + +/* + * PHY control Registers + */ +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_USE_PAD (1 << 28) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_TEST_BURNIN (1 << 27) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_TEST_POWERDOWN (1 << 26) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_RTUNE_REQ (1 << 25) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_LANE0_PWR_PRESENT (1 << 24) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_USB2_REF_CLK_EN (1 << 23) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_USB2_REF_CLK_SEL (1 << 22) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_SSC_REF_CLK_SEL(n) ((n) << 13) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_SSC_RANGE(n) ((n) << 10) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_USB2_EN (1 << 9) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_REF_SS_PHY_EN (1 << 8) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_SS_PHY_RESET (1 << 7) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_MPLL_MULTI(n) ((n) << 0) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_SS_PHY_RESET (1 << 7) +#define IPQ_SSUSB_QSCRATCH_SS_PHY_CTRL_SS_PHY_RESET (1 << 7) + +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_LANE0_TX_TERM_OFFSET(n) ((n) << 27) +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_SWING_FULL(n) ((n) << 20) +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_6DB(n) ((n) << 14) +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_TX_DEEMPH_3_5DB(n) ((n) << 8) +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_LOS_LEVEL(n) ((n) << 3) +#define IPQ_SSUSB_REG_QSCRATCH_SS_PHY_PARAM_CTRL_1_LOS_BIAS(n) ((n) << 0) +#define IPQ_SSUSB_REG_QSCRATCH_GENERAL_CFG_XHCI_REV(n) ((n) << 2) +#define IPQ_SSUSB_REG_QSCRATCH_GENERAL_CFG_DBM_EN (1 << 1) + +#define IPQ_TCSR_USB_CONTROLLER_TYPE_SEL 0x1A4000B0 +#define IPQ806X_USB_CONT_TYPE 0x3 +#define IPQ806X_USB_REG_MAP_SIZE 0x4 + +#define USB30_MODE_DEVICE 0 +#define USB30_MODE_HOST 1 + +struct dwc3_platform_data { + u8 usb_mode; + u8 pwr_en; + u8 pwr_en_gpio1; + u8 pwr_en_gpio2; +}; +#endif /*__MSM_USB30_H */