diff options
| -rw-r--r-- | arch/arm/mach-s3c2442/mach-gta02.c | 3 | ||||
| -rw-r--r-- | drivers/mfd/wm831x-core.c | 9 | ||||
| -rw-r--r-- | drivers/power/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/power/Makefile | 1 | ||||
| -rw-r--r-- | drivers/power/pcf50633-charger.c | 228 | ||||
| -rw-r--r-- | drivers/power/power_supply_sysfs.c | 5 | ||||
| -rw-r--r-- | drivers/power/wm831x_backup.c | 233 | ||||
| -rw-r--r-- | drivers/power/wm831x_power.c | 144 | ||||
| -rw-r--r-- | include/linux/mfd/pcf50633/core.h | 7 | ||||
| -rw-r--r-- | include/linux/mfd/pcf50633/mbc.h | 1 |
10 files changed, 420 insertions, 218 deletions
diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index f76d6ff4aeb9..0b4a3a03071f 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c | |||
| @@ -268,6 +268,9 @@ struct pcf50633_platform_data gta02_pcf_pdata = { | |||
| 268 | 268 | ||
| 269 | .batteries = gta02_batteries, | 269 | .batteries = gta02_batteries, |
| 270 | .num_batteries = ARRAY_SIZE(gta02_batteries), | 270 | .num_batteries = ARRAY_SIZE(gta02_batteries), |
| 271 | |||
| 272 | .charger_reference_current_ma = 1000, | ||
| 273 | |||
| 271 | .reg_init_data = { | 274 | .reg_init_data = { |
| 272 | [PCF50633_REGULATOR_AUTO] = { | 275 | [PCF50633_REGULATOR_AUTO] = { |
| 273 | .constraints = { | 276 | .constraints = { |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 223a90c7492f..4b2021af1d96 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
| @@ -809,6 +809,9 @@ static struct resource wm831x_wdt_resources[] = { | |||
| 809 | 809 | ||
| 810 | static struct mfd_cell wm8310_devs[] = { | 810 | static struct mfd_cell wm8310_devs[] = { |
| 811 | { | 811 | { |
| 812 | .name = "wm831x-backup", | ||
| 813 | }, | ||
| 814 | { | ||
| 812 | .name = "wm831x-buckv", | 815 | .name = "wm831x-buckv", |
| 813 | .id = 1, | 816 | .id = 1, |
| 814 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), | 817 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), |
| @@ -962,6 +965,9 @@ static struct mfd_cell wm8310_devs[] = { | |||
| 962 | 965 | ||
| 963 | static struct mfd_cell wm8311_devs[] = { | 966 | static struct mfd_cell wm8311_devs[] = { |
| 964 | { | 967 | { |
| 968 | .name = "wm831x-backup", | ||
| 969 | }, | ||
| 970 | { | ||
| 965 | .name = "wm831x-buckv", | 971 | .name = "wm831x-buckv", |
| 966 | .id = 1, | 972 | .id = 1, |
| 967 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), | 973 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), |
| @@ -1096,6 +1102,9 @@ static struct mfd_cell wm8311_devs[] = { | |||
| 1096 | 1102 | ||
| 1097 | static struct mfd_cell wm8312_devs[] = { | 1103 | static struct mfd_cell wm8312_devs[] = { |
| 1098 | { | 1104 | { |
| 1105 | .name = "wm831x-backup", | ||
| 1106 | }, | ||
| 1107 | { | ||
| 1099 | .name = "wm831x-buckv", | 1108 | .name = "wm831x-buckv", |
| 1100 | .id = 1, | 1109 | .id = 1, |
| 1101 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), | 1110 | .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources), |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 118674925516..d4b3d67f0548 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
| @@ -29,6 +29,13 @@ config APM_POWER | |||
| 29 | Say Y here to enable support APM status emulation using | 29 | Say Y here to enable support APM status emulation using |
| 30 | battery class devices. | 30 | battery class devices. |
| 31 | 31 | ||
| 32 | config WM831X_BACKUP | ||
| 33 | tristate "WM831X backup battery charger support" | ||
| 34 | depends on MFD_WM831X | ||
| 35 | help | ||
| 36 | Say Y here to enable support for the backup battery charger | ||
| 37 | in the Wolfson Microelectronics WM831x PMICs. | ||
| 38 | |||
| 32 | config WM831X_POWER | 39 | config WM831X_POWER |
| 33 | tristate "WM831X PMU support" | 40 | tristate "WM831X PMU support" |
| 34 | depends on MFD_WM831X | 41 | depends on MFD_WM831X |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 356cdfd3c8b2..573597c683b4 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o | |||
| 16 | 16 | ||
| 17 | obj-$(CONFIG_PDA_POWER) += pda_power.o | 17 | obj-$(CONFIG_PDA_POWER) += pda_power.o |
| 18 | obj-$(CONFIG_APM_POWER) += apm_power.o | 18 | obj-$(CONFIG_APM_POWER) += apm_power.o |
| 19 | obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o | ||
| 19 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o | 20 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o |
| 20 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o | 21 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o |
| 21 | 22 | ||
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 6a84a8eb8d7a..ea3fdfaca90d 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c | |||
| @@ -29,15 +29,12 @@ | |||
| 29 | struct pcf50633_mbc { | 29 | struct 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; |
| 38 | struct power_supply adapter; | 36 | struct power_supply adapter; |
| 39 | 37 | struct power_supply ac; | |
| 40 | struct delayed_work charging_restart_work; | ||
| 41 | }; | 38 | }; |
| 42 | 39 | ||
| 43 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | 40 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) |
| @@ -47,16 +44,21 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
| 47 | u8 bits; | 44 | u8 bits; |
| 48 | int charging_start = 1; | 45 | int charging_start = 1; |
| 49 | u8 mbcs2, chgmod; | 46 | u8 mbcs2, chgmod; |
| 47 | unsigned int mbcc5; | ||
| 50 | 48 | ||
| 51 | if (ma >= 1000) | 49 | if (ma >= 1000) { |
| 52 | bits = PCF50633_MBCC7_USB_1000mA; | 50 | bits = PCF50633_MBCC7_USB_1000mA; |
| 53 | else if (ma >= 500) | 51 | ma = 1000; |
| 52 | } else if (ma >= 500) { | ||
| 54 | bits = PCF50633_MBCC7_USB_500mA; | 53 | bits = PCF50633_MBCC7_USB_500mA; |
| 55 | else if (ma >= 100) | 54 | ma = 500; |
| 55 | } else if (ma >= 100) { | ||
| 56 | bits = PCF50633_MBCC7_USB_100mA; | 56 | bits = PCF50633_MBCC7_USB_100mA; |
| 57 | else { | 57 | ma = 100; |
| 58 | } else { | ||
| 58 | bits = PCF50633_MBCC7_USB_SUSPEND; | 59 | bits = PCF50633_MBCC7_USB_SUSPEND; |
| 59 | charging_start = 0; | 60 | charging_start = 0; |
| 61 | ma = 0; | ||
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, | 64 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, |
| @@ -66,21 +68,40 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
| 66 | else | 68 | else |
| 67 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); | 69 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); |
| 68 | 70 | ||
| 69 | /* Manual charging start */ | 71 | /* |
| 70 | mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | 72 | * We limit the charging current to be the USB current limit. |
| 73 | * The reason is that on pcf50633, when it enters PMU Standby mode, | ||
| 74 | * which it does when the device goes "off", the USB current limit | ||
| 75 | * reverts to the variant default. In at least one common case, that | ||
| 76 | * default is 500mA. By setting the charging current to be the same | ||
| 77 | * as the USB limit we set here before PMU standby, we enforce it only | ||
| 78 | * using the correct amount of current even when the USB current limit | ||
| 79 | * gets reset to the wrong thing | ||
| 80 | */ | ||
| 81 | |||
| 82 | if (mbc->pcf->pdata->charger_reference_current_ma) { | ||
| 83 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
| 84 | if (mbcc5 > 255) | ||
| 85 | mbcc5 = 255; | ||
| 86 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
| 87 | } | ||
| 88 | |||
| 89 | mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); | ||
| 71 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); | 90 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); |
| 72 | 91 | ||
| 73 | /* If chgmod == BATFULL, setting chgena has no effect. | 92 | /* If chgmod == BATFULL, setting chgena has no effect. |
| 74 | * We need to set resume instead. | 93 | * Datasheet says we need to set resume instead but when autoresume is |
| 94 | * used resume doesn't work. Clear and set chgena instead. | ||
| 75 | */ | 95 | */ |
| 76 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) | 96 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) |
| 77 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, | 97 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, |
| 78 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); | 98 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); |
| 79 | else | 99 | else { |
| 100 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1, | ||
| 101 | PCF50633_MBCC1_CHGENA); | ||
| 80 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, | 102 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, |
| 81 | PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); | 103 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); |
| 82 | 104 | } | |
| 83 | mbc->usb_active = charging_start; | ||
| 84 | 105 | ||
| 85 | power_supply_changed(&mbc->usb); | 106 | power_supply_changed(&mbc->usb); |
| 86 | 107 | ||
| @@ -92,20 +113,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf) | |||
| 92 | { | 113 | { |
| 93 | struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); | 114 | struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); |
| 94 | 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; | ||
| 95 | 123 | ||
| 96 | if (mbc->usb_online) | 124 | if (mbc->usb_online) |
| 97 | status |= PCF50633_MBC_USB_ONLINE; | 125 | status |= PCF50633_MBC_USB_ONLINE; |
| 98 | 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) | ||
| 99 | status |= PCF50633_MBC_USB_ACTIVE; | 130 | status |= PCF50633_MBC_USB_ACTIVE; |
| 100 | if (mbc->adapter_online) | 131 | if (mbc->adapter_online) |
| 101 | status |= PCF50633_MBC_ADAPTER_ONLINE; | 132 | status |= PCF50633_MBC_ADAPTER_ONLINE; |
| 102 | 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) | ||
| 103 | status |= PCF50633_MBC_ADAPTER_ACTIVE; | 137 | status |= PCF50633_MBC_ADAPTER_ACTIVE; |
| 104 | 138 | ||
| 105 | return status; | 139 | return status; |
| 106 | } | 140 | } |
| 107 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); | 141 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); |
| 108 | 142 | ||
| 143 | int 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 | } | ||
| 152 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status); | ||
| 153 | |||
| 109 | static ssize_t | 154 | static ssize_t |
| 110 | show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) | 155 | show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) |
| 111 | { | 156 | { |
| @@ -156,9 +201,55 @@ static ssize_t set_usblim(struct device *dev, | |||
| 156 | 201 | ||
| 157 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); | 202 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); |
| 158 | 203 | ||
| 204 | static ssize_t | ||
| 205 | show_chglim(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 206 | { | ||
| 207 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
| 208 | u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5); | ||
| 209 | unsigned int ma; | ||
| 210 | |||
| 211 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
| 212 | return -ENODEV; | ||
| 213 | |||
| 214 | ma = (mbc->pcf->pdata->charger_reference_current_ma * mbcc5) >> 8; | ||
| 215 | |||
| 216 | return sprintf(buf, "%u\n", ma); | ||
| 217 | } | ||
| 218 | |||
| 219 | static ssize_t set_chglim(struct device *dev, | ||
| 220 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 221 | { | ||
| 222 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
| 223 | unsigned long ma; | ||
| 224 | unsigned int mbcc5; | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
| 228 | return -ENODEV; | ||
| 229 | |||
| 230 | ret = strict_strtoul(buf, 10, &ma); | ||
| 231 | if (ret) | ||
| 232 | return -EINVAL; | ||
| 233 | |||
| 234 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
| 235 | if (mbcc5 > 255) | ||
| 236 | mbcc5 = 255; | ||
| 237 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
| 238 | |||
| 239 | return count; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* | ||
| 243 | * This attribute allows to change MBC charging limit on the fly | ||
| 244 | * independently of usb current limit. It also gets set automatically every | ||
| 245 | * time usb current limit is changed. | ||
| 246 | */ | ||
| 247 | static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim); | ||
| 248 | |||
| 159 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { | 249 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { |
| 160 | &dev_attr_chgmode.attr, | 250 | &dev_attr_chgmode.attr, |
| 161 | &dev_attr_usb_curlim.attr, | 251 | &dev_attr_usb_curlim.attr, |
| 252 | &dev_attr_chg_curlim.attr, | ||
| 162 | NULL, | 253 | NULL, |
| 163 | }; | 254 | }; |
| 164 | 255 | ||
| @@ -167,76 +258,26 @@ static struct attribute_group mbc_attr_group = { | |||
| 167 | .attrs = pcf50633_mbc_sysfs_entries, | 258 | .attrs = pcf50633_mbc_sysfs_entries, |
| 168 | }; | 259 | }; |
| 169 | 260 | ||
| 170 | /* MBC state machine switches into charging mode when the battery voltage | ||
| 171 | * falls below 96% of a battery float voltage. But the voltage drop in Li-ion | ||
| 172 | * batteries is marginal(1~2 %) till about 80% of its capacity - which means, | ||
| 173 | * after a BATFULL, charging won't be restarted until 80%. | ||
| 174 | * | ||
| 175 | * This work_struct function restarts charging at regular intervals to make | ||
| 176 | * sure we don't discharge too much | ||
| 177 | */ | ||
| 178 | |||
| 179 | static void pcf50633_mbc_charging_restart(struct work_struct *work) | ||
| 180 | { | ||
| 181 | struct pcf50633_mbc *mbc; | ||
| 182 | u8 mbcs2, chgmod; | ||
| 183 | |||
| 184 | mbc = container_of(work, struct pcf50633_mbc, | ||
| 185 | charging_restart_work.work); | ||
| 186 | |||
| 187 | mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); | ||
| 188 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); | ||
| 189 | |||
| 190 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) | ||
| 191 | return; | ||
| 192 | |||
| 193 | /* Restart charging */ | ||
| 194 | pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1, | ||
| 195 | PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); | ||
| 196 | mbc->usb_active = 1; | ||
| 197 | power_supply_changed(&mbc->usb); | ||
| 198 | |||
| 199 | dev_info(mbc->pcf->dev, "Charging restarted\n"); | ||
| 200 | } | ||
| 201 | |||
| 202 | static void | 261 | static void |
| 203 | pcf50633_mbc_irq_handler(int irq, void *data) | 262 | pcf50633_mbc_irq_handler(int irq, void *data) |
| 204 | { | 263 | { |
| 205 | struct pcf50633_mbc *mbc = data; | 264 | struct pcf50633_mbc *mbc = data; |
| 206 | int chg_restart_interval = | ||
| 207 | mbc->pcf->pdata->charging_restart_interval; | ||
| 208 | 265 | ||
| 209 | /* USB */ | 266 | /* USB */ |
| 210 | if (irq == PCF50633_IRQ_USBINS) { | 267 | if (irq == PCF50633_IRQ_USBINS) { |
| 211 | mbc->usb_online = 1; | 268 | mbc->usb_online = 1; |
| 212 | } else if (irq == PCF50633_IRQ_USBREM) { | 269 | } else if (irq == PCF50633_IRQ_USBREM) { |
| 213 | mbc->usb_online = 0; | 270 | mbc->usb_online = 0; |
| 214 | mbc->usb_active = 0; | ||
| 215 | pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); | 271 | pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); |
| 216 | cancel_delayed_work_sync(&mbc->charging_restart_work); | ||
| 217 | } | 272 | } |
| 218 | 273 | ||
| 219 | /* Adapter */ | 274 | /* Adapter */ |
| 220 | if (irq == PCF50633_IRQ_ADPINS) { | 275 | if (irq == PCF50633_IRQ_ADPINS) |
| 221 | mbc->adapter_online = 1; | 276 | mbc->adapter_online = 1; |
| 222 | mbc->adapter_active = 1; | 277 | else if (irq == PCF50633_IRQ_ADPREM) |
| 223 | } else if (irq == PCF50633_IRQ_ADPREM) { | ||
| 224 | mbc->adapter_online = 0; | 278 | mbc->adapter_online = 0; |
| 225 | mbc->adapter_active = 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (irq == PCF50633_IRQ_BATFULL) { | ||
| 229 | mbc->usb_active = 0; | ||
| 230 | mbc->adapter_active = 0; | ||
| 231 | |||
| 232 | if (chg_restart_interval > 0) | ||
| 233 | schedule_delayed_work(&mbc->charging_restart_work, | ||
| 234 | chg_restart_interval); | ||
| 235 | } else if (irq == PCF50633_IRQ_USBLIMON) | ||
| 236 | mbc->usb_active = 0; | ||
| 237 | else if (irq == PCF50633_IRQ_USBLIMOFF) | ||
| 238 | mbc->usb_active = 1; | ||
| 239 | 279 | ||
| 280 | power_supply_changed(&mbc->ac); | ||
| 240 | power_supply_changed(&mbc->usb); | 281 | power_supply_changed(&mbc->usb); |
| 241 | power_supply_changed(&mbc->adapter); | 282 | power_supply_changed(&mbc->adapter); |
| 242 | 283 | ||
| @@ -269,10 +310,34 @@ static int usb_get_property(struct power_supply *psy, | |||
| 269 | { | 310 | { |
| 270 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb); | 311 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb); |
| 271 | int ret = 0; | 312 | int ret = 0; |
| 313 | u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) & | ||
| 314 | PCF50633_MBCC7_USB_MASK; | ||
| 272 | 315 | ||
| 273 | switch (psp) { | 316 | switch (psp) { |
| 274 | case POWER_SUPPLY_PROP_ONLINE: | 317 | case POWER_SUPPLY_PROP_ONLINE: |
| 275 | val->intval = mbc->usb_online; | 318 | val->intval = mbc->usb_online && |
| 319 | (usblim <= PCF50633_MBCC7_USB_500mA); | ||
| 320 | break; | ||
| 321 | default: | ||
| 322 | ret = -EINVAL; | ||
| 323 | break; | ||
| 324 | } | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int ac_get_property(struct power_supply *psy, | ||
| 329 | enum power_supply_property psp, | ||
| 330 | union power_supply_propval *val) | ||
| 331 | { | ||
| 332 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac); | ||
| 333 | int ret = 0; | ||
| 334 | u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) & | ||
| 335 | PCF50633_MBCC7_USB_MASK; | ||
| 336 | |||
| 337 | switch (psp) { | ||
| 338 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 339 | val->intval = mbc->usb_online && | ||
| 340 | (usblim == PCF50633_MBCC7_USB_1000mA); | ||
| 276 | break; | 341 | break; |
| 277 | default: | 342 | default: |
| 278 | ret = -EINVAL; | 343 | ret = -EINVAL; |
| @@ -336,6 +401,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | |||
| 336 | mbc->usb.supplied_to = mbc->pcf->pdata->batteries; | 401 | mbc->usb.supplied_to = mbc->pcf->pdata->batteries; |
| 337 | mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries; | 402 | mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries; |
| 338 | 403 | ||
| 404 | mbc->ac.name = "ac"; | ||
| 405 | mbc->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
| 406 | mbc->ac.properties = power_props; | ||
| 407 | mbc->ac.num_properties = ARRAY_SIZE(power_props); | ||
| 408 | mbc->ac.get_property = ac_get_property; | ||
| 409 | mbc->ac.supplied_to = mbc->pcf->pdata->batteries; | ||
| 410 | mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries; | ||
| 411 | |||
| 339 | ret = power_supply_register(&pdev->dev, &mbc->adapter); | 412 | ret = power_supply_register(&pdev->dev, &mbc->adapter); |
| 340 | if (ret) { | 413 | if (ret) { |
| 341 | dev_err(mbc->pcf->dev, "failed to register adapter\n"); | 414 | dev_err(mbc->pcf->dev, "failed to register adapter\n"); |
| @@ -351,8 +424,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | |||
| 351 | return ret; | 424 | return ret; |
| 352 | } | 425 | } |
| 353 | 426 | ||
| 354 | INIT_DELAYED_WORK(&mbc->charging_restart_work, | 427 | ret = power_supply_register(&pdev->dev, &mbc->ac); |
| 355 | pcf50633_mbc_charging_restart); | 428 | if (ret) { |
| 429 | dev_err(mbc->pcf->dev, "failed to register ac\n"); | ||
| 430 | power_supply_unregister(&mbc->adapter); | ||
| 431 | power_supply_unregister(&mbc->usb); | ||
| 432 | kfree(mbc); | ||
| 433 | return ret; | ||
| 434 | } | ||
| 356 | 435 | ||
| 357 | ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group); | 436 | ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group); |
| 358 | if (ret) | 437 | if (ret) |
| @@ -378,8 +457,7 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev) | |||
| 378 | 457 | ||
| 379 | power_supply_unregister(&mbc->usb); | 458 | power_supply_unregister(&mbc->usb); |
| 380 | power_supply_unregister(&mbc->adapter); | 459 | power_supply_unregister(&mbc->adapter); |
| 381 | 460 | power_supply_unregister(&mbc->ac); | |
| 382 | cancel_delayed_work_sync(&mbc->charging_restart_work); | ||
| 383 | 461 | ||
| 384 | kfree(mbc); | 462 | kfree(mbc); |
| 385 | 463 | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 08144393d64b..c790e0c77d4b 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
| @@ -65,7 +65,10 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
| 65 | ret = psy->get_property(psy, off, &value); | 65 | ret = psy->get_property(psy, off, &value); |
| 66 | 66 | ||
| 67 | if (ret < 0) { | 67 | if (ret < 0) { |
| 68 | if (ret != -ENODEV) | 68 | if (ret == -ENODATA) |
| 69 | dev_dbg(dev, "driver has no data for `%s' property\n", | ||
| 70 | attr->attr.name); | ||
| 71 | else if (ret != -ENODEV) | ||
| 69 | dev_err(dev, "driver failed to report `%s' property\n", | 72 | dev_err(dev, "driver failed to report `%s' property\n", |
| 70 | attr->attr.name); | 73 | attr->attr.name); |
| 71 | return ret; | 74 | return ret; |
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c new file mode 100644 index 000000000000..bf4f387a8009 --- /dev/null +++ b/drivers/power/wm831x_backup.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * Backup battery driver for Wolfson Microelectronics wm831x PMICs | ||
| 3 | * | ||
| 4 | * Copyright 2009 Wolfson Microelectronics PLC. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/power_supply.h> | ||
| 15 | |||
| 16 | #include <linux/mfd/wm831x/core.h> | ||
| 17 | #include <linux/mfd/wm831x/auxadc.h> | ||
| 18 | #include <linux/mfd/wm831x/pmu.h> | ||
| 19 | #include <linux/mfd/wm831x/pdata.h> | ||
| 20 | |||
| 21 | struct wm831x_backup { | ||
| 22 | struct wm831x *wm831x; | ||
| 23 | struct power_supply backup; | ||
| 24 | }; | ||
| 25 | |||
| 26 | static int wm831x_backup_read_voltage(struct wm831x *wm831x, | ||
| 27 | enum wm831x_auxadc src, | ||
| 28 | union power_supply_propval *val) | ||
| 29 | { | ||
| 30 | int ret; | ||
| 31 | |||
| 32 | ret = wm831x_auxadc_read_uv(wm831x, src); | ||
| 33 | if (ret >= 0) | ||
| 34 | val->intval = ret; | ||
| 35 | |||
| 36 | return ret; | ||
| 37 | } | ||
| 38 | |||
| 39 | /********************************************************************* | ||
| 40 | * Backup supply properties | ||
| 41 | *********************************************************************/ | ||
| 42 | |||
| 43 | static void wm831x_config_backup(struct wm831x *wm831x) | ||
| 44 | { | ||
| 45 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; | ||
| 46 | struct wm831x_backup_pdata *pdata; | ||
| 47 | int ret, reg; | ||
| 48 | |||
| 49 | if (!wm831x_pdata || !wm831x_pdata->backup) { | ||
| 50 | dev_warn(wm831x->dev, | ||
| 51 | "No backup battery charger configuration\n"); | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | |||
| 55 | pdata = wm831x_pdata->backup; | ||
| 56 | |||
| 57 | reg = 0; | ||
| 58 | |||
| 59 | if (pdata->charger_enable) | ||
| 60 | reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA; | ||
| 61 | if (pdata->no_constant_voltage) | ||
| 62 | reg |= WM831X_BKUP_CHG_MODE; | ||
| 63 | |||
| 64 | switch (pdata->vlim) { | ||
| 65 | case 2500: | ||
| 66 | break; | ||
| 67 | case 3100: | ||
| 68 | reg |= WM831X_BKUP_CHG_VLIM; | ||
| 69 | break; | ||
| 70 | default: | ||
| 71 | dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n", | ||
| 72 | pdata->vlim); | ||
| 73 | } | ||
| 74 | |||
| 75 | switch (pdata->ilim) { | ||
| 76 | case 100: | ||
| 77 | break; | ||
| 78 | case 200: | ||
| 79 | reg |= 1; | ||
| 80 | break; | ||
| 81 | case 300: | ||
| 82 | reg |= 2; | ||
| 83 | break; | ||
| 84 | case 400: | ||
| 85 | reg |= 3; | ||
| 86 | break; | ||
| 87 | default: | ||
| 88 | dev_err(wm831x->dev, "Invalid backup current limit %duA\n", | ||
| 89 | pdata->ilim); | ||
| 90 | } | ||
| 91 | |||
| 92 | ret = wm831x_reg_unlock(wm831x); | ||
| 93 | if (ret != 0) { | ||
| 94 | dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret); | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | |||
| 98 | ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL, | ||
| 99 | WM831X_BKUP_CHG_ENA_MASK | | ||
| 100 | WM831X_BKUP_CHG_MODE_MASK | | ||
| 101 | WM831X_BKUP_BATT_DET_ENA_MASK | | ||
| 102 | WM831X_BKUP_CHG_VLIM_MASK | | ||
| 103 | WM831X_BKUP_CHG_ILIM_MASK, | ||
| 104 | reg); | ||
| 105 | if (ret != 0) | ||
| 106 | dev_err(wm831x->dev, | ||
| 107 | "Failed to set backup charger config: %d\n", ret); | ||
| 108 | |||
| 109 | wm831x_reg_lock(wm831x); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int wm831x_backup_get_prop(struct power_supply *psy, | ||
| 113 | enum power_supply_property psp, | ||
| 114 | union power_supply_propval *val) | ||
| 115 | { | ||
| 116 | struct wm831x_backup *devdata = dev_get_drvdata(psy->dev->parent); | ||
| 117 | struct wm831x *wm831x = devdata->wm831x; | ||
| 118 | int ret = 0; | ||
| 119 | |||
| 120 | ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL); | ||
| 121 | if (ret < 0) | ||
| 122 | return ret; | ||
| 123 | |||
| 124 | switch (psp) { | ||
| 125 | case POWER_SUPPLY_PROP_STATUS: | ||
| 126 | if (ret & WM831X_BKUP_CHG_STS) | ||
| 127 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
| 128 | else | ||
| 129 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
| 130 | break; | ||
| 131 | |||
| 132 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
| 133 | ret = wm831x_backup_read_voltage(wm831x, WM831X_AUX_BKUP_BATT, | ||
| 134 | val); | ||
| 135 | break; | ||
| 136 | |||
| 137 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 138 | if (ret & WM831X_BKUP_CHG_STS) | ||
| 139 | val->intval = 1; | ||
| 140 | else | ||
| 141 | val->intval = 0; | ||
| 142 | break; | ||
| 143 | |||
| 144 | default: | ||
| 145 | ret = -EINVAL; | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | |||
| 149 | return ret; | ||
| 150 | } | ||
| 151 | |||
| 152 | static enum power_supply_property wm831x_backup_props[] = { | ||
| 153 | POWER_SUPPLY_PROP_STATUS, | ||
| 154 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 155 | POWER_SUPPLY_PROP_PRESENT, | ||
| 156 | }; | ||
| 157 | |||
| 158 | /********************************************************************* | ||
| 159 | * Initialisation | ||
| 160 | *********************************************************************/ | ||
| 161 | |||
| 162 | static __devinit int wm831x_backup_probe(struct platform_device *pdev) | ||
| 163 | { | ||
| 164 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | ||
| 165 | struct wm831x_backup *devdata; | ||
| 166 | struct power_supply *backup; | ||
| 167 | int ret; | ||
| 168 | |||
| 169 | devdata = kzalloc(sizeof(struct wm831x_backup), GFP_KERNEL); | ||
| 170 | if (devdata == NULL) | ||
| 171 | return -ENOMEM; | ||
| 172 | |||
| 173 | devdata->wm831x = wm831x; | ||
| 174 | platform_set_drvdata(pdev, devdata); | ||
| 175 | |||
| 176 | backup = &devdata->backup; | ||
| 177 | |||
| 178 | /* We ignore configuration failures since we can still read | ||
| 179 | * back the status without enabling the charger (which may | ||
| 180 | * already be enabled anyway). | ||
| 181 | */ | ||
| 182 | wm831x_config_backup(wm831x); | ||
| 183 | |||
| 184 | backup->name = "wm831x-backup"; | ||
| 185 | backup->type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 186 | backup->properties = wm831x_backup_props; | ||
| 187 | backup->num_properties = ARRAY_SIZE(wm831x_backup_props); | ||
| 188 | backup->get_property = wm831x_backup_get_prop; | ||
| 189 | ret = power_supply_register(&pdev->dev, backup); | ||
| 190 | if (ret) | ||
| 191 | goto err_kmalloc; | ||
| 192 | |||
| 193 | return ret; | ||
| 194 | |||
| 195 | err_kmalloc: | ||
| 196 | kfree(devdata); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | static __devexit int wm831x_backup_remove(struct platform_device *pdev) | ||
| 201 | { | ||
| 202 | struct wm831x_backup *devdata = platform_get_drvdata(pdev); | ||
| 203 | |||
| 204 | power_supply_unregister(&devdata->backup); | ||
| 205 | kfree(devdata); | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static struct platform_driver wm831x_backup_driver = { | ||
| 211 | .probe = wm831x_backup_probe, | ||
| 212 | .remove = __devexit_p(wm831x_backup_remove), | ||
| 213 | .driver = { | ||
| 214 | .name = "wm831x-backup", | ||
| 215 | }, | ||
| 216 | }; | ||
| 217 | |||
| 218 | static int __init wm831x_backup_init(void) | ||
| 219 | { | ||
| 220 | return platform_driver_register(&wm831x_backup_driver); | ||
| 221 | } | ||
| 222 | module_init(wm831x_backup_init); | ||
| 223 | |||
| 224 | static void __exit wm831x_backup_exit(void) | ||
| 225 | { | ||
| 226 | platform_driver_unregister(&wm831x_backup_driver); | ||
| 227 | } | ||
| 228 | module_exit(wm831x_backup_exit); | ||
| 229 | |||
| 230 | MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs"); | ||
| 231 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
| 232 | MODULE_LICENSE("GPL"); | ||
| 233 | MODULE_ALIAS("platform:wm831x-backup"); | ||
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 2a4c8b0b829c..f85e80b1b400 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | struct wm831x_power { | 21 | struct wm831x_power { |
| 22 | struct wm831x *wm831x; | 22 | struct wm831x *wm831x; |
| 23 | struct power_supply wall; | 23 | struct power_supply wall; |
| 24 | struct power_supply backup; | ||
| 25 | struct power_supply usb; | 24 | struct power_supply usb; |
| 26 | struct power_supply battery; | 25 | struct power_supply battery; |
| 27 | }; | 26 | }; |
| @@ -454,125 +453,6 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data) | |||
| 454 | 453 | ||
| 455 | 454 | ||
| 456 | /********************************************************************* | 455 | /********************************************************************* |
| 457 | * Backup supply properties | ||
| 458 | *********************************************************************/ | ||
| 459 | |||
| 460 | static void wm831x_config_backup(struct wm831x *wm831x) | ||
| 461 | { | ||
| 462 | struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; | ||
| 463 | struct wm831x_backup_pdata *pdata; | ||
| 464 | int ret, reg; | ||
| 465 | |||
| 466 | if (!wm831x_pdata || !wm831x_pdata->backup) { | ||
| 467 | dev_warn(wm831x->dev, | ||
| 468 | "No backup battery charger configuration\n"); | ||
| 469 | return; | ||
| 470 | } | ||
| 471 | |||
| 472 | pdata = wm831x_pdata->backup; | ||
| 473 | |||
| 474 | reg = 0; | ||
| 475 | |||
| 476 | if (pdata->charger_enable) | ||
| 477 | reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA; | ||
| 478 | if (pdata->no_constant_voltage) | ||
| 479 | reg |= WM831X_BKUP_CHG_MODE; | ||
| 480 | |||
| 481 | switch (pdata->vlim) { | ||
| 482 | case 2500: | ||
| 483 | break; | ||
| 484 | case 3100: | ||
| 485 | reg |= WM831X_BKUP_CHG_VLIM; | ||
| 486 | break; | ||
| 487 | default: | ||
| 488 | dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n", | ||
| 489 | pdata->vlim); | ||
| 490 | } | ||
| 491 | |||
| 492 | switch (pdata->ilim) { | ||
| 493 | case 100: | ||
| 494 | break; | ||
| 495 | case 200: | ||
| 496 | reg |= 1; | ||
| 497 | break; | ||
| 498 | case 300: | ||
| 499 | reg |= 2; | ||
| 500 | break; | ||
| 501 | case 400: | ||
| 502 | reg |= 3; | ||
| 503 | break; | ||
| 504 | default: | ||
| 505 | dev_err(wm831x->dev, "Invalid backup current limit %duA\n", | ||
| 506 | pdata->ilim); | ||
| 507 | } | ||
| 508 | |||
| 509 | ret = wm831x_reg_unlock(wm831x); | ||
| 510 | if (ret != 0) { | ||
| 511 | dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret); | ||
| 512 | return; | ||
| 513 | } | ||
| 514 | |||
| 515 | ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL, | ||
| 516 | WM831X_BKUP_CHG_ENA_MASK | | ||
| 517 | WM831X_BKUP_CHG_MODE_MASK | | ||
| 518 | WM831X_BKUP_BATT_DET_ENA_MASK | | ||
| 519 | WM831X_BKUP_CHG_VLIM_MASK | | ||
| 520 | WM831X_BKUP_CHG_ILIM_MASK, | ||
| 521 | reg); | ||
| 522 | if (ret != 0) | ||
| 523 | dev_err(wm831x->dev, | ||
| 524 | "Failed to set backup charger config: %d\n", ret); | ||
| 525 | |||
| 526 | wm831x_reg_lock(wm831x); | ||
| 527 | } | ||
| 528 | |||
| 529 | static int wm831x_backup_get_prop(struct power_supply *psy, | ||
| 530 | enum power_supply_property psp, | ||
| 531 | union power_supply_propval *val) | ||
| 532 | { | ||
| 533 | struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent); | ||
| 534 | struct wm831x *wm831x = wm831x_power->wm831x; | ||
| 535 | int ret = 0; | ||
| 536 | |||
| 537 | ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL); | ||
| 538 | if (ret < 0) | ||
| 539 | return ret; | ||
| 540 | |||
| 541 | switch (psp) { | ||
| 542 | case POWER_SUPPLY_PROP_STATUS: | ||
| 543 | if (ret & WM831X_BKUP_CHG_STS) | ||
| 544 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
| 545 | else | ||
| 546 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
| 547 | break; | ||
| 548 | |||
| 549 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
| 550 | ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BKUP_BATT, | ||
| 551 | val); | ||
| 552 | break; | ||
| 553 | |||
| 554 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 555 | if (ret & WM831X_BKUP_CHG_STS) | ||
| 556 | val->intval = 1; | ||
| 557 | else | ||
| 558 | val->intval = 0; | ||
| 559 | break; | ||
| 560 | |||
| 561 | default: | ||
| 562 | ret = -EINVAL; | ||
| 563 | break; | ||
| 564 | } | ||
| 565 | |||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | |||
| 569 | static enum power_supply_property wm831x_backup_props[] = { | ||
| 570 | POWER_SUPPLY_PROP_STATUS, | ||
| 571 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
| 572 | POWER_SUPPLY_PROP_PRESENT, | ||
| 573 | }; | ||
| 574 | |||
| 575 | /********************************************************************* | ||
| 576 | * Initialisation | 456 | * Initialisation |
| 577 | *********************************************************************/ | 457 | *********************************************************************/ |
| 578 | 458 | ||
| @@ -595,10 +475,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data) | |||
| 595 | 475 | ||
| 596 | dev_dbg(wm831x->dev, "Power source changed\n"); | 476 | dev_dbg(wm831x->dev, "Power source changed\n"); |
| 597 | 477 | ||
| 598 | /* Just notify for everything - little harm in overnotifying. | 478 | /* Just notify for everything - little harm in overnotifying. */ |
| 599 | * The backup battery is not a power source while the system | ||
| 600 | * is running so skip that. | ||
| 601 | */ | ||
| 602 | power_supply_changed(&wm831x_power->battery); | 479 | power_supply_changed(&wm831x_power->battery); |
| 603 | power_supply_changed(&wm831x_power->usb); | 480 | power_supply_changed(&wm831x_power->usb); |
| 604 | power_supply_changed(&wm831x_power->wall); | 481 | power_supply_changed(&wm831x_power->wall); |
| @@ -613,7 +490,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
| 613 | struct power_supply *usb; | 490 | struct power_supply *usb; |
| 614 | struct power_supply *battery; | 491 | struct power_supply *battery; |
| 615 | struct power_supply *wall; | 492 | struct power_supply *wall; |
| 616 | struct power_supply *backup; | ||
| 617 | int ret, irq, i; | 493 | int ret, irq, i; |
| 618 | 494 | ||
| 619 | power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); | 495 | power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); |
| @@ -626,13 +502,11 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
| 626 | usb = &power->usb; | 502 | usb = &power->usb; |
| 627 | battery = &power->battery; | 503 | battery = &power->battery; |
| 628 | wall = &power->wall; | 504 | wall = &power->wall; |
| 629 | backup = &power->backup; | ||
| 630 | 505 | ||
| 631 | /* We ignore configuration failures since we can still read back | 506 | /* We ignore configuration failures since we can still read back |
| 632 | * the status without enabling either of the chargers. | 507 | * the status without enabling the charger. |
| 633 | */ | 508 | */ |
| 634 | wm831x_config_battery(wm831x); | 509 | wm831x_config_battery(wm831x); |
| 635 | wm831x_config_backup(wm831x); | ||
| 636 | 510 | ||
| 637 | wall->name = "wm831x-wall"; | 511 | wall->name = "wm831x-wall"; |
| 638 | wall->type = POWER_SUPPLY_TYPE_MAINS; | 512 | wall->type = POWER_SUPPLY_TYPE_MAINS; |
| @@ -661,15 +535,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
| 661 | if (ret) | 535 | if (ret) |
| 662 | goto err_battery; | 536 | goto err_battery; |
| 663 | 537 | ||
| 664 | backup->name = "wm831x-backup"; | ||
| 665 | backup->type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 666 | backup->properties = wm831x_backup_props; | ||
| 667 | backup->num_properties = ARRAY_SIZE(wm831x_backup_props); | ||
| 668 | backup->get_property = wm831x_backup_get_prop; | ||
| 669 | ret = power_supply_register(&pdev->dev, backup); | ||
| 670 | if (ret) | ||
| 671 | goto err_usb; | ||
| 672 | |||
| 673 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 538 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
| 674 | ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, | 539 | ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, |
| 675 | IRQF_TRIGGER_RISING, "SYSLO", | 540 | IRQF_TRIGGER_RISING, "SYSLO", |
| @@ -677,7 +542,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
| 677 | if (ret != 0) { | 542 | if (ret != 0) { |
| 678 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", | 543 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", |
| 679 | irq, ret); | 544 | irq, ret); |
| 680 | goto err_backup; | 545 | goto err_usb; |
| 681 | } | 546 | } |
| 682 | 547 | ||
| 683 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 548 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
| @@ -716,8 +581,6 @@ err_bat_irq: | |||
| 716 | err_syslo: | 581 | err_syslo: |
| 717 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 582 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
| 718 | wm831x_free_irq(wm831x, irq, power); | 583 | wm831x_free_irq(wm831x, irq, power); |
| 719 | err_backup: | ||
| 720 | power_supply_unregister(backup); | ||
| 721 | err_usb: | 584 | err_usb: |
| 722 | power_supply_unregister(usb); | 585 | power_supply_unregister(usb); |
| 723 | err_battery: | 586 | err_battery: |
| @@ -746,7 +609,6 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev) | |||
| 746 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 609 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
| 747 | wm831x_free_irq(wm831x, irq, wm831x_power); | 610 | wm831x_free_irq(wm831x, irq, wm831x_power); |
| 748 | 611 | ||
| 749 | power_supply_unregister(&wm831x_power->backup); | ||
| 750 | power_supply_unregister(&wm831x_power->battery); | 612 | power_supply_unregister(&wm831x_power->battery); |
| 751 | power_supply_unregister(&wm831x_power->wall); | 613 | power_supply_unregister(&wm831x_power->wall); |
| 752 | power_supply_unregister(&wm831x_power->usb); | 614 | power_supply_unregister(&wm831x_power->usb); |
diff --git a/include/linux/mfd/pcf50633/core.h b/include/linux/mfd/pcf50633/core.h index d9034cc87f18..3398bd9aab11 100644 --- a/include/linux/mfd/pcf50633/core.h +++ b/include/linux/mfd/pcf50633/core.h | |||
| @@ -29,7 +29,12 @@ struct pcf50633_platform_data { | |||
| 29 | char **batteries; | 29 | char **batteries; |
| 30 | int num_batteries; | 30 | int num_batteries; |
| 31 | 31 | ||
| 32 | int charging_restart_interval; | 32 | /* |
| 33 | * Should be set accordingly to the reference resistor used, see | ||
| 34 | * I_{ch(ref)} charger reference current in the pcf50633 User | ||
| 35 | * Manual. | ||
| 36 | */ | ||
| 37 | int charger_reference_current_ma; | ||
| 33 | 38 | ||
| 34 | /* Callbacks */ | 39 | /* Callbacks */ |
| 35 | void (*probe_done)(struct pcf50633 *); | 40 | void (*probe_done)(struct pcf50633 *); |
diff --git a/include/linux/mfd/pcf50633/mbc.h b/include/linux/mfd/pcf50633/mbc.h index 4119579acf2c..df4f5fa88de3 100644 --- a/include/linux/mfd/pcf50633/mbc.h +++ b/include/linux/mfd/pcf50633/mbc.h | |||
| @@ -128,6 +128,7 @@ enum pcf50633_reg_mbcs3 { | |||
| 128 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma); | 128 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma); |
| 129 | 129 | ||
| 130 | int pcf50633_mbc_get_status(struct pcf50633 *); | 130 | int pcf50633_mbc_get_status(struct pcf50633 *); |
| 131 | int pcf50633_mbc_get_usb_online_status(struct pcf50633 *); | ||
| 131 | 132 | ||
| 132 | #endif | 133 | #endif |
| 133 | 134 | ||
