Re: ARM Linux at91: installing Timer Controller Interrupt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi there,

Thanks for the help.

This code works: 

/*
 * Kernel interrupt demo for Timer Channel 0
 * Author  : 
 * Date    : 24.02.2009
 * Version : 1.00
 * License : GPL
 */



#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/irq.h>
#include <linux/platform_device.h>
#include <linux/ioctl.h>

#include <asm/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/irq.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm-arm/arch-at91rm9200/hardware.h>
#include <asm-arm/arch-at91rm9200/at91rm9200_tc.h>
#include <asm-arm/arch-at91rm9200/at91rm9200.h>

#include <asm/uaccess.h>
#include <asm/arch/hardware.h> 
#include <asm/mach/time.h>


#include "adirq.h"
//#include "at91_timer.h"

#define AT91_TC0 0x00
#define AT91_TC1 0x40
#define AT91_TC2 0x80

#define AT91_TC3 0x00
#define AT91_TC4 0x40
#define AT91_TC5 0x80

static void __exit ad_irq_cleanup(void);

static volatile unsigned long ad_irq_count = 0;

#ifdef MODULE_AUTHOR
 MODULE_AUTHOR("Ole");
 MODULE_DESCRIPTION("AD Kernel interrupt module for DNP/9200");
 MODULE_LICENSE("GPL");
#endif






/* unload kernel module */
static void __exit ad_irq_cleanup(void) {
    /* unregister irq handler */
	free_irq(AT91_ID_TC0, NULL);
    printk(KERN_INFO "ad_irq module removed.\n");
}

/*
 * Read from Timerblock 0 registers.
 */
static inline unsigned long at91_tcb1_read(unsigned int reg)
{
	void __iomem *tcb1_base = (void __iomem *)AT91_VA_BASE_TCB0;
	printk(KERN_INFO "read p: %p + (%d)\n", tcb1_base, reg);

	return __raw_readl(tcb1_base + reg);
}

/*
 * Write to Timerblock 0 registers.
 */
static inline void at91_tcb1_write(unsigned int reg, unsigned long value)
{
	void __iomem *tcb1_base = (void __iomem *)AT91_VA_BASE_TCB0;
		printk(KERN_INFO "write p: %p + (%d)\n", tcb1_base, reg);

	__raw_writel(value, tcb1_base + reg);
}

/*
 * Read from Timerblock 1 registers.
 */
static inline unsigned long at91_tcb2_read(unsigned int reg)
{
	void __iomem *tcb2_base = (void __iomem *)AT91_VA_BASE_TCB1;


	return __raw_readl(tcb2_base + reg);
}

/*
 * Write to Timerblock 1 registers.
 */
static inline void at91_tcb2_write(unsigned int reg, unsigned long value)
{
	void __iomem *tcb2_base = (void __iomem *)AT91_VA_BASE_TCB1;

	__raw_writel(value, tcb2_base + reg);
}

/* irq timer routine */
irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
	unsigned int status; 

	// read & clear status: 
	status = at91_tcb1_read(AT91_TC0 + AT91_TC_SR);
	ad_irq_count++;
	return(IRQ_HANDLED);
}


static int __init ad_irq_init(void) 
{
	printk(KERN_INFO "init timer\n");

	// disable clock: 
	at91_tcb1_write(AT91_TC0 + AT91_TC_CCR,  ((at91_tcb1_read(AT91_TC0 +
AT91_TC_CCR) | 2) ) );

	// disable all Timer Channel 0 interrupts: 
	at91_tcb1_write(AT91_TC0 + AT91_TC_IDR, 0xFFFFFFFF  );

	// read & clear status: 
	at91_tcb1_read(AT91_TC0 + AT91_TC_SR );

	// enable timer clock 5, reset counter and start clock
	at91_tcb1_write(AT91_TC0 + AT91_TC_CMR, AT91_TC_TIMER_CLOCK4 | 
AT91_TC_CPCTRG | !AT91_TC_WAVE );


	 printk(KERN_INFO "CMR: %d\n", at91_tcb1_read(AT91_TC0 + AT91_TC_CMR) );

	// Enables the RC Compare Interrupt:
	at91_tcb1_write(AT91_TC0 + AT91_TC_IER, 0x10 );


	if (request_irq(AT91_ID_TC0, (void *)timer_interrupt, 0
,AD_IRQ_DEVICE_NAME, NULL)) {
        	printk(KERN_ERR "ad_irq: irq alrdy claimed!\n");
		return -EIO;
    }




	// write something to timer register c:
	at91_tcb1_write( AT91_TC0 + AT91_TC_RC , 0xFBC5 );

	// enable & start clock 
	at91_tcb1_write(AT91_TC0 + AT91_TC_CCR , 0x01 );
	at91_tcb1_write(AT91_TC0 + AT91_TC_CCR , 0x05 );

	// maybe sync is needed ? 
	at91_tcb1_write(AT91_TC0 + AT91_TC_BMR, 1 );

    printk(KERN_INFO "ad_irq module installed with irqnr=%d.\n",
AT91_ID_TC0);
    return 0;
}
EXPORT_NO_SYMBOLS;

module_init(ad_irq_init);
module_exit(ad_irq_cleanup);


On Tue, 24 Feb 2009 08:11:07 +0800, Peter Teoh <htmldeveloper@xxxxxxxxx>
wrote:

> it seemed there is either:
> 
> 1.   some missing registers not setup.
> 2.   or some of the register setup got its order wrong.

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux