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

Commit a5a4fbe8 authored by Lena Salman's avatar Lena Salman Committed by Gerrit - the friendly Code Review server
Browse files

drivers: usb: gadget: Add bus voting to hsic gadget



HSIC needs to vote for its bus via the bus scaling mechanism.
Otherwise, it might not be able to access the bus in some cases.
The problem was seen in concurrent scenarios of USB and HSIC,
when the USB cable was unplugged and USB went to LPM. In
such cases the SNOC bus needed PNOC bus voting, that
should have beem implemented by HSIC voting for PNOC bus.

Change-Id: I6ebec0162a07a95c303048816a88a147dc469e91
Signed-off-by: default avatarLena Salman <esalman@codeaurora.org>
parent dbd2b72e
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/usb/gadget.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/msm-bus.h>

#include <mach/msm_iomap.h>
#include <mach/rpm-regulator.h>
@@ -64,6 +65,8 @@ struct msm_hsic_per {
	struct workqueue_struct *wq;
	struct work_struct	suspend_w;
	struct msm_hsic_peripheral_platform_data *pdata;
	u32			bus_perf_client;
	struct msm_bus_scale_pdata	*bus_scale_table;
	enum usb_vdd_type	vdd_type;
	bool connected;
};
@@ -444,6 +447,12 @@ static int msm_hsic_suspend(struct msm_hsic_per *mhsic)
							mhsic->vdd_val[MAX]);
	if (ret < 0)
		dev_err(mhsic->dev, "unable to set vdd voltage for VDD MIN\n");
	if (mhsic->bus_perf_client) {
		ret = msm_bus_scale_client_update_request(
				mhsic->bus_perf_client, 0);
		if (ret)
			dev_err(mhsic->dev, "Failed to vote for bus scaling\n");
	}

	if (device_may_wakeup(mhsic->dev))
		enable_irq_wake(mhsic->irq);
@@ -469,6 +478,13 @@ static int msm_hsic_resume(struct msm_hsic_per *mhsic)

	wake_lock(&mhsic->wlock);

	if (mhsic->bus_perf_client) {
		ret = msm_bus_scale_client_update_request(
				mhsic->bus_perf_client, 1);
		if (ret)
			dev_err(mhsic->dev, "Failed to vote for bus scaling\n");
	}

	ret = regulator_set_voltage(mhsic->hsic_vdd, mhsic->vdd_val[MIN],
							mhsic->vdd_val[MAX]);
	if (ret < 0)
@@ -804,6 +820,19 @@ static int msm_hsic_probe(struct platform_device *pdev)
		goto deinit_vddcx;
	}

	mhsic->bus_scale_table = msm_bus_cl_get_pdata(pdev);
	if (!mhsic->bus_scale_table) {
		dev_err(&pdev->dev, "bus scaling is disabled\n");
	} else {
		mhsic->bus_perf_client =
			msm_bus_scale_register_client(mhsic->bus_scale_table);
		ret = msm_bus_scale_client_update_request(
						mhsic->bus_perf_client, 1);
		dev_debug(&pdev->dev, "bus scaling is enabled\n");
		if (ret)
			dev_err(mhsic->dev, "Failed to vote for bus scaling\n");
	}

	ret = udc_probe(&ci13xxx_msm_udc_hsic_driver, &pdev->dev, mhsic->regs);
	if (ret < 0) {
		dev_err(&pdev->dev, "udc_probe failed\n");
@@ -832,6 +861,8 @@ static int msm_hsic_probe(struct platform_device *pdev)
	return 0;
udc_remove:
	udc_remove();
	if (mhsic->bus_perf_client)
		msm_bus_scale_unregister_client(mhsic->bus_perf_client);
deinit_vddcx:
	msm_hsic_init_vdd(mhsic, 0);
deinit_clocks:
@@ -858,6 +889,8 @@ static int hsic_msm_remove(struct platform_device *pdev)
	msm_hsic_enable_clocks(pdev, mhsic, 0);
	wake_lock_destroy(&mhsic->wlock);
	destroy_workqueue(mhsic->wq);
	if (mhsic->bus_perf_client)
		msm_bus_scale_unregister_client(mhsic->bus_perf_client);
	udc_remove();
	iounmap(mhsic->regs);
	kfree(mhsic);