64-bit reads and writes
John Whitney
john.whitney at timesys.com
Fri Nov 21 06:43:08 EST 2003
I have a board with 4-way interleaved, 16-bit flash on a 64-bit data bus. I
need to ensure that I have one 64-bit read or write, not two 32-bit reads or
writes. To do this, I've used a floating point register in newly created
__raw_readll() and __raw_writell() (code below).
Effectively, I save the current MSR, and OR in MSR_FP to allow floating
point access. I save off FPR1, load my value into it, and use "stfdx" to
write the value out. Then I restore FPR1 and MSR to their original values.
Does anyone see any problems with this method, or have a better way of
accomplishing this?
The two routines are coded as follows:
/*
* For reading and writing 64-bit values, we need to use the floating point
* registers. The code will enable MSR_FP in the MSR register, use FPR1 to
* read from and write to memory, and then restore everything to the
* previous values.
*/
static inline unsigned long long __raw_readll (int addr)
{
unsigned long flags;
unsigned long msr;
unsigned long msr_save;
unsigned long long result;
unsigned long long fp_save;
local_irq_save (flags);
asm volatile ("sync\n"
"mfmsr %0\n"
"ori %1,%0,0x2000\n"
"mtmsr %1\n"
"isync\n"
"stfdx 1,0,%2\n"
"lfdx 1,0,%4\n"
"stfdx 1,0,%3\n"
"sync\n"
"lfdx 1,0,%2\n"
"mtmsr %0\n"
"sync\n"
"isync\n"
: "=&r" (msr_save), "=&r" (msr)
: "r" (&fp_save), "r" (&result), "r" (addr)
: "memory" );
local_irq_restore (flags);
return result;
}
static inline void __raw_writell (unsigned long long value, int addr)
{
unsigned long flags;
unsigned long msr;
unsigned long msr_save;
unsigned long long fp_save;
local_irq_save (flags);
asm volatile ("sync\n"
"mfmsr %0\n"
"ori %1,%0,0x2000\n"
"mtmsr %1\n"
"isync\n"
"stfdx 1,0,%2\n"
"lfdx 1,0,%3\n"
"stfdx 1,0,%4\n"
"sync\n"
"lfdx 1,0,%2\n"
"mtmsr %0\n"
"sync\n"
"isync\n"
: "=&r" (msr_save), "=&r" (msr)
: "r" (&fp_save), "r" (&value), "r" (addr)
: "memory" );
local_irq_restore (flags);
return;
}
John Whitney
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc-dev
mailing list