xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/ebc-dev/pmic/tps65185.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Zorro Liu <zorro.liu@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/device.h>
9*4882a593Smuzhiyun #include <linux/of_gpio.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/errno.h>
13*4882a593Smuzhiyun #include <linux/string.h>
14*4882a593Smuzhiyun #include <linux/mm.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/device.h>
18*4882a593Smuzhiyun #include <linux/major.h>
19*4882a593Smuzhiyun #include <linux/fs.h>
20*4882a593Smuzhiyun #include <linux/cdev.h>
21*4882a593Smuzhiyun #include <linux/uaccess.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/workqueue.h>
24*4882a593Smuzhiyun #include <linux/delay.h>
25*4882a593Smuzhiyun #include <linux/i2c.h>
26*4882a593Smuzhiyun #include <linux/version.h>
27*4882a593Smuzhiyun #include <linux/suspend.h>
28*4882a593Smuzhiyun #include <linux/soc/rockchip/rk_vendor_storage.h>
29*4882a593Smuzhiyun #include <linux/gpio.h>
30*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
31*4882a593Smuzhiyun #include "ebc_pmic.h"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* After waking up from sleep, Papyrus
34*4882a593Smuzhiyun    waits for VN to be discharged and all
35*4882a593Smuzhiyun    voltage ref to startup before loading
36*4882a593Smuzhiyun    the default EEPROM settings. So accessing
37*4882a593Smuzhiyun    registers too early after WAKEUP could
38*4882a593Smuzhiyun    cause the register to be overridden by
39*4882a593Smuzhiyun    default values */
40*4882a593Smuzhiyun #define PAPYRUS_EEPROM_DELAY_MS 50
41*4882a593Smuzhiyun /* Papyrus WAKEUP pin must stay low for
42*4882a593Smuzhiyun    a minimum time */
43*4882a593Smuzhiyun #define PAPYRUS_SLEEP_MINIMUM_MS 110
44*4882a593Smuzhiyun /* Temp sensor might take a little time to
45*4882a593Smuzhiyun    settle eventhough the status bit in TMST1
46*4882a593Smuzhiyun    state conversion is done - if read too early
47*4882a593Smuzhiyun    0C will be returned instead of the right temp */
48*4882a593Smuzhiyun #define PAPYRUS_TEMP_READ_TIME_MS 10
49*4882a593Smuzhiyun /* Powerup sequence takes at least 24 ms - no need to poll too frequently */
50*4882a593Smuzhiyun #define HW_GET_STATE_INTERVAL_MS 24
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #define SEQ_VDD(index)		((index % 4) << 6)
53*4882a593Smuzhiyun #define SEQ_VPOS(index)	((index % 4) << 4)
54*4882a593Smuzhiyun #define SEQ_VEE(index)		((index % 4) << 2)
55*4882a593Smuzhiyun #define SEQ_VNEG(index)	((index % 4) << 0)
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* power up seq delay time */
58*4882a593Smuzhiyun #define UDLY_3ms(index)	(0x00 << ((index%4) * 2))
59*4882a593Smuzhiyun #define UDLY_6ms(index)	(0x01 << ((index%4) * 2))
60*4882a593Smuzhiyun #define UDLY_9ms(index)	(0x10 << ((index%4) * 2))
61*4882a593Smuzhiyun #define UDLY_12ms(index)	(0x11 << ((index%4) * 2))
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /* power down seq delay time */
64*4882a593Smuzhiyun #define DDLY_6ms(index)	(0x00 << ((index%4) * 2))
65*4882a593Smuzhiyun #define DDLY_12ms(index)	(0x01 << ((index%4) * 2))
66*4882a593Smuzhiyun #define DDLY_24ms(index)	(0x10 << ((index%4) * 2))
67*4882a593Smuzhiyun #define DDLY_48ms(index)	(0x11 << ((index%4) * 2))
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define NUMBER_PMIC_REGS	10
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define PAPYRUS_ADDR_TMST_VALUE	0x00
72*4882a593Smuzhiyun #define PAPYRUS_ADDR_ENABLE			0x01
73*4882a593Smuzhiyun #define PAPYRUS_ADDR_VADJ			0x02
74*4882a593Smuzhiyun #define PAPYRUS_ADDR_VCOM1_ADJUST	0x03
75*4882a593Smuzhiyun #define PAPYRUS_ADDR_VCOM2_ADJUST	0x04
76*4882a593Smuzhiyun #define PAPYRUS_ADDR_INT_ENABLE1	0x05
77*4882a593Smuzhiyun #define PAPYRUS_ADDR_INT_ENABLE2	0x06
78*4882a593Smuzhiyun #define PAPYRUS_ADDR_INT_STATUS1	0x07
79*4882a593Smuzhiyun #define PAPYRUS_ADDR_INT_STATUS2	0x08
80*4882a593Smuzhiyun #define PAPYRUS_ADDR_UPSEQ0			0x09
81*4882a593Smuzhiyun #define PAPYRUS_ADDR_UPSEQ1			0x0a
82*4882a593Smuzhiyun #define PAPYRUS_ADDR_DWNSEQ0		0x0b
83*4882a593Smuzhiyun #define PAPYRUS_ADDR_DWNSEQ1		0x0c
84*4882a593Smuzhiyun #define PAPYRUS_ADDR_TMST1			0x0d
85*4882a593Smuzhiyun #define PAPYRUS_ADDR_TMST2			0x0e
86*4882a593Smuzhiyun #define PAPYRUS_ADDR_PG_STATUS		0x0f
87*4882a593Smuzhiyun #define PAPYRUS_ADDR_REVID			0x10
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun // INT_ENABLE1
90*4882a593Smuzhiyun #define PAPYRUS_INT_ENABLE1_ACQC_EN	1
91*4882a593Smuzhiyun #define PAPYRUS_INT_ENABLE1_PRGC_EN		0
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun // INT_STATUS1
94*4882a593Smuzhiyun #define PAPYRUS_INT_STATUS1_ACQC		1
95*4882a593Smuzhiyun #define PAPYRUS_INT_STATUS1_PRGC		0
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun // VCOM2_ADJUST
98*4882a593Smuzhiyun #define PAPYRUS_VCOM2_ACQ		7
99*4882a593Smuzhiyun #define PAPYRUS_VCOM2_PROG		6
100*4882a593Smuzhiyun #define PAPYRUS_VCOM2_HIZ		5
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun #define PAPYRUS_MV_TO_VCOMREG(MV)	((MV) / 10)
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun #define V3P3_EN_MASK		0x20
105*4882a593Smuzhiyun #define PAPYRUS_V3P3OFF_DELAY_MS	20//100
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun struct papyrus_sess {
108*4882a593Smuzhiyun 	struct device *dev;
109*4882a593Smuzhiyun 	struct i2c_client *client;
110*4882a593Smuzhiyun 	uint8_t enable_reg_shadow;
111*4882a593Smuzhiyun 	uint8_t vadj;
112*4882a593Smuzhiyun 	uint8_t vcom1;
113*4882a593Smuzhiyun 	uint8_t vcom2;
114*4882a593Smuzhiyun 	uint8_t upseq0;
115*4882a593Smuzhiyun 	uint8_t upseq1;
116*4882a593Smuzhiyun 	uint8_t dwnseq0;
117*4882a593Smuzhiyun 	uint8_t dwnseq1;
118*4882a593Smuzhiyun 	int irq;
119*4882a593Smuzhiyun 	struct gpio_desc *int_pin;
120*4882a593Smuzhiyun 	struct gpio_desc *pwr_en_pin;
121*4882a593Smuzhiyun 	struct gpio_desc *pwr_up_pin;
122*4882a593Smuzhiyun 	struct gpio_desc *wake_up_pin;
123*4882a593Smuzhiyun 	struct gpio_desc *vcom_ctl_pin;
124*4882a593Smuzhiyun 	struct mutex power_lock;
125*4882a593Smuzhiyun 	struct workqueue_struct *tmp_monitor_wq;
126*4882a593Smuzhiyun 	struct delayed_work tmp_delay_work;
127*4882a593Smuzhiyun };
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun struct papyrus_hw_state {
130*4882a593Smuzhiyun 	uint8_t tmst_value;
131*4882a593Smuzhiyun 	uint8_t int_status1;
132*4882a593Smuzhiyun 	uint8_t int_status2;
133*4882a593Smuzhiyun 	uint8_t pg_status;
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun static bool papyrus_need_reconfig = true;
136*4882a593Smuzhiyun 
papyrus_hw_setreg(struct papyrus_sess * sess,uint8_t regaddr,uint8_t val)137*4882a593Smuzhiyun static int papyrus_hw_setreg(struct papyrus_sess *sess, uint8_t regaddr, uint8_t val)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	int stat;
140*4882a593Smuzhiyun 	uint8_t txbuf[2] = { regaddr, val };
141*4882a593Smuzhiyun 	struct i2c_msg msgs[] = {
142*4882a593Smuzhiyun 		{
143*4882a593Smuzhiyun 			.addr = sess->client->addr,
144*4882a593Smuzhiyun 			.flags = 0,
145*4882a593Smuzhiyun 			.len = 2,
146*4882a593Smuzhiyun 			.buf = txbuf,
147*4882a593Smuzhiyun 		}
148*4882a593Smuzhiyun 	};
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	stat = i2c_transfer(sess->client->adapter, msgs, ARRAY_SIZE(msgs));
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (stat < 0) {
153*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c send error: %d\n", stat);
154*4882a593Smuzhiyun 	} else if (stat != ARRAY_SIZE(msgs)) {
155*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c send N mismatch: %d\n", stat);
156*4882a593Smuzhiyun 		stat = -EIO;
157*4882a593Smuzhiyun 	} else {
158*4882a593Smuzhiyun 		stat = 0;
159*4882a593Smuzhiyun 	}
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return stat;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
papyrus_hw_getreg(struct papyrus_sess * sess,uint8_t regaddr,uint8_t * val)164*4882a593Smuzhiyun static int papyrus_hw_getreg(struct papyrus_sess *sess, uint8_t regaddr, uint8_t *val)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	int stat;
167*4882a593Smuzhiyun 	struct i2c_msg msgs[] = {
168*4882a593Smuzhiyun 		{
169*4882a593Smuzhiyun 			.addr = sess->client->addr,
170*4882a593Smuzhiyun 			.flags = 0,
171*4882a593Smuzhiyun 			.len = 1,
172*4882a593Smuzhiyun 			.buf = &regaddr,
173*4882a593Smuzhiyun 		},
174*4882a593Smuzhiyun 		{
175*4882a593Smuzhiyun 			.addr = sess->client->addr,
176*4882a593Smuzhiyun 			.flags = I2C_M_RD,
177*4882a593Smuzhiyun 			.len = 1,
178*4882a593Smuzhiyun 			.buf = val,
179*4882a593Smuzhiyun 		}
180*4882a593Smuzhiyun 	};
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	stat = i2c_transfer(sess->client->adapter, msgs, ARRAY_SIZE(msgs));
183*4882a593Smuzhiyun 	if (stat < 0) {
184*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c read error: %d\n", stat);
185*4882a593Smuzhiyun 	} else if (stat != ARRAY_SIZE(msgs)) {
186*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c read N mismatch: %d\n", stat);
187*4882a593Smuzhiyun 		stat = -EIO;
188*4882a593Smuzhiyun 	} else {
189*4882a593Smuzhiyun 		stat = 0;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	return stat;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
papyrus_hw_get_int_state(struct papyrus_sess * sess,struct papyrus_hw_state * hwst)195*4882a593Smuzhiyun static void papyrus_hw_get_int_state(struct papyrus_sess *sess, struct papyrus_hw_state *hwst)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	int stat;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	stat = papyrus_hw_getreg(sess, PAPYRUS_ADDR_INT_STATUS1, &hwst->int_status1);
200*4882a593Smuzhiyun 	if (stat)
201*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c error: %d\n", stat);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	stat = papyrus_hw_getreg(sess, PAPYRUS_ADDR_INT_STATUS2, &hwst->int_status2);
204*4882a593Smuzhiyun 	if (stat)
205*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c error: %d\n", stat);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun #if 0
208*4882a593Smuzhiyun static bool papyrus_hw_power_ack(struct papyrus_sess *sess, int up)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	struct papyrus_hw_state hwst;
211*4882a593Smuzhiyun 	int st;
212*4882a593Smuzhiyun 	int retries_left = 10;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if ((up & ~(1UL))) {
215*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "invalid power flag %d.\n", up);
216*4882a593Smuzhiyun 		return false;
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	do {
220*4882a593Smuzhiyun 		papyrus_hw_getreg(sess, PAPYRUS_ADDR_PG_STATUS, &hwst.pg_status);
221*4882a593Smuzhiyun 		dev_dbg(&sess->client->dev, "hwst: tmst_val=%d, ist1=%02x, ist2=%02x, pg=%02x\n",
222*4882a593Smuzhiyun 			hwst.tmst_value, hwst.int_status1, hwst.int_status2, hwst.pg_status);
223*4882a593Smuzhiyun 		hwst.pg_status &= 0xfa;
224*4882a593Smuzhiyun 		if ((hwst.pg_status == 0xfa) && (up == 1)) {
225*4882a593Smuzhiyun 			st = 1;
226*4882a593Smuzhiyun 		} else if ((hwst.pg_status == 0x00) && (up == 0)) {
227*4882a593Smuzhiyun 			st = 0;
228*4882a593Smuzhiyun 		} else {
229*4882a593Smuzhiyun 			st = -1;	/* not settled yet */
230*4882a593Smuzhiyun 			msleep(HW_GET_STATE_INTERVAL_MS);
231*4882a593Smuzhiyun 		}
232*4882a593Smuzhiyun 		retries_left--;
233*4882a593Smuzhiyun 	} while ((st == -1) && retries_left);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	if (st == -1)
236*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "power %s settle error (PG = %02x)\n", up ? "up" : "down", hwst.pg_status);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	return (st == up);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun #endif
papyrus_hw_send_powerup(struct papyrus_sess * sess)241*4882a593Smuzhiyun static void papyrus_hw_send_powerup(struct papyrus_sess *sess)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	int stat = 0;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VADJ, sess->vadj);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_UPSEQ0, sess->upseq0);
248*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_UPSEQ1, sess->upseq1);
249*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_DWNSEQ0, sess->dwnseq0);
250*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_DWNSEQ1, sess->dwnseq1);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	//stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VCOM1_ADJUST, sess->vcom1);
253*4882a593Smuzhiyun 	//stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VCOM2_ADJUST, sess->vcom2);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	sess->enable_reg_shadow |= V3P3_EN_MASK;
256*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
257*4882a593Smuzhiyun 	usleep_range(2 * 1000, 3 * 1000);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	sess->enable_reg_shadow = (0x80 | 0x30 | 0x0F);
260*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
261*4882a593Smuzhiyun 	if (stat)
262*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c error: %d\n", stat);
263*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(sess->pwr_up_pin))
264*4882a593Smuzhiyun 		gpiod_direction_output(sess->pwr_up_pin, 1);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	return;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
papyrus_hw_send_powerdown(struct papyrus_sess * sess)269*4882a593Smuzhiyun static void papyrus_hw_send_powerdown(struct papyrus_sess *sess)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun 	int stat = 0;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	sess->enable_reg_shadow = (0x40 | 0x20 | 0x0F);
274*4882a593Smuzhiyun 	stat = papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
275*4882a593Smuzhiyun 	usleep_range(2 * 1000, 3 * 1000);
276*4882a593Smuzhiyun 	sess->enable_reg_shadow &= ~V3P3_EN_MASK;
277*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
278*4882a593Smuzhiyun 	if (stat)
279*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c error: %d\n", stat);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	return;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
papyrus_irq(int irq,void * dev_id)285*4882a593Smuzhiyun static irqreturn_t papyrus_irq(int irq, void *dev_id)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	struct papyrus_sess *sess = dev_id;
288*4882a593Smuzhiyun 	struct papyrus_hw_state hwst;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	papyrus_hw_get_int_state(sess, &hwst);
291*4882a593Smuzhiyun 	dev_info(&sess->client->dev, "%s: (INT1 = %02x, INT2 = %02x)\n", __func__,
292*4882a593Smuzhiyun 						hwst.int_status1, hwst.int_status2);
293*4882a593Smuzhiyun 	//reset pmic
294*4882a593Smuzhiyun 	if ((hwst.int_status2 & 0xfa) || (hwst.int_status1 & 0x04)) {
295*4882a593Smuzhiyun 		if (sess->enable_reg_shadow | V3P3_EN_MASK)
296*4882a593Smuzhiyun 			papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return IRQ_HANDLED;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
papyrus_hw_get_revid(struct papyrus_sess * sess)302*4882a593Smuzhiyun static int papyrus_hw_get_revid(struct papyrus_sess *sess)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	int stat;
305*4882a593Smuzhiyun 	uint8_t revid;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	stat = papyrus_hw_getreg(sess, PAPYRUS_ADDR_REVID, &revid);
308*4882a593Smuzhiyun 	if (stat) {
309*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "i2c error: %d\n", stat);
310*4882a593Smuzhiyun 		return stat;
311*4882a593Smuzhiyun 	} else {
312*4882a593Smuzhiyun 		return revid;
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
papyrus_hw_arg_init(struct papyrus_sess * sess)316*4882a593Smuzhiyun static void papyrus_hw_arg_init(struct papyrus_sess *sess)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	sess->vadj = 0x03;
319*4882a593Smuzhiyun 	sess->upseq0 = SEQ_VEE(0) | SEQ_VNEG(1) | SEQ_VPOS(2) | SEQ_VDD(3);
320*4882a593Smuzhiyun 	sess->upseq1 = UDLY_3ms(0) | UDLY_3ms(1) | UDLY_3ms(2) | UDLY_3ms(3);
321*4882a593Smuzhiyun 	sess->dwnseq0 = SEQ_VDD(0) | SEQ_VPOS(1) | SEQ_VNEG(2) | SEQ_VEE(3);
322*4882a593Smuzhiyun 	sess->dwnseq1 = DDLY_6ms(0) | DDLY_6ms(1) | DDLY_6ms(2) | DDLY_6ms(3);
323*4882a593Smuzhiyun 	sess->vcom1 = (PAPYRUS_MV_TO_VCOMREG(1560) & 0x00FF);
324*4882a593Smuzhiyun 	sess->vcom2 = ((PAPYRUS_MV_TO_VCOMREG(1560) & 0x0100) >> 8);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun 
papyrus_hw_init(struct papyrus_sess * sess)327*4882a593Smuzhiyun static int papyrus_hw_init(struct papyrus_sess *sess)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	int stat = 0;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(sess->pwr_en_pin)) {
332*4882a593Smuzhiyun 		gpiod_direction_output(sess->pwr_en_pin, 1);
333*4882a593Smuzhiyun 		usleep_range(2 * 1000, 3 * 1000);
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 	gpiod_direction_output(sess->wake_up_pin, 0);
336*4882a593Smuzhiyun 	/* wait to reset papyrus */
337*4882a593Smuzhiyun 	msleep(PAPYRUS_SLEEP_MINIMUM_MS);
338*4882a593Smuzhiyun 	gpiod_direction_output(sess->wake_up_pin, 1);
339*4882a593Smuzhiyun 	/* power up pin no need to control, use i2c control */
340*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(sess->pwr_up_pin))
341*4882a593Smuzhiyun 		gpiod_direction_output(sess->pwr_up_pin, 0);
342*4882a593Smuzhiyun 	gpiod_direction_output(sess->vcom_ctl_pin, 1);
343*4882a593Smuzhiyun 	msleep(PAPYRUS_EEPROM_DELAY_MS);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	stat = papyrus_hw_get_revid(sess);
346*4882a593Smuzhiyun 	if (stat < 0) {
347*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "get id failed");
348*4882a593Smuzhiyun 		return stat;
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	dev_info(&sess->client->dev, "detected device with ID=%02x (TPS6518%dr%dp%d)\n",
352*4882a593Smuzhiyun 		 stat, stat & 0xF, (stat & 0xC0) >> 6, (stat & 0x30) >> 4);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
papyrus_set_vcom_voltage(struct papyrus_sess * sess,int vcom_mv)357*4882a593Smuzhiyun static void papyrus_set_vcom_voltage(struct papyrus_sess *sess, int vcom_mv)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	sess->vcom1 = (PAPYRUS_MV_TO_VCOMREG(vcom_mv) & 0x00FF);
360*4882a593Smuzhiyun 	sess->vcom2 = ((PAPYRUS_MV_TO_VCOMREG(vcom_mv) & 0x0100) >> 8);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
papyrus_hw_read_temperature(struct ebc_pmic * pmic,int * t)363*4882a593Smuzhiyun static int papyrus_hw_read_temperature(struct ebc_pmic *pmic, int *t)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	struct papyrus_sess *sess = (struct papyrus_sess *)pmic->drvpar;
366*4882a593Smuzhiyun 	int stat;
367*4882a593Smuzhiyun 	uint8_t tb;
368*4882a593Smuzhiyun #if 0
369*4882a593Smuzhiyun 	int ntries = 50;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	stat = papyrus_hw_setreg(sess, PAPYRUS_ADDR_TMST1, 0x80);
372*4882a593Smuzhiyun 	if (stat)
373*4882a593Smuzhiyun 		return stat;
374*4882a593Smuzhiyun 	do {
375*4882a593Smuzhiyun 		stat = papyrus_hw_getreg(sess, PAPYRUS_ADDR_TMST1, &tb);
376*4882a593Smuzhiyun 	} while (!stat && ntries-- && (((tb & 0x20) == 0) || (tb & 0x80)));
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	if (stat)
379*4882a593Smuzhiyun 		return stat;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	msleep(PAPYRUS_TEMP_READ_TIME_MS);
382*4882a593Smuzhiyun #endif
383*4882a593Smuzhiyun 	stat = papyrus_hw_getreg(sess, PAPYRUS_ADDR_TMST_VALUE, &tb);
384*4882a593Smuzhiyun 	*t = (int)(int8_t)tb;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	return stat;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun 
papyrus_hw_power_req(struct ebc_pmic * pmic,bool up)389*4882a593Smuzhiyun static void papyrus_hw_power_req(struct ebc_pmic *pmic, bool up)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	struct papyrus_sess *sess = (struct papyrus_sess *)pmic->drvpar;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	if (up)
394*4882a593Smuzhiyun 		mutex_lock(&sess->power_lock);
395*4882a593Smuzhiyun 	if (papyrus_need_reconfig) {
396*4882a593Smuzhiyun 		if (up) {
397*4882a593Smuzhiyun 			papyrus_hw_send_powerup(sess);
398*4882a593Smuzhiyun 			//papyrus_hw_power_ack(sess, up);
399*4882a593Smuzhiyun 			enable_irq(sess->irq);
400*4882a593Smuzhiyun 		} else {
401*4882a593Smuzhiyun 			disable_irq(sess->irq);
402*4882a593Smuzhiyun 			papyrus_hw_send_powerdown(sess);
403*4882a593Smuzhiyun 			//papyrus_hw_power_ack(sess, up);
404*4882a593Smuzhiyun 		}
405*4882a593Smuzhiyun 		papyrus_need_reconfig = false;
406*4882a593Smuzhiyun 	} else {
407*4882a593Smuzhiyun 		if (up) {
408*4882a593Smuzhiyun 			if (!IS_ERR_OR_NULL(sess->pwr_up_pin))
409*4882a593Smuzhiyun 				gpiod_direction_output(sess->pwr_up_pin, 1);
410*4882a593Smuzhiyun 			enable_irq(sess->irq);
411*4882a593Smuzhiyun 		} else {
412*4882a593Smuzhiyun 			disable_irq(sess->irq);
413*4882a593Smuzhiyun 			if (!IS_ERR_OR_NULL(sess->pwr_up_pin))
414*4882a593Smuzhiyun 				gpiod_direction_output(sess->pwr_up_pin, 0);
415*4882a593Smuzhiyun 		}
416*4882a593Smuzhiyun 	}
417*4882a593Smuzhiyun 	if (!up)
418*4882a593Smuzhiyun 		mutex_unlock(&sess->power_lock);
419*4882a593Smuzhiyun 	return;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
papyrus_hw_vcom_get(struct ebc_pmic * pmic)422*4882a593Smuzhiyun static int papyrus_hw_vcom_get(struct ebc_pmic *pmic)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	struct papyrus_sess *sess = (struct papyrus_sess *)pmic->drvpar;
425*4882a593Smuzhiyun 	uint8_t rev_val = 0;
426*4882a593Smuzhiyun 	int stat = 0;
427*4882a593Smuzhiyun 	int read_vcom_mv = 0;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	mutex_lock(&sess->power_lock);
430*4882a593Smuzhiyun 	// VERIFICATION
431*4882a593Smuzhiyun 	gpiod_direction_output(sess->wake_up_pin, 0);
432*4882a593Smuzhiyun 	msleep(10);
433*4882a593Smuzhiyun 	gpiod_direction_output(sess->wake_up_pin, 1);
434*4882a593Smuzhiyun 	msleep(10);
435*4882a593Smuzhiyun 	read_vcom_mv = 0;
436*4882a593Smuzhiyun 	stat |= papyrus_hw_getreg(sess, PAPYRUS_ADDR_VCOM1_ADJUST, &rev_val);
437*4882a593Smuzhiyun 	read_vcom_mv += rev_val;
438*4882a593Smuzhiyun 	stat |= papyrus_hw_getreg(sess, PAPYRUS_ADDR_VCOM2_ADJUST, &rev_val);
439*4882a593Smuzhiyun 	read_vcom_mv += ((rev_val & 0x0001) << 8);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	if (stat)
442*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "papyrus: I2C error: %d\n", stat);
443*4882a593Smuzhiyun 	mutex_unlock(&sess->power_lock);
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	return read_vcom_mv * 10;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun 
papyrus_hw_vcom_set(struct ebc_pmic * pmic,int vcom_mv)448*4882a593Smuzhiyun static int papyrus_hw_vcom_set(struct ebc_pmic *pmic, int vcom_mv)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	struct papyrus_sess *sess = (struct papyrus_sess *)pmic->drvpar;
451*4882a593Smuzhiyun 	uint8_t rev_val = 0;
452*4882a593Smuzhiyun 	int stat = 0;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	mutex_lock(&sess->power_lock);
455*4882a593Smuzhiyun 	gpiod_direction_output(sess->wake_up_pin, 1);
456*4882a593Smuzhiyun 	msleep(10);
457*4882a593Smuzhiyun 	// Set vcom voltage
458*4882a593Smuzhiyun 	papyrus_set_vcom_voltage(sess, vcom_mv);
459*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VCOM1_ADJUST, sess->vcom1);
460*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VCOM2_ADJUST, sess->vcom2);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	// PROGRAMMING
463*4882a593Smuzhiyun 	sess->vcom2 |= 1 << PAPYRUS_VCOM2_PROG;
464*4882a593Smuzhiyun 	stat |= papyrus_hw_setreg(sess, PAPYRUS_ADDR_VCOM2_ADJUST, sess->vcom2);
465*4882a593Smuzhiyun 	rev_val = 0;
466*4882a593Smuzhiyun 	while (!(rev_val & (1 << PAPYRUS_INT_STATUS1_PRGC))) {
467*4882a593Smuzhiyun 		stat |= papyrus_hw_getreg(sess, PAPYRUS_ADDR_INT_STATUS1, &rev_val);
468*4882a593Smuzhiyun 		if (stat)
469*4882a593Smuzhiyun 			break;
470*4882a593Smuzhiyun 		msleep(50);
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	if (stat)
474*4882a593Smuzhiyun 		dev_err(&sess->client->dev, "papyrus: I2C error: %d\n", stat);
475*4882a593Smuzhiyun 	mutex_unlock(&sess->power_lock);
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	return 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
papyrus_pm_sleep(struct ebc_pmic * pmic)480*4882a593Smuzhiyun static void papyrus_pm_sleep(struct ebc_pmic *pmic)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	struct papyrus_sess *s = (struct papyrus_sess *)pmic->drvpar;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	cancel_delayed_work_sync(&s->tmp_delay_work);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	mutex_lock(&s->power_lock);
487*4882a593Smuzhiyun 	gpiod_direction_output(s->vcom_ctl_pin, 0);
488*4882a593Smuzhiyun 	gpiod_direction_output(s->wake_up_pin, 0);
489*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(s->pwr_en_pin))
490*4882a593Smuzhiyun 		gpiod_direction_output(s->pwr_en_pin, 0);
491*4882a593Smuzhiyun 	papyrus_need_reconfig = true;
492*4882a593Smuzhiyun 	mutex_unlock(&s->power_lock);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
papyrus_pm_resume(struct ebc_pmic * pmic)495*4882a593Smuzhiyun static void papyrus_pm_resume(struct ebc_pmic *pmic)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	struct papyrus_sess *s = (struct papyrus_sess *)pmic->drvpar;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	mutex_lock(&s->power_lock);
500*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(s->pwr_en_pin)) {
501*4882a593Smuzhiyun 		gpiod_direction_output(s->pwr_en_pin, 1);
502*4882a593Smuzhiyun 		usleep_range(2 * 1000, 3 * 1000);
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 	gpiod_direction_output(s->wake_up_pin, 1);
505*4882a593Smuzhiyun 	gpiod_direction_output(s->vcom_ctl_pin, 1);
506*4882a593Smuzhiyun 	usleep_range(2 * 1000, 3 * 1000);
507*4882a593Smuzhiyun 	mutex_unlock(&s->power_lock);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	//trigger temperature measurement
510*4882a593Smuzhiyun 	papyrus_hw_setreg(s, PAPYRUS_ADDR_TMST1, 0x80);
511*4882a593Smuzhiyun 	queue_delayed_work(s->tmp_monitor_wq, &s->tmp_delay_work,
512*4882a593Smuzhiyun 			   msecs_to_jiffies(10000));
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun 
papyrus_tmp_work(struct work_struct * work)515*4882a593Smuzhiyun static void papyrus_tmp_work(struct work_struct *work)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun 	struct papyrus_sess *s =
518*4882a593Smuzhiyun 		container_of(work, struct papyrus_sess, tmp_delay_work.work);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	//trigger temperature measurement
521*4882a593Smuzhiyun 	papyrus_hw_setreg(s, PAPYRUS_ADDR_TMST1, 0x80);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	queue_delayed_work(s->tmp_monitor_wq, &s->tmp_delay_work,
524*4882a593Smuzhiyun 			   msecs_to_jiffies(10000));
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
papyrus_probe(struct ebc_pmic * pmic,struct i2c_client * client)527*4882a593Smuzhiyun static int papyrus_probe(struct ebc_pmic *pmic, struct i2c_client *client)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct papyrus_sess *sess;
530*4882a593Smuzhiyun 	int stat;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	sess = devm_kzalloc(&client->dev, sizeof(*sess), GFP_KERNEL);
533*4882a593Smuzhiyun 	if (!sess) {
534*4882a593Smuzhiyun 		dev_err(&client->dev, "%s:%d: kzalloc failed\n", __func__, __LINE__);
535*4882a593Smuzhiyun 		return -ENOMEM;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 	sess->client = client;
538*4882a593Smuzhiyun 	mutex_init(&sess->power_lock);
539*4882a593Smuzhiyun 	papyrus_hw_arg_init(sess);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	sess->pwr_en_pin = devm_gpiod_get_optional(&client->dev, "poweren", GPIOD_OUT_HIGH);
542*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(sess->pwr_en_pin)) {
543*4882a593Smuzhiyun 		dev_err(&client->dev, "tsp65185: failed to find poweren pin, no defined\n");
544*4882a593Smuzhiyun 	}
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	sess->wake_up_pin = devm_gpiod_get_optional(&client->dev, "wakeup", GPIOD_OUT_HIGH);
547*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(sess->wake_up_pin)) {
548*4882a593Smuzhiyun 		dev_err(&client->dev, "tsp65185: failed to find wakeup pin\n");
549*4882a593Smuzhiyun 		return -ENOMEM;
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	sess->vcom_ctl_pin = devm_gpiod_get_optional(&client->dev, "vcomctl", GPIOD_OUT_HIGH);
553*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(sess->vcom_ctl_pin)) {
554*4882a593Smuzhiyun 		dev_err(&client->dev, "tsp65185: failed to find vcom_ctl pin\n");
555*4882a593Smuzhiyun 		return -ENOMEM;
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	sess->pwr_up_pin = devm_gpiod_get_optional(&client->dev, "powerup", GPIOD_OUT_HIGH);
559*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(sess->pwr_up_pin))
560*4882a593Smuzhiyun 		dev_err(&client->dev, "tsp65185: no pwr_up pin find\n");
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	sess->int_pin = devm_gpiod_get(&client->dev, "int", GPIOD_IN);
563*4882a593Smuzhiyun 	if (IS_ERR(sess->int_pin)) {
564*4882a593Smuzhiyun 		dev_err(&client->dev, "tsp65185: failed to find int pin\n");
565*4882a593Smuzhiyun 		return PTR_ERR(sess->int_pin);
566*4882a593Smuzhiyun 	}
567*4882a593Smuzhiyun 	sess->irq = gpiod_to_irq(sess->int_pin);
568*4882a593Smuzhiyun 	if (sess->irq < 0) {
569*4882a593Smuzhiyun 		dev_err(&client->dev, "Unable to get irq number for int pin\n");
570*4882a593Smuzhiyun 		return sess->irq;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	irq_set_status_flags(sess->irq, IRQ_NOAUTOEN);
574*4882a593Smuzhiyun 	stat = devm_request_threaded_irq(&client->dev, sess->irq, NULL, papyrus_irq,
575*4882a593Smuzhiyun 					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
576*4882a593Smuzhiyun 					"tps65185", sess);
577*4882a593Smuzhiyun 	if (stat) {
578*4882a593Smuzhiyun 		dev_err(&client->dev,
579*4882a593Smuzhiyun 			"Failed to enable IRQ, error: %d\n", stat);
580*4882a593Smuzhiyun 		return stat;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	sess->tmp_monitor_wq = alloc_ordered_workqueue("%s",
584*4882a593Smuzhiyun 			WQ_MEM_RECLAIM | WQ_FREEZABLE, "tps-tmp-monitor-wq");
585*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&sess->tmp_delay_work, papyrus_tmp_work);
586*4882a593Smuzhiyun 	queue_delayed_work(sess->tmp_monitor_wq, &sess->tmp_delay_work,
587*4882a593Smuzhiyun 			   msecs_to_jiffies(10000));
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	stat = papyrus_hw_init(sess);
590*4882a593Smuzhiyun 	if (stat)
591*4882a593Smuzhiyun 		return stat;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	sess->enable_reg_shadow = 0;
594*4882a593Smuzhiyun 	stat = papyrus_hw_setreg(sess, PAPYRUS_ADDR_ENABLE, sess->enable_reg_shadow);
595*4882a593Smuzhiyun 	if (stat)
596*4882a593Smuzhiyun 		return stat;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	//trigger temperature measurement
599*4882a593Smuzhiyun 	papyrus_hw_setreg(sess, PAPYRUS_ADDR_TMST1, 0x80);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	pmic->drvpar = sess;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	pmic->pmic_get_vcom = papyrus_hw_vcom_get;
604*4882a593Smuzhiyun 	pmic->pmic_set_vcom = papyrus_hw_vcom_set;
605*4882a593Smuzhiyun 	pmic->pmic_pm_resume = papyrus_pm_resume;
606*4882a593Smuzhiyun 	pmic->pmic_pm_suspend = papyrus_pm_sleep;
607*4882a593Smuzhiyun 	pmic->pmic_power_req = papyrus_hw_power_req;
608*4882a593Smuzhiyun 	pmic->pmic_read_temperature = papyrus_hw_read_temperature;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	return 0;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
tps65185_probe(struct i2c_client * client,const struct i2c_device_id * id)613*4882a593Smuzhiyun static int tps65185_probe(struct i2c_client *client, const struct i2c_device_id *id)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	struct ebc_pmic *pmic;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
618*4882a593Smuzhiyun 		dev_err(&client->dev, "i2c check functionality failed.");
619*4882a593Smuzhiyun 		return -ENODEV;
620*4882a593Smuzhiyun 	}
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	pmic = devm_kzalloc(&client->dev, sizeof(*pmic), GFP_KERNEL);
623*4882a593Smuzhiyun 	if (!pmic) {
624*4882a593Smuzhiyun 		dev_err(&client->dev, "%s:%d: kzalloc failed\n", __func__, __LINE__);
625*4882a593Smuzhiyun 		return -ENOMEM;
626*4882a593Smuzhiyun 	}
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	if (0 != papyrus_probe(pmic, client)) {
629*4882a593Smuzhiyun 		dev_err(&client->dev, "tps65185 hw init failed.");
630*4882a593Smuzhiyun 		return -ENODEV;
631*4882a593Smuzhiyun 	}
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	pmic->dev = &client->dev;
634*4882a593Smuzhiyun 	sprintf(pmic->pmic_name, "tps65185");
635*4882a593Smuzhiyun 	i2c_set_clientdata(client, pmic);
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	dev_info(&client->dev, "tps65185 probe ok.\n");
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	return 0;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun 
tps65185_remove(struct i2c_client * client)642*4882a593Smuzhiyun static int tps65185_remove(struct i2c_client *client)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	return 0;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun static const struct i2c_device_id tps65185_id[] = {
648*4882a593Smuzhiyun 	{ "tps65185", 0 },
649*4882a593Smuzhiyun 	{ }
650*4882a593Smuzhiyun };
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun static const struct of_device_id tps65185_dt_ids[] = {
653*4882a593Smuzhiyun 	{ .compatible = "ti,tps65185", },
654*4882a593Smuzhiyun 	{ /* sentinel */ }
655*4882a593Smuzhiyun };
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tps65185_dt_ids);
658*4882a593Smuzhiyun static struct i2c_driver tps65185_driver = {
659*4882a593Smuzhiyun 	.probe	= tps65185_probe,
660*4882a593Smuzhiyun 	.remove 	= tps65185_remove,
661*4882a593Smuzhiyun 	.id_table	= tps65185_id,
662*4882a593Smuzhiyun 	.driver = {
663*4882a593Smuzhiyun 		.of_match_table = tps65185_dt_ids,
664*4882a593Smuzhiyun 		.name	  = "tps65185",
665*4882a593Smuzhiyun 		.owner	  = THIS_MODULE,
666*4882a593Smuzhiyun 	},
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun module_i2c_driver(tps65185_driver);
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun MODULE_DESCRIPTION("ti tps65185 pmic");
672*4882a593Smuzhiyun MODULE_LICENSE("GPL");
673