blob: f0f271b097063985303257319f69602f84801035 [file] [log] [blame]
Amol Jadif3d5a892013-07-23 16:09:44 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * The USB 3.0 core wrapper in MSM chipset includes:
31 * - DWC core
32 * - PHY control and configuration
33 * - Configuration and buffers to be provided to the DWC core.
34 *
35 * This file implements the USB30 core wrapper configuration functions.
36 * Core wrapper glues the dwc usb controller into msm chip.
37*/
38
39
40#include <debug.h>
41#include <reg.h>
42#include <malloc.h>
43#include <assert.h>
44#include <board.h>
45#include <pm8x41.h>
46#include <platform/iomap.h>
47#include <platform/timer.h>
48#include <platform/iomap.h>
49#include <platform/clock.h>
50#include <usb30_wrapper.h>
51#include <usb30_wrapper_hwio.h>
52
53
54/* Configure DBM mode: by-pass or DBM */
55void usb_wrapper_dbm_mode(usb_wrapper_dev_t *dev, dbm_mode_t mode)
56{
57 if (mode == DBM_MODE_BYPASS)
58 {
59 REG_WRITE_FIELD(dev, GENERAL_CFG, DBM_EN, 0);
60 }
61 else
62 {
63 REG_WRITE_FIELD(dev, GENERAL_CFG, DBM_EN, 1);
64 }
65}
66
67/* use config 0: all of RAM1 */
68void usb_wrapper_ram_configure(usb_wrapper_dev_t *dev)
69{
70 REG_WRITE(dev, RAM1_REG, 0x0);
71}
72
73/* reset SS phy */
74void usb_wrapper_ss_phy_reset(usb_wrapper_dev_t *dev)
75{
76 REG_WRITE_FIELD(dev, SS_PHY_CTRL, SS_PHY_RESET, 1);
77
78 /* per HPG */
79 udelay(10);
80
81 REG_WRITE_FIELD(dev, SS_PHY_CTRL, SS_PHY_RESET, 0);
82}
83
84/* configure SS phy as specified in HPG */
85void usb_wrapper_ss_phy_configure(usb_wrapper_dev_t *dev)
86{
87 /* 4.a */
88 REG_WRITE_FIELD(dev, SS_PHY_CTRL, REF_USE_PAD, 1);
89 /* .b */
90 REG_WRITE_FIELD(dev, SS_PHY_CTRL, LANE0_PWR_PRESENT, 1);
91 /* .c */
92 REG_WRITE_FIELD(dev, SS_PHY_CTRL, REF_SS_PHY_EN, 1);
93
94 /* For Aragorn V1, reset value fix is required.*/
95 if ( (board_platform_id() == MSM8974) &&
96 (board_soc_version() < BOARD_SOC_VERSION2))
97 {
98 REG_WRITE_FIELD(dev, SS_PHY_CTRL, SSC_REF_CLK_SEL, 0x108);
99 }
100}
101
102/* configure SS phy electrical params */
103void usb_wrapper_ss_phy_electrical_config(usb_wrapper_dev_t *dev)
104{
105 /* reset value seems to work just fine for now. */
106}
107
108/* Initialize HS phy */
109void usb_wrapper_hs_phy_init(usb_wrapper_dev_t *dev)
110{
111 /* 5.a */
112 REG_WRITE_FIELD(dev, HS_PHY_CTRL, FREECLK_SEL, 0x0);
113
114 /* 5.b */
115 REG_WRITE_FIELD(dev, HS_PHY_CTRL, COMMONONN, 0x1);
116}
117
118/* configure HS phy as specified in HPG */
119void usb_wrapper_hs_phy_configure(usb_wrapper_dev_t *dev)
120{
121 /* 6.a */
122 REG_WRITE(dev, PARAMETER_OVERRIDE_X, 0xD190E4);
123}
124
125void usb_wrapper_workaround_10(usb_wrapper_dev_t *dev)
126{
127 /* 10. */
128 if ( (board_platform_id() == MSM8974) &&
129 (board_soc_version() < BOARD_SOC_VERSION2))
130 {
131 /* TODO: confirm if V1 in HPG only applies to 8974 */
132 REG_WRITE(dev, GENERAL_CFG, 0x78);
133 }
134}
135
136void usb_wrapper_workaround_11(usb_wrapper_dev_t *dev)
137{
138 /*
139 * 11. Apply WA for QCTDD00335018 -
140 * a. Description: Enables the Tx for alt bus mode, powers up the pmos_bias block, and so on; required if manually running the alt bus features.
141 * b. Assert LANE0.TX_ALT_BLOCK (102D) EN_ALT_BUS (bit 7);
142 * c. To be replaced in V2 with other WA (which will be applied during suspend sequence)
143 *
144 */
145
146 /* Not implemented. required if manually running the alt bus features.*/
147}
148
149/* workaround #13 as described in HPG */
150void usb_wrapper_workaround_13(usb_wrapper_dev_t *dev)
151{
152 REG_WRITE_FIELD(dev, SS_PHY_PARAM_CTRL_1, LOS_BIAS, 0x5);
153}
154
155
156/* API to read SS PHY registers */
157uint16_t usb_wrapper_ss_phy_read(usb_wrapper_dev_t *dev, uint16_t addr)
158{
159 uint16_t data;
160
161 /* write address to be read */
162 REG_WRITE(dev, SS_CR_PROTOCOL_DATA_IN, addr);
163
164 /* trigger capture of address in addr reg and wait until done */
165 REG_WRITE(dev, SS_CR_PROTOCOL_CAP_ADDR, 0x1);
166 while(REG_READ(dev, SS_CR_PROTOCOL_CAP_ADDR) & 0x1);
167
168 /* read from referenced register */
169 REG_WRITE(dev, SS_CR_PROTOCOL_READ, 0x1);
170
171 /* wait until read is done */
172 while(REG_READ(dev, SS_CR_PROTOCOL_READ) & 0x1);
173 data = REG_READ(dev, SS_CR_PROTOCOL_DATA_OUT);
174
175 /* TODO: hpg 4.14.2 note: reading ss phy register must be performed twice.
176 * does this whole sequence need to be done twice or just the reading from
177 * data_out??
178 * QCTDD00516153
179 */
180 ASSERT(0);
181
182 return data;
183}
184
185/* API to write to SS PHY registers */
186void usb_wrapper_ss_phy_write(usb_wrapper_dev_t *dev, uint16_t addr, uint16_t data)
187{
188 /* write address to be read */
189 REG_WRITE(dev, SS_CR_PROTOCOL_DATA_IN, addr);
190
191 /* trigger capture of address in addr reg and wait until done */
192 REG_WRITE(dev, SS_CR_PROTOCOL_CAP_ADDR, 0x1);
193 while(REG_READ(dev, SS_CR_PROTOCOL_CAP_ADDR) & 0x1);
194
195 /* write address to be read */
196 REG_WRITE(dev, SS_CR_PROTOCOL_DATA_IN, data);
197
198 /* trigger capture of data in addr reg and wait until done */
199 REG_WRITE(dev, SS_CR_PROTOCOL_CAP_DATA, 0x1);
200 while(REG_READ(dev, SS_CR_PROTOCOL_CAP_DATA) & 0x1);
201
202 /* write to referenced register and wait until done */
203 REG_WRITE(dev, SS_CR_PROTOCOL_WRITE, 0x1);
204 while(REG_READ(dev, SS_CR_PROTOCOL_READ) & 0x1);
205
206 /* TODO: hpg 4.14.2 note: reading ss phy register must be performed twice.
207 * does this whole sequence need to be done twice or just the reading from
208 * data_out??
209 * QCTDD00516153
210 */
211 ASSERT(0);
212}
213
214/* initialize the wrapper core */
215usb_wrapper_dev_t * usb_wrapper_init(usb_wrapper_config_t *config)
216{
217 usb_wrapper_dev_t *wrapper;
218
219 /* create a wrapper device */
220 wrapper = (usb_wrapper_dev_t*) malloc(sizeof(usb_wrapper_dev_t));
221 ASSERT(wrapper);
222
223 /* save qscratch base */
224 wrapper->base = config->qscratch_base;
225
226 /* initialize usb clocks */
227 clock_usb30_init();
228
229 /* enable ss phy clock */
230 pm8x41_diff_clock_ctrl(1);
231
232 /* HPG: section 4.4.1 Control sequence */
233 usb_wrapper_dbm_mode(wrapper, DBM_MODE_BYPASS);
234
235 /* HPG: section 4.4.1: use config 0 - all of RAM1 */
236 usb_wrapper_ram_configure(wrapper);
237
238 return wrapper;
239}