1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for Allwinner sunXi IR controller 4 * 5 * Copyright (C) 2014 Alexsey Shestacov <wingrime@linux-sunxi.org> 6 * Copyright (C) 2014 Alexander Bersenev <bay@hackerdom.ru> 7 * 8 * Based on sun5i-ir.c: 9 * Copyright (C) 2007-2012 Daniel Wang 10 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> 11 */ 12 13 #include <linux/clk.h> 14 #include <linux/interrupt.h> 15 #include <linux/module.h> 16 #include <linux/of_platform.h> 17 #include <linux/reset.h> 18 #include <media/rc-core.h> 19 20 #define SUNXI_IR_DEV "sunxi-ir" 21 22 /* Registers */ 23 /* IR Control */ 24 #define SUNXI_IR_CTL_REG 0x00 25 /* Global Enable */ 26 #define REG_CTL_GEN BIT(0) 27 /* RX block enable */ 28 #define REG_CTL_RXEN BIT(1) 29 /* CIR mode */ 30 #define REG_CTL_MD (BIT(4) | BIT(5)) 31 32 /* Rx Config */ 33 #define SUNXI_IR_RXCTL_REG 0x10 34 /* Pulse Polarity Invert flag */ 35 #define REG_RXCTL_RPPI BIT(2) 36 37 /* Rx Data */ 38 #define SUNXI_IR_RXFIFO_REG 0x20 39 40 /* Rx Interrupt Enable */ 41 #define SUNXI_IR_RXINT_REG 0x2C 42 /* Rx FIFO Overflow Interrupt Enable */ 43 #define REG_RXINT_ROI_EN BIT(0) 44 /* Rx Packet End Interrupt Enable */ 45 #define REG_RXINT_RPEI_EN BIT(1) 46 /* Rx FIFO Data Available Interrupt Enable */ 47 #define REG_RXINT_RAI_EN BIT(4) 48 49 /* Rx FIFO available byte level */ 50 #define REG_RXINT_RAL(val) ((val) << 8) 51 52 /* Rx Interrupt Status */ 53 #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 60 /* RX FIFO Get Available Counter */ 61 #define REG_RXSTA_GET_AC(val) (((val) >> 8) & (ir->fifo_size * 2 - 1)) 62 /* Clear all interrupt status value */ 63 #define REG_RXSTA_CLEARALL 0xff 64 65 /* IR Sample Config */ 66 #define SUNXI_IR_CIR_REG 0x34 67 /* CIR_REG register noise threshold */ 68 #define REG_CIR_NTHR(val) (((val) << 2) & (GENMASK(7, 2))) 69 /* CIR_REG register idle threshold */ 70 #define REG_CIR_ITHR(val) (((val) << 8) & (GENMASK(15, 8))) 71 72 /* Required frequency for IR0 or IR1 clock in CIR mode (default) */ 73 #define SUNXI_IR_BASE_CLK 8000000 74 /* Noise threshold in samples */ 75 #define SUNXI_IR_RXNOISE 1 76 77 /** 78 * struct sunxi_ir_quirks - Differences between SoC variants. 79 * 80 * @has_reset: SoC needs reset deasserted. 81 * @fifo_size: size of the fifo. 82 */ 83 struct sunxi_ir_quirks { 84 bool has_reset; 85 int fifo_size; 86 }; 87 88 struct sunxi_ir { 89 struct rc_dev *rc; 90 void __iomem *base; 91 int irq; 92 int fifo_size; 93 struct clk *clk; 94 struct clk *apb_clk; 95 struct reset_control *rst; 96 const char *map_name; 97 }; 98 99 static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) 100 { 101 unsigned long status; 102 unsigned char dt; 103 unsigned int cnt, rc; 104 struct sunxi_ir *ir = dev_id; 105 struct ir_raw_event rawir = {}; 106 107 status = readl(ir->base + SUNXI_IR_RXSTA_REG); 108 109 /* clean all pending statuses */ 110 writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG); 111 112 if (status & (REG_RXSTA_RA | REG_RXSTA_RPE)) { 113 /* How many messages in fifo */ 114 rc = REG_RXSTA_GET_AC(status); 115 /* Sanity check */ 116 rc = rc > ir->fifo_size ? ir->fifo_size : rc; 117 /* If we have data */ 118 for (cnt = 0; cnt < rc; cnt++) { 119 /* for each bit in fifo */ 120 dt = readb(ir->base + SUNXI_IR_RXFIFO_REG); 121 rawir.pulse = (dt & 0x80) != 0; 122 rawir.duration = ((dt & 0x7f) + 1) * 123 ir->rc->rx_resolution; 124 ir_raw_event_store_with_filter(ir->rc, &rawir); 125 } 126 } 127 128 if (status & REG_RXSTA_ROI) { 129 ir_raw_event_overflow(ir->rc); 130 } else if (status & REG_RXSTA_RPE) { 131 ir_raw_event_set_idle(ir->rc, true); 132 ir_raw_event_handle(ir->rc); 133 } else { 134 ir_raw_event_handle(ir->rc); 135 } 136 137 return IRQ_HANDLED; 138 } 139 140 /* Convert idle threshold to usec */ 141 static unsigned int sunxi_ithr_to_usec(unsigned int base_clk, unsigned int ithr) 142 { 143 return DIV_ROUND_CLOSEST(USEC_PER_SEC * (ithr + 1), 144 base_clk / (128 * 64)); 145 } 146 147 /* Convert usec to idle threshold */ 148 static unsigned int sunxi_usec_to_ithr(unsigned int base_clk, unsigned int usec) 149 { 150 /* make sure we don't end up with a timeout less than requested */ 151 return DIV_ROUND_UP((base_clk / (128 * 64)) * usec, USEC_PER_SEC) - 1; 152 } 153 154 static int sunxi_ir_set_timeout(struct rc_dev *rc_dev, unsigned int timeout) 155 { 156 struct sunxi_ir *ir = rc_dev->priv; 157 unsigned int base_clk = clk_get_rate(ir->clk); 158 159 unsigned int ithr = sunxi_usec_to_ithr(base_clk, timeout); 160 161 dev_dbg(rc_dev->dev.parent, "setting idle threshold to %u\n", ithr); 162 163 /* Set noise threshold and idle threshold */ 164 writel(REG_CIR_NTHR(SUNXI_IR_RXNOISE) | REG_CIR_ITHR(ithr), 165 ir->base + SUNXI_IR_CIR_REG); 166 167 rc_dev->timeout = sunxi_ithr_to_usec(base_clk, ithr); 168 169 return 0; 170 } 171 172 static int sunxi_ir_hw_init(struct device *dev) 173 { 174 struct sunxi_ir *ir = dev_get_drvdata(dev); 175 u32 tmp; 176 int ret; 177 178 ret = reset_control_deassert(ir->rst); 179 if (ret) 180 return ret; 181 182 ret = clk_prepare_enable(ir->apb_clk); 183 if (ret) { 184 dev_err(dev, "failed to enable apb clk\n"); 185 goto exit_assert_reset; 186 } 187 188 ret = clk_prepare_enable(ir->clk); 189 if (ret) { 190 dev_err(dev, "failed to enable ir clk\n"); 191 goto exit_disable_apb_clk; 192 } 193 194 /* Enable CIR Mode */ 195 writel(REG_CTL_MD, ir->base + SUNXI_IR_CTL_REG); 196 197 /* Set noise threshold and idle threshold */ 198 sunxi_ir_set_timeout(ir->rc, ir->rc->timeout); 199 200 /* Invert Input Signal */ 201 writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG); 202 203 /* Clear All Rx Interrupt Status */ 204 writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG); 205 206 /* 207 * Enable IRQ on overflow, packet end, FIFO available with trigger 208 * level 209 */ 210 writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN | 211 REG_RXINT_RAI_EN | REG_RXINT_RAL(ir->fifo_size / 2 - 1), 212 ir->base + SUNXI_IR_RXINT_REG); 213 214 /* Enable IR Module */ 215 tmp = readl(ir->base + SUNXI_IR_CTL_REG); 216 writel(tmp | REG_CTL_GEN | REG_CTL_RXEN, ir->base + SUNXI_IR_CTL_REG); 217 218 return 0; 219 220 exit_disable_apb_clk: 221 clk_disable_unprepare(ir->apb_clk); 222 exit_assert_reset: 223 reset_control_assert(ir->rst); 224 225 return ret; 226 } 227 228 static void sunxi_ir_hw_exit(struct device *dev) 229 { 230 struct sunxi_ir *ir = dev_get_drvdata(dev); 231 232 clk_disable_unprepare(ir->clk); 233 clk_disable_unprepare(ir->apb_clk); 234 reset_control_assert(ir->rst); 235 } 236 237 static int __maybe_unused sunxi_ir_suspend(struct device *dev) 238 { 239 sunxi_ir_hw_exit(dev); 240 241 return 0; 242 } 243 244 static int __maybe_unused sunxi_ir_resume(struct device *dev) 245 { 246 return sunxi_ir_hw_init(dev); 247 } 248 249 static SIMPLE_DEV_PM_OPS(sunxi_ir_pm_ops, sunxi_ir_suspend, sunxi_ir_resume); 250 251 static int sunxi_ir_probe(struct platform_device *pdev) 252 { 253 int ret = 0; 254 255 struct device *dev = &pdev->dev; 256 struct device_node *dn = dev->of_node; 257 const struct sunxi_ir_quirks *quirks; 258 struct sunxi_ir *ir; 259 u32 b_clk_freq = SUNXI_IR_BASE_CLK; 260 261 ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL); 262 if (!ir) 263 return -ENOMEM; 264 265 quirks = of_device_get_match_data(&pdev->dev); 266 if (!quirks) { 267 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); 268 return -ENODEV; 269 } 270 271 ir->fifo_size = quirks->fifo_size; 272 273 /* Clock */ 274 ir->apb_clk = devm_clk_get(dev, "apb"); 275 if (IS_ERR(ir->apb_clk)) { 276 dev_err(dev, "failed to get a apb clock.\n"); 277 return PTR_ERR(ir->apb_clk); 278 } 279 ir->clk = devm_clk_get(dev, "ir"); 280 if (IS_ERR(ir->clk)) { 281 dev_err(dev, "failed to get a ir clock.\n"); 282 return PTR_ERR(ir->clk); 283 } 284 285 /* Base clock frequency (optional) */ 286 of_property_read_u32(dn, "clock-frequency", &b_clk_freq); 287 288 /* Reset */ 289 if (quirks->has_reset) { 290 ir->rst = devm_reset_control_get_exclusive(dev, NULL); 291 if (IS_ERR(ir->rst)) 292 return PTR_ERR(ir->rst); 293 } 294 295 ret = clk_set_rate(ir->clk, b_clk_freq); 296 if (ret) { 297 dev_err(dev, "set ir base clock failed!\n"); 298 return ret; 299 } 300 dev_dbg(dev, "set base clock frequency to %d Hz.\n", b_clk_freq); 301 302 /* IO */ 303 ir->base = devm_platform_ioremap_resource(pdev, 0); 304 if (IS_ERR(ir->base)) { 305 return PTR_ERR(ir->base); 306 } 307 308 ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW); 309 if (!ir->rc) { 310 dev_err(dev, "failed to allocate device\n"); 311 return -ENOMEM; 312 } 313 314 ir->rc->priv = ir; 315 ir->rc->device_name = SUNXI_IR_DEV; 316 ir->rc->input_phys = "sunxi-ir/input0"; 317 ir->rc->input_id.bustype = BUS_HOST; 318 ir->rc->input_id.vendor = 0x0001; 319 ir->rc->input_id.product = 0x0001; 320 ir->rc->input_id.version = 0x0100; 321 ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL); 322 ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY; 323 ir->rc->dev.parent = dev; 324 ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; 325 /* Frequency after IR internal divider with sample period in us */ 326 ir->rc->rx_resolution = (USEC_PER_SEC / (b_clk_freq / 64)); 327 ir->rc->timeout = IR_DEFAULT_TIMEOUT; 328 ir->rc->min_timeout = sunxi_ithr_to_usec(b_clk_freq, 0); 329 ir->rc->max_timeout = sunxi_ithr_to_usec(b_clk_freq, 255); 330 ir->rc->s_timeout = sunxi_ir_set_timeout; 331 ir->rc->driver_name = SUNXI_IR_DEV; 332 333 ret = rc_register_device(ir->rc); 334 if (ret) { 335 dev_err(dev, "failed to register rc device\n"); 336 goto exit_free_dev; 337 } 338 339 platform_set_drvdata(pdev, ir); 340 341 /* IRQ */ 342 ir->irq = platform_get_irq(pdev, 0); 343 if (ir->irq < 0) { 344 ret = ir->irq; 345 goto exit_free_dev; 346 } 347 348 ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir); 349 if (ret) { 350 dev_err(dev, "failed request irq\n"); 351 goto exit_free_dev; 352 } 353 354 ret = sunxi_ir_hw_init(dev); 355 if (ret) 356 goto exit_free_dev; 357 358 dev_info(dev, "initialized sunXi IR driver\n"); 359 return 0; 360 361 exit_free_dev: 362 rc_free_device(ir->rc); 363 364 return ret; 365 } 366 367 static void sunxi_ir_remove(struct platform_device *pdev) 368 { 369 struct sunxi_ir *ir = platform_get_drvdata(pdev); 370 371 rc_unregister_device(ir->rc); 372 sunxi_ir_hw_exit(&pdev->dev); 373 } 374 375 static void sunxi_ir_shutdown(struct platform_device *pdev) 376 { 377 sunxi_ir_hw_exit(&pdev->dev); 378 } 379 380 static const struct sunxi_ir_quirks sun4i_a10_ir_quirks = { 381 .has_reset = false, 382 .fifo_size = 16, 383 }; 384 385 static const struct sunxi_ir_quirks sun5i_a13_ir_quirks = { 386 .has_reset = false, 387 .fifo_size = 64, 388 }; 389 390 static const struct sunxi_ir_quirks sun6i_a31_ir_quirks = { 391 .has_reset = true, 392 .fifo_size = 64, 393 }; 394 395 static const struct of_device_id sunxi_ir_match[] = { 396 { 397 .compatible = "allwinner,sun4i-a10-ir", 398 .data = &sun4i_a10_ir_quirks, 399 }, 400 { 401 .compatible = "allwinner,sun5i-a13-ir", 402 .data = &sun5i_a13_ir_quirks, 403 }, 404 { 405 .compatible = "allwinner,sun6i-a31-ir", 406 .data = &sun6i_a31_ir_quirks, 407 }, 408 {} 409 }; 410 MODULE_DEVICE_TABLE(of, sunxi_ir_match); 411 412 static struct platform_driver sunxi_ir_driver = { 413 .probe = sunxi_ir_probe, 414 .remove_new = sunxi_ir_remove, 415 .shutdown = sunxi_ir_shutdown, 416 .driver = { 417 .name = SUNXI_IR_DEV, 418 .of_match_table = sunxi_ir_match, 419 .pm = &sunxi_ir_pm_ops, 420 }, 421 }; 422 423 module_platform_driver(sunxi_ir_driver); 424 425 MODULE_DESCRIPTION("Allwinner sunXi IR controller driver"); 426 MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>"); 427 MODULE_LICENSE("GPL"); 428