From 42082bc61b4646ef1e61ad01cfb4ffefc457db75 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 16 Oct 2020 09:28:59 +0200 Subject: [PATCH] board: stm32pm1: update USB-C power detection algorithm on DK boards 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 Reviewed-by: Patrick Delaunay --- 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 60e3a34054..78362d24a2 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.39.5