2005-04-17 02:20:36 +04:00
/*
* linux / arch / arm / mach - footbridge / common . c
*
* Copyright ( C ) 1998 - 2000 Russell King , Dave Gilbert .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/ioport.h>
# include <linux/list.h>
# include <linux/init.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2008-12-06 11:25:16 +03:00
# include <linux/spinlock.h>
2012-03-02 06:48:12 +04:00
2005-04-17 02:20:36 +04:00
# include <asm/pgtable.h>
# include <asm/page.h>
# include <asm/irq.h>
# include <asm/mach-types.h>
# include <asm/setup.h>
2012-03-28 21:30:01 +04:00
# include <asm/system_misc.h>
2005-04-17 02:20:36 +04:00
# include <asm/hardware/dec21285.h>
# include <asm/mach/irq.h>
# include <asm/mach/map.h>
2012-03-02 06:48:12 +04:00
# include <asm/mach/pci.h>
2005-04-17 02:20:36 +04:00
# include "common.h"
unsigned int mem_fclk_21285 = 50000000 ;
EXPORT_SYMBOL ( mem_fclk_21285 ) ;
2010-01-12 01:17:34 +03:00
static int __init early_fclk ( char * arg )
2008-12-30 19:24:17 +03:00
{
2010-01-12 01:17:34 +03:00
mem_fclk_21285 = simple_strtoul ( arg , NULL , 0 ) ;
return 0 ;
2008-12-30 19:24:17 +03:00
}
2010-01-12 01:17:34 +03:00
early_param ( " mem_fclk_21285 " , early_fclk ) ;
2008-12-30 19:24:17 +03:00
2005-04-17 02:20:36 +04:00
static int __init parse_tag_memclk ( const struct tag * tag )
{
mem_fclk_21285 = tag - > u . memclk . fmemclk ;
return 0 ;
}
__tagtable ( ATAG_MEMCLK , parse_tag_memclk ) ;
/*
* Footbridge IRQ translation table
* Converts from our IRQ numbers into FootBridge masks
*/
static const int fb_irq_mask [ ] = {
IRQ_MASK_UART_RX , /* 0 */
IRQ_MASK_UART_TX , /* 1 */
IRQ_MASK_TIMER1 , /* 2 */
IRQ_MASK_TIMER2 , /* 3 */
IRQ_MASK_TIMER3 , /* 4 */
IRQ_MASK_IN0 , /* 5 */
IRQ_MASK_IN1 , /* 6 */
IRQ_MASK_IN2 , /* 7 */
IRQ_MASK_IN3 , /* 8 */
IRQ_MASK_DOORBELLHOST , /* 9 */
IRQ_MASK_DMA1 , /* 10 */
IRQ_MASK_DMA2 , /* 11 */
IRQ_MASK_PCI , /* 12 */
IRQ_MASK_SDRAMPARITY , /* 13 */
IRQ_MASK_I2OINPOST , /* 14 */
IRQ_MASK_PCI_ABORT , /* 15 */
IRQ_MASK_PCI_SERR , /* 16 */
IRQ_MASK_DISCARD_TIMER , /* 17 */
IRQ_MASK_PCI_DPERR , /* 18 */
IRQ_MASK_PCI_PERR , /* 19 */
} ;
2010-11-29 12:30:13 +03:00
static void fb_mask_irq ( struct irq_data * d )
2005-04-17 02:20:36 +04:00
{
2010-11-29 12:30:13 +03:00
* CSR_IRQ_DISABLE = fb_irq_mask [ _DC21285_INR ( d - > irq ) ] ;
2005-04-17 02:20:36 +04:00
}
2010-11-29 12:30:13 +03:00
static void fb_unmask_irq ( struct irq_data * d )
2005-04-17 02:20:36 +04:00
{
2010-11-29 12:30:13 +03:00
* CSR_IRQ_ENABLE = fb_irq_mask [ _DC21285_INR ( d - > irq ) ] ;
2005-04-17 02:20:36 +04:00
}
2006-11-23 14:41:32 +03:00
static struct irq_chip fb_chip = {
2010-11-29 12:30:13 +03:00
. irq_ack = fb_mask_irq ,
. irq_mask = fb_mask_irq ,
. irq_unmask = fb_unmask_irq ,
2005-04-17 02:20:36 +04:00
} ;
static void __init __fb_init_irq ( void )
{
unsigned int irq ;
/*
* setup DC21285 IRQs
*/
* CSR_IRQ_DISABLE = - 1 ;
* CSR_FIQ_DISABLE = - 1 ;
for ( irq = _DC21285_IRQ ( 0 ) ; irq < _DC21285_IRQ ( 20 ) ; irq + + ) {
2011-03-24 15:35:09 +03:00
irq_set_chip_and_handler ( irq , & fb_chip , handle_level_irq ) ;
2005-04-17 02:20:36 +04:00
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
}
void __init footbridge_init_irq ( void )
{
__fb_init_irq ( ) ;
if ( ! footbridge_cfn_mode ( ) )
return ;
if ( machine_is_ebsa285 ( ) )
/* The following is dependent on which slot
* you plug the Southbridge card into . We
* currently assume that you plug it into
* the right - hand most slot .
*/
isa_init_irq ( IRQ_PCI ) ;
if ( machine_is_cats ( ) )
isa_init_irq ( IRQ_IN2 ) ;
if ( machine_is_netwinder ( ) )
isa_init_irq ( IRQ_IN3 ) ;
}
/*
* Common mapping for all systems . Note that the outbound write flush is
* commented out since there is a " No Fix " problem with it . Not mapping
* it means that we have extra bullet protection on our feet .
*/
static struct map_desc fb_common_io_desc [ ] __initdata = {
2005-10-28 18:19:08 +04:00
{
. virtual = ARMCSR_BASE ,
2005-11-13 12:53:34 +03:00
. pfn = __phys_to_pfn ( DC21285_ARMCSR_BASE ) ,
2005-10-28 18:19:08 +04:00
. length = ARMCSR_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
2005-10-28 18:19:08 +04:00
} , {
. virtual = XBUS_BASE ,
. pfn = __phys_to_pfn ( 0x40000000 ) ,
. length = XBUS_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
2005-10-28 18:19:08 +04:00
}
2005-04-17 02:20:36 +04:00
} ;
/*
* The mapping when the footbridge is in host mode . We don ' t map any of
* this when we are in add - in mode .
*/
static struct map_desc ebsa285_host_io_desc [ ] __initdata = {
# if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
2005-10-28 18:19:08 +04:00
{
. virtual = PCIMEM_BASE ,
. pfn = __phys_to_pfn ( DC21285_PCI_MEM ) ,
. length = PCIMEM_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
2005-10-28 18:19:08 +04:00
} , {
. virtual = PCICFG0_BASE ,
. pfn = __phys_to_pfn ( DC21285_PCI_TYPE_0_CONFIG ) ,
. length = PCICFG0_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
2005-10-28 18:19:08 +04:00
} , {
. virtual = PCICFG1_BASE ,
. pfn = __phys_to_pfn ( DC21285_PCI_TYPE_1_CONFIG ) ,
. length = PCICFG1_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
2005-10-28 18:19:08 +04:00
} , {
. virtual = PCIIACK_BASE ,
. pfn = __phys_to_pfn ( DC21285_PCI_IACK ) ,
. length = PCIIACK_SIZE ,
2005-11-12 19:49:37 +03:00
. type = MT_DEVICE ,
} ,
2005-04-17 02:20:36 +04:00
# endif
} ;
void __init footbridge_map_io ( void )
{
/*
* Set up the common mapping first ; we need this to
* determine whether we ' re in host mode or not .
*/
iotable_init ( fb_common_io_desc , ARRAY_SIZE ( fb_common_io_desc ) ) ;
/*
* Now , work out what we ' ve got to map in addition on this
* platform .
*/
2012-03-02 06:48:12 +04:00
if ( footbridge_cfn_mode ( ) ) {
2005-04-17 02:20:36 +04:00
iotable_init ( ebsa285_host_io_desc , ARRAY_SIZE ( ebsa285_host_io_desc ) ) ;
2012-03-02 06:48:12 +04:00
pci_map_io_early ( __phys_to_pfn ( DC21285_PCI_IO ) ) ;
}
2005-04-17 02:20:36 +04:00
}
2011-11-03 23:47:54 +04:00
void footbridge_restart ( char mode , const char * cmd )
{
if ( mode = = ' s ' ) {
/* Jump into the ROM */
soft_restart ( 0x41000000 ) ;
} else {
/*
* Force the watchdog to do a CPU reset .
*
* After making sure that the watchdog is disabled
* ( so we can change the timer registers ) we first
* enable the timer to autoreload itself . Next , the
* timer interval is set really short and any
* current interrupt request is cleared ( so we can
* see an edge transition ) . Finally , TIMER4 is
* enabled as the watchdog .
*/
* CSR_SA110_CNTL & = ~ ( 1 < < 13 ) ;
* CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
TIMER_CNTL_AUTORELOAD |
TIMER_CNTL_DIV16 ;
* CSR_TIMER4_LOAD = 0x2 ;
* CSR_TIMER4_CLR = 0 ;
* CSR_SA110_CNTL | = ( 1 < < 13 ) ;
}
}
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_FOOTBRIDGE_ADDIN
2009-12-12 17:53:08 +03:00
static inline unsigned long fb_bus_sdram_offset ( void )
{
return * CSR_PCISDRAMBASE & 0xfffffff0 ;
}
2005-04-17 02:20:36 +04:00
/*
* These two functions convert virtual addresses to PCI addresses and PCI
* addresses to virtual addresses . Note that it is only legal to use these
* on memory obtained via get_zeroed_page or kmalloc .
*/
unsigned long __virt_to_bus ( unsigned long res )
{
WARN_ON ( res < PAGE_OFFSET | | res > = ( unsigned long ) high_memory ) ;
2009-12-12 17:53:08 +03:00
return res + ( fb_bus_sdram_offset ( ) - PAGE_OFFSET ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( __virt_to_bus ) ;
unsigned long __bus_to_virt ( unsigned long res )
{
2009-12-12 17:53:08 +03:00
res = res - ( fb_bus_sdram_offset ( ) - PAGE_OFFSET ) ;
2005-04-17 02:20:36 +04:00
WARN_ON ( res < PAGE_OFFSET | | res > = ( unsigned long ) high_memory ) ;
return res ;
}
EXPORT_SYMBOL ( __bus_to_virt ) ;
2009-12-12 17:53:08 +03:00
unsigned long __pfn_to_bus ( unsigned long pfn )
{
2010-07-19 07:06:12 +04:00
return __pfn_to_phys ( pfn ) + ( fb_bus_sdram_offset ( ) - PHYS_OFFSET ) ;
2009-12-12 17:53:08 +03:00
}
EXPORT_SYMBOL ( __pfn_to_bus ) ;
unsigned long __bus_to_pfn ( unsigned long bus )
{
return __phys_to_pfn ( bus - ( fb_bus_sdram_offset ( ) - PHYS_OFFSET ) ) ;
}
EXPORT_SYMBOL ( __bus_to_pfn ) ;
2005-04-17 02:20:36 +04:00
# endif