lpc55_hal/peripherals/
usbhs.rs1use core::ops::Deref;
2use embedded_time::duration::Extensions;
3
4use crate::drivers::timer;
5use crate::peripherals::{anactrl, ctimer, pmc, syscon};
6use crate::raw;
7use crate::traits::wg::timer::CountDown;
8use crate::typestates::{
9 init_state,
10 usbhs_mode,
11 ClocksSupportUsbhsToken,
14};
15
16use crate::traits::usb::{Usb, UsbSpeed};
17
18pub struct Usbhs<
20 State: init_state::InitState = init_state::Unknown,
21 Mode: usbhs_mode::UsbhsMode = usbhs_mode::Unknown,
22> {
23 pub(crate) raw_phy: raw::USBPHY,
24 pub(crate) raw_hsd: raw::USB1,
25 pub(crate) raw_hsh: raw::USBHSH,
26 _state: State,
27 _mode: Mode,
28}
29
30pub type EnabledUsbhsDevice = Usbhs<init_state::Enabled, usbhs_mode::Device>;
31pub type EnabledUsbhsHost = Usbhs<init_state::Enabled, usbhs_mode::Host>;
32
33impl Deref for EnabledUsbhsDevice {
34 type Target = raw::usb1::RegisterBlock;
35 fn deref(&self) -> &Self::Target {
36 &self.raw_hsd
37 }
38}
39
40unsafe impl Sync for EnabledUsbhsDevice {}
41
42impl Usb<init_state::Enabled> for EnabledUsbhsDevice {
43 const SPEED: UsbSpeed = UsbSpeed::HighSpeed;
44 }
46
47impl Usbhs {
48 pub fn new(raw_phy: raw::USBPHY, raw_hsd: raw::USB1, raw_hsh: raw::USBHSH) -> Self {
49 Usbhs {
50 raw_phy,
51 raw_hsd,
52 raw_hsh,
53 _state: init_state::Unknown,
54 _mode: usbhs_mode::Unknown,
55 }
56 }
57}
58
59impl<State: init_state::InitState, Mode: usbhs_mode::UsbhsMode> Usbhs<State, Mode> {
60 pub fn release(self) -> (raw::USB1, raw::USBHSH) {
61 (self.raw_hsd, self.raw_hsh)
62 }
63
64 pub fn enabled_as_device(
65 mut self,
66 anactrl: &mut anactrl::Anactrl,
67 pmc: &mut pmc::Pmc,
68 syscon: &mut syscon::Syscon,
69 timer: &mut timer::Timer<impl ctimer::Ctimer<init_state::Enabled>>,
70 _clocks_token: ClocksSupportUsbhsToken,
72 ) -> EnabledUsbhsDevice {
73 syscon.reset(&mut self.raw_hsh);
75 syscon.reset(&mut self.raw_hsd);
76 syscon.reset(&mut self.raw_phy);
77
78 syscon.enable_clock(&mut self.raw_hsh);
80
81 self.raw_hsh
82 .portmode
83 .modify(|_, w| w.dev_enable().set_bit());
84
85 syscon.disable_clock(&mut self.raw_hsh);
86
87 pmc.raw
89 .pdruncfg0
90 .modify(|_, w| w.pden_xtal32m().poweredon());
91 pmc.raw
92 .pdruncfg0
93 .modify(|_, w| w.pden_ldoxo32m().poweredon());
94 anactrl
95 .raw
96 .xo32m_ctrl
97 .modify(|_, w| w.enable_pll_usb_out().set_bit());
98
99 pmc.power_on(&mut self.raw_phy);
100
101 timer.start(5000_u32.microseconds());
103 nb::block!(timer.wait()).ok();
104
105 syscon.enable_clock(&mut self.raw_phy);
106
107 self.raw_phy.ctrl.write(|w| w.sftrst().clear_bit());
109
110 self.raw_phy.pll_sic.modify(|_, w| {
111 w.pll_div_sel()
112 .bits(6) .pll_reg_enable()
114 .set_bit()
115 });
116
117 self.raw_phy.pll_sic_clr.write(|w| unsafe {
118 w.bits(1 << 16 )
120 });
121
122 timer.start(15.microseconds());
124 nb::block!(timer.wait()).ok();
125
126 self.raw_phy
127 .pll_sic
128 .modify(|_, w| w.pll_power().set_bit().pll_en_usb_clks().set_bit());
129
130 self.raw_phy.ctrl.modify(|_, w| {
131 w.clkgate()
132 .clear_bit()
133 .enautoclr_clkgate()
134 .set_bit()
135 .enautoclr_phy_pwd()
136 .clear_bit()
137 });
138
139 self.raw_phy.pwd.write(|w| unsafe { w.bits(0) });
141
142 syscon.enable_clock(&mut self.raw_hsd);
144
145 Usbhs {
146 raw_phy: self.raw_phy,
147 raw_hsd: self.raw_hsd,
148 raw_hsh: self.raw_hsh,
149 _state: init_state::Enabled(()),
150 _mode: usbhs_mode::Device,
151 }
152 }
153
154 pub fn borrow<F: Fn(&mut Self)>(&mut self, func: F) {
155 func(self);
156 }
157}
158
159#[derive(Debug)]
160pub struct UsbHsDevInfo {
161 pub maj_rev: u8,
162 pub min_rev: u8,
163 pub err_code: u8,
164 pub frame_nr: u16,
165}
166
167impl EnabledUsbhsDevice {
168 pub fn info(&self) -> UsbHsDevInfo {
169 UsbHsDevInfo {
171 maj_rev: self.raw_hsd.info.read().majrev().bits(),
172 min_rev: self.raw_hsd.info.read().minrev().bits(),
173 err_code: self.raw_hsd.info.read().err_code().bits(),
174 frame_nr: self.raw_hsd.info.read().frame_nr().bits(),
175 }
176 }
177
178 pub fn disable_high_speed(&mut self) {
179 self.raw_phy.pwd_set.write(|w| unsafe {
182 w.bits(1 << 12) });
184 }
185}
186
187impl<State: init_state::InitState> Usbhs<State, usbhs_mode::Device> {
188 pub fn disabled(
190 mut self,
191 pmc: &mut pmc::Pmc,
192 syscon: &mut syscon::Syscon,
193 ) -> Usbhs<init_state::Disabled, usbhs_mode::Device> {
194 syscon.disable_clock(&mut self.raw_hsd);
195
196 syscon.disable_clock(&mut self.raw_phy);
197
198 pmc.power_off(&mut self.raw_phy);
199
200 pmc.raw
201 .pdruncfg0
202 .modify(|_, w| w.pden_xtal32m().poweredoff());
203 pmc.raw
204 .pdruncfg0
205 .modify(|_, w| w.pden_ldoxo32m().poweredoff());
206
207 Usbhs {
208 raw_phy: self.raw_phy,
209 raw_hsd: self.raw_hsd,
210 raw_hsh: self.raw_hsh,
211 _state: init_state::Disabled,
212 _mode: usbhs_mode::Device,
213 }
214 }
215}
216
217impl From<(raw::USBPHY, raw::USB1, raw::USBHSH)> for Usbhs {
218 fn from(raw: (raw::USBPHY, raw::USB1, raw::USBHSH)) -> Self {
219 Usbhs::new(raw.0, raw.1, raw.2)
220 }
221}