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> 14b486413dSKrzysztof Kozlowski #include <linux/of_device.h> 1577b71b37SThomas Abraham #include <linux/of_irq.h> 1601fdaab8SMyungJoo Ham #include <linux/interrupt.h> 17527e7e9aSMyungJoo Ham #include <linux/pm_runtime.h> 189cf0c21fSPaul Gortmaker #include <linux/init.h> 19527e7e9aSMyungJoo Ham #include <linux/mutex.h> 20527e7e9aSMyungJoo Ham #include <linux/mfd/core.h> 21527e7e9aSMyungJoo Ham #include <linux/mfd/max8997.h> 22527e7e9aSMyungJoo Ham #include <linux/mfd/max8997-private.h> 23527e7e9aSMyungJoo Ham 24527e7e9aSMyungJoo Ham #define I2C_ADDR_PMIC (0xCC >> 1) 25527e7e9aSMyungJoo Ham #define I2C_ADDR_MUIC (0x4A >> 1) 26527e7e9aSMyungJoo Ham #define I2C_ADDR_BATTERY (0x6C >> 1) 27527e7e9aSMyungJoo Ham #define I2C_ADDR_RTC (0x0C >> 1) 28527e7e9aSMyungJoo Ham #define I2C_ADDR_HAPTIC (0x90 >> 1) 29527e7e9aSMyungJoo Ham 307c0517b1SGeert Uytterhoeven static const struct mfd_cell max8997_devs[] = { 31527e7e9aSMyungJoo Ham { .name = "max8997-pmic", }, 32527e7e9aSMyungJoo Ham { .name = "max8997-rtc", }, 332397c3eeSTimon Baetz { .name = "max8997-battery", }, 34527e7e9aSMyungJoo Ham { .name = "max8997-haptic", }, 352397c3eeSTimon Baetz { .name = "max8997-muic", }, 36f6dd2db9SDonggeun Kim { .name = "max8997-led", .id = 1 }, 37f6dd2db9SDonggeun Kim { .name = "max8997-led", .id = 2 }, 38527e7e9aSMyungJoo Ham }; 39527e7e9aSMyungJoo Ham 4077b71b37SThomas Abraham #ifdef CONFIG_OF 41f1eb2cb8SKrzysztof Kozlowski static const struct of_device_id max8997_pmic_dt_match[] = { 42ed6ccdc6SJingoo Han { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, 4377b71b37SThomas Abraham {}, 4477b71b37SThomas Abraham }; 4577b71b37SThomas Abraham #endif 4677b71b37SThomas Abraham 47527e7e9aSMyungJoo Ham int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) 48527e7e9aSMyungJoo Ham { 49527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 50527e7e9aSMyungJoo Ham int ret; 51527e7e9aSMyungJoo Ham 52527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 53527e7e9aSMyungJoo Ham ret = i2c_smbus_read_byte_data(i2c, reg); 54527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 55527e7e9aSMyungJoo Ham if (ret < 0) 56527e7e9aSMyungJoo Ham return ret; 57527e7e9aSMyungJoo Ham 58527e7e9aSMyungJoo Ham ret &= 0xff; 59527e7e9aSMyungJoo Ham *dest = ret; 60527e7e9aSMyungJoo Ham return 0; 61527e7e9aSMyungJoo Ham } 62527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_read_reg); 63527e7e9aSMyungJoo Ham 64527e7e9aSMyungJoo Ham int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 65527e7e9aSMyungJoo Ham { 66527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 67527e7e9aSMyungJoo Ham int ret; 68527e7e9aSMyungJoo Ham 69527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 70527e7e9aSMyungJoo Ham ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf); 71527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 72527e7e9aSMyungJoo Ham if (ret < 0) 73527e7e9aSMyungJoo Ham return ret; 74527e7e9aSMyungJoo Ham 75527e7e9aSMyungJoo Ham return 0; 76527e7e9aSMyungJoo Ham } 77527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_bulk_read); 78527e7e9aSMyungJoo Ham 79527e7e9aSMyungJoo Ham int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value) 80527e7e9aSMyungJoo Ham { 81527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 82527e7e9aSMyungJoo Ham int ret; 83527e7e9aSMyungJoo Ham 84527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 85527e7e9aSMyungJoo Ham ret = i2c_smbus_write_byte_data(i2c, reg, value); 86527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 87527e7e9aSMyungJoo Ham return ret; 88527e7e9aSMyungJoo Ham } 89527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_write_reg); 90527e7e9aSMyungJoo Ham 91527e7e9aSMyungJoo Ham int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf) 92527e7e9aSMyungJoo Ham { 93527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 94527e7e9aSMyungJoo Ham int ret; 95527e7e9aSMyungJoo Ham 96527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 97527e7e9aSMyungJoo Ham ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf); 98527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 99527e7e9aSMyungJoo Ham if (ret < 0) 100527e7e9aSMyungJoo Ham return ret; 101527e7e9aSMyungJoo Ham 102527e7e9aSMyungJoo Ham return 0; 103527e7e9aSMyungJoo Ham } 104527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_bulk_write); 105527e7e9aSMyungJoo Ham 106527e7e9aSMyungJoo Ham int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) 107527e7e9aSMyungJoo Ham { 108527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 109527e7e9aSMyungJoo Ham int ret; 110527e7e9aSMyungJoo Ham 111527e7e9aSMyungJoo Ham mutex_lock(&max8997->iolock); 112527e7e9aSMyungJoo Ham ret = i2c_smbus_read_byte_data(i2c, reg); 113527e7e9aSMyungJoo Ham if (ret >= 0) { 114527e7e9aSMyungJoo Ham u8 old_val = ret & 0xff; 115527e7e9aSMyungJoo Ham u8 new_val = (val & mask) | (old_val & (~mask)); 116527e7e9aSMyungJoo Ham ret = i2c_smbus_write_byte_data(i2c, reg, new_val); 117527e7e9aSMyungJoo Ham } 118527e7e9aSMyungJoo Ham mutex_unlock(&max8997->iolock); 119527e7e9aSMyungJoo Ham return ret; 120527e7e9aSMyungJoo Ham } 121527e7e9aSMyungJoo Ham EXPORT_SYMBOL_GPL(max8997_update_reg); 122527e7e9aSMyungJoo Ham 12377b71b37SThomas Abraham /* 12477b71b37SThomas Abraham * Only the common platform data elements for max8997 are parsed here from the 12577b71b37SThomas Abraham * device tree. Other sub-modules of max8997 such as pmic, rtc and others have 12677b71b37SThomas Abraham * to parse their own platform data elements from device tree. 12777b71b37SThomas Abraham * 12877b71b37SThomas Abraham * The max8997 platform data structure is instantiated here and the drivers for 12977b71b37SThomas Abraham * the sub-modules need not instantiate another instance while parsing their 13077b71b37SThomas Abraham * platform data. 13177b71b37SThomas Abraham */ 13277b71b37SThomas Abraham static struct max8997_platform_data *max8997_i2c_parse_dt_pdata( 13377b71b37SThomas Abraham struct device *dev) 13477b71b37SThomas Abraham { 13577b71b37SThomas Abraham struct max8997_platform_data *pd; 13677b71b37SThomas Abraham 13777b71b37SThomas Abraham pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 138f01b90b2SMarkus Elfring if (!pd) 13977b71b37SThomas Abraham return ERR_PTR(-ENOMEM); 14077b71b37SThomas Abraham 14177b71b37SThomas Abraham pd->ono = irq_of_parse_and_map(dev->of_node, 1); 14277b71b37SThomas Abraham 14377b71b37SThomas Abraham return pd; 14477b71b37SThomas Abraham } 14577b71b37SThomas Abraham 14605fb7a56SLee Jones static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c, 14777b71b37SThomas Abraham const struct i2c_device_id *id) 14877b71b37SThomas Abraham { 149b486413dSKrzysztof Kozlowski if (i2c->dev.of_node) 150b486413dSKrzysztof Kozlowski return (unsigned long)of_device_get_match_data(&i2c->dev); 151b486413dSKrzysztof Kozlowski 15205fb7a56SLee Jones return id->driver_data; 15377b71b37SThomas Abraham } 15477b71b37SThomas Abraham 155c9f105ecSUwe Kleine-König static int max8997_i2c_probe(struct i2c_client *i2c) 156527e7e9aSMyungJoo Ham { 157c9f105ecSUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 158527e7e9aSMyungJoo Ham struct max8997_dev *max8997; 159334a41ceSJingoo Han struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev); 160527e7e9aSMyungJoo Ham int ret = 0; 161527e7e9aSMyungJoo Ham 1626922ffcfSJingoo Han max8997 = devm_kzalloc(&i2c->dev, sizeof(struct max8997_dev), 1636922ffcfSJingoo Han GFP_KERNEL); 164527e7e9aSMyungJoo Ham if (max8997 == NULL) 165527e7e9aSMyungJoo Ham return -ENOMEM; 166527e7e9aSMyungJoo Ham 167527e7e9aSMyungJoo Ham i2c_set_clientdata(i2c, max8997); 168527e7e9aSMyungJoo Ham max8997->dev = &i2c->dev; 169527e7e9aSMyungJoo Ham max8997->i2c = i2c; 17077b71b37SThomas Abraham max8997->type = max8997_i2c_get_driver_data(i2c, id); 1717eb3154eSMyungJoo Ham max8997->irq = i2c->irq; 172527e7e9aSMyungJoo Ham 17301c3f110SManish Badarkhe if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) { 17477b71b37SThomas Abraham pdata = max8997_i2c_parse_dt_pdata(max8997->dev); 1756922ffcfSJingoo Han if (IS_ERR(pdata)) 1766922ffcfSJingoo Han return PTR_ERR(pdata); 17777b71b37SThomas Abraham } 17877b71b37SThomas Abraham 179527e7e9aSMyungJoo Ham if (!pdata) 1806922ffcfSJingoo Han return ret; 181527e7e9aSMyungJoo Ham 18277b71b37SThomas Abraham max8997->pdata = pdata; 1837eb3154eSMyungJoo Ham max8997->ono = pdata->ono; 184527e7e9aSMyungJoo Ham 185527e7e9aSMyungJoo Ham mutex_init(&max8997->iolock); 186527e7e9aSMyungJoo Ham 1874e32bff6SWolfram Sang max8997->rtc = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_RTC); 1884e32bff6SWolfram Sang if (IS_ERR(max8997->rtc)) { 18997dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n"); 1904e32bff6SWolfram Sang return PTR_ERR(max8997->rtc); 19197dc4ed3SKrzysztof Kozlowski } 192527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->rtc, max8997); 19397dc4ed3SKrzysztof Kozlowski 1944e32bff6SWolfram Sang max8997->haptic = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_HAPTIC); 1954e32bff6SWolfram Sang if (IS_ERR(max8997->haptic)) { 19697dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n"); 1974e32bff6SWolfram Sang ret = PTR_ERR(max8997->haptic); 19897dc4ed3SKrzysztof Kozlowski goto err_i2c_haptic; 19997dc4ed3SKrzysztof Kozlowski } 200527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->haptic, max8997); 20197dc4ed3SKrzysztof Kozlowski 2024e32bff6SWolfram Sang max8997->muic = i2c_new_dummy_device(i2c->adapter, I2C_ADDR_MUIC); 2034e32bff6SWolfram Sang if (IS_ERR(max8997->muic)) { 20497dc4ed3SKrzysztof Kozlowski dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n"); 2054e32bff6SWolfram Sang ret = PTR_ERR(max8997->muic); 20697dc4ed3SKrzysztof Kozlowski goto err_i2c_muic; 20797dc4ed3SKrzysztof Kozlowski } 208527e7e9aSMyungJoo Ham i2c_set_clientdata(max8997->muic, max8997); 209527e7e9aSMyungJoo Ham 210527e7e9aSMyungJoo Ham pm_runtime_set_active(max8997->dev); 211527e7e9aSMyungJoo Ham 2127eb3154eSMyungJoo Ham max8997_irq_init(max8997); 2137eb3154eSMyungJoo Ham 214c1ec8fc3SLaszlo Papp ret = mfd_add_devices(max8997->dev, -1, max8997_devs, 215527e7e9aSMyungJoo Ham ARRAY_SIZE(max8997_devs), 2160848c94fSMark Brown NULL, 0, NULL); 217c1ec8fc3SLaszlo Papp if (ret < 0) { 218c1ec8fc3SLaszlo Papp dev_err(max8997->dev, "failed to add MFD devices %d\n", ret); 219c1ec8fc3SLaszlo Papp goto err_mfd; 220c1ec8fc3SLaszlo Papp } 221527e7e9aSMyungJoo Ham 222527e7e9aSMyungJoo Ham /* 223527e7e9aSMyungJoo Ham * TODO: enable others (flash, muic, rtc, battery, ...) and 224527e7e9aSMyungJoo Ham * check the return value 225527e7e9aSMyungJoo Ham */ 226527e7e9aSMyungJoo Ham 22701fdaab8SMyungJoo Ham /* MAX8997 has a power button input. */ 228efddff27SMarek Szyprowski device_init_wakeup(max8997->dev, true); 22901fdaab8SMyungJoo Ham 230527e7e9aSMyungJoo Ham return ret; 231527e7e9aSMyungJoo Ham 232527e7e9aSMyungJoo Ham err_mfd: 233527e7e9aSMyungJoo Ham mfd_remove_devices(max8997->dev); 234527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->muic); 23597dc4ed3SKrzysztof Kozlowski err_i2c_muic: 236527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->haptic); 23797dc4ed3SKrzysztof Kozlowski err_i2c_haptic: 238527e7e9aSMyungJoo Ham i2c_unregister_device(max8997->rtc); 239527e7e9aSMyungJoo Ham return ret; 240527e7e9aSMyungJoo Ham } 241527e7e9aSMyungJoo Ham 242527e7e9aSMyungJoo Ham static const struct i2c_device_id max8997_i2c_id[] = { 243527e7e9aSMyungJoo Ham { "max8997", TYPE_MAX8997 }, 244527e7e9aSMyungJoo Ham { "max8966", TYPE_MAX8966 }, 245527e7e9aSMyungJoo Ham { } 246527e7e9aSMyungJoo Ham }; 247527e7e9aSMyungJoo Ham 248b673e24cSSachin Kamat static u8 max8997_dumpaddr_pmic[] = { 249527e7e9aSMyungJoo Ham MAX8997_REG_INT1MSK, 250527e7e9aSMyungJoo Ham MAX8997_REG_INT2MSK, 251527e7e9aSMyungJoo Ham MAX8997_REG_INT3MSK, 252527e7e9aSMyungJoo Ham MAX8997_REG_INT4MSK, 253527e7e9aSMyungJoo Ham MAX8997_REG_MAINCON1, 254527e7e9aSMyungJoo Ham MAX8997_REG_MAINCON2, 255527e7e9aSMyungJoo Ham MAX8997_REG_BUCKRAMP, 256527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1CTRL, 257527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS1, 258527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS2, 259527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS3, 260527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS4, 261527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS5, 262527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS6, 263527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS7, 264527e7e9aSMyungJoo Ham MAX8997_REG_BUCK1DVS8, 265527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2CTRL, 266527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS1, 267527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS2, 268527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS3, 269527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS4, 270527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS5, 271527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS6, 272527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS7, 273527e7e9aSMyungJoo Ham MAX8997_REG_BUCK2DVS8, 274527e7e9aSMyungJoo Ham MAX8997_REG_BUCK3CTRL, 275527e7e9aSMyungJoo Ham MAX8997_REG_BUCK3DVS, 276527e7e9aSMyungJoo Ham MAX8997_REG_BUCK4CTRL, 277527e7e9aSMyungJoo Ham MAX8997_REG_BUCK4DVS, 278527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5CTRL, 279527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS1, 280527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS2, 281527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS3, 282527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS4, 283527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS5, 284527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS6, 285527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS7, 286527e7e9aSMyungJoo Ham MAX8997_REG_BUCK5DVS8, 287527e7e9aSMyungJoo Ham MAX8997_REG_BUCK6CTRL, 288527e7e9aSMyungJoo Ham MAX8997_REG_BUCK6BPSKIPCTRL, 289527e7e9aSMyungJoo Ham MAX8997_REG_BUCK7CTRL, 290527e7e9aSMyungJoo Ham MAX8997_REG_BUCK7DVS, 291527e7e9aSMyungJoo Ham MAX8997_REG_LDO1CTRL, 292527e7e9aSMyungJoo Ham MAX8997_REG_LDO2CTRL, 293527e7e9aSMyungJoo Ham MAX8997_REG_LDO3CTRL, 294527e7e9aSMyungJoo Ham MAX8997_REG_LDO4CTRL, 295527e7e9aSMyungJoo Ham MAX8997_REG_LDO5CTRL, 296527e7e9aSMyungJoo Ham MAX8997_REG_LDO6CTRL, 297527e7e9aSMyungJoo Ham MAX8997_REG_LDO7CTRL, 298527e7e9aSMyungJoo Ham MAX8997_REG_LDO8CTRL, 299527e7e9aSMyungJoo Ham MAX8997_REG_LDO9CTRL, 300527e7e9aSMyungJoo Ham MAX8997_REG_LDO10CTRL, 301527e7e9aSMyungJoo Ham MAX8997_REG_LDO11CTRL, 302527e7e9aSMyungJoo Ham MAX8997_REG_LDO12CTRL, 303527e7e9aSMyungJoo Ham MAX8997_REG_LDO13CTRL, 304527e7e9aSMyungJoo Ham MAX8997_REG_LDO14CTRL, 305527e7e9aSMyungJoo Ham MAX8997_REG_LDO15CTRL, 306527e7e9aSMyungJoo Ham MAX8997_REG_LDO16CTRL, 307527e7e9aSMyungJoo Ham MAX8997_REG_LDO17CTRL, 308527e7e9aSMyungJoo Ham MAX8997_REG_LDO18CTRL, 309527e7e9aSMyungJoo Ham MAX8997_REG_LDO21CTRL, 310527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL1, 311527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL2, 312527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL3, 313527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL4, 314527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL5, 315527e7e9aSMyungJoo Ham MAX8997_REG_MBCCTRL6, 316527e7e9aSMyungJoo Ham MAX8997_REG_OTPCGHCVS, 317527e7e9aSMyungJoo Ham MAX8997_REG_SAFEOUTCTRL, 318527e7e9aSMyungJoo Ham MAX8997_REG_LBCNFG1, 319527e7e9aSMyungJoo Ham MAX8997_REG_LBCNFG2, 320527e7e9aSMyungJoo Ham MAX8997_REG_BBCCTRL, 321527e7e9aSMyungJoo Ham 322527e7e9aSMyungJoo Ham MAX8997_REG_FLASH1_CUR, 323527e7e9aSMyungJoo Ham MAX8997_REG_FLASH2_CUR, 324527e7e9aSMyungJoo Ham MAX8997_REG_MOVIE_CUR, 325527e7e9aSMyungJoo Ham MAX8997_REG_GSMB_CUR, 326527e7e9aSMyungJoo Ham MAX8997_REG_BOOST_CNTL, 327527e7e9aSMyungJoo Ham MAX8997_REG_LEN_CNTL, 328527e7e9aSMyungJoo Ham MAX8997_REG_FLASH_CNTL, 329527e7e9aSMyungJoo Ham MAX8997_REG_WDT_CNTL, 330527e7e9aSMyungJoo Ham MAX8997_REG_MAXFLASH1, 331527e7e9aSMyungJoo Ham MAX8997_REG_MAXFLASH2, 332527e7e9aSMyungJoo Ham MAX8997_REG_FLASHSTATUSMASK, 333527e7e9aSMyungJoo Ham 334527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL1, 335527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL2, 336527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL3, 337527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL4, 338527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL5, 339527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL6, 340527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL7, 341527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL8, 342527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL9, 343527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL10, 344527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL11, 345527e7e9aSMyungJoo Ham MAX8997_REG_GPIOCNTL12, 346527e7e9aSMyungJoo Ham 347527e7e9aSMyungJoo Ham MAX8997_REG_LDO1CONFIG, 348527e7e9aSMyungJoo Ham MAX8997_REG_LDO2CONFIG, 349527e7e9aSMyungJoo Ham MAX8997_REG_LDO3CONFIG, 350527e7e9aSMyungJoo Ham MAX8997_REG_LDO4CONFIG, 351527e7e9aSMyungJoo Ham MAX8997_REG_LDO5CONFIG, 352527e7e9aSMyungJoo Ham MAX8997_REG_LDO6CONFIG, 353527e7e9aSMyungJoo Ham MAX8997_REG_LDO7CONFIG, 354527e7e9aSMyungJoo Ham MAX8997_REG_LDO8CONFIG, 355527e7e9aSMyungJoo Ham MAX8997_REG_LDO9CONFIG, 356527e7e9aSMyungJoo Ham MAX8997_REG_LDO10CONFIG, 357527e7e9aSMyungJoo Ham MAX8997_REG_LDO11CONFIG, 358527e7e9aSMyungJoo Ham MAX8997_REG_LDO12CONFIG, 359527e7e9aSMyungJoo Ham MAX8997_REG_LDO13CONFIG, 360527e7e9aSMyungJoo Ham MAX8997_REG_LDO14CONFIG, 361527e7e9aSMyungJoo Ham MAX8997_REG_LDO15CONFIG, 362527e7e9aSMyungJoo Ham MAX8997_REG_LDO16CONFIG, 363527e7e9aSMyungJoo Ham MAX8997_REG_LDO17CONFIG, 364527e7e9aSMyungJoo Ham MAX8997_REG_LDO18CONFIG, 365527e7e9aSMyungJoo Ham MAX8997_REG_LDO21CONFIG, 366527e7e9aSMyungJoo Ham 367527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER1, 368527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER2, 369527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER4, 370527e7e9aSMyungJoo Ham MAX8997_REG_DVSOKTIMER5, 371527e7e9aSMyungJoo Ham }; 372527e7e9aSMyungJoo Ham 373b673e24cSSachin Kamat static u8 max8997_dumpaddr_muic[] = { 374527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK1, 375527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK2, 376527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_INTMASK3, 377527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CDETCTRL, 378527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL1, 379527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL2, 380527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_CONTROL3, 381527e7e9aSMyungJoo Ham }; 382527e7e9aSMyungJoo Ham 383b673e24cSSachin Kamat static u8 max8997_dumpaddr_haptic[] = { 384527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CONF1, 385527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CONF2, 386527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_DRVCONF, 387527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CYCLECONF1, 388527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_CYCLECONF2, 389527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF1, 390527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF2, 391527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF3, 392527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGCONF4, 393527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGDC1, 394527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGDC2, 395527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC1, 396527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC2, 397527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC3, 398527e7e9aSMyungJoo Ham MAX8997_HAPTIC_REG_SIGPWMDC4, 399527e7e9aSMyungJoo Ham }; 400527e7e9aSMyungJoo Ham 401527e7e9aSMyungJoo Ham static int max8997_freeze(struct device *dev) 402527e7e9aSMyungJoo Ham { 4031b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 404527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 405527e7e9aSMyungJoo Ham int i; 406527e7e9aSMyungJoo Ham 407527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 408527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_pmic[i], 409527e7e9aSMyungJoo Ham &max8997->reg_dump[i]); 410527e7e9aSMyungJoo Ham 411527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 412527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_muic[i], 413527e7e9aSMyungJoo Ham &max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 414527e7e9aSMyungJoo Ham 415527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 416527e7e9aSMyungJoo Ham max8997_read_reg(i2c, max8997_dumpaddr_haptic[i], 417527e7e9aSMyungJoo Ham &max8997->reg_dump[i + MAX8997_REG_PMIC_END + 418527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_END]); 419527e7e9aSMyungJoo Ham 420527e7e9aSMyungJoo Ham return 0; 421527e7e9aSMyungJoo Ham } 422527e7e9aSMyungJoo Ham 423527e7e9aSMyungJoo Ham static int max8997_restore(struct device *dev) 424527e7e9aSMyungJoo Ham { 4251b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 426527e7e9aSMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 427527e7e9aSMyungJoo Ham int i; 428527e7e9aSMyungJoo Ham 429527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++) 430527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_pmic[i], 431527e7e9aSMyungJoo Ham max8997->reg_dump[i]); 432527e7e9aSMyungJoo Ham 433527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++) 434527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_muic[i], 435527e7e9aSMyungJoo Ham max8997->reg_dump[i + MAX8997_REG_PMIC_END]); 436527e7e9aSMyungJoo Ham 437527e7e9aSMyungJoo Ham for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++) 438527e7e9aSMyungJoo Ham max8997_write_reg(i2c, max8997_dumpaddr_haptic[i], 439527e7e9aSMyungJoo Ham max8997->reg_dump[i + MAX8997_REG_PMIC_END + 440527e7e9aSMyungJoo Ham MAX8997_MUIC_REG_END]); 441527e7e9aSMyungJoo Ham 442527e7e9aSMyungJoo Ham return 0; 443527e7e9aSMyungJoo Ham } 444527e7e9aSMyungJoo Ham 44501fdaab8SMyungJoo Ham static int max8997_suspend(struct device *dev) 44601fdaab8SMyungJoo Ham { 4471b5420e1SGeliang Tang struct i2c_client *i2c = to_i2c_client(dev); 44801fdaab8SMyungJoo Ham struct max8997_dev *max8997 = i2c_get_clientdata(i2c); 44901fdaab8SMyungJoo Ham 450c1aaaa1cSMarek Szyprowski disable_irq(max8997->irq); 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); 463c1aaaa1cSMarek Szyprowski enable_irq(max8997->irq); 46401fdaab8SMyungJoo Ham return max8997_irq_resume(max8997); 46501fdaab8SMyungJoo Ham } 46601fdaab8SMyungJoo Ham 467b673e24cSSachin Kamat static const struct dev_pm_ops max8997_pm = { 46801fdaab8SMyungJoo Ham .suspend = max8997_suspend, 46901fdaab8SMyungJoo Ham .resume = max8997_resume, 470527e7e9aSMyungJoo Ham .freeze = max8997_freeze, 471527e7e9aSMyungJoo Ham .restore = max8997_restore, 472527e7e9aSMyungJoo Ham }; 473527e7e9aSMyungJoo Ham 474527e7e9aSMyungJoo Ham static struct i2c_driver max8997_i2c_driver = { 475527e7e9aSMyungJoo Ham .driver = { 476527e7e9aSMyungJoo Ham .name = "max8997", 477527e7e9aSMyungJoo Ham .pm = &max8997_pm, 4789cf0c21fSPaul Gortmaker .suppress_bind_attrs = true, 47977b71b37SThomas Abraham .of_match_table = of_match_ptr(max8997_pmic_dt_match), 480527e7e9aSMyungJoo Ham }, 481*9816d859SUwe Kleine-König .probe = max8997_i2c_probe, 482527e7e9aSMyungJoo Ham .id_table = max8997_i2c_id, 483527e7e9aSMyungJoo Ham }; 484527e7e9aSMyungJoo Ham 485527e7e9aSMyungJoo Ham static int __init max8997_i2c_init(void) 486527e7e9aSMyungJoo Ham { 487527e7e9aSMyungJoo Ham return i2c_add_driver(&max8997_i2c_driver); 488527e7e9aSMyungJoo Ham } 489527e7e9aSMyungJoo Ham /* init early so consumer devices can complete system boot */ 490527e7e9aSMyungJoo Ham subsys_initcall(max8997_i2c_init); 491