Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Rockchip RK805/RK808/RK816/RK817/RK818 Core (I2C) driver
  4 *
  5 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
  6 * Copyright (C) 2016 PHYTEC Messtechnik GmbH
  7 *
  8 * Author: Chris Zhong <zyw@rock-chips.com>
  9 * Author: Zhang Qing <zhangqing@rock-chips.com>
 10 * Author: Wadim Egorov <w.egorov@phytec.de>
 11 */
 12
 13#include <linux/i2c.h>
 14#include <linux/mfd/rk808.h>
 15#include <linux/module.h>
 16#include <linux/of.h>
 17#include <linux/regmap.h>
 18
 19struct rk8xx_i2c_platform_data {
 20	const struct regmap_config *regmap_cfg;
 21	int variant;
 22};
 23
 24static bool rk806_is_volatile_reg(struct device *dev, unsigned int reg)
 25{
 26	switch (reg) {
 27	case RK806_POWER_EN0 ... RK806_POWER_EN5:
 28	case RK806_DVS_START_CTRL ... RK806_INT_MSK1:
 29		return true;
 30	}
 31
 32	return false;
 33}
 34
 35static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg)
 36{
 37	/*
 38	 * Notes:
 39	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
 40	 *   we don't use that feature.  It's better to cache.
 41	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
 42	 *   bits are cleared in case when we shutoff anyway, but better safe.
 43	 */
 44
 45	switch (reg) {
 46	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
 47	case RK808_RTC_STATUS_REG:
 48	case RK808_VB_MON_REG:
 49	case RK808_THERMAL_REG:
 50	case RK808_DCDC_UV_STS_REG:
 51	case RK808_LDO_UV_STS_REG:
 52	case RK808_DCDC_PG_REG:
 53	case RK808_LDO_PG_REG:
 54	case RK808_DEVCTRL_REG:
 55	case RK808_INT_STS_REG1:
 56	case RK808_INT_STS_REG2:
 57		return true;
 58	}
 59
 60	return false;
 61}
 62
 63static bool rk816_is_volatile_reg(struct device *dev, unsigned int reg)
 64{
 65	/*
 66	 * Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
 67	 * we don't use that feature.  It's better to cache.
 68	 */
 69
 70	switch (reg) {
 71	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
 72	case RK808_RTC_STATUS_REG:
 73	case RK808_VB_MON_REG:
 74	case RK808_THERMAL_REG:
 75	case RK816_DCDC_EN_REG1:
 76	case RK816_DCDC_EN_REG2:
 77	case RK816_INT_STS_REG1:
 78	case RK816_INT_STS_REG2:
 79	case RK816_INT_STS_REG3:
 80	case RK808_DEVCTRL_REG:
 81	case RK816_SUP_STS_REG:
 82	case RK816_GGSTS_REG:
 83	case RK816_ZERO_CUR_ADC_REGH:
 84	case RK816_ZERO_CUR_ADC_REGL:
 85	case RK816_GASCNT_REG(0) ... RK816_BAT_VOL_REGL:
 86		return true;
 87	}
 88
 89	return false;
 90}
 91
 92static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
 93{
 94	/*
 95	 * Notes:
 96	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
 97	 *   we don't use that feature.  It's better to cache.
 98	 */
 99
100	switch (reg) {
101	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
102	case RK817_RTC_STATUS_REG:
103	case RK817_CODEC_DTOP_LPT_SRST:
104	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
105	case RK817_PMIC_CHRG_STS:
106	case RK817_PMIC_CHRG_OUT:
107	case RK817_PMIC_CHRG_IN:
108	case RK817_INT_STS_REG0:
109	case RK817_INT_STS_REG1:
110	case RK817_INT_STS_REG2:
111	case RK817_SYS_STS:
112		return true;
113	}
114
115	return false;
116}
117
118
119static const struct regmap_config rk818_regmap_config = {
120	.reg_bits = 8,
121	.val_bits = 8,
122	.max_register = RK818_USB_CTRL_REG,
123	.cache_type = REGCACHE_MAPLE,
124	.volatile_reg = rk808_is_volatile_reg,
125};
126
127static const struct regmap_config rk805_regmap_config = {
128	.reg_bits = 8,
129	.val_bits = 8,
130	.max_register = RK805_OFF_SOURCE_REG,
131	.cache_type = REGCACHE_MAPLE,
132	.volatile_reg = rk808_is_volatile_reg,
133};
134
135static const struct regmap_config rk806_regmap_config = {
136	.reg_bits = 8,
137	.val_bits = 8,
138	.max_register = RK806_BUCK_RSERVE_REG5,
139	.cache_type = REGCACHE_MAPLE,
140	.volatile_reg = rk806_is_volatile_reg,
141};
142
143static const struct regmap_config rk808_regmap_config = {
144	.reg_bits = 8,
145	.val_bits = 8,
146	.max_register = RK808_IO_POL_REG,
147	.cache_type = REGCACHE_MAPLE,
148	.volatile_reg = rk808_is_volatile_reg,
149};
150
151static const struct regmap_config rk816_regmap_config = {
152	.reg_bits = 8,
153	.val_bits = 8,
154	.max_register = RK816_DATA_REG(18),
155	.cache_type = REGCACHE_MAPLE,
156	.volatile_reg = rk816_is_volatile_reg,
157};
158
159static const struct regmap_config rk817_regmap_config = {
160	.reg_bits = 8,
161	.val_bits = 8,
162	.max_register = RK817_GPIO_INT_CFG,
163	.cache_type = REGCACHE_NONE,
164	.volatile_reg = rk817_is_volatile_reg,
165};
166
167static const struct rk8xx_i2c_platform_data rk805_data = {
168	.regmap_cfg = &rk805_regmap_config,
169	.variant = RK805_ID,
170};
171
172static const struct rk8xx_i2c_platform_data rk806_data = {
173	.regmap_cfg = &rk806_regmap_config,
174	.variant = RK806_ID,
175};
176
177static const struct rk8xx_i2c_platform_data rk808_data = {
178	.regmap_cfg = &rk808_regmap_config,
179	.variant = RK808_ID,
180};
181
182static const struct rk8xx_i2c_platform_data rk809_data = {
183	.regmap_cfg = &rk817_regmap_config,
184	.variant = RK809_ID,
185};
186
187static const struct rk8xx_i2c_platform_data rk816_data = {
188	.regmap_cfg = &rk816_regmap_config,
189	.variant = RK816_ID,
190};
191
192static const struct rk8xx_i2c_platform_data rk817_data = {
193	.regmap_cfg = &rk817_regmap_config,
194	.variant = RK817_ID,
195};
196
197static const struct rk8xx_i2c_platform_data rk818_data = {
198	.regmap_cfg = &rk818_regmap_config,
199	.variant = RK818_ID,
200};
201
202static int rk8xx_i2c_probe(struct i2c_client *client)
203{
204	const struct rk8xx_i2c_platform_data *data;
205	struct regmap *regmap;
206
207	data = device_get_match_data(&client->dev);
208	if (!data)
209		return -ENODEV;
210
211	regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
212	if (IS_ERR(regmap))
213		return dev_err_probe(&client->dev, PTR_ERR(regmap),
214				     "regmap initialization failed\n");
215
216	return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
217}
218
219static void rk8xx_i2c_shutdown(struct i2c_client *client)
220{
221	rk8xx_shutdown(&client->dev);
222}
223
224static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
225
226static const struct of_device_id rk8xx_i2c_of_match[] = {
227	{ .compatible = "rockchip,rk805", .data = &rk805_data },
228	{ .compatible = "rockchip,rk806", .data = &rk806_data },
229	{ .compatible = "rockchip,rk808", .data = &rk808_data },
230	{ .compatible = "rockchip,rk809", .data = &rk809_data },
231	{ .compatible = "rockchip,rk816", .data = &rk816_data },
232	{ .compatible = "rockchip,rk817", .data = &rk817_data },
233	{ .compatible = "rockchip,rk818", .data = &rk818_data },
234	{ },
235};
236MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
237
238static struct i2c_driver rk8xx_i2c_driver = {
239	.driver = {
240		.name = "rk8xx-i2c",
241		.of_match_table = rk8xx_i2c_of_match,
242		.pm = &rk8xx_i2c_pm_ops,
243	},
244	.probe = rk8xx_i2c_probe,
245	.shutdown  = rk8xx_i2c_shutdown,
246};
247module_i2c_driver(rk8xx_i2c_driver);
248
249MODULE_LICENSE("GPL");
250MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
251MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
252MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
253MODULE_DESCRIPTION("RK8xx I2C PMIC driver");