162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Copyright (C) 2018 BayLibre SAS 462306a36Sopenharmony_ci// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> 562306a36Sopenharmony_ci// 662306a36Sopenharmony_ci// Battery charger driver for MAXIM 77650/77651 charger/power-supply. 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/i2c.h> 962306a36Sopenharmony_ci#include <linux/interrupt.h> 1062306a36Sopenharmony_ci#include <linux/mfd/max77650.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/power_supply.h> 1462306a36Sopenharmony_ci#include <linux/regmap.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MAX77650_CHARGER_ENABLED BIT(0) 1762306a36Sopenharmony_ci#define MAX77650_CHARGER_DISABLED 0x00 1862306a36Sopenharmony_ci#define MAX77650_CHARGER_CHG_EN_MASK BIT(0) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define MAX77650_CHG_DETAILS_MASK GENMASK(7, 4) 2162306a36Sopenharmony_ci#define MAX77650_CHG_DETAILS_BITS(_reg) \ 2262306a36Sopenharmony_ci (((_reg) & MAX77650_CHG_DETAILS_MASK) >> 4) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Charger is OFF. */ 2562306a36Sopenharmony_ci#define MAX77650_CHG_OFF 0x00 2662306a36Sopenharmony_ci/* Charger is in prequalification mode. */ 2762306a36Sopenharmony_ci#define MAX77650_CHG_PREQ 0x01 2862306a36Sopenharmony_ci/* Charger is in fast-charge constant current mode. */ 2962306a36Sopenharmony_ci#define MAX77650_CHG_ON_CURR 0x02 3062306a36Sopenharmony_ci/* Charger is in JEITA modified fast-charge constant-current mode. */ 3162306a36Sopenharmony_ci#define MAX77650_CHG_ON_CURR_JEITA 0x03 3262306a36Sopenharmony_ci/* Charger is in fast-charge constant-voltage mode. */ 3362306a36Sopenharmony_ci#define MAX77650_CHG_ON_VOLT 0x04 3462306a36Sopenharmony_ci/* Charger is in JEITA modified fast-charge constant-voltage mode. */ 3562306a36Sopenharmony_ci#define MAX77650_CHG_ON_VOLT_JEITA 0x05 3662306a36Sopenharmony_ci/* Charger is in top-off mode. */ 3762306a36Sopenharmony_ci#define MAX77650_CHG_ON_TOPOFF 0x06 3862306a36Sopenharmony_ci/* Charger is in JEITA modified top-off mode. */ 3962306a36Sopenharmony_ci#define MAX77650_CHG_ON_TOPOFF_JEITA 0x07 4062306a36Sopenharmony_ci/* Charger is done. */ 4162306a36Sopenharmony_ci#define MAX77650_CHG_DONE 0x08 4262306a36Sopenharmony_ci/* Charger is JEITA modified done. */ 4362306a36Sopenharmony_ci#define MAX77650_CHG_DONE_JEITA 0x09 4462306a36Sopenharmony_ci/* Charger is suspended due to a prequalification timer fault. */ 4562306a36Sopenharmony_ci#define MAX77650_CHG_SUSP_PREQ_TIM_FAULT 0x0a 4662306a36Sopenharmony_ci/* Charger is suspended due to a fast-charge timer fault. */ 4762306a36Sopenharmony_ci#define MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT 0x0b 4862306a36Sopenharmony_ci/* Charger is suspended due to a battery temperature fault. */ 4962306a36Sopenharmony_ci#define MAX77650_CHG_SUSP_BATT_TEMP_FAULT 0x0c 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define MAX77650_CHGIN_DETAILS_MASK GENMASK(3, 2) 5262306a36Sopenharmony_ci#define MAX77650_CHGIN_DETAILS_BITS(_reg) \ 5362306a36Sopenharmony_ci (((_reg) & MAX77650_CHGIN_DETAILS_MASK) >> 2) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT 0x00 5662306a36Sopenharmony_ci#define MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT 0x01 5762306a36Sopenharmony_ci#define MAX77650_CHGIN_OKAY 0x11 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define MAX77650_CHARGER_CHG_MASK BIT(1) 6062306a36Sopenharmony_ci#define MAX77650_CHARGER_CHG_CHARGING(_reg) \ 6162306a36Sopenharmony_ci (((_reg) & MAX77650_CHARGER_CHG_MASK) > 1) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define MAX77650_CHARGER_VCHGIN_MIN_MASK 0xc0 6462306a36Sopenharmony_ci#define MAX77650_CHARGER_VCHGIN_MIN_SHIFT(_val) ((_val) << 5) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define MAX77650_CHARGER_ICHGIN_LIM_MASK 0x1c 6762306a36Sopenharmony_ci#define MAX77650_CHARGER_ICHGIN_LIM_SHIFT(_val) ((_val) << 2) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct max77650_charger_data { 7062306a36Sopenharmony_ci struct regmap *map; 7162306a36Sopenharmony_ci struct device *dev; 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic enum power_supply_property max77650_charger_properties[] = { 7562306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7662306a36Sopenharmony_ci POWER_SUPPLY_PROP_ONLINE, 7762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_TYPE 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic const unsigned int max77650_charger_vchgin_min_table[] = { 8162306a36Sopenharmony_ci 4000000, 4100000, 4200000, 4300000, 4400000, 4500000, 4600000, 4700000 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic const unsigned int max77650_charger_ichgin_lim_table[] = { 8562306a36Sopenharmony_ci 95000, 190000, 285000, 380000, 475000 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic int max77650_charger_set_vchgin_min(struct max77650_charger_data *chg, 8962306a36Sopenharmony_ci unsigned int val) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci int i, rv; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max77650_charger_vchgin_min_table); i++) { 9462306a36Sopenharmony_ci if (val == max77650_charger_vchgin_min_table[i]) { 9562306a36Sopenharmony_ci rv = regmap_update_bits(chg->map, 9662306a36Sopenharmony_ci MAX77650_REG_CNFG_CHG_B, 9762306a36Sopenharmony_ci MAX77650_CHARGER_VCHGIN_MIN_MASK, 9862306a36Sopenharmony_ci MAX77650_CHARGER_VCHGIN_MIN_SHIFT(i)); 9962306a36Sopenharmony_ci if (rv) 10062306a36Sopenharmony_ci return rv; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return -EINVAL; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int max77650_charger_set_ichgin_lim(struct max77650_charger_data *chg, 11062306a36Sopenharmony_ci unsigned int val) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci int i, rv; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max77650_charger_ichgin_lim_table); i++) { 11562306a36Sopenharmony_ci if (val == max77650_charger_ichgin_lim_table[i]) { 11662306a36Sopenharmony_ci rv = regmap_update_bits(chg->map, 11762306a36Sopenharmony_ci MAX77650_REG_CNFG_CHG_B, 11862306a36Sopenharmony_ci MAX77650_CHARGER_ICHGIN_LIM_MASK, 11962306a36Sopenharmony_ci MAX77650_CHARGER_ICHGIN_LIM_SHIFT(i)); 12062306a36Sopenharmony_ci if (rv) 12162306a36Sopenharmony_ci return rv; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return 0; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci return -EINVAL; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic int max77650_charger_enable(struct max77650_charger_data *chg) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci int rv; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci rv = regmap_update_bits(chg->map, 13562306a36Sopenharmony_ci MAX77650_REG_CNFG_CHG_B, 13662306a36Sopenharmony_ci MAX77650_CHARGER_CHG_EN_MASK, 13762306a36Sopenharmony_ci MAX77650_CHARGER_ENABLED); 13862306a36Sopenharmony_ci if (rv) 13962306a36Sopenharmony_ci dev_err(chg->dev, "unable to enable the charger: %d\n", rv); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci return rv; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic void max77650_charger_disable(struct max77650_charger_data *chg) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci int rv; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci rv = regmap_update_bits(chg->map, 14962306a36Sopenharmony_ci MAX77650_REG_CNFG_CHG_B, 15062306a36Sopenharmony_ci MAX77650_CHARGER_CHG_EN_MASK, 15162306a36Sopenharmony_ci MAX77650_CHARGER_DISABLED); 15262306a36Sopenharmony_ci if (rv) 15362306a36Sopenharmony_ci dev_err(chg->dev, "unable to disable the charger: %d\n", rv); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic irqreturn_t max77650_charger_check_status(int irq, void *data) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct max77650_charger_data *chg = data; 15962306a36Sopenharmony_ci int rv, reg; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); 16262306a36Sopenharmony_ci if (rv) { 16362306a36Sopenharmony_ci dev_err(chg->dev, 16462306a36Sopenharmony_ci "unable to read the charger status: %d\n", rv); 16562306a36Sopenharmony_ci return IRQ_HANDLED; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci switch (MAX77650_CHGIN_DETAILS_BITS(reg)) { 16962306a36Sopenharmony_ci case MAX77650_CHGIN_UNDERVOLTAGE_LOCKOUT: 17062306a36Sopenharmony_ci dev_err(chg->dev, "undervoltage lockout detected, disabling charger\n"); 17162306a36Sopenharmony_ci max77650_charger_disable(chg); 17262306a36Sopenharmony_ci break; 17362306a36Sopenharmony_ci case MAX77650_CHGIN_OVERVOLTAGE_LOCKOUT: 17462306a36Sopenharmony_ci dev_err(chg->dev, "overvoltage lockout detected, disabling charger\n"); 17562306a36Sopenharmony_ci max77650_charger_disable(chg); 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci case MAX77650_CHGIN_OKAY: 17862306a36Sopenharmony_ci max77650_charger_enable(chg); 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci default: 18162306a36Sopenharmony_ci /* May be 0x10 - debouncing */ 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return IRQ_HANDLED; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic int max77650_charger_get_property(struct power_supply *psy, 18962306a36Sopenharmony_ci enum power_supply_property psp, 19062306a36Sopenharmony_ci union power_supply_propval *val) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci struct max77650_charger_data *chg = power_supply_get_drvdata(psy); 19362306a36Sopenharmony_ci int rv, reg; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci switch (psp) { 19662306a36Sopenharmony_ci case POWER_SUPPLY_PROP_STATUS: 19762306a36Sopenharmony_ci rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); 19862306a36Sopenharmony_ci if (rv) 19962306a36Sopenharmony_ci return rv; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (MAX77650_CHARGER_CHG_CHARGING(reg)) { 20262306a36Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_CHARGING; 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci switch (MAX77650_CHG_DETAILS_BITS(reg)) { 20762306a36Sopenharmony_ci case MAX77650_CHG_OFF: 20862306a36Sopenharmony_ci case MAX77650_CHG_SUSP_PREQ_TIM_FAULT: 20962306a36Sopenharmony_ci case MAX77650_CHG_SUSP_FAST_CHG_TIM_FAULT: 21062306a36Sopenharmony_ci case MAX77650_CHG_SUSP_BATT_TEMP_FAULT: 21162306a36Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 21262306a36Sopenharmony_ci break; 21362306a36Sopenharmony_ci case MAX77650_CHG_PREQ: 21462306a36Sopenharmony_ci case MAX77650_CHG_ON_CURR: 21562306a36Sopenharmony_ci case MAX77650_CHG_ON_CURR_JEITA: 21662306a36Sopenharmony_ci case MAX77650_CHG_ON_VOLT: 21762306a36Sopenharmony_ci case MAX77650_CHG_ON_VOLT_JEITA: 21862306a36Sopenharmony_ci case MAX77650_CHG_ON_TOPOFF: 21962306a36Sopenharmony_ci case MAX77650_CHG_ON_TOPOFF_JEITA: 22062306a36Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_CHARGING; 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci case MAX77650_CHG_DONE: 22362306a36Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_FULL; 22462306a36Sopenharmony_ci break; 22562306a36Sopenharmony_ci default: 22662306a36Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci break; 22962306a36Sopenharmony_ci case POWER_SUPPLY_PROP_ONLINE: 23062306a36Sopenharmony_ci rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); 23162306a36Sopenharmony_ci if (rv) 23262306a36Sopenharmony_ci return rv; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci val->intval = MAX77650_CHARGER_CHG_CHARGING(reg); 23562306a36Sopenharmony_ci break; 23662306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_TYPE: 23762306a36Sopenharmony_ci rv = regmap_read(chg->map, MAX77650_REG_STAT_CHG_B, ®); 23862306a36Sopenharmony_ci if (rv) 23962306a36Sopenharmony_ci return rv; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (!MAX77650_CHARGER_CHG_CHARGING(reg)) { 24262306a36Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci switch (MAX77650_CHG_DETAILS_BITS(reg)) { 24762306a36Sopenharmony_ci case MAX77650_CHG_PREQ: 24862306a36Sopenharmony_ci case MAX77650_CHG_ON_CURR: 24962306a36Sopenharmony_ci case MAX77650_CHG_ON_CURR_JEITA: 25062306a36Sopenharmony_ci case MAX77650_CHG_ON_VOLT: 25162306a36Sopenharmony_ci case MAX77650_CHG_ON_VOLT_JEITA: 25262306a36Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case MAX77650_CHG_ON_TOPOFF: 25562306a36Sopenharmony_ci case MAX77650_CHG_ON_TOPOFF_JEITA: 25662306a36Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci default: 25962306a36Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci default: 26362306a36Sopenharmony_ci return -EINVAL; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci return 0; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic const struct power_supply_desc max77650_battery_desc = { 27062306a36Sopenharmony_ci .name = "max77650", 27162306a36Sopenharmony_ci .type = POWER_SUPPLY_TYPE_USB, 27262306a36Sopenharmony_ci .get_property = max77650_charger_get_property, 27362306a36Sopenharmony_ci .properties = max77650_charger_properties, 27462306a36Sopenharmony_ci .num_properties = ARRAY_SIZE(max77650_charger_properties), 27562306a36Sopenharmony_ci}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int max77650_charger_probe(struct platform_device *pdev) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct power_supply_config pscfg = {}; 28062306a36Sopenharmony_ci struct max77650_charger_data *chg; 28162306a36Sopenharmony_ci struct power_supply *battery; 28262306a36Sopenharmony_ci struct device *dev, *parent; 28362306a36Sopenharmony_ci int rv, chg_irq, chgin_irq; 28462306a36Sopenharmony_ci unsigned int prop; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci dev = &pdev->dev; 28762306a36Sopenharmony_ci parent = dev->parent; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); 29062306a36Sopenharmony_ci if (!chg) 29162306a36Sopenharmony_ci return -ENOMEM; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci platform_set_drvdata(pdev, chg); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci chg->map = dev_get_regmap(parent, NULL); 29662306a36Sopenharmony_ci if (!chg->map) 29762306a36Sopenharmony_ci return -ENODEV; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci chg->dev = dev; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci pscfg.of_node = dev->of_node; 30262306a36Sopenharmony_ci pscfg.drv_data = chg; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci chg_irq = platform_get_irq_byname(pdev, "CHG"); 30562306a36Sopenharmony_ci if (chg_irq < 0) 30662306a36Sopenharmony_ci return chg_irq; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci chgin_irq = platform_get_irq_byname(pdev, "CHGIN"); 30962306a36Sopenharmony_ci if (chgin_irq < 0) 31062306a36Sopenharmony_ci return chgin_irq; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci rv = devm_request_any_context_irq(dev, chg_irq, 31362306a36Sopenharmony_ci max77650_charger_check_status, 31462306a36Sopenharmony_ci IRQF_ONESHOT, "chg", chg); 31562306a36Sopenharmony_ci if (rv < 0) 31662306a36Sopenharmony_ci return rv; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci rv = devm_request_any_context_irq(dev, chgin_irq, 31962306a36Sopenharmony_ci max77650_charger_check_status, 32062306a36Sopenharmony_ci IRQF_ONESHOT, "chgin", chg); 32162306a36Sopenharmony_ci if (rv < 0) 32262306a36Sopenharmony_ci return rv; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci battery = devm_power_supply_register(dev, 32562306a36Sopenharmony_ci &max77650_battery_desc, &pscfg); 32662306a36Sopenharmony_ci if (IS_ERR(battery)) 32762306a36Sopenharmony_ci return PTR_ERR(battery); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci rv = of_property_read_u32(dev->of_node, 33062306a36Sopenharmony_ci "input-voltage-min-microvolt", &prop); 33162306a36Sopenharmony_ci if (rv == 0) { 33262306a36Sopenharmony_ci rv = max77650_charger_set_vchgin_min(chg, prop); 33362306a36Sopenharmony_ci if (rv) 33462306a36Sopenharmony_ci return rv; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci rv = of_property_read_u32(dev->of_node, 33862306a36Sopenharmony_ci "input-current-limit-microamp", &prop); 33962306a36Sopenharmony_ci if (rv == 0) { 34062306a36Sopenharmony_ci rv = max77650_charger_set_ichgin_lim(chg, prop); 34162306a36Sopenharmony_ci if (rv) 34262306a36Sopenharmony_ci return rv; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return max77650_charger_enable(chg); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int max77650_charger_remove(struct platform_device *pdev) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct max77650_charger_data *chg = platform_get_drvdata(pdev); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci max77650_charger_disable(chg); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic const struct of_device_id max77650_charger_of_match[] = { 35862306a36Sopenharmony_ci { .compatible = "maxim,max77650-charger" }, 35962306a36Sopenharmony_ci { } 36062306a36Sopenharmony_ci}; 36162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max77650_charger_of_match); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_cistatic struct platform_driver max77650_charger_driver = { 36462306a36Sopenharmony_ci .driver = { 36562306a36Sopenharmony_ci .name = "max77650-charger", 36662306a36Sopenharmony_ci .of_match_table = max77650_charger_of_match, 36762306a36Sopenharmony_ci }, 36862306a36Sopenharmony_ci .probe = max77650_charger_probe, 36962306a36Sopenharmony_ci .remove = max77650_charger_remove, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_cimodule_platform_driver(max77650_charger_driver); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ciMODULE_DESCRIPTION("MAXIM 77650/77651 charger driver"); 37462306a36Sopenharmony_ciMODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); 37562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 37662306a36Sopenharmony_ciMODULE_ALIAS("platform:max77650-charger"); 377