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