drivers: usb: otg: Change the PHY control to PMIC control for the power consumption.
Change-Id: Ib37951810c33f96832b12d188106d87ebb481af2 Change-Id: I91f5fb5ed8f6c1795af5c923ec649f03f63a3487 Reviewed-on: http://mcrd1-5.corpnet.asus/code-review/master/67938 Reviewed-by: Yi-Hsin Hung <Yi-Hsin_Hung@asus.com> Tested-by: Yi-Hsin Hung <Yi-Hsin_Hung@asus.com> Reviewed-by: Leslie Yu <Leslie_Yu@asus.com>
This commit is contained in:
committed by
Iliyan Malchev
parent
ad31fba73d
commit
6a413e06cb
@@ -961,9 +961,9 @@ static int phy_init_seq[] = {
|
|||||||
|
|
||||||
static struct msm_otg_platform_data msm_otg_pdata = {
|
static struct msm_otg_platform_data msm_otg_pdata = {
|
||||||
.mode = USB_OTG,
|
.mode = USB_OTG,
|
||||||
.otg_control = OTG_PHY_CONTROL,
|
.otg_control = OTG_PMIC_CONTROL,
|
||||||
.phy_type = SNPS_28NM_INTEGRATED_PHY,
|
.phy_type = SNPS_28NM_INTEGRATED_PHY,
|
||||||
.pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
|
// .pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
|
||||||
.power_budget = 750,
|
.power_budget = 750,
|
||||||
.bus_scale_table = &usb_bus_scale_pdata,
|
.bus_scale_table = &usb_bus_scale_pdata,
|
||||||
.phy_init_seq = phy_init_seq,
|
.phy_init_seq = phy_init_seq,
|
||||||
|
|||||||
@@ -50,6 +50,9 @@
|
|||||||
#include <mach/msm_xo.h>
|
#include <mach/msm_xo.h>
|
||||||
#include <mach/msm_bus.h>
|
#include <mach/msm_bus.h>
|
||||||
#include <mach/rpm-regulator.h>
|
#include <mach/rpm-regulator.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
#define MSM_USB_BASE (motg->regs)
|
#define MSM_USB_BASE (motg->regs)
|
||||||
#define DRIVER_NAME "msm_otg"
|
#define DRIVER_NAME "msm_otg"
|
||||||
@@ -84,6 +87,12 @@ static struct regulator *mhl_usb_hs_switch;
|
|||||||
static struct power_supply *psy;
|
static struct power_supply *psy;
|
||||||
|
|
||||||
static bool aca_id_turned_on;
|
static bool aca_id_turned_on;
|
||||||
|
static struct workqueue_struct *msm_otg_acok_wq;
|
||||||
|
static int pm_suspend_acok_status = 0;
|
||||||
|
|
||||||
|
/* APQ8064 GPIO pin definition */
|
||||||
|
#define APQ_AP_ACOK 23
|
||||||
|
|
||||||
static inline bool aca_enabled(void)
|
static inline bool aca_enabled(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USB_MSM_ACA
|
#ifdef CONFIG_USB_MSM_ACA
|
||||||
@@ -2183,7 +2192,7 @@ static void msm_chg_detect_work(struct work_struct *w)
|
|||||||
*/
|
*/
|
||||||
udelay(100);
|
udelay(100);
|
||||||
msm_chg_enable_aca_intr(motg);
|
msm_chg_enable_aca_intr(motg);
|
||||||
dev_dbg(phy->dev, "chg_type = %s\n",
|
dev_info(phy->dev, "chg_type = %s\n",
|
||||||
chg_to_string(motg->chg_type));
|
chg_to_string(motg->chg_type));
|
||||||
queue_work(system_nrt_wq, &motg->sm_work);
|
queue_work(system_nrt_wq, &motg->sm_work);
|
||||||
return;
|
return;
|
||||||
@@ -2235,6 +2244,10 @@ static void msm_otg_init_sm(struct msm_otg *motg)
|
|||||||
set_bit(ID, &motg->inputs);
|
set_bit(ID, &motg->inputs);
|
||||||
else
|
else
|
||||||
clear_bit(ID, &motg->inputs);
|
clear_bit(ID, &motg->inputs);
|
||||||
|
} else {
|
||||||
|
// set to peripheral
|
||||||
|
printk("[usb_otg] switch to peripheral mode by default (boot)\r\n");
|
||||||
|
set_bit(ID, &motg->inputs);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* VBUS initial state is reported after PMIC
|
* VBUS initial state is reported after PMIC
|
||||||
@@ -3042,6 +3055,76 @@ static void msm_otg_set_vbus_state(int online)
|
|||||||
queue_work(system_nrt_wq, &motg->sm_work);
|
queue_work(system_nrt_wq, &motg->sm_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void (*notify_vbus_state_func_ptr)(int);
|
||||||
|
static void acok_irq_work_function(struct work_struct *work)
|
||||||
|
{
|
||||||
|
int gpio = !gpio_get_value(APQ_AP_ACOK);
|
||||||
|
|
||||||
|
if (notify_vbus_state_func_ptr) {
|
||||||
|
pr_info("notifying plugin\n");
|
||||||
|
(*notify_vbus_state_func_ptr) (gpio);
|
||||||
|
} else {
|
||||||
|
pr_info("unable to notify plugin\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_otg_register_vbus_sn(void (*callback)(int))
|
||||||
|
{
|
||||||
|
pr_debug("%p\n", callback);
|
||||||
|
notify_vbus_state_func_ptr = callback;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msm_otg_unregister_vbus_sn(void (*callback)(int))
|
||||||
|
{
|
||||||
|
pr_debug("%p\n", callback);
|
||||||
|
notify_vbus_state_func_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t msm_otg_acok_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct msm_otg *motg = dev_id;
|
||||||
|
|
||||||
|
queue_delayed_work(msm_otg_acok_wq, &motg->acok_irq_work, 0.6*HZ);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msm_otg_acok_init(struct msm_otg *motg)
|
||||||
|
{
|
||||||
|
int err = 0 ;
|
||||||
|
unsigned gpio = APQ_AP_ACOK;
|
||||||
|
unsigned irq_num = gpio_to_irq(gpio);
|
||||||
|
|
||||||
|
err = gpio_request(gpio, "msm_otg_ap_acok");
|
||||||
|
if (err) {
|
||||||
|
printk("gpio %d request failed \n", gpio);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gpio_direction_input(gpio);
|
||||||
|
if (err) {
|
||||||
|
printk("gpio %d unavaliable for input \n", gpio);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = request_irq(irq_num, msm_otg_acok_irq, IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING|IRQF_SHARED,
|
||||||
|
"msm_otg_ap_acok", motg);
|
||||||
|
if (err < 0) {
|
||||||
|
printk("%s irq %d request failed \n","msm_otg_ap_acok", irq_num);
|
||||||
|
}
|
||||||
|
printk("%s: GPIO pin irq %d requested ok, msm_otg_ACOK = %s\n", __func__, irq_num, gpio_get_value(gpio)? "H":"L");
|
||||||
|
|
||||||
|
enable_irq_wake(irq_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msm_otg_acok_free(struct msm_otg *motg)
|
||||||
|
{
|
||||||
|
unsigned gpio = APQ_AP_ACOK;
|
||||||
|
unsigned irq_num = gpio_to_irq(gpio);
|
||||||
|
|
||||||
|
disable_irq_wake(irq_num);
|
||||||
|
free_irq(irq_num, motg);
|
||||||
|
}
|
||||||
|
|
||||||
static void msm_pmic_id_status_w(struct work_struct *w)
|
static void msm_pmic_id_status_w(struct work_struct *w)
|
||||||
{
|
{
|
||||||
struct msm_otg *motg = container_of(w, struct msm_otg,
|
struct msm_otg *motg = container_of(w, struct msm_otg,
|
||||||
@@ -3768,9 +3851,9 @@ static int __init msm_otg_probe(struct platform_device *pdev)
|
|||||||
goto remove_phy;
|
goto remove_phy;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = -ENODEV;
|
//ret = -ENODEV;
|
||||||
dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
|
dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
|
||||||
goto remove_phy;
|
//goto remove_phy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3780,20 +3863,23 @@ static int __init msm_otg_probe(struct platform_device *pdev)
|
|||||||
device_init_wakeup(&pdev->dev, 1);
|
device_init_wakeup(&pdev->dev, 1);
|
||||||
motg->mA_port = IUNIT;
|
motg->mA_port = IUNIT;
|
||||||
|
|
||||||
|
msm_otg_acok_init(motg);
|
||||||
|
msm_otg_acok_wq = create_singlethread_workqueue("msm_otg_acok_wq");
|
||||||
|
INIT_DELAYED_WORK_DEFERRABLE(&motg->acok_irq_work, acok_irq_work_function);
|
||||||
|
|
||||||
ret = msm_otg_debugfs_init(motg);
|
ret = msm_otg_debugfs_init(motg);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_dbg(&pdev->dev, "mode debugfs file is"
|
dev_dbg(&pdev->dev, "mode debugfs file is"
|
||||||
"not available\n");
|
"not available\n");
|
||||||
|
|
||||||
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
|
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
|
||||||
pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
|
msm_otg_register_vbus_sn(&msm_otg_set_vbus_state);
|
||||||
|
|
||||||
if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
|
if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
|
||||||
if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
|
if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
|
||||||
(!(motg->pdata->mode == USB_OTG) ||
|
|
||||||
motg->pdata->pmic_id_irq))
|
|
||||||
motg->caps = ALLOW_PHY_POWER_COLLAPSE |
|
motg->caps = ALLOW_PHY_POWER_COLLAPSE |
|
||||||
ALLOW_PHY_RETENTION;
|
ALLOW_PHY_RETENTION;
|
||||||
|
}
|
||||||
|
|
||||||
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
|
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
|
||||||
motg->caps = ALLOW_PHY_RETENTION;
|
motg->caps = ALLOW_PHY_RETENTION;
|
||||||
@@ -3816,6 +3902,8 @@ static int __init msm_otg_probe(struct platform_device *pdev)
|
|||||||
debug_bus_voting_enabled = true;
|
debug_bus_voting_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queue_delayed_work(msm_otg_acok_wq, &motg->acok_irq_work, 0.5*HZ);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
remove_phy:
|
remove_phy:
|
||||||
@@ -3872,7 +3960,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
|
|||||||
if (pdev->dev.of_node)
|
if (pdev->dev.of_node)
|
||||||
msm_otg_setup_devices(pdev, motg->pdata->mode, false);
|
msm_otg_setup_devices(pdev, motg->pdata->mode, false);
|
||||||
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
|
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
|
||||||
pm8921_charger_unregister_vbus_sn(0);
|
msm_otg_unregister_vbus_sn(0);
|
||||||
msm_otg_mhl_register_callback(motg, NULL);
|
msm_otg_mhl_register_callback(motg, NULL);
|
||||||
msm_otg_debugfs_cleanup();
|
msm_otg_debugfs_cleanup();
|
||||||
cancel_delayed_work_sync(&motg->chg_work);
|
cancel_delayed_work_sync(&motg->chg_work);
|
||||||
@@ -3886,6 +3974,8 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
|
|||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
wake_lock_destroy(&motg->wlock);
|
wake_lock_destroy(&motg->wlock);
|
||||||
|
|
||||||
|
msm_otg_acok_free(motg);
|
||||||
|
|
||||||
msm_hsusb_mhl_switch_enable(motg, 0);
|
msm_hsusb_mhl_switch_enable(motg, 0);
|
||||||
if (motg->pdata->pmic_id_irq)
|
if (motg->pdata->pmic_id_irq)
|
||||||
free_irq(motg->pdata->pmic_id_irq, motg);
|
free_irq(motg->pdata->pmic_id_irq, motg);
|
||||||
@@ -3985,6 +4075,8 @@ static int msm_otg_pm_suspend(struct device *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
atomic_set(&motg->pm_suspended, 0);
|
atomic_set(&motg->pm_suspended, 0);
|
||||||
|
|
||||||
|
pm_suspend_acok_status = !gpio_get_value(APQ_AP_ACOK);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3992,6 +4084,7 @@ static int msm_otg_pm_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct msm_otg *motg = dev_get_drvdata(dev);
|
struct msm_otg *motg = dev_get_drvdata(dev);
|
||||||
|
int ac_gpio;
|
||||||
|
|
||||||
dev_dbg(dev, "OTG PM resume\n");
|
dev_dbg(dev, "OTG PM resume\n");
|
||||||
|
|
||||||
@@ -4011,6 +4104,10 @@ static int msm_otg_pm_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ac_gpio = !gpio_get_value(APQ_AP_ACOK);
|
||||||
|
if (pm_suspend_acok_status != ac_gpio)
|
||||||
|
acok_irq_work_function(NULL);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ struct msm_otg {
|
|||||||
u8 active_tmout;
|
u8 active_tmout;
|
||||||
struct hrtimer timer;
|
struct hrtimer timer;
|
||||||
enum usb_vdd_type vdd_type;
|
enum usb_vdd_type vdd_type;
|
||||||
|
struct delayed_work acok_irq_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_hsic_host_platform_data {
|
struct msm_hsic_host_platform_data {
|
||||||
|
|||||||
Reference in New Issue
Block a user