hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/rc/sunxi-cir.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Driver for Allwinner sunXi IR controller
34 *
....@@ -7,16 +8,6 @@
78 * Based on sun5i-ir.c:
89 * Copyright (C) 2007-2012 Daniel Wang
910 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
10
- *
11
- * This program is free software; you can redistribute it and/or
12
- * modify it under the terms of the GNU General Public License as
13
- * published by the Free Software Foundation; either version 2 of
14
- * the License, or (at your option) any later version.
15
- *
16
- * This program is distributed in the hope that it will be useful,
17
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- * GNU General Public License for more details.
2011 */
2112
2213 #include <linux/clk.h>
....@@ -48,11 +39,11 @@
4839
4940 /* Rx Interrupt Enable */
5041 #define SUNXI_IR_RXINT_REG 0x2C
51
-/* Rx FIFO Overflow */
42
+/* Rx FIFO Overflow Interrupt Enable */
5243 #define REG_RXINT_ROI_EN BIT(0)
53
-/* Rx Packet End */
44
+/* Rx Packet End Interrupt Enable */
5445 #define REG_RXINT_RPEI_EN BIT(1)
55
-/* Rx FIFO Data Available */
46
+/* Rx FIFO Data Available Interrupt Enable */
5647 #define REG_RXINT_RAI_EN BIT(4)
5748
5849 /* Rx FIFO available byte level */
....@@ -60,6 +51,12 @@
6051
6152 /* Rx Interrupt Status */
6253 #define SUNXI_IR_RXSTA_REG 0x30
54
+/* Rx FIFO Overflow */
55
+#define REG_RXSTA_ROI REG_RXINT_ROI_EN
56
+/* Rx Packet End */
57
+#define REG_RXSTA_RPE REG_RXINT_RPEI_EN
58
+/* Rx FIFO Data Available */
59
+#define REG_RXSTA_RA REG_RXINT_RAI_EN
6360 /* RX FIFO Get Available Counter */
6461 #define REG_RXSTA_GET_AC(val) (((val) >> 8) & (ir->fifo_size * 2 - 1))
6562 /* Clear all interrupt status value */
....@@ -81,6 +78,17 @@
8178 /* Time after which device stops sending data in ms */
8279 #define SUNXI_IR_TIMEOUT 120
8380
81
+/**
82
+ * struct sunxi_ir_quirks - Differences between SoC variants.
83
+ *
84
+ * @has_reset: SoC needs reset deasserted.
85
+ * @fifo_size: size of the fifo.
86
+ */
87
+struct sunxi_ir_quirks {
88
+ bool has_reset;
89
+ int fifo_size;
90
+};
91
+
8492 struct sunxi_ir {
8593 spinlock_t ir_lock;
8694 struct rc_dev *rc;
....@@ -99,7 +107,7 @@
99107 unsigned char dt;
100108 unsigned int cnt, rc;
101109 struct sunxi_ir *ir = dev_id;
102
- DEFINE_IR_RAW_EVENT(rawir);
110
+ struct ir_raw_event rawir = {};
103111
104112 spin_lock(&ir->ir_lock);
105113
....@@ -108,7 +116,7 @@
108116 /* clean all pending statuses */
109117 writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
110118
111
- if (status & (REG_RXINT_RAI_EN | REG_RXINT_RPEI_EN)) {
119
+ if (status & (REG_RXSTA_RA | REG_RXSTA_RPE)) {
112120 /* How many messages in fifo */
113121 rc = REG_RXSTA_GET_AC(status);
114122 /* Sanity check */
....@@ -124,9 +132,9 @@
124132 }
125133 }
126134
127
- if (status & REG_RXINT_ROI_EN) {
135
+ if (status & REG_RXSTA_ROI) {
128136 ir_raw_event_reset(ir->rc);
129
- } else if (status & REG_RXINT_RPEI_EN) {
137
+ } else if (status & REG_RXSTA_RPE) {
130138 ir_raw_event_set_idle(ir->rc, true);
131139 ir_raw_event_handle(ir->rc);
132140 } else {
....@@ -145,6 +153,7 @@
145153
146154 struct device *dev = &pdev->dev;
147155 struct device_node *dn = dev->of_node;
156
+ const struct sunxi_ir_quirks *quirks;
148157 struct resource *res;
149158 struct sunxi_ir *ir;
150159 u32 b_clk_freq = SUNXI_IR_BASE_CLK;
....@@ -153,12 +162,15 @@
153162 if (!ir)
154163 return -ENOMEM;
155164
165
+ quirks = of_device_get_match_data(&pdev->dev);
166
+ if (!quirks) {
167
+ dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
168
+ return -ENODEV;
169
+ }
170
+
156171 spin_lock_init(&ir->ir_lock);
157172
158
- if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir"))
159
- ir->fifo_size = 64;
160
- else
161
- ir->fifo_size = 16;
173
+ ir->fifo_size = quirks->fifo_size;
162174
163175 /* Clock */
164176 ir->apb_clk = devm_clk_get(dev, "apb");
....@@ -175,13 +187,15 @@
175187 /* Base clock frequency (optional) */
176188 of_property_read_u32(dn, "clock-frequency", &b_clk_freq);
177189
178
- /* Reset (optional) */
179
- ir->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
180
- if (IS_ERR(ir->rst))
181
- return PTR_ERR(ir->rst);
182
- ret = reset_control_deassert(ir->rst);
183
- if (ret)
184
- return ret;
190
+ /* Reset */
191
+ if (quirks->has_reset) {
192
+ ir->rst = devm_reset_control_get_exclusive(dev, NULL);
193
+ if (IS_ERR(ir->rst))
194
+ return PTR_ERR(ir->rst);
195
+ ret = reset_control_deassert(ir->rst);
196
+ if (ret)
197
+ return ret;
198
+ }
185199
186200 ret = clk_set_rate(ir->clk, b_clk_freq);
187201 if (ret) {
....@@ -206,7 +220,6 @@
206220 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
207221 ir->base = devm_ioremap_resource(dev, res);
208222 if (IS_ERR(ir->base)) {
209
- dev_err(dev, "failed to map registers\n");
210223 ret = PTR_ERR(ir->base);
211224 goto exit_clkdisable_clk;
212225 }
....@@ -230,8 +243,8 @@
230243 ir->rc->dev.parent = dev;
231244 ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
232245 /* Frequency after IR internal divider with sample period in ns */
233
- ir->rc->rx_resolution = (1000000000ul / (b_clk_freq / 64));
234
- ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
246
+ ir->rc->rx_resolution = (USEC_PER_SEC / (b_clk_freq / 64));
247
+ ir->rc->timeout = MS_TO_US(SUNXI_IR_TIMEOUT);
235248 ir->rc->driver_name = SUNXI_IR_DEV;
236249
237250 ret = rc_register_device(ir->rc);
....@@ -245,7 +258,6 @@
245258 /* IRQ */
246259 ir->irq = platform_get_irq(pdev, 0);
247260 if (ir->irq < 0) {
248
- dev_err(dev, "no irq resource\n");
249261 ret = ir->irq;
250262 goto exit_free_dev;
251263 }
....@@ -318,10 +330,35 @@
318330 return 0;
319331 }
320332
333
+static const struct sunxi_ir_quirks sun4i_a10_ir_quirks = {
334
+ .has_reset = false,
335
+ .fifo_size = 16,
336
+};
337
+
338
+static const struct sunxi_ir_quirks sun5i_a13_ir_quirks = {
339
+ .has_reset = false,
340
+ .fifo_size = 64,
341
+};
342
+
343
+static const struct sunxi_ir_quirks sun6i_a31_ir_quirks = {
344
+ .has_reset = true,
345
+ .fifo_size = 64,
346
+};
347
+
321348 static const struct of_device_id sunxi_ir_match[] = {
322
- { .compatible = "allwinner,sun4i-a10-ir", },
323
- { .compatible = "allwinner,sun5i-a13-ir", },
324
- {},
349
+ {
350
+ .compatible = "allwinner,sun4i-a10-ir",
351
+ .data = &sun4i_a10_ir_quirks,
352
+ },
353
+ {
354
+ .compatible = "allwinner,sun5i-a13-ir",
355
+ .data = &sun5i_a13_ir_quirks,
356
+ },
357
+ {
358
+ .compatible = "allwinner,sun6i-a31-ir",
359
+ .data = &sun6i_a31_ir_quirks,
360
+ },
361
+ {}
325362 };
326363 MODULE_DEVICE_TABLE(of, sunxi_ir_match);
327364