xref: /openbmc/linux/drivers/input/keyboard/adp5520-keys.c (revision fba65fe0ededc538771e47f6d099d7c853f4776e)
1*fba65fe0SMichael Hennerich /*
2*fba65fe0SMichael Hennerich  * Keypad driver for Analog Devices ADP5520 MFD PMICs
3*fba65fe0SMichael Hennerich  *
4*fba65fe0SMichael Hennerich  * Copyright 2009 Analog Devices Inc.
5*fba65fe0SMichael Hennerich  *
6*fba65fe0SMichael Hennerich  * Licensed under the GPL-2 or later.
7*fba65fe0SMichael Hennerich  */
8*fba65fe0SMichael Hennerich 
9*fba65fe0SMichael Hennerich #include <linux/module.h>
10*fba65fe0SMichael Hennerich #include <linux/kernel.h>
11*fba65fe0SMichael Hennerich #include <linux/init.h>
12*fba65fe0SMichael Hennerich #include <linux/platform_device.h>
13*fba65fe0SMichael Hennerich #include <linux/input.h>
14*fba65fe0SMichael Hennerich #include <linux/mfd/adp5520.h>
15*fba65fe0SMichael Hennerich 
16*fba65fe0SMichael Hennerich struct adp5520_keys {
17*fba65fe0SMichael Hennerich 	struct input_dev *input;
18*fba65fe0SMichael Hennerich 	struct notifier_block notifier;
19*fba65fe0SMichael Hennerich 	struct device *master;
20*fba65fe0SMichael Hennerich 	unsigned short keycode[ADP5520_KEYMAPSIZE];
21*fba65fe0SMichael Hennerich };
22*fba65fe0SMichael Hennerich 
23*fba65fe0SMichael Hennerich static void adp5520_keys_report_event(struct adp5520_keys *dev,
24*fba65fe0SMichael Hennerich 					unsigned short keymask, int value)
25*fba65fe0SMichael Hennerich {
26*fba65fe0SMichael Hennerich 	int i;
27*fba65fe0SMichael Hennerich 
28*fba65fe0SMichael Hennerich 	for (i = 0; i < ADP5520_MAXKEYS; i++)
29*fba65fe0SMichael Hennerich 		if (keymask & (1 << i))
30*fba65fe0SMichael Hennerich 			input_report_key(dev->input, dev->keycode[i], value);
31*fba65fe0SMichael Hennerich 
32*fba65fe0SMichael Hennerich 	input_sync(dev->input);
33*fba65fe0SMichael Hennerich }
34*fba65fe0SMichael Hennerich 
35*fba65fe0SMichael Hennerich static int adp5520_keys_notifier(struct notifier_block *nb,
36*fba65fe0SMichael Hennerich 				 unsigned long event, void *data)
37*fba65fe0SMichael Hennerich {
38*fba65fe0SMichael Hennerich 	struct adp5520_keys *dev;
39*fba65fe0SMichael Hennerich 	uint8_t reg_val_lo, reg_val_hi;
40*fba65fe0SMichael Hennerich 	unsigned short keymask;
41*fba65fe0SMichael Hennerich 
42*fba65fe0SMichael Hennerich 	dev = container_of(nb, struct adp5520_keys, notifier);
43*fba65fe0SMichael Hennerich 
44*fba65fe0SMichael Hennerich 	if (event & ADP5520_KP_INT) {
45*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, &reg_val_lo);
46*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, &reg_val_hi);
47*fba65fe0SMichael Hennerich 
48*fba65fe0SMichael Hennerich 		keymask = (reg_val_hi << 8) | reg_val_lo;
49*fba65fe0SMichael Hennerich 		/* Read twice to clear */
50*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, &reg_val_lo);
51*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, &reg_val_hi);
52*fba65fe0SMichael Hennerich 		keymask |= (reg_val_hi << 8) | reg_val_lo;
53*fba65fe0SMichael Hennerich 		adp5520_keys_report_event(dev, keymask, 1);
54*fba65fe0SMichael Hennerich 	}
55*fba65fe0SMichael Hennerich 
56*fba65fe0SMichael Hennerich 	if (event & ADP5520_KR_INT) {
57*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, &reg_val_lo);
58*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, &reg_val_hi);
59*fba65fe0SMichael Hennerich 
60*fba65fe0SMichael Hennerich 		keymask = (reg_val_hi << 8) | reg_val_lo;
61*fba65fe0SMichael Hennerich 		/* Read twice to clear */
62*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, &reg_val_lo);
63*fba65fe0SMichael Hennerich 		adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, &reg_val_hi);
64*fba65fe0SMichael Hennerich 		keymask |= (reg_val_hi << 8) | reg_val_lo;
65*fba65fe0SMichael Hennerich 		adp5520_keys_report_event(dev, keymask, 0);
66*fba65fe0SMichael Hennerich 	}
67*fba65fe0SMichael Hennerich 
68*fba65fe0SMichael Hennerich 	return 0;
69*fba65fe0SMichael Hennerich }
70*fba65fe0SMichael Hennerich 
71*fba65fe0SMichael Hennerich static int __devinit adp5520_keys_probe(struct platform_device *pdev)
72*fba65fe0SMichael Hennerich {
73*fba65fe0SMichael Hennerich 	struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data;
74*fba65fe0SMichael Hennerich 	struct input_dev *input;
75*fba65fe0SMichael Hennerich 	struct adp5520_keys *dev;
76*fba65fe0SMichael Hennerich 	int ret, i;
77*fba65fe0SMichael Hennerich 	unsigned char en_mask, ctl_mask = 0;
78*fba65fe0SMichael Hennerich 
79*fba65fe0SMichael Hennerich 	if (pdev->id != ID_ADP5520) {
80*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "only ADP5520 supports Keypad\n");
81*fba65fe0SMichael Hennerich 		return -EINVAL;
82*fba65fe0SMichael Hennerich 	}
83*fba65fe0SMichael Hennerich 
84*fba65fe0SMichael Hennerich 	if (pdata == NULL) {
85*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "missing platform data\n");
86*fba65fe0SMichael Hennerich 		return -EINVAL;
87*fba65fe0SMichael Hennerich 	}
88*fba65fe0SMichael Hennerich 
89*fba65fe0SMichael Hennerich 	if (!(pdata->rows_en_mask && pdata->cols_en_mask))
90*fba65fe0SMichael Hennerich 		return -EINVAL;
91*fba65fe0SMichael Hennerich 
92*fba65fe0SMichael Hennerich 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
93*fba65fe0SMichael Hennerich 	if (dev == NULL) {
94*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "failed to alloc memory\n");
95*fba65fe0SMichael Hennerich 		return -ENOMEM;
96*fba65fe0SMichael Hennerich 	}
97*fba65fe0SMichael Hennerich 
98*fba65fe0SMichael Hennerich 	input = input_allocate_device();
99*fba65fe0SMichael Hennerich 	if (!input) {
100*fba65fe0SMichael Hennerich 		ret = -ENOMEM;
101*fba65fe0SMichael Hennerich 		goto err;
102*fba65fe0SMichael Hennerich 	}
103*fba65fe0SMichael Hennerich 
104*fba65fe0SMichael Hennerich 	dev->master = pdev->dev.parent;
105*fba65fe0SMichael Hennerich 	dev->input = input;
106*fba65fe0SMichael Hennerich 
107*fba65fe0SMichael Hennerich 	input->name = pdev->name;
108*fba65fe0SMichael Hennerich 	input->phys = "adp5520-keys/input0";
109*fba65fe0SMichael Hennerich 	input->dev.parent = &pdev->dev;
110*fba65fe0SMichael Hennerich 
111*fba65fe0SMichael Hennerich 	input_set_drvdata(input, dev);
112*fba65fe0SMichael Hennerich 
113*fba65fe0SMichael Hennerich 	input->id.bustype = BUS_I2C;
114*fba65fe0SMichael Hennerich 	input->id.vendor = 0x0001;
115*fba65fe0SMichael Hennerich 	input->id.product = 0x5520;
116*fba65fe0SMichael Hennerich 	input->id.version = 0x0001;
117*fba65fe0SMichael Hennerich 
118*fba65fe0SMichael Hennerich 	input->keycodesize = sizeof(dev->keycode[0]);
119*fba65fe0SMichael Hennerich 	input->keycodemax = pdata->keymapsize;
120*fba65fe0SMichael Hennerich 	input->keycode = dev->keycode;
121*fba65fe0SMichael Hennerich 
122*fba65fe0SMichael Hennerich 	memcpy(dev->keycode, pdata->keymap,
123*fba65fe0SMichael Hennerich 		pdata->keymapsize * input->keycodesize);
124*fba65fe0SMichael Hennerich 
125*fba65fe0SMichael Hennerich 	/* setup input device */
126*fba65fe0SMichael Hennerich 	__set_bit(EV_KEY, input->evbit);
127*fba65fe0SMichael Hennerich 
128*fba65fe0SMichael Hennerich 	if (pdata->repeat)
129*fba65fe0SMichael Hennerich 		__set_bit(EV_REP, input->evbit);
130*fba65fe0SMichael Hennerich 
131*fba65fe0SMichael Hennerich 	for (i = 0; i < input->keycodemax; i++)
132*fba65fe0SMichael Hennerich 		__set_bit(dev->keycode[i], input->keybit);
133*fba65fe0SMichael Hennerich 	__clear_bit(KEY_RESERVED, input->keybit);
134*fba65fe0SMichael Hennerich 
135*fba65fe0SMichael Hennerich 	ret = input_register_device(input);
136*fba65fe0SMichael Hennerich 	if (ret) {
137*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "unable to register input device\n");
138*fba65fe0SMichael Hennerich 		goto err;
139*fba65fe0SMichael Hennerich 	}
140*fba65fe0SMichael Hennerich 
141*fba65fe0SMichael Hennerich 	en_mask = pdata->rows_en_mask | pdata->cols_en_mask;
142*fba65fe0SMichael Hennerich 
143*fba65fe0SMichael Hennerich 	ret = adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_1, en_mask);
144*fba65fe0SMichael Hennerich 
145*fba65fe0SMichael Hennerich 	if (en_mask & ADP5520_COL_C3)
146*fba65fe0SMichael Hennerich 		ctl_mask |= ADP5520_C3_MODE;
147*fba65fe0SMichael Hennerich 
148*fba65fe0SMichael Hennerich 	if (en_mask & ADP5520_ROW_R3)
149*fba65fe0SMichael Hennerich 		ctl_mask |= ADP5520_R3_MODE;
150*fba65fe0SMichael Hennerich 
151*fba65fe0SMichael Hennerich 	if (ctl_mask)
152*fba65fe0SMichael Hennerich 		ret |= adp5520_set_bits(dev->master, ADP5520_LED_CONTROL,
153*fba65fe0SMichael Hennerich 			ctl_mask);
154*fba65fe0SMichael Hennerich 
155*fba65fe0SMichael Hennerich 	ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP,
156*fba65fe0SMichael Hennerich 		pdata->rows_en_mask);
157*fba65fe0SMichael Hennerich 
158*fba65fe0SMichael Hennerich 	if (ret) {
159*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "failed to write\n");
160*fba65fe0SMichael Hennerich 		ret = -EIO;
161*fba65fe0SMichael Hennerich 		goto err1;
162*fba65fe0SMichael Hennerich 	}
163*fba65fe0SMichael Hennerich 
164*fba65fe0SMichael Hennerich 	dev->notifier.notifier_call = adp5520_keys_notifier;
165*fba65fe0SMichael Hennerich 	ret = adp5520_register_notifier(dev->master, &dev->notifier,
166*fba65fe0SMichael Hennerich 			ADP5520_KP_IEN | ADP5520_KR_IEN);
167*fba65fe0SMichael Hennerich 	if (ret) {
168*fba65fe0SMichael Hennerich 		dev_err(&pdev->dev, "failed to register notifier\n");
169*fba65fe0SMichael Hennerich 		goto err1;
170*fba65fe0SMichael Hennerich 	}
171*fba65fe0SMichael Hennerich 
172*fba65fe0SMichael Hennerich 	platform_set_drvdata(pdev, dev);
173*fba65fe0SMichael Hennerich 	return 0;
174*fba65fe0SMichael Hennerich 
175*fba65fe0SMichael Hennerich err1:
176*fba65fe0SMichael Hennerich 	input_unregister_device(input);
177*fba65fe0SMichael Hennerich 	input = NULL;
178*fba65fe0SMichael Hennerich err:
179*fba65fe0SMichael Hennerich 	input_free_device(input);
180*fba65fe0SMichael Hennerich 	kfree(dev);
181*fba65fe0SMichael Hennerich 	return ret;
182*fba65fe0SMichael Hennerich }
183*fba65fe0SMichael Hennerich 
184*fba65fe0SMichael Hennerich static int __devexit adp5520_keys_remove(struct platform_device *pdev)
185*fba65fe0SMichael Hennerich {
186*fba65fe0SMichael Hennerich 	struct adp5520_keys *dev = platform_get_drvdata(pdev);
187*fba65fe0SMichael Hennerich 
188*fba65fe0SMichael Hennerich 	adp5520_unregister_notifier(dev->master, &dev->notifier,
189*fba65fe0SMichael Hennerich 				ADP5520_KP_IEN | ADP5520_KR_IEN);
190*fba65fe0SMichael Hennerich 
191*fba65fe0SMichael Hennerich 	input_unregister_device(dev->input);
192*fba65fe0SMichael Hennerich 	kfree(dev);
193*fba65fe0SMichael Hennerich 	return 0;
194*fba65fe0SMichael Hennerich }
195*fba65fe0SMichael Hennerich 
196*fba65fe0SMichael Hennerich static struct platform_driver adp5520_keys_driver = {
197*fba65fe0SMichael Hennerich 	.driver	= {
198*fba65fe0SMichael Hennerich 		.name	= "adp5520-keys",
199*fba65fe0SMichael Hennerich 		.owner	= THIS_MODULE,
200*fba65fe0SMichael Hennerich 	},
201*fba65fe0SMichael Hennerich 	.probe		= adp5520_keys_probe,
202*fba65fe0SMichael Hennerich 	.remove		= __devexit_p(adp5520_keys_remove),
203*fba65fe0SMichael Hennerich };
204*fba65fe0SMichael Hennerich 
205*fba65fe0SMichael Hennerich static int __init adp5520_keys_init(void)
206*fba65fe0SMichael Hennerich {
207*fba65fe0SMichael Hennerich 	return platform_driver_register(&adp5520_keys_driver);
208*fba65fe0SMichael Hennerich }
209*fba65fe0SMichael Hennerich module_init(adp5520_keys_init);
210*fba65fe0SMichael Hennerich 
211*fba65fe0SMichael Hennerich static void __exit adp5520_keys_exit(void)
212*fba65fe0SMichael Hennerich {
213*fba65fe0SMichael Hennerich 	platform_driver_unregister(&adp5520_keys_driver);
214*fba65fe0SMichael Hennerich }
215*fba65fe0SMichael Hennerich module_exit(adp5520_keys_exit);
216*fba65fe0SMichael Hennerich 
217*fba65fe0SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
218*fba65fe0SMichael Hennerich MODULE_DESCRIPTION("Keys ADP5520 Driver");
219*fba65fe0SMichael Hennerich MODULE_LICENSE("GPL");
220*fba65fe0SMichael Hennerich MODULE_ALIAS("platform:adp5520-keys");
221