2005-04-16 15:20:36 -07:00
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/tty.h>
# include <linux/console.h>
# include <linux/rtc.h>
# include <linux/vt_kern.h>
# include <linux/interrupt.h>
# include <asm/setup.h>
# include <asm/bootinfo.h>
# include <asm/pgtable.h>
# include <asm/apollohw.h>
# include <asm/irq.h>
# include <asm/rtc.h>
# include <asm/machdep.h>
u_long sio01_physaddr ;
u_long sio23_physaddr ;
u_long rtc_physaddr ;
u_long pica_physaddr ;
u_long picb_physaddr ;
u_long cpuctrl_physaddr ;
u_long timer_physaddr ;
u_long apollo_model ;
2006-10-09 12:19:47 +01:00
extern void dn_sched_init ( irq_handler_t handler ) ;
2005-04-16 15:20:36 -07:00
extern void dn_init_IRQ ( void ) ;
extern unsigned long dn_gettimeoffset ( void ) ;
extern int dn_dummy_hwclk ( int , struct rtc_time * ) ;
extern int dn_dummy_set_clock_mmss ( unsigned long ) ;
extern void dn_dummy_reset ( void ) ;
# ifdef CONFIG_HEARTBEAT
static void dn_heartbeat ( int on ) ;
# endif
2006-10-07 14:16:45 +01:00
static irqreturn_t dn_timer_int ( int irq , void * ) ;
2005-04-16 15:20:36 -07:00
static void dn_get_model ( char * model ) ;
static const char * apollo_models [ ] = {
[ APOLLO_DN3000 - APOLLO_DN3000 ] = " DN3000 (Otter) " ,
[ APOLLO_DN3010 - APOLLO_DN3000 ] = " DN3010 (Otter) " ,
[ APOLLO_DN3500 - APOLLO_DN3000 ] = " DN3500 (Cougar II) " ,
[ APOLLO_DN4000 - APOLLO_DN3000 ] = " DN4000 (Mink) " ,
[ APOLLO_DN4500 - APOLLO_DN3000 ] = " DN4500 (Roadrunner) "
} ;
int apollo_parse_bootinfo ( const struct bi_record * record ) {
int unknown = 0 ;
const unsigned long * data = record - > data ;
switch ( record - > tag ) {
case BI_APOLLO_MODEL :
apollo_model = * data ;
break ;
default :
unknown = 1 ;
}
return unknown ;
}
void dn_setup_model ( void ) {
printk ( " Apollo hardware found: " ) ;
printk ( " [%s] \n " , apollo_models [ apollo_model - APOLLO_DN3000 ] ) ;
switch ( apollo_model ) {
case APOLLO_UNKNOWN :
panic ( " Unknown apollo model " ) ;
break ;
case APOLLO_DN3000 :
case APOLLO_DN3010 :
sio01_physaddr = SAU8_SIO01_PHYSADDR ;
rtc_physaddr = SAU8_RTC_PHYSADDR ;
pica_physaddr = SAU8_PICA ;
picb_physaddr = SAU8_PICB ;
cpuctrl_physaddr = SAU8_CPUCTRL ;
timer_physaddr = SAU8_TIMER ;
break ;
case APOLLO_DN4000 :
sio01_physaddr = SAU7_SIO01_PHYSADDR ;
sio23_physaddr = SAU7_SIO23_PHYSADDR ;
rtc_physaddr = SAU7_RTC_PHYSADDR ;
pica_physaddr = SAU7_PICA ;
picb_physaddr = SAU7_PICB ;
cpuctrl_physaddr = SAU7_CPUCTRL ;
timer_physaddr = SAU7_TIMER ;
break ;
case APOLLO_DN4500 :
panic ( " Apollo model not yet supported " ) ;
break ;
case APOLLO_DN3500 :
sio01_physaddr = SAU7_SIO01_PHYSADDR ;
sio23_physaddr = SAU7_SIO23_PHYSADDR ;
rtc_physaddr = SAU7_RTC_PHYSADDR ;
pica_physaddr = SAU7_PICA ;
picb_physaddr = SAU7_PICB ;
cpuctrl_physaddr = SAU7_CPUCTRL ;
timer_physaddr = SAU7_TIMER ;
break ;
default :
panic ( " Undefined apollo model " ) ;
break ;
}
}
int dn_serial_console_wait_key ( struct console * co ) {
while ( ! ( sio01 . srb_csrb & 1 ) )
barrier ( ) ;
return sio01 . rhrb_thrb ;
}
void dn_serial_console_write ( struct console * co , const char * str , unsigned int count )
{
while ( count - - ) {
if ( * str = = ' \n ' ) {
sio01 . rhrb_thrb = ( unsigned char ) ' \r ' ;
while ( ! ( sio01 . srb_csrb & 0x4 ) )
;
}
sio01 . rhrb_thrb = ( unsigned char ) * str + + ;
while ( ! ( sio01 . srb_csrb & 0x4 ) )
;
}
}
void dn_serial_print ( const char * str )
{
while ( * str ) {
if ( * str = = ' \n ' ) {
sio01 . rhrb_thrb = ( unsigned char ) ' \r ' ;
while ( ! ( sio01 . srb_csrb & 0x4 ) )
;
}
sio01 . rhrb_thrb = ( unsigned char ) * str + + ;
while ( ! ( sio01 . srb_csrb & 0x4 ) )
;
}
}
2007-07-20 04:33:28 +01:00
void __init config_apollo ( void )
{
2005-04-16 15:20:36 -07:00
int i ;
dn_setup_model ( ) ;
mach_sched_init = dn_sched_init ; /* */
mach_init_IRQ = dn_init_IRQ ;
mach_gettimeoffset = dn_gettimeoffset ;
mach_max_dma_address = 0xffffffff ;
mach_hwclk = dn_dummy_hwclk ; /* */
mach_set_clock_mmss = dn_dummy_set_clock_mmss ; /* */
mach_reset = dn_dummy_reset ; /* */
# ifdef CONFIG_HEARTBEAT
mach_heartbeat = dn_heartbeat ;
# endif
mach_get_model = dn_get_model ;
cpuctrl = 0xaa00 ;
/* clear DMA translation table */
for ( i = 0 ; i < 0x400 ; i + + )
addr_xlat_map [ i ] = 0 ;
}
2006-10-07 14:16:45 +01:00
irqreturn_t dn_timer_int ( int irq , void * dev_id )
2006-06-25 05:47:02 -07:00
{
2006-10-09 12:19:47 +01:00
irq_handler_t timer_handler = dev_id ;
2005-04-16 15:20:36 -07:00
volatile unsigned char x ;
2006-10-07 14:16:45 +01:00
timer_handler ( irq , dev_id ) ;
2005-04-16 15:20:36 -07:00
2012-07-20 21:54:29 +02:00
x = * ( volatile unsigned char * ) ( apollo_timer + 3 ) ;
x = * ( volatile unsigned char * ) ( apollo_timer + 5 ) ;
2005-04-16 15:20:36 -07:00
return IRQ_HANDLED ;
}
2006-10-09 12:19:47 +01:00
void dn_sched_init ( irq_handler_t timer_routine )
2006-10-07 14:16:45 +01:00
{
2005-04-16 15:20:36 -07:00
/* program timer 1 */
2012-07-20 21:54:29 +02:00
* ( volatile unsigned char * ) ( apollo_timer + 3 ) = 0x01 ;
* ( volatile unsigned char * ) ( apollo_timer + 1 ) = 0x40 ;
* ( volatile unsigned char * ) ( apollo_timer + 5 ) = 0x09 ;
* ( volatile unsigned char * ) ( apollo_timer + 7 ) = 0xc4 ;
2005-04-16 15:20:36 -07:00
/* enable IRQ of PIC B */
* ( volatile unsigned char * ) ( pica + 1 ) & = ( ~ 8 ) ;
#if 0
2012-07-20 21:54:29 +02:00
printk ( " *(0x10803) %02x \n " , * ( volatile unsigned char * ) ( apollo_timer + 0x3 ) ) ;
printk ( " *(0x10803) %02x \n " , * ( volatile unsigned char * ) ( apollo_timer + 0x3 ) ) ;
2005-04-16 15:20:36 -07:00
# endif
2008-12-30 14:01:07 +01:00
if ( request_irq ( IRQ_APOLLO , dn_timer_int , 0 , " time " , timer_routine ) )
pr_err ( " Couldn't register timer interrupt \n " ) ;
2005-04-16 15:20:36 -07:00
}
unsigned long dn_gettimeoffset ( void ) {
return 0xdeadbeef ;
}
int dn_dummy_hwclk ( int op , struct rtc_time * t ) {
if ( ! op ) { /* read */
t - > tm_sec = rtc - > second ;
t - > tm_min = rtc - > minute ;
t - > tm_hour = rtc - > hours ;
t - > tm_mday = rtc - > day_of_month ;
t - > tm_wday = rtc - > day_of_week ;
t - > tm_mon = rtc - > month ;
t - > tm_year = rtc - > year ;
} else {
rtc - > second = t - > tm_sec ;
rtc - > minute = t - > tm_min ;
rtc - > hours = t - > tm_hour ;
rtc - > day_of_month = t - > tm_mday ;
if ( t - > tm_wday ! = - 1 )
rtc - > day_of_week = t - > tm_wday ;
rtc - > month = t - > tm_mon ;
rtc - > year = t - > tm_year ;
}
return 0 ;
}
int dn_dummy_set_clock_mmss ( unsigned long nowtime ) {
printk ( " set_clock_mmss \n " ) ;
return 0 ;
}
void dn_dummy_reset ( void ) {
dn_serial_print ( " The end ! \n " ) ;
for ( ; ; ) ;
}
void dn_dummy_waitbut ( void ) {
dn_serial_print ( " waitbut \n " ) ;
}
static void dn_get_model ( char * model )
{
strcpy ( model , " Apollo " ) ;
if ( apollo_model > = APOLLO_DN3000 & & apollo_model < = APOLLO_DN4500 )
strcat ( model , apollo_models [ apollo_model - APOLLO_DN3000 ] ) ;
}
# ifdef CONFIG_HEARTBEAT
static int dn_cpuctrl = 0xff00 ;
static void dn_heartbeat ( int on ) {
if ( on ) {
dn_cpuctrl & = ~ 0x100 ;
cpuctrl = dn_cpuctrl ;
}
else {
dn_cpuctrl & = ~ 0x100 ;
dn_cpuctrl | = 0x100 ;
cpuctrl = dn_cpuctrl ;
}
}
# endif