source: rtems-libbsd/rtemsbsd/sys/dev/usb/controller/usb_otg_transceiver.c @ 278bc93

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 278bc93 was 278bc93, checked in by Sebastian Huber <sebastian.huber@…>, on 03/16/15 at 20:39:14

usb: Import USB support from libusb

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <info@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <dev/usb/usb_otg_transceiver.h>
33
34#define COUNT(array) (sizeof(array) / sizeof(array [0]))
35
36#define USB_OTG_CONTROL_1_SPEED_REG (1 << 0)
37#define USB_OTG_CONTROL_1_SUSPEND_REG (1 << 1)
38#define USB_OTG_CONTROL_1_DAT_SE0 (1 << 2)
39#define USB_OTG_CONTROL_1_TRANSP_EN (1 << 3)
40#define USB_OTG_CONTROL_1_BDIS_ACON_EN (1 << 4)
41#define USB_OTG_CONTROL_1_OE_INT_EN (1 << 5)
42#define USB_OTG_CONTROL_1_UART_EN (1 << 6)
43
44/*
45 * USB_OTG_CONTROL_3
46 *
47 * On ISP130x  this is register MODE CONTROL 2
48 * On STOTG04E this is register CONTROL 3
49 *
50 *  'rsrvd' = not available reserved bit.
51 *  'diff'  = different functionality.
52 *
53 * Bit  Function              ISP1301      ISP1302       STOTG04E
54 * --------------------------------------------------------------
55 *  0   PWR_DN                  Y            Y             rsrvd
56 *  1   SPD_SUSP_CTRL           Y           rsrvd          diff
57 *  2   BI_DI                   Y           rsrvd           Y
58 *  3   TRANSP_BDIR[0]          Y            Y              Y
59 *  4   TRANSP_BDIR[1]          Y            Y              Y
60 *  5   AUDIO_EN                Y            Y              Y
61 *  6   PSW_OE                  Y            Y              Y
62 *  7   EN2V7                   Y           rsrvd           Y
63 */
64
65/* ISP1301 & ISP1302 (Reserved on STOTG04E) */
66#define ISP130x_CONTROL_3_GLOBAL_PWR_DN (1 << 0)
67/* ISP1301   (ISP1302 reserved bit!) */
68#define ISP1301_CONTROL_3_SPD_SUSP_CTRL (1 << 1)
69/* STOTG04E (Different functionality!) */
70#define STOTG04E_CONTROL_3_RX_BIAS_EN ISP1301_CONTROL_3_SPD_SUSP_CTRL
71/* ISP1301  (ISP1302 reserved bit!) */
72#define ISP1301_CONTROL_3_BI_DI (1 << 2)
73/* STOTG04E */
74#define STOTG04E_CONTROL_3_RC_BIAS_EN (1 << 1)
75#define STOTG04E_CONTROL_3_BIDI_EN ISP1301_CONTROL_3_BI_DI
76/* ISP1301, ISP1302 & STOTG04E common definitions. */
77#define USB_OTG_CONTROL_3_TRANSP_BDIR0 (1 << 3)
78#define USB_OTG_CONTROL_3_TRANSP_BDIR1 (1 << 4)
79#define USB_OTG_CONTROL_3_AUDIO_EN (1 << 5)
80#define USB_OTG_CONTROL_3_PSW_OE (1 << 6)
81/* ISP1301   (ISP1302 reserved bit.) */
82#define ISP1301_CONTROL_3_EN2V7 (1 << 7)
83/* STOTG04E */
84#define STOTG04E_CONTROL_3_2V7_EN ISP1301_CONTROL_3_EN2V7
85
86/* Note: STOTG04E Control register 2 = ISP130x OTG Control register */
87#define USB_OTG_CONTROL_2_DP_PULLUP (1 << 0)
88#define USB_OTG_CONTROL_2_DM_PULLUP (1 << 1)
89#define USB_OTG_CONTROL_2_DP_PULLDOWN (1 << 2)
90#define USB_OTG_CONTROL_2_DM_PULLDOWN (1 << 3)
91#define USB_OTG_CONTROL_2_ID_PULLDOWN (1 << 4)
92#define USB_OTG_CONTROL_2_VBUS_DRV (1 << 5)
93#define USB_OTG_CONTROL_2_VBUS_DISCHRG (1 << 6)
94#define USB_OTG_CONTROL_2_VBUS_CHRG (1 << 7)
95
96/* ISP1302 specific */
97#define ISP1302_MISC_CONTROL_REG_BYPASS_DIS (1 << 0)
98#define ISP1302_MISC_CONTROL_SRP_INIT (1 << 1)
99#define ISP1302_MISC_CONTROL_DP_WKPU_EN (1 << 2)
100#define ISP1302_MISC_CONTROL_IDPU_DIS (1 << 3)
101#define ISP1302_MISC_CONTROL_UART_2V8_EN (1 << 4)
102#define ISP1302_MISC_CONTROL_FORCE_DP_LOW (1 << 6)
103#define ISP1302_MISC_CONTROL_FORCE_DP_HIGH (1 << 7)
104
105int usb_otg_transceiver_read(
106        const struct usb_otg_transceiver *self,
107        const uint8_t *reg_addrs,
108        uint8_t *values,
109        size_t count
110)
111{
112        int eno = 0;
113        size_t i;
114
115        for (i = 0; eno == 0 && i < count; ++i) {
116                eno = (*self->read)(self, reg_addrs [i], &values [i]);
117        }
118
119        return eno;
120}
121
122int usb_otg_transceiver_write(
123        const struct usb_otg_transceiver *self,
124        const struct usb_otg_transceiver_write_request *requests,
125        size_t count
126)
127{
128        int eno = 0;
129        size_t i;
130
131        for (i = 0; eno == 0 && i < count; ++i) {
132                const struct usb_otg_transceiver_write_request *request = &requests [i];
133
134                eno = (*self->write)(self, request->reg_addr, request->value);
135        }
136
137        return eno;
138}
139
140int usb_otg_transceiver_init(struct usb_otg_transceiver *self)
141{
142        static const uint8_t reg_addrs [4] = {
143                USB_OTG_VENDOR_ID_LOW,
144                USB_OTG_VENDOR_ID_HIGH,
145                USB_OTG_PRODUCT_ID_LOW,
146                USB_OTG_PRODUCT_ID_HIGH
147        };
148
149        int eno;
150        uint8_t values [4];
151
152        eno = usb_otg_transceiver_read(self, reg_addrs, values, 4);
153        if (eno == 0) {
154                self->vendor_id = (uint16_t) ((values [1] << 8) | values [0]);
155                self->product_id = (uint16_t) ((values [3] << 8) | values [2]);
156        }
157
158        return eno;
159}
160
161#define RESUME_SETUP_REQUESTS \
162        { USB_OTG_CONTROL_1_CLEAR, 0xff }, \
163        { USB_OTG_CONTROL_1_SET, USB_OTG_CONTROL_1_SPEED_REG }, \
164        { USB_OTG_CONTROL_3_CLEAR, 0xff }
165
166#define RESUME_FINALIZE_REQUESTS \
167        { USB_OTG_CONTROL_2_CLEAR, 0xff }, \
168        { USB_OTG_CONTROL_1_SET, USB_OTG_CONTROL_1_DAT_SE0 }, \
169        { \
170                USB_OTG_CONTROL_2_SET, \
171                USB_OTG_CONTROL_2_DM_PULLDOWN | USB_OTG_CONTROL_2_DP_PULLDOWN \
172        }, \
173        { USB_OTG_INT_LATCH_CLEAR, 0xff }, \
174        { USB_OTG_INT_ENABLE_LOW_CLEAR, 0xff }, \
175        { USB_OTG_INT_ENABLE_HIGH_CLEAR, 0xff }
176
177int usb_otg_transceiver_resume(const struct usb_otg_transceiver *self)
178{
179        static const struct usb_otg_transceiver_write_request
180        default_requests [] = {
181                RESUME_SETUP_REQUESTS,
182                RESUME_FINALIZE_REQUESTS
183        };
184
185        static const struct usb_otg_transceiver_write_request
186        isp1301_requests [] = {
187                RESUME_SETUP_REQUESTS,
188                {
189                        USB_OTG_CONTROL_3_SET,
190                        ISP1301_CONTROL_3_BI_DI
191                                | USB_OTG_CONTROL_3_PSW_OE
192                                | ISP1301_CONTROL_3_SPD_SUSP_CTRL
193                },
194                RESUME_FINALIZE_REQUESTS
195        };
196
197        static const struct usb_otg_transceiver_write_request
198        isp1302_requests [] = {
199                RESUME_SETUP_REQUESTS,
200                {
201                        USB_OTG_CONTROL_3_SET,
202                        ISP1301_CONTROL_3_BI_DI | USB_OTG_CONTROL_3_PSW_OE
203                }, {
204                        ISP1302_MISC_CONTROL_CLEAR,
205                        0xff
206                }, {
207                        ISP1302_MISC_CONTROL_SET,
208                        ISP1302_MISC_CONTROL_UART_2V8_EN
209                },
210                RESUME_FINALIZE_REQUESTS
211        };
212
213        static const struct usb_otg_transceiver_write_request
214        stotg04e_requests [] = {
215                RESUME_SETUP_REQUESTS,
216                {
217                        USB_OTG_CONTROL_3_SET,
218                        STOTG04E_CONTROL_3_BIDI_EN | USB_OTG_CONTROL_3_PSW_OE,
219                },
220                RESUME_FINALIZE_REQUESTS
221        };
222
223        int eno;
224        const struct usb_otg_transceiver_write_request *requests;
225        size_t count;
226
227        switch (self->product_id) {
228                case USB_OTG_PRODUCT_ID_ISP1301:
229                        requests = isp1301_requests;
230                        count = COUNT(isp1301_requests);
231                        break;
232                case USB_OTG_PRODUCT_ID_ISP1302:
233                        requests = isp1302_requests;
234                        count = COUNT(isp1302_requests);
235                        break;
236                case USB_OTG_PRODUCT_ID_STOTG04E:
237                        requests = stotg04e_requests;
238                        count = COUNT(stotg04e_requests);
239                        break;
240                default:
241                        requests = default_requests;
242                        count = COUNT(default_requests);
243                        break;
244        }
245
246        eno = usb_otg_transceiver_write(self, requests, count);
247
248        return eno;
249}
250
251int usb_otg_transceiver_suspend(const struct usb_otg_transceiver *self)
252{
253        static const struct usb_otg_transceiver_write_request
254        default_requests [] = {
255                {
256                        USB_OTG_CONTROL_1_SET,
257                        USB_OTG_CONTROL_1_SUSPEND_REG
258                }, {
259                        USB_OTG_CONTROL_1_CLEAR,
260                        USB_OTG_CONTROL_1_TRANSP_EN | USB_OTG_CONTROL_1_UART_EN
261                }, {
262                        USB_OTG_CONTROL_2_CLEAR,
263                        USB_OTG_CONTROL_2_DP_PULLUP
264                                | USB_OTG_CONTROL_2_DM_PULLUP
265                                | USB_OTG_CONTROL_2_ID_PULLDOWN
266                                | USB_OTG_CONTROL_2_VBUS_DRV
267                                | USB_OTG_CONTROL_2_VBUS_CHRG
268                }, {
269                        USB_OTG_CONTROL_3_SET,
270                        USB_OTG_CONTROL_3_PSW_OE
271                }, {
272                        USB_OTG_CONTROL_3_CLEAR,
273                        USB_OTG_CONTROL_3_AUDIO_EN
274                }
275        };
276
277        int eno;
278        const struct usb_otg_transceiver_write_request *requests;
279        size_t count;
280
281        requests = default_requests;
282        count = COUNT(default_requests);
283
284        eno = usb_otg_transceiver_write(self, requests, count);
285
286        return eno;
287}
288
289int usb_otg_transceiver_set_vbus(
290        const struct usb_otg_transceiver *self,
291        enum usb_otg_transceiver_vbus vbus
292)
293{
294        int eno;
295        int all = USB_OTG_VBUS_POWER_WITH_CHARGE_PUMP
296                | USB_OTG_VBUS_DISCHARGE_VIA_RESISTOR
297                | USB_OTG_VBUS_CHARGE_VIA_RESISTOR;
298        struct usb_otg_transceiver_write_request requests [] = {
299                { USB_OTG_CONTROL_2_CLEAR, (uint8_t) (all & ~vbus) },
300                { USB_OTG_CONTROL_2_SET, (uint8_t) (all & vbus) }
301        };
302
303        eno = usb_otg_transceiver_write(self, &requests [0], COUNT(requests));
304
305        return eno;
306}
Note: See TracBrowser for help on using the repository browser.