FIQ interrupts and IRQCHIP

This forum is for users of Atmel's SAM Series and who are interested in using Linux OS.

Moderator: nferre

J4x
Posts: 11
Joined: Thu Jun 22, 2017 8:00 pm

FIQ interrupts and IRQCHIP

Tue Jul 04, 2017 9:11 pm

Dear colleagues,

It seems that SAM SoCs have been ported to the "irqchip" subsystem quite a long time ago.

All material I could gather about FIQ interrupts are either considering an older kernel either targeting a different platform.

This classic reference "FIQ Handlers in the ARM Linux Kernel" makes FIQ stuff seem a piece of cake, but targets iMX's.
This other one "SPI 16 / 32 bits_per_word transfers fail" deals with SAMA5D3 and kernel 3.15 in a very low level manner that surely hurts the "irqchip" effort.

Well, I am really confused.

I have tried to follow both approaches to learn something and try to find out which one is going to give me any results but, up to now, I haven't moved as far as I needed.

The low level approach seems to be trying to vainly fight against kernel protection while I haven't been able to make the simple and high level "set_fiq_handler" from free-electrons work for me.

Surely I am missing something.

Could anybody here please point me any working example for FIQ in an Atmel SoC using any 4.x kernel that I could take as basis or give any further directions?

Thanks in advance.
J4x
Posts: 11
Joined: Thu Jun 22, 2017 8:00 pm

[SOLVED] FIQ interrupts and IRQCHIP

Thu Jul 06, 2017 7:51 pm

I got to make my FIQ work

There are some caveats, though, and I'll share with you..

1) It looks like someone at Atmel forgot to add a dependency for FIQ in "kernel-source/arch/arm/mach-at91/Kconfig".

I haven't performed a thorough investigation and I don't want to blame anyone but all I can say is that my Kconfig had none and I fixed that with:

Code: Select all

menuconfig ARCH_AT91
	bool "Atmel SoCs"
	depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7
	select ARCH_REQUIRE_GPIOLIB
	select COMMON_CLK_AT91
	select PINCTRL
	select PINCTRL_AT91
	select SOC_BUS
	select FIQ  <== Added this line.
Withou this, `fiq.c` is not compiled and even the most perfect code won't work.

Code: Select all

j4x: Unknown symbol claim_fiq (err 0)
j4x: Unknown symbol enable_fiq (err 0)
j4x: Unknown symbol set_fiq_handler (err 0)
2) Every production code I could find makes FIQ routine in Assembly. I could find a few people telling that it is possible to make it in C but the very few examples I could gather start from a "naked" function and inline-asm the entry and exit, with a small C core in it.

In particular one example found HERE makes it and gives some precious advices.

Nevertheless, I tend to use C just because I need to learn one thing at a time, and ARM Assembly can be left for later.

(To be honest, right now my FIQ handler is just a bunch of bytes in an array compiled from the simplest assembly needed to make it doubtlessly run - it turns on an LED.)

========================================
Finally, the code:

Code: Select all

unsigned int _fiq_routine_[] = {
 	0xe599b000,	// ldr	fp, [r9]
 	0xe3a0b001,	// mov	fp, #1
 	0xe588b000,	// str	fp, [r8]
 	0xe3a0c401,	// mov   r12, #16777216
 	0xe58ac030, 	// str   r12, [r10, #0x0030]
 	0xe25ef004,	// subs  pc, lr, #4
};

int	fiq_init ( void )
{
	struct pt_regs    regs;
	u32               dummy;
	int               result = claim_fiq( &fh );

	if ( result )
	{
		pr_alert( "Couldn't claim FIQ: %d.\n", result );
		return result;
	}

	set_fiq_handler( &_fiq_routine_, sizeof( _fiq_routine_ ) );

	local_irq_disable ();
	local_fiq_disable();

	// load r8 with base address of AIC
	regs.ARM_r8   = ( long ) &aic->iccr; // ioremap'ed ICCR register.
	regs.ARM_r9  = tcb->regs + ATMEL_TC_REG ( TC_CH_NO, SR );

   	set_fiq_regs( &regs );

	// Fast Force TC IRQ to be FIQ.
	// - must be done by direct access to AIC registers.
	__raw_writel( IRQ_PID( TC_IRQ_NO ), &aic->ffer );

	if ( 0 == ( IRQ_PID( TC_IRQ_NO ) & dummy ) )
	{
		pr_alert( "Fast Forcing activation failed for PID: %i\n", TC_IRQ_NO );
		return -EIO;
	}

	local_fiq_enable ();
	local_irq_enable ();

	return 0;
}

Return to “Linux”

Who is online

Users browsing this forum: Google [Bot] and 1 guest