From ffd1ee934f310a644c03b88fa2ae3e66ec847a04 Mon Sep 17 00:00:00 2001 From: Aseda Aboagye Date: Tue, 28 Feb 2017 07:39:12 -0800 Subject: [PATCH] cr50: Only drive CCD_MODE_L when in CCD mode. This commit changes the behaviour of handling the CCD_MODE_L pin. When Cr50 is not in CCD mode, it will stop driving the pin and turn it into an input. This allows the pin to be driven by the EC. Cr50 will then poll the CCD_MODE_L pin to see when it is pulled low and then enter CCD mode. Once the pin is deasserted, CCD mode is disabled. However, when Cr50 itself makes the decision to enter CCD mode, it changes the pin from an input to an output and drives the pin low. NOTE: The rdd interrupt does not directly trigger CCD mode, but now drives the pin low. A side-effect of the pin going low is that CCD is enabled. Once Cr50 decides to leave CCD mode, it then reconfigures the pin to be setup as an input again. CQ-DEPEND=CL:448988 BUG=b:35804738 BRANCH=cr50 TEST=Flash dev board, use `ccd` console command to both enable and disable CCD. Verify that when CCD is enabled, the state of DIOM1 does not disable CCD. Verify that when CCD is disabled, pulling DIOM1 low enables CCD. Letting it float disables CCD. TEST=Verify that CCD mode is reflected in the device state. Change-Id: I44645f28b362977ca6a502b646e4f4ff1a7430c7 Signed-off-by: Aseda Aboagye Reviewed-on: https://chromium-review.googlesource.com/448161 Commit-Ready: Aseda Aboagye Tested-by: Aseda Aboagye Reviewed-by: Vadim Bendebury --- board/cr50/board.c | 21 +++++++++++ board/cr50/board.h | 1 + board/cr50/gpio.inc | 8 +++-- board/cr50/rdd.c | 87 ++++++++++++++++++++++++++++++--------------- chip/g/rdd.h | 8 +++++ 5 files changed, 93 insertions(+), 32 deletions(-) diff --git a/board/cr50/board.c b/board/cr50/board.c index 609d35766b..9db8f1a8ce 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -794,6 +794,11 @@ struct device_config device_states[] = { .detect = GPIO_BATT_PRES_L, .name = "BattPrsnt" }, + [DEVICE_CCD_MODE] = { + .deferred = NULL, + .detect = GPIO_CCD_MODE_L, + .name = "CCD Mode" + }, }; BUILD_ASSERT(ARRAY_SIZE(device_states) == DEVICE_COUNT); @@ -892,6 +897,22 @@ void board_update_device_state(enum device_type device) return; } + if (device == DEVICE_CCD_MODE) { + int pin_level = gpio_get_level(device_states[device].detect); + /* The CCD mode pin is active low. */ + int changed = device_set_state(device, + pin_level ? + DEVICE_STATE_OFF : + DEVICE_STATE_ON); + + if (changed) { + CPRINTS("CCD MODE changed: %d", pin_level); + ccd_mode_pin_changed(pin_level); + } + + return; + } + if (device == DEVICE_SERVO && servo_state_unknown()) return; diff --git a/board/cr50/board.h b/board/cr50/board.h index 1cf4b70bef..85fa1b2f11 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -150,6 +150,7 @@ enum device_type { DEVICE_EC, DEVICE_SERVO, DEVICE_BATTERY_PRESENT, + DEVICE_CCD_MODE, DEVICE_COUNT }; diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc index f2ac78ae1d..824b77f498 100644 --- a/board/cr50/gpio.inc +++ b/board/cr50/gpio.inc @@ -71,9 +71,11 @@ GPIO(AP_FLASH_SELECT, PIN(0, 2), GPIO_OUT_LOW) /* Pull this low to reset the AP. (We reset the EC with the RBOX.) */ GPIO(SYS_RST_L_OUT, PIN(0, 4), GPIO_INPUT) -/* Indicate to EC when CCD is enabled. EC can pull this down too, to tell us if - * it decided instead. The pullup is on the EC's side. */ -GPIO(CCD_MODE_L, PIN(0, 5), GPIO_ODR_HIGH) +/* + * Indicate to EC when CCD is enabled. EC can pull this down too, to tell us if + * it decided instead. + */ +GPIO(CCD_MODE_L, PIN(0, 5), GPIO_INPUT | GPIO_PULL_UP) /* Battery present signal is active low */ GPIO(BATT_PRES_L, PIN(0, 6), GPIO_INPUT) diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 993ccfc167..f0071fefb5 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -107,45 +107,74 @@ void uartn_tx_disconnect(int uart) uart_select_tx(uart, 0); } +static void configure_ccd(int enable) +{ + if (enable) { + if (ccd_is_enabled()) + return; + + /* Enable CCD */ + ccd_set_mode(CCD_MODE_ENABLED); + + enable_usb_wakeup = 1; + + uartn_tx_connect(UART_AP); + + /* Turn on 3.3V rail used for INAs and initialize I2CM module */ + usb_i2c_board_enable(); + } else { + /* Disconnect from AP and EC UART TX peripheral from gpios */ + uartn_tx_disconnect(UART_EC); + uartn_tx_disconnect(UART_AP); + + enable_usb_wakeup = board_has_ap_usb(); + ec_uart_enabled = 0; + + /* Disable CCD */ + ccd_set_mode(CCD_MODE_DISABLED); + + /* Turn off 3.3V rail to INAs and disconnect I2CM module */ + usb_i2c_board_disable(); + } + CPRINTS("CCD is now %sabled.", enable ? "en" : "dis"); +} + void rdd_attached(void) { - if (ccd_is_enabled()) - return; - + /* Change CCD_MODE_L to an output which follows the internal GPIO. */ + GWRITE(PINMUX, DIOM1_SEL, GC_PINMUX_GPIO0_GPIO5_SEL); /* Indicate case-closed debug mode (active low) */ - gpio_set_level(GPIO_CCD_MODE_L, 0); + gpio_set_flags(GPIO_CCD_MODE_L, GPIO_OUT_LOW); - /* Enable CCD */ - ccd_set_mode(CCD_MODE_ENABLED); - - enable_usb_wakeup = 1; - - uartn_tx_connect(UART_AP); - - /* Turn on 3.3V rail used for INAs and initialize I2CM module */ - usb_i2c_board_enable(); + /* The device state module will handle the actual enabling of CCD. */ } void rdd_detached(void) { - if (keep_ccd_enabled) + /* + * Done with case-closed debug mode, therfore re-setup the CCD_MODE_L + * pin as an input. + * + * NOTE: A pull up is required on this pin, however it was already + * configured during the set up of the pinmux in gpio_pre_init(). The + * chip-specific GPIO module will ignore any pull up/down configuration + * anyways. + */ + gpio_set_flags(GPIO_CCD_MODE_L, GPIO_INPUT); + + /* The device state module will handle the disabling of CCD. */ +} + +void ccd_mode_pin_changed(int pin_level) +{ + /* Inverted because active low. */ + int enable = pin_level ? 0 : 1; + + /* Keep CCD enabled if it's being forced enabled. */ + if (!enable && keep_ccd_enabled) return; - /* Disconnect from AP and EC UART TX peripheral from gpios */ - uartn_tx_disconnect(UART_EC); - uartn_tx_disconnect(UART_AP); - - /* Done with case-closed debug mode */ - gpio_set_level(GPIO_CCD_MODE_L, 1); - - enable_usb_wakeup = board_has_ap_usb(); - ec_uart_enabled = 0; - - /* Disable CCD */ - ccd_set_mode(CCD_MODE_DISABLED); - - /* Turn off 3.3V rail to INAs and disconnect I2CM module */ - usb_i2c_board_disable(); + configure_ccd(enable); } void ccd_phy_init(int enable_ccd) diff --git a/chip/g/rdd.h b/chip/g/rdd.h index 1f19ee9b3e..a71ace3895 100644 --- a/chip/g/rdd.h +++ b/chip/g/rdd.h @@ -12,6 +12,14 @@ void rdd_detached(void); /* Attach to debug cable */ void rdd_attached(void); +/* + * Called by the device state module when the state of the CCD mode pin changes + * and will either enable or disable case closed debugging. + * + * @param pin_level: The level of the CCD_MODE_L pin. + */ +void ccd_mode_pin_changed(int pin_level); + /* * USB is only used for CCD, so only enable UTMI wakeups when RDD detects that * a debug accessory is attached and disable it as a wakeup source when the