1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Core driver access RC5T583 power management chip.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
6*4882a593Smuzhiyun * Author: Laxman dewangan <ldewangan@nvidia.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Based on code
9*4882a593Smuzhiyun * Copyright (C) 2011 RICOH COMPANY,LTD
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/irq.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/init.h>
15*4882a593Smuzhiyun #include <linux/err.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/i2c.h>
18*4882a593Smuzhiyun #include <linux/mfd/core.h>
19*4882a593Smuzhiyun #include <linux/mfd/rc5t583.h>
20*4882a593Smuzhiyun #include <linux/regmap.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define RICOH_ONOFFSEL_REG 0x10
23*4882a593Smuzhiyun #define RICOH_SWCTL_REG 0x5E
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun struct deepsleep_control_data {
26*4882a593Smuzhiyun u8 reg_add;
27*4882a593Smuzhiyun u8 ds_pos_bit;
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define DEEPSLEEP_INIT(_id, _reg, _pos) \
31*4882a593Smuzhiyun { \
32*4882a593Smuzhiyun .reg_add = RC5T583_##_reg, \
33*4882a593Smuzhiyun .ds_pos_bit = _pos, \
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun static struct deepsleep_control_data deepsleep_data[] = {
37*4882a593Smuzhiyun DEEPSLEEP_INIT(DC0, SLPSEQ1, 0),
38*4882a593Smuzhiyun DEEPSLEEP_INIT(DC1, SLPSEQ1, 4),
39*4882a593Smuzhiyun DEEPSLEEP_INIT(DC2, SLPSEQ2, 0),
40*4882a593Smuzhiyun DEEPSLEEP_INIT(DC3, SLPSEQ2, 4),
41*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0),
42*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4),
43*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0),
44*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4),
45*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0),
46*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4),
47*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0),
48*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4),
49*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0),
50*4882a593Smuzhiyun DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4),
51*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0),
52*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4),
53*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0),
54*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4),
55*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0),
56*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4),
57*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0),
58*4882a593Smuzhiyun DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4),
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define EXT_PWR_REQ \
62*4882a593Smuzhiyun (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun static const struct mfd_cell rc5t583_subdevs[] = {
65*4882a593Smuzhiyun {.name = "rc5t583-gpio",},
66*4882a593Smuzhiyun {.name = "rc5t583-regulator",},
67*4882a593Smuzhiyun {.name = "rc5t583-rtc", },
68*4882a593Smuzhiyun {.name = "rc5t583-key", }
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
__rc5t583_set_ext_pwrreq1_control(struct device * dev,int id,int ext_pwr,int slots)71*4882a593Smuzhiyun static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
72*4882a593Smuzhiyun int id, int ext_pwr, int slots)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun int ret;
75*4882a593Smuzhiyun uint8_t sleepseq_val = 0;
76*4882a593Smuzhiyun unsigned int en_bit;
77*4882a593Smuzhiyun unsigned int slot_bit;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (id == RC5T583_DS_DC0) {
80*4882a593Smuzhiyun dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id);
81*4882a593Smuzhiyun return -EINVAL;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun en_bit = deepsleep_data[id].ds_pos_bit;
85*4882a593Smuzhiyun slot_bit = en_bit + 1;
86*4882a593Smuzhiyun ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val);
87*4882a593Smuzhiyun if (ret < 0) {
88*4882a593Smuzhiyun dev_err(dev, "Error in reading reg 0x%x\n",
89*4882a593Smuzhiyun deepsleep_data[id].reg_add);
90*4882a593Smuzhiyun return ret;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun sleepseq_val &= ~(0xF << en_bit);
94*4882a593Smuzhiyun sleepseq_val |= BIT(en_bit);
95*4882a593Smuzhiyun sleepseq_val |= ((slots & 0x7) << slot_bit);
96*4882a593Smuzhiyun ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1));
97*4882a593Smuzhiyun if (ret < 0) {
98*4882a593Smuzhiyun dev_err(dev, "Error in updating the 0x%02x register\n",
99*4882a593Smuzhiyun RICOH_ONOFFSEL_REG);
100*4882a593Smuzhiyun return ret;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val);
104*4882a593Smuzhiyun if (ret < 0) {
105*4882a593Smuzhiyun dev_err(dev, "Error in writing reg 0x%x\n",
106*4882a593Smuzhiyun deepsleep_data[id].reg_add);
107*4882a593Smuzhiyun return ret;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun if (id == RC5T583_DS_LDO4) {
111*4882a593Smuzhiyun ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1);
112*4882a593Smuzhiyun if (ret < 0)
113*4882a593Smuzhiyun dev_err(dev, "Error in writing reg 0x%x\n",
114*4882a593Smuzhiyun RICOH_SWCTL_REG);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun return ret;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
__rc5t583_set_ext_pwrreq2_control(struct device * dev,int id,int ext_pwr)119*4882a593Smuzhiyun static int __rc5t583_set_ext_pwrreq2_control(struct device *dev,
120*4882a593Smuzhiyun int id, int ext_pwr)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun int ret;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun if (id != RC5T583_DS_DC0) {
125*4882a593Smuzhiyun dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id);
126*4882a593Smuzhiyun return -EINVAL;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2));
130*4882a593Smuzhiyun if (ret < 0)
131*4882a593Smuzhiyun dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n");
132*4882a593Smuzhiyun return ret;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
rc5t583_ext_power_req_config(struct device * dev,int ds_id,int ext_pwr_req,int deepsleep_slot_nr)135*4882a593Smuzhiyun int rc5t583_ext_power_req_config(struct device *dev, int ds_id,
136*4882a593Smuzhiyun int ext_pwr_req, int deepsleep_slot_nr)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ)
139*4882a593Smuzhiyun return -EINVAL;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL)
142*4882a593Smuzhiyun return __rc5t583_set_ext_pwrreq1_control(dev, ds_id,
143*4882a593Smuzhiyun ext_pwr_req, deepsleep_slot_nr);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL)
146*4882a593Smuzhiyun return __rc5t583_set_ext_pwrreq2_control(dev,
147*4882a593Smuzhiyun ds_id, ext_pwr_req);
148*4882a593Smuzhiyun return 0;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun EXPORT_SYMBOL(rc5t583_ext_power_req_config);
151*4882a593Smuzhiyun
rc5t583_clear_ext_power_req(struct rc5t583 * rc5t583,struct rc5t583_platform_data * pdata)152*4882a593Smuzhiyun static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
153*4882a593Smuzhiyun struct rc5t583_platform_data *pdata)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun int ret;
156*4882a593Smuzhiyun int i;
157*4882a593Smuzhiyun uint8_t on_off_val = 0;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun /* Clear ONOFFSEL register */
160*4882a593Smuzhiyun if (pdata->enable_shutdown)
161*4882a593Smuzhiyun on_off_val = 0x1;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val);
164*4882a593Smuzhiyun if (ret < 0)
165*4882a593Smuzhiyun dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
166*4882a593Smuzhiyun RICOH_ONOFFSEL_REG, ret);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0);
169*4882a593Smuzhiyun if (ret < 0)
170*4882a593Smuzhiyun dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
171*4882a593Smuzhiyun RICOH_SWCTL_REG, ret);
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* Clear sleep sequence register */
174*4882a593Smuzhiyun for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) {
175*4882a593Smuzhiyun ret = rc5t583_write(rc5t583->dev, i, 0x0);
176*4882a593Smuzhiyun if (ret < 0)
177*4882a593Smuzhiyun dev_warn(rc5t583->dev,
178*4882a593Smuzhiyun "Error in writing reg 0x%02x error: %d\n",
179*4882a593Smuzhiyun i, ret);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun return 0;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
volatile_reg(struct device * dev,unsigned int reg)184*4882a593Smuzhiyun static bool volatile_reg(struct device *dev, unsigned int reg)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun /* Enable caching in interrupt registers */
187*4882a593Smuzhiyun switch (reg) {
188*4882a593Smuzhiyun case RC5T583_INT_EN_SYS1:
189*4882a593Smuzhiyun case RC5T583_INT_EN_SYS2:
190*4882a593Smuzhiyun case RC5T583_INT_EN_DCDC:
191*4882a593Smuzhiyun case RC5T583_INT_EN_RTC:
192*4882a593Smuzhiyun case RC5T583_INT_EN_ADC1:
193*4882a593Smuzhiyun case RC5T583_INT_EN_ADC2:
194*4882a593Smuzhiyun case RC5T583_INT_EN_ADC3:
195*4882a593Smuzhiyun case RC5T583_GPIO_GPEDGE1:
196*4882a593Smuzhiyun case RC5T583_GPIO_GPEDGE2:
197*4882a593Smuzhiyun case RC5T583_GPIO_EN_INT:
198*4882a593Smuzhiyun return false;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun case RC5T583_GPIO_MON_IOIN:
201*4882a593Smuzhiyun /* This is gpio input register */
202*4882a593Smuzhiyun return true;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun default:
205*4882a593Smuzhiyun /* Enable caching in gpio registers */
206*4882a593Smuzhiyun if ((reg >= RC5T583_GPIO_IOSEL) &&
207*4882a593Smuzhiyun (reg <= RC5T583_GPIO_GPOFUNC))
208*4882a593Smuzhiyun return false;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Enable caching in sleep seq registers */
211*4882a593Smuzhiyun if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11))
212*4882a593Smuzhiyun return false;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* Enable caching of regulator registers */
215*4882a593Smuzhiyun if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL))
216*4882a593Smuzhiyun return false;
217*4882a593Smuzhiyun if ((reg >= RC5T583_REG_LDOEN1) &&
218*4882a593Smuzhiyun (reg <= RC5T583_REG_LDO9DAC_DS))
219*4882a593Smuzhiyun return false;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun break;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun return true;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun static const struct regmap_config rc5t583_regmap_config = {
228*4882a593Smuzhiyun .reg_bits = 8,
229*4882a593Smuzhiyun .val_bits = 8,
230*4882a593Smuzhiyun .volatile_reg = volatile_reg,
231*4882a593Smuzhiyun .max_register = RC5T583_MAX_REG,
232*4882a593Smuzhiyun .num_reg_defaults_raw = RC5T583_NUM_REGS,
233*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun
rc5t583_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)236*4882a593Smuzhiyun static int rc5t583_i2c_probe(struct i2c_client *i2c,
237*4882a593Smuzhiyun const struct i2c_device_id *id)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun struct rc5t583 *rc5t583;
240*4882a593Smuzhiyun struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);
241*4882a593Smuzhiyun int ret;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (!pdata) {
244*4882a593Smuzhiyun dev_err(&i2c->dev, "Err: Platform data not found\n");
245*4882a593Smuzhiyun return -EINVAL;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun rc5t583 = devm_kzalloc(&i2c->dev, sizeof(*rc5t583), GFP_KERNEL);
249*4882a593Smuzhiyun if (!rc5t583)
250*4882a593Smuzhiyun return -ENOMEM;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun rc5t583->dev = &i2c->dev;
253*4882a593Smuzhiyun i2c_set_clientdata(i2c, rc5t583);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun rc5t583->regmap = devm_regmap_init_i2c(i2c, &rc5t583_regmap_config);
256*4882a593Smuzhiyun if (IS_ERR(rc5t583->regmap)) {
257*4882a593Smuzhiyun ret = PTR_ERR(rc5t583->regmap);
258*4882a593Smuzhiyun dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
259*4882a593Smuzhiyun return ret;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun ret = rc5t583_clear_ext_power_req(rc5t583, pdata);
263*4882a593Smuzhiyun if (ret < 0)
264*4882a593Smuzhiyun return ret;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (i2c->irq) {
267*4882a593Smuzhiyun ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);
268*4882a593Smuzhiyun /* Still continue with warning, if irq init fails */
269*4882a593Smuzhiyun if (ret)
270*4882a593Smuzhiyun dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun ret = devm_mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
274*4882a593Smuzhiyun ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
275*4882a593Smuzhiyun if (ret) {
276*4882a593Smuzhiyun dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
277*4882a593Smuzhiyun return ret;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static const struct i2c_device_id rc5t583_i2c_id[] = {
284*4882a593Smuzhiyun {.name = "rc5t583", .driver_data = 0},
285*4882a593Smuzhiyun {}
286*4882a593Smuzhiyun };
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static struct i2c_driver rc5t583_i2c_driver = {
289*4882a593Smuzhiyun .driver = {
290*4882a593Smuzhiyun .name = "rc5t583",
291*4882a593Smuzhiyun },
292*4882a593Smuzhiyun .probe = rc5t583_i2c_probe,
293*4882a593Smuzhiyun .id_table = rc5t583_i2c_id,
294*4882a593Smuzhiyun };
295*4882a593Smuzhiyun
rc5t583_i2c_init(void)296*4882a593Smuzhiyun static int __init rc5t583_i2c_init(void)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun return i2c_add_driver(&rc5t583_i2c_driver);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun subsys_initcall(rc5t583_i2c_init);
301