Commit c20e8c5b authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Lee Jones

mfd: rk808: Split into core and i2c

Split rk808 into a core and an i2c part in preparation for
SPI support.

Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> # for RTC
Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock64, Quartz64 Model A + B
Tested-by: Vincent Legoll <vincent.legoll@gmail.com> # Pine64 QuartzPro64
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20230504173618.142075-6-sebastian.reichel@collabora.comSigned-off-by: default avatarLee Jones <lee@kernel.org>
parent 04944997
...@@ -82,7 +82,7 @@ config COMMON_CLK_MAX9485 ...@@ -82,7 +82,7 @@ config COMMON_CLK_MAX9485
config COMMON_CLK_RK808 config COMMON_CLK_RK808
tristate "Clock driver for RK805/RK808/RK809/RK817/RK818" tristate "Clock driver for RK805/RK808/RK809/RK817/RK818"
depends on MFD_RK808 depends on MFD_RK8XX
help help
This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock. This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock.
These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each.
......
...@@ -609,7 +609,7 @@ config INPUT_PWM_VIBRA ...@@ -609,7 +609,7 @@ config INPUT_PWM_VIBRA
config INPUT_RK805_PWRKEY config INPUT_RK805_PWRKEY
tristate "Rockchip RK805 PMIC power key support" tristate "Rockchip RK805 PMIC power key support"
depends on MFD_RK808 depends on MFD_RK8XX
help help
Select this option to enable power key driver for RK805. Select this option to enable power key driver for RK805.
......
...@@ -1183,12 +1183,17 @@ config MFD_RC5T583 ...@@ -1183,12 +1183,17 @@ config MFD_RC5T583
Additional drivers must be enabled in order to use the Additional drivers must be enabled in order to use the
different functionality of the device. different functionality of the device.
config MFD_RK808 config MFD_RK8XX
bool
select MFD_CORE
config MFD_RK8XX_I2C
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip" tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
depends on I2C && OF depends on I2C && OF
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ select REGMAP_IRQ
select MFD_RK8XX
help help
If you say yes here you get support for the RK805, RK808, RK809, If you say yes here you get support for the RK805, RK808, RK809,
RK817 and RK818 Power Management chips. RK817 and RK818 Power Management chips.
......
...@@ -214,7 +214,8 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o ...@@ -214,7 +214,8 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
obj-$(CONFIG_MFD_NTXEC) += ntxec.o obj-$(CONFIG_MFD_NTXEC) += ntxec.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_RK808) += rk808.o obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o
obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o
obj-$(CONFIG_MFD_RN5T618) += rn5t618.o obj-$(CONFIG_MFD_RN5T618) += rn5t618.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o obj-$(CONFIG_MFD_SYSCON) += syscon.o
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* MFD core driver for Rockchip RK808/RK818 * MFD core driver for Rockchip RK8XX
* *
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
* *
* Author: Chris Zhong <zyw@rock-chips.com> * Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com> * Author: Zhang Qing <zhangqing@rock-chips.com>
*
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
*
* Author: Wadim Egorov <w.egorov@phytec.de> * Author: Wadim Egorov <w.egorov@phytec.de>
*/ */
#include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/rk808.h> #include <linux/mfd/rk808.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
...@@ -27,92 +24,6 @@ struct rk808_reg_data { ...@@ -27,92 +24,6 @@ struct rk808_reg_data {
int value; int value;
}; };
static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
{
/*
* Notes:
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
* we don't use that feature. It's better to cache.
* - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
* bits are cleared in case when we shutoff anyway, but better safe.
*/
switch (reg) {
case RK808_SECONDS_REG ... RK808_WEEKS_REG:
case RK808_RTC_STATUS_REG:
case RK808_VB_MON_REG:
case RK808_THERMAL_REG:
case RK808_DCDC_UV_STS_REG:
case RK808_LDO_UV_STS_REG:
case RK808_DCDC_PG_REG:
case RK808_LDO_PG_REG:
case RK808_DEVCTRL_REG:
case RK808_INT_STS_REG1:
case RK808_INT_STS_REG2:
return true;
}
return false;
}
static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
{
/*
* Notes:
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
* we don't use that feature. It's better to cache.
*/
switch (reg) {
case RK817_SECONDS_REG ... RK817_WEEKS_REG:
case RK817_RTC_STATUS_REG:
case RK817_CODEC_DTOP_LPT_SRST:
case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
case RK817_PMIC_CHRG_STS:
case RK817_PMIC_CHRG_OUT:
case RK817_PMIC_CHRG_IN:
case RK817_INT_STS_REG0:
case RK817_INT_STS_REG1:
case RK817_INT_STS_REG2:
case RK817_SYS_STS:
return true;
}
return false;
}
static const struct regmap_config rk818_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK818_USB_CTRL_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk805_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK805_OFF_SOURCE_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk808_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK808_IO_POL_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk817_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK817_GPIO_INT_CFG,
.cache_type = REGCACHE_NONE,
.volatile_reg = rk817_is_volatile_reg,
};
static const struct resource rtc_resources[] = { static const struct resource rtc_resources[] = {
DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM),
}; };
...@@ -605,9 +516,9 @@ static int rk808_restart(struct sys_off_data *data) ...@@ -605,9 +516,9 @@ static int rk808_restart(struct sys_off_data *data)
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static void rk8xx_shutdown(struct i2c_client *client) void rk8xx_shutdown(struct device *dev)
{ {
struct rk808 *rk808 = i2c_get_clientdata(client); struct rk808 *rk808 = dev_get_drvdata(dev);
int ret; int ret;
switch (rk808->variant) { switch (rk808->variant) {
...@@ -628,61 +539,31 @@ static void rk8xx_shutdown(struct i2c_client *client) ...@@ -628,61 +539,31 @@ static void rk8xx_shutdown(struct i2c_client *client)
return; return;
} }
if (ret) if (ret)
dev_warn(&client->dev, dev_warn(dev,
"Cannot switch to power down function\n"); "Cannot switch to power down function\n");
} }
EXPORT_SYMBOL_GPL(rk8xx_shutdown);
static const struct of_device_id rk808_of_match[] = { int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap)
{ .compatible = "rockchip,rk805" },
{ .compatible = "rockchip,rk808" },
{ .compatible = "rockchip,rk809" },
{ .compatible = "rockchip,rk817" },
{ .compatible = "rockchip,rk818" },
{ },
};
MODULE_DEVICE_TABLE(of, rk808_of_match);
static int rk808_probe(struct i2c_client *client)
{ {
struct device_node *np = client->dev.of_node;
struct rk808 *rk808; struct rk808 *rk808;
const struct rk808_reg_data *pre_init_reg; const struct rk808_reg_data *pre_init_reg;
const struct mfd_cell *cells; const struct mfd_cell *cells;
int nr_pre_init_regs; int nr_pre_init_regs;
int nr_cells; int nr_cells;
int msb, lsb;
unsigned char pmic_id_msb, pmic_id_lsb;
int ret; int ret;
int i; int i;
rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL);
if (!rk808) if (!rk808)
return -ENOMEM; return -ENOMEM;
rk808->dev = dev;
if (of_device_is_compatible(np, "rockchip,rk817") || rk808->variant = variant;
of_device_is_compatible(np, "rockchip,rk809")) { rk808->regmap = regmap;
pmic_id_msb = RK817_ID_MSB; dev_set_drvdata(dev, rk808);
pmic_id_lsb = RK817_ID_LSB;
} else {
pmic_id_msb = RK808_ID_MSB;
pmic_id_lsb = RK808_ID_LSB;
}
/* Read chip variant */
msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
if (msb < 0)
return dev_err_probe(&client->dev, msb, "failed to read the chip id MSB\n");
lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
if (lsb < 0)
return dev_err_probe(&client->dev, lsb, "failed to read the chip id LSB\n");
rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
switch (rk808->variant) { switch (rk808->variant) {
case RK805_ID: case RK805_ID:
rk808->regmap_cfg = &rk805_regmap_config;
rk808->regmap_irq_chip = &rk805_irq_chip; rk808->regmap_irq_chip = &rk805_irq_chip;
pre_init_reg = rk805_pre_init_reg; pre_init_reg = rk805_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
...@@ -690,7 +571,6 @@ static int rk808_probe(struct i2c_client *client) ...@@ -690,7 +571,6 @@ static int rk808_probe(struct i2c_client *client)
nr_cells = ARRAY_SIZE(rk805s); nr_cells = ARRAY_SIZE(rk805s);
break; break;
case RK808_ID: case RK808_ID:
rk808->regmap_cfg = &rk808_regmap_config;
rk808->regmap_irq_chip = &rk808_irq_chip; rk808->regmap_irq_chip = &rk808_irq_chip;
pre_init_reg = rk808_pre_init_reg; pre_init_reg = rk808_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
...@@ -698,7 +578,6 @@ static int rk808_probe(struct i2c_client *client) ...@@ -698,7 +578,6 @@ static int rk808_probe(struct i2c_client *client)
nr_cells = ARRAY_SIZE(rk808s); nr_cells = ARRAY_SIZE(rk808s);
break; break;
case RK818_ID: case RK818_ID:
rk808->regmap_cfg = &rk818_regmap_config;
rk808->regmap_irq_chip = &rk818_irq_chip; rk808->regmap_irq_chip = &rk818_irq_chip;
pre_init_reg = rk818_pre_init_reg; pre_init_reg = rk818_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
...@@ -707,7 +586,6 @@ static int rk808_probe(struct i2c_client *client) ...@@ -707,7 +586,6 @@ static int rk808_probe(struct i2c_client *client)
break; break;
case RK809_ID: case RK809_ID:
case RK817_ID: case RK817_ID:
rk808->regmap_cfg = &rk817_regmap_config;
rk808->regmap_irq_chip = &rk817_irq_chip; rk808->regmap_irq_chip = &rk817_irq_chip;
pre_init_reg = rk817_pre_init_reg; pre_init_reg = rk817_pre_init_reg;
nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
...@@ -715,27 +593,20 @@ static int rk808_probe(struct i2c_client *client) ...@@ -715,27 +593,20 @@ static int rk808_probe(struct i2c_client *client)
nr_cells = ARRAY_SIZE(rk817s); nr_cells = ARRAY_SIZE(rk817s);
break; break;
default: default:
dev_err(&client->dev, "Unsupported RK8XX ID %lu\n", dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant);
rk808->variant);
return -EINVAL; return -EINVAL;
} }
rk808->dev = &client->dev; dev_info(dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
i2c_set_clientdata(client, rk808);
rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg); if (!irq)
if (IS_ERR(rk808->regmap)) return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n");
return dev_err_probe(&client->dev, PTR_ERR(rk808->regmap),
"regmap initialization failed\n");
if (!client->irq) ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq,
return dev_err_probe(&client->dev, -EINVAL, "No interrupt support, no core IRQ\n");
ret = devm_regmap_add_irq_chip(&client->dev, rk808->regmap, client->irq,
IRQF_ONESHOT, -1, IRQF_ONESHOT, -1,
rk808->regmap_irq_chip, &rk808->irq_data); rk808->regmap_irq_chip, &rk808->irq_data);
if (ret) if (ret)
return dev_err_probe(&client->dev, ret, "Failed to add irq_chip\n"); return dev_err_probe(dev, ret, "Failed to add irq_chip\n");
for (i = 0; i < nr_pre_init_regs; i++) { for (i = 0; i < nr_pre_init_regs; i++) {
ret = regmap_update_bits(rk808->regmap, ret = regmap_update_bits(rk808->regmap,
...@@ -743,45 +614,46 @@ static int rk808_probe(struct i2c_client *client) ...@@ -743,45 +614,46 @@ static int rk808_probe(struct i2c_client *client)
pre_init_reg[i].mask, pre_init_reg[i].mask,
pre_init_reg[i].value); pre_init_reg[i].value);
if (ret) if (ret)
return dev_err_probe(&client->dev, ret, "0x%x write err\n", return dev_err_probe(dev, ret, "0x%x write err\n",
pre_init_reg[i].addr); pre_init_reg[i].addr);
} }
ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
cells, nr_cells, NULL, 0, cells, nr_cells, NULL, 0,
regmap_irq_get_domain(rk808->irq_data)); regmap_irq_get_domain(rk808->irq_data));
if (ret) if (ret)
return dev_err_probe(&client->dev, ret, "failed to add MFD devices\n"); return dev_err_probe(dev, ret, "failed to add MFD devices\n");
if (of_property_read_bool(np, "rockchip,system-power-controller")) { if (device_property_read_bool(dev, "rockchip,system-power-controller")) {
ret = devm_register_sys_off_handler(&client->dev, ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH,
&rk808_power_off, rk808); &rk808_power_off, rk808);
if (ret) if (ret)
return dev_err_probe(&client->dev, ret, return dev_err_probe(dev, ret,
"failed to register poweroff handler\n"); "failed to register poweroff handler\n");
switch (rk808->variant) { switch (rk808->variant) {
case RK809_ID: case RK809_ID:
case RK817_ID: case RK817_ID:
ret = devm_register_sys_off_handler(&client->dev, ret = devm_register_sys_off_handler(dev,
SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH,
&rk808_restart, rk808); &rk808_restart, rk808);
if (ret) if (ret)
dev_warn(&client->dev, "failed to register rst handler, %d\n", ret); dev_warn(dev, "failed to register rst handler, %d\n", ret);
break; break;
default: default:
dev_dbg(&client->dev, "pmic controlled board reset not supported\n"); dev_dbg(dev, "pmic controlled board reset not supported\n");
break; break;
} }
} }
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rk8xx_probe);
static int __maybe_unused rk8xx_suspend(struct device *dev) int rk8xx_suspend(struct device *dev)
{ {
struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); struct rk808 *rk808 = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
switch (rk808->variant) { switch (rk808->variant) {
...@@ -804,10 +676,11 @@ static int __maybe_unused rk8xx_suspend(struct device *dev) ...@@ -804,10 +676,11 @@ static int __maybe_unused rk8xx_suspend(struct device *dev)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(rk8xx_suspend);
static int __maybe_unused rk8xx_resume(struct device *dev) int rk8xx_resume(struct device *dev)
{ {
struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); struct rk808 *rk808 = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
switch (rk808->variant) { switch (rk808->variant) {
...@@ -824,22 +697,10 @@ static int __maybe_unused rk8xx_resume(struct device *dev) ...@@ -824,22 +697,10 @@ static int __maybe_unused rk8xx_resume(struct device *dev)
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); EXPORT_SYMBOL_GPL(rk8xx_resume);
static struct i2c_driver rk808_i2c_driver = {
.driver = {
.name = "rk808",
.of_match_table = rk808_of_match,
.pm = &rk8xx_pm_ops,
},
.probe_new = rk808_probe,
.shutdown = rk8xx_shutdown,
};
module_i2c_driver(rk808_i2c_driver);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
MODULE_DESCRIPTION("RK808/RK818 PMIC driver"); MODULE_DESCRIPTION("RK8xx PMIC core");
// SPDX-License-Identifier: GPL-2.0-only
/*
* Rockchip RK808/RK818 Core (I2C) driver
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
* Author: Wadim Egorov <w.egorov@phytec.de>
*/
#include <linux/i2c.h>
#include <linux/mfd/rk808.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
{
/*
* Notes:
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
* we don't use that feature. It's better to cache.
* - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
* bits are cleared in case when we shutoff anyway, but better safe.
*/
switch (reg) {
case RK808_SECONDS_REG ... RK808_WEEKS_REG:
case RK808_RTC_STATUS_REG:
case RK808_VB_MON_REG:
case RK808_THERMAL_REG:
case RK808_DCDC_UV_STS_REG:
case RK808_LDO_UV_STS_REG:
case RK808_DCDC_PG_REG:
case RK808_LDO_PG_REG:
case RK808_DEVCTRL_REG:
case RK808_INT_STS_REG1:
case RK808_INT_STS_REG2:
return true;
}
return false;
}
static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
{
/*
* Notes:
* - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
* we don't use that feature. It's better to cache.
*/
switch (reg) {
case RK817_SECONDS_REG ... RK817_WEEKS_REG:
case RK817_RTC_STATUS_REG:
case RK817_CODEC_DTOP_LPT_SRST:
case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
case RK817_PMIC_CHRG_STS:
case RK817_PMIC_CHRG_OUT:
case RK817_PMIC_CHRG_IN:
case RK817_INT_STS_REG0:
case RK817_INT_STS_REG1:
case RK817_INT_STS_REG2:
case RK817_SYS_STS:
return true;
}
return false;
}
static const struct regmap_config rk818_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK818_USB_CTRL_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk805_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK805_OFF_SOURCE_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk808_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK808_IO_POL_REG,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = rk808_is_volatile_reg,
};
static const struct regmap_config rk817_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RK817_GPIO_INT_CFG,
.cache_type = REGCACHE_NONE,
.volatile_reg = rk817_is_volatile_reg,
};
static int rk8xx_i2c_get_variant(struct i2c_client *client)
{
u8 pmic_id_msb, pmic_id_lsb;
int msb, lsb;
if (of_device_is_compatible(client->dev.of_node, "rockchip,rk817") ||
of_device_is_compatible(client->dev.of_node, "rockchip,rk809")) {
pmic_id_msb = RK817_ID_MSB;
pmic_id_lsb = RK817_ID_LSB;
} else {
pmic_id_msb = RK808_ID_MSB;
pmic_id_lsb = RK808_ID_LSB;
}
/* Read chip variant */
msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
if (msb < 0)
return dev_err_probe(&client->dev, msb, "failed to read the chip id MSB\n");
lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
if (lsb < 0)
return dev_err_probe(&client->dev, lsb, "failed to read the chip id LSB\n");
return ((msb << 8) | lsb) & RK8XX_ID_MSK;
}
static int rk8xx_i2c_probe(struct i2c_client *client)
{
const struct regmap_config *regmap_cfg;
struct regmap *regmap;
int variant;
variant = rk8xx_i2c_get_variant(client);
if (variant < 0)
return variant;
switch (variant) {
case RK805_ID:
regmap_cfg = &rk805_regmap_config;
break;
case RK808_ID:
regmap_cfg = &rk808_regmap_config;
break;
case RK818_ID:
regmap_cfg = &rk818_regmap_config;
break;
case RK809_ID:
case RK817_ID:
regmap_cfg = &rk817_regmap_config;
break;
default:
return dev_err_probe(&client->dev, -EINVAL, "Unsupported RK8XX ID %x\n", variant);
}
regmap = devm_regmap_init_i2c(client, regmap_cfg);
if (IS_ERR(regmap))
return dev_err_probe(&client->dev, PTR_ERR(regmap),
"regmap initialization failed\n");
return rk8xx_probe(&client->dev, variant, client->irq, regmap);
}
static void rk8xx_i2c_shutdown(struct i2c_client *client)
{
rk8xx_shutdown(&client->dev);
}
static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
static const struct of_device_id rk8xx_i2c_of_match[] = {
{ .compatible = "rockchip,rk805" },
{ .compatible = "rockchip,rk808" },
{ .compatible = "rockchip,rk809" },
{ .compatible = "rockchip,rk817" },
{ .compatible = "rockchip,rk818" },
{ },
};
MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
static struct i2c_driver rk8xx_i2c_driver = {
.driver = {
.name = "rk8xx-i2c",
.of_match_table = rk8xx_i2c_of_match,
.pm = &rk8xx_i2c_pm_ops,
},
.probe_new = rk8xx_i2c_probe,
.shutdown = rk8xx_i2c_shutdown,
};
module_i2c_driver(rk8xx_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
MODULE_DESCRIPTION("RK8xx I2C PMIC driver");
...@@ -407,7 +407,7 @@ config PINCTRL_PISTACHIO ...@@ -407,7 +407,7 @@ config PINCTRL_PISTACHIO
config PINCTRL_RK805 config PINCTRL_RK805
tristate "Pinctrl and GPIO driver for RK805 PMIC" tristate "Pinctrl and GPIO driver for RK805 PMIC"
depends on MFD_RK808 depends on MFD_RK8XX
select GPIOLIB select GPIOLIB
select PINMUX select PINMUX
select GENERIC_PINCONF select GENERIC_PINCONF
......
...@@ -706,7 +706,7 @@ config CHARGER_BQ256XX ...@@ -706,7 +706,7 @@ config CHARGER_BQ256XX
config CHARGER_RK817 config CHARGER_RK817
tristate "Rockchip RK817 PMIC Battery Charger" tristate "Rockchip RK817 PMIC Battery Charger"
depends on MFD_RK808 depends on MFD_RK8XX
help help
Say Y to include support for Rockchip RK817 Battery Charger. Say Y to include support for Rockchip RK817 Battery Charger.
......
...@@ -1056,7 +1056,7 @@ config REGULATOR_RC5T583 ...@@ -1056,7 +1056,7 @@ config REGULATOR_RC5T583
config REGULATOR_RK808 config REGULATOR_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators" tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators"
depends on MFD_RK808 depends on MFD_RK8XX
help help
Select this option to enable the power regulator of ROCKCHIP Select this option to enable the power regulator of ROCKCHIP
PMIC RK805,RK809&RK817,RK808 and RK818. PMIC RK805,RK809&RK817,RK808 and RK818.
......
...@@ -395,7 +395,7 @@ config RTC_DRV_NCT3018Y ...@@ -395,7 +395,7 @@ config RTC_DRV_NCT3018Y
config RTC_DRV_RK808 config RTC_DRV_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
depends on MFD_RK808 depends on MFD_RK8XX
help help
If you say yes here you will get support for the If you say yes here you will get support for the
RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC. RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC.
......
...@@ -794,4 +794,10 @@ struct rk808 { ...@@ -794,4 +794,10 @@ struct rk808 {
const struct regmap_config *regmap_cfg; const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip; const struct regmap_irq_chip *regmap_irq_chip;
}; };
void rk8xx_shutdown(struct device *dev);
int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap);
int rk8xx_suspend(struct device *dev);
int rk8xx_resume(struct device *dev);
#endif /* __LINUX_REGULATOR_RK808_H */ #endif /* __LINUX_REGULATOR_RK808_H */
...@@ -1313,7 +1313,7 @@ config SND_SOC_RK3328 ...@@ -1313,7 +1313,7 @@ config SND_SOC_RK3328
config SND_SOC_RK817 config SND_SOC_RK817
tristate "Rockchip RK817 audio CODEC" tristate "Rockchip RK817 audio CODEC"
depends on MFD_RK808 || COMPILE_TEST depends on MFD_RK8XX || COMPILE_TEST
config SND_SOC_RL6231 config SND_SOC_RL6231
tristate tristate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment