cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max77843.c (5540B)


      1// SPDX-License-Identifier: GPL-2.0+
      2//
      3// MFD core driver for the Maxim MAX77843
      4//
      5// Copyright (C) 2015 Samsung Electronics
      6// 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/of_device.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	.mask_invert	= false,
     63	.num_regs	= 1,
     64	.irqs		= max77843_irqs,
     65	.num_irqs	= ARRAY_SIZE(max77843_irqs),
     66};
     67
     68/* Charger and Charger regulator use same regmap. */
     69static int max77843_chg_init(struct max77693_dev *max77843)
     70{
     71	int ret;
     72
     73	max77843->i2c_chg = i2c_new_dummy_device(max77843->i2c->adapter, I2C_ADDR_CHG);
     74	if (IS_ERR(max77843->i2c_chg)) {
     75		dev_err(&max77843->i2c->dev,
     76				"Cannot allocate I2C device for Charger\n");
     77		return PTR_ERR(max77843->i2c_chg);
     78	}
     79	i2c_set_clientdata(max77843->i2c_chg, max77843);
     80
     81	max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg,
     82			&max77843_charger_regmap_config);
     83	if (IS_ERR(max77843->regmap_chg)) {
     84		ret = PTR_ERR(max77843->regmap_chg);
     85		goto err_chg_i2c;
     86	}
     87
     88	return 0;
     89
     90err_chg_i2c:
     91	i2c_unregister_device(max77843->i2c_chg);
     92
     93	return ret;
     94}
     95
     96static int max77843_probe(struct i2c_client *i2c,
     97			  const struct i2c_device_id *id)
     98{
     99	struct max77693_dev *max77843;
    100	unsigned int reg_data;
    101	int ret;
    102
    103	max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL);
    104	if (!max77843)
    105		return -ENOMEM;
    106
    107	i2c_set_clientdata(i2c, max77843);
    108	max77843->dev = &i2c->dev;
    109	max77843->i2c = i2c;
    110	max77843->irq = i2c->irq;
    111	max77843->type = id->driver_data;
    112
    113	max77843->regmap = devm_regmap_init_i2c(i2c,
    114			&max77843_regmap_config);
    115	if (IS_ERR(max77843->regmap)) {
    116		dev_err(&i2c->dev, "Failed to allocate topsys register map\n");
    117		return PTR_ERR(max77843->regmap);
    118	}
    119
    120	ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,
    121			IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
    122			0, &max77843_irq_chip, &max77843->irq_data_topsys);
    123	if (ret) {
    124		dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");
    125		return ret;
    126	}
    127
    128	ret = regmap_read(max77843->regmap,
    129			MAX77843_SYS_REG_PMICID, &reg_data);
    130	if (ret < 0) {
    131		dev_err(&i2c->dev, "Failed to read PMIC ID\n");
    132		goto err_pmic_id;
    133	}
    134	dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data);
    135
    136	ret = max77843_chg_init(max77843);
    137	if (ret) {
    138		dev_err(&i2c->dev, "Failed to init Charger\n");
    139		goto err_pmic_id;
    140	}
    141
    142	ret = regmap_update_bits(max77843->regmap,
    143				 MAX77843_SYS_REG_INTSRCMASK,
    144				 MAX77843_INTSRC_MASK_MASK,
    145				 (unsigned int)~MAX77843_INTSRC_MASK_MASK);
    146	if (ret < 0) {
    147		dev_err(&i2c->dev, "Failed to unmask interrupt source\n");
    148		goto err_pmic_id;
    149	}
    150
    151	ret = mfd_add_devices(max77843->dev, -1, max77843_devs,
    152			      ARRAY_SIZE(max77843_devs), NULL, 0, NULL);
    153	if (ret < 0) {
    154		dev_err(&i2c->dev, "Failed to add mfd device\n");
    155		goto err_pmic_id;
    156	}
    157
    158	device_init_wakeup(max77843->dev, true);
    159
    160	return 0;
    161
    162err_pmic_id:
    163	regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);
    164
    165	return ret;
    166}
    167
    168static const struct of_device_id max77843_dt_match[] = {
    169	{ .compatible = "maxim,max77843", },
    170	{ },
    171};
    172
    173static const struct i2c_device_id max77843_id[] = {
    174	{ "max77843", TYPE_MAX77843, },
    175	{ },
    176};
    177
    178static int __maybe_unused max77843_suspend(struct device *dev)
    179{
    180	struct i2c_client *i2c = to_i2c_client(dev);
    181	struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
    182
    183	disable_irq(max77843->irq);
    184	if (device_may_wakeup(dev))
    185		enable_irq_wake(max77843->irq);
    186
    187	return 0;
    188}
    189
    190static int __maybe_unused max77843_resume(struct device *dev)
    191{
    192	struct i2c_client *i2c = to_i2c_client(dev);
    193	struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
    194
    195	if (device_may_wakeup(dev))
    196		disable_irq_wake(max77843->irq);
    197	enable_irq(max77843->irq);
    198
    199	return 0;
    200}
    201
    202static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);
    203
    204static struct i2c_driver max77843_i2c_driver = {
    205	.driver	= {
    206		.name = "max77843",
    207		.pm = &max77843_pm,
    208		.of_match_table = max77843_dt_match,
    209		.suppress_bind_attrs = true,
    210	},
    211	.probe = max77843_probe,
    212	.id_table = max77843_id,
    213};
    214
    215static int __init max77843_i2c_init(void)
    216{
    217	return i2c_add_driver(&max77843_i2c_driver);
    218}
    219subsys_initcall(max77843_i2c_init);