1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2021 Richtek Technology Corp.
5 * Author: ChiYuan Huang <cy_huang@richtek.com>
8 #include <linux/gpio/consumer.h>
10 #include <linux/kernel.h>
11 #include <linux/mfd/core.h>
12 #include <linux/module.h>
13 #include <linux/regmap.h>
15 #define RT4831_REG_REVISION 0x01
16 #define RT4831_REG_ENABLE 0x08
17 #define RT4831_REG_I2CPROT 0x15
19 #define RICHTEK_VENDOR_ID 0x03
20 #define RT4831_VID_MASK GENMASK(1, 0)
21 #define RT4831_RESET_MASK BIT(7)
22 #define RT4831_I2CSAFETMR_MASK BIT(0)
24 static const struct mfd_cell rt4831_subdevs
[] = {
25 MFD_CELL_OF("rt4831-backlight", NULL
, NULL
, 0, 0, "richtek,rt4831-backlight"),
26 MFD_CELL_NAME("rt4831-regulator")
29 static bool rt4831_is_accessible_reg(struct device
*dev
, unsigned int reg
)
31 if (reg
>= RT4831_REG_REVISION
&& reg
<= RT4831_REG_I2CPROT
)
36 static const struct regmap_config rt4831_regmap_config
= {
39 .max_register
= RT4831_REG_I2CPROT
,
41 .readable_reg
= rt4831_is_accessible_reg
,
42 .writeable_reg
= rt4831_is_accessible_reg
,
45 static int rt4831_probe(struct i2c_client
*client
)
47 struct gpio_desc
*enable_gpio
;
48 struct regmap
*regmap
;
52 enable_gpio
= devm_gpiod_get_optional(&client
->dev
, "enable", GPIOD_OUT_HIGH
);
53 if (IS_ERR(enable_gpio
)) {
54 dev_err(&client
->dev
, "Failed to get 'enable' GPIO\n");
55 return PTR_ERR(enable_gpio
);
58 regmap
= devm_regmap_init_i2c(client
, &rt4831_regmap_config
);
60 dev_err(&client
->dev
, "Failed to initialize regmap\n");
61 return PTR_ERR(regmap
);
64 ret
= regmap_read(regmap
, RT4831_REG_REVISION
, &chip_id
);
66 dev_err(&client
->dev
, "Failed to get H/W revision\n");
70 if ((chip_id
& RT4831_VID_MASK
) != RICHTEK_VENDOR_ID
) {
71 dev_err(&client
->dev
, "Chip vendor ID 0x%02x not matched\n", chip_id
);
76 * Used to prevent the abnormal shutdown.
77 * If SCL/SDA both keep low for one second to reset HW.
79 ret
= regmap_update_bits(regmap
, RT4831_REG_I2CPROT
, RT4831_I2CSAFETMR_MASK
,
80 RT4831_I2CSAFETMR_MASK
);
82 dev_err(&client
->dev
, "Failed to enable I2C safety timer\n");
86 return devm_mfd_add_devices(&client
->dev
, PLATFORM_DEVID_AUTO
, rt4831_subdevs
,
87 ARRAY_SIZE(rt4831_subdevs
), NULL
, 0, NULL
);
90 static void rt4831_remove(struct i2c_client
*client
)
92 struct regmap
*regmap
= dev_get_regmap(&client
->dev
, NULL
);
95 /* Disable WLED and DSV outputs */
96 ret
= regmap_update_bits(regmap
, RT4831_REG_ENABLE
, RT4831_RESET_MASK
, RT4831_RESET_MASK
);
98 dev_warn(&client
->dev
, "Failed to disable outputs (%pe)\n", ERR_PTR(ret
));
101 static const struct of_device_id __maybe_unused rt4831_of_match
[] = {
102 { .compatible
= "richtek,rt4831", },
105 MODULE_DEVICE_TABLE(of
, rt4831_of_match
);
107 static struct i2c_driver rt4831_driver
= {
110 .of_match_table
= rt4831_of_match
,
112 .probe
= rt4831_probe
,
113 .remove
= rt4831_remove
,
115 module_i2c_driver(rt4831_driver
);
117 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
118 MODULE_DESCRIPTION("Richtek RT4831 core driver");
119 MODULE_LICENSE("GPL v2");