2009-02-10 12:20:49 +00:00
/*
* AmigaOne platform setup
*
* Copyright 2008 Gerhard Pircher ( gerhard_pircher @ gmx . net )
*
* Based on original amigaone_setup . c source code
* Copyright 2003 by Hans - Joerg Frieden and Thomas Frieden
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <linux/kernel.h>
2010-07-29 11:49:01 -06:00
# include <linux/of.h>
# include <linux/of_address.h>
2009-02-10 12:20:49 +00:00
# include <linux/seq_file.h>
2009-10-18 00:52:28 +02:00
# include <generated/utsrelease.h>
2009-02-10 12:20:49 +00:00
# include <asm/machdep.h>
# include <asm/cputable.h>
# include <asm/pci-bridge.h>
# include <asm/i8259.h>
# include <asm/time.h>
# include <asm/udbg.h>
extern void __flush_disable_L1 ( void ) ;
void amigaone_show_cpuinfo ( struct seq_file * m )
{
seq_printf ( m , " vendor \t \t : Eyetech Ltd. \n " ) ;
}
static int __init amigaone_add_bridge ( struct device_node * dev )
{
const u32 * cfg_addr , * cfg_data ;
int len ;
const int * bus_range ;
struct pci_controller * hose ;
printk ( KERN_INFO " Adding PCI host bridge %s \n " , dev - > full_name ) ;
cfg_addr = of_get_address ( dev , 0 , NULL , NULL ) ;
cfg_data = of_get_address ( dev , 1 , NULL , NULL ) ;
if ( ( cfg_addr = = NULL ) | | ( cfg_data = = NULL ) )
return - ENODEV ;
bus_range = of_get_property ( dev , " bus-range " , & len ) ;
if ( ( bus_range = = NULL ) | | ( len < 2 * sizeof ( int ) ) )
printk ( KERN_WARNING " Can't get bus-range for %s, assume "
" bus 0 \n " , dev - > full_name ) ;
hose = pcibios_alloc_controller ( dev ) ;
if ( hose = = NULL )
return - ENOMEM ;
hose - > first_busno = bus_range ? bus_range [ 0 ] : 0 ;
hose - > last_busno = bus_range ? bus_range [ 1 ] : 0xff ;
setup_indirect_pci ( hose , cfg_addr [ 0 ] , cfg_data [ 0 ] , 0 ) ;
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges ( hose , dev , 1 ) ;
return 0 ;
}
void __init amigaone_setup_arch ( void )
{
struct device_node * np ;
int phb = - ENODEV ;
/* Lookup PCI host bridges. */
for_each_compatible_node ( np , " pci " , " mai-logic,articia-s " )
phb = amigaone_add_bridge ( np ) ;
BUG_ON ( phb ! = 0 ) ;
if ( ppc_md . progress )
ppc_md . progress ( " Linux/PPC " UTS_RELEASE " \n " , 0 ) ;
}
void __init amigaone_init_IRQ ( void )
{
struct device_node * pic , * np = NULL ;
const unsigned long * prop = NULL ;
unsigned long int_ack = 0 ;
/* Search for ISA interrupt controller. */
pic = of_find_compatible_node ( NULL , " interrupt-controller " ,
" pnpPNP,000 " ) ;
BUG_ON ( pic = = NULL ) ;
/* Look for interrupt acknowledge address in the PCI root node. */
np = of_find_compatible_node ( NULL , " pci " , " mai-logic,articia-s " ) ;
if ( np ) {
prop = of_get_property ( np , " 8259-interrupt-acknowledge " , NULL ) ;
if ( prop )
int_ack = prop [ 0 ] ;
of_node_put ( np ) ;
}
if ( int_ack = = 0 )
printk ( KERN_WARNING " Cannot find PCI interrupt acknowledge "
" address, polling \n " ) ;
i8259_init ( pic , int_ack ) ;
ppc_md . get_irq = i8259_irq ;
irq_set_default_host ( i8259_get_host ( ) ) ;
}
2009-06-19 11:40:57 +00:00
static int __init request_isa_regions ( void )
2009-02-10 12:20:49 +00:00
{
request_region ( 0x00 , 0x20 , " dma1 " ) ;
request_region ( 0x40 , 0x20 , " timer " ) ;
request_region ( 0x80 , 0x10 , " dma page reg " ) ;
request_region ( 0xc0 , 0x20 , " dma2 " ) ;
2009-06-19 11:40:57 +00:00
return 0 ;
2009-02-10 12:20:49 +00:00
}
2009-06-19 11:40:57 +00:00
machine_device_initcall ( amigaone , request_isa_regions ) ;
2009-02-10 12:20:49 +00:00
void amigaone_restart ( char * cmd )
{
local_irq_disable ( ) ;
/* Flush and disable caches. */
__flush_disable_L1 ( ) ;
/* Set SRR0 to the reset vector and turn on MSR_IP. */
mtspr ( SPRN_SRR0 , 0xfff00100 ) ;
mtspr ( SPRN_SRR1 , MSR_IP ) ;
/* Do an rfi to jump back to firmware. */
__asm__ __volatile__ ( " rfi " : : : " memory " ) ;
/* Not reached. */
while ( 1 ) ;
}
static int __init amigaone_probe ( void )
{
unsigned long root = of_get_flat_dt_root ( ) ;
if ( of_flat_dt_is_compatible ( root , " eyetech,amigaone " ) ) {
/*
* Coherent memory access cause complete system lockup ! Thus
* disable this CPU feature , even if the CPU needs it .
*/
cur_cpu_spec - > cpu_features & = ~ CPU_FTR_NEED_COHERENT ;
ISA_DMA_THRESHOLD = 0x00ffffff ;
DMA_MODE_READ = 0x44 ;
DMA_MODE_WRITE = 0x48 ;
return 1 ;
}
return 0 ;
}
define_machine ( amigaone ) {
. name = " AmigaOne " ,
. probe = amigaone_probe ,
. setup_arch = amigaone_setup_arch ,
. show_cpuinfo = amigaone_show_cpuinfo ,
. init_IRQ = amigaone_init_IRQ ,
. restart = amigaone_restart ,
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;