Open FFBoard
Open source force feedback firmware
musb_max32.h
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2024, Brent Kowal (Analog Devices, Inc)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#ifndef TUSB_MUSB_MAX32_H_
28#define TUSB_MUSB_MAX32_H_
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34#include "mxc_device.h"
35#include "usbhs_regs.h"
36
37#define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints
38#define MUSB_CFG_DYNAMIC_FIFO 0 // dynamic EP FIFO sizing
39
40const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS };
41
42#if CFG_TUD_ENABLED
43#define USBHS_M31_CLOCK_RECOVERY
44
45// Mapping of IRQ numbers to port. Currently just 1.
46static const IRQn_Type musb_irqs[] = {
47 USB_IRQn
48};
49
50TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_enable(uint8_t rhport) {
51 NVIC_EnableIRQ(musb_irqs[rhport]);
52}
53
54TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_disable(uint8_t rhport) {
55 NVIC_DisableIRQ(musb_irqs[rhport]);
56}
57
58TU_ATTR_ALWAYS_INLINE static inline unsigned musb_dcd_get_int_enable(uint8_t rhport) {
59 #ifdef NVIC_GetEnableIRQ // only defined in CMSIS 5
60 return NVIC_GetEnableIRQ(musb_irqs[rhport]);
61 #else
62 uint32_t IRQn = (uint32_t) musb_irqs[rhport];
63 return ((NVIC->ISER[IRQn >> 5UL] & (1UL << (IRQn & 0x1FUL))) != 0UL) ? 1UL : 0UL;
64 #endif
65}
66
67TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_clear(uint8_t rhport) {
68 NVIC_ClearPendingIRQ(musb_irqs[rhport]);
69}
70
71static inline void musb_dcd_int_handler_enter(uint8_t rhport) {
72 mxc_usbhs_regs_t* hs_phy = MXC_USBHS;
73 uint32_t mxm_int, mxm_int_en, mxm_is;
74
75 //Handle PHY specific events
76 mxm_int = hs_phy->mxm_int;
77 mxm_int_en = hs_phy->mxm_int_en;
78 mxm_is = mxm_int & mxm_int_en;
79 hs_phy->mxm_int = mxm_is;
80
81 if (mxm_is & MXC_F_USBHS_MXM_INT_NOVBUS) {
82 dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
83 }
84}
85
86static inline void musb_dcd_phy_init(uint8_t rhport) {
87 (void) rhport;
88 mxc_usbhs_regs_t* hs_phy = MXC_USBHS;
89
90 // Interrupt for VBUS disconnect
91 hs_phy->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS;
92
93 musb_dcd_int_clear(rhport);
94
95 // Unsuspend the MAC
96 hs_phy->mxm_suspend = 0;
97
98 // Configure PHY
99 hs_phy->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11);
100 hs_phy->m31_phy_xcfgi_63_32 = 0;
101 hs_phy->m31_phy_xcfgi_95_64 = 0x1 << (72 - 64);
102 hs_phy->m31_phy_xcfgi_127_96 = 0;
103
104 #ifdef USBHS_M31_CLOCK_RECOVERY
105 hs_phy->m31_phy_noncry_rstb = 1;
106 hs_phy->m31_phy_noncry_en = 1;
107 hs_phy->m31_phy_outclksel = 0;
108 hs_phy->m31_phy_coreclkin = 0;
109 hs_phy->m31_phy_xtlsel = 2; /* Select 25 MHz clock */
110 #else
111 hs_phy->m31_phy_noncry_rstb = 0;
112 hs_phy->m31_phy_noncry_en = 0;
113 hs_phy->m31_phy_outclksel = 1;
114 hs_phy->m31_phy_coreclkin = 1;
115 hs_phy->m31_phy_xtlsel = 3; /* Select 30 MHz clock */
116 #endif
117 hs_phy->m31_phy_pll_en = 1;
118 hs_phy->m31_phy_oscouten = 1;
119
120 /* Reset PHY */
121 hs_phy->m31_phy_ponrst = 0;
122 hs_phy->m31_phy_ponrst = 1;
123}
124
125// static inline void musb_dcd_setup_fifo(uint8_t rhport, unsigned epnum, unsigned dir_in, unsigned mps) {
126// (void) mps;
127//
128// //Most likely the caller has already grabbed the right register block. But
129// //as a precaution save and restore the register bank anyways
130// unsigned saved_index = musb_periph_inst[rhport]->index;
131//
132// musb_periph_inst[rhport]->index = epnum;
133//
134// //Disable double buffering
135// if (dir_in) {
136// musb_periph_inst[rhport]->incsru |= (MXC_F_USBHS_INCSRU_DPKTBUFDIS | MXC_F_USBHS_INCSRU_MODE);
137// } else {
138// musb_periph_inst[rhport]->outcsru |= (MXC_F_USBHS_OUTCSRU_DPKTBUFDIS);
139// }
140//
141// musb_periph_inst[rhport]->index = saved_index;
142// }
143
144#endif // CFG_TUD_ENABLED
145
146#ifdef __cplusplus
147}
148#endif
149
150#endif // TUSB_MUSB_MAX32_H_
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
Definition: dcd.h:196
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_disable(uint8_t rhport)
Definition: musb_max32.h:54
static void musb_dcd_phy_init(uint8_t rhport)
Definition: musb_max32.h:86
static void musb_dcd_int_handler_enter(uint8_t rhport)
Definition: musb_max32.h:71
static const IRQn_Type musb_irqs[]
Definition: musb_max32.h:46
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_clear(uint8_t rhport)
Definition: musb_max32.h:67
static TU_ATTR_ALWAYS_INLINE void musb_dcd_int_enable(uint8_t rhport)
Definition: musb_max32.h:50
static TU_ATTR_ALWAYS_INLINE unsigned musb_dcd_get_int_enable(uint8_t rhport)
Definition: musb_max32.h:58
const uintptr_t MUSB_BASES[]
Definition: musb_max32.h:40