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