1*44f6b6a5SCristian Ciocaltea // SPDX-License-Identifier: GPL-2.0+
2*44f6b6a5SCristian Ciocaltea /*
3*44f6b6a5SCristian Ciocaltea * Onkey driver for Actions Semi ATC260x PMICs.
4*44f6b6a5SCristian Ciocaltea *
5*44f6b6a5SCristian Ciocaltea * Copyright (c) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
6*44f6b6a5SCristian Ciocaltea */
7*44f6b6a5SCristian Ciocaltea
8*44f6b6a5SCristian Ciocaltea #include <linux/bitfield.h>
9*44f6b6a5SCristian Ciocaltea #include <linux/input.h>
10*44f6b6a5SCristian Ciocaltea #include <linux/interrupt.h>
11*44f6b6a5SCristian Ciocaltea #include <linux/mfd/atc260x/core.h>
12*44f6b6a5SCristian Ciocaltea #include <linux/module.h>
13*44f6b6a5SCristian Ciocaltea #include <linux/of.h>
14*44f6b6a5SCristian Ciocaltea #include <linux/platform_device.h>
15*44f6b6a5SCristian Ciocaltea #include <linux/regmap.h>
16*44f6b6a5SCristian Ciocaltea
17*44f6b6a5SCristian Ciocaltea /* <2s for short press, >2s for long press */
18*44f6b6a5SCristian Ciocaltea #define KEY_PRESS_TIME_SEC 2
19*44f6b6a5SCristian Ciocaltea
20*44f6b6a5SCristian Ciocaltea /* Driver internals */
21*44f6b6a5SCristian Ciocaltea enum atc260x_onkey_reset_status {
22*44f6b6a5SCristian Ciocaltea KEY_RESET_HW_DEFAULT,
23*44f6b6a5SCristian Ciocaltea KEY_RESET_DISABLED,
24*44f6b6a5SCristian Ciocaltea KEY_RESET_USER_SEL,
25*44f6b6a5SCristian Ciocaltea };
26*44f6b6a5SCristian Ciocaltea
27*44f6b6a5SCristian Ciocaltea struct atc260x_onkey_params {
28*44f6b6a5SCristian Ciocaltea u32 reg_int_ctl;
29*44f6b6a5SCristian Ciocaltea u32 kdwn_state_bm;
30*44f6b6a5SCristian Ciocaltea u32 long_int_pnd_bm;
31*44f6b6a5SCristian Ciocaltea u32 short_int_pnd_bm;
32*44f6b6a5SCristian Ciocaltea u32 kdwn_int_pnd_bm;
33*44f6b6a5SCristian Ciocaltea u32 press_int_en_bm;
34*44f6b6a5SCristian Ciocaltea u32 kdwn_int_en_bm;
35*44f6b6a5SCristian Ciocaltea u32 press_time_bm;
36*44f6b6a5SCristian Ciocaltea u32 reset_en_bm;
37*44f6b6a5SCristian Ciocaltea u32 reset_time_bm;
38*44f6b6a5SCristian Ciocaltea };
39*44f6b6a5SCristian Ciocaltea
40*44f6b6a5SCristian Ciocaltea struct atc260x_onkey {
41*44f6b6a5SCristian Ciocaltea struct atc260x *atc260x;
42*44f6b6a5SCristian Ciocaltea const struct atc260x_onkey_params *params;
43*44f6b6a5SCristian Ciocaltea struct input_dev *input_dev;
44*44f6b6a5SCristian Ciocaltea struct delayed_work work;
45*44f6b6a5SCristian Ciocaltea int irq;
46*44f6b6a5SCristian Ciocaltea };
47*44f6b6a5SCristian Ciocaltea
48*44f6b6a5SCristian Ciocaltea static const struct atc260x_onkey_params atc2603c_onkey_params = {
49*44f6b6a5SCristian Ciocaltea .reg_int_ctl = ATC2603C_PMU_SYS_CTL2,
50*44f6b6a5SCristian Ciocaltea .long_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_LONG_PRESS,
51*44f6b6a5SCristian Ciocaltea .short_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_SHORT_PRESS,
52*44f6b6a5SCristian Ciocaltea .kdwn_int_pnd_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_PD,
53*44f6b6a5SCristian Ciocaltea .press_int_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_INT_EN,
54*44f6b6a5SCristian Ciocaltea .kdwn_int_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN,
55*44f6b6a5SCristian Ciocaltea .kdwn_state_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS,
56*44f6b6a5SCristian Ciocaltea .press_time_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
57*44f6b6a5SCristian Ciocaltea .reset_en_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_RESET_EN,
58*44f6b6a5SCristian Ciocaltea .reset_time_bm = ATC2603C_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
59*44f6b6a5SCristian Ciocaltea };
60*44f6b6a5SCristian Ciocaltea
61*44f6b6a5SCristian Ciocaltea static const struct atc260x_onkey_params atc2609a_onkey_params = {
62*44f6b6a5SCristian Ciocaltea .reg_int_ctl = ATC2609A_PMU_SYS_CTL2,
63*44f6b6a5SCristian Ciocaltea .long_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_LONG_PRESS,
64*44f6b6a5SCristian Ciocaltea .short_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_SHORT_PRESS,
65*44f6b6a5SCristian Ciocaltea .kdwn_int_pnd_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_PD,
66*44f6b6a5SCristian Ciocaltea .press_int_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_LSP_INT_EN,
67*44f6b6a5SCristian Ciocaltea .kdwn_int_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN,
68*44f6b6a5SCristian Ciocaltea .kdwn_state_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS,
69*44f6b6a5SCristian Ciocaltea .press_time_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
70*44f6b6a5SCristian Ciocaltea .reset_en_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_EN,
71*44f6b6a5SCristian Ciocaltea .reset_time_bm = ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
72*44f6b6a5SCristian Ciocaltea };
73*44f6b6a5SCristian Ciocaltea
atc2603x_onkey_hw_init(struct atc260x_onkey * onkey,enum atc260x_onkey_reset_status reset_status,u32 reset_time,u32 press_time)74*44f6b6a5SCristian Ciocaltea static int atc2603x_onkey_hw_init(struct atc260x_onkey *onkey,
75*44f6b6a5SCristian Ciocaltea enum atc260x_onkey_reset_status reset_status,
76*44f6b6a5SCristian Ciocaltea u32 reset_time, u32 press_time)
77*44f6b6a5SCristian Ciocaltea {
78*44f6b6a5SCristian Ciocaltea u32 reg_bm, reg_val;
79*44f6b6a5SCristian Ciocaltea
80*44f6b6a5SCristian Ciocaltea reg_bm = onkey->params->long_int_pnd_bm |
81*44f6b6a5SCristian Ciocaltea onkey->params->short_int_pnd_bm |
82*44f6b6a5SCristian Ciocaltea onkey->params->kdwn_int_pnd_bm |
83*44f6b6a5SCristian Ciocaltea onkey->params->press_int_en_bm |
84*44f6b6a5SCristian Ciocaltea onkey->params->kdwn_int_en_bm;
85*44f6b6a5SCristian Ciocaltea
86*44f6b6a5SCristian Ciocaltea reg_val = reg_bm | press_time;
87*44f6b6a5SCristian Ciocaltea reg_bm |= onkey->params->press_time_bm;
88*44f6b6a5SCristian Ciocaltea
89*44f6b6a5SCristian Ciocaltea if (reset_status == KEY_RESET_DISABLED) {
90*44f6b6a5SCristian Ciocaltea reg_bm |= onkey->params->reset_en_bm;
91*44f6b6a5SCristian Ciocaltea } else if (reset_status == KEY_RESET_USER_SEL) {
92*44f6b6a5SCristian Ciocaltea reg_bm |= onkey->params->reset_en_bm |
93*44f6b6a5SCristian Ciocaltea onkey->params->reset_time_bm;
94*44f6b6a5SCristian Ciocaltea reg_val |= onkey->params->reset_en_bm | reset_time;
95*44f6b6a5SCristian Ciocaltea }
96*44f6b6a5SCristian Ciocaltea
97*44f6b6a5SCristian Ciocaltea return regmap_update_bits(onkey->atc260x->regmap,
98*44f6b6a5SCristian Ciocaltea onkey->params->reg_int_ctl, reg_bm, reg_val);
99*44f6b6a5SCristian Ciocaltea }
100*44f6b6a5SCristian Ciocaltea
atc260x_onkey_query(struct atc260x_onkey * onkey)101*44f6b6a5SCristian Ciocaltea static void atc260x_onkey_query(struct atc260x_onkey *onkey)
102*44f6b6a5SCristian Ciocaltea {
103*44f6b6a5SCristian Ciocaltea u32 reg_bits;
104*44f6b6a5SCristian Ciocaltea int ret, key_down;
105*44f6b6a5SCristian Ciocaltea
106*44f6b6a5SCristian Ciocaltea ret = regmap_read(onkey->atc260x->regmap,
107*44f6b6a5SCristian Ciocaltea onkey->params->reg_int_ctl, &key_down);
108*44f6b6a5SCristian Ciocaltea if (ret) {
109*44f6b6a5SCristian Ciocaltea key_down = 1;
110*44f6b6a5SCristian Ciocaltea dev_err(onkey->atc260x->dev,
111*44f6b6a5SCristian Ciocaltea "Failed to read onkey status: %d\n", ret);
112*44f6b6a5SCristian Ciocaltea } else {
113*44f6b6a5SCristian Ciocaltea key_down &= onkey->params->kdwn_state_bm;
114*44f6b6a5SCristian Ciocaltea }
115*44f6b6a5SCristian Ciocaltea
116*44f6b6a5SCristian Ciocaltea /*
117*44f6b6a5SCristian Ciocaltea * The hardware generates interrupt only when the onkey pin is
118*44f6b6a5SCristian Ciocaltea * asserted. Hence, the deassertion of the pin is simulated through
119*44f6b6a5SCristian Ciocaltea * work queue.
120*44f6b6a5SCristian Ciocaltea */
121*44f6b6a5SCristian Ciocaltea if (key_down) {
122*44f6b6a5SCristian Ciocaltea schedule_delayed_work(&onkey->work, msecs_to_jiffies(200));
123*44f6b6a5SCristian Ciocaltea return;
124*44f6b6a5SCristian Ciocaltea }
125*44f6b6a5SCristian Ciocaltea
126*44f6b6a5SCristian Ciocaltea /*
127*44f6b6a5SCristian Ciocaltea * The key-down status bit is cleared when the On/Off button
128*44f6b6a5SCristian Ciocaltea * is released.
129*44f6b6a5SCristian Ciocaltea */
130*44f6b6a5SCristian Ciocaltea input_report_key(onkey->input_dev, KEY_POWER, 0);
131*44f6b6a5SCristian Ciocaltea input_sync(onkey->input_dev);
132*44f6b6a5SCristian Ciocaltea
133*44f6b6a5SCristian Ciocaltea reg_bits = onkey->params->long_int_pnd_bm |
134*44f6b6a5SCristian Ciocaltea onkey->params->short_int_pnd_bm |
135*44f6b6a5SCristian Ciocaltea onkey->params->kdwn_int_pnd_bm |
136*44f6b6a5SCristian Ciocaltea onkey->params->press_int_en_bm |
137*44f6b6a5SCristian Ciocaltea onkey->params->kdwn_int_en_bm;
138*44f6b6a5SCristian Ciocaltea
139*44f6b6a5SCristian Ciocaltea /* Clear key press pending events and enable key press interrupts. */
140*44f6b6a5SCristian Ciocaltea regmap_update_bits(onkey->atc260x->regmap, onkey->params->reg_int_ctl,
141*44f6b6a5SCristian Ciocaltea reg_bits, reg_bits);
142*44f6b6a5SCristian Ciocaltea }
143*44f6b6a5SCristian Ciocaltea
atc260x_onkey_work(struct work_struct * work)144*44f6b6a5SCristian Ciocaltea static void atc260x_onkey_work(struct work_struct *work)
145*44f6b6a5SCristian Ciocaltea {
146*44f6b6a5SCristian Ciocaltea struct atc260x_onkey *onkey = container_of(work, struct atc260x_onkey,
147*44f6b6a5SCristian Ciocaltea work.work);
148*44f6b6a5SCristian Ciocaltea atc260x_onkey_query(onkey);
149*44f6b6a5SCristian Ciocaltea }
150*44f6b6a5SCristian Ciocaltea
atc260x_onkey_irq(int irq,void * data)151*44f6b6a5SCristian Ciocaltea static irqreturn_t atc260x_onkey_irq(int irq, void *data)
152*44f6b6a5SCristian Ciocaltea {
153*44f6b6a5SCristian Ciocaltea struct atc260x_onkey *onkey = data;
154*44f6b6a5SCristian Ciocaltea int ret;
155*44f6b6a5SCristian Ciocaltea
156*44f6b6a5SCristian Ciocaltea /* Disable key press interrupts. */
157*44f6b6a5SCristian Ciocaltea ret = regmap_update_bits(onkey->atc260x->regmap,
158*44f6b6a5SCristian Ciocaltea onkey->params->reg_int_ctl,
159*44f6b6a5SCristian Ciocaltea onkey->params->press_int_en_bm |
160*44f6b6a5SCristian Ciocaltea onkey->params->kdwn_int_en_bm, 0);
161*44f6b6a5SCristian Ciocaltea if (ret)
162*44f6b6a5SCristian Ciocaltea dev_err(onkey->atc260x->dev,
163*44f6b6a5SCristian Ciocaltea "Failed to disable interrupts: %d\n", ret);
164*44f6b6a5SCristian Ciocaltea
165*44f6b6a5SCristian Ciocaltea input_report_key(onkey->input_dev, KEY_POWER, 1);
166*44f6b6a5SCristian Ciocaltea input_sync(onkey->input_dev);
167*44f6b6a5SCristian Ciocaltea
168*44f6b6a5SCristian Ciocaltea atc260x_onkey_query(onkey);
169*44f6b6a5SCristian Ciocaltea
170*44f6b6a5SCristian Ciocaltea return IRQ_HANDLED;
171*44f6b6a5SCristian Ciocaltea }
172*44f6b6a5SCristian Ciocaltea
atc260x_onkey_open(struct input_dev * dev)173*44f6b6a5SCristian Ciocaltea static int atc260x_onkey_open(struct input_dev *dev)
174*44f6b6a5SCristian Ciocaltea {
175*44f6b6a5SCristian Ciocaltea struct atc260x_onkey *onkey = input_get_drvdata(dev);
176*44f6b6a5SCristian Ciocaltea
177*44f6b6a5SCristian Ciocaltea enable_irq(onkey->irq);
178*44f6b6a5SCristian Ciocaltea
179*44f6b6a5SCristian Ciocaltea return 0;
180*44f6b6a5SCristian Ciocaltea }
181*44f6b6a5SCristian Ciocaltea
atc260x_onkey_close(struct input_dev * dev)182*44f6b6a5SCristian Ciocaltea static void atc260x_onkey_close(struct input_dev *dev)
183*44f6b6a5SCristian Ciocaltea {
184*44f6b6a5SCristian Ciocaltea struct atc260x_onkey *onkey = input_get_drvdata(dev);
185*44f6b6a5SCristian Ciocaltea
186*44f6b6a5SCristian Ciocaltea disable_irq(onkey->irq);
187*44f6b6a5SCristian Ciocaltea cancel_delayed_work_sync(&onkey->work);
188*44f6b6a5SCristian Ciocaltea }
189*44f6b6a5SCristian Ciocaltea
atc260x_onkey_probe(struct platform_device * pdev)190*44f6b6a5SCristian Ciocaltea static int atc260x_onkey_probe(struct platform_device *pdev)
191*44f6b6a5SCristian Ciocaltea {
192*44f6b6a5SCristian Ciocaltea struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent);
193*44f6b6a5SCristian Ciocaltea struct atc260x_onkey *onkey;
194*44f6b6a5SCristian Ciocaltea struct input_dev *input_dev;
195*44f6b6a5SCristian Ciocaltea enum atc260x_onkey_reset_status reset_status;
196*44f6b6a5SCristian Ciocaltea u32 press_time = KEY_PRESS_TIME_SEC, reset_time = 0;
197*44f6b6a5SCristian Ciocaltea int val, error;
198*44f6b6a5SCristian Ciocaltea
199*44f6b6a5SCristian Ciocaltea onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
200*44f6b6a5SCristian Ciocaltea if (!onkey)
201*44f6b6a5SCristian Ciocaltea return -ENOMEM;
202*44f6b6a5SCristian Ciocaltea
203*44f6b6a5SCristian Ciocaltea error = device_property_read_u32(pdev->dev.parent,
204*44f6b6a5SCristian Ciocaltea "reset-time-sec", &val);
205*44f6b6a5SCristian Ciocaltea if (error) {
206*44f6b6a5SCristian Ciocaltea reset_status = KEY_RESET_HW_DEFAULT;
207*44f6b6a5SCristian Ciocaltea } else if (val) {
208*44f6b6a5SCristian Ciocaltea if (val < 6 || val > 12) {
209*44f6b6a5SCristian Ciocaltea dev_err(&pdev->dev, "reset-time-sec out of range\n");
210*44f6b6a5SCristian Ciocaltea return -EINVAL;
211*44f6b6a5SCristian Ciocaltea }
212*44f6b6a5SCristian Ciocaltea
213*44f6b6a5SCristian Ciocaltea reset_status = KEY_RESET_USER_SEL;
214*44f6b6a5SCristian Ciocaltea reset_time = (val - 6) / 2;
215*44f6b6a5SCristian Ciocaltea } else {
216*44f6b6a5SCristian Ciocaltea reset_status = KEY_RESET_DISABLED;
217*44f6b6a5SCristian Ciocaltea dev_dbg(&pdev->dev, "Disabled reset on long-press\n");
218*44f6b6a5SCristian Ciocaltea }
219*44f6b6a5SCristian Ciocaltea
220*44f6b6a5SCristian Ciocaltea switch (atc260x->ic_type) {
221*44f6b6a5SCristian Ciocaltea case ATC2603C:
222*44f6b6a5SCristian Ciocaltea onkey->params = &atc2603c_onkey_params;
223*44f6b6a5SCristian Ciocaltea press_time = FIELD_PREP(ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
224*44f6b6a5SCristian Ciocaltea press_time);
225*44f6b6a5SCristian Ciocaltea reset_time = FIELD_PREP(ATC2603C_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
226*44f6b6a5SCristian Ciocaltea reset_time);
227*44f6b6a5SCristian Ciocaltea break;
228*44f6b6a5SCristian Ciocaltea case ATC2609A:
229*44f6b6a5SCristian Ciocaltea onkey->params = &atc2609a_onkey_params;
230*44f6b6a5SCristian Ciocaltea press_time = FIELD_PREP(ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_TIME,
231*44f6b6a5SCristian Ciocaltea press_time);
232*44f6b6a5SCristian Ciocaltea reset_time = FIELD_PREP(ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL,
233*44f6b6a5SCristian Ciocaltea reset_time);
234*44f6b6a5SCristian Ciocaltea break;
235*44f6b6a5SCristian Ciocaltea default:
236*44f6b6a5SCristian Ciocaltea dev_err(&pdev->dev,
237*44f6b6a5SCristian Ciocaltea "OnKey not supported for ATC260x PMIC type: %u\n",
238*44f6b6a5SCristian Ciocaltea atc260x->ic_type);
239*44f6b6a5SCristian Ciocaltea return -EINVAL;
240*44f6b6a5SCristian Ciocaltea }
241*44f6b6a5SCristian Ciocaltea
242*44f6b6a5SCristian Ciocaltea input_dev = devm_input_allocate_device(&pdev->dev);
243*44f6b6a5SCristian Ciocaltea if (!input_dev) {
244*44f6b6a5SCristian Ciocaltea dev_err(&pdev->dev, "Failed to allocate input device\n");
245*44f6b6a5SCristian Ciocaltea return -ENOMEM;
246*44f6b6a5SCristian Ciocaltea }
247*44f6b6a5SCristian Ciocaltea
248*44f6b6a5SCristian Ciocaltea onkey->input_dev = input_dev;
249*44f6b6a5SCristian Ciocaltea onkey->atc260x = atc260x;
250*44f6b6a5SCristian Ciocaltea
251*44f6b6a5SCristian Ciocaltea input_dev->name = "atc260x-onkey";
252*44f6b6a5SCristian Ciocaltea input_dev->phys = "atc260x-onkey/input0";
253*44f6b6a5SCristian Ciocaltea input_dev->open = atc260x_onkey_open;
254*44f6b6a5SCristian Ciocaltea input_dev->close = atc260x_onkey_close;
255*44f6b6a5SCristian Ciocaltea
256*44f6b6a5SCristian Ciocaltea input_set_capability(input_dev, EV_KEY, KEY_POWER);
257*44f6b6a5SCristian Ciocaltea input_set_drvdata(input_dev, onkey);
258*44f6b6a5SCristian Ciocaltea
259*44f6b6a5SCristian Ciocaltea INIT_DELAYED_WORK(&onkey->work, atc260x_onkey_work);
260*44f6b6a5SCristian Ciocaltea
261*44f6b6a5SCristian Ciocaltea onkey->irq = platform_get_irq(pdev, 0);
262*44f6b6a5SCristian Ciocaltea if (onkey->irq < 0)
263*44f6b6a5SCristian Ciocaltea return onkey->irq;
264*44f6b6a5SCristian Ciocaltea
265*44f6b6a5SCristian Ciocaltea error = devm_request_threaded_irq(&pdev->dev, onkey->irq, NULL,
266*44f6b6a5SCristian Ciocaltea atc260x_onkey_irq, IRQF_ONESHOT,
267*44f6b6a5SCristian Ciocaltea dev_name(&pdev->dev), onkey);
268*44f6b6a5SCristian Ciocaltea if (error) {
269*44f6b6a5SCristian Ciocaltea dev_err(&pdev->dev,
270*44f6b6a5SCristian Ciocaltea "Failed to register IRQ %d: %d\n", onkey->irq, error);
271*44f6b6a5SCristian Ciocaltea return error;
272*44f6b6a5SCristian Ciocaltea }
273*44f6b6a5SCristian Ciocaltea
274*44f6b6a5SCristian Ciocaltea /* Keep IRQ disabled until atc260x_onkey_open() is called. */
275*44f6b6a5SCristian Ciocaltea disable_irq(onkey->irq);
276*44f6b6a5SCristian Ciocaltea
277*44f6b6a5SCristian Ciocaltea error = input_register_device(input_dev);
278*44f6b6a5SCristian Ciocaltea if (error) {
279*44f6b6a5SCristian Ciocaltea dev_err(&pdev->dev,
280*44f6b6a5SCristian Ciocaltea "Failed to register input device: %d\n", error);
281*44f6b6a5SCristian Ciocaltea return error;
282*44f6b6a5SCristian Ciocaltea }
283*44f6b6a5SCristian Ciocaltea
284*44f6b6a5SCristian Ciocaltea error = atc2603x_onkey_hw_init(onkey, reset_status,
285*44f6b6a5SCristian Ciocaltea reset_time, press_time);
286*44f6b6a5SCristian Ciocaltea if (error)
287*44f6b6a5SCristian Ciocaltea return error;
288*44f6b6a5SCristian Ciocaltea
289*44f6b6a5SCristian Ciocaltea device_init_wakeup(&pdev->dev, true);
290*44f6b6a5SCristian Ciocaltea
291*44f6b6a5SCristian Ciocaltea return 0;
292*44f6b6a5SCristian Ciocaltea }
293*44f6b6a5SCristian Ciocaltea
294*44f6b6a5SCristian Ciocaltea static struct platform_driver atc260x_onkey_driver = {
295*44f6b6a5SCristian Ciocaltea .probe = atc260x_onkey_probe,
296*44f6b6a5SCristian Ciocaltea .driver = {
297*44f6b6a5SCristian Ciocaltea .name = "atc260x-onkey",
298*44f6b6a5SCristian Ciocaltea },
299*44f6b6a5SCristian Ciocaltea };
300*44f6b6a5SCristian Ciocaltea
301*44f6b6a5SCristian Ciocaltea module_platform_driver(atc260x_onkey_driver);
302*44f6b6a5SCristian Ciocaltea
303*44f6b6a5SCristian Ciocaltea MODULE_DESCRIPTION("Onkey driver for ATC260x PMICs");
304*44f6b6a5SCristian Ciocaltea MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
305*44f6b6a5SCristian Ciocaltea MODULE_LICENSE("GPL");
306