common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / usb / ulpi / ulpi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2011 Jana Rapava <fermata7@gmail.com>
4  * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il>
5  *
6  * Authors: Jana Rapava <fermata7@gmail.com>
7  *          Igor Grinberg <grinberg@compulab.co.il>
8  *
9  * Based on:
10  * linux/drivers/usb/otg/ulpi.c
11  * Generic ULPI USB transceiver support
12  *
13  * Original Copyright follow:
14  * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
15  *
16  * Based on sources from
17  *
18  *   Sascha Hauer <s.hauer@pengutronix.de>
19  *   Freescale Semiconductors
20  */
21
22 #include <common.h>
23 #include <exports.h>
24 #include <log.h>
25 #include <linux/delay.h>
26 #include <usb/ulpi.h>
27
28 #define ULPI_ID_REGS_COUNT      4
29 #define ULPI_TEST_VALUE         0x55    /* 0x55 == 0b01010101 */
30
31 static struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
32
33 static int ulpi_integrity_check(struct ulpi_viewport *ulpi_vp)
34 {
35         u32 val, tval = ULPI_TEST_VALUE;
36         int err, i;
37
38         /* Use the 'special' test value to check all bits */
39         for (i = 0; i < 2; i++, tval <<= 1) {
40                 err = ulpi_write(ulpi_vp, &ulpi->scratch, tval);
41                 if (err)
42                         return err;
43
44                 val = ulpi_read(ulpi_vp, &ulpi->scratch);
45                 if (val != tval) {
46                         printf("ULPI integrity check failed\n");
47                         return val;
48                 }
49         }
50
51         return 0;
52 }
53
54 int ulpi_init(struct ulpi_viewport *ulpi_vp)
55 {
56         u32 val, id = 0;
57         u8 *reg = &ulpi->product_id_high;
58         int i;
59
60         /* Assemble ID from four ULPI ID registers (8 bits each). */
61         for (i = 0; i < ULPI_ID_REGS_COUNT; i++) {
62                 val = ulpi_read(ulpi_vp, reg - i);
63                 if (val == ULPI_ERROR)
64                         return val;
65
66                 id = (id << 8) | val;
67         }
68
69         /* Split ID into vendor and product ID. */
70         debug("ULPI transceiver ID 0x%04x:0x%04x\n", id >> 16, id & 0xffff);
71
72         return ulpi_integrity_check(ulpi_vp);
73 }
74
75 int ulpi_select_transceiver(struct ulpi_viewport *ulpi_vp, unsigned speed)
76 {
77         u32 tspeed = ULPI_FC_FULL_SPEED;
78         u32 val;
79
80         switch (speed) {
81         case ULPI_FC_HIGH_SPEED:
82         case ULPI_FC_FULL_SPEED:
83         case ULPI_FC_LOW_SPEED:
84         case ULPI_FC_FS4LS:
85                 tspeed = speed;
86                 break;
87         default:
88                 printf("ULPI: %s: wrong transceiver speed specified: %u, "
89                         "falling back to full speed\n", __func__, speed);
90         }
91
92         val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
93         if (val == ULPI_ERROR)
94                 return val;
95
96         /* clear the previous speed setting */
97         val = (val & ~ULPI_FC_XCVRSEL_MASK) | tspeed;
98
99         return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
100 }
101
102 int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power)
103 {
104         u32 flags = ULPI_OTG_DRVVBUS;
105         u8 *reg = on ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
106
107         if (ext_power)
108                 flags |= ULPI_OTG_DRVVBUS_EXT;
109
110         return ulpi_write(ulpi_vp, reg, flags);
111 }
112
113 int ulpi_set_vbus_indicator(struct ulpi_viewport *ulpi_vp, int external,
114                         int passthu, int complement)
115 {
116         u32 flags, val;
117         u8 *reg;
118
119         reg = external ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
120         val = ulpi_write(ulpi_vp, reg, ULPI_OTG_EXTVBUSIND);
121         if (val)
122                 return val;
123
124         flags = passthu ? ULPI_IFACE_PASSTHRU : 0;
125         flags |= complement ? ULPI_IFACE_EXTVBUS_COMPLEMENT : 0;
126
127         val = ulpi_read(ulpi_vp, &ulpi->iface_ctrl);
128         if (val == ULPI_ERROR)
129                 return val;
130
131         val = val & ~(ULPI_IFACE_PASSTHRU & ULPI_IFACE_EXTVBUS_COMPLEMENT);
132         val |= flags;
133         val = ulpi_write(ulpi_vp, &ulpi->iface_ctrl, val);
134         if (val)
135                 return val;
136
137         return 0;
138 }
139
140 int ulpi_set_pd(struct ulpi_viewport *ulpi_vp, int enable)
141 {
142         u32 val = ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN;
143         u8 *reg = enable ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
144
145         return ulpi_write(ulpi_vp, reg, val);
146 }
147
148 int ulpi_opmode_sel(struct ulpi_viewport *ulpi_vp, unsigned opmode)
149 {
150         u32 topmode = ULPI_FC_OPMODE_NORMAL;
151         u32 val;
152
153         switch (opmode) {
154         case ULPI_FC_OPMODE_NORMAL:
155         case ULPI_FC_OPMODE_NONDRIVING:
156         case ULPI_FC_OPMODE_DISABLE_NRZI:
157         case ULPI_FC_OPMODE_NOSYNC_NOEOP:
158                 topmode = opmode;
159                 break;
160         default:
161                 printf("ULPI: %s: wrong OpMode specified: %u, "
162                         "falling back to OpMode Normal\n", __func__, opmode);
163         }
164
165         val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
166         if (val == ULPI_ERROR)
167                 return val;
168
169         /* clear the previous opmode setting */
170         val = (val & ~ULPI_FC_OPMODE_MASK) | topmode;
171
172         return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
173 }
174
175 int ulpi_serial_mode_enable(struct ulpi_viewport *ulpi_vp, unsigned smode)
176 {
177         switch (smode) {
178         case ULPI_IFACE_6_PIN_SERIAL_MODE:
179         case ULPI_IFACE_3_PIN_SERIAL_MODE:
180                 break;
181         default:
182                 printf("ULPI: %s: unrecognized Serial Mode specified: %u\n",
183                         __func__, smode);
184                 return ULPI_ERROR;
185         }
186
187         return ulpi_write(ulpi_vp, &ulpi->iface_ctrl_set, smode);
188 }
189
190 int ulpi_suspend(struct ulpi_viewport *ulpi_vp)
191 {
192         int err;
193
194         err = ulpi_write(ulpi_vp, &ulpi->function_ctrl_clear,
195                         ULPI_FC_SUSPENDM);
196         if (err)
197                 printf("ULPI: %s: failed writing the suspend bit\n", __func__);
198
199         return err;
200 }
201
202 /*
203  * Wait for ULPI PHY reset to complete.
204  * Actual wait for reset must be done in a view port specific way,
205  * because it involves checking the DIR line.
206  */
207 static int __ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
208 {
209         u32 val;
210         int timeout = CONFIG_USB_ULPI_TIMEOUT;
211
212         /* Wait for the RESET bit to become zero */
213         while (--timeout) {
214                 /*
215                  * This function is generic and suppose to work
216                  * with any viewport, so we cheat here and don't check
217                  * for the error of ulpi_read(), if there is one, then
218                  * there will be a timeout.
219                  */
220                 val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
221                 if (!(val & ULPI_FC_RESET))
222                         return 0;
223
224                 udelay(1);
225         }
226
227         printf("ULPI: %s: reset timed out\n", __func__);
228
229         return ULPI_ERROR;
230 }
231 int ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
232         __attribute__((weak, alias("__ulpi_reset_wait")));
233
234 int ulpi_reset(struct ulpi_viewport *ulpi_vp)
235 {
236         int err;
237
238         err = ulpi_write(ulpi_vp,
239                         &ulpi->function_ctrl_set, ULPI_FC_RESET);
240         if (err) {
241                 printf("ULPI: %s: failed writing reset bit\n", __func__);
242                 return err;
243         }
244
245         return ulpi_reset_wait(ulpi_vp);
246 }