Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5557eaa6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: Add USB ID GPIO for APQ8009"

parents 6f42d0be 3629042a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@ Optional Properties:
	value is 0 or device mode if 1.
- qcom,disable-device-mode: If present then don't treat GPIO high as Vbus high.
	And only notify host mode similar to ID line.
-qcom,id-det-gpio: If present, specifies a gpio that is tied to ID, switch
	to host mode if value is 0.
-qcom,dpdm_switch_gpio: If present, specifies a gpio that drives a switch
	which routes DPDM lines to different ports.

Example:

+30 −1
Original line number Diff line number Diff line
@@ -30,6 +30,19 @@
	status = "disabled";
};

&pm8916_gpios {
	gpio@c200 {
		qcom,mode = <1>;
		qcom,output-type = <0>;
		qcom,src-sel = <0>;
		qcom,pull = <5>;
		qcom,master-en = <1>;
		qcom,vin-sel = <1>;
		qcom,out-strength = <3>;
		status = "ok";
	};
};

&msm_gpio {
	hsuart_active: default {
		mux {
@@ -69,6 +82,19 @@
			bias-disable;
		};
	};

	usb_id_detect: usb_id_detect {
		mux {
			pins = "gpio110";
			function = "gpio";
		};

		config {
			pins = "gpio110";
			drive-strength = <2>;
			bias-pull-up;
		};
	};
};

&soc {
@@ -197,9 +223,12 @@
		interrupt-parent = <&msm_gpio>;
		interrupts = <97 0>;
		interrupt-names = "vbus_det_irq";
		pinctrl-names = "usb_vbus_detect";
		pinctrl-names = "usb_vbus_detect", "usb_id_detect";
		pinctrl-0 = <&usb_vbus_detect>;
		pinctrl-1 = <&usb_id_detect>;
		qcom,gpio-mode-sel = <&msm_gpio 97 0>;
		qcom,id-det-gpio = <&msm_gpio 110 0>;
		qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
	};
};

+30 −1
Original line number Diff line number Diff line
@@ -30,6 +30,19 @@
	status = "disabled";
};

&pm8916_gpios {
	gpio@c200 {
		qcom,mode = <1>;
		qcom,output-type = <0>;
		qcom,src-sel = <0>;
		qcom,pull = <5>;
		qcom,master-en = <1>;
		qcom,vin-sel = <1>;
		qcom,out-strength = <3>;
		status = "ok";
	};
};

&msm_gpio {
	hsuart_active: default {
		mux {
@@ -69,6 +82,19 @@
			bias-disable;
		};
	};

	usb_id_detect: usb_id_detect {
		mux {
			pins = "gpio110";
			function = "gpio";
		};

		config {
			pins = "gpio110";
			drive-strength = <2>;
			bias-pull-up;
		};
	};
};

&soc {
@@ -175,9 +201,12 @@
		interrupt-parent = <&msm_gpio>;
		interrupts = <97 0>;
		interrupt-names = "vbus_det_irq";
		pinctrl-names = "usb_vbus_detect";
		pinctrl-names = "usb_vbus_detect", "usb_id_detect";
		pinctrl-0 = <&usb_vbus_detect>;
		pinctrl-1 = <&usb_id_detect>;
		qcom,gpio-mode-sel = <&msm_gpio 97 0>;
		qcom,id-det-gpio = <&msm_gpio 110 0>;
		qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
	};
};

+89 −4
Original line number Diff line number Diff line
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, 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
@@ -37,8 +37,15 @@ struct gpio_usbdetect {
	struct regulator	*vdd33;
	struct regulator	*vdd12;
	int			gpio_usbdetect;

	int			id;
	int			id_det_gpio;
	int			id_det_irq;

	bool			notify_host_mode;
	bool			disable_device_mode;

	int			dpdm_switch_gpio;
};

static int gpio_enable_ldos(struct gpio_usbdetect *usb, int on)
@@ -154,15 +161,28 @@ disable_vin:
	return ret;
}

static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data)
static irqreturn_t gpio_usbdetect_irq(int irq, void *data)
{
	struct gpio_usbdetect *usb = data;

	if (gpio_is_valid(usb->id_det_gpio)) {
		usb->id = gpio_get_value(usb->id_det_gpio);
		if (usb->id) {
			dev_dbg(&usb->pdev->dev, "ID\n");
			usb->vbus = gpio_get_value(usb->gpio_usbdetect);
			goto queue_chg_work;
		}
		dev_dbg(&usb->pdev->dev, "!ID\n");
		schedule_delayed_work(&usb->chg_work, 0);
		return IRQ_HANDLED;
	}

	if (gpio_is_valid(usb->gpio_usbdetect))
		usb->vbus = gpio_get_value(usb->gpio_usbdetect);
	else
		usb->vbus = !!irq_read_line(irq);

queue_chg_work:
	pm_wakeup_event(&usb->pdev->dev, WAKEUP_SRC_TIMEOUT_MS);
	if (!usb->vbus)
		schedule_delayed_work(&usb->chg_work, 0);
@@ -178,6 +198,37 @@ static void gpio_usbdetect_chg_work(struct work_struct *w)
	struct gpio_usbdetect *usb = container_of(w, struct gpio_usbdetect,
							chg_work.work);

	if (gpio_is_valid(usb->id_det_gpio)) {
		dev_dbg(&usb->pdev->dev, "ID:%d VBUS:%d\n",
						usb->id, usb->vbus);
		if (!usb->id) {
			power_supply_set_supply_type(usb->usb_psy,
					POWER_SUPPLY_TYPE_UNKNOWN);
			power_supply_set_present(usb->usb_psy, 0);
			power_supply_set_usb_otg(usb->usb_psy, 1);
			if (gpio_is_valid(usb->dpdm_switch_gpio))
				gpio_set_value(usb->dpdm_switch_gpio, 1);

			return;
		}

		power_supply_set_usb_otg(usb->usb_psy, 0);
		if (gpio_is_valid(usb->dpdm_switch_gpio))
			gpio_set_value(usb->dpdm_switch_gpio, 0);

		if (usb->vbus) {
			power_supply_set_supply_type(usb->usb_psy,
						POWER_SUPPLY_TYPE_USB);
			power_supply_set_present(usb->usb_psy, usb->vbus);
		} else {
			power_supply_set_supply_type(usb->usb_psy,
					POWER_SUPPLY_TYPE_UNKNOWN);
			power_supply_set_present(usb->usb_psy, usb->vbus);
		}

		return;
	}

	if (usb->vbus) {
		if (usb->notify_host_mode)
			power_supply_set_usb_otg(usb->usb_psy, 0);
@@ -254,7 +305,7 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
	}

	rc = devm_request_irq(&pdev->dev, usb->vbus_det_irq,
			      gpio_usbdetect_vbus_irq,
			      gpio_usbdetect_irq,
			      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
			      "vbus_det_irq", usb);
	if (rc) {
@@ -263,14 +314,48 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
		goto disable_ldo;
	}

	usb->id_det_gpio = of_get_named_gpio(pdev->dev.of_node,
						"qcom,id-det-gpio", 0);
	if (gpio_is_valid(usb->id_det_gpio)) {
		rc = devm_gpio_request(&pdev->dev, usb->id_det_gpio,
					"GPIO_ID_DET");
		if (rc) {
			dev_err(&pdev->dev, "gpio req failed for gpio_%d\n",
							usb->id_det_gpio);
			goto disable_ldo;
		}

		usb->id_det_irq = gpio_to_irq(usb->id_det_gpio);
		if (usb->id_det_irq < 0) {
			dev_err(&pdev->dev, "get id_det_irq failed\n");
			goto disable_ldo;
		}
		rc = devm_request_irq(&pdev->dev, usb->id_det_irq,
					gpio_usbdetect_irq,
					IRQF_TRIGGER_RISING |
					IRQF_TRIGGER_FALLING, "id_det_irq",
					usb);
		if (rc) {
			dev_err(&pdev->dev, "request for id_det_irq failed:%d\n",
					rc);
			goto disable_ldo;
		}
	}

	usb->dpdm_switch_gpio = of_get_named_gpio(pdev->dev.of_node,
						"qcom,dpdm_switch_gpio", 0);
	dev_dbg(&pdev->dev, "is dpdm_switch_gpio valid:%d\n",
					gpio_is_valid(usb->dpdm_switch_gpio));

	device_init_wakeup(&pdev->dev, 1);

	enable_irq_wake(usb->vbus_det_irq);
	enable_irq_wake(usb->id_det_irq);
	dev_set_drvdata(&pdev->dev, usb);

	/* Read and report initial VBUS state */
	local_irq_save(flags);
	gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb);
	gpio_usbdetect_irq(usb->vbus_det_irq, usb);
	local_irq_restore(flags);

	return 0;