162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// max8997.c - mfd core driver for the Maxim 8966 and 8997 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (C) 2011 Samsung Electronics 662306a36Sopenharmony_ci// MyungJoo Ham <myungjoo.ham@samsung.com> 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// This driver is based on max8998.c 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/err.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/of.h> 1462306a36Sopenharmony_ci#include <linux/of_irq.h> 1562306a36Sopenharmony_ci#include <linux/interrupt.h> 1662306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/mutex.h> 1962306a36Sopenharmony_ci#include <linux/mfd/core.h> 2062306a36Sopenharmony_ci#include <linux/mfd/max8997.h> 2162306a36Sopenharmony_ci#include <linux/mfd/max8997-private.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define I2C_ADDR_PMIC (0xCC >> 1) 2462306a36Sopenharmony_ci#define I2C_ADDR_MUIC (0x4A >> 1) 2562306a36Sopenharmony_ci#define I2C_ADDR_BATTERY (0x6C >> 1) 2662306a36Sopenharmony_ci#define I2C_ADDR_RTC (0x0C >> 1) 2762306a36Sopenharmony_ci#define I2C_ADDR_HAPTIC (0x90 >> 1) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic const struct mfd_cell max8997_devs[] = { 3062306a36Sopenharmony_ci { .name = "max8997-pmic", }, 3162306a36Sopenharmony_ci { .name = "max8997-rtc", }, 3262306a36Sopenharmony_ci { .name = "max8997-battery", }, 3362306a36Sopenharmony_ci { .name = "max8997-haptic", }, 3462306a36Sopenharmony_ci { .name = "max8997-muic", }, 3562306a36Sopenharmony_ci { .name = "max8997-led", .id = 1 }, 3662306a36Sopenharmony_ci { .name = "max8997-led", .id = 2 }, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#ifdef CONFIG_OF 4062306a36Sopenharmony_cistatic const struct of_device_id max8997_pmic_dt_match[] = { 4162306a36Sopenharmony_ci { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, 4262306a36Sopenharmony_ci {}, 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci#endif 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciint max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 4962306a36Sopenharmony_ci int ret; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci mutex_lock(&max8997->iolock); 5262306a36Sopenharmony_ci ret = i2c_smbus_read_byte_data(i2c, reg); 5362306a36Sopenharmony_ci mutex_unlock(&max8997->iolock); 5462306a36Sopenharmony_ci if (ret < 0) 5562306a36Sopenharmony_ci return ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci ret &= 0xff; 5862306a36Sopenharmony_ci *dest = ret; 5962306a36Sopenharmony_ci return 0; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(max8997_read_reg); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciint max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 6662306a36Sopenharmony_ci int ret; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci mutex_lock(&max8997->iolock); 6962306a36Sopenharmony_ci ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf); 7062306a36Sopenharmony_ci mutex_unlock(&max8997->iolock); 7162306a36Sopenharmony_ci if (ret < 0) 7262306a36Sopenharmony_ci return ret; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return 0; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(max8997_bulk_read); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciint max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 8162306a36Sopenharmony_ci int ret; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci mutex_lock(&max8997->iolock); 8462306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(i2c, reg, value); 8562306a36Sopenharmony_ci mutex_unlock(&max8997->iolock); 8662306a36Sopenharmony_ci return ret; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(max8997_write_reg); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciint max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 9362306a36Sopenharmony_ci int ret; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci mutex_lock(&max8997->iolock); 9662306a36Sopenharmony_ci ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf); 9762306a36Sopenharmony_ci mutex_unlock(&max8997->iolock); 9862306a36Sopenharmony_ci if (ret < 0) 9962306a36Sopenharmony_ci return ret; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return 0; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(max8997_bulk_write); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciint max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 10862306a36Sopenharmony_ci int ret; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci mutex_lock(&max8997->iolock); 11162306a36Sopenharmony_ci ret = i2c_smbus_read_byte_data(i2c, reg); 11262306a36Sopenharmony_ci if (ret >= 0) { 11362306a36Sopenharmony_ci u8 old_val = ret & 0xff; 11462306a36Sopenharmony_ci u8 new_val = (val & mask) | (old_val & (~mask)); 11562306a36Sopenharmony_ci ret = i2c_smbus_write_byte_data(i2c, reg, new_val); 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci mutex_unlock(&max8997->iolock); 11862306a36Sopenharmony_ci return ret; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(max8997_update_reg); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* 12362306a36Sopenharmony_ci * Only the common platform data elements for max8997 are parsed here from the 12462306a36Sopenharmony_ci * device tree. Other sub-modules of max8997 such as pmic, rtc and others have 12562306a36Sopenharmony_ci * to parse their own platform data elements from device tree. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * The max8997 platform data structure is instantiated here and the drivers for 12862306a36Sopenharmony_ci * the sub-modules need not instantiate another instance while parsing their 12962306a36Sopenharmony_ci * platform data. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_cistatic struct max8997_platform_data *max8997_i2c_parse_dt_pdata( 13262306a36Sopenharmony_ci struct device *dev) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct max8997_platform_data *pd; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 13762306a36Sopenharmony_ci if (!pd) 13862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci pd->ono = irq_of_parse_and_map(dev->of_node, 1); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return pd; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, 14662306a36Sopenharmony_ci const struct i2c_device_id *id) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if (i2c->dev.of_node) 14962306a36Sopenharmony_ci return (unsigned long)of_device_get_match_data(&i2c->dev); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return id->driver_data; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic int max8997_i2c_probe(struct i2c_client *i2c) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 15762306a36Sopenharmony_ci struct max8997_dev *max8997; 15862306a36Sopenharmony_ci struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev); 15962306a36Sopenharmony_ci int ret = 0; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci max8997 = devm_kzalloc(&i2c->dev, sizeof(struct max8997_dev), 16262306a36Sopenharmony_ci GFP_KERNEL); 16362306a36Sopenharmony_ci if (max8997 == NULL) 16462306a36Sopenharmony_ci return -ENOMEM; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci i2c_set_clientdata(i2c, max8997); 16762306a36Sopenharmony_ci max8997->dev = &i2c->dev; 16862306a36Sopenharmony_ci max8997->i2c = i2c; 16962306a36Sopenharmony_ci max8997->type = max8997_i2c_get_driver_data(i2c, id); 17062306a36Sopenharmony_ci max8997->irq = i2c->irq; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) { 17362306a36Sopenharmony_ci pdata = max8997_i2c_parse_dt_pdata(max8997->dev); 17462306a36Sopenharmony_ci if (IS_ERR(pdata)) 17562306a36Sopenharmony_ci return PTR_ERR(pdata); 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (!pdata) 17962306a36Sopenharmony_ci return ret; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci max8997->pdata = pdata; 18262306a36Sopenharmony_ci max8997->ono = pdata->ono; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci mutex_init(&max8997->iolock); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci max8997->rtc = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_RTC); 18762306a36Sopenharmony_ci if (IS_ERR(max8997->rtc)) { 18862306a36Sopenharmony_ci dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n"); 18962306a36Sopenharmony_ci return PTR_ERR(max8997->rtc); 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci i2c_set_clientdata(max8997->rtc, max8997); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci max8997->haptic = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_HAPTIC); 19462306a36Sopenharmony_ci if (IS_ERR(max8997->haptic)) { 19562306a36Sopenharmony_ci dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n"); 19662306a36Sopenharmony_ci ret = PTR_ERR(max8997->haptic); 19762306a36Sopenharmony_ci goto err_i2c_haptic; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci i2c_set_clientdata(max8997->haptic, max8997); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci max8997->muic = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_MUIC); 20262306a36Sopenharmony_ci if (IS_ERR(max8997->muic)) { 20362306a36Sopenharmony_ci dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n"); 20462306a36Sopenharmony_ci ret = PTR_ERR(max8997->muic); 20562306a36Sopenharmony_ci goto err_i2c_muic; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci i2c_set_clientdata(max8997->muic, max8997); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci pm_runtime_set_active(max8997->dev); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci max8997_irq_init(max8997); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci ret = mfd_add_devices(max8997->dev, -1, max8997_devs, 21462306a36Sopenharmony_ci ARRAY_SIZE(max8997_devs), 21562306a36Sopenharmony_ci NULL, 0, NULL); 21662306a36Sopenharmony_ci if (ret < 0) { 21762306a36Sopenharmony_ci dev_err(max8997->dev, "failed to add MFD devices %d\n", ret); 21862306a36Sopenharmony_ci goto err_mfd; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* 22262306a36Sopenharmony_ci * TODO: enable others (flash, muic, rtc, battery, ...) and 22362306a36Sopenharmony_ci * check the return value 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* MAX8997 has a power button input. */ 22762306a36Sopenharmony_ci device_init_wakeup(max8997->dev, true); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cierr_mfd: 23262306a36Sopenharmony_ci mfd_remove_devices(max8997->dev); 23362306a36Sopenharmony_ci i2c_unregister_device(max8997->muic); 23462306a36Sopenharmony_cierr_i2c_muic: 23562306a36Sopenharmony_ci i2c_unregister_device(max8997->haptic); 23662306a36Sopenharmony_cierr_i2c_haptic: 23762306a36Sopenharmony_ci i2c_unregister_device(max8997->rtc); 23862306a36Sopenharmony_ci return ret; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const struct i2c_device_id max8997_i2c_id[] = { 24262306a36Sopenharmony_ci { "max8997", TYPE_MAX8997 }, 24362306a36Sopenharmony_ci { "max8966", TYPE_MAX8966 }, 24462306a36Sopenharmony_ci { } 24562306a36Sopenharmony_ci}; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic u8 max8997_dumpaddr_pmic[] = { 24862306a36Sopenharmony_ci MAX8997_REG_INT1MSK, 24962306a36Sopenharmony_ci MAX8997_REG_INT2MSK, 25062306a36Sopenharmony_ci MAX8997_REG_INT3MSK, 25162306a36Sopenharmony_ci MAX8997_REG_INT4MSK, 25262306a36Sopenharmony_ci MAX8997_REG_MAINCON1, 25362306a36Sopenharmony_ci MAX8997_REG_MAINCON2, 25462306a36Sopenharmony_ci MAX8997_REG_BUCKRAMP, 25562306a36Sopenharmony_ci MAX8997_REG_BUCK1CTRL, 25662306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS1, 25762306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS2, 25862306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS3, 25962306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS4, 26062306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS5, 26162306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS6, 26262306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS7, 26362306a36Sopenharmony_ci MAX8997_REG_BUCK1DVS8, 26462306a36Sopenharmony_ci MAX8997_REG_BUCK2CTRL, 26562306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS1, 26662306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS2, 26762306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS3, 26862306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS4, 26962306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS5, 27062306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS6, 27162306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS7, 27262306a36Sopenharmony_ci MAX8997_REG_BUCK2DVS8, 27362306a36Sopenharmony_ci MAX8997_REG_BUCK3CTRL, 27462306a36Sopenharmony_ci MAX8997_REG_BUCK3DVS, 27562306a36Sopenharmony_ci MAX8997_REG_BUCK4CTRL, 27662306a36Sopenharmony_ci MAX8997_REG_BUCK4DVS, 27762306a36Sopenharmony_ci MAX8997_REG_BUCK5CTRL, 27862306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS1, 27962306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS2, 28062306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS3, 28162306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS4, 28262306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS5, 28362306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS6, 28462306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS7, 28562306a36Sopenharmony_ci MAX8997_REG_BUCK5DVS8, 28662306a36Sopenharmony_ci MAX8997_REG_BUCK6CTRL, 28762306a36Sopenharmony_ci MAX8997_REG_BUCK6BPSKIPCTRL, 28862306a36Sopenharmony_ci MAX8997_REG_BUCK7CTRL, 28962306a36Sopenharmony_ci MAX8997_REG_BUCK7DVS, 29062306a36Sopenharmony_ci MAX8997_REG_LDO1CTRL, 29162306a36Sopenharmony_ci MAX8997_REG_LDO2CTRL, 29262306a36Sopenharmony_ci MAX8997_REG_LDO3CTRL, 29362306a36Sopenharmony_ci MAX8997_REG_LDO4CTRL, 29462306a36Sopenharmony_ci MAX8997_REG_LDO5CTRL, 29562306a36Sopenharmony_ci MAX8997_REG_LDO6CTRL, 29662306a36Sopenharmony_ci MAX8997_REG_LDO7CTRL, 29762306a36Sopenharmony_ci MAX8997_REG_LDO8CTRL, 29862306a36Sopenharmony_ci MAX8997_REG_LDO9CTRL, 29962306a36Sopenharmony_ci MAX8997_REG_LDO10CTRL, 30062306a36Sopenharmony_ci MAX8997_REG_LDO11CTRL, 30162306a36Sopenharmony_ci MAX8997_REG_LDO12CTRL, 30262306a36Sopenharmony_ci MAX8997_REG_LDO13CTRL, 30362306a36Sopenharmony_ci MAX8997_REG_LDO14CTRL, 30462306a36Sopenharmony_ci MAX8997_REG_LDO15CTRL, 30562306a36Sopenharmony_ci MAX8997_REG_LDO16CTRL, 30662306a36Sopenharmony_ci MAX8997_REG_LDO17CTRL, 30762306a36Sopenharmony_ci MAX8997_REG_LDO18CTRL, 30862306a36Sopenharmony_ci MAX8997_REG_LDO21CTRL, 30962306a36Sopenharmony_ci MAX8997_REG_MBCCTRL1, 31062306a36Sopenharmony_ci MAX8997_REG_MBCCTRL2, 31162306a36Sopenharmony_ci MAX8997_REG_MBCCTRL3, 31262306a36Sopenharmony_ci MAX8997_REG_MBCCTRL4, 31362306a36Sopenharmony_ci MAX8997_REG_MBCCTRL5, 31462306a36Sopenharmony_ci MAX8997_REG_MBCCTRL6, 31562306a36Sopenharmony_ci MAX8997_REG_OTPCGHCVS, 31662306a36Sopenharmony_ci MAX8997_REG_SAFEOUTCTRL, 31762306a36Sopenharmony_ci MAX8997_REG_LBCNFG1, 31862306a36Sopenharmony_ci MAX8997_REG_LBCNFG2, 31962306a36Sopenharmony_ci MAX8997_REG_BBCCTRL, 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci MAX8997_REG_FLASH1_CUR, 32262306a36Sopenharmony_ci MAX8997_REG_FLASH2_CUR, 32362306a36Sopenharmony_ci MAX8997_REG_MOVIE_CUR, 32462306a36Sopenharmony_ci MAX8997_REG_GSMB_CUR, 32562306a36Sopenharmony_ci MAX8997_REG_BOOST_CNTL, 32662306a36Sopenharmony_ci MAX8997_REG_LEN_CNTL, 32762306a36Sopenharmony_ci MAX8997_REG_FLASH_CNTL, 32862306a36Sopenharmony_ci MAX8997_REG_WDT_CNTL, 32962306a36Sopenharmony_ci MAX8997_REG_MAXFLASH1, 33062306a36Sopenharmony_ci MAX8997_REG_MAXFLASH2, 33162306a36Sopenharmony_ci MAX8997_REG_FLASHSTATUSMASK, 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL1, 33462306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL2, 33562306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL3, 33662306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL4, 33762306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL5, 33862306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL6, 33962306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL7, 34062306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL8, 34162306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL9, 34262306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL10, 34362306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL11, 34462306a36Sopenharmony_ci MAX8997_REG_GPIOCNTL12, 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci MAX8997_REG_LDO1CONFIG, 34762306a36Sopenharmony_ci MAX8997_REG_LDO2CONFIG, 34862306a36Sopenharmony_ci MAX8997_REG_LDO3CONFIG, 34962306a36Sopenharmony_ci MAX8997_REG_LDO4CONFIG, 35062306a36Sopenharmony_ci MAX8997_REG_LDO5CONFIG, 35162306a36Sopenharmony_ci MAX8997_REG_LDO6CONFIG, 35262306a36Sopenharmony_ci MAX8997_REG_LDO7CONFIG, 35362306a36Sopenharmony_ci MAX8997_REG_LDO8CONFIG, 35462306a36Sopenharmony_ci MAX8997_REG_LDO9CONFIG, 35562306a36Sopenharmony_ci MAX8997_REG_LDO10CONFIG, 35662306a36Sopenharmony_ci MAX8997_REG_LDO11CONFIG, 35762306a36Sopenharmony_ci MAX8997_REG_LDO12CONFIG, 35862306a36Sopenharmony_ci MAX8997_REG_LDO13CONFIG, 35962306a36Sopenharmony_ci MAX8997_REG_LDO14CONFIG, 36062306a36Sopenharmony_ci MAX8997_REG_LDO15CONFIG, 36162306a36Sopenharmony_ci MAX8997_REG_LDO16CONFIG, 36262306a36Sopenharmony_ci MAX8997_REG_LDO17CONFIG, 36362306a36Sopenharmony_ci MAX8997_REG_LDO18CONFIG, 36462306a36Sopenharmony_ci MAX8997_REG_LDO21CONFIG, 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci MAX8997_REG_DVSOKTIMER1, 36762306a36Sopenharmony_ci MAX8997_REG_DVSOKTIMER2, 36862306a36Sopenharmony_ci MAX8997_REG_DVSOKTIMER4, 36962306a36Sopenharmony_ci MAX8997_REG_DVSOKTIMER5, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic u8 max8997_dumpaddr_muic[] = { 37362306a36Sopenharmony_ci MAX8997_MUIC_REG_INTMASK1, 37462306a36Sopenharmony_ci MAX8997_MUIC_REG_INTMASK2, 37562306a36Sopenharmony_ci MAX8997_MUIC_REG_INTMASK3, 37662306a36Sopenharmony_ci MAX8997_MUIC_REG_CDETCTRL, 37762306a36Sopenharmony_ci MAX8997_MUIC_REG_CONTROL1, 37862306a36Sopenharmony_ci MAX8997_MUIC_REG_CONTROL2, 37962306a36Sopenharmony_ci MAX8997_MUIC_REG_CONTROL3, 38062306a36Sopenharmony_ci}; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic u8 max8997_dumpaddr_haptic[] = { 38362306a36Sopenharmony_ci MAX8997_HAPTIC_REG_CONF1, 38462306a36Sopenharmony_ci MAX8997_HAPTIC_REG_CONF2, 38562306a36Sopenharmony_ci MAX8997_HAPTIC_REG_DRVCONF, 38662306a36Sopenharmony_ci MAX8997_HAPTIC_REG_CYCLECONF1, 38762306a36Sopenharmony_ci MAX8997_HAPTIC_REG_CYCLECONF2, 38862306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGCONF1, 38962306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGCONF2, 39062306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGCONF3, 39162306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGCONF4, 39262306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGDC1, 39362306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGDC2, 39462306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGPWMDC1, 39562306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGPWMDC2, 39662306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGPWMDC3, 39762306a36Sopenharmony_ci MAX8997_HAPTIC_REG_SIGPWMDC4, 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic int max8997_freeze(struct device *dev) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(dev); 40362306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 40462306a36Sopenharmony_ci int i; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 40762306a36Sopenharmony_ci max8997_read_reg(i2c, max8997_dumpaddr_pmic[i], 40862306a36Sopenharmony_ci &max8997->reg_dump[i]); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 41162306a36Sopenharmony_ci max8997_read_reg(i2c, max8997_dumpaddr_muic[i], 41262306a36Sopenharmony_ci &max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 41562306a36Sopenharmony_ci max8997_read_reg(i2c, max8997_dumpaddr_haptic[i], 41662306a36Sopenharmony_ci &max8997->reg_dump[i + MAX8997_REG_PMIC_END + 41762306a36Sopenharmony_ci MAX8997_MUIC_REG_END]); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci return 0; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic int max8997_restore(struct device *dev) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(dev); 42562306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 42662306a36Sopenharmony_ci int i; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 42962306a36Sopenharmony_ci max8997_write_reg(i2c, max8997_dumpaddr_pmic[i], 43062306a36Sopenharmony_ci max8997->reg_dump[i]); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 43362306a36Sopenharmony_ci max8997_write_reg(i2c, max8997_dumpaddr_muic[i], 43462306a36Sopenharmony_ci max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 43762306a36Sopenharmony_ci max8997_write_reg(i2c, max8997_dumpaddr_haptic[i], 43862306a36Sopenharmony_ci max8997->reg_dump[i + MAX8997_REG_PMIC_END + 43962306a36Sopenharmony_ci MAX8997_MUIC_REG_END]); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int max8997_suspend(struct device *dev) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(dev); 44762306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci disable_irq(max8997->irq); 45062306a36Sopenharmony_ci if (device_may_wakeup(dev)) 45162306a36Sopenharmony_ci irq_set_irq_wake(max8997->irq, 1); 45262306a36Sopenharmony_ci return 0; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic int max8997_resume(struct device *dev) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(dev); 45862306a36Sopenharmony_ci struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci if (device_may_wakeup(dev)) 46162306a36Sopenharmony_ci irq_set_irq_wake(max8997->irq, 0); 46262306a36Sopenharmony_ci enable_irq(max8997->irq); 46362306a36Sopenharmony_ci return max8997_irq_resume(max8997); 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic const struct dev_pm_ops max8997_pm = { 46762306a36Sopenharmony_ci .suspend = max8997_suspend, 46862306a36Sopenharmony_ci .resume = max8997_resume, 46962306a36Sopenharmony_ci .freeze = max8997_freeze, 47062306a36Sopenharmony_ci .restore = max8997_restore, 47162306a36Sopenharmony_ci}; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistatic struct i2c_driver max8997_i2c_driver = { 47462306a36Sopenharmony_ci .driver = { 47562306a36Sopenharmony_ci .name = "max8997", 47662306a36Sopenharmony_ci .pm = &max8997_pm, 47762306a36Sopenharmony_ci .suppress_bind_attrs = true, 47862306a36Sopenharmony_ci .of_match_table = of_match_ptr(max8997_pmic_dt_match), 47962306a36Sopenharmony_ci }, 48062306a36Sopenharmony_ci .probe = max8997_i2c_probe, 48162306a36Sopenharmony_ci .id_table = max8997_i2c_id, 48262306a36Sopenharmony_ci}; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic int __init max8997_i2c_init(void) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci return i2c_add_driver(&max8997_i2c_driver); 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci/* init early so consumer devices can complete system boot */ 48962306a36Sopenharmony_cisubsys_initcall(max8997_i2c_init); 490