Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.17-rc3 311 lines 8.9 kB view raw
1/* 2 * Battery charger driver for the Maxim 14577 3 * 4 * Copyright (C) 2013 Samsung Electronics 5 * Krzysztof Kozlowski <k.kozlowski@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18#include <linux/module.h> 19#include <linux/platform_device.h> 20#include <linux/power_supply.h> 21#include <linux/mfd/max14577-private.h> 22 23struct max14577_charger { 24 struct device *dev; 25 struct max14577 *max14577; 26 struct power_supply charger; 27 28 unsigned int charging_state; 29 unsigned int battery_state; 30}; 31 32static int max14577_get_charger_state(struct max14577_charger *chg) 33{ 34 struct regmap *rmap = chg->max14577->regmap; 35 int state = POWER_SUPPLY_STATUS_DISCHARGING; 36 u8 reg_data; 37 38 /* 39 * Charging occurs only if: 40 * - CHGCTRL2/MBCHOSTEN == 1 41 * - STATUS2/CGMBC == 1 42 * 43 * TODO: 44 * - handle FULL after Top-off timer (EOC register may be off 45 * and the charger won't be charging although MBCHOSTEN is on) 46 * - handle properly dead-battery charging (respect timer) 47 * - handle timers (fast-charge and prequal) /MBCCHGERR/ 48 */ 49 max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data); 50 if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0) 51 goto state_set; 52 53 max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data); 54 if (reg_data & STATUS3_CGMBC_MASK) { 55 /* Charger or USB-cable is connected */ 56 if (reg_data & STATUS3_EOC_MASK) 57 state = POWER_SUPPLY_STATUS_FULL; 58 else 59 state = POWER_SUPPLY_STATUS_CHARGING; 60 goto state_set; 61 } 62 63state_set: 64 chg->charging_state = state; 65 return state; 66} 67 68/* 69 * Supported charge types: 70 * - POWER_SUPPLY_CHARGE_TYPE_NONE 71 * - POWER_SUPPLY_CHARGE_TYPE_FAST 72 */ 73static int max14577_get_charge_type(struct max14577_charger *chg) 74{ 75 /* 76 * TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)? 77 * As spec says: 78 * [after reaching EOC interrupt] 79 * "When the battery is fully charged, the 30-minute (typ) 80 * top-off timer starts. The device continues to trickle 81 * charge the battery until the top-off timer runs out." 82 */ 83 if (max14577_get_charger_state(chg) == POWER_SUPPLY_STATUS_CHARGING) 84 return POWER_SUPPLY_CHARGE_TYPE_FAST; 85 return POWER_SUPPLY_CHARGE_TYPE_NONE; 86} 87 88static int max14577_get_online(struct max14577_charger *chg) 89{ 90 struct regmap *rmap = chg->max14577->regmap; 91 u8 reg_data; 92 93 max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data); 94 reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT); 95 switch (reg_data) { 96 case MAX14577_CHARGER_TYPE_USB: 97 case MAX14577_CHARGER_TYPE_DEDICATED_CHG: 98 case MAX14577_CHARGER_TYPE_SPECIAL_500MA: 99 case MAX14577_CHARGER_TYPE_SPECIAL_1A: 100 case MAX14577_CHARGER_TYPE_DEAD_BATTERY: 101 return 1; 102 case MAX14577_CHARGER_TYPE_NONE: 103 case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT: 104 case MAX14577_CHARGER_TYPE_RESERVED: 105 default: 106 return 0; 107 } 108} 109 110/* 111 * Supported health statuses: 112 * - POWER_SUPPLY_HEALTH_DEAD 113 * - POWER_SUPPLY_HEALTH_OVERVOLTAGE 114 * - POWER_SUPPLY_HEALTH_GOOD 115 */ 116static int max14577_get_battery_health(struct max14577_charger *chg) 117{ 118 struct regmap *rmap = chg->max14577->regmap; 119 int state = POWER_SUPPLY_HEALTH_GOOD; 120 u8 reg_data; 121 122 max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data); 123 reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT); 124 if (reg_data == MAX14577_CHARGER_TYPE_DEAD_BATTERY) { 125 state = POWER_SUPPLY_HEALTH_DEAD; 126 goto state_set; 127 } 128 129 max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data); 130 if (reg_data & STATUS3_OVP_MASK) { 131 state = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 132 goto state_set; 133 } 134 135state_set: 136 chg->battery_state = state; 137 return state; 138} 139 140/* 141 * Always returns 1. 142 * The max14577 chip doesn't report any status of battery presence. 143 * Lets assume that it will always be used with some battery. 144 */ 145static int max14577_get_present(struct max14577_charger *chg) 146{ 147 return 1; 148} 149 150/* 151 * Sets charger registers to proper and safe default values. 152 * Some of these values are equal to defaults in MAX14577E 153 * data sheet but there are minor differences. 154 */ 155static void max14577_charger_reg_init(struct max14577_charger *chg) 156{ 157 struct regmap *rmap = chg->max14577->regmap; 158 u8 reg_data; 159 160 /* 161 * Charger-Type Manual Detection, default off (set CHGTYPMAN to 0) 162 * Charger-Detection Enable, default on (set CHGDETEN to 1) 163 * Combined mask of CHGDETEN and CHGTYPMAN will zero the CHGTYPMAN bit 164 */ 165 reg_data = 0x1 << CDETCTRL1_CHGDETEN_SHIFT; 166 max14577_update_reg(rmap, MAX14577_REG_CDETCTRL1, 167 CDETCTRL1_CHGDETEN_MASK | CDETCTRL1_CHGTYPMAN_MASK, 168 reg_data); 169 170 /* Battery Fast-Charge Timer, from SM-V700: 6hrs */ 171 reg_data = 0x3 << CHGCTRL1_TCHW_SHIFT; 172 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL1, reg_data); 173 174 /* 175 * Wall-Adapter Rapid Charge, default on 176 * Battery-Charger, default on 177 */ 178 reg_data = 0x1 << CHGCTRL2_VCHGR_RC_SHIFT; 179 reg_data |= 0x1 << CHGCTRL2_MBCHOSTEN_SHIFT; 180 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL2, reg_data); 181 182 /* Battery-Charger Constant Voltage (CV) Mode, from SM-V700: 4.35V */ 183 reg_data = 0xf << CHGCTRL3_MBCCVWRC_SHIFT; 184 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL3, reg_data); 185 186 /* 187 * Fast Battery-Charge Current Low, default 200-950mA 188 * Fast Battery-Charge Current High, from SM-V700: 450mA 189 */ 190 reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT; 191 reg_data |= 0x5 << CHGCTRL4_MBCICHWRCH_SHIFT; 192 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL4, reg_data); 193 194 /* End-of-Charge Current, from SM-V700: 50mA */ 195 reg_data = 0x0 << CHGCTRL5_EOCS_SHIFT; 196 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL5, reg_data); 197 198 /* Auto Charging Stop, default off */ 199 reg_data = 0x0 << CHGCTRL6_AUTOSTOP_SHIFT; 200 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL6, reg_data); 201 202 /* Overvoltage-Protection Threshold, from SM-V700: 6.5V */ 203 reg_data = 0x2 << CHGCTRL7_OTPCGHCVS_SHIFT; 204 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL7, reg_data); 205} 206 207/* Support property from charger */ 208static enum power_supply_property max14577_charger_props[] = { 209 POWER_SUPPLY_PROP_STATUS, 210 POWER_SUPPLY_PROP_CHARGE_TYPE, 211 POWER_SUPPLY_PROP_HEALTH, 212 POWER_SUPPLY_PROP_PRESENT, 213 POWER_SUPPLY_PROP_ONLINE, 214 POWER_SUPPLY_PROP_MODEL_NAME, 215 POWER_SUPPLY_PROP_MANUFACTURER, 216}; 217 218static const char *model_name = "MAX14577"; 219static const char *manufacturer = "Maxim Integrated"; 220 221static int max14577_charger_get_property(struct power_supply *psy, 222 enum power_supply_property psp, 223 union power_supply_propval *val) 224{ 225 struct max14577_charger *chg = container_of(psy, 226 struct max14577_charger, 227 charger); 228 int ret = 0; 229 230 switch (psp) { 231 case POWER_SUPPLY_PROP_STATUS: 232 val->intval = max14577_get_charger_state(chg); 233 break; 234 case POWER_SUPPLY_PROP_CHARGE_TYPE: 235 val->intval = max14577_get_charge_type(chg); 236 break; 237 case POWER_SUPPLY_PROP_HEALTH: 238 val->intval = max14577_get_battery_health(chg); 239 break; 240 case POWER_SUPPLY_PROP_PRESENT: 241 val->intval = max14577_get_present(chg); 242 break; 243 case POWER_SUPPLY_PROP_ONLINE: 244 val->intval = max14577_get_online(chg); 245 break; 246 case POWER_SUPPLY_PROP_MODEL_NAME: 247 val->strval = model_name; 248 break; 249 case POWER_SUPPLY_PROP_MANUFACTURER: 250 val->strval = manufacturer; 251 break; 252 default: 253 return -EINVAL; 254 } 255 256 return ret; 257} 258 259static int max14577_charger_probe(struct platform_device *pdev) 260{ 261 struct max14577_charger *chg; 262 struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent); 263 int ret; 264 265 chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL); 266 if (!chg) 267 return -ENOMEM; 268 269 platform_set_drvdata(pdev, chg); 270 chg->dev = &pdev->dev; 271 chg->max14577 = max14577; 272 273 max14577_charger_reg_init(chg); 274 275 chg->charger.name = "max14577-charger", 276 chg->charger.type = POWER_SUPPLY_TYPE_BATTERY, 277 chg->charger.properties = max14577_charger_props, 278 chg->charger.num_properties = ARRAY_SIZE(max14577_charger_props), 279 chg->charger.get_property = max14577_charger_get_property, 280 281 ret = power_supply_register(&pdev->dev, &chg->charger); 282 if (ret) { 283 dev_err(&pdev->dev, "failed: power supply register\n"); 284 return ret; 285 } 286 287 return 0; 288} 289 290static int max14577_charger_remove(struct platform_device *pdev) 291{ 292 struct max14577_charger *chg = platform_get_drvdata(pdev); 293 294 power_supply_unregister(&chg->charger); 295 296 return 0; 297} 298 299static struct platform_driver max14577_charger_driver = { 300 .driver = { 301 .owner = THIS_MODULE, 302 .name = "max14577-charger", 303 }, 304 .probe = max14577_charger_probe, 305 .remove = max14577_charger_remove, 306}; 307module_platform_driver(max14577_charger_driver); 308 309MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>"); 310MODULE_DESCRIPTION("MAXIM 14577 charger driver"); 311MODULE_LICENSE("GPL");