1d7d8d7a2SKrzysztof Kozlowski // SPDX-License-Identifier: GPL-2.0+ 2d7d8d7a2SKrzysztof Kozlowski // 3d7d8d7a2SKrzysztof Kozlowski // max8997.c - mfd core driver for the Maxim 8966 and 8997 4d7d8d7a2SKrzysztof Kozlowski // 5d7d8d7a2SKrzysztof Kozlowski // Copyright (C) 2011 Samsung Electronics 6d7d8d7a2SKrzysztof Kozlowski // MyungJoo Ham <myungjoo.ham@samsung.com> 7d7d8d7a2SKrzysztof Kozlowski // 8d7d8d7a2SKrzysztof Kozlowski // This driver is based on max8998.c 9527e7e9aSMyungJoo Ham 1077b71b37SThomas Abraham #include <linux/err.h> 11527e7e9aSMyungJoo Ham #include <linux/slab.h> 12527e7e9aSMyungJoo Ham #include <linux/i2c.h> 13fb7d4a53SSachin Kamat #include <linux/of.h> 1477b71b37SThomas Abraham #include <linux/of_irq.h> 1501fdaab8SMyungJoo Ham #include <linux/interrupt.h> 16527e7e9aSMyungJoo Ham #include <linux/pm_runtime.h> 179cf0c21fSPaul Gortmaker #include <linux/init.h> 18527e7e9aSMyungJoo Ham #include <linux/mutex.h> 19527e7e9aSMyungJoo Ham #include <linux/mfd/core.h> 20527e7e9aSMyungJoo Ham #include <linux/mfd/max8997.h> 21527e7e9aSMyungJoo Ham #include <linux/mfd/max8997-private.h> 22527e7e9aSMyungJoo Ham 23527e7e9aSMyungJoo Ham #define I2C_ADDR_PMIC (0xCC >> 1) 24527e7e9aSMyungJoo Ham #define I2C_ADDR_MUIC (0x4A >> 1) 25527e7e9aSMyungJoo Ham #define I2C_ADDR_BATTERY (0x6C >> 1) 26527e7e9aSMyungJoo Ham #define I2C_ADDR_RTC (0x0C >> 1) 27527e7e9aSMyungJoo Ham #define I2C_ADDR_HAPTIC (0x90 >> 1) 28527e7e9aSMyungJoo Ham 297c0517b1SGeert Uytterhoeven static const struct mfd_cell max8997_devs[] = { 30527e7e9aSMyungJoo Ham { .name = "max8997-pmic", }, 31527e7e9aSMyungJoo Ham { .name = "max8997-rtc", }, 32527e7e9aSMyungJoo Ham { .name = "max8997-battery", }, 33527e7e9aSMyungJoo Ham { .name = "max8997-haptic", }, 34527e7e9aSMyungJoo Ham { .name = "max8997-muic", }, 35f6dd2db9SDonggeun Kim { .name = "max8997-led", .id = 1 }, 36f6dd2db9SDonggeun Kim { .name = "max8997-led", .id = 2 }, 37527e7e9aSMyungJoo Ham }; 38527e7e9aSMyungJoo Ham 3977b71b37SThomas Abraham #ifdef CONFIG_OF 40f1eb2cb8SKrzysztof Kozlowski static const struct of_device_id max8997_pmic_dt_match[] = { 41ed6ccdc6SJingoo Han { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, 4277b71b37SThomas Abraham {}, 4377b71b37SThomas Abraham }; 4477b71b37SThomas Abraham #endif 4577b71b37SThomas Abraham 46527e7e9aSMyungJoo Ham int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) 47527e7e9aSMyungJoo Ham { 48527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 49527e7e9aSMyungJoo Ham int ret; 50527e7e9aSMyungJoo Ham 51527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 52527e7e9aSMyungJoo Ham ret = i2c_smbus_read_byte_data(i2c, reg); 53527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 54527e7e9aSMyungJoo Ham if (ret < 0) 55527e7e9aSMyungJoo Ham return ret; 56527e7e9aSMyungJoo Ham 57527e7e9aSMyungJoo Ham ret &= 0xff; 58527e7e9aSMyungJoo Ham *dest = ret; 59527e7e9aSMyungJoo Ham return 0; 60527e7e9aSMyungJoo Ham } 61527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_read_reg); 62527e7e9aSMyungJoo Ham 63527e7e9aSMyungJoo Ham int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 64527e7e9aSMyungJoo Ham { 65527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 66527e7e9aSMyungJoo Ham int ret; 67527e7e9aSMyungJoo Ham 68527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 69527e7e9aSMyungJoo Ham ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf); 70527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 71527e7e9aSMyungJoo Ham if (ret < 0) 72527e7e9aSMyungJoo Ham return ret; 73527e7e9aSMyungJoo Ham 74527e7e9aSMyungJoo Ham return 0; 75527e7e9aSMyungJoo Ham } 76527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_bulk_read); 77527e7e9aSMyungJoo Ham 78527e7e9aSMyungJoo Ham int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value) 79527e7e9aSMyungJoo Ham { 80527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 81527e7e9aSMyungJoo Ham int ret; 82527e7e9aSMyungJoo Ham 83527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 84527e7e9aSMyungJoo Ham ret = i2c_smbus_write_byte_data(i2c, reg, value); 85527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 86527e7e9aSMyungJoo Ham return ret; 87527e7e9aSMyungJoo Ham } 88527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_write_reg); 89527e7e9aSMyungJoo Ham 90527e7e9aSMyungJoo Ham int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 91527e7e9aSMyungJoo Ham { 92527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 93527e7e9aSMyungJoo Ham int ret; 94527e7e9aSMyungJoo Ham 95527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 96527e7e9aSMyungJoo Ham ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf); 97527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 98527e7e9aSMyungJoo Ham if (ret < 0) 99527e7e9aSMyungJoo Ham return ret; 100527e7e9aSMyungJoo Ham 101527e7e9aSMyungJoo Ham return 0; 102527e7e9aSMyungJoo Ham } 103527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_bulk_write); 104527e7e9aSMyungJoo Ham 105527e7e9aSMyungJoo Ham int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) 106527e7e9aSMyungJoo Ham { 107527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 108527e7e9aSMyungJoo Ham int ret; 109527e7e9aSMyungJoo Ham 110527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 111527e7e9aSMyungJoo Ham ret = i2c_smbus_read_byte_data(i2c, reg); 112527e7e9aSMyungJoo Ham if (ret >= 0) { 113527e7e9aSMyungJoo Ham u8 old_val = ret & 0xff; 114527e7e9aSMyungJoo Ham u8 new_val = (val & mask) | (old_val & (~mask)); 115527e7e9aSMyungJoo Ham ret = i2c_smbus_write_byte_data(i2c, reg, new_val); 116527e7e9aSMyungJoo Ham } 117527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 118527e7e9aSMyungJoo Ham return ret; 119527e7e9aSMyungJoo Ham } 120527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_update_reg); 121527e7e9aSMyungJoo Ham 12277b71b37SThomas Abraham /* 12377b71b37SThomas Abraham * Only the common platform data elements for max8997 are parsed here from the 12477b71b37SThomas Abraham * device tree. Other sub-modules of max8997 such as pmic, rtc and others have 12577b71b37SThomas Abraham * to parse their own platform data elements from device tree. 12677b71b37SThomas Abraham * 12777b71b37SThomas Abraham * The max8997 platform data structure is instantiated here and the drivers for 12877b71b37SThomas Abraham * the sub-modules need not instantiate another instance while parsing their 12977b71b37SThomas Abraham * platform data. 13077b71b37SThomas Abraham */ 13177b71b37SThomas Abraham static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( 13277b71b37SThomas Abraham struct device *dev) 13377b71b37SThomas Abraham { 13477b71b37SThomas Abraham struct max8997_platform_data *pd; 13577b71b37SThomas Abraham 13677b71b37SThomas Abraham pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 137f01b90b2SMarkus Elfring if (!pd) 13877b71b37SThomas Abraham return ERR_PTR(-ENOMEM); 13977b71b37SThomas Abraham 14077b71b37SThomas Abraham pd->ono = irq_of_parse_and_map(dev->of_node, 1); 14177b71b37SThomas Abraham 14277b71b37SThomas Abraham return pd; 14377b71b37SThomas Abraham } 14477b71b37SThomas Abraham 14505fb7a56SLee Jones static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, 14677b71b37SThomas Abraham const struct i2c_device_id *id) 14777b71b37SThomas Abraham { 14801c3f110SManish Badarkhe if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { 14977b71b37SThomas Abraham const struct of_device_id *match; 15077b71b37SThomas Abraham match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node); 15105fb7a56SLee Jones return (unsigned long)match->data; 15277b71b37SThomas Abraham } 15305fb7a56SLee Jones return id->driver_data; 15477b71b37SThomas Abraham } 15577b71b37SThomas Abraham 156527e7e9aSMyungJoo Ham static int max8997_i2c_probe(struct i2c_client *i2c, 157527e7e9aSMyungJoo Ham const struct i2c_device_id *id) 158527e7e9aSMyungJoo Ham { 159527e7e9aSMyungJoo Ham struct max8997_dev *max8997; 160334a41ceSJingoo Han struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev); 161527e7e9aSMyungJoo Ham int ret = 0; 162527e7e9aSMyungJoo Ham 1636922ffcfSJingoo Han max8997 = devm_kzalloc(&i2c->dev, sizeof(struct max8997_dev), 1646922ffcfSJingoo Han GFP_KERNEL); 165527e7e9aSMyungJoo Ham if (max8997 == NULL) 166527e7e9aSMyungJoo Ham return -ENOMEM; 167527e7e9aSMyungJoo Ham 168527e7e9aSMyungJoo Ham i2c_set_clientdata(i2c, max8997); 169527e7e9aSMyungJoo Ham max8997->dev = &i2c->dev; 170527e7e9aSMyungJoo Ham max8997->i2c = i2c; 17177b71b37SThomas Abraham max8997->type = max8997_i2c_get_driver_data(i2c, id); 1727eb3154eSMyungJoo Ham max8997->irq = i2c->irq; 173527e7e9aSMyungJoo Ham 17401c3f110SManish Badarkhe if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) { 17577b71b37SThomas Abraham pdata = max8997_i2c_parse_dt_pdata(max8997->dev); 1766922ffcfSJingoo Han if (IS_ERR(pdata)) 1776922ffcfSJingoo Han return PTR_ERR(pdata); 17877b71b37SThomas Abraham } 17977b71b37SThomas Abraham 180527e7e9aSMyungJoo Ham if (!pdata) 1816922ffcfSJingoo Han return ret; 182527e7e9aSMyungJoo Ham 18377b71b37SThomas Abraham max8997->pdata = pdata; 1847eb3154eSMyungJoo Ham max8997->ono = pdata->ono; 185527e7e9aSMyungJoo Ham 186527e7e9aSMyungJoo Ham mutex_init(&max8997->iolock); 187527e7e9aSMyungJoo Ham 188527e7e9aSMyungJoo Ham max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); 18997dc4ed3SKrzysztof Kozlowski if (!max8997->rtc) { 19097dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n"); 19197dc4ed3SKrzysztof Kozlowski return -ENODEV; 19297dc4ed3SKrzysztof Kozlowski } 193527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->rtc, max8997); 19497dc4ed3SKrzysztof Kozlowski 195527e7e9aSMyungJoo Ham max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); 19697dc4ed3SKrzysztof Kozlowski if (!max8997->haptic) { 19797dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n"); 19897dc4ed3SKrzysztof Kozlowski ret = -ENODEV; 19997dc4ed3SKrzysztof Kozlowski goto err_i2c_haptic; 20097dc4ed3SKrzysztof Kozlowski } 201527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->haptic, max8997); 20297dc4ed3SKrzysztof Kozlowski 203527e7e9aSMyungJoo Ham max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); 20497dc4ed3SKrzysztof Kozlowski if (!max8997->muic) { 20597dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n"); 20697dc4ed3SKrzysztof Kozlowski ret = -ENODEV; 20797dc4ed3SKrzysztof Kozlowski goto err_i2c_muic; 20897dc4ed3SKrzysztof Kozlowski } 209527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->muic, max8997); 210527e7e9aSMyungJoo Ham 211527e7e9aSMyungJoo Ham pm_runtime_set_active(max8997->dev); 212527e7e9aSMyungJoo Ham 2137eb3154eSMyungJoo Ham max8997_irq_init(max8997); 2147eb3154eSMyungJoo Ham 215c1ec8fc3SLaszlo Papp ret = mfd_add_devices(max8997->dev, -1, max8997_devs, 216527e7e9aSMyungJoo Ham ARRAY_SIZE(max8997_devs), 2170848c94fSMark Brown NULL, 0, NULL); 218c1ec8fc3SLaszlo Papp if (ret < 0) { 219c1ec8fc3SLaszlo Papp dev_err(max8997->dev, "failed to add MFD devices %d\n", ret); 220c1ec8fc3SLaszlo Papp goto err_mfd; 221c1ec8fc3SLaszlo Papp } 222527e7e9aSMyungJoo Ham 223527e7e9aSMyungJoo Ham /* 224527e7e9aSMyungJoo Ham * TODO: enable others (flash, muic, rtc, battery, ...) and 225527e7e9aSMyungJoo Ham * check the return value 226527e7e9aSMyungJoo Ham */ 227527e7e9aSMyungJoo Ham 22801fdaab8SMyungJoo Ham /* MAX8997 has a power button input. */ 229efddff27SMarek Szyprowski device_init_wakeup(max8997->dev, true); 23001fdaab8SMyungJoo Ham 231527e7e9aSMyungJoo Ham return ret; 232527e7e9aSMyungJoo Ham 233527e7e9aSMyungJoo Ham err_mfd: 234527e7e9aSMyungJoo Ham mfd_remove_devices(max8997->dev); 235527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->muic); 23697dc4ed3SKrzysztof Kozlowski err_i2c_muic: 237527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->haptic); 23897dc4ed3SKrzysztof Kozlowski err_i2c_haptic: 239527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->rtc); 240527e7e9aSMyungJoo Ham return ret; 241527e7e9aSMyungJoo Ham } 242527e7e9aSMyungJoo Ham 243527e7e9aSMyungJoo Ham static const struct i2c_device_id max8997_i2c_id[] = { 244527e7e9aSMyungJoo Ham { "max8997", TYPE_MAX8997 }, 245527e7e9aSMyungJoo Ham { "max8966", TYPE_MAX8966 }, 246527e7e9aSMyungJoo Ham { } 247527e7e9aSMyungJoo Ham }; 248527e7e9aSMyungJoo Ham 249b673e24cSSachin Kamat static u8 max8997_dumpaddr_pmic[] = { 250527e7e9aSMyungJoo Ham MAX8997_REG_INT1MSK, 251527e7e9aSMyungJoo Ham MAX8997_REG_INT2MSK, 252527e7e9aSMyungJoo Ham MAX8997_REG_INT3MSK, 253527e7e9aSMyungJoo Ham MAX8997_REG_INT4MSK, 254527e7e9aSMyungJoo Ham MAX8997_REG_MAINCON1, 255527e7e9aSMyungJoo Ham MAX8997_REG_MAINCON2, 256527e7e9aSMyungJoo Ham MAX8997_REG_BUCKRAMP, 257527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1CTRL, 258527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS1, 259527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS2, 260527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS3, 261527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS4, 262527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS5, 263527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS6, 264527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS7, 265527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS8, 266527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2CTRL, 267527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS1, 268527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS2, 269527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS3, 270527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS4, 271527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS5, 272527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS6, 273527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS7, 274527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS8, 275527e7e9aSMyungJoo Ham MAX8997_REG_BUCK3CTRL, 276527e7e9aSMyungJoo Ham MAX8997_REG_BUCK3DVS, 277527e7e9aSMyungJoo Ham MAX8997_REG_BUCK4CTRL, 278527e7e9aSMyungJoo Ham MAX8997_REG_BUCK4DVS, 279527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5CTRL, 280527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS1, 281527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS2, 282527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS3, 283527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS4, 284527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS5, 285527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS6, 286527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS7, 287527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS8, 288527e7e9aSMyungJoo Ham MAX8997_REG_BUCK6CTRL, 289527e7e9aSMyungJoo Ham MAX8997_REG_BUCK6BPSKIPCTRL, 290527e7e9aSMyungJoo Ham MAX8997_REG_BUCK7CTRL, 291527e7e9aSMyungJoo Ham MAX8997_REG_BUCK7DVS, 292527e7e9aSMyungJoo Ham MAX8997_REG_LDO1CTRL, 293527e7e9aSMyungJoo Ham MAX8997_REG_LDO2CTRL, 294527e7e9aSMyungJoo Ham MAX8997_REG_LDO3CTRL, 295527e7e9aSMyungJoo Ham MAX8997_REG_LDO4CTRL, 296527e7e9aSMyungJoo Ham MAX8997_REG_LDO5CTRL, 297527e7e9aSMyungJoo Ham MAX8997_REG_LDO6CTRL, 298527e7e9aSMyungJoo Ham MAX8997_REG_LDO7CTRL, 299527e7e9aSMyungJoo Ham MAX8997_REG_LDO8CTRL, 300527e7e9aSMyungJoo Ham MAX8997_REG_LDO9CTRL, 301527e7e9aSMyungJoo Ham MAX8997_REG_LDO10CTRL, 302527e7e9aSMyungJoo Ham MAX8997_REG_LDO11CTRL, 303527e7e9aSMyungJoo Ham MAX8997_REG_LDO12CTRL, 304527e7e9aSMyungJoo Ham MAX8997_REG_LDO13CTRL, 305527e7e9aSMyungJoo Ham MAX8997_REG_LDO14CTRL, 306527e7e9aSMyungJoo Ham MAX8997_REG_LDO15CTRL, 307527e7e9aSMyungJoo Ham MAX8997_REG_LDO16CTRL, 308527e7e9aSMyungJoo Ham MAX8997_REG_LDO17CTRL, 309527e7e9aSMyungJoo Ham MAX8997_REG_LDO18CTRL, 310527e7e9aSMyungJoo Ham MAX8997_REG_LDO21CTRL, 311527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL1, 312527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL2, 313527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL3, 314527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL4, 315527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL5, 316527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL6, 317527e7e9aSMyungJoo Ham MAX8997_REG_OTPCGHCVS, 318527e7e9aSMyungJoo Ham MAX8997_REG_SAFEOUTCTRL, 319527e7e9aSMyungJoo Ham MAX8997_REG_LBCNFG1, 320527e7e9aSMyungJoo Ham MAX8997_REG_LBCNFG2, 321527e7e9aSMyungJoo Ham MAX8997_REG_BBCCTRL, 322527e7e9aSMyungJoo Ham 323527e7e9aSMyungJoo Ham MAX8997_REG_FLASH1_CUR, 324527e7e9aSMyungJoo Ham MAX8997_REG_FLASH2_CUR, 325527e7e9aSMyungJoo Ham MAX8997_REG_MOVIE_CUR, 326527e7e9aSMyungJoo Ham MAX8997_REG_GSMB_CUR, 327527e7e9aSMyungJoo Ham MAX8997_REG_BOOST_CNTL, 328527e7e9aSMyungJoo Ham MAX8997_REG_LEN_CNTL, 329527e7e9aSMyungJoo Ham MAX8997_REG_FLASH_CNTL, 330527e7e9aSMyungJoo Ham MAX8997_REG_WDT_CNTL, 331527e7e9aSMyungJoo Ham MAX8997_REG_MAXFLASH1, 332527e7e9aSMyungJoo Ham MAX8997_REG_MAXFLASH2, 333527e7e9aSMyungJoo Ham MAX8997_REG_FLASHSTATUSMASK, 334527e7e9aSMyungJoo Ham 335527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL1, 336527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL2, 337527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL3, 338527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL4, 339527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL5, 340527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL6, 341527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL7, 342527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL8, 343527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL9, 344527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL10, 345527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL11, 346527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL12, 347527e7e9aSMyungJoo Ham 348527e7e9aSMyungJoo Ham MAX8997_REG_LDO1CONFIG, 349527e7e9aSMyungJoo Ham MAX8997_REG_LDO2CONFIG, 350527e7e9aSMyungJoo Ham MAX8997_REG_LDO3CONFIG, 351527e7e9aSMyungJoo Ham MAX8997_REG_LDO4CONFIG, 352527e7e9aSMyungJoo Ham MAX8997_REG_LDO5CONFIG, 353527e7e9aSMyungJoo Ham MAX8997_REG_LDO6CONFIG, 354527e7e9aSMyungJoo Ham MAX8997_REG_LDO7CONFIG, 355527e7e9aSMyungJoo Ham MAX8997_REG_LDO8CONFIG, 356527e7e9aSMyungJoo Ham MAX8997_REG_LDO9CONFIG, 357527e7e9aSMyungJoo Ham MAX8997_REG_LDO10CONFIG, 358527e7e9aSMyungJoo Ham MAX8997_REG_LDO11CONFIG, 359527e7e9aSMyungJoo Ham MAX8997_REG_LDO12CONFIG, 360527e7e9aSMyungJoo Ham MAX8997_REG_LDO13CONFIG, 361527e7e9aSMyungJoo Ham MAX8997_REG_LDO14CONFIG, 362527e7e9aSMyungJoo Ham MAX8997_REG_LDO15CONFIG, 363527e7e9aSMyungJoo Ham MAX8997_REG_LDO16CONFIG, 364527e7e9aSMyungJoo Ham MAX8997_REG_LDO17CONFIG, 365527e7e9aSMyungJoo Ham MAX8997_REG_LDO18CONFIG, 366527e7e9aSMyungJoo Ham MAX8997_REG_LDO21CONFIG, 367527e7e9aSMyungJoo Ham 368527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER1, 369527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER2, 370527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER4, 371527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER5, 372527e7e9aSMyungJoo Ham }; 373527e7e9aSMyungJoo Ham 374b673e24cSSachin Kamat static u8 max8997_dumpaddr_muic[] = { 375527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK1, 376527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK2, 377527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK3, 378527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CDETCTRL, 379527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL1, 380527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL2, 381527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL3, 382527e7e9aSMyungJoo Ham }; 383527e7e9aSMyungJoo Ham 384b673e24cSSachin Kamat static u8 max8997_dumpaddr_haptic[] = { 385527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CONF1, 386527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CONF2, 387527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_DRVCONF, 388527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CYCLECONF1, 389527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CYCLECONF2, 390527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF1, 391527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF2, 392527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF3, 393527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF4, 394527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGDC1, 395527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGDC2, 396527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC1, 397527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC2, 398527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC3, 399527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC4, 400527e7e9aSMyungJoo Ham }; 401527e7e9aSMyungJoo Ham 402527e7e9aSMyungJoo Ham static int max8997_freeze(struct device *dev) 403527e7e9aSMyungJoo Ham { 4041b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 405527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 406527e7e9aSMyungJoo Ham int i; 407527e7e9aSMyungJoo Ham 408527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 409527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_pmic[i], 410527e7e9aSMyungJoo Ham &max8997->reg_dump[i]); 411527e7e9aSMyungJoo Ham 412527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 413527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_muic[i], 414527e7e9aSMyungJoo Ham &max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 415527e7e9aSMyungJoo Ham 416527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 417527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_haptic[i], 418527e7e9aSMyungJoo Ham &max8997->reg_dump[i + MAX8997_REG_PMIC_END + 419527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_END]); 420527e7e9aSMyungJoo Ham 421527e7e9aSMyungJoo Ham return 0; 422527e7e9aSMyungJoo Ham } 423527e7e9aSMyungJoo Ham 424527e7e9aSMyungJoo Ham static int max8997_restore(struct device *dev) 425527e7e9aSMyungJoo Ham { 4261b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 427527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 428527e7e9aSMyungJoo Ham int i; 429527e7e9aSMyungJoo Ham 430527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 431527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_pmic[i], 432527e7e9aSMyungJoo Ham max8997->reg_dump[i]); 433527e7e9aSMyungJoo Ham 434527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 435527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_muic[i], 436527e7e9aSMyungJoo Ham max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 437527e7e9aSMyungJoo Ham 438527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 439527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_haptic[i], 440527e7e9aSMyungJoo Ham max8997->reg_dump[i + MAX8997_REG_PMIC_END + 441527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_END]); 442527e7e9aSMyungJoo Ham 443527e7e9aSMyungJoo Ham return 0; 444527e7e9aSMyungJoo Ham } 445527e7e9aSMyungJoo Ham 44601fdaab8SMyungJoo Ham static int max8997_suspend(struct device *dev) 44701fdaab8SMyungJoo Ham { 4481b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 44901fdaab8SMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 45001fdaab8SMyungJoo Ham 45101fdaab8SMyungJoo Ham if (device_may_wakeup(dev)) 45201fdaab8SMyungJoo Ham irq_set_irq_wake(max8997->irq, 1); 45301fdaab8SMyungJoo Ham return 0; 45401fdaab8SMyungJoo Ham } 45501fdaab8SMyungJoo Ham 45601fdaab8SMyungJoo Ham static int max8997_resume(struct device *dev) 45701fdaab8SMyungJoo Ham { 4581b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 45901fdaab8SMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 46001fdaab8SMyungJoo Ham 46101fdaab8SMyungJoo Ham if (device_may_wakeup(dev)) 46201fdaab8SMyungJoo Ham irq_set_irq_wake(max8997->irq, 0); 46301fdaab8SMyungJoo Ham return max8997_irq_resume(max8997); 46401fdaab8SMyungJoo Ham } 46501fdaab8SMyungJoo Ham 466b673e24cSSachin Kamat static const struct dev_pm_ops max8997_pm = { 46701fdaab8SMyungJoo Ham .suspend = max8997_suspend, 46801fdaab8SMyungJoo Ham .resume = max8997_resume, 469527e7e9aSMyungJoo Ham .freeze = max8997_freeze, 470527e7e9aSMyungJoo Ham .restore = max8997_restore, 471527e7e9aSMyungJoo Ham }; 472527e7e9aSMyungJoo Ham 473527e7e9aSMyungJoo Ham static struct i2c_driver max8997_i2c_driver = { 474527e7e9aSMyungJoo Ham .driver = { 475527e7e9aSMyungJoo Ham .name = "max8997", 476527e7e9aSMyungJoo Ham .pm = &max8997_pm, 4779cf0c21fSPaul Gortmaker .suppress_bind_attrs = true, 47877b71b37SThomas Abraham .of_match_table = of_match_ptr(max8997_pmic_dt_match), 479527e7e9aSMyungJoo Ham }, 480527e7e9aSMyungJoo Ham .probe = max8997_i2c_probe, 481527e7e9aSMyungJoo Ham .id_table = max8997_i2c_id, 482527e7e9aSMyungJoo Ham }; 483527e7e9aSMyungJoo Ham 484527e7e9aSMyungJoo Ham static int __init max8997_i2c_init(void) 485527e7e9aSMyungJoo Ham { 486527e7e9aSMyungJoo Ham return i2c_add_driver(&max8997_i2c_driver); 487527e7e9aSMyungJoo Ham } 488527e7e9aSMyungJoo Ham /* init early so consumer devices can complete system boot */ 489527e7e9aSMyungJoo Ham subsys_initcall(max8997_i2c_init); 490