brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · fcff0c4 Raw
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, &reg_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