1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * OnSemi NB7VPQ904M Type-C driver 4 * 5 * Copyright (C) 2023 Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 6 */ 7#include <linux/i2c.h> 8#include <linux/mutex.h> 9#include <linux/kernel.h> 10#include <linux/module.h> 11#include <linux/regmap.h> 12#include <linux/bitfield.h> 13#include <linux/of_graph.h> 14#include <drm/bridge/aux-bridge.h> 15#include <linux/usb/typec_dp.h> 16#include <linux/usb/typec_mux.h> 17#include <linux/usb/typec_retimer.h> 18#include <linux/gpio/consumer.h> 19#include <linux/regulator/consumer.h> 20 21#define NB7_CHNA 0 22#define NB7_CHNB 1 23#define NB7_CHNC 2 24#define NB7_CHND 3 25#define NB7_IS_CHAN_AD(channel) (channel == NB7_CHNA || channel == NB7_CHND) 26 27#define GEN_DEV_SET_REG 0x00 28 29#define GEN_DEV_SET_CHIP_EN BIT(0) 30#define GEN_DEV_SET_CHNA_EN BIT(4) 31#define GEN_DEV_SET_CHNB_EN BIT(5) 32#define GEN_DEV_SET_CHNC_EN BIT(6) 33#define GEN_DEV_SET_CHND_EN BIT(7) 34 35#define GEN_DEV_SET_OP_MODE_MASK GENMASK(3, 1) 36 37#define GEN_DEV_SET_OP_MODE_DP_CC2 0 38#define GEN_DEV_SET_OP_MODE_DP_CC1 1 39#define GEN_DEV_SET_OP_MODE_DP_4LANE 2 40#define GEN_DEV_SET_OP_MODE_USB 5 41 42#define EQ_SETTING_REG_BASE 0x01 43#define EQ_SETTING_REG(n) (EQ_SETTING_REG_BASE + (n) * 2) 44#define EQ_SETTING_MASK GENMASK(3, 1) 45 46#define OUTPUT_COMPRESSION_AND_POL_REG_BASE 0x02 47#define OUTPUT_COMPRESSION_AND_POL_REG(n) (OUTPUT_COMPRESSION_AND_POL_REG_BASE + (n) * 2) 48#define OUTPUT_COMPRESSION_MASK GENMASK(2, 1) 49 50#define FLAT_GAIN_REG_BASE 0x18 51#define FLAT_GAIN_REG(n) (FLAT_GAIN_REG_BASE + (n) * 2) 52#define FLAT_GAIN_MASK GENMASK(1, 0) 53 54#define LOSS_MATCH_REG_BASE 0x19 55#define LOSS_MATCH_REG(n) (LOSS_MATCH_REG_BASE + (n) * 2) 56#define LOSS_MATCH_MASK GENMASK(1, 0) 57 58#define AUX_CC_REG 0x09 59 60#define CHIP_VERSION_REG 0x17 61 62struct nb7vpq904m { 63 struct i2c_client *client; 64 struct gpio_desc *enable_gpio; 65 struct regulator *vcc_supply; 66 struct regmap *regmap; 67 struct typec_switch_dev *sw; 68 struct typec_retimer *retimer; 69 70 bool swap_data_lanes; 71 struct typec_switch *typec_switch; 72 73 struct mutex lock; /* protect non-concurrent retimer & switch */ 74 75 enum typec_orientation orientation; 76 unsigned long mode; 77 unsigned int svid; 78}; 79 80static void nb7vpq904m_set_channel(struct nb7vpq904m *nb7, unsigned int channel, bool dp) 81{ 82 u8 eq, out_comp, flat_gain, loss_match; 83 84 if (dp) { 85 eq = NB7_IS_CHAN_AD(channel) ? 0x6 : 0x4; 86 out_comp = 0x3; 87 flat_gain = NB7_IS_CHAN_AD(channel) ? 0x2 : 0x1; 88 loss_match = 0x3; 89 } else { 90 eq = 0x4; 91 out_comp = 0x3; 92 flat_gain = NB7_IS_CHAN_AD(channel) ? 0x3 : 0x1; 93 loss_match = NB7_IS_CHAN_AD(channel) ? 0x1 : 0x3; 94 } 95 96 regmap_update_bits(nb7->regmap, EQ_SETTING_REG(channel), 97 EQ_SETTING_MASK, FIELD_PREP(EQ_SETTING_MASK, eq)); 98 regmap_update_bits(nb7->regmap, OUTPUT_COMPRESSION_AND_POL_REG(channel), 99 OUTPUT_COMPRESSION_MASK, FIELD_PREP(OUTPUT_COMPRESSION_MASK, out_comp)); 100 regmap_update_bits(nb7->regmap, FLAT_GAIN_REG(channel), 101 FLAT_GAIN_MASK, FIELD_PREP(FLAT_GAIN_MASK, flat_gain)); 102 regmap_update_bits(nb7->regmap, LOSS_MATCH_REG(channel), 103 LOSS_MATCH_MASK, FIELD_PREP(LOSS_MATCH_MASK, loss_match)); 104} 105 106static int nb7vpq904m_set(struct nb7vpq904m *nb7) 107{ 108 bool reverse = (nb7->orientation == TYPEC_ORIENTATION_REVERSE); 109 110 switch (nb7->mode) { 111 case TYPEC_STATE_SAFE: 112 regmap_write(nb7->regmap, GEN_DEV_SET_REG, 113 GEN_DEV_SET_CHIP_EN | 114 GEN_DEV_SET_CHNA_EN | 115 GEN_DEV_SET_CHNB_EN | 116 GEN_DEV_SET_CHNC_EN | 117 GEN_DEV_SET_CHND_EN | 118 FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, 119 GEN_DEV_SET_OP_MODE_USB)); 120 nb7vpq904m_set_channel(nb7, NB7_CHNA, false); 121 nb7vpq904m_set_channel(nb7, NB7_CHNB, false); 122 nb7vpq904m_set_channel(nb7, NB7_CHNC, false); 123 nb7vpq904m_set_channel(nb7, NB7_CHND, false); 124 regmap_write(nb7->regmap, AUX_CC_REG, 0x2); 125 126 return 0; 127 128 case TYPEC_STATE_USB: 129 /* 130 * Normal Orientation (CC1) 131 * A -> USB RX 132 * B -> USB TX 133 * C -> X 134 * D -> X 135 * Flipped Orientation (CC2) 136 * A -> X 137 * B -> X 138 * C -> USB TX 139 * D -> USB RX 140 * 141 * Reversed if data lanes are swapped 142 */ 143 if (reverse ^ nb7->swap_data_lanes) { 144 regmap_write(nb7->regmap, GEN_DEV_SET_REG, 145 GEN_DEV_SET_CHIP_EN | 146 GEN_DEV_SET_CHNA_EN | 147 GEN_DEV_SET_CHNB_EN | 148 FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, 149 GEN_DEV_SET_OP_MODE_USB)); 150 nb7vpq904m_set_channel(nb7, NB7_CHNA, false); 151 nb7vpq904m_set_channel(nb7, NB7_CHNB, false); 152 } else { 153 regmap_write(nb7->regmap, GEN_DEV_SET_REG, 154 GEN_DEV_SET_CHIP_EN | 155 GEN_DEV_SET_CHNC_EN | 156 GEN_DEV_SET_CHND_EN | 157 FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, 158 GEN_DEV_SET_OP_MODE_USB)); 159 nb7vpq904m_set_channel(nb7, NB7_CHNC, false); 160 nb7vpq904m_set_channel(nb7, NB7_CHND, false); 161 } 162 regmap_write(nb7->regmap, AUX_CC_REG, 0x2); 163 164 return 0; 165 166 default: 167 if (nb7->svid != USB_TYPEC_DP_SID) 168 return -EINVAL; 169 170 break; 171 } 172 173 /* DP Altmode Setup */ 174 175 regmap_write(nb7->regmap, AUX_CC_REG, reverse ? 0x1 : 0x0); 176 177 switch (nb7->mode) { 178 case TYPEC_DP_STATE_C: 179 case TYPEC_DP_STATE_E: 180 /* 181 * Normal Orientation (CC1) 182 * A -> DP3 183 * B -> DP2 184 * C -> DP1 185 * D -> DP0 186 * Flipped Orientation (CC2) 187 * A -> DP0 188 * B -> DP1 189 * C -> DP2 190 * D -> DP3 191 */ 192 regmap_write(nb7->regmap, GEN_DEV_SET_REG, 193 GEN_DEV_SET_CHIP_EN | 194 GEN_DEV_SET_CHNA_EN | 195 GEN_DEV_SET_CHNB_EN | 196 GEN_DEV_SET_CHNC_EN | 197 GEN_DEV_SET_CHND_EN | 198 FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, 199 GEN_DEV_SET_OP_MODE_DP_4LANE)); 200 nb7vpq904m_set_channel(nb7, NB7_CHNA, true); 201 nb7vpq904m_set_channel(nb7, NB7_CHNB, true); 202 nb7vpq904m_set_channel(nb7, NB7_CHNC, true); 203 nb7vpq904m_set_channel(nb7, NB7_CHND, true); 204 break; 205 206 case TYPEC_DP_STATE_D: 207 case TYPEC_DP_STATE_F: 208 regmap_write(nb7->regmap, GEN_DEV_SET_REG, 209 GEN_DEV_SET_CHIP_EN | 210 GEN_DEV_SET_CHNA_EN | 211 GEN_DEV_SET_CHNB_EN | 212 GEN_DEV_SET_CHNC_EN | 213 GEN_DEV_SET_CHND_EN | 214 FIELD_PREP(GEN_DEV_SET_OP_MODE_MASK, 215 reverse ^ nb7->swap_data_lanes ? 216 GEN_DEV_SET_OP_MODE_DP_CC2 217 : GEN_DEV_SET_OP_MODE_DP_CC1)); 218 219 /* 220 * Normal Orientation (CC1) 221 * A -> USB RX 222 * B -> USB TX 223 * C -> DP1 224 * D -> DP0 225 * Flipped Orientation (CC2) 226 * A -> DP0 227 * B -> DP1 228 * C -> USB TX 229 * D -> USB RX 230 * 231 * Reversed if data lanes are swapped 232 */ 233 if (nb7->swap_data_lanes) { 234 nb7vpq904m_set_channel(nb7, NB7_CHNA, !reverse); 235 nb7vpq904m_set_channel(nb7, NB7_CHNB, !reverse); 236 nb7vpq904m_set_channel(nb7, NB7_CHNC, reverse); 237 nb7vpq904m_set_channel(nb7, NB7_CHND, reverse); 238 } else { 239 nb7vpq904m_set_channel(nb7, NB7_CHNA, reverse); 240 nb7vpq904m_set_channel(nb7, NB7_CHNB, reverse); 241 nb7vpq904m_set_channel(nb7, NB7_CHNC, !reverse); 242 nb7vpq904m_set_channel(nb7, NB7_CHND, !reverse); 243 } 244 break; 245 246 default: 247 return -EOPNOTSUPP; 248 } 249 250 return 0; 251} 252 253static int nb7vpq904m_sw_set(struct typec_switch_dev *sw, enum typec_orientation orientation) 254{ 255 struct nb7vpq904m *nb7 = typec_switch_get_drvdata(sw); 256 int ret; 257 258 ret = typec_switch_set(nb7->typec_switch, orientation); 259 if (ret) 260 return ret; 261 262 mutex_lock(&nb7->lock); 263 264 if (nb7->orientation != orientation) { 265 nb7->orientation = orientation; 266 267 ret = nb7vpq904m_set(nb7); 268 } 269 270 mutex_unlock(&nb7->lock); 271 272 return ret; 273} 274 275static int nb7vpq904m_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state) 276{ 277 struct nb7vpq904m *nb7 = typec_retimer_get_drvdata(retimer); 278 int ret = 0; 279 280 mutex_lock(&nb7->lock); 281 282 if (nb7->mode != state->mode) { 283 nb7->mode = state->mode; 284 285 if (state->alt) 286 nb7->svid = state->alt->svid; 287 else 288 nb7->svid = 0; // No SVID 289 290 ret = nb7vpq904m_set(nb7); 291 } 292 293 mutex_unlock(&nb7->lock); 294 295 return ret; 296} 297 298static const struct regmap_config nb7_regmap = { 299 .max_register = 0x1f, 300 .reg_bits = 8, 301 .val_bits = 8, 302}; 303 304enum { 305 NORMAL_LANE_MAPPING, 306 INVERT_LANE_MAPPING, 307}; 308 309#define DATA_LANES_COUNT 4 310 311static const int supported_data_lane_mapping[][DATA_LANES_COUNT] = { 312 [NORMAL_LANE_MAPPING] = { 0, 1, 2, 3 }, 313 [INVERT_LANE_MAPPING] = { 3, 2, 1, 0 }, 314}; 315 316static int nb7vpq904m_parse_data_lanes_mapping(struct nb7vpq904m *nb7) 317{ 318 struct device_node *ep; 319 u32 data_lanes[4]; 320 int ret, i, j; 321 322 ep = of_graph_get_endpoint_by_regs(nb7->client->dev.of_node, 1, 0); 323 324 if (ep) { 325 ret = of_property_count_u32_elems(ep, "data-lanes"); 326 if (ret == -EINVAL) 327 /* Property isn't here, consider default mapping */ 328 goto out_done; 329 if (ret < 0) 330 goto out_error; 331 332 if (ret != DATA_LANES_COUNT) { 333 dev_err(&nb7->client->dev, "expected 4 data lanes\n"); 334 ret = -EINVAL; 335 goto out_error; 336 } 337 338 ret = of_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT); 339 if (ret) 340 goto out_error; 341 342 for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) { 343 for (j = 0; j < DATA_LANES_COUNT; j++) { 344 if (data_lanes[j] != supported_data_lane_mapping[i][j]) 345 break; 346 } 347 348 if (j == DATA_LANES_COUNT) 349 break; 350 } 351 352 switch (i) { 353 case NORMAL_LANE_MAPPING: 354 break; 355 case INVERT_LANE_MAPPING: 356 nb7->swap_data_lanes = true; 357 dev_info(&nb7->client->dev, "using inverted data lanes mapping\n"); 358 break; 359 default: 360 dev_err(&nb7->client->dev, "invalid data lanes mapping\n"); 361 ret = -EINVAL; 362 goto out_error; 363 } 364 } 365 366out_done: 367 ret = 0; 368 369out_error: 370 of_node_put(ep); 371 372 return ret; 373} 374 375static int nb7vpq904m_probe(struct i2c_client *client) 376{ 377 struct device *dev = &client->dev; 378 struct typec_switch_desc sw_desc = { }; 379 struct typec_retimer_desc retimer_desc = { }; 380 struct nb7vpq904m *nb7; 381 int ret; 382 383 nb7 = devm_kzalloc(dev, sizeof(*nb7), GFP_KERNEL); 384 if (!nb7) 385 return -ENOMEM; 386 387 nb7->client = client; 388 389 nb7->regmap = devm_regmap_init_i2c(client, &nb7_regmap); 390 if (IS_ERR(nb7->regmap)) { 391 dev_err(&client->dev, "Failed to allocate register map\n"); 392 return PTR_ERR(nb7->regmap); 393 } 394 395 nb7->mode = TYPEC_STATE_SAFE; 396 nb7->orientation = TYPEC_ORIENTATION_NONE; 397 398 mutex_init(&nb7->lock); 399 400 nb7->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); 401 if (IS_ERR(nb7->enable_gpio)) 402 return dev_err_probe(dev, PTR_ERR(nb7->enable_gpio), 403 "unable to acquire enable gpio\n"); 404 405 nb7->vcc_supply = devm_regulator_get_optional(dev, "vcc"); 406 if (IS_ERR(nb7->vcc_supply)) 407 return PTR_ERR(nb7->vcc_supply); 408 409 nb7->typec_switch = fwnode_typec_switch_get(dev->fwnode); 410 if (IS_ERR(nb7->typec_switch)) 411 return dev_err_probe(dev, PTR_ERR(nb7->typec_switch), 412 "failed to acquire orientation-switch\n"); 413 414 ret = nb7vpq904m_parse_data_lanes_mapping(nb7); 415 if (ret) 416 return ret; 417 418 ret = regulator_enable(nb7->vcc_supply); 419 if (ret) 420 dev_warn(dev, "Failed to enable vcc: %d\n", ret); 421 422 gpiod_set_value(nb7->enable_gpio, 1); 423 424 ret = drm_aux_bridge_register(dev); 425 if (ret) 426 goto err_disable_gpio; 427 428 sw_desc.drvdata = nb7; 429 sw_desc.fwnode = dev->fwnode; 430 sw_desc.set = nb7vpq904m_sw_set; 431 432 nb7->sw = typec_switch_register(dev, &sw_desc); 433 if (IS_ERR(nb7->sw)) { 434 ret = dev_err_probe(dev, PTR_ERR(nb7->sw), 435 "Error registering typec switch\n"); 436 goto err_disable_gpio; 437 } 438 439 retimer_desc.drvdata = nb7; 440 retimer_desc.fwnode = dev->fwnode; 441 retimer_desc.set = nb7vpq904m_retimer_set; 442 443 nb7->retimer = typec_retimer_register(dev, &retimer_desc); 444 if (IS_ERR(nb7->retimer)) { 445 ret = dev_err_probe(dev, PTR_ERR(nb7->retimer), 446 "Error registering typec retimer\n"); 447 goto err_switch_unregister; 448 } 449 450 return 0; 451 452err_switch_unregister: 453 typec_switch_unregister(nb7->sw); 454 455err_disable_gpio: 456 gpiod_set_value(nb7->enable_gpio, 0); 457 regulator_disable(nb7->vcc_supply); 458 459 return ret; 460} 461 462static void nb7vpq904m_remove(struct i2c_client *client) 463{ 464 struct nb7vpq904m *nb7 = i2c_get_clientdata(client); 465 466 typec_retimer_unregister(nb7->retimer); 467 typec_switch_unregister(nb7->sw); 468 469 gpiod_set_value(nb7->enable_gpio, 0); 470 471 regulator_disable(nb7->vcc_supply); 472} 473 474static const struct i2c_device_id nb7vpq904m_table[] = { 475 { "nb7vpq904m" }, 476 { } 477}; 478MODULE_DEVICE_TABLE(i2c, nb7vpq904m_table); 479 480static const struct of_device_id nb7vpq904m_of_table[] = { 481 { .compatible = "onnn,nb7vpq904m" }, 482 { } 483}; 484MODULE_DEVICE_TABLE(of, nb7vpq904m_of_table); 485 486static struct i2c_driver nb7vpq904m_driver = { 487 .driver = { 488 .name = "nb7vpq904m", 489 .of_match_table = nb7vpq904m_of_table, 490 }, 491 .probe = nb7vpq904m_probe, 492 .remove = nb7vpq904m_remove, 493 .id_table = nb7vpq904m_table, 494}; 495 496module_i2c_driver(nb7vpq904m_driver); 497 498MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>"); 499MODULE_DESCRIPTION("OnSemi NB7VPQ904M Type-C driver"); 500MODULE_LICENSE("GPL"); 501