1 //*****************************************************************************
2 //
3 //! @file am_hal_usbcharger.h
4 //!
5 //! @brief HAL for the USB Charger Functionality
6 //!
7 //! @addtogroup usb_charger_4p USB Charger Functionality
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #ifndef AM_HAL_USB_CHARGER_H_
49 #define AM_HAL_USB_CHARGER_H_
50 
51 #include "am_mcu_apollo.h"
52 
53 #ifdef __cplusplus
54 extern "C" {
55 #endif
56 
57 //*****************************************************************************
58 //
59 //! @name USB charger physical connection status.
60 //! @{
61 //! USB charger data pin connection status.
62 //!
63 //! The Dm and Dp pins of the USB device have two connection status:
64 //! 1- Connected: When the Dm and Dp are connected (for SDP(Standard Downstream
65 //!    Port) and CDP(Charger Downstream Port) chargers only)
66 //! 2- Unknown: When the Dm and Dp are not connected to the USB cable or the
67 //!    charger type is DCP(Dedicated Charger Port).
68 //!
69 //
70 //*****************************************************************************
71 typedef enum
72 {
73     AM_HAL_USB_CHARGER_DATA_PIN_CONNECTED,
74     AM_HAL_USB_CHARGER_DATA_PIN_CONNECTION_UNKNOWN,
75 }
76 am_hal_usb_charger_data_pin_status_e;
77 //! @}
78 
79 //*****************************************************************************
80 //
81 //! @name USB charger type
82 //! @{
83 //! Macro definitions for the USB charger type.
84 //!
85 //! These macros are used to indicate what kind of charger is connected to the USB port:
86 //!   1-SDP: Standard Downstream Port like a PC/laptop.
87 //!   2-CDP: Charging Downstream Port is a downstream port on a device that complies with the
88 //!          USB 2.0 definition of a host or a hub.
89 //!   3-DCP: A Dedicated Charging Port (DCP) is a downstream port on a device that outputs power
90 //!          through a USB connector, but is not capable of enumerating a downstream device.
91 //!
92 //
93 //*****************************************************************************
94 typedef enum
95 {
96     AM_HAL_USB_CHARGER_SDP,
97     AM_HAL_USB_CHARGER_CDP,
98     AM_HAL_USB_CHARGER_DCP,
99     AM_HAL_USB_CHARGER_NO_CHARGER
100 } am_hal_usb_charger_type_e;
101 //! @}
102 
103 //*****************************************************************************
104 //
105 //! @name Vendor-specific comparator ref voltage
106 //! @{
107 //! Vendor-specific comparator ref voltage
108 //!
109 //! These macros are used to program the voltage comparator for DP/DM USB pins:
110 //! The reference voltage for the comparator for each pin can be 1.25V, 1.65V, 2.35V, and 3.10V.
111 //! The output of the comparators is connected to BCDETSTATUS.DMCOMPOUT and BCDETSTATUS.DPCOMPOUT.
112 //
113 //*****************************************************************************
114 typedef enum
115 {
116     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_1P65  = 0x0,  // set comparator voltage to 1.65V
117     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_3P10V = 0x1,  // set comparator voltage to 3.10V
118     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_2P35  = 0x2,  // set comparator voltage to 2.35V
119     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_1P25V = 0x3   // set comparator voltage to 1.25V
120 } am_hal_usb_charger_comparator_reference_voltage_e;
121 //! @}
122 
123 
124 //*****************************************************************************
125 //
126 //! @brief Bring the USB hardware out of reset
127 //!
128 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
129 //
130 //*****************************************************************************
am_hal_usb_hardware_unreset(void)131 static inline void am_hal_usb_hardware_unreset(void)
132 {
133     //
134     // Unreset the USB controller and PHY. To make sure the USB can do enumuration, all the USB charger detection
135     // circuit should be disconnected from the Dp/Dm pins.
136     //
137     USB->BCDETCRTL1 =
138         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET,       1)    |
139         _VAL2FLD(USB_BCDETCRTL1_USBDCOMPEN,       0)    |
140         _VAL2FLD(USB_BCDETCRTL1_USBDCOMPREF,      0)    |
141         _VAL2FLD(USB_BCDETCRTL1_IDPSINKEN,        0)    |
142         _VAL2FLD(USB_BCDETCRTL1_VDMSRCEN,         0)    |
143         _VAL2FLD(USB_BCDETCRTL1_RDMPDWNEN,        0)    |
144         _VAL2FLD(USB_BCDETCRTL1_VDPSRCEN,         0)    |
145         _VAL2FLD(USB_BCDETCRTL1_IDPSRCEN,         0)    |
146         _VAL2FLD(USB_BCDETCRTL1_IDMSINKEN,        0)    |
147         _VAL2FLD(USB_BCDETCRTL1_BCWEAKPULLDOWNEN, 0)    |
148         _VAL2FLD(USB_BCDETCRTL1_BCWEAKPULLUPEN,   0);
149 }
150 
151 //*****************************************************************
152 //
153 //! @brief Put the USB hardware into reset
154 //!
155 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
156 //
157 //*****************************************************************
158 
am_hal_usb_hardware_reset(void)159 static inline void am_hal_usb_hardware_reset(void)
160 {
161     //
162     // Holds a USB controller and PHY in the reset for BC detection
163     // After MCU hardware reset, the USB is always in reset.
164     //
165     USB->BCDETCRTL1_b.USBSWRESET = 0;
166 }
167 
168 //*****************************************************************************
169 //
170 //! @brief enable Data Contact Detection(DCD) based on BC1.2 protocol
171 //!
172 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
173 //
174 //*****************************************************************************
175 
am_hal_usb_charger_enable_data_pin_contact_detection(void)176 static inline void  am_hal_usb_charger_enable_data_pin_contact_detection(void)
177 {
178     //
179     // Clear all other bits
180     // Holds a USB controller and PHY in the reset for BC detection
181     // enables DP current source as per USB BC 1.2 spec.
182     // enables DM pull-down as per USB BC 1.2 spec.
183     //
184     USB->BCDETCRTL1 =
185         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET, 0)  |
186         _VAL2FLD(USB_BCDETCRTL1_IDPSRCEN,   1)  |
187         _VAL2FLD(USB_BCDETCRTL1_RDMPDWNEN,  1);
188 }
189 
190 //*****************************************************************************
191 //
192 //! @brief Check the connection status of the data pins(Dp/Dm)
193 //!
194 //! @return one of am_hal_usb_charger_data_pin_status_e like AM_HAL_USB_CHARGER_DATA_PIN_CONNECTED
195 //
196 //*****************************************************************************
am_hal_usb_charger_data_pin_connection_status(void)197 static inline am_hal_usb_charger_data_pin_status_e am_hal_usb_charger_data_pin_connection_status(void)
198 {
199     return ( USB->BCDETSTATUS_b.DPATTACHED )? AM_HAL_USB_CHARGER_DATA_PIN_CONNECTED :AM_HAL_USB_CHARGER_DATA_PIN_CONNECTION_UNKNOWN;
200 }
201 
202 //*****************************************************************************
203 //
204 //! @brief Enable SDP connection detection hardware
205 //!
206 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
207 //
208 //*****************************************************************************
am_hal_usb_charger_enable_primary_detection(void)209 static inline void am_hal_usb_charger_enable_primary_detection(void)
210 {
211     //
212     // Clear all other bits
213     // Holds a USB controller and PHY in the reset for BC detection
214     // enables DM current sink as per USB BC 1.2 spec.
215     // enables DP voltage source as per USB BC 1.2 spec.
216     //
217     USB->BCDETCRTL1 =
218         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET, 0)  |
219         _VAL2FLD(USB_BCDETCRTL1_IDMSINKEN,  1)  |
220         _VAL2FLD(USB_BCDETCRTL1_VDPSRCEN,   1);
221 }
222 
223 //*****************************************************************************
224 //
225 
226 //! @brief detect SDP charger hardware connection
227 //! This function must be called in the primary phase of BC1.2 protocol, else the
228 //! return value is invalid.
229 //! Returns AM_HAL_USB_CHARGER_SDP_DETECTED when the SDP charger(such as a PC) is
230 //! detected.
231 //! Returns AM_HAL_USB_CHARGER_NO_CHARGER_DETECTED when the charger type is CDP or DCP.
232 //!
233 //! @return one of am_hal_usb_charger_detection_status_e like AM_HAL_USB_CHARGER_SDP_DETECTED
234 //
235 //*****************************************************************************
am_hal_usb_charger_sdp_connection_status(void)236 static inline am_hal_usb_charger_type_e  am_hal_usb_charger_sdp_connection_status(void)
237 {
238     //
239     // During Primary Detection the PD shall turn on VDP_SRC and IDM_SINK. When a voltage of VDP_SRC is
240     // applied to Dp, an SDP will continue pulling Dm low through RDM_DWN.
241     // A PD shall compare the voltage on Dm with VDAT_REF. If Dm is less than VDAT_REF, then the PD is
242     // allowed determining that it is attached to an SDP. Because the Dm is less than VDAT_REF, the
243     // CPDETECTED would be zero.
244     //
245     return (USB->BCDETSTATUS_b.CPDETECTED == 0) ? AM_HAL_USB_CHARGER_SDP: AM_HAL_USB_CHARGER_NO_CHARGER;
246 }
247 
248 //*****************************************************************************
249 //
250 //! @brief Enable CDP or DCP connection detection hardware
251 //!
252 //! Returns AM_HAL_USB_CHARGER_SDP_DETECTED when the SDP charger(such as a PC) is
253 //! detected.
254 //! Returns AM_HAL_USB_CHARGER_NO_CHARGER_DETECTED when the charger type is CDP or DCP.
255 //!
256 //! @return one of am_hal_usb_charger_detection_status_e like AM_HAL_USB_CHARGER_SDP_DETECTED
257 //
258 //*****************************************************************************
am_hal_usb_charger_enable_secondary_detection(void)259 static inline void am_hal_usb_charger_enable_secondary_detection(void)
260 {
261     //
262     // Secondary Detection can be used to distinguish between a DCP and a CDP. PDs that are not ready
263     // to be enumerated within TSVLD_CON_PWD of detecting VBUS are required to implement Secondary
264     // Detection. PDs that are ready to be enumerated are allowed to bypass Secondary Detection.
265     // During Secondary Detection, a PD shall output VDM_SRC(0.5V) on Dm, turn on IDP_SINK, and compare the
266     // voltage on Dp to VDAT_REF(0.25V). Since a DCP is required to short Dp to Dm through a resistance
267     // of RDCP_DAT(200 ohm), the voltage on Dp will be close to VDM_SRC, which is above VDAT_REF.
268     // If a PD detects that Dp is greater than VDAT_REF, it knows that it is attached to a DCP.
269     //
270     USB->BCDETCRTL1 =
271         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET, 0)  |
272         _VAL2FLD(USB_BCDETCRTL1_VDMSRCEN,   1)  |
273         _VAL2FLD(USB_BCDETCRTL1_IDPSINKEN,  1);
274 }
275 
276 //*****************************************************************************
277 //
278 //! @brief Enable the downstream device to draw current based on CDP charger
279 //!
280 //! This function should be called at the end of BC1.2 charger detection algorithm after
281 //! detecting a CDP charger.
282 //!
283 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
284 //
285 //*****************************************************************************
am_hal_usb_charger_enable_cdp_charger(void)286 static inline void am_hal_usb_charger_enable_cdp_charger(void)
287 {
288     //
289     // If a PD detects that Dp is less than VDAT_REF, it knows that it is attached to a CDP.
290     // It is then required to turn off VDP_SRC and VDM_SRC, as shown in the Good Battery
291     // Algorithm in Section 3.3.2, and is allowed to draw IDEV_CHG.
292     // Note: Here all bits in BCDETCRTL1 are cleared to zero.
293     //
294     USB->BCDETCRTL1 =
295         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET, 0)  |
296         _VAL2FLD(USB_BCDETCRTL1_VDMSRCEN,   0)  |
297         _VAL2FLD(USB_BCDETCRTL1_VDPSRCEN,   0);
298 }
299 
300 //*****************************************************************************
301 //
302 //! @brief Enable the downstream device to draw current based on DCP charger
303 //!
304 //! This function should be called at the end of BC1.2 charger detection algorithm after
305 //! detecting a DCP charger.
306 //!
307 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
308 //
309 //*****************************************************************************
am_hal_usb_charger_enable_dcp_charger(void)310 static inline void  am_hal_usb_charger_enable_dcp_charger(void)
311 {
312     //
313     // If a PD detects that Dp is greater than VDAT_REF, it knows that it is attached to a DCP.
314     // It is then required to enable VDP_SRC or pull Dp to VDP_UP through RDP_UP, as defined in
315     // the Good Battery Algorithm in Section 3.3.2.
316     //
317     USB->BCDETCRTL1 =
318         _VAL2FLD(USB_BCDETCRTL1_USBSWRESET, 0)  |
319         _VAL2FLD(USB_BCDETCRTL1_VDPSRCEN,   1);
320 }
321 
322 //*****************************************************************************
323 //
324 //! @brief detect CDP or DCP USB charger
325 //!
326 //! This function must be call in the secondary phase of BC1.2 protocol, else the
327 //! return value in invalid.
328 //!
329 //! @return one of am_hal_usb_charger_detection_status_e
330 //!     Returns AM_HAL_USB_CHARGER_DCP_DETECTED when the DCP charger is detected.
331 //!     Returns AM_HAL_USB_CHARGER_CDP_DETECTED when the CDP charger is detected.
332 //
333 //*****************************************************************************
am_hal_usb_charger_cdp_or_dcp_connection_status(void)334 static inline am_hal_usb_charger_type_e  am_hal_usb_charger_cdp_or_dcp_connection_status(void)
335 {
336     return ( USB->BCDETSTATUS_b.DCPDETECTED ) ? AM_HAL_USB_CHARGER_DCP : AM_HAL_USB_CHARGER_CDP;
337 }
338 
339 //*****************************************************************************
340 //
341 //! @brief Enable vendor-specific comparator ref voltage
342 //!
343 //! @param am_hal_usb_charger_comparator_reference_voltage_e - voltage reference value
344 //!     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_1P65
345 //!     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_3P10V
346 //!     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_2P35
347 //!     AM_HAL_USB_CHARGER_SET_REF_VOL_TO_1P25V
348 //!
349 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
350 //
351 //*****************************************************************************
am_hal_usb_charger_configure_vendore_comparators(am_hal_usb_charger_comparator_reference_voltage_e e)352 static inline void am_hal_usb_charger_configure_vendore_comparators(am_hal_usb_charger_comparator_reference_voltage_e e)
353 {
354     //
355     // Make sure the USB logic held in reset
356     //
357     USB->BCDETCRTL1_b.USBSWRESET = 0;
358 
359     //
360     // Enable the DM/DP comparators
361     //
362     USB->BCDETCRTL1_b.USBDCOMPEN = 1;
363     USB->BCDETCRTL1_b.USBDCOMPREF = (unsigned) e;
364 }
365 
366 //*****************************************************************************
367 //
368 //! @brief Disable vendore-specific voltage comparators for DP and DM pins
369 //!
370 //! @return one of am_hal_status_e like AM_HAL_STATUS_SUCCESS
371 //
372 //*****************************************************************************
am_hal_usb_charger_disable_vendore_comparators(void)373 static inline void am_hal_usb_charger_disable_vendore_comparators(void)
374 {
375     //
376     // Disable the DM/DP comparators
377     //
378     USB->BCDETCRTL1_b.USBDCOMPEN = 0;
379 }
380 
381 //*****************************************************************************
382 //
383 //! @brief Read vendore-specific voltage comparator for DP pins
384 //!
385 //! @return the Dp comparator output value
386 //
387 //*****************************************************************************
am_hal_usb_charger_read_dp_comparator_output(void)388 static inline uint32_t am_hal_usb_charger_read_dp_comparator_output(void)
389 {
390     return USB->BCDETSTATUS_b.DPCOMPOUT;
391 }
392 
393 //*****************************************************************************
394 //
395 //! @brief Read vendore-specific voltage comparator for DM pins
396 //!
397 //! @return the Dp comparator output value
398 //
399 //*****************************************************************************
am_hal_usb_charger_read_dm_comparator_output(void)400 static inline uint32_t am_hal_usb_charger_read_dm_comparator_output(void)
401 {
402     return USB->BCDETSTATUS_b.DMCOMPOUT;
403 }
404 
405 //*****************************************************************************
406 //
407 //! @brief Enable the USB PHY reset override for charger detection
408 //!
409 //! @return - none
410 //
411 //*****************************************************************************
am_hal_usb_enable_phy_reset_override(void)412 static inline void am_hal_usb_enable_phy_reset_override(void)
413 {
414     MCUCTRL->USBPHYRESET &= ~ (_VAL2FLD(MCUCTRL_USBPHYRESET_USBPHYPORRSTDIS, 0x1) |
415                                _VAL2FLD(MCUCTRL_USBPHYRESET_USBPHYUTMIRSTDIS, 0x1));
416 }
417 
418 //*****************************************************************************
419 //
420 //! @brief Disable the USB PHY reset override for USB enumeration
421 //!
422 //! @return - none
423 //
424 //*****************************************************************************
am_hal_usb_disable_phy_reset_override(void)425 static inline void am_hal_usb_disable_phy_reset_override(void)
426 {
427     MCUCTRL->USBPHYRESET |= (_VAL2FLD(MCUCTRL_USBPHYRESET_USBPHYPORRSTDIS, 0x1) |
428                              _VAL2FLD(MCUCTRL_USBPHYRESET_USBPHYUTMIRSTDIS, 0x1));
429 }
430 
431 #ifdef __cplusplus
432 }
433 #endif
434 
435 #endif /* AM_HAL_USB_CHARGER_H_ */
436 
437 //*****************************************************************************
438 //
439 // End Doxygen group.
440 //! @}
441 //
442 //*****************************************************************************
443 
444