1f71e7375SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29d60595aSAlexander Kurz /* 39d60595aSAlexander Kurz * Maxim MAX14656 / AL32 USB Charger Detector driver 49d60595aSAlexander Kurz * 59d60595aSAlexander Kurz * Copyright (C) 2014 LG Electronics, Inc 69d60595aSAlexander Kurz * Copyright (C) 2016 Alexander Kurz <akurz@blala.de> 79d60595aSAlexander Kurz * 89d60595aSAlexander Kurz * Components from Maxim AL32 Charger detection Driver for MX50 Yoshi Board 99d60595aSAlexander Kurz * Copyright (C) Amazon Technologies Inc. All rights reserved. 109d60595aSAlexander Kurz * Manish Lachwani (lachwani@lab126.com) 119d60595aSAlexander Kurz */ 129d60595aSAlexander Kurz #include <linux/module.h> 139d60595aSAlexander Kurz #include <linux/init.h> 149d60595aSAlexander Kurz #include <linux/delay.h> 159d60595aSAlexander Kurz #include <linux/i2c.h> 169d60595aSAlexander Kurz #include <linux/interrupt.h> 17*2ce8284cSRob Herring #include <linux/mod_devicetable.h> 189d60595aSAlexander Kurz #include <linux/slab.h> 199d60595aSAlexander Kurz #include <linux/workqueue.h> 209d60595aSAlexander Kurz #include <linux/power_supply.h> 21d016fc7aSChristophe JAILLET #include <linux/devm-helpers.h> 229d60595aSAlexander Kurz 239d60595aSAlexander Kurz #define MAX14656_MANUFACTURER "Maxim Integrated" 249d60595aSAlexander Kurz #define MAX14656_NAME "max14656" 259d60595aSAlexander Kurz 269d60595aSAlexander Kurz #define MAX14656_DEVICE_ID 0x00 279d60595aSAlexander Kurz #define MAX14656_INTERRUPT_1 0x01 289d60595aSAlexander Kurz #define MAX14656_INTERRUPT_2 0x02 299d60595aSAlexander Kurz #define MAX14656_STATUS_1 0x03 309d60595aSAlexander Kurz #define MAX14656_STATUS_2 0x04 319d60595aSAlexander Kurz #define MAX14656_INTMASK_1 0x05 329d60595aSAlexander Kurz #define MAX14656_INTMASK_2 0x06 339d60595aSAlexander Kurz #define MAX14656_CONTROL_1 0x07 349d60595aSAlexander Kurz #define MAX14656_CONTROL_2 0x08 359d60595aSAlexander Kurz #define MAX14656_CONTROL_3 0x09 369d60595aSAlexander Kurz 379d60595aSAlexander Kurz #define DEVICE_VENDOR_MASK 0xf0 389d60595aSAlexander Kurz #define DEVICE_REV_MASK 0x0f 399d60595aSAlexander Kurz #define INT_EN_REG_MASK BIT(4) 409d60595aSAlexander Kurz #define CHG_TYPE_INT_MASK BIT(0) 419d60595aSAlexander Kurz #define STATUS1_VB_VALID_MASK BIT(4) 429d60595aSAlexander Kurz #define STATUS1_CHG_TYPE_MASK 0xf 439d60595aSAlexander Kurz #define INT1_DCD_TIMEOUT_MASK BIT(7) 449d60595aSAlexander Kurz #define CONTROL1_DEFAULT 0x0d 459d60595aSAlexander Kurz #define CONTROL1_INT_EN BIT(4) 469d60595aSAlexander Kurz #define CONTROL1_INT_ACTIVE_HIGH BIT(5) 479d60595aSAlexander Kurz #define CONTROL1_EDGE BIT(7) 489d60595aSAlexander Kurz #define CONTROL2_DEFAULT 0x8e 499d60595aSAlexander Kurz #define CONTROL2_ADC_EN BIT(0) 509d60595aSAlexander Kurz #define CONTROL3_DEFAULT 0x8d 519d60595aSAlexander Kurz 529d60595aSAlexander Kurz enum max14656_chg_type { 539d60595aSAlexander Kurz MAX14656_NO_CHARGER = 0, 549d60595aSAlexander Kurz MAX14656_SDP_CHARGER, 559d60595aSAlexander Kurz MAX14656_CDP_CHARGER, 569d60595aSAlexander Kurz MAX14656_DCP_CHARGER, 579d60595aSAlexander Kurz MAX14656_APPLE_500MA_CHARGER, 589d60595aSAlexander Kurz MAX14656_APPLE_1A_CHARGER, 599d60595aSAlexander Kurz MAX14656_APPLE_2A_CHARGER, 609d60595aSAlexander Kurz MAX14656_SPECIAL_500MA_CHARGER, 619d60595aSAlexander Kurz MAX14656_APPLE_12W, 629d60595aSAlexander Kurz MAX14656_CHARGER_LAST 639d60595aSAlexander Kurz }; 649d60595aSAlexander Kurz 659d60595aSAlexander Kurz static const struct max14656_chg_type_props { 669d60595aSAlexander Kurz enum power_supply_type type; 679d60595aSAlexander Kurz } chg_type_props[] = { 689d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_UNKNOWN }, 699d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB }, 709d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_CDP }, 719d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_DCP }, 729d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_DCP }, 739d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_DCP }, 749d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_DCP }, 759d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB_DCP }, 769d60595aSAlexander Kurz { POWER_SUPPLY_TYPE_USB }, 779d60595aSAlexander Kurz }; 789d60595aSAlexander Kurz 799d60595aSAlexander Kurz struct max14656_chip { 809d60595aSAlexander Kurz struct i2c_client *client; 819d60595aSAlexander Kurz struct power_supply *detect_psy; 829d60595aSAlexander Kurz struct power_supply_desc psy_desc; 839d60595aSAlexander Kurz struct delayed_work irq_work; 849d60595aSAlexander Kurz 859d60595aSAlexander Kurz int irq; 869d60595aSAlexander Kurz int online; 879d60595aSAlexander Kurz }; 889d60595aSAlexander Kurz 899d60595aSAlexander Kurz static int max14656_read_reg(struct i2c_client *client, int reg, u8 *val) 909d60595aSAlexander Kurz { 919d60595aSAlexander Kurz s32 ret; 929d60595aSAlexander Kurz 939d60595aSAlexander Kurz ret = i2c_smbus_read_byte_data(client, reg); 949d60595aSAlexander Kurz if (ret < 0) { 959d60595aSAlexander Kurz dev_err(&client->dev, 969d60595aSAlexander Kurz "i2c read fail: can't read from %02x: %d\n", 979d60595aSAlexander Kurz reg, ret); 989d60595aSAlexander Kurz return ret; 999d60595aSAlexander Kurz } 1009d60595aSAlexander Kurz *val = ret; 1019d60595aSAlexander Kurz return 0; 1029d60595aSAlexander Kurz } 1039d60595aSAlexander Kurz 1049d60595aSAlexander Kurz static int max14656_write_reg(struct i2c_client *client, int reg, u8 val) 1059d60595aSAlexander Kurz { 1069d60595aSAlexander Kurz s32 ret; 1079d60595aSAlexander Kurz 1089d60595aSAlexander Kurz ret = i2c_smbus_write_byte_data(client, reg, val); 1099d60595aSAlexander Kurz if (ret < 0) { 1109d60595aSAlexander Kurz dev_err(&client->dev, 1119d60595aSAlexander Kurz "i2c write fail: can't write %02x to %02x: %d\n", 1129d60595aSAlexander Kurz val, reg, ret); 1139d60595aSAlexander Kurz return ret; 1149d60595aSAlexander Kurz } 1159d60595aSAlexander Kurz return 0; 1169d60595aSAlexander Kurz } 1179d60595aSAlexander Kurz 1189d60595aSAlexander Kurz static int max14656_read_block_reg(struct i2c_client *client, u8 reg, 1199d60595aSAlexander Kurz u8 length, u8 *val) 1209d60595aSAlexander Kurz { 1219d60595aSAlexander Kurz int ret; 1229d60595aSAlexander Kurz 1239d60595aSAlexander Kurz ret = i2c_smbus_read_i2c_block_data(client, reg, length, val); 1249d60595aSAlexander Kurz if (ret < 0) { 1259d60595aSAlexander Kurz dev_err(&client->dev, "failed to block read reg 0x%x: %d\n", 1269d60595aSAlexander Kurz reg, ret); 1279d60595aSAlexander Kurz return ret; 1289d60595aSAlexander Kurz } 1299d60595aSAlexander Kurz 1309d60595aSAlexander Kurz return 0; 1319d60595aSAlexander Kurz } 1329d60595aSAlexander Kurz 1339d60595aSAlexander Kurz #define REG_TOTAL_NUM 5 1349d60595aSAlexander Kurz static void max14656_irq_worker(struct work_struct *work) 1359d60595aSAlexander Kurz { 1369d60595aSAlexander Kurz struct max14656_chip *chip = 1379d60595aSAlexander Kurz container_of(work, struct max14656_chip, irq_work.work); 1389d60595aSAlexander Kurz 1399d60595aSAlexander Kurz u8 buf[REG_TOTAL_NUM]; 1409d60595aSAlexander Kurz u8 chg_type; 1419d60595aSAlexander Kurz 142f05ec507SJason Yan max14656_read_block_reg(chip->client, MAX14656_DEVICE_ID, 1439d60595aSAlexander Kurz REG_TOTAL_NUM, buf); 1449d60595aSAlexander Kurz 1459d60595aSAlexander Kurz if ((buf[MAX14656_STATUS_1] & STATUS1_VB_VALID_MASK) && 1469d60595aSAlexander Kurz (buf[MAX14656_STATUS_1] & STATUS1_CHG_TYPE_MASK)) { 1479d60595aSAlexander Kurz chg_type = buf[MAX14656_STATUS_1] & STATUS1_CHG_TYPE_MASK; 1489d60595aSAlexander Kurz if (chg_type < MAX14656_CHARGER_LAST) 1499d60595aSAlexander Kurz chip->psy_desc.type = chg_type_props[chg_type].type; 1509d60595aSAlexander Kurz else 1519d60595aSAlexander Kurz chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; 1529d60595aSAlexander Kurz chip->online = 1; 1539d60595aSAlexander Kurz } else { 1549d60595aSAlexander Kurz chip->online = 0; 1559d60595aSAlexander Kurz chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; 1569d60595aSAlexander Kurz } 1579d60595aSAlexander Kurz 1589d60595aSAlexander Kurz power_supply_changed(chip->detect_psy); 1599d60595aSAlexander Kurz } 1609d60595aSAlexander Kurz 1619d60595aSAlexander Kurz static irqreturn_t max14656_irq(int irq, void *dev_id) 1629d60595aSAlexander Kurz { 1639d60595aSAlexander Kurz struct max14656_chip *chip = dev_id; 1649d60595aSAlexander Kurz 1659d60595aSAlexander Kurz schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(100)); 1669d60595aSAlexander Kurz 1679d60595aSAlexander Kurz return IRQ_HANDLED; 1689d60595aSAlexander Kurz } 1699d60595aSAlexander Kurz 1709d60595aSAlexander Kurz static int max14656_hw_init(struct max14656_chip *chip) 1719d60595aSAlexander Kurz { 1729d60595aSAlexander Kurz uint8_t val = 0; 1739d60595aSAlexander Kurz uint8_t rev; 1749d60595aSAlexander Kurz struct i2c_client *client = chip->client; 1759d60595aSAlexander Kurz 1769d60595aSAlexander Kurz if (max14656_read_reg(client, MAX14656_DEVICE_ID, &val)) 1779d60595aSAlexander Kurz return -ENODEV; 1789d60595aSAlexander Kurz 1799d60595aSAlexander Kurz if ((val & DEVICE_VENDOR_MASK) != 0x20) { 1809d60595aSAlexander Kurz dev_err(&client->dev, "wrong vendor ID %d\n", 1819d60595aSAlexander Kurz ((val & DEVICE_VENDOR_MASK) >> 4)); 1829d60595aSAlexander Kurz return -ENODEV; 1839d60595aSAlexander Kurz } 1849d60595aSAlexander Kurz rev = val & DEVICE_REV_MASK; 1859d60595aSAlexander Kurz 1869d60595aSAlexander Kurz /* Turn on ADC_EN */ 1879d60595aSAlexander Kurz if (max14656_write_reg(client, MAX14656_CONTROL_2, CONTROL2_ADC_EN)) 1889d60595aSAlexander Kurz return -EINVAL; 1899d60595aSAlexander Kurz 1909d60595aSAlexander Kurz /* turn on interrupts and low power mode */ 1919d60595aSAlexander Kurz if (max14656_write_reg(client, MAX14656_CONTROL_1, 1929d60595aSAlexander Kurz CONTROL1_DEFAULT | 1939d60595aSAlexander Kurz CONTROL1_INT_EN | 1949d60595aSAlexander Kurz CONTROL1_INT_ACTIVE_HIGH | 1959d60595aSAlexander Kurz CONTROL1_EDGE)) 1969d60595aSAlexander Kurz return -EINVAL; 1979d60595aSAlexander Kurz 1989d60595aSAlexander Kurz if (max14656_write_reg(client, MAX14656_INTMASK_1, 0x3)) 1999d60595aSAlexander Kurz return -EINVAL; 2009d60595aSAlexander Kurz 2019d60595aSAlexander Kurz if (max14656_write_reg(client, MAX14656_INTMASK_2, 0x1)) 2029d60595aSAlexander Kurz return -EINVAL; 2039d60595aSAlexander Kurz 2049d60595aSAlexander Kurz dev_info(&client->dev, "detected revision %d\n", rev); 2059d60595aSAlexander Kurz return 0; 2069d60595aSAlexander Kurz } 2079d60595aSAlexander Kurz 2089d60595aSAlexander Kurz static int max14656_get_property(struct power_supply *psy, 2099d60595aSAlexander Kurz enum power_supply_property psp, 2109d60595aSAlexander Kurz union power_supply_propval *val) 2119d60595aSAlexander Kurz { 2129d60595aSAlexander Kurz struct max14656_chip *chip = power_supply_get_drvdata(psy); 2139d60595aSAlexander Kurz 2149d60595aSAlexander Kurz switch (psp) { 2159d60595aSAlexander Kurz case POWER_SUPPLY_PROP_ONLINE: 2169d60595aSAlexander Kurz val->intval = chip->online; 2179d60595aSAlexander Kurz break; 2189d60595aSAlexander Kurz case POWER_SUPPLY_PROP_MODEL_NAME: 2199d60595aSAlexander Kurz val->strval = MAX14656_NAME; 2209d60595aSAlexander Kurz break; 2219d60595aSAlexander Kurz case POWER_SUPPLY_PROP_MANUFACTURER: 2229d60595aSAlexander Kurz val->strval = MAX14656_MANUFACTURER; 2239d60595aSAlexander Kurz break; 2249d60595aSAlexander Kurz default: 2259d60595aSAlexander Kurz return -EINVAL; 2269d60595aSAlexander Kurz } 2279d60595aSAlexander Kurz 2289d60595aSAlexander Kurz return 0; 2299d60595aSAlexander Kurz } 2309d60595aSAlexander Kurz 2319d60595aSAlexander Kurz static enum power_supply_property max14656_battery_props[] = { 2329d60595aSAlexander Kurz POWER_SUPPLY_PROP_ONLINE, 2339d60595aSAlexander Kurz POWER_SUPPLY_PROP_MODEL_NAME, 2349d60595aSAlexander Kurz POWER_SUPPLY_PROP_MANUFACTURER, 2359d60595aSAlexander Kurz }; 2369d60595aSAlexander Kurz 237b17018deSUwe Kleine-König static int max14656_probe(struct i2c_client *client) 2389d60595aSAlexander Kurz { 23971d7ffb2SWolfram Sang struct i2c_adapter *adapter = client->adapter; 2409d60595aSAlexander Kurz struct device *dev = &client->dev; 2419d60595aSAlexander Kurz struct power_supply_config psy_cfg = {}; 2429d60595aSAlexander Kurz struct max14656_chip *chip; 2439d60595aSAlexander Kurz int irq = client->irq; 2449d60595aSAlexander Kurz int ret = 0; 2459d60595aSAlexander Kurz 2469d60595aSAlexander Kurz if (irq <= 0) { 2479d60595aSAlexander Kurz dev_err(dev, "invalid irq number: %d\n", irq); 2489d60595aSAlexander Kurz return -ENODEV; 2499d60595aSAlexander Kurz } 2509d60595aSAlexander Kurz 2519d60595aSAlexander Kurz if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 2529d60595aSAlexander Kurz dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); 2539d60595aSAlexander Kurz return -ENODEV; 2549d60595aSAlexander Kurz } 2559d60595aSAlexander Kurz 2569d60595aSAlexander Kurz chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 2579d60595aSAlexander Kurz if (!chip) 2589d60595aSAlexander Kurz return -ENOMEM; 2599d60595aSAlexander Kurz 2609d60595aSAlexander Kurz psy_cfg.drv_data = chip; 2619d60595aSAlexander Kurz chip->client = client; 2629d60595aSAlexander Kurz chip->online = 0; 2639d60595aSAlexander Kurz chip->psy_desc.name = MAX14656_NAME; 2649d60595aSAlexander Kurz chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN; 2659d60595aSAlexander Kurz chip->psy_desc.properties = max14656_battery_props; 2669d60595aSAlexander Kurz chip->psy_desc.num_properties = ARRAY_SIZE(max14656_battery_props); 2679d60595aSAlexander Kurz chip->psy_desc.get_property = max14656_get_property; 2689d60595aSAlexander Kurz chip->irq = irq; 2699d60595aSAlexander Kurz 2709d60595aSAlexander Kurz ret = max14656_hw_init(chip); 2719d60595aSAlexander Kurz if (ret) 2729d60595aSAlexander Kurz return -ENODEV; 2739d60595aSAlexander Kurz 2740cd0e497SSven Van Asbroeck chip->detect_psy = devm_power_supply_register(dev, 2750cd0e497SSven Van Asbroeck &chip->psy_desc, &psy_cfg); 2760cd0e497SSven Van Asbroeck if (IS_ERR(chip->detect_psy)) { 2770cd0e497SSven Van Asbroeck dev_err(dev, "power_supply_register failed\n"); 2780cd0e497SSven Van Asbroeck return -EINVAL; 2790cd0e497SSven Van Asbroeck } 2800cd0e497SSven Van Asbroeck 281d016fc7aSChristophe JAILLET ret = devm_delayed_work_autocancel(dev, &chip->irq_work, 282d016fc7aSChristophe JAILLET max14656_irq_worker); 283252fbeb8SSven Van Asbroeck if (ret) { 284d016fc7aSChristophe JAILLET dev_err(dev, "devm_delayed_work_autocancel %d failed\n", ret); 285252fbeb8SSven Van Asbroeck return ret; 286252fbeb8SSven Van Asbroeck } 287252fbeb8SSven Van Asbroeck 2889d60595aSAlexander Kurz ret = devm_request_irq(dev, chip->irq, max14656_irq, 2899d60595aSAlexander Kurz IRQF_TRIGGER_FALLING, 2909d60595aSAlexander Kurz MAX14656_NAME, chip); 2919d60595aSAlexander Kurz if (ret) { 2929d60595aSAlexander Kurz dev_err(dev, "request_irq %d failed\n", chip->irq); 2939d60595aSAlexander Kurz return -EINVAL; 2949d60595aSAlexander Kurz } 2959d60595aSAlexander Kurz enable_irq_wake(chip->irq); 2969d60595aSAlexander Kurz 2979d60595aSAlexander Kurz schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(2000)); 2989d60595aSAlexander Kurz 2999d60595aSAlexander Kurz return 0; 3009d60595aSAlexander Kurz } 3019d60595aSAlexander Kurz 3029d60595aSAlexander Kurz static const struct i2c_device_id max14656_id[] = { 3039d60595aSAlexander Kurz { "max14656", 0 }, 3049d60595aSAlexander Kurz {} 3059d60595aSAlexander Kurz }; 306166e8dbdSJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, max14656_id); 3079d60595aSAlexander Kurz 3089d60595aSAlexander Kurz static const struct of_device_id max14656_match_table[] = { 3099d60595aSAlexander Kurz { .compatible = "maxim,max14656", }, 3109d60595aSAlexander Kurz {} 3119d60595aSAlexander Kurz }; 312166e8dbdSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, max14656_match_table); 3139d60595aSAlexander Kurz 3149d60595aSAlexander Kurz static struct i2c_driver max14656_i2c_driver = { 3159d60595aSAlexander Kurz .driver = { 3169d60595aSAlexander Kurz .name = "max14656", 3179d60595aSAlexander Kurz .of_match_table = max14656_match_table, 3189d60595aSAlexander Kurz }, 319fe20b1dcSUwe Kleine-König .probe = max14656_probe, 3209d60595aSAlexander Kurz .id_table = max14656_id, 3219d60595aSAlexander Kurz }; 3229d60595aSAlexander Kurz module_i2c_driver(max14656_i2c_driver); 3239d60595aSAlexander Kurz 3249d60595aSAlexander Kurz MODULE_DESCRIPTION("MAX14656 USB charger detector"); 3259d60595aSAlexander Kurz MODULE_LICENSE("GPL v2"); 326