Beispiel #1
0
static void send_pulse_irdeo(unsigned int length, ktime_t target)
{
	long rawbits;
	int i;
	unsigned char output;
	unsigned char chunk, shifted;

	/* how many bits have to be sent ? */
	rawbits = length * 1152 / 10000;
	if (serial_ir.duty_cycle > 50)
		chunk = 3;
	else
		chunk = 1;
	for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
		shifted = chunk << (i * 3);
		shifted >>= 1;
		output &= (~shifted);
		i++;
		if (i == 3) {
			soutp(UART_TX, output);
			while (!(sinp(UART_LSR) & UART_LSR_THRE))
				;
			output = 0x7f;
			i = 0;
		}
	}
	if (i != 0) {
		soutp(UART_TX, output);
		while (!(sinp(UART_LSR) & UART_LSR_TEMT))
			;
	}
}
Beispiel #2
0
static void serial_ir_close(struct rc_dev *rcdev)
{
	unsigned long flags;

	spin_lock_irqsave(&hardware[type].lock, flags);

	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));

	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER) &
	      (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
	spin_unlock_irqrestore(&hardware[type].lock, flags);
}
Beispiel #3
0
static int serial_ir_open(struct rc_dev *rcdev)
{
	unsigned long flags;

	/* initialize timestamp */
	serial_ir.lastkt = ktime_get();

	spin_lock_irqsave(&hardware[type].lock, flags);

	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));

	soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);

	spin_unlock_irqrestore(&hardware[type].lock, flags);

	return 0;
}
Beispiel #4
0
static int set_use_inc(void* data)
{
	int result;
	unsigned long flags;
	
	/* Init read buffer. */
	if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0)
		return -ENOMEM;
	
	/* initialize timestamp */
	do_gettimeofday(&lasttv);

	result=request_irq(irq,irq_handler,
			   SA_INTERRUPT | (share_irq ? SA_SHIRQ:0),
			   LIRC_DRIVER_NAME,(void *)&hardware);
	
	switch(result)
	{
	case -EBUSY:
		printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
                lirc_buffer_free(&rbuf);
		return -EBUSY;
	case -EINVAL:
		printk(KERN_ERR LIRC_DRIVER_NAME
		       ": Bad irq number or handler\n");
                lirc_buffer_free(&rbuf);
		return -EINVAL;
	default:
		dprintk("Interrupt %d, port %04x obtained\n", irq, io);
		break;
	};

	local_irq_save(flags);
	
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
	
	local_irq_restore(flags);
	
	MOD_INC_USE_COUNT;
	return 0;
}
Beispiel #5
0
static void set_use_dec(void* data)
{	unsigned long flags;
	
	local_irq_save(flags);
	
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER)&
	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
	local_irq_restore(flags);

	free_irq(irq, (void *)&hardware);
	
	dprintk("freed IRQ %d\n", irq);
	lirc_buffer_free(&rbuf);
	
	MOD_DEC_USE_COUNT;
}
Beispiel #6
0
static long send_pulse_irdeo(unsigned long length)
{
	long rawbits;
	int i;
	unsigned char output;
	unsigned char chunk,shifted;
	
	/* how many bits have to be sent ? */
	rawbits=length*1152/10000;
	if(duty_cycle>50) chunk=3;
	else chunk=1;
	for(i=0,output=0x7f;rawbits>0;rawbits-=3)
	{
		shifted=chunk<<(i*3);
		shifted>>=1;
		output&=(~shifted);
		i++;
		if(i==3)
		{
			soutp(UART_TX,output);
			while(!(sinp(UART_LSR) & UART_LSR_THRE));
			output=0x7f;
			i=0;
		}
	}
	if(i!=0)
	{
		soutp(UART_TX,output);
		while(!(sinp(UART_LSR) & UART_LSR_TEMT));
	}

	if(i==0)
	{
		return((-rawbits)*10000/1152);
	}
	else
	{
		return((3-i)*3*10000/1152+(-rawbits)*10000/1152);
	}
}
Beispiel #7
0
static void lirc_close(struct inode *node, struct file *file)
#endif
{	unsigned long flags;
	
	save_flags(flags);cli();
	
#ifndef CONFIG_COLDFIRE
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER)&
	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
#else
#ifndef LIRC_PORT
{
	volatile unsigned long *icrp;
	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
	*icrp = 0x80000000; /* INT1 ipl cleared */
}
#else
	soutp(MCFUART_UIMR, 0); /* disable UART interrupts */
#endif
#endif

	restore_flags(flags);
	
	free_irq(irq, NULL);
#       ifdef DEBUG
	printk(KERN_INFO  LIRC_DRIVER_NAME  ": freed IRQ %d\n", irq);
#       endif
	MOD_DEC_USE_COUNT;
#ifdef KERNEL_2_1
	return 0;
#endif
}
Beispiel #8
0
static int lirc_serial_resume(struct platform_device *dev) {
	unsigned long flags;

	hardware_init_port();

	local_irq_save(flags);
	/* Enable Interrupt */
	do_gettimeofday(&lasttv);
	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
	off();

	lirc_buffer_clear(&rbuf);

	local_irq_restore(flags);

	return 0;
}
Beispiel #9
0
static int serial_ir_resume(struct platform_device *dev)
{
	unsigned long flags;
	int result;

	result = hardware_init_port();
	if (result < 0)
		return result;

	spin_lock_irqsave(&hardware[type].lock, flags);
	/* Enable Interrupt */
	serial_ir.lastkt = ktime_get();
	soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);
	off();

	spin_unlock_irqrestore(&hardware[type].lock, flags);

	return 0;
}
Beispiel #10
0
static int lirc_serial_resume(struct platform_device *dev)
{
	unsigned long flags;

	if (hardware_init_port() < 0) {
		lirc_serial_exit();
		return -EINVAL;
	}

	spin_lock_irqsave(&hardware[type].lock, flags);
	/* Enable Interrupt */
	do_gettimeofday(&lasttv);
	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
	off();

	lirc_buffer_clear(&rbuf);

	spin_unlock_irqrestore(&hardware[type].lock, flags);

	return 0;
}
Beispiel #11
0
static int lirc_serial_suspend(struct platform_device *dev, pm_message_t state) {
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	/* Disable all interrupts */
	soutp(UART_IER, sinp(UART_IER)&
	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));

	/* Clear registers. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);

	return 0;
}
Beispiel #12
0
static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
#endif
{
	struct timeval tv;
	int status,counter,dcd;
	long deltv;
	lirc_t data;
	
	if((sinp(UART_IIR) & UART_IIR_NO_INT))
	{
		/* not our interrupt */
		return IRQ_RETVAL(IRQ_NONE);
	}
	
	counter=0;
	do{
		counter++;
		status=sinp(UART_MSR);
		if(counter>RS_ISR_PASS_LIMIT)
		{
			printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "
			       "We're caught!\n");
			break;
		}
		if((status&hardware[type].signal_pin_change) && sense!=-1)
		{
			/* get current time */
			do_gettimeofday(&tv);
			
			/* New mode, written by Trent Piepho 
			   <*****@*****.**>. */
			
			/* The old format was not very portable.
			   We now use the type lirc_t to pass pulses
			   and spaces to user space.
			   
			   If PULSE_BIT is set a pulse has been
			   received, otherwise a space has been
			   received.  The driver needs to know if your
			   receiver is active high or active low, or
			   the space/pulse sense could be
			   inverted. The bits denoted by PULSE_MASK are
			   the length in microseconds. Lengths greater
			   than or equal to 16 seconds are clamped to
			   PULSE_MASK.  All other bits are unused.
			   This is a much simpler interface for user
			   programs, as well as eliminating "out of
			   phase" errors with space/pulse
			   autodetection. */

			/* calculate time since last interrupt in
			   microseconds */
			dcd=(status & hardware[type].signal_pin) ? 1:0;
			
			deltv=tv.tv_sec-lasttv.tv_sec;
			if(tv.tv_sec<lasttv.tv_sec ||
			   (tv.tv_sec==lasttv.tv_sec &&
			    tv.tv_usec<lasttv.tv_usec))
			{
				printk(KERN_WARNING LIRC_DRIVER_NAME
				       ": AIEEEE: your clock just jumped "
				       "backwards\n");
				printk(KERN_WARNING LIRC_DRIVER_NAME
				       ": %d %d %lx %lx %lx %lx\n",
				       dcd,sense,
				       tv.tv_sec,lasttv.tv_sec,
				       tv.tv_usec,lasttv.tv_usec);
				data=PULSE_MASK;
			}
			else if(deltv>15) 
			{
				data=PULSE_MASK; /* really long time */
				if(!(dcd^sense)) /* sanity check */
				{
					printk(KERN_WARNING LIRC_DRIVER_NAME
					       "AIEEEE: %d %d %lx %lx %lx %lx\n",
					       dcd,sense,
					       tv.tv_sec,lasttv.tv_sec,
					       tv.tv_usec,lasttv.tv_usec);
				        /* detecting pulse while this
					   MUST be a space! */
				        sense=sense ? 0:1;
				}
			}
			else
			{
				data=(lirc_t) (deltv*1000000+
					       tv.tv_usec-
					       lasttv.tv_usec);
			}
			frbwrite(dcd^sense ? data : (data|PULSE_BIT));
			lasttv=tv;
			wake_up_interruptible(&rbuf.wait_poll);
		}
	} while(!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
	return IRQ_RETVAL(IRQ_HANDLED);
}
Beispiel #13
0
void irq_handler(int i, void *blah, struct pt_regs *regs)
{
	static struct timeval tv;
	int status,counter,dcd;
	long deltv;
	lirc_t data;
	unsigned long flags;

#ifndef LIRC_PORT
	save_flags(flags);cli();
	data= (lirc_t) (fast_tv.tv_sec*1000000+ fast_tv.tv_usec);
	pin_status = (pin_status + 1) & 0x1;
	if (data > 100000 && pin_status == 0) {/* 1/2 second fixup if broken */
		pin_status = 1;
		printk("F");
	}
	restore_flags(flags);
#endif

	counter=0;
	do{
#if DAVIDM
		counter++;
#ifndef LIRC_PORT
		status=LIRC_SIGNAL_PIN_CHANGE | (pin_status ? LIRC_SIGNAL_PIN : 0);
#else
		status=sinp(UART_MSR);
#endif
		if(counter>RS_ISR_PASS_LIMIT)
		{
			printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "
			       "We're caught!\n");
			break;
		}
		if((status&LIRC_SIGNAL_PIN_CHANGE) && sense!=-1)
#endif /* DAVIDM */
		{
#if DAVIDM
			/* get current time */
			do_gettimeofday(&tv);
#endif
			
			/* New mode, written by Trent Piepho 
			   <*****@*****.**>. */
			
			/* The old format was not very portable.
			   We now use the type lirc_t to pass pulses
			   and spaces to user space.
			   
			   If PULSE_BIT is set a pulse has been
			   received, otherwise a space has been
			   received.  The driver needs to know if your
			   receiver is active high or active low, or
			   the space/pulse sense could be
			   inverted. The bits denoted by PULSE_MASK are
			   the length in microseconds. Lengths greater
			   than or equal to 16 seconds are clamped to
			   PULSE_MASK.  All other bits are unused.
			   This is a much simpler interface for user
			   programs, as well as eliminating "out of
			   phase" errors with space/pulse
			   autodetection. */

			/* calculate time since last interrupt in
			   microseconds */
#if DAVIDM
			dcd=(status & LIRC_SIGNAL_PIN) ? 1:0;

			deltv=tv.tv_sec-lasttv.tv_sec;
#else
			dcd=pin_status;

			deltv=fast_tv.tv_sec;
#endif
			if(deltv>15) 
			{
#ifdef DEBUG
				printk(KERN_WARNING LIRC_DRIVER_NAME
				       ": AIEEEE: %d %d %lx %lx %lx %lx\n",
				       dcd,sense,
				       tv.tv_sec,lasttv.tv_sec,
				       tv.tv_usec,lasttv.tv_usec);
#endif
				data=PULSE_MASK; /* really long time */
				if(!(dcd^sense)) /* sanity check */
				{
				        /* detecting pulse while this
					   MUST be a space! */
				        sense=sense ? 0:1;
				}
			}
			else
			{
#ifdef DAVIDM
				data=(lirc_t) (deltv*1000000+ tv.tv_usec- lasttv.tv_usec);
#else
				// data=(lirc_t) (fast_tv.tv_sec*1000000+ fast_tv.tv_usec);
#endif
			}
#if DAVIDM
			if(tv.tv_sec<lasttv.tv_sec ||
			   (tv.tv_sec==lasttv.tv_sec &&
			    tv.tv_usec<lasttv.tv_usec))
			{
				printk(KERN_WARNING LIRC_DRIVER_NAME
				       ": AIEEEE: your clock just jumped "
				       "backwards\n");
				printk(KERN_WARNING LIRC_DRIVER_NAME
				       "%d %d %lx %lx %lx %lx\n",
				       dcd,sense,
				       tv.tv_sec,lasttv.tv_sec,
				       tv.tv_usec,lasttv.tv_usec);
				data=PULSE_MASK;
			}
#endif
			frbwrite(dcd^sense ? data : (data|PULSE_BIT));
#if DAVIDM
			lasttv=tv;
#else
			fast_tv.tv_sec = fast_tv.tv_usec = 0;
#endif
			wake_up_interruptible(&lirc_wait_in);
		}
	}
#ifndef CONFIG_COLDFIRE
	while(!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
#else
	while (0);
#endif

#ifndef LIRC_PORT
#ifndef LIRC_PORT
	* (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1) = 0xe0000000;
#endif
#endif
}
Beispiel #14
0
static int init_port(void)
{
	unsigned long flags;

        /* Check io region*/
	
#ifdef LIRC_PORT
        if((check_region(port,8))==-EBUSY)
	{
#if 0
		/* this is the correct behaviour but many people have
                   the serial driver compiled into the kernel... */
		printk(KERN_ERR  LIRC_DRIVER_NAME  
		       ": port %04x already in use\n", port);
		return(-EBUSY);
#else
		printk(KERN_ERR LIRC_DRIVER_NAME  
		       ": port %04x already in use, proceding anyway\n", port);
		printk(KERN_WARNING LIRC_DRIVER_NAME  
		       ": compile the serial port driver as module and\n");
		printk(KERN_WARNING LIRC_DRIVER_NAME  
		       ": make sure this module is loaded first\n");
		release_region(port,8);
#endif
	}
	
	/* Reserve io region. */
	request_region(port, 8, LIRC_DRIVER_NAME);
#endif
	
	save_flags(flags);cli();

#ifndef CONFIG_COLDFIRE
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER)&
	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
	
	/* Clear registers. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);
	
	/* Set line for power source */
	soutp(UART_MCR, LIRC_OFF);
	
	/* Clear registers again to be sure. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);

#ifdef LIRC_SERIAL_IRDEO
	/* setup port to 7N1 @ 115200 Baud */
	/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */

	/* Set DLAB 1. */
	soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
	/* Set divisor to 1 => 115200 Baud */
	soutp(UART_DLM,0);
	soutp(UART_DLL,1);
	/* Set DLAB 0 +  7N1 */
	soutp(UART_LCR,UART_LCR_WLEN7);
	/* THR interrupt already disabled at this point */
#endif

#else /* CONFIG_COLDFIRE */
{
	volatile unsigned char	*uartp;
#ifdef CONFIG_M5272
	volatile unsigned long	*icrp;
#else
	volatile unsigned char	*icrp;
#endif

/*
 *	we need a fast timer
 */
	coldfire_fast_init();
/*
 *	Setup the interrupts
 */
#ifdef CONFIG_M5272
#ifndef LIRC_PORT
	/* nothing to do */
#else
	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2);
	switch (LIRC_PORT) {
	case MCFUART_BASE1:
		*icrp = 0xe0000000;
		break;
	case MCFUART_BASE2:
		*icrp = 0x0e000000;
		break;
	default:
		printk("SERIAL: don't know how to handle UART %d interrupt?\n",
			LIRC_PORT;
		return;
	}
#endif
#else
	switch (LIRC_PORT) {
	case MCFUART_BASE1:
		icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR);
		*icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
			MCFSIM_ICR_PRI1;
		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
		break;
	case MCFUART_BASE2:
		icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR);
		*icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
			MCFSIM_ICR_PRI2;
		mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
		break;
	default:
		printk("SERIAL: don't know how to handle UART %d interrupt?\n",
			LIRC_PORT);
		return(-EIO);
	}

	soutp(MCFUART_UIVR, LIRC_IRQ);
#endif

#ifdef LIRC_PORT
	/*
	 *	disable all interrupts
	 */
	soutp(MCFUART_UIMR, 0);
	soutp(MCFUART_UCR, MCFUART_UCR_CMDRESETRX);  /* reset RX */
	soutp(MCFUART_UCR, MCFUART_UCR_CMDRESETTX);  /* reset TX */
	soutp(MCFUART_UCR, MCFUART_UCR_CMDRESETMRPTR);  /* reset MR pointer */
	/*
	 * Set port for defined baud , 8 data bits, 1 stop bit, no parity.
	 */
	soutp(MCFUART_UMR, MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8);
	soutp(MCFUART_UMR, MCFUART_MR2_STOP1);

#define	clk ((MCF_CLK / 32) / 115200)
	soutp(MCFUART_UBG1, (clk & 0xff00) >> 8);  /* set msb baud */
	soutp(MCFUART_UBG2, (clk & 0xff));  /* set lsb baud */
#undef clk

	soutp(MCFUART_UCSR, MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER);
	soutp(MCFUART_UCR, 0 /* MCFUART_UCR_RXENABLE */);
	/*
	 *	Allow COS interrupts
	 */
	soutp(MCFUART_UACR, MCFUART_UACR_IEC);
	/*
	 *	turn on RTS for power
	 */
	soutp(MCFUART_UOP1, MCFUART_UOP_RTS);
#endif /* LIRC_PORT */
}
#endif /* CONFIG_COLDFIRE */
	
	restore_flags(flags);
	
	/* If pin is high, then this must be an active low receiver. */
	if(sense==-1)
	{
#if DAVIDM
		/* wait 1 sec for the power supply */
		
#               ifdef KERNEL_2_1
		sleep_on_timeout(&power_supply_queue,HZ);
#               else
		init_timer(&power_supply_timer);
		power_supply_timer.expires=jiffies+HZ;
		power_supply_timer.data=(unsigned long) current;
		power_supply_timer.function=power_supply_up;
		add_timer(&power_supply_timer);
		sleep_on(&power_supply_queue);
		del_timer(&power_supply_timer);
#               endif
		
#ifndef LIRC_PORT
		sense=(pin_status & LIRC_SIGNAL_PIN) ? 1:0;
#else
		sense=(sinp(UART_MSR) & LIRC_SIGNAL_PIN) ? 1:0;
#endif
#else
		sense = 0;
#endif /* DAVIDM */
		printk(KERN_INFO  LIRC_DRIVER_NAME  ": auto-detected active "
		       "%s receiver\n",sense ? "low":"high");
	}
	else
	{
		printk(KERN_INFO  LIRC_DRIVER_NAME  ": Manually using active "
		       "%s receiver\n",sense ? "low":"high");
	};
	
	return 0;
}
Beispiel #15
0
static int serial_ir_probe(struct platform_device *dev)
{
	struct rc_dev *rcdev;
	int i, nlow, nhigh, result;

	rcdev = devm_rc_allocate_device(&dev->dev, RC_DRIVER_IR_RAW);
	if (!rcdev)
		return -ENOMEM;

	if (hardware[type].send_pulse && hardware[type].send_space)
		rcdev->tx_ir = serial_ir_tx;
	if (hardware[type].set_send_carrier)
		rcdev->s_tx_carrier = serial_ir_tx_carrier;
	if (hardware[type].set_duty_cycle)
		rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;

	switch (type) {
	case IR_HOMEBREW:
		rcdev->input_name = "Serial IR type home-brew";
		break;
	case IR_IRDEO:
		rcdev->input_name = "Serial IR type IRdeo";
		break;
	case IR_IRDEO_REMOTE:
		rcdev->input_name = "Serial IR type IRdeo remote";
		break;
	case IR_ANIMAX:
		rcdev->input_name = "Serial IR type AnimaX";
		break;
	case IR_IGOR:
		rcdev->input_name = "Serial IR type IgorPlug";
		break;
	}

	rcdev->input_phys = KBUILD_MODNAME "/input0";
	rcdev->input_id.bustype = BUS_HOST;
	rcdev->input_id.vendor = 0x0001;
	rcdev->input_id.product = 0x0001;
	rcdev->input_id.version = 0x0100;
	rcdev->open = serial_ir_open;
	rcdev->close = serial_ir_close;
	rcdev->dev.parent = &serial_ir.pdev->dev;
	rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
	rcdev->driver_name = KBUILD_MODNAME;
	rcdev->map_name = RC_MAP_RC6_MCE;
	rcdev->min_timeout = 1;
	rcdev->timeout = IR_DEFAULT_TIMEOUT;
	rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
	rcdev->rx_resolution = 250000;

	serial_ir.rcdev = rcdev;

	setup_timer(&serial_ir.timeout_timer, serial_ir_timeout,
		    (unsigned long)&serial_ir);

	result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler,
				  share_irq ? IRQF_SHARED : 0,
				  KBUILD_MODNAME, &hardware);
	if (result < 0) {
		if (result == -EBUSY)
			dev_err(&dev->dev, "IRQ %d busy\n", irq);
		else if (result == -EINVAL)
			dev_err(&dev->dev, "Bad irq number or handler\n");
		return result;
	}

	/* Reserve io region. */
	if ((iommap &&
	     (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift,
				      KBUILD_MODNAME) == NULL)) ||
	     (!iommap && (devm_request_region(&dev->dev, io, 8,
			  KBUILD_MODNAME) == NULL))) {
		dev_err(&dev->dev, "port %04x already in use\n", io);
		dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n");
		dev_warn(&dev->dev,
			 "or compile the serial port driver as module and\n");
		dev_warn(&dev->dev, "make sure this module is loaded first\n");
		return -EBUSY;
	}

	result = hardware_init_port();
	if (result < 0)
		return result;

	/* Initialize pulse/space widths */
	init_timing_params(50, 38000);

	/* If pin is high, then this must be an active low receiver. */
	if (sense == -1) {
		/* wait 1/2 sec for the power supply */
		msleep(500);

		/*
		 * probe 9 times every 0.04s, collect "votes" for
		 * active high/low
		 */
		nlow = 0;
		nhigh = 0;
		for (i = 0; i < 9; i++) {
			if (sinp(UART_MSR) & hardware[type].signal_pin)
				nlow++;
			else
				nhigh++;
			msleep(40);
		}
		sense = nlow >= nhigh ? 1 : 0;
		dev_info(&dev->dev, "auto-detected active %s receiver\n",
			 sense ? "low" : "high");
	} else
		dev_info(&dev->dev, "Manually using active %s receiver\n",
			 sense ? "low" : "high");

	dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);

	return devm_rc_register_device(&dev->dev, rcdev);
}
Beispiel #16
0
static int hardware_init_port(void)
{
	u8 scratch, scratch2, scratch3;

	/*
	 * This is a simple port existence test, borrowed from the autoconfig
	 * function in drivers/tty/serial/8250/8250_port.c
	 */
	scratch = sinp(UART_IER);
	soutp(UART_IER, 0);
#ifdef __i386__
	outb(0xff, 0x080);
#endif
	scratch2 = sinp(UART_IER) & 0x0f;
	soutp(UART_IER, 0x0f);
#ifdef __i386__
	outb(0x00, 0x080);
#endif
	scratch3 = sinp(UART_IER) & 0x0f;
	soutp(UART_IER, scratch);
	if (scratch2 != 0 || scratch3 != 0x0f) {
		/* we fail, there's nothing here */
		pr_err("port existence test failed, cannot continue\n");
		return -ENODEV;
	}

	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));

	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER) &
	      (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));

	/* Clear registers. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);

	/* Set line for power source */
	off();

	/* Clear registers again to be sure. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);

	switch (type) {
	case IR_IRDEO:
	case IR_IRDEO_REMOTE:
		/* setup port to 7N1 @ 115200 Baud */
		/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */

		/* Set DLAB 1. */
		soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
		/* Set divisor to 1 => 115200 Baud */
		soutp(UART_DLM, 0);
		soutp(UART_DLL, 1);
		/* Set DLAB 0 +  7N1 */
		soutp(UART_LCR, UART_LCR_WLEN7);
		/* THR interrupt already disabled at this point */
		break;
	default:
		break;
	}

	return 0;
}
Beispiel #17
0
static irqreturn_t serial_ir_irq_handler(int i, void *blah)
{
	ktime_t kt;
	int counter, dcd;
	u8 status;
	ktime_t delkt;
	unsigned int data;
	static int last_dcd = -1;

	if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
		/* not our interrupt */
		return IRQ_NONE;
	}

	counter = 0;
	do {
		counter++;
		status = sinp(UART_MSR);
		if (counter > RS_ISR_PASS_LIMIT) {
			dev_err(&serial_ir.pdev->dev, "Trapped in interrupt");
			break;
		}
		if ((status & hardware[type].signal_pin_change) &&
		    sense != -1) {
			/* get current time */
			kt = ktime_get();

			/*
			 * The driver needs to know if your receiver is
			 * active high or active low, or the space/pulse
			 * sense could be inverted.
			 */

			/* calc time since last interrupt in nanoseconds */
			dcd = (status & hardware[type].signal_pin) ? 1 : 0;

			if (dcd == last_dcd) {
				dev_err(&serial_ir.pdev->dev,
					"ignoring spike: %d %d %lldns %lldns\n",
					dcd, sense, ktime_to_ns(kt),
					ktime_to_ns(serial_ir.lastkt));
				continue;
			}

			delkt = ktime_sub(kt, serial_ir.lastkt);
			if (ktime_compare(delkt, ktime_set(15, 0)) > 0) {
				data = IR_MAX_DURATION; /* really long time */
				if (!(dcd ^ sense)) {
					/* sanity check */
					dev_err(&serial_ir.pdev->dev,
						"dcd unexpected: %d %d %lldns %lldns\n",
						dcd, sense, ktime_to_ns(kt),
						ktime_to_ns(serial_ir.lastkt));
					/*
					 * detecting pulse while this
					 * MUST be a space!
					 */
					sense = sense ? 0 : 1;
				}
			} else {
				data = ktime_to_ns(delkt);
			}
			frbwrite(data, !(dcd ^ sense));
			serial_ir.lastkt = kt;
			last_dcd = dcd;
		}
	} while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */

	mod_timer(&serial_ir.timeout_timer,
		  jiffies + nsecs_to_jiffies(serial_ir.rcdev->timeout));

	ir_raw_event_handle(serial_ir.rcdev);

	return IRQ_HANDLED;
}
Beispiel #18
0
static int lirc_open(struct inode *ino, struct file *filep)
{
	int result;
	unsigned long flags;
	
#       ifdef KERNEL_2_1
	spin_lock(&lirc_lock);
#       endif
	if(MOD_IN_USE)
	{
#               ifdef KERNEL_2_1
		spin_unlock(&lirc_lock);
#               endif
		return -EBUSY;
	}
	
	/* initialize timestamp */
	do_gettimeofday(&lasttv);
	
	result=request_irq(irq,irq_handler,
			SA_INTERRUPT|IRQ_FLG_FAST,
			LIRC_DRIVER_NAME,NULL);
	switch(result)
	{
	case -EBUSY:
		printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
#               ifdef KERNEL_2_1
		spin_unlock(&lirc_lock);
#               endif
		return -EBUSY;
	case -EINVAL:
		printk(KERN_ERR LIRC_DRIVER_NAME
		       ": Bad irq number or handler\n");
#               ifdef KERNEL_2_1
		spin_unlock(&lirc_lock);
#               endif
		return -EINVAL;
	default:
#               ifdef DEBUG
		printk(KERN_INFO LIRC_DRIVER_NAME
		       ": Interrupt %d, port %04x obtained\n", irq, port);
#               endif
		break;
	};

	/* finally enable interrupts. */
	save_flags(flags);cli();
	
#ifndef CONFIG_COLDFIRE
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
#else

#ifndef LIRC_PORT
	/*
	 * INT1 ipl set
	 */
	* (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1) = 0xe0000000;
#else
	/*
	 *	turn on CTS change interrupts
	 */
	soutp(MCFUART_UIMR, MCFUART_UIR_COS);
#endif
#endif
	
	restore_flags(flags);
	
	/* Init read buffer pointers. */
	rbh = rbt = 0;
	
	MOD_INC_USE_COUNT;
#       ifdef KERNEL_2_1
	spin_unlock(&lirc_lock);
#       endif
	return 0;
}
Beispiel #19
0
static int init_port(void)
{
	int i, nlow, nhigh;
	
	/* Reserve io region. */
#if defined(LIRC_ALLOW_MMAPPED_IO)
	/* Future MMAP-Developers: Attention!
	   For memory mapped I/O you *might* need to use ioremap() first,
	   for the NSLU2 it's done in boot code. */
	if(((iommap != 0)
	    && (request_mem_region(iommap, 8<<ioshift,
				   LIRC_DRIVER_NAME) == NULL))
	   || ((iommap == 0)
	       && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL)))
#else
	if(request_region(io, 8, LIRC_DRIVER_NAME)==NULL)
#endif
	{
		printk(KERN_ERR  LIRC_DRIVER_NAME  
		       ": port %04x already in use\n", io);
		printk(KERN_WARNING LIRC_DRIVER_NAME  
		       ": use 'setserial /dev/ttySX uart none'\n");
		printk(KERN_WARNING LIRC_DRIVER_NAME  
		       ": or compile the serial port driver as module and\n");
		printk(KERN_WARNING LIRC_DRIVER_NAME  
		       ": make sure this module is loaded first\n");
		return(-EBUSY);
	}
	
	hardware_init_port();

	/* Initialize pulse/space widths */
	init_timing_params(duty_cycle, freq);

	/* If pin is high, then this must be an active low receiver. */
	if(sense==-1)
	{
		/* wait 1/2 sec for the power supply */
		
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ/2);
		
		/* probe 9 times every 0.04s, collect "votes" for
		   active high/low */
		nlow = 0;
		nhigh = 0;
		for(i = 0; i < 9; i ++)
		{
			if (sinp(UART_MSR) & hardware[type].signal_pin)
			{
				nlow++;
			}
			else
			{
				nhigh++;
			}
			schedule_timeout(HZ/25);
		}
		sense = (nlow >= nhigh ? 1 : 0);
		printk(KERN_INFO  LIRC_DRIVER_NAME  ": auto-detected active "
		       "%s receiver\n",sense ? "low":"high");
	}
	else
	{
		printk(KERN_INFO  LIRC_DRIVER_NAME  ": Manually using active "
		       "%s receiver\n",sense ? "low":"high");
	};
	
	return 0;
}
Beispiel #20
0
static void hardware_init_port(void)
{
	unsigned long flags;
	local_irq_save(flags);
	
	/* Set DLAB 0. */
	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
	
	/* First of all, disable all interrupts */
	soutp(UART_IER, sinp(UART_IER)&
	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
	
	/* Clear registers. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);
	
#if defined(LIRC_SERIAL_NSLU2)
	if(type == LIRC_NSLU2) /* Setup NSLU2 UART */
	{
		/* Enable UART */
		soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE);
		/* Disable Receiver data Time out interrupt */
		soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE);
		/* set out2 = interupt unmask; off() doesn't set MCR
		   on NSLU2 */
		soutp(UART_MCR,UART_MCR_RTS|UART_MCR_OUT2);
	}
#endif

	/* Set line for power source */
	off();
	
	/* Clear registers again to be sure. */
	sinp(UART_LSR);
	sinp(UART_RX);
	sinp(UART_IIR);
	sinp(UART_MSR);

	switch(type)
	{
	case LIRC_IRDEO:
	case LIRC_IRDEO_REMOTE:
		/* setup port to 7N1 @ 115200 Baud */
		/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */
		
		/* Set DLAB 1. */
		soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
		/* Set divisor to 1 => 115200 Baud */
		soutp(UART_DLM,0);
		soutp(UART_DLL,1);
		/* Set DLAB 0 +  7N1 */
		soutp(UART_LCR,UART_LCR_WLEN7);
		/* THR interrupt already disabled at this point */
		break;
	default:
		break;
	}
	
	local_irq_restore(flags);
}
Beispiel #21
0
void send_pulse(unsigned long length)
{
#ifdef LIRC_SERIAL_IRDEO
	long rawbits;
	int i;
	unsigned char output;
	unsigned char chunk,shifted;
	
	/* how many bits have to be sent ? */
	rawbits=length*1152/10000;
	if(duty_cycle>50) chunk=3;
	else chunk=1;
	for(i=0,output=0x7f;rawbits>0;rawbits-=3)
	{
		shifted=chunk<<(i*3);
		shifted>>=1;
		output&=(~shifted);
		i++;
		if(i==3)
		{
			soutp(UART_TX,output);
			while(!(sinp(UART_LSR) & UART_LSR_TEMT));
			output=0x7f;
			i=0;
		}
	}
	if(i!=2)
	{
		soutp(UART_TX,output);
		while(!(sinp(UART_LSR) & UART_LSR_TEMT));
	}
#else
#ifdef LIRC_SERIAL_SOFTCARRIER
	unsigned long k,delay;
	int flag;
#endif

	if(length==0) return;
#ifdef LIRC_SERIAL_SOFTCARRIER
	/* this won't give us the carrier frequency we really want
	   due to integer arithmetic, but we can accept this inaccuracy */

	for(k=flag=0;k<length;k+=delay,flag=!flag)
	{
		if(flag)
		{
			off();
			delay=space_width;
		}
		else
		{
			on();
			delay=pulse_width;
		}
		udelay(delay);
	}
#else
	on();
	udelay(length);
#endif
#endif
}