LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Kernel (https://www.linuxquestions.org/questions/linux-kernel-70/)
-   -   About use FIQ for SPI slave in device driver. (https://www.linuxquestions.org/questions/linux-kernel-70/about-use-fiq-for-spi-slave-in-device-driver-839452/)

jason222333 10-20-2010 10:54 PM

About use FIQ for SPI slave in device driver.
 
Hi, I want to used FIQ for spi slave ISR.
when I set VICIntSelect for fiq and enable VICIntEnable for fiq.
Can I used FIQ to execute spi_ISR?
or need to modify VectAddr or orther?

Thanks!!

Mara 10-23-2010 04:56 PM

You can. You just need to add your handler to the handlers run at the right interrupt. You're working on ARM, right?

jason222333 10-24-2010 09:04 PM

But linux seem can't used fiq, and fiq only used simple capability.

This is fig.c in linux,I don't know how do used this function?

/*
* linux/arch/arm/kernel/fiq.c
*
* Copyright (C) 1998 Russell King
* Copyright (C) 1998, 1999 Phil Blundell
*
* FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
*
* FIQ support re-written by Russell King to be more generic
*
* We now properly support a method by which the FIQ handlers can
* be stacked onto the vector. We still do not support sharing
* the FIQ vector itself.
*
* Operation is as follows:
* 1. Owner A claims FIQ:
* - default_fiq relinquishes control.
* 2. Owner A:
* - inserts code.
* - sets any registers,
* - enables FIQ.
* 3. Owner B claims FIQ:
* - if owner A has a relinquish function.
* - disable FIQs.
* - saves any registers.
* - returns zero.
* 4. Owner B:
* - inserts code.
* - sets any registers,
* - enables FIQ.
* 5. Owner B releases FIQ:
* - Owner A is asked to reacquire FIQ:
* - inserts code.
* - restores saved registers.
* - enables FIQ.
* 6. Goto 3
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/seq_file.h>

#include <asm/cacheflush.h>
#include <asm/fiq.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#warning This file requires GCC 3.3.x or older to build. Alternatively,
#warning please talk to GCC people to resolve the issues with the
#warning assembly clobber list.
#endif

static unsigned long no_fiq_insn;

/* Default reacquire function
* - we always relinquish FIQ control
* - we always reacquire FIQ control
*/
static int fiq_def_op(void *ref, int relinquish)
{
if (!relinquish)
set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn));

return 0;
}

static struct fiq_handler default_owner = {
.name = "default",
.fiq_op = fiq_def_op,
};

static struct fiq_handler *current_fiq = &default_owner;

int show_fiq_list(struct seq_file *p, void *v)
{
if (current_fiq != &default_owner)
seq_printf(p, "FIQ: %s\n", current_fiq->name);

return 0;
}

void set_fiq_handler(void *start, unsigned int length)
{
memcpy((void *)0xffff001c, start, length);
flush_icache_range(0xffff001c, 0xffff001c + length);
if (!vectors_high())
flush_icache_range(0x1c, 0x1c + length);
}

/*
* Taking an interrupt in FIQ mode is death, so both these functions
* disable irqs for the duration.
*/
void set_fiq_regs(struct pt_regs *regs)
{
register unsigned long tmp;
__asm__ volatile (
"mrs %0, cpsr\n\
msr cpsr_c, %2 @ select FIQ mode\n\
mov r0, r0\n\
ldmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
mov r0, r0"
: "=&r" (tmp)
: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
so that GCC won't put any of the input or output operands in
them. */
: "r8", "r9", "r10", "r11", "r12", "r13", "r14");
}

void get_fiq_regs(struct pt_regs *regs)
{
register unsigned long tmp;
__asm__ volatile (
"mrs %0, cpsr\n\
msr cpsr_c, %2 @ select FIQ mode\n\
mov r0, r0\n\
stmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
mov r0, r0"
: "=&r" (tmp)
: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
so that GCC won't put any of the input or output operands in
them. */
: "r8", "r9", "r10", "r11", "r12", "r13", "r14");
}

int claim_fiq(struct fiq_handler *f)
{
int ret = 0;

if (current_fiq) {
ret = -EBUSY;

if (current_fiq->fiq_op != NULL)
ret = current_fiq->fiq_op(current_fiq->dev_id, 1);
}

if (!ret) {
f->next = current_fiq;
current_fiq = f;
}

return ret;
}

void release_fiq(struct fiq_handler *f)
{
if (current_fiq != f) {
printk(KERN_ERR "%s FIQ trying to release %s FIQ\n",
f->name, current_fiq->name);
dump_stack();
return;
}

do
current_fiq = current_fiq->next;
while (current_fiq->fiq_op(current_fiq->dev_id, 0));
}

void enable_fiq(int fiq)
{
enable_irq(fiq + FIQ_START);
}

void disable_fiq(int fiq)
{
disable_irq(fiq + FIQ_START);
}

EXPORT_SYMBOL(set_fiq_handler);
EXPORT_SYMBOL(set_fiq_regs);
EXPORT_SYMBOL(get_fiq_regs);
EXPORT_SYMBOL(claim_fiq);
EXPORT_SYMBOL(release_fiq);
EXPORT_SYMBOL(enable_fiq);
EXPORT_SYMBOL(disable_fiq);

void __init init_FIQ(void)
{
no_fiq_insn = *(unsigned long *)0xffff001c;
}

jason222333 10-24-2010 09:05 PM

and this use for camera.

static struct fiq_handler fh = {
.name = "csi_sof"
};




static int __init imx_camera_probe(struct platform_device *pdev)

/* request irq */
err = claim_fiq(&fh);
if (err) {
dev_err(pcdev->dev, "Camera interrupt register failed \n");
goto exit;
}


set_fiq_handler(&imx_camera_sof_fiq_start, &imx_camera_sof_fiq_end - &imx_camera_sof_fiq_start);
//void *start, unsigned int length


regs.ARM_r8 = DMA_BASE + DMA_DIMR; /* Interrupt mask Register */
regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan); /* Control Registers */
regs.ARM_r10 = (long)pcdev->base + CSICR1; /* CSI Control Register 1 */
regs.ARM_fp = (long)pcdev->base + CSISR; /* CSI Status Register ?*/
regs.ARM_sp = 1 << pcdev->dma_chan; /* CSI Status Register ?*/
set_fiq_regs(&regs);


mxc_set_irq_fiq(irq, 1);


enable_fiq(irq);




static int __exit imx_camera_remove(struct platform_device *pdev)

disable_fiq(irq);
mxc_set_irq_fiq(irq, 0);
release_fiq(&fh);




extern unsigned char imx_camera_sof_fiq_start, imx_camera_sof_fiq_end;



+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+ .global imx_camera_sof_fiq_end
+ .global imx_camera_sof_fiq_start
+imx_camera_sof_fiq_start:
+ @ enable dma
+ ldr r12, [r9]
+ orr r12, r12, #0x00000001
+ str r12, [r9]
+ @ unmask DMA interrupt
+ ldr r12, [r8]
+ bic r12, r12, r13
+ str r12, [r8]
+ @ disable SOF interrupt
+ ldr r12, [r10]
+ bic r12, r12, #0x00010000
+ str r12, [r10]
+ @ clear SOF flag
+ mov r12, #0x00010000
+ str r12, [r11]
+ @ return from FIQ
+ subs pc, lr, #4
+imx_camera_sof_fiq_end:

Mara 10-25-2010 02:37 PM

You need to use claim_fiq.


All times are GMT -5. The time now is 03:57 AM.