18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MP2629 battery charger driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2020 Monolithic Power Systems, Inc 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Saravanan Sekar <sravanhome@gmail.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bits.h> 118c2ecf20Sopenharmony_ci#include <linux/iio/consumer.h> 128c2ecf20Sopenharmony_ci#include <linux/iio/types.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/mp2629.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/power_supply.h> 198c2ecf20Sopenharmony_ci#include <linux/regmap.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define MP2629_REG_INPUT_ILIM 0x00 228c2ecf20Sopenharmony_ci#define MP2629_REG_INPUT_VLIM 0x01 238c2ecf20Sopenharmony_ci#define MP2629_REG_CHARGE_CTRL 0x04 248c2ecf20Sopenharmony_ci#define MP2629_REG_CHARGE_ILIM 0x05 258c2ecf20Sopenharmony_ci#define MP2629_REG_PRECHARGE 0x06 268c2ecf20Sopenharmony_ci#define MP2629_REG_TERM_CURRENT 0x06 278c2ecf20Sopenharmony_ci#define MP2629_REG_CHARGE_VLIM 0x07 288c2ecf20Sopenharmony_ci#define MP2629_REG_TIMER_CTRL 0x08 298c2ecf20Sopenharmony_ci#define MP2629_REG_IMPEDANCE_COMP 0x09 308c2ecf20Sopenharmony_ci#define MP2629_REG_INTERRUPT 0x0b 318c2ecf20Sopenharmony_ci#define MP2629_REG_STATUS 0x0c 328c2ecf20Sopenharmony_ci#define MP2629_REG_FAULT 0x0d 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define MP2629_MASK_INPUT_TYPE GENMASK(7, 5) 358c2ecf20Sopenharmony_ci#define MP2629_MASK_CHARGE_TYPE GENMASK(4, 3) 368c2ecf20Sopenharmony_ci#define MP2629_MASK_CHARGE_CTRL GENMASK(5, 4) 378c2ecf20Sopenharmony_ci#define MP2629_MASK_WDOG_CTRL GENMASK(5, 4) 388c2ecf20Sopenharmony_ci#define MP2629_MASK_IMPEDANCE GENMASK(7, 4) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define MP2629_INPUTSOURCE_CHANGE GENMASK(7, 5) 418c2ecf20Sopenharmony_ci#define MP2629_CHARGING_CHANGE GENMASK(4, 3) 428c2ecf20Sopenharmony_ci#define MP2629_FAULT_BATTERY BIT(3) 438c2ecf20Sopenharmony_ci#define MP2629_FAULT_THERMAL BIT(4) 448c2ecf20Sopenharmony_ci#define MP2629_FAULT_INPUT BIT(5) 458c2ecf20Sopenharmony_ci#define MP2629_FAULT_OTG BIT(6) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define MP2629_MAX_BATT_CAPACITY 100 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define MP2629_PROPS(_idx, _min, _max, _step) \ 508c2ecf20Sopenharmony_ci [_idx] = { \ 518c2ecf20Sopenharmony_ci .min = _min, \ 528c2ecf20Sopenharmony_ci .max = _max, \ 538c2ecf20Sopenharmony_ci .step = _step, \ 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cienum mp2629_source_type { 578c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_NO_INPUT, 588c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_NON_STD, 598c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_SDP, 608c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_CDP, 618c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_DCP, 628c2ecf20Sopenharmony_ci MP2629_SOURCE_TYPE_OTG = 7, 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cienum mp2629_field { 668c2ecf20Sopenharmony_ci INPUT_ILIM, 678c2ecf20Sopenharmony_ci INPUT_VLIM, 688c2ecf20Sopenharmony_ci CHARGE_ILIM, 698c2ecf20Sopenharmony_ci CHARGE_VLIM, 708c2ecf20Sopenharmony_ci PRECHARGE, 718c2ecf20Sopenharmony_ci TERM_CURRENT, 728c2ecf20Sopenharmony_ci MP2629_MAX_FIELD 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistruct mp2629_charger { 768c2ecf20Sopenharmony_ci struct device *dev; 778c2ecf20Sopenharmony_ci int status; 788c2ecf20Sopenharmony_ci int fault; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci struct regmap *regmap; 818c2ecf20Sopenharmony_ci struct regmap_field *regmap_fields[MP2629_MAX_FIELD]; 828c2ecf20Sopenharmony_ci struct mutex lock; 838c2ecf20Sopenharmony_ci struct power_supply *usb; 848c2ecf20Sopenharmony_ci struct power_supply *battery; 858c2ecf20Sopenharmony_ci struct iio_channel *iiochan[MP2629_ADC_CHAN_END]; 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistruct mp2629_prop { 898c2ecf20Sopenharmony_ci int reg; 908c2ecf20Sopenharmony_ci int mask; 918c2ecf20Sopenharmony_ci int min; 928c2ecf20Sopenharmony_ci int max; 938c2ecf20Sopenharmony_ci int step; 948c2ecf20Sopenharmony_ci int shift; 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic enum power_supply_usb_type mp2629_usb_types[] = { 988c2ecf20Sopenharmony_ci POWER_SUPPLY_USB_TYPE_SDP, 998c2ecf20Sopenharmony_ci POWER_SUPPLY_USB_TYPE_DCP, 1008c2ecf20Sopenharmony_ci POWER_SUPPLY_USB_TYPE_CDP, 1018c2ecf20Sopenharmony_ci POWER_SUPPLY_USB_TYPE_PD_DRP, 1028c2ecf20Sopenharmony_ci POWER_SUPPLY_USB_TYPE_UNKNOWN 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic enum power_supply_property mp2629_charger_usb_props[] = { 1068c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ONLINE, 1078c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_USB_TYPE, 1088c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 1098c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 1108c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 1118c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic enum power_supply_property mp2629_charger_bat_props[] = { 1158c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 1168c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 1178c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_TYPE, 1188c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 1198c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 1208c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 1218c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 1228c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 1238c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 1248c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 1258c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 1268c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic struct mp2629_prop props[] = { 1308c2ecf20Sopenharmony_ci MP2629_PROPS(INPUT_ILIM, 100000, 3250000, 50000), 1318c2ecf20Sopenharmony_ci MP2629_PROPS(INPUT_VLIM, 3800000, 5300000, 100000), 1328c2ecf20Sopenharmony_ci MP2629_PROPS(CHARGE_ILIM, 320000, 4520000, 40000), 1338c2ecf20Sopenharmony_ci MP2629_PROPS(CHARGE_VLIM, 3400000, 4670000, 10000), 1348c2ecf20Sopenharmony_ci MP2629_PROPS(PRECHARGE, 120000, 720000, 40000), 1358c2ecf20Sopenharmony_ci MP2629_PROPS(TERM_CURRENT, 80000, 680000, 40000), 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic const struct reg_field mp2629_reg_fields[] = { 1398c2ecf20Sopenharmony_ci [INPUT_ILIM] = REG_FIELD(MP2629_REG_INPUT_ILIM, 0, 5), 1408c2ecf20Sopenharmony_ci [INPUT_VLIM] = REG_FIELD(MP2629_REG_INPUT_VLIM, 0, 3), 1418c2ecf20Sopenharmony_ci [CHARGE_ILIM] = REG_FIELD(MP2629_REG_CHARGE_ILIM, 0, 6), 1428c2ecf20Sopenharmony_ci [CHARGE_VLIM] = REG_FIELD(MP2629_REG_CHARGE_VLIM, 1, 7), 1438c2ecf20Sopenharmony_ci [PRECHARGE] = REG_FIELD(MP2629_REG_PRECHARGE, 4, 7), 1448c2ecf20Sopenharmony_ci [TERM_CURRENT] = REG_FIELD(MP2629_REG_TERM_CURRENT, 0, 3), 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic char *adc_chan_name[] = { 1488c2ecf20Sopenharmony_ci "mp2629-batt-volt", 1498c2ecf20Sopenharmony_ci "mp2629-system-volt", 1508c2ecf20Sopenharmony_ci "mp2629-input-volt", 1518c2ecf20Sopenharmony_ci "mp2629-batt-current", 1528c2ecf20Sopenharmony_ci "mp2629-input-current", 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int mp2629_read_adc(struct mp2629_charger *charger, 1568c2ecf20Sopenharmony_ci enum mp2629_adc_chan ch, 1578c2ecf20Sopenharmony_ci union power_supply_propval *val) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci int ret; 1608c2ecf20Sopenharmony_ci int chval; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci ret = iio_read_channel_processed(charger->iiochan[ch], &chval); 1638c2ecf20Sopenharmony_ci if (ret) 1648c2ecf20Sopenharmony_ci return ret; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci val->intval = chval * 1000; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int mp2629_get_prop(struct mp2629_charger *charger, 1728c2ecf20Sopenharmony_ci enum mp2629_field fld, 1738c2ecf20Sopenharmony_ci union power_supply_propval *val) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci int ret; 1768c2ecf20Sopenharmony_ci unsigned int rval; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci ret = regmap_field_read(charger->regmap_fields[fld], &rval); 1798c2ecf20Sopenharmony_ci if (ret) 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci val->intval = rval * props[fld].step + props[fld].min; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci return 0; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int mp2629_set_prop(struct mp2629_charger *charger, 1888c2ecf20Sopenharmony_ci enum mp2629_field fld, 1898c2ecf20Sopenharmony_ci const union power_supply_propval *val) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci unsigned int rval; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (val->intval < props[fld].min || val->intval > props[fld].max) 1948c2ecf20Sopenharmony_ci return -EINVAL; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci rval = (val->intval - props[fld].min) / props[fld].step; 1978c2ecf20Sopenharmony_ci return regmap_field_write(charger->regmap_fields[fld], rval); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int mp2629_get_battery_capacity(struct mp2629_charger *charger, 2018c2ecf20Sopenharmony_ci union power_supply_propval *val) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci union power_supply_propval vnow, vlim; 2048c2ecf20Sopenharmony_ci int ret; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, &vnow); 2078c2ecf20Sopenharmony_ci if (ret) 2088c2ecf20Sopenharmony_ci return ret; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, CHARGE_VLIM, &vlim); 2118c2ecf20Sopenharmony_ci if (ret) 2128c2ecf20Sopenharmony_ci return ret; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci val->intval = (vnow.intval * 100) / vlim.intval; 2158c2ecf20Sopenharmony_ci val->intval = min(val->intval, MP2629_MAX_BATT_CAPACITY); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return 0; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic int mp2629_charger_battery_get_prop(struct power_supply *psy, 2218c2ecf20Sopenharmony_ci enum power_supply_property psp, 2228c2ecf20Sopenharmony_ci union power_supply_propval *val) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 2258c2ecf20Sopenharmony_ci unsigned int rval; 2268c2ecf20Sopenharmony_ci int ret = 0; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci switch (psp) { 2298c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_NOW: 2308c2ecf20Sopenharmony_ci ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, val); 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CURRENT_NOW: 2348c2ecf20Sopenharmony_ci ret = mp2629_read_adc(charger, MP2629_BATT_CURRENT, val); 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 2388c2ecf20Sopenharmony_ci val->intval = 4520000; 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 2428c2ecf20Sopenharmony_ci val->intval = 4670000; 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CAPACITY: 2468c2ecf20Sopenharmony_ci ret = mp2629_get_battery_capacity(charger, val); 2478c2ecf20Sopenharmony_ci break; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 2508c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, TERM_CURRENT, val); 2518c2ecf20Sopenharmony_ci break; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 2548c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, PRECHARGE, val); 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 2588c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, CHARGE_VLIM, val); 2598c2ecf20Sopenharmony_ci break; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 2628c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, CHARGE_ILIM, val); 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_HEALTH: 2668c2ecf20Sopenharmony_ci if (!charger->fault) 2678c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_HEALTH_GOOD; 2688c2ecf20Sopenharmony_ci if (MP2629_FAULT_BATTERY & charger->fault) 2698c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 2708c2ecf20Sopenharmony_ci else if (MP2629_FAULT_THERMAL & charger->fault) 2718c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 2728c2ecf20Sopenharmony_ci else if (MP2629_FAULT_INPUT & charger->fault) 2738c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 2748c2ecf20Sopenharmony_ci break; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_STATUS: 2778c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 2788c2ecf20Sopenharmony_ci if (ret) 2798c2ecf20Sopenharmony_ci break; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3; 2828c2ecf20Sopenharmony_ci switch (rval) { 2838c2ecf20Sopenharmony_ci case 0x00: 2848c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 2858c2ecf20Sopenharmony_ci break; 2868c2ecf20Sopenharmony_ci case 0x01: 2878c2ecf20Sopenharmony_ci case 0x10: 2888c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_CHARGING; 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci case 0x11: 2918c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_STATUS_FULL; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci break; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_TYPE: 2968c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 2978c2ecf20Sopenharmony_ci if (ret) 2988c2ecf20Sopenharmony_ci break; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3; 3018c2ecf20Sopenharmony_ci switch (rval) { 3028c2ecf20Sopenharmony_ci case 0x00: 3038c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 3048c2ecf20Sopenharmony_ci break; 3058c2ecf20Sopenharmony_ci case 0x01: 3068c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 3078c2ecf20Sopenharmony_ci break; 3088c2ecf20Sopenharmony_ci case 0x10: 3098c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; 3108c2ecf20Sopenharmony_ci break; 3118c2ecf20Sopenharmony_ci default: 3128c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci break; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci default: 3178c2ecf20Sopenharmony_ci return -EINVAL; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci return ret; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic int mp2629_charger_battery_set_prop(struct power_supply *psy, 3248c2ecf20Sopenharmony_ci enum power_supply_property psp, 3258c2ecf20Sopenharmony_ci const union power_supply_propval *val) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci switch (psp) { 3308c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 3318c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, TERM_CURRENT, val); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 3348c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, PRECHARGE, val); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 3378c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, CHARGE_VLIM, val); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 3408c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, CHARGE_ILIM, val); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci default: 3438c2ecf20Sopenharmony_ci return -EINVAL; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int mp2629_charger_usb_get_prop(struct power_supply *psy, 3488c2ecf20Sopenharmony_ci enum power_supply_property psp, 3498c2ecf20Sopenharmony_ci union power_supply_propval *val) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 3528c2ecf20Sopenharmony_ci unsigned int rval; 3538c2ecf20Sopenharmony_ci int ret; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci switch (psp) { 3568c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_ONLINE: 3578c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 3588c2ecf20Sopenharmony_ci if (ret) 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci val->intval = !!(rval & MP2629_MASK_INPUT_TYPE); 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_USB_TYPE: 3658c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 3668c2ecf20Sopenharmony_ci if (ret) 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci rval = (rval & MP2629_MASK_INPUT_TYPE) >> 5; 3708c2ecf20Sopenharmony_ci switch (rval) { 3718c2ecf20Sopenharmony_ci case MP2629_SOURCE_TYPE_SDP: 3728c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_USB_TYPE_SDP; 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci case MP2629_SOURCE_TYPE_CDP: 3758c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_USB_TYPE_CDP; 3768c2ecf20Sopenharmony_ci break; 3778c2ecf20Sopenharmony_ci case MP2629_SOURCE_TYPE_DCP: 3788c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_USB_TYPE_DCP; 3798c2ecf20Sopenharmony_ci break; 3808c2ecf20Sopenharmony_ci case MP2629_SOURCE_TYPE_OTG: 3818c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP; 3828c2ecf20Sopenharmony_ci break; 3838c2ecf20Sopenharmony_ci default: 3848c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; 3858c2ecf20Sopenharmony_ci break; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci break; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_NOW: 3908c2ecf20Sopenharmony_ci ret = mp2629_read_adc(charger, MP2629_INPUT_VOLT, val); 3918c2ecf20Sopenharmony_ci break; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CURRENT_NOW: 3948c2ecf20Sopenharmony_ci ret = mp2629_read_adc(charger, MP2629_INPUT_CURRENT, val); 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 3988c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, INPUT_VLIM, val); 3998c2ecf20Sopenharmony_ci break; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 4028c2ecf20Sopenharmony_ci ret = mp2629_get_prop(charger, INPUT_ILIM, val); 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci default: 4068c2ecf20Sopenharmony_ci return -EINVAL; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci return ret; 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic int mp2629_charger_usb_set_prop(struct power_supply *psy, 4138c2ecf20Sopenharmony_ci enum power_supply_property psp, 4148c2ecf20Sopenharmony_ci const union power_supply_propval *val) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci switch (psp) { 4198c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 4208c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, INPUT_VLIM, val); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 4238c2ecf20Sopenharmony_ci return mp2629_set_prop(charger, INPUT_ILIM, val); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci default: 4268c2ecf20Sopenharmony_ci return -EINVAL; 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int mp2629_charger_battery_prop_writeable(struct power_supply *psy, 4318c2ecf20Sopenharmony_ci enum power_supply_property psp) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci return (psp == POWER_SUPPLY_PROP_PRECHARGE_CURRENT) || 4348c2ecf20Sopenharmony_ci (psp == POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT) || 4358c2ecf20Sopenharmony_ci (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT) || 4368c2ecf20Sopenharmony_ci (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int mp2629_charger_usb_prop_writeable(struct power_supply *psy, 4408c2ecf20Sopenharmony_ci enum power_supply_property psp) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci return (psp == POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT) || 4438c2ecf20Sopenharmony_ci (psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT); 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic irqreturn_t mp2629_irq_handler(int irq, void *dev_id) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_id; 4498c2ecf20Sopenharmony_ci unsigned int rval; 4508c2ecf20Sopenharmony_ci int ret; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci mutex_lock(&charger->lock); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_FAULT, &rval); 4558c2ecf20Sopenharmony_ci if (ret) 4568c2ecf20Sopenharmony_ci goto unlock; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci if (rval) { 4598c2ecf20Sopenharmony_ci charger->fault = rval; 4608c2ecf20Sopenharmony_ci if (MP2629_FAULT_BATTERY & rval) 4618c2ecf20Sopenharmony_ci dev_err(charger->dev, "Battery fault OVP\n"); 4628c2ecf20Sopenharmony_ci else if (MP2629_FAULT_THERMAL & rval) 4638c2ecf20Sopenharmony_ci dev_err(charger->dev, "Thermal shutdown fault\n"); 4648c2ecf20Sopenharmony_ci else if (MP2629_FAULT_INPUT & rval) 4658c2ecf20Sopenharmony_ci dev_err(charger->dev, "no input or input OVP\n"); 4668c2ecf20Sopenharmony_ci else if (MP2629_FAULT_OTG & rval) 4678c2ecf20Sopenharmony_ci dev_err(charger->dev, "VIN overloaded\n"); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci goto unlock; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval); 4738c2ecf20Sopenharmony_ci if (ret) 4748c2ecf20Sopenharmony_ci goto unlock; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci if (rval & MP2629_INPUTSOURCE_CHANGE) 4778c2ecf20Sopenharmony_ci power_supply_changed(charger->usb); 4788c2ecf20Sopenharmony_ci else if (rval & MP2629_CHARGING_CHANGE) 4798c2ecf20Sopenharmony_ci power_supply_changed(charger->battery); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ciunlock: 4828c2ecf20Sopenharmony_ci mutex_unlock(&charger->lock); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic const struct power_supply_desc mp2629_usb_desc = { 4888c2ecf20Sopenharmony_ci .name = "mp2629_usb", 4898c2ecf20Sopenharmony_ci .type = POWER_SUPPLY_TYPE_USB, 4908c2ecf20Sopenharmony_ci .usb_types = mp2629_usb_types, 4918c2ecf20Sopenharmony_ci .num_usb_types = ARRAY_SIZE(mp2629_usb_types), 4928c2ecf20Sopenharmony_ci .properties = mp2629_charger_usb_props, 4938c2ecf20Sopenharmony_ci .num_properties = ARRAY_SIZE(mp2629_charger_usb_props), 4948c2ecf20Sopenharmony_ci .get_property = mp2629_charger_usb_get_prop, 4958c2ecf20Sopenharmony_ci .set_property = mp2629_charger_usb_set_prop, 4968c2ecf20Sopenharmony_ci .property_is_writeable = mp2629_charger_usb_prop_writeable, 4978c2ecf20Sopenharmony_ci}; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic const struct power_supply_desc mp2629_battery_desc = { 5008c2ecf20Sopenharmony_ci .name = "mp2629_battery", 5018c2ecf20Sopenharmony_ci .type = POWER_SUPPLY_TYPE_BATTERY, 5028c2ecf20Sopenharmony_ci .properties = mp2629_charger_bat_props, 5038c2ecf20Sopenharmony_ci .num_properties = ARRAY_SIZE(mp2629_charger_bat_props), 5048c2ecf20Sopenharmony_ci .get_property = mp2629_charger_battery_get_prop, 5058c2ecf20Sopenharmony_ci .set_property = mp2629_charger_battery_set_prop, 5068c2ecf20Sopenharmony_ci .property_is_writeable = mp2629_charger_battery_prop_writeable, 5078c2ecf20Sopenharmony_ci}; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic ssize_t batt_impedance_compensation_show(struct device *dev, 5108c2ecf20Sopenharmony_ci struct device_attribute *attr, 5118c2ecf20Sopenharmony_ci char *buf) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(dev->parent); 5148c2ecf20Sopenharmony_ci unsigned int rval; 5158c2ecf20Sopenharmony_ci int ret; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci ret = regmap_read(charger->regmap, MP2629_REG_IMPEDANCE_COMP, &rval); 5188c2ecf20Sopenharmony_ci if (ret) 5198c2ecf20Sopenharmony_ci return ret; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci rval = (rval >> 4) * 10; 5228c2ecf20Sopenharmony_ci return sprintf(buf, "%d mohm\n", rval); 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic ssize_t batt_impedance_compensation_store(struct device *dev, 5268c2ecf20Sopenharmony_ci struct device_attribute *attr, 5278c2ecf20Sopenharmony_ci const char *buf, 5288c2ecf20Sopenharmony_ci size_t count) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci struct mp2629_charger *charger = dev_get_drvdata(dev->parent); 5318c2ecf20Sopenharmony_ci unsigned int val; 5328c2ecf20Sopenharmony_ci int ret; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci ret = kstrtouint(buf, 10, &val); 5358c2ecf20Sopenharmony_ci if (ret) 5368c2ecf20Sopenharmony_ci return ret; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if (val > 140) 5398c2ecf20Sopenharmony_ci return -ERANGE; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* multiples of 10 mohm so round off */ 5428c2ecf20Sopenharmony_ci val = val / 10; 5438c2ecf20Sopenharmony_ci ret = regmap_update_bits(charger->regmap, MP2629_REG_IMPEDANCE_COMP, 5448c2ecf20Sopenharmony_ci MP2629_MASK_IMPEDANCE, val << 4); 5458c2ecf20Sopenharmony_ci if (ret) 5468c2ecf20Sopenharmony_ci return ret; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return count; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(batt_impedance_compensation); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic struct attribute *mp2629_charger_sysfs_attrs[] = { 5548c2ecf20Sopenharmony_ci &dev_attr_batt_impedance_compensation.attr, 5558c2ecf20Sopenharmony_ci NULL 5568c2ecf20Sopenharmony_ci}; 5578c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(mp2629_charger_sysfs); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic void mp2629_charger_disable(void *data) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci struct mp2629_charger *charger = data; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL, 5648c2ecf20Sopenharmony_ci MP2629_MASK_CHARGE_CTRL, 0); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic int mp2629_charger_probe(struct platform_device *pdev) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 5708c2ecf20Sopenharmony_ci struct mp2629_data *ddata = dev_get_drvdata(dev->parent); 5718c2ecf20Sopenharmony_ci struct mp2629_charger *charger; 5728c2ecf20Sopenharmony_ci struct power_supply_config psy_cfg = {}; 5738c2ecf20Sopenharmony_ci int ret, i, irq; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL); 5768c2ecf20Sopenharmony_ci if (!charger) 5778c2ecf20Sopenharmony_ci return -ENOMEM; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci charger->regmap = ddata->regmap; 5808c2ecf20Sopenharmony_ci charger->dev = dev; 5818c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, charger); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci irq = platform_get_irq_optional(to_platform_device(dev->parent), 0); 5848c2ecf20Sopenharmony_ci if (irq < 0) { 5858c2ecf20Sopenharmony_ci dev_err(dev, "get irq fail: %d\n", irq); 5868c2ecf20Sopenharmony_ci return irq; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci for (i = 0; i < MP2629_MAX_FIELD; i++) { 5908c2ecf20Sopenharmony_ci charger->regmap_fields[i] = devm_regmap_field_alloc(dev, 5918c2ecf20Sopenharmony_ci charger->regmap, mp2629_reg_fields[i]); 5928c2ecf20Sopenharmony_ci if (IS_ERR(charger->regmap_fields[i])) { 5938c2ecf20Sopenharmony_ci dev_err(dev, "regmap field alloc fail %d\n", i); 5948c2ecf20Sopenharmony_ci return PTR_ERR(charger->regmap_fields[i]); 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci for (i = 0; i < MP2629_ADC_CHAN_END; i++) { 5998c2ecf20Sopenharmony_ci charger->iiochan[i] = devm_iio_channel_get(dev, 6008c2ecf20Sopenharmony_ci adc_chan_name[i]); 6018c2ecf20Sopenharmony_ci if (IS_ERR(charger->iiochan[i])) { 6028c2ecf20Sopenharmony_ci dev_err(dev, "iio chan get %s err\n", adc_chan_name[i]); 6038c2ecf20Sopenharmony_ci return PTR_ERR(charger->iiochan[i]); 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci ret = devm_add_action_or_reset(dev, mp2629_charger_disable, charger); 6088c2ecf20Sopenharmony_ci if (ret) 6098c2ecf20Sopenharmony_ci return ret; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci charger->usb = devm_power_supply_register(dev, &mp2629_usb_desc, NULL); 6128c2ecf20Sopenharmony_ci if (IS_ERR(charger->usb)) { 6138c2ecf20Sopenharmony_ci dev_err(dev, "power supply register usb failed\n"); 6148c2ecf20Sopenharmony_ci return PTR_ERR(charger->usb); 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci psy_cfg.drv_data = charger; 6188c2ecf20Sopenharmony_ci psy_cfg.attr_grp = mp2629_charger_sysfs_groups; 6198c2ecf20Sopenharmony_ci charger->battery = devm_power_supply_register(dev, 6208c2ecf20Sopenharmony_ci &mp2629_battery_desc, &psy_cfg); 6218c2ecf20Sopenharmony_ci if (IS_ERR(charger->battery)) { 6228c2ecf20Sopenharmony_ci dev_err(dev, "power supply register battery failed\n"); 6238c2ecf20Sopenharmony_ci return PTR_ERR(charger->battery); 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci ret = regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL, 6278c2ecf20Sopenharmony_ci MP2629_MASK_CHARGE_CTRL, BIT(4)); 6288c2ecf20Sopenharmony_ci if (ret) { 6298c2ecf20Sopenharmony_ci dev_err(dev, "enable charge fail: %d\n", ret); 6308c2ecf20Sopenharmony_ci return ret; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci regmap_update_bits(charger->regmap, MP2629_REG_TIMER_CTRL, 6348c2ecf20Sopenharmony_ci MP2629_MASK_WDOG_CTRL, 0); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci mutex_init(&charger->lock); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(dev, irq, NULL, mp2629_irq_handler, 6398c2ecf20Sopenharmony_ci IRQF_ONESHOT | IRQF_TRIGGER_RISING, 6408c2ecf20Sopenharmony_ci "mp2629-charger", charger); 6418c2ecf20Sopenharmony_ci if (ret) { 6428c2ecf20Sopenharmony_ci dev_err(dev, "failed to request gpio IRQ\n"); 6438c2ecf20Sopenharmony_ci return ret; 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci regmap_update_bits(charger->regmap, MP2629_REG_INTERRUPT, 6478c2ecf20Sopenharmony_ci GENMASK(6, 5), BIT(6) | BIT(5)); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci return 0; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic const struct of_device_id mp2629_charger_of_match[] = { 6538c2ecf20Sopenharmony_ci { .compatible = "mps,mp2629_charger"}, 6548c2ecf20Sopenharmony_ci {} 6558c2ecf20Sopenharmony_ci}; 6568c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mp2629_charger_of_match); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic struct platform_driver mp2629_charger_driver = { 6598c2ecf20Sopenharmony_ci .driver = { 6608c2ecf20Sopenharmony_ci .name = "mp2629_charger", 6618c2ecf20Sopenharmony_ci .of_match_table = mp2629_charger_of_match, 6628c2ecf20Sopenharmony_ci }, 6638c2ecf20Sopenharmony_ci .probe = mp2629_charger_probe, 6648c2ecf20Sopenharmony_ci}; 6658c2ecf20Sopenharmony_cimodule_platform_driver(mp2629_charger_driver); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ciMODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>"); 6688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MP2629 Charger driver"); 6698c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 670