1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * Copyright (C) 2023 Linaro Ltd. 5 */ 6 7 #include <linux/bits.h> 8 #include <linux/i2c.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/mutex.h> 12 #include <linux/regmap.h> 13 #include <linux/bitfield.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/usb/typec_dp.h> 16 #include <linux/usb/typec_mux.h> 17 18 #define WCD_USBSS_PMP_OUT1 0x2 19 20 #define WCD_USBSS_DP_DN_MISC1 0x20 21 22 #define WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN BIT(3) 23 #define WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN BIT(0) 24 25 #define WCD_USBSS_MG1_EN 0x24 26 27 #define WCD_USBSS_MG1_EN_CT_SNS_EN BIT(1) 28 29 #define WCD_USBSS_MG1_BIAS 0x25 30 31 #define WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN BIT(3) 32 33 #define WCD_USBSS_MG1_MISC 0x27 34 35 #define WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN BIT(5) 36 37 #define WCD_USBSS_MG2_EN 0x28 38 39 #define WCD_USBSS_MG2_EN_CT_SNS_EN BIT(1) 40 41 #define WCD_USBSS_MG2_BIAS 0x29 42 43 #define WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN BIT(3) 44 45 #define WCD_USBSS_MG2_MISC 0x30 46 47 #define WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN BIT(5) 48 49 #define WCD_USBSS_DISP_AUXP_THRESH 0x80 50 51 #define WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM GENMASK(7, 5) 52 53 #define WCD_USBSS_DISP_AUXP_CTL 0x81 54 55 #define WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF GENMASK(2, 0) 56 57 #define WCD_USBSS_CPLDO_CTL2 0xa1 58 59 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE 0x403 60 61 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE BIT(7) 62 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES BIT(6) 63 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES BIT(5) 64 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES BIT(4) 65 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES BIT(3) 66 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES BIT(2) 67 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES BIT(1) 68 #define WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES BIT(0) 69 70 #define WCD_USBSS_SWITCH_SELECT0 0x404 71 72 #define WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES BIT(7) /* 1-> MG2 */ 73 #define WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES BIT(6) /* 1-> MG2 */ 74 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES GENMASK(5, 4) 75 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES GENMASK(3, 2) 76 #define WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES BIT(1) /* 1-> SBU2 */ 77 #define WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES BIT(0) /* 1-> MG2 */ 78 79 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L 0 80 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN 1 81 #define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN2 2 82 83 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R 0 84 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP 1 85 #define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DR2 2 86 87 #define WCD_USBSS_SWITCH_SELECT1 0x405 88 89 #define WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES BIT(0) /* 1-> MG2 */ 90 91 #define WCD_USBSS_DELAY_R_SW 0x40d 92 #define WCD_USBSS_DELAY_MIC_SW 0x40e 93 #define WCD_USBSS_DELAY_SENSE_SW 0x40f 94 #define WCD_USBSS_DELAY_GND_SW 0x410 95 #define WCD_USBSS_DELAY_L_SW 0x411 96 97 #define WCD_USBSS_FUNCTION_ENABLE 0x413 98 99 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT GENMASK(1, 0) 100 101 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL 1 102 #define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_AUDIO_FSM 2 103 104 #define WCD_USBSS_EQUALIZER1 0x415 105 106 #define WCD_USBSS_EQUALIZER1_EQ_EN BIT(7) 107 #define WCD_USBSS_EQUALIZER1_BW_SETTINGS GENMASK(6, 3) 108 109 #define WCD_USBSS_USB_SS_CNTL 0x419 110 111 #define WCD_USBSS_USB_SS_CNTL_STANDBY_STATE BIT(4) 112 #define WCD_USBSS_USB_SS_CNTL_RCO_EN BIT(3) 113 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE GENMASK(2, 0) 114 115 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC 2 116 #define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB 5 117 118 #define WCD_USBSS_AUDIO_FSM_START 0x433 119 120 #define WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG BIT(0) 121 122 #define WCD_USBSS_RATIO_SPKR_REXT_L_LSB 0x461 123 #define WCD_USBSS_RATIO_SPKR_REXT_L_MSB 0x462 124 #define WCD_USBSS_RATIO_SPKR_REXT_R_LSB 0x463 125 #define WCD_USBSS_RATIO_SPKR_REXT_R_MSB 0x464 126 #define WCD_USBSS_AUD_COEF_L_K0_0 0x475 127 #define WCD_USBSS_AUD_COEF_L_K0_1 0x476 128 #define WCD_USBSS_AUD_COEF_L_K0_2 0x477 129 #define WCD_USBSS_AUD_COEF_L_K1_0 0x478 130 #define WCD_USBSS_AUD_COEF_L_K1_1 0x479 131 #define WCD_USBSS_AUD_COEF_L_K2_0 0x47a 132 #define WCD_USBSS_AUD_COEF_L_K2_1 0x47b 133 #define WCD_USBSS_AUD_COEF_L_K3_0 0x47c 134 #define WCD_USBSS_AUD_COEF_L_K3_1 0x47d 135 #define WCD_USBSS_AUD_COEF_L_K4_0 0x47e 136 #define WCD_USBSS_AUD_COEF_L_K4_1 0x47f 137 #define WCD_USBSS_AUD_COEF_L_K5_0 0x480 138 #define WCD_USBSS_AUD_COEF_L_K5_1 0x481 139 #define WCD_USBSS_AUD_COEF_R_K0_0 0x482 140 #define WCD_USBSS_AUD_COEF_R_K0_1 0x483 141 #define WCD_USBSS_AUD_COEF_R_K0_2 0x484 142 #define WCD_USBSS_AUD_COEF_R_K1_0 0x485 143 #define WCD_USBSS_AUD_COEF_R_K1_1 0x486 144 #define WCD_USBSS_AUD_COEF_R_K2_0 0x487 145 #define WCD_USBSS_AUD_COEF_R_K2_1 0x488 146 #define WCD_USBSS_AUD_COEF_R_K3_0 0x489 147 #define WCD_USBSS_AUD_COEF_R_K3_1 0x48a 148 #define WCD_USBSS_AUD_COEF_R_K4_0 0x48b 149 #define WCD_USBSS_AUD_COEF_R_K4_1 0x48c 150 #define WCD_USBSS_AUD_COEF_R_K5_0 0x48d 151 #define WCD_USBSS_AUD_COEF_R_K5_1 0x48e 152 #define WCD_USBSS_GND_COEF_L_K0_0 0x48f 153 #define WCD_USBSS_GND_COEF_L_K0_1 0x490 154 #define WCD_USBSS_GND_COEF_L_K0_2 0x491 155 #define WCD_USBSS_GND_COEF_L_K1_0 0x492 156 #define WCD_USBSS_GND_COEF_L_K1_1 0x493 157 #define WCD_USBSS_GND_COEF_L_K2_0 0x494 158 #define WCD_USBSS_GND_COEF_L_K2_1 0x495 159 #define WCD_USBSS_GND_COEF_L_K3_0 0x496 160 #define WCD_USBSS_GND_COEF_L_K3_1 0x497 161 #define WCD_USBSS_GND_COEF_L_K4_0 0x498 162 #define WCD_USBSS_GND_COEF_L_K4_1 0x499 163 #define WCD_USBSS_GND_COEF_L_K5_0 0x49a 164 #define WCD_USBSS_GND_COEF_L_K5_1 0x49b 165 #define WCD_USBSS_GND_COEF_R_K0_0 0x49c 166 #define WCD_USBSS_GND_COEF_R_K0_1 0x49d 167 #define WCD_USBSS_GND_COEF_R_K0_2 0x49e 168 #define WCD_USBSS_GND_COEF_R_K1_0 0x49f 169 #define WCD_USBSS_GND_COEF_R_K1_1 0x4a0 170 #define WCD_USBSS_GND_COEF_R_K2_0 0x4a1 171 #define WCD_USBSS_GND_COEF_R_K2_1 0x4a2 172 #define WCD_USBSS_GND_COEF_R_K3_0 0x4a3 173 #define WCD_USBSS_GND_COEF_R_K3_1 0x4a4 174 #define WCD_USBSS_GND_COEF_R_K4_0 0x4a5 175 #define WCD_USBSS_GND_COEF_R_K4_1 0x4a6 176 #define WCD_USBSS_GND_COEF_R_K5_0 0x4a7 177 #define WCD_USBSS_GND_COEF_R_K5_1 0x4a8 178 179 #define WCD_USBSS_MAX_REGISTER 0x4c1 180 181 struct wcd939x_usbss { 182 struct i2c_client *client; 183 struct gpio_desc *reset_gpio; 184 struct regulator *vdd_supply; 185 186 /* used to serialize concurrent change requests */ 187 struct mutex lock; 188 189 struct typec_switch_dev *sw; 190 struct typec_mux_dev *mux; 191 192 struct regmap *regmap; 193 194 struct typec_mux *codec; 195 struct typec_switch *codec_switch; 196 197 enum typec_orientation orientation; 198 unsigned long mode; 199 unsigned int svid; 200 }; 201 202 static const struct regmap_range_cfg wcd939x_usbss_ranges[] = { 203 { 204 .range_min = 0, 205 .range_max = WCD_USBSS_MAX_REGISTER, 206 .selector_reg = 0x0, 207 .selector_mask = 0xff, 208 .selector_shift = 0, 209 .window_start = 0, 210 .window_len = 0x100, 211 }, 212 }; 213 214 static const struct regmap_config wcd939x_usbss_regmap_config = { 215 .reg_bits = 8, 216 .val_bits = 8, 217 .max_register = WCD_USBSS_MAX_REGISTER, 218 .ranges = wcd939x_usbss_ranges, 219 .num_ranges = ARRAY_SIZE(wcd939x_usbss_ranges), 220 }; 221 222 /* Linearlizer coefficients for 32ohm load */ 223 static const struct { 224 unsigned int offset; 225 unsigned int mask; 226 unsigned int value; 227 } wcd939x_usbss_coeff_init[] = { 228 { WCD_USBSS_AUD_COEF_L_K5_0, GENMASK(7, 0), 0x39 }, 229 { WCD_USBSS_AUD_COEF_R_K5_0, GENMASK(7, 0), 0x39 }, 230 { WCD_USBSS_GND_COEF_L_K2_0, GENMASK(7, 0), 0xe8 }, 231 { WCD_USBSS_GND_COEF_L_K4_0, GENMASK(7, 0), 0x73 }, 232 { WCD_USBSS_GND_COEF_R_K2_0, GENMASK(7, 0), 0xe8 }, 233 { WCD_USBSS_GND_COEF_R_K4_0, GENMASK(7, 0), 0x73 }, 234 { WCD_USBSS_RATIO_SPKR_REXT_L_LSB, GENMASK(7, 0), 0x00 }, 235 { WCD_USBSS_RATIO_SPKR_REXT_L_MSB, GENMASK(6, 0), 0x04 }, 236 { WCD_USBSS_RATIO_SPKR_REXT_R_LSB, GENMASK(7, 0), 0x00 }, 237 { WCD_USBSS_RATIO_SPKR_REXT_R_MSB, GENMASK(6, 0), 0x04 }, 238 }; 239 240 static int wcd939x_usbss_set(struct wcd939x_usbss *usbss) 241 { 242 bool reverse = (usbss->orientation == TYPEC_ORIENTATION_REVERSE); 243 bool enable_audio = false; 244 bool enable_usb = false; 245 bool enable_dp = false; 246 int ret; 247 248 /* USB Mode */ 249 if (usbss->mode < TYPEC_STATE_MODAL || 250 (!usbss->svid && (usbss->mode == TYPEC_MODE_USB2 || 251 usbss->mode == TYPEC_MODE_USB3))) { 252 enable_usb = true; 253 } else if (usbss->svid) { 254 switch (usbss->mode) { 255 /* DP Only */ 256 case TYPEC_DP_STATE_C: 257 case TYPEC_DP_STATE_E: 258 enable_dp = true; 259 break; 260 261 /* DP + USB */ 262 case TYPEC_DP_STATE_D: 263 case TYPEC_DP_STATE_F: 264 enable_usb = true; 265 enable_dp = true; 266 break; 267 268 default: 269 return -EOPNOTSUPP; 270 } 271 } else if (usbss->mode == TYPEC_MODE_AUDIO) { 272 enable_audio = true; 273 } else { 274 return -EOPNOTSUPP; 275 } 276 277 /* Disable all switches */ 278 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 279 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | 280 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES | 281 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | 282 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | 283 WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | 284 WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES | 285 WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); 286 if (ret) 287 return ret; 288 289 /* Clear switches */ 290 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 291 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 292 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES | 293 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 294 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES | 295 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES | 296 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); 297 if (ret) 298 return ret; 299 300 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 301 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 302 if (ret) 303 return ret; 304 305 /* Enable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ 306 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, 307 WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); 308 if (ret) 309 return ret; 310 311 /* Enable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ 312 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, 313 WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); 314 if (ret) 315 return ret; 316 317 /* Disable Equalizer in safe mode */ 318 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, 319 WCD_USBSS_EQUALIZER1_EQ_EN); 320 if (ret) 321 return ret; 322 323 /* Start FSM with all disabled, force write */ 324 ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, 325 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, 326 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); 327 328 /* 35us to allow the SBU switch to turn off */ 329 usleep_range(35, 1000); 330 331 /* Setup Audio Accessory mux/switch */ 332 if (enable_audio) { 333 int i; 334 335 /* 336 * AATC switch configuration: 337 * "Normal": 338 * - R: DNR 339 * - L: DNL 340 * - Sense: GSBU2 341 * - Mic: MG1 342 * - AGND: MG2 343 * "Swapped": 344 * - R: DNR 345 * - L: DNL 346 * - Sense: GSBU1 347 * - Mic: MG2 348 * - AGND: MG1 349 * Swapped information is given by the codec MBHC logic 350 */ 351 352 /* Set AATC mode */ 353 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 354 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 355 FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 356 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC)); 357 if (ret) 358 return ret; 359 360 /* Select L for DNL_SWITCHES and R for DPR_SWITCHES */ 361 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 362 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 363 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 364 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 365 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L) | 366 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, 367 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R)); 368 if (ret) 369 return ret; 370 371 if (reverse) 372 /* Select MG2 for MIC, SBU1 for Sense */ 373 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 374 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES, 375 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); 376 else 377 /* Select MG1 for MIC, SBU2 for Sense */ 378 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 379 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES, 380 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES); 381 if (ret) 382 return ret; 383 384 if (reverse) 385 /* Disable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ 386 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, 387 WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); 388 else 389 /* Disable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ 390 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, 391 WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); 392 if (ret) 393 return ret; 394 395 /* Enable SENSE, MIC switches */ 396 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 397 WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | 398 WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES); 399 if (ret) 400 return ret; 401 402 if (reverse) 403 /* Select MG1 for AGND_SWITCHES */ 404 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 405 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 406 else 407 /* Select MG2 for AGND_SWITCHES */ 408 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 409 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 410 if (ret) 411 return ret; 412 413 /* Enable AGND switches */ 414 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 415 WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); 416 if (ret) 417 return ret; 418 419 /* Enable DPR, DNL switches */ 420 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 421 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | 422 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES); 423 if (ret) 424 return ret; 425 426 /* Setup FSM delays */ 427 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_L_SW, 0x02); 428 if (ret) 429 return ret; 430 431 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_R_SW, 0x02); 432 if (ret) 433 return ret; 434 435 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_MIC_SW, 0x01); 436 if (ret) 437 return ret; 438 439 /* Start FSM, force write */ 440 ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, 441 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, 442 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); 443 if (ret) 444 return ret; 445 446 /* Default Linearlizer coefficients */ 447 for (i = 0; i < ARRAY_SIZE(wcd939x_usbss_coeff_init); ++i) 448 regmap_update_bits(usbss->regmap, 449 wcd939x_usbss_coeff_init[i].offset, 450 wcd939x_usbss_coeff_init[i].mask, 451 wcd939x_usbss_coeff_init[i].value); 452 453 return 0; 454 } 455 456 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 457 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 458 FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 459 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB)); 460 if (ret) 461 return ret; 462 463 /* Enable USB muxes */ 464 if (enable_usb) { 465 /* Do not enable Equalizer in safe mode */ 466 if (usbss->mode != TYPEC_STATE_SAFE) { 467 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, 468 WCD_USBSS_EQUALIZER1_EQ_EN); 469 if (ret) 470 return ret; 471 } 472 473 /* Select DN for DNL_SWITCHES and DP for DPR_SWITCHES */ 474 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 475 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 476 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 477 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 478 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN) | 479 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, 480 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP)); 481 if (ret) 482 return ret; 483 484 /* Enable DNL_SWITCHES and DPR_SWITCHES */ 485 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 486 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | 487 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES); 488 if (ret) 489 return ret; 490 } 491 492 /* Enable DP AUX muxes */ 493 if (enable_dp) { 494 /* Update Leakage Canceller Coefficient for AUXP pins */ 495 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_CTL, 496 WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, 497 FIELD_PREP(WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, 498 5)); 499 if (ret) 500 return ret; 501 502 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_THRESH, 503 WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM); 504 if (ret) 505 return ret; 506 507 if (reverse) 508 /* Select MG2 for AUXP and MG1 for AUXM */ 509 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 510 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 511 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, 512 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES); 513 else 514 /* Select MG1 for AUXP and MG2 for AUXM */ 515 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 516 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 517 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, 518 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES); 519 if (ret) 520 return ret; 521 522 /* Enable DP_AUXP_TO_MGX and DP_AUXM_TO_MGX switches */ 523 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 524 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | 525 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES); 526 527 /* 15us to allow the SBU switch to turn on again */ 528 usleep_range(15, 1000); 529 } 530 531 return 0; 532 } 533 534 static int wcd939x_usbss_switch_set(struct typec_switch_dev *sw, 535 enum typec_orientation orientation) 536 { 537 struct wcd939x_usbss *usbss = typec_switch_get_drvdata(sw); 538 int ret = 0; 539 540 mutex_lock(&usbss->lock); 541 542 if (usbss->orientation != orientation) { 543 usbss->orientation = orientation; 544 545 ret = wcd939x_usbss_set(usbss); 546 } 547 548 mutex_unlock(&usbss->lock); 549 550 if (ret) 551 return ret; 552 553 /* Report orientation to codec after switch has been done */ 554 return typec_switch_set(usbss->codec_switch, orientation); 555 } 556 557 static int wcd939x_usbss_mux_set(struct typec_mux_dev *mux, 558 struct typec_mux_state *state) 559 { 560 struct wcd939x_usbss *usbss = typec_mux_get_drvdata(mux); 561 int ret = 0; 562 563 mutex_lock(&usbss->lock); 564 565 if (usbss->mode != state->mode) { 566 usbss->mode = state->mode; 567 568 if (state->alt) 569 usbss->svid = state->alt->svid; 570 else 571 usbss->svid = 0; // No SVID 572 573 ret = wcd939x_usbss_set(usbss); 574 } 575 576 mutex_unlock(&usbss->lock); 577 578 if (ret) 579 return ret; 580 581 /* Report event to codec after switch has been done */ 582 return typec_mux_set(usbss->codec, state); 583 } 584 585 static int wcd939x_usbss_probe(struct i2c_client *client) 586 { 587 struct device *dev = &client->dev; 588 struct typec_switch_desc sw_desc = { }; 589 struct typec_mux_desc mux_desc = { }; 590 struct wcd939x_usbss *usbss; 591 int ret; 592 593 usbss = devm_kzalloc(dev, sizeof(*usbss), GFP_KERNEL); 594 if (!usbss) 595 return -ENOMEM; 596 597 usbss->client = client; 598 mutex_init(&usbss->lock); 599 600 usbss->regmap = devm_regmap_init_i2c(client, &wcd939x_usbss_regmap_config); 601 if (IS_ERR(usbss->regmap)) 602 return dev_err_probe(dev, PTR_ERR(usbss->regmap), "failed to initialize regmap\n"); 603 604 usbss->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 605 if (IS_ERR(usbss->reset_gpio)) 606 return dev_err_probe(dev, PTR_ERR(usbss->reset_gpio), 607 "unable to acquire reset gpio\n"); 608 609 usbss->vdd_supply = devm_regulator_get_optional(dev, "vdd"); 610 if (IS_ERR(usbss->vdd_supply)) 611 return PTR_ERR(usbss->vdd_supply); 612 613 /* Get Codec's MUX & Switch devices */ 614 usbss->codec = fwnode_typec_mux_get(dev->fwnode); 615 if (IS_ERR(usbss->codec)) 616 return dev_err_probe(dev, PTR_ERR(usbss->codec), 617 "failed to acquire codec mode-switch\n"); 618 619 usbss->codec_switch = fwnode_typec_switch_get(dev->fwnode); 620 if (IS_ERR(usbss->codec_switch)) { 621 ret = dev_err_probe(dev, PTR_ERR(usbss->codec_switch), 622 "failed to acquire codec orientation-switch\n"); 623 goto err_mux_put; 624 } 625 626 usbss->mode = TYPEC_STATE_SAFE; 627 usbss->orientation = TYPEC_ORIENTATION_NONE; 628 629 gpiod_set_value(usbss->reset_gpio, 1); 630 631 ret = regulator_enable(usbss->vdd_supply); 632 if (ret) { 633 dev_err(dev, "Failed to enable vdd: %d\n", ret); 634 goto err_mux_switch; 635 } 636 637 msleep(20); 638 639 gpiod_set_value(usbss->reset_gpio, 0); 640 641 msleep(20); 642 643 /* Disable standby */ 644 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 645 WCD_USBSS_USB_SS_CNTL_STANDBY_STATE); 646 if (ret) 647 goto err_regulator_disable; 648 649 /* Set manual mode by default */ 650 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_FUNCTION_ENABLE, 651 WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT, 652 FIELD_PREP(WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT, 653 WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL)); 654 if (ret) 655 goto err_regulator_disable; 656 657 /* Enable dynamic boosting for DP and DN */ 658 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DP_DN_MISC1, 659 WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN | 660 WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN); 661 if (ret) 662 goto err_regulator_disable; 663 664 /* Enable dynamic boosting for MG1 OVP */ 665 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_MISC, 666 WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN); 667 if (ret) 668 goto err_regulator_disable; 669 670 /* Enable dynamic boosting for MG2 OVP */ 671 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_MISC, 672 WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN); 673 if (ret) 674 goto err_regulator_disable; 675 676 /* Write 0xFF to WCD_USBSS_CPLDO_CTL2 */ 677 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_CPLDO_CTL2, 0xff); 678 if (ret) 679 goto err_regulator_disable; 680 681 /* Set RCO_EN: WCD_USBSS_USB_SS_CNTL Bit<3> --> 0x0 --> 0x1 */ 682 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 683 WCD_USBSS_USB_SS_CNTL_RCO_EN); 684 if (ret) 685 goto err_regulator_disable; 686 687 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 688 WCD_USBSS_USB_SS_CNTL_RCO_EN); 689 if (ret) 690 goto err_regulator_disable; 691 692 /* Disable all switches but enable the mux */ 693 ret = regmap_write(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 694 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE); 695 if (ret) 696 goto err_regulator_disable; 697 698 /* Setup in SAFE mode */ 699 ret = wcd939x_usbss_set(usbss); 700 if (ret) 701 goto err_regulator_disable; 702 703 sw_desc.drvdata = usbss; 704 sw_desc.fwnode = dev_fwnode(dev); 705 sw_desc.set = wcd939x_usbss_switch_set; 706 707 usbss->sw = typec_switch_register(dev, &sw_desc); 708 if (IS_ERR(usbss->sw)) { 709 ret = dev_err_probe(dev, PTR_ERR(usbss->sw), "failed to register typec switch\n"); 710 goto err_regulator_disable; 711 } 712 713 mux_desc.drvdata = usbss; 714 mux_desc.fwnode = dev_fwnode(dev); 715 mux_desc.set = wcd939x_usbss_mux_set; 716 717 usbss->mux = typec_mux_register(dev, &mux_desc); 718 if (IS_ERR(usbss->mux)) { 719 ret = dev_err_probe(dev, PTR_ERR(usbss->mux), "failed to register typec mux\n"); 720 goto err_switch_unregister; 721 } 722 723 i2c_set_clientdata(client, usbss); 724 725 return 0; 726 727 err_switch_unregister: 728 typec_switch_unregister(usbss->sw); 729 730 err_regulator_disable: 731 regulator_disable(usbss->vdd_supply); 732 733 err_mux_switch: 734 typec_switch_put(usbss->codec_switch); 735 736 err_mux_put: 737 typec_mux_put(usbss->codec); 738 739 return ret; 740 } 741 742 static void wcd939x_usbss_remove(struct i2c_client *client) 743 { 744 struct wcd939x_usbss *usbss = i2c_get_clientdata(client); 745 746 typec_mux_unregister(usbss->mux); 747 typec_switch_unregister(usbss->sw); 748 749 regulator_disable(usbss->vdd_supply); 750 751 typec_switch_put(usbss->codec_switch); 752 typec_mux_put(usbss->codec); 753 } 754 755 static const struct i2c_device_id wcd939x_usbss_table[] = { 756 { "wcd9390-usbss" }, 757 { } 758 }; 759 MODULE_DEVICE_TABLE(i2c, wcd939x_usbss_table); 760 761 static const struct of_device_id wcd939x_usbss_of_table[] = { 762 { .compatible = "qcom,wcd9390-usbss" }, 763 { } 764 }; 765 MODULE_DEVICE_TABLE(of, wcd939x_usbss_of_table); 766 767 static struct i2c_driver wcd939x_usbss_driver = { 768 .driver = { 769 .name = "wcd939x-usbss", 770 .of_match_table = wcd939x_usbss_of_table, 771 }, 772 .probe = wcd939x_usbss_probe, 773 .remove = wcd939x_usbss_remove, 774 .id_table = wcd939x_usbss_table, 775 }; 776 module_i2c_driver(wcd939x_usbss_driver); 777 778 MODULE_DESCRIPTION("Qualcomm WCD939x USBSS driver"); 779 MODULE_LICENSE("GPL"); 780