xref: /openbmc/linux/drivers/mfd/rt5120.c (revision 9816d859)
14e4627e1SChiYuan Huang // SPDX-License-Identifier: GPL-2.0-only
24e4627e1SChiYuan Huang /*
34e4627e1SChiYuan Huang  * Copyright (C) 2022 Richtek Technology Corp.
44e4627e1SChiYuan Huang  * Author: ChiYuan Huang <cy_huang@richtek.com>
54e4627e1SChiYuan Huang  */
64e4627e1SChiYuan Huang 
74e4627e1SChiYuan Huang #include <linux/i2c.h>
84e4627e1SChiYuan Huang #include <linux/kernel.h>
94e4627e1SChiYuan Huang #include <linux/mfd/core.h>
104e4627e1SChiYuan Huang #include <linux/module.h>
114e4627e1SChiYuan Huang #include <linux/mod_devicetable.h>
124e4627e1SChiYuan Huang #include <linux/regmap.h>
134e4627e1SChiYuan Huang 
144e4627e1SChiYuan Huang #define RT5120_REG_INTENABLE	0x1D
154e4627e1SChiYuan Huang #define RT5120_REG_INTSTAT	0x1E
164e4627e1SChiYuan Huang #define RT5120_REG_FZCMODE	0x44
174e4627e1SChiYuan Huang 
184e4627e1SChiYuan Huang #define RT5120_INT_HOTDIE	0
194e4627e1SChiYuan Huang #define RT5120_INT_PWRKEY_REL	5
204e4627e1SChiYuan Huang #define RT5120_INT_PWRKEY_PRESS	6
214e4627e1SChiYuan Huang 
224e4627e1SChiYuan Huang static const struct regmap_range rt5120_rd_yes_ranges[] = {
234e4627e1SChiYuan Huang 	regmap_reg_range(0x03, 0x13),
244e4627e1SChiYuan Huang 	regmap_reg_range(0x1c, 0x20),
254e4627e1SChiYuan Huang 	regmap_reg_range(0x44, 0x44),
264e4627e1SChiYuan Huang };
274e4627e1SChiYuan Huang 
284e4627e1SChiYuan Huang static const struct regmap_range rt5120_wr_yes_ranges[] = {
294e4627e1SChiYuan Huang 	regmap_reg_range(0x06, 0x13),
304e4627e1SChiYuan Huang 	regmap_reg_range(0x1c, 0x20),
314e4627e1SChiYuan Huang 	regmap_reg_range(0x44, 0x44),
324e4627e1SChiYuan Huang };
334e4627e1SChiYuan Huang 
344e4627e1SChiYuan Huang static const struct regmap_access_table rt5120_rd_table = {
354e4627e1SChiYuan Huang 	.yes_ranges = rt5120_rd_yes_ranges,
364e4627e1SChiYuan Huang 	.n_yes_ranges = ARRAY_SIZE(rt5120_rd_yes_ranges),
374e4627e1SChiYuan Huang };
384e4627e1SChiYuan Huang 
394e4627e1SChiYuan Huang static const struct regmap_access_table rt5120_wr_table = {
404e4627e1SChiYuan Huang 	.yes_ranges = rt5120_wr_yes_ranges,
414e4627e1SChiYuan Huang 	.n_yes_ranges = ARRAY_SIZE(rt5120_wr_yes_ranges),
424e4627e1SChiYuan Huang };
434e4627e1SChiYuan Huang 
444e4627e1SChiYuan Huang static const struct regmap_config rt5120_regmap_config = {
454e4627e1SChiYuan Huang 	.reg_bits = 8,
464e4627e1SChiYuan Huang 	.val_bits = 8,
474e4627e1SChiYuan Huang 	.max_register = RT5120_REG_FZCMODE,
484e4627e1SChiYuan Huang 
494e4627e1SChiYuan Huang 	.wr_table = &rt5120_wr_table,
504e4627e1SChiYuan Huang 	.rd_table = &rt5120_rd_table,
514e4627e1SChiYuan Huang };
524e4627e1SChiYuan Huang 
534e4627e1SChiYuan Huang static const struct regmap_irq rt5120_irqs[] = {
544e4627e1SChiYuan Huang 	REGMAP_IRQ_REG_LINE(RT5120_INT_HOTDIE, 8),
554e4627e1SChiYuan Huang 	REGMAP_IRQ_REG_LINE(RT5120_INT_PWRKEY_REL, 8),
564e4627e1SChiYuan Huang 	REGMAP_IRQ_REG_LINE(RT5120_INT_PWRKEY_PRESS, 8),
574e4627e1SChiYuan Huang };
584e4627e1SChiYuan Huang 
594e4627e1SChiYuan Huang static const struct regmap_irq_chip rt5120_irq_chip = {
604e4627e1SChiYuan Huang 	.name = "rt5120-pmic",
614e4627e1SChiYuan Huang 	.status_base = RT5120_REG_INTSTAT,
62cdd13e72SAidan MacDonald 	.unmask_base = RT5120_REG_INTENABLE,
634e4627e1SChiYuan Huang 	.ack_base = RT5120_REG_INTSTAT,
644e4627e1SChiYuan Huang 	.use_ack = true,
654e4627e1SChiYuan Huang 	.num_regs = 1,
664e4627e1SChiYuan Huang 	.irqs = rt5120_irqs,
674e4627e1SChiYuan Huang 	.num_irqs = ARRAY_SIZE(rt5120_irqs),
684e4627e1SChiYuan Huang };
694e4627e1SChiYuan Huang 
704e4627e1SChiYuan Huang static const struct resource rt5120_regulator_resources[] = {
714e4627e1SChiYuan Huang 	DEFINE_RES_IRQ(RT5120_INT_HOTDIE),
724e4627e1SChiYuan Huang };
734e4627e1SChiYuan Huang 
744e4627e1SChiYuan Huang static const struct resource rt5120_pwrkey_resources[] = {
754e4627e1SChiYuan Huang 	DEFINE_RES_IRQ_NAMED(RT5120_INT_PWRKEY_PRESS, "pwrkey-press"),
764e4627e1SChiYuan Huang 	DEFINE_RES_IRQ_NAMED(RT5120_INT_PWRKEY_REL, "pwrkey-release"),
774e4627e1SChiYuan Huang };
784e4627e1SChiYuan Huang 
794e4627e1SChiYuan Huang static const struct mfd_cell rt5120_devs[] = {
804e4627e1SChiYuan Huang 	MFD_CELL_RES("rt5120-regulator", rt5120_regulator_resources),
814e4627e1SChiYuan Huang 	MFD_CELL_OF("rt5120-pwrkey", rt5120_pwrkey_resources, NULL, 0, 0, "richtek,rt5120-pwrkey"),
824e4627e1SChiYuan Huang };
834e4627e1SChiYuan Huang 
rt5120_probe(struct i2c_client * i2c)844e4627e1SChiYuan Huang static int rt5120_probe(struct i2c_client *i2c)
854e4627e1SChiYuan Huang {
864e4627e1SChiYuan Huang 	struct device *dev = &i2c->dev;
874e4627e1SChiYuan Huang 	struct regmap *regmap;
884e4627e1SChiYuan Huang 	struct regmap_irq_chip_data *irq_data;
894e4627e1SChiYuan Huang 	int ret;
904e4627e1SChiYuan Huang 
914e4627e1SChiYuan Huang 	regmap = devm_regmap_init_i2c(i2c, &rt5120_regmap_config);
924e4627e1SChiYuan Huang 	if (IS_ERR(regmap))
934e4627e1SChiYuan Huang 		return dev_err_probe(dev, PTR_ERR(regmap),
944e4627e1SChiYuan Huang 				     "Failed to init regmap\n");
954e4627e1SChiYuan Huang 
964e4627e1SChiYuan Huang 	ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq, IRQF_ONESHOT, 0,
974e4627e1SChiYuan Huang 				       &rt5120_irq_chip, &irq_data);
984e4627e1SChiYuan Huang 	if (ret)
994e4627e1SChiYuan Huang 		return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
1004e4627e1SChiYuan Huang 
1014e4627e1SChiYuan Huang 	return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, rt5120_devs,
1024e4627e1SChiYuan Huang 				    ARRAY_SIZE(rt5120_devs), NULL, 0,
1034e4627e1SChiYuan Huang 				    regmap_irq_get_domain(irq_data));
1044e4627e1SChiYuan Huang }
1054e4627e1SChiYuan Huang 
1064e4627e1SChiYuan Huang static const struct of_device_id rt5120_device_match_table[] = {
1074e4627e1SChiYuan Huang 	{ .compatible = "richtek,rt5120" },
1084e4627e1SChiYuan Huang 	{}
1094e4627e1SChiYuan Huang };
1104e4627e1SChiYuan Huang MODULE_DEVICE_TABLE(of, rt5120_device_match_table);
1114e4627e1SChiYuan Huang 
1124e4627e1SChiYuan Huang static struct i2c_driver rt5120_driver = {
1134e4627e1SChiYuan Huang 	.driver = {
1144e4627e1SChiYuan Huang 		.name = "rt5120",
1154e4627e1SChiYuan Huang 		.of_match_table = rt5120_device_match_table,
1164e4627e1SChiYuan Huang 	},
117*9816d859SUwe Kleine-König 	.probe = rt5120_probe,
1184e4627e1SChiYuan Huang };
1194e4627e1SChiYuan Huang module_i2c_driver(rt5120_driver);
1204e4627e1SChiYuan Huang 
1214e4627e1SChiYuan Huang MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
1224e4627e1SChiYuan Huang MODULE_DESCRIPTION("Richtek RT5120 I2C driver");
1234e4627e1SChiYuan Huang MODULE_LICENSE("GPL v2");
124