Proposed changes to io.h

John Whitney johnw at sands-edge.com
Thu Apr 1 01:44:25 EST 2004


I've made few changes to include/asm-ppc/io.h that might want to be
incorporated into the mainline tree.  These changes include:

1. Modifications to virt_to_bus, bus_to_virt, virt_to_phys, and
phys_to_virt.  With the use of fully virtual addresses for
cache-coherent allocations (consistent_alloc(), etc.), just subracting
KERNELBASE from the virtual address is no longer sufficient.  Because
of this, I have modified virt_to_phys and phys_to_virt to look like:

extern inline unsigned long virt_to_phys(volatile void * address)
{
     unsigned long phys_addr;
     unsigned long virt_addr = (unsigned long) address;

#ifndef CONFIG_APUS
     if ((virt_addr >= KERNELBASE) && (virt_addr < (unsigned long)
high_memory))
         phys_addr = (virt_addr - KERNELBASE);
     else
         phys_addr = iopa (virt_addr);
#else
     phys_addr = iopa (virt_addr);
#endif

     return phys_addr;
}

extern inline void * phys_to_virt(unsigned long address)
{
#ifndef CONFIG_APUS
     return (void *) (address + KERNELBASE);
#else
     return (void*) mm_ptov (address);
#endif
}

And I have modified virt_to_bus and bus_to_virt to use those inlined
functions:

extern inline unsigned long virt_to_bus(volatile void * address)
{
     if (address == (void *) 0)
         return 0;

     return virt_to_phys (address) + PCI_DRAM_OFFSET;
}

extern inline void * bus_to_virt(unsigned long address)
{
     if (address == 0)
         return 0;

     return phys_to_virt (address - PCI_DRAM_OFFSET);
}

This simplifies the "bus" routines, and makes sure that they use the
standard virtual/physical translations.


2. I'd like to add 64-bit __raw_readll and __raw_writell routines to
io.h, done using floating-point registers.  Currently, modules such as
MTD (when writing to 64-bit buses) perform two 32-bit, non-atomic
writes, which can cause problems.  Using a floating-point register to
guarantee a 64-bit write is ugly, but it works.  Code for these inlined
routines is 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.
  */
#define __raw_readll __raw_readll
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;
}

#define __raw_writell __raw_writell
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;
}


Questions, comments, or flames?

John Whitney
-------------- next part --------------
A non-text attachment was scrubbed...
Name: io.h.patch
Type: application/octet-stream
Size: 4949 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20040331/4e07aec6/attachment.obj>


More information about the Linuxppc-dev mailing list