All of lore.kernel.org
 help / color / mirror / Atom feed
From: bennett78 <bennett78@digis.net>
To: linuxppc-embedded@ozlabs.org
Subject: mpc5200 timer3 Interrupts stopped working
Date: Fri, 24 Feb 2006 08:59:37 -0700	[thread overview]
Message-ID: <43FF2D69.3030902@digis.net> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 3303 bytes --]

Help, how do I debug timer3 Interrupts?  My driver was working and then 
interrupts
stopped coming (most likely blocked).  I have a driver that is very 
similar to
     linuxppc_2_4_devel/drivers/char/pp01_ad64.c
I have attached the complete driver (et.c)

/ # insmod et
ET Display Driver v0.1 loaded ET_TIN irq 16

et_init 00 intr->per_mask  1bfffc00
et_init 10 intr->ctrl      00c01001
et_init 14 intr->main_mask 00010e00
et_init 24 intr->enc_stat  00000001
et_init 28 intr->crit_stat 00000000
et_init 2c intr->main_stat 00002000
et_init 30 intr->per_stat  00000000
et_init 38 intr->per_error 00000000

/ # cat /proc/interrupts
           CPU0
 16:          0  MPC5xxx Edge      et Trubine
 23:       1049  MPC5xxx Edge      eth_xmit
 24:       2468  MPC5xxx Edge      eth_recv
 39:         51  MPC5xxx Edge      serial
 40:          0  MPC5xxx Edge      serial
 43:         69  MPC5xxx Edge      eth_err
BAD:          0

with a pulse train on timer3 input "et_interrupt" no longer gets
called.

code snippets
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define ET_TIN         3   // Turbine PULSE IN

static void et_interrupt (int irq, void *dev_id, struct pt_regs * regs)
{
    int port = ET_IRQ_TO_PORT(irq);
    unsigned long stat;

    printk(KERN_INFO "et_interrupt IRQ %d port %d main_stat %x gpt.sr %x 
\n",
                        irq, port, intr->main_status, gpt[port].sr );

    if( port == ET_TIN ) {
        // Clear pending interrupt
        stat = in_be32(&gpt[port].sr) & 0xffff;
        out_be32(&gpt[port].sr,  MPC5xxx_GPT_SR_CAPT);
        printk(KERN_INFO "et_int irq=%d port=%d stat %0lx \n", irq, 
port, stat);
        // wake_up_interruptible(&et_wait);
    } else {
        printk(KERN_ERR ET_MSG "Unexpected IRQ %d received", irq);
    }
    spin_lock (&et_lock);
    turbine_per = in_be32(&gpt[port].sr) >> 16;
    spin_unlock (&et_lock);
}


static int __init et_init (void)
....
if (request_irq(ET_PORT_TO_IRQ(ET_TIN), et_interrupt, 0, "et Trubine", 
NULL)) {
            printk(KERN_ERR ET_MSG "couldn't register interrupts\n");
            goto abort_remove_proc;
    }
out_be32(&gpt[ET_TIN].cir, (   66<<16) | 1 );  /* prescale(16), 
period(16)  */
out_be32(&gpt[ET_TIN].emsr,
        MPC5xxx_GPT_EMSR_INP_CAPTURE
      | MPC5xxx_GPT_EMSR_ICT_FALLING
      | MPC5xxx_GPT_EMSR_INT_ENABLE);
...
printk(KERN_INFO "ET Display Driver v%s loaded ET_TIN irq %d\n",
        ET_VERSION, ET_PORT_TO_IRQ(ET_TIN) );

    //broke with or without the following
    intr->main_mask &= ~(0x000000ff);   /* enable timer ints */

    printk(KERN_INFO "et_init 00 intr->per_mask  %08x\n", intr->per_mask);
    printk(KERN_INFO "et_init 10 intr->ctrl      %08x\n", intr->ctrl);
    printk(KERN_INFO "et_init 14 intr->main_mask %08x\n", intr->main_mask);
    printk(KERN_INFO "et_init 24 intr->enc_stat  %08x\n", intr->enc_status);
    printk(KERN_INFO "et_init 28 intr->crit_stat %08x\n", 
intr->crit_status);
    printk(KERN_INFO "et_init 2c intr->main_stat %08x\n", 
intr->main_status);
    printk(KERN_INFO "et_init 30 intr->per_stat  %08x\n", intr->per_status);
    printk(KERN_INFO "et_init 38 intr->per_error %08x\n", intr->per_error);

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
thanks in advance for any help,

Frank Bennett

*//*




[-- Attachment #1.2: Type: text/html, Size: 5932 bytes --]

[-- Attachment #2: et.c --]
[-- Type: text/x-c, Size: 11242 bytes --]

/*
 * et.c - Driver for EMCO Timers 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include <linux/module.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>

#include <asm/uaccess.h>
#include <asm/types.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mpc5xxx.h>
#include <asm/emco_et.h>

#define CONFIG_PPC_5xxx_IPBFREQ 66000

#define	ET_VERSION	"0.1"
#define ET_NAME	"et"
#define ET_MSG	"et: "

#undef ET_EXCLUSIVE_OPEN

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Frank Bennett");
MODULE_DESCRIPTION("Emco Timers Driver");

#define ET_MAJOR	190
static int major = ET_MAJOR;
MODULE_PARM(major,"i");
MODULE_PARM_DESC(major, "Device major number (default=190)");

static struct mpc5xxx_gpt  *gpt    = (struct mpc5xxx_gpt  *)MPC5xxx_GPT;
// static struct mpc5xxx_gpio *gpio   = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
static struct mpc5xxx_intr *intr   = (struct mpc5xxx_intr *)MPC5xxx_INTR;
static unsigned long turbine_per;
static DECLARE_WAIT_QUEUE_HEAD(et_wait);

/*
 * ET timer related definitions:
 *
 */
#define ET_POUT        0   // Pulse Out
#define ET_KP_ACTIVE   1   // not KeyPad active (low) IN see gui.c
#define ET_TDIR        2   // Turbine DIR IN
#define ET_TIN         3   // Turbine PULSE IN
#define ET_52k         4   // start SAR convert
#define ET_RLY1        5   // RELAY 1 active low OUT
#define ET_RLY2        6   // RELAY 2 active low OUT
#define ET_BKL         7   // LCD Backlite OUT

#define ET_DELAY_US		10 /* in micro-seconds */

#define ET_PORT_TO_IRQ(port) (13 + port)
#define ET_IRQ_TO_PORT(irq)  (irq - 13)

#ifdef ET_EXCLUSICE_OPEN
static char et_is_open = 0;
#endif

static spinlock_t et_lock = SPIN_LOCK_UNLOCKED;

static void et_interrupt (int irq, void *dev_id, struct pt_regs * regs)
{	
    int port = ET_IRQ_TO_PORT(irq);
	unsigned long stat;

	printk(KERN_INFO "et_interrupt IRQ %d port %d main_stat %x gpt.sr %x \n", 
	 		  			irq, port, intr->main_status, gpt[port].sr ); 

    if( port == ET_TIN ) {
		// Clear pending interrupt 
		stat = in_be32(&gpt[port].sr) & 0xffff;
    	out_be32(&gpt[port].sr,  MPC5xxx_GPT_SR_CAPT);
    	printk(KERN_INFO "et_int irq=%d port=%d stat %0lx \n", irq, port, stat); 
		// wake_up_interruptible(&et_wait);
    } else {		
		printk(KERN_ERR ET_MSG "Unexpected IRQ %d received", irq); 
    }
	spin_lock (&et_lock);
	turbine_per = in_be32(&gpt[port].sr) >> 16;
	spin_unlock (&et_lock);
}

#ifdef CONFIG_PROC_FS
static int et_read_proc(char *page, char **start, off_t off,
                          int count, int *eof, void *data)
{
    *eof = 1;
    return count;
}

static int et_write_proc(struct file *file, const char *buffer,
			   unsigned long count, void *data)
{    
    if (count > 128)
		return -EINVAL;

    return count;
}
#endif

/*
 * Device file operations
 */

static int et_open(struct inode *inode, struct file *file)
{
#ifdef ET_EXCLUSICE_OPEN
    if (et_is_open != 0)
		return -EBUSY;
    et_is_open = 1;
#endif
	spin_lock_irq (&et_lock);
	turbine_per = 0L;
	spin_unlock_irq (&et_lock);
    return 0;
}

static int et_close(struct inode *inode, struct file *file)
{
#ifdef ET_EXCLUSICE_OPEN
    et_is_open = 0;
#endif
    return 0;
}

static int et_write (struct file *file, u8 *buf, 
			  size_t count, loff_t *ppos)
{
    printk(KERN_DEBUG "  et_write \n" );
	return 0;
} 

static size_t et_read (struct file *file, char *buf, 
			 size_t count, loff_t *ppos)
{
    DECLARE_WAITQUEUE(wait, current);
    unsigned long data;
    ssize_t retval;

    printk(KERN_DEBUG "  et_read \n" );

    if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
        return -EINVAL;

//    add_wait_queue(&et_wait, &wait);

    while (1) {
        __set_current_state(TASK_INTERRUPTIBLE);
        spin_lock_irq (&et_lock);
        data = turbine_per;
        turbine_per = 0L;
        spin_unlock_irq (&et_lock);

        if (data != 0)
            break;

        if (file->f_flags & O_NONBLOCK) {
            retval = -EAGAIN;
            goto out;
        }
        if (signal_pending(current)) {
            retval = -ERESTARTSYS;
            goto out;
        }
        schedule();
    }
    if (count == sizeof(unsigned int))
        retval = put_user(data, (unsigned int *)buf);
    else
        retval = put_user(data, (unsigned long *)buf);
    if (!retval)
        retval = count;
 out:
    current->state = TASK_RUNNING;
//    remove_wait_queue(&et_wait, &wait);

    return retval;
}

static int et_ioctl (struct inode *inode, struct file *file, 
		      unsigned int cmd, unsigned long arg)
{
	unsigned long data;

	// printk(KERN_DEBUG "et_ioctl %04x %08lx\n", cmd, arg);
	switch (cmd) {
	case ET_POUT:
	case ET_52k:
	case ET_BKL: 
	case ET_RLY1: 
	case ET_RLY2:
		out_be32(&gpt[cmd].cr,  (arg & 0xffff0000) |1);  /* width, update_now */
    	out_be32(&gpt[cmd].cir, ((CONFIG_PPC_5xxx_IPBFREQ / 1000) << 16) | (arg&0xffff) ); // prescale, period
		break;
	case ET_TIN: 
		data = turbine_per;
		turbine_per = 0L;
		return copy_to_user((void *)arg, &data, sizeof data) ? -EFAULT : 0;
		break;
	case ET_TDIR:
	case ET_KP_ACTIVE: 
		data = (gpt[cmd].sr & MPC5xxx_GPT_SR_PIN)>>8;
		return copy_to_user((void *)arg, &data, sizeof data) ? -EFAULT : 0;

	//case ET_RLY1: 
	//case ET_RLY2:
	//	if( arg == 1L)
	//		out_be32(&gpt[cmd].emsr, MPC5xxx_GPT_EMSR_OUTPUT_1 | MPC5xxx_GPT_EMSR_INTERNAL);
	//	else
	//		out_be32(&gpt[cmd].emsr, MPC5xxx_GPT_EMSR_OUTPUT_0 | MPC5xxx_GPT_EMSR_INTERNAL);
	//	break;
	}
    return 0;
}

static struct file_operations et_fops = {
    owner: 		THIS_MODULE,
    open:  		et_open,
    release:  	et_close,
    read: 		et_read,
    write: 		et_write,
    ioctl: 		et_ioctl,
};

static void et_init_gpt(void)
{
	unsigned int per;

    /* Pulse Out   -      Timer 0 */
    out_be32(&gpt[ET_POUT].emsr, 
        MPC5xxx_GPT_EMSR_PWM | MPC5xxx_GPT_EMSR_CE | MPC5xxx_GPT_EMSR_CONTINOUS);

	/* Turbine in  - GPIO Timer 1 */
	turbine_per = 0L;
    out_be32(&gpt[ET_TIN].cir, (   66<<16) | 1 );  /* prescale(16), period(16)  */
    out_be32(&gpt[ET_TIN].emsr,
        MPC5xxx_GPT_EMSR_INP_CAPTURE | MPC5xxx_GPT_EMSR_ICT_FALLING | MPC5xxx_GPT_EMSR_INT_ENABLE);

	/* Turbine dir - GPIO Timer 2 */
    out_be32(&gpt[ET_TDIR].emsr,
        MPC5xxx_GPT_EMSR_INP_CAPTURE | MPC5xxx_GPT_EMSR_ICT_FALLING );

	/* 52k ref     - GPIO Timer 3 */
	per = 40 ; // 40 usec
    out_be32(&gpt[ET_52k].cr,  (per/2)<<16  | 1);     /* width, update_now */
    out_be32(&gpt[ET_52k].cir, (    33<<16) | per );  /* prescale(16), period(16)  */
    out_be32(&gpt[ET_52k].emsr,
         MPC5xxx_GPT_EMSR_PWM | MPC5xxx_GPT_EMSR_CE | MPC5xxx_GPT_EMSR_CONTINOUS);

	/* KP_active  - GPIO Timer 4 */
    out_be32(&gpt[ET_KP_ACTIVE].emsr,
        MPC5xxx_GPT_EMSR_INP_CAPTURE | MPC5xxx_GPT_EMSR_ICT_FALLING );

	/* Relay 1    - GPIO Timer 5 */
    out_be32(&gpt[ET_RLY1].emsr,
        MPC5xxx_GPT_EMSR_PWM | MPC5xxx_GPT_EMSR_CE | MPC5xxx_GPT_EMSR_CONTINOUS);
    //		MPC5xxx_GPT_EMSR_OUTPUT_1 | MPC5xxx_GPT_EMSR_INTERNAL);

	/* Relay 2    - GPIO Timer 5 */
    out_be32(&gpt[ET_RLY2].emsr,
        MPC5xxx_GPT_EMSR_PWM | MPC5xxx_GPT_EMSR_CE | MPC5xxx_GPT_EMSR_CONTINOUS);
 	//		MPC5xxx_GPT_EMSR_OUTPUT_1 | MPC5xxx_GPT_EMSR_INTERNAL);


	/* LCD BL Lite- GPIO Timer 7 */
	per = 4000 ; // 4 msec
    out_be32(&gpt[ET_BKL].cr,  (per/4)<<16  | 1);     /* width, update_now */
    out_be32(&gpt[ET_BKL].cir, (    66<<16) | per );  /* prescale(16), period(16)  */
    out_be32(&gpt[ET_BKL].emsr,
         MPC5xxx_GPT_EMSR_PWM | MPC5xxx_GPT_EMSR_CE | MPC5xxx_GPT_EMSR_CONTINOUS);
}

static int __init et_init (void)
{
#ifdef CONFIG_PROC_FS
    struct proc_dir_entry * proc;
#endif
    int ret = -ENODEV;
	
    ret = register_chrdev(ET_MAJOR, ET_NAME, &et_fops);
    if (ret < 0) {
		printk(KERN_ERR ET_MSG "Couldn't register " ET_NAME " driver\n");
		goto abort;
    }
    if (major == 0)
		major = ret;   /* dynamic */

#ifdef CONFIG_PROC_FS
    proc = create_proc_entry(ET_NAME, S_IFREG | S_IRUGO, NULL);
    if (proc == NULL) {
		printk(KERN_ERR ET_MSG "failed to create /proc/"ET_NAME"\n");
		goto abort_unregister;
    }
    proc->read_proc  = et_read_proc;
    proc->write_proc = et_write_proc;
#endif

	if (request_irq(ET_PORT_TO_IRQ(ET_TIN), et_interrupt, 0, "et Trubine", NULL)) {
			printk(KERN_ERR ET_MSG "couldn't register interrupts\n");
			goto abort_remove_proc;
    }
	et_init_gpt();

    printk(KERN_INFO "ET Display Driver v%s loaded ET_TIN irq %d\n", 
		ET_VERSION, ET_PORT_TO_IRQ(ET_TIN) );

	intr->main_mask &= ~(0x000000ff);	/* enable timer ints */
    printk(KERN_INFO "et_init 00 intr->per_mask  %08x\n", intr->per_mask);
    printk(KERN_INFO "et_init 10 intr->ctrl      %08x\n", intr->ctrl);
    printk(KERN_INFO "et_init 14 intr->main_mask %08x\n", intr->main_mask);
    printk(KERN_INFO "et_init 24 intr->enc_stat  %08x\n", intr->enc_status);
    printk(KERN_INFO "et_init 28 intr->crit_stat %08x\n", intr->crit_status);
    printk(KERN_INFO "et_init 2c intr->main_stat %08x\n", intr->main_status);
    printk(KERN_INFO "et_init 30 intr->per_stat  %08x\n", intr->per_status);
    printk(KERN_INFO "et_init 38 intr->per_error %08x\n", intr->per_error);

	sti();

/*
    volatile u32        per_mask;    // INTR + 0x00 
    volatile u32        per_pri1;    // INTR + 0x04
    volatile u32        per_pri2;    // INTR + 0x08
    volatile u32        per_pri3;    // INTR + 0x0c
    volatile u32        ctrl;        // INTR + 0x10
    volatile u32        main_mask;   // INTR + 0x14
    volatile u32        main_pri1;   // INTR + 0x18
    volatile u32        main_pri2;   // INTR + 0x1c
    volatile u32        reserved1;   // INTR + 0x20
    volatile u32        enc_status;  // INTR + 0x24
    volatile u32        crit_status; // INTR + 0x28
    volatile u32        main_status; // INTR + 0x2c
    volatile u32        per_status;  // INTR + 0x30
    volatile u32        reserved2;   // INTR + 0x34
    volatile u32        per_error;   // INTR + 0x38
*/

    return 0;
	
 abort_remove_proc:
    remove_proc_entry(ET_NAME,  NULL);
 abort_unregister:
    unregister_chrdev(major, ET_NAME);	
 abort:
    return ret;
}

static void __devexit et_cleanup (void)
{
    free_irq(ET_PORT_TO_IRQ(ET_TIN), NULL);
    remove_proc_entry(ET_NAME,  NULL);
    unregister_chrdev(major, ET_NAME);
    printk(KERN_INFO "ET Display Driver v%s unloaded\n", ET_VERSION);
}

EXPORT_NO_SYMBOLS;

module_init(et_init)
module_exit(et_cleanup)


             reply	other threads:[~2006-02-24 15:59 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-24 15:59 bennett78 [this message]
2006-02-24 22:49 ` mpc5200 timer3 Interrupts stopped working bennett78

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43FF2D69.3030902@digis.net \
    --to=bennett78@digis.net \
    --cc=linuxppc-embedded@ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.