From b473fca294b26a7afffcae8444936e24198aab6e Mon Sep 17 00:00:00 2001 From: shengfei Xu Date: Thu, 23 Nov 2023 03:02:22 +0000 Subject: [PATCH] mfd: rk806: Add RK806 support i2c Signed-off-by: shengfei Xu Change-Id: Ic7a633fe53b3218cbcc2e8a36d214d6c4c865f85 --- drivers/mfd/Kconfig | 8 +++++ drivers/mfd/Makefile | 1 + drivers/mfd/rk806-core.c | 10 +++++-- drivers/mfd/rk806-i2c.c | 62 +++++++++++++++++++++++++++++++++++++++ drivers/mfd/rk806-spi.c | 10 ++----- include/linux/mfd/rk806.h | 4 ++- 6 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 drivers/mfd/rk806-i2c.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index aa1fe3bcf7f6..0ace44230a00 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1188,6 +1188,14 @@ config MFD_RK806 through SPI interface. The device supports multiple sub-devices including interrupts, LDO & DCDC regulators, and onkey. +config MFD_RK806_I2C + tristate "RK806 Power Management chip with I2C" + select MFD_RK806 + select REGMAP_I2C + select REGMAP_IRQ + help + If you say yes here you get support for the RK806 PM chips with I2c interface. + config MFD_RK806_SPI tristate "RK806 Power Management chip with SPI" select MFD_RK806 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 17c722019f32..57f62d328f22 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -227,6 +227,7 @@ obj-$(CONFIG_MFD_RK630) += rk630.o obj-$(CONFIG_MFD_RK630_I2C) += rk630-i2c.o obj-$(CONFIG_MFD_RK630_SPI) += rk630-spi.o obj-$(CONFIG_MFD_RK806) += rk806-core.o +obj-$(CONFIG_MFD_RK806_I2C) += rk806-i2c.o obj-$(CONFIG_MFD_RK806_SPI) += rk806-spi.o obj-$(CONFIG_MFD_RK808) += rk808.o obj-$(CONFIG_MFD_RK1000) += rk1000-core.o diff --git a/drivers/mfd/rk806-core.c b/drivers/mfd/rk806-core.c index 5421ac95578f..1ab83fbf397c 100644 --- a/drivers/mfd/rk806-core.c +++ b/drivers/mfd/rk806-core.c @@ -352,13 +352,13 @@ static const struct regmap_access_table rk806_volatile_table = { .n_yes_ranges = ARRAY_SIZE(rk806_yes_ranges), }; -const struct regmap_config rk806_regmap_config_spi = { +const struct regmap_config rk806_regmap_config = { .reg_bits = 8, .val_bits = 8, .cache_type = REGCACHE_RBTREE, .volatile_table = &rk806_volatile_table, }; -EXPORT_SYMBOL_GPL(rk806_regmap_config_spi); +EXPORT_SYMBOL_GPL(rk806_regmap_config); static struct kobject *rk806_kobj[2]; static struct rk806 *rk806_master; @@ -825,6 +825,12 @@ int rk806_device_exit(struct rk806 *rk806) } EXPORT_SYMBOL_GPL(rk806_device_exit); +const struct of_device_id rk806_of_match[] = { + { .compatible = "rockchip,rk806", }, + { } +}; +EXPORT_SYMBOL_GPL(rk806_of_match); + MODULE_AUTHOR("Xu Shengfei "); MODULE_DESCRIPTION("rk806 MFD Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/rk806-i2c.c b/drivers/mfd/rk806-i2c.c new file mode 100644 index 000000000000..26558e90d1fe --- /dev/null +++ b/drivers/mfd/rk806-i2c.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rk806-i2c.c -- I2C access for Rockchip RK806 + * + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + * + * Author: Xu Shengfei + */ + +#include +#include +#include + +static int rk806_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rk806 *rk806; + + rk806 = devm_kzalloc(&client->dev, sizeof(*rk806), GFP_KERNEL); + if (!rk806) + return -ENOMEM; + + i2c_set_clientdata(client, rk806); + rk806->dev = &client->dev; + rk806->irq = client->irq; + + if (!client->irq) { + dev_err(&client->dev, "No interrupt support, no core IRQ\n"); + return -EINVAL; + } + + rk806->regmap = devm_regmap_init_i2c(client, &rk806_regmap_config); + if (IS_ERR(rk806->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(rk806->regmap); + } + + return rk806_device_init(rk806); +} + +static int rk806_remove(struct i2c_client *client) +{ + struct rk806 *rk806 = i2c_get_clientdata(client); + + rk806_device_exit(rk806); + + return 0; +} + +static struct i2c_driver rk806_i2c_driver = { + .driver = { + .name = "rk806", + .of_match_table = of_match_ptr(rk806_of_match), + }, + .probe = rk806_i2c_probe, + .remove = rk806_remove, +}; +module_i2c_driver(rk806_i2c_driver); + +MODULE_AUTHOR("Xu Shengfei "); +MODULE_DESCRIPTION("RK806 I2C Interface Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/rk806-spi.c b/drivers/mfd/rk806-spi.c index 246602417c66..561037865200 100644 --- a/drivers/mfd/rk806-spi.c +++ b/drivers/mfd/rk806-spi.c @@ -12,12 +12,6 @@ #include #include -static const struct of_device_id rk806_spi_of_match_table[] = { - { .compatible = "rockchip,rk806", }, - { } -}; -MODULE_DEVICE_TABLE(of, rk806_spi_of_match_table); - static int rk806_spi_write(struct spi_device *spi, char addr, const char *data, @@ -101,7 +95,7 @@ static int rk806_spi_probe(struct spi_device *spi) rk806->regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi, &spi->dev, - &rk806_regmap_config_spi); + &rk806_regmap_config); if (IS_ERR(rk806->regmap)) { dev_err(rk806->dev, "Failed to initialize register map\n"); return PTR_ERR(rk806->regmap); @@ -127,7 +121,7 @@ static struct spi_driver rk806_spi_driver = { .driver = { .name = "rk806", .owner = THIS_MODULE, - .of_match_table = rk806_spi_of_match_table, + .of_match_table = of_match_ptr(rk806_of_match), }, .probe = rk806_spi_probe, .remove = rk806_spi_remove, diff --git a/include/linux/mfd/rk806.h b/include/linux/mfd/rk806.h index 71e833c51444..7735121592c8 100644 --- a/include/linux/mfd/rk806.h +++ b/include/linux/mfd/rk806.h @@ -6,6 +6,7 @@ #ifndef __LINUX_REGULATOR_RK806_H #define __LINUX_REGULATOR_RK806_H +#include #include #include #include @@ -518,7 +519,8 @@ struct rk806 { int vb_lo_irq; }; -extern const struct regmap_config rk806_regmap_config_spi; +extern const struct regmap_config rk806_regmap_config; +extern const struct of_device_id rk806_of_match[]; int rk806_device_init(struct rk806 *rk806); int rk806_device_exit(struct rk806 *rk806); int rk806_field_write(struct rk806 *rk806,