xref: /OK3568_Linux_fs/kernel/drivers/mfd/tc3589x.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) ST-Ericsson SA 2010
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
6*4882a593Smuzhiyun  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/irq.h>
12*4882a593Smuzhiyun #include <linux/irqdomain.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/i2c.h>
15*4882a593Smuzhiyun #include <linux/of.h>
16*4882a593Smuzhiyun #include <linux/of_device.h>
17*4882a593Smuzhiyun #include <linux/mfd/core.h>
18*4882a593Smuzhiyun #include <linux/mfd/tc3589x.h>
19*4882a593Smuzhiyun #include <linux/err.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun  * enum tc3589x_version - indicates the TC3589x version
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun enum tc3589x_version {
25*4882a593Smuzhiyun 	TC3589X_TC35890,
26*4882a593Smuzhiyun 	TC3589X_TC35892,
27*4882a593Smuzhiyun 	TC3589X_TC35893,
28*4882a593Smuzhiyun 	TC3589X_TC35894,
29*4882a593Smuzhiyun 	TC3589X_TC35895,
30*4882a593Smuzhiyun 	TC3589X_TC35896,
31*4882a593Smuzhiyun 	TC3589X_UNKNOWN,
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define TC3589x_CLKMODE_MODCTL_SLEEP		0x0
35*4882a593Smuzhiyun #define TC3589x_CLKMODE_MODCTL_OPERATION	(1 << 0)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /**
38*4882a593Smuzhiyun  * tc3589x_reg_read() - read a single TC3589x register
39*4882a593Smuzhiyun  * @tc3589x:	Device to read from
40*4882a593Smuzhiyun  * @reg:	Register to read
41*4882a593Smuzhiyun  */
tc3589x_reg_read(struct tc3589x * tc3589x,u8 reg)42*4882a593Smuzhiyun int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	int ret;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg);
47*4882a593Smuzhiyun 	if (ret < 0)
48*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to read reg %#x: %d\n",
49*4882a593Smuzhiyun 			reg, ret);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return ret;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tc3589x_reg_read);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /**
56*4882a593Smuzhiyun  * tc3589x_reg_write() - write a single TC3589x register
57*4882a593Smuzhiyun  * @tc3589x:	Device to write to
58*4882a593Smuzhiyun  * @reg:	Register to read
59*4882a593Smuzhiyun  * @data:	Value to write
60*4882a593Smuzhiyun  */
tc3589x_reg_write(struct tc3589x * tc3589x,u8 reg,u8 data)61*4882a593Smuzhiyun int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	int ret;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data);
66*4882a593Smuzhiyun 	if (ret < 0)
67*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to write reg %#x: %d\n",
68*4882a593Smuzhiyun 			reg, ret);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return ret;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tc3589x_reg_write);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /**
75*4882a593Smuzhiyun  * tc3589x_block_read() - read multiple TC3589x registers
76*4882a593Smuzhiyun  * @tc3589x:	Device to read from
77*4882a593Smuzhiyun  * @reg:	First register
78*4882a593Smuzhiyun  * @length:	Number of registers
79*4882a593Smuzhiyun  * @values:	Buffer to write to
80*4882a593Smuzhiyun  */
tc3589x_block_read(struct tc3589x * tc3589x,u8 reg,u8 length,u8 * values)81*4882a593Smuzhiyun int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	int ret;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values);
86*4882a593Smuzhiyun 	if (ret < 0)
87*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to read regs %#x: %d\n",
88*4882a593Smuzhiyun 			reg, ret);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return ret;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tc3589x_block_read);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /**
95*4882a593Smuzhiyun  * tc3589x_block_write() - write multiple TC3589x registers
96*4882a593Smuzhiyun  * @tc3589x:	Device to write to
97*4882a593Smuzhiyun  * @reg:	First register
98*4882a593Smuzhiyun  * @length:	Number of registers
99*4882a593Smuzhiyun  * @values:	Values to write
100*4882a593Smuzhiyun  */
tc3589x_block_write(struct tc3589x * tc3589x,u8 reg,u8 length,const u8 * values)101*4882a593Smuzhiyun int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length,
102*4882a593Smuzhiyun 			const u8 *values)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	int ret;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length,
107*4882a593Smuzhiyun 					     values);
108*4882a593Smuzhiyun 	if (ret < 0)
109*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to write regs %#x: %d\n",
110*4882a593Smuzhiyun 			reg, ret);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return ret;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tc3589x_block_write);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /**
117*4882a593Smuzhiyun  * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register
118*4882a593Smuzhiyun  * @tc3589x:	Device to write to
119*4882a593Smuzhiyun  * @reg:	Register to write
120*4882a593Smuzhiyun  * @mask:	Mask of bits to set
121*4882a593Smuzhiyun  * @val:	Value to set
122*4882a593Smuzhiyun  */
tc3589x_set_bits(struct tc3589x * tc3589x,u8 reg,u8 mask,u8 val)123*4882a593Smuzhiyun int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	int ret;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	mutex_lock(&tc3589x->lock);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	ret = tc3589x_reg_read(tc3589x, reg);
130*4882a593Smuzhiyun 	if (ret < 0)
131*4882a593Smuzhiyun 		goto out;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	ret &= ~mask;
134*4882a593Smuzhiyun 	ret |= val;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	ret = tc3589x_reg_write(tc3589x, reg, ret);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun out:
139*4882a593Smuzhiyun 	mutex_unlock(&tc3589x->lock);
140*4882a593Smuzhiyun 	return ret;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tc3589x_set_bits);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun static struct resource gpio_resources[] = {
145*4882a593Smuzhiyun 	{
146*4882a593Smuzhiyun 		.start	= TC3589x_INT_GPIIRQ,
147*4882a593Smuzhiyun 		.end	= TC3589x_INT_GPIIRQ,
148*4882a593Smuzhiyun 		.flags	= IORESOURCE_IRQ,
149*4882a593Smuzhiyun 	},
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static struct resource keypad_resources[] = {
153*4882a593Smuzhiyun 	{
154*4882a593Smuzhiyun 		.start  = TC3589x_INT_KBDIRQ,
155*4882a593Smuzhiyun 		.end    = TC3589x_INT_KBDIRQ,
156*4882a593Smuzhiyun 		.flags  = IORESOURCE_IRQ,
157*4882a593Smuzhiyun 	},
158*4882a593Smuzhiyun };
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static const struct mfd_cell tc3589x_dev_gpio[] = {
161*4882a593Smuzhiyun 	{
162*4882a593Smuzhiyun 		.name		= "tc3589x-gpio",
163*4882a593Smuzhiyun 		.num_resources	= ARRAY_SIZE(gpio_resources),
164*4882a593Smuzhiyun 		.resources	= &gpio_resources[0],
165*4882a593Smuzhiyun 		.of_compatible	= "toshiba,tc3589x-gpio",
166*4882a593Smuzhiyun 	},
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static const struct mfd_cell tc3589x_dev_keypad[] = {
170*4882a593Smuzhiyun 	{
171*4882a593Smuzhiyun 		.name           = "tc3589x-keypad",
172*4882a593Smuzhiyun 		.num_resources  = ARRAY_SIZE(keypad_resources),
173*4882a593Smuzhiyun 		.resources      = &keypad_resources[0],
174*4882a593Smuzhiyun 		.of_compatible	= "toshiba,tc3589x-keypad",
175*4882a593Smuzhiyun 	},
176*4882a593Smuzhiyun };
177*4882a593Smuzhiyun 
tc3589x_irq(int irq,void * data)178*4882a593Smuzhiyun static irqreturn_t tc3589x_irq(int irq, void *data)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct tc3589x *tc3589x = data;
181*4882a593Smuzhiyun 	int status;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun again:
184*4882a593Smuzhiyun 	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
185*4882a593Smuzhiyun 	if (status < 0)
186*4882a593Smuzhiyun 		return IRQ_NONE;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	while (status) {
189*4882a593Smuzhiyun 		int bit = __ffs(status);
190*4882a593Smuzhiyun 		int virq = irq_find_mapping(tc3589x->domain, bit);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		handle_nested_irq(virq);
193*4882a593Smuzhiyun 		status &= ~(1 << bit);
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	/*
197*4882a593Smuzhiyun 	 * A dummy read or write (to any register) appears to be necessary to
198*4882a593Smuzhiyun 	 * have the last interrupt clear (for example, GPIO IC write) take
199*4882a593Smuzhiyun 	 * effect. In such a case, recheck for any interrupt which is still
200*4882a593Smuzhiyun 	 * pending.
201*4882a593Smuzhiyun 	 */
202*4882a593Smuzhiyun 	status = tc3589x_reg_read(tc3589x, TC3589x_IRQST);
203*4882a593Smuzhiyun 	if (status)
204*4882a593Smuzhiyun 		goto again;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return IRQ_HANDLED;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
tc3589x_irq_map(struct irq_domain * d,unsigned int virq,irq_hw_number_t hwirq)209*4882a593Smuzhiyun static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq,
210*4882a593Smuzhiyun 				irq_hw_number_t hwirq)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	struct tc3589x *tc3589x = d->host_data;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	irq_set_chip_data(virq, tc3589x);
215*4882a593Smuzhiyun 	irq_set_chip_and_handler(virq, &dummy_irq_chip,
216*4882a593Smuzhiyun 				handle_edge_irq);
217*4882a593Smuzhiyun 	irq_set_nested_thread(virq, 1);
218*4882a593Smuzhiyun 	irq_set_noprobe(virq);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	return 0;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
tc3589x_irq_unmap(struct irq_domain * d,unsigned int virq)223*4882a593Smuzhiyun static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun 	irq_set_chip_and_handler(virq, NULL, NULL);
226*4882a593Smuzhiyun 	irq_set_chip_data(virq, NULL);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static const struct irq_domain_ops tc3589x_irq_ops = {
230*4882a593Smuzhiyun 	.map    = tc3589x_irq_map,
231*4882a593Smuzhiyun 	.unmap  = tc3589x_irq_unmap,
232*4882a593Smuzhiyun 	.xlate  = irq_domain_xlate_onecell,
233*4882a593Smuzhiyun };
234*4882a593Smuzhiyun 
tc3589x_irq_init(struct tc3589x * tc3589x,struct device_node * np)235*4882a593Smuzhiyun static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	tc3589x->domain = irq_domain_add_simple(
238*4882a593Smuzhiyun 		np, TC3589x_NR_INTERNAL_IRQS, 0,
239*4882a593Smuzhiyun 		&tc3589x_irq_ops, tc3589x);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	if (!tc3589x->domain) {
242*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "Failed to create irqdomain\n");
243*4882a593Smuzhiyun 		return -ENOSYS;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
tc3589x_chip_init(struct tc3589x * tc3589x)249*4882a593Smuzhiyun static int tc3589x_chip_init(struct tc3589x *tc3589x)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	int manf, ver, ret;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE);
254*4882a593Smuzhiyun 	if (manf < 0)
255*4882a593Smuzhiyun 		return manf;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION);
258*4882a593Smuzhiyun 	if (ver < 0)
259*4882a593Smuzhiyun 		return ver;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	if (manf != TC3589x_MANFCODE_MAGIC) {
262*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf);
263*4882a593Smuzhiyun 		return -EINVAL;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	/*
269*4882a593Smuzhiyun 	 * Put everything except the IRQ module into reset;
270*4882a593Smuzhiyun 	 * also spare the GPIO module for any pin initialization
271*4882a593Smuzhiyun 	 * done during pre-kernel boot
272*4882a593Smuzhiyun 	 */
273*4882a593Smuzhiyun 	ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL,
274*4882a593Smuzhiyun 				TC3589x_RSTCTRL_TIMRST
275*4882a593Smuzhiyun 				| TC3589x_RSTCTRL_ROTRST
276*4882a593Smuzhiyun 				| TC3589x_RSTCTRL_KBDRST);
277*4882a593Smuzhiyun 	if (ret < 0)
278*4882a593Smuzhiyun 		return ret;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	/* Clear the reset interrupt. */
281*4882a593Smuzhiyun 	return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
tc3589x_device_init(struct tc3589x * tc3589x)284*4882a593Smuzhiyun static int tc3589x_device_init(struct tc3589x *tc3589x)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	int ret = 0;
287*4882a593Smuzhiyun 	unsigned int blocks = tc3589x->pdata->block;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	if (blocks & TC3589x_BLOCK_GPIO) {
290*4882a593Smuzhiyun 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
291*4882a593Smuzhiyun 				      ARRAY_SIZE(tc3589x_dev_gpio), NULL,
292*4882a593Smuzhiyun 				      0, tc3589x->domain);
293*4882a593Smuzhiyun 		if (ret) {
294*4882a593Smuzhiyun 			dev_err(tc3589x->dev, "failed to add gpio child\n");
295*4882a593Smuzhiyun 			return ret;
296*4882a593Smuzhiyun 		}
297*4882a593Smuzhiyun 		dev_info(tc3589x->dev, "added gpio block\n");
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (blocks & TC3589x_BLOCK_KEYPAD) {
301*4882a593Smuzhiyun 		ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
302*4882a593Smuzhiyun 				      ARRAY_SIZE(tc3589x_dev_keypad), NULL,
303*4882a593Smuzhiyun 				      0, tc3589x->domain);
304*4882a593Smuzhiyun 		if (ret) {
305*4882a593Smuzhiyun 			dev_err(tc3589x->dev, "failed to keypad child\n");
306*4882a593Smuzhiyun 			return ret;
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 		dev_info(tc3589x->dev, "added keypad block\n");
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	return ret;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun static const struct of_device_id tc3589x_match[] = {
315*4882a593Smuzhiyun 	/* Legacy compatible string */
316*4882a593Smuzhiyun 	{ .compatible = "tc3589x", .data = (void *) TC3589X_UNKNOWN },
317*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35890", .data = (void *) TC3589X_TC35890 },
318*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35892", .data = (void *) TC3589X_TC35892 },
319*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35893", .data = (void *) TC3589X_TC35893 },
320*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35894", .data = (void *) TC3589X_TC35894 },
321*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35895", .data = (void *) TC3589X_TC35895 },
322*4882a593Smuzhiyun 	{ .compatible = "toshiba,tc35896", .data = (void *) TC3589X_TC35896 },
323*4882a593Smuzhiyun 	{ }
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tc3589x_match);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun static struct tc3589x_platform_data *
tc3589x_of_probe(struct device * dev,enum tc3589x_version * version)329*4882a593Smuzhiyun tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
332*4882a593Smuzhiyun 	struct tc3589x_platform_data *pdata;
333*4882a593Smuzhiyun 	struct device_node *child;
334*4882a593Smuzhiyun 	const struct of_device_id *of_id;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
337*4882a593Smuzhiyun 	if (!pdata)
338*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	of_id = of_match_device(tc3589x_match, dev);
341*4882a593Smuzhiyun 	if (!of_id)
342*4882a593Smuzhiyun 		return ERR_PTR(-ENODEV);
343*4882a593Smuzhiyun 	*version = (enum tc3589x_version) of_id->data;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	for_each_child_of_node(np, child) {
346*4882a593Smuzhiyun 		if (of_device_is_compatible(child, "toshiba,tc3589x-gpio"))
347*4882a593Smuzhiyun 			pdata->block |= TC3589x_BLOCK_GPIO;
348*4882a593Smuzhiyun 		if (of_device_is_compatible(child, "toshiba,tc3589x-keypad"))
349*4882a593Smuzhiyun 			pdata->block |= TC3589x_BLOCK_KEYPAD;
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	return pdata;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
tc3589x_probe(struct i2c_client * i2c,const struct i2c_device_id * id)355*4882a593Smuzhiyun static int tc3589x_probe(struct i2c_client *i2c,
356*4882a593Smuzhiyun 				   const struct i2c_device_id *id)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	struct device_node *np = i2c->dev.of_node;
359*4882a593Smuzhiyun 	struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
360*4882a593Smuzhiyun 	struct tc3589x *tc3589x;
361*4882a593Smuzhiyun 	enum tc3589x_version version;
362*4882a593Smuzhiyun 	int ret;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	if (!pdata) {
365*4882a593Smuzhiyun 		pdata = tc3589x_of_probe(&i2c->dev, &version);
366*4882a593Smuzhiyun 		if (IS_ERR(pdata)) {
367*4882a593Smuzhiyun 			dev_err(&i2c->dev, "No platform data or DT found\n");
368*4882a593Smuzhiyun 			return PTR_ERR(pdata);
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 	} else {
371*4882a593Smuzhiyun 		/* When not probing from device tree we have this ID */
372*4882a593Smuzhiyun 		version = id->driver_data;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
376*4882a593Smuzhiyun 				     | I2C_FUNC_SMBUS_I2C_BLOCK))
377*4882a593Smuzhiyun 		return -EIO;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	tc3589x = devm_kzalloc(&i2c->dev, sizeof(struct tc3589x),
380*4882a593Smuzhiyun 				GFP_KERNEL);
381*4882a593Smuzhiyun 	if (!tc3589x)
382*4882a593Smuzhiyun 		return -ENOMEM;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	mutex_init(&tc3589x->lock);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	tc3589x->dev = &i2c->dev;
387*4882a593Smuzhiyun 	tc3589x->i2c = i2c;
388*4882a593Smuzhiyun 	tc3589x->pdata = pdata;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	switch (version) {
391*4882a593Smuzhiyun 	case TC3589X_TC35893:
392*4882a593Smuzhiyun 	case TC3589X_TC35895:
393*4882a593Smuzhiyun 	case TC3589X_TC35896:
394*4882a593Smuzhiyun 		tc3589x->num_gpio = 20;
395*4882a593Smuzhiyun 		break;
396*4882a593Smuzhiyun 	case TC3589X_TC35890:
397*4882a593Smuzhiyun 	case TC3589X_TC35892:
398*4882a593Smuzhiyun 	case TC3589X_TC35894:
399*4882a593Smuzhiyun 	case TC3589X_UNKNOWN:
400*4882a593Smuzhiyun 	default:
401*4882a593Smuzhiyun 		tc3589x->num_gpio = 24;
402*4882a593Smuzhiyun 		break;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	i2c_set_clientdata(i2c, tc3589x);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	ret = tc3589x_chip_init(tc3589x);
408*4882a593Smuzhiyun 	if (ret)
409*4882a593Smuzhiyun 		return ret;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	ret = tc3589x_irq_init(tc3589x, np);
412*4882a593Smuzhiyun 	if (ret)
413*4882a593Smuzhiyun 		return ret;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq,
416*4882a593Smuzhiyun 				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
417*4882a593Smuzhiyun 				   "tc3589x", tc3589x);
418*4882a593Smuzhiyun 	if (ret) {
419*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
420*4882a593Smuzhiyun 		return ret;
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	ret = tc3589x_device_init(tc3589x);
424*4882a593Smuzhiyun 	if (ret) {
425*4882a593Smuzhiyun 		dev_err(tc3589x->dev, "failed to add child devices\n");
426*4882a593Smuzhiyun 		return ret;
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	return 0;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
tc3589x_remove(struct i2c_client * client)432*4882a593Smuzhiyun static int tc3589x_remove(struct i2c_client *client)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	struct tc3589x *tc3589x = i2c_get_clientdata(client);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	mfd_remove_devices(tc3589x->dev);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	return 0;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
tc3589x_suspend(struct device * dev)442*4882a593Smuzhiyun static int tc3589x_suspend(struct device *dev)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	struct tc3589x *tc3589x = dev_get_drvdata(dev);
445*4882a593Smuzhiyun 	struct i2c_client *client = tc3589x->i2c;
446*4882a593Smuzhiyun 	int ret = 0;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	/* put the system to sleep mode */
449*4882a593Smuzhiyun 	if (!device_may_wakeup(&client->dev))
450*4882a593Smuzhiyun 		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
451*4882a593Smuzhiyun 				TC3589x_CLKMODE_MODCTL_SLEEP);
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	return ret;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
tc3589x_resume(struct device * dev)456*4882a593Smuzhiyun static int tc3589x_resume(struct device *dev)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	struct tc3589x *tc3589x = dev_get_drvdata(dev);
459*4882a593Smuzhiyun 	struct i2c_client *client = tc3589x->i2c;
460*4882a593Smuzhiyun 	int ret = 0;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	/* enable the system into operation */
463*4882a593Smuzhiyun 	if (!device_may_wakeup(&client->dev))
464*4882a593Smuzhiyun 		ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE,
465*4882a593Smuzhiyun 				TC3589x_CLKMODE_MODCTL_OPERATION);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	return ret;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun #endif
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume);
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun static const struct i2c_device_id tc3589x_id[] = {
474*4882a593Smuzhiyun 	{ "tc35890", TC3589X_TC35890 },
475*4882a593Smuzhiyun 	{ "tc35892", TC3589X_TC35892 },
476*4882a593Smuzhiyun 	{ "tc35893", TC3589X_TC35893 },
477*4882a593Smuzhiyun 	{ "tc35894", TC3589X_TC35894 },
478*4882a593Smuzhiyun 	{ "tc35895", TC3589X_TC35895 },
479*4882a593Smuzhiyun 	{ "tc35896", TC3589X_TC35896 },
480*4882a593Smuzhiyun 	{ "tc3589x", TC3589X_UNKNOWN },
481*4882a593Smuzhiyun 	{ }
482*4882a593Smuzhiyun };
483*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, tc3589x_id);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun static struct i2c_driver tc3589x_driver = {
486*4882a593Smuzhiyun 	.driver = {
487*4882a593Smuzhiyun 		.name	= "tc3589x",
488*4882a593Smuzhiyun 		.pm	= &tc3589x_dev_pm_ops,
489*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(tc3589x_match),
490*4882a593Smuzhiyun 	},
491*4882a593Smuzhiyun 	.probe		= tc3589x_probe,
492*4882a593Smuzhiyun 	.remove		= tc3589x_remove,
493*4882a593Smuzhiyun 	.id_table	= tc3589x_id,
494*4882a593Smuzhiyun };
495*4882a593Smuzhiyun 
tc3589x_init(void)496*4882a593Smuzhiyun static int __init tc3589x_init(void)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	return i2c_add_driver(&tc3589x_driver);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun subsys_initcall(tc3589x_init);
501*4882a593Smuzhiyun 
tc3589x_exit(void)502*4882a593Smuzhiyun static void __exit tc3589x_exit(void)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	i2c_del_driver(&tc3589x_driver);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun module_exit(tc3589x_exit);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
509*4882a593Smuzhiyun MODULE_DESCRIPTION("TC3589x MFD core driver");
510*4882a593Smuzhiyun MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
511