| .. | .. |
|---|
| 5 | 5 | |
|---|
| 6 | 6 | #include <linux/bitops.h> |
|---|
| 7 | 7 | #include <linux/device.h> |
|---|
| 8 | +#include <linux/power_supply.h> |
|---|
| 8 | 9 | #include <linux/types.h> |
|---|
| 10 | +#include <linux/usb/typec.h> |
|---|
| 11 | +#include <linux/usb/pd.h> |
|---|
| 12 | +#include <linux/usb/role.h> |
|---|
| 13 | +#include <linux/usb/pd.h> |
|---|
| 9 | 14 | |
|---|
| 10 | 15 | /* -------------------------------------------------------------------------- */ |
|---|
| 11 | 16 | |
|---|
| 12 | | -/* Command Status and Connector Change Indication (CCI) data structure */ |
|---|
| 13 | | -struct ucsi_cci { |
|---|
| 14 | | - u8:1; /* reserved */ |
|---|
| 15 | | - u8 connector_change:7; |
|---|
| 16 | | - u8 data_length; |
|---|
| 17 | | - u16:9; /* reserved */ |
|---|
| 18 | | - u16 not_supported:1; |
|---|
| 19 | | - u16 cancel_complete:1; |
|---|
| 20 | | - u16 reset_complete:1; |
|---|
| 21 | | - u16 busy:1; |
|---|
| 22 | | - u16 ack_complete:1; |
|---|
| 23 | | - u16 error:1; |
|---|
| 24 | | - u16 cmd_complete:1; |
|---|
| 25 | | -} __packed; |
|---|
| 17 | +struct ucsi; |
|---|
| 18 | +struct ucsi_altmode; |
|---|
| 26 | 19 | |
|---|
| 27 | | -/* Default fields in CONTROL data structure */ |
|---|
| 28 | | -struct ucsi_command { |
|---|
| 29 | | - u8 cmd; |
|---|
| 30 | | - u8 length; |
|---|
| 31 | | - u64 data:48; |
|---|
| 32 | | -} __packed; |
|---|
| 20 | +/* UCSI offsets (Bytes) */ |
|---|
| 21 | +#define UCSI_VERSION 0 |
|---|
| 22 | +#define UCSI_CCI 4 |
|---|
| 23 | +#define UCSI_CONTROL 8 |
|---|
| 24 | +#define UCSI_MESSAGE_IN 16 |
|---|
| 25 | +#define UCSI_MESSAGE_OUT 32 |
|---|
| 33 | 26 | |
|---|
| 34 | | -/* ACK Command structure */ |
|---|
| 35 | | -struct ucsi_ack_cmd { |
|---|
| 36 | | - u8 cmd; |
|---|
| 37 | | - u8 length; |
|---|
| 38 | | - u8 cci_ack:1; |
|---|
| 39 | | - u8 cmd_ack:1; |
|---|
| 40 | | - u8:6; /* reserved */ |
|---|
| 41 | | -} __packed; |
|---|
| 27 | +/* Command Status and Connector Change Indication (CCI) bits */ |
|---|
| 28 | +#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1) |
|---|
| 29 | +#define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8) |
|---|
| 30 | +#define UCSI_CCI_NOT_SUPPORTED BIT(25) |
|---|
| 31 | +#define UCSI_CCI_CANCEL_COMPLETE BIT(26) |
|---|
| 32 | +#define UCSI_CCI_RESET_COMPLETE BIT(27) |
|---|
| 33 | +#define UCSI_CCI_BUSY BIT(28) |
|---|
| 34 | +#define UCSI_CCI_ACK_COMPLETE BIT(29) |
|---|
| 35 | +#define UCSI_CCI_ERROR BIT(30) |
|---|
| 36 | +#define UCSI_CCI_COMMAND_COMPLETE BIT(31) |
|---|
| 42 | 37 | |
|---|
| 43 | | -/* Connector Reset Command structure */ |
|---|
| 44 | | -struct ucsi_con_rst { |
|---|
| 45 | | - u8 cmd; |
|---|
| 46 | | - u8 length; |
|---|
| 47 | | - u8 con_num:7; |
|---|
| 48 | | - u8 hard_reset:1; |
|---|
| 49 | | -} __packed; |
|---|
| 50 | | - |
|---|
| 51 | | -/* Set USB Operation Mode Command structure */ |
|---|
| 52 | | -struct ucsi_uor_cmd { |
|---|
| 53 | | - u8 cmd; |
|---|
| 54 | | - u8 length; |
|---|
| 55 | | - u16 con_num:7; |
|---|
| 56 | | - u16 role:3; |
|---|
| 57 | | -#define UCSI_UOR_ROLE_DFP BIT(0) |
|---|
| 58 | | -#define UCSI_UOR_ROLE_UFP BIT(1) |
|---|
| 59 | | -#define UCSI_UOR_ROLE_DRP BIT(2) |
|---|
| 60 | | - u16:6; /* reserved */ |
|---|
| 61 | | -} __packed; |
|---|
| 62 | | - |
|---|
| 63 | | -struct ucsi_control { |
|---|
| 64 | | - union { |
|---|
| 65 | | - u64 raw_cmd; |
|---|
| 66 | | - struct ucsi_command cmd; |
|---|
| 67 | | - struct ucsi_uor_cmd uor; |
|---|
| 68 | | - struct ucsi_ack_cmd ack; |
|---|
| 69 | | - struct ucsi_con_rst con_rst; |
|---|
| 70 | | - }; |
|---|
| 38 | +/** |
|---|
| 39 | + * struct ucsi_operations - UCSI I/O operations |
|---|
| 40 | + * @read: Read operation |
|---|
| 41 | + * @sync_write: Blocking write operation |
|---|
| 42 | + * @async_write: Non-blocking write operation |
|---|
| 43 | + * @update_altmodes: Squashes duplicate DP altmodes |
|---|
| 44 | + * |
|---|
| 45 | + * Read and write routines for UCSI interface. @sync_write must wait for the |
|---|
| 46 | + * Command Completion Event from the PPM before returning, and @async_write must |
|---|
| 47 | + * return immediately after sending the data to the PPM. |
|---|
| 48 | + */ |
|---|
| 49 | +struct ucsi_operations { |
|---|
| 50 | + int (*read)(struct ucsi *ucsi, unsigned int offset, |
|---|
| 51 | + void *val, size_t val_len); |
|---|
| 52 | + int (*sync_write)(struct ucsi *ucsi, unsigned int offset, |
|---|
| 53 | + const void *val, size_t val_len); |
|---|
| 54 | + int (*async_write)(struct ucsi *ucsi, unsigned int offset, |
|---|
| 55 | + const void *val, size_t val_len); |
|---|
| 56 | + bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig, |
|---|
| 57 | + struct ucsi_altmode *updated); |
|---|
| 71 | 58 | }; |
|---|
| 72 | 59 | |
|---|
| 73 | | -#define __UCSI_CMD(_ctrl_, _cmd_) \ |
|---|
| 74 | | -{ \ |
|---|
| 75 | | - (_ctrl_).raw_cmd = 0; \ |
|---|
| 76 | | - (_ctrl_).cmd.cmd = _cmd_; \ |
|---|
| 77 | | -} |
|---|
| 60 | +struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops); |
|---|
| 61 | +void ucsi_destroy(struct ucsi *ucsi); |
|---|
| 62 | +int ucsi_register(struct ucsi *ucsi); |
|---|
| 63 | +void ucsi_unregister(struct ucsi *ucsi); |
|---|
| 64 | +void *ucsi_get_drvdata(struct ucsi *ucsi); |
|---|
| 65 | +void ucsi_set_drvdata(struct ucsi *ucsi, void *data); |
|---|
| 78 | 66 | |
|---|
| 79 | | -/* Helper for preparing ucsi_control for CONNECTOR_RESET command. */ |
|---|
| 80 | | -#define UCSI_CMD_CONNECTOR_RESET(_ctrl_, _con_, _hard_) \ |
|---|
| 81 | | -{ \ |
|---|
| 82 | | - __UCSI_CMD(_ctrl_, UCSI_CONNECTOR_RESET) \ |
|---|
| 83 | | - (_ctrl_).con_rst.con_num = (_con_)->num; \ |
|---|
| 84 | | - (_ctrl_).con_rst.hard_reset = _hard_; \ |
|---|
| 85 | | -} |
|---|
| 67 | +void ucsi_connector_change(struct ucsi *ucsi, u8 num); |
|---|
| 86 | 68 | |
|---|
| 87 | | -/* Helper for preparing ucsi_control for ACK_CC_CI command. */ |
|---|
| 88 | | -#define UCSI_CMD_ACK(_ctrl_, _ack_) \ |
|---|
| 89 | | -{ \ |
|---|
| 90 | | - __UCSI_CMD(_ctrl_, UCSI_ACK_CC_CI) \ |
|---|
| 91 | | - (_ctrl_).ack.cci_ack = ((_ack_) == UCSI_ACK_EVENT); \ |
|---|
| 92 | | - (_ctrl_).ack.cmd_ack = ((_ack_) == UCSI_ACK_CMD); \ |
|---|
| 93 | | -} |
|---|
| 94 | | - |
|---|
| 95 | | -/* Helper for preparing ucsi_control for SET_NOTIFY_ENABLE command. */ |
|---|
| 96 | | -#define UCSI_CMD_SET_NTFY_ENABLE(_ctrl_, _ntfys_) \ |
|---|
| 97 | | -{ \ |
|---|
| 98 | | - __UCSI_CMD(_ctrl_, UCSI_SET_NOTIFICATION_ENABLE) \ |
|---|
| 99 | | - (_ctrl_).cmd.data = _ntfys_; \ |
|---|
| 100 | | -} |
|---|
| 101 | | - |
|---|
| 102 | | -/* Helper for preparing ucsi_control for GET_CAPABILITY command. */ |
|---|
| 103 | | -#define UCSI_CMD_GET_CAPABILITY(_ctrl_) \ |
|---|
| 104 | | -{ \ |
|---|
| 105 | | - __UCSI_CMD(_ctrl_, UCSI_GET_CAPABILITY) \ |
|---|
| 106 | | -} |
|---|
| 107 | | - |
|---|
| 108 | | -/* Helper for preparing ucsi_control for GET_CONNECTOR_CAPABILITY command. */ |
|---|
| 109 | | -#define UCSI_CMD_GET_CONNECTOR_CAPABILITY(_ctrl_, _con_) \ |
|---|
| 110 | | -{ \ |
|---|
| 111 | | - __UCSI_CMD(_ctrl_, UCSI_GET_CONNECTOR_CAPABILITY) \ |
|---|
| 112 | | - (_ctrl_).cmd.data = _con_; \ |
|---|
| 113 | | -} |
|---|
| 114 | | - |
|---|
| 115 | | -/* Helper for preparing ucsi_control for GET_CONNECTOR_STATUS command. */ |
|---|
| 116 | | -#define UCSI_CMD_GET_CONNECTOR_STATUS(_ctrl_, _con_) \ |
|---|
| 117 | | -{ \ |
|---|
| 118 | | - __UCSI_CMD(_ctrl_, UCSI_GET_CONNECTOR_STATUS) \ |
|---|
| 119 | | - (_ctrl_).cmd.data = _con_; \ |
|---|
| 120 | | -} |
|---|
| 121 | | - |
|---|
| 122 | | -#define __UCSI_ROLE(_ctrl_, _cmd_, _con_num_) \ |
|---|
| 123 | | -{ \ |
|---|
| 124 | | - __UCSI_CMD(_ctrl_, _cmd_) \ |
|---|
| 125 | | - (_ctrl_).uor.con_num = _con_num_; \ |
|---|
| 126 | | - (_ctrl_).uor.role = UCSI_UOR_ROLE_DRP; \ |
|---|
| 127 | | -} |
|---|
| 128 | | - |
|---|
| 129 | | -/* Helper for preparing ucsi_control for SET_UOR command. */ |
|---|
| 130 | | -#define UCSI_CMD_SET_UOR(_ctrl_, _con_, _role_) \ |
|---|
| 131 | | -{ \ |
|---|
| 132 | | - __UCSI_ROLE(_ctrl_, UCSI_SET_UOR, (_con_)->num) \ |
|---|
| 133 | | - (_ctrl_).uor.role |= (_role_) == TYPEC_HOST ? UCSI_UOR_ROLE_DFP : \ |
|---|
| 134 | | - UCSI_UOR_ROLE_UFP; \ |
|---|
| 135 | | -} |
|---|
| 136 | | - |
|---|
| 137 | | -/* Helper for preparing ucsi_control for SET_PDR command. */ |
|---|
| 138 | | -#define UCSI_CMD_SET_PDR(_ctrl_, _con_, _role_) \ |
|---|
| 139 | | -{ \ |
|---|
| 140 | | - __UCSI_ROLE(_ctrl_, UCSI_SET_PDR, (_con_)->num) \ |
|---|
| 141 | | - (_ctrl_).uor.role |= (_role_) == TYPEC_SOURCE ? UCSI_UOR_ROLE_DFP : \ |
|---|
| 142 | | - UCSI_UOR_ROLE_UFP; \ |
|---|
| 143 | | -} |
|---|
| 69 | +/* -------------------------------------------------------------------------- */ |
|---|
| 144 | 70 | |
|---|
| 145 | 71 | /* Commands */ |
|---|
| 146 | 72 | #define UCSI_PPM_RESET 0x01 |
|---|
| .. | .. |
|---|
| 163 | 89 | #define UCSI_GET_CONNECTOR_STATUS 0x12 |
|---|
| 164 | 90 | #define UCSI_GET_ERROR_STATUS 0x13 |
|---|
| 165 | 91 | |
|---|
| 166 | | -/* ACK_CC_CI commands */ |
|---|
| 167 | | -#define UCSI_ACK_EVENT 1 |
|---|
| 168 | | -#define UCSI_ACK_CMD 2 |
|---|
| 92 | +#define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16) |
|---|
| 93 | +#define UCSI_COMMAND(_cmd_) ((_cmd_) & 0xff) |
|---|
| 169 | 94 | |
|---|
| 170 | | -/* Bits for SET_NOTIFICATION_ENABLE command */ |
|---|
| 171 | | -#define UCSI_ENABLE_NTFY_CMD_COMPLETE BIT(0) |
|---|
| 172 | | -#define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE BIT(1) |
|---|
| 173 | | -#define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE BIT(2) |
|---|
| 174 | | -#define UCSI_ENABLE_NTFY_CAP_CHANGE BIT(5) |
|---|
| 175 | | -#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE BIT(6) |
|---|
| 176 | | -#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE BIT(7) |
|---|
| 177 | | -#define UCSI_ENABLE_NTFY_CAM_CHANGE BIT(8) |
|---|
| 178 | | -#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE BIT(9) |
|---|
| 179 | | -#define UCSI_ENABLE_NTFY_PARTNER_CHANGE BIT(11) |
|---|
| 180 | | -#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE BIT(12) |
|---|
| 181 | | -#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT(14) |
|---|
| 182 | | -#define UCSI_ENABLE_NTFY_ERROR BIT(15) |
|---|
| 183 | | -#define UCSI_ENABLE_NTFY_ALL 0xdbe7 |
|---|
| 95 | +/* CONNECTOR_RESET command bits */ |
|---|
| 96 | +#define UCSI_CONNECTOR_RESET_HARD BIT(23) /* Deprecated in v1.1 */ |
|---|
| 97 | + |
|---|
| 98 | +/* ACK_CC_CI bits */ |
|---|
| 99 | +#define UCSI_ACK_CONNECTOR_CHANGE BIT(16) |
|---|
| 100 | +#define UCSI_ACK_COMMAND_COMPLETE BIT(17) |
|---|
| 101 | + |
|---|
| 102 | +/* SET_NOTIFICATION_ENABLE command bits */ |
|---|
| 103 | +#define UCSI_ENABLE_NTFY_CMD_COMPLETE BIT(16) |
|---|
| 104 | +#define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE BIT(17) |
|---|
| 105 | +#define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE BIT(18) |
|---|
| 106 | +#define UCSI_ENABLE_NTFY_CAP_CHANGE BIT(21) |
|---|
| 107 | +#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE BIT(22) |
|---|
| 108 | +#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE BIT(23) |
|---|
| 109 | +#define UCSI_ENABLE_NTFY_CAM_CHANGE BIT(24) |
|---|
| 110 | +#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE BIT(25) |
|---|
| 111 | +#define UCSI_ENABLE_NTFY_PARTNER_CHANGE BIT(27) |
|---|
| 112 | +#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE BIT(28) |
|---|
| 113 | +#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE BIT(30) |
|---|
| 114 | +#define UCSI_ENABLE_NTFY_ERROR BIT(31) |
|---|
| 115 | +#define UCSI_ENABLE_NTFY_ALL 0xdbe70000 |
|---|
| 116 | + |
|---|
| 117 | +/* SET_UOR command bits */ |
|---|
| 118 | +#define UCSI_SET_UOR_ROLE(_r_) (((_r_) == TYPEC_HOST ? 1 : 2) << 23) |
|---|
| 119 | +#define UCSI_SET_UOR_ACCEPT_ROLE_SWAPS BIT(25) |
|---|
| 120 | + |
|---|
| 121 | +/* SET_PDF command bits */ |
|---|
| 122 | +#define UCSI_SET_PDR_ROLE(_r_) (((_r_) == TYPEC_SOURCE ? 1 : 2) << 23) |
|---|
| 123 | +#define UCSI_SET_PDR_ACCEPT_ROLE_SWAPS BIT(25) |
|---|
| 124 | + |
|---|
| 125 | +/* GET_ALTERNATE_MODES command bits */ |
|---|
| 126 | +#define UCSI_ALTMODE_RECIPIENT(_r_) (((_r_) >> 16) & 0x7) |
|---|
| 127 | +#define UCSI_GET_ALTMODE_RECIPIENT(_r_) ((u64)(_r_) << 16) |
|---|
| 128 | +#define UCSI_RECIPIENT_CON 0 |
|---|
| 129 | +#define UCSI_RECIPIENT_SOP 1 |
|---|
| 130 | +#define UCSI_RECIPIENT_SOP_P 2 |
|---|
| 131 | +#define UCSI_RECIPIENT_SOP_PP 3 |
|---|
| 132 | +#define UCSI_GET_ALTMODE_CONNECTOR_NUMBER(_r_) ((u64)(_r_) << 24) |
|---|
| 133 | +#define UCSI_ALTMODE_OFFSET(_r_) (((_r_) >> 32) & 0xff) |
|---|
| 134 | +#define UCSI_GET_ALTMODE_OFFSET(_r_) ((u64)(_r_) << 32) |
|---|
| 135 | +#define UCSI_GET_ALTMODE_NUM_ALTMODES(_r_) ((u64)(_r_) << 40) |
|---|
| 136 | + |
|---|
| 137 | +/* GET_PDOS command bits */ |
|---|
| 138 | +#define UCSI_GET_PDOS_PARTNER_PDO(_r_) ((u64)(_r_) << 23) |
|---|
| 139 | +#define UCSI_GET_PDOS_PDO_OFFSET(_r_) ((u64)(_r_) << 24) |
|---|
| 140 | +#define UCSI_GET_PDOS_NUM_PDOS(_r_) ((u64)(_r_) << 32) |
|---|
| 141 | +#define UCSI_MAX_PDOS (4) |
|---|
| 142 | +#define UCSI_GET_PDOS_SRC_PDOS ((u64)1 << 34) |
|---|
| 143 | + |
|---|
| 144 | +/* -------------------------------------------------------------------------- */ |
|---|
| 184 | 145 | |
|---|
| 185 | 146 | /* Error information returned by PPM in response to GET_ERROR_STATUS command. */ |
|---|
| 186 | 147 | #define UCSI_ERROR_UNREGONIZED_CMD BIT(0) |
|---|
| .. | .. |
|---|
| 190 | 151 | #define UCSI_ERROR_CC_COMMUNICATION_ERR BIT(4) |
|---|
| 191 | 152 | #define UCSI_ERROR_DEAD_BATTERY BIT(5) |
|---|
| 192 | 153 | #define UCSI_ERROR_CONTRACT_NEGOTIATION_FAIL BIT(6) |
|---|
| 154 | +#define UCSI_ERROR_OVERCURRENT BIT(7) |
|---|
| 155 | +#define UCSI_ERROR_UNDEFINED BIT(8) |
|---|
| 156 | +#define UCSI_ERROR_PARTNER_REJECTED_SWAP BIT(9) |
|---|
| 157 | +#define UCSI_ERROR_HARD_RESET BIT(10) |
|---|
| 158 | +#define UCSI_ERROR_PPM_POLICY_CONFLICT BIT(11) |
|---|
| 159 | +#define UCSI_ERROR_SWAP_REJECTED BIT(12) |
|---|
| 160 | + |
|---|
| 161 | +#define UCSI_SET_NEW_CAM_ENTER(x) (((x) >> 23) & 0x1) |
|---|
| 162 | +#define UCSI_SET_NEW_CAM_GET_AM(x) (((x) >> 24) & 0xff) |
|---|
| 163 | +#define UCSI_SET_NEW_CAM_AM_MASK (0xff << 24) |
|---|
| 164 | +#define UCSI_SET_NEW_CAM_SET_AM(x) (((x) & 0xff) << 24) |
|---|
| 165 | +#define UCSI_CMD_CONNECTOR_MASK (0x7) |
|---|
| 193 | 166 | |
|---|
| 194 | 167 | /* Data structure filled by PPM in response to GET_CAPABILITY command. */ |
|---|
| 195 | 168 | struct ucsi_capability { |
|---|
| .. | .. |
|---|
| 201 | 174 | #define UCSI_CAP_ATTR_POWER_AC_SUPPLY BIT(8) |
|---|
| 202 | 175 | #define UCSI_CAP_ATTR_POWER_OTHER BIT(10) |
|---|
| 203 | 176 | #define UCSI_CAP_ATTR_POWER_VBUS BIT(14) |
|---|
| 204 | | - u32 num_connectors:8; |
|---|
| 205 | | - u32 features:24; |
|---|
| 177 | + u8 num_connectors; |
|---|
| 178 | + u8 features; |
|---|
| 206 | 179 | #define UCSI_CAP_SET_UOM BIT(0) |
|---|
| 207 | 180 | #define UCSI_CAP_SET_PDM BIT(1) |
|---|
| 208 | 181 | #define UCSI_CAP_ALT_MODE_DETAILS BIT(2) |
|---|
| .. | .. |
|---|
| 211 | 184 | #define UCSI_CAP_CABLE_DETAILS BIT(5) |
|---|
| 212 | 185 | #define UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS BIT(6) |
|---|
| 213 | 186 | #define UCSI_CAP_PD_RESET BIT(7) |
|---|
| 187 | + u16 reserved_1; |
|---|
| 214 | 188 | u8 num_alt_modes; |
|---|
| 215 | | - u8 reserved; |
|---|
| 189 | + u8 reserved_2; |
|---|
| 216 | 190 | u16 bc_version; |
|---|
| 217 | 191 | u16 pd_version; |
|---|
| 218 | 192 | u16 typec_version; |
|---|
| .. | .. |
|---|
| 229 | 203 | #define UCSI_CONCAP_OPMODE_USB2 BIT(5) |
|---|
| 230 | 204 | #define UCSI_CONCAP_OPMODE_USB3 BIT(6) |
|---|
| 231 | 205 | #define UCSI_CONCAP_OPMODE_ALT_MODE BIT(7) |
|---|
| 232 | | - u8 provider:1; |
|---|
| 233 | | - u8 consumer:1; |
|---|
| 234 | | - u8:6; /* reserved */ |
|---|
| 206 | + u8 flags; |
|---|
| 207 | +#define UCSI_CONCAP_FLAG_PROVIDER BIT(0) |
|---|
| 208 | +#define UCSI_CONCAP_FLAG_CONSUMER BIT(1) |
|---|
| 235 | 209 | } __packed; |
|---|
| 236 | 210 | |
|---|
| 237 | 211 | struct ucsi_altmode { |
|---|
| .. | .. |
|---|
| 243 | 217 | struct ucsi_cable_property { |
|---|
| 244 | 218 | u16 speed_supported; |
|---|
| 245 | 219 | u8 current_capability; |
|---|
| 246 | | - u8 vbus_in_cable:1; |
|---|
| 247 | | - u8 active_cable:1; |
|---|
| 248 | | - u8 directionality:1; |
|---|
| 249 | | - u8 plug_type:2; |
|---|
| 250 | | -#define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0 |
|---|
| 251 | | -#define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1 |
|---|
| 252 | | -#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2 |
|---|
| 253 | | -#define UCSI_CABLE_PROPERTY_PLUG_OTHER 3 |
|---|
| 254 | | - u8 mode_support:1; |
|---|
| 255 | | - u8:2; /* reserved */ |
|---|
| 256 | | - u8 latency:4; |
|---|
| 257 | | - u8:4; /* reserved */ |
|---|
| 220 | + u8 flags; |
|---|
| 221 | +#define UCSI_CABLE_PROP_FLAG_VBUS_IN_CABLE BIT(0) |
|---|
| 222 | +#define UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE BIT(1) |
|---|
| 223 | +#define UCSI_CABLE_PROP_FLAG_DIRECTIONALITY BIT(2) |
|---|
| 224 | +#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) ((_f_) & GENMASK(3, 0)) |
|---|
| 225 | +#define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0 |
|---|
| 226 | +#define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1 |
|---|
| 227 | +#define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2 |
|---|
| 228 | +#define UCSI_CABLE_PROPERTY_PLUG_OTHER 3 |
|---|
| 229 | +#define UCSI_CABLE_PROP_MODE_SUPPORT BIT(5) |
|---|
| 230 | + u8 latency; |
|---|
| 258 | 231 | } __packed; |
|---|
| 259 | 232 | |
|---|
| 260 | 233 | /* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */ |
|---|
| .. | .. |
|---|
| 271 | 244 | #define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12) |
|---|
| 272 | 245 | #define UCSI_CONSTAT_CONNECT_CHANGE BIT(14) |
|---|
| 273 | 246 | #define UCSI_CONSTAT_ERROR BIT(15) |
|---|
| 274 | | - u16 pwr_op_mode:3; |
|---|
| 275 | | -#define UCSI_CONSTAT_PWR_OPMODE_NONE 0 |
|---|
| 276 | | -#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1 |
|---|
| 277 | | -#define UCSI_CONSTAT_PWR_OPMODE_BC 2 |
|---|
| 278 | | -#define UCSI_CONSTAT_PWR_OPMODE_PD 3 |
|---|
| 279 | | -#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5 4 |
|---|
| 280 | | -#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5 |
|---|
| 281 | | - u16 connected:1; |
|---|
| 282 | | - u16 pwr_dir:1; |
|---|
| 283 | | - u16 partner_flags:8; |
|---|
| 284 | | -#define UCSI_CONSTAT_PARTNER_FLAG_USB BIT(0) |
|---|
| 285 | | -#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE BIT(1) |
|---|
| 286 | | - u16 partner_type:3; |
|---|
| 287 | | -#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1 |
|---|
| 288 | | -#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2 |
|---|
| 289 | | -#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */ |
|---|
| 290 | | -#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */ |
|---|
| 291 | | -#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5 |
|---|
| 292 | | -#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6 |
|---|
| 247 | + u16 flags; |
|---|
| 248 | +#define UCSI_CONSTAT_PWR_OPMODE(_f_) ((_f_) & GENMASK(2, 0)) |
|---|
| 249 | +#define UCSI_CONSTAT_PWR_OPMODE_NONE 0 |
|---|
| 250 | +#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1 |
|---|
| 251 | +#define UCSI_CONSTAT_PWR_OPMODE_BC 2 |
|---|
| 252 | +#define UCSI_CONSTAT_PWR_OPMODE_PD 3 |
|---|
| 253 | +#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5 4 |
|---|
| 254 | +#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5 |
|---|
| 255 | +#define UCSI_CONSTAT_CONNECTED BIT(3) |
|---|
| 256 | +#define UCSI_CONSTAT_PWR_DIR BIT(4) |
|---|
| 257 | +#define UCSI_CONSTAT_PARTNER_FLAGS(_f_) (((_f_) & GENMASK(12, 5)) >> 5) |
|---|
| 258 | +#define UCSI_CONSTAT_PARTNER_FLAG_USB 1 |
|---|
| 259 | +#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE 2 |
|---|
| 260 | +#define UCSI_CONSTAT_PARTNER_TYPE(_f_) (((_f_) & GENMASK(15, 13)) >> 13) |
|---|
| 261 | +#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1 |
|---|
| 262 | +#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2 |
|---|
| 263 | +#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */ |
|---|
| 264 | +#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */ |
|---|
| 265 | +#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5 |
|---|
| 266 | +#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6 |
|---|
| 293 | 267 | u32 request_data_obj; |
|---|
| 294 | | - u8 bc_status:2; |
|---|
| 295 | | -#define UCSI_CONSTAT_BC_NOT_CHARGING 0 |
|---|
| 296 | | -#define UCSI_CONSTAT_BC_NOMINAL_CHARGING 1 |
|---|
| 297 | | -#define UCSI_CONSTAT_BC_SLOW_CHARGING 2 |
|---|
| 298 | | -#define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3 |
|---|
| 299 | | - u8 provider_cap_limit_reason:4; |
|---|
| 300 | | -#define UCSI_CONSTAT_CAP_PWR_LOWERED 0 |
|---|
| 301 | | -#define UCSI_CONSTAT_CAP_PWR_BUDGET_LIMIT 1 |
|---|
| 302 | | - u8:2; /* reserved */ |
|---|
| 268 | + u8 pwr_status; |
|---|
| 269 | +#define UCSI_CONSTAT_BC_STATUS(_p_) ((_p_) & GENMASK(2, 0)) |
|---|
| 270 | +#define UCSI_CONSTAT_BC_NOT_CHARGING 0 |
|---|
| 271 | +#define UCSI_CONSTAT_BC_NOMINAL_CHARGING 1 |
|---|
| 272 | +#define UCSI_CONSTAT_BC_SLOW_CHARGING 2 |
|---|
| 273 | +#define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3 |
|---|
| 274 | +#define UCSI_CONSTAT_PROVIDER_CAP_LIMIT(_p_) (((_p_) & GENMASK(6, 3)) >> 3) |
|---|
| 275 | +#define UCSI_CONSTAT_CAP_PWR_LOWERED 0 |
|---|
| 276 | +#define UCSI_CONSTAT_CAP_PWR_BUDGET_LIMIT 1 |
|---|
| 303 | 277 | } __packed; |
|---|
| 304 | 278 | |
|---|
| 305 | 279 | /* -------------------------------------------------------------------------- */ |
|---|
| 306 | 280 | |
|---|
| 307 | | -struct ucsi; |
|---|
| 308 | | - |
|---|
| 309 | | -struct ucsi_data { |
|---|
| 281 | +struct ucsi { |
|---|
| 310 | 282 | u16 version; |
|---|
| 311 | | - u16 reserved; |
|---|
| 312 | | - union { |
|---|
| 313 | | - u32 raw_cci; |
|---|
| 314 | | - struct ucsi_cci cci; |
|---|
| 315 | | - }; |
|---|
| 316 | | - struct ucsi_control ctrl; |
|---|
| 317 | | - u32 message_in[4]; |
|---|
| 318 | | - u32 message_out[4]; |
|---|
| 319 | | -} __packed; |
|---|
| 283 | + struct device *dev; |
|---|
| 284 | + struct driver_data *driver_data; |
|---|
| 320 | 285 | |
|---|
| 321 | | -/* |
|---|
| 322 | | - * struct ucsi_ppm - Interface to UCSI Platform Policy Manager |
|---|
| 323 | | - * @data: memory location to the UCSI data structures |
|---|
| 324 | | - * @cmd: UCSI command execution routine |
|---|
| 325 | | - * @sync: Refresh UCSI mailbox (the data structures) |
|---|
| 326 | | - */ |
|---|
| 327 | | -struct ucsi_ppm { |
|---|
| 328 | | - struct ucsi_data *data; |
|---|
| 329 | | - int (*cmd)(struct ucsi_ppm *, struct ucsi_control *); |
|---|
| 330 | | - int (*sync)(struct ucsi_ppm *); |
|---|
| 286 | + const struct ucsi_operations *ops; |
|---|
| 287 | + |
|---|
| 288 | + struct ucsi_capability cap; |
|---|
| 289 | + struct ucsi_connector *connector; |
|---|
| 290 | + |
|---|
| 291 | + struct work_struct work; |
|---|
| 292 | +#define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10 |
|---|
| 293 | +#define UCSI_ROLE_SWITCH_INTERVAL (HZ / UCSI_ROLE_SWITCH_RETRY_PER_HZ) |
|---|
| 294 | +#define UCSI_ROLE_SWITCH_WAIT_COUNT (10 * UCSI_ROLE_SWITCH_RETRY_PER_HZ) |
|---|
| 295 | + |
|---|
| 296 | + /* PPM Communication lock */ |
|---|
| 297 | + struct mutex ppm_lock; |
|---|
| 298 | + |
|---|
| 299 | + /* The latest "Notification Enable" bits (SET_NOTIFICATION_ENABLE) */ |
|---|
| 300 | + u64 ntfy; |
|---|
| 301 | + |
|---|
| 302 | + /* PPM communication flags */ |
|---|
| 303 | + unsigned long flags; |
|---|
| 304 | +#define EVENT_PENDING 0 |
|---|
| 305 | +#define COMMAND_PENDING 1 |
|---|
| 306 | +#define ACK_PENDING 2 |
|---|
| 307 | +#define EVENT_PROCESSING 3 |
|---|
| 331 | 308 | }; |
|---|
| 332 | 309 | |
|---|
| 333 | | -struct ucsi *ucsi_register_ppm(struct device *dev, struct ucsi_ppm *ppm); |
|---|
| 334 | | -void ucsi_unregister_ppm(struct ucsi *ucsi); |
|---|
| 335 | | -void ucsi_notify(struct ucsi *ucsi); |
|---|
| 310 | +/** |
|---|
| 311 | + * struct ucsi_android - contains parameters without modifying the format |
|---|
| 312 | + * of ucsi struct. |
|---|
| 313 | + * @ucsi: contains the ucsi reference. |
|---|
| 314 | + * @work: work structure for queuing ucsi_init_work. |
|---|
| 315 | + * @work_count: to track the wait count(MAX= UCSI_ROLE_SWITCH_WAIT_COUNT). |
|---|
| 316 | + * |
|---|
| 317 | + * Required to address Bug: 260537721 |
|---|
| 318 | + * If the role switch module probes late the |
|---|
| 319 | + * fwnode_usb_role_switch_get() will fail with -EPROBE_DEFER. |
|---|
| 320 | + * To recover from this, restart the ucsi_init_work |
|---|
| 321 | + * to find the fwnode again using a delayed workqueue. |
|---|
| 322 | + */ |
|---|
| 323 | +struct ucsi_android { |
|---|
| 324 | + struct ucsi ucsi; |
|---|
| 325 | + struct delayed_work work; |
|---|
| 326 | + int work_count; |
|---|
| 327 | +}; |
|---|
| 328 | + |
|---|
| 329 | +#define UCSI_MAX_SVID 5 |
|---|
| 330 | +#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) |
|---|
| 331 | + |
|---|
| 332 | +#define UCSI_TYPEC_VSAFE5V 5000 |
|---|
| 333 | +#define UCSI_TYPEC_1_5_CURRENT 1500 |
|---|
| 334 | +#define UCSI_TYPEC_3_0_CURRENT 3000 |
|---|
| 335 | + |
|---|
| 336 | +struct ucsi_connector { |
|---|
| 337 | + int num; |
|---|
| 338 | + |
|---|
| 339 | + struct ucsi *ucsi; |
|---|
| 340 | + struct mutex lock; /* port lock */ |
|---|
| 341 | + struct work_struct work; |
|---|
| 342 | + struct completion complete; |
|---|
| 343 | + |
|---|
| 344 | + struct typec_port *port; |
|---|
| 345 | + struct typec_partner *partner; |
|---|
| 346 | + |
|---|
| 347 | + struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES]; |
|---|
| 348 | + struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES]; |
|---|
| 349 | + |
|---|
| 350 | + struct typec_capability typec_cap; |
|---|
| 351 | + |
|---|
| 352 | + u16 unprocessed_changes; |
|---|
| 353 | + struct ucsi_connector_status status; |
|---|
| 354 | + struct ucsi_connector_capability cap; |
|---|
| 355 | + struct power_supply *psy; |
|---|
| 356 | + struct power_supply_desc psy_desc; |
|---|
| 357 | + u32 rdo; |
|---|
| 358 | + u32 src_pdos[PDO_MAX_OBJECTS]; |
|---|
| 359 | + int num_pdos; |
|---|
| 360 | + |
|---|
| 361 | + struct usb_role_switch *usb_role_sw; |
|---|
| 362 | +}; |
|---|
| 363 | + |
|---|
| 364 | +int ucsi_send_command(struct ucsi *ucsi, u64 command, |
|---|
| 365 | + void *retval, size_t size); |
|---|
| 366 | + |
|---|
| 367 | +void ucsi_altmode_update_active(struct ucsi_connector *con); |
|---|
| 368 | +int ucsi_resume(struct ucsi *ucsi); |
|---|
| 369 | + |
|---|
| 370 | +#if IS_ENABLED(CONFIG_POWER_SUPPLY) |
|---|
| 371 | +int ucsi_register_port_psy(struct ucsi_connector *con); |
|---|
| 372 | +void ucsi_unregister_port_psy(struct ucsi_connector *con); |
|---|
| 373 | +void ucsi_port_psy_changed(struct ucsi_connector *con); |
|---|
| 374 | +#else |
|---|
| 375 | +static inline int ucsi_register_port_psy(struct ucsi_connector *con) { return 0; } |
|---|
| 376 | +static inline void ucsi_unregister_port_psy(struct ucsi_connector *con) { } |
|---|
| 377 | +static inline void ucsi_port_psy_changed(struct ucsi_connector *con) { } |
|---|
| 378 | +#endif /* CONFIG_POWER_SUPPLY */ |
|---|
| 379 | + |
|---|
| 380 | +#if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE) |
|---|
| 381 | +struct typec_altmode * |
|---|
| 382 | +ucsi_register_displayport(struct ucsi_connector *con, |
|---|
| 383 | + bool override, int offset, |
|---|
| 384 | + struct typec_altmode_desc *desc); |
|---|
| 385 | + |
|---|
| 386 | +void ucsi_displayport_remove_partner(struct typec_altmode *adev); |
|---|
| 387 | + |
|---|
| 388 | +#else |
|---|
| 389 | +static inline struct typec_altmode * |
|---|
| 390 | +ucsi_register_displayport(struct ucsi_connector *con, |
|---|
| 391 | + bool override, int offset, |
|---|
| 392 | + struct typec_altmode_desc *desc) |
|---|
| 393 | +{ |
|---|
| 394 | + return NULL; |
|---|
| 395 | +} |
|---|
| 396 | + |
|---|
| 397 | +static inline void |
|---|
| 398 | +ucsi_displayport_remove_partner(struct typec_altmode *adev) { } |
|---|
| 399 | +#endif /* CONFIG_TYPEC_DP_ALTMODE */ |
|---|
| 400 | + |
|---|
| 401 | +/* |
|---|
| 402 | + * NVIDIA VirtualLink (svid 0x955) has two altmode. VirtualLink |
|---|
| 403 | + * DP mode with vdo=0x1 and NVIDIA test mode with vdo=0x3 |
|---|
| 404 | + */ |
|---|
| 405 | +#define USB_TYPEC_NVIDIA_VLINK_DP_VDO 0x1 |
|---|
| 406 | +#define USB_TYPEC_NVIDIA_VLINK_DBG_VDO 0x3 |
|---|
| 336 | 407 | |
|---|
| 337 | 408 | #endif /* __DRIVER_USB_TYPEC_UCSI_H */ |
|---|