xref: /OK3568_Linux_fs/kernel/drivers/mfd/rc5t583.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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