[PATCH] board: stm32pm1: update USB-C power detection algorithm on DK boards

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] board: stm32pm1: update USB-C power detection algorithm on DK boards

Patrice Chotard
USB-C power supply which are Power Delivery compliant (USB-PD) are able
to provide different voltage/current (for example 5V/3A 9V/3A 12V/2.25A...)

In this case, the power supply need to negotiate the voltage/current to
use with the device using CC1/CC2 USB-C signals.

If this negotiation occurs during ADC measurement (done also on CC1/CC2
USB-C signals) some ADC acquisition can be corrupted which cause wrong
power supply current detection.

To avoid this, the power supply current detection algorithm is updated
as following:
  - perform an ADC measurement, if a 3A current is detected, continue the
    boot process.
  - else, wait 20ms (max tPDDebounce duration) to ensure that USB-PD
    negotiation is done and perform another ADC measurement.

Signed-off-by: Patrice Chotard <[hidden email]>
---

 board/st/stm32mp1/stm32mp1.c | 106 +++++++++++++++++++++--------------
 1 file changed, 63 insertions(+), 43 deletions(-)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 202f782906c2..cabd0e09f11d 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -289,41 +289,13 @@ static void __maybe_unused led_error_blink(u32 nb_blink)
  hang();
 }
 
-static int board_check_usb_power(void)
+static int adc_measurement(ofnode node, int adc_count, int *min_uV, int *max_uV)
 {
  struct ofnode_phandle_args adc_args;
  struct udevice *adc;
- ofnode node;
  unsigned int raw;
- int max_uV = 0;
- int min_uV = USB_START_HIGH_THRESHOLD_UV;
- int ret, uV, adc_count;
- u32 nb_blink;
- u8 i;
-
- if (!IS_ENABLED(CONFIG_ADC))
- return -ENODEV;
-
- node = ofnode_path("/config");
- if (!ofnode_valid(node)) {
- log_debug("no /config node?\n");
- return -ENOENT;
- }
-
- /*
- * Retrieve the ADC channels devices and get measurement
- * for each of them
- */
- adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
-   "#io-channel-cells", 0);
- if (adc_count < 0) {
- if (adc_count == -ENOENT)
- return 0;
-
- log_err("can't find adc channel (%d)\n", adc_count);
-
- return adc_count;
- }
+ int ret, uV;
+ int i;
 
  for (i = 0; i < adc_count; i++) {
  if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
@@ -350,10 +322,10 @@ static int board_check_usb_power(void)
  }
  /* Convert to uV */
  if (!adc_raw_to_uV(adc, raw, &uV)) {
- if (uV > max_uV)
- max_uV = uV;
- if (uV < min_uV)
- min_uV = uV;
+ if (uV > *max_uV)
+ *max_uV = uV;
+ if (uV < *min_uV)
+ *min_uV = uV;
  log_debug("%s[%02d] = %u, %d uV\n",
   adc->name, adc_args.args[0], raw, uV);
  } else {
@@ -362,18 +334,66 @@ static int board_check_usb_power(void)
  }
  }
 
+ return 0;
+}
+
+static int board_check_usb_power(void)
+{
+ ofnode node;
+ int max_uV = 0;
+ int min_uV = USB_START_HIGH_THRESHOLD_UV;
+ int adc_count, ret;
+ u32 nb_blink;
+ u8 i;
+
+ node = ofnode_path("/config");
+ if (!ofnode_valid(node)) {
+ log_debug("no /config node?\n");
+ return -ENOENT;
+ }
+
  /*
- * If highest value is inside 1.23 Volts and 2.10 Volts, that means
- * board is plugged on an USB-C 3A power supply and boot process can
- * continue.
+ * Retrieve the ADC channels devices and get measurement
+ * for each of them
  */
- if (max_uV > USB_START_LOW_THRESHOLD_UV &&
-    max_uV <= USB_START_HIGH_THRESHOLD_UV &&
-    min_uV <= USB_LOW_THRESHOLD_UV)
- return 0;
+ adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
+   "#io-channel-cells", 0);
+ if (adc_count < 0) {
+ if (adc_count == -ENOENT)
+ return 0;
 
- log_notice("****************************************************\n");
+ log_err("Can't find adc channel (%d)\n", adc_count);
+
+ return adc_count;
+ }
+
+ /* perform maximum of 2 ADC measurements to detect power supply current */
+ for (i = 0; i < 2; i++) {
+ if (IS_ENABLED(CONFIG_ADC))
+ ret = adc_measurement(node, adc_count, &min_uV, &max_uV);
+ else
+ ret = -ENODEV;
 
+ if (ret)
+ return ret;
+
+ /*
+ * If highest value is inside 1.23 Volts and 2.10 Volts, that means
+ * board is plugged on an USB-C 3A power supply and boot process can
+ * continue.
+ */
+ if (max_uV > USB_START_LOW_THRESHOLD_UV &&
+    max_uV <= USB_START_HIGH_THRESHOLD_UV &&
+    min_uV <= USB_LOW_THRESHOLD_UV)
+ return 0;
+
+ if (i == 0) {
+ log_err("Previous ADC measurements was not the one expected, retry in 20ms\n");
+ mdelay(20);  /* equal to max tPDDebounce duration (min 10ms - max 20ms) */
+ }
+ }
+
+ log_notice("****************************************************\n");
  /*
  * If highest and lowest value are either both below
  * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

RE: [PATCH] board: stm32pm1: update USB-C power detection algorithm on DK boards

Patrick DELAUNAY-2
Hi Patrice,

> From: Patrice CHOTARD <[hidden email]>
> Sent: vendredi 16 octobre 2020 09:29
>
> USB-C power supply which are Power Delivery compliant (USB-PD) are able to
> provide different voltage/current (for example 5V/3A 9V/3A 12V/2.25A...)
>
> In this case, the power supply need to negotiate the voltage/current to use with
> the device using CC1/CC2 USB-C signals.
>
> If this negotiation occurs during ADC measurement (done also on CC1/CC2 USB-
> C signals) some ADC acquisition can be corrupted which cause wrong power
> supply current detection.
>
> To avoid this, the power supply current detection algorithm is updated as
> following:
>   - perform an ADC measurement, if a 3A current is detected, continue the
>     boot process.
>   - else, wait 20ms (max tPDDebounce duration) to ensure that USB-PD
>     negotiation is done and perform another ADC measurement.
>
> Signed-off-by: Patrice Chotard <[hidden email]>
> ---
>
>  board/st/stm32mp1/stm32mp1.c | 106 +++++++++++++++++++++--------------
>  1 file changed, 63 insertions(+), 43 deletions(-)
>

Reviewed-by: Patrick Delaunay <[hidden email]>

Thanks

Patrick