Loading Documentation/devicetree/bindings/platform/msm/qpnp-usbdetect.txt 0 → 100644 +24 −0 Original line number Diff line number Diff line QPNP External USB VBUS Detection Circuit Discrete USB VBUS detection circuitry can be connected to Qualcomm PMICs. Such circuits can be used to detect the when a USB cable is connected to an upstream port such as a standard host or a wall charger by detecting the presence of VBUS voltage. The PMIC is notified by a detection event via SPMI bus interrupt. A software driver can in turn notify the USB subsytem using the power_supply framework. Required Properties: - compatible: must be "qcom,qpnp-usbdetect" - interrupts: an interrupt triggered by the output of the detection circuit - interrupt-names: must be "vbus_det_irq" - vin-supply: phandle to a regulator that supplies 5V to this circuit Example: usb_detect { compatible = "qcom,qpnp-usbdetect"; interrupt-parent = <&spmi_bus>; interrupts = <0x0 0xCA 0x0>; /* PMA8084 GPIO 11 */ interrupt-names = "vbus_det_irq"; vin-supply = <&vbus_det_reg>; }; drivers/platform/msm/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,16 @@ config QPNP_COINCELL maintain PMIC register state when the main battery is removed from the mobile device. config QPNP_USB_DETECT tristate "Qualcomm QPNP USB VBUS Detection" depends on POWER_SUPPLY help This driver supports external USB VBUS detection circuitry which can be connected to Qualcomm QPNP PMIC devices. The driver will configure a GPIO from the detector's output line and in turn notify the USB driver of VBUS presence/disconnection using the power_supply framework. config IPA tristate "IPA support" depends on SPS Loading drivers/platform/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,4 @@ obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o obj-$(CONFIG_MSM_AVTIMER) += avtimer.o obj-$(CONFIG_SSM) += ssm.o obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o obj-$(CONFIG_QPNP_USB_DETECT) += qpnp-usbdetect.o drivers/platform/msm/qpnp-usbdetect.c 0 → 100644 +126 −0 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/of_platform.h> #include <linux/interrupt.h> #include <linux/power_supply.h> #include <linux/regulator/consumer.h> struct qpnp_usbdetect { struct platform_device *pdev; struct regulator *vin; struct power_supply *usb_psy; int vbus_det_irq; }; static irqreturn_t qpnp_usbdetect_vbus_irq(int irq, void *data) { struct qpnp_usbdetect *usb = data; int vbus; vbus = !!irq_read_line(irq); power_supply_set_present(usb->usb_psy, vbus); return IRQ_HANDLED; } static int qpnp_usbdetect_probe(struct platform_device *pdev) { struct qpnp_usbdetect *usb; struct power_supply *usb_psy; int rc; usb_psy = power_supply_get_by_name("usb"); if (!usb_psy) { dev_dbg(&pdev->dev, "USB power_supply not found, deferring probe\n"); return -EPROBE_DEFER; } usb = devm_kzalloc(&pdev->dev, sizeof(*usb), GFP_KERNEL); if (!usb) return -ENOMEM; usb->pdev = pdev; usb->usb_psy = usb_psy; usb->vin = devm_regulator_get(&pdev->dev, "vin"); if (IS_ERR(usb->vin)) { dev_err(&pdev->dev, "Failed to get VIN regulator: %ld\n", PTR_ERR(usb->vin)); return PTR_ERR(usb->vin); } rc = regulator_enable(usb->vin); if (rc) { dev_err(&pdev->dev, "Failed to enable VIN regulator: %d\n", rc); return rc; } usb->vbus_det_irq = platform_get_irq_byname(pdev, "vbus_det_irq"); if (usb->vbus_det_irq < 0) { regulator_disable(usb->vin); return usb->vbus_det_irq; } rc = devm_request_irq(&pdev->dev, usb->vbus_det_irq, qpnp_usbdetect_vbus_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "vbus_det_irq", usb); if (rc) { dev_err(&pdev->dev, "request for vbus_det_irq failed: %d\n", rc); regulator_disable(usb->vin); return rc; } enable_irq_wake(usb->vbus_det_irq); dev_set_drvdata(&pdev->dev, usb); return 0; } static int qpnp_usbdetect_remove(struct platform_device *pdev) { struct qpnp_usbdetect *usb = dev_get_drvdata(&pdev->dev); disable_irq_wake(usb->vbus_det_irq); disable_irq(usb->vbus_det_irq); regulator_disable(usb->vin); return 0; } static struct of_device_id of_match_table[] = { { .compatible = "qcom,qpnp-usbdetect", } }; static struct platform_driver qpnp_usbdetect_driver = { .driver = { .name = "qcom,qpnp-usbdetect", .of_match_table = of_match_table, }, .probe = qpnp_usbdetect_probe, .remove = qpnp_usbdetect_remove, }; module_driver(qpnp_usbdetect_driver, platform_driver_register, platform_driver_unregister); MODULE_DESCRIPTION("QPNP PMIC USB VBUS Detection driver"); MODULE_LICENSE("GPL v2"); Loading
Documentation/devicetree/bindings/platform/msm/qpnp-usbdetect.txt 0 → 100644 +24 −0 Original line number Diff line number Diff line QPNP External USB VBUS Detection Circuit Discrete USB VBUS detection circuitry can be connected to Qualcomm PMICs. Such circuits can be used to detect the when a USB cable is connected to an upstream port such as a standard host or a wall charger by detecting the presence of VBUS voltage. The PMIC is notified by a detection event via SPMI bus interrupt. A software driver can in turn notify the USB subsytem using the power_supply framework. Required Properties: - compatible: must be "qcom,qpnp-usbdetect" - interrupts: an interrupt triggered by the output of the detection circuit - interrupt-names: must be "vbus_det_irq" - vin-supply: phandle to a regulator that supplies 5V to this circuit Example: usb_detect { compatible = "qcom,qpnp-usbdetect"; interrupt-parent = <&spmi_bus>; interrupts = <0x0 0xCA 0x0>; /* PMA8084 GPIO 11 */ interrupt-names = "vbus_det_irq"; vin-supply = <&vbus_det_reg>; };
drivers/platform/msm/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,16 @@ config QPNP_COINCELL maintain PMIC register state when the main battery is removed from the mobile device. config QPNP_USB_DETECT tristate "Qualcomm QPNP USB VBUS Detection" depends on POWER_SUPPLY help This driver supports external USB VBUS detection circuitry which can be connected to Qualcomm QPNP PMIC devices. The driver will configure a GPIO from the detector's output line and in turn notify the USB driver of VBUS presence/disconnection using the power_supply framework. config IPA tristate "IPA support" depends on SPS Loading
drivers/platform/msm/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,4 @@ obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o obj-$(CONFIG_MSM_AVTIMER) += avtimer.o obj-$(CONFIG_SSM) += ssm.o obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o obj-$(CONFIG_QPNP_USB_DETECT) += qpnp-usbdetect.o
drivers/platform/msm/qpnp-usbdetect.c 0 → 100644 +126 −0 Original line number Diff line number Diff line /* Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/slab.h> #include <linux/of_platform.h> #include <linux/interrupt.h> #include <linux/power_supply.h> #include <linux/regulator/consumer.h> struct qpnp_usbdetect { struct platform_device *pdev; struct regulator *vin; struct power_supply *usb_psy; int vbus_det_irq; }; static irqreturn_t qpnp_usbdetect_vbus_irq(int irq, void *data) { struct qpnp_usbdetect *usb = data; int vbus; vbus = !!irq_read_line(irq); power_supply_set_present(usb->usb_psy, vbus); return IRQ_HANDLED; } static int qpnp_usbdetect_probe(struct platform_device *pdev) { struct qpnp_usbdetect *usb; struct power_supply *usb_psy; int rc; usb_psy = power_supply_get_by_name("usb"); if (!usb_psy) { dev_dbg(&pdev->dev, "USB power_supply not found, deferring probe\n"); return -EPROBE_DEFER; } usb = devm_kzalloc(&pdev->dev, sizeof(*usb), GFP_KERNEL); if (!usb) return -ENOMEM; usb->pdev = pdev; usb->usb_psy = usb_psy; usb->vin = devm_regulator_get(&pdev->dev, "vin"); if (IS_ERR(usb->vin)) { dev_err(&pdev->dev, "Failed to get VIN regulator: %ld\n", PTR_ERR(usb->vin)); return PTR_ERR(usb->vin); } rc = regulator_enable(usb->vin); if (rc) { dev_err(&pdev->dev, "Failed to enable VIN regulator: %d\n", rc); return rc; } usb->vbus_det_irq = platform_get_irq_byname(pdev, "vbus_det_irq"); if (usb->vbus_det_irq < 0) { regulator_disable(usb->vin); return usb->vbus_det_irq; } rc = devm_request_irq(&pdev->dev, usb->vbus_det_irq, qpnp_usbdetect_vbus_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "vbus_det_irq", usb); if (rc) { dev_err(&pdev->dev, "request for vbus_det_irq failed: %d\n", rc); regulator_disable(usb->vin); return rc; } enable_irq_wake(usb->vbus_det_irq); dev_set_drvdata(&pdev->dev, usb); return 0; } static int qpnp_usbdetect_remove(struct platform_device *pdev) { struct qpnp_usbdetect *usb = dev_get_drvdata(&pdev->dev); disable_irq_wake(usb->vbus_det_irq); disable_irq(usb->vbus_det_irq); regulator_disable(usb->vin); return 0; } static struct of_device_id of_match_table[] = { { .compatible = "qcom,qpnp-usbdetect", } }; static struct platform_driver qpnp_usbdetect_driver = { .driver = { .name = "qcom,qpnp-usbdetect", .of_match_table = of_match_table, }, .probe = qpnp_usbdetect_probe, .remove = qpnp_usbdetect_remove, }; module_driver(qpnp_usbdetect_driver, platform_driver_register, platform_driver_unregister); MODULE_DESCRIPTION("QPNP PMIC USB VBUS Detection driver"); MODULE_LICENSE("GPL v2");