Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

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

usb: typec: tcpm/tcpci_maxim: deprecate WAR for setting charger mode

TCPCI maxim driver directly writes to the charger's register space to
set charger mode depending on the power role. As MAX77759 chg driver
exists, this WAR is not required.

Instead, use a regulator interface to source vbus when typec is in
source power mode. In other power modes, this regulator will be turned
off if active.

Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: André Draszik <andre.draszik@linaro.org>
Link: https://patch.msgid.link/20260325-max77759-charger-v9-6-4486dd297adc@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Amit Sunil Dhamne and committed by
Greg Kroah-Hartman
0c893564 70d7dd27

+34 -21
+1
drivers/usb/typec/tcpm/tcpci_maxim.h
··· 60 60 struct tcpm_port *port; 61 61 enum contamiant_state contaminant_state; 62 62 bool veto_vconn_swap; 63 + struct regulator *vbus_reg; 63 64 }; 64 65 65 66 static inline int max_tcpci_read16(struct max_tcpci_chip *chip, unsigned int reg, u16 *val)
+33 -21
drivers/usb/typec/tcpm/tcpci_maxim_core.c
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/module.h> 12 12 #include <linux/regmap.h> 13 + #include <linux/regulator/consumer.h> 13 14 #include <linux/usb/pd.h> 14 15 #include <linux/usb/tcpci.h> 15 16 #include <linux/usb/tcpm.h> ··· 35 34 * less than or equal to 31. Since, RECEIVE_BUFFER len = 31 + 1(READABLE_BYTE_COUNT). 36 35 */ 37 36 #define TCPC_RECEIVE_BUFFER_LEN 32 38 - 39 - #define MAX_BUCK_BOOST_SID 0x69 40 - #define MAX_BUCK_BOOST_OP 0xb9 41 - #define MAX_BUCK_BOOST_OFF 0 42 - #define MAX_BUCK_BOOST_SOURCE 0xa 43 - #define MAX_BUCK_BOOST_SINK 0x5 44 37 45 38 static const struct regmap_range max_tcpci_tcpci_range[] = { 46 39 regmap_reg_range(0x00, 0x95) ··· 197 202 tcpm_pd_receive(chip->port, &msg, rx_type); 198 203 } 199 204 205 + static int get_vbus_regulator_handle(struct max_tcpci_chip *chip) 206 + { 207 + if (IS_ERR_OR_NULL(chip->vbus_reg)) { 208 + chip->vbus_reg = devm_regulator_get_exclusive(chip->dev, 209 + "vbus"); 210 + if (IS_ERR_OR_NULL(chip->vbus_reg)) { 211 + dev_err(chip->dev, 212 + "Failed to get vbus regulator handle\n"); 213 + return -ENODEV; 214 + } 215 + } 216 + 217 + return 0; 218 + } 219 + 200 220 static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink) 201 221 { 202 222 struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata); 203 - u8 buffer_source[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SOURCE}; 204 - u8 buffer_sink[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SINK}; 205 - u8 buffer_none[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_OFF}; 206 - struct i2c_client *i2c = chip->client; 207 223 int ret; 208 - 209 - struct i2c_msg msgs[] = { 210 - { 211 - .addr = MAX_BUCK_BOOST_SID, 212 - .flags = i2c->flags & I2C_M_TEN, 213 - .len = 2, 214 - .buf = source ? buffer_source : sink ? buffer_sink : buffer_none, 215 - }, 216 - }; 217 224 218 225 if (source && sink) { 219 226 dev_err(chip->dev, "Both source and sink set\n"); 220 227 return -EINVAL; 221 228 } 222 229 223 - ret = i2c_transfer(i2c->adapter, msgs, 1); 230 + ret = get_vbus_regulator_handle(chip); 231 + if (ret) { 232 + /* 233 + * Regulator is not necessary for sink only applications. Return 234 + * success in cases where sink mode is being modified. 235 + */ 236 + return source ? ret : 1; 237 + } 224 238 225 - return ret < 0 ? ret : 1; 239 + if (source) { 240 + if (!regulator_is_enabled(chip->vbus_reg)) 241 + ret = regulator_enable(chip->vbus_reg); 242 + } else { 243 + if (regulator_is_enabled(chip->vbus_reg)) 244 + ret = regulator_disable(chip->vbus_reg); 245 + } 246 + 247 + return ret < 0 ? ret : 1; 226 248 } 227 249 228 250 static void process_power_status(struct max_tcpci_chip *chip)