1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
4 * Copyright 2017 Linaro Ltd.
7 #include <linux/device.h>
9 #include <linux/interrupt.h>
11 #include <linux/module.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
15 #include <media/rc-core.h>
17 #define DRIVER_NAME "zx-irdec"
19 #define ZX_IR_ENABLE 0x04
20 #define ZX_IREN BIT(0)
21 #define ZX_IR_CTRL 0x08
22 #define ZX_DEGL_MASK GENMASK(21, 20)
23 #define ZX_DEGL_VALUE(x) (((x) << 20) & ZX_DEGL_MASK)
24 #define ZX_WDBEGIN_MASK GENMASK(18, 8)
25 #define ZX_WDBEGIN_VALUE(x) (((x) << 8) & ZX_WDBEGIN_MASK)
26 #define ZX_IR_INTEN 0x10
27 #define ZX_IR_INTSTCLR 0x14
28 #define ZX_IR_CODE 0x30
29 #define ZX_IR_CNUM 0x34
30 #define ZX_NECRPT BIT(16)
37 static void zx_irdec_set_mask(struct zx_irdec
*irdec
, unsigned int reg
,
42 data
= readl(irdec
->base
+ reg
);
45 writel(data
, irdec
->base
+ reg
);
48 static irqreturn_t
zx_irdec_irq(int irq
, void *dev_id
)
50 struct zx_irdec
*irdec
= dev_id
;
51 u8 address
, not_address
;
52 u8 command
, not_command
;
53 u32 rawcode
, scancode
;
54 enum rc_proto rc_proto
;
57 writel(1, irdec
->base
+ ZX_IR_INTSTCLR
);
59 /* Check repeat frame */
60 if (readl(irdec
->base
+ ZX_IR_CNUM
) & ZX_NECRPT
) {
61 rc_repeat(irdec
->rcd
);
65 rawcode
= readl(irdec
->base
+ ZX_IR_CODE
);
66 not_command
= (rawcode
>> 24) & 0xff;
67 command
= (rawcode
>> 16) & 0xff;
68 not_address
= (rawcode
>> 8) & 0xff;
69 address
= rawcode
& 0xff;
71 scancode
= ir_nec_bytes_to_scancode(address
, not_address
,
74 rc_keydown(irdec
->rcd
, rc_proto
, scancode
, 0);
80 static int zx_irdec_probe(struct platform_device
*pdev
)
82 struct device
*dev
= &pdev
->dev
;
83 struct zx_irdec
*irdec
;
89 irdec
= devm_kzalloc(dev
, sizeof(*irdec
), GFP_KERNEL
);
93 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
94 irdec
->base
= devm_ioremap_resource(dev
, res
);
95 if (IS_ERR(irdec
->base
))
96 return PTR_ERR(irdec
->base
);
98 irq
= platform_get_irq(pdev
, 0);
102 rcd
= devm_rc_allocate_device(dev
, RC_DRIVER_SCANCODE
);
104 dev_err(dev
, "failed to allocate rc device\n");
111 rcd
->input_phys
= DRIVER_NAME
"/input0";
112 rcd
->input_id
.bustype
= BUS_HOST
;
113 rcd
->map_name
= RC_MAP_ZX_IRDEC
;
114 rcd
->allowed_protocols
= RC_PROTO_BIT_NEC
| RC_PROTO_BIT_NECX
|
116 rcd
->driver_name
= DRIVER_NAME
;
117 rcd
->device_name
= DRIVER_NAME
;
119 platform_set_drvdata(pdev
, irdec
);
121 ret
= devm_rc_register_device(dev
, rcd
);
123 dev_err(dev
, "failed to register rc device\n");
127 ret
= devm_request_irq(dev
, irq
, zx_irdec_irq
, 0, NULL
, irdec
);
129 dev_err(dev
, "failed to request irq\n");
134 * Initialize deglitch level and watchdog counter beginner as
135 * recommended by vendor BSP code.
137 zx_irdec_set_mask(irdec
, ZX_IR_CTRL
, ZX_DEGL_MASK
, ZX_DEGL_VALUE(0));
138 zx_irdec_set_mask(irdec
, ZX_IR_CTRL
, ZX_WDBEGIN_MASK
,
139 ZX_WDBEGIN_VALUE(0x21c));
141 /* Enable interrupt */
142 writel(1, irdec
->base
+ ZX_IR_INTEN
);
144 /* Enable the decoder */
145 zx_irdec_set_mask(irdec
, ZX_IR_ENABLE
, ZX_IREN
, ZX_IREN
);
150 static int zx_irdec_remove(struct platform_device
*pdev
)
152 struct zx_irdec
*irdec
= platform_get_drvdata(pdev
);
154 /* Disable the decoder */
155 zx_irdec_set_mask(irdec
, ZX_IR_ENABLE
, ZX_IREN
, 0);
157 /* Disable interrupt */
158 writel(0, irdec
->base
+ ZX_IR_INTEN
);
163 static const struct of_device_id zx_irdec_match
[] = {
164 { .compatible
= "zte,zx296718-irdec" },
167 MODULE_DEVICE_TABLE(of
, zx_irdec_match
);
169 static struct platform_driver zx_irdec_driver
= {
170 .probe
= zx_irdec_probe
,
171 .remove
= zx_irdec_remove
,
174 .of_match_table
= zx_irdec_match
,
177 module_platform_driver(zx_irdec_driver
);
179 MODULE_DESCRIPTION("ZTE ZX IR remote control driver");
180 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
181 MODULE_LICENSE("GPL v2");