1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IR SIR driver, (C) 2000 Milan Pikula <www@fornax.sk> 4 * 5 * sir_ir - Device driver for use with SIR (serial infra red) 6 * mode of IrDA on many notebooks. 7 */ 8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11#include <linux/module.h> 12#include <linux/interrupt.h> 13#include <linux/kernel.h> 14#include <linux/serial_reg.h> 15#include <linux/ktime.h> 16#include <linux/delay.h> 17#include <linux/platform_device.h> 18 19#include <media/rc-core.h> 20 21/* SECTION: Definitions */ 22#define PULSE '[' 23 24/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/ 25#define TIME_CONST (9000000ul / 115200ul) 26 27/* timeout for sequences in jiffies (=5/100s), must be longer than TIME_CONST */ 28#define SIR_TIMEOUT (HZ * 5 / 100) 29 30/* onboard sir ports are typically com3 */ 31static int io = 0x3e8; 32static int irq = 4; 33static int threshold = 3; 34 35static DEFINE_SPINLOCK(timer_lock); 36static struct timer_list timerlist; 37/* time of last signal change detected */ 38static ktime_t last; 39/* time of last UART data ready interrupt */ 40static ktime_t last_intr_time; 41static int last_value; 42static struct rc_dev *rcdev; 43 44static struct platform_device *sir_ir_dev; 45 46static DEFINE_SPINLOCK(hardware_lock); 47 48/* SECTION: Prototypes */ 49 50/* Communication with user-space */ 51static void add_read_queue(int flag, unsigned long val); 52/* Hardware */ 53static irqreturn_t sir_interrupt(int irq, void *dev_id); 54static void send_space(unsigned long len); 55static void send_pulse(unsigned long len); 56static int init_hardware(void); 57static void drop_hardware(void); 58/* Initialisation */ 59 60static inline unsigned int sinp(int offset) 61{ 62 return inb(io + offset); 63} 64 65static inline void soutp(int offset, int value) 66{ 67 outb(value, io + offset); 68} 69 70/* SECTION: Communication with user-space */ 71static int sir_tx_ir(struct rc_dev *dev, unsigned int *tx_buf, 72 unsigned int count) 73{ 74 unsigned long flags; 75 int i; 76 77 local_irq_save(flags); 78 for (i = 0; i < count;) { 79 if (tx_buf[i]) 80 send_pulse(tx_buf[i]); 81 i++; 82 if (i >= count) 83 break; 84 if (tx_buf[i]) 85 send_space(tx_buf[i]); 86 i++; 87 } 88 local_irq_restore(flags); 89 90 return count; 91} 92 93static void add_read_queue(int flag, unsigned long val) 94{ 95 struct ir_raw_event ev = {}; 96 97 pr_debug("add flag %d with val %lu\n", flag, val); 98 99 /* 100 * statistically, pulses are ~TIME_CONST/2 too long. we could 101 * maybe make this more exact, but this is good enough 102 */ 103 if (flag) { 104 /* pulse */ 105 if (val > TIME_CONST / 2) 106 val -= TIME_CONST / 2; 107 else /* should not ever happen */ 108 val = 1; 109 ev.pulse = true; 110 } else { 111 val += TIME_CONST / 2; 112 } 113 ev.duration = val; 114 115 ir_raw_event_store_with_filter(rcdev, &ev); 116} 117 118/* SECTION: Hardware */ 119static void sir_timeout(struct timer_list *unused) 120{ 121 /* 122 * if last received signal was a pulse, but receiving stopped 123 * within the 9 bit frame, we need to finish this pulse and 124 * simulate a signal change to from pulse to space. Otherwise 125 * upper layers will receive two sequences next time. 126 */ 127 128 unsigned long flags; 129 unsigned long pulse_end; 130 131 /* avoid interference with interrupt */ 132 spin_lock_irqsave(&timer_lock, flags); 133 if (last_value) { 134 /* clear unread bits in UART and restart */ 135 outb(UART_FCR_CLEAR_RCVR, io + UART_FCR); 136 /* determine 'virtual' pulse end: */ 137 pulse_end = min_t(unsigned long, 138 ktime_us_delta(last, last_intr_time), 139 IR_MAX_DURATION); 140 dev_dbg(&sir_ir_dev->dev, "timeout add %d for %lu usec\n", 141 last_value, pulse_end); 142 add_read_queue(last_value, pulse_end); 143 last_value = 0; 144 last = last_intr_time; 145 } 146 spin_unlock_irqrestore(&timer_lock, flags); 147 ir_raw_event_handle(rcdev); 148} 149 150static irqreturn_t sir_interrupt(int irq, void *dev_id) 151{ 152 unsigned char data; 153 ktime_t curr_time; 154 unsigned long delt; 155 unsigned long deltintr; 156 unsigned long flags; 157 int counter = 0; 158 int iir, lsr; 159 160 while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { 161 if (++counter > 256) { 162 dev_err(&sir_ir_dev->dev, "Trapped in interrupt"); 163 break; 164 } 165 166 switch (iir & UART_IIR_ID) { /* FIXME toto treba preriedit */ 167 case UART_IIR_MSI: 168 (void)inb(io + UART_MSR); 169 break; 170 case UART_IIR_RLSI: 171 case UART_IIR_THRI: 172 (void)inb(io + UART_LSR); 173 break; 174 case UART_IIR_RDI: 175 /* avoid interference with timer */ 176 spin_lock_irqsave(&timer_lock, flags); 177 do { 178 del_timer(&timerlist); 179 data = inb(io + UART_RX); 180 curr_time = ktime_get(); 181 delt = min_t(unsigned long, 182 ktime_us_delta(last, curr_time), 183 IR_MAX_DURATION); 184 deltintr = min_t(unsigned long, 185 ktime_us_delta(last_intr_time, 186 curr_time), 187 IR_MAX_DURATION); 188 dev_dbg(&sir_ir_dev->dev, "t %lu, d %d\n", 189 deltintr, (int)data); 190 /* 191 * if nothing came in last X cycles, 192 * it was gap 193 */ 194 if (deltintr > TIME_CONST * threshold) { 195 if (last_value) { 196 dev_dbg(&sir_ir_dev->dev, "GAP\n"); 197 /* simulate signal change */ 198 add_read_queue(last_value, 199 delt - 200 deltintr); 201 last_value = 0; 202 last = last_intr_time; 203 delt = deltintr; 204 } 205 } 206 data = 1; 207 if (data ^ last_value) { 208 /* 209 * deltintr > 2*TIME_CONST, remember? 210 * the other case is timeout 211 */ 212 add_read_queue(last_value, 213 delt - TIME_CONST); 214 last_value = data; 215 last = curr_time; 216 last = ktime_sub_us(last, 217 TIME_CONST); 218 } 219 last_intr_time = curr_time; 220 if (data) { 221 /* 222 * start timer for end of 223 * sequence detection 224 */ 225 timerlist.expires = jiffies + 226 SIR_TIMEOUT; 227 add_timer(&timerlist); 228 } 229 230 lsr = inb(io + UART_LSR); 231 } while (lsr & UART_LSR_DR); /* data ready */ 232 spin_unlock_irqrestore(&timer_lock, flags); 233 break; 234 default: 235 break; 236 } 237 } 238 ir_raw_event_handle(rcdev); 239 return IRQ_RETVAL(IRQ_HANDLED); 240} 241 242static void send_space(unsigned long len) 243{ 244 usleep_range(len, len + 25); 245} 246 247static void send_pulse(unsigned long len) 248{ 249 long bytes_out = len / TIME_CONST; 250 251 if (bytes_out == 0) 252 bytes_out++; 253 254 while (bytes_out--) { 255 outb(PULSE, io + UART_TX); 256 /* FIXME treba seriozne cakanie z char/serial.c */ 257 while (!(inb(io + UART_LSR) & UART_LSR_THRE)) 258 ; 259 } 260} 261 262static int init_hardware(void) 263{ 264 u8 scratch, scratch2, scratch3; 265 unsigned long flags; 266 267 spin_lock_irqsave(&hardware_lock, flags); 268 269 /* 270 * This is a simple port existence test, borrowed from the autoconfig 271 * function in drivers/tty/serial/8250/8250_port.c 272 */ 273 scratch = sinp(UART_IER); 274 soutp(UART_IER, 0); 275#ifdef __i386__ 276 outb(0xff, 0x080); 277#endif 278 scratch2 = sinp(UART_IER) & 0x0f; 279 soutp(UART_IER, 0x0f); 280#ifdef __i386__ 281 outb(0x00, 0x080); 282#endif 283 scratch3 = sinp(UART_IER) & 0x0f; 284 soutp(UART_IER, scratch); 285 if (scratch2 != 0 || scratch3 != 0x0f) { 286 /* we fail, there's nothing here */ 287 spin_unlock_irqrestore(&hardware_lock, flags); 288 pr_err("port existence test failed, cannot continue\n"); 289 return -ENODEV; 290 } 291 292 /* reset UART */ 293 outb(0, io + UART_MCR); 294 outb(0, io + UART_IER); 295 /* init UART */ 296 /* set DLAB, speed = 115200 */ 297 outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); 298 outb(1, io + UART_DLL); outb(0, io + UART_DLM); 299 /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ 300 outb(UART_LCR_WLEN7, io + UART_LCR); 301 /* FIFO operation */ 302 outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); 303 /* interrupts */ 304 /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */ 305 outb(UART_IER_RDI, io + UART_IER); 306 /* turn on UART */ 307 outb(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2, io + UART_MCR); 308 spin_unlock_irqrestore(&hardware_lock, flags); 309 310 return 0; 311} 312 313static void drop_hardware(void) 314{ 315 unsigned long flags; 316 317 spin_lock_irqsave(&hardware_lock, flags); 318 319 /* turn off interrupts */ 320 outb(0, io + UART_IER); 321 322 spin_unlock_irqrestore(&hardware_lock, flags); 323} 324 325/* SECTION: Initialisation */ 326static int sir_ir_probe(struct platform_device *dev) 327{ 328 int retval; 329 330 rcdev = devm_rc_allocate_device(&sir_ir_dev->dev, RC_DRIVER_IR_RAW); 331 if (!rcdev) 332 return -ENOMEM; 333 334 rcdev->device_name = "SIR IrDA port"; 335 rcdev->input_phys = KBUILD_MODNAME "/input0"; 336 rcdev->input_id.bustype = BUS_HOST; 337 rcdev->input_id.vendor = 0x0001; 338 rcdev->input_id.product = 0x0001; 339 rcdev->input_id.version = 0x0100; 340 rcdev->tx_ir = sir_tx_ir; 341 rcdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER; 342 rcdev->driver_name = KBUILD_MODNAME; 343 rcdev->map_name = RC_MAP_RC6_MCE; 344 rcdev->timeout = IR_DEFAULT_TIMEOUT; 345 rcdev->dev.parent = &sir_ir_dev->dev; 346 347 timer_setup(&timerlist, sir_timeout, 0); 348 349 /* get I/O port access and IRQ line */ 350 if (!devm_request_region(&sir_ir_dev->dev, io, 8, KBUILD_MODNAME)) { 351 pr_err("i/o port 0x%.4x already in use.\n", io); 352 return -EBUSY; 353 } 354 retval = devm_request_irq(&sir_ir_dev->dev, irq, sir_interrupt, 0, 355 KBUILD_MODNAME, NULL); 356 if (retval < 0) { 357 pr_err("IRQ %d already in use.\n", irq); 358 return retval; 359 } 360 361 retval = init_hardware(); 362 if (retval) { 363 del_timer_sync(&timerlist); 364 return retval; 365 } 366 367 pr_info("I/O port 0x%.4x, IRQ %d.\n", io, irq); 368 369 retval = devm_rc_register_device(&sir_ir_dev->dev, rcdev); 370 if (retval < 0) 371 return retval; 372 373 return 0; 374} 375 376static int sir_ir_remove(struct platform_device *dev) 377{ 378 drop_hardware(); 379 del_timer_sync(&timerlist); 380 return 0; 381} 382 383static struct platform_driver sir_ir_driver = { 384 .probe = sir_ir_probe, 385 .remove = sir_ir_remove, 386 .driver = { 387 .name = "sir_ir", 388 }, 389}; 390 391static int __init sir_ir_init(void) 392{ 393 int retval; 394 395 retval = platform_driver_register(&sir_ir_driver); 396 if (retval) 397 return retval; 398 399 sir_ir_dev = platform_device_alloc("sir_ir", 0); 400 if (!sir_ir_dev) { 401 retval = -ENOMEM; 402 goto pdev_alloc_fail; 403 } 404 405 retval = platform_device_add(sir_ir_dev); 406 if (retval) 407 goto pdev_add_fail; 408 409 return 0; 410 411pdev_add_fail: 412 platform_device_put(sir_ir_dev); 413pdev_alloc_fail: 414 platform_driver_unregister(&sir_ir_driver); 415 return retval; 416} 417 418static void __exit sir_ir_exit(void) 419{ 420 platform_device_unregister(sir_ir_dev); 421 platform_driver_unregister(&sir_ir_driver); 422} 423 424module_init(sir_ir_init); 425module_exit(sir_ir_exit); 426 427MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports"); 428MODULE_AUTHOR("Milan Pikula"); 429MODULE_LICENSE("GPL"); 430 431module_param_hw(io, int, ioport, 0444); 432MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); 433 434module_param_hw(irq, int, irq, 0444); 435MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); 436 437module_param(threshold, int, 0444); 438MODULE_PARM_DESC(threshold, "space detection threshold (3)"); 439