1*a9beb1edSmglocker /* $OpenBSD: dwc2.h,v 1.16 2022/09/04 08:42:39 mglocker Exp $ */
225e434cbSuebayasi /* $NetBSD: dwc2.h,v 1.4 2014/12/23 16:20:06 macallan Exp $ */
3578f812dSuebayasi
4578f812dSuebayasi /*-
5578f812dSuebayasi * Copyright (c) 2013 The NetBSD Foundation, Inc.
6578f812dSuebayasi * All rights reserved.
7578f812dSuebayasi *
8578f812dSuebayasi * This code is derived from software contributed to The NetBSD Foundation
9578f812dSuebayasi * by Nick Hudson
10578f812dSuebayasi *
11578f812dSuebayasi * Redistribution and use in source and binary forms, with or without
12578f812dSuebayasi * modification, are permitted provided that the following conditions
13578f812dSuebayasi * are met:
14578f812dSuebayasi * 1. Redistributions of source code must retain the above copyright
15578f812dSuebayasi * notice, this list of conditions and the following disclaimer.
16578f812dSuebayasi * 2. Redistributions in binary form must reproduce the above copyright
17578f812dSuebayasi * notice, this list of conditions and the following disclaimer in the
18578f812dSuebayasi * documentation and/or other materials provided with the distribution.
19578f812dSuebayasi *
20578f812dSuebayasi * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21578f812dSuebayasi * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22578f812dSuebayasi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23578f812dSuebayasi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24578f812dSuebayasi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25578f812dSuebayasi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26578f812dSuebayasi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27578f812dSuebayasi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28578f812dSuebayasi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29578f812dSuebayasi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30578f812dSuebayasi * POSSIBILITY OF SUCH DAMAGE.
31578f812dSuebayasi */
32578f812dSuebayasi
33578f812dSuebayasi #ifndef _EXTERNAL_BSD_DWC2_DWC2_H_
34578f812dSuebayasi #define _EXTERNAL_BSD_DWC2_DWC2_H_
35578f812dSuebayasi
36578f812dSuebayasi #include <sys/param.h>
37578f812dSuebayasi #include <sys/kernel.h>
38578f812dSuebayasi
39309465dbSuebayasi #include <sys/task.h>
40578f812dSuebayasi
41c95c98b7Sjmatthew #include <lib/libkern/libkern.h>
42578f812dSuebayasi
4305c50565Suebayasi #define STATIC
4405c50565Suebayasi
45*a9beb1edSmglocker // #define DWC2_DEBUG
46578f812dSuebayasi // #define VERBOSE_DEBUG
47578f812dSuebayasi // #define CONFIG_USB_DWC2_TRACK_MISSED_SOFS
48578f812dSuebayasi
49d05ae140Smglocker #define CONFIG_USB_DWC2_HOST 1
50d05ae140Smglocker #define CONFIG_USB_DWC2_DUAL_ROLE 0
51d05ae140Smglocker #define CONFIG_USB_DWC2_PERIPHERAL 0
52d05ae140Smglocker
53578f812dSuebayasi typedef int irqreturn_t;
54578f812dSuebayasi #define IRQ_NONE 0
55578f812dSuebayasi #define IRQ_HANDLED 1
56578f812dSuebayasi
57578f812dSuebayasi #define u8 uint8_t
58578f812dSuebayasi #define u16 uint16_t
59578f812dSuebayasi #define s16 int16_t
60578f812dSuebayasi #define u32 uint32_t
61578f812dSuebayasi #define u64 uint64_t
62578f812dSuebayasi
63578f812dSuebayasi #define dma_addr_t bus_addr_t
64578f812dSuebayasi
65578f812dSuebayasi #ifdef DWC2_DEBUG
66578f812dSuebayasi extern int dwc2debug;
67578f812dSuebayasi #define dev_info(d,fmt,...) do { \
68578f812dSuebayasi printf("%s: " fmt, device_xname(d), \
69578f812dSuebayasi ## __VA_ARGS__); \
70578f812dSuebayasi } while (0)
71578f812dSuebayasi #define dev_warn(d,fmt,...) do { \
72578f812dSuebayasi printf("%s: " fmt, device_xname(d), \
73578f812dSuebayasi ## __VA_ARGS__); \
74578f812dSuebayasi } while (0)
75578f812dSuebayasi #define dev_err(d,fmt,...) do { \
76578f812dSuebayasi printf("%s: " fmt, device_xname(d), \
77578f812dSuebayasi ## __VA_ARGS__); \
78578f812dSuebayasi } while (0)
79578f812dSuebayasi #define dev_dbg(d,fmt,...) do { \
80578f812dSuebayasi if (dwc2debug >= 1) { \
81578f812dSuebayasi printf("%s: " fmt, device_xname(d), \
82578f812dSuebayasi ## __VA_ARGS__); \
83578f812dSuebayasi } \
84578f812dSuebayasi } while (0)
85578f812dSuebayasi #define dev_vdbg(d,fmt,...) do { \
86578f812dSuebayasi if (dwc2debug >= 2) { \
87578f812dSuebayasi printf("%s: " fmt, device_xname(d), \
88578f812dSuebayasi ## __VA_ARGS__); \
89578f812dSuebayasi } \
90578f812dSuebayasi } while (0)
91578f812dSuebayasi #else
92578f812dSuebayasi #define dev_info(...) do { } while (0)
93578f812dSuebayasi #define dev_warn(...) do { } while (0)
94578f812dSuebayasi #define dev_err(...) do { } while (0)
95578f812dSuebayasi #define dev_dbg(...) do { } while (0)
96578f812dSuebayasi #define dev_vdbg(...) do { } while (0)
97578f812dSuebayasi #endif
98578f812dSuebayasi
99578f812dSuebayasi enum usb_otg_state {
100578f812dSuebayasi OTG_STATE_RESERVED = 0,
101578f812dSuebayasi
102578f812dSuebayasi OTG_STATE_A_HOST,
103578f812dSuebayasi OTG_STATE_A_PERIPHERAL,
104578f812dSuebayasi OTG_STATE_A_SUSPEND,
105578f812dSuebayasi OTG_STATE_B_HOST,
106578f812dSuebayasi OTG_STATE_B_PERIPHERAL,
107578f812dSuebayasi };
108578f812dSuebayasi
109b6c5b329Suebayasi #define spinlock_t struct mutex
110*a9beb1edSmglocker #define spin_lock_init(lock) mtx_init(lock, IPL_VM)
111b6c5b329Suebayasi #define spin_lock(l) do { mtx_enter(l); } while (0)
112b6c5b329Suebayasi #define spin_unlock(l) do { mtx_leave(l); } while (0)
113578f812dSuebayasi
114578f812dSuebayasi #define spin_lock_irqsave(l, f) \
115b6c5b329Suebayasi do { mtx_enter(l); (void)(f); } while (0)
116578f812dSuebayasi
117*a9beb1edSmglocker #define spin_trylock_irqsave(l, f) mtx_enter_try(l)
118*a9beb1edSmglocker
119578f812dSuebayasi #define spin_unlock_irqrestore(l, f) \
120b6c5b329Suebayasi do { mtx_leave(l); (void)(f); } while (0)
121578f812dSuebayasi
122578f812dSuebayasi #define IRQ_RETVAL(r) (r)
123578f812dSuebayasi
124578f812dSuebayasi #define USB_ENDPOINT_XFER_CONTROL UE_CONTROL /* 0 */
125578f812dSuebayasi #define USB_ENDPOINT_XFER_ISOC UE_ISOCHRONOUS /* 1 */
126578f812dSuebayasi #define USB_ENDPOINT_XFER_BULK UE_BULK /* 2 */
127578f812dSuebayasi #define USB_ENDPOINT_XFER_INT UE_INTERRUPT /* 3 */
128578f812dSuebayasi
129578f812dSuebayasi #define USB_DIR_IN UE_DIR_IN
130578f812dSuebayasi #define USB_DIR_OUT UE_DIR_OUT
131578f812dSuebayasi
132578f812dSuebayasi #define USB_PORT_FEAT_CONNECTION UHF_PORT_CONNECTION
133578f812dSuebayasi #define USB_PORT_FEAT_ENABLE UHF_PORT_ENABLE
134578f812dSuebayasi #define USB_PORT_FEAT_SUSPEND UHF_PORT_SUSPEND
135578f812dSuebayasi #define USB_PORT_FEAT_OVER_CURRENT UHF_PORT_OVER_CURRENT
136578f812dSuebayasi #define USB_PORT_FEAT_RESET UHF_PORT_RESET
137578f812dSuebayasi // #define USB_PORT_FEAT_L1 5 /* L1 suspend */
138578f812dSuebayasi #define USB_PORT_FEAT_POWER UHF_PORT_POWER
139578f812dSuebayasi #define USB_PORT_FEAT_LOWSPEED UHF_PORT_LOW_SPEED
140578f812dSuebayasi #define USB_PORT_FEAT_C_CONNECTION UHF_C_PORT_CONNECTION
141578f812dSuebayasi #define USB_PORT_FEAT_C_ENABLE UHF_C_PORT_ENABLE
142578f812dSuebayasi #define USB_PORT_FEAT_C_SUSPEND UHF_C_PORT_SUSPEND
143578f812dSuebayasi #define USB_PORT_FEAT_C_OVER_CURRENT UHF_C_PORT_OVER_CURRENT
144578f812dSuebayasi #define USB_PORT_FEAT_C_RESET UHF_C_PORT_RESET
145578f812dSuebayasi #define USB_PORT_FEAT_TEST UHF_PORT_TEST
146578f812dSuebayasi #define USB_PORT_FEAT_INDICATOR UHF_PORT_INDICATOR
147578f812dSuebayasi #define USB_PORT_FEAT_C_PORT_L1 UHF_C_PORT_L1
148578f812dSuebayasi
149578f812dSuebayasi #define C_HUB_LOCAL_POWER UHF_C_HUB_LOCAL_POWER
150578f812dSuebayasi #define C_HUB_OVER_CURRENT UHF_C_HUB_OVER_CURRENT
151578f812dSuebayasi
152578f812dSuebayasi #define USB_REQ_GET_STATUS UR_GET_STATUS
153578f812dSuebayasi #define USB_REQ_CLEAR_FEATURE UR_CLEAR_FEATURE
154578f812dSuebayasi #define USB_REQ_SET_FEATURE UR_SET_FEATURE
155578f812dSuebayasi #define USB_REQ_GET_DESCRIPTOR UR_GET_DESCRIPTOR
156578f812dSuebayasi
157578f812dSuebayasi #define ClearHubFeature ((UT_WRITE_CLASS_DEVICE << 8) | USB_REQ_CLEAR_FEATURE)
158578f812dSuebayasi #define ClearPortFeature ((UT_WRITE_CLASS_OTHER << 8) | USB_REQ_CLEAR_FEATURE)
159578f812dSuebayasi #define GetHubDescriptor ((UT_READ_CLASS_DEVICE << 8) | USB_REQ_GET_DESCRIPTOR)
160578f812dSuebayasi #define GetHubStatus ((UT_READ_CLASS_DEVICE << 8) | USB_REQ_GET_STATUS)
161578f812dSuebayasi #define GetPortStatus ((UT_READ_CLASS_OTHER << 8) | USB_REQ_GET_STATUS)
162578f812dSuebayasi #define SetHubFeature ((UT_WRITE_CLASS_DEVICE << 8) | USB_REQ_SET_FEATURE)
163578f812dSuebayasi #define SetPortFeature ((UT_WRITE_CLASS_OTHER << 8) | USB_REQ_SET_FEATURE)
164578f812dSuebayasi
165578f812dSuebayasi #define USB_PORT_STAT_CONNECTION UPS_CURRENT_CONNECT_STATUS
166578f812dSuebayasi #define USB_PORT_STAT_ENABLE UPS_PORT_ENABLED
167578f812dSuebayasi #define USB_PORT_STAT_SUSPEND UPS_SUSPEND
168578f812dSuebayasi #define USB_PORT_STAT_OVERCURRENT UPS_OVERCURRENT_INDICATOR
169578f812dSuebayasi #define USB_PORT_STAT_RESET UPS_RESET
170578f812dSuebayasi #define USB_PORT_STAT_L1 UPS_PORT_L1
171578f812dSuebayasi #define USB_PORT_STAT_POWER UPS_PORT_POWER
172578f812dSuebayasi #define USB_PORT_STAT_LOW_SPEED UPS_LOW_SPEED
173578f812dSuebayasi #define USB_PORT_STAT_HIGH_SPEED UPS_HIGH_SPEED
174578f812dSuebayasi #define USB_PORT_STAT_TEST UPS_PORT_TEST
175578f812dSuebayasi #define USB_PORT_STAT_INDICATOR UPS_PORT_INDICATOR
176578f812dSuebayasi
177578f812dSuebayasi #define USB_PORT_STAT_C_CONNECTION UPS_C_CONNECT_STATUS
178578f812dSuebayasi #define USB_PORT_STAT_C_ENABLE UPS_C_PORT_ENABLED
179578f812dSuebayasi #define USB_PORT_STAT_C_SUSPEND UPS_C_SUSPEND
180578f812dSuebayasi #define USB_PORT_STAT_C_OVERCURRENT UPS_C_OVERCURRENT_INDICATOR
181578f812dSuebayasi #define USB_PORT_STAT_C_RESET UPS_C_PORT_RESET
182578f812dSuebayasi #define USB_PORT_STAT_C_L1 UPS_C_PORT_L1
183578f812dSuebayasi
184d05ae140Smglocker #define USB_DT_HUB UDESC_HUB
185d05ae140Smglocker
186d05ae140Smglocker /* See USB 2.0 spec Table 11-13, offset 3 */
187d05ae140Smglocker #define HUB_CHAR_LPSM UHD_PWR
188d05ae140Smglocker #define HUB_CHAR_COMMON_LPSM UHD_PWR_GANGED
189d05ae140Smglocker #define HUB_CHAR_INDV_PORT_LPSM UHD_PWR_INDIVIDUAL
190d05ae140Smglocker #define HUB_CHAR_NO_LPSM UHD_PWR_NO_SWITCH
191d05ae140Smglocker
192d05ae140Smglocker #define HUB_CHAR_COMPOUND UHD_COMPOUND
193d05ae140Smglocker
194d05ae140Smglocker #define HUB_CHAR_OCPM UHD_OC
195d05ae140Smglocker #define HUB_CHAR_COMMON_OCPM UHD_OC_GLOBAL
196d05ae140Smglocker #define HUB_CHAR_INDV_PORT_OCPM UHD_OC_INDIVIDUAL
197d05ae140Smglocker #define HUB_CHAR_NO_OCPM UHD_OC_NONE
198d05ae140Smglocker
199d05ae140Smglocker #define HUB_CHAR_TTTT UHD_TT_THINK
200d05ae140Smglocker #define HUB_CHAR_PORTIND UHD_PORT_IND
201d05ae140Smglocker
202d05ae140Smglocker enum usb_dr_mode {
203d05ae140Smglocker USB_DR_MODE_UNKNOWN,
204d05ae140Smglocker USB_DR_MODE_HOST,
205d05ae140Smglocker USB_DR_MODE_PERIPHERAL,
206d05ae140Smglocker USB_DR_MODE_OTG,
207d05ae140Smglocker };
208d05ae140Smglocker
209d05ae140Smglocker struct usb_phy;
210d05ae140Smglocker struct usb_hcd;
211d05ae140Smglocker
212d05ae140Smglocker static inline int
usb_phy_set_suspend(struct usb_phy * x,int suspend)213d05ae140Smglocker usb_phy_set_suspend(struct usb_phy *x, int suspend)
214d05ae140Smglocker {
215d05ae140Smglocker
216d05ae140Smglocker return 0;
217d05ae140Smglocker }
218d05ae140Smglocker
219d05ae140Smglocker static inline void
usb_hcd_resume_root_hub(struct usb_hcd * hcd)220d05ae140Smglocker usb_hcd_resume_root_hub(struct usb_hcd *hcd)
221d05ae140Smglocker {
222d05ae140Smglocker
223d05ae140Smglocker return;
224d05ae140Smglocker }
225d05ae140Smglocker
226d05ae140Smglocker static inline int
usb_disabled(void)227d05ae140Smglocker usb_disabled(void)
228d05ae140Smglocker {
229d05ae140Smglocker
230d05ae140Smglocker return 0;
231d05ae140Smglocker }
232d05ae140Smglocker
233d05ae140Smglocker static inline void
udelay(unsigned long usecs)234578f812dSuebayasi udelay(unsigned long usecs)
235578f812dSuebayasi {
236578f812dSuebayasi DELAY(usecs);
237578f812dSuebayasi }
238578f812dSuebayasi
239d05ae140Smglocker static inline void
mdelay(unsigned long msecs)240*a9beb1edSmglocker mdelay(unsigned long msecs)
241d05ae140Smglocker {
242*a9beb1edSmglocker int loops = msecs;
243*a9beb1edSmglocker while (loops--)
244*a9beb1edSmglocker DELAY(1000);
245d05ae140Smglocker }
246d05ae140Smglocker
247*a9beb1edSmglocker static inline void
usleep_range(unsigned long min,unsigned long max)248*a9beb1edSmglocker usleep_range(unsigned long min, unsigned long max)
249*a9beb1edSmglocker {
250*a9beb1edSmglocker DELAY((min + max) / 2);
251*a9beb1edSmglocker }
252*a9beb1edSmglocker
253*a9beb1edSmglocker #define dwc2_msleep(x) mdelay(x)
254*a9beb1edSmglocker
255578f812dSuebayasi #define EREMOTEIO EIO
256578f812dSuebayasi #define ECOMM EIO
257d05ae140Smglocker #define ENOTSUPP ENOTSUP
258578f812dSuebayasi
2590395aa1eSuebayasi void dw_timeout(void *);
260578f812dSuebayasi
261578f812dSuebayasi struct delayed_work {
262b6c5b329Suebayasi struct task work;
2630395aa1eSuebayasi struct timeout dw_timer;
264578f812dSuebayasi
265b6c5b329Suebayasi struct taskq *dw_wq;
2669eb3c3f2Suebayasi void (*dw_fn)(void *);
267ea6872ecSjmatthew void *dw_arg;
268578f812dSuebayasi };
269578f812dSuebayasi
270d05ae140Smglocker static inline void
INIT_DELAYED_WORK(struct delayed_work * dw,void (* fn)(void *),void * arg)271ea6872ecSjmatthew INIT_DELAYED_WORK(struct delayed_work *dw, void (*fn)(void *), void *arg)
272578f812dSuebayasi {
273ea6872ecSjmatthew dw->dw_fn = fn;
274ea6872ecSjmatthew dw->dw_arg = arg;
275016aa740Suebayasi timeout_set(&dw->dw_timer, dw_timeout, dw);
276578f812dSuebayasi }
277578f812dSuebayasi
278d05ae140Smglocker static inline void
queue_delayed_work(struct taskq * wq,struct delayed_work * dw,int j)279b6c5b329Suebayasi queue_delayed_work(struct taskq *wq, struct delayed_work *dw, int j)
280578f812dSuebayasi {
281ea6872ecSjmatthew dw->dw_wq = wq;
282016aa740Suebayasi timeout_add(&dw->dw_timer, j);
283578f812dSuebayasi }
284578f812dSuebayasi
285d05ae140Smglocker #define USB_RESUME_TIMEOUT 40 /* ms */
286d05ae140Smglocker
287578f812dSuebayasi #endif
288