GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / mfd / rk8xx-i2c.c
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
19 struct rk8xx_i2c_platform_data {
20         const struct regmap_config *regmap_cfg;
21         int variant;
22 };
23
24 static 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
52 static 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
79 static 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
87 static 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
95 static 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
103 static 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
111 static const struct rk8xx_i2c_platform_data rk805_data = {
112         .regmap_cfg = &rk805_regmap_config,
113         .variant = RK805_ID,
114 };
115
116 static const struct rk8xx_i2c_platform_data rk808_data = {
117         .regmap_cfg = &rk808_regmap_config,
118         .variant = RK808_ID,
119 };
120
121 static const struct rk8xx_i2c_platform_data rk809_data = {
122         .regmap_cfg = &rk817_regmap_config,
123         .variant = RK809_ID,
124 };
125
126 static const struct rk8xx_i2c_platform_data rk817_data = {
127         .regmap_cfg = &rk817_regmap_config,
128         .variant = RK817_ID,
129 };
130
131 static const struct rk8xx_i2c_platform_data rk818_data = {
132         .regmap_cfg = &rk818_regmap_config,
133         .variant = RK818_ID,
134 };
135
136 static 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
153 static void rk8xx_i2c_shutdown(struct i2c_client *client)
154 {
155         rk8xx_shutdown(&client->dev);
156 }
157
158 static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
159
160 static 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 };
168 MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match);
169
170 static 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 };
179 module_i2c_driver(rk8xx_i2c_driver);
180
181 MODULE_LICENSE("GPL");
182 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
183 MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
184 MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
185 MODULE_DESCRIPTION("RK8xx I2C PMIC driver");