typec CC脚检测中断

发布时间 2023-07-07 17:29:44作者: 轻轻的吻
	[TYPEC_ATTACH_DETACH_IRQ] = {
		.name		= "typec-attach-detach",
		.handler	= smblite_typec_attach_detach_irq_handler,
		.wake		= true,
	},

 

irqreturn_t smblite_typec_attach_detach_irq_handler(int irq, void *data)
{
        struct smb_irq_data *irq_data = data;
        struct smb_charger *chg = irq_data->parent_data;
        u8 stat;
        bool attached = false;
        int rc;

        /* IRQ not expected to be executed for uUSB, return */
        if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
                return IRQ_HANDLED;

        smblite_lib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);

        rc = smblite_lib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG, &stat);
        if (rc < 0) {
                smblite_lib_err(chg, "Couldn't read TYPE_C_STATE_MACHINE_STATUS_REG rc=%d\n",
                        rc);
                return IRQ_HANDLED;
        }

        attached = !!(stat & TYPEC_ATTACH_DETACH_STATE_BIT);

        if (attached) {
                rc = smblite_lib_read(chg, TYPE_C_MISC_STATUS_REG, &stat);
                if (rc < 0) {
                        smblite_lib_err(chg, "Couldn't read TYPE_C_MISC_STATUS_REG rc=%d\n",
                                rc);
                        return IRQ_HANDLED;
                }

                if (smblite_lib_get_prop_dfp_mode(chg) ==
                                POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) {
                        chg->sink_src_mode = AUDIO_ACCESS_MODE;
                        typec_ra_ra_insertion(chg);
                } else if (stat & SNK_SRC_MODE_BIT) {
                        chg->sink_src_mode = SRC_MODE;
                        typec_sink_insertion(chg);  //mode的切换
                } else {
                        chg->sink_src_mode = SINK_MODE;
                        typec_src_insertion(chg);//mode的切换
                }

                rc = typec_partner_register(chg);
                if (rc < 0)
                        smblite_lib_err(chg, "Couldn't to register partner rc =%d\n",
                                        rc);
        } else {
                switch (chg->sink_src_mode) {
                case SRC_MODE:
                        typec_sink_removal(chg);  
                        break;
                case SINK_MODE:
                case AUDIO_ACCESS_MODE:
                        typec_src_removal(chg);
                        break;
                case UNATTACHED_MODE:
                default:
                        typec_mode_unattached(chg);
                        break;
                }

                if (!chg->pr_swap_in_progress)
                        chg->sink_src_mode = UNATTACHED_MODE;

                /*
                 * Restore DRP mode on type-C cable disconnect if role
                 * swap is not in progress, to ensure forced sink or src
                 * mode configuration is reset properly.
                 */

                if (chg->typec_port && !chg->pr_swap_in_progress) {
                        /*
                         * Schedule the work to differentiate actual removal
                         * of cable and detach interrupt during role swap,
                         * unregister the partner only during actual cable
                         * removal.
                         */
                        cancel_delayed_work(&chg->pr_swap_detach_work);
                        vote(chg->awake_votable, DETACH_DETECT_VOTER, true, 0);
                        schedule_delayed_work(&chg->pr_swap_detach_work,
                                msecs_to_jiffies(TYPEC_DETACH_DETECT_DELAY_MS));
                        smblite_lib_force_dr_mode(chg, TYPEC_PORT_DRP);

                        /*
                         * To handle cable removal during role
                         * swap failure.
                         */
                        chg->typec_role_swap_failed = false;
                }
        }

        rc = smblite_lib_masked_write(chg, USB_CMD_PULLDOWN_REG,
                        EN_PULLDOWN_USB_IN_BIT,
                        attached ?  0 : EN_PULLDOWN_USB_IN_BIT);
        if (rc < 0)
                smblite_lib_err(chg, "Couldn't configure pulldown on USB_IN rc=%d\n",
                                rc);

        power_supply_changed(chg->usb_psy);

        return IRQ_HANDLED;
}