linux/drivers/mfd/rt4831.c
Uwe Kleine-König ed5c2f5fd1 i2c: Make remove callback return void
The value returned by an i2c driver's remove function is mostly ignored.
(Only an error message is printed if the value is non-zero that the
error is ignored.)

So change the prototype of the remove function to return no value. This
way driver authors are not tempted to assume that passing an error to
the upper layer is a good idea. All drivers are adapted accordingly.
There is no intended change of behaviour, all callbacks were prepared to
return 0 before.

Reviewed-by: Peter Senna Tschudin <peter.senna@gmail.com>
Reviewed-by: Jeremy Kerr <jk@codeconstruct.com.au>
Reviewed-by: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Crt Mori <cmo@melexis.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Marek Behún <kabel@kernel.org> # for leds-turris-omnia
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Petr Machata <petrm@nvidia.com> # for mlxsw
Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com> # for surface3_power
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> # for bmc150-accel-i2c + kxcjk-1013
Reviewed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> # for media/* + staging/media/*
Acked-by: Miguel Ojeda <ojeda@kernel.org> # for auxdisplay/ht16k33 + auxdisplay/lcd2s
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # for versaclock5
Reviewed-by: Ajay Gupta <ajayg@nvidia.com> # for ucsi_ccg
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # for iio
Acked-by: Peter Rosin <peda@axentia.se> # for i2c-mux-*, max9860
Acked-by: Adrien Grassein <adrien.grassein@gmail.com> # for lontium-lt8912b
Reviewed-by: Jean Delvare <jdelvare@suse.de> # for hwmon, i2c-core and i2c/muxes
Acked-by: Corey Minyard <cminyard@mvista.com> # for IPMI
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> # for drivers/power
Acked-by: Krzysztof Hałasa <khalasa@piap.pl>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
2022-08-16 12:46:26 +02:00

119 lines
3.1 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Richtek Technology Corp.
*
* Author: ChiYuan Huang <cy_huang@richtek.com>
*/
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/regmap.h>
#define RT4831_REG_REVISION 0x01
#define RT4831_REG_ENABLE 0x08
#define RT4831_REG_I2CPROT 0x15
#define RICHTEK_VENDOR_ID 0x03
#define RT4831_VID_MASK GENMASK(1, 0)
#define RT4831_RESET_MASK BIT(7)
#define RT4831_I2CSAFETMR_MASK BIT(0)
static const struct mfd_cell rt4831_subdevs[] = {
MFD_CELL_OF("rt4831-backlight", NULL, NULL, 0, 0, "richtek,rt4831-backlight"),
MFD_CELL_NAME("rt4831-regulator")
};
static bool rt4831_is_accessible_reg(struct device *dev, unsigned int reg)
{
if (reg >= RT4831_REG_REVISION && reg <= RT4831_REG_I2CPROT)
return true;
return false;
}
static const struct regmap_config rt4831_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RT4831_REG_I2CPROT,
.readable_reg = rt4831_is_accessible_reg,
.writeable_reg = rt4831_is_accessible_reg,
};
static int rt4831_probe(struct i2c_client *client)
{
struct gpio_desc *enable_gpio;
struct regmap *regmap;
unsigned int chip_id;
int ret;
enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(enable_gpio)) {
dev_err(&client->dev, "Failed to get 'enable' GPIO\n");
return PTR_ERR(enable_gpio);
}
regmap = devm_regmap_init_i2c(client, &rt4831_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to initialize regmap\n");
return PTR_ERR(regmap);
}
ret = regmap_read(regmap, RT4831_REG_REVISION, &chip_id);
if (ret) {
dev_err(&client->dev, "Failed to get H/W revision\n");
return ret;
}
if ((chip_id & RT4831_VID_MASK) != RICHTEK_VENDOR_ID) {
dev_err(&client->dev, "Chip vendor ID 0x%02x not matched\n", chip_id);
return -ENODEV;
}
/*
* Used to prevent the abnormal shutdown.
* If SCL/SDA both keep low for one second to reset HW.
*/
ret = regmap_update_bits(regmap, RT4831_REG_I2CPROT, RT4831_I2CSAFETMR_MASK,
RT4831_I2CSAFETMR_MASK);
if (ret) {
dev_err(&client->dev, "Failed to enable I2C safety timer\n");
return ret;
}
return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, rt4831_subdevs,
ARRAY_SIZE(rt4831_subdevs), NULL, 0, NULL);
}
static void rt4831_remove(struct i2c_client *client)
{
struct regmap *regmap = dev_get_regmap(&client->dev, NULL);
int ret;
/* Disable WLED and DSV outputs */
ret = regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK);
if (ret)
dev_warn(&client->dev, "Failed to disable outputs (%pe)\n", ERR_PTR(ret));
}
static const struct of_device_id __maybe_unused rt4831_of_match[] = {
{ .compatible = "richtek,rt4831", },
{}
};
MODULE_DEVICE_TABLE(of, rt4831_of_match);
static struct i2c_driver rt4831_driver = {
.driver = {
.name = "rt4831",
.of_match_table = rt4831_of_match,
},
.probe_new = rt4831_probe,
.remove = rt4831_remove,
};
module_i2c_driver(rt4831_driver);
MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
MODULE_LICENSE("GPL v2");