2005-04-17 02:20:36 +04:00
# ifndef _ASM_IO_H
# define _ASM_IO_H
# include <linux/string.h>
# include <linux/compiler.h>
/*
* This file contains the definitions for the x86 IO instructions
* inb / inw / inl / outb / outw / outl and the " string versions " of the same
* ( insb / insw / insl / outsb / outsw / outsl ) . You can also use " pausing "
* versions of the single - IO instructions ( inb_p / inw_p / . . ) .
*
* This file is not meant to be obfuscating : it ' s just complicated
* to ( a ) handle it all in a way that makes gcc able to optimize it
* as well as possible and ( b ) trying to avoid writing the same thing
* over and over again with slight variations and possibly making a
* mistake somewhere .
*/
/*
* Thanks to James van Artsdalen for a better timing - fix than
* the two short jumps : using outb ' s to a nonexistent port seems
* to guarantee better timings even on fast machines .
*
* On the other hand , I ' d like to be sure of a non - existent port :
* I feel a bit unsafe about using 0x80 ( should be safe , though )
*
* Linus
*/
/*
* Bit simplified and optimized by Jan Hubicka
* Support of BIGMEM added by Gerhard Wichert , Siemens AG , July 1999.
*
* isa_memset_io , isa_memcpy_fromio , isa_memcpy_toio added ,
* isa_read [ wl ] and isa_write [ wl ] fixed
* - Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
*/
# define IO_SPACE_LIMIT 0xffff
# define XQUAD_PORTIO_BASE 0xfe400000
# define XQUAD_PORTIO_QUAD 0x40000 /* 256k per quad. */
# ifdef __KERNEL__
# include <asm-generic/iomap.h>
# include <linux/vmalloc.h>
/*
* Convert a physical pointer to a virtual kernel pointer for / dev / mem
* access
*/
# define xlate_dev_mem_ptr(p) __va(p)
/*
* Convert a virtual cached pointer to an uncached pointer
*/
# define xlate_dev_kmem_ptr(p) p
/**
* virt_to_phys - map virtual addresses to physical
* @ address : address to remap
*
* The returned physical address is the physical ( CPU ) mapping for
* the memory address given . It is only valid to use this function on
* addresses directly mapped or allocated via kmalloc .
*
* This function does not give bus mappings for DMA transfers . In
* almost all conceivable cases a device driver should not be using
* this function
*/
static inline unsigned long virt_to_phys ( volatile void * address )
{
return __pa ( address ) ;
}
/**
* phys_to_virt - map physical address to virtual
* @ address : address to remap
*
* The returned virtual address is a current CPU mapping for
* the memory address given . It is only valid to use this function on
* addresses that have a kernel mapping
*
* This function does not handle bus mappings for DMA transfers . In
* almost all conceivable cases a device driver should not be using
* this function
*/
static inline void * phys_to_virt ( unsigned long address )
{
return __va ( address ) ;
}
/*
* Change " struct page " to physical address .
*/
# define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
/**
* ioremap - map bus memory into CPU space
* @ offset : bus address of the memory
* @ size : size of the resource to map
*
* ioremap performs a platform specific sequence of operations to
* make bus memory CPU accessible via the readb / readw / readl / writeb /
* writew / writel functions and the other mmio helpers . The returned
* address is not guaranteed to be usable directly as a virtual
2008-01-30 15:33:40 +03:00
* address .
2007-07-20 04:48:44 +04:00
*
* If the area you are trying to map is a PCI BAR you should have a
* look at pci_iomap ( ) .
2005-04-17 02:20:36 +04:00
*/
2008-01-30 15:34:06 +03:00
extern void __iomem * ioremap_nocache ( unsigned long offset , unsigned long size ) ;
extern void __iomem * ioremap_cache ( unsigned long offset , unsigned long size ) ;
2005-04-17 02:20:36 +04:00
2008-01-30 15:33:40 +03:00
/*
* The default ioremap ( ) behavior is non - cached :
*/
2008-01-30 15:34:06 +03:00
static inline void __iomem * ioremap ( unsigned long offset , unsigned long size )
2008-01-30 15:33:40 +03:00
{
return ioremap_nocache ( offset , size ) ;
}
2005-04-17 02:20:36 +04:00
extern void iounmap ( volatile void __iomem * addr ) ;
/*
2008-01-30 15:33:44 +03:00
* early_ioremap ( ) and early_iounmap ( ) are for temporary early boot - time
2005-04-17 02:20:36 +04:00
* mappings , before the real ioremap ( ) is functional .
* A boot - time mapping is currently limited to at most 16 pages .
*/
2008-01-30 15:33:44 +03:00
extern void early_ioremap_init ( void ) ;
extern void early_ioremap_clear ( void ) ;
extern void early_ioremap_reset ( void ) ;
extern void * early_ioremap ( unsigned long offset , unsigned long size ) ;
extern void early_iounmap ( void * addr , unsigned long size ) ;
serial: convert early_uart to earlycon for 8250
Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and
include/asm-x86_64/serial.h. the serial8250_ports need to be probed late in
serial initializing stage. the console_init=>serial8250_console_init=>
register_console=>serial8250_console_setup will return -ENDEV, and console
ttyS0 can not be enabled at that time. need to wait till uart_add_one_port in
drivers/serial/serial_core.c to call register_console to get console ttyS0.
that is too late.
Make early_uart to use early_param, so uart console can be used earlier. Make
it to be bootconsole with CON_BOOT flag, so can use console handover feature.
and it will switch to corresponding normal serial console automatically.
new command line will be:
console=uart8250,io,0x3f8,9600n8
console=uart8250,mmio,0xff5e0000,115200n8
or
earlycon=uart8250,io,0x3f8,9600n8
earlycon=uart8250,mmio,0xff5e0000,115200n8
it will print in very early stage:
Early serial console at I/O port 0x3f8 (options '9600n8')
console [uart0] enabled
later for console it will print:
console handover: boot [uart0] -> real [ttyS0]
Signed-off-by: <yinghai.lu@sun.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Gerd Hoffmann <kraxel@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-16 10:37:59 +04:00
extern void __iomem * fix_ioremap ( unsigned idx , unsigned long phys ) ;
2005-04-17 02:20:36 +04:00
2006-01-12 00:43:33 +03:00
/* Use early IO mappings for DMI because it's initialized early */
2008-01-30 15:33:44 +03:00
# define dmi_ioremap early_ioremap
# define dmi_iounmap early_iounmap
2006-01-12 00:43:33 +03:00
# define dmi_alloc alloc_bootmem
2005-04-17 02:20:36 +04:00
/*
* ISA I / O bus memory addresses are 1 : 1 with the physical address .
*/
# define isa_virt_to_bus virt_to_phys
# define isa_page_to_bus page_to_phys
# define isa_bus_to_virt phys_to_virt
/*
* However PCI ones are not necessarily 1 : 1 and therefore these interfaces
* are forbidden in portable PCI drivers .
*
* Allow them on x86 for legacy drivers , though .
*/
# define virt_to_bus virt_to_phys
# define bus_to_virt phys_to_virt
/*
* readX / writeX ( ) are used to access memory mapped devices . On some
* architectures the memory mapped IO stuff needs to be accessed
* differently . On the x86 architecture , we just read / write the
* memory location directly .
*/
static inline unsigned char readb ( const volatile void __iomem * addr )
{
return * ( volatile unsigned char __force * ) addr ;
}
static inline unsigned short readw ( const volatile void __iomem * addr )
{
return * ( volatile unsigned short __force * ) addr ;
}
static inline unsigned int readl ( const volatile void __iomem * addr )
{
return * ( volatile unsigned int __force * ) addr ;
}
# define readb_relaxed(addr) readb(addr)
# define readw_relaxed(addr) readw(addr)
# define readl_relaxed(addr) readl(addr)
# define __raw_readb readb
# define __raw_readw readw
# define __raw_readl readl
static inline void writeb ( unsigned char b , volatile void __iomem * addr )
{
* ( volatile unsigned char __force * ) addr = b ;
}
static inline void writew ( unsigned short b , volatile void __iomem * addr )
{
* ( volatile unsigned short __force * ) addr = b ;
}
static inline void writel ( unsigned int b , volatile void __iomem * addr )
{
* ( volatile unsigned int __force * ) addr = b ;
}
# define __raw_writeb writeb
# define __raw_writew writew
# define __raw_writel writel
# define mmiowb()
2007-10-17 20:04:39 +04:00
static inline void
memset_io ( volatile void __iomem * addr , unsigned char val , int count )
2005-04-17 02:20:36 +04:00
{
2007-10-17 20:04:39 +04:00
memset ( ( void __force * ) addr , val , count ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-17 20:04:39 +04:00
static inline void
memcpy_fromio ( void * dst , const volatile void __iomem * src , int count )
2005-04-17 02:20:36 +04:00
{
2007-10-17 20:04:39 +04:00
__memcpy ( dst , ( const void __force * ) src , count ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-17 20:04:39 +04:00
static inline void
memcpy_toio ( volatile void __iomem * dst , const void * src , int count )
2005-04-17 02:20:36 +04:00
{
2007-10-17 20:04:39 +04:00
__memcpy ( ( void __force * ) dst , src , count ) ;
2005-04-17 02:20:36 +04:00
}
/*
* ISA space is ' always mapped ' on a typical x86 system , no need to
* explicitly ioremap ( ) it . The fact that the ISA IO space is mapped
* to PAGE_OFFSET is pure coincidence - it does not mean ISA values
* are physical addresses . The following constant pointer can be
* used as the IO - area pointer ( it can be iounmapped as well , so the
* analogy with PCI is quite large ) :
*/
# define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
/*
* Cache management
*
* This needed for two cases
* 1. Out of order aware processors
* 2. Accidentally out of order processors ( PPro errata # 51 )
*/
# if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
static inline void flush_write_buffers ( void )
{
__asm__ __volatile__ ( " lock; addl $0,0(%%esp) " : : : " memory " ) ;
}
# else
2007-10-17 10:29:42 +04:00
# define flush_write_buffers() do { } while (0)
2005-04-17 02:20:36 +04:00
# endif
# endif /* __KERNEL__ */
2008-01-30 15:30:05 +03:00
extern void native_io_delay ( void ) ;
2007-05-02 21:27:10 +04:00
2008-01-30 15:30:05 +03:00
extern int io_delay_type ;
extern void io_delay_init ( void ) ;
2006-12-07 04:14:07 +03:00
# if defined(CONFIG_PARAVIRT)
# include <asm/paravirt.h>
2005-04-17 02:20:36 +04:00
# else
2006-12-07 04:14:07 +03:00
2005-04-17 02:20:36 +04:00
static inline void slow_down_io ( void ) {
2007-05-02 21:27:10 +04:00
native_io_delay ( ) ;
2005-04-17 02:20:36 +04:00
# ifdef REALLY_SLOW_IO
2007-05-02 21:27:10 +04:00
native_io_delay ( ) ;
native_io_delay ( ) ;
native_io_delay ( ) ;
2005-04-17 02:20:36 +04:00
# endif
}
2006-12-07 04:14:07 +03:00
# endif
2005-04-17 02:20:36 +04:00
# define __BUILDIO(bwl,bw,type) \
static inline void out # # bwl ( unsigned type value , int port ) { \
out # # bwl # # _local ( value , port ) ; \
} \
static inline unsigned type in # # bwl ( int port ) { \
return in # # bwl # # _local ( port ) ; \
}
# define BUILDIO(bwl,bw,type) \
static inline void out # # bwl # # _local ( unsigned type value , int port ) { \
__asm__ __volatile__ ( " out " # bwl " % " # bw " 0, %w1 " : : " a " ( value ) , " Nd " ( port ) ) ; \
} \
static inline unsigned type in # # bwl # # _local ( int port ) { \
unsigned type value ; \
__asm__ __volatile__ ( " in " # bwl " %w1, % " # bw " 0 " : " =a " ( value ) : " Nd " ( port ) ) ; \
return value ; \
} \
static inline void out # # bwl # # _local_p ( unsigned type value , int port ) { \
out # # bwl # # _local ( value , port ) ; \
slow_down_io ( ) ; \
} \
static inline unsigned type in # # bwl # # _local_p ( int port ) { \
unsigned type value = in # # bwl # # _local ( port ) ; \
slow_down_io ( ) ; \
return value ; \
} \
__BUILDIO ( bwl , bw , type ) \
static inline void out # # bwl # # _p ( unsigned type value , int port ) { \
out # # bwl ( value , port ) ; \
slow_down_io ( ) ; \
} \
static inline unsigned type in # # bwl # # _p ( int port ) { \
unsigned type value = in # # bwl ( port ) ; \
slow_down_io ( ) ; \
return value ; \
} \
static inline void outs # # bwl ( int port , const void * addr , unsigned long count ) { \
__asm__ __volatile__ ( " rep; outs " # bwl : " +S " ( addr ) , " +c " ( count ) : " d " ( port ) ) ; \
} \
static inline void ins # # bwl ( int port , void * addr , unsigned long count ) { \
__asm__ __volatile__ ( " rep; ins " # bwl : " +D " ( addr ) , " +c " ( count ) : " d " ( port ) ) ; \
}
BUILDIO ( b , b , char )
BUILDIO ( w , w , short )
BUILDIO ( l , , int )
# endif