diff options
-rw-r--r-- | drivers/power/pcf50633-charger.c | 78 | ||||
-rw-r--r-- | include/linux/mfd/pcf50633/core.h | 7 |
2 files changed, 80 insertions, 5 deletions
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 48e92c020f4b..21b6e64e7805 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c | |||
@@ -48,16 +48,21 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
48 | u8 bits; | 48 | u8 bits; |
49 | int charging_start = 1; | 49 | int charging_start = 1; |
50 | u8 mbcs2, chgmod; | 50 | u8 mbcs2, chgmod; |
51 | unsigned int mbcc5; | ||
51 | 52 | ||
52 | if (ma >= 1000) | 53 | if (ma >= 1000) { |
53 | bits = PCF50633_MBCC7_USB_1000mA; | 54 | bits = PCF50633_MBCC7_USB_1000mA; |
54 | else if (ma >= 500) | 55 | ma = 1000; |
56 | } else if (ma >= 500) { | ||
55 | bits = PCF50633_MBCC7_USB_500mA; | 57 | bits = PCF50633_MBCC7_USB_500mA; |
56 | else if (ma >= 100) | 58 | ma = 500; |
59 | } else if (ma >= 100) { | ||
57 | bits = PCF50633_MBCC7_USB_100mA; | 60 | bits = PCF50633_MBCC7_USB_100mA; |
58 | else { | 61 | ma = 100; |
62 | } else { | ||
59 | bits = PCF50633_MBCC7_USB_SUSPEND; | 63 | bits = PCF50633_MBCC7_USB_SUSPEND; |
60 | charging_start = 0; | 64 | charging_start = 0; |
65 | ma = 0; | ||
61 | } | 66 | } |
62 | 67 | ||
63 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, | 68 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, |
@@ -67,7 +72,24 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
67 | else | 72 | else |
68 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); | 73 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); |
69 | 74 | ||
70 | /* Manual charging start */ | 75 | /* |
76 | * We limit the charging current to be the USB current limit. | ||
77 | * The reason is that on pcf50633, when it enters PMU Standby mode, | ||
78 | * which it does when the device goes "off", the USB current limit | ||
79 | * reverts to the variant default. In at least one common case, that | ||
80 | * default is 500mA. By setting the charging current to be the same | ||
81 | * as the USB limit we set here before PMU standby, we enforce it only | ||
82 | * using the correct amount of current even when the USB current limit | ||
83 | * gets reset to the wrong thing | ||
84 | */ | ||
85 | |||
86 | if (mbc->pcf->pdata->charger_reference_current_ma) { | ||
87 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
88 | if (mbcc5 > 255) | ||
89 | mbcc5 = 255; | ||
90 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
91 | } | ||
92 | |||
71 | mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | 93 | mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); |
72 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); | 94 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); |
73 | 95 | ||
@@ -157,9 +179,55 @@ static ssize_t set_usblim(struct device *dev, | |||
157 | 179 | ||
158 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); | 180 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); |
159 | 181 | ||
182 | static ssize_t | ||
183 | show_chglim(struct device *dev, struct device_attribute *attr, char *buf) | ||
184 | { | ||
185 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
186 | u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5); | ||
187 | unsigned int ma; | ||
188 | |||
189 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
190 | return -ENODEV; | ||
191 | |||
192 | ma = (mbc->pcf->pdata->charger_reference_current_ma * mbcc5) >> 8; | ||
193 | |||
194 | return sprintf(buf, "%u\n", ma); | ||
195 | } | ||
196 | |||
197 | static ssize_t set_chglim(struct device *dev, | ||
198 | struct device_attribute *attr, const char *buf, size_t count) | ||
199 | { | ||
200 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
201 | unsigned long ma; | ||
202 | unsigned int mbcc5; | ||
203 | int ret; | ||
204 | |||
205 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
206 | return -ENODEV; | ||
207 | |||
208 | ret = strict_strtoul(buf, 10, &ma); | ||
209 | if (ret) | ||
210 | return -EINVAL; | ||
211 | |||
212 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
213 | if (mbcc5 > 255) | ||
214 | mbcc5 = 255; | ||
215 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
216 | |||
217 | return count; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * This attribute allows to change MBC charging limit on the fly | ||
222 | * independently of usb current limit. It also gets set automatically every | ||
223 | * time usb current limit is changed. | ||
224 | */ | ||
225 | static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim); | ||
226 | |||
160 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { | 227 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { |
161 | &dev_attr_chgmode.attr, | 228 | &dev_attr_chgmode.attr, |
162 | &dev_attr_usb_curlim.attr, | 229 | &dev_attr_usb_curlim.attr, |
230 | &dev_attr_chg_curlim.attr, | ||
163 | NULL, | 231 | NULL, |
164 | }; | 232 | }; |
165 | 233 | ||
diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index 9aba7b779fbc..09af8fdfbb5d 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h | |||
@@ -31,6 +31,13 @@ struct pcf50633_platform_data { | |||
31 | 31 | ||
32 | int charging_restart_interval; | 32 | int charging_restart_interval; |
33 | 33 | ||
34 | /* | ||
35 | * Should be set accordingly to the reference resistor used, see | ||
36 | * I_{ch(ref)} charger reference current in the pcf50633 User | ||
37 | * Manual. | ||
38 | */ | ||
39 | int charger_reference_current_ma; | ||
40 | |||
34 | /* Callbacks */ | 41 | /* Callbacks */ |
35 | void (*probe_done)(struct pcf50633 *); | 42 | void (*probe_done)(struct pcf50633 *); |
36 | void (*mbc_event_callback)(struct pcf50633 *, int); | 43 | void (*mbc_event_callback)(struct pcf50633 *, int); |