1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015 Mans Rullgard <mans@mansr.com>
6 #include <linux/input.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/interrupt.h>
11 #include <linux/clk.h>
13 #include <media/rc-core.h>
15 #define DRIVER_NAME "tango-ir"
17 #define IR_NEC_CTRL 0x00
18 #define IR_NEC_DATA 0x04
20 #define IR_RC5_CLK_DIV 0x0c
21 #define IR_RC5_DATA 0x10
24 #define NEC_TIME_BASE 560
25 #define RC5_TIME_BASE 1778
28 #define RC6_CLKDIV 0x04
29 #define RC6_DATA0 0x08
30 #define RC6_DATA1 0x0c
31 #define RC6_DATA2 0x10
32 #define RC6_DATA3 0x14
33 #define RC6_DATA4 0x18
35 #define RC6_CARRIER 36000
36 #define RC6_TIME_BASE 16
38 #define NEC_CAP(n) ((n) << 24)
39 #define GPIO_SEL(n) ((n) << 16)
40 #define DISABLE_NEC (BIT(4) | BIT(8))
41 #define ENABLE_RC5 (BIT(0) | BIT(9))
42 #define ENABLE_RC6 (BIT(0) | BIT(7))
43 #define ACK_IR_INT (BIT(0) | BIT(1))
44 #define ACK_RC6_INT (BIT(31))
46 #define NEC_ANY (RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX | RC_PROTO_BIT_NEC32)
49 void __iomem
*rc5_base
;
50 void __iomem
*rc6_base
;
55 static void tango_ir_handle_nec(struct tango_ir
*ir
)
60 v
= readl_relaxed(ir
->rc5_base
+ IR_NEC_DATA
);
66 code
= ir_nec_bytes_to_scancode(v
, v
>> 8, v
>> 16, v
>> 24, &proto
);
67 rc_keydown(ir
->rc
, proto
, code
, 0);
70 static void tango_ir_handle_rc5(struct tango_ir
*ir
)
72 u32 data
, field
, toggle
, addr
, cmd
, code
;
74 data
= readl_relaxed(ir
->rc5_base
+ IR_RC5_DATA
);
78 field
= data
>> 12 & 1;
79 toggle
= data
>> 11 & 1;
80 addr
= data
>> 6 & 0x1f;
81 cmd
= (data
& 0x3f) | (field
^ 1) << 6;
83 code
= RC_SCANCODE_RC5(addr
, cmd
);
84 rc_keydown(ir
->rc
, RC_PROTO_RC5
, code
, toggle
);
87 static void tango_ir_handle_rc6(struct tango_ir
*ir
)
89 u32 data0
, data1
, toggle
, mode
, addr
, cmd
, code
;
91 data0
= readl_relaxed(ir
->rc6_base
+ RC6_DATA0
);
92 data1
= readl_relaxed(ir
->rc6_base
+ RC6_DATA1
);
94 mode
= data0
>> 1 & 7;
102 code
= RC_SCANCODE_RC6_0(addr
, cmd
);
103 rc_keydown(ir
->rc
, RC_PROTO_RC6_0
, code
, toggle
);
106 static irqreturn_t
tango_ir_irq(int irq
, void *dev_id
)
108 struct tango_ir
*ir
= dev_id
;
109 unsigned int rc5_stat
;
110 unsigned int rc6_stat
;
112 rc5_stat
= readl_relaxed(ir
->rc5_base
+ IR_INT
);
113 writel_relaxed(rc5_stat
, ir
->rc5_base
+ IR_INT
);
115 rc6_stat
= readl_relaxed(ir
->rc6_base
+ RC6_CTRL
);
116 writel_relaxed(rc6_stat
, ir
->rc6_base
+ RC6_CTRL
);
118 if (!(rc5_stat
& 3) && !(rc6_stat
& BIT(31)))
121 if (rc5_stat
& BIT(0))
122 tango_ir_handle_rc5(ir
);
124 if (rc5_stat
& BIT(1))
125 tango_ir_handle_nec(ir
);
127 if (rc6_stat
& BIT(31))
128 tango_ir_handle_rc6(ir
);
133 static int tango_change_protocol(struct rc_dev
*dev
, u64
*rc_type
)
135 struct tango_ir
*ir
= dev
->priv
;
136 u32 rc5_ctrl
= DISABLE_NEC
;
139 if (*rc_type
& NEC_ANY
)
142 if (*rc_type
& RC_PROTO_BIT_RC5
)
143 rc5_ctrl
|= ENABLE_RC5
;
145 if (*rc_type
& RC_PROTO_BIT_RC6_0
)
146 rc6_ctrl
= ENABLE_RC6
;
148 writel_relaxed(rc5_ctrl
, ir
->rc5_base
+ IR_CTRL
);
149 writel_relaxed(rc6_ctrl
, ir
->rc6_base
+ RC6_CTRL
);
154 static int tango_ir_probe(struct platform_device
*pdev
)
156 const char *map_name
= RC_MAP_TANGO
;
157 struct device
*dev
= &pdev
->dev
;
164 irq
= platform_get_irq(pdev
, 0);
168 ir
= devm_kzalloc(dev
, sizeof(*ir
), GFP_KERNEL
);
172 ir
->rc5_base
= devm_platform_ioremap_resource(pdev
, 0);
173 if (IS_ERR(ir
->rc5_base
))
174 return PTR_ERR(ir
->rc5_base
);
176 ir
->rc6_base
= devm_platform_ioremap_resource(pdev
, 1);
177 if (IS_ERR(ir
->rc6_base
))
178 return PTR_ERR(ir
->rc6_base
);
180 ir
->clk
= devm_clk_get(dev
, NULL
);
182 return PTR_ERR(ir
->clk
);
184 rc
= devm_rc_allocate_device(dev
, RC_DRIVER_SCANCODE
);
188 of_property_read_string(dev
->of_node
, "linux,rc-map-name", &map_name
);
190 rc
->device_name
= DRIVER_NAME
;
191 rc
->driver_name
= DRIVER_NAME
;
192 rc
->input_phys
= DRIVER_NAME
"/input0";
193 rc
->map_name
= map_name
;
194 rc
->allowed_protocols
= NEC_ANY
| RC_PROTO_BIT_RC5
| RC_PROTO_BIT_RC6_0
;
195 rc
->change_protocol
= tango_change_protocol
;
199 err
= clk_prepare_enable(ir
->clk
);
203 clkrate
= clk_get_rate(ir
->clk
);
205 clkdiv
= clkrate
* NEC_TIME_BASE
;
206 do_div(clkdiv
, 1000000);
208 val
= NEC_CAP(31) | GPIO_SEL(12) | clkdiv
;
209 writel_relaxed(val
, ir
->rc5_base
+ IR_NEC_CTRL
);
211 clkdiv
= clkrate
* RC5_TIME_BASE
;
212 do_div(clkdiv
, 1000000);
214 writel_relaxed(DISABLE_NEC
, ir
->rc5_base
+ IR_CTRL
);
215 writel_relaxed(clkdiv
, ir
->rc5_base
+ IR_RC5_CLK_DIV
);
216 writel_relaxed(ACK_IR_INT
, ir
->rc5_base
+ IR_INT
);
218 clkdiv
= clkrate
* RC6_TIME_BASE
;
219 do_div(clkdiv
, RC6_CARRIER
);
221 writel_relaxed(ACK_RC6_INT
, ir
->rc6_base
+ RC6_CTRL
);
222 writel_relaxed((clkdiv
>> 2) << 18 | clkdiv
, ir
->rc6_base
+ RC6_CLKDIV
);
224 err
= devm_request_irq(dev
, irq
, tango_ir_irq
, IRQF_SHARED
,
229 err
= devm_rc_register_device(dev
, rc
);
233 platform_set_drvdata(pdev
, ir
);
237 clk_disable_unprepare(ir
->clk
);
241 static int tango_ir_remove(struct platform_device
*pdev
)
243 struct tango_ir
*ir
= platform_get_drvdata(pdev
);
245 clk_disable_unprepare(ir
->clk
);
249 static const struct of_device_id tango_ir_dt_ids
[] = {
250 { .compatible
= "sigma,smp8642-ir" },
253 MODULE_DEVICE_TABLE(of
, tango_ir_dt_ids
);
255 static struct platform_driver tango_ir_driver
= {
256 .probe
= tango_ir_probe
,
257 .remove
= tango_ir_remove
,
260 .of_match_table
= tango_ir_dt_ids
,
263 module_platform_driver(tango_ir_driver
);
265 MODULE_DESCRIPTION("SMP86xx IR decoder driver");
266 MODULE_AUTHOR("Mans Rullgard <mans@mansr.com>");
267 MODULE_LICENSE("GPL");