xref: /openbmc/linux/drivers/mfd/rk8xx-i2c.c (revision 9816d859)
1c20e8c5bSSebastian Reichel // SPDX-License-Identifier: GPL-2.0-only
2c20e8c5bSSebastian Reichel /*
3c20e8c5bSSebastian Reichel  * Rockchip RK808/RK818 Core (I2C) driver
4c20e8c5bSSebastian Reichel  *
5c20e8c5bSSebastian Reichel  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
6c20e8c5bSSebastian Reichel  * Copyright (C) 2016 PHYTEC Messtechnik GmbH
7c20e8c5bSSebastian Reichel  *
8c20e8c5bSSebastian Reichel  * Author: Chris Zhong <zyw@rock-chips.com>
9c20e8c5bSSebastian Reichel  * Author: Zhang Qing <zhangqing@rock-chips.com>
10c20e8c5bSSebastian Reichel  * Author: Wadim Egorov <w.egorov@phytec.de>
11c20e8c5bSSebastian Reichel  */
12c20e8c5bSSebastian Reichel 
13c20e8c5bSSebastian Reichel #include <linux/i2c.h>
14c20e8c5bSSebastian Reichel #include <linux/mfd/rk808.h>
15c20e8c5bSSebastian Reichel #include <linux/module.h>
16c20e8c5bSSebastian Reichel #include <linux/of.h>
17c20e8c5bSSebastian Reichel #include <linux/regmap.h>
18c20e8c5bSSebastian Reichel 
1974413bd6SSebastian Reichel struct rk8xx_i2c_platform_data {
2074413bd6SSebastian Reichel 	const struct regmap_config *regmap_cfg;
2174413bd6SSebastian Reichel 	int variant;
2274413bd6SSebastian Reichel };
2374413bd6SSebastian Reichel 
rk808_is_volatile_reg(struct device * dev,unsigned int reg)24c20e8c5bSSebastian Reichel static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
25c20e8c5bSSebastian Reichel {
26c20e8c5bSSebastian Reichel 	/*
27c20e8c5bSSebastian Reichel 	 * Notes:
28c20e8c5bSSebastian Reichel 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
29c20e8c5bSSebastian Reichel 	 *   we don't use that feature.  It's better to cache.
30c20e8c5bSSebastian Reichel 	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
31c20e8c5bSSebastian Reichel 	 *   bits are cleared in case when we shutoff anyway, but better safe.
32c20e8c5bSSebastian Reichel 	 */
33c20e8c5bSSebastian Reichel 
34c20e8c5bSSebastian Reichel 	switch (reg) {
35c20e8c5bSSebastian Reichel 	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
36c20e8c5bSSebastian Reichel 	case RK808_RTC_STATUS_REG:
37c20e8c5bSSebastian Reichel 	case RK808_VB_MON_REG:
38c20e8c5bSSebastian Reichel 	case RK808_THERMAL_REG:
39c20e8c5bSSebastian Reichel 	case RK808_DCDC_UV_STS_REG:
40c20e8c5bSSebastian Reichel 	case RK808_LDO_UV_STS_REG:
41c20e8c5bSSebastian Reichel 	case RK808_DCDC_PG_REG:
42c20e8c5bSSebastian Reichel 	case RK808_LDO_PG_REG:
43c20e8c5bSSebastian Reichel 	case RK808_DEVCTRL_REG:
44c20e8c5bSSebastian Reichel 	case RK808_INT_STS_REG1:
45c20e8c5bSSebastian Reichel 	case RK808_INT_STS_REG2:
46c20e8c5bSSebastian Reichel 		return true;
47c20e8c5bSSebastian Reichel 	}
48c20e8c5bSSebastian Reichel 
49c20e8c5bSSebastian Reichel 	return false;
50c20e8c5bSSebastian Reichel }
51c20e8c5bSSebastian Reichel 
rk817_is_volatile_reg(struct device * dev,unsigned int reg)52c20e8c5bSSebastian Reichel static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
53c20e8c5bSSebastian Reichel {
54c20e8c5bSSebastian Reichel 	/*
55c20e8c5bSSebastian Reichel 	 * Notes:
56c20e8c5bSSebastian Reichel 	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
57c20e8c5bSSebastian Reichel 	 *   we don't use that feature.  It's better to cache.
58c20e8c5bSSebastian Reichel 	 */
59c20e8c5bSSebastian Reichel 
60c20e8c5bSSebastian Reichel 	switch (reg) {
61c20e8c5bSSebastian Reichel 	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
62c20e8c5bSSebastian Reichel 	case RK817_RTC_STATUS_REG:
63c20e8c5bSSebastian Reichel 	case RK817_CODEC_DTOP_LPT_SRST:
64c20e8c5bSSebastian Reichel 	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
65c20e8c5bSSebastian Reichel 	case RK817_PMIC_CHRG_STS:
66c20e8c5bSSebastian Reichel 	case RK817_PMIC_CHRG_OUT:
67c20e8c5bSSebastian Reichel 	case RK817_PMIC_CHRG_IN:
68c20e8c5bSSebastian Reichel 	case RK817_INT_STS_REG0:
69c20e8c5bSSebastian Reichel 	case RK817_INT_STS_REG1:
70c20e8c5bSSebastian Reichel 	case RK817_INT_STS_REG2:
71c20e8c5bSSebastian Reichel 	case RK817_SYS_STS:
72c20e8c5bSSebastian Reichel 		return true;
73c20e8c5bSSebastian Reichel 	}
74c20e8c5bSSebastian Reichel 
75c20e8c5bSSebastian Reichel 	return false;
76c20e8c5bSSebastian Reichel }
77c20e8c5bSSebastian Reichel 
78c20e8c5bSSebastian Reichel 
79c20e8c5bSSebastian Reichel static const struct regmap_config rk818_regmap_config = {
80c20e8c5bSSebastian Reichel 	.reg_bits = 8,
81c20e8c5bSSebastian Reichel 	.val_bits = 8,
82c20e8c5bSSebastian Reichel 	.max_register = RK818_USB_CTRL_REG,
83c20e8c5bSSebastian Reichel 	.cache_type = REGCACHE_RBTREE,
84c20e8c5bSSebastian Reichel 	.volatile_reg = rk808_is_volatile_reg,
85c20e8c5bSSebastian Reichel };
86c20e8c5bSSebastian Reichel 
87c20e8c5bSSebastian Reichel static const struct regmap_config rk805_regmap_config = {
88c20e8c5bSSebastian Reichel 	.reg_bits = 8,
89c20e8c5bSSebastian Reichel 	.val_bits = 8,
90c20e8c5bSSebastian Reichel 	.max_register = RK805_OFF_SOURCE_REG,
91c20e8c5bSSebastian Reichel 	.cache_type = REGCACHE_RBTREE,
92c20e8c5bSSebastian Reichel 	.volatile_reg = rk808_is_volatile_reg,
93c20e8c5bSSebastian Reichel };
94c20e8c5bSSebastian Reichel 
95c20e8c5bSSebastian Reichel static const struct regmap_config rk808_regmap_config = {
96c20e8c5bSSebastian Reichel 	.reg_bits = 8,
97c20e8c5bSSebastian Reichel 	.val_bits = 8,
98c20e8c5bSSebastian Reichel 	.max_register = RK808_IO_POL_REG,
99c20e8c5bSSebastian Reichel 	.cache_type = REGCACHE_RBTREE,
100c20e8c5bSSebastian Reichel 	.volatile_reg = rk808_is_volatile_reg,
101c20e8c5bSSebastian Reichel };
102c20e8c5bSSebastian Reichel 
103c20e8c5bSSebastian Reichel static const struct regmap_config rk817_regmap_config = {
104c20e8c5bSSebastian Reichel 	.reg_bits = 8,
105c20e8c5bSSebastian Reichel 	.val_bits = 8,
106c20e8c5bSSebastian Reichel 	.max_register = RK817_GPIO_INT_CFG,
107c20e8c5bSSebastian Reichel 	.cache_type = REGCACHE_NONE,
108c20e8c5bSSebastian Reichel 	.volatile_reg = rk817_is_volatile_reg,
109c20e8c5bSSebastian Reichel };
110c20e8c5bSSebastian Reichel 
11174413bd6SSebastian Reichel static const struct rk8xx_i2c_platform_data rk805_data = {
11274413bd6SSebastian Reichel 	.regmap_cfg = &rk805_regmap_config,
11374413bd6SSebastian Reichel 	.variant = RK805_ID,
11474413bd6SSebastian Reichel };
115c20e8c5bSSebastian Reichel 
11674413bd6SSebastian Reichel static const struct rk8xx_i2c_platform_data rk808_data = {
11774413bd6SSebastian Reichel 	.regmap_cfg = &rk808_regmap_config,
11874413bd6SSebastian Reichel 	.variant = RK808_ID,
11974413bd6SSebastian Reichel };
120c20e8c5bSSebastian Reichel 
12174413bd6SSebastian Reichel static const struct rk8xx_i2c_platform_data rk809_data = {
12274413bd6SSebastian Reichel 	.regmap_cfg = &rk817_regmap_config,
12374413bd6SSebastian Reichel 	.variant = RK809_ID,
12474413bd6SSebastian Reichel };
125c20e8c5bSSebastian Reichel 
12674413bd6SSebastian Reichel static const struct rk8xx_i2c_platform_data rk817_data = {
12774413bd6SSebastian Reichel 	.regmap_cfg = &rk817_regmap_config,
12874413bd6SSebastian Reichel 	.variant = RK817_ID,
12974413bd6SSebastian Reichel };
130c20e8c5bSSebastian Reichel 
13174413bd6SSebastian Reichel static const struct rk8xx_i2c_platform_data rk818_data = {
13274413bd6SSebastian Reichel 	.regmap_cfg = &rk818_regmap_config,
13374413bd6SSebastian Reichel 	.variant = RK818_ID,
13474413bd6SSebastian Reichel };
135c20e8c5bSSebastian Reichel 
rk8xx_i2c_probe(struct i2c_client * client)136c20e8c5bSSebastian Reichel static int rk8xx_i2c_probe(struct i2c_client *client)
137c20e8c5bSSebastian Reichel {
13874413bd6SSebastian Reichel 	const struct rk8xx_i2c_platform_data *data;
139c20e8c5bSSebastian Reichel 	struct regmap *regmap;
140c20e8c5bSSebastian Reichel 
14174413bd6SSebastian Reichel 	data = device_get_match_data(&client->dev);
14274413bd6SSebastian Reichel 	if (!data)
14374413bd6SSebastian Reichel 		return -ENODEV;
144c20e8c5bSSebastian Reichel 
14574413bd6SSebastian Reichel 	regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
146c20e8c5bSSebastian Reichel 	if (IS_ERR(regmap))
147c20e8c5bSSebastian Reichel 		return dev_err_probe(&client->dev, PTR_ERR(regmap),
148c20e8c5bSSebastian Reichel 				     "regmap initialization failed\n");
149c20e8c5bSSebastian Reichel 
15074413bd6SSebastian Reichel 	return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
151c20e8c5bSSebastian Reichel }
152c20e8c5bSSebastian Reichel 
rk8xx_i2c_shutdown(struct i2c_client * client)153c20e8c5bSSebastian Reichel static void rk8xx_i2c_shutdown(struct i2c_client *client)
154c20e8c5bSSebastian Reichel {
155c20e8c5bSSebastian Reichel 	rk8xx_shutdown(&client->dev);
156c20e8c5bSSebastian Reichel }
157c20e8c5bSSebastian Reichel 
158c20e8c5bSSebastian Reichel static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
159c20e8c5bSSebastian Reichel 
160c20e8c5bSSebastian Reichel static const struct of_device_id rk8xx_i2c_of_match[] = {
16174413bd6SSebastian Reichel 	{ .compatible = "rockchip,rk805", .data = &rk805_data },
16274413bd6SSebastian Reichel 	{ .compatible = "rockchip,rk808", .data = &rk808_data },
16374413bd6SSebastian Reichel 	{ .compatible = "rockchip,rk809", .data = &rk809_data },
16474413bd6SSebastian Reichel 	{ .compatible = "rockchip,rk817", .data = &rk817_data },
16574413bd6SSebastian Reichel 	{ .compatible = "rockchip,rk818", .data = &rk818_data },
166c20e8c5bSSebastian Reichel 	{ },
167c20e8c5bSSebastian Reichel };
168c20e8c5bSSebastian Reichel MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
169c20e8c5bSSebastian Reichel 
170c20e8c5bSSebastian Reichel static struct i2c_driver rk8xx_i2c_driver = {
171c20e8c5bSSebastian Reichel 	.driver = {
172c20e8c5bSSebastian Reichel 		.name = "rk8xx-i2c",
173c20e8c5bSSebastian Reichel 		.of_match_table = rk8xx_i2c_of_match,
174c20e8c5bSSebastian Reichel 		.pm = &rk8xx_i2c_pm_ops,
175c20e8c5bSSebastian Reichel 	},
176*9816d859SUwe Kleine-König 	.probe = rk8xx_i2c_probe,
177c20e8c5bSSebastian Reichel 	.shutdown  = rk8xx_i2c_shutdown,
178c20e8c5bSSebastian Reichel };
179c20e8c5bSSebastian Reichel module_i2c_driver(rk8xx_i2c_driver);
180c20e8c5bSSebastian Reichel 
181c20e8c5bSSebastian Reichel MODULE_LICENSE("GPL");
182c20e8c5bSSebastian Reichel MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
183c20e8c5bSSebastian Reichel MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
184c20e8c5bSSebastian Reichel MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
185c20e8c5bSSebastian Reichel MODULE_DESCRIPTION("RK8xx I2C PMIC driver");
186