cr50: Detect debug cable and switch the PHY

This adds support for RD Detection on cr50. It can be used to detect a
debug device and signal the controller to switch from the AP PHY to the
to CCD PHY. When RDCC1 and 2 no longer detect the debug device, then
the controller switches back to using the USB to AP PHY.

BUG=chrome-os-partner:50700
BRANCH=none
TEST=change the value on RDCC1 and RDCC1 and check that the usb
controller connects to the right PHY.

Change-Id: Ice01a45a31fe1932945f89df2e3b851f4d287a17
Signed-off-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/338454
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
Mary Ruthven
2016-04-12 11:46:16 -07:00
committed by chrome-bot
parent 0374c599af
commit d281308b48
8 changed files with 110 additions and 10 deletions

View File

@@ -28,6 +28,7 @@
#define CONFIG_USB
#define CONFIG_USB_HID
#define CONFIG_USB_CONSOLE
#define CONFIG_USB_SELECT_PHY
#define CONFIG_STREAM_USART
#define CONFIG_STREAM_USB

View File

@@ -50,6 +50,7 @@ chip-$(CONFIG_USB)+=usb.o usb_endpoints.o
chip-$(CONFIG_USB_CONSOLE)+=usb_console.o
chip-$(CONFIG_USB_HID)+=usb_hid.o
chip-$(CONFIG_USB_BLOB)+=blob.o
chip-$(CONFIG_RDD)+=rdd.o
chip-$(CONFIG_STREAM_USB)+=usb-stream.o
chip-$(CONFIG_STREAM_USART)+=usart.o

View File

@@ -30,6 +30,9 @@ void clock_enable_module(enum module_id module, int enable)
clock_func(PERIPH_I2C0);
clock_func(PERIPH_I2C1);
break;
case MODULE_RDD:
clock_func(PERIPH_RDD0);
break;
case MODULE_SPI_FLASH:
case MODULE_SPI_MASTER:
clock_func(PERIPH_SPI);

75
chip/g/rdd.c Normal file
View File

@@ -0,0 +1,75 @@
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "clock.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
#include "task.h"
#include "usb_api.h"
#define CCD_PHY USB_SEL_PHY1
#define AP_PHY USB_SEL_PHY0
uint16_t ccd_detect;
static int debug_cable_is_detected(void)
{
uint8_t cc1 = GREAD_FIELD(RDD, INPUT_PIN_VALUES, CC1);
uint8_t cc2 = GREAD_FIELD(RDD, INPUT_PIN_VALUES, CC2);
return (cc1 == cc2 && (cc1 == 3 || cc1 == 1));
}
void rdd_interrupt(void)
{
if (debug_cable_is_detected()) {
ccprintf("Debug Accessory connected\n");
/* Detect when debug cable is disconnected */
GWRITE(RDD, PROG_DEBUG_STATE_MAP, ~ccd_detect);
/* Select the CCD PHY */
usb_select_phy(CCD_PHY);
} else {
ccprintf("Debug Accessory disconnected\n");
/* Detect when debug cable is connected */
GWRITE(RDD, PROG_DEBUG_STATE_MAP, ccd_detect);
/* Select the AP PHY */
usb_select_phy(AP_PHY);
}
/* Connect to selected phy */
usb_init();
/* Clear interrupt */
GWRITE_FIELD(RDD, INT_STATE, INTR_DEBUG_STATE_DETECTED, 1);
}
DECLARE_IRQ(GC_IRQNUM_RDD0_INTR_DEBUG_STATE_DETECTED_INT, rdd_interrupt, 1);
void rdd_init(void)
{
/* Enable RDD */
clock_enable_module(MODULE_RDD, 1);
GWRITE(RDD, POWER_DOWN_B, 1);
ccd_detect = GREAD(RDD, PROG_DEBUG_STATE_MAP);
/* Detect cable disconnect if CCD is enabled */
if (usb_get_phy() == CCD_PHY)
GWRITE(RDD, PROG_DEBUG_STATE_MAP, ~ccd_detect);
/* Enable RDD interrupts */
task_enable_irq(GC_IRQNUM_RDD0_INTR_DEBUG_STATE_DETECTED_INT);
GWRITE_FIELD(RDD, INT_ENABLE, INTR_DEBUG_STATE_DETECTED, 1);
}
DECLARE_HOOK(HOOK_INIT, rdd_init, HOOK_PRIO_DEFAULT);
static int command_test_rdd(int argc, char **argv)
{
GWRITE_FIELD(RDD, INT_TEST, INTR_DEBUG_STATE_DETECTED, 1);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(test_rdd, command_test_rdd, "", "", NULL);

View File

@@ -314,13 +314,19 @@ static uint8_t configuration_value;
/* Default PHY to use */
static uint32_t which_phy = USB_SEL_PHY1;
static inline void select_phy(uint32_t phy)
void usb_select_phy(uint32_t phy)
{
which_phy = phy;
GR_USB_GGPIO = GGPIO_WRITE(USB_CUSTOM_CFG_REG,
(USB_PHY_ACTIVE | which_phy));
}
uint32_t usb_get_phy(void)
{
return which_phy;
}
/* Reset all this to a good starting state. */
static void initialize_dma_buffers(void)
{
@@ -1237,7 +1243,7 @@ void usb_init(void)
GR_USB_DOEPMSK = 0;
/* Select the correct PHY */
select_phy(which_phy);
usb_select_phy(which_phy);
gpio_set_level(GPIO_CCD_MODE_L, !(which_phy == USB_SEL_PHY1));
/* Full-Speed Serial PHY */
@@ -1363,9 +1369,9 @@ static int command_usb(int argc, char **argv)
else if (!strcasecmp("off", argv[1]))
usb_release();
else if (!strcasecmp("a", argv[1]))
select_phy(USB_SEL_PHY0);
usb_select_phy(USB_SEL_PHY0);
else if (!strcasecmp("b", argv[1]))
select_phy(USB_SEL_PHY1);
usb_select_phy(USB_SEL_PHY1);
}
showregs();

View File

@@ -1480,6 +1480,9 @@
/* Size of RAM available on the chip, in bytes */
#undef CONFIG_RAM_SIZE
/* Enable RDD peripheral */
#undef CONFIG_RDD
/* Support IR357x Link voltage regulator debugging / reprogramming */
#undef CONFIG_REGULATOR_IR357X
@@ -1945,6 +1948,9 @@
/* Disable automatic initialization of USB peripheral */
#undef CONFIG_USB_INHIBIT_INIT
/* Support control of multiple PHY */
#undef CONFIG_USB_SELECT_PHY
/* Support simple control of power to the device's USB ports */
#undef CONFIG_USB_PORT_POWER_DUMB

View File

@@ -32,21 +32,22 @@ enum module_id {
MODULE_PORT80,
MODULE_POWER_LED,
MODULE_PWM, /* 20 */
MODULE_RDD,
MODULE_SPI,
MODULE_SPI_FLASH,
MODULE_SPI_MASTER,
MODULE_SWITCH,
MODULE_SYSTEM, /* 25 */
MODULE_SWITCH, /* 25 */
MODULE_SYSTEM,
MODULE_TASK,
MODULE_THERMAL,
MODULE_UART,
MODULE_USART,
MODULE_USB, /* 30 */
MODULE_USART, /* 30 */
MODULE_USB,
MODULE_USB_DEBUG,
MODULE_USB_PD,
MODULE_USB_PORT_POWER,
MODULE_USB_SWITCH,
MODULE_VBOOT, /* 35 */
MODULE_USB_SWITCH, /* 35 */
MODULE_VBOOT,
/* Module count; not an actual module */
MODULE_COUNT

View File

@@ -42,4 +42,11 @@ void usb_disconnect(void);
*/
void usb_release(void);
#ifdef CONFIG_USB_SELECT_PHY
/* Select which PHY to use. */
void usb_select_phy(uint32_t phy);
/* Get the current PHY */
uint32_t usb_get_phy(void);
#endif
#endif /* __CROS_EC_USB_API_H */