On ARM FIQ interrupts, we have some registers reserved only for FIQ use, and those are a handy way to "save the state" for example of data transfer between FIQ calls.
Currently I'm triggering some GPIO
pins from the FIQ, and it is working as expected. When setting up the FIQ handler, I pass the pointers to the data registers, that were mapped with ioremap. Working code looks like this:
//Driver initialization:
static char* dout0;
static char* din0;
...
static int driver_probe(struct platform_device *pdev)
{
struct pt_regs regs;
...
dout0 = ioremap(HW_PINCTRL_DOUT0, 0xffff);
din0 = ioremap(HW_PINCTRL_DIN0, 0xffff);
...
regs.ARM_r8 = (long) dout0;
regs.ARM_r9 = (long) din0;
set_fiq_regs(®s);
...
//In the FIQ handler:
LDR r12, [r8]
ORR r12, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8]
The above code performs as expected, the pin 5
is set high after FIQ handler is executed.
For more complicated operation, I want to prepare a struct, that will hold data-pointers, and other processing related data, including more mappings to different registers - and pass this to the FIQ handler. But something is going wrong there already when migrating the above code to this.
I modified the code above to look like this
//In Driver:
struct fiq_processing {
char* din0;
char* dout0;
};
static fiq_processing * pdata; //Pointer to our processing data structure
...
static int driver_probe(struct platform_device *pdev)
{
struct pt_regs regs;
pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); //Allocate memory for struct
printk("Size of the data struct %d \n", sizeof(*pdata)); //I get "8" as the size
...
pdata->din0 = ioremap(HW_PINCTRL_DIN0, 0xffff);
pdata->dout0 = ioremap(HW_PINCTRL_DOUT0, 0xffff);
...
regs.ARM_r8 = (long) pdata;
set_fiq_regs(®s);
...
//In the FIQ handler:
#define OFFSET_DIN0 0x0
#define OFFSET_DOUT0 0x4 //We know size is 8, so offset for dout is half from that
...
LDR r12, [r8, #OFFSET_DOUT0]
ORR r12, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8, #OFFSET_DOUT0] /* This will do nothing ? */
After I have allocated the memory for the structure, and mapped the register pointers, I pass the address for pdata structure to the FIQ handler.
In the FIQ handler, I have offsets for din0
and dout0
, which I have thought to be 0x0
and 0x4
respectively (deducted from the structure size of 8).
But for some reason, now my FIQ is unable to set the output pin high anymore - I can't figure out what I'm doing wrong here..
Am I calculating the offset wrong there ? OR is the call STR r12, [r8, #OFFSET_DOUT0]
incorrect ?
The actual FIQ is somewhat more longer (it reads input state, and input from that creates some conditions), but even basic bit set seems to fail now..