File Index
Files and directories
Sign in
FILE

max77705.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mfd/max77705.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Maxim MAX77705 PMIC core driver
  4 *
  5 * Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.com>
  6 **/
  7#include <linux/i2c.h>
  8#include <linux/interrupt.h>
  9#include <linux/mfd/core.h>
 10#include <linux/mfd/max77705-private.h>
 11#include <linux/mfd/max77693-common.h>
 12#include <linux/pm.h>
 13#include <linux/power/max17042_battery.h>
 14#include <linux/module.h>
 15#include <linux/regmap.h>
 16#include <linux/of.h>
 17
 18static struct mfd_cell max77705_devs[] = {
 19	MFD_CELL_OF("max77705-rgb", NULL, NULL, 0, 0, "maxim,max77705-rgb"),
 20	MFD_CELL_OF("max77705-charger", NULL, NULL, 0, 0, "maxim,max77705-charger"),
 21	MFD_CELL_OF("max77705-haptic", NULL, NULL, 0, 0, "maxim,max77705-haptic"),
 22};
 23
 24static const struct regmap_range max77705_readable_ranges[] = {
 25	regmap_reg_range(MAX77705_PMIC_REG_PMICID1,		MAX77705_PMIC_REG_BSTOUT_MASK),
 26	regmap_reg_range(MAX77705_PMIC_REG_INTSRC,		MAX77705_PMIC_REG_RESERVED_29),
 27	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1,	MAX77705_PMIC_REG_BOOSTCONTROL1),
 28	regmap_reg_range(MAX77705_PMIC_REG_MCONFIG,		MAX77705_PMIC_REG_MCONFIG2),
 29	regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK,	MAX77705_PMIC_REG_FORCE_EN_MASK),
 30	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1,	MAX77705_PMIC_REG_BOOSTCONTROL1),
 31	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2,	MAX77705_PMIC_REG_BOOSTCONTROL2),
 32	regmap_reg_range(MAX77705_PMIC_REG_SW_RESET,		MAX77705_PMIC_REG_USBC_RESET),
 33};
 34
 35static const struct regmap_range max77705_writable_ranges[] = {
 36	regmap_reg_range(MAX77705_PMIC_REG_MAINCTRL1,		MAX77705_PMIC_REG_BSTOUT_MASK),
 37	regmap_reg_range(MAX77705_PMIC_REG_INTSRC,		MAX77705_PMIC_REG_RESERVED_29),
 38	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1,	MAX77705_PMIC_REG_BOOSTCONTROL1),
 39	regmap_reg_range(MAX77705_PMIC_REG_MCONFIG,		MAX77705_PMIC_REG_MCONFIG2),
 40	regmap_reg_range(MAX77705_PMIC_REG_FORCE_EN_MASK,	MAX77705_PMIC_REG_FORCE_EN_MASK),
 41	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL1,	MAX77705_PMIC_REG_BOOSTCONTROL1),
 42	regmap_reg_range(MAX77705_PMIC_REG_BOOSTCONTROL2,	MAX77705_PMIC_REG_BOOSTCONTROL2),
 43	regmap_reg_range(MAX77705_PMIC_REG_SW_RESET,		MAX77705_PMIC_REG_USBC_RESET),
 44};
 45
 46static const struct regmap_access_table max77705_readable_table = {
 47	.yes_ranges = max77705_readable_ranges,
 48	.n_yes_ranges = ARRAY_SIZE(max77705_readable_ranges),
 49};
 50
 51static const struct regmap_access_table max77705_writable_table = {
 52	.yes_ranges = max77705_writable_ranges,
 53	.n_yes_ranges = ARRAY_SIZE(max77705_writable_ranges),
 54};
 55
 56static const struct regmap_config max77705_regmap_config = {
 57	.reg_bits = 8,
 58	.val_bits = 8,
 59	.rd_table = &max77705_readable_table,
 60	.wr_table = &max77705_writable_table,
 61	.max_register = MAX77705_PMIC_REG_USBC_RESET,
 62};
 63
 64static const struct regmap_irq max77705_irqs[] = {
 65	{ .mask = MAX77705_SRC_IRQ_CHG, },
 66	{ .mask = MAX77705_SRC_IRQ_TOP, },
 67	{ .mask = MAX77705_SRC_IRQ_FG, },
 68	{ .mask = MAX77705_SRC_IRQ_USBC, },
 69};
 70
 71static const struct regmap_irq_chip max77705_irq_chip = {
 72	.name		= "max77705",
 73	.status_base	= MAX77705_PMIC_REG_INTSRC,
 74	.ack_base	= MAX77705_PMIC_REG_INTSRC,
 75	.mask_base	= MAX77705_PMIC_REG_INTSRC_MASK,
 76	.num_regs	= 1,
 77	.irqs		= max77705_irqs,
 78	.num_irqs	= ARRAY_SIZE(max77705_irqs),
 79};
 80
 81static int max77705_i2c_probe(struct i2c_client *i2c)
 82{
 83	struct device *dev = &i2c->dev;
 84	struct max77693_dev *max77705;
 85	struct regmap_irq_chip_data *irq_data;
 86	struct irq_domain *domain;
 87	enum max77705_hw_rev pmic_rev;
 88	unsigned int pmic_rev_value;
 89	int ret;
 90
 91	max77705 = devm_kzalloc(dev, sizeof(*max77705), GFP_KERNEL);
 92	if (!max77705)
 93		return -ENOMEM;
 94
 95	max77705->i2c = i2c;
 96	max77705->type = TYPE_MAX77705;
 97	i2c_set_clientdata(i2c, max77705);
 98
 99	max77705->regmap = devm_regmap_init_i2c(i2c, &max77705_regmap_config);
100	if (IS_ERR(max77705->regmap))
101		return PTR_ERR(max77705->regmap);
102
103	ret = regmap_read(max77705->regmap, MAX77705_PMIC_REG_PMICREV, &pmic_rev_value);
104	if (ret < 0)
105		return -ENODEV;
106
107	pmic_rev = pmic_rev_value & MAX77705_REVISION_MASK;
108	if (pmic_rev != MAX77705_PASS3)
109		return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
110
111	/* Active Discharge Enable */
112	regmap_update_bits(max77705->regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
113
114	ret = devm_regmap_add_irq_chip(dev, max77705->regmap,
115					i2c->irq,
116					IRQF_ONESHOT, 0,
117					&max77705_irq_chip,
118					&irq_data);
119	if (ret)
120		return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
121
122	domain = regmap_irq_get_domain(irq_data);
123
124	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
125				   max77705_devs, ARRAY_SIZE(max77705_devs),
126				   NULL, 0, domain);
127	if (ret)
128		return dev_err_probe(dev, ret, "Failed to register child devices\n");
129
130	ret = devm_device_init_wakeup(dev);
131	if (ret)
132		return dev_err_probe(dev, ret, "Failed to init wakeup\n");
133
134	return 0;
135}
136
137static int max77705_suspend(struct device *dev)
138{
139	struct i2c_client *i2c = to_i2c_client(dev);
140
141	disable_irq(i2c->irq);
142
143	if (device_may_wakeup(dev))
144		enable_irq_wake(i2c->irq);
145
146	return 0;
147}
148
149static int max77705_resume(struct device *dev)
150{
151	struct i2c_client *i2c = to_i2c_client(dev);
152
153	if (device_may_wakeup(dev))
154		disable_irq_wake(i2c->irq);
155
156	enable_irq(i2c->irq);
157
158	return 0;
159}
160DEFINE_SIMPLE_DEV_PM_OPS(max77705_pm_ops, max77705_suspend, max77705_resume);
161
162static const struct of_device_id max77705_i2c_of_match[] = {
163	{ .compatible = "maxim,max77705" },
164	{ }
165};
166MODULE_DEVICE_TABLE(of, max77705_i2c_of_match);
167
168static struct i2c_driver max77705_i2c_driver = {
169	.driver = {
170		.name			= "max77705",
171		.of_match_table		= max77705_i2c_of_match,
172		.pm			= pm_sleep_ptr(&max77705_pm_ops),
173	},
174	.probe = max77705_i2c_probe
175};
176module_i2c_driver(max77705_i2c_driver);
177
178MODULE_DESCRIPTION("Maxim MAX77705 PMIC core driver");
179MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>");
180MODULE_LICENSE("GPL");
~/ Read-only file preview.