aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorPaul Fertser <fercerpav@gmail.com>2009-11-04 16:24:59 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2009-11-15 19:32:09 -0500
commitc329795052aa339850a45fab649ab97a36905136 (patch)
tree96bc7769c35baaec5d87c0ab418e333b6983eeac /drivers/power
parent1282b35a1edf5f12ae58a2b16ae8615dfe0d9ecc (diff)
pcf50633: Query charger status directly
Current scheme is fragile and is likely to go off sync, especially on batfull->adapter charging automatic MBC transition. Query the status bit every time we need it instead. We need to export another function to query for USB presence because we can't read anything from PCF50633 (via I2C) inside irq context and that is needed by usb gadgets. Signed-off-by: Paul Fertser <fercerpav@gmail.com> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/pcf50633-charger.c50
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 47187337b96c..b915a008f587 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -29,9 +29,7 @@
29struct pcf50633_mbc { 29struct pcf50633_mbc {
30 struct pcf50633 *pcf; 30 struct pcf50633 *pcf;
31 31
32 int adapter_active;
33 int adapter_online; 32 int adapter_online;
34 int usb_active;
35 int usb_online; 33 int usb_online;
36 34
37 struct power_supply usb; 35 struct power_supply usb;
@@ -88,7 +86,7 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
88 pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); 86 pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
89 } 87 }
90 88
91 mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); 89 mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
92 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); 90 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
93 91
94 /* If chgmod == BATFULL, setting chgena has no effect. 92 /* If chgmod == BATFULL, setting chgena has no effect.
@@ -105,8 +103,6 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
105 PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); 103 PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
106 } 104 }
107 105
108 mbc->usb_active = charging_start;
109
110 power_supply_changed(&mbc->usb); 106 power_supply_changed(&mbc->usb);
111 107
112 return ret; 108 return ret;
@@ -117,20 +113,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf)
117{ 113{
118 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); 114 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
119 int status = 0; 115 int status = 0;
116 u8 chgmod;
117
118 if (!mbc)
119 return 0;
120
121 chgmod = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2)
122 & PCF50633_MBCS2_MBC_MASK;
120 123
121 if (mbc->usb_online) 124 if (mbc->usb_online)
122 status |= PCF50633_MBC_USB_ONLINE; 125 status |= PCF50633_MBC_USB_ONLINE;
123 if (mbc->usb_active) 126 if (chgmod == PCF50633_MBCS2_MBC_USB_PRE ||
127 chgmod == PCF50633_MBCS2_MBC_USB_PRE_WAIT ||
128 chgmod == PCF50633_MBCS2_MBC_USB_FAST ||
129 chgmod == PCF50633_MBCS2_MBC_USB_FAST_WAIT)
124 status |= PCF50633_MBC_USB_ACTIVE; 130 status |= PCF50633_MBC_USB_ACTIVE;
125 if (mbc->adapter_online) 131 if (mbc->adapter_online)
126 status |= PCF50633_MBC_ADAPTER_ONLINE; 132 status |= PCF50633_MBC_ADAPTER_ONLINE;
127 if (mbc->adapter_active) 133 if (chgmod == PCF50633_MBCS2_MBC_ADP_PRE ||
134 chgmod == PCF50633_MBCS2_MBC_ADP_PRE_WAIT ||
135 chgmod == PCF50633_MBCS2_MBC_ADP_FAST ||
136 chgmod == PCF50633_MBCS2_MBC_ADP_FAST_WAIT)
128 status |= PCF50633_MBC_ADAPTER_ACTIVE; 137 status |= PCF50633_MBC_ADAPTER_ACTIVE;
129 138
130 return status; 139 return status;
131} 140}
132EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); 141EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
133 142
143int pcf50633_mbc_get_usb_online_status(struct pcf50633 *pcf)
144{
145 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
146
147 if (!mbc)
148 return 0;
149
150 return mbc->usb_online;
151}
152EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status);
153
134static ssize_t 154static ssize_t
135show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) 155show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
136{ 156{
@@ -248,26 +268,14 @@ pcf50633_mbc_irq_handler(int irq, void *data)
248 mbc->usb_online = 1; 268 mbc->usb_online = 1;
249 } else if (irq == PCF50633_IRQ_USBREM) { 269 } else if (irq == PCF50633_IRQ_USBREM) {
250 mbc->usb_online = 0; 270 mbc->usb_online = 0;
251 mbc->usb_active = 0;
252 pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); 271 pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
253 } 272 }
254 273
255 /* Adapter */ 274 /* Adapter */
256 if (irq == PCF50633_IRQ_ADPINS) { 275 if (irq == PCF50633_IRQ_ADPINS)
257 mbc->adapter_online = 1; 276 mbc->adapter_online = 1;
258 mbc->adapter_active = 1; 277 else if (irq == PCF50633_IRQ_ADPREM)
259 } else if (irq == PCF50633_IRQ_ADPREM) {
260 mbc->adapter_online = 0; 278 mbc->adapter_online = 0;
261 mbc->adapter_active = 0;
262 }
263
264 if (irq == PCF50633_IRQ_BATFULL) {
265 mbc->usb_active = 0;
266 mbc->adapter_active = 0;
267 } else if (irq == PCF50633_IRQ_USBLIMON)
268 mbc->usb_active = 0;
269 else if (irq == PCF50633_IRQ_USBLIMOFF)
270 mbc->usb_active = 1;
271 279
272 power_supply_changed(&mbc->ac); 280 power_supply_changed(&mbc->ac);
273 power_supply_changed(&mbc->usb); 281 power_supply_changed(&mbc->usb);