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