diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch new file mode 100644 index 0000000000..db3481b87b --- /dev/null +++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch | |||
@@ -0,0 +1,181 @@ | |||
1 | From 60e7ce93befe795357db05001fe4caab522a421d Mon Sep 17 00:00:00 2001 | ||
2 | From: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:57 -0700 | ||
4 | Subject: [PATCH] USB: TWL: disable VUSB regulators when cable unplugged | ||
5 | |||
6 | This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 | ||
7 | when the USB cable is unplugged to reduce power consumption. | ||
8 | Added a depencency from twl4030 usb driver to TWL_REGULATOR. | ||
9 | |||
10 | Signed-off-by: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
11 | Signed-off-by: Kalle Jokiniemi <kalle.jokiniemi-sMOQStClEysAvxtiuMwx3w@public.gmane.org> | ||
12 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
13 | --- | ||
14 | drivers/usb/otg/Kconfig | 2 +- | ||
15 | drivers/usb/otg/twl4030-usb.c | 73 ++++++++++++++++++++++++++++++++++++----- | ||
16 | 2 files changed, 65 insertions(+), 10 deletions(-) | ||
17 | |||
18 | diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig | ||
19 | index ee55b44..5790a5b 100644 | ||
20 | --- a/drivers/usb/otg/Kconfig | ||
21 | +++ b/drivers/usb/otg/Kconfig | ||
22 | @@ -43,7 +43,7 @@ config ISP1301_OMAP | ||
23 | |||
24 | config TWL4030_USB | ||
25 | tristate "TWL4030 USB Transceiver Driver" | ||
26 | - depends on TWL4030_CORE | ||
27 | + depends on TWL4030_CORE && REGULATOR_TWL4030 | ||
28 | select USB_OTG_UTILS | ||
29 | help | ||
30 | Enable this to support the USB OTG transceiver on TWL4030 | ||
31 | diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c | ||
32 | index 416e441..d9478d0 100644 | ||
33 | --- a/drivers/usb/otg/twl4030-usb.c | ||
34 | +++ b/drivers/usb/otg/twl4030-usb.c | ||
35 | @@ -34,6 +34,8 @@ | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/usb/otg.h> | ||
38 | #include <linux/i2c/twl4030.h> | ||
39 | +#include <linux/regulator/consumer.h> | ||
40 | +#include <linux/err.h> | ||
41 | |||
42 | |||
43 | /* Register defines */ | ||
44 | @@ -246,6 +248,11 @@ struct twl4030_usb { | ||
45 | struct otg_transceiver otg; | ||
46 | struct device *dev; | ||
47 | |||
48 | + /* TWL4030 internal USB regulator supplies */ | ||
49 | + struct regulator *usb1v5; | ||
50 | + struct regulator *usb1v8; | ||
51 | + struct regulator *usb3v1; | ||
52 | + | ||
53 | /* for vbus reporting with irqs disabled */ | ||
54 | spinlock_t lock; | ||
55 | |||
56 | @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) | ||
57 | |||
58 | pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); | ||
59 | if (on) { | ||
60 | + regulator_enable(twl->usb3v1); | ||
61 | + regulator_enable(twl->usb1v8); | ||
62 | + /* | ||
63 | + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP | ||
64 | + * in twl4030) resets the VUSB_DEDICATED2 register. This reset | ||
65 | + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to | ||
66 | + * SLEEP. We work around this by clearing the bit after usv3v1 | ||
67 | + * is re-activated. This ensures that VUSB3V1 is really active. | ||
68 | + */ | ||
69 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, | ||
70 | + VUSB_DEDICATED2); | ||
71 | + regulator_enable(twl->usb1v5); | ||
72 | pwr &= ~PHY_PWR_PHYPWD; | ||
73 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
74 | twl4030_usb_write(twl, PHY_CLK_CTRL, | ||
75 | @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) | ||
76 | } else { | ||
77 | pwr |= PHY_PWR_PHYPWD; | ||
78 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
79 | + regulator_disable(twl->usb1v5); | ||
80 | + regulator_disable(twl->usb1v8); | ||
81 | + regulator_disable(twl->usb3v1); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) | ||
86 | twl->asleep = 0; | ||
87 | } | ||
88 | |||
89 | -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
90 | +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
91 | { | ||
92 | /* Enable writing to power configuration registers */ | ||
93 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | ||
94 | @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
95 | /* input to VUSB3V1 LDO is from VBAT, not VBUS */ | ||
96 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); | ||
97 | |||
98 | - /* turn on 3.1V regulator */ | ||
99 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); | ||
100 | + /* Initialize 3.1V regulator */ | ||
101 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); | ||
102 | + | ||
103 | + twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); | ||
104 | + if (IS_ERR(twl->usb3v1)) | ||
105 | + return -ENODEV; | ||
106 | + | ||
107 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); | ||
108 | |||
109 | - /* turn on 1.5V regulator */ | ||
110 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); | ||
111 | + /* Initialize 1.5V regulator */ | ||
112 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); | ||
113 | + | ||
114 | + twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); | ||
115 | + if (IS_ERR(twl->usb1v5)) | ||
116 | + goto fail1; | ||
117 | + | ||
118 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); | ||
119 | |||
120 | - /* turn on 1.8V regulator */ | ||
121 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); | ||
122 | + /* Initialize 1.8V regulator */ | ||
123 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); | ||
124 | + | ||
125 | + twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); | ||
126 | + if (IS_ERR(twl->usb1v8)) | ||
127 | + goto fail2; | ||
128 | + | ||
129 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | ||
130 | |||
131 | /* disable access to power configuration registers */ | ||
132 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | ||
133 | + | ||
134 | + return 0; | ||
135 | + | ||
136 | +fail2: | ||
137 | + regulator_put(twl->usb1v5); | ||
138 | + twl->usb1v5 = NULL; | ||
139 | +fail1: | ||
140 | + regulator_put(twl->usb3v1); | ||
141 | + twl->usb3v1 = NULL; | ||
142 | + return -ENODEV; | ||
143 | } | ||
144 | |||
145 | static ssize_t twl4030_usb_vbus_show(struct device *dev, | ||
146 | @@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) | ||
147 | { | ||
148 | struct twl4030_usb_data *pdata = pdev->dev.platform_data; | ||
149 | struct twl4030_usb *twl; | ||
150 | - int status; | ||
151 | + int status, err; | ||
152 | |||
153 | if (!pdata) { | ||
154 | dev_dbg(&pdev->dev, "platform_data not available\n"); | ||
155 | @@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) | ||
156 | /* init spinlock for workqueue */ | ||
157 | spin_lock_init(&twl->lock); | ||
158 | |||
159 | - twl4030_usb_ldo_init(twl); | ||
160 | + err = twl4030_usb_ldo_init(twl); | ||
161 | + if (err) { | ||
162 | + dev_err(&pdev->dev, "ldo init failed\n"); | ||
163 | + kfree(twl); | ||
164 | + return err; | ||
165 | + } | ||
166 | otg_set_transceiver(&twl->otg); | ||
167 | |||
168 | platform_set_drvdata(pdev, twl); | ||
169 | @@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) | ||
170 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | ||
171 | |||
172 | twl4030_phy_power(twl, 0); | ||
173 | + regulator_put(twl->usb1v5); | ||
174 | + regulator_put(twl->usb1v8); | ||
175 | + regulator_put(twl->usb3v1); | ||
176 | |||
177 | kfree(twl); | ||
178 | |||
179 | -- | ||
180 | 1.6.0.4 | ||
181 | |||