typec CC脚检测中断

	[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;
}
  •   typec的otg功能,是当otg线插上时CC pin会被到下拉GND,触发typec-attach-detach然后就会切换成host mode,识别设备:
static void smblite_lib_notify_usb_host(struct smb_charger *chg, bool enable)
{
        int rc = 0;

        /* LDO mode doesn't support OTG */
        if (chg->ldo_mode)
                return;

        if (enable) {
                smblite_lib_dbg(chg, PR_OTG, "enabling VBUS in OTG mode\n");
                rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG,
                                        OTG_EN_BIT, OTG_EN_BIT);  //typec打开otg功能,给设备供电
                if (rc < 0) {
                        smblite_lib_err(chg,
                                "Couldn't enable VBUS in OTG mode rc=%d\n", rc);
                        return;
                }
                rc = smblite_lib_masked_write(chg, DCDC_BST_VREG_SEL,
                                        VBOOST_MASK, VBOOST_5P00V);
                if (rc < 0) {
                        smblite_lib_err(chg,
                                "Couldn't write BST_VREG_SEL rc=%d\n", rc);
                        return;
                }
                smblite_lib_notify_extcon_props(chg, EXTCON_USB_HOST);
        } else {
                smblite_lib_dbg(chg, PR_OTG, "disabling VBUS in OTG mode\n");
                rc = smblite_lib_masked_write(chg, DCDC_CMD_OTG_REG,
                                        OTG_EN_BIT, 0);
                if (rc < 0) {
                        smblite_lib_err(chg,
                                "Couldn't disable VBUS in OTG mode rc=%d\n",
                                rc);
                        return;
                }
        }

        extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);//切换host模式
        chg->otg_present = enable;
}

 当插入typec线CCpin会被上拉到vbus时,切换成device模式:

static void smblite_lib_notify_device_mode(struct smb_charger *chg, bool enable)
{
        if (enable)
                smblite_lib_notify_extcon_props(chg, EXTCON_USB);

        extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
}

一文详解Type C-CC引脚的作用

  

 

 

posted @ 2023-07-07 17:20  轻轻的吻  阅读(214)  评论(0编辑  收藏  举报