/*
 * MFD core driver for the Maxim MAX77843
 *
 * Copyright (C) 2015 Samsung Electronics
 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
 * Author: Beomho Seo <beomho.seo@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77843-private.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>

static const struct mfd_cell max77843_devs[] = {
	{
		.name = "max77843-muic",
		.of_compatible = "maxim,max77843-muic",
	}, {
		.name = "max77843-regulator",
		.of_compatible = "maxim,max77843-regulator",
	}, {
		.name = "max77843-charger",
		.of_compatible = "maxim,max77843-charger"
	}, {
		.name = "max77843-fuelgauge",
		.of_compatible = "maxim,max77843-fuelgauge",
	}, {
		.name = "max77843-haptic",
		.of_compatible = "maxim,max77843-haptic",
	},
};

static const struct regmap_config max77843_charger_regmap_config = {
	.reg_bits	= 8,
	.val_bits	= 8,
	.max_register	= MAX77843_CHG_REG_END,
};

static const struct regmap_config max77843_regmap_config = {
	.reg_bits	= 8,
	.val_bits	= 8,
	.max_register	= MAX77843_SYS_REG_END,
};

static const struct regmap_irq max77843_irqs[] = {
	/* TOPSYS interrupts */
	{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSUVLO_INT, },
	{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSOVLO_INT, },
	{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TSHDN_INT, },
	{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TM_INT, },
};

static const struct regmap_irq_chip max77843_irq_chip = {
	.name		= "max77843",
	.status_base	= MAX77843_SYS_REG_SYSINTSRC,
	.mask_base	= MAX77843_SYS_REG_SYSINTMASK,
	.mask_invert	= false,
	.num_regs	= 1,
	.irqs		= max77843_irqs,
	.num_irqs	= ARRAY_SIZE(max77843_irqs),
};

/* Charger and Charger regulator use same regmap. */
static int max77843_chg_init(struct max77693_dev *max77843)
{
	int ret;

	max77843->i2c_chg = i2c_new_dummy(max77843->i2c->adapter, I2C_ADDR_CHG);
	if (!max77843->i2c_chg) {
		dev_err(&max77843->i2c->dev,
				"Cannot allocate I2C device for Charger\n");
		return PTR_ERR(max77843->i2c_chg);
	}
	i2c_set_clientdata(max77843->i2c_chg, max77843);

	max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg,
			&max77843_charger_regmap_config);
	if (IS_ERR(max77843->regmap_chg)) {
		ret = PTR_ERR(max77843->regmap_chg);
		goto err_chg_i2c;
	}

	return 0;

err_chg_i2c:
	i2c_unregister_device(max77843->i2c_chg);

	return ret;
}

static int max77843_probe(struct i2c_client *i2c,
			  const struct i2c_device_id *id)
{
	struct max77693_dev *max77843;
	unsigned int reg_data;
	int ret;

	max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL);
	if (!max77843)
		return -ENOMEM;

	i2c_set_clientdata(i2c, max77843);
	max77843->dev = &i2c->dev;
	max77843->i2c = i2c;
	max77843->irq = i2c->irq;
	max77843->type = id->driver_data;

	max77843->regmap = devm_regmap_init_i2c(i2c,
			&max77843_regmap_config);
	if (IS_ERR(max77843->regmap)) {
		dev_err(&i2c->dev, "Failed to allocate topsys register map\n");
		return PTR_ERR(max77843->regmap);
	}

	ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,
			IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
			0, &max77843_irq_chip, &max77843->irq_data_topsys);
	if (ret) {
		dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");
		return ret;
	}

	ret = regmap_read(max77843->regmap,
			MAX77843_SYS_REG_PMICID, &reg_data);
	if (ret < 0) {
		dev_err(&i2c->dev, "Failed to read PMIC ID\n");
		goto err_pmic_id;
	}
	dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data);

	ret = max77843_chg_init(max77843);
	if (ret) {
		dev_err(&i2c->dev, "Failed to init Charger\n");
		goto err_pmic_id;
	}

	ret = regmap_update_bits(max77843->regmap,
				 MAX77843_SYS_REG_INTSRCMASK,
				 MAX77843_INTSRC_MASK_MASK,
				 (unsigned int)~MAX77843_INTSRC_MASK_MASK);
	if (ret < 0) {
		dev_err(&i2c->dev, "Failed to unmask interrupt source\n");
		goto err_pmic_id;
	}

	ret = mfd_add_devices(max77843->dev, -1, max77843_devs,
			      ARRAY_SIZE(max77843_devs), NULL, 0, NULL);
	if (ret < 0) {
		dev_err(&i2c->dev, "Failed to add mfd device\n");
		goto err_pmic_id;
	}

	device_init_wakeup(max77843->dev, true);

	return 0;

err_pmic_id:
	regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);

	return ret;
}

static int max77843_remove(struct i2c_client *i2c)
{
	struct max77693_dev *max77843 = i2c_get_clientdata(i2c);

	mfd_remove_devices(max77843->dev);

	regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);

	i2c_unregister_device(max77843->i2c_chg);

	return 0;
}

static const struct of_device_id max77843_dt_match[] = {
	{ .compatible = "maxim,max77843", },
	{ },
};

static const struct i2c_device_id max77843_id[] = {
	{ "max77843", TYPE_MAX77843, },
	{ },
};
MODULE_DEVICE_TABLE(i2c, max77843_id);

static int __maybe_unused max77843_suspend(struct device *dev)
{
	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
	struct max77693_dev *max77843 = i2c_get_clientdata(i2c);

	disable_irq(max77843->irq);
	if (device_may_wakeup(dev))
		enable_irq_wake(max77843->irq);

	return 0;
}

static int __maybe_unused max77843_resume(struct device *dev)
{
	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
	struct max77693_dev *max77843 = i2c_get_clientdata(i2c);

	if (device_may_wakeup(dev))
		disable_irq_wake(max77843->irq);
	enable_irq(max77843->irq);

	return 0;
}

static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);

static struct i2c_driver max77843_i2c_driver = {
	.driver	= {
		.name = "max77843",
		.pm = &max77843_pm,
		.of_match_table = max77843_dt_match,
	},
	.probe = max77843_probe,
	.remove = max77843_remove,
	.id_table = max77843_id,
};

static int __init max77843_i2c_init(void)
{
	return i2c_add_driver(&max77843_i2c_driver);
}
subsys_initcall(max77843_i2c_init);

static void __exit max77843_i2c_exit(void)
{
	i2c_del_driver(&max77843_i2c_driver);
}
module_exit(max77843_i2c_exit);
