1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #include <linux/clk.h>
4*4882a593Smuzhiyun #include <linux/io.h>
5*4882a593Smuzhiyun #include <linux/irq.h>
6*4882a593Smuzhiyun #include <linux/irqdesc.h>
7*4882a593Smuzhiyun #include <linux/irqdomain.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/input.h>
16*4882a593Smuzhiyun #include <linux/workqueue.h>
17*4882a593Smuzhiyun #include <linux/wakelock.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/rockchip/rockchip_sip.h>
20*4882a593Smuzhiyun #include "rockchip_pwm_remotectl.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun * sys/module/rk_pwm_remotectl/parameters,
26*4882a593Smuzhiyun * modify code_print to change the value
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun static int rk_remote_print_code;
30*4882a593Smuzhiyun module_param_named(code_print, rk_remote_print_code, int, 0644);
31*4882a593Smuzhiyun #define DBG_CODE(args...) \
32*4882a593Smuzhiyun do { \
33*4882a593Smuzhiyun if (rk_remote_print_code) { \
34*4882a593Smuzhiyun pr_info(args); \
35*4882a593Smuzhiyun } \
36*4882a593Smuzhiyun } while (0)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun static int rk_remote_pwm_dbg_level;
39*4882a593Smuzhiyun module_param_named(dbg_level, rk_remote_pwm_dbg_level, int, 0644);
40*4882a593Smuzhiyun #define DBG(args...) \
41*4882a593Smuzhiyun do { \
42*4882a593Smuzhiyun if (rk_remote_pwm_dbg_level) { \
43*4882a593Smuzhiyun pr_info(args); \
44*4882a593Smuzhiyun } \
45*4882a593Smuzhiyun } while (0)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun struct rkxx_remote_key_table {
49*4882a593Smuzhiyun int scancode;
50*4882a593Smuzhiyun int keycode;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun struct rkxx_remotectl_button {
54*4882a593Smuzhiyun int usercode;
55*4882a593Smuzhiyun int nbuttons;
56*4882a593Smuzhiyun struct rkxx_remote_key_table key_table[MAX_NUM_KEYS];
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun struct rkxx_remotectl_drvdata {
60*4882a593Smuzhiyun void __iomem *base;
61*4882a593Smuzhiyun int state;
62*4882a593Smuzhiyun int nbuttons;
63*4882a593Smuzhiyun int scandata;
64*4882a593Smuzhiyun int count;
65*4882a593Smuzhiyun int keynum;
66*4882a593Smuzhiyun int maxkeybdnum;
67*4882a593Smuzhiyun int keycode;
68*4882a593Smuzhiyun int press;
69*4882a593Smuzhiyun int pre_press;
70*4882a593Smuzhiyun int irq;
71*4882a593Smuzhiyun int remote_pwm_id;
72*4882a593Smuzhiyun int handle_cpu_id;
73*4882a593Smuzhiyun int wakeup;
74*4882a593Smuzhiyun int support_psci;
75*4882a593Smuzhiyun int pwm_pwrkey_capture;
76*4882a593Smuzhiyun unsigned long period;
77*4882a593Smuzhiyun unsigned long temp_period;
78*4882a593Smuzhiyun int pwm_freq_nstime;
79*4882a593Smuzhiyun int pwrkey_wakeup;
80*4882a593Smuzhiyun struct input_dev *input;
81*4882a593Smuzhiyun struct timer_list timer;
82*4882a593Smuzhiyun struct tasklet_struct remote_tasklet;
83*4882a593Smuzhiyun struct wake_lock remotectl_wake_lock;
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun static struct rkxx_remotectl_button *remotectl_button;
87*4882a593Smuzhiyun
remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata * ddata)88*4882a593Smuzhiyun static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun int i;
91*4882a593Smuzhiyun int num;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun num = ddata->maxkeybdnum;
94*4882a593Smuzhiyun for (i = 0; i < num; i++) {
95*4882a593Smuzhiyun if (remotectl_button[i].usercode == (ddata->scandata&0xFFFF)) {
96*4882a593Smuzhiyun ddata->keynum = i;
97*4882a593Smuzhiyun return 1;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun return 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun
remotectl_keycode_lookup(struct rkxx_remotectl_drvdata * ddata)104*4882a593Smuzhiyun static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun int i;
107*4882a593Smuzhiyun unsigned char keydata = (unsigned char)((ddata->scandata >> 8) & 0xff);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun for (i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++) {
110*4882a593Smuzhiyun if (remotectl_button[ddata->keynum].key_table[i].scancode ==
111*4882a593Smuzhiyun keydata) {
112*4882a593Smuzhiyun ddata->keycode =
113*4882a593Smuzhiyun remotectl_button[ddata->keynum].key_table[i].keycode;
114*4882a593Smuzhiyun return 1;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
rk_remotectl_get_irkeybd_count(struct platform_device * pdev)120*4882a593Smuzhiyun static int rk_remotectl_get_irkeybd_count(struct platform_device *pdev)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun struct device_node *node = pdev->dev.of_node;
123*4882a593Smuzhiyun struct device_node *child_node;
124*4882a593Smuzhiyun int boardnum;
125*4882a593Smuzhiyun int temp_usercode;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun boardnum = 0;
128*4882a593Smuzhiyun for_each_child_of_node(node, child_node) {
129*4882a593Smuzhiyun if (of_property_read_u32(child_node, "rockchip,usercode",
130*4882a593Smuzhiyun &temp_usercode)) {
131*4882a593Smuzhiyun DBG("get keybd num error.\n");
132*4882a593Smuzhiyun } else {
133*4882a593Smuzhiyun boardnum++;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun DBG("get keybd num = 0x%x.\n", boardnum);
137*4882a593Smuzhiyun return boardnum;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun
rk_remotectl_parse_ir_keys(struct platform_device * pdev)141*4882a593Smuzhiyun static int rk_remotectl_parse_ir_keys(struct platform_device *pdev)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);
144*4882a593Smuzhiyun struct device_node *node = pdev->dev.of_node;
145*4882a593Smuzhiyun struct device_node *child_node;
146*4882a593Smuzhiyun int loop;
147*4882a593Smuzhiyun int ret;
148*4882a593Smuzhiyun int len;
149*4882a593Smuzhiyun int boardnum;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun boardnum = 0;
152*4882a593Smuzhiyun for_each_child_of_node(node, child_node) {
153*4882a593Smuzhiyun if (of_property_read_u32(child_node, "rockchip,usercode",
154*4882a593Smuzhiyun &remotectl_button[boardnum].usercode)) {
155*4882a593Smuzhiyun dev_err(&pdev->dev, "Missing usercode in the DTS.\n");
156*4882a593Smuzhiyun ret = -1;
157*4882a593Smuzhiyun return ret;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun DBG("remotectl_button[0].usercode=0x%x\n",
160*4882a593Smuzhiyun remotectl_button[boardnum].usercode);
161*4882a593Smuzhiyun of_get_property(child_node, "rockchip,key_table", &len);
162*4882a593Smuzhiyun len /= sizeof(u32);
163*4882a593Smuzhiyun DBG("len=0x%x\n", len);
164*4882a593Smuzhiyun remotectl_button[boardnum].nbuttons = len/2;
165*4882a593Smuzhiyun if (of_property_read_u32_array(child_node, "rockchip,key_table",
166*4882a593Smuzhiyun (u32 *)remotectl_button[boardnum].key_table, len)) {
167*4882a593Smuzhiyun dev_err(&pdev->dev, "Missing key_table in the DTS.\n");
168*4882a593Smuzhiyun ret = -1;
169*4882a593Smuzhiyun return ret;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun for (loop = 0; loop < (len/2); loop++) {
172*4882a593Smuzhiyun DBG("board[%d].scanCode[%d]=0x%x\n", boardnum, loop,
173*4882a593Smuzhiyun remotectl_button[boardnum].key_table[loop].scancode);
174*4882a593Smuzhiyun DBG("board[%d].keyCode[%d]=%d\n", boardnum, loop,
175*4882a593Smuzhiyun remotectl_button[boardnum].key_table[loop].keycode);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun boardnum++;
178*4882a593Smuzhiyun if (boardnum > ddata->maxkeybdnum)
179*4882a593Smuzhiyun break;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun DBG("keybdNum=0x%x\n", boardnum);
182*4882a593Smuzhiyun return 0;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun
rk_pwm_remotectl_do_something(unsigned long data)187*4882a593Smuzhiyun static void rk_pwm_remotectl_do_something(unsigned long data)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun ddata = (struct rkxx_remotectl_drvdata *)data;
192*4882a593Smuzhiyun switch (ddata->state) {
193*4882a593Smuzhiyun case RMC_IDLE: {
194*4882a593Smuzhiyun ;
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun case RMC_PRELOAD: {
198*4882a593Smuzhiyun mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(140));
199*4882a593Smuzhiyun if ((ddata->period > RK_PWM_TIME_PRE_MIN) &&
200*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_PRE_MAX)) {
201*4882a593Smuzhiyun ddata->scandata = 0;
202*4882a593Smuzhiyun ddata->count = 0;
203*4882a593Smuzhiyun ddata->state = RMC_USERCODE;
204*4882a593Smuzhiyun } else {
205*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun break;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun case RMC_USERCODE: {
210*4882a593Smuzhiyun if ((ddata->period > RK_PWM_TIME_BIT1_MIN) &&
211*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_BIT1_MAX))
212*4882a593Smuzhiyun ddata->scandata |= (0x01 << ddata->count);
213*4882a593Smuzhiyun ddata->count++;
214*4882a593Smuzhiyun if (ddata->count == 0x10) {
215*4882a593Smuzhiyun DBG_CODE("USERCODE=0x%x\n", ddata->scandata);
216*4882a593Smuzhiyun if (remotectl_keybd_num_lookup(ddata)) {
217*4882a593Smuzhiyun ddata->state = RMC_GETDATA;
218*4882a593Smuzhiyun ddata->scandata = 0;
219*4882a593Smuzhiyun ddata->count = 0;
220*4882a593Smuzhiyun } else {
221*4882a593Smuzhiyun if (rk_remote_print_code) {
222*4882a593Smuzhiyun ddata->state = RMC_GETDATA;
223*4882a593Smuzhiyun ddata->scandata = 0;
224*4882a593Smuzhiyun ddata->count = 0;
225*4882a593Smuzhiyun } else
226*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun case RMC_GETDATA: {
232*4882a593Smuzhiyun if ((ddata->period > RK_PWM_TIME_BIT1_MIN) &&
233*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_BIT1_MAX))
234*4882a593Smuzhiyun ddata->scandata |= (0x01<<ddata->count);
235*4882a593Smuzhiyun ddata->count++;
236*4882a593Smuzhiyun if (ddata->count < 0x10)
237*4882a593Smuzhiyun return;
238*4882a593Smuzhiyun DBG_CODE("RMC_GETDATA=%x\n", (ddata->scandata>>8));
239*4882a593Smuzhiyun if ((ddata->scandata&0x0ff) ==
240*4882a593Smuzhiyun ((~ddata->scandata >> 8) & 0x0ff)) {
241*4882a593Smuzhiyun if (remotectl_keycode_lookup(ddata)) {
242*4882a593Smuzhiyun ddata->press = 1;
243*4882a593Smuzhiyun input_event(ddata->input, EV_KEY,
244*4882a593Smuzhiyun ddata->keycode, 1);
245*4882a593Smuzhiyun input_sync(ddata->input);
246*4882a593Smuzhiyun ddata->state = RMC_SEQUENCE;
247*4882a593Smuzhiyun } else {
248*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun } else {
251*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun break;
255*4882a593Smuzhiyun case RMC_SEQUENCE:{
256*4882a593Smuzhiyun DBG("S=%ld\n", ddata->period);
257*4882a593Smuzhiyun if ((ddata->period > RK_PWM_TIME_RPT_MIN) &&
258*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_RPT_MAX)) {
259*4882a593Smuzhiyun DBG("S1\n");
260*4882a593Smuzhiyun mod_timer(&ddata->timer, jiffies
261*4882a593Smuzhiyun + msecs_to_jiffies(130));
262*4882a593Smuzhiyun } else if ((ddata->period > RK_PWM_TIME_SEQ1_MIN) &&
263*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_SEQ1_MAX)) {
264*4882a593Smuzhiyun DBG("S2\n");
265*4882a593Smuzhiyun mod_timer(&ddata->timer, jiffies
266*4882a593Smuzhiyun + msecs_to_jiffies(130));
267*4882a593Smuzhiyun } else if ((ddata->period > RK_PWM_TIME_SEQ2_MIN) &&
268*4882a593Smuzhiyun (ddata->period < RK_PWM_TIME_SEQ2_MAX)) {
269*4882a593Smuzhiyun DBG("S3\n");
270*4882a593Smuzhiyun mod_timer(&ddata->timer, jiffies
271*4882a593Smuzhiyun + msecs_to_jiffies(130));
272*4882a593Smuzhiyun } else {
273*4882a593Smuzhiyun DBG("S4\n");
274*4882a593Smuzhiyun input_event(ddata->input, EV_KEY,
275*4882a593Smuzhiyun ddata->keycode, 0);
276*4882a593Smuzhiyun input_sync(ddata->input);
277*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
278*4882a593Smuzhiyun ddata->press = 0;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun break;
282*4882a593Smuzhiyun default:
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
rk_pwm_remotectl_timer(struct timer_list * t)287*4882a593Smuzhiyun static void rk_pwm_remotectl_timer(struct timer_list *t)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = from_timer(ddata, t, timer);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (ddata->press != ddata->pre_press) {
292*4882a593Smuzhiyun ddata->pre_press = 0;
293*4882a593Smuzhiyun ddata->press = 0;
294*4882a593Smuzhiyun input_event(ddata->input, EV_KEY, ddata->keycode, 0);
295*4882a593Smuzhiyun input_sync(ddata->input);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
rockchip_pwm_pwrirq(int irq,void * dev_id)300*4882a593Smuzhiyun static irqreturn_t rockchip_pwm_pwrirq(int irq, void *dev_id)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = dev_id;
303*4882a593Smuzhiyun int val;
304*4882a593Smuzhiyun unsigned int id = ddata->remote_pwm_id;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun if (id > 3)
307*4882a593Smuzhiyun return IRQ_NONE;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun val = readl_relaxed(ddata->base + PWM_REG_INTSTS(id));
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun if (val & PWM_PWR_KEY_INT) {
312*4882a593Smuzhiyun DBG("pwr=0x%x\n", readl_relaxed(ddata->base + PWM_PWRCAPTURE_VALUE(id)));
313*4882a593Smuzhiyun writel_relaxed(PWM_PWR_KEY_INT, ddata->base + PWM_REG_INTSTS(id));
314*4882a593Smuzhiyun ddata->pwrkey_wakeup = 1;
315*4882a593Smuzhiyun return IRQ_HANDLED;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun return IRQ_NONE;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
rockchip_pwm_irq(int irq,void * dev_id)321*4882a593Smuzhiyun static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = dev_id;
324*4882a593Smuzhiyun int val;
325*4882a593Smuzhiyun int temp_hpr;
326*4882a593Smuzhiyun int temp_lpr;
327*4882a593Smuzhiyun int temp_period;
328*4882a593Smuzhiyun unsigned int id = ddata->remote_pwm_id;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun if (id > 3)
331*4882a593Smuzhiyun return IRQ_NONE;
332*4882a593Smuzhiyun val = readl_relaxed(ddata->base + PWM_REG_INTSTS(id));
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if ((val & PWM_CH_INT(id)) == 0)
335*4882a593Smuzhiyun return IRQ_NONE;
336*4882a593Smuzhiyun if ((val & PWM_CH_POL(id)) == 0) {
337*4882a593Smuzhiyun temp_hpr = readl_relaxed(ddata->base + PWM_REG_HPR);
338*4882a593Smuzhiyun writel_relaxed(0, ddata->base + PWM_REG_HPR);
339*4882a593Smuzhiyun temp_lpr = readl_relaxed(ddata->base + PWM_REG_LPR);
340*4882a593Smuzhiyun writel_relaxed(0, ddata->base + PWM_REG_LPR);
341*4882a593Smuzhiyun DBG("hpr=%d\n", temp_hpr);
342*4882a593Smuzhiyun DBG("lpr=%d\n", temp_lpr);
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun temp_period = ddata->pwm_freq_nstime * temp_lpr / 1000;
345*4882a593Smuzhiyun if (temp_period > RK_PWM_TIME_BIT0_MIN) {
346*4882a593Smuzhiyun ddata->period = ddata->temp_period
347*4882a593Smuzhiyun + ddata->pwm_freq_nstime * temp_hpr / 1000;
348*4882a593Smuzhiyun tasklet_hi_schedule(&ddata->remote_tasklet);
349*4882a593Smuzhiyun ddata->temp_period = 0;
350*4882a593Smuzhiyun DBG("period+ =%ld\n", ddata->period);
351*4882a593Smuzhiyun } else {
352*4882a593Smuzhiyun ddata->temp_period += ddata->pwm_freq_nstime
353*4882a593Smuzhiyun * (temp_hpr + temp_lpr) / 1000;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun writel_relaxed(PWM_CH_INT(id), ddata->base + PWM_REG_INTSTS(id));
357*4882a593Smuzhiyun if (ddata->state == RMC_PRELOAD)
358*4882a593Smuzhiyun wake_lock_timeout(&ddata->remotectl_wake_lock, HZ);
359*4882a593Smuzhiyun return IRQ_HANDLED;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
rk_pwm_pwrkey_wakeup_init(struct platform_device * pdev)362*4882a593Smuzhiyun static int rk_pwm_pwrkey_wakeup_init(struct platform_device *pdev)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);
365*4882a593Smuzhiyun int val, min_temp, max_temp;
366*4882a593Smuzhiyun unsigned int pwm_id = ddata->remote_pwm_id;
367*4882a593Smuzhiyun int version;
368*4882a593Smuzhiyun int i, j;
369*4882a593Smuzhiyun int num = 0;
370*4882a593Smuzhiyun int ret = -1;
371*4882a593Smuzhiyun int pwr_irq;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun ddata->pwm_pwrkey_capture = 0;
374*4882a593Smuzhiyun version = readl_relaxed(ddata->base + RK_PWM_VERSION_ID(pwm_id));
375*4882a593Smuzhiyun dev_info(&pdev->dev, "pwm version is 0x%x\n", version & 0xffff0000);
376*4882a593Smuzhiyun if (((version >> 24) & 0xFF) < 2) {
377*4882a593Smuzhiyun dev_info(&pdev->dev, "pwm version is less v2.0\n");
378*4882a593Smuzhiyun goto end;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun pwr_irq = platform_get_irq(pdev, 1);
381*4882a593Smuzhiyun if (pwr_irq < 0) {
382*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot find PWR IRQ\n");
383*4882a593Smuzhiyun goto end;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun ret = devm_request_irq(&pdev->dev, pwr_irq, rockchip_pwm_pwrirq,
386*4882a593Smuzhiyun IRQF_NO_SUSPEND, "rk_pwm_pwr_irq", ddata);
387*4882a593Smuzhiyun if (ret) {
388*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot claim PWR_IRQ!!!\n");
389*4882a593Smuzhiyun goto end;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun val = readl_relaxed(ddata->base + PWM_REG_CTRL);
392*4882a593Smuzhiyun val = (val & 0xFFFFFFFE) | PWM_DISABLE;
393*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_CTRL);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun //preloader low min:8000us, max:10000us
396*4882a593Smuzhiyun min_temp = RK_PWM_TIME_PRE_MIN_LOW * 1000 / ddata->pwm_freq_nstime;
397*4882a593Smuzhiyun max_temp = RK_PWM_TIME_PRE_MAX_LOW * 1000 / ddata->pwm_freq_nstime;
398*4882a593Smuzhiyun val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff);
399*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_LPRE(pwm_id));
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun //preloader higt min:4000us, max:5000us
402*4882a593Smuzhiyun min_temp = RK_PWM_TIME_PRE_MIN * 1000 / ddata->pwm_freq_nstime;
403*4882a593Smuzhiyun max_temp = RK_PWM_TIME_PRE_MAX * 1000 / ddata->pwm_freq_nstime;
404*4882a593Smuzhiyun val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff);
405*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HPRE(pwm_id));
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun //logic 0/1 low min:480us, max 700us
408*4882a593Smuzhiyun min_temp = RK_PWM_TIME_BIT_MIN_LOW * 1000 / ddata->pwm_freq_nstime;
409*4882a593Smuzhiyun max_temp = RK_PWM_TIME_BIT_MAX_LOW * 1000 / ddata->pwm_freq_nstime;
410*4882a593Smuzhiyun val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff);
411*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_LD(pwm_id));
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun //logic 0 higt min:480us, max 700us
414*4882a593Smuzhiyun min_temp = RK_PWM_TIME_BIT0_MIN * 1000 / ddata->pwm_freq_nstime;
415*4882a593Smuzhiyun max_temp = RK_PWM_TIME_BIT0_MAX * 1000 / ddata->pwm_freq_nstime;
416*4882a593Smuzhiyun val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff);
417*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HD_ZERO(pwm_id));
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun //logic 1 higt min:1300us, max 2000us
420*4882a593Smuzhiyun min_temp = RK_PWM_TIME_BIT1_MIN * 1000 / ddata->pwm_freq_nstime;
421*4882a593Smuzhiyun max_temp = RK_PWM_TIME_BIT1_MAX * 1000 / ddata->pwm_freq_nstime;
422*4882a593Smuzhiyun val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff);
423*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HD_ONE(pwm_id));
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun for (j = 0; j < ddata->maxkeybdnum; j++) {
426*4882a593Smuzhiyun for (i = 0; i < remotectl_button[j].nbuttons; i++) {
427*4882a593Smuzhiyun int scancode, usercode, pwrkey;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun if (remotectl_button[j].key_table[i].keycode != KEY_POWER)
430*4882a593Smuzhiyun continue;
431*4882a593Smuzhiyun usercode = remotectl_button[j].usercode & 0xffff;
432*4882a593Smuzhiyun scancode = remotectl_button[j].key_table[i].scancode & 0xff;
433*4882a593Smuzhiyun DBG("usercode=%x, key=%x\n", usercode, scancode);
434*4882a593Smuzhiyun pwrkey = usercode;
435*4882a593Smuzhiyun pwrkey |= (scancode << 24) | ((~scancode & 0xff) << 16);
436*4882a593Smuzhiyun DBG("pwrkey = %x\n", pwrkey);
437*4882a593Smuzhiyun writel_relaxed(pwrkey, ddata->base
438*4882a593Smuzhiyun + PWM_PWRMATCH_VALUE(pwm_id) + num * 4);
439*4882a593Smuzhiyun num++;
440*4882a593Smuzhiyun if (num >= PWM_PWR_KEY_CAPURURE_MAX)
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun val = readl_relaxed(ddata->base + PWM_REG_INT_EN(pwm_id));
446*4882a593Smuzhiyun val = (val & 0xFFFFFF7F) | PWM_PWR_INT_ENABLE;
447*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_INT_EN(pwm_id));
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun val = CH3_PWRKEY_ENABLE;
450*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_CTRL(pwm_id));
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun val = readl_relaxed(ddata->base + PWM_REG_CTRL);
453*4882a593Smuzhiyun val = (val & 0xFFFFFFFE) | PWM_ENABLE;
454*4882a593Smuzhiyun writel_relaxed(val, ddata->base + PWM_REG_CTRL);
455*4882a593Smuzhiyun ddata->pwm_pwrkey_capture = 1;
456*4882a593Smuzhiyun end:
457*4882a593Smuzhiyun return ret;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
rk_pwm_int_ctrl(void __iomem * pwm_base,uint pwm_id,int ctrl)460*4882a593Smuzhiyun static void rk_pwm_int_ctrl(void __iomem *pwm_base, uint pwm_id, int ctrl)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun int val;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun if (pwm_id > 3)
465*4882a593Smuzhiyun return;
466*4882a593Smuzhiyun val = readl_relaxed(pwm_base + PWM_REG_INT_EN(pwm_id));
467*4882a593Smuzhiyun if (ctrl) {
468*4882a593Smuzhiyun val |= PWM_CH_INT_ENABLE(pwm_id);
469*4882a593Smuzhiyun DBG("pwm int enabled, value is 0x%x\n", val);
470*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_INT_EN(pwm_id));
471*4882a593Smuzhiyun } else {
472*4882a593Smuzhiyun val &= ~PWM_CH_INT_ENABLE(pwm_id);
473*4882a593Smuzhiyun DBG("pwm int disabled, value is 0x%x\n", val);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_INT_EN(pwm_id));
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
rk_pwm_remotectl_hw_init(void __iomem * pwm_base,uint pwm_id)478*4882a593Smuzhiyun static int rk_pwm_remotectl_hw_init(void __iomem *pwm_base, uint pwm_id)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun int val;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (pwm_id > 3)
483*4882a593Smuzhiyun return -1;
484*4882a593Smuzhiyun //1. disabled pwm
485*4882a593Smuzhiyun val = readl_relaxed(pwm_base + PWM_REG_CTRL);
486*4882a593Smuzhiyun val = (val & 0xFFFFFFFE) | PWM_DISABLE;
487*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_CTRL);
488*4882a593Smuzhiyun //2. capture mode
489*4882a593Smuzhiyun val = readl_relaxed(pwm_base + PWM_REG_CTRL);
490*4882a593Smuzhiyun val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE;
491*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_CTRL);
492*4882a593Smuzhiyun //set clk div, clk div to 64
493*4882a593Smuzhiyun val = readl_relaxed(pwm_base + PWM_REG_CTRL);
494*4882a593Smuzhiyun val = (val & 0xFF0001FF) | PWM_DIV64;
495*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_CTRL);
496*4882a593Smuzhiyun //4. enabled pwm int
497*4882a593Smuzhiyun rk_pwm_int_ctrl(pwm_base, pwm_id, PWM_INT_ENABLE);
498*4882a593Smuzhiyun //5. enabled pwm
499*4882a593Smuzhiyun val = readl_relaxed(pwm_base + PWM_REG_CTRL);
500*4882a593Smuzhiyun val = (val & 0xFFFFFFFE) | PWM_ENABLE;
501*4882a593Smuzhiyun writel_relaxed(val, pwm_base + PWM_REG_CTRL);
502*4882a593Smuzhiyun return 0;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
rk_pwm_sip_wakeup_init(struct platform_device * pdev)505*4882a593Smuzhiyun static int rk_pwm_sip_wakeup_init(struct platform_device *pdev)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);
508*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
509*4882a593Smuzhiyun struct irq_desc *desc;
510*4882a593Smuzhiyun int support_psci = 0;
511*4882a593Smuzhiyun int irq;
512*4882a593Smuzhiyun int hwirq;
513*4882a593Smuzhiyun int i, j;
514*4882a593Smuzhiyun int num;
515*4882a593Smuzhiyun int pwm_id;
516*4882a593Smuzhiyun int ret = -1;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun if (of_property_read_u32(np, "remote_support_psci", &support_psci)) {
519*4882a593Smuzhiyun dev_info(&pdev->dev, "PWM Missing psci property in the DT.\n");
520*4882a593Smuzhiyun goto end;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun DBG("support_psci=0x%x\n", support_psci);
523*4882a593Smuzhiyun if (!support_psci)
524*4882a593Smuzhiyun goto end;
525*4882a593Smuzhiyun irq = ddata->irq;
526*4882a593Smuzhiyun desc = irq_to_desc(irq);
527*4882a593Smuzhiyun if (!desc || !desc->irq_data.domain)
528*4882a593Smuzhiyun goto end;
529*4882a593Smuzhiyun hwirq = desc->irq_data.hwirq;
530*4882a593Smuzhiyun ret = sip_smc_remotectl_config(REMOTECTL_SET_IRQ, hwirq);
531*4882a593Smuzhiyun if (ret) {
532*4882a593Smuzhiyun dev_err(&pdev->dev, "set irq err, set support_psci to 0 !!\n");
533*4882a593Smuzhiyun /*
534*4882a593Smuzhiyun * if atf doesn't support, return probe success to abandon atf
535*4882a593Smuzhiyun * function and still use kernel pwm parse function
536*4882a593Smuzhiyun */
537*4882a593Smuzhiyun goto end;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun pwm_id = ddata->remote_pwm_id;
540*4882a593Smuzhiyun num = ddata->maxkeybdnum;
541*4882a593Smuzhiyun sip_smc_remotectl_config(REMOTECTL_SET_PWM_CH, pwm_id);
542*4882a593Smuzhiyun for (j = 0; j < num; j++) {
543*4882a593Smuzhiyun for (i = 0; i < remotectl_button[j].nbuttons; i++) {
544*4882a593Smuzhiyun int scancode, pwrkey;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun if (remotectl_button[j].key_table[i].keycode
547*4882a593Smuzhiyun != KEY_POWER)
548*4882a593Smuzhiyun continue;
549*4882a593Smuzhiyun scancode = remotectl_button[j].key_table[i].scancode;
550*4882a593Smuzhiyun DBG("usercode=%x, key=%x\n",
551*4882a593Smuzhiyun remotectl_button[j].usercode, scancode);
552*4882a593Smuzhiyun pwrkey = (remotectl_button[j].usercode & 0xffff) << 16;
553*4882a593Smuzhiyun pwrkey |= (scancode & 0xff) << 8;
554*4882a593Smuzhiyun DBG("deliver: key=%x\n", pwrkey);
555*4882a593Smuzhiyun sip_smc_remotectl_config(REMOTECTL_SET_PWRKEY,
556*4882a593Smuzhiyun pwrkey);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun sip_smc_remotectl_config(REMOTECTL_ENABLE, 1);
560*4882a593Smuzhiyun ddata->support_psci = support_psci;
561*4882a593Smuzhiyun DBG("rk pwm sip init end!\n");
562*4882a593Smuzhiyun return 0;
563*4882a593Smuzhiyun end:
564*4882a593Smuzhiyun dev_info(&pdev->dev, "pwm sip wakeup config error!!\n");
565*4882a593Smuzhiyun ddata->support_psci = 0;
566*4882a593Smuzhiyun return ret;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
rk_pwm_wakeup(struct input_dev * input)569*4882a593Smuzhiyun static inline void rk_pwm_wakeup(struct input_dev *input)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun input_event(input, EV_KEY, KEY_POWER, 1);
572*4882a593Smuzhiyun input_event(input, EV_KEY, KEY_POWER, 0);
573*4882a593Smuzhiyun input_sync(input);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
rk_pwm_probe(struct platform_device * pdev)576*4882a593Smuzhiyun static int rk_pwm_probe(struct platform_device *pdev)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata;
579*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
580*4882a593Smuzhiyun struct resource *r;
581*4882a593Smuzhiyun struct input_dev *input;
582*4882a593Smuzhiyun struct clk *clk;
583*4882a593Smuzhiyun struct clk *p_clk;
584*4882a593Smuzhiyun struct cpumask cpumask;
585*4882a593Smuzhiyun int num;
586*4882a593Smuzhiyun int irq;
587*4882a593Smuzhiyun int ret;
588*4882a593Smuzhiyun int i, j;
589*4882a593Smuzhiyun int cpu_id;
590*4882a593Smuzhiyun int pwm_id;
591*4882a593Smuzhiyun int pwm_freq;
592*4882a593Smuzhiyun int count;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun pr_err(".. rk pwm remotectl v2.0 init\n");
595*4882a593Smuzhiyun r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
596*4882a593Smuzhiyun if (!r) {
597*4882a593Smuzhiyun dev_err(&pdev->dev, "no memory resources defined\n");
598*4882a593Smuzhiyun return -ENODEV;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun ddata = devm_kzalloc(&pdev->dev, sizeof(struct rkxx_remotectl_drvdata),
601*4882a593Smuzhiyun GFP_KERNEL);
602*4882a593Smuzhiyun if (!ddata) {
603*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate memory\n");
604*4882a593Smuzhiyun return -ENOMEM;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun ddata->state = RMC_PRELOAD;
607*4882a593Smuzhiyun ddata->temp_period = 0;
608*4882a593Smuzhiyun ddata->base = devm_ioremap_resource(&pdev->dev, r);
609*4882a593Smuzhiyun if (IS_ERR(ddata->base))
610*4882a593Smuzhiyun return PTR_ERR(ddata->base);
611*4882a593Smuzhiyun count = of_property_count_strings(np, "clock-names");
612*4882a593Smuzhiyun if (count == 2) {
613*4882a593Smuzhiyun clk = devm_clk_get(&pdev->dev, "pwm");
614*4882a593Smuzhiyun p_clk = devm_clk_get(&pdev->dev, "pclk");
615*4882a593Smuzhiyun } else {
616*4882a593Smuzhiyun clk = devm_clk_get(&pdev->dev, NULL);
617*4882a593Smuzhiyun p_clk = clk;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun if (IS_ERR(clk)) {
620*4882a593Smuzhiyun ret = PTR_ERR(clk);
621*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
622*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
623*4882a593Smuzhiyun return ret;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun if (IS_ERR(p_clk)) {
626*4882a593Smuzhiyun ret = PTR_ERR(p_clk);
627*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
628*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
629*4882a593Smuzhiyun return ret;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun ret = clk_prepare_enable(clk);
632*4882a593Smuzhiyun if (ret) {
633*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't enable bus clk: %d\n", ret);
634*4882a593Smuzhiyun return ret;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun ret = clk_prepare_enable(p_clk);
637*4882a593Smuzhiyun if (ret) {
638*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't enable bus periph clk: %d\n", ret);
639*4882a593Smuzhiyun goto error_clk;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun platform_set_drvdata(pdev, ddata);
642*4882a593Smuzhiyun num = rk_remotectl_get_irkeybd_count(pdev);
643*4882a593Smuzhiyun if (num == 0) {
644*4882a593Smuzhiyun pr_err("remotectl: no ir keyboard add in dts!!\n");
645*4882a593Smuzhiyun ret = -EINVAL;
646*4882a593Smuzhiyun goto error_pclk;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun ddata->maxkeybdnum = num;
649*4882a593Smuzhiyun remotectl_button = devm_kzalloc(&pdev->dev,
650*4882a593Smuzhiyun num * sizeof(struct rkxx_remotectl_button),
651*4882a593Smuzhiyun GFP_KERNEL);
652*4882a593Smuzhiyun if (!remotectl_button) {
653*4882a593Smuzhiyun pr_err("failed to malloc remote button memory\n");
654*4882a593Smuzhiyun ret = -ENOMEM;
655*4882a593Smuzhiyun goto error_pclk;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun input = devm_input_allocate_device(&pdev->dev);
658*4882a593Smuzhiyun if (!input) {
659*4882a593Smuzhiyun pr_err("failed to allocate input device\n");
660*4882a593Smuzhiyun ret = -ENOMEM;
661*4882a593Smuzhiyun goto error_pclk;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun input->name = pdev->name;
664*4882a593Smuzhiyun input->phys = "gpio-keys/remotectl";
665*4882a593Smuzhiyun input->dev.parent = &pdev->dev;
666*4882a593Smuzhiyun input->id.bustype = BUS_HOST;
667*4882a593Smuzhiyun input->id.vendor = 0x524b;
668*4882a593Smuzhiyun input->id.product = 0x0006;
669*4882a593Smuzhiyun input->id.version = 0x0100;
670*4882a593Smuzhiyun ddata->input = input;
671*4882a593Smuzhiyun irq = platform_get_irq(pdev, 0);
672*4882a593Smuzhiyun if (irq < 0) {
673*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot find IRQ\n");
674*4882a593Smuzhiyun goto error_pclk;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun ddata->irq = irq;
677*4882a593Smuzhiyun ddata->wakeup = 1;
678*4882a593Smuzhiyun of_property_read_u32(np, "remote_pwm_id", &pwm_id);
679*4882a593Smuzhiyun pwm_id %= 4;
680*4882a593Smuzhiyun ddata->remote_pwm_id = pwm_id;
681*4882a593Smuzhiyun if (pwm_id > 3) {
682*4882a593Smuzhiyun dev_err(&pdev->dev, "pwm id error\n");
683*4882a593Smuzhiyun goto error_pclk;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun DBG("remotectl: remote pwm id=0x%x\n", pwm_id);
686*4882a593Smuzhiyun of_property_read_u32(np, "handle_cpu_id", &cpu_id);
687*4882a593Smuzhiyun ddata->handle_cpu_id = cpu_id;
688*4882a593Smuzhiyun DBG("remotectl: handle cpu id=0x%x\n", cpu_id);
689*4882a593Smuzhiyun rk_remotectl_parse_ir_keys(pdev);
690*4882a593Smuzhiyun tasklet_init(&ddata->remote_tasklet, rk_pwm_remotectl_do_something,
691*4882a593Smuzhiyun (unsigned long)ddata);
692*4882a593Smuzhiyun for (j = 0; j < num; j++) {
693*4882a593Smuzhiyun DBG("remotectl probe j = 0x%x\n", j);
694*4882a593Smuzhiyun for (i = 0; i < remotectl_button[j].nbuttons; i++) {
695*4882a593Smuzhiyun int keycode;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun keycode = remotectl_button[j].key_table[i].keycode;
698*4882a593Smuzhiyun input_set_capability(input, EV_KEY, keycode);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun ret = input_register_device(input);
702*4882a593Smuzhiyun if (ret)
703*4882a593Smuzhiyun dev_err(&pdev->dev, "register input device err, ret=%d\n", ret);
704*4882a593Smuzhiyun input_set_capability(input, EV_KEY, KEY_WAKEUP);
705*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, 1);
706*4882a593Smuzhiyun enable_irq_wake(irq);
707*4882a593Smuzhiyun timer_setup(&ddata->timer, rk_pwm_remotectl_timer, 0);
708*4882a593Smuzhiyun wake_lock_init(&ddata->remotectl_wake_lock,
709*4882a593Smuzhiyun WAKE_LOCK_SUSPEND, "rockchip_pwm_remote");
710*4882a593Smuzhiyun cpumask_clear(&cpumask);
711*4882a593Smuzhiyun cpumask_set_cpu(cpu_id, &cpumask);
712*4882a593Smuzhiyun irq_set_affinity_hint(irq, &cpumask);
713*4882a593Smuzhiyun ret = devm_request_irq(&pdev->dev, irq, rockchip_pwm_irq,
714*4882a593Smuzhiyun IRQF_NO_SUSPEND, "rk_pwm_irq", ddata);
715*4882a593Smuzhiyun if (ret) {
716*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq);
717*4882a593Smuzhiyun goto error_irq;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun pwm_freq = clk_get_rate(clk) / 64;
721*4882a593Smuzhiyun ddata->pwm_freq_nstime = 1000000000 / pwm_freq;
722*4882a593Smuzhiyun rk_pwm_remotectl_hw_init(ddata->base, pwm_id);
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun ret = rk_pwm_pwrkey_wakeup_init(pdev);
725*4882a593Smuzhiyun if (!ret) {
726*4882a593Smuzhiyun dev_info(&pdev->dev, "Controller support pwrkey capture\n");
727*4882a593Smuzhiyun goto end;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun ret = rk_pwm_sip_wakeup_init(pdev);
731*4882a593Smuzhiyun if (ret)
732*4882a593Smuzhiyun dev_info(&pdev->dev, "Donot support ATF Wakeup\n");
733*4882a593Smuzhiyun else
734*4882a593Smuzhiyun dev_info(&pdev->dev, "Support ATF Wakeup\n");
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun DBG("rk pwm remotectl init end!\n");
737*4882a593Smuzhiyun end:
738*4882a593Smuzhiyun return 0;
739*4882a593Smuzhiyun error_irq:
740*4882a593Smuzhiyun wake_lock_destroy(&ddata->remotectl_wake_lock);
741*4882a593Smuzhiyun error_pclk:
742*4882a593Smuzhiyun clk_unprepare(p_clk);
743*4882a593Smuzhiyun error_clk:
744*4882a593Smuzhiyun clk_unprepare(clk);
745*4882a593Smuzhiyun return ret;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
rk_pwm_remove(struct platform_device * pdev)748*4882a593Smuzhiyun static int rk_pwm_remove(struct platform_device *pdev)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun return 0;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun #ifdef CONFIG_PM
remotectl_suspend(struct device * dev)754*4882a593Smuzhiyun static int remotectl_suspend(struct device *dev)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun int cpu = 0;
757*4882a593Smuzhiyun int pwm_id;
758*4882a593Smuzhiyun struct cpumask cpumask;
759*4882a593Smuzhiyun struct platform_device *pdev = to_platform_device(dev);
760*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun if (ddata->pwm_pwrkey_capture) {
763*4882a593Smuzhiyun pwm_id = ddata->remote_pwm_id;
764*4882a593Smuzhiyun ddata->pwrkey_wakeup = 0;
765*4882a593Smuzhiyun rk_pwm_int_ctrl(ddata->base, pwm_id, PWM_INT_DISABLE);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun cpumask_clear(&cpumask);
768*4882a593Smuzhiyun cpumask_set_cpu(cpu, &cpumask);
769*4882a593Smuzhiyun irq_set_affinity_hint(ddata->irq, &cpumask);
770*4882a593Smuzhiyun return 0;
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun
remotectl_resume(struct device * dev)774*4882a593Smuzhiyun static int remotectl_resume(struct device *dev)
775*4882a593Smuzhiyun {
776*4882a593Smuzhiyun struct cpumask cpumask;
777*4882a593Smuzhiyun int pwm_id;
778*4882a593Smuzhiyun struct platform_device *pdev = to_platform_device(dev);
779*4882a593Smuzhiyun struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev);
780*4882a593Smuzhiyun int state;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun cpumask_clear(&cpumask);
783*4882a593Smuzhiyun cpumask_set_cpu(ddata->handle_cpu_id, &cpumask);
784*4882a593Smuzhiyun irq_set_affinity_hint(ddata->irq, &cpumask);
785*4882a593Smuzhiyun if (ddata->support_psci) {
786*4882a593Smuzhiyun /*
787*4882a593Smuzhiyun * loop wakeup state
788*4882a593Smuzhiyun */
789*4882a593Smuzhiyun state = sip_smc_remotectl_config(
790*4882a593Smuzhiyun REMOTECTL_GET_WAKEUP_STATE, 0);
791*4882a593Smuzhiyun if (state == REMOTECTL_PWRKEY_WAKEUP)
792*4882a593Smuzhiyun rk_pwm_wakeup(ddata->input);
793*4882a593Smuzhiyun } else if (ddata->pwm_pwrkey_capture) {
794*4882a593Smuzhiyun pwm_id = ddata->remote_pwm_id;
795*4882a593Smuzhiyun rk_pwm_int_ctrl(ddata->base, pwm_id, PWM_INT_ENABLE);
796*4882a593Smuzhiyun if (ddata->pwrkey_wakeup == 0)
797*4882a593Smuzhiyun return 0;
798*4882a593Smuzhiyun ddata->pwrkey_wakeup = 0;
799*4882a593Smuzhiyun rk_pwm_wakeup(ddata->input);
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun return 0;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun static const struct dev_pm_ops remotectl_pm_ops = {
806*4882a593Smuzhiyun .suspend_late = remotectl_suspend,
807*4882a593Smuzhiyun .resume_early = remotectl_resume,
808*4882a593Smuzhiyun };
809*4882a593Smuzhiyun #endif
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun static const struct of_device_id rk_pwm_of_match[] = {
812*4882a593Smuzhiyun { .compatible = "rockchip,remotectl-pwm"},
813*4882a593Smuzhiyun { }
814*4882a593Smuzhiyun };
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk_pwm_of_match);
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun static struct platform_driver rk_pwm_driver = {
819*4882a593Smuzhiyun .driver = {
820*4882a593Smuzhiyun .name = "remotectl-pwm",
821*4882a593Smuzhiyun .of_match_table = rk_pwm_of_match,
822*4882a593Smuzhiyun #ifdef CONFIG_PM
823*4882a593Smuzhiyun .pm = &remotectl_pm_ops,
824*4882a593Smuzhiyun #endif
825*4882a593Smuzhiyun },
826*4882a593Smuzhiyun .remove = rk_pwm_remove,
827*4882a593Smuzhiyun };
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun module_platform_driver_probe(rk_pwm_driver, rk_pwm_probe);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun MODULE_LICENSE("GPL");
832