summaryrefslogtreecommitdiff
path: root/src/soc/qualcomm/common/usb/usb.c
blob: 3a0c00327bcc912313d207daa15a946f42eab41a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <device/mmio.h>
#include <soc/usb/usb_common.h>
#include <soc/addressmap.h>
#include <soc/clock.h>

struct usb_dwc3 {
	u32 sbuscfg0;
	u32 sbuscfg1;
	u32 txthrcfg;
	u32 rxthrcfg;
	u32 ctl;
	u32 pmsts;
	u32 sts;
	u32 uctl1;
	u32 snpsid;
	u32 gpio;
	u32 uid;
	u32 uctl;
	u64 buserraddr;
	u64 prtbimap;
	u8 reserved1[32];
	u32 dbgfifospace;
	u32 dbgltssm;
	u32 dbglnmcc;
	u32 dbgbmu;
	u32 dbglspmux;
	u32 dbglsp;
	u32 dbgepinfo0;
	u32 dbgepinfo1;
	u64 prtbimap_hs;
	u64 prtbimap_fs;
	u8 reserved2[112];
	u32 usb2phycfg;
	u8 reserved3[124];
	u32 usb2phyacc;
	u8 reserved4[60];
	u32 usb3pipectl;
	u8 reserved5[60];
};
check_member(usb_dwc3, usb2phycfg, 0x100);
check_member(usb_dwc3, usb3pipectl, 0x1c0);

struct usb_dwc3_cfg {
	struct usb_dwc3 *usb_host_dwc3;
	u32 *usb3_bcr;
	u32 *qusb2phy_bcr;
	u32 *gcc_usb3phy_bcr_reg;
	u32 *gcc_qmpphy_bcr_reg;
};

static struct usb_dwc3_cfg usb_port0 = {
	.usb_host_dwc3 =	(void *)USB_HOST_DWC3_BASE,
	.usb3_bcr =		&gcc->usb30_prim_bcr,
	.qusb2phy_bcr =		&gcc->qusb2phy_prim_bcr,
	.gcc_usb3phy_bcr_reg =	&gcc->usb3_dp_phy_prim_bcr,
	.gcc_qmpphy_bcr_reg =	&gcc->usb3_phy_prim_bcr,
};

static void reset_usb(struct usb_dwc3_cfg *dwc3)
{
	/* Assert Core reset */
	clock_reset_bcr(dwc3->usb3_bcr, 1);

	/* Assert HS PHY reset */
	clock_reset_bcr(dwc3->qusb2phy_bcr, 1);

	/* Assert QMP PHY reset */
	clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 1);
	clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 1);
}

void reset_usb0(void)
{
	/* Before Resetting PHY, put Core in Reset */
	printk(BIOS_INFO, "Starting DWC3 and PHY resets for USB(0)\n");

	reset_usb(&usb_port0);
}

static void setup_dwc3(struct usb_dwc3 *dwc3)
{
	/* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */
	clrsetbits32(&dwc3->usb3pipectl,
		DWC3_GUSB3PIPECTL_DELAYP1TRANS,
		DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX);

	/*
	 * Configure USB phy interface of DWC3 core.
	 * 1. Select UTMI+ PHY with 16-bit interface.
	 * 2. Set USBTRDTIM to the corresponding value
	 * according to the UTMI+ PHY interface.
	 */
	clrsetbits32(&dwc3->usb2phycfg,
			(DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK |
			DWC3_GUSB2PHYCFG_PHYIF_MASK),
			(DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
			DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT)));

	clrsetbits32(&dwc3->ctl, (DWC3_GCTL_SCALEDOWN_MASK |
			DWC3_GCTL_DISSCRAMBLE),
			DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_DSBLCLKGTNG);

	/* configure controller in Host mode */
	clrsetbits32(&dwc3->ctl, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)),
			DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST));
	printk(BIOS_SPEW, "Configure USB in Host mode\n");
}

/* Initialization of DWC3 Core and PHY */

static void setup_usb_host(struct usb_dwc3_cfg *dwc3,
			void  *board_data)
{
	 /* Clear core reset. */
	clock_reset_bcr(dwc3->usb3_bcr, 0);

	/* Clear QUSB PHY reset. */
	clock_reset_bcr(dwc3->qusb2phy_bcr, 0);

	/* Initialize HS PHY */
	hs_usb_phy_init(board_data);

	/* Clear QMP PHY resets. */
	clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 0);
	clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 0);

	/* Initialize QMP PHY */
	ss_qmp_phy_init();

	setup_dwc3(dwc3->usb_host_dwc3);

	printk(BIOS_INFO, "DWC3 and PHY setup finished\n");
}
void setup_usb_host0(void  *board_data)
{
	printk(BIOS_INFO, "Setting up USB HOST0 controller.\n");
	setup_usb_host(&usb_port0, board_data);
}