Loading Documentation/devicetree/bindings/usb/msm-hsusb.txt +2 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ Optional properties : vdd min. - qcom,usbin-vadc: Corresponding vadc device's phandle to read usbin voltage using VADC. This will be used to get value of usb power supply's VOLTAGE_NOW property. - qcom,usbid-gpio: This corresponds to gpio which is used for USB ID detection. Example HSUSB OTG controller device node : usb@f9690000 { Loading Loading @@ -151,6 +152,7 @@ Example HSUSB OTG controller device node : qcom,hsusb-otg-rw-during-lpm-workaround = <1>; qcom,disable-retention-with-vdd-min; qcom,usbin-vadc = <&pm8226_vadc>; qcom,usbid-gpio = <&msm_gpio 110 0>; }; MSM HSUSB EHCI controller Loading drivers/usb/phy/phy-msm-usb.c +52 −19 Original line number Diff line number Diff line Loading @@ -2571,6 +2571,11 @@ static void msm_otg_init_sm(struct msm_otg *motg) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); } else if (motg->ext_id_irq) { if (gpio_get_value(pdata->usb_id_gpio)) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); } /* * VBUS initial state is reported after PMIC Loading Loading @@ -3481,20 +3486,26 @@ static void msm_otg_set_vbus_state(int online) queue_work(system_nrt_wq, &motg->sm_work); } static void msm_pmic_id_status_w(struct work_struct *w) static void msm_id_status_w(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, pmic_id_status_work.work); id_status_work.work); int work = 0; int id_state = 0; if (msm_otg_read_pmic_id_state(motg)) { if (motg->pdata->pmic_id_irq) id_state = msm_otg_read_pmic_id_state(motg); else if (motg->ext_id_irq) id_state = gpio_get_value(motg->pdata->usb_id_gpio); if (id_state) { if (!test_and_set_bit(ID, &motg->inputs)) { pr_debug("PMIC: ID set\n"); pr_debug("ID set\n"); work = 1; } } else { if (test_and_clear_bit(ID, &motg->inputs)) { pr_debug("PMIC: ID clear\n"); pr_debug("ID clear\n"); set_bit(A_BUS_REQ, &motg->inputs); work = 1; } Loading @@ -3509,8 +3520,8 @@ static void msm_pmic_id_status_w(struct work_struct *w) } #define MSM_PMIC_ID_STATUS_DELAY 5 /* 5msec */ static irqreturn_t msm_pmic_id_irq(int irq, void *data) #define MSM_ID_STATUS_DELAY 5 /* 5msec */ static irqreturn_t msm_id_irq(int irq, void *data) { struct msm_otg *motg = data; Loading @@ -3522,8 +3533,8 @@ static irqreturn_t msm_pmic_id_irq(int irq, void *data) if (!aca_id_turned_on) /*schedule delayed work for 5msec for ID line state to settle*/ queue_delayed_work(system_nrt_wq, &motg->pmic_id_status_work, msecs_to_jiffies(MSM_PMIC_ID_STATUS_DELAY)); queue_delayed_work(system_nrt_wq, &motg->id_status_work, msecs_to_jiffies(MSM_ID_STATUS_DELAY)); return IRQ_HANDLED; } Loading Loading @@ -4376,6 +4387,10 @@ struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev) if (pdata->pmic_id_irq < 0) pdata->pmic_id_irq = 0; pdata->usb_id_gpio = of_get_named_gpio(node, "qcom,usbid-gpio", 0); if (pdata->usb_id_gpio < 0) pr_debug("usb_id_gpio is not available\n"); pdata->l1_supported = of_property_read_bool(node, "qcom,hsusb-l1-supported"); pdata->enable_ahb2ahb_bypass = of_property_read_bool(node, Loading Loading @@ -4404,6 +4419,7 @@ static int msm_otg_probe(struct platform_device *pdev) struct usb_phy *phy; struct msm_otg_platform_data *pdata; void __iomem *tcsr; int id_irq = 0; dev_info(&pdev->dev, "msm_otg probe\n"); Loading Loading @@ -4714,7 +4730,7 @@ static int msm_otg_probe(struct platform_device *pdev) msm_otg_init_timer(motg); INIT_WORK(&motg->sm_work, msm_otg_sm_work); INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); INIT_DELAYED_WORK(&motg->pmic_id_status_work, msm_pmic_id_status_w); INIT_DELAYED_WORK(&motg->id_status_work, msm_id_status_w); INIT_DELAYED_WORK(&motg->suspend_work, msm_otg_suspend_work); setup_timer(&motg->id_timer, msm_otg_id_timer_func, (unsigned long) motg); Loading Loading @@ -4770,19 +4786,36 @@ static int msm_otg_probe(struct platform_device *pdev) if (motg->pdata->mode == USB_OTG && motg->pdata->otg_control == OTG_PMIC_CONTROL) { if (motg->pdata->pmic_id_irq) { ret = request_irq(motg->pdata->pmic_id_irq, msm_pmic_id_irq, if (gpio_is_valid(motg->pdata->usb_id_gpio)) { /* usb_id_gpio request */ ret = gpio_request(motg->pdata->usb_id_gpio, "USB_ID_GPIO"); if (ret < 0) { dev_err(&pdev->dev, "gpio req failed for id\n"); motg->pdata->usb_id_gpio = 0; goto remove_phy; } /* usb_id_gpio to irq */ id_irq = gpio_to_irq(motg->pdata->usb_id_gpio); motg->ext_id_irq = id_irq; } else if (motg->pdata->pmic_id_irq) { id_irq = motg->pdata->pmic_id_irq; } if (id_irq) { ret = request_irq(id_irq, msm_id_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "msm_otg", motg); if (ret) { dev_err(&pdev->dev, "request irq failed for PMIC ID\n"); dev_err(&pdev->dev, "request irq failed for ID\n"); goto remove_phy; } } else { ret = -ENODEV; dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n"); dev_err(&pdev->dev, "ID IRQ doesn't exist\n"); goto remove_phy; } } Loading Loading @@ -4958,7 +4991,7 @@ static int msm_otg_remove(struct platform_device *pdev) msm_otg_mhl_register_callback(motg, NULL); msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_delayed_work_sync(&motg->pmic_id_status_work); cancel_delayed_work_sync(&motg->id_status_work); cancel_delayed_work_sync(&motg->suspend_work); cancel_work_sync(&motg->sm_work); Loading include/linux/usb/msm_hsusb.h +5 −1 Original line number Diff line number Diff line Loading @@ -250,6 +250,7 @@ enum usb_ctrl { * mode with controller in device mode. * @bool disable_retention_with_vdd_min: Indicates whether to enable allowing VDDmin without putting PHY into retention. * @usb_id_gpio: Gpio used for USB ID detection. */ struct msm_otg_platform_data { int *phy_init_seq; Loading Loading @@ -281,6 +282,7 @@ struct msm_otg_platform_data { bool rw_during_lpm_workaround; bool enable_ahb2ahb_bypass; bool disable_retention_with_vdd_min; int usb_id_gpio; }; /* phy related flags */ Loading Loading @@ -369,6 +371,7 @@ struct msm_otg_platform_data { * very slow plug in of wall charger. * @ui_enabled: USB Intterupt is enabled or disabled. * @pm_done: Indicates whether USB is PM resumed * @ext_id_irq: IRQ for ID interrupt. */ struct msm_otg { struct usb_phy phy; Loading Loading @@ -412,7 +415,7 @@ struct msm_otg { int async_int; unsigned cur_power; struct delayed_work chg_work; struct delayed_work pmic_id_status_work; struct delayed_work id_status_work; struct delayed_work suspend_work; enum usb_chg_state chg_state; enum usb_chg_type chg_type; Loading Loading @@ -490,6 +493,7 @@ struct msm_otg { int ui_enabled; bool pm_done; struct qpnp_vadc_chip *vadc_dev; int ext_id_irq; }; struct ci13xxx_platform_data { Loading Loading
Documentation/devicetree/bindings/usb/msm-hsusb.txt +2 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ Optional properties : vdd min. - qcom,usbin-vadc: Corresponding vadc device's phandle to read usbin voltage using VADC. This will be used to get value of usb power supply's VOLTAGE_NOW property. - qcom,usbid-gpio: This corresponds to gpio which is used for USB ID detection. Example HSUSB OTG controller device node : usb@f9690000 { Loading Loading @@ -151,6 +152,7 @@ Example HSUSB OTG controller device node : qcom,hsusb-otg-rw-during-lpm-workaround = <1>; qcom,disable-retention-with-vdd-min; qcom,usbin-vadc = <&pm8226_vadc>; qcom,usbid-gpio = <&msm_gpio 110 0>; }; MSM HSUSB EHCI controller Loading
drivers/usb/phy/phy-msm-usb.c +52 −19 Original line number Diff line number Diff line Loading @@ -2571,6 +2571,11 @@ static void msm_otg_init_sm(struct msm_otg *motg) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); } else if (motg->ext_id_irq) { if (gpio_get_value(pdata->usb_id_gpio)) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); } /* * VBUS initial state is reported after PMIC Loading Loading @@ -3481,20 +3486,26 @@ static void msm_otg_set_vbus_state(int online) queue_work(system_nrt_wq, &motg->sm_work); } static void msm_pmic_id_status_w(struct work_struct *w) static void msm_id_status_w(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, pmic_id_status_work.work); id_status_work.work); int work = 0; int id_state = 0; if (msm_otg_read_pmic_id_state(motg)) { if (motg->pdata->pmic_id_irq) id_state = msm_otg_read_pmic_id_state(motg); else if (motg->ext_id_irq) id_state = gpio_get_value(motg->pdata->usb_id_gpio); if (id_state) { if (!test_and_set_bit(ID, &motg->inputs)) { pr_debug("PMIC: ID set\n"); pr_debug("ID set\n"); work = 1; } } else { if (test_and_clear_bit(ID, &motg->inputs)) { pr_debug("PMIC: ID clear\n"); pr_debug("ID clear\n"); set_bit(A_BUS_REQ, &motg->inputs); work = 1; } Loading @@ -3509,8 +3520,8 @@ static void msm_pmic_id_status_w(struct work_struct *w) } #define MSM_PMIC_ID_STATUS_DELAY 5 /* 5msec */ static irqreturn_t msm_pmic_id_irq(int irq, void *data) #define MSM_ID_STATUS_DELAY 5 /* 5msec */ static irqreturn_t msm_id_irq(int irq, void *data) { struct msm_otg *motg = data; Loading @@ -3522,8 +3533,8 @@ static irqreturn_t msm_pmic_id_irq(int irq, void *data) if (!aca_id_turned_on) /*schedule delayed work for 5msec for ID line state to settle*/ queue_delayed_work(system_nrt_wq, &motg->pmic_id_status_work, msecs_to_jiffies(MSM_PMIC_ID_STATUS_DELAY)); queue_delayed_work(system_nrt_wq, &motg->id_status_work, msecs_to_jiffies(MSM_ID_STATUS_DELAY)); return IRQ_HANDLED; } Loading Loading @@ -4376,6 +4387,10 @@ struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev) if (pdata->pmic_id_irq < 0) pdata->pmic_id_irq = 0; pdata->usb_id_gpio = of_get_named_gpio(node, "qcom,usbid-gpio", 0); if (pdata->usb_id_gpio < 0) pr_debug("usb_id_gpio is not available\n"); pdata->l1_supported = of_property_read_bool(node, "qcom,hsusb-l1-supported"); pdata->enable_ahb2ahb_bypass = of_property_read_bool(node, Loading Loading @@ -4404,6 +4419,7 @@ static int msm_otg_probe(struct platform_device *pdev) struct usb_phy *phy; struct msm_otg_platform_data *pdata; void __iomem *tcsr; int id_irq = 0; dev_info(&pdev->dev, "msm_otg probe\n"); Loading Loading @@ -4714,7 +4730,7 @@ static int msm_otg_probe(struct platform_device *pdev) msm_otg_init_timer(motg); INIT_WORK(&motg->sm_work, msm_otg_sm_work); INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); INIT_DELAYED_WORK(&motg->pmic_id_status_work, msm_pmic_id_status_w); INIT_DELAYED_WORK(&motg->id_status_work, msm_id_status_w); INIT_DELAYED_WORK(&motg->suspend_work, msm_otg_suspend_work); setup_timer(&motg->id_timer, msm_otg_id_timer_func, (unsigned long) motg); Loading Loading @@ -4770,19 +4786,36 @@ static int msm_otg_probe(struct platform_device *pdev) if (motg->pdata->mode == USB_OTG && motg->pdata->otg_control == OTG_PMIC_CONTROL) { if (motg->pdata->pmic_id_irq) { ret = request_irq(motg->pdata->pmic_id_irq, msm_pmic_id_irq, if (gpio_is_valid(motg->pdata->usb_id_gpio)) { /* usb_id_gpio request */ ret = gpio_request(motg->pdata->usb_id_gpio, "USB_ID_GPIO"); if (ret < 0) { dev_err(&pdev->dev, "gpio req failed for id\n"); motg->pdata->usb_id_gpio = 0; goto remove_phy; } /* usb_id_gpio to irq */ id_irq = gpio_to_irq(motg->pdata->usb_id_gpio); motg->ext_id_irq = id_irq; } else if (motg->pdata->pmic_id_irq) { id_irq = motg->pdata->pmic_id_irq; } if (id_irq) { ret = request_irq(id_irq, msm_id_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "msm_otg", motg); if (ret) { dev_err(&pdev->dev, "request irq failed for PMIC ID\n"); dev_err(&pdev->dev, "request irq failed for ID\n"); goto remove_phy; } } else { ret = -ENODEV; dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n"); dev_err(&pdev->dev, "ID IRQ doesn't exist\n"); goto remove_phy; } } Loading Loading @@ -4958,7 +4991,7 @@ static int msm_otg_remove(struct platform_device *pdev) msm_otg_mhl_register_callback(motg, NULL); msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_delayed_work_sync(&motg->pmic_id_status_work); cancel_delayed_work_sync(&motg->id_status_work); cancel_delayed_work_sync(&motg->suspend_work); cancel_work_sync(&motg->sm_work); Loading
include/linux/usb/msm_hsusb.h +5 −1 Original line number Diff line number Diff line Loading @@ -250,6 +250,7 @@ enum usb_ctrl { * mode with controller in device mode. * @bool disable_retention_with_vdd_min: Indicates whether to enable allowing VDDmin without putting PHY into retention. * @usb_id_gpio: Gpio used for USB ID detection. */ struct msm_otg_platform_data { int *phy_init_seq; Loading Loading @@ -281,6 +282,7 @@ struct msm_otg_platform_data { bool rw_during_lpm_workaround; bool enable_ahb2ahb_bypass; bool disable_retention_with_vdd_min; int usb_id_gpio; }; /* phy related flags */ Loading Loading @@ -369,6 +371,7 @@ struct msm_otg_platform_data { * very slow plug in of wall charger. * @ui_enabled: USB Intterupt is enabled or disabled. * @pm_done: Indicates whether USB is PM resumed * @ext_id_irq: IRQ for ID interrupt. */ struct msm_otg { struct usb_phy phy; Loading Loading @@ -412,7 +415,7 @@ struct msm_otg { int async_int; unsigned cur_power; struct delayed_work chg_work; struct delayed_work pmic_id_status_work; struct delayed_work id_status_work; struct delayed_work suspend_work; enum usb_chg_state chg_state; enum usb_chg_type chg_type; Loading Loading @@ -490,6 +493,7 @@ struct msm_otg { int ui_enabled; bool pm_done; struct qpnp_vadc_chip *vadc_dev; int ext_id_irq; }; struct ci13xxx_platform_data { Loading