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.

at v5.0-rc4 522 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Driver for TI TPS6598x USB Power Delivery controller family 4 * 5 * Copyright (C) 2017, Intel Corporation 6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> 7 */ 8 9#include <linux/i2c.h> 10#include <linux/acpi.h> 11#include <linux/module.h> 12#include <linux/regmap.h> 13#include <linux/interrupt.h> 14#include <linux/usb/typec.h> 15 16/* Register offsets */ 17#define TPS_REG_CMD1 0x08 18#define TPS_REG_DATA1 0x09 19#define TPS_REG_INT_EVENT1 0x14 20#define TPS_REG_INT_EVENT2 0x15 21#define TPS_REG_INT_MASK1 0x16 22#define TPS_REG_INT_MASK2 0x17 23#define TPS_REG_INT_CLEAR1 0x18 24#define TPS_REG_INT_CLEAR2 0x19 25#define TPS_REG_STATUS 0x1a 26#define TPS_REG_SYSTEM_CONF 0x28 27#define TPS_REG_CTRL_CONF 0x29 28#define TPS_REG_POWER_STATUS 0x3f 29#define TPS_REG_RX_IDENTITY_SOP 0x48 30 31/* TPS_REG_INT_* bits */ 32#define TPS_REG_INT_PLUG_EVENT BIT(3) 33 34/* TPS_REG_STATUS bits */ 35#define TPS_STATUS_PLUG_PRESENT BIT(0) 36#define TPS_STATUS_ORIENTATION BIT(4) 37#define TPS_STATUS_PORTROLE(s) (!!((s) & BIT(5))) 38#define TPS_STATUS_DATAROLE(s) (!!((s) & BIT(6))) 39#define TPS_STATUS_VCONN(s) (!!((s) & BIT(7))) 40 41/* TPS_REG_SYSTEM_CONF bits */ 42#define TPS_SYSCONF_PORTINFO(c) ((c) & 3) 43 44enum { 45 TPS_PORTINFO_SINK, 46 TPS_PORTINFO_SINK_ACCESSORY, 47 TPS_PORTINFO_DRP_UFP, 48 TPS_PORTINFO_DRP_UFP_DRD, 49 TPS_PORTINFO_DRP_DFP, 50 TPS_PORTINFO_DRP_DFP_DRD, 51 TPS_PORTINFO_SOURCE, 52}; 53 54/* TPS_REG_POWER_STATUS bits */ 55#define TPS_POWER_STATUS_SOURCESINK BIT(1) 56#define TPS_POWER_STATUS_PWROPMODE(p) (((p) & GENMASK(3, 2)) >> 2) 57 58/* TPS_REG_RX_IDENTITY_SOP */ 59struct tps6598x_rx_identity_reg { 60 u8 status; 61 struct usb_pd_identity identity; 62 u32 vdo[3]; 63} __packed; 64 65/* Standard Task return codes */ 66#define TPS_TASK_TIMEOUT 1 67#define TPS_TASK_REJECTED 3 68 69/* Unrecognized commands will be replaced with "!CMD" */ 70#define INVALID_CMD(_cmd_) (_cmd_ == 0x444d4321) 71 72struct tps6598x { 73 struct device *dev; 74 struct regmap *regmap; 75 struct mutex lock; /* device lock */ 76 u8 i2c_protocol:1; 77 78 struct typec_port *port; 79 struct typec_partner *partner; 80 struct usb_pd_identity partner_identity; 81 struct typec_capability typec_cap; 82}; 83 84/* 85 * Max data bytes for Data1, Data2, and other registers. See ch 1.3.2: 86 * http://www.ti.com/lit/ug/slvuan1a/slvuan1a.pdf 87 */ 88#define TPS_MAX_LEN 64 89 90static int 91tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len) 92{ 93 u8 data[TPS_MAX_LEN + 1]; 94 int ret; 95 96 if (WARN_ON(len + 1 > sizeof(data))) 97 return -EINVAL; 98 99 if (!tps->i2c_protocol) 100 return regmap_raw_read(tps->regmap, reg, val, len); 101 102 ret = regmap_raw_read(tps->regmap, reg, data, sizeof(data)); 103 if (ret) 104 return ret; 105 106 if (data[0] < len) 107 return -EIO; 108 109 memcpy(val, &data[1], len); 110 return 0; 111} 112 113static inline int tps6598x_read16(struct tps6598x *tps, u8 reg, u16 *val) 114{ 115 return tps6598x_block_read(tps, reg, val, sizeof(u16)); 116} 117 118static inline int tps6598x_read32(struct tps6598x *tps, u8 reg, u32 *val) 119{ 120 return tps6598x_block_read(tps, reg, val, sizeof(u32)); 121} 122 123static inline int tps6598x_read64(struct tps6598x *tps, u8 reg, u64 *val) 124{ 125 return tps6598x_block_read(tps, reg, val, sizeof(u64)); 126} 127 128static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val) 129{ 130 return regmap_raw_write(tps->regmap, reg, &val, sizeof(u16)); 131} 132 133static inline int tps6598x_write32(struct tps6598x *tps, u8 reg, u32 val) 134{ 135 return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32)); 136} 137 138static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val) 139{ 140 return regmap_raw_write(tps->regmap, reg, &val, sizeof(u64)); 141} 142 143static inline int 144tps6598x_write_4cc(struct tps6598x *tps, u8 reg, const char *val) 145{ 146 return regmap_raw_write(tps->regmap, reg, &val, sizeof(u32)); 147} 148 149static int tps6598x_read_partner_identity(struct tps6598x *tps) 150{ 151 struct tps6598x_rx_identity_reg id; 152 int ret; 153 154 ret = tps6598x_block_read(tps, TPS_REG_RX_IDENTITY_SOP, 155 &id, sizeof(id)); 156 if (ret) 157 return ret; 158 159 tps->partner_identity = id.identity; 160 161 return 0; 162} 163 164static int tps6598x_connect(struct tps6598x *tps, u32 status) 165{ 166 struct typec_partner_desc desc; 167 enum typec_pwr_opmode mode; 168 u16 pwr_status; 169 int ret; 170 171 if (tps->partner) 172 return 0; 173 174 ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &pwr_status); 175 if (ret < 0) 176 return ret; 177 178 mode = TPS_POWER_STATUS_PWROPMODE(pwr_status); 179 180 desc.usb_pd = mode == TYPEC_PWR_MODE_PD; 181 desc.accessory = TYPEC_ACCESSORY_NONE; /* XXX: handle accessories */ 182 desc.identity = NULL; 183 184 if (desc.usb_pd) { 185 ret = tps6598x_read_partner_identity(tps); 186 if (ret) 187 return ret; 188 desc.identity = &tps->partner_identity; 189 } 190 191 typec_set_pwr_opmode(tps->port, mode); 192 typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status)); 193 typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status)); 194 typec_set_data_role(tps->port, TPS_STATUS_DATAROLE(status)); 195 196 tps->partner = typec_register_partner(tps->port, &desc); 197 if (IS_ERR(tps->partner)) 198 return PTR_ERR(tps->partner); 199 200 if (desc.identity) 201 typec_partner_set_identity(tps->partner); 202 203 return 0; 204} 205 206static void tps6598x_disconnect(struct tps6598x *tps, u32 status) 207{ 208 if (!IS_ERR(tps->partner)) 209 typec_unregister_partner(tps->partner); 210 tps->partner = NULL; 211 typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB); 212 typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status)); 213 typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status)); 214 typec_set_data_role(tps->port, TPS_STATUS_DATAROLE(status)); 215} 216 217static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd, 218 size_t in_len, u8 *in_data, 219 size_t out_len, u8 *out_data) 220{ 221 unsigned long timeout; 222 u32 val; 223 int ret; 224 225 ret = tps6598x_read32(tps, TPS_REG_CMD1, &val); 226 if (ret) 227 return ret; 228 if (val && !INVALID_CMD(val)) 229 return -EBUSY; 230 231 if (in_len) { 232 ret = regmap_raw_write(tps->regmap, TPS_REG_DATA1, 233 in_data, in_len); 234 if (ret) 235 return ret; 236 } 237 238 ret = tps6598x_write_4cc(tps, TPS_REG_CMD1, cmd); 239 if (ret < 0) 240 return ret; 241 242 /* XXX: Using 1s for now, but it may not be enough for every command. */ 243 timeout = jiffies + msecs_to_jiffies(1000); 244 245 do { 246 ret = tps6598x_read32(tps, TPS_REG_CMD1, &val); 247 if (ret) 248 return ret; 249 if (INVALID_CMD(val)) 250 return -EINVAL; 251 252 if (time_is_before_jiffies(timeout)) 253 return -ETIMEDOUT; 254 } while (val); 255 256 if (out_len) { 257 ret = tps6598x_block_read(tps, TPS_REG_DATA1, 258 out_data, out_len); 259 if (ret) 260 return ret; 261 val = out_data[0]; 262 } else { 263 ret = tps6598x_block_read(tps, TPS_REG_DATA1, &val, sizeof(u8)); 264 if (ret) 265 return ret; 266 } 267 268 switch (val) { 269 case TPS_TASK_TIMEOUT: 270 return -ETIMEDOUT; 271 case TPS_TASK_REJECTED: 272 return -EPERM; 273 default: 274 break; 275 } 276 277 return 0; 278} 279 280static int 281tps6598x_dr_set(const struct typec_capability *cap, enum typec_data_role role) 282{ 283 struct tps6598x *tps = container_of(cap, struct tps6598x, typec_cap); 284 const char *cmd = (role == TYPEC_DEVICE) ? "SWUF" : "SWDF"; 285 u32 status; 286 int ret; 287 288 mutex_lock(&tps->lock); 289 290 ret = tps6598x_exec_cmd(tps, cmd, 0, NULL, 0, NULL); 291 if (ret) 292 goto out_unlock; 293 294 ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); 295 if (ret) 296 goto out_unlock; 297 298 if (role != TPS_STATUS_DATAROLE(status)) { 299 ret = -EPROTO; 300 goto out_unlock; 301 } 302 303 typec_set_data_role(tps->port, role); 304 305out_unlock: 306 mutex_unlock(&tps->lock); 307 308 return ret; 309} 310 311static int 312tps6598x_pr_set(const struct typec_capability *cap, enum typec_role role) 313{ 314 struct tps6598x *tps = container_of(cap, struct tps6598x, typec_cap); 315 const char *cmd = (role == TYPEC_SINK) ? "SWSk" : "SWSr"; 316 u32 status; 317 int ret; 318 319 mutex_lock(&tps->lock); 320 321 ret = tps6598x_exec_cmd(tps, cmd, 0, NULL, 0, NULL); 322 if (ret) 323 goto out_unlock; 324 325 ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); 326 if (ret) 327 goto out_unlock; 328 329 if (role != TPS_STATUS_PORTROLE(status)) { 330 ret = -EPROTO; 331 goto out_unlock; 332 } 333 334 typec_set_pwr_role(tps->port, role); 335 336out_unlock: 337 mutex_unlock(&tps->lock); 338 339 return ret; 340} 341 342static irqreturn_t tps6598x_interrupt(int irq, void *data) 343{ 344 struct tps6598x *tps = data; 345 u64 event1; 346 u64 event2; 347 u32 status; 348 int ret; 349 350 mutex_lock(&tps->lock); 351 352 ret = tps6598x_read64(tps, TPS_REG_INT_EVENT1, &event1); 353 ret |= tps6598x_read64(tps, TPS_REG_INT_EVENT2, &event2); 354 if (ret) { 355 dev_err(tps->dev, "%s: failed to read events\n", __func__); 356 goto err_unlock; 357 } 358 359 ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); 360 if (ret) { 361 dev_err(tps->dev, "%s: failed to read status\n", __func__); 362 goto err_clear_ints; 363 } 364 365 /* Handle plug insert or removal */ 366 if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) { 367 if (status & TPS_STATUS_PLUG_PRESENT) { 368 ret = tps6598x_connect(tps, status); 369 if (ret) 370 dev_err(tps->dev, 371 "failed to register partner\n"); 372 } else { 373 tps6598x_disconnect(tps, status); 374 } 375 } 376 377err_clear_ints: 378 tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1); 379 tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2); 380 381err_unlock: 382 mutex_unlock(&tps->lock); 383 384 return IRQ_HANDLED; 385} 386 387static const struct regmap_config tps6598x_regmap_config = { 388 .reg_bits = 8, 389 .val_bits = 8, 390 .max_register = 0x7F, 391}; 392 393static int tps6598x_probe(struct i2c_client *client) 394{ 395 struct tps6598x *tps; 396 u32 status; 397 u32 conf; 398 u32 vid; 399 int ret; 400 401 tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); 402 if (!tps) 403 return -ENOMEM; 404 405 mutex_init(&tps->lock); 406 tps->dev = &client->dev; 407 408 tps->regmap = devm_regmap_init_i2c(client, &tps6598x_regmap_config); 409 if (IS_ERR(tps->regmap)) 410 return PTR_ERR(tps->regmap); 411 412 ret = tps6598x_read32(tps, 0, &vid); 413 if (ret < 0) 414 return ret; 415 if (!vid) 416 return -ENODEV; 417 418 /* 419 * Checking can the adapter handle SMBus protocol. If it can not, the 420 * driver needs to take care of block reads separately. 421 * 422 * FIXME: Testing with I2C_FUNC_I2C. regmap-i2c uses I2C protocol 423 * unconditionally if the adapter has I2C_FUNC_I2C set. 424 */ 425 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 426 tps->i2c_protocol = true; 427 428 ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); 429 if (ret < 0) 430 return ret; 431 432 ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf); 433 if (ret < 0) 434 return ret; 435 436 tps->typec_cap.revision = USB_TYPEC_REV_1_2; 437 tps->typec_cap.pd_revision = 0x200; 438 tps->typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; 439 tps->typec_cap.pr_set = tps6598x_pr_set; 440 tps->typec_cap.dr_set = tps6598x_dr_set; 441 442 switch (TPS_SYSCONF_PORTINFO(conf)) { 443 case TPS_PORTINFO_SINK_ACCESSORY: 444 case TPS_PORTINFO_SINK: 445 tps->typec_cap.type = TYPEC_PORT_SNK; 446 tps->typec_cap.data = TYPEC_PORT_UFP; 447 break; 448 case TPS_PORTINFO_DRP_UFP_DRD: 449 case TPS_PORTINFO_DRP_DFP_DRD: 450 tps->typec_cap.type = TYPEC_PORT_DRP; 451 tps->typec_cap.data = TYPEC_PORT_DRD; 452 break; 453 case TPS_PORTINFO_DRP_UFP: 454 tps->typec_cap.type = TYPEC_PORT_DRP; 455 tps->typec_cap.data = TYPEC_PORT_UFP; 456 break; 457 case TPS_PORTINFO_DRP_DFP: 458 tps->typec_cap.type = TYPEC_PORT_DRP; 459 tps->typec_cap.data = TYPEC_PORT_DFP; 460 break; 461 case TPS_PORTINFO_SOURCE: 462 tps->typec_cap.type = TYPEC_PORT_SRC; 463 tps->typec_cap.data = TYPEC_PORT_DFP; 464 break; 465 default: 466 return -ENODEV; 467 } 468 469 tps->port = typec_register_port(&client->dev, &tps->typec_cap); 470 if (IS_ERR(tps->port)) 471 return PTR_ERR(tps->port); 472 473 if (status & TPS_STATUS_PLUG_PRESENT) { 474 ret = tps6598x_connect(tps, status); 475 if (ret) 476 dev_err(&client->dev, "failed to register partner\n"); 477 } 478 479 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, 480 tps6598x_interrupt, 481 IRQF_SHARED | IRQF_ONESHOT, 482 dev_name(&client->dev), tps); 483 if (ret) { 484 tps6598x_disconnect(tps, 0); 485 typec_unregister_port(tps->port); 486 return ret; 487 } 488 489 i2c_set_clientdata(client, tps); 490 491 return 0; 492} 493 494static int tps6598x_remove(struct i2c_client *client) 495{ 496 struct tps6598x *tps = i2c_get_clientdata(client); 497 498 tps6598x_disconnect(tps, 0); 499 typec_unregister_port(tps->port); 500 501 return 0; 502} 503 504static const struct i2c_device_id tps6598x_id[] = { 505 { "tps6598x" }, 506 { } 507}; 508MODULE_DEVICE_TABLE(i2c, tps6598x_id); 509 510static struct i2c_driver tps6598x_i2c_driver = { 511 .driver = { 512 .name = "tps6598x", 513 }, 514 .probe_new = tps6598x_probe, 515 .remove = tps6598x_remove, 516 .id_table = tps6598x_id, 517}; 518module_i2c_driver(tps6598x_i2c_driver); 519 520MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); 521MODULE_LICENSE("GPL v2"); 522MODULE_DESCRIPTION("TI TPS6598x USB Power Delivery Controller Driver");