hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/rc/ir-hix5hd2.c
....@@ -1,10 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2014 Linaro Ltd.
34 * Copyright (c) 2014 Hisilicon Limited.
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms and conditions of the GNU General Public License,
7
- * version 2, as published by the Free Software Foundation.
85 */
96
107 #include <linux/clk.h>
....@@ -40,9 +37,12 @@
4037 #define INT_CLR_RCV BIT(16)
4138 #define INT_CLR_RCVTIMEOUT (BIT(16) | BIT(17))
4239
43
-#define IR_CLK 0x48
4440 #define IR_CLK_ENABLE BIT(4)
4541 #define IR_CLK_RESET BIT(5)
42
+
43
+/* IR_ENABLE register bits */
44
+#define IR_ENABLE_EN BIT(0)
45
+#define IR_ENABLE_EN_EXTRA BIT(8)
4646
4747 #define IR_CFG_WIDTH_MASK 0xffff
4848 #define IR_CFG_WIDTH_SHIFT 16
....@@ -61,6 +61,23 @@
6161
6262 #define IR_HIX5HD2_NAME "hix5hd2-ir"
6363
64
+/* Need to set extra bit for enabling IR */
65
+#define HIX5HD2_FLAG_EXTRA_ENABLE BIT(0)
66
+
67
+struct hix5hd2_soc_data {
68
+ u32 clk_reg;
69
+ u32 flags;
70
+};
71
+
72
+static const struct hix5hd2_soc_data hix5hd2_data = {
73
+ .clk_reg = 0x48,
74
+};
75
+
76
+static const struct hix5hd2_soc_data hi3796cv300_data = {
77
+ .clk_reg = 0x60,
78
+ .flags = HIX5HD2_FLAG_EXTRA_ENABLE,
79
+};
80
+
6481 struct hix5hd2_ir_priv {
6582 int irq;
6683 void __iomem *base;
....@@ -69,15 +86,17 @@
6986 struct regmap *regmap;
7087 struct clk *clock;
7188 unsigned long rate;
89
+ const struct hix5hd2_soc_data *socdata;
7290 };
7391
74
-static int hix5hd2_ir_enable(struct hix5hd2_ir_priv *dev, bool on)
92
+static int hix5hd2_ir_clk_enable(struct hix5hd2_ir_priv *dev, bool on)
7593 {
94
+ u32 clk_reg = dev->socdata->clk_reg;
7695 u32 val;
7796 int ret = 0;
7897
7998 if (dev->regmap) {
80
- regmap_read(dev->regmap, IR_CLK, &val);
99
+ regmap_read(dev->regmap, clk_reg, &val);
81100 if (on) {
82101 val &= ~IR_CLK_RESET;
83102 val |= IR_CLK_ENABLE;
....@@ -85,7 +104,7 @@
85104 val &= ~IR_CLK_ENABLE;
86105 val |= IR_CLK_RESET;
87106 }
88
- regmap_write(dev->regmap, IR_CLK, val);
107
+ regmap_write(dev->regmap, clk_reg, val);
89108 } else {
90109 if (on)
91110 ret = clk_prepare_enable(dev->clock);
....@@ -95,12 +114,23 @@
95114 return ret;
96115 }
97116
117
+static inline void hix5hd2_ir_enable(struct hix5hd2_ir_priv *priv)
118
+{
119
+ u32 val = IR_ENABLE_EN;
120
+
121
+ if (priv->socdata->flags & HIX5HD2_FLAG_EXTRA_ENABLE)
122
+ val |= IR_ENABLE_EN_EXTRA;
123
+
124
+ writel_relaxed(val, priv->base + IR_ENABLE);
125
+}
126
+
98127 static int hix5hd2_ir_config(struct hix5hd2_ir_priv *priv)
99128 {
100129 int timeout = 10000;
101130 u32 val, rate;
102131
103
- writel_relaxed(0x01, priv->base + IR_ENABLE);
132
+ hix5hd2_ir_enable(priv);
133
+
104134 while (readl_relaxed(priv->base + IR_BUSY)) {
105135 if (timeout--) {
106136 udelay(1);
....@@ -131,13 +161,13 @@
131161 struct hix5hd2_ir_priv *priv = rdev->priv;
132162 int ret;
133163
134
- ret = hix5hd2_ir_enable(priv, true);
164
+ ret = hix5hd2_ir_clk_enable(priv, true);
135165 if (ret)
136166 return ret;
137167
138168 ret = hix5hd2_ir_config(priv);
139169 if (ret) {
140
- hix5hd2_ir_enable(priv, false);
170
+ hix5hd2_ir_clk_enable(priv, false);
141171 return ret;
142172 }
143173 return 0;
....@@ -147,7 +177,7 @@
147177 {
148178 struct hix5hd2_ir_priv *priv = rdev->priv;
149179
150
- hix5hd2_ir_enable(priv, false);
180
+ hix5hd2_ir_clk_enable(priv, false);
151181 }
152182
153183 static irqreturn_t hix5hd2_ir_rx_interrupt(int irq, void *data)
....@@ -175,7 +205,7 @@
175205 }
176206
177207 if ((irq_sr & INTMS_SYMBRCV) || (irq_sr & INTMS_TIMEOUT)) {
178
- DEFINE_IR_RAW_EVENT(ev);
208
+ struct ir_raw_event ev = {};
179209
180210 symb_num = readl_relaxed(priv->base + IR_DATAH);
181211 for (i = 0; i < symb_num; i++) {
....@@ -184,12 +214,12 @@
184214 data_h = ((symb_val >> 16) & 0xffff) * 10;
185215 symb_time = (data_l + data_h) / 10;
186216
187
- ev.duration = US_TO_NS(data_l);
217
+ ev.duration = data_l;
188218 ev.pulse = true;
189219 ir_raw_event_store(priv->rdev, &ev);
190220
191221 if (symb_time < IR_CFG_SYMBOL_MAXWIDTH) {
192
- ev.duration = US_TO_NS(data_h);
222
+ ev.duration = data_h;
193223 ev.pulse = false;
194224 ir_raw_event_store(priv->rdev, &ev);
195225 } else {
....@@ -208,6 +238,13 @@
208238 return IRQ_HANDLED;
209239 }
210240
241
+static const struct of_device_id hix5hd2_ir_table[] = {
242
+ { .compatible = "hisilicon,hix5hd2-ir", &hix5hd2_data, },
243
+ { .compatible = "hisilicon,hi3796cv300-ir", &hi3796cv300_data, },
244
+ {},
245
+};
246
+MODULE_DEVICE_TABLE(of, hix5hd2_ir_table);
247
+
211248 static int hix5hd2_ir_probe(struct platform_device *pdev)
212249 {
213250 struct rc_dev *rdev;
....@@ -215,12 +252,20 @@
215252 struct resource *res;
216253 struct hix5hd2_ir_priv *priv;
217254 struct device_node *node = pdev->dev.of_node;
255
+ const struct of_device_id *of_id;
218256 const char *map_name;
219257 int ret;
220258
221259 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
222260 if (!priv)
223261 return -ENOMEM;
262
+
263
+ of_id = of_match_device(hix5hd2_ir_table, dev);
264
+ if (!of_id) {
265
+ dev_err(dev, "Unable to initialize IR data\n");
266
+ return -ENODEV;
267
+ }
268
+ priv->socdata = of_id->data;
224269
225270 priv->regmap = syscon_regmap_lookup_by_phandle(node,
226271 "hisilicon,power-syscon");
....@@ -235,10 +280,8 @@
235280 return PTR_ERR(priv->base);
236281
237282 priv->irq = platform_get_irq(pdev, 0);
238
- if (priv->irq < 0) {
239
- dev_err(dev, "irq can not get\n");
283
+ if (priv->irq < 0)
240284 return priv->irq;
241
- }
242285
243286 rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
244287 if (!rdev)
....@@ -268,8 +311,8 @@
268311 rdev->input_id.vendor = 0x0001;
269312 rdev->input_id.product = 0x0001;
270313 rdev->input_id.version = 0x0100;
271
- rdev->rx_resolution = US_TO_NS(10);
272
- rdev->timeout = US_TO_NS(IR_CFG_SYMBOL_MAXWIDTH * 10);
314
+ rdev->rx_resolution = 10;
315
+ rdev->timeout = IR_CFG_SYMBOL_MAXWIDTH * 10;
273316
274317 ret = rc_register_device(rdev);
275318 if (ret < 0)
....@@ -314,7 +357,7 @@
314357 struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
315358
316359 clk_disable_unprepare(priv->clock);
317
- hix5hd2_ir_enable(priv, false);
360
+ hix5hd2_ir_clk_enable(priv, false);
318361
319362 return 0;
320363 }
....@@ -324,17 +367,18 @@
324367 struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
325368 int ret;
326369
327
- ret = hix5hd2_ir_enable(priv, true);
370
+ ret = hix5hd2_ir_clk_enable(priv, true);
328371 if (ret)
329372 return ret;
330373
331374 ret = clk_prepare_enable(priv->clock);
332375 if (ret) {
333
- hix5hd2_ir_enable(priv, false);
376
+ hix5hd2_ir_clk_enable(priv, false);
334377 return ret;
335378 }
336379
337
- writel_relaxed(0x01, priv->base + IR_ENABLE);
380
+ hix5hd2_ir_enable(priv);
381
+
338382 writel_relaxed(0x00, priv->base + IR_INTM);
339383 writel_relaxed(0xff, priv->base + IR_INTC);
340384 writel_relaxed(0x01, priv->base + IR_START);
....@@ -345,12 +389,6 @@
345389
346390 static SIMPLE_DEV_PM_OPS(hix5hd2_ir_pm_ops, hix5hd2_ir_suspend,
347391 hix5hd2_ir_resume);
348
-
349
-static const struct of_device_id hix5hd2_ir_table[] = {
350
- { .compatible = "hisilicon,hix5hd2-ir", },
351
- {},
352
-};
353
-MODULE_DEVICE_TABLE(of, hix5hd2_ir_table);
354392
355393 static struct platform_driver hix5hd2_ir_driver = {
356394 .driver = {