Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Rockchip RK808/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 rk808_is_volatile_reg(struct device *dev, unsigned int reg)
 25{
 26	/*
 27	 * Notes:
 28	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
 29	 *   we don't use that feature.  It's better to cache.
 30	 * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since
 31	 *   bits are cleared in case when we shutoff anyway, but better safe.
 32	 */
 33
 34	switch (reg) {
 35	case RK808_SECONDS_REG ... RK808_WEEKS_REG:
 36	case RK808_RTC_STATUS_REG:
 37	case RK808_VB_MON_REG:
 38	case RK808_THERMAL_REG:
 39	case RK808_DCDC_UV_STS_REG:
 40	case RK808_LDO_UV_STS_REG:
 41	case RK808_DCDC_PG_REG:
 42	case RK808_LDO_PG_REG:
 43	case RK808_DEVCTRL_REG:
 44	case RK808_INT_STS_REG1:
 45	case RK808_INT_STS_REG2:
 46		return true;
 47	}
 48
 49	return false;
 50}
 51
 52static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
 53{
 54	/*
 55	 * Notes:
 56	 * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but
 57	 *   we don't use that feature.  It's better to cache.
 58	 */
 59
 60	switch (reg) {
 61	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
 62	case RK817_RTC_STATUS_REG:
 63	case RK817_CODEC_DTOP_LPT_SRST:
 64	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
 65	case RK817_PMIC_CHRG_STS:
 66	case RK817_PMIC_CHRG_OUT:
 67	case RK817_PMIC_CHRG_IN:
 68	case RK817_INT_STS_REG0:
 69	case RK817_INT_STS_REG1:
 70	case RK817_INT_STS_REG2:
 71	case RK817_SYS_STS:
 72		return true;
 73	}
 74
 75	return false;
 76}
 77
 78
 79static const struct regmap_config rk818_regmap_config = {
 80	.reg_bits = 8,
 81	.val_bits = 8,
 82	.max_register = RK818_USB_CTRL_REG,
 83	.cache_type = REGCACHE_MAPLE,
 84	.volatile_reg = rk808_is_volatile_reg,
 85};
 86
 87static const struct regmap_config rk805_regmap_config = {
 88	.reg_bits = 8,
 89	.val_bits = 8,
 90	.max_register = RK805_OFF_SOURCE_REG,
 91	.cache_type = REGCACHE_MAPLE,
 92	.volatile_reg = rk808_is_volatile_reg,
 93};
 94
 95static const struct regmap_config rk808_regmap_config = {
 96	.reg_bits = 8,
 97	.val_bits = 8,
 98	.max_register = RK808_IO_POL_REG,
 99	.cache_type = REGCACHE_MAPLE,
100	.volatile_reg = rk808_is_volatile_reg,
101};
102
103static const struct regmap_config rk817_regmap_config = {
104	.reg_bits = 8,
105	.val_bits = 8,
106	.max_register = RK817_GPIO_INT_CFG,
107	.cache_type = REGCACHE_NONE,
108	.volatile_reg = rk817_is_volatile_reg,
109};
110
111static const struct rk8xx_i2c_platform_data rk805_data = {
112	.regmap_cfg = &rk805_regmap_config,
113	.variant = RK805_ID,
114};
115
116static const struct rk8xx_i2c_platform_data rk808_data = {
117	.regmap_cfg = &rk808_regmap_config,
118	.variant = RK808_ID,
119};
120
121static const struct rk8xx_i2c_platform_data rk809_data = {
122	.regmap_cfg = &rk817_regmap_config,
123	.variant = RK809_ID,
124};
125
126static const struct rk8xx_i2c_platform_data rk817_data = {
127	.regmap_cfg = &rk817_regmap_config,
128	.variant = RK817_ID,
129};
130
131static const struct rk8xx_i2c_platform_data rk818_data = {
132	.regmap_cfg = &rk818_regmap_config,
133	.variant = RK818_ID,
134};
135
136static int rk8xx_i2c_probe(struct i2c_client *client)
137{
138	const struct rk8xx_i2c_platform_data *data;
139	struct regmap *regmap;
140
141	data = device_get_match_data(&client->dev);
142	if (!data)
143		return -ENODEV;
144
145	regmap = devm_regmap_init_i2c(client, data->regmap_cfg);
146	if (IS_ERR(regmap))
147		return dev_err_probe(&client->dev, PTR_ERR(regmap),
148				     "regmap initialization failed\n");
149
150	return rk8xx_probe(&client->dev, data->variant, client->irq, regmap);
151}
152
153static void rk8xx_i2c_shutdown(struct i2c_client *client)
154{
155	rk8xx_shutdown(&client->dev);
156}
157
158static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
159
160static const struct of_device_id rk8xx_i2c_of_match[] = {
161	{ .compatible = "rockchip,rk805", .data = &rk805_data },
162	{ .compatible = "rockchip,rk808", .data = &rk808_data },
163	{ .compatible = "rockchip,rk809", .data = &rk809_data },
164	{ .compatible = "rockchip,rk817", .data = &rk817_data },
165	{ .compatible = "rockchip,rk818", .data = &rk818_data },
166	{ },
167};
168MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
169
170static struct i2c_driver rk8xx_i2c_driver = {
171	.driver = {
172		.name = "rk8xx-i2c",
173		.of_match_table = rk8xx_i2c_of_match,
174		.pm = &rk8xx_i2c_pm_ops,
175	},
176	.probe = rk8xx_i2c_probe,
177	.shutdown  = rk8xx_i2c_shutdown,
178};
179module_i2c_driver(rk8xx_i2c_driver);
180
181MODULE_LICENSE("GPL");
182MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
183MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
184MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
185MODULE_DESCRIPTION("RK8xx I2C PMIC driver");