219 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// MFD core driver for the Maxim MAX778434//5// Copyright (C) 2015 Samsung Electronics6// Author: Jaewon Kim <jaewon02.kim@samsung.com>7// Author: Beomho Seo <beomho.seo@samsung.com>8 9#include <linux/err.h>10#include <linux/i2c.h>11#include <linux/init.h>12#include <linux/interrupt.h>13#include <linux/mfd/core.h>14#include <linux/mfd/max77693-common.h>15#include <linux/mfd/max77843-private.h>16#include <linux/mod_devicetable.h>17#include <linux/platform_device.h>18 19static const struct mfd_cell max77843_devs[] = {20 {21 .name = "max77843-muic",22 .of_compatible = "maxim,max77843-muic",23 }, {24 .name = "max77843-regulator",25 .of_compatible = "maxim,max77843-regulator",26 }, {27 .name = "max77843-charger",28 .of_compatible = "maxim,max77843-charger"29 }, {30 .name = "max77843-fuelgauge",31 .of_compatible = "maxim,max77843-fuelgauge",32 }, {33 .name = "max77843-haptic",34 .of_compatible = "maxim,max77843-haptic",35 },36};37 38static const struct regmap_config max77843_charger_regmap_config = {39 .reg_bits = 8,40 .val_bits = 8,41 .max_register = MAX77843_CHG_REG_END,42};43 44static const struct regmap_config max77843_regmap_config = {45 .reg_bits = 8,46 .val_bits = 8,47 .max_register = MAX77843_SYS_REG_END,48};49 50static const struct regmap_irq max77843_irqs[] = {51 /* TOPSYS interrupts */52 { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSUVLO_INT, },53 { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSOVLO_INT, },54 { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TSHDN_INT, },55 { .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TM_INT, },56};57 58static const struct regmap_irq_chip max77843_irq_chip = {59 .name = "max77843",60 .status_base = MAX77843_SYS_REG_SYSINTSRC,61 .mask_base = MAX77843_SYS_REG_SYSINTMASK,62 .num_regs = 1,63 .irqs = max77843_irqs,64 .num_irqs = ARRAY_SIZE(max77843_irqs),65};66 67/* Charger and Charger regulator use same regmap. */68static int max77843_chg_init(struct max77693_dev *max77843)69{70 int ret;71 72 max77843->i2c_chg = i2c_new_dummy_device(max77843->i2c->adapter, I2C_ADDR_CHG);73 if (IS_ERR(max77843->i2c_chg)) {74 dev_err(&max77843->i2c->dev,75 "Cannot allocate I2C device for Charger\n");76 return PTR_ERR(max77843->i2c_chg);77 }78 i2c_set_clientdata(max77843->i2c_chg, max77843);79 80 max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg,81 &max77843_charger_regmap_config);82 if (IS_ERR(max77843->regmap_chg)) {83 ret = PTR_ERR(max77843->regmap_chg);84 goto err_chg_i2c;85 }86 87 return 0;88 89err_chg_i2c:90 i2c_unregister_device(max77843->i2c_chg);91 92 return ret;93}94 95static int max77843_probe(struct i2c_client *i2c)96{97 const struct i2c_device_id *id = i2c_client_get_device_id(i2c);98 struct max77693_dev *max77843;99 unsigned int reg_data;100 int ret;101 102 max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL);103 if (!max77843)104 return -ENOMEM;105 106 i2c_set_clientdata(i2c, max77843);107 max77843->dev = &i2c->dev;108 max77843->i2c = i2c;109 max77843->irq = i2c->irq;110 max77843->type = id->driver_data;111 112 max77843->regmap = devm_regmap_init_i2c(i2c,113 &max77843_regmap_config);114 if (IS_ERR(max77843->regmap)) {115 dev_err(&i2c->dev, "Failed to allocate topsys register map\n");116 return PTR_ERR(max77843->regmap);117 }118 119 ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,120 IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,121 0, &max77843_irq_chip, &max77843->irq_data_topsys);122 if (ret) {123 dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");124 return ret;125 }126 127 ret = regmap_read(max77843->regmap,128 MAX77843_SYS_REG_PMICID, ®_data);129 if (ret < 0) {130 dev_err(&i2c->dev, "Failed to read PMIC ID\n");131 goto err_pmic_id;132 }133 dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data);134 135 ret = max77843_chg_init(max77843);136 if (ret) {137 dev_err(&i2c->dev, "Failed to init Charger\n");138 goto err_pmic_id;139 }140 141 ret = regmap_update_bits(max77843->regmap,142 MAX77843_SYS_REG_INTSRCMASK,143 MAX77843_INTSRC_MASK_MASK,144 (unsigned int)~MAX77843_INTSRC_MASK_MASK);145 if (ret < 0) {146 dev_err(&i2c->dev, "Failed to unmask interrupt source\n");147 goto err_pmic_id;148 }149 150 ret = mfd_add_devices(max77843->dev, -1, max77843_devs,151 ARRAY_SIZE(max77843_devs), NULL, 0, NULL);152 if (ret < 0) {153 dev_err(&i2c->dev, "Failed to add mfd device\n");154 goto err_pmic_id;155 }156 157 device_init_wakeup(max77843->dev, true);158 159 return 0;160 161err_pmic_id:162 regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);163 164 return ret;165}166 167static const struct of_device_id max77843_dt_match[] = {168 { .compatible = "maxim,max77843", },169 { },170};171 172static const struct i2c_device_id max77843_id[] = {173 { "max77843", TYPE_MAX77843, },174 { },175};176 177static int __maybe_unused max77843_suspend(struct device *dev)178{179 struct i2c_client *i2c = to_i2c_client(dev);180 struct max77693_dev *max77843 = i2c_get_clientdata(i2c);181 182 disable_irq(max77843->irq);183 if (device_may_wakeup(dev))184 enable_irq_wake(max77843->irq);185 186 return 0;187}188 189static int __maybe_unused max77843_resume(struct device *dev)190{191 struct i2c_client *i2c = to_i2c_client(dev);192 struct max77693_dev *max77843 = i2c_get_clientdata(i2c);193 194 if (device_may_wakeup(dev))195 disable_irq_wake(max77843->irq);196 enable_irq(max77843->irq);197 198 return 0;199}200 201static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);202 203static struct i2c_driver max77843_i2c_driver = {204 .driver = {205 .name = "max77843",206 .pm = &max77843_pm,207 .of_match_table = max77843_dt_match,208 .suppress_bind_attrs = true,209 },210 .probe = max77843_probe,211 .id_table = max77843_id,212};213 214static int __init max77843_i2c_init(void)215{216 return i2c_add_driver(&max77843_i2c_driver);217}218subsys_initcall(max77843_i2c_init);219