2005-04-16 15:20:36 -07:00
/*
* arch / m68k / mvme147 / config . c
*
* Copyright ( C ) 1996 Dave Frascone [ chaos @ mindspring . com ]
* Cloned from Richard Hirst [ richard @ sleepie . demon . co . uk ]
*
* Based on :
*
* Copyright ( C ) 1993 Hamish Macdonald
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file README . legal in the main directory of this archive
* for more details .
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/tty.h>
2018-12-01 11:53:10 +11:00
# include <linux/clocksource.h>
2005-04-16 15:20:36 -07:00
# include <linux/console.h>
# include <linux/linkage.h>
# include <linux/init.h>
# include <linux/major.h>
# include <linux/genhd.h>
# include <linux/rtc.h>
# include <linux/interrupt.h>
# include <asm/bootinfo.h>
2013-10-02 11:37:33 +02:00
# include <asm/bootinfo-vme.h>
2013-10-04 11:41:24 +02:00
# include <asm/byteorder.h>
2005-04-16 15:20:36 -07:00
# include <asm/pgtable.h>
# include <asm/setup.h>
# include <asm/irq.h>
# include <asm/traps.h>
# include <asm/machdep.h>
# include <asm/mvme147hw.h>
static void mvme147_get_model ( char * model ) ;
2006-10-09 12:19:47 +01:00
extern void mvme147_sched_init ( irq_handler_t handler ) ;
2005-04-16 15:20:36 -07:00
extern int mvme147_hwclk ( int , struct rtc_time * ) ;
extern void mvme147_reset ( void ) ;
static int bcd2int ( unsigned char b ) ;
2013-06-25 21:15:24 +02:00
int __init mvme147_parse_bootinfo ( const struct bi_record * bi )
2005-04-16 15:20:36 -07:00
{
2013-10-04 11:41:24 +02:00
uint16_t tag = be16_to_cpu ( bi - > tag ) ;
if ( tag = = BI_VME_TYPE | | tag = = BI_VME_BRDINFO )
2005-04-16 15:20:36 -07:00
return 0 ;
else
return 1 ;
}
void mvme147_reset ( void )
{
2016-12-06 17:09:58 +01:00
pr_info ( " \r \n \n Called mvme147_reset \r \n " ) ;
2005-04-16 15:20:36 -07:00
m147_pcc - > watchdog = 0x0a ; /* Clear timer */
m147_pcc - > watchdog = 0xa5 ; /* Enable watchdog - 100ms to reset */
while ( 1 )
;
}
static void mvme147_get_model ( char * model )
{
sprintf ( model , " Motorola MVME147 " ) ;
}
2006-06-25 05:47:06 -07:00
/*
* This function is called during kernel startup to initialize
* the mvme147 IRQ handling routines .
*/
2007-07-20 04:33:28 +01:00
void __init mvme147_init_IRQ ( void )
2006-06-25 05:47:06 -07:00
{
2011-09-11 11:54:50 +02:00
m68k_setup_user_interrupt ( VEC_USER , 192 ) ;
2006-06-25 05:47:06 -07:00
}
2005-04-16 15:20:36 -07:00
void __init config_mvme147 ( void )
{
mach_max_dma_address = 0x01000000 ;
mach_sched_init = mvme147_sched_init ;
mach_init_IRQ = mvme147_init_IRQ ;
mach_hwclk = mvme147_hwclk ;
mach_reset = mvme147_reset ;
mach_get_model = mvme147_get_model ;
/* Board type is only set by newer versions of vmelilo/tftplilo */
if ( ! vme_brdtype )
vme_brdtype = VME_TYPE_MVME147 ;
}
2018-12-01 11:53:10 +11:00
static u64 mvme147_read_clk ( struct clocksource * cs ) ;
static struct clocksource mvme147_clk = {
. name = " pcc " ,
. rating = 250 ,
. read = mvme147_read_clk ,
. mask = CLOCKSOURCE_MASK ( 32 ) ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
} ;
static u32 clk_total ;
# define PCC_TIMER_CLOCK_FREQ 160000
# define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ)
# define PCC_TIMER_PRELOAD (0x10000 - PCC_TIMER_CYCLES)
2005-04-16 15:20:36 -07:00
/* Using pcc tick timer 1 */
2006-10-07 14:16:45 +01:00
static irqreturn_t mvme147_timer_int ( int irq , void * dev_id )
2005-04-16 15:20:36 -07:00
{
2018-12-01 11:53:10 +11:00
irq_handler_t timer_routine = dev_id ;
unsigned long flags ;
local_irq_save ( flags ) ;
2005-04-16 15:20:36 -07:00
m147_pcc - > t1_int_cntrl = PCC_TIMER_INT_CLR ;
2018-12-01 11:53:10 +11:00
m147_pcc - > t1_cntrl = PCC_TIMER_CLR_OVF ;
2018-12-01 11:53:10 +11:00
clk_total + = PCC_TIMER_CYCLES ;
2018-12-01 11:53:10 +11:00
timer_routine ( 0 , NULL ) ;
local_irq_restore ( flags ) ;
return IRQ_HANDLED ;
2005-04-16 15:20:36 -07:00
}
2006-10-09 12:19:47 +01:00
void mvme147_sched_init ( irq_handler_t timer_routine )
2005-04-16 15:20:36 -07:00
{
2018-12-01 11:53:10 +11:00
if ( request_irq ( PCC_IRQ_TIMER1 , mvme147_timer_int , IRQF_TIMER ,
" timer 1 " , timer_routine ) )
2008-12-30 14:03:28 +01:00
pr_err ( " Couldn't register timer interrupt \n " ) ;
2005-04-16 15:20:36 -07:00
/* Init the clock with a value */
2018-12-01 11:53:10 +11:00
/* The clock counter increments until 0xFFFF then reloads */
2005-04-16 15:20:36 -07:00
m147_pcc - > t1_preload = PCC_TIMER_PRELOAD ;
m147_pcc - > t1_cntrl = 0x0 ; /* clear timer */
m147_pcc - > t1_cntrl = 0x3 ; /* start timer */
m147_pcc - > t1_int_cntrl = PCC_TIMER_INT_CLR ; /* clear pending ints */
m147_pcc - > t1_int_cntrl = PCC_INT_ENAB | PCC_LEVEL_TIMER1 ;
2018-12-01 11:53:10 +11:00
clocksource_register_hz ( & mvme147_clk , PCC_TIMER_CLOCK_FREQ ) ;
2005-04-16 15:20:36 -07:00
}
2018-12-01 11:53:10 +11:00
static u64 mvme147_read_clk ( struct clocksource * cs )
2005-04-16 15:20:36 -07:00
{
2018-12-01 11:53:10 +11:00
unsigned long flags ;
2018-12-01 11:53:10 +11:00
u8 overflow , tmp ;
u16 count ;
2018-12-01 11:53:10 +11:00
u32 ticks ;
2005-04-16 15:20:36 -07:00
2018-12-01 11:53:10 +11:00
local_irq_save ( flags ) ;
2018-12-01 11:53:10 +11:00
tmp = m147_pcc - > t1_cntrl > > 4 ;
count = m147_pcc - > t1_count ;
overflow = m147_pcc - > t1_cntrl > > 4 ;
if ( overflow ! = tmp )
count = m147_pcc - > t1_count ;
count - = PCC_TIMER_PRELOAD ;
ticks = count + overflow * PCC_TIMER_CYCLES ;
ticks + = clk_total ;
2018-12-01 11:53:10 +11:00
local_irq_restore ( flags ) ;
return ticks ;
2005-04-16 15:20:36 -07:00
}
static int bcd2int ( unsigned char b )
{
return ( ( b > > 4 ) * 10 + ( b & 15 ) ) ;
}
int mvme147_hwclk ( int op , struct rtc_time * t )
{
# warning check me!
if ( ! op ) {
m147_rtc - > ctrl = RTC_READ ;
t - > tm_year = bcd2int ( m147_rtc - > bcd_year ) ;
m68k: Fix off-by-one calendar month
This fixes a bug in read_persistent_clock() which causes the system
clock to lag the Real Time Clock by one month. The problem was noticed
on a Mac, but theoretically it must also affect Atari, BVME6000 and Q40.
The tm_mon value in the struct rtc_time passed to mach_hwclk() is
zero-based, and atari_mste_hwclk(), atari_tt_hwclk(), bvme6000_hwclk(),
mac_hwclk() and q40_hwclk() all make this adjustment. Unfortunately,
dn_dummy_hwclk(), mvme147_hwclk(), mvme16x_hwclk(), sun3_hwclk() and
sun3x_hwclk() fail to decrement tm_mon. Also m68328_hwclk() assumes
a one-based tm_mon.
Bring these platforms into line and fix read_persistent_clock() so it
works correctly on all m68k platforms.
The datasheets for the RTC devices found on the affected platforms
all confirm that the year is stored as a value in the range 0-99 and
the month is stored as a value in the range 1-12. Please refer to the
datasheets for MC146818 (Apollo), DS1643 (MVME), ICM7170 (Sun 3)
and M48T02 (Sun 3x).
Reported-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
2018-04-23 11:02:57 +10:00
t - > tm_mon = bcd2int ( m147_rtc - > bcd_mth ) - 1 ;
2005-04-16 15:20:36 -07:00
t - > tm_mday = bcd2int ( m147_rtc - > bcd_dom ) ;
t - > tm_hour = bcd2int ( m147_rtc - > bcd_hr ) ;
t - > tm_min = bcd2int ( m147_rtc - > bcd_min ) ;
t - > tm_sec = bcd2int ( m147_rtc - > bcd_sec ) ;
m147_rtc - > ctrl = 0 ;
m68k: Fix off-by-one calendar month
This fixes a bug in read_persistent_clock() which causes the system
clock to lag the Real Time Clock by one month. The problem was noticed
on a Mac, but theoretically it must also affect Atari, BVME6000 and Q40.
The tm_mon value in the struct rtc_time passed to mach_hwclk() is
zero-based, and atari_mste_hwclk(), atari_tt_hwclk(), bvme6000_hwclk(),
mac_hwclk() and q40_hwclk() all make this adjustment. Unfortunately,
dn_dummy_hwclk(), mvme147_hwclk(), mvme16x_hwclk(), sun3_hwclk() and
sun3x_hwclk() fail to decrement tm_mon. Also m68328_hwclk() assumes
a one-based tm_mon.
Bring these platforms into line and fix read_persistent_clock() so it
works correctly on all m68k platforms.
The datasheets for the RTC devices found on the affected platforms
all confirm that the year is stored as a value in the range 0-99 and
the month is stored as a value in the range 1-12. Please refer to the
datasheets for MC146818 (Apollo), DS1643 (MVME), ICM7170 (Sun 3)
and M48T02 (Sun 3x).
Reported-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
2018-04-23 11:02:57 +10:00
if ( t - > tm_year < 70 )
t - > tm_year + = 100 ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}