822 lines
27 KiB
Diff
822 lines
27 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: tom <tom@focalcrest.com>
|
||
|
Date: Fri, 28 Apr 2023 01:44:01 +0800
|
||
|
Subject: Fixed restart issues with pd adapter.
|
||
|
|
||
|
---
|
||
|
arch/arm/mach-rockchip/board.c | 9 +
|
||
|
drivers/power/power_delivery/fusb302.c | 84 ++++---
|
||
|
drivers/power/power_delivery/tcpm.c | 123 +++++++---
|
||
|
3 files changed, 140 insertions(+), 76 deletions(-)
|
||
|
|
||
|
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
|
||
|
index 9ffb017dd8..a998ea75d9 100644
|
||
|
--- a/arch/arm/mach-rockchip/board.c
|
||
|
+++ b/arch/arm/mach-rockchip/board.c
|
||
|
@@ -445,8 +445,17 @@ static void scan_run_cmd(void)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+
|
||
|
+static void power_delivery_func(void)
|
||
|
+{
|
||
|
+ struct udevice *dev;
|
||
|
+ uclass_get_device_by_driver(UCLASS_PD,
|
||
|
+ DM_GET_DRIVER(fusb302), &dev);
|
||
|
+}
|
||
|
+
|
||
|
int board_late_init(void)
|
||
|
{
|
||
|
+ power_delivery_func();
|
||
|
#ifdef CONFIG_ROCKCHIP_SET_ETHADDR
|
||
|
rockchip_set_ethaddr();
|
||
|
#endif
|
||
|
diff --git a/drivers/power/power_delivery/fusb302.c b/drivers/power/power_delivery/fusb302.c
|
||
|
index 395455d06b..cf64df4ca4 100644
|
||
|
--- a/drivers/power/power_delivery/fusb302.c
|
||
|
+++ b/drivers/power/power_delivery/fusb302.c
|
||
|
@@ -11,7 +11,7 @@
|
||
|
#include <power/power_delivery/tcpm.h>
|
||
|
#include <power/power_delivery/power_delivery.h>
|
||
|
#include "fusb302_reg.h"
|
||
|
-
|
||
|
+#include <irq-generic.h>
|
||
|
/*
|
||
|
* When the device is SNK, BC_LVL interrupt is used to monitor cc pins
|
||
|
* for the current capability offered by the SRC. As FUSB302 chip fires
|
||
|
@@ -192,6 +192,7 @@ static int fusb302_enable_tx_auto_retries(struct fusb302_chip *chip, u8 retry_co
|
||
|
/*
|
||
|
* mask all interrupt on the chip
|
||
|
*/
|
||
|
+#if 0
|
||
|
static int fusb302_mask_interrupt(struct fusb302_chip *chip)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
@@ -209,6 +210,7 @@ static int fusb302_mask_interrupt(struct fusb302_chip *chip)
|
||
|
FUSB_REG_CONTROL0_INT_MASK);
|
||
|
return ret;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
/*
|
||
|
* initialize interrupt on the chip
|
||
|
@@ -268,7 +270,7 @@ static int tcpm_init(struct tcpc_dev *dev)
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
- printf("fusb302 device ID: 0x%02x\n", data);
|
||
|
+ debug("fusb302 device ID: 0x%02x\n", data);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -401,7 +403,7 @@ static int fusb302_set_toggling(struct fusb302_chip *chip,
|
||
|
} else {
|
||
|
/* Datasheet says vconn MUST be off when toggling */
|
||
|
if (chip->vconn_on)
|
||
|
- printf("%s: Vconn is on during toggle start\n", __func__);
|
||
|
+ debug("%s: Vconn is on during toggle start\n", __func__);
|
||
|
/* unmask TOGDONE interrupt */
|
||
|
ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA,
|
||
|
FUSB_REG_MASKA_TOGDONE);
|
||
|
@@ -568,7 +570,7 @@ static int tcpm_set_vconn(struct tcpc_dev *dev, bool on)
|
||
|
FUSB_REG_SWITCHES0_VCONN_CC2;
|
||
|
|
||
|
if (chip->vconn_on == on) {
|
||
|
- printf("vconn is already %s\n", on ? "On" : "Off");
|
||
|
+ debug("vconn is already %s\n", on ? "On" : "Off");
|
||
|
goto done;
|
||
|
}
|
||
|
if (on) {
|
||
|
@@ -771,7 +773,7 @@ static int tcpm_start_toggling(struct tcpc_dev *dev,
|
||
|
printf("%s: unable to start drp toggling(%d)\n", __func__, ret);
|
||
|
goto done;
|
||
|
}
|
||
|
- printf("fusb302 start drp toggling\n");
|
||
|
+ debug("fusb302 start drp toggling\n");
|
||
|
done:
|
||
|
|
||
|
return ret;
|
||
|
@@ -896,9 +898,8 @@ static void fusb302_bc_lvl_handler(struct fusb302_chip *chip)
|
||
|
u8 status0;
|
||
|
u8 bc_lvl;
|
||
|
enum typec_cc_status cc_status;
|
||
|
-
|
||
|
if (!chip->intr_bc_lvl) {
|
||
|
- printf("BC_LVL interrupt is turned off, abort\n");
|
||
|
+ debug("BC_LVL interrupt is turned off, abort\n");
|
||
|
goto done;
|
||
|
}
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
|
||
|
@@ -907,7 +908,7 @@ static void fusb302_bc_lvl_handler(struct fusb302_chip *chip)
|
||
|
|
||
|
debug("BC_LVL handler, status0 = 0x%02x\n", status0);
|
||
|
if (status0 & FUSB_REG_STATUS0_ACTIVITY)
|
||
|
- printf("CC activities detected, delay handling\n");
|
||
|
+ debug("CC activities detected, delay handling\n");
|
||
|
bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK;
|
||
|
cc_status = fusb302_bc_lvl_to_cc(bc_lvl);
|
||
|
if (chip->cc_polarity == TYPEC_POLARITY_CC1) {
|
||
|
@@ -933,14 +934,14 @@ done:
|
||
|
}
|
||
|
|
||
|
static void fusb302_interrupt_handle(struct fusb302_chip *chip);
|
||
|
+
|
||
|
+
|
||
|
static void fusb302_poll_event(struct tcpc_dev *dev)
|
||
|
{
|
||
|
- struct fusb302_chip *chip = container_of(dev, struct fusb302_chip,
|
||
|
- tcpc_dev);
|
||
|
-
|
||
|
- fusb302_interrupt_handle(chip);
|
||
|
}
|
||
|
|
||
|
+
|
||
|
+#if 0
|
||
|
static int fusb302_enter_low_power_mode(struct tcpc_dev *dev,
|
||
|
bool attached, bool pd_capable)
|
||
|
{
|
||
|
@@ -961,6 +962,7 @@ static int fusb302_enter_low_power_mode(struct tcpc_dev *dev,
|
||
|
|
||
|
return fusb302_set_power_mode(chip, reg);
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev)
|
||
|
{
|
||
|
@@ -977,7 +979,8 @@ static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev)
|
||
|
fusb302_tcpc_dev->start_toggling = tcpm_start_toggling;
|
||
|
fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit;
|
||
|
fusb302_tcpc_dev->poll_event = fusb302_poll_event;
|
||
|
- fusb302_tcpc_dev->enter_low_power_mode = fusb302_enter_low_power_mode;
|
||
|
+ // fusb302_tcpc_dev->enter_low_power_mode = fusb302_enter_low_power_mode;
|
||
|
+ fusb302_tcpc_dev->enter_low_power_mode = NULL;
|
||
|
}
|
||
|
|
||
|
static const char * const cc_polarity_name[] = {
|
||
|
@@ -1052,7 +1055,7 @@ static int fusb302_handle_togdone_snk(struct fusb302_chip *chip,
|
||
|
cc_status_active = fusb302_bc_lvl_to_cc(bc_lvl);
|
||
|
/* restart toggling if the cc status on the active line is OPEN */
|
||
|
if (cc_status_active == TYPEC_CC_OPEN) {
|
||
|
- printf("restart toggling as CC_OPEN detected\n");
|
||
|
+ debug("restart toggling as CC_OPEN detected\n");
|
||
|
ret = fusb302_set_toggling(chip, chip->toggling_mode);
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -1190,7 +1193,7 @@ static int fusb302_handle_togdone_src(struct fusb302_chip *chip,
|
||
|
(cc1 == TYPEC_CC_OPEN || cc1 == TYPEC_CC_RA)) {
|
||
|
cc_polarity = TYPEC_POLARITY_CC2;
|
||
|
} else {
|
||
|
- printf("unexpected CC status cc1=%s, cc2=%s, restarting toggling\n",
|
||
|
+ debug("unexpected CC status cc1=%s, cc2=%s, restarting toggling\n",
|
||
|
typec_cc_status_name[cc1],
|
||
|
typec_cc_status_name[cc2]);
|
||
|
return fusb302_set_toggling(chip, toggling_mode);
|
||
|
@@ -1271,7 +1274,6 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
|
||
|
u8 token;
|
||
|
u8 crc[4];
|
||
|
int len;
|
||
|
-
|
||
|
/* first SOP token */
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_FIFOS, &token);
|
||
|
if (ret)
|
||
|
@@ -1336,22 +1338,27 @@ static void fusb302_interrupt_handle(struct fusb302_chip *chip)
|
||
|
intr_bc_lvl = chip->intr_bc_lvl;
|
||
|
intr_comp_chng = chip->intr_comp_chng;
|
||
|
|
||
|
- if (chip->gpio_cc_int_present)
|
||
|
- if (!dm_gpio_get_value(&chip->gpio_cc_int))
|
||
|
- return;
|
||
|
-
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &interrupt);
|
||
|
- if (ret)
|
||
|
+ if (ret) {
|
||
|
+ printf("read interrupt fail\n");
|
||
|
return;
|
||
|
+ }
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTA, &interrupta);
|
||
|
- if (ret)
|
||
|
+ if (ret) {
|
||
|
+ printf("read interrupta fail\n");
|
||
|
return;
|
||
|
+ }
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTB, &interruptb);
|
||
|
- if (ret)
|
||
|
+ if (ret) {
|
||
|
+ printf("read interruptb fail\n");
|
||
|
return;
|
||
|
+ }
|
||
|
ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
|
||
|
- if (ret)
|
||
|
+ if (ret) {
|
||
|
+ printf("read status0 fail\n");
|
||
|
return;
|
||
|
+ }
|
||
|
+
|
||
|
debug("IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x\n",
|
||
|
interrupt, interrupta, interruptb, status0);
|
||
|
|
||
|
@@ -1444,13 +1451,17 @@ static void fusb302_interrupt_handle(struct fusb302_chip *chip)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+void fusb302_irq_intn(int irq, void *dev_id)
|
||
|
+{
|
||
|
+ struct fusb302_chip *chip = dev_id;
|
||
|
+ fusb302_interrupt_handle(chip);
|
||
|
+}
|
||
|
+
|
||
|
static int fusb302_probe(struct udevice *dev)
|
||
|
{
|
||
|
struct fusb302_chip *chip = dev_get_priv(dev);
|
||
|
- int ret = 0;
|
||
|
|
||
|
chip->udev = dev;
|
||
|
-
|
||
|
#if 0
|
||
|
/* get vbus regulator */
|
||
|
ret = regulator_get_by_platname("vbus5v0_typec", chip->vbus_regulator);
|
||
|
@@ -1459,7 +1470,6 @@ static int fusb302_probe(struct udevice *dev)
|
||
|
chip->vbus_regulator = NULL;
|
||
|
}
|
||
|
#endif
|
||
|
-
|
||
|
chip->tcpc_dev.connector_node = dev_read_subnode(dev, "connector");
|
||
|
if (!ofnode_valid(chip->tcpc_dev.connector_node)) {
|
||
|
printf("%s: 'connector' node is not found\n", __func__);
|
||
|
@@ -1467,28 +1477,24 @@ static int fusb302_probe(struct udevice *dev)
|
||
|
}
|
||
|
|
||
|
init_tcpc_dev(&chip->tcpc_dev);
|
||
|
-
|
||
|
- ret = gpio_request_by_name(dev, "int-n-gpios", 0,
|
||
|
- &chip->gpio_cc_int, GPIOD_IS_IN);
|
||
|
- if (ret) {
|
||
|
- printf("%s: fail to get int GPIO: ret=%d\n", __func__, ret);
|
||
|
- chip->gpio_cc_int_present = false;
|
||
|
- } else {
|
||
|
- chip->gpio_cc_int_present = true;
|
||
|
- }
|
||
|
-
|
||
|
chip->tcpm_port = tcpm_port_init(dev, &chip->tcpc_dev);
|
||
|
if (IS_ERR(chip->tcpm_port)) {
|
||
|
printf("%s: failed to tcpm port init\n", __func__);
|
||
|
return PTR_ERR(chip->tcpm_port);
|
||
|
}
|
||
|
|
||
|
+ chip->irq = hard_gpio_to_irq(RK_IRQ_GPIO(RK_GPIO0, RK_PC6));
|
||
|
+ if (chip->irq < 0) {
|
||
|
+ printf("%s request irq fail!\n", __func__);
|
||
|
+ return EINTR;
|
||
|
+ }
|
||
|
+ irq_install_handler(chip->irq, fusb302_irq_intn, chip);
|
||
|
+ irq_set_irq_type(chip->irq, IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW);
|
||
|
+ irq_handler_enable(chip->irq);
|
||
|
tcpm_poll_event(chip->tcpm_port);
|
||
|
-
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-
|
||
|
static int fusb302_get_voltage(struct udevice *dev)
|
||
|
{
|
||
|
struct fusb302_chip *chip = dev_get_priv(dev);
|
||
|
diff --git a/drivers/power/power_delivery/tcpm.c b/drivers/power/power_delivery/tcpm.c
|
||
|
index 22334c6230..6b628bafa2 100644
|
||
|
--- a/drivers/power/power_delivery/tcpm.c
|
||
|
+++ b/drivers/power/power_delivery/tcpm.c
|
||
|
@@ -165,7 +165,7 @@
|
||
|
|
||
|
#define GENERATE_ENUM(e) e
|
||
|
#define GENERATE_STRING(s) #s
|
||
|
-#define TCPM_POLL_EVENT_TIME_OUT 2000
|
||
|
+#define TCPM_POLL_EVENT_TIME_OUT 1000
|
||
|
|
||
|
enum tcpm_state {
|
||
|
FOREACH_STATE(GENERATE_ENUM)
|
||
|
@@ -282,6 +282,7 @@ enum power_supply_usb_type {
|
||
|
};
|
||
|
|
||
|
struct tcpm_port {
|
||
|
+ int time_count;
|
||
|
struct udevice *dev;
|
||
|
struct typec_capability typec_caps;
|
||
|
struct tcpc_dev *tcpc;
|
||
|
@@ -577,7 +578,7 @@ static int tcpm_pd_transmit(struct tcpm_port *port,
|
||
|
const struct pd_message *msg)
|
||
|
{
|
||
|
int ret;
|
||
|
- int timeout = PD_T_TCPC_TX_TIMEOUT;
|
||
|
+ // int timeout = PD_T_TCPC_TX_TIMEOUT;
|
||
|
|
||
|
if (msg)
|
||
|
debug("PD TX, header: %#x\n", le16_to_cpu(msg->header));
|
||
|
@@ -589,17 +590,18 @@ static int tcpm_pd_transmit(struct tcpm_port *port,
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
- while ((timeout > 0) && (!port->tx_complete)) {
|
||
|
- port->tcpc->poll_event(port->tcpc);
|
||
|
- udelay(1000);
|
||
|
- timeout--;
|
||
|
- }
|
||
|
-
|
||
|
- if (!timeout) {
|
||
|
- printf("%s: pd transmit data timeout\n", __func__);
|
||
|
- return -ETIMEDOUT;
|
||
|
- }
|
||
|
-
|
||
|
+ /* Using the delay function at this point will affect the gpio interrupt response */
|
||
|
+ // while ((timeout > 0) && (!port->tx_complete)) {
|
||
|
+ // // port->tcpc->poll_event(port->tcpc);
|
||
|
+ // udelay(1000);
|
||
|
+ // timeout--;
|
||
|
+ // }
|
||
|
+
|
||
|
+ // if (!timeout) {
|
||
|
+ // printf("%s: pd transmit data timeout\n", __func__);
|
||
|
+ // return -ETIMEDOUT;
|
||
|
+ // }
|
||
|
+ debug("%s status %u\n", __func__, port->tx_status);
|
||
|
switch (port->tx_status) {
|
||
|
case TCPC_TX_SUCCESS:
|
||
|
port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK;
|
||
|
@@ -685,7 +687,6 @@ static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
|
||
|
int ret = -EOPNOTSUPP;
|
||
|
|
||
|
debug("Setting voltage/current limit %u mV %u mA\n", mv, max_ma);
|
||
|
-
|
||
|
port->supply_voltage = mv;
|
||
|
port->current_limit = max_ma;
|
||
|
|
||
|
@@ -851,7 +852,6 @@ static void tcpm_set_state(struct tcpm_port *port, enum tcpm_state state,
|
||
|
{
|
||
|
debug("%s: line = %d, delay_ms = %d, set state = %s\n",
|
||
|
__func__, __LINE__, delay_ms, tcpm_states[state]);
|
||
|
-
|
||
|
if (delay_ms) {
|
||
|
debug("pending state change %s -> %s @ %u ms [%s]\n",
|
||
|
tcpm_states[port->state], tcpm_states[state], delay_ms,
|
||
|
@@ -1181,6 +1181,8 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
|
||
|
case SRC_READY:
|
||
|
case SNK_READY:
|
||
|
tcpm_queue_message(port, PD_MSG_DATA_SINK_CAP);
|
||
|
+ // tcpm_timer_uninit(port);
|
||
|
+ // port->tcpc->mask_interrupt(port->tcpc);
|
||
|
break;
|
||
|
default:
|
||
|
tcpm_queue_message(port, PD_MSG_CTRL_REJECT);
|
||
|
@@ -1390,7 +1392,7 @@ static void tcpm_pd_rx_handler(struct tcpm_port *port,
|
||
|
*/
|
||
|
if (!!(le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE) ==
|
||
|
(port->data_role == TYPEC_HOST)) {
|
||
|
- printf("Data role mismatch, initiating error recovery\n");
|
||
|
+ debug("Data role mismatch, initiating error recovery\n");
|
||
|
tcpm_set_state(port, ERROR_RECOVERY, 0);
|
||
|
} else {
|
||
|
if (cnt)
|
||
|
@@ -1407,7 +1409,7 @@ done:
|
||
|
void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg)
|
||
|
{
|
||
|
struct pd_rx_event *event;
|
||
|
-
|
||
|
+ debug("%s\n", __func__);
|
||
|
port->poll_event_cnt = 0;
|
||
|
event = kzalloc(sizeof(*event), GFP_ATOMIC);
|
||
|
if (!event)
|
||
|
@@ -1522,7 +1524,7 @@ static int tcpm_pd_check_request(struct tcpm_port *port)
|
||
|
return -EINVAL;
|
||
|
if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH))
|
||
|
return -EINVAL;
|
||
|
- printf("Requested %u -> %u mV, %u mW for %u / %u mW\n",
|
||
|
+ debug("Requested %u -> %u mV, %u mW for %u / %u mW\n",
|
||
|
pdo_min_voltage(pdo), pdo_max_voltage(pdo),
|
||
|
pdo_max, op, max);
|
||
|
break;
|
||
|
@@ -1795,13 +1797,13 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
|
||
|
if (type == PDO_TYPE_BATT) {
|
||
|
*rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags);
|
||
|
|
||
|
- printf("Requesting PDO %d: %u mV, %u mW%s\n",
|
||
|
+ debug("Requesting PDO %d: %u mV, %u mW%s\n",
|
||
|
src_pdo_index, mv, mw,
|
||
|
flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
|
||
|
} else {
|
||
|
*rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags);
|
||
|
|
||
|
- printf("Requesting PDO %d: %u mV, %u mA%s\n",
|
||
|
+ debug("Requesting PDO %d: %u mV, %u mA%s\n",
|
||
|
src_pdo_index, mv, ma,
|
||
|
flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
|
||
|
}
|
||
|
@@ -1900,7 +1902,7 @@ static int tcpm_pd_build_pps_request(struct tcpm_port *port, u32 *rdo)
|
||
|
|
||
|
*rdo = RDO_PROG(src_pdo_index + 1, out_mv, op_ma, flags);
|
||
|
|
||
|
- printf("Requesting APDO %d: %u mV, %u mA\n",
|
||
|
+ debug("Requesting APDO %d: %u mV, %u mA\n",
|
||
|
src_pdo_index, out_mv, op_ma);
|
||
|
|
||
|
port->pps_data.req_op_curr = op_ma;
|
||
|
@@ -1972,7 +1974,7 @@ static bool tcpm_start_toggling(struct tcpm_port *port, enum typec_cc_status cc)
|
||
|
if (!port->tcpc->start_toggling)
|
||
|
return false;
|
||
|
|
||
|
- printf("Start toggling\n");
|
||
|
+ debug("Start toggling\n");
|
||
|
ret = port->tcpc->start_toggling(port->tcpc, port->port_type, cc);
|
||
|
return ret == 0;
|
||
|
}
|
||
|
@@ -2056,7 +2058,7 @@ out_disable_vconn:
|
||
|
out_disable_pd:
|
||
|
port->tcpc->set_pd_rx(port->tcpc, false);
|
||
|
out_disable_mux:
|
||
|
- printf("CC connected in %s as DFP\n",
|
||
|
+ debug("CC connected in %s as DFP\n",
|
||
|
polarity ? "CC2" : "CC1");
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -2088,7 +2090,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
|
||
|
port->tcpc->set_pd_rx(port->tcpc, false);
|
||
|
tcpm_init_vbus(port); /* also disables charging */
|
||
|
tcpm_init_vconn(port);
|
||
|
- tcpm_set_current_limit(port, 0, 0);
|
||
|
+ tcpm_set_current_limit(port, 3000, 5000);
|
||
|
tcpm_set_polarity(port, TYPEC_POLARITY_CC1);
|
||
|
tcpm_set_attached_state(port, false);
|
||
|
port->usb_type = POWER_SUPPLY_USB_TYPE_C;
|
||
|
@@ -2134,7 +2136,7 @@ static int tcpm_snk_attach(struct tcpm_port *port)
|
||
|
|
||
|
port->attached = true;
|
||
|
port->debouncing = false;
|
||
|
- printf("CC connected in %s as UFP\n",
|
||
|
+ debug("CC connected in %s as UFP\n",
|
||
|
port->cc1 != TYPEC_CC_OPEN ? "CC1" : "CC2");
|
||
|
|
||
|
return 0;
|
||
|
@@ -2174,14 +2176,18 @@ static void tcpm_acc_detach(struct tcpm_port *port)
|
||
|
|
||
|
static inline enum tcpm_state hard_reset_state(struct tcpm_port *port)
|
||
|
{
|
||
|
- if (port->hard_reset_count < PD_N_HARD_RESET_COUNT)
|
||
|
+ if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
|
||
|
return HARD_RESET_SEND;
|
||
|
- if (port->pd_capable)
|
||
|
+ }
|
||
|
+ if (port->pd_capable) {
|
||
|
return ERROR_RECOVERY;
|
||
|
- if (port->pwr_role == TYPEC_SOURCE)
|
||
|
+ }
|
||
|
+ if (port->pwr_role == TYPEC_SOURCE) {
|
||
|
return SRC_UNATTACHED;
|
||
|
- if (port->state == SNK_WAIT_CAPABILITIES)
|
||
|
+ }
|
||
|
+ if (port->state == SNK_WAIT_CAPABILITIES) {
|
||
|
return SNK_READY;
|
||
|
+ }
|
||
|
return SNK_UNATTACHED;
|
||
|
}
|
||
|
|
||
|
@@ -2219,6 +2225,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
break;
|
||
|
/* SRC states */
|
||
|
case SRC_UNATTACHED:
|
||
|
+ debug("%s state SRC_UNATTACHED\n", __func__);
|
||
|
tcpm_src_detach(port);
|
||
|
if (tcpm_start_toggling(port, tcpm_rp_cc(port))) {
|
||
|
tcpm_set_state(port, TOGGLING, 0);
|
||
|
@@ -2342,6 +2349,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
|
||
|
/* SNK states */
|
||
|
case SNK_UNATTACHED:
|
||
|
+ debug("%s state SNK_UNATTACHED\n", __func__);
|
||
|
tcpm_snk_detach(port);
|
||
|
if (tcpm_start_toggling(port, TYPEC_CC_RD)) {
|
||
|
tcpm_set_state(port, TOGGLING, 0);
|
||
|
@@ -2352,6 +2360,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC);
|
||
|
break;
|
||
|
case SNK_ATTACH_WAIT:
|
||
|
+ debug("%s state SNK_ATTACH_WAIT\n", __func__);
|
||
|
if ((port->cc1 == TYPEC_CC_OPEN &&
|
||
|
port->cc2 != TYPEC_CC_OPEN) ||
|
||
|
(port->cc1 != TYPEC_CC_OPEN &&
|
||
|
@@ -2363,6 +2372,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
PD_T_CC_DEBOUNCE);
|
||
|
break;
|
||
|
case SNK_DEBOUNCED:
|
||
|
+ debug("%s state SNK_DEBOUNCED\n", __func__);
|
||
|
if (tcpm_port_is_disconnected(port)) {
|
||
|
tcpm_set_state(port, SNK_UNATTACHED,
|
||
|
PD_T_PD_DEBOUNCE);
|
||
|
@@ -2374,6 +2384,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
break;
|
||
|
|
||
|
case SNK_ATTACHED:
|
||
|
+ debug("%s state SNK_ATTACHED\n", __func__);
|
||
|
ret = tcpm_snk_attach(port);
|
||
|
if (ret < 0)
|
||
|
tcpm_set_state(port, SNK_UNATTACHED, 0);
|
||
|
@@ -2381,6 +2392,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SNK_STARTUP, 0);
|
||
|
break;
|
||
|
case SNK_STARTUP:
|
||
|
+ debug("%s state SNK_STARTUP\n", __func__);
|
||
|
port->negotiated_rev = PD_MAX_REV;
|
||
|
port->message_id = 0;
|
||
|
port->rx_msgid = -1;
|
||
|
@@ -2388,6 +2400,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SNK_DISCOVERY, 0);
|
||
|
break;
|
||
|
case SNK_DISCOVERY:
|
||
|
+ debug("%s state SNK_DISCOVERY\n", __func__);
|
||
|
if (port->vbus_present) {
|
||
|
tcpm_set_current_limit(port,
|
||
|
tcpm_get_current_limit(port),
|
||
|
@@ -2406,10 +2419,12 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
PD_T_DB_DETECT : PD_T_NO_RESPONSE);
|
||
|
break;
|
||
|
case SNK_DISCOVERY_DEBOUNCE:
|
||
|
+ debug("%s state SNK_DISCOVERY_DEBOUNCE\n", __func__);
|
||
|
tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
|
||
|
PD_T_CC_DEBOUNCE);
|
||
|
break;
|
||
|
case SNK_DISCOVERY_DEBOUNCE_DONE:
|
||
|
+ debug("%s state SNK_DISCOVERY_DEBOUNCE_DONE\n", __func__);
|
||
|
#if 0
|
||
|
if (!tcpm_port_is_disconnected(port) &&
|
||
|
tcpm_port_is_sink(port) &&
|
||
|
@@ -2422,6 +2437,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, unattached_state(port), 0);
|
||
|
break;
|
||
|
case SNK_WAIT_CAPABILITIES:
|
||
|
+ debug("%s state SNK_WAIT_CAPABILITIES\n", __func__);
|
||
|
ret = port->tcpc->set_pd_rx(port->tcpc, true);
|
||
|
if (ret < 0) {
|
||
|
tcpm_set_state(port, SNK_READY, 0);
|
||
|
@@ -2433,6 +2449,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
* were already in a stable contract before this boot.
|
||
|
* Do this only once.
|
||
|
*/
|
||
|
+ debug("## vbus_never_low: %d\n", port->vbus_never_low);
|
||
|
if (port->vbus_never_low) {
|
||
|
port->vbus_never_low = false;
|
||
|
tcpm_set_state(port, SOFT_RESET_SEND,
|
||
|
@@ -2443,6 +2460,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
}
|
||
|
break;
|
||
|
case SNK_NEGOTIATE_CAPABILITIES:
|
||
|
+ debug("%s state SNK_NEGOTIATE_CAPABILITIES\n", __func__);
|
||
|
port->pd_capable = true;
|
||
|
port->hard_reset_count = 0;
|
||
|
ret = tcpm_pd_send_request(port);
|
||
|
@@ -2455,6 +2473,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
}
|
||
|
break;
|
||
|
case SNK_NEGOTIATE_PPS_CAPABILITIES:
|
||
|
+ debug("%s state SNK_NEGOTIATE_PPS_CAPABILITIES\n", __func__);
|
||
|
ret = tcpm_pd_send_pps_request(port);
|
||
|
if (ret < 0) {
|
||
|
port->pps_status = ret;
|
||
|
@@ -2474,10 +2493,12 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
break;
|
||
|
case SNK_TRANSITION_SINK:
|
||
|
case SNK_TRANSITION_SINK_VBUS:
|
||
|
+ debug("%s state SNK_TRANSITION_SINK\n", __func__);
|
||
|
tcpm_set_state(port, hard_reset_state(port),
|
||
|
PD_T_PS_TRANSITION);
|
||
|
break;
|
||
|
case SNK_READY:
|
||
|
+ debug("%s state SNK_READY\n", __func__);
|
||
|
port->try_snk_count = 0;
|
||
|
port->update_sink_caps = false;
|
||
|
tcpm_typec_connect(port);
|
||
|
@@ -2485,6 +2506,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
* Here poll_event_cnt is cleared, waiting for self-powered Type-C devices
|
||
|
* to send DR_swap Messge until 1s (TCPM_POLL_EVENT_TIME_OUT * 500us)timeout
|
||
|
*/
|
||
|
+ debug("SNK_READY wait_dr_swap_Message: %d\n", port->wait_dr_swap_Message);
|
||
|
if (port->wait_dr_swap_Message)
|
||
|
port->poll_event_cnt = 0;
|
||
|
|
||
|
@@ -2507,11 +2529,14 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
|
||
|
/* Hard_Reset states */
|
||
|
case HARD_RESET_SEND:
|
||
|
+ debug("%s state HARD_RESET_SEND\n", __func__);
|
||
|
tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL);
|
||
|
+ debug("%s transmit TCPC_TX_HARD_RESET\n", __func__);
|
||
|
tcpm_set_state(port, HARD_RESET_START, 0);
|
||
|
port->wait_dr_swap_Message = false;
|
||
|
break;
|
||
|
case HARD_RESET_START:
|
||
|
+ debug("%s state HARD_RESET_START\n", __func__);
|
||
|
port->hard_reset_count++;
|
||
|
port->tcpc->set_pd_rx(port->tcpc, false);
|
||
|
port->nr_sink_caps = 0;
|
||
|
@@ -2523,6 +2548,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0);
|
||
|
break;
|
||
|
case SRC_HARD_RESET_VBUS_OFF:
|
||
|
+ debug("%s state SRC_HARD_RESET_VBUS_OFF\n", __func__);
|
||
|
tcpm_set_vconn(port, true);
|
||
|
tcpm_set_vbus(port, false);
|
||
|
tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
|
||
|
@@ -2537,6 +2563,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
|
||
|
break;
|
||
|
case SNK_HARD_RESET_SINK_OFF:
|
||
|
+ debug("%s state SNK_HARD_RESET_SINK_OFF\n", __func__);
|
||
|
memset(&port->pps_data, 0, sizeof(port->pps_data));
|
||
|
tcpm_set_vconn(port, false);
|
||
|
if (port->pd_capable)
|
||
|
@@ -2551,11 +2578,13 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V);
|
||
|
break;
|
||
|
case SNK_HARD_RESET_WAIT_VBUS:
|
||
|
+ debug("%s state SNK_HARD_RESET_WAIT_VBUS\n", __func__);
|
||
|
/* Assume we're disconnected if VBUS doesn't come back. */
|
||
|
tcpm_set_state(port, SNK_UNATTACHED,
|
||
|
PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON);
|
||
|
break;
|
||
|
case SNK_HARD_RESET_SINK_ON:
|
||
|
+ debug("%s state SNK_HARD_RESET_SINK_ON\n", __func__);
|
||
|
/* Note: There is no guarantee that VBUS is on in this state */
|
||
|
/*
|
||
|
* XXX:
|
||
|
@@ -2584,6 +2613,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
|
||
|
/* Soft_Reset states */
|
||
|
case SOFT_RESET:
|
||
|
+ debug("%s state SOFT_RESET\n", __func__);
|
||
|
port->message_id = 0;
|
||
|
port->rx_msgid = -1;
|
||
|
tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
|
||
|
@@ -2594,6 +2624,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||
|
}
|
||
|
break;
|
||
|
case SOFT_RESET_SEND:
|
||
|
+ debug("%s state SOFT_RESET_SEND\n", __func__);
|
||
|
port->message_id = 0;
|
||
|
port->rx_msgid = -1;
|
||
|
if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
|
||
|
@@ -2797,6 +2828,7 @@ static void tcpm_state_machine(struct tcpm_port *port)
|
||
|
debug("state change %s -> %s [delayed %ld ms]\n",
|
||
|
tcpm_states[port->state],
|
||
|
tcpm_states[port->delayed_state], port->delay_ms);
|
||
|
+
|
||
|
port->prev_state = port->state;
|
||
|
port->state = port->delayed_state;
|
||
|
port->delayed_state = INVALID_STATE;
|
||
|
@@ -2836,6 +2868,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
|
||
|
switch (port->state) {
|
||
|
case TOGGLING:
|
||
|
+ debug("%s state TOGGLING\n", __func__);
|
||
|
if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) ||
|
||
|
tcpm_port_is_source(port))
|
||
|
tcpm_set_state(port, SRC_ATTACH_WAIT, 0);
|
||
|
@@ -2863,10 +2896,12 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
tcpm_set_state(port, SRC_UNATTACHED, 0);
|
||
|
break;
|
||
|
case SNK_UNATTACHED:
|
||
|
+ debug("%s state SNK_UNATTACHED\n", __func__);
|
||
|
if (tcpm_port_is_sink(port))
|
||
|
tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
|
||
|
break;
|
||
|
case SNK_ATTACH_WAIT:
|
||
|
+ debug("%s state SNK_ATTACH_WAIT\n", __func__);
|
||
|
if ((port->cc1 == TYPEC_CC_OPEN &&
|
||
|
port->cc2 != TYPEC_CC_OPEN) ||
|
||
|
(port->cc1 != TYPEC_CC_OPEN &&
|
||
|
@@ -2880,6 +2915,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
tcpm_set_state(port, SNK_ATTACH_WAIT, 0);
|
||
|
break;
|
||
|
case SNK_DEBOUNCED:
|
||
|
+ debug("%s state SNK_DEBOUNCED\n", __func__);
|
||
|
if (tcpm_port_is_disconnected(port))
|
||
|
new_state = SNK_UNATTACHED;
|
||
|
else if (port->vbus_present)
|
||
|
@@ -2890,6 +2926,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
tcpm_set_state(port, SNK_DEBOUNCED, 0);
|
||
|
break;
|
||
|
case SNK_READY:
|
||
|
+ debug("%s state SNK_READY\n", __func__);
|
||
|
if (tcpm_port_is_disconnected(port))
|
||
|
tcpm_set_state(port, unattached_state(port), 0);
|
||
|
else if (!port->pd_capable &&
|
||
|
@@ -2900,29 +2937,35 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
break;
|
||
|
|
||
|
case AUDIO_ACC_ATTACHED:
|
||
|
+ debug("%s state AUDIO_ACC_ATTACHED\n", __func__);
|
||
|
if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN)
|
||
|
tcpm_set_state(port, AUDIO_ACC_DEBOUNCE, 0);
|
||
|
break;
|
||
|
case AUDIO_ACC_DEBOUNCE:
|
||
|
+ debug("%s state AUDIO_ACC_DEBOUNCE\n", __func__);
|
||
|
if (tcpm_port_is_audio(port))
|
||
|
tcpm_set_state(port, AUDIO_ACC_ATTACHED, 0);
|
||
|
break;
|
||
|
|
||
|
case DEBUG_ACC_ATTACHED:
|
||
|
+ debug("%s state DEBUG_ACC_ATTACHED\n", __func__);
|
||
|
if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN)
|
||
|
tcpm_set_state(port, ACC_UNATTACHED, 0);
|
||
|
break;
|
||
|
|
||
|
case SNK_TRY:
|
||
|
+ debug("%s state SNK_TRY\n", __func__);
|
||
|
/* Do nothing, waiting for timeout */
|
||
|
break;
|
||
|
|
||
|
case SNK_DISCOVERY:
|
||
|
+ debug("%s state SNK_DISCOVERY\n", __func__);
|
||
|
/* CC line is unstable, wait for debounce */
|
||
|
if (tcpm_port_is_disconnected(port))
|
||
|
tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE, 0);
|
||
|
break;
|
||
|
case SNK_DISCOVERY_DEBOUNCE:
|
||
|
+ debug("%s state SNK_DISCOVERY_DEBOUNCE\n", __func__);
|
||
|
break;
|
||
|
|
||
|
case SRC_TRYWAIT:
|
||
|
@@ -2935,6 +2978,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
tcpm_set_state(port, SRC_TRYWAIT, 0);
|
||
|
break;
|
||
|
case SNK_TRY_WAIT_DEBOUNCE:
|
||
|
+ debug("%s state SNK_TRY_WAIT_DEBOUNCE\n", __func__);
|
||
|
if (!tcpm_port_is_sink(port)) {
|
||
|
port->max_wait = 0;
|
||
|
tcpm_set_state(port, SRC_TRYWAIT, 0);
|
||
|
@@ -2948,14 +2992,17 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
|
||
|
tcpm_set_state(port, SRC_TRY_WAIT, 0);
|
||
|
break;
|
||
|
case SNK_TRYWAIT_DEBOUNCE:
|
||
|
+ debug("%s state SNK_TRYWAIT_DEBOUNCE\n", __func__);
|
||
|
if (tcpm_port_is_sink(port))
|
||
|
tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0);
|
||
|
break;
|
||
|
case SNK_TRYWAIT_VBUS:
|
||
|
+ debug("%s state SNK_TRYWAIT_VBUS\n", __func__);
|
||
|
if (!tcpm_port_is_sink(port))
|
||
|
tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0);
|
||
|
break;
|
||
|
case SNK_TRYWAIT:
|
||
|
+ debug("%s state SNK_TRYWAIT\n", __func__);
|
||
|
/* Do nothing, waiting for tCCDebounce */
|
||
|
break;
|
||
|
case PR_SWAP_SNK_SRC_SINK_OFF:
|
||
|
@@ -3457,7 +3504,7 @@ struct tcpm_port *tcpm_port_init(struct udevice *dev, struct tcpc_dev *tcpc)
|
||
|
|
||
|
tcpm_init(port);
|
||
|
|
||
|
- printf("%s: init finished\n", dev_read_name(dev));
|
||
|
+ debug("%s: init finished\n", dev_read_name(dev));
|
||
|
|
||
|
return port;
|
||
|
}
|
||
|
@@ -3465,8 +3512,10 @@ EXPORT_SYMBOL_GPL(tcpm_port_init);
|
||
|
|
||
|
void tcpm_poll_event(struct tcpm_port *port)
|
||
|
{
|
||
|
- if (!port->tcpc->get_vbus(port->tcpc))
|
||
|
+ port->time_count = 3000;
|
||
|
+ if (!port->tcpc->get_vbus(port->tcpc)) {
|
||
|
return ;
|
||
|
+ }
|
||
|
|
||
|
while (port->poll_event_cnt < TCPM_POLL_EVENT_TIME_OUT) {
|
||
|
if (!port->wait_dr_swap_Message &&
|
||
|
@@ -3475,12 +3524,12 @@ void tcpm_poll_event(struct tcpm_port *port)
|
||
|
(port->state == DEBUG_ACC_ATTACHED) ||
|
||
|
(port->state == AUDIO_ACC_ATTACHED)))
|
||
|
break;
|
||
|
-
|
||
|
- port->tcpc->poll_event(port->tcpc);
|
||
|
- port->poll_event_cnt++;
|
||
|
- udelay(500);
|
||
|
}
|
||
|
|
||
|
+ while (port->time_count > 0) {
|
||
|
+ port->time_count--;
|
||
|
+ udelay(1000);
|
||
|
+ }
|
||
|
/*
|
||
|
* At this time, call the callback function of the respective pd chip
|
||
|
* to enter the low-power mode. In order to reduce the time spent on
|
||
|
@@ -3497,9 +3546,9 @@ void tcpm_poll_event(struct tcpm_port *port)
|
||
|
if (port->tcpc->enter_low_power_mode(port->tcpc,
|
||
|
port->attached,
|
||
|
port->pd_capable))
|
||
|
- printf("failed to enter low power\n");
|
||
|
+ debug("failed to enter low power\n");
|
||
|
else
|
||
|
- printf("PD chip enter low power mode\n");
|
||
|
+ debug("PD chip enter low power mode\n");
|
||
|
}
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(tcpm_poll_event);
|
||
|
--
|
||
|
Armbian
|
||
|
|