| .. | .. |
|---|
| 17 | 17 | #include <linux/of_gpio.h> |
|---|
| 18 | 18 | #include <linux/regmap.h> |
|---|
| 19 | 19 | #include <linux/power_supply.h> |
|---|
| 20 | +#include <linux/kthread.h> |
|---|
| 21 | +#include <uapi/linux/sched/types.h> |
|---|
| 20 | 22 | |
|---|
| 21 | 23 | #include "fusb302.h" |
|---|
| 22 | 24 | |
|---|
| .. | .. |
|---|
| 188 | 190 | break; |
|---|
| 189 | 191 | case 1: |
|---|
| 190 | 192 | /* Battery */ |
|---|
| 191 | | - if ((CAP_VPDO_VOLTAGE(chip->rec_load[i]) * 50) <= |
|---|
| 193 | + if ((CAP_VPDO_MAX_VOLTAGE(chip->rec_load[i]) * 50) <= |
|---|
| 192 | 194 | max_vol && |
|---|
| 193 | 195 | (CAP_VPDO_CURRENT(chip->rec_load[i]) * 10) <= |
|---|
| 194 | 196 | max_cur) { |
|---|
| 195 | 197 | chip->pos_power = i + 1; |
|---|
| 196 | | - tmp = CAP_VPDO_VOLTAGE(chip->rec_load[i]); |
|---|
| 198 | + tmp = CAP_VPDO_MAX_VOLTAGE(chip->rec_load[i]); |
|---|
| 197 | 199 | chip->pd_output_vol = tmp * 50; |
|---|
| 198 | 200 | tmp = CAP_VPDO_CURRENT(chip->rec_load[i]); |
|---|
| 199 | 201 | chip->pd_output_cur = tmp * 10; |
|---|
| .. | .. |
|---|
| 929 | 931 | static void set_mesg(struct fusb30x_chip *chip, int cmd, int is_DMT) |
|---|
| 930 | 932 | { |
|---|
| 931 | 933 | int i; |
|---|
| 934 | + uint32_t rec_load; |
|---|
| 932 | 935 | struct PD_CAP_INFO *pd_cap_info = &chip->pd_cap_info; |
|---|
| 933 | 936 | |
|---|
| 934 | 937 | chip->send_head = ((chip->msg_id & 0x7) << 9) | |
|---|
| .. | .. |
|---|
| 962 | 965 | (0 << 25) | |
|---|
| 963 | 966 | (0 << 24); |
|---|
| 964 | 967 | |
|---|
| 965 | | - switch (CAP_POWER_TYPE(chip->rec_load[chip->pos_power - 1])) { |
|---|
| 968 | + rec_load = chip->rec_load[chip->pos_power - 1]; |
|---|
| 969 | + switch (CAP_POWER_TYPE(rec_load)) { |
|---|
| 966 | 970 | case 0: |
|---|
| 967 | 971 | /* Fixed Supply */ |
|---|
| 968 | | - chip->send_load[0] |= ((CAP_FPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); |
|---|
| 969 | | - chip->send_load[0] |= (CAP_FPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); |
|---|
| 972 | + chip->sink_supply_type = 0; |
|---|
| 973 | + chip->sink_volt = CAP_FPDO_VOLTAGE(rec_load); |
|---|
| 974 | + chip->sink_opr_cur = CAP_FPDO_CURRENT(rec_load); |
|---|
| 975 | + chip->send_load[0] |= chip->sink_volt << 10; |
|---|
| 976 | + chip->send_load[0] |= chip->sink_opr_cur; |
|---|
| 970 | 977 | break; |
|---|
| 971 | 978 | case 1: |
|---|
| 972 | | - /* Battery */ |
|---|
| 973 | | - chip->send_load[0] |= ((CAP_VPDO_VOLTAGE(chip->rec_load[chip->pos_power - 1]) << 10) & 0x3ff); |
|---|
| 974 | | - chip->send_load[0] |= (CAP_VPDO_CURRENT(chip->rec_load[chip->pos_power - 1]) & 0x3ff); |
|---|
| 979 | + /* Battery Supply */ |
|---|
| 980 | + chip->sink_supply_type = 1; |
|---|
| 981 | + chip->sink_max_volt = |
|---|
| 982 | + CAP_VPDO_MAX_VOLTAGE(rec_load); |
|---|
| 983 | + chip->sink_min_volt = |
|---|
| 984 | + CAP_VPDO_MIN_VOLTAGE(rec_load); |
|---|
| 985 | + chip->sink_opr_power = |
|---|
| 986 | + CAP_VPDO_CURRENT(rec_load); |
|---|
| 987 | + chip->send_load[0] |= chip->sink_max_volt << 20; |
|---|
| 988 | + chip->send_load[0] |= chip->sink_min_volt << 10; |
|---|
| 989 | + chip->send_load[0] |= chip->sink_opr_power; |
|---|
| 975 | 990 | break; |
|---|
| 976 | 991 | default: |
|---|
| 977 | | - /* not meet battery caps */ |
|---|
| 992 | + dev_warn(chip->dev, "No support supply req type %d\n", |
|---|
| 993 | + CAP_POWER_TYPE(rec_load)); |
|---|
| 978 | 994 | break; |
|---|
| 979 | 995 | } |
|---|
| 980 | 996 | break; |
|---|
| 981 | 997 | case DMT_SINKCAPABILITIES: |
|---|
| 998 | + chip->send_head |= (1 << 12) | (cmd & 0xf); |
|---|
| 999 | + switch (chip->sink_supply_type) { |
|---|
| 1000 | + case 0: |
|---|
| 1001 | + /* |
|---|
| 1002 | + * Fixed Supply |
|---|
| 1003 | + * bit26 for 'USB Communiications Capable' |
|---|
| 1004 | + */ |
|---|
| 1005 | + chip->send_load[0] = |
|---|
| 1006 | + (chip->sink_supply_type << 30) | |
|---|
| 1007 | + (1 << 26) | |
|---|
| 1008 | + (chip->sink_volt << 10) | |
|---|
| 1009 | + (chip->sink_opr_cur); |
|---|
| 1010 | + break; |
|---|
| 1011 | + case 1: |
|---|
| 1012 | + /* Battery Supply */ |
|---|
| 1013 | + chip->send_load[0] = |
|---|
| 1014 | + (chip->sink_supply_type << 30) | |
|---|
| 1015 | + (chip->sink_max_volt << 20) | |
|---|
| 1016 | + (chip->sink_min_volt << 10) | |
|---|
| 1017 | + (chip->sink_opr_cur); |
|---|
| 1018 | + break; |
|---|
| 1019 | + default: |
|---|
| 1020 | + dev_warn(chip->dev, "No support sink supply type %d\n", |
|---|
| 1021 | + chip->sink_supply_type); |
|---|
| 1022 | + break; |
|---|
| 1023 | + } |
|---|
| 982 | 1024 | break; |
|---|
| 983 | 1025 | case DMT_VENDERDEFINED: |
|---|
| 984 | 1026 | break; |
|---|
| .. | .. |
|---|
| 2529 | 2571 | break; |
|---|
| 2530 | 2572 | case 1: |
|---|
| 2531 | 2573 | /* Battery */ |
|---|
| 2532 | | - if (CAP_VPDO_VOLTAGE(chip->rec_load[tmp]) <= 100) |
|---|
| 2574 | + if (CAP_VPDO_MAX_VOLTAGE(chip->rec_load[tmp]) <= 100) |
|---|
| 2533 | 2575 | chip->pos_power = tmp + 1; |
|---|
| 2534 | 2576 | break; |
|---|
| 2535 | 2577 | default: |
|---|
| .. | .. |
|---|
| 2620 | 2662 | chip->notify.is_pd_connected = true; |
|---|
| 2621 | 2663 | dev_info(chip->dev, |
|---|
| 2622 | 2664 | "PD connected as UFP, fetching 5V\n"); |
|---|
| 2665 | + tcpm_get_message(chip); |
|---|
| 2666 | + if (PACKET_IS_CONTROL_MSG(chip->rec_head, |
|---|
| 2667 | + CMT_GETSINKCAP)) { |
|---|
| 2668 | + set_mesg(chip, DMT_SINKCAPABILITIES, |
|---|
| 2669 | + DATAMESSAGE); |
|---|
| 2670 | + chip->tx_state = tx_idle; |
|---|
| 2671 | + policy_send_data(chip); |
|---|
| 2672 | + } |
|---|
| 2623 | 2673 | set_state(chip, policy_snk_ready); |
|---|
| 2624 | 2674 | } else if (PACKET_IS_DATA_MSG(chip->rec_head, |
|---|
| 2625 | 2675 | DMT_SOURCECAPABILITIES)) { |
|---|
| .. | .. |
|---|
| 2671 | 2721 | static void fusb_state_snk_ready(struct fusb30x_chip *chip, u32 evt) |
|---|
| 2672 | 2722 | { |
|---|
| 2673 | 2723 | if (evt & EVENT_RX) { |
|---|
| 2674 | | - if (PACKET_IS_DATA_MSG(chip->rec_head, DMT_VENDERDEFINED)) { |
|---|
| 2724 | + if (PACKET_IS_CONTROL_MSG(chip->rec_head, CMT_GETSINKCAP)) { |
|---|
| 2725 | + set_mesg(chip, DMT_SINKCAPABILITIES, DATAMESSAGE); |
|---|
| 2726 | + chip->tx_state = tx_idle; |
|---|
| 2727 | + policy_send_data(chip); |
|---|
| 2728 | + } else if (PACKET_IS_DATA_MSG(chip->rec_head, |
|---|
| 2729 | + DMT_VENDERDEFINED)) { |
|---|
| 2675 | 2730 | process_vdm_msg(chip); |
|---|
| 2676 | 2731 | chip->work_continue |= EVENT_WORK_CONTINUE; |
|---|
| 2677 | 2732 | chip->timer_state = T_DISABLED; |
|---|
| .. | .. |
|---|
| 3189 | 3244 | |
|---|
| 3190 | 3245 | BACK: |
|---|
| 3191 | 3246 | if (chip->work_continue) { |
|---|
| 3192 | | - queue_work(chip->fusb30x_wq, &chip->work); |
|---|
| 3247 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 3193 | 3248 | return; |
|---|
| 3194 | 3249 | } |
|---|
| 3195 | 3250 | |
|---|
| 3196 | 3251 | if (!platform_get_device_irq_state(chip)) |
|---|
| 3197 | 3252 | fusb_irq_enable(chip); |
|---|
| 3198 | 3253 | else |
|---|
| 3199 | | - queue_work(chip->fusb30x_wq, &chip->work); |
|---|
| 3254 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 3200 | 3255 | } |
|---|
| 3201 | 3256 | |
|---|
| 3202 | 3257 | static irqreturn_t cc_interrupt_handler(int irq, void *dev_id) |
|---|
| 3203 | 3258 | { |
|---|
| 3204 | 3259 | struct fusb30x_chip *chip = dev_id; |
|---|
| 3205 | 3260 | |
|---|
| 3206 | | - queue_work(chip->fusb30x_wq, &chip->work); |
|---|
| 3207 | 3261 | fusb_irq_disable(chip); |
|---|
| 3262 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 3208 | 3263 | return IRQ_HANDLED; |
|---|
| 3209 | 3264 | } |
|---|
| 3210 | 3265 | |
|---|
| .. | .. |
|---|
| 3266 | 3321 | } |
|---|
| 3267 | 3322 | |
|---|
| 3268 | 3323 | if (i != fusb30x_port_used) |
|---|
| 3269 | | - queue_work(fusb30x_port_info[i]->fusb30x_wq, |
|---|
| 3270 | | - &fusb30x_port_info[i]->work); |
|---|
| 3324 | + kthread_queue_work(fusb30x_port_info[i]->irq_worker, |
|---|
| 3325 | + &fusb30x_port_info[i]->irq_work); |
|---|
| 3271 | 3326 | |
|---|
| 3272 | 3327 | return HRTIMER_NORESTART; |
|---|
| 3273 | 3328 | } |
|---|
| .. | .. |
|---|
| 3286 | 3341 | chip->timer_mux = T_DISABLED; |
|---|
| 3287 | 3342 | } |
|---|
| 3288 | 3343 | |
|---|
| 3289 | | -static void fusb302_work_func(struct work_struct *work) |
|---|
| 3344 | +static void fusb302_work_func(struct kthread_work *work) |
|---|
| 3290 | 3345 | { |
|---|
| 3291 | 3346 | struct fusb30x_chip *chip; |
|---|
| 3292 | 3347 | |
|---|
| 3293 | | - chip = container_of(work, struct fusb30x_chip, work); |
|---|
| 3348 | + chip = container_of(work, struct fusb30x_chip, irq_work); |
|---|
| 3294 | 3349 | if (!chip->suspended) |
|---|
| 3295 | 3350 | state_machine_typec(chip); |
|---|
| 3296 | 3351 | } |
|---|
| .. | .. |
|---|
| 3300 | 3355 | { |
|---|
| 3301 | 3356 | struct fusb30x_chip *chip; |
|---|
| 3302 | 3357 | struct PD_CAP_INFO *pd_cap_info; |
|---|
| 3358 | + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; |
|---|
| 3303 | 3359 | int ret; |
|---|
| 3304 | 3360 | char *string[2]; |
|---|
| 3305 | 3361 | |
|---|
| .. | .. |
|---|
| 3326 | 3382 | |
|---|
| 3327 | 3383 | fusb_initialize_timer(chip); |
|---|
| 3328 | 3384 | |
|---|
| 3329 | | - chip->fusb30x_wq = create_workqueue("fusb302_wq"); |
|---|
| 3330 | | - INIT_WORK(&chip->work, fusb302_work_func); |
|---|
| 3385 | + chip->irq_worker = kthread_create_worker(0, dev_name(chip->dev)); |
|---|
| 3386 | + if (IS_ERR(chip->irq_worker)) |
|---|
| 3387 | + return PTR_ERR(chip->irq_worker); |
|---|
| 3388 | + sched_setscheduler_nocheck(chip->irq_worker->task, SCHED_FIFO, ¶m); |
|---|
| 3389 | + kthread_init_work(&chip->irq_work, fusb302_work_func); |
|---|
| 3331 | 3390 | |
|---|
| 3332 | 3391 | chip->role = ROLE_MODE_NONE; |
|---|
| 3333 | 3392 | chip->try_role = ROLE_MODE_NONE; |
|---|
| .. | .. |
|---|
| 3368 | 3427 | chip->n_caps_used = 1; |
|---|
| 3369 | 3428 | chip->source_power_supply[0] = 0x64; |
|---|
| 3370 | 3429 | chip->source_max_current[0] = 0x96; |
|---|
| 3430 | + chip->sink_volt = 100; |
|---|
| 3431 | + chip->sink_opr_cur = 200; |
|---|
| 3371 | 3432 | |
|---|
| 3372 | 3433 | pd_cap_info = &chip->pd_cap_info; |
|---|
| 3373 | 3434 | pd_cap_info->dual_role_power = 1; |
|---|
| .. | .. |
|---|
| 3468 | 3529 | goto IRQ_ERR; |
|---|
| 3469 | 3530 | } |
|---|
| 3470 | 3531 | |
|---|
| 3471 | | - ret = devm_request_threaded_irq(&client->dev, |
|---|
| 3472 | | - chip->gpio_int_irq, |
|---|
| 3473 | | - NULL, |
|---|
| 3474 | | - cc_interrupt_handler, |
|---|
| 3475 | | - IRQF_ONESHOT | IRQF_TRIGGER_LOW, |
|---|
| 3476 | | - client->name, |
|---|
| 3477 | | - chip); |
|---|
| 3532 | + ret = request_irq(chip->gpio_int_irq, cc_interrupt_handler, |
|---|
| 3533 | + IRQF_TRIGGER_LOW, "fsc_interrupt_int_n", chip); |
|---|
| 3478 | 3534 | if (ret) { |
|---|
| 3479 | 3535 | dev_err(&client->dev, "irq request failed\n"); |
|---|
| 3480 | 3536 | goto IRQ_ERR; |
|---|
| .. | .. |
|---|
| 3503 | 3559 | } |
|---|
| 3504 | 3560 | return 0; |
|---|
| 3505 | 3561 | IRQ_ERR: |
|---|
| 3506 | | - destroy_workqueue(chip->fusb30x_wq); |
|---|
| 3562 | + kthread_destroy_worker(chip->irq_worker); |
|---|
| 3507 | 3563 | return ret; |
|---|
| 3508 | 3564 | } |
|---|
| 3509 | 3565 | |
|---|
| .. | .. |
|---|
| 3511 | 3567 | { |
|---|
| 3512 | 3568 | struct fusb30x_chip *chip = i2c_get_clientdata(client); |
|---|
| 3513 | 3569 | |
|---|
| 3514 | | - destroy_workqueue(chip->fusb30x_wq); |
|---|
| 3570 | + free_irq(chip->gpio_int_irq, chip); |
|---|
| 3571 | + kthread_destroy_worker(chip->irq_worker); |
|---|
| 3515 | 3572 | return 0; |
|---|
| 3516 | 3573 | } |
|---|
| 3517 | 3574 | |
|---|
| .. | .. |
|---|
| 3534 | 3591 | |
|---|
| 3535 | 3592 | fusb_irq_disable(chip); |
|---|
| 3536 | 3593 | chip->suspended = true; |
|---|
| 3537 | | - cancel_work_sync(&chip->work); |
|---|
| 3594 | + kthread_cancel_work_sync(&chip->irq_work); |
|---|
| 3538 | 3595 | |
|---|
| 3539 | 3596 | return 0; |
|---|
| 3540 | 3597 | } |
|---|
| .. | .. |
|---|
| 3545 | 3602 | |
|---|
| 3546 | 3603 | fusb_irq_enable(chip); |
|---|
| 3547 | 3604 | chip->suspended = false; |
|---|
| 3548 | | - queue_work(chip->fusb30x_wq, &chip->work); |
|---|
| 3605 | + kthread_queue_work(chip->irq_worker, &chip->irq_work); |
|---|
| 3549 | 3606 | |
|---|
| 3550 | 3607 | return 0; |
|---|
| 3551 | 3608 | } |
|---|