"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge https://source.denx.de/u-boot/custodians/u-boot-usb

Tom Rini 9e1cd2f2 98a36deb

+5023
+9
MAINTAINERS
··· 1754 1754 F: common/usb_storage.c 1755 1755 F: include/usb.h 1756 1756 1757 + USB TCPM 1758 + M: Sebastian Reichel <sebastian.reichel@collabora.com> 1759 + S: Maintained 1760 + F: cmd/tcpm.c 1761 + F: doc/usage/cmd/tcpm.rst 1762 + F: drivers/usb/tcpm/ 1763 + F: include/usb/pd.h 1764 + F: include/usb/tcpm.h 1765 + 1757 1766 USB xHCI 1758 1767 M: Bin Meng <bmeng.cn@gmail.com> 1759 1768 S: Maintained
+1
Makefile
··· 887 887 libs-y += drivers/usb/musb-new/ 888 888 libs-y += drivers/usb/isp1760/ 889 889 libs-y += drivers/usb/phy/ 890 + libs-y += drivers/usb/tcpm/ 890 891 libs-y += drivers/usb/ulpi/ 891 892 ifdef CONFIG_POST 892 893 libs-y += post/
+28
arch/arm/dts/rk3588-rock-5b-u-boot.dtsi
··· 3 3 * Copyright (c) 2023 Collabora Ltd. 4 4 */ 5 5 6 + #include <dt-bindings/usb/pd.h> 6 7 #include "rk3588-u-boot.dtsi" 7 8 8 9 &fspim2_pins { 9 10 bootph-pre-ram; 10 11 bootph-some-ram; 12 + }; 13 + 14 + &i2c4 { 15 + pinctrl-names = "default"; 16 + pinctrl-0 = <&i2c4m1_xfer>; 17 + status = "okay"; 18 + 19 + usbc0: usb-typec@22 { 20 + compatible = "fcs,fusb302"; 21 + reg = <0x22>; 22 + interrupt-parent = <&gpio3>; 23 + interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>; 24 + pinctrl-names = "default"; 25 + status = "okay"; 26 + 27 + usb_con: connector { 28 + compatible = "usb-c-connector"; 29 + label = "USB-C"; 30 + data-role = "dual"; 31 + power-role = "sink"; 32 + try-power-role = "sink"; 33 + op-sink-microwatt = <1000000>; 34 + sink-pdos = 35 + <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>, 36 + <PDO_VAR(5000, 20000, 5000)>; 37 + }; 38 + }; 11 39 }; 12 40 13 41 &sdhci {
+6
board/radxa/rock5b-rk3588/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0+ 2 + # 3 + # Copyright (c) 2022 Collabora Ltd. 4 + # 5 + 6 + obj-y += rock5b-rk3588.o
+16
board/radxa/rock5b-rk3588/rock5b-rk3588.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) 2023-2024 Collabora Ltd. 4 + */ 5 + 6 + #include <fdtdec.h> 7 + #include <fdt_support.h> 8 + 9 + #ifdef CONFIG_OF_BOARD_SETUP 10 + int ft_board_setup(void *blob, struct bd_info *bd) 11 + { 12 + if (IS_ENABLED(CONFIG_TYPEC_FUSB302)) 13 + fdt_status_okay_by_compatible(blob, "fcs,fusb302"); 14 + return 0; 15 + } 16 + #endif
+7
cmd/Kconfig
··· 221 221 help 222 222 Register dump 223 223 224 + config CMD_TCPM 225 + bool "tcpm" 226 + depends on TYPEC_TCPM 227 + help 228 + Show voltage and current negotiated via USB PD as well as the 229 + current state of the Type C Port Manager (TCPM) state machine. 230 + 224 231 config CMD_TLV_EEPROM 225 232 bool "tlv_eeprom" 226 233 depends on I2C_EEPROM
+1
cmd/Makefile
··· 179 179 obj-$(CONFIG_CMD_SMC) += smccc.o 180 180 obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o 181 181 obj-$(CONFIG_CMD_STACKPROTECTOR_TEST) += stackprot_test.o 182 + obj-$(CONFIG_CMD_TCPM) += tcpm.o 182 183 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o 183 184 obj-$(CONFIG_CMD_TERMINAL) += terminal.o 184 185 obj-$(CONFIG_CMD_TIME) += time.o
+136
cmd/tcpm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * (C) Copyright 2024 Collabora 4 + */ 5 + 6 + #include <command.h> 7 + #include <errno.h> 8 + #include <dm.h> 9 + #include <dm/uclass-internal.h> 10 + #include <usb/tcpm.h> 11 + 12 + #define LIMIT_DEV 32 13 + #define LIMIT_PARENT 20 14 + 15 + static struct udevice *currdev; 16 + 17 + static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 18 + { 19 + int devnum, ret; 20 + 21 + switch (argc) { 22 + case 2: 23 + devnum = (int)dectoul(argv[1], NULL); 24 + ret = tcpm_get(devnum, &currdev); 25 + if (ret) { 26 + log_err("Can't get TCPM %d: %d (%s)!\n", devnum, ret, errno_str(ret)); 27 + return CMD_RET_FAILURE; 28 + } 29 + case 1: 30 + if (!currdev) { 31 + log_err("TCPM device is not set!\n\n"); 32 + return CMD_RET_USAGE; 33 + } 34 + 35 + printf("dev: %d @ %s\n", dev_seq(currdev), currdev->name); 36 + } 37 + 38 + return CMD_RET_SUCCESS; 39 + } 40 + 41 + static int do_list(struct cmd_tbl *cmdtp, int flag, int argc, 42 + char *const argv[]) 43 + { 44 + struct udevice *dev; 45 + int ret, err = 0; 46 + 47 + printf("| ID | %-*.*s| %-*.*s| %s @ %s\n", 48 + LIMIT_DEV, LIMIT_DEV, "Name", 49 + LIMIT_PARENT, LIMIT_PARENT, "Parent name", 50 + "Parent uclass", "seq"); 51 + 52 + for (ret = uclass_first_device_check(UCLASS_TCPM, &dev); dev; 53 + ret = uclass_next_device_check(&dev)) { 54 + if (ret) 55 + err = ret; 56 + 57 + printf("| %2d | %-*.*s| %-*.*s| %s @ %d | status: %i\n", 58 + dev_seq(dev), 59 + LIMIT_DEV, LIMIT_DEV, dev->name, 60 + LIMIT_PARENT, LIMIT_PARENT, dev->parent->name, 61 + dev_get_uclass_name(dev->parent), dev_seq(dev->parent), 62 + ret); 63 + } 64 + 65 + if (err) 66 + return CMD_RET_FAILURE; 67 + 68 + return CMD_RET_SUCCESS; 69 + } 70 + 71 + int do_print_info(struct udevice *dev) 72 + { 73 + enum typec_orientation orientation = tcpm_get_orientation(dev); 74 + const char *state = tcpm_get_state(dev); 75 + int pd_rev = tcpm_get_pd_rev(dev); 76 + int mv = tcpm_get_voltage(dev); 77 + int ma = tcpm_get_current(dev); 78 + enum typec_role pwr_role = tcpm_get_pwr_role(dev); 79 + enum typec_data_role data_role = tcpm_get_data_role(dev); 80 + bool connected = tcpm_is_connected(dev); 81 + 82 + if (!connected) { 83 + printf("TCPM State: %s\n", state); 84 + return 0; 85 + } 86 + 87 + printf("Orientation: %s\n", typec_orientation_name[orientation]); 88 + printf("PD Revision: %s\n", typec_pd_rev_name[pd_rev]); 89 + printf("Power Role: %s\n", typec_role_name[pwr_role]); 90 + printf("Data Role: %s\n", typec_data_role_name[data_role]); 91 + printf("Voltage: %2d.%03d V\n", mv / 1000, mv % 1000); 92 + printf("Current: %2d.%03d A\n", ma / 1000, ma % 1000); 93 + 94 + return 0; 95 + } 96 + 97 + static int do_info(struct cmd_tbl *cmdtp, int flag, int argc, 98 + char *const argv[]) 99 + { 100 + if (!currdev) { 101 + printf("First, set the TCPM device!\n"); 102 + return CMD_RET_USAGE; 103 + } 104 + 105 + return do_print_info(currdev); 106 + } 107 + 108 + static struct cmd_tbl subcmd[] = { 109 + U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), 110 + U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), 111 + U_BOOT_CMD_MKENT(info, 1, 1, do_info, "", ""), 112 + }; 113 + 114 + static int do_tcpm(struct cmd_tbl *cmdtp, int flag, int argc, 115 + char *const argv[]) 116 + { 117 + struct cmd_tbl *cmd; 118 + 119 + argc--; 120 + argv++; 121 + 122 + cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); 123 + if (!cmd || argc > cmd->maxargs) 124 + return CMD_RET_USAGE; 125 + 126 + return cmd->cmd(cmdtp, flag, argc, argv); 127 + } 128 + 129 + /**************************************************/ 130 + 131 + U_BOOT_CMD(tcpm, CONFIG_SYS_MAXARGS, 1, do_tcpm, 132 + "TCPM sub-system", 133 + "list - list TCPM devices\n" 134 + "tcpm dev [ID] - show or [set] operating TCPM device\n" 135 + "tcpm info - dump information\n" 136 + );
+4
configs/rock5b-rk3588_defconfig
··· 24 24 CONFIG_SPL_FIT_SIGNATURE=y 25 25 CONFIG_SPL_LOAD_FIT=y 26 26 CONFIG_LEGACY_IMAGE_FORMAT=y 27 + CONFIG_OF_BOARD_SETUP=y 27 28 CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588-rock-5b.dtb" 28 29 # CONFIG_DISPLAY_CPUINFO is not set 29 30 CONFIG_DISPLAY_BOARDINFO_LATE=y ··· 103 104 CONFIG_USB_GADGET_DOWNLOAD=y 104 105 CONFIG_USB_FUNCTION_ROCKUSB=y 105 106 CONFIG_ERRNO_STR=y 107 + CONFIG_TYPEC_TCPM=y 108 + CONFIG_TYPEC_FUSB302=y 109 + CONFIG_CMD_TCPM=y
+66
doc/usage/cmd/tcpm.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+: 2 + 3 + .. index:: 4 + single: tcpm (command) 5 + 6 + tcpm command 7 + ============ 8 + 9 + Synopsis 10 + -------- 11 + 12 + :: 13 + 14 + tcpm dev [devnum] 15 + tcpm info 16 + tcpm list 17 + 18 + Description 19 + ----------- 20 + 21 + The tcpm command is used to control USB-PD controllers, also known as TypeC Port Manager (TCPM). 22 + 23 + The 'tcpm dev' command shows or set current TCPM device. 24 + 25 + devnum 26 + device number to change 27 + 28 + The 'tcpm info' command displays the current state of the device 29 + 30 + The 'tcpm list' command displays the list available devices. 31 + 32 + Examples 33 + -------- 34 + 35 + The 'tcpm info' command displays device's status: 36 + :: 37 + 38 + => tcpm info 39 + Orientation: normal 40 + PD Revision: rev3 41 + Power Role: sink 42 + Data Role: device 43 + Voltage: 20.000 V 44 + Current: 2.250 A 45 + 46 + The current device can be shown or set via 'tcpm dev' command: 47 + :: 48 + 49 + => tcpm dev 50 + TCPM device is not set! 51 + => tcpm dev 0 52 + dev: 0 @ usb-typec@22 53 + => tcpm dev 54 + dev: 0 @ usb-typec@22 55 + 56 + The list of available devices can be shown via 'tcpm list' command: 57 + :: 58 + 59 + => tcpm list 60 + | ID | Name | Parent name | Parent uclass @ seq 61 + | 0 | usb-typec@22 | i2c@feac0000 | i2c @ 4 | status: 0 62 + 63 + Configuration 64 + ------------- 65 + 66 + The tcpm command is only available if CONFIG_CMD_TCPM=y.
+1
doc/usage/index.rst
··· 112 112 cmd/smbios 113 113 cmd/sound 114 114 cmd/source 115 + cmd/tcpm 115 116 cmd/temperature 116 117 cmd/tftpput 117 118 cmd/trace
+2
drivers/usb/Kconfig
··· 85 85 86 86 source "drivers/usb/phy/Kconfig" 87 87 88 + source "drivers/usb/tcpm/Kconfig" 89 + 88 90 source "drivers/usb/ulpi/Kconfig" 89 91 90 92 if USB_HOST
+16
drivers/usb/tcpm/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + config TYPEC_TCPM 4 + tristate "USB Type-C Port Controller Manager" 5 + depends on DM 6 + help 7 + The Type-C Port Controller Manager provides a USB PD and USB Type-C 8 + state machine for use with Type-C Port Controllers. 9 + 10 + config TYPEC_FUSB302 11 + tristate "Fairchild FUSB302 Type-C chip driver" 12 + depends on DM && DM_I2C && TYPEC_TCPM 13 + help 14 + The Fairchild FUSB302 Type-C chip driver that works with 15 + Type-C Port Controller Manager to provide USB PD and USB 16 + Type-C functionalities.
+4
drivers/usb/tcpm/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_TYPEC_TCPM) += tcpm.o tcpm-uclass.o 4 + obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o
+1323
drivers/usb/tcpm/fusb302.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2016-2017 Google, Inc 4 + * 5 + * Fairchild FUSB302 Type-C Chip Driver 6 + */ 7 + 8 + #include <dm.h> 9 + #include <i2c.h> 10 + #include <asm/gpio.h> 11 + #include <linux/delay.h> 12 + #include <linux/err.h> 13 + #include <dm/device_compat.h> 14 + #include <usb/tcpm.h> 15 + #include "fusb302_reg.h" 16 + 17 + #define FUSB302_MAX_MSG_LEN 0x1F 18 + 19 + enum toggling_mode { 20 + TOGGLING_MODE_OFF, 21 + TOGGLING_MODE_DRP, 22 + TOGGLING_MODE_SNK, 23 + TOGGLING_MODE_SRC, 24 + }; 25 + 26 + enum src_current_status { 27 + SRC_CURRENT_DEFAULT, 28 + SRC_CURRENT_MEDIUM, 29 + SRC_CURRENT_HIGH, 30 + }; 31 + 32 + static const u8 ra_mda_value[] = { 33 + [SRC_CURRENT_DEFAULT] = 4, /* 210mV */ 34 + [SRC_CURRENT_MEDIUM] = 9, /* 420mV */ 35 + [SRC_CURRENT_HIGH] = 18, /* 798mV */ 36 + }; 37 + 38 + static const u8 rd_mda_value[] = { 39 + [SRC_CURRENT_DEFAULT] = 38, /* 1638mV */ 40 + [SRC_CURRENT_MEDIUM] = 38, /* 1638mV */ 41 + [SRC_CURRENT_HIGH] = 61, /* 2604mV */ 42 + }; 43 + 44 + struct fusb302_chip { 45 + enum toggling_mode toggling_mode; 46 + enum src_current_status src_current_status; 47 + bool intr_togdone; 48 + bool intr_bc_lvl; 49 + bool intr_comp_chng; 50 + 51 + /* port status */ 52 + bool vconn_on; 53 + bool vbus_present; 54 + enum typec_cc_polarity cc_polarity; 55 + enum typec_cc_status cc1; 56 + enum typec_cc_status cc2; 57 + }; 58 + 59 + static int fusb302_i2c_write(struct udevice *dev, u8 address, u8 data) 60 + { 61 + int ret; 62 + 63 + ret = dm_i2c_write(dev, address, &data, 1); 64 + if (ret) 65 + dev_err(dev, "cannot write 0x%02x to 0x%02x, ret=%d\n", 66 + data, address, ret); 67 + 68 + return ret; 69 + } 70 + 71 + static int fusb302_i2c_block_write(struct udevice *dev, u8 address, 72 + u8 length, const u8 *data) 73 + { 74 + int ret; 75 + 76 + if (!length) 77 + return 0; 78 + 79 + ret = dm_i2c_write(dev, address, data, length); 80 + if (ret) 81 + dev_err(dev, "cannot block write 0x%02x, len=%d, ret=%d\n", 82 + address, length, ret); 83 + 84 + return ret; 85 + } 86 + 87 + static int fusb302_i2c_read(struct udevice *dev, u8 address, u8 *data) 88 + { 89 + int ret, retries; 90 + 91 + for (retries = 0; retries < 3; retries++) { 92 + ret = dm_i2c_read(dev, address, data, 1); 93 + if (ret == 0) 94 + return ret; 95 + dev_err(dev, "cannot read %02x, ret=%d\n", address, ret); 96 + } 97 + 98 + return ret; 99 + } 100 + 101 + static int fusb302_i2c_block_read(struct udevice *dev, u8 address, 102 + u8 length, u8 *data) 103 + { 104 + int ret; 105 + 106 + if (!length) 107 + return 0; 108 + 109 + ret = dm_i2c_read(dev, address, data, length); 110 + if (ret) 111 + dev_err(dev, "cannot block read 0x%02x, len=%d, ret=%d\n", 112 + address, length, ret); 113 + return ret; 114 + } 115 + 116 + static int fusb302_i2c_mask_write(struct udevice *dev, u8 address, 117 + u8 mask, u8 value) 118 + { 119 + int ret; 120 + u8 data; 121 + 122 + ret = fusb302_i2c_read(dev, address, &data); 123 + if (ret) 124 + return ret; 125 + data &= ~mask; 126 + data |= value; 127 + ret = fusb302_i2c_write(dev, address, data); 128 + if (ret) 129 + return ret; 130 + 131 + return ret; 132 + } 133 + 134 + static int fusb302_i2c_set_bits(struct udevice *dev, u8 address, u8 set_bits) 135 + { 136 + return fusb302_i2c_mask_write(dev, address, 0x00, set_bits); 137 + } 138 + 139 + static int fusb302_i2c_clear_bits(struct udevice *dev, u8 address, u8 clear_bits) 140 + { 141 + return fusb302_i2c_mask_write(dev, address, clear_bits, 0x00); 142 + } 143 + 144 + static int fusb302_sw_reset(struct udevice *dev) 145 + { 146 + int ret = fusb302_i2c_write(dev, FUSB_REG_RESET, FUSB_REG_RESET_SW_RESET); 147 + 148 + if (ret) 149 + dev_err(dev, "cannot sw reset the fusb302: %d\n", ret); 150 + 151 + return ret; 152 + } 153 + 154 + static int fusb302_enable_tx_auto_retries(struct udevice *dev, u8 retry_count) 155 + { 156 + int ret; 157 + 158 + ret = fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL3, retry_count | 159 + FUSB_REG_CONTROL3_AUTO_RETRY); 160 + 161 + return ret; 162 + } 163 + 164 + /* 165 + * mask all interrupt on the chip 166 + */ 167 + static int fusb302_mask_interrupt(struct udevice *dev) 168 + { 169 + int ret; 170 + 171 + ret = fusb302_i2c_write(dev, FUSB_REG_MASK, 0xFF); 172 + if (ret) 173 + return ret; 174 + ret = fusb302_i2c_write(dev, FUSB_REG_MASKA, 0xFF); 175 + if (ret) 176 + return ret; 177 + ret = fusb302_i2c_write(dev, FUSB_REG_MASKB, 0xFF); 178 + if (ret) 179 + return ret; 180 + ret = fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL0, 181 + FUSB_REG_CONTROL0_INT_MASK); 182 + return ret; 183 + } 184 + 185 + /* 186 + * initialize interrupt on the chip 187 + * - unmasked interrupt: VBUS_OK 188 + */ 189 + static int fusb302_init_interrupt(struct udevice *dev) 190 + { 191 + int ret; 192 + 193 + ret = fusb302_i2c_write(dev, FUSB_REG_MASK, 194 + 0xFF & ~FUSB_REG_MASK_VBUSOK); 195 + if (ret) 196 + return ret; 197 + ret = fusb302_i2c_write(dev, FUSB_REG_MASKA, 0xFF); 198 + if (ret) 199 + return ret; 200 + ret = fusb302_i2c_write(dev, FUSB_REG_MASKB, 0xFF); 201 + if (ret) 202 + return ret; 203 + ret = fusb302_i2c_clear_bits(dev, FUSB_REG_CONTROL0, 204 + FUSB_REG_CONTROL0_INT_MASK); 205 + return ret; 206 + } 207 + 208 + static int fusb302_set_power_mode(struct udevice *dev, u8 power_mode) 209 + { 210 + int ret; 211 + 212 + ret = fusb302_i2c_write(dev, FUSB_REG_POWER, power_mode); 213 + 214 + return ret; 215 + } 216 + 217 + static int fusb302_init(struct udevice *dev) 218 + { 219 + struct fusb302_chip *chip = dev_get_priv(dev); 220 + int ret; 221 + u8 data; 222 + 223 + ret = fusb302_sw_reset(dev); 224 + if (ret) 225 + return ret; 226 + ret = fusb302_enable_tx_auto_retries(dev, FUSB_REG_CONTROL3_N_RETRIES_3); 227 + if (ret) 228 + return ret; 229 + ret = fusb302_init_interrupt(dev); 230 + if (ret) 231 + return ret; 232 + ret = fusb302_set_power_mode(dev, FUSB_REG_POWER_PWR_ALL); 233 + if (ret) 234 + return ret; 235 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &data); 236 + if (ret) 237 + return ret; 238 + chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK); 239 + ret = fusb302_i2c_read(dev, FUSB_REG_DEVICE_ID, &data); 240 + if (ret) 241 + return ret; 242 + dev_info(dev, "fusb302 device ID: 0x%02x\n", data); 243 + 244 + return ret; 245 + } 246 + 247 + static int fusb302_get_vbus(struct udevice *dev) 248 + { 249 + struct fusb302_chip *chip = dev_get_priv(dev); 250 + 251 + return chip->vbus_present ? 1 : 0; 252 + } 253 + 254 + static int fusb302_set_src_current(struct udevice *dev, 255 + enum src_current_status status) 256 + { 257 + struct fusb302_chip *chip = dev_get_priv(dev); 258 + int ret; 259 + 260 + chip->src_current_status = status; 261 + switch (status) { 262 + case SRC_CURRENT_DEFAULT: 263 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL0, 264 + FUSB_REG_CONTROL0_HOST_CUR_MASK, 265 + FUSB_REG_CONTROL0_HOST_CUR_DEF); 266 + break; 267 + case SRC_CURRENT_MEDIUM: 268 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL0, 269 + FUSB_REG_CONTROL0_HOST_CUR_MASK, 270 + FUSB_REG_CONTROL0_HOST_CUR_MED); 271 + break; 272 + case SRC_CURRENT_HIGH: 273 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL0, 274 + FUSB_REG_CONTROL0_HOST_CUR_MASK, 275 + FUSB_REG_CONTROL0_HOST_CUR_HIGH); 276 + break; 277 + default: 278 + ret = -EINVAL; 279 + break; 280 + } 281 + 282 + return ret; 283 + } 284 + 285 + static int fusb302_set_toggling(struct udevice *dev, 286 + enum toggling_mode mode) 287 + { 288 + struct fusb302_chip *chip = dev_get_priv(dev); 289 + int ret; 290 + 291 + /* first disable toggling */ 292 + ret = fusb302_i2c_clear_bits(dev, FUSB_REG_CONTROL2, 293 + FUSB_REG_CONTROL2_TOGGLE); 294 + if (ret) 295 + return ret; 296 + /* mask interrupts for SRC or SNK */ 297 + ret = fusb302_i2c_set_bits(dev, FUSB_REG_MASK, 298 + FUSB_REG_MASK_BC_LVL | 299 + FUSB_REG_MASK_COMP_CHNG); 300 + if (ret) 301 + return ret; 302 + chip->intr_bc_lvl = false; 303 + chip->intr_comp_chng = false; 304 + /* configure toggling mode: none/snk/src/drp */ 305 + switch (mode) { 306 + case TOGGLING_MODE_OFF: 307 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL2, 308 + FUSB_REG_CONTROL2_MODE_MASK, 309 + FUSB_REG_CONTROL2_MODE_NONE); 310 + break; 311 + case TOGGLING_MODE_SNK: 312 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL2, 313 + FUSB_REG_CONTROL2_MODE_MASK, 314 + FUSB_REG_CONTROL2_MODE_UFP); 315 + break; 316 + case TOGGLING_MODE_SRC: 317 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL2, 318 + FUSB_REG_CONTROL2_MODE_MASK, 319 + FUSB_REG_CONTROL2_MODE_DFP); 320 + break; 321 + case TOGGLING_MODE_DRP: 322 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_CONTROL2, 323 + FUSB_REG_CONTROL2_MODE_MASK, 324 + FUSB_REG_CONTROL2_MODE_DRP); 325 + break; 326 + default: 327 + break; 328 + } 329 + 330 + if (ret) 331 + return ret; 332 + 333 + if (mode == TOGGLING_MODE_OFF) { 334 + /* mask TOGDONE interrupt */ 335 + ret = fusb302_i2c_set_bits(dev, FUSB_REG_MASKA, 336 + FUSB_REG_MASKA_TOGDONE); 337 + if (ret) 338 + return ret; 339 + chip->intr_togdone = false; 340 + } else { 341 + /* Datasheet says vconn MUST be off when toggling */ 342 + if (chip->vconn_on) 343 + dev_warn(dev, "Vconn is on during toggle start\n"); 344 + /* unmask TOGDONE interrupt */ 345 + ret = fusb302_i2c_clear_bits(dev, FUSB_REG_MASKA, 346 + FUSB_REG_MASKA_TOGDONE); 347 + if (ret) 348 + return ret; 349 + chip->intr_togdone = true; 350 + /* start toggling */ 351 + ret = fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL2, 352 + FUSB_REG_CONTROL2_TOGGLE); 353 + if (ret) 354 + return ret; 355 + /* during toggling, consider cc as Open */ 356 + chip->cc1 = TYPEC_CC_OPEN; 357 + chip->cc2 = TYPEC_CC_OPEN; 358 + } 359 + chip->toggling_mode = mode; 360 + 361 + return ret; 362 + } 363 + 364 + static const enum src_current_status cc_src_current[] = { 365 + [TYPEC_CC_OPEN] = SRC_CURRENT_DEFAULT, 366 + [TYPEC_CC_RA] = SRC_CURRENT_DEFAULT, 367 + [TYPEC_CC_RD] = SRC_CURRENT_DEFAULT, 368 + [TYPEC_CC_RP_DEF] = SRC_CURRENT_DEFAULT, 369 + [TYPEC_CC_RP_1_5] = SRC_CURRENT_MEDIUM, 370 + [TYPEC_CC_RP_3_0] = SRC_CURRENT_HIGH, 371 + }; 372 + 373 + static int fusb302_set_cc(struct udevice *dev, enum typec_cc_status cc) 374 + { 375 + struct fusb302_chip *chip = dev_get_priv(dev); 376 + const u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN | 377 + FUSB_REG_SWITCHES0_CC2_PU_EN | 378 + FUSB_REG_SWITCHES0_CC1_PD_EN | 379 + FUSB_REG_SWITCHES0_CC2_PD_EN; 380 + u8 rd_mda, switches0_data = 0x00; 381 + int ret; 382 + 383 + switch (cc) { 384 + case TYPEC_CC_OPEN: 385 + break; 386 + case TYPEC_CC_RD: 387 + switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN | 388 + FUSB_REG_SWITCHES0_CC2_PD_EN; 389 + break; 390 + case TYPEC_CC_RP_DEF: 391 + case TYPEC_CC_RP_1_5: 392 + case TYPEC_CC_RP_3_0: 393 + switches0_data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? 394 + FUSB_REG_SWITCHES0_CC1_PU_EN : 395 + FUSB_REG_SWITCHES0_CC2_PU_EN; 396 + break; 397 + default: 398 + dev_err(dev, "unsupported CC value: %s\n", 399 + typec_cc_status_name[cc]); 400 + ret = -EINVAL; 401 + goto done; 402 + } 403 + 404 + ret = fusb302_set_toggling(dev, TOGGLING_MODE_OFF); 405 + if (ret) { 406 + dev_err(dev, "cannot set toggling mode: %d\n", ret); 407 + goto done; 408 + } 409 + 410 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_SWITCHES0, 411 + switches0_mask, switches0_data); 412 + if (ret) { 413 + dev_err(dev, "cannot set pull-up/-down: %d\n", ret); 414 + goto done; 415 + } 416 + /* reset the cc status */ 417 + chip->cc1 = TYPEC_CC_OPEN; 418 + chip->cc2 = TYPEC_CC_OPEN; 419 + 420 + /* adjust current for SRC */ 421 + ret = fusb302_set_src_current(dev, cc_src_current[cc]); 422 + if (ret) { 423 + dev_err(dev, "cannot set src current %s: %d\n", 424 + typec_cc_status_name[cc], ret); 425 + goto done; 426 + } 427 + 428 + /* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */ 429 + switch (cc) { 430 + case TYPEC_CC_RP_DEF: 431 + case TYPEC_CC_RP_1_5: 432 + case TYPEC_CC_RP_3_0: 433 + rd_mda = rd_mda_value[cc_src_current[cc]]; 434 + ret = fusb302_i2c_write(dev, FUSB_REG_MEASURE, rd_mda); 435 + if (ret) { 436 + dev_err(dev, "cannot set SRC measure value: %d\n", ret); 437 + goto done; 438 + } 439 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_MASK, 440 + FUSB_REG_MASK_BC_LVL | 441 + FUSB_REG_MASK_COMP_CHNG, 442 + FUSB_REG_MASK_BC_LVL); 443 + if (ret) { 444 + dev_err(dev, "cannot set SRC irq: %d\n", ret); 445 + goto done; 446 + } 447 + chip->intr_comp_chng = true; 448 + break; 449 + case TYPEC_CC_RD: 450 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_MASK, 451 + FUSB_REG_MASK_BC_LVL | 452 + FUSB_REG_MASK_COMP_CHNG, 453 + FUSB_REG_MASK_COMP_CHNG); 454 + if (ret) { 455 + dev_err(dev, "cannot set SRC irq: %d\n", ret); 456 + goto done; 457 + } 458 + chip->intr_bc_lvl = true; 459 + break; 460 + default: 461 + break; 462 + } 463 + done: 464 + return ret; 465 + } 466 + 467 + static int fusb302_get_cc(struct udevice *dev, enum typec_cc_status *cc1, 468 + enum typec_cc_status *cc2) 469 + { 470 + struct fusb302_chip *chip = dev_get_priv(dev); 471 + 472 + *cc1 = chip->cc1; 473 + *cc2 = chip->cc2; 474 + dev_dbg(dev, "get cc1 = %s, cc2 = %s\n", typec_cc_status_name[*cc1], 475 + typec_cc_status_name[*cc2]); 476 + 477 + return 0; 478 + } 479 + 480 + static int fusb302_set_vconn(struct udevice *dev, bool on) 481 + { 482 + struct fusb302_chip *chip = dev_get_priv(dev); 483 + int ret; 484 + u8 switches0_data = 0x00; 485 + u8 switches0_mask = FUSB_REG_SWITCHES0_VCONN_CC1 | 486 + FUSB_REG_SWITCHES0_VCONN_CC2; 487 + 488 + if (chip->vconn_on == on) { 489 + ret = 0; 490 + dev_dbg(dev, "vconn is already %s\n", on ? "on" : "off"); 491 + goto done; 492 + } 493 + if (on) { 494 + switches0_data = (chip->cc_polarity == TYPEC_POLARITY_CC1) ? 495 + FUSB_REG_SWITCHES0_VCONN_CC2 : 496 + FUSB_REG_SWITCHES0_VCONN_CC1; 497 + } 498 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_SWITCHES0, 499 + switches0_mask, switches0_data); 500 + if (ret) 501 + goto done; 502 + dev_dbg(dev, "set vconn = %s\n", on ? "on" : "off"); 503 + done: 504 + return ret; 505 + } 506 + 507 + static int fusb302_set_vbus(struct udevice *dev, bool on, bool charge) 508 + { 509 + return 0; 510 + } 511 + 512 + static int fusb302_pd_tx_flush(struct udevice *dev) 513 + { 514 + return fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL0, 515 + FUSB_REG_CONTROL0_TX_FLUSH); 516 + } 517 + 518 + static int fusb302_pd_rx_flush(struct udevice *dev) 519 + { 520 + return fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL1, 521 + FUSB_REG_CONTROL1_RX_FLUSH); 522 + } 523 + 524 + static int fusb302_pd_set_auto_goodcrc(struct udevice *dev, bool on) 525 + { 526 + if (on) 527 + return fusb302_i2c_set_bits(dev, FUSB_REG_SWITCHES1, 528 + FUSB_REG_SWITCHES1_AUTO_GCRC); 529 + return fusb302_i2c_clear_bits(dev, FUSB_REG_SWITCHES1, 530 + FUSB_REG_SWITCHES1_AUTO_GCRC); 531 + } 532 + 533 + static int fusb302_pd_set_interrupts(struct udevice *dev, bool on) 534 + { 535 + int ret; 536 + u8 mask_interrupts = FUSB_REG_MASK_COLLISION; 537 + u8 maska_interrupts = FUSB_REG_MASKA_RETRYFAIL | 538 + FUSB_REG_MASKA_HARDSENT | 539 + FUSB_REG_MASKA_TX_SUCCESS | 540 + FUSB_REG_MASKA_HARDRESET; 541 + u8 maskb_interrupts = FUSB_REG_MASKB_GCRCSENT; 542 + 543 + ret = on ? 544 + fusb302_i2c_clear_bits(dev, FUSB_REG_MASK, mask_interrupts) : 545 + fusb302_i2c_set_bits(dev, FUSB_REG_MASK, mask_interrupts); 546 + if (ret) 547 + return ret; 548 + ret = on ? 549 + fusb302_i2c_clear_bits(dev, FUSB_REG_MASKA, maska_interrupts) : 550 + fusb302_i2c_set_bits(dev, FUSB_REG_MASKA, maska_interrupts); 551 + if (ret) 552 + return ret; 553 + ret = on ? 554 + fusb302_i2c_clear_bits(dev, FUSB_REG_MASKB, maskb_interrupts) : 555 + fusb302_i2c_set_bits(dev, FUSB_REG_MASKB, maskb_interrupts); 556 + return ret; 557 + } 558 + 559 + static int fusb302_set_pd_rx(struct udevice *dev, bool on) 560 + { 561 + int ret; 562 + 563 + ret = fusb302_pd_rx_flush(dev); 564 + if (ret) { 565 + dev_err(dev, "cannot flush pd rx buffer: %d\n", ret); 566 + goto done; 567 + } 568 + ret = fusb302_pd_tx_flush(dev); 569 + if (ret) { 570 + dev_err(dev, "cannot flush pd tx buffer: %d\n", ret); 571 + goto done; 572 + } 573 + ret = fusb302_pd_set_auto_goodcrc(dev, on); 574 + if (ret) { 575 + dev_err(dev, "cannot turn %s auto GoodCRC: %d\n", 576 + on ? "on" : "off", ret); 577 + goto done; 578 + } 579 + ret = fusb302_pd_set_interrupts(dev, on); 580 + if (ret) { 581 + dev_err(dev, "cannot turn %s pd interrupts: %d\n", 582 + on ? "on" : "off", ret); 583 + goto done; 584 + } 585 + dev_dbg(dev, "set pd RX %s\n", on ? "on" : "off"); 586 + done: 587 + return ret; 588 + } 589 + 590 + static int fusb302_set_roles(struct udevice *dev, bool attached, 591 + enum typec_role pwr, enum typec_data_role data) 592 + { 593 + int ret; 594 + u8 switches1_mask = FUSB_REG_SWITCHES1_POWERROLE | 595 + FUSB_REG_SWITCHES1_DATAROLE; 596 + u8 switches1_data = 0x00; 597 + 598 + if (pwr == TYPEC_SOURCE) 599 + switches1_data |= FUSB_REG_SWITCHES1_POWERROLE; 600 + if (data == TYPEC_HOST) 601 + switches1_data |= FUSB_REG_SWITCHES1_DATAROLE; 602 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_SWITCHES1, 603 + switches1_mask, switches1_data); 604 + if (ret) { 605 + dev_err(dev, "unable to set pd header %s, %s, ret=%d\n", 606 + typec_role_name[pwr], typec_data_role_name[data], ret); 607 + goto done; 608 + } 609 + dev_dbg(dev, "pd header : %s, %s\n", typec_role_name[pwr], 610 + typec_data_role_name[data]); 611 + done: 612 + 613 + return ret; 614 + } 615 + 616 + static int fusb302_start_toggling(struct udevice *dev, 617 + enum typec_port_type port_type, 618 + enum typec_cc_status cc) 619 + { 620 + enum toggling_mode mode = TOGGLING_MODE_OFF; 621 + int ret; 622 + 623 + switch (port_type) { 624 + case TYPEC_PORT_SRC: 625 + mode = TOGGLING_MODE_SRC; 626 + break; 627 + case TYPEC_PORT_SNK: 628 + mode = TOGGLING_MODE_SNK; 629 + break; 630 + case TYPEC_PORT_DRP: 631 + mode = TOGGLING_MODE_DRP; 632 + break; 633 + } 634 + 635 + ret = fusb302_set_src_current(dev, cc_src_current[cc]); 636 + if (ret) { 637 + dev_err(dev, "unable to set src current %s, ret=%d", 638 + typec_cc_status_name[cc], ret); 639 + goto done; 640 + } 641 + ret = fusb302_set_toggling(dev, mode); 642 + if (ret) { 643 + dev_err(dev, "unable to start drp toggling: %d\n", ret); 644 + goto done; 645 + } 646 + dev_info(dev, "fusb302 start drp toggling\n"); 647 + done: 648 + 649 + return ret; 650 + } 651 + 652 + static int fusb302_pd_send_message(struct udevice *dev, 653 + const struct pd_message *msg) 654 + { 655 + int ret; 656 + /* SOP tokens */ 657 + u8 buf[40] = {FUSB302_TKN_SYNC1, FUSB302_TKN_SYNC1, FUSB302_TKN_SYNC1, 658 + FUSB302_TKN_SYNC2}; 659 + u8 pos = 4; 660 + int len; 661 + 662 + len = pd_header_cnt_le(msg->header) * 4; 663 + /* plug 2 for header */ 664 + len += 2; 665 + if (len > FUSB302_MAX_MSG_LEN) { 666 + dev_err(dev, "PD message too long %d (incl. header)", len); 667 + return -EINVAL; 668 + } 669 + /* packsym tells the FUSB302 chip that the next X bytes are payload */ 670 + buf[pos++] = FUSB302_TKN_PACKSYM | (len & FUSB302_MAX_MSG_LEN); 671 + memcpy(&buf[pos], &msg->header, sizeof(msg->header)); 672 + pos += sizeof(msg->header); 673 + 674 + len -= 2; 675 + memcpy(&buf[pos], msg->payload, len); 676 + pos += len; 677 + 678 + /* CRC */ 679 + buf[pos++] = FUSB302_TKN_JAMCRC; 680 + /* EOP */ 681 + buf[pos++] = FUSB302_TKN_EOP; 682 + /* turn tx off after sending message */ 683 + buf[pos++] = FUSB302_TKN_TXOFF; 684 + /* start transmission */ 685 + buf[pos++] = FUSB302_TKN_TXON; 686 + 687 + ret = fusb302_i2c_block_write(dev, FUSB_REG_FIFOS, pos, buf); 688 + if (ret) 689 + return ret; 690 + dev_dbg(dev, "Send PD message (header=0x%x len=%d)\n", msg->header, len); 691 + 692 + return ret; 693 + } 694 + 695 + static int fusb302_pd_send_hardreset(struct udevice *dev) 696 + { 697 + return fusb302_i2c_set_bits(dev, FUSB_REG_CONTROL3, 698 + FUSB_REG_CONTROL3_SEND_HARDRESET); 699 + } 700 + 701 + static const char * const transmit_type_name[] = { 702 + [TCPC_TX_SOP] = "SOP", 703 + [TCPC_TX_SOP_PRIME] = "SOP'", 704 + [TCPC_TX_SOP_PRIME_PRIME] = "SOP''", 705 + [TCPC_TX_SOP_DEBUG_PRIME] = "DEBUG'", 706 + [TCPC_TX_SOP_DEBUG_PRIME_PRIME] = "DEBUG''", 707 + [TCPC_TX_HARD_RESET] = "HARD_RESET", 708 + [TCPC_TX_CABLE_RESET] = "CABLE_RESET", 709 + [TCPC_TX_BIST_MODE_2] = "BIST_MODE_2", 710 + }; 711 + 712 + static int fusb302_pd_transmit(struct udevice *dev, enum tcpm_transmit_type type, 713 + const struct pd_message *msg, unsigned int negotiated_rev) 714 + { 715 + int ret; 716 + 717 + switch (type) { 718 + case TCPC_TX_SOP: 719 + /* nRetryCount 3 in P2.0 spec, whereas 2 in PD3.0 spec */ 720 + ret = fusb302_enable_tx_auto_retries(dev, negotiated_rev > PD_REV20 ? 721 + FUSB_REG_CONTROL3_N_RETRIES_2 : 722 + FUSB_REG_CONTROL3_N_RETRIES_3); 723 + if (ret) 724 + dev_err(dev, "cannot update retry count: %d\n", ret); 725 + 726 + ret = fusb302_pd_send_message(dev, msg); 727 + if (ret) 728 + dev_err(dev, "cannot send PD message: %d\n", ret); 729 + break; 730 + case TCPC_TX_HARD_RESET: 731 + ret = fusb302_pd_send_hardreset(dev); 732 + if (ret) 733 + dev_err(dev, "cannot send hardreset: %d\n", ret); 734 + break; 735 + default: 736 + dev_err(dev, "type %s not supported", transmit_type_name[type]); 737 + ret = -EINVAL; 738 + } 739 + 740 + return ret; 741 + } 742 + 743 + static enum typec_cc_status fusb302_bc_lvl_to_cc(u8 bc_lvl) 744 + { 745 + if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_1230_MAX) 746 + return TYPEC_CC_RP_3_0; 747 + if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_600_1230) 748 + return TYPEC_CC_RP_1_5; 749 + if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_200_600) 750 + return TYPEC_CC_RP_DEF; 751 + return TYPEC_CC_OPEN; 752 + } 753 + 754 + static void fusb302_bc_lvl_handler(struct udevice *dev) 755 + { 756 + struct fusb302_chip *chip = dev_get_priv(dev); 757 + enum typec_cc_status cc_status; 758 + u8 status0, bc_lvl; 759 + int ret; 760 + 761 + if (!chip->intr_bc_lvl) { 762 + dev_err(dev, "BC_LVL interrupt is turned off, abort\n"); 763 + goto done; 764 + } 765 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &status0); 766 + if (ret) 767 + goto done; 768 + 769 + dev_dbg(dev, "BC_LVL handler, status0 = 0x%02x\n", status0); 770 + if (status0 & FUSB_REG_STATUS0_ACTIVITY) 771 + dev_info(dev, "CC activities detected, delay handling\n"); 772 + bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK; 773 + cc_status = fusb302_bc_lvl_to_cc(bc_lvl); 774 + if (chip->cc_polarity == TYPEC_POLARITY_CC1) { 775 + if (chip->cc1 != cc_status) { 776 + dev_dbg(dev, "cc1: %s -> %s\n", 777 + typec_cc_status_name[chip->cc1], 778 + typec_cc_status_name[cc_status]); 779 + chip->cc1 = cc_status; 780 + tcpm_cc_change(dev); 781 + } 782 + } else { 783 + if (chip->cc2 != cc_status) { 784 + dev_dbg(dev, "cc2: %s -> %s\n", 785 + typec_cc_status_name[chip->cc2], 786 + typec_cc_status_name[cc_status]); 787 + chip->cc2 = cc_status; 788 + tcpm_cc_change(dev); 789 + } 790 + } 791 + 792 + done: 793 + return; 794 + } 795 + 796 + static int fusb302_enter_low_power_mode(struct udevice *dev, 797 + bool attached, bool pd_capable) 798 + { 799 + unsigned int reg; 800 + int ret; 801 + 802 + ret = fusb302_mask_interrupt(dev); 803 + if (ret) 804 + return ret; 805 + if (attached && pd_capable) 806 + reg = FUSB_REG_POWER_PWR_MEDIUM; 807 + else if (attached) 808 + reg = FUSB_REG_POWER_PWR_LOW; 809 + else 810 + reg = 0; 811 + 812 + return fusb302_set_power_mode(dev, reg); 813 + } 814 + 815 + static const char * const cc_polarity_name[] = { 816 + [TYPEC_POLARITY_CC1] = "Polarity_CC1", 817 + [TYPEC_POLARITY_CC2] = "Polarity_CC2", 818 + }; 819 + 820 + static int fusb302_set_cc_polarity_and_pull(struct udevice *dev, 821 + enum typec_cc_polarity cc_polarity, 822 + bool pull_up, bool pull_down) 823 + { 824 + struct fusb302_chip *chip = dev_get_priv(dev); 825 + int ret; 826 + u8 switches0_data = 0x00; 827 + u8 switches1_mask = FUSB_REG_SWITCHES1_TXCC1_EN | 828 + FUSB_REG_SWITCHES1_TXCC2_EN; 829 + u8 switches1_data = 0x00; 830 + 831 + if (pull_down) 832 + switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN | 833 + FUSB_REG_SWITCHES0_CC2_PD_EN; 834 + 835 + if (cc_polarity == TYPEC_POLARITY_CC1) { 836 + switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC1; 837 + if (chip->vconn_on) 838 + switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC2; 839 + if (pull_up) 840 + switches0_data |= FUSB_REG_SWITCHES0_CC1_PU_EN; 841 + switches1_data = FUSB_REG_SWITCHES1_TXCC1_EN; 842 + } else { 843 + switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC2; 844 + if (chip->vconn_on) 845 + switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC1; 846 + if (pull_up) 847 + switches0_data |= FUSB_REG_SWITCHES0_CC2_PU_EN; 848 + switches1_data = FUSB_REG_SWITCHES1_TXCC2_EN; 849 + } 850 + ret = fusb302_i2c_write(dev, FUSB_REG_SWITCHES0, switches0_data); 851 + if (ret) 852 + return ret; 853 + ret = fusb302_i2c_mask_write(dev, FUSB_REG_SWITCHES1, 854 + switches1_mask, switches1_data); 855 + if (ret) 856 + return ret; 857 + chip->cc_polarity = cc_polarity; 858 + 859 + return ret; 860 + } 861 + 862 + static int fusb302_handle_togdone_snk(struct udevice *dev, 863 + u8 togdone_result) 864 + { 865 + struct fusb302_chip *chip = dev_get_priv(dev); 866 + int ret; 867 + u8 status0; 868 + u8 bc_lvl; 869 + enum typec_cc_polarity cc_polarity; 870 + enum typec_cc_status cc_status_active, cc1, cc2; 871 + 872 + /* set polarity and pull_up, pull_down */ 873 + cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SNK1) ? 874 + TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; 875 + ret = fusb302_set_cc_polarity_and_pull(dev, cc_polarity, false, true); 876 + if (ret) { 877 + dev_err(dev, "cannot set cc polarity %s, ret = %d\n", 878 + cc_polarity_name[cc_polarity], ret); 879 + return ret; 880 + } 881 + /* fusb302_set_cc_polarity() has set the correct measure block */ 882 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &status0); 883 + if (ret < 0) 884 + return ret; 885 + bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK; 886 + cc_status_active = fusb302_bc_lvl_to_cc(bc_lvl); 887 + /* restart toggling if the cc status on the active line is OPEN */ 888 + if (cc_status_active == TYPEC_CC_OPEN) { 889 + dev_info(dev, "restart toggling as CC_OPEN detected\n"); 890 + ret = fusb302_set_toggling(dev, chip->toggling_mode); 891 + return ret; 892 + } 893 + /* update tcpm with the new cc value */ 894 + cc1 = (cc_polarity == TYPEC_POLARITY_CC1) ? 895 + cc_status_active : TYPEC_CC_OPEN; 896 + cc2 = (cc_polarity == TYPEC_POLARITY_CC2) ? 897 + cc_status_active : TYPEC_CC_OPEN; 898 + if (chip->cc1 != cc1 || chip->cc2 != cc2) { 899 + chip->cc1 = cc1; 900 + chip->cc2 = cc2; 901 + tcpm_cc_change(dev); 902 + } 903 + /* turn off toggling */ 904 + ret = fusb302_set_toggling(dev, TOGGLING_MODE_OFF); 905 + if (ret) { 906 + dev_err(dev, "cannot set toggling mode off, ret=%d\n", ret); 907 + return ret; 908 + } 909 + /* unmask bc_lvl interrupt */ 910 + ret = fusb302_i2c_clear_bits(dev, FUSB_REG_MASK, FUSB_REG_MASK_BC_LVL); 911 + if (ret) { 912 + dev_err(dev, "cannot unmask bc_lcl irq, ret=%d\n", ret); 913 + return ret; 914 + } 915 + chip->intr_bc_lvl = true; 916 + dev_dbg(dev, "detected cc1=%s, cc2=%s\n", 917 + typec_cc_status_name[cc1], 918 + typec_cc_status_name[cc2]); 919 + 920 + return ret; 921 + } 922 + 923 + /* On error returns < 0, otherwise a typec_cc_status value */ 924 + static int fusb302_get_src_cc_status(struct udevice *dev, 925 + enum typec_cc_polarity cc_polarity, 926 + enum typec_cc_status *cc) 927 + { 928 + struct fusb302_chip *chip = dev_get_priv(dev); 929 + u8 ra_mda = ra_mda_value[chip->src_current_status]; 930 + u8 rd_mda = rd_mda_value[chip->src_current_status]; 931 + u8 switches0_data, status0; 932 + int ret; 933 + 934 + /* Step 1: Set switches so that we measure the right CC pin */ 935 + switches0_data = (cc_polarity == TYPEC_POLARITY_CC1) ? 936 + FUSB_REG_SWITCHES0_CC1_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC1 : 937 + FUSB_REG_SWITCHES0_CC2_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC2; 938 + ret = fusb302_i2c_write(dev, FUSB_REG_SWITCHES0, switches0_data); 939 + if (ret < 0) 940 + return ret; 941 + 942 + fusb302_i2c_read(dev, FUSB_REG_SWITCHES0, &status0); 943 + dev_dbg(dev, "get_src_cc_status switches: 0x%0x", status0); 944 + 945 + /* Step 2: Set compararator volt to differentiate between Open and Rd */ 946 + ret = fusb302_i2c_write(dev, FUSB_REG_MEASURE, rd_mda); 947 + if (ret) 948 + return ret; 949 + 950 + udelay(100); 951 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &status0); 952 + if (ret) 953 + return ret; 954 + 955 + dev_dbg(dev, "get_src_cc_status rd_mda status0: 0x%0x", status0); 956 + if (status0 & FUSB_REG_STATUS0_COMP) { 957 + *cc = TYPEC_CC_OPEN; 958 + return 0; 959 + } 960 + 961 + /* Step 3: Set compararator input to differentiate between Rd and Ra. */ 962 + ret = fusb302_i2c_write(dev, FUSB_REG_MEASURE, ra_mda); 963 + if (ret) 964 + return ret; 965 + 966 + udelay(100); 967 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &status0); 968 + if (ret) 969 + return ret; 970 + 971 + dev_dbg(dev, "get_src_cc_status ra_mda status0: 0x%0x", status0); 972 + if (status0 & FUSB_REG_STATUS0_COMP) 973 + *cc = TYPEC_CC_RD; 974 + else 975 + *cc = TYPEC_CC_RA; 976 + 977 + return 0; 978 + } 979 + 980 + static int fusb302_handle_togdone_src(struct udevice *dev, 981 + u8 togdone_result) 982 + { 983 + /* 984 + * - set polarity (measure cc, vconn, tx) 985 + * - set pull_up, pull_down 986 + * - set cc1, cc2, and update to tcpm state machine 987 + * - set I_COMP interrupt on 988 + */ 989 + struct fusb302_chip *chip = dev_get_priv(dev); 990 + u8 rd_mda = rd_mda_value[chip->src_current_status]; 991 + enum toggling_mode toggling_mode = chip->toggling_mode; 992 + enum typec_cc_polarity cc_polarity; 993 + enum typec_cc_status cc1, cc2; 994 + int ret; 995 + 996 + /* 997 + * The toggle-engine will stop in a src state if it sees either Ra or 998 + * Rd. Determine the status for both CC pins, starting with the one 999 + * where toggling stopped, as that is where the switches point now. 1000 + */ 1001 + if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) 1002 + ret = fusb302_get_src_cc_status(dev, TYPEC_POLARITY_CC1, &cc1); 1003 + else 1004 + ret = fusb302_get_src_cc_status(dev, TYPEC_POLARITY_CC2, &cc2); 1005 + if (ret) 1006 + return ret; 1007 + /* we must turn off toggling before we can measure the other pin */ 1008 + ret = fusb302_set_toggling(dev, TOGGLING_MODE_OFF); 1009 + if (ret) { 1010 + dev_err(dev, "cannot set toggling mode off, ret=%d\n", ret); 1011 + return ret; 1012 + } 1013 + /* get the status of the other pin */ 1014 + if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) 1015 + ret = fusb302_get_src_cc_status(dev, TYPEC_POLARITY_CC2, &cc2); 1016 + else 1017 + ret = fusb302_get_src_cc_status(dev, TYPEC_POLARITY_CC1, &cc1); 1018 + if (ret) 1019 + return ret; 1020 + 1021 + /* determine polarity based on the status of both pins */ 1022 + if (cc1 == TYPEC_CC_RD && (cc2 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_RA)) { 1023 + cc_polarity = TYPEC_POLARITY_CC1; 1024 + } else if (cc2 == TYPEC_CC_RD && 1025 + (cc1 == TYPEC_CC_OPEN || cc1 == TYPEC_CC_RA)) { 1026 + cc_polarity = TYPEC_POLARITY_CC2; 1027 + } else { 1028 + dev_err(dev, "unexpected CC status cc1=%s, cc2=%s, restarting toggling\n", 1029 + typec_cc_status_name[cc1], 1030 + typec_cc_status_name[cc2]); 1031 + return fusb302_set_toggling(dev, toggling_mode); 1032 + } 1033 + /* set polarity and pull_up, pull_down */ 1034 + ret = fusb302_set_cc_polarity_and_pull(dev, cc_polarity, true, false); 1035 + if (ret < 0) { 1036 + dev_err(dev, "cannot set cc polarity %s, ret=%d\n", 1037 + cc_polarity_name[cc_polarity], ret); 1038 + return ret; 1039 + } 1040 + /* update tcpm with the new cc value */ 1041 + if (chip->cc1 != cc1 || chip->cc2 != cc2) { 1042 + chip->cc1 = cc1; 1043 + chip->cc2 = cc2; 1044 + tcpm_cc_change(dev); 1045 + } 1046 + /* set MDAC to Rd threshold, and unmask I_COMP for unplug detection */ 1047 + ret = fusb302_i2c_write(dev, FUSB_REG_MEASURE, rd_mda); 1048 + if (ret) 1049 + return ret; 1050 + /* unmask comp_chng interrupt */ 1051 + ret = fusb302_i2c_clear_bits(dev, FUSB_REG_MASK, 1052 + FUSB_REG_MASK_COMP_CHNG); 1053 + if (ret) { 1054 + dev_err(dev, "cannot unmask comp_chng irq, ret=%d\n", ret); 1055 + return ret; 1056 + } 1057 + chip->intr_comp_chng = true; 1058 + dev_dbg(dev, "detected cc1=%s, cc2=%s\n", 1059 + typec_cc_status_name[cc1], 1060 + typec_cc_status_name[cc2]); 1061 + 1062 + return ret; 1063 + } 1064 + 1065 + static int fusb302_handle_togdone(struct udevice *dev) 1066 + { 1067 + struct fusb302_chip *chip = dev_get_priv(dev); 1068 + u8 togdone_result, status1a; 1069 + int ret; 1070 + 1071 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS1A, &status1a); 1072 + if (ret < 0) 1073 + return ret; 1074 + togdone_result = (status1a >> FUSB_REG_STATUS1A_TOGSS_POS) & 1075 + FUSB_REG_STATUS1A_TOGSS_MASK; 1076 + switch (togdone_result) { 1077 + case FUSB_REG_STATUS1A_TOGSS_SNK1: 1078 + case FUSB_REG_STATUS1A_TOGSS_SNK2: 1079 + return fusb302_handle_togdone_snk(dev, togdone_result); 1080 + case FUSB_REG_STATUS1A_TOGSS_SRC1: 1081 + case FUSB_REG_STATUS1A_TOGSS_SRC2: 1082 + return fusb302_handle_togdone_src(dev, togdone_result); 1083 + case FUSB_REG_STATUS1A_TOGSS_AA: 1084 + /* doesn't support */ 1085 + dev_err(dev, "AudioAccessory not supported\n"); 1086 + fusb302_set_toggling(dev, chip->toggling_mode); 1087 + break; 1088 + default: 1089 + dev_err(dev, "TOGDONE with an invalid state: %d\n", 1090 + togdone_result); 1091 + fusb302_set_toggling(dev, chip->toggling_mode); 1092 + break; 1093 + } 1094 + return ret; 1095 + } 1096 + 1097 + static int fusb302_pd_reset(struct udevice *dev) 1098 + { 1099 + return fusb302_i2c_set_bits(dev, FUSB_REG_RESET, 1100 + FUSB_REG_RESET_PD_RESET); 1101 + } 1102 + 1103 + static int fusb302_pd_read_message(struct udevice *dev, 1104 + struct pd_message *msg) 1105 + { 1106 + int len, ret; 1107 + u8 crc[4]; 1108 + u8 token; 1109 + 1110 + /* first SOP token */ 1111 + ret = fusb302_i2c_read(dev, FUSB_REG_FIFOS, &token); 1112 + if (ret) 1113 + return ret; 1114 + ret = fusb302_i2c_block_read(dev, FUSB_REG_FIFOS, 2, 1115 + (u8 *)&msg->header); 1116 + if (ret) 1117 + return ret; 1118 + len = pd_header_cnt_le(msg->header) * 4; 1119 + /* add 4 to length to include the CRC */ 1120 + if (len > PD_MAX_PAYLOAD * 4) { 1121 + dev_err(dev, "PD message too long %d\n", len); 1122 + return -EINVAL; 1123 + } 1124 + if (len > 0) { 1125 + ret = fusb302_i2c_block_read(dev, FUSB_REG_FIFOS, len, 1126 + (u8 *)msg->payload); 1127 + if (ret) 1128 + return ret; 1129 + } 1130 + /* another 4 bytes to read CRC out */ 1131 + ret = fusb302_i2c_block_read(dev, FUSB_REG_FIFOS, 4, crc); 1132 + if (ret) 1133 + return ret; 1134 + dev_dbg(dev, "Received PD message (header=0x%x len=%d)\n", msg->header, len); 1135 + 1136 + /* 1137 + * Check if we've read off a GoodCRC message. If so then indicate to 1138 + * TCPM that the previous transmission has completed. Otherwise we pass 1139 + * the received message over to TCPM for processing. 1140 + * 1141 + * We make this check here instead of basing the reporting decision on 1142 + * the IRQ event type, as it's possible for the chip to report the 1143 + * TX_SUCCESS and GCRCSENT events out of order on occasion, so we need 1144 + * to check the message type to ensure correct reporting to TCPM. 1145 + */ 1146 + if (!len && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC)) 1147 + tcpm_pd_transmit_complete(dev, TCPC_TX_SUCCESS); 1148 + else 1149 + tcpm_pd_receive(dev, msg); 1150 + 1151 + return ret; 1152 + } 1153 + 1154 + static void fusb302_interrupt_handle(struct udevice *dev) 1155 + { 1156 + struct fusb302_chip *chip = dev_get_priv(dev); 1157 + u8 interrupt; 1158 + u8 interrupta; 1159 + u8 interruptb; 1160 + u8 status0; 1161 + bool vbus_present; 1162 + bool comp_result; 1163 + bool intr_togdone; 1164 + bool intr_bc_lvl; 1165 + bool intr_comp_chng; 1166 + struct pd_message pd_msg; 1167 + int ret; 1168 + 1169 + /* grab a snapshot of intr flags */ 1170 + intr_togdone = chip->intr_togdone; 1171 + intr_bc_lvl = chip->intr_bc_lvl; 1172 + intr_comp_chng = chip->intr_comp_chng; 1173 + 1174 + ret = fusb302_i2c_read(dev, FUSB_REG_INTERRUPT, &interrupt); 1175 + if (ret) 1176 + return; 1177 + ret = fusb302_i2c_read(dev, FUSB_REG_INTERRUPTA, &interrupta); 1178 + if (ret) 1179 + return; 1180 + ret = fusb302_i2c_read(dev, FUSB_REG_INTERRUPTB, &interruptb); 1181 + if (ret) 1182 + return; 1183 + ret = fusb302_i2c_read(dev, FUSB_REG_STATUS0, &status0); 1184 + if (ret) 1185 + return; 1186 + 1187 + /* 1188 + * Since we are polling the IRQs, avoid printing messages when there 1189 + * no interrupts at all to avoid spamming the log. 1190 + */ 1191 + if (interrupt != 0 || interrupta != 0 || interruptb != 0) 1192 + dev_dbg(dev, "IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x\n", 1193 + interrupt, interrupta, interruptb, status0); 1194 + 1195 + if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) { 1196 + vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK); 1197 + dev_dbg(dev, "IRQ: VBUS_OK, vbus=%s\n", 1198 + vbus_present ? "On" : "Off"); 1199 + if (vbus_present != chip->vbus_present) { 1200 + chip->vbus_present = vbus_present; 1201 + tcpm_vbus_change(dev); 1202 + } 1203 + } 1204 + 1205 + if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) { 1206 + dev_dbg(dev, "IRQ: TOGDONE\n"); 1207 + ret = fusb302_handle_togdone(dev); 1208 + if (ret) { 1209 + dev_err(dev, "handle togdone error: %d\n", ret); 1210 + return; 1211 + } 1212 + } 1213 + 1214 + if ((interrupt & FUSB_REG_INTERRUPT_BC_LVL) && intr_bc_lvl) { 1215 + dev_dbg(dev, "IRQ: BC_LVL, handler pending\n"); 1216 + fusb302_bc_lvl_handler(dev); 1217 + } 1218 + 1219 + if ((interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) && intr_comp_chng) { 1220 + comp_result = !!(status0 & FUSB_REG_STATUS0_COMP); 1221 + dev_dbg(dev, "IRQ: COMP_CHNG, comp=%s\n", 1222 + comp_result ? "true" : "false"); 1223 + if (comp_result) { 1224 + /* cc level > Rd_threshold, detach */ 1225 + chip->cc1 = TYPEC_CC_OPEN; 1226 + chip->cc2 = TYPEC_CC_OPEN; 1227 + tcpm_cc_change(dev); 1228 + } 1229 + } 1230 + 1231 + if (interrupt & FUSB_REG_INTERRUPT_COLLISION) { 1232 + dev_dbg(dev, "IRQ: PD collision\n"); 1233 + tcpm_pd_transmit_complete(dev, TCPC_TX_FAILED); 1234 + } 1235 + 1236 + if (interrupta & FUSB_REG_INTERRUPTA_RETRYFAIL) { 1237 + dev_dbg(dev, "IRQ: PD retry failed\n"); 1238 + tcpm_pd_transmit_complete(dev, TCPC_TX_FAILED); 1239 + } 1240 + 1241 + if (interrupta & FUSB_REG_INTERRUPTA_HARDSENT) { 1242 + dev_dbg(dev, "IRQ: PD hardreset sent\n"); 1243 + ret = fusb302_pd_reset(dev); 1244 + if (ret) { 1245 + dev_err(dev, "cannot PD reset, ret=%d\n", ret); 1246 + return; 1247 + } 1248 + tcpm_pd_transmit_complete(dev, TCPC_TX_SUCCESS); 1249 + } 1250 + 1251 + if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { 1252 + dev_dbg(dev, "IRQ: PD tx success\n"); 1253 + ret = fusb302_pd_read_message(dev, &pd_msg); 1254 + if (ret) { 1255 + dev_err(dev, "cannot read in PD message, ret=%d\n", ret); 1256 + return; 1257 + } 1258 + } 1259 + 1260 + if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) { 1261 + dev_dbg(dev, "IRQ: PD received hardreset\n"); 1262 + ret = fusb302_pd_reset(dev); 1263 + if (ret) { 1264 + dev_err(dev, "cannot PD reset, ret=%d\n", ret); 1265 + return; 1266 + } 1267 + tcpm_pd_hard_reset(dev); 1268 + } 1269 + 1270 + if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) { 1271 + dev_dbg(dev, "IRQ: PD sent good CRC\n"); 1272 + ret = fusb302_pd_read_message(dev, &pd_msg); 1273 + if (ret) { 1274 + dev_err(dev, "cannot read in PD message, ret=%d\n", ret); 1275 + return; 1276 + } 1277 + } 1278 + } 1279 + 1280 + static void fusb302_poll_event(struct udevice *dev) 1281 + { 1282 + fusb302_interrupt_handle(dev); 1283 + } 1284 + 1285 + static int fusb302_get_connector_node(struct udevice *dev, ofnode *connector_node) 1286 + { 1287 + *connector_node = dev_read_subnode(dev, "connector"); 1288 + if (!ofnode_valid(*connector_node)) { 1289 + dev_err(dev, "'connector' node is not found\n"); 1290 + return -ENODEV; 1291 + } 1292 + 1293 + return 0; 1294 + } 1295 + 1296 + static struct dm_tcpm_ops fusb302_ops = { 1297 + .get_connector_node = fusb302_get_connector_node, 1298 + .init = fusb302_init, 1299 + .get_vbus = fusb302_get_vbus, 1300 + .set_cc = fusb302_set_cc, 1301 + .get_cc = fusb302_get_cc, 1302 + .set_vconn = fusb302_set_vconn, 1303 + .set_vbus = fusb302_set_vbus, 1304 + .set_pd_rx = fusb302_set_pd_rx, 1305 + .set_roles = fusb302_set_roles, 1306 + .start_toggling = fusb302_start_toggling, 1307 + .pd_transmit = fusb302_pd_transmit, 1308 + .poll_event = fusb302_poll_event, 1309 + .enter_low_power_mode = fusb302_enter_low_power_mode, 1310 + }; 1311 + 1312 + static const struct udevice_id fusb302_ids[] = { 1313 + { .compatible = "fcs,fusb302" }, 1314 + { } 1315 + }; 1316 + 1317 + U_BOOT_DRIVER(fusb302) = { 1318 + .name = "fusb302", 1319 + .id = UCLASS_TCPM, 1320 + .of_match = fusb302_ids, 1321 + .ops = &fusb302_ops, 1322 + .priv_auto = sizeof(struct fusb302_chip), 1323 + };
+177
drivers/usb/tcpm/fusb302_reg.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright 2016-2017 Google, Inc 4 + * 5 + * Fairchild FUSB302 Type-C Chip Driver 6 + */ 7 + 8 + #ifndef FUSB302_REG_H 9 + #define FUSB302_REG_H 10 + 11 + #define FUSB_REG_DEVICE_ID 0x01 12 + #define FUSB_REG_SWITCHES0 0x02 13 + #define FUSB_REG_SWITCHES0_CC2_PU_EN BIT(7) 14 + #define FUSB_REG_SWITCHES0_CC1_PU_EN BIT(6) 15 + #define FUSB_REG_SWITCHES0_VCONN_CC2 BIT(5) 16 + #define FUSB_REG_SWITCHES0_VCONN_CC1 BIT(4) 17 + #define FUSB_REG_SWITCHES0_MEAS_CC2 BIT(3) 18 + #define FUSB_REG_SWITCHES0_MEAS_CC1 BIT(2) 19 + #define FUSB_REG_SWITCHES0_CC2_PD_EN BIT(1) 20 + #define FUSB_REG_SWITCHES0_CC1_PD_EN BIT(0) 21 + #define FUSB_REG_SWITCHES1 0x03 22 + #define FUSB_REG_SWITCHES1_POWERROLE BIT(7) 23 + #define FUSB_REG_SWITCHES1_SPECREV1 BIT(6) 24 + #define FUSB_REG_SWITCHES1_SPECREV0 BIT(5) 25 + #define FUSB_REG_SWITCHES1_DATAROLE BIT(4) 26 + #define FUSB_REG_SWITCHES1_AUTO_GCRC BIT(2) 27 + #define FUSB_REG_SWITCHES1_TXCC2_EN BIT(1) 28 + #define FUSB_REG_SWITCHES1_TXCC1_EN BIT(0) 29 + #define FUSB_REG_MEASURE 0x04 30 + #define FUSB_REG_MEASURE_MDAC5 BIT(7) 31 + #define FUSB_REG_MEASURE_MDAC4 BIT(6) 32 + #define FUSB_REG_MEASURE_MDAC3 BIT(5) 33 + #define FUSB_REG_MEASURE_MDAC2 BIT(4) 34 + #define FUSB_REG_MEASURE_MDAC1 BIT(3) 35 + #define FUSB_REG_MEASURE_MDAC0 BIT(2) 36 + #define FUSB_REG_MEASURE_VBUS BIT(1) 37 + #define FUSB_REG_MEASURE_XXXX5 BIT(0) 38 + #define FUSB_REG_CONTROL0 0x06 39 + #define FUSB_REG_CONTROL0_TX_FLUSH BIT(6) 40 + #define FUSB_REG_CONTROL0_INT_MASK BIT(5) 41 + #define FUSB_REG_CONTROL0_HOST_CUR_MASK (0xC) 42 + #define FUSB_REG_CONTROL0_HOST_CUR_HIGH (0xC) 43 + #define FUSB_REG_CONTROL0_HOST_CUR_MED (0x8) 44 + #define FUSB_REG_CONTROL0_HOST_CUR_DEF (0x4) 45 + #define FUSB_REG_CONTROL0_TX_START BIT(0) 46 + #define FUSB_REG_CONTROL1 0x07 47 + #define FUSB_REG_CONTROL1_ENSOP2DB BIT(6) 48 + #define FUSB_REG_CONTROL1_ENSOP1DB BIT(5) 49 + #define FUSB_REG_CONTROL1_BIST_MODE2 BIT(4) 50 + #define FUSB_REG_CONTROL1_RX_FLUSH BIT(2) 51 + #define FUSB_REG_CONTROL1_ENSOP2 BIT(1) 52 + #define FUSB_REG_CONTROL1_ENSOP1 BIT(0) 53 + #define FUSB_REG_CONTROL2 0x08 54 + #define FUSB_REG_CONTROL2_MODE BIT(1) 55 + #define FUSB_REG_CONTROL2_MODE_MASK (0x6) 56 + #define FUSB_REG_CONTROL2_MODE_DFP (0x6) 57 + #define FUSB_REG_CONTROL2_MODE_UFP (0x4) 58 + #define FUSB_REG_CONTROL2_MODE_DRP (0x2) 59 + #define FUSB_REG_CONTROL2_MODE_NONE (0x0) 60 + #define FUSB_REG_CONTROL2_TOGGLE BIT(0) 61 + #define FUSB_REG_CONTROL3 0x09 62 + #define FUSB_REG_CONTROL3_SEND_HARDRESET BIT(6) 63 + #define FUSB_REG_CONTROL3_BIST_TMODE BIT(5) /* 302B Only */ 64 + #define FUSB_REG_CONTROL3_AUTO_HARDRESET BIT(4) 65 + #define FUSB_REG_CONTROL3_AUTO_SOFTRESET BIT(3) 66 + #define FUSB_REG_CONTROL3_N_RETRIES BIT(1) 67 + #define FUSB_REG_CONTROL3_N_RETRIES_MASK (0x6) 68 + #define FUSB_REG_CONTROL3_N_RETRIES_3 (0x6) 69 + #define FUSB_REG_CONTROL3_N_RETRIES_2 (0x4) 70 + #define FUSB_REG_CONTROL3_N_RETRIES_1 (0x2) 71 + #define FUSB_REG_CONTROL3_AUTO_RETRY BIT(0) 72 + #define FUSB_REG_MASK 0x0A 73 + #define FUSB_REG_MASK_VBUSOK BIT(7) 74 + #define FUSB_REG_MASK_ACTIVITY BIT(6) 75 + #define FUSB_REG_MASK_COMP_CHNG BIT(5) 76 + #define FUSB_REG_MASK_CRC_CHK BIT(4) 77 + #define FUSB_REG_MASK_ALERT BIT(3) 78 + #define FUSB_REG_MASK_WAKE BIT(2) 79 + #define FUSB_REG_MASK_COLLISION BIT(1) 80 + #define FUSB_REG_MASK_BC_LVL BIT(0) 81 + #define FUSB_REG_POWER 0x0B 82 + #define FUSB_REG_POWER_PWR BIT(0) 83 + #define FUSB_REG_POWER_PWR_LOW 0x1 84 + #define FUSB_REG_POWER_PWR_MEDIUM 0x3 85 + #define FUSB_REG_POWER_PWR_HIGH 0x7 86 + #define FUSB_REG_POWER_PWR_ALL 0xF 87 + #define FUSB_REG_RESET 0x0C 88 + #define FUSB_REG_RESET_PD_RESET BIT(1) 89 + #define FUSB_REG_RESET_SW_RESET BIT(0) 90 + #define FUSB_REG_MASKA 0x0E 91 + #define FUSB_REG_MASKA_OCP_TEMP BIT(7) 92 + #define FUSB_REG_MASKA_TOGDONE BIT(6) 93 + #define FUSB_REG_MASKA_SOFTFAIL BIT(5) 94 + #define FUSB_REG_MASKA_RETRYFAIL BIT(4) 95 + #define FUSB_REG_MASKA_HARDSENT BIT(3) 96 + #define FUSB_REG_MASKA_TX_SUCCESS BIT(2) 97 + #define FUSB_REG_MASKA_SOFTRESET BIT(1) 98 + #define FUSB_REG_MASKA_HARDRESET BIT(0) 99 + #define FUSB_REG_MASKB 0x0F 100 + #define FUSB_REG_MASKB_GCRCSENT BIT(0) 101 + #define FUSB_REG_STATUS0A 0x3C 102 + #define FUSB_REG_STATUS0A_SOFTFAIL BIT(5) 103 + #define FUSB_REG_STATUS0A_RETRYFAIL BIT(4) 104 + #define FUSB_REG_STATUS0A_POWER BIT(2) 105 + #define FUSB_REG_STATUS0A_RX_SOFT_RESET BIT(1) 106 + #define FUSB_REG_STATUS0A_RX_HARD_RESET BIT(0) 107 + #define FUSB_REG_STATUS1A 0x3D 108 + #define FUSB_REG_STATUS1A_TOGSS BIT(3) 109 + #define FUSB_REG_STATUS1A_TOGSS_RUNNING 0x0 110 + #define FUSB_REG_STATUS1A_TOGSS_SRC1 0x1 111 + #define FUSB_REG_STATUS1A_TOGSS_SRC2 0x2 112 + #define FUSB_REG_STATUS1A_TOGSS_SNK1 0x5 113 + #define FUSB_REG_STATUS1A_TOGSS_SNK2 0x6 114 + #define FUSB_REG_STATUS1A_TOGSS_AA 0x7 115 + #define FUSB_REG_STATUS1A_TOGSS_POS (3) 116 + #define FUSB_REG_STATUS1A_TOGSS_MASK (0x7) 117 + #define FUSB_REG_STATUS1A_RXSOP2DB BIT(2) 118 + #define FUSB_REG_STATUS1A_RXSOP1DB BIT(1) 119 + #define FUSB_REG_STATUS1A_RXSOP BIT(0) 120 + #define FUSB_REG_INTERRUPTA 0x3E 121 + #define FUSB_REG_INTERRUPTA_OCP_TEMP BIT(7) 122 + #define FUSB_REG_INTERRUPTA_TOGDONE BIT(6) 123 + #define FUSB_REG_INTERRUPTA_SOFTFAIL BIT(5) 124 + #define FUSB_REG_INTERRUPTA_RETRYFAIL BIT(4) 125 + #define FUSB_REG_INTERRUPTA_HARDSENT BIT(3) 126 + #define FUSB_REG_INTERRUPTA_TX_SUCCESS BIT(2) 127 + #define FUSB_REG_INTERRUPTA_SOFTRESET BIT(1) 128 + #define FUSB_REG_INTERRUPTA_HARDRESET BIT(0) 129 + #define FUSB_REG_INTERRUPTB 0x3F 130 + #define FUSB_REG_INTERRUPTB_GCRCSENT BIT(0) 131 + #define FUSB_REG_STATUS0 0x40 132 + #define FUSB_REG_STATUS0_VBUSOK BIT(7) 133 + #define FUSB_REG_STATUS0_ACTIVITY BIT(6) 134 + #define FUSB_REG_STATUS0_COMP BIT(5) 135 + #define FUSB_REG_STATUS0_CRC_CHK BIT(4) 136 + #define FUSB_REG_STATUS0_ALERT BIT(3) 137 + #define FUSB_REG_STATUS0_WAKE BIT(2) 138 + #define FUSB_REG_STATUS0_BC_LVL_MASK 0x03 139 + #define FUSB_REG_STATUS0_BC_LVL_0_200 0x0 140 + #define FUSB_REG_STATUS0_BC_LVL_200_600 0x1 141 + #define FUSB_REG_STATUS0_BC_LVL_600_1230 0x2 142 + #define FUSB_REG_STATUS0_BC_LVL_1230_MAX 0x3 143 + #define FUSB_REG_STATUS0_BC_LVL1 BIT(1) 144 + #define FUSB_REG_STATUS0_BC_LVL0 BIT(0) 145 + #define FUSB_REG_STATUS1 0x41 146 + #define FUSB_REG_STATUS1_RXSOP2 BIT(7) 147 + #define FUSB_REG_STATUS1_RXSOP1 BIT(6) 148 + #define FUSB_REG_STATUS1_RX_EMPTY BIT(5) 149 + #define FUSB_REG_STATUS1_RX_FULL BIT(4) 150 + #define FUSB_REG_STATUS1_TX_EMPTY BIT(3) 151 + #define FUSB_REG_STATUS1_TX_FULL BIT(2) 152 + #define FUSB_REG_INTERRUPT 0x42 153 + #define FUSB_REG_INTERRUPT_VBUSOK BIT(7) 154 + #define FUSB_REG_INTERRUPT_ACTIVITY BIT(6) 155 + #define FUSB_REG_INTERRUPT_COMP_CHNG BIT(5) 156 + #define FUSB_REG_INTERRUPT_CRC_CHK BIT(4) 157 + #define FUSB_REG_INTERRUPT_ALERT BIT(3) 158 + #define FUSB_REG_INTERRUPT_WAKE BIT(2) 159 + #define FUSB_REG_INTERRUPT_COLLISION BIT(1) 160 + #define FUSB_REG_INTERRUPT_BC_LVL BIT(0) 161 + #define FUSB_REG_FIFOS 0x43 162 + 163 + /* Tokens defined for the FUSB302 TX FIFO */ 164 + enum fusb302_txfifo_tokens { 165 + FUSB302_TKN_TXON = 0xA1, 166 + FUSB302_TKN_SYNC1 = 0x12, 167 + FUSB302_TKN_SYNC2 = 0x13, 168 + FUSB302_TKN_SYNC3 = 0x1B, 169 + FUSB302_TKN_RST1 = 0x15, 170 + FUSB302_TKN_RST2 = 0x16, 171 + FUSB302_TKN_PACKSYM = 0x80, 172 + FUSB302_TKN_JAMCRC = 0xFF, 173 + FUSB302_TKN_EOP = 0x14, 174 + FUSB302_TKN_TXOFF = 0xFE, 175 + }; 176 + 177 + #endif
+173
drivers/usb/tcpm/tcpm-internal.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright 2015-2017 Google, Inc 4 + * Copyright 2024 Collabora 5 + */ 6 + 7 + #ifndef __LINUX_USB_TCPM_INTERNAL_H 8 + #define __LINUX_USB_TCPM_INTERNAL_H 9 + 10 + #define FOREACH_TCPM_STATE(S) \ 11 + S(INVALID_STATE), \ 12 + S(TOGGLING), \ 13 + S(SRC_UNATTACHED), \ 14 + S(SRC_ATTACH_WAIT), \ 15 + S(SRC_ATTACHED), \ 16 + S(SRC_STARTUP), \ 17 + S(SRC_SEND_CAPABILITIES), \ 18 + S(SRC_SEND_CAPABILITIES_TIMEOUT), \ 19 + S(SRC_NEGOTIATE_CAPABILITIES), \ 20 + S(SRC_TRANSITION_SUPPLY), \ 21 + S(SRC_READY), \ 22 + S(SRC_WAIT_NEW_CAPABILITIES), \ 23 + \ 24 + S(SNK_UNATTACHED), \ 25 + S(SNK_ATTACH_WAIT), \ 26 + S(SNK_DEBOUNCED), \ 27 + S(SNK_ATTACHED), \ 28 + S(SNK_STARTUP), \ 29 + S(SNK_DISCOVERY), \ 30 + S(SNK_DISCOVERY_DEBOUNCE), \ 31 + S(SNK_DISCOVERY_DEBOUNCE_DONE), \ 32 + S(SNK_WAIT_CAPABILITIES), \ 33 + S(SNK_NEGOTIATE_CAPABILITIES), \ 34 + S(SNK_TRANSITION_SINK), \ 35 + S(SNK_TRANSITION_SINK_VBUS), \ 36 + S(SNK_READY), \ 37 + \ 38 + S(HARD_RESET_SEND), \ 39 + S(HARD_RESET_START), \ 40 + S(SRC_HARD_RESET_VBUS_OFF), \ 41 + S(SRC_HARD_RESET_VBUS_ON), \ 42 + S(SNK_HARD_RESET_SINK_OFF), \ 43 + S(SNK_HARD_RESET_WAIT_VBUS), \ 44 + S(SNK_HARD_RESET_SINK_ON), \ 45 + \ 46 + S(SOFT_RESET), \ 47 + S(SOFT_RESET_SEND), \ 48 + \ 49 + S(DR_SWAP_ACCEPT), \ 50 + S(DR_SWAP_CHANGE_DR), \ 51 + \ 52 + S(ERROR_RECOVERY), \ 53 + S(PORT_RESET), \ 54 + S(PORT_RESET_WAIT_OFF) 55 + 56 + #define GENERATE_TCPM_ENUM(e) e 57 + #define GENERATE_TCPM_STRING(s) #s 58 + #define TCPM_POLL_EVENT_TIME_OUT 2000 59 + 60 + enum tcpm_state { 61 + FOREACH_TCPM_STATE(GENERATE_TCPM_ENUM) 62 + }; 63 + 64 + enum pd_msg_request { 65 + PD_MSG_NONE = 0, 66 + PD_MSG_CTRL_REJECT, 67 + PD_MSG_CTRL_WAIT, 68 + PD_MSG_CTRL_NOT_SUPP, 69 + PD_MSG_DATA_SINK_CAP, 70 + PD_MSG_DATA_SOURCE_CAP, 71 + }; 72 + 73 + struct tcpm_port { 74 + enum typec_port_type typec_type; 75 + int typec_prefer_role; 76 + 77 + enum typec_role vconn_role; 78 + enum typec_role pwr_role; 79 + enum typec_data_role data_role; 80 + 81 + struct typec_partner *partner; 82 + 83 + enum typec_cc_status cc_req; 84 + enum typec_cc_status cc1; 85 + enum typec_cc_status cc2; 86 + enum typec_cc_polarity polarity; 87 + 88 + bool attached; 89 + bool connected; 90 + int poll_event_cnt; 91 + enum typec_port_type port_type; 92 + 93 + /* 94 + * Set to true when vbus is greater than VSAFE5V min. 95 + * Set to false when vbus falls below vSinkDisconnect max threshold. 96 + */ 97 + bool vbus_present; 98 + 99 + /* 100 + * Set to true when vbus is less than VSAFE0V max. 101 + * Set to false when vbus is greater than VSAFE0V max. 102 + */ 103 + bool vbus_vsafe0v; 104 + 105 + bool vbus_never_low; 106 + bool vbus_source; 107 + bool vbus_charge; 108 + 109 + int try_role; 110 + 111 + enum pd_msg_request queued_message; 112 + 113 + enum tcpm_state enter_state; 114 + enum tcpm_state prev_state; 115 + enum tcpm_state state; 116 + enum tcpm_state delayed_state; 117 + unsigned long delay_ms; 118 + 119 + bool state_machine_running; 120 + 121 + bool tx_complete; 122 + enum tcpm_transmit_status tx_status; 123 + 124 + unsigned int negotiated_rev; 125 + unsigned int message_id; 126 + unsigned int caps_count; 127 + unsigned int hard_reset_count; 128 + bool pd_capable; 129 + bool explicit_contract; 130 + unsigned int rx_msgid; 131 + 132 + /* Partner capabilities/requests */ 133 + u32 sink_request; 134 + u32 source_caps[PDO_MAX_OBJECTS]; 135 + unsigned int nr_source_caps; 136 + u32 sink_caps[PDO_MAX_OBJECTS]; 137 + unsigned int nr_sink_caps; 138 + 139 + /* 140 + * whether to wait for the Type-C device to send the DR_SWAP Message flag 141 + * For Type-C device with Dual-Role Power and Dual-Role Data, the port side 142 + * is used as sink + ufp, then the tcpm framework needs to wait for Type-C 143 + * device to initiate DR_swap Message. 144 + */ 145 + bool wait_dr_swap_message; 146 + 147 + /* Local capabilities */ 148 + u32 src_pdo[PDO_MAX_OBJECTS]; 149 + unsigned int nr_src_pdo; 150 + u32 snk_pdo[PDO_MAX_OBJECTS]; 151 + unsigned int nr_snk_pdo; 152 + 153 + unsigned int operating_snk_mw; 154 + bool update_sink_caps; 155 + 156 + /* Requested current / voltage to the port partner */ 157 + u32 req_current_limit; 158 + u32 req_supply_voltage; 159 + /* Actual current / voltage limit of the local port */ 160 + u32 current_limit; 161 + u32 supply_voltage; 162 + 163 + /* port belongs to a self powered device */ 164 + bool self_powered; 165 + 166 + unsigned long delay_target; 167 + }; 168 + 169 + extern const char * const tcpm_states[]; 170 + 171 + int tcpm_post_probe(struct udevice *dev); 172 + 173 + #endif
+149
drivers/usb/tcpm/tcpm-uclass.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2024 Collabora Ltd. 4 + * 5 + * USB Power Delivery protocol stack. 6 + */ 7 + 8 + #include <dm/device.h> 9 + #include <dm/device_compat.h> 10 + #include <dm/uclass.h> 11 + #include <linux/err.h> 12 + #include <usb/tcpm.h> 13 + #include "tcpm-internal.h" 14 + 15 + int tcpm_get_voltage(struct udevice *dev) 16 + { 17 + struct tcpm_port *port = dev_get_uclass_plat(dev); 18 + 19 + return port->supply_voltage; 20 + } 21 + 22 + int tcpm_get_current(struct udevice *dev) 23 + { 24 + struct tcpm_port *port = dev_get_uclass_plat(dev); 25 + 26 + return port->current_limit; 27 + } 28 + 29 + enum typec_orientation tcpm_get_orientation(struct udevice *dev) 30 + { 31 + struct tcpm_port *port = dev_get_uclass_plat(dev); 32 + 33 + switch (port->polarity) { 34 + case TYPEC_POLARITY_CC1: 35 + return TYPEC_ORIENTATION_NORMAL; 36 + case TYPEC_POLARITY_CC2: 37 + return TYPEC_ORIENTATION_REVERSE; 38 + default: 39 + return TYPEC_ORIENTATION_NONE; 40 + } 41 + } 42 + 43 + const char *tcpm_get_state(struct udevice *dev) 44 + { 45 + struct tcpm_port *port = dev_get_uclass_plat(dev); 46 + 47 + return tcpm_states[port->state]; 48 + } 49 + 50 + int tcpm_get_pd_rev(struct udevice *dev) 51 + { 52 + struct tcpm_port *port = dev_get_uclass_plat(dev); 53 + 54 + return port->negotiated_rev; 55 + } 56 + 57 + enum typec_role tcpm_get_pwr_role(struct udevice *dev) 58 + { 59 + struct tcpm_port *port = dev_get_uclass_plat(dev); 60 + 61 + return port->pwr_role; 62 + } 63 + 64 + enum typec_data_role tcpm_get_data_role(struct udevice *dev) 65 + { 66 + struct tcpm_port *port = dev_get_uclass_plat(dev); 67 + 68 + return port->data_role; 69 + } 70 + 71 + bool tcpm_is_connected(struct udevice *dev) 72 + { 73 + struct tcpm_port *port = dev_get_uclass_plat(dev); 74 + 75 + return port->connected; 76 + } 77 + 78 + int tcpm_get(int index, struct udevice **devp) 79 + { 80 + return uclass_get_device(UCLASS_TCPM, index, devp); 81 + } 82 + 83 + static int tcpm_post_bind(struct udevice *dev) 84 + { 85 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 86 + const char *cap_str; 87 + ofnode node; 88 + int ret; 89 + 90 + /* 91 + * USB Power Delivery (USB PD) specification requires, that communication 92 + * with a sink happens within roughly 5 seconds. Otherwise the source 93 + * might assume that the sink does not support USB PD. Starting to do 94 + * USB PD communication after that results in a hard reset, which briefly 95 + * removes any power from the USB-C port. 96 + * 97 + * On systems with alternative power supplies this is not an issue, but 98 + * systems, which get soleley powered through their USB-C port will end 99 + * up losing their power supply and doing a board level reset. The hard 100 + * reset will also restart the 5 second timeout. That means a operating 101 + * system initializing USB PD will put the system into a boot loop when 102 + * it takes more than 5 seconds from cold boot to the operating system 103 + * starting to transmit USB PD messages. 104 + * 105 + * The issue can be avoided by doing the initial USB PD communication 106 + * in U-Boot. The operating system can then re-negotiate by doing a 107 + * soft reset, which does not trigger removal of the supply voltage. 108 + * 109 + * Since the TCPM state machine is quite complex and depending on the 110 + * remote side can take quite some time to finish, this tries to limit 111 + * the automatic probing to systems probably relying on power being 112 + * provided by the USB-C port(s): 113 + * 114 + * 1. self-powered devices won't reset when the USB-C port looses power 115 + * 2. if the power is allowed to go into anything else than sink mode 116 + * it is not the only power source 117 + */ 118 + ret = drvops->get_connector_node(dev, &node); 119 + if (ret) 120 + return ret; 121 + 122 + if (ofnode_read_bool(node, "self-powered")) 123 + return 0; 124 + 125 + cap_str = ofnode_read_string(node, "power-role"); 126 + if (!cap_str) 127 + return -EINVAL; 128 + 129 + if (strcmp("sink", cap_str)) 130 + return 0; 131 + 132 + /* Do not auto-probe PD controller when PD is disabled */ 133 + if (ofnode_read_bool(node, "pd-disable")) 134 + return 0; 135 + 136 + dev_info(dev, "probing Type-C port manager..."); 137 + 138 + dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); 139 + 140 + return 0; 141 + } 142 + 143 + UCLASS_DRIVER(tcpm) = { 144 + .id = UCLASS_TCPM, 145 + .name = "tcpm", 146 + .per_device_plat_auto = sizeof(struct tcpm_port), 147 + .post_bind = tcpm_post_bind, 148 + .post_probe = tcpm_post_probe, 149 + };
+2288
drivers/usb/tcpm/tcpm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright 2015-2017 Google, Inc 4 + * 5 + * USB Power Delivery protocol stack. 6 + */ 7 + 8 + #include <asm/gpio.h> 9 + #include <asm/io.h> 10 + #include <dm.h> 11 + #include <dm/device_compat.h> 12 + #include <dm/device-internal.h> 13 + #include <dm/devres.h> 14 + #include <linux/compat.h> 15 + #include <linux/delay.h> 16 + #include <linux/err.h> 17 + #include <linux/iopoll.h> 18 + #include <time.h> 19 + #include <usb/tcpm.h> 20 + #include "tcpm-internal.h" 21 + 22 + DECLARE_GLOBAL_DATA_PTR; 23 + 24 + const char * const tcpm_states[] = { 25 + FOREACH_TCPM_STATE(GENERATE_TCPM_STRING) 26 + }; 27 + 28 + const char * const typec_pd_rev_name[] = { 29 + [PD_REV10] = "rev1", 30 + [PD_REV20] = "rev2", 31 + [PD_REV30] = "rev3", 32 + }; 33 + 34 + const char * const typec_role_name[] = { 35 + [TYPEC_SINK] = "sink", 36 + [TYPEC_SOURCE] = "source", 37 + }; 38 + 39 + const char * const typec_data_role_name[] = { 40 + [TYPEC_DEVICE] = "device", 41 + [TYPEC_HOST] = "host", 42 + }; 43 + 44 + const char * const typec_orientation_name[] = { 45 + [TYPEC_ORIENTATION_NONE] = "none", 46 + [TYPEC_ORIENTATION_NORMAL] = "normal", 47 + [TYPEC_ORIENTATION_REVERSE] = "reverse", 48 + }; 49 + 50 + const char * const typec_cc_status_name[] = { 51 + [TYPEC_CC_OPEN] = "open", 52 + [TYPEC_CC_RA] = "ra", 53 + [TYPEC_CC_RD] = "rd", 54 + [TYPEC_CC_RP_DEF] = "rp-def", 55 + [TYPEC_CC_RP_1_5] = "rp-1.5", 56 + [TYPEC_CC_RP_3_0] = "rp-3.0", 57 + }; 58 + 59 + static inline bool tcpm_cc_is_sink(enum typec_cc_status cc) 60 + { 61 + return cc == TYPEC_CC_RP_DEF || 62 + cc == TYPEC_CC_RP_1_5 || 63 + cc == TYPEC_CC_RP_3_0; 64 + } 65 + 66 + static inline bool tcpm_port_is_sink(struct tcpm_port *port) 67 + { 68 + bool cc1_is_snk = tcpm_cc_is_sink(port->cc1); 69 + bool cc2_is_snk = tcpm_cc_is_sink(port->cc2); 70 + 71 + return (cc1_is_snk && !cc2_is_snk) || 72 + (cc2_is_snk && !cc1_is_snk); 73 + } 74 + 75 + static inline bool tcpm_cc_is_source(enum typec_cc_status cc) 76 + { 77 + return cc == TYPEC_CC_RD; 78 + } 79 + 80 + static inline bool tcpm_port_is_source(struct tcpm_port *port) 81 + { 82 + bool cc1_is_src = tcpm_cc_is_source(port->cc1); 83 + bool cc2_is_src = tcpm_cc_is_source(port->cc2); 84 + 85 + return (cc1_is_src && !cc2_is_src) || 86 + (cc2_is_src && !cc1_is_src); 87 + } 88 + 89 + static inline bool tcpm_try_src(struct tcpm_port *port) 90 + { 91 + return port->try_role == TYPEC_SOURCE && 92 + port->port_type == TYPEC_PORT_DRP; 93 + } 94 + 95 + static inline void tcpm_reset_event_cnt(struct udevice *dev) 96 + { 97 + struct tcpm_port *port = dev_get_uclass_plat(dev); 98 + 99 + port->poll_event_cnt = 0; 100 + } 101 + 102 + static enum tcpm_state tcpm_default_state(struct tcpm_port *port) 103 + { 104 + if (port->port_type == TYPEC_PORT_DRP) { 105 + if (port->try_role == TYPEC_SINK) 106 + return SNK_UNATTACHED; 107 + else if (port->try_role == TYPEC_SOURCE) 108 + return SRC_UNATTACHED; 109 + } else if (port->port_type == TYPEC_PORT_SNK) { 110 + return SNK_UNATTACHED; 111 + } 112 + return SRC_UNATTACHED; 113 + } 114 + 115 + static bool tcpm_port_is_disconnected(struct tcpm_port *port) 116 + { 117 + return (!port->attached && port->cc1 == TYPEC_CC_OPEN && 118 + port->cc2 == TYPEC_CC_OPEN) || 119 + (port->attached && ((port->polarity == TYPEC_POLARITY_CC1 && 120 + port->cc1 == TYPEC_CC_OPEN) || 121 + (port->polarity == TYPEC_POLARITY_CC2 && 122 + port->cc2 == TYPEC_CC_OPEN))); 123 + } 124 + 125 + static void tcpm_set_cc(struct udevice *dev, enum typec_cc_status cc) 126 + { 127 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 128 + struct tcpm_port *port = dev_get_uclass_plat(dev); 129 + 130 + dev_dbg(dev, "TCPM: set cc = %d\n", cc); 131 + port->cc_req = cc; 132 + drvops->set_cc(dev, cc); 133 + } 134 + 135 + /* 136 + * Determine RP value to set based on maximum current supported 137 + * by a port if configured as source. 138 + * Returns CC value to report to link partner. 139 + */ 140 + static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port) 141 + { 142 + const u32 *src_pdo = port->src_pdo; 143 + int nr_pdo = port->nr_src_pdo; 144 + int i; 145 + 146 + /* 147 + * Search for first entry with matching voltage. 148 + * It should report the maximum supported current. 149 + */ 150 + for (i = 0; i < nr_pdo; i++) { 151 + const u32 pdo = src_pdo[i]; 152 + 153 + if (pdo_type(pdo) == PDO_TYPE_FIXED && 154 + pdo_fixed_voltage(pdo) == 5000) { 155 + unsigned int curr = pdo_max_current(pdo); 156 + 157 + if (curr >= 3000) 158 + return TYPEC_CC_RP_3_0; 159 + else if (curr >= 1500) 160 + return TYPEC_CC_RP_1_5; 161 + return TYPEC_CC_RP_DEF; 162 + } 163 + } 164 + 165 + return TYPEC_CC_RP_DEF; 166 + } 167 + 168 + static void tcpm_check_and_run_delayed_work(struct udevice *dev); 169 + 170 + static bool tcpm_transmit_helper(struct udevice *dev) 171 + { 172 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 173 + struct tcpm_port *port = dev_get_uclass_plat(dev); 174 + 175 + drvops->poll_event(dev); 176 + udelay(500); 177 + tcpm_check_and_run_delayed_work(dev); 178 + return port->tx_complete; 179 + } 180 + 181 + static int tcpm_pd_transmit(struct udevice *dev, 182 + enum tcpm_transmit_type type, 183 + const struct pd_message *msg) 184 + { 185 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 186 + struct tcpm_port *port = dev_get_uclass_plat(dev); 187 + u32 timeout_us = PD_T_TCPC_TX_TIMEOUT * 1000; 188 + bool tx_complete; 189 + int ret; 190 + 191 + if (msg) 192 + dev_dbg(dev, "TCPM: PD TX, header: %#x\n", 193 + le16_to_cpu(msg->header)); 194 + else 195 + dev_dbg(dev, "TCPM: PD TX, type: %#x\n", type); 196 + 197 + port->tx_complete = false; 198 + ret = drvops->pd_transmit(dev, type, msg, port->negotiated_rev); 199 + if (ret < 0) 200 + return ret; 201 + 202 + /* 203 + * At this point we basically need to block until the TCPM controller 204 + * returns successful transmission. Since this is usually done using 205 + * the generic interrupt status bits, we poll for any events. That 206 + * will clear the interrupt status, so we also need to process any 207 + * of the incoming events. This means we will do more processing and 208 + * thus let's give everything a bit more time. 209 + */ 210 + timeout_us *= 5; 211 + ret = read_poll_timeout(tcpm_transmit_helper, tx_complete, 212 + !tx_complete, false, timeout_us, dev); 213 + if (ret < 0) { 214 + dev_err(dev, "TCPM: PD transmit data failed: %d\n", ret); 215 + return ret; 216 + } 217 + 218 + switch (port->tx_status) { 219 + case TCPC_TX_SUCCESS: 220 + port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK; 221 + break; 222 + case TCPC_TX_DISCARDED: 223 + ret = -EAGAIN; 224 + break; 225 + case TCPC_TX_FAILED: 226 + default: 227 + ret = -EIO; 228 + break; 229 + } 230 + 231 + return ret; 232 + } 233 + 234 + void tcpm_pd_transmit_complete(struct udevice *dev, 235 + enum tcpm_transmit_status status) 236 + { 237 + struct tcpm_port *port = dev_get_uclass_plat(dev); 238 + 239 + dev_dbg(dev, "TCPM: PD TX complete, status: %u\n", status); 240 + tcpm_reset_event_cnt(dev); 241 + port->tx_status = status; 242 + port->tx_complete = true; 243 + } 244 + 245 + static int tcpm_set_polarity(struct udevice *dev, 246 + enum typec_cc_polarity polarity) 247 + { 248 + struct tcpm_port *port = dev_get_uclass_plat(dev); 249 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 250 + int ret; 251 + 252 + dev_dbg(dev, "TCPM: set polarity = %d\n", polarity); 253 + 254 + if (drvops->set_polarity) { 255 + ret = drvops->set_polarity(dev, polarity); 256 + if (ret < 0) 257 + return ret; 258 + } 259 + 260 + port->polarity = polarity; 261 + 262 + return 0; 263 + } 264 + 265 + static int tcpm_set_vconn(struct udevice *dev, bool enable) 266 + { 267 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 268 + struct tcpm_port *port = dev_get_uclass_plat(dev); 269 + int ret; 270 + 271 + dev_dbg(dev, "TCPM: set vconn = %d\n", enable); 272 + 273 + ret = drvops->set_vconn(dev, enable); 274 + if (!ret) 275 + port->vconn_role = enable ? TYPEC_SOURCE : TYPEC_SINK; 276 + 277 + return ret; 278 + } 279 + 280 + static inline u32 tcpm_get_current_limit(struct tcpm_port *port) 281 + { 282 + switch (port->polarity ? port->cc2 : port->cc1) { 283 + case TYPEC_CC_RP_1_5: 284 + return 1500; 285 + case TYPEC_CC_RP_3_0: 286 + return 3000; 287 + case TYPEC_CC_RP_DEF: 288 + default: 289 + return 0; 290 + } 291 + } 292 + 293 + static int tcpm_set_current_limit(struct udevice *dev, u32 max_ma, u32 mv) 294 + { 295 + struct tcpm_port *port = dev_get_uclass_plat(dev); 296 + int ret = -EOPNOTSUPP; 297 + 298 + dev_info(dev, "TCPM: set voltage limit = %u mV\n", mv); 299 + dev_info(dev, "TCPM: set current limit = %u mA\n", max_ma); 300 + 301 + port->supply_voltage = mv; 302 + port->current_limit = max_ma; 303 + 304 + return ret; 305 + } 306 + 307 + static int tcpm_set_attached_state(struct udevice *dev, bool attached) 308 + { 309 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 310 + struct tcpm_port *port = dev_get_uclass_plat(dev); 311 + 312 + return drvops->set_roles(dev, attached, port->pwr_role, 313 + port->data_role); 314 + } 315 + 316 + static int tcpm_set_roles(struct udevice *dev, bool attached, 317 + enum typec_role role, enum typec_data_role data) 318 + { 319 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 320 + struct tcpm_port *port = dev_get_uclass_plat(dev); 321 + int ret; 322 + 323 + ret = drvops->set_roles(dev, attached, role, data); 324 + if (ret < 0) 325 + return ret; 326 + 327 + port->pwr_role = role; 328 + port->data_role = data; 329 + 330 + return 0; 331 + } 332 + 333 + static int tcpm_pd_send_source_caps(struct udevice *dev) 334 + { 335 + struct tcpm_port *port = dev_get_uclass_plat(dev); 336 + struct pd_message msg; 337 + int i; 338 + 339 + memset(&msg, 0, sizeof(msg)); 340 + 341 + if (!port->nr_src_pdo) { 342 + /* No source capabilities defined, sink only */ 343 + msg.header = PD_HEADER_LE(PD_CTRL_REJECT, 344 + port->pwr_role, 345 + port->data_role, 346 + port->negotiated_rev, 347 + port->message_id, 0); 348 + } else { 349 + msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, 350 + port->pwr_role, 351 + port->data_role, 352 + port->negotiated_rev, 353 + port->message_id, 354 + port->nr_src_pdo); 355 + } 356 + 357 + for (i = 0; i < port->nr_src_pdo; i++) 358 + msg.payload[i] = cpu_to_le32(port->src_pdo[i]); 359 + 360 + return tcpm_pd_transmit(dev, TCPC_TX_SOP, &msg); 361 + } 362 + 363 + static int tcpm_pd_send_sink_caps(struct udevice *dev) 364 + { 365 + struct tcpm_port *port = dev_get_uclass_plat(dev); 366 + struct pd_message msg; 367 + unsigned int i; 368 + 369 + memset(&msg, 0, sizeof(msg)); 370 + 371 + if (!port->nr_snk_pdo) { 372 + /* No sink capabilities defined, source only */ 373 + msg.header = PD_HEADER_LE(PD_CTRL_REJECT, 374 + port->pwr_role, 375 + port->data_role, 376 + port->negotiated_rev, 377 + port->message_id, 0); 378 + } else { 379 + msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, 380 + port->pwr_role, 381 + port->data_role, 382 + port->negotiated_rev, 383 + port->message_id, 384 + port->nr_snk_pdo); 385 + } 386 + 387 + for (i = 0; i < port->nr_snk_pdo; i++) 388 + msg.payload[i] = cpu_to_le32(port->snk_pdo[i]); 389 + 390 + return tcpm_pd_transmit(dev, TCPC_TX_SOP, &msg); 391 + } 392 + 393 + static void tcpm_state_machine(struct udevice *dev); 394 + 395 + static inline void tcpm_timer_uninit(struct udevice *dev) 396 + { 397 + struct tcpm_port *port = dev_get_uclass_plat(dev); 398 + 399 + port->delay_target = 0; 400 + } 401 + 402 + static void tcpm_timer_init(struct udevice *dev, uint32_t ms) 403 + { 404 + struct tcpm_port *port = dev_get_uclass_plat(dev); 405 + unsigned long time_us = ms * 1000; 406 + 407 + port->delay_target = timer_get_us() + time_us; 408 + } 409 + 410 + static void tcpm_check_and_run_delayed_work(struct udevice *dev) 411 + { 412 + struct tcpm_port *port = dev_get_uclass_plat(dev); 413 + 414 + /* no delayed state changes scheduled */ 415 + if (port->delay_target == 0) 416 + return; 417 + 418 + /* it's not yet time */ 419 + if (timer_get_us() < port->delay_target) 420 + return; 421 + 422 + tcpm_timer_uninit(dev); 423 + tcpm_state_machine(dev); 424 + } 425 + 426 + static void mod_tcpm_delayed_work(struct udevice *dev, unsigned int delay_ms) 427 + { 428 + if (delay_ms) { 429 + tcpm_timer_init(dev, delay_ms); 430 + } else { 431 + tcpm_timer_uninit(dev); 432 + tcpm_state_machine(dev); 433 + } 434 + } 435 + 436 + static void tcpm_set_state(struct udevice *dev, enum tcpm_state state, 437 + unsigned int delay_ms) 438 + { 439 + struct tcpm_port *port = dev_get_uclass_plat(dev); 440 + 441 + if (delay_ms) { 442 + dev_dbg(dev, "TCPM: pending state change %s -> %s @ %u ms [%s]\n", 443 + tcpm_states[port->state], tcpm_states[state], delay_ms, 444 + typec_pd_rev_name[port->negotiated_rev]); 445 + port->delayed_state = state; 446 + mod_tcpm_delayed_work(dev, delay_ms); 447 + port->delay_ms = delay_ms; 448 + } else { 449 + dev_dbg(dev, "TCPM: state change %s -> %s\n", 450 + tcpm_states[port->state], tcpm_states[state]); 451 + port->delayed_state = INVALID_STATE; 452 + port->prev_state = port->state; 453 + port->state = state; 454 + /* 455 + * Don't re-queue the state machine work item if we're currently 456 + * in the state machine and we're immediately changing states. 457 + * tcpm_state_machine_work() will continue running the state 458 + * machine. 459 + */ 460 + if (!port->state_machine_running) 461 + mod_tcpm_delayed_work(dev, 0); 462 + } 463 + } 464 + 465 + static void tcpm_set_state_cond(struct udevice *dev, enum tcpm_state state, 466 + unsigned int delay_ms) 467 + { 468 + struct tcpm_port *port = dev_get_uclass_plat(dev); 469 + 470 + if (port->enter_state == port->state) 471 + tcpm_set_state(dev, state, delay_ms); 472 + else 473 + dev_dbg(dev, "TCPM: skipped %sstate change %s -> %s [%u ms], context state %s [%s]\n", 474 + delay_ms ? "delayed " : "", 475 + tcpm_states[port->state], tcpm_states[state], 476 + delay_ms, tcpm_states[port->enter_state], 477 + typec_pd_rev_name[port->negotiated_rev]); 478 + } 479 + 480 + static void tcpm_queue_message(struct udevice *dev, 481 + enum pd_msg_request message) 482 + { 483 + struct tcpm_port *port = dev_get_uclass_plat(dev); 484 + 485 + port->queued_message = message; 486 + mod_tcpm_delayed_work(dev, 0); 487 + } 488 + 489 + enum pdo_err { 490 + PDO_NO_ERR, 491 + PDO_ERR_NO_VSAFE5V, 492 + PDO_ERR_VSAFE5V_NOT_FIRST, 493 + PDO_ERR_PDO_TYPE_NOT_IN_ORDER, 494 + PDO_ERR_FIXED_NOT_SORTED, 495 + PDO_ERR_VARIABLE_BATT_NOT_SORTED, 496 + PDO_ERR_DUPE_PDO, 497 + PDO_ERR_PPS_APDO_NOT_SORTED, 498 + PDO_ERR_DUPE_PPS_APDO, 499 + }; 500 + 501 + static const char * const pdo_err_msg[] = { 502 + [PDO_ERR_NO_VSAFE5V] = 503 + " err: source/sink caps should at least have vSafe5V", 504 + [PDO_ERR_VSAFE5V_NOT_FIRST] = 505 + " err: vSafe5V Fixed Supply Object Shall always be the first object", 506 + [PDO_ERR_PDO_TYPE_NOT_IN_ORDER] = 507 + " err: PDOs should be in the following order: Fixed; Battery; Variable", 508 + [PDO_ERR_FIXED_NOT_SORTED] = 509 + " err: Fixed supply pdos should be in increasing order of their fixed voltage", 510 + [PDO_ERR_VARIABLE_BATT_NOT_SORTED] = 511 + " err: Variable/Battery supply pdos should be in increasing order of their minimum voltage", 512 + [PDO_ERR_DUPE_PDO] = 513 + " err: Variable/Batt supply pdos cannot have same min/max voltage", 514 + [PDO_ERR_PPS_APDO_NOT_SORTED] = 515 + " err: Programmable power supply apdos should be in increasing order of their maximum voltage", 516 + [PDO_ERR_DUPE_PPS_APDO] = 517 + " err: Programmable power supply apdos cannot have same min/max voltage and max current", 518 + }; 519 + 520 + static enum pdo_err tcpm_caps_err(struct udevice *dev, const u32 *pdo, 521 + unsigned int nr_pdo) 522 + { 523 + unsigned int i; 524 + 525 + /* Should at least contain vSafe5v */ 526 + if (nr_pdo < 1) 527 + return PDO_ERR_NO_VSAFE5V; 528 + 529 + /* The vSafe5V Fixed Supply Object Shall always be the first object */ 530 + if (pdo_type(pdo[0]) != PDO_TYPE_FIXED || 531 + pdo_fixed_voltage(pdo[0]) != VSAFE5V) 532 + return PDO_ERR_VSAFE5V_NOT_FIRST; 533 + 534 + for (i = 1; i < nr_pdo; i++) { 535 + if (pdo_type(pdo[i]) < pdo_type(pdo[i - 1])) { 536 + return PDO_ERR_PDO_TYPE_NOT_IN_ORDER; 537 + } else if (pdo_type(pdo[i]) == pdo_type(pdo[i - 1])) { 538 + enum pd_pdo_type type = pdo_type(pdo[i]); 539 + 540 + switch (type) { 541 + /* 542 + * The remaining Fixed Supply Objects, if 543 + * present, shall be sent in voltage order; 544 + * lowest to highest. 545 + */ 546 + case PDO_TYPE_FIXED: 547 + if (pdo_fixed_voltage(pdo[i]) <= 548 + pdo_fixed_voltage(pdo[i - 1])) 549 + return PDO_ERR_FIXED_NOT_SORTED; 550 + break; 551 + /* 552 + * The Battery Supply Objects and Variable 553 + * supply, if present shall be sent in Minimum 554 + * Voltage order; lowest to highest. 555 + */ 556 + case PDO_TYPE_VAR: 557 + case PDO_TYPE_BATT: 558 + if (pdo_min_voltage(pdo[i]) < 559 + pdo_min_voltage(pdo[i - 1])) 560 + return PDO_ERR_VARIABLE_BATT_NOT_SORTED; 561 + else if ((pdo_min_voltage(pdo[i]) == 562 + pdo_min_voltage(pdo[i - 1])) && 563 + (pdo_max_voltage(pdo[i]) == 564 + pdo_max_voltage(pdo[i - 1]))) 565 + return PDO_ERR_DUPE_PDO; 566 + break; 567 + /* 568 + * The Programmable Power Supply APDOs, if present, 569 + * shall be sent in Maximum Voltage order; 570 + * lowest to highest. 571 + */ 572 + case PDO_TYPE_APDO: 573 + if (pdo_apdo_type(pdo[i]) != APDO_TYPE_PPS) 574 + break; 575 + 576 + if (pdo_pps_apdo_max_voltage(pdo[i]) < 577 + pdo_pps_apdo_max_voltage(pdo[i - 1])) 578 + return PDO_ERR_PPS_APDO_NOT_SORTED; 579 + else if (pdo_pps_apdo_min_voltage(pdo[i]) == 580 + pdo_pps_apdo_min_voltage(pdo[i - 1]) && 581 + pdo_pps_apdo_max_voltage(pdo[i]) == 582 + pdo_pps_apdo_max_voltage(pdo[i - 1]) && 583 + pdo_pps_apdo_max_current(pdo[i]) == 584 + pdo_pps_apdo_max_current(pdo[i - 1])) 585 + return PDO_ERR_DUPE_PPS_APDO; 586 + break; 587 + default: 588 + dev_err(dev, "TCPM: Unknown pdo type\n"); 589 + } 590 + } 591 + } 592 + 593 + return PDO_NO_ERR; 594 + } 595 + 596 + static int tcpm_validate_caps(struct udevice *dev, const u32 *pdo, 597 + unsigned int nr_pdo) 598 + { 599 + enum pdo_err err_index = tcpm_caps_err(dev, pdo, nr_pdo); 600 + 601 + if (err_index != PDO_NO_ERR) { 602 + dev_err(dev, "TCPM:%s\n", pdo_err_msg[err_index]); 603 + return -EINVAL; 604 + } 605 + 606 + return 0; 607 + } 608 + 609 + /* 610 + * PD (data, control) command handling functions 611 + */ 612 + static inline enum tcpm_state ready_state(struct tcpm_port *port) 613 + { 614 + if (port->pwr_role == TYPEC_SOURCE) 615 + return SRC_READY; 616 + else 617 + return SNK_READY; 618 + } 619 + 620 + static void tcpm_pd_data_request(struct udevice *dev, 621 + const struct pd_message *msg) 622 + { 623 + enum pd_data_msg_type type = pd_header_type_le(msg->header); 624 + struct tcpm_port *port = dev_get_uclass_plat(dev); 625 + unsigned int cnt = pd_header_cnt_le(msg->header); 626 + unsigned int rev = pd_header_rev_le(msg->header); 627 + unsigned int i; 628 + 629 + switch (type) { 630 + case PD_DATA_SOURCE_CAP: 631 + for (i = 0; i < cnt; i++) 632 + port->source_caps[i] = le32_to_cpu(msg->payload[i]); 633 + 634 + port->nr_source_caps = cnt; 635 + 636 + tcpm_validate_caps(dev, port->source_caps, 637 + port->nr_source_caps); 638 + 639 + /* 640 + * Adjust revision in subsequent message headers, as required, 641 + * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't 642 + * support Rev 1.0 so just do nothing in that scenario. 643 + */ 644 + if (rev == PD_REV10) 645 + break; 646 + 647 + if (rev < PD_MAX_REV) 648 + port->negotiated_rev = rev; 649 + 650 + if ((pdo_type(port->source_caps[0]) == PDO_TYPE_FIXED) && 651 + (port->source_caps[0] & PDO_FIXED_DUAL_ROLE) && 652 + (port->source_caps[0] & PDO_FIXED_DATA_SWAP)) { 653 + /* Dual role power and data, eg: self-powered Type-C */ 654 + port->wait_dr_swap_message = true; 655 + } else { 656 + /* Non-Dual role power, eg: adapter */ 657 + port->wait_dr_swap_message = false; 658 + } 659 + 660 + /* 661 + * This message may be received even if VBUS is not 662 + * present. This is quite unexpected; see USB PD 663 + * specification, sections 8.3.3.6.3.1 and 8.3.3.6.3.2. 664 + * However, at the same time, we must be ready to 665 + * receive this message and respond to it 15ms after 666 + * receiving PS_RDY during power swap operations, no matter 667 + * if VBUS is available or not (USB PD specification, 668 + * section 6.5.9.2). 669 + * So we need to accept the message either way, 670 + * but be prepared to keep waiting for VBUS after it was 671 + * handled. 672 + */ 673 + tcpm_set_state(dev, SNK_NEGOTIATE_CAPABILITIES, 0); 674 + break; 675 + case PD_DATA_REQUEST: 676 + /* 677 + * Adjust revision in subsequent message headers, as required, 678 + * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't 679 + * support Rev 1.0 so just reject in that scenario. 680 + */ 681 + if (rev == PD_REV10) { 682 + tcpm_queue_message(dev, PD_MSG_CTRL_REJECT); 683 + break; 684 + } 685 + 686 + if (rev < PD_MAX_REV) 687 + port->negotiated_rev = rev; 688 + 689 + port->sink_request = le32_to_cpu(msg->payload[0]); 690 + 691 + tcpm_set_state(dev, SRC_NEGOTIATE_CAPABILITIES, 0); 692 + break; 693 + case PD_DATA_SINK_CAP: 694 + /* We don't do anything with this at the moment... */ 695 + for (i = 0; i < cnt; i++) 696 + port->sink_caps[i] = le32_to_cpu(msg->payload[i]); 697 + 698 + port->nr_sink_caps = cnt; 699 + break; 700 + default: 701 + break; 702 + } 703 + } 704 + 705 + static void tcpm_pd_ctrl_request(struct udevice *dev, 706 + const struct pd_message *msg) 707 + { 708 + enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); 709 + struct tcpm_port *port = dev_get_uclass_plat(dev); 710 + enum tcpm_state next_state; 711 + 712 + switch (type) { 713 + case PD_CTRL_GOOD_CRC: 714 + case PD_CTRL_PING: 715 + break; 716 + case PD_CTRL_GET_SOURCE_CAP: 717 + switch (port->state) { 718 + case SRC_READY: 719 + case SNK_READY: 720 + tcpm_queue_message(dev, PD_MSG_DATA_SOURCE_CAP); 721 + break; 722 + default: 723 + tcpm_queue_message(dev, PD_MSG_CTRL_REJECT); 724 + break; 725 + } 726 + break; 727 + case PD_CTRL_GET_SINK_CAP: 728 + switch (port->state) { 729 + case SRC_READY: 730 + case SNK_READY: 731 + tcpm_queue_message(dev, PD_MSG_DATA_SINK_CAP); 732 + break; 733 + default: 734 + tcpm_queue_message(dev, PD_MSG_CTRL_REJECT); 735 + break; 736 + } 737 + break; 738 + case PD_CTRL_GOTO_MIN: 739 + break; 740 + case PD_CTRL_PS_RDY: 741 + switch (port->state) { 742 + case SNK_TRANSITION_SINK: 743 + if (port->vbus_present) { 744 + tcpm_set_current_limit(dev, 745 + port->req_current_limit, 746 + port->req_supply_voltage); 747 + port->explicit_contract = true; 748 + tcpm_set_state(dev, SNK_READY, 0); 749 + } else { 750 + /* 751 + * Seen after power swap. Keep waiting for VBUS 752 + * in a transitional state. 753 + */ 754 + tcpm_set_state(dev, 755 + SNK_TRANSITION_SINK_VBUS, 0); 756 + } 757 + break; 758 + default: 759 + break; 760 + } 761 + break; 762 + case PD_CTRL_REJECT: 763 + case PD_CTRL_WAIT: 764 + case PD_CTRL_NOT_SUPP: 765 + switch (port->state) { 766 + case SNK_NEGOTIATE_CAPABILITIES: 767 + /* USB PD specification, Figure 8-43 */ 768 + if (port->explicit_contract) 769 + next_state = SNK_READY; 770 + else 771 + next_state = SNK_WAIT_CAPABILITIES; 772 + 773 + tcpm_set_state(dev, next_state, 0); 774 + break; 775 + default: 776 + break; 777 + } 778 + break; 779 + case PD_CTRL_ACCEPT: 780 + switch (port->state) { 781 + case SNK_NEGOTIATE_CAPABILITIES: 782 + tcpm_set_state(dev, SNK_TRANSITION_SINK, 0); 783 + break; 784 + case SOFT_RESET_SEND: 785 + port->message_id = 0; 786 + port->rx_msgid = -1; 787 + if (port->pwr_role == TYPEC_SOURCE) 788 + next_state = SRC_SEND_CAPABILITIES; 789 + else 790 + next_state = SNK_WAIT_CAPABILITIES; 791 + tcpm_set_state(dev, next_state, 0); 792 + break; 793 + default: 794 + break; 795 + } 796 + break; 797 + case PD_CTRL_SOFT_RESET: 798 + tcpm_set_state(dev, SOFT_RESET, 0); 799 + break; 800 + case PD_CTRL_DR_SWAP: 801 + if (port->port_type != TYPEC_PORT_DRP) { 802 + tcpm_queue_message(dev, PD_MSG_CTRL_REJECT); 803 + break; 804 + } 805 + /* 806 + * 6.3.9: If an alternate mode is active, a request to swap 807 + * alternate modes shall trigger a port reset. 808 + */ 809 + switch (port->state) { 810 + case SRC_READY: 811 + case SNK_READY: 812 + tcpm_set_state(dev, DR_SWAP_ACCEPT, 0); 813 + break; 814 + default: 815 + tcpm_queue_message(dev, PD_MSG_CTRL_WAIT); 816 + break; 817 + } 818 + break; 819 + case PD_CTRL_PR_SWAP: 820 + case PD_CTRL_VCONN_SWAP: 821 + case PD_CTRL_GET_SOURCE_CAP_EXT: 822 + case PD_CTRL_GET_STATUS: 823 + case PD_CTRL_FR_SWAP: 824 + case PD_CTRL_GET_PPS_STATUS: 825 + case PD_CTRL_GET_COUNTRY_CODES: 826 + /* Currently not supported */ 827 + dev_err(dev, "TCPM: Currently not supported type %#x\n", type); 828 + tcpm_queue_message(dev, PD_MSG_CTRL_NOT_SUPP); 829 + break; 830 + default: 831 + dev_err(dev, "TCPM: Unrecognized ctrl message type %#x\n", type); 832 + break; 833 + } 834 + } 835 + 836 + static void tcpm_pd_rx_handler(struct udevice *dev, 837 + const struct pd_message *msg) 838 + { 839 + struct tcpm_port *port = dev_get_uclass_plat(dev); 840 + unsigned int cnt = pd_header_cnt_le(msg->header); 841 + bool remote_is_host, local_is_host; 842 + 843 + dev_dbg(dev, "TCPM: PD RX, header: %#x [%d]\n", 844 + le16_to_cpu(msg->header), port->attached); 845 + 846 + if (port->attached) { 847 + enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); 848 + unsigned int msgid = pd_header_msgid_le(msg->header); 849 + 850 + /* 851 + * USB PD standard, 6.6.1.2: 852 + * "... if MessageID value in a received Message is the 853 + * same as the stored value, the receiver shall return a 854 + * GoodCRC Message with that MessageID value and drop 855 + * the Message (this is a retry of an already received 856 + * Message). Note: this shall not apply to the Soft_Reset 857 + * Message which always has a MessageID value of zero." 858 + */ 859 + if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET) 860 + return; 861 + port->rx_msgid = msgid; 862 + 863 + /* 864 + * If both ends believe to be DFP/host, we have a data role 865 + * mismatch. 866 + */ 867 + remote_is_host = !!(le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE); 868 + local_is_host = port->data_role == TYPEC_HOST; 869 + if (remote_is_host == local_is_host) { 870 + dev_err(dev, "TCPM: data role mismatch, initiating error recovery\n"); 871 + tcpm_set_state(dev, ERROR_RECOVERY, 0); 872 + } else { 873 + if (cnt) 874 + tcpm_pd_data_request(dev, msg); 875 + else 876 + tcpm_pd_ctrl_request(dev, msg); 877 + } 878 + } 879 + } 880 + 881 + void tcpm_pd_receive(struct udevice *dev, const struct pd_message *msg) 882 + { 883 + tcpm_reset_event_cnt(dev); 884 + tcpm_pd_rx_handler(dev, msg); 885 + } 886 + 887 + static int tcpm_pd_send_control(struct udevice *dev, 888 + enum pd_ctrl_msg_type type) 889 + { 890 + struct tcpm_port *port = dev_get_uclass_plat(dev); 891 + struct pd_message msg; 892 + 893 + memset(&msg, 0, sizeof(msg)); 894 + msg.header = PD_HEADER_LE(type, port->pwr_role, 895 + port->data_role, 896 + port->negotiated_rev, 897 + port->message_id, 0); 898 + 899 + return tcpm_pd_transmit(dev, TCPC_TX_SOP, &msg); 900 + } 901 + 902 + /* 903 + * Send queued message without affecting state. 904 + * Return true if state machine should go back to sleep, 905 + * false otherwise. 906 + */ 907 + static bool tcpm_send_queued_message(struct udevice *dev) 908 + { 909 + struct tcpm_port *port = dev_get_uclass_plat(dev); 910 + enum pd_msg_request queued_message; 911 + int max_messages = 100; 912 + 913 + do { 914 + queued_message = port->queued_message; 915 + port->queued_message = PD_MSG_NONE; 916 + max_messages--; 917 + 918 + switch (queued_message) { 919 + case PD_MSG_CTRL_WAIT: 920 + tcpm_pd_send_control(dev, PD_CTRL_WAIT); 921 + break; 922 + case PD_MSG_CTRL_REJECT: 923 + tcpm_pd_send_control(dev, PD_CTRL_REJECT); 924 + break; 925 + case PD_MSG_CTRL_NOT_SUPP: 926 + tcpm_pd_send_control(dev, PD_CTRL_NOT_SUPP); 927 + break; 928 + case PD_MSG_DATA_SINK_CAP: 929 + tcpm_pd_send_sink_caps(dev); 930 + break; 931 + case PD_MSG_DATA_SOURCE_CAP: 932 + tcpm_pd_send_source_caps(dev); 933 + break; 934 + default: 935 + break; 936 + } 937 + } while (max_messages > 0 && port->queued_message != PD_MSG_NONE); 938 + 939 + if (!max_messages) 940 + dev_err(dev, "Aborted sending of too many queued messages\n"); 941 + 942 + return false; 943 + } 944 + 945 + static int tcpm_pd_check_request(struct udevice *dev) 946 + { 947 + struct tcpm_port *port = dev_get_uclass_plat(dev); 948 + u32 pdo, rdo = port->sink_request; 949 + unsigned int max, op, pdo_max, index; 950 + enum pd_pdo_type type; 951 + 952 + index = rdo_index(rdo); 953 + if (!index || index > port->nr_src_pdo) 954 + return -EINVAL; 955 + 956 + pdo = port->src_pdo[index - 1]; 957 + type = pdo_type(pdo); 958 + switch (type) { 959 + case PDO_TYPE_FIXED: 960 + case PDO_TYPE_VAR: 961 + max = rdo_max_current(rdo); 962 + op = rdo_op_current(rdo); 963 + pdo_max = pdo_max_current(pdo); 964 + 965 + if (op > pdo_max) 966 + return -EINVAL; 967 + if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH)) 968 + return -EINVAL; 969 + 970 + if (type == PDO_TYPE_FIXED) 971 + dev_dbg(dev, "TCPM: Requested %u mV, %u mA for %u / %u mA\n", 972 + pdo_fixed_voltage(pdo), pdo_max, op, max); 973 + else 974 + dev_dbg(dev, "TCPM: Requested %u -> %u mV, %u mA for %u / %u mA\n", 975 + pdo_min_voltage(pdo), pdo_max_voltage(pdo), 976 + pdo_max, op, max); 977 + break; 978 + case PDO_TYPE_BATT: 979 + max = rdo_max_power(rdo); 980 + op = rdo_op_power(rdo); 981 + pdo_max = pdo_max_power(pdo); 982 + 983 + if (op > pdo_max) 984 + return -EINVAL; 985 + if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH)) 986 + return -EINVAL; 987 + dev_info(dev, "TCPM: Requested %u -> %u mV, %u mW for %u / %u mW\n", 988 + pdo_min_voltage(pdo), pdo_max_voltage(pdo), 989 + pdo_max, op, max); 990 + break; 991 + default: 992 + return -EINVAL; 993 + } 994 + 995 + return 0; 996 + } 997 + 998 + #define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) 999 + #define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) 1000 + 1001 + static int tcpm_pd_select_pdo(struct udevice *dev, int *sink_pdo, 1002 + int *src_pdo) 1003 + { 1004 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1005 + unsigned int i, j, max_src_mv = 0, min_src_mv = 0, max_mw = 0, 1006 + max_mv = 0, src_mw = 0, src_ma = 0, max_snk_mv = 0, 1007 + min_snk_mv = 0; 1008 + int ret = -EINVAL; 1009 + 1010 + /* 1011 + * Select the source PDO providing the most power which has a 1012 + * matchig sink cap. 1013 + */ 1014 + for (i = 0; i < port->nr_source_caps; i++) { 1015 + u32 pdo = port->source_caps[i]; 1016 + enum pd_pdo_type type = pdo_type(pdo); 1017 + 1018 + switch (type) { 1019 + case PDO_TYPE_FIXED: 1020 + max_src_mv = pdo_fixed_voltage(pdo); 1021 + min_src_mv = max_src_mv; 1022 + break; 1023 + case PDO_TYPE_BATT: 1024 + case PDO_TYPE_VAR: 1025 + max_src_mv = pdo_max_voltage(pdo); 1026 + min_src_mv = pdo_min_voltage(pdo); 1027 + break; 1028 + case PDO_TYPE_APDO: 1029 + continue; 1030 + default: 1031 + dev_err(dev, "TCPM: Invalid source PDO type, ignoring\n"); 1032 + continue; 1033 + } 1034 + 1035 + switch (type) { 1036 + case PDO_TYPE_FIXED: 1037 + case PDO_TYPE_VAR: 1038 + src_ma = pdo_max_current(pdo); 1039 + src_mw = src_ma * min_src_mv / 1000; 1040 + break; 1041 + case PDO_TYPE_BATT: 1042 + src_mw = pdo_max_power(pdo); 1043 + break; 1044 + case PDO_TYPE_APDO: 1045 + continue; 1046 + default: 1047 + dev_err(dev, "TCPM: Invalid source PDO type, ignoring\n"); 1048 + continue; 1049 + } 1050 + 1051 + for (j = 0; j < port->nr_snk_pdo; j++) { 1052 + pdo = port->snk_pdo[j]; 1053 + 1054 + switch (pdo_type(pdo)) { 1055 + case PDO_TYPE_FIXED: 1056 + max_snk_mv = pdo_fixed_voltage(pdo); 1057 + min_snk_mv = max_snk_mv; 1058 + break; 1059 + case PDO_TYPE_BATT: 1060 + case PDO_TYPE_VAR: 1061 + max_snk_mv = pdo_max_voltage(pdo); 1062 + min_snk_mv = pdo_min_voltage(pdo); 1063 + break; 1064 + case PDO_TYPE_APDO: 1065 + continue; 1066 + default: 1067 + dev_err(dev, "TCPM: Invalid sink PDO type, ignoring\n"); 1068 + continue; 1069 + } 1070 + 1071 + if (max_src_mv <= max_snk_mv && min_src_mv >= min_snk_mv) { 1072 + /* Prefer higher voltages if available */ 1073 + if ((src_mw == max_mw && min_src_mv > max_mv) || 1074 + src_mw > max_mw) { 1075 + *src_pdo = i; 1076 + *sink_pdo = j; 1077 + max_mw = src_mw; 1078 + max_mv = min_src_mv; 1079 + ret = 0; 1080 + } 1081 + } 1082 + } 1083 + } 1084 + 1085 + return ret; 1086 + } 1087 + 1088 + static int tcpm_pd_build_request(struct udevice *dev, u32 *rdo) 1089 + { 1090 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1091 + unsigned int mv, ma, mw, flags; 1092 + unsigned int max_ma, max_mw; 1093 + enum pd_pdo_type type; 1094 + u32 pdo, matching_snk_pdo; 1095 + int src_pdo_index = 0; 1096 + int snk_pdo_index = 0; 1097 + int ret; 1098 + 1099 + ret = tcpm_pd_select_pdo(dev, &snk_pdo_index, &src_pdo_index); 1100 + if (ret < 0) 1101 + return ret; 1102 + 1103 + pdo = port->source_caps[src_pdo_index]; 1104 + matching_snk_pdo = port->snk_pdo[snk_pdo_index]; 1105 + type = pdo_type(pdo); 1106 + 1107 + switch (type) { 1108 + case PDO_TYPE_FIXED: 1109 + mv = pdo_fixed_voltage(pdo); 1110 + break; 1111 + case PDO_TYPE_BATT: 1112 + case PDO_TYPE_VAR: 1113 + mv = pdo_min_voltage(pdo); 1114 + break; 1115 + default: 1116 + dev_err(dev, "TCPM: Invalid PDO selected!\n"); 1117 + return -EINVAL; 1118 + } 1119 + 1120 + /* Select maximum available current within the sink pdo's limit */ 1121 + if (type == PDO_TYPE_BATT) { 1122 + mw = min_power(pdo, matching_snk_pdo); 1123 + ma = 1000 * mw / mv; 1124 + } else { 1125 + ma = min_current(pdo, matching_snk_pdo); 1126 + mw = ma * mv / 1000; 1127 + } 1128 + 1129 + flags = RDO_USB_COMM | RDO_NO_SUSPEND; 1130 + 1131 + /* Set mismatch bit if offered power is less than operating power */ 1132 + max_ma = ma; 1133 + max_mw = mw; 1134 + if (mw < port->operating_snk_mw) { 1135 + flags |= RDO_CAP_MISMATCH; 1136 + if (type == PDO_TYPE_BATT && 1137 + (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo))) 1138 + max_mw = pdo_max_power(matching_snk_pdo); 1139 + else if (pdo_max_current(matching_snk_pdo) > 1140 + pdo_max_current(pdo)) 1141 + max_ma = pdo_max_current(matching_snk_pdo); 1142 + } 1143 + 1144 + dev_dbg(dev, "TCPM: cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d\n", 1145 + port->cc_req, port->cc1, port->cc2, port->vbus_source, 1146 + port->vconn_role == TYPEC_SOURCE ? "source" : "sink", 1147 + port->polarity); 1148 + 1149 + if (type == PDO_TYPE_BATT) { 1150 + *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); 1151 + 1152 + dev_info(dev, "TCPM: requesting PDO %d: %u mV, %u mW%s\n", 1153 + src_pdo_index, mv, mw, 1154 + flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); 1155 + } else { 1156 + *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); 1157 + 1158 + dev_info(dev, "TCPM: requesting PDO %d: %u mV, %u mA%s\n", 1159 + src_pdo_index, mv, ma, 1160 + flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); 1161 + } 1162 + 1163 + port->req_current_limit = ma; 1164 + port->req_supply_voltage = mv; 1165 + 1166 + return 0; 1167 + } 1168 + 1169 + static int tcpm_pd_send_request(struct udevice *dev) 1170 + { 1171 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1172 + struct pd_message msg; 1173 + int ret; 1174 + u32 rdo; 1175 + 1176 + ret = tcpm_pd_build_request(dev, &rdo); 1177 + if (ret < 0) 1178 + return ret; 1179 + 1180 + memset(&msg, 0, sizeof(msg)); 1181 + msg.header = PD_HEADER_LE(PD_DATA_REQUEST, 1182 + port->pwr_role, 1183 + port->data_role, 1184 + port->negotiated_rev, 1185 + port->message_id, 1); 1186 + msg.payload[0] = cpu_to_le32(rdo); 1187 + 1188 + return tcpm_pd_transmit(dev, TCPC_TX_SOP, &msg); 1189 + } 1190 + 1191 + static int tcpm_set_vbus(struct udevice *dev, bool enable) 1192 + { 1193 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1194 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1195 + int ret; 1196 + 1197 + if (enable && port->vbus_charge) 1198 + return -EINVAL; 1199 + 1200 + dev_dbg(dev, "TCPM: set vbus = %d charge = %d\n", 1201 + enable, port->vbus_charge); 1202 + 1203 + ret = drvops->set_vbus(dev, enable, port->vbus_charge); 1204 + if (ret < 0) 1205 + return ret; 1206 + 1207 + port->vbus_source = enable; 1208 + return 0; 1209 + } 1210 + 1211 + static int tcpm_set_charge(struct udevice *dev, bool charge) 1212 + { 1213 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1214 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1215 + int ret; 1216 + 1217 + if (charge && port->vbus_source) 1218 + return -EINVAL; 1219 + 1220 + if (charge != port->vbus_charge) { 1221 + dev_dbg(dev, "TCPM: set vbus = %d charge = %d\n", 1222 + port->vbus_source, charge); 1223 + ret = drvops->set_vbus(dev, port->vbus_source, 1224 + charge); 1225 + if (ret < 0) 1226 + return ret; 1227 + } 1228 + port->vbus_charge = charge; 1229 + return 0; 1230 + } 1231 + 1232 + static bool tcpm_start_toggling(struct udevice *dev, enum typec_cc_status cc) 1233 + { 1234 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1235 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1236 + int ret; 1237 + 1238 + if (!drvops->start_toggling) 1239 + return false; 1240 + 1241 + dev_dbg(dev, "TCPM: Start toggling\n"); 1242 + ret = drvops->start_toggling(dev, port->port_type, cc); 1243 + return ret == 0; 1244 + } 1245 + 1246 + static int tcpm_init_vbus(struct udevice *dev) 1247 + { 1248 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1249 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1250 + int ret; 1251 + 1252 + ret = drvops->set_vbus(dev, false, false); 1253 + port->vbus_source = false; 1254 + port->vbus_charge = false; 1255 + return ret; 1256 + } 1257 + 1258 + static int tcpm_init_vconn(struct udevice *dev) 1259 + { 1260 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1261 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1262 + int ret; 1263 + 1264 + ret = drvops->set_vconn(dev, false); 1265 + port->vconn_role = TYPEC_SINK; 1266 + return ret; 1267 + } 1268 + 1269 + static inline void tcpm_typec_connect(struct tcpm_port *port) 1270 + { 1271 + if (!port->connected) 1272 + port->connected = true; 1273 + } 1274 + 1275 + static int tcpm_src_attach(struct udevice *dev) 1276 + { 1277 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1278 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1279 + enum typec_cc_polarity polarity = 1280 + port->cc2 == TYPEC_CC_RD ? TYPEC_POLARITY_CC2 1281 + : TYPEC_POLARITY_CC1; 1282 + int ret; 1283 + 1284 + if (port->attached) 1285 + return 0; 1286 + 1287 + ret = tcpm_set_polarity(dev, polarity); 1288 + if (ret < 0) 1289 + return ret; 1290 + 1291 + ret = tcpm_set_roles(dev, true, TYPEC_SOURCE, TYPEC_HOST); 1292 + if (ret < 0) 1293 + return ret; 1294 + 1295 + ret = drvops->set_pd_rx(dev, true); 1296 + if (ret < 0) 1297 + goto out_disable_mux; 1298 + 1299 + /* 1300 + * USB Type-C specification, version 1.2, 1301 + * chapter 4.5.2.2.8.1 (Attached.SRC Requirements) 1302 + * Enable VCONN only if the non-RD port is set to RA. 1303 + */ 1304 + if ((polarity == TYPEC_POLARITY_CC1 && port->cc2 == TYPEC_CC_RA) || 1305 + (polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) { 1306 + ret = tcpm_set_vconn(dev, true); 1307 + if (ret < 0) 1308 + goto out_disable_pd; 1309 + } 1310 + 1311 + ret = tcpm_set_vbus(dev, true); 1312 + if (ret < 0) 1313 + goto out_disable_vconn; 1314 + 1315 + port->pd_capable = false; 1316 + 1317 + port->partner = NULL; 1318 + 1319 + port->attached = true; 1320 + 1321 + return 0; 1322 + 1323 + out_disable_vconn: 1324 + tcpm_set_vconn(dev, false); 1325 + out_disable_pd: 1326 + drvops->set_pd_rx(dev, false); 1327 + out_disable_mux: 1328 + dev_err(dev, "TCPM: CC connected in %s as DFP\n", 1329 + polarity ? "CC2" : "CC1"); 1330 + return 0; 1331 + } 1332 + 1333 + static inline void tcpm_typec_disconnect(struct tcpm_port *port) 1334 + { 1335 + if (port->connected) { 1336 + port->partner = NULL; 1337 + port->connected = false; 1338 + } 1339 + } 1340 + 1341 + static void tcpm_reset_port(struct udevice *dev) 1342 + { 1343 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1344 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1345 + 1346 + tcpm_timer_uninit(dev); 1347 + tcpm_typec_disconnect(port); 1348 + tcpm_reset_event_cnt(dev); 1349 + port->wait_dr_swap_message = false; 1350 + port->attached = false; 1351 + port->pd_capable = false; 1352 + 1353 + /* 1354 + * First Rx ID should be 0; set this to a sentinel of -1 so that 1355 + * we can check tcpm_pd_rx_handler() if we had seen it before. 1356 + */ 1357 + port->rx_msgid = -1; 1358 + 1359 + drvops->set_pd_rx(dev, false); 1360 + tcpm_init_vbus(dev); /* also disables charging */ 1361 + tcpm_init_vconn(dev); 1362 + tcpm_set_current_limit(dev, 0, 0); 1363 + tcpm_set_polarity(dev, TYPEC_POLARITY_CC1); 1364 + tcpm_set_attached_state(dev, false); 1365 + port->nr_sink_caps = 0; 1366 + } 1367 + 1368 + static void tcpm_detach(struct udevice *dev) 1369 + { 1370 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1371 + 1372 + if (tcpm_port_is_disconnected(port)) 1373 + port->hard_reset_count = 0; 1374 + 1375 + if (!port->attached) 1376 + return; 1377 + 1378 + tcpm_reset_port(dev); 1379 + } 1380 + 1381 + static void tcpm_src_detach(struct udevice *dev) 1382 + { 1383 + tcpm_detach(dev); 1384 + } 1385 + 1386 + static int tcpm_snk_attach(struct udevice *dev) 1387 + { 1388 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1389 + int ret; 1390 + 1391 + if (port->attached) 1392 + return 0; 1393 + 1394 + ret = tcpm_set_polarity(dev, port->cc2 != TYPEC_CC_OPEN ? 1395 + TYPEC_POLARITY_CC2 : TYPEC_POLARITY_CC1); 1396 + if (ret < 0) 1397 + return ret; 1398 + 1399 + ret = tcpm_set_roles(dev, true, TYPEC_SINK, TYPEC_DEVICE); 1400 + if (ret < 0) 1401 + return ret; 1402 + 1403 + port->pd_capable = false; 1404 + 1405 + port->partner = NULL; 1406 + 1407 + port->attached = true; 1408 + dev_info(dev, "TCPM: CC connected in %s as UFP\n", 1409 + port->cc1 != TYPEC_CC_OPEN ? "CC1" : "CC2"); 1410 + 1411 + return 0; 1412 + } 1413 + 1414 + static void tcpm_snk_detach(struct udevice *dev) 1415 + { 1416 + tcpm_detach(dev); 1417 + } 1418 + 1419 + static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) 1420 + { 1421 + if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) 1422 + return HARD_RESET_SEND; 1423 + if (port->pd_capable) 1424 + return ERROR_RECOVERY; 1425 + if (port->pwr_role == TYPEC_SOURCE) 1426 + return SRC_UNATTACHED; 1427 + if (port->state == SNK_WAIT_CAPABILITIES) 1428 + return SNK_READY; 1429 + return SNK_UNATTACHED; 1430 + } 1431 + 1432 + static inline enum tcpm_state unattached_state(struct tcpm_port *port) 1433 + { 1434 + if (port->port_type == TYPEC_PORT_DRP) { 1435 + if (port->pwr_role == TYPEC_SOURCE) 1436 + return SRC_UNATTACHED; 1437 + else 1438 + return SNK_UNATTACHED; 1439 + } else if (port->port_type == TYPEC_PORT_SRC) { 1440 + return SRC_UNATTACHED; 1441 + } 1442 + 1443 + return SNK_UNATTACHED; 1444 + } 1445 + 1446 + static void run_state_machine(struct udevice *dev) 1447 + { 1448 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 1449 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1450 + int ret; 1451 + 1452 + port->enter_state = port->state; 1453 + switch (port->state) { 1454 + case TOGGLING: 1455 + break; 1456 + /* SRC states */ 1457 + case SRC_UNATTACHED: 1458 + tcpm_src_detach(dev); 1459 + if (tcpm_start_toggling(dev, tcpm_rp_cc(port))) { 1460 + tcpm_set_state(dev, TOGGLING, 0); 1461 + break; 1462 + } 1463 + tcpm_set_cc(dev, tcpm_rp_cc(port)); 1464 + if (port->port_type == TYPEC_PORT_DRP) 1465 + tcpm_set_state(dev, SNK_UNATTACHED, PD_T_DRP_SNK); 1466 + break; 1467 + case SRC_ATTACH_WAIT: 1468 + if (tcpm_port_is_source(port)) 1469 + tcpm_set_state(dev, SRC_ATTACHED, PD_T_CC_DEBOUNCE); 1470 + break; 1471 + 1472 + case SRC_ATTACHED: 1473 + ret = tcpm_src_attach(dev); 1474 + /* 1475 + * Currently, vbus control is not implemented, 1476 + * and the SRC detection process cannot be fully implemented. 1477 + */ 1478 + tcpm_set_state(dev, SRC_READY, 0); 1479 + break; 1480 + case SRC_STARTUP: 1481 + port->caps_count = 0; 1482 + port->negotiated_rev = PD_MAX_REV; 1483 + port->message_id = 0; 1484 + port->rx_msgid = -1; 1485 + port->explicit_contract = false; 1486 + tcpm_set_state(dev, SRC_SEND_CAPABILITIES, 0); 1487 + break; 1488 + case SRC_SEND_CAPABILITIES: 1489 + port->caps_count++; 1490 + if (port->caps_count > PD_N_CAPS_COUNT) { 1491 + tcpm_set_state(dev, SRC_READY, 0); 1492 + break; 1493 + } 1494 + ret = tcpm_pd_send_source_caps(dev); 1495 + if (ret < 0) { 1496 + tcpm_set_state(dev, SRC_SEND_CAPABILITIES, 1497 + PD_T_SEND_SOURCE_CAP); 1498 + } else { 1499 + /* 1500 + * Per standard, we should clear the reset counter here. 1501 + * However, that can result in state machine hang-ups. 1502 + * Reset it only in READY state to improve stability. 1503 + */ 1504 + /* port->hard_reset_count = 0; */ 1505 + port->caps_count = 0; 1506 + port->pd_capable = true; 1507 + tcpm_set_state_cond(dev, SRC_SEND_CAPABILITIES_TIMEOUT, 1508 + PD_T_SEND_SOURCE_CAP); 1509 + } 1510 + break; 1511 + case SRC_SEND_CAPABILITIES_TIMEOUT: 1512 + /* 1513 + * Error recovery for a PD_DATA_SOURCE_CAP reply timeout. 1514 + * 1515 + * PD 2.0 sinks are supposed to accept src-capabilities with a 1516 + * 3.0 header and simply ignore any src PDOs which the sink does 1517 + * not understand such as PPS but some 2.0 sinks instead ignore 1518 + * the entire PD_DATA_SOURCE_CAP message, causing contract 1519 + * negotiation to fail. 1520 + * 1521 + * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try 1522 + * sending src-capabilities with a lower PD revision to 1523 + * make these broken sinks work. 1524 + */ 1525 + if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) { 1526 + tcpm_set_state(dev, HARD_RESET_SEND, 0); 1527 + } else if (port->negotiated_rev > PD_REV20) { 1528 + port->negotiated_rev--; 1529 + port->hard_reset_count = 0; 1530 + tcpm_set_state(dev, SRC_SEND_CAPABILITIES, 0); 1531 + } else { 1532 + tcpm_set_state(dev, hard_reset_state(port), 0); 1533 + } 1534 + break; 1535 + case SRC_NEGOTIATE_CAPABILITIES: 1536 + ret = tcpm_pd_check_request(dev); 1537 + if (ret < 0) { 1538 + tcpm_pd_send_control(dev, PD_CTRL_REJECT); 1539 + if (!port->explicit_contract) { 1540 + tcpm_set_state(dev, 1541 + SRC_WAIT_NEW_CAPABILITIES, 0); 1542 + } else { 1543 + tcpm_set_state(dev, SRC_READY, 0); 1544 + } 1545 + } else { 1546 + tcpm_pd_send_control(dev, PD_CTRL_ACCEPT); 1547 + tcpm_set_state(dev, SRC_TRANSITION_SUPPLY, 1548 + PD_T_SRC_TRANSITION); 1549 + } 1550 + break; 1551 + case SRC_TRANSITION_SUPPLY: 1552 + /* XXX: regulator_set_voltage(vbus, ...) */ 1553 + tcpm_pd_send_control(dev, PD_CTRL_PS_RDY); 1554 + port->explicit_contract = true; 1555 + tcpm_set_state_cond(dev, SRC_READY, 0); 1556 + break; 1557 + case SRC_READY: 1558 + port->hard_reset_count = 0; 1559 + 1560 + tcpm_typec_connect(port); 1561 + break; 1562 + case SRC_WAIT_NEW_CAPABILITIES: 1563 + /* Nothing to do... */ 1564 + break; 1565 + 1566 + /* SNK states */ 1567 + case SNK_UNATTACHED: 1568 + tcpm_snk_detach(dev); 1569 + if (tcpm_start_toggling(dev, TYPEC_CC_RD)) { 1570 + tcpm_set_state(dev, TOGGLING, 0); 1571 + break; 1572 + } 1573 + tcpm_set_cc(dev, TYPEC_CC_RD); 1574 + if (port->port_type == TYPEC_PORT_DRP) 1575 + tcpm_set_state(dev, SRC_UNATTACHED, PD_T_DRP_SRC); 1576 + break; 1577 + case SNK_ATTACH_WAIT: 1578 + if ((port->cc1 == TYPEC_CC_OPEN && 1579 + port->cc2 != TYPEC_CC_OPEN) || 1580 + (port->cc1 != TYPEC_CC_OPEN && 1581 + port->cc2 == TYPEC_CC_OPEN)) 1582 + tcpm_set_state(dev, SNK_DEBOUNCED, 1583 + PD_T_CC_DEBOUNCE); 1584 + else if (tcpm_port_is_disconnected(port)) 1585 + tcpm_set_state(dev, SNK_UNATTACHED, 1586 + PD_T_CC_DEBOUNCE); 1587 + break; 1588 + case SNK_DEBOUNCED: 1589 + if (tcpm_port_is_disconnected(port)) 1590 + tcpm_set_state(dev, SNK_UNATTACHED, PD_T_PD_DEBOUNCE); 1591 + else if (port->vbus_present) 1592 + tcpm_set_state(dev, SNK_ATTACHED, 0); 1593 + else 1594 + /* Wait for VBUS, but not forever */ 1595 + tcpm_set_state(dev, PORT_RESET, PD_T_PS_SOURCE_ON); 1596 + break; 1597 + case SNK_ATTACHED: 1598 + ret = tcpm_snk_attach(dev); 1599 + if (ret < 0) 1600 + tcpm_set_state(dev, SNK_UNATTACHED, 0); 1601 + else 1602 + tcpm_set_state(dev, SNK_STARTUP, 0); 1603 + break; 1604 + case SNK_STARTUP: 1605 + port->negotiated_rev = PD_MAX_REV; 1606 + port->message_id = 0; 1607 + port->rx_msgid = -1; 1608 + port->explicit_contract = false; 1609 + tcpm_set_state(dev, SNK_DISCOVERY, 0); 1610 + break; 1611 + case SNK_DISCOVERY: 1612 + if (port->vbus_present) { 1613 + tcpm_set_current_limit(dev, 1614 + tcpm_get_current_limit(port), 1615 + 5000); 1616 + tcpm_set_charge(dev, true); 1617 + tcpm_set_state(dev, SNK_WAIT_CAPABILITIES, 0); 1618 + break; 1619 + } 1620 + /* 1621 + * For DRP, timeouts differ. Also, handling is supposed to be 1622 + * different and much more complex (dead battery detection; 1623 + * see USB power delivery specification, section 8.3.3.6.1.5.1). 1624 + */ 1625 + tcpm_set_state(dev, hard_reset_state(port), 1626 + port->port_type == TYPEC_PORT_DRP ? 1627 + PD_T_DB_DETECT : PD_T_NO_RESPONSE); 1628 + break; 1629 + case SNK_DISCOVERY_DEBOUNCE: 1630 + tcpm_set_state(dev, SNK_DISCOVERY_DEBOUNCE_DONE, 1631 + PD_T_CC_DEBOUNCE); 1632 + break; 1633 + case SNK_DISCOVERY_DEBOUNCE_DONE: 1634 + tcpm_set_state(dev, unattached_state(port), 0); 1635 + break; 1636 + case SNK_WAIT_CAPABILITIES: 1637 + ret = drvops->set_pd_rx(dev, true); 1638 + if (ret < 0) { 1639 + tcpm_set_state(dev, SNK_READY, 0); 1640 + break; 1641 + } 1642 + /* 1643 + * If VBUS has never been low, and we time out waiting 1644 + * for source cap, try a soft reset first, in case we 1645 + * were already in a stable contract before this boot. 1646 + * Do this only once. 1647 + */ 1648 + if (port->vbus_never_low) { 1649 + port->vbus_never_low = false; 1650 + tcpm_set_state(dev, SOFT_RESET_SEND, 1651 + PD_T_SINK_WAIT_CAP); 1652 + } else { 1653 + tcpm_set_state(dev, hard_reset_state(port), 1654 + PD_T_SINK_WAIT_CAP); 1655 + } 1656 + break; 1657 + case SNK_NEGOTIATE_CAPABILITIES: 1658 + port->pd_capable = true; 1659 + port->hard_reset_count = 0; 1660 + ret = tcpm_pd_send_request(dev); 1661 + if (ret < 0) { 1662 + /* Let the Source send capabilities again. */ 1663 + tcpm_set_state(dev, SNK_WAIT_CAPABILITIES, 0); 1664 + } else { 1665 + tcpm_set_state_cond(dev, hard_reset_state(port), 1666 + PD_T_SENDER_RESPONSE); 1667 + } 1668 + break; 1669 + case SNK_TRANSITION_SINK: 1670 + case SNK_TRANSITION_SINK_VBUS: 1671 + tcpm_set_state(dev, hard_reset_state(port), 1672 + PD_T_PS_TRANSITION); 1673 + break; 1674 + case SNK_READY: 1675 + port->update_sink_caps = false; 1676 + tcpm_typec_connect(port); 1677 + /* 1678 + * Here poll_event_cnt is cleared, waiting for self-powered Type-C devices 1679 + * to send DR_swap Messge until 1s (TCPM_POLL_EVENT_TIME_OUT * 500us)timeout 1680 + */ 1681 + if (port->wait_dr_swap_message) 1682 + tcpm_reset_event_cnt(dev); 1683 + 1684 + break; 1685 + 1686 + /* Hard_Reset states */ 1687 + case HARD_RESET_SEND: 1688 + tcpm_pd_transmit(dev, TCPC_TX_HARD_RESET, NULL); 1689 + tcpm_set_state(dev, HARD_RESET_START, 0); 1690 + port->wait_dr_swap_message = false; 1691 + break; 1692 + case HARD_RESET_START: 1693 + port->hard_reset_count++; 1694 + drvops->set_pd_rx(dev, false); 1695 + port->nr_sink_caps = 0; 1696 + if (port->pwr_role == TYPEC_SOURCE) 1697 + tcpm_set_state(dev, SRC_HARD_RESET_VBUS_OFF, 1698 + PD_T_PS_HARD_RESET); 1699 + else 1700 + tcpm_set_state(dev, SNK_HARD_RESET_SINK_OFF, 0); 1701 + break; 1702 + case SRC_HARD_RESET_VBUS_OFF: 1703 + tcpm_set_vconn(dev, true); 1704 + tcpm_set_vbus(dev, false); 1705 + tcpm_set_roles(dev, port->self_powered, TYPEC_SOURCE, 1706 + TYPEC_HOST); 1707 + tcpm_set_state(dev, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); 1708 + break; 1709 + case SRC_HARD_RESET_VBUS_ON: 1710 + tcpm_set_vconn(dev, true); 1711 + tcpm_set_vbus(dev, true); 1712 + drvops->set_pd_rx(dev, true); 1713 + tcpm_set_attached_state(dev, true); 1714 + tcpm_set_state(dev, SRC_UNATTACHED, PD_T_PS_SOURCE_ON); 1715 + break; 1716 + case SNK_HARD_RESET_SINK_OFF: 1717 + tcpm_set_vconn(dev, false); 1718 + if (port->pd_capable) 1719 + tcpm_set_charge(dev, false); 1720 + tcpm_set_roles(dev, port->self_powered, TYPEC_SINK, 1721 + TYPEC_DEVICE); 1722 + /* 1723 + * VBUS may or may not toggle, depending on the adapter. 1724 + * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON 1725 + * directly after timeout. 1726 + */ 1727 + tcpm_set_state(dev, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V); 1728 + break; 1729 + case SNK_HARD_RESET_WAIT_VBUS: 1730 + /* Assume we're disconnected if VBUS doesn't come back. */ 1731 + tcpm_set_state(dev, SNK_UNATTACHED, 1732 + PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON); 1733 + break; 1734 + case SNK_HARD_RESET_SINK_ON: 1735 + /* Note: There is no guarantee that VBUS is on in this state */ 1736 + /* 1737 + * XXX: 1738 + * The specification suggests that dual mode ports in sink 1739 + * mode should transition to state PE_SRC_Transition_to_default. 1740 + * See USB power delivery specification chapter 8.3.3.6.1.3. 1741 + * This would mean to 1742 + * - turn off VCONN, reset power supply 1743 + * - request hardware reset 1744 + * - turn on VCONN 1745 + * - Transition to state PE_Src_Startup 1746 + * SNK only ports shall transition to state Snk_Startup 1747 + * (see chapter 8.3.3.3.8). 1748 + * Similar, dual-mode ports in source mode should transition 1749 + * to PE_SNK_Transition_to_default. 1750 + */ 1751 + if (port->pd_capable) { 1752 + tcpm_set_current_limit(dev, 1753 + tcpm_get_current_limit(port), 1754 + 5000); 1755 + tcpm_set_charge(dev, true); 1756 + } 1757 + tcpm_set_attached_state(dev, true); 1758 + tcpm_set_state(dev, SNK_STARTUP, 0); 1759 + break; 1760 + 1761 + /* Soft_Reset states */ 1762 + case SOFT_RESET: 1763 + port->message_id = 0; 1764 + port->rx_msgid = -1; 1765 + tcpm_pd_send_control(dev, PD_CTRL_ACCEPT); 1766 + if (port->pwr_role == TYPEC_SOURCE) 1767 + tcpm_set_state(dev, SRC_SEND_CAPABILITIES, 0); 1768 + else 1769 + tcpm_set_state(dev, SNK_WAIT_CAPABILITIES, 0); 1770 + break; 1771 + case SOFT_RESET_SEND: 1772 + port->message_id = 0; 1773 + port->rx_msgid = -1; 1774 + if (tcpm_pd_send_control(dev, PD_CTRL_SOFT_RESET)) 1775 + tcpm_set_state_cond(dev, hard_reset_state(port), 0); 1776 + else 1777 + tcpm_set_state_cond(dev, hard_reset_state(port), 1778 + PD_T_SENDER_RESPONSE); 1779 + break; 1780 + 1781 + /* DR_Swap states */ 1782 + case DR_SWAP_ACCEPT: 1783 + tcpm_pd_send_control(dev, PD_CTRL_ACCEPT); 1784 + tcpm_set_state_cond(dev, DR_SWAP_CHANGE_DR, 0); 1785 + break; 1786 + case DR_SWAP_CHANGE_DR: 1787 + if (port->data_role == TYPEC_HOST) { 1788 + tcpm_set_roles(dev, true, port->pwr_role, 1789 + TYPEC_DEVICE); 1790 + } else { 1791 + tcpm_set_roles(dev, true, port->pwr_role, 1792 + TYPEC_HOST); 1793 + } 1794 + /* DR_swap process complete, wait_dr_swap_message is cleared */ 1795 + port->wait_dr_swap_message = false; 1796 + tcpm_set_state(dev, ready_state(port), 0); 1797 + break; 1798 + case ERROR_RECOVERY: 1799 + tcpm_set_state(dev, PORT_RESET, 0); 1800 + break; 1801 + case PORT_RESET: 1802 + tcpm_reset_port(dev); 1803 + if (port->self_powered) 1804 + tcpm_set_cc(dev, TYPEC_CC_OPEN); 1805 + else 1806 + tcpm_set_cc(dev, tcpm_default_state(port) == SNK_UNATTACHED ? 1807 + TYPEC_CC_RD : tcpm_rp_cc(port)); 1808 + tcpm_set_state(dev, PORT_RESET_WAIT_OFF, 1809 + PD_T_ERROR_RECOVERY); 1810 + break; 1811 + case PORT_RESET_WAIT_OFF: 1812 + tcpm_set_state(dev, 1813 + tcpm_default_state(port), 1814 + port->vbus_present ? PD_T_PS_SOURCE_OFF : 0); 1815 + break; 1816 + default: 1817 + dev_err(dev, "TCPM: Unexpected port state %d\n", port->state); 1818 + break; 1819 + } 1820 + } 1821 + 1822 + static void tcpm_state_machine(struct udevice *dev) 1823 + { 1824 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1825 + enum tcpm_state prev_state; 1826 + 1827 + mutex_lock(&port->lock); 1828 + port->state_machine_running = true; 1829 + 1830 + if (port->queued_message && tcpm_send_queued_message(dev)) 1831 + goto done; 1832 + 1833 + /* If we were queued due to a delayed state change, update it now */ 1834 + if (port->delayed_state) { 1835 + dev_dbg(dev, "TCPM: state change %s -> %s [delayed %ld ms]\n", 1836 + tcpm_states[port->state], 1837 + tcpm_states[port->delayed_state], port->delay_ms); 1838 + port->prev_state = port->state; 1839 + port->state = port->delayed_state; 1840 + port->delayed_state = INVALID_STATE; 1841 + } 1842 + 1843 + /* 1844 + * Continue running as long as we have (non-delayed) state changes 1845 + * to make. 1846 + */ 1847 + do { 1848 + prev_state = port->state; 1849 + run_state_machine(dev); 1850 + if (port->queued_message) 1851 + tcpm_send_queued_message(dev); 1852 + } while (port->state != prev_state && !port->delayed_state); 1853 + 1854 + done: 1855 + port->state_machine_running = false; 1856 + mutex_unlock(&port->lock); 1857 + } 1858 + 1859 + static void _tcpm_cc_change(struct udevice *dev, enum typec_cc_status cc1, 1860 + enum typec_cc_status cc2) 1861 + { 1862 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1863 + enum typec_cc_status old_cc1, old_cc2; 1864 + enum tcpm_state new_state; 1865 + 1866 + old_cc1 = port->cc1; 1867 + old_cc2 = port->cc2; 1868 + port->cc1 = cc1; 1869 + port->cc2 = cc2; 1870 + 1871 + dev_dbg(dev, "TCPM: CC1: %u -> %u, CC2: %u -> %u [state %s, polarity %d, %s]\n", 1872 + old_cc1, cc1, old_cc2, cc2, tcpm_states[port->state], 1873 + port->polarity, 1874 + tcpm_port_is_disconnected(port) ? "disconnected" : "connected"); 1875 + 1876 + switch (port->state) { 1877 + case TOGGLING: 1878 + if (tcpm_port_is_source(port)) 1879 + tcpm_set_state(dev, SRC_ATTACH_WAIT, 0); 1880 + else if (tcpm_port_is_sink(port)) 1881 + tcpm_set_state(dev, SNK_ATTACH_WAIT, 0); 1882 + break; 1883 + case SRC_UNATTACHED: 1884 + case SRC_ATTACH_WAIT: 1885 + if (tcpm_port_is_disconnected(port)) 1886 + tcpm_set_state(dev, SRC_UNATTACHED, 0); 1887 + else if (cc1 != old_cc1 || cc2 != old_cc2) 1888 + tcpm_set_state(dev, SRC_ATTACH_WAIT, 0); 1889 + break; 1890 + case SRC_ATTACHED: 1891 + case SRC_SEND_CAPABILITIES: 1892 + case SRC_READY: 1893 + if (tcpm_port_is_disconnected(port) || 1894 + !tcpm_port_is_source(port)) 1895 + tcpm_set_state(dev, SRC_UNATTACHED, 0); 1896 + break; 1897 + case SNK_UNATTACHED: 1898 + if (tcpm_port_is_sink(port)) 1899 + tcpm_set_state(dev, SNK_ATTACH_WAIT, 0); 1900 + break; 1901 + case SNK_ATTACH_WAIT: 1902 + if ((port->cc1 == TYPEC_CC_OPEN && 1903 + port->cc2 != TYPEC_CC_OPEN) || 1904 + (port->cc1 != TYPEC_CC_OPEN && 1905 + port->cc2 == TYPEC_CC_OPEN)) 1906 + new_state = SNK_DEBOUNCED; 1907 + else if (tcpm_port_is_disconnected(port)) 1908 + new_state = SNK_UNATTACHED; 1909 + else 1910 + break; 1911 + if (new_state != port->delayed_state) 1912 + tcpm_set_state(dev, SNK_ATTACH_WAIT, 0); 1913 + break; 1914 + case SNK_DEBOUNCED: 1915 + if (tcpm_port_is_disconnected(port)) 1916 + new_state = SNK_UNATTACHED; 1917 + else if (port->vbus_present) 1918 + new_state = tcpm_try_src(port) ? INVALID_STATE : SNK_ATTACHED; 1919 + else 1920 + new_state = SNK_UNATTACHED; 1921 + if (new_state != port->delayed_state) 1922 + tcpm_set_state(dev, SNK_DEBOUNCED, 0); 1923 + break; 1924 + case SNK_READY: 1925 + if (tcpm_port_is_disconnected(port)) 1926 + tcpm_set_state(dev, unattached_state(port), 0); 1927 + else if (!port->pd_capable && 1928 + (cc1 != old_cc1 || cc2 != old_cc2)) 1929 + tcpm_set_current_limit(dev, 1930 + tcpm_get_current_limit(port), 1931 + 5000); 1932 + break; 1933 + 1934 + case SNK_DISCOVERY: 1935 + /* CC line is unstable, wait for debounce */ 1936 + if (tcpm_port_is_disconnected(port)) 1937 + tcpm_set_state(dev, SNK_DISCOVERY_DEBOUNCE, 0); 1938 + break; 1939 + case SNK_DISCOVERY_DEBOUNCE: 1940 + break; 1941 + 1942 + case PORT_RESET: 1943 + case PORT_RESET_WAIT_OFF: 1944 + /* 1945 + * State set back to default mode once the timer completes. 1946 + * Ignore CC changes here. 1947 + */ 1948 + break; 1949 + default: 1950 + /* 1951 + * While acting as sink and auto vbus discharge is enabled, Allow disconnect 1952 + * to be driven by vbus disconnect. 1953 + */ 1954 + if (tcpm_port_is_disconnected(port)) 1955 + tcpm_set_state(dev, unattached_state(port), 0); 1956 + break; 1957 + } 1958 + } 1959 + 1960 + static void _tcpm_pd_vbus_on(struct udevice *dev) 1961 + { 1962 + struct tcpm_port *port = dev_get_uclass_plat(dev); 1963 + 1964 + dev_dbg(dev, "TCPM: VBUS on event\n"); 1965 + port->vbus_present = true; 1966 + /* 1967 + * When vbus_present is true i.e. Voltage at VBUS is greater than VSAFE5V implicitly 1968 + * states that vbus is not at VSAFE0V, hence clear the vbus_vsafe0v flag here. 1969 + */ 1970 + port->vbus_vsafe0v = false; 1971 + 1972 + switch (port->state) { 1973 + case SNK_TRANSITION_SINK_VBUS: 1974 + port->explicit_contract = true; 1975 + tcpm_set_state(dev, SNK_READY, 0); 1976 + break; 1977 + case SNK_DISCOVERY: 1978 + tcpm_set_state(dev, SNK_DISCOVERY, 0); 1979 + break; 1980 + case SNK_DEBOUNCED: 1981 + tcpm_set_state(dev, SNK_ATTACHED, 0); 1982 + break; 1983 + case SNK_HARD_RESET_WAIT_VBUS: 1984 + tcpm_set_state(dev, SNK_HARD_RESET_SINK_ON, 0); 1985 + break; 1986 + case SRC_ATTACHED: 1987 + tcpm_set_state(dev, SRC_STARTUP, 0); 1988 + break; 1989 + case SRC_HARD_RESET_VBUS_ON: 1990 + tcpm_set_state(dev, SRC_STARTUP, 0); 1991 + break; 1992 + 1993 + case PORT_RESET: 1994 + case PORT_RESET_WAIT_OFF: 1995 + /* 1996 + * State set back to default mode once the timer completes. 1997 + * Ignore vbus changes here. 1998 + */ 1999 + break; 2000 + 2001 + default: 2002 + break; 2003 + } 2004 + } 2005 + 2006 + static void _tcpm_pd_vbus_off(struct udevice *dev) 2007 + { 2008 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2009 + 2010 + dev_dbg(dev, "TCPM: VBUS off event\n"); 2011 + port->vbus_present = false; 2012 + port->vbus_never_low = false; 2013 + switch (port->state) { 2014 + case SNK_HARD_RESET_SINK_OFF: 2015 + tcpm_set_state(dev, SNK_HARD_RESET_WAIT_VBUS, 0); 2016 + break; 2017 + case HARD_RESET_SEND: 2018 + break; 2019 + case SNK_ATTACH_WAIT: 2020 + tcpm_set_state(dev, SNK_UNATTACHED, 0); 2021 + break; 2022 + 2023 + case SNK_NEGOTIATE_CAPABILITIES: 2024 + break; 2025 + 2026 + case PORT_RESET_WAIT_OFF: 2027 + tcpm_set_state(dev, tcpm_default_state(port), 0); 2028 + break; 2029 + 2030 + case PORT_RESET: 2031 + /* 2032 + * State set back to default mode once the timer completes. 2033 + * Ignore vbus changes here. 2034 + */ 2035 + break; 2036 + 2037 + default: 2038 + if (port->pwr_role == TYPEC_SINK && port->attached) 2039 + tcpm_set_state(dev, SNK_UNATTACHED, 0); 2040 + break; 2041 + } 2042 + } 2043 + 2044 + void tcpm_cc_change(struct udevice *dev) 2045 + { 2046 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 2047 + enum typec_cc_status cc1, cc2; 2048 + 2049 + tcpm_reset_event_cnt(dev); 2050 + if (drvops->get_cc(dev, &cc1, &cc2) == 0) 2051 + _tcpm_cc_change(dev, cc1, cc2); 2052 + } 2053 + 2054 + void tcpm_vbus_change(struct udevice *dev) 2055 + { 2056 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 2057 + bool vbus; 2058 + 2059 + tcpm_reset_event_cnt(dev); 2060 + vbus = drvops->get_vbus(dev); 2061 + if (vbus) 2062 + _tcpm_pd_vbus_on(dev); 2063 + else 2064 + _tcpm_pd_vbus_off(dev); 2065 + } 2066 + 2067 + void tcpm_pd_hard_reset(struct udevice *dev) 2068 + { 2069 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2070 + 2071 + tcpm_reset_event_cnt(dev); 2072 + dev_dbg(dev, "TCPM: Received hard reset\n"); 2073 + 2074 + /* If a hard reset message is received during the port reset process, 2075 + * we should ignore it, that is, do not set port->state to HARD_RESET_START. 2076 + */ 2077 + if (port->state == PORT_RESET || port->state == PORT_RESET_WAIT_OFF) 2078 + return; 2079 + 2080 + /* 2081 + * If we keep receiving hard reset requests, executing the hard reset 2082 + * must have failed. Revert to error recovery if that happens. 2083 + */ 2084 + tcpm_set_state(dev, 2085 + port->hard_reset_count < PD_N_HARD_RESET_COUNT ? 2086 + HARD_RESET_START : ERROR_RECOVERY, 2087 + 0); 2088 + } 2089 + 2090 + static void tcpm_init(struct udevice *dev) 2091 + { 2092 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 2093 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2094 + enum typec_cc_status cc1, cc2; 2095 + 2096 + drvops->init(dev); 2097 + 2098 + tcpm_reset_port(dev); 2099 + 2100 + /* 2101 + * XXX 2102 + * Should possibly wait for VBUS to settle if it was enabled locally 2103 + * since tcpm_reset_port() will disable VBUS. 2104 + */ 2105 + port->vbus_present = drvops->get_vbus(dev); 2106 + if (port->vbus_present) 2107 + port->vbus_never_low = true; 2108 + 2109 + /* 2110 + * 1. When vbus_present is true, voltage on VBUS is already at VSAFE5V. 2111 + * So implicitly vbus_vsafe0v = false. 2112 + * 2113 + * 2. When vbus_present is false and TCPC does NOT support querying 2114 + * vsafe0v status, then, it's best to assume vbus is at VSAFE0V i.e. 2115 + * vbus_vsafe0v is true. 2116 + * 2117 + * 3. When vbus_present is false and TCPC does support querying vsafe0v, 2118 + * then, query tcpc for vsafe0v status. 2119 + */ 2120 + if (port->vbus_present) 2121 + port->vbus_vsafe0v = false; 2122 + else 2123 + port->vbus_vsafe0v = true; 2124 + 2125 + tcpm_set_state(dev, tcpm_default_state(port), 0); 2126 + 2127 + if (drvops->get_cc(dev, &cc1, &cc2) == 0) 2128 + _tcpm_cc_change(dev, cc1, cc2); 2129 + } 2130 + 2131 + static int tcpm_fw_get_caps(struct udevice *dev) 2132 + { 2133 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 2134 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2135 + ofnode node; 2136 + const char *cap_str; 2137 + int ret; 2138 + u32 mw; 2139 + 2140 + ret = drvops->get_connector_node(dev, &node); 2141 + if (ret) 2142 + return ret; 2143 + 2144 + cap_str = ofnode_read_string(node, "power-role"); 2145 + if (!cap_str) 2146 + return -EINVAL; 2147 + 2148 + if (!strcmp("dual", cap_str)) 2149 + port->typec_type = TYPEC_PORT_DRP; 2150 + else if (!strcmp("source", cap_str)) 2151 + port->typec_type = TYPEC_PORT_SRC; 2152 + else if (!strcmp("sink", cap_str)) 2153 + port->typec_type = TYPEC_PORT_SNK; 2154 + else 2155 + return -EINVAL; 2156 + 2157 + port->port_type = port->typec_type; 2158 + 2159 + if (port->port_type == TYPEC_PORT_SNK) 2160 + goto sink; 2161 + 2162 + /* Get source pdos */ 2163 + ret = ofnode_read_size(node, "source-pdos") / sizeof(u32); 2164 + if (ret <= 0) 2165 + return -EINVAL; 2166 + 2167 + port->nr_src_pdo = min(ret, PDO_MAX_OBJECTS); 2168 + ret = ofnode_read_u32_array(node, "source-pdos", 2169 + port->src_pdo, port->nr_src_pdo); 2170 + if (ret || tcpm_validate_caps(dev, port->src_pdo, port->nr_src_pdo)) 2171 + return -EINVAL; 2172 + 2173 + if (port->port_type == TYPEC_PORT_SRC) 2174 + return 0; 2175 + 2176 + /* Get the preferred power role for DRP */ 2177 + cap_str = ofnode_read_string(node, "try-power-role"); 2178 + if (!cap_str) 2179 + return -EINVAL; 2180 + 2181 + if (!strcmp("sink", cap_str)) 2182 + port->typec_prefer_role = TYPEC_SINK; 2183 + else if (!strcmp("source", cap_str)) 2184 + port->typec_prefer_role = TYPEC_SOURCE; 2185 + else 2186 + return -EINVAL; 2187 + 2188 + if (port->typec_prefer_role < 0) 2189 + return -EINVAL; 2190 + sink: 2191 + /* Get sink pdos */ 2192 + ret = ofnode_read_size(node, "sink-pdos") / sizeof(u32); 2193 + if (ret <= 0) 2194 + return -EINVAL; 2195 + 2196 + port->nr_snk_pdo = min(ret, PDO_MAX_OBJECTS); 2197 + ret = ofnode_read_u32_array(node, "sink-pdos", 2198 + port->snk_pdo, port->nr_snk_pdo); 2199 + if (ret || tcpm_validate_caps(dev, port->snk_pdo, port->nr_snk_pdo)) 2200 + return -EINVAL; 2201 + 2202 + if (ofnode_read_u32_array(node, "op-sink-microwatt", &mw, 1)) 2203 + return -EINVAL; 2204 + port->operating_snk_mw = mw / 1000; 2205 + 2206 + port->self_powered = ofnode_read_bool(node, "self-powered"); 2207 + 2208 + return 0; 2209 + } 2210 + 2211 + static int tcpm_port_init(struct udevice *dev) 2212 + { 2213 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2214 + int err; 2215 + 2216 + err = tcpm_fw_get_caps(dev); 2217 + if (err < 0) { 2218 + dev_err(dev, "TCPM: please check the dts config: %d\n", err); 2219 + return err; 2220 + } 2221 + 2222 + port->try_role = port->typec_prefer_role; 2223 + port->port_type = port->typec_type; 2224 + 2225 + tcpm_init(dev); 2226 + 2227 + dev_info(dev, "TCPM: init finished\n"); 2228 + 2229 + return 0; 2230 + } 2231 + 2232 + static void tcpm_poll_event(struct udevice *dev) 2233 + { 2234 + const struct dm_tcpm_ops *drvops = dev_get_driver_ops(dev); 2235 + struct tcpm_port *port = dev_get_uclass_plat(dev); 2236 + 2237 + if (!drvops->get_vbus(dev)) 2238 + return; 2239 + 2240 + while (port->poll_event_cnt < TCPM_POLL_EVENT_TIME_OUT) { 2241 + if (!port->wait_dr_swap_message && 2242 + (port->state == SNK_READY || port->state == SRC_READY)) 2243 + break; 2244 + 2245 + drvops->poll_event(dev); 2246 + port->poll_event_cnt++; 2247 + udelay(500); 2248 + tcpm_check_and_run_delayed_work(dev); 2249 + } 2250 + 2251 + if (port->state != SNK_READY && port->state != SRC_READY) 2252 + dev_warn(dev, "TCPM: exit in state %s\n", 2253 + tcpm_states[port->state]); 2254 + 2255 + /* 2256 + * At this time, call the callback function of the respective pd chip 2257 + * to enter the low-power mode. In order to reduce the time spent on 2258 + * the PD chip driver as much as possible, the tcpm framework does not 2259 + * fully process the communication initiated by the device,so it should 2260 + * be noted that we can disable the internal oscillator, etc., but do 2261 + * not turn off the power of the transceiver module, otherwise the 2262 + * self-powered Type-C device will initiate a Message(eg: self-powered 2263 + * Type-C hub initiates a SINK capability request(PD_CTRL_GET_SINK_CAP)) 2264 + * and the pd chip cannot reply to GoodCRC, causing the self-powered Type-C 2265 + * device to switch vbus to vSafe5v, or even turn off vbus. 2266 + */ 2267 + if (!drvops->enter_low_power_mode) 2268 + return; 2269 + 2270 + if (drvops->enter_low_power_mode(dev, port->attached, port->pd_capable)) 2271 + dev_err(dev, "TCPM: failed to enter low power\n"); 2272 + else 2273 + dev_info(dev, "TCPM: PD chip enter low power mode\n"); 2274 + } 2275 + 2276 + int tcpm_post_probe(struct udevice *dev) 2277 + { 2278 + int ret = tcpm_port_init(dev); 2279 + 2280 + if (ret < 0) { 2281 + dev_err(dev, "failed to tcpm port init\n"); 2282 + return ret; 2283 + } 2284 + 2285 + tcpm_poll_event(dev); 2286 + 2287 + return 0; 2288 + }
+1
include/dm/uclass-id.h
··· 139 139 UCLASS_SYSCON, /* System configuration device */ 140 140 UCLASS_SYSINFO, /* Device information from hardware */ 141 141 UCLASS_SYSRESET, /* System reset device */ 142 + UCLASS_TCPM, /* TypeC port manager */ 142 143 UCLASS_TEE, /* Trusted Execution Environment device */ 143 144 UCLASS_THERMAL, /* Thermal sensor */ 144 145 UCLASS_TIMER, /* Timer device */
+516
include/usb/pd.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright 2015-2017 Google, Inc 4 + */ 5 + 6 + #ifndef __LINUX_USB_PD_H 7 + #define __LINUX_USB_PD_H 8 + 9 + #include <linux/kernel.h> 10 + #include <linux/types.h> 11 + 12 + enum typec_port_type { 13 + TYPEC_PORT_SRC, 14 + TYPEC_PORT_SNK, 15 + TYPEC_PORT_DRP, 16 + }; 17 + 18 + enum typec_data_role { 19 + TYPEC_DEVICE, 20 + TYPEC_HOST, 21 + }; 22 + 23 + enum typec_role { 24 + TYPEC_SINK, 25 + TYPEC_SOURCE, 26 + }; 27 + 28 + /* USB PD Messages */ 29 + enum pd_ctrl_msg_type { 30 + /* 0 Reserved */ 31 + PD_CTRL_GOOD_CRC = 1, 32 + PD_CTRL_GOTO_MIN = 2, 33 + PD_CTRL_ACCEPT = 3, 34 + PD_CTRL_REJECT = 4, 35 + PD_CTRL_PING = 5, 36 + PD_CTRL_PS_RDY = 6, 37 + PD_CTRL_GET_SOURCE_CAP = 7, 38 + PD_CTRL_GET_SINK_CAP = 8, 39 + PD_CTRL_DR_SWAP = 9, 40 + PD_CTRL_PR_SWAP = 10, 41 + PD_CTRL_VCONN_SWAP = 11, 42 + PD_CTRL_WAIT = 12, 43 + PD_CTRL_SOFT_RESET = 13, 44 + /* 14-15 Reserved */ 45 + PD_CTRL_NOT_SUPP = 16, 46 + PD_CTRL_GET_SOURCE_CAP_EXT = 17, 47 + PD_CTRL_GET_STATUS = 18, 48 + PD_CTRL_FR_SWAP = 19, 49 + PD_CTRL_GET_PPS_STATUS = 20, 50 + PD_CTRL_GET_COUNTRY_CODES = 21, 51 + /* 22-31 Reserved */ 52 + }; 53 + 54 + enum pd_data_msg_type { 55 + /* 0 Reserved */ 56 + PD_DATA_SOURCE_CAP = 1, 57 + PD_DATA_REQUEST = 2, 58 + PD_DATA_BIST = 3, 59 + PD_DATA_SINK_CAP = 4, 60 + PD_DATA_BATT_STATUS = 5, 61 + PD_DATA_ALERT = 6, 62 + PD_DATA_GET_COUNTRY_INFO = 7, 63 + PD_DATA_ENTER_USB = 8, 64 + /* 9-14 Reserved */ 65 + PD_DATA_VENDOR_DEF = 15, 66 + /* 16-31 Reserved */ 67 + }; 68 + 69 + enum pd_ext_msg_type { 70 + /* 0 Reserved */ 71 + PD_EXT_SOURCE_CAP_EXT = 1, 72 + PD_EXT_STATUS = 2, 73 + PD_EXT_GET_BATT_CAP = 3, 74 + PD_EXT_GET_BATT_STATUS = 4, 75 + PD_EXT_BATT_CAP = 5, 76 + PD_EXT_GET_MANUFACTURER_INFO = 6, 77 + PD_EXT_MANUFACTURER_INFO = 7, 78 + PD_EXT_SECURITY_REQUEST = 8, 79 + PD_EXT_SECURITY_RESPONSE = 9, 80 + PD_EXT_FW_UPDATE_REQUEST = 10, 81 + PD_EXT_FW_UPDATE_RESPONSE = 11, 82 + PD_EXT_PPS_STATUS = 12, 83 + PD_EXT_COUNTRY_INFO = 13, 84 + PD_EXT_COUNTRY_CODES = 14, 85 + /* 15-31 Reserved */ 86 + }; 87 + 88 + #define PD_REV10 0x0 89 + #define PD_REV20 0x1 90 + #define PD_REV30 0x2 91 + #define PD_MAX_REV PD_REV30 92 + 93 + #define PD_HEADER_EXT_HDR BIT(15) 94 + #define PD_HEADER_CNT_SHIFT 12 95 + #define PD_HEADER_CNT_MASK 0x7 96 + #define PD_HEADER_ID_SHIFT 9 97 + #define PD_HEADER_ID_MASK 0x7 98 + #define PD_HEADER_PWR_ROLE BIT(8) 99 + #define PD_HEADER_REV_SHIFT 6 100 + #define PD_HEADER_REV_MASK 0x3 101 + #define PD_HEADER_DATA_ROLE BIT(5) 102 + #define PD_HEADER_TYPE_SHIFT 0 103 + #define PD_HEADER_TYPE_MASK 0x1f 104 + 105 + #define PD_HEADER(type, pwr, data, rev, id, cnt, ext_hdr) \ 106 + ((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ 107 + ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ 108 + ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ 109 + ((rev) << PD_HEADER_REV_SHIFT) | \ 110 + (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ 111 + (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \ 112 + ((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) 113 + 114 + #define PD_HEADER_LE(type, pwr, data, rev, id, cnt) \ 115 + cpu_to_le16(PD_HEADER((type), (pwr), (data), (rev), (id), (cnt), (0))) 116 + 117 + static inline unsigned int pd_header_cnt(u16 header) 118 + { 119 + return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK; 120 + } 121 + 122 + static inline unsigned int pd_header_cnt_le(__le16 header) 123 + { 124 + return pd_header_cnt(le16_to_cpu(header)); 125 + } 126 + 127 + static inline unsigned int pd_header_type(u16 header) 128 + { 129 + return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK; 130 + } 131 + 132 + static inline unsigned int pd_header_type_le(__le16 header) 133 + { 134 + return pd_header_type(le16_to_cpu(header)); 135 + } 136 + 137 + static inline unsigned int pd_header_msgid(u16 header) 138 + { 139 + return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK; 140 + } 141 + 142 + static inline unsigned int pd_header_msgid_le(__le16 header) 143 + { 144 + return pd_header_msgid(le16_to_cpu(header)); 145 + } 146 + 147 + static inline unsigned int pd_header_rev(u16 header) 148 + { 149 + return (header >> PD_HEADER_REV_SHIFT) & PD_HEADER_REV_MASK; 150 + } 151 + 152 + static inline unsigned int pd_header_rev_le(__le16 header) 153 + { 154 + return pd_header_rev(le16_to_cpu(header)); 155 + } 156 + 157 + #define PD_EXT_HDR_CHUNKED BIT(15) 158 + #define PD_EXT_HDR_CHUNK_NUM_SHIFT 11 159 + #define PD_EXT_HDR_CHUNK_NUM_MASK 0xf 160 + #define PD_EXT_HDR_REQ_CHUNK BIT(10) 161 + #define PD_EXT_HDR_DATA_SIZE_SHIFT 0 162 + #define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff 163 + 164 + #define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \ 165 + ((((data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) | \ 166 + ((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \ 167 + (((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) | \ 168 + ((chunked) ? PD_EXT_HDR_CHUNKED : 0)) 169 + 170 + #define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \ 171 + cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked))) 172 + 173 + static inline unsigned int pd_ext_header_chunk_num(u16 ext_header) 174 + { 175 + return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) & 176 + PD_EXT_HDR_CHUNK_NUM_MASK; 177 + } 178 + 179 + static inline unsigned int pd_ext_header_data_size(u16 ext_header) 180 + { 181 + return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) & 182 + PD_EXT_HDR_DATA_SIZE_MASK; 183 + } 184 + 185 + static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header) 186 + { 187 + return pd_ext_header_data_size(le16_to_cpu(ext_header)); 188 + } 189 + 190 + #define PD_MAX_PAYLOAD 7 191 + #define PD_EXT_MAX_CHUNK_DATA 26 192 + 193 + /* 194 + * struct pd_chunked_ext_message_data - PD chunked extended message data as 195 + * seen on wire 196 + * @header: PD extended message header 197 + * @data: PD extended message data 198 + */ 199 + struct pd_chunked_ext_message_data { 200 + __le16 header; 201 + u8 data[PD_EXT_MAX_CHUNK_DATA]; 202 + } __packed; 203 + 204 + /* 205 + * struct pd_message - PD message as seen on wire 206 + * @header: PD message header 207 + * @payload: PD message payload 208 + * @ext_msg: PD message chunked extended message data 209 + */ 210 + struct pd_message { 211 + __le16 header; 212 + union { 213 + __le32 payload[PD_MAX_PAYLOAD]; 214 + struct pd_chunked_ext_message_data ext_msg; 215 + }; 216 + } __packed; 217 + 218 + /* PDO: Power Data Object */ 219 + #define PDO_MAX_OBJECTS 7 220 + 221 + enum pd_pdo_type { 222 + PDO_TYPE_FIXED = 0, 223 + PDO_TYPE_BATT = 1, 224 + PDO_TYPE_VAR = 2, 225 + PDO_TYPE_APDO = 3, 226 + }; 227 + 228 + #define PDO_TYPE_SHIFT 30 229 + #define PDO_TYPE_MASK 0x3 230 + 231 + #define PDO_TYPE(t) ((t) << PDO_TYPE_SHIFT) 232 + 233 + #define PDO_VOLT_MASK 0x3ff 234 + #define PDO_CURR_MASK 0x3ff 235 + #define PDO_PWR_MASK 0x3ff 236 + 237 + #define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */ 238 + #define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */ 239 + #define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */ 240 + #define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */ 241 + #define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */ 242 + #define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */ 243 + #define PDO_FIXED_UNCHUNK_EXT BIT(24) /* Unchunked Extended Message supported (Source) */ 244 + #define PDO_FIXED_FRS_CURR_MASK (BIT(24) | BIT(23)) /* FR_Swap Current (Sink) */ 245 + #define PDO_FIXED_FRS_CURR_SHIFT 23 246 + #define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */ 247 + #define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */ 248 + 249 + #define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT) 250 + #define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT) 251 + 252 + #define PDO_FIXED(mv, ma, flags) \ 253 + (PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \ 254 + PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma)) 255 + 256 + #define VSAFE5V 5000 /* mv units */ 257 + 258 + #define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */ 259 + #define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */ 260 + #define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ 261 + 262 + #define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT) 263 + #define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT) 264 + #define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT) 265 + 266 + #define PDO_BATT(min_mv, max_mv, max_mw) \ 267 + (PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) | \ 268 + PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw)) 269 + 270 + #define PDO_VAR_MAX_VOLT_SHIFT 20 /* 50mV units */ 271 + #define PDO_VAR_MIN_VOLT_SHIFT 10 /* 50mV units */ 272 + #define PDO_VAR_MAX_CURR_SHIFT 0 /* 10mA units */ 273 + 274 + #define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT) 275 + #define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT) 276 + #define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT) 277 + 278 + #define PDO_VAR(min_mv, max_mv, max_ma) \ 279 + (PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \ 280 + PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma)) 281 + 282 + enum pd_apdo_type { 283 + APDO_TYPE_PPS = 0, 284 + }; 285 + 286 + #define PDO_APDO_TYPE_SHIFT 28 /* Only valid value currently is 0x0 - PPS */ 287 + #define PDO_APDO_TYPE_MASK 0x3 288 + 289 + #define PDO_APDO_TYPE(t) ((t) << PDO_APDO_TYPE_SHIFT) 290 + 291 + #define PDO_PPS_APDO_MAX_VOLT_SHIFT 17 /* 100mV units */ 292 + #define PDO_PPS_APDO_MIN_VOLT_SHIFT 8 /* 100mV units */ 293 + #define PDO_PPS_APDO_MAX_CURR_SHIFT 0 /* 50mA units */ 294 + 295 + #define PDO_PPS_APDO_VOLT_MASK 0xff 296 + #define PDO_PPS_APDO_CURR_MASK 0x7f 297 + 298 + #define PDO_PPS_APDO_MIN_VOLT(mv) \ 299 + ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MIN_VOLT_SHIFT) 300 + #define PDO_PPS_APDO_MAX_VOLT(mv) \ 301 + ((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MAX_VOLT_SHIFT) 302 + #define PDO_PPS_APDO_MAX_CURR(ma) \ 303 + ((((ma) / 50) & PDO_PPS_APDO_CURR_MASK) << PDO_PPS_APDO_MAX_CURR_SHIFT) 304 + 305 + #define PDO_PPS_APDO(min_mv, max_mv, max_ma) \ 306 + (PDO_TYPE(PDO_TYPE_APDO) | PDO_APDO_TYPE(APDO_TYPE_PPS) | \ 307 + PDO_PPS_APDO_MIN_VOLT(min_mv) | PDO_PPS_APDO_MAX_VOLT(max_mv) | \ 308 + PDO_PPS_APDO_MAX_CURR(max_ma)) 309 + 310 + static inline enum pd_pdo_type pdo_type(u32 pdo) 311 + { 312 + return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK; 313 + } 314 + 315 + static inline unsigned int pdo_fixed_voltage(u32 pdo) 316 + { 317 + return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; 318 + } 319 + 320 + static inline unsigned int pdo_min_voltage(u32 pdo) 321 + { 322 + return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; 323 + } 324 + 325 + static inline unsigned int pdo_max_voltage(u32 pdo) 326 + { 327 + return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; 328 + } 329 + 330 + static inline unsigned int pdo_max_current(u32 pdo) 331 + { 332 + return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10; 333 + } 334 + 335 + static inline unsigned int pdo_max_power(u32 pdo) 336 + { 337 + return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250; 338 + } 339 + 340 + static inline enum pd_apdo_type pdo_apdo_type(u32 pdo) 341 + { 342 + return (pdo >> PDO_APDO_TYPE_SHIFT) & PDO_APDO_TYPE_MASK; 343 + } 344 + 345 + static inline unsigned int pdo_pps_apdo_min_voltage(u32 pdo) 346 + { 347 + return ((pdo >> PDO_PPS_APDO_MIN_VOLT_SHIFT) & 348 + PDO_PPS_APDO_VOLT_MASK) * 100; 349 + } 350 + 351 + static inline unsigned int pdo_pps_apdo_max_voltage(u32 pdo) 352 + { 353 + return ((pdo >> PDO_PPS_APDO_MAX_VOLT_SHIFT) & 354 + PDO_PPS_APDO_VOLT_MASK) * 100; 355 + } 356 + 357 + static inline unsigned int pdo_pps_apdo_max_current(u32 pdo) 358 + { 359 + return ((pdo >> PDO_PPS_APDO_MAX_CURR_SHIFT) & 360 + PDO_PPS_APDO_CURR_MASK) * 50; 361 + } 362 + 363 + /* RDO: Request Data Object */ 364 + #define RDO_OBJ_POS_SHIFT 28 365 + #define RDO_OBJ_POS_MASK 0x7 366 + #define RDO_GIVE_BACK BIT(27) /* Supports reduced operating current */ 367 + #define RDO_CAP_MISMATCH BIT(26) /* Not satisfied by source caps */ 368 + #define RDO_USB_COMM BIT(25) /* USB communications capable */ 369 + #define RDO_NO_SUSPEND BIT(24) /* USB Suspend not supported */ 370 + 371 + #define RDO_PWR_MASK 0x3ff 372 + #define RDO_CURR_MASK 0x3ff 373 + 374 + #define RDO_FIXED_OP_CURR_SHIFT 10 375 + #define RDO_FIXED_MAX_CURR_SHIFT 0 376 + 377 + #define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT) 378 + 379 + #define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT) 380 + #define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT) 381 + 382 + #define RDO_FIXED(idx, op_ma, max_ma, flags) \ 383 + (RDO_OBJ(idx) | (flags) | \ 384 + PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma)) 385 + 386 + #define RDO_BATT_OP_PWR_SHIFT 10 /* 250mW units */ 387 + #define RDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ 388 + 389 + #define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT) 390 + #define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT) 391 + 392 + #define RDO_BATT(idx, op_mw, max_mw, flags) \ 393 + (RDO_OBJ(idx) | (flags) | \ 394 + RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw)) 395 + 396 + #define RDO_PROG_VOLT_MASK 0x7ff 397 + #define RDO_PROG_CURR_MASK 0x7f 398 + 399 + #define RDO_PROG_VOLT_SHIFT 9 400 + #define RDO_PROG_CURR_SHIFT 0 401 + 402 + #define RDO_PROG_VOLT_MV_STEP 20 403 + #define RDO_PROG_CURR_MA_STEP 50 404 + 405 + #define PDO_PROG_OUT_VOLT(mv) \ 406 + ((((mv) / RDO_PROG_VOLT_MV_STEP) & RDO_PROG_VOLT_MASK) << RDO_PROG_VOLT_SHIFT) 407 + #define PDO_PROG_OP_CURR(ma) \ 408 + ((((ma) / RDO_PROG_CURR_MA_STEP) & RDO_PROG_CURR_MASK) << RDO_PROG_CURR_SHIFT) 409 + 410 + #define RDO_PROG(idx, out_mv, op_ma, flags) \ 411 + (RDO_OBJ(idx) | (flags) | \ 412 + PDO_PROG_OUT_VOLT(out_mv) | PDO_PROG_OP_CURR(op_ma)) 413 + 414 + static inline unsigned int rdo_index(u32 rdo) 415 + { 416 + return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK; 417 + } 418 + 419 + static inline unsigned int rdo_op_current(u32 rdo) 420 + { 421 + return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10; 422 + } 423 + 424 + static inline unsigned int rdo_max_current(u32 rdo) 425 + { 426 + return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) & 427 + RDO_CURR_MASK) * 10; 428 + } 429 + 430 + static inline unsigned int rdo_op_power(u32 rdo) 431 + { 432 + return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250; 433 + } 434 + 435 + static inline unsigned int rdo_max_power(u32 rdo) 436 + { 437 + return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250; 438 + } 439 + 440 + /* Enter_USB Data Object */ 441 + #define EUDO_USB_MODE_MASK GENMASK(30, 28) 442 + #define EUDO_USB_MODE_SHIFT 28 443 + #define EUDO_USB_MODE_USB2 0 444 + #define EUDO_USB_MODE_USB3 1 445 + #define EUDO_USB_MODE_USB4 2 446 + #define EUDO_USB4_DRD BIT(26) 447 + #define EUDO_USB3_DRD BIT(25) 448 + #define EUDO_CABLE_SPEED_MASK GENMASK(23, 21) 449 + #define EUDO_CABLE_SPEED_SHIFT 21 450 + #define EUDO_CABLE_SPEED_USB2 0 451 + #define EUDO_CABLE_SPEED_USB3_GEN1 1 452 + #define EUDO_CABLE_SPEED_USB4_GEN2 2 453 + #define EUDO_CABLE_SPEED_USB4_GEN3 3 454 + #define EUDO_CABLE_TYPE_MASK GENMASK(20, 19) 455 + #define EUDO_CABLE_TYPE_SHIFT 19 456 + #define EUDO_CABLE_TYPE_PASSIVE 0 457 + #define EUDO_CABLE_TYPE_RE_TIMER 1 458 + #define EUDO_CABLE_TYPE_RE_DRIVER 2 459 + #define EUDO_CABLE_TYPE_OPTICAL 3 460 + #define EUDO_CABLE_CURRENT_MASK GENMASK(18, 17) 461 + #define EUDO_CABLE_CURRENT_SHIFT 17 462 + #define EUDO_CABLE_CURRENT_NOTSUPP 0 463 + #define EUDO_CABLE_CURRENT_3A 2 464 + #define EUDO_CABLE_CURRENT_5A 3 465 + #define EUDO_PCIE_SUPPORT BIT(16) 466 + #define EUDO_DP_SUPPORT BIT(15) 467 + #define EUDO_TBT_SUPPORT BIT(14) 468 + #define EUDO_HOST_PRESENT BIT(13) 469 + 470 + /* USB PD timers and counters */ 471 + #define PD_T_NO_RESPONSE 5000 /* 4.5 - 5.5 seconds */ 472 + #define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */ 473 + #define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */ 474 + #define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */ 475 + #define PD_T_RECEIVER_RESPONSE 15 /* 15ms max */ 476 + #define PD_T_SOURCE_ACTIVITY 45 477 + #define PD_T_SINK_ACTIVITY 135 478 + #define PD_T_SINK_WAIT_CAP 310 /* 310 - 620 ms */ 479 + #define PD_T_PS_TRANSITION 500 480 + #define PD_T_SRC_TRANSITION 35 481 + #define PD_T_DRP_SNK 40 482 + #define PD_T_DRP_SRC 30 483 + #define PD_T_PS_SOURCE_OFF 920 484 + #define PD_T_PS_SOURCE_ON 480 485 + #define PD_T_PS_SOURCE_ON_PRS 450 /* 390 - 480ms */ 486 + #define PD_T_PS_HARD_RESET 30 487 + #define PD_T_SRC_RECOVER 760 488 + #define PD_T_SRC_RECOVER_MAX 1000 489 + #define PD_T_SRC_TURN_ON 275 490 + #define PD_T_SAFE_0V 650 491 + #define PD_T_VCONN_SOURCE_ON 100 492 + #define PD_T_SINK_REQUEST 100 /* 100 ms minimum */ 493 + #define PD_T_ERROR_RECOVERY 100 /* minimum 25 is insufficient */ 494 + #define PD_T_SRCSWAPSTDBY 625 /* Maximum of 650ms */ 495 + #define PD_T_NEWSRC 250 /* Maximum of 275ms */ 496 + #define PD_T_SWAP_SRC_START 20 /* Minimum of 20ms */ 497 + #define PD_T_BIST_CONT_MODE 50 /* 30 - 60 ms */ 498 + #define PD_T_SINK_TX 16 /* 16 - 20 ms */ 499 + #define PD_T_CHUNK_NOT_SUPP 42 /* 40 - 50 ms */ 500 + 501 + #define PD_T_DRP_TRY 100 /* 75 - 150 ms */ 502 + #define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */ 503 + 504 + #define PD_T_CC_DEBOUNCE 200 /* 100 - 200 ms */ 505 + #define PD_T_PD_DEBOUNCE 20 /* 10 - 20 ms */ 506 + #define PD_T_TRY_CC_DEBOUNCE 15 /* 10 - 20 ms */ 507 + 508 + #define PD_N_CAPS_COUNT (PD_T_NO_RESPONSE / PD_T_SEND_SOURCE_CAP) 509 + #define PD_N_HARD_RESET_COUNT 1 510 + 511 + #define PD_P_SNK_STDBY_MW 2500 /* 2500 mW */ 512 + 513 + /* Time to wait for TCPC to complete transmit */ 514 + #define PD_T_TCPC_TX_TIMEOUT 100 /* in ms */ 515 + 516 + #endif /* __LINUX_USB_PD_H */
+99
include/usb/tcpm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright 2015-2017 Google, Inc 4 + * Copyright 2024 Collabora 5 + */ 6 + 7 + #ifndef __LINUX_USB_TCPM_H 8 + #define __LINUX_USB_TCPM_H 9 + 10 + #include <dm/of.h> 11 + #include <linux/bitops.h> 12 + #include "pd.h" 13 + 14 + enum typec_orientation { 15 + TYPEC_ORIENTATION_NONE, 16 + TYPEC_ORIENTATION_NORMAL, 17 + TYPEC_ORIENTATION_REVERSE, 18 + }; 19 + 20 + enum typec_cc_status { 21 + TYPEC_CC_OPEN, 22 + TYPEC_CC_RA, 23 + TYPEC_CC_RD, 24 + TYPEC_CC_RP_DEF, 25 + TYPEC_CC_RP_1_5, 26 + TYPEC_CC_RP_3_0, 27 + }; 28 + 29 + enum typec_cc_polarity { 30 + TYPEC_POLARITY_CC1, 31 + TYPEC_POLARITY_CC2, 32 + }; 33 + 34 + enum tcpm_transmit_status { 35 + TCPC_TX_SUCCESS = 0, 36 + TCPC_TX_DISCARDED = 1, 37 + TCPC_TX_FAILED = 2, 38 + }; 39 + 40 + enum tcpm_transmit_type { 41 + TCPC_TX_SOP = 0, 42 + TCPC_TX_SOP_PRIME = 1, 43 + TCPC_TX_SOP_PRIME_PRIME = 2, 44 + TCPC_TX_SOP_DEBUG_PRIME = 3, 45 + TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, 46 + TCPC_TX_HARD_RESET = 5, 47 + TCPC_TX_CABLE_RESET = 6, 48 + TCPC_TX_BIST_MODE_2 = 7 49 + }; 50 + 51 + struct dm_tcpm_ops { 52 + int (*get_connector_node)(struct udevice *dev, ofnode *connector_node); 53 + int (*init)(struct udevice *dev); 54 + int (*get_vbus)(struct udevice *dev); 55 + int (*set_cc)(struct udevice *dev, enum typec_cc_status cc); 56 + int (*get_cc)(struct udevice *dev, enum typec_cc_status *cc1, 57 + enum typec_cc_status *cc2); 58 + int (*set_polarity)(struct udevice *dev, 59 + enum typec_cc_polarity polarity); 60 + int (*set_vconn)(struct udevice *dev, bool on); 61 + int (*set_vbus)(struct udevice *dev, bool on, bool charge); 62 + int (*set_pd_rx)(struct udevice *dev, bool on); 63 + int (*set_roles)(struct udevice *dev, bool attached, 64 + enum typec_role role, enum typec_data_role data); 65 + int (*start_toggling)(struct udevice *dev, 66 + enum typec_port_type port_type, 67 + enum typec_cc_status cc); 68 + int (*pd_transmit)(struct udevice *dev, enum tcpm_transmit_type type, 69 + const struct pd_message *msg, unsigned int negotiated_rev); 70 + void (*poll_event)(struct udevice *dev); 71 + int (*enter_low_power_mode)(struct udevice *dev, bool attached, bool pd_capable); 72 + }; 73 + 74 + /* API for drivers */ 75 + void tcpm_vbus_change(struct udevice *dev); 76 + void tcpm_cc_change(struct udevice *dev); 77 + void tcpm_pd_receive(struct udevice *dev, const struct pd_message *msg); 78 + void tcpm_pd_transmit_complete(struct udevice *dev, 79 + enum tcpm_transmit_status status); 80 + void tcpm_pd_hard_reset(struct udevice *dev); 81 + 82 + /* API for boards */ 83 + extern const char * const typec_pd_rev_name[]; 84 + extern const char * const typec_orientation_name[]; 85 + extern const char * const typec_role_name[]; 86 + extern const char * const typec_data_role_name[]; 87 + extern const char * const typec_cc_status_name[]; 88 + 89 + int tcpm_get(int index, struct udevice **devp); 90 + int tcpm_get_pd_rev(struct udevice *dev); 91 + int tcpm_get_current(struct udevice *dev); 92 + int tcpm_get_voltage(struct udevice *dev); 93 + enum typec_orientation tcpm_get_orientation(struct udevice *dev); 94 + enum typec_role tcpm_get_pwr_role(struct udevice *dev); 95 + enum typec_data_role tcpm_get_data_role(struct udevice *dev); 96 + bool tcpm_is_connected(struct udevice *dev); 97 + const char *tcpm_get_state(struct udevice *dev); 98 + 99 + #endif /* __LINUX_USB_TCPM_H */