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_reset(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 resource *res; 259 struct sunxi_ir *ir; 260 u32 b_clk_freq = SUNXI_IR_BASE_CLK; 261 262 ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL); 263 if (!ir) 264 return -ENOMEM; 265 266 quirks = of_device_get_match_data(&pdev->dev); 267 if (!quirks) { 268 dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); 269 return -ENODEV; 270 } 271 272 ir->fifo_size = quirks->fifo_size; 273 274 /* Clock */ 275 ir->apb_clk = devm_clk_get(dev, "apb"); 276 if (IS_ERR(ir->apb_clk)) { 277 dev_err(dev, "failed to get a apb clock.\n"); 278 return PTR_ERR(ir->apb_clk); 279 } 280 ir->clk = devm_clk_get(dev, "ir"); 281 if (IS_ERR(ir->clk)) { 282 dev_err(dev, "failed to get a ir clock.\n"); 283 return PTR_ERR(ir->clk); 284 } 285 286 /* Base clock frequency (optional) */ 287 of_property_read_u32(dn, "clock-frequency", &b_clk_freq); 288 289 /* Reset */ 290 if (quirks->has_reset) { 291 ir->rst = devm_reset_control_get_exclusive(dev, NULL); 292 if (IS_ERR(ir->rst)) 293 return PTR_ERR(ir->rst); 294 } 295 296 ret = clk_set_rate(ir->clk, b_clk_freq); 297 if (ret) { 298 dev_err(dev, "set ir base clock failed!\n"); 299 return ret; 300 } 301 dev_dbg(dev, "set base clock frequency to %d Hz.\n", b_clk_freq); 302 303 /* IO */ 304 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 305 ir->base = devm_ioremap_resource(dev, res); 306 if (IS_ERR(ir->base)) { 307 return PTR_ERR(ir->base); 308 } 309 310 ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW); 311 if (!ir->rc) { 312 dev_err(dev, "failed to allocate device\n"); 313 return -ENOMEM; 314 } 315 316 ir->rc->priv = ir; 317 ir->rc->device_name = SUNXI_IR_DEV; 318 ir->rc->input_phys = "sunxi-ir/input0"; 319 ir->rc->input_id.bustype = BUS_HOST; 320 ir->rc->input_id.vendor = 0x0001; 321 ir->rc->input_id.product = 0x0001; 322 ir->rc->input_id.version = 0x0100; 323 ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL); 324 ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY; 325 ir->rc->dev.parent = dev; 326 ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; 327 /* Frequency after IR internal divider with sample period in us */ 328 ir->rc->rx_resolution = (USEC_PER_SEC / (b_clk_freq / 64)); 329 ir->rc->timeout = IR_DEFAULT_TIMEOUT; 330 ir->rc->min_timeout = sunxi_ithr_to_usec(b_clk_freq, 0); 331 ir->rc->max_timeout = sunxi_ithr_to_usec(b_clk_freq, 255); 332 ir->rc->s_timeout = sunxi_ir_set_timeout; 333 ir->rc->driver_name = SUNXI_IR_DEV; 334 335 ret = rc_register_device(ir->rc); 336 if (ret) { 337 dev_err(dev, "failed to register rc device\n"); 338 goto exit_free_dev; 339 } 340 341 platform_set_drvdata(pdev, ir); 342 343 /* IRQ */ 344 ir->irq = platform_get_irq(pdev, 0); 345 if (ir->irq < 0) { 346 ret = ir->irq; 347 goto exit_free_dev; 348 } 349 350 ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir); 351 if (ret) { 352 dev_err(dev, "failed request irq\n"); 353 goto exit_free_dev; 354 } 355 356 ret = sunxi_ir_hw_init(dev); 357 if (ret) 358 goto exit_free_dev; 359 360 dev_info(dev, "initialized sunXi IR driver\n"); 361 return 0; 362 363 exit_free_dev: 364 rc_free_device(ir->rc); 365 366 return ret; 367 } 368 369 static int sunxi_ir_remove(struct platform_device *pdev) 370 { 371 struct sunxi_ir *ir = platform_get_drvdata(pdev); 372 373 rc_unregister_device(ir->rc); 374 sunxi_ir_hw_exit(&pdev->dev); 375 376 return 0; 377 } 378 379 static void sunxi_ir_shutdown(struct platform_device *pdev) 380 { 381 sunxi_ir_hw_exit(&pdev->dev); 382 } 383 384 static const struct sunxi_ir_quirks sun4i_a10_ir_quirks = { 385 .has_reset = false, 386 .fifo_size = 16, 387 }; 388 389 static const struct sunxi_ir_quirks sun5i_a13_ir_quirks = { 390 .has_reset = false, 391 .fifo_size = 64, 392 }; 393 394 static const struct sunxi_ir_quirks sun6i_a31_ir_quirks = { 395 .has_reset = true, 396 .fifo_size = 64, 397 }; 398 399 static const struct of_device_id sunxi_ir_match[] = { 400 { 401 .compatible = "allwinner,sun4i-a10-ir", 402 .data = &sun4i_a10_ir_quirks, 403 }, 404 { 405 .compatible = "allwinner,sun5i-a13-ir", 406 .data = &sun5i_a13_ir_quirks, 407 }, 408 { 409 .compatible = "allwinner,sun6i-a31-ir", 410 .data = &sun6i_a31_ir_quirks, 411 }, 412 {} 413 }; 414 MODULE_DEVICE_TABLE(of, sunxi_ir_match); 415 416 static struct platform_driver sunxi_ir_driver = { 417 .probe = sunxi_ir_probe, 418 .remove = sunxi_ir_remove, 419 .shutdown = sunxi_ir_shutdown, 420 .driver = { 421 .name = SUNXI_IR_DEV, 422 .of_match_table = sunxi_ir_match, 423 .pm = &sunxi_ir_pm_ops, 424 }, 425 }; 426 427 module_platform_driver(sunxi_ir_driver); 428 429 MODULE_DESCRIPTION("Allwinner sunXi IR controller driver"); 430 MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>"); 431 MODULE_LICENSE("GPL"); 432