| .. | .. |
|---|
| 9 | 9 | #include <linux/delay.h> |
|---|
| 10 | 10 | #include <linux/errno.h> |
|---|
| 11 | 11 | #include <linux/extcon.h> |
|---|
| 12 | | -#include <linux/gpio.h> |
|---|
| 12 | +#include <linux/gpio/consumer.h> |
|---|
| 13 | 13 | #include <linux/i2c.h> |
|---|
| 14 | 14 | #include <linux/interrupt.h> |
|---|
| 15 | 15 | #include <linux/kernel.h> |
|---|
| 16 | 16 | #include <linux/module.h> |
|---|
| 17 | 17 | #include <linux/mutex.h> |
|---|
| 18 | 18 | #include <linux/of_device.h> |
|---|
| 19 | | -#include <linux/of_gpio.h> |
|---|
| 20 | 19 | #include <linux/pinctrl/consumer.h> |
|---|
| 21 | 20 | #include <linux/proc_fs.h> |
|---|
| 22 | 21 | #include <linux/regulator/consumer.h> |
|---|
| 23 | 22 | #include <linux/sched/clock.h> |
|---|
| 24 | 23 | #include <linux/seq_file.h> |
|---|
| 25 | 24 | #include <linux/slab.h> |
|---|
| 25 | +#include <linux/spinlock.h> |
|---|
| 26 | 26 | #include <linux/string.h> |
|---|
| 27 | 27 | #include <linux/types.h> |
|---|
| 28 | +#include <linux/usb.h> |
|---|
| 28 | 29 | #include <linux/usb/typec.h> |
|---|
| 29 | 30 | #include <linux/usb/tcpm.h> |
|---|
| 30 | 31 | #include <linux/usb/pd.h> |
|---|
| .. | .. |
|---|
| 74 | 75 | struct i2c_client *i2c_client; |
|---|
| 75 | 76 | struct tcpm_port *tcpm_port; |
|---|
| 76 | 77 | struct tcpc_dev tcpc_dev; |
|---|
| 77 | | - struct tcpc_config tcpc_config; |
|---|
| 78 | 78 | |
|---|
| 79 | 79 | struct regulator *vbus; |
|---|
| 80 | 80 | |
|---|
| 81 | | - int gpio_int_n; |
|---|
| 81 | + spinlock_t irq_lock; |
|---|
| 82 | + struct kthread_work irq_work; |
|---|
| 83 | + struct kthread_worker *irq_worker; |
|---|
| 84 | + bool irq_suspended; |
|---|
| 85 | + bool irq_while_suspended; |
|---|
| 86 | + struct gpio_desc *gpio_int_n; |
|---|
| 82 | 87 | int gpio_int_n_irq; |
|---|
| 83 | 88 | struct extcon_dev *extcon; |
|---|
| 84 | 89 | |
|---|
| 85 | 90 | struct workqueue_struct *wq; |
|---|
| 86 | 91 | struct delayed_work bc_lvl_handler; |
|---|
| 87 | | - |
|---|
| 88 | | - atomic_t pm_suspend; |
|---|
| 89 | | - atomic_t i2c_busy; |
|---|
| 90 | 92 | |
|---|
| 91 | 93 | /* lock for sharing chip states */ |
|---|
| 92 | 94 | struct mutex lock; |
|---|
| .. | .. |
|---|
| 123 | 125 | */ |
|---|
| 124 | 126 | |
|---|
| 125 | 127 | #ifdef CONFIG_DEBUG_FS |
|---|
| 126 | | - |
|---|
| 127 | 128 | static bool fusb302_log_full(struct fusb302_chip *chip) |
|---|
| 128 | 129 | { |
|---|
| 129 | 130 | return chip->logbuffer_tail == |
|---|
| 130 | 131 | (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; |
|---|
| 131 | 132 | } |
|---|
| 132 | 133 | |
|---|
| 134 | +__printf(2, 0) |
|---|
| 133 | 135 | static void _fusb302_log(struct fusb302_chip *chip, const char *fmt, |
|---|
| 134 | 136 | va_list args) |
|---|
| 135 | 137 | { |
|---|
| .. | .. |
|---|
| 177 | 179 | mutex_unlock(&chip->logbuffer_lock); |
|---|
| 178 | 180 | } |
|---|
| 179 | 181 | |
|---|
| 182 | +__printf(2, 3) |
|---|
| 180 | 183 | static void fusb302_log(struct fusb302_chip *chip, const char *fmt, ...) |
|---|
| 181 | 184 | { |
|---|
| 182 | 185 | va_list args; |
|---|
| .. | .. |
|---|
| 205 | 208 | } |
|---|
| 206 | 209 | DEFINE_SHOW_ATTRIBUTE(fusb302_debug); |
|---|
| 207 | 210 | |
|---|
| 208 | | -static struct dentry *rootdir; |
|---|
| 209 | | - |
|---|
| 210 | 211 | static void fusb302_debugfs_init(struct fusb302_chip *chip) |
|---|
| 211 | 212 | { |
|---|
| 212 | | - mutex_init(&chip->logbuffer_lock); |
|---|
| 213 | | - if (!rootdir) |
|---|
| 214 | | - rootdir = debugfs_create_dir("fusb302", NULL); |
|---|
| 213 | + char name[NAME_MAX]; |
|---|
| 215 | 214 | |
|---|
| 216 | | - chip->dentry = debugfs_create_file(dev_name(chip->dev), |
|---|
| 217 | | - S_IFREG | 0444, rootdir, |
|---|
| 215 | + mutex_init(&chip->logbuffer_lock); |
|---|
| 216 | + snprintf(name, NAME_MAX, "fusb302-%s", dev_name(chip->dev)); |
|---|
| 217 | + chip->dentry = debugfs_create_file(name, S_IFREG | 0444, usb_debug_root, |
|---|
| 218 | 218 | chip, &fusb302_debug_fops); |
|---|
| 219 | 219 | } |
|---|
| 220 | 220 | |
|---|
| 221 | 221 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) |
|---|
| 222 | 222 | { |
|---|
| 223 | 223 | debugfs_remove(chip->dentry); |
|---|
| 224 | | - debugfs_remove(rootdir); |
|---|
| 225 | 224 | } |
|---|
| 226 | 225 | |
|---|
| 227 | 226 | #else |
|---|
| .. | .. |
|---|
| 233 | 232 | |
|---|
| 234 | 233 | #endif |
|---|
| 235 | 234 | |
|---|
| 236 | | -#define FUSB302_RESUME_RETRY 10 |
|---|
| 237 | | -#define FUSB302_RESUME_RETRY_SLEEP 50 |
|---|
| 238 | | - |
|---|
| 239 | | -static bool fusb302_is_suspended(struct fusb302_chip *chip) |
|---|
| 240 | | -{ |
|---|
| 241 | | - int retry_cnt; |
|---|
| 242 | | - |
|---|
| 243 | | - for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { |
|---|
| 244 | | - if (atomic_read(&chip->pm_suspend)) { |
|---|
| 245 | | - dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n", |
|---|
| 246 | | - retry_cnt + 1, FUSB302_RESUME_RETRY); |
|---|
| 247 | | - msleep(FUSB302_RESUME_RETRY_SLEEP); |
|---|
| 248 | | - } else { |
|---|
| 249 | | - return false; |
|---|
| 250 | | - } |
|---|
| 251 | | - } |
|---|
| 252 | | - |
|---|
| 253 | | - return true; |
|---|
| 254 | | -} |
|---|
| 255 | | - |
|---|
| 256 | 235 | static int fusb302_i2c_write(struct fusb302_chip *chip, |
|---|
| 257 | 236 | u8 address, u8 data) |
|---|
| 258 | 237 | { |
|---|
| 259 | 238 | int ret = 0; |
|---|
| 260 | 239 | |
|---|
| 261 | | - atomic_set(&chip->i2c_busy, 1); |
|---|
| 262 | | - |
|---|
| 263 | | - if (fusb302_is_suspended(chip)) { |
|---|
| 264 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 265 | | - return -ETIMEDOUT; |
|---|
| 266 | | - } |
|---|
| 267 | | - |
|---|
| 268 | 240 | ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data); |
|---|
| 269 | 241 | if (ret < 0) |
|---|
| 270 | 242 | fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", |
|---|
| 271 | 243 | data, address, ret); |
|---|
| 272 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 273 | 244 | |
|---|
| 274 | 245 | return ret; |
|---|
| 275 | 246 | } |
|---|
| .. | .. |
|---|
| 281 | 252 | |
|---|
| 282 | 253 | if (length <= 0) |
|---|
| 283 | 254 | return ret; |
|---|
| 284 | | - atomic_set(&chip->i2c_busy, 1); |
|---|
| 285 | | - |
|---|
| 286 | | - if (fusb302_is_suspended(chip)) { |
|---|
| 287 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 288 | | - return -ETIMEDOUT; |
|---|
| 289 | | - } |
|---|
| 290 | 255 | |
|---|
| 291 | 256 | ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address, |
|---|
| 292 | 257 | length, data); |
|---|
| 293 | 258 | if (ret < 0) |
|---|
| 294 | 259 | fusb302_log(chip, "cannot block write 0x%02x, len=%d, ret=%d", |
|---|
| 295 | 260 | address, length, ret); |
|---|
| 296 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 297 | 261 | |
|---|
| 298 | 262 | return ret; |
|---|
| 299 | 263 | } |
|---|
| .. | .. |
|---|
| 303 | 267 | { |
|---|
| 304 | 268 | int ret = 0; |
|---|
| 305 | 269 | |
|---|
| 306 | | - atomic_set(&chip->i2c_busy, 1); |
|---|
| 307 | | - |
|---|
| 308 | | - if (fusb302_is_suspended(chip)) { |
|---|
| 309 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 310 | | - return -ETIMEDOUT; |
|---|
| 311 | | - } |
|---|
| 312 | | - |
|---|
| 313 | 270 | ret = i2c_smbus_read_byte_data(chip->i2c_client, address); |
|---|
| 314 | 271 | *data = (u8)ret; |
|---|
| 315 | 272 | if (ret < 0) |
|---|
| 316 | 273 | fusb302_log(chip, "cannot read %02x, ret=%d", address, ret); |
|---|
| 317 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 318 | 274 | |
|---|
| 319 | 275 | return ret; |
|---|
| 320 | 276 | } |
|---|
| .. | .. |
|---|
| 326 | 282 | |
|---|
| 327 | 283 | if (length <= 0) |
|---|
| 328 | 284 | return ret; |
|---|
| 329 | | - atomic_set(&chip->i2c_busy, 1); |
|---|
| 330 | | - |
|---|
| 331 | | - if (fusb302_is_suspended(chip)) { |
|---|
| 332 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 333 | | - return -ETIMEDOUT; |
|---|
| 334 | | - } |
|---|
| 335 | 285 | |
|---|
| 336 | 286 | ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address, |
|---|
| 337 | 287 | length, data); |
|---|
| .. | .. |
|---|
| 347 | 297 | } |
|---|
| 348 | 298 | |
|---|
| 349 | 299 | done: |
|---|
| 350 | | - atomic_set(&chip->i2c_busy, 0); |
|---|
| 351 | | - |
|---|
| 352 | 300 | return ret; |
|---|
| 353 | 301 | } |
|---|
| 354 | 302 | |
|---|
| .. | .. |
|---|
| 396 | 344 | return ret; |
|---|
| 397 | 345 | } |
|---|
| 398 | 346 | |
|---|
| 399 | | -static int fusb302_enable_tx_auto_retries(struct fusb302_chip *chip) |
|---|
| 347 | +static int fusb302_enable_tx_auto_retries(struct fusb302_chip *chip, u8 retry_count) |
|---|
| 400 | 348 | { |
|---|
| 401 | 349 | int ret = 0; |
|---|
| 402 | 350 | |
|---|
| 403 | | - ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3, |
|---|
| 404 | | - FUSB_REG_CONTROL3_N_RETRIES_3 | |
|---|
| 351 | + ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3, retry_count | |
|---|
| 405 | 352 | FUSB_REG_CONTROL3_AUTO_RETRY); |
|---|
| 406 | 353 | |
|---|
| 407 | 354 | return ret; |
|---|
| .. | .. |
|---|
| 442 | 389 | return ret; |
|---|
| 443 | 390 | } |
|---|
| 444 | 391 | |
|---|
| 392 | +static int fusb302_rx_fifo_is_empty(struct fusb302_chip *chip) |
|---|
| 393 | +{ |
|---|
| 394 | + u8 data; |
|---|
| 395 | + |
|---|
| 396 | + return (fusb302_i2c_read(chip, FUSB_REG_STATUS1, &data) > 0) && |
|---|
| 397 | + (data & FUSB_REG_STATUS1_RX_EMPTY); |
|---|
| 398 | +} |
|---|
| 399 | + |
|---|
| 445 | 400 | static int tcpm_init(struct tcpc_dev *dev) |
|---|
| 446 | 401 | { |
|---|
| 447 | 402 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, |
|---|
| .. | .. |
|---|
| 452 | 407 | ret = fusb302_sw_reset(chip); |
|---|
| 453 | 408 | if (ret < 0) |
|---|
| 454 | 409 | return ret; |
|---|
| 455 | | - ret = fusb302_enable_tx_auto_retries(chip); |
|---|
| 410 | + ret = fusb302_enable_tx_auto_retries(chip, FUSB_REG_CONTROL3_N_RETRIES_3); |
|---|
| 456 | 411 | if (ret < 0) |
|---|
| 457 | 412 | return ret; |
|---|
| 458 | 413 | ret = fusb302_init_interrupt(chip); |
|---|
| .. | .. |
|---|
| 516 | 471 | } while (current_limit == 0 && time_before(jiffies, timeout)); |
|---|
| 517 | 472 | |
|---|
| 518 | 473 | return current_limit; |
|---|
| 519 | | -} |
|---|
| 520 | | - |
|---|
| 521 | | -static int fusb302_set_cc_pull(struct fusb302_chip *chip, |
|---|
| 522 | | - bool pull_up, bool pull_down) |
|---|
| 523 | | -{ |
|---|
| 524 | | - int ret = 0; |
|---|
| 525 | | - u8 data = 0x00; |
|---|
| 526 | | - u8 mask = FUSB_REG_SWITCHES0_CC1_PU_EN | |
|---|
| 527 | | - FUSB_REG_SWITCHES0_CC2_PU_EN | |
|---|
| 528 | | - FUSB_REG_SWITCHES0_CC1_PD_EN | |
|---|
| 529 | | - FUSB_REG_SWITCHES0_CC2_PD_EN; |
|---|
| 530 | | - |
|---|
| 531 | | - if (pull_up) |
|---|
| 532 | | - data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? |
|---|
| 533 | | - FUSB_REG_SWITCHES0_CC1_PU_EN : |
|---|
| 534 | | - FUSB_REG_SWITCHES0_CC2_PU_EN; |
|---|
| 535 | | - if (pull_down) |
|---|
| 536 | | - data |= FUSB_REG_SWITCHES0_CC1_PD_EN | |
|---|
| 537 | | - FUSB_REG_SWITCHES0_CC2_PD_EN; |
|---|
| 538 | | - ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, |
|---|
| 539 | | - mask, data); |
|---|
| 540 | | - if (ret < 0) |
|---|
| 541 | | - return ret; |
|---|
| 542 | | - |
|---|
| 543 | | - return ret; |
|---|
| 544 | 474 | } |
|---|
| 545 | 475 | |
|---|
| 546 | 476 | static int fusb302_set_src_current(struct fusb302_chip *chip, |
|---|
| .. | .. |
|---|
| 676 | 606 | { |
|---|
| 677 | 607 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, |
|---|
| 678 | 608 | tcpc_dev); |
|---|
| 609 | + u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN | |
|---|
| 610 | + FUSB_REG_SWITCHES0_CC2_PU_EN | |
|---|
| 611 | + FUSB_REG_SWITCHES0_CC1_PD_EN | |
|---|
| 612 | + FUSB_REG_SWITCHES0_CC2_PD_EN; |
|---|
| 613 | + u8 rd_mda, switches0_data = 0x00; |
|---|
| 679 | 614 | int ret = 0; |
|---|
| 680 | | - bool pull_up, pull_down; |
|---|
| 681 | | - u8 rd_mda; |
|---|
| 682 | | - enum toggling_mode mode; |
|---|
| 683 | 615 | |
|---|
| 684 | 616 | mutex_lock(&chip->lock); |
|---|
| 685 | 617 | switch (cc) { |
|---|
| 686 | 618 | case TYPEC_CC_OPEN: |
|---|
| 687 | | - pull_up = false; |
|---|
| 688 | | - pull_down = false; |
|---|
| 689 | 619 | break; |
|---|
| 690 | 620 | case TYPEC_CC_RD: |
|---|
| 691 | | - pull_up = false; |
|---|
| 692 | | - pull_down = true; |
|---|
| 621 | + switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN | |
|---|
| 622 | + FUSB_REG_SWITCHES0_CC2_PD_EN; |
|---|
| 693 | 623 | break; |
|---|
| 694 | 624 | case TYPEC_CC_RP_DEF: |
|---|
| 695 | 625 | case TYPEC_CC_RP_1_5: |
|---|
| 696 | 626 | case TYPEC_CC_RP_3_0: |
|---|
| 697 | | - pull_up = true; |
|---|
| 698 | | - pull_down = false; |
|---|
| 627 | + switches0_data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? |
|---|
| 628 | + FUSB_REG_SWITCHES0_CC1_PU_EN : |
|---|
| 629 | + FUSB_REG_SWITCHES0_CC2_PU_EN; |
|---|
| 699 | 630 | break; |
|---|
| 700 | 631 | default: |
|---|
| 701 | 632 | fusb302_log(chip, "unsupported cc value %s", |
|---|
| .. | .. |
|---|
| 703 | 634 | ret = -EINVAL; |
|---|
| 704 | 635 | goto done; |
|---|
| 705 | 636 | } |
|---|
| 637 | + |
|---|
| 638 | + fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); |
|---|
| 639 | + |
|---|
| 706 | 640 | ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF); |
|---|
| 707 | 641 | if (ret < 0) { |
|---|
| 708 | | - fusb302_log(chip, "cannot stop toggling, ret=%d", ret); |
|---|
| 642 | + fusb302_log(chip, "cannot set toggling mode, ret=%d", ret); |
|---|
| 709 | 643 | goto done; |
|---|
| 710 | 644 | } |
|---|
| 711 | | - ret = fusb302_set_cc_pull(chip, pull_up, pull_down); |
|---|
| 645 | + |
|---|
| 646 | + ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, |
|---|
| 647 | + switches0_mask, switches0_data); |
|---|
| 712 | 648 | if (ret < 0) { |
|---|
| 713 | | - fusb302_log(chip, |
|---|
| 714 | | - "cannot set cc pulling up %s, down %s, ret = %d", |
|---|
| 715 | | - pull_up ? "True" : "False", |
|---|
| 716 | | - pull_down ? "True" : "False", |
|---|
| 717 | | - ret); |
|---|
| 649 | + fusb302_log(chip, "cannot set pull-up/-down, ret = %d", ret); |
|---|
| 718 | 650 | goto done; |
|---|
| 719 | 651 | } |
|---|
| 720 | 652 | /* reset the cc status */ |
|---|
| 721 | 653 | chip->cc1 = TYPEC_CC_OPEN; |
|---|
| 722 | 654 | chip->cc2 = TYPEC_CC_OPEN; |
|---|
| 655 | + |
|---|
| 723 | 656 | /* adjust current for SRC */ |
|---|
| 724 | | - if (pull_up) { |
|---|
| 725 | | - ret = fusb302_set_src_current(chip, cc_src_current[cc]); |
|---|
| 726 | | - if (ret < 0) { |
|---|
| 727 | | - fusb302_log(chip, "cannot set src current %s, ret=%d", |
|---|
| 728 | | - typec_cc_status_name[cc], ret); |
|---|
| 729 | | - goto done; |
|---|
| 730 | | - } |
|---|
| 657 | + ret = fusb302_set_src_current(chip, cc_src_current[cc]); |
|---|
| 658 | + if (ret < 0) { |
|---|
| 659 | + fusb302_log(chip, "cannot set src current %s, ret=%d", |
|---|
| 660 | + typec_cc_status_name[cc], ret); |
|---|
| 661 | + goto done; |
|---|
| 731 | 662 | } |
|---|
| 663 | + |
|---|
| 732 | 664 | /* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */ |
|---|
| 733 | | - if (pull_up) { |
|---|
| 665 | + switch (cc) { |
|---|
| 666 | + case TYPEC_CC_RP_DEF: |
|---|
| 667 | + case TYPEC_CC_RP_1_5: |
|---|
| 668 | + case TYPEC_CC_RP_3_0: |
|---|
| 734 | 669 | rd_mda = rd_mda_value[cc_src_current[cc]]; |
|---|
| 735 | 670 | ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); |
|---|
| 736 | 671 | if (ret < 0) { |
|---|
| .. | .. |
|---|
| 742 | 677 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, |
|---|
| 743 | 678 | FUSB_REG_MASK_BC_LVL | |
|---|
| 744 | 679 | FUSB_REG_MASK_COMP_CHNG, |
|---|
| 745 | | - FUSB_REG_MASK_COMP_CHNG); |
|---|
| 680 | + FUSB_REG_MASK_BC_LVL); |
|---|
| 746 | 681 | if (ret < 0) { |
|---|
| 747 | 682 | fusb302_log(chip, "cannot set SRC interrupt, ret=%d", |
|---|
| 748 | 683 | ret); |
|---|
| 749 | 684 | goto done; |
|---|
| 750 | 685 | } |
|---|
| 751 | | - chip->intr_bc_lvl = false; |
|---|
| 752 | 686 | chip->intr_comp_chng = true; |
|---|
| 753 | | - } |
|---|
| 754 | | - if (pull_down) { |
|---|
| 687 | + chip->intr_bc_lvl = false; |
|---|
| 688 | + break; |
|---|
| 689 | + case TYPEC_CC_RD: |
|---|
| 755 | 690 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, |
|---|
| 756 | 691 | FUSB_REG_MASK_BC_LVL | |
|---|
| 757 | 692 | FUSB_REG_MASK_COMP_CHNG, |
|---|
| 758 | | - FUSB_REG_MASK_BC_LVL); |
|---|
| 693 | + FUSB_REG_MASK_COMP_CHNG); |
|---|
| 759 | 694 | if (ret < 0) { |
|---|
| 760 | 695 | fusb302_log(chip, "cannot set SRC interrupt, ret=%d", |
|---|
| 761 | 696 | ret); |
|---|
| .. | .. |
|---|
| 763 | 698 | } |
|---|
| 764 | 699 | chip->intr_bc_lvl = true; |
|---|
| 765 | 700 | chip->intr_comp_chng = false; |
|---|
| 766 | | - } |
|---|
| 767 | | - fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); |
|---|
| 768 | | - |
|---|
| 769 | | - /* Enable detection for fixed SNK or SRC only roles */ |
|---|
| 770 | | - switch (cc) { |
|---|
| 771 | | - case TYPEC_CC_RD: |
|---|
| 772 | | - mode = TOGGLING_MODE_SNK; |
|---|
| 773 | | - break; |
|---|
| 774 | | - case TYPEC_CC_RP_DEF: |
|---|
| 775 | | - case TYPEC_CC_RP_1_5: |
|---|
| 776 | | - case TYPEC_CC_RP_3_0: |
|---|
| 777 | | - mode = TOGGLING_MODE_SRC; |
|---|
| 778 | 701 | break; |
|---|
| 779 | 702 | default: |
|---|
| 780 | | - mode = TOGGLING_MODE_OFF; |
|---|
| 781 | 703 | break; |
|---|
| 782 | | - } |
|---|
| 783 | | - |
|---|
| 784 | | - if (mode != TOGGLING_MODE_OFF) { |
|---|
| 785 | | - ret = fusb302_set_toggling(chip, mode); |
|---|
| 786 | | - if (ret < 0) |
|---|
| 787 | | - fusb302_log(chip, |
|---|
| 788 | | - "cannot set fixed role toggling mode, ret=%d", |
|---|
| 789 | | - ret); |
|---|
| 790 | 704 | } |
|---|
| 791 | 705 | done: |
|---|
| 792 | 706 | mutex_unlock(&chip->lock); |
|---|
| .. | .. |
|---|
| 1011 | 925 | { |
|---|
| 1012 | 926 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, |
|---|
| 1013 | 927 | tcpc_dev); |
|---|
| 928 | + enum toggling_mode mode = TOGGLING_MODE_OFF; |
|---|
| 1014 | 929 | int ret = 0; |
|---|
| 1015 | 930 | |
|---|
| 1016 | | - if (port_type != TYPEC_PORT_DRP) |
|---|
| 1017 | | - return -EOPNOTSUPP; |
|---|
| 931 | + switch (port_type) { |
|---|
| 932 | + case TYPEC_PORT_SRC: |
|---|
| 933 | + mode = TOGGLING_MODE_SRC; |
|---|
| 934 | + break; |
|---|
| 935 | + case TYPEC_PORT_SNK: |
|---|
| 936 | + mode = TOGGLING_MODE_SNK; |
|---|
| 937 | + break; |
|---|
| 938 | + case TYPEC_PORT_DRP: |
|---|
| 939 | + mode = TOGGLING_MODE_DRP; |
|---|
| 940 | + break; |
|---|
| 941 | + } |
|---|
| 1018 | 942 | |
|---|
| 1019 | 943 | mutex_lock(&chip->lock); |
|---|
| 1020 | 944 | ret = fusb302_set_src_current(chip, cc_src_current[cc]); |
|---|
| .. | .. |
|---|
| 1023 | 947 | typec_cc_status_name[cc], ret); |
|---|
| 1024 | 948 | goto done; |
|---|
| 1025 | 949 | } |
|---|
| 1026 | | - ret = fusb302_set_toggling(chip, TOGGLING_MODE_DRP); |
|---|
| 950 | + ret = fusb302_set_toggling(chip, mode); |
|---|
| 1027 | 951 | if (ret < 0) { |
|---|
| 1028 | 952 | fusb302_log(chip, |
|---|
| 1029 | 953 | "unable to start drp toggling, ret=%d", ret); |
|---|
| .. | .. |
|---|
| 1103 | 1027 | }; |
|---|
| 1104 | 1028 | |
|---|
| 1105 | 1029 | static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type, |
|---|
| 1106 | | - const struct pd_message *msg) |
|---|
| 1030 | + const struct pd_message *msg, unsigned int negotiated_rev) |
|---|
| 1107 | 1031 | { |
|---|
| 1108 | 1032 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, |
|---|
| 1109 | 1033 | tcpc_dev); |
|---|
| .. | .. |
|---|
| 1112 | 1036 | mutex_lock(&chip->lock); |
|---|
| 1113 | 1037 | switch (type) { |
|---|
| 1114 | 1038 | case TCPC_TX_SOP: |
|---|
| 1039 | + /* nRetryCount 3 in P2.0 spec, whereas 2 in PD3.0 spec */ |
|---|
| 1040 | + ret = fusb302_enable_tx_auto_retries(chip, negotiated_rev > PD_REV20 ? |
|---|
| 1041 | + FUSB_REG_CONTROL3_N_RETRIES_2 : |
|---|
| 1042 | + FUSB_REG_CONTROL3_N_RETRIES_3); |
|---|
| 1043 | + if (ret < 0) |
|---|
| 1044 | + fusb302_log(chip, "Cannot update retry count ret=%d", ret); |
|---|
| 1045 | + |
|---|
| 1115 | 1046 | ret = fusb302_pd_send_message(chip, msg); |
|---|
| 1116 | 1047 | if (ret < 0) |
|---|
| 1117 | 1048 | fusb302_log(chip, |
|---|
| .. | .. |
|---|
| 1191 | 1122 | done: |
|---|
| 1192 | 1123 | mutex_unlock(&chip->lock); |
|---|
| 1193 | 1124 | } |
|---|
| 1194 | | - |
|---|
| 1195 | | -#define PDO_FIXED_FLAGS \ |
|---|
| 1196 | | - (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) |
|---|
| 1197 | | - |
|---|
| 1198 | | -static const u32 src_pdo[] = { |
|---|
| 1199 | | - PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), |
|---|
| 1200 | | -}; |
|---|
| 1201 | | - |
|---|
| 1202 | | -static const struct tcpc_config fusb302_tcpc_config = { |
|---|
| 1203 | | - .src_pdo = src_pdo, |
|---|
| 1204 | | - .nr_src_pdo = ARRAY_SIZE(src_pdo), |
|---|
| 1205 | | - .operating_snk_mw = 2500, |
|---|
| 1206 | | - .type = TYPEC_PORT_DRP, |
|---|
| 1207 | | - .data = TYPEC_PORT_DRD, |
|---|
| 1208 | | - .default_role = TYPEC_SINK, |
|---|
| 1209 | | - .alt_modes = NULL, |
|---|
| 1210 | | -}; |
|---|
| 1211 | 1125 | |
|---|
| 1212 | 1126 | static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev) |
|---|
| 1213 | 1127 | { |
|---|
| .. | .. |
|---|
| 1436 | 1350 | } else if (cc2 == TYPEC_CC_RD && |
|---|
| 1437 | 1351 | (cc1 == TYPEC_CC_OPEN || cc1 == TYPEC_CC_RA)) { |
|---|
| 1438 | 1352 | cc_polarity = TYPEC_POLARITY_CC2; |
|---|
| 1353 | + } else if (cc1 == TYPEC_CC_RA && cc2 == TYPEC_CC_RA) { |
|---|
| 1354 | + cc_polarity = TYPEC_POLARITY_CC2; |
|---|
| 1439 | 1355 | } else { |
|---|
| 1440 | 1356 | fusb302_log(chip, "unexpected CC status cc1=%s, cc2=%s, restarting toggling", |
|---|
| 1441 | 1357 | typec_cc_status_name[cc1], |
|---|
| .. | .. |
|---|
| 1569 | 1485 | static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) |
|---|
| 1570 | 1486 | { |
|---|
| 1571 | 1487 | struct fusb302_chip *chip = dev_id; |
|---|
| 1488 | + unsigned long flags; |
|---|
| 1489 | + |
|---|
| 1490 | + /* Disable our level triggered IRQ until our irq_work has cleared it */ |
|---|
| 1491 | + disable_irq_nosync(chip->gpio_int_n_irq); |
|---|
| 1492 | + |
|---|
| 1493 | + spin_lock_irqsave(&chip->irq_lock, flags); |
|---|
| 1494 | + if (chip->irq_suspended) |
|---|
| 1495 | + chip->irq_while_suspended = true; |
|---|
| 1496 | + else |
|---|
| 1497 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 1498 | + spin_unlock_irqrestore(&chip->irq_lock, flags); |
|---|
| 1499 | + |
|---|
| 1500 | + return IRQ_HANDLED; |
|---|
| 1501 | +} |
|---|
| 1502 | + |
|---|
| 1503 | +static void fusb302_irq_work(struct kthread_work *work) |
|---|
| 1504 | +{ |
|---|
| 1505 | + struct fusb302_chip *chip = container_of(work, struct fusb302_chip, irq_work); |
|---|
| 1572 | 1506 | int ret = 0; |
|---|
| 1573 | 1507 | u8 interrupt; |
|---|
| 1574 | 1508 | u8 interrupta; |
|---|
| .. | .. |
|---|
| 1668 | 1602 | |
|---|
| 1669 | 1603 | if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { |
|---|
| 1670 | 1604 | fusb302_log(chip, "IRQ: PD tx success"); |
|---|
| 1671 | | - ret = fusb302_pd_read_message(chip, &pd_msg); |
|---|
| 1672 | | - if (ret < 0) { |
|---|
| 1673 | | - fusb302_log(chip, |
|---|
| 1674 | | - "cannot read in PD message, ret=%d", ret); |
|---|
| 1675 | | - goto done; |
|---|
| 1676 | | - } |
|---|
| 1605 | + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); |
|---|
| 1677 | 1606 | } |
|---|
| 1678 | 1607 | |
|---|
| 1679 | 1608 | if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) { |
|---|
| .. | .. |
|---|
| 1688 | 1617 | |
|---|
| 1689 | 1618 | if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) { |
|---|
| 1690 | 1619 | fusb302_log(chip, "IRQ: PD sent good CRC"); |
|---|
| 1691 | | - ret = fusb302_pd_read_message(chip, &pd_msg); |
|---|
| 1692 | | - if (ret < 0) { |
|---|
| 1693 | | - fusb302_log(chip, |
|---|
| 1694 | | - "cannot read in PD message, ret=%d", ret); |
|---|
| 1695 | | - goto done; |
|---|
| 1620 | + |
|---|
| 1621 | + while (!fusb302_rx_fifo_is_empty(chip)) { |
|---|
| 1622 | + memset(&pd_msg, 0, sizeof(struct pd_message)); |
|---|
| 1623 | + ret = fusb302_pd_read_message(chip, &pd_msg); |
|---|
| 1624 | + if (ret < 0) { |
|---|
| 1625 | + fusb302_log(chip, |
|---|
| 1626 | + "cannot read in PD message, ret=%d", ret); |
|---|
| 1627 | + goto done; |
|---|
| 1628 | + } |
|---|
| 1696 | 1629 | } |
|---|
| 1697 | 1630 | } |
|---|
| 1698 | 1631 | done: |
|---|
| 1699 | 1632 | mutex_unlock(&chip->lock); |
|---|
| 1700 | | - |
|---|
| 1701 | | - return IRQ_HANDLED; |
|---|
| 1633 | + enable_irq(chip->gpio_int_n_irq); |
|---|
| 1702 | 1634 | } |
|---|
| 1703 | 1635 | |
|---|
| 1704 | 1636 | static int init_gpio(struct fusb302_chip *chip) |
|---|
| 1705 | 1637 | { |
|---|
| 1706 | | - struct device_node *node; |
|---|
| 1638 | + struct device *dev = chip->dev; |
|---|
| 1707 | 1639 | int ret = 0; |
|---|
| 1708 | 1640 | |
|---|
| 1709 | | - node = chip->dev->of_node; |
|---|
| 1710 | | - chip->gpio_int_n = of_get_named_gpio(node, "fcs,int_n", 0); |
|---|
| 1711 | | - if (!gpio_is_valid(chip->gpio_int_n)) { |
|---|
| 1712 | | - ret = chip->gpio_int_n; |
|---|
| 1713 | | - dev_err(chip->dev, "cannot get named GPIO Int_N, ret=%d", ret); |
|---|
| 1714 | | - return ret; |
|---|
| 1641 | + chip->gpio_int_n = devm_gpiod_get(dev, "fcs,int_n", GPIOD_IN); |
|---|
| 1642 | + if (IS_ERR(chip->gpio_int_n)) { |
|---|
| 1643 | + dev_err(dev, "failed to request gpio_int_n\n"); |
|---|
| 1644 | + return PTR_ERR(chip->gpio_int_n); |
|---|
| 1715 | 1645 | } |
|---|
| 1716 | | - ret = devm_gpio_request(chip->dev, chip->gpio_int_n, "fcs,int_n"); |
|---|
| 1646 | + ret = gpiod_to_irq(chip->gpio_int_n); |
|---|
| 1717 | 1647 | if (ret < 0) { |
|---|
| 1718 | | - dev_err(chip->dev, "cannot request GPIO Int_N, ret=%d", ret); |
|---|
| 1719 | | - return ret; |
|---|
| 1720 | | - } |
|---|
| 1721 | | - ret = gpio_direction_input(chip->gpio_int_n); |
|---|
| 1722 | | - if (ret < 0) { |
|---|
| 1723 | | - dev_err(chip->dev, |
|---|
| 1724 | | - "cannot set GPIO Int_N to input, ret=%d", ret); |
|---|
| 1725 | | - return ret; |
|---|
| 1726 | | - } |
|---|
| 1727 | | - ret = gpio_to_irq(chip->gpio_int_n); |
|---|
| 1728 | | - if (ret < 0) { |
|---|
| 1729 | | - dev_err(chip->dev, |
|---|
| 1648 | + dev_err(dev, |
|---|
| 1730 | 1649 | "cannot request IRQ for GPIO Int_N, ret=%d", ret); |
|---|
| 1731 | 1650 | return ret; |
|---|
| 1732 | 1651 | } |
|---|
| .. | .. |
|---|
| 1734 | 1653 | return 0; |
|---|
| 1735 | 1654 | } |
|---|
| 1736 | 1655 | |
|---|
| 1737 | | -static int fusb302_composite_snk_pdo_array(struct fusb302_chip *chip) |
|---|
| 1656 | +#define PDO_FIXED_FLAGS \ |
|---|
| 1657 | + (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) |
|---|
| 1658 | + |
|---|
| 1659 | +static const u32 src_pdo[] = { |
|---|
| 1660 | + PDO_FIXED(5000, 400, PDO_FIXED_FLAGS) |
|---|
| 1661 | +}; |
|---|
| 1662 | + |
|---|
| 1663 | +static const u32 snk_pdo[] = { |
|---|
| 1664 | + PDO_FIXED(5000, 400, PDO_FIXED_FLAGS) |
|---|
| 1665 | +}; |
|---|
| 1666 | + |
|---|
| 1667 | +static const struct property_entry port_props[] = { |
|---|
| 1668 | + PROPERTY_ENTRY_STRING("data-role", "dual"), |
|---|
| 1669 | + PROPERTY_ENTRY_STRING("power-role", "dual"), |
|---|
| 1670 | + PROPERTY_ENTRY_STRING("try-power-role", "sink"), |
|---|
| 1671 | + PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo), |
|---|
| 1672 | + PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo), |
|---|
| 1673 | + PROPERTY_ENTRY_U32("op-sink-microwatt", 2500000), |
|---|
| 1674 | + { } |
|---|
| 1675 | +}; |
|---|
| 1676 | + |
|---|
| 1677 | +static struct fwnode_handle *fusb302_fwnode_get(struct device *dev) |
|---|
| 1738 | 1678 | { |
|---|
| 1739 | | - struct device *dev = chip->dev; |
|---|
| 1740 | | - u32 max_uv, max_ua; |
|---|
| 1679 | + struct fwnode_handle *fwnode; |
|---|
| 1741 | 1680 | |
|---|
| 1742 | | - chip->snk_pdo[0] = PDO_FIXED(5000, 400, PDO_FIXED_FLAGS); |
|---|
| 1681 | + fwnode = device_get_named_child_node(dev, "connector"); |
|---|
| 1682 | + if (!fwnode) |
|---|
| 1683 | + fwnode = fwnode_create_software_node(port_props, NULL); |
|---|
| 1743 | 1684 | |
|---|
| 1744 | | - /* |
|---|
| 1745 | | - * As max_snk_ma/mv/mw is not needed for tcpc_config, |
|---|
| 1746 | | - * those settings should be passed in via sink PDO, so |
|---|
| 1747 | | - * "fcs, max-sink-*" properties will be deprecated, to |
|---|
| 1748 | | - * perserve compatibility with existing users of them, |
|---|
| 1749 | | - * we read those properties to convert them to be a var |
|---|
| 1750 | | - * PDO. |
|---|
| 1751 | | - */ |
|---|
| 1752 | | - if (device_property_read_u32(dev, "fcs,max-sink-microvolt", &max_uv) || |
|---|
| 1753 | | - device_property_read_u32(dev, "fcs,max-sink-microamp", &max_ua)) |
|---|
| 1754 | | - return 1; |
|---|
| 1755 | | - |
|---|
| 1756 | | - chip->snk_pdo[1] = PDO_VAR(5000, max_uv / 1000, max_ua / 1000); |
|---|
| 1757 | | - return 2; |
|---|
| 1685 | + return fwnode; |
|---|
| 1758 | 1686 | } |
|---|
| 1759 | 1687 | |
|---|
| 1760 | 1688 | static int fusb302_probe(struct i2c_client *client, |
|---|
| 1761 | 1689 | const struct i2c_device_id *id) |
|---|
| 1762 | 1690 | { |
|---|
| 1763 | 1691 | struct fusb302_chip *chip; |
|---|
| 1764 | | - struct i2c_adapter *adapter; |
|---|
| 1692 | + struct i2c_adapter *adapter = client->adapter; |
|---|
| 1765 | 1693 | struct device *dev = &client->dev; |
|---|
| 1766 | 1694 | const char *name; |
|---|
| 1767 | 1695 | int ret = 0; |
|---|
| 1768 | | - u32 v; |
|---|
| 1769 | 1696 | |
|---|
| 1770 | | - adapter = to_i2c_adapter(client->dev.parent); |
|---|
| 1771 | 1697 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { |
|---|
| 1772 | 1698 | dev_err(&client->dev, |
|---|
| 1773 | 1699 | "I2C/SMBus block functionality not supported!\n"); |
|---|
| .. | .. |
|---|
| 1779 | 1705 | |
|---|
| 1780 | 1706 | chip->i2c_client = client; |
|---|
| 1781 | 1707 | chip->dev = &client->dev; |
|---|
| 1782 | | - chip->tcpc_config = fusb302_tcpc_config; |
|---|
| 1783 | | - chip->tcpc_dev.config = &chip->tcpc_config; |
|---|
| 1784 | 1708 | mutex_init(&chip->lock); |
|---|
| 1785 | | - |
|---|
| 1786 | | - chip->tcpc_dev.fwnode = |
|---|
| 1787 | | - device_get_named_child_node(dev, "connector"); |
|---|
| 1788 | | - |
|---|
| 1789 | | - if (!device_property_read_u32(dev, "fcs,operating-sink-microwatt", &v)) |
|---|
| 1790 | | - chip->tcpc_config.operating_snk_mw = v / 1000; |
|---|
| 1791 | | - |
|---|
| 1792 | | - /* Composite sink PDO */ |
|---|
| 1793 | | - chip->tcpc_config.nr_snk_pdo = fusb302_composite_snk_pdo_array(chip); |
|---|
| 1794 | | - chip->tcpc_config.snk_pdo = chip->snk_pdo; |
|---|
| 1795 | 1709 | |
|---|
| 1796 | 1710 | /* |
|---|
| 1797 | 1711 | * Devicetree platforms should get extcon via phandle (not yet |
|---|
| .. | .. |
|---|
| 1800 | 1714 | * to be set by the platform code which also registers the i2c client |
|---|
| 1801 | 1715 | * for the fusb302. |
|---|
| 1802 | 1716 | */ |
|---|
| 1803 | | - if (device_property_read_string(dev, "fcs,extcon-name", &name) == 0) { |
|---|
| 1717 | + if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { |
|---|
| 1804 | 1718 | chip->extcon = extcon_get_extcon_dev(name); |
|---|
| 1805 | 1719 | if (!chip->extcon) |
|---|
| 1806 | 1720 | return -EPROBE_DEFER; |
|---|
| .. | .. |
|---|
| 1814 | 1728 | if (!chip->wq) |
|---|
| 1815 | 1729 | return -ENOMEM; |
|---|
| 1816 | 1730 | |
|---|
| 1731 | + chip->irq_worker = kthread_create_worker(0, dev_name(dev)); |
|---|
| 1732 | + if (IS_ERR(chip->irq_worker)) |
|---|
| 1733 | + return PTR_ERR(chip->irq_worker); |
|---|
| 1734 | + sched_set_fifo(chip->irq_worker->task); |
|---|
| 1735 | + |
|---|
| 1736 | + spin_lock_init(&chip->irq_lock); |
|---|
| 1737 | + kthread_init_work(&chip->irq_work, fusb302_irq_work); |
|---|
| 1817 | 1738 | INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); |
|---|
| 1818 | 1739 | init_tcpc_dev(&chip->tcpc_dev); |
|---|
| 1740 | + fusb302_debugfs_init(chip); |
|---|
| 1819 | 1741 | |
|---|
| 1820 | 1742 | if (client->irq) { |
|---|
| 1821 | 1743 | chip->gpio_int_n_irq = client->irq; |
|---|
| .. | .. |
|---|
| 1825 | 1747 | goto destroy_workqueue; |
|---|
| 1826 | 1748 | } |
|---|
| 1827 | 1749 | |
|---|
| 1750 | + chip->tcpc_dev.fwnode = fusb302_fwnode_get(dev); |
|---|
| 1751 | + if (IS_ERR(chip->tcpc_dev.fwnode)) { |
|---|
| 1752 | + ret = PTR_ERR(chip->tcpc_dev.fwnode); |
|---|
| 1753 | + goto destroy_workqueue; |
|---|
| 1754 | + } |
|---|
| 1755 | + |
|---|
| 1828 | 1756 | chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); |
|---|
| 1829 | 1757 | if (IS_ERR(chip->tcpm_port)) { |
|---|
| 1758 | + fwnode_handle_put(chip->tcpc_dev.fwnode); |
|---|
| 1830 | 1759 | ret = PTR_ERR(chip->tcpm_port); |
|---|
| 1831 | 1760 | if (ret != -EPROBE_DEFER) |
|---|
| 1832 | 1761 | dev_err(dev, "cannot register tcpm port, ret=%d", ret); |
|---|
| 1833 | 1762 | goto destroy_workqueue; |
|---|
| 1834 | 1763 | } |
|---|
| 1835 | 1764 | |
|---|
| 1836 | | - ret = devm_request_threaded_irq(chip->dev, chip->gpio_int_n_irq, |
|---|
| 1837 | | - NULL, fusb302_irq_intn, |
|---|
| 1838 | | - IRQF_ONESHOT | IRQF_TRIGGER_LOW, |
|---|
| 1839 | | - "fsc_interrupt_int_n", chip); |
|---|
| 1765 | + ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn, |
|---|
| 1766 | + IRQF_TRIGGER_LOW, |
|---|
| 1767 | + "fsc_interrupt_int_n", chip); |
|---|
| 1840 | 1768 | if (ret < 0) { |
|---|
| 1841 | 1769 | dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); |
|---|
| 1842 | 1770 | goto tcpm_unregister_port; |
|---|
| 1843 | 1771 | } |
|---|
| 1844 | 1772 | enable_irq_wake(chip->gpio_int_n_irq); |
|---|
| 1845 | | - fusb302_debugfs_init(chip); |
|---|
| 1846 | 1773 | i2c_set_clientdata(client, chip); |
|---|
| 1847 | 1774 | |
|---|
| 1848 | 1775 | return ret; |
|---|
| 1849 | 1776 | |
|---|
| 1850 | 1777 | tcpm_unregister_port: |
|---|
| 1851 | 1778 | tcpm_unregister_port(chip->tcpm_port); |
|---|
| 1779 | + fwnode_handle_put(chip->tcpc_dev.fwnode); |
|---|
| 1852 | 1780 | destroy_workqueue: |
|---|
| 1781 | + fusb302_debugfs_exit(chip); |
|---|
| 1853 | 1782 | destroy_workqueue(chip->wq); |
|---|
| 1854 | 1783 | |
|---|
| 1855 | 1784 | return ret; |
|---|
| .. | .. |
|---|
| 1859 | 1788 | { |
|---|
| 1860 | 1789 | struct fusb302_chip *chip = i2c_get_clientdata(client); |
|---|
| 1861 | 1790 | |
|---|
| 1791 | + disable_irq_wake(chip->gpio_int_n_irq); |
|---|
| 1792 | + free_irq(chip->gpio_int_n_irq, chip); |
|---|
| 1793 | + kthread_destroy_worker(chip->irq_worker); |
|---|
| 1794 | + cancel_delayed_work_sync(&chip->bc_lvl_handler); |
|---|
| 1862 | 1795 | tcpm_unregister_port(chip->tcpm_port); |
|---|
| 1796 | + fwnode_handle_put(chip->tcpc_dev.fwnode); |
|---|
| 1863 | 1797 | destroy_workqueue(chip->wq); |
|---|
| 1864 | 1798 | fusb302_debugfs_exit(chip); |
|---|
| 1865 | 1799 | |
|---|
| .. | .. |
|---|
| 1869 | 1803 | static int fusb302_pm_suspend(struct device *dev) |
|---|
| 1870 | 1804 | { |
|---|
| 1871 | 1805 | struct fusb302_chip *chip = dev->driver_data; |
|---|
| 1806 | + unsigned long flags; |
|---|
| 1872 | 1807 | |
|---|
| 1873 | | - if (atomic_read(&chip->i2c_busy)) |
|---|
| 1874 | | - return -EBUSY; |
|---|
| 1875 | | - atomic_set(&chip->pm_suspend, 1); |
|---|
| 1808 | + spin_lock_irqsave(&chip->irq_lock, flags); |
|---|
| 1809 | + chip->irq_suspended = true; |
|---|
| 1810 | + spin_unlock_irqrestore(&chip->irq_lock, flags); |
|---|
| 1876 | 1811 | |
|---|
| 1812 | + /* Make sure any pending irq_work is finished before the bus suspends */ |
|---|
| 1813 | + kthread_flush_worker(chip->irq_worker); |
|---|
| 1877 | 1814 | return 0; |
|---|
| 1878 | 1815 | } |
|---|
| 1879 | 1816 | |
|---|
| 1880 | 1817 | static int fusb302_pm_resume(struct device *dev) |
|---|
| 1881 | 1818 | { |
|---|
| 1882 | 1819 | struct fusb302_chip *chip = dev->driver_data; |
|---|
| 1820 | + unsigned long flags; |
|---|
| 1821 | + u8 pwr; |
|---|
| 1822 | + int ret = 0; |
|---|
| 1883 | 1823 | |
|---|
| 1884 | | - atomic_set(&chip->pm_suspend, 0); |
|---|
| 1824 | + /* |
|---|
| 1825 | + * When the power of fusb302 is lost or i2c read failed in PM S/R |
|---|
| 1826 | + * process, we must reset the tcpm port first to ensure the devices |
|---|
| 1827 | + * can attach again. |
|---|
| 1828 | + */ |
|---|
| 1829 | + ret = fusb302_i2c_read(chip, FUSB_REG_POWER, &pwr); |
|---|
| 1830 | + if (pwr != FUSB_REG_POWER_PWR_ALL || ret < 0) |
|---|
| 1831 | + tcpm_tcpc_reset(chip->tcpm_port); |
|---|
| 1832 | + |
|---|
| 1833 | + spin_lock_irqsave(&chip->irq_lock, flags); |
|---|
| 1834 | + if (chip->irq_while_suspended) { |
|---|
| 1835 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 1836 | + chip->irq_while_suspended = false; |
|---|
| 1837 | + } |
|---|
| 1838 | + chip->irq_suspended = false; |
|---|
| 1839 | + spin_unlock_irqrestore(&chip->irq_lock, flags); |
|---|
| 1885 | 1840 | |
|---|
| 1886 | 1841 | return 0; |
|---|
| 1887 | 1842 | } |
|---|