summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJun Li <r65092@freescale.com>2009-12-01 21:16:33 +0800
committerJustin Waters <justin.waters@timesys.com>2010-03-25 14:01:30 -0400
commit8ef14364cf09cb520ec60c5291f0186c1024ec42 (patch)
tree3b1ae8eb3061e7f3b278f7dc9f17b16d4d33f001 /arch
parent511ecffed290b7e87f734aaf33e8689b9bf497c9 (diff)
ENGR00117147-2 USB clock gating and PHY low power mode.
1. If there is no usb devices connectted or all connectted usb devices are in suspend state, usb host can suspend its whole bus, then put the PHY into low power mode and close all usb clocks. 2. close all usb clocks for usb device low power mode. (The patch is splitted 2 patches, this is FSL specific driver part.) Signed-off-by: Li Jun <r65092@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c7
-rw-r--r--arch/arm/mach-mx51/usb_dr.c38
-rw-r--r--arch/arm/mach-mx51/usb_h1.c19
-rw-r--r--arch/arm/plat-mxc/include/mach/arc_otg.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/fsl_usb.h7
-rw-r--r--arch/arm/plat-mxc/usb_common.c21
6 files changed, 81 insertions, 12 deletions
diff --git a/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c
index 8165e12d1356..7425d93b240b 100644
--- a/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c
+++ b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c
@@ -72,11 +72,10 @@
/* 0x92412 */
#define REG_MODE_0_ALL_MASK (GEN1_STBY_MASK |\
DIG_STBY_MASK | GEN2_STBY_MASK |\
- PLL_STBY_MASK | USB2_STBY_MASK)
+ PLL_STBY_MASK)
/* 0x92082 */
-#define REG_MODE_1_ALL_MASK (GEN3_STBY_MASK | CAM_STBY_MASK |\
- VIDEO_STBY_MASK | AUDIO_STBY_MASK |\
- SD_STBY_MASK)
+#define REG_MODE_1_ALL_MASK (CAM_STBY_MASK | VIDEO_STBY_MASK |\
+ AUDIO_STBY_MASK | SD_STBY_MASK)
/* CPU */
static struct regulator_consumer_supply sw1_consumers[] = {
diff --git a/arch/arm/mach-mx51/usb_dr.c b/arch/arm/mach-mx51/usb_dr.c
index 3bbc69b6d8e1..010ec2ac4d3e 100644
--- a/arch/arm/mach-mx51/usb_dr.c
+++ b/arch/arm/mach-mx51/usb_dr.c
@@ -23,6 +23,7 @@
static int usbotg_init_ext(struct platform_device *pdev);
static void usbotg_uninit_ext(struct fsl_usb2_platform_data *pdata);
static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable);
+static void usbotg_clock_gate(bool on);
/*
* platform data structs
@@ -37,6 +38,7 @@ static struct fsl_usb2_platform_data __maybe_unused dr_utmi_config = {
.power_budget = 500, /* 500 mA max power */
.gpio_usb_active = gpio_usbotg_hs_active,
.gpio_usb_inactive = gpio_usbotg_hs_inactive,
+ .usb_clock_for_pm = usbotg_clock_gate,
.wake_up_enable = _wake_up_enable,
.transceiver = "utmi",
};
@@ -155,6 +157,42 @@ static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
}
}
+static void usbotg_clock_gate(bool on)
+{
+ struct clk *usb_clk;
+
+ if (on) {
+ usb_clk = clk_get(NULL, "usb_ahb_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usb_phy_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+
+ /*derive clock from oscillator */
+ usb_clk = clk_get(NULL, "usb_utmi_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+ } else {
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usb_phy_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usb_ahb_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+ }
+}
+
static int __init usb_dr_init(void)
{
pr_debug("%s: \n", __func__);
diff --git a/arch/arm/mach-mx51/usb_h1.c b/arch/arm/mach-mx51/usb_h1.c
index fe9ac29017a0..6fa5f5e0b6e9 100644
--- a/arch/arm/mach-mx51/usb_h1.c
+++ b/arch/arm/mach-mx51/usb_h1.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <mach/arc_otg.h>
@@ -85,6 +86,23 @@ static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
USBCTRL &= ~UCTRL_H1WIE;
}
+static void usbotg_clock_gate(bool on)
+{
+ struct clk *usboh3_clk = clk_get(NULL, "usboh3_clk");
+ struct clk *usb_ahb_clk = clk_get(NULL, "usb_ahb_clk");
+
+ if (on) {
+ clk_enable(usb_ahb_clk);
+ clk_enable(usboh3_clk);
+ } else {
+ clk_disable(usboh3_clk);
+ clk_disable(usb_ahb_clk);
+ }
+
+ clk_put(usboh3_clk);
+ clk_put(usb_ahb_clk);
+}
+
static struct fsl_usb2_platform_data usbh1_config = {
.name = "Host 1",
.platform_init = fsl_usb_host_init,
@@ -95,6 +113,7 @@ static struct fsl_usb2_platform_data usbh1_config = {
.gpio_usb_active = gpio_usbh1_active,
.gpio_usb_inactive = gpio_usbh1_inactive,
.wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = usbotg_clock_gate,
.transceiver = "isp1504",
};
diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h
index 467ab1379e62..4dc2eeafe4a6 100644
--- a/arch/arm/plat-mxc/include/mach/arc_otg.h
+++ b/arch/arm/plat-mxc/include/mach/arc_otg.h
@@ -326,6 +326,7 @@
#define USB_UTMI_PHYCTRL_CHGRDETON (1 << 23) /* Charger Detector Power On Control */
#define USB_UTMI_PHYCTRL_OC_POL (1 << 9) /* OTG Polarity of Overcurrent */
#define USB_UTMI_PHYCTRL_OC_DIS (1 << 8) /* OTG Disable Overcurrent Event */
+#define USB_UH1_OC_DIS (1 << 5) /* UH1 Disable Overcurrent Event */
/* USB_PHY_CTRL_FUNC2*/
#define USB_UTMI_PHYCTRL2_PLLDIV_MASK 0x3
#define USB_UTMI_PHYCTRL2_PLLDIV_SHIFT 0
diff --git a/arch/arm/plat-mxc/include/mach/fsl_usb.h b/arch/arm/plat-mxc/include/mach/fsl_usb.h
index 2149d38c91c5..d1235fc337ff 100644
--- a/arch/arm/plat-mxc/include/mach/fsl_usb.h
+++ b/arch/arm/plat-mxc/include/mach/fsl_usb.h
@@ -56,7 +56,12 @@ fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on)
/* Port Power Control */
if (temp & HCSPARAMS_PPC) {
temp = readl(pdata->regs + FSL_SOC_USB_PORTSC1);
- writel(temp | PORT_POWER, pdata->regs + FSL_SOC_USB_PORTSC1);
+ if (on)
+ temp |= PORT_POWER;
+ else
+ temp &= ~PORT_POWER;
+
+ writel(temp, pdata->regs + FSL_SOC_USB_PORTSC1);
}
if (pdata->xcvr_ops && pdata->xcvr_ops->set_vbus_power)
diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c
index 6edaf43ba11c..c6551a5c26af 100644
--- a/arch/arm/plat-mxc/usb_common.c
+++ b/arch/arm/plat-mxc/usb_common.c
@@ -291,9 +291,10 @@ static void usbh1_set_ulpi_xcvr(void)
/* select ULPI PHY PTS=2 */
UH1_PORTSC1 = (UH1_PORTSC1 & ~PORTSC_PTS_MASK) | PORTSC_PTS_ULPI;
- USBCTRL |= UCTRL_H1WIE; /* HOST1 wakeup intr enable */
- USBCTRL |= UCTRL_H1UIE; /* Host1 ULPI interrupt enable */
- USBCTRL &= ~UCTRL_H1PM; /* HOST1 power mask */
+ USBCTRL &= ~UCTRL_H1WIE; /* HOST1 wakeup intr disable */
+ USBCTRL &= ~UCTRL_H1UIE; /* Host1 ULPI interrupt disable */
+ USBCTRL |= UCTRL_H1PM; /* HOST1 power mask */
+ USB_PHY_CTR_FUNC |= USB_UH1_OC_DIS; /* OC is not used */
/* Interrupt Threshold Control:Immediate (no threshold) */
UH1_USBCMD &= UCMD_ITC_NO_THRESHOLD;
@@ -541,6 +542,7 @@ void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata)
clk_disable(usb_clk);
clk_put(usb_clk);
}
+ clk_disable(usb_ahb_clk);
}
EXPORT_SYMBOL(fsl_usb_host_uninit);
@@ -671,10 +673,15 @@ static void otg_set_utmi_xcvr(void)
while ((UOG_USBCMD) & (UCMD_RESET)) ;
if (cpu_is_mx51()) {
- /* OTG Polarity of Overcurrent is Low active */
- USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_OC_POL;
- /* Enable OTG Overcurrent Event */
- USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_OC_DIS;
+ if (machine_is_mx51_3ds()) {
+ /* OTG Polarity of Overcurrent is Low active */
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_OC_POL;
+ /* Enable OTG Overcurrent Event */
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_OC_DIS;
+ } else {
+ /* BBG is not using OC */
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_OC_DIS;
+ }
} else if (cpu_is_mx25()) {
USBCTRL |= UCTRL_OCPOL;
USBCTRL &= ~UCTRL_PP;