diff options
Diffstat (limited to 'arch/m68k/mvme147/config.c')
| -rw-r--r-- | arch/m68k/mvme147/config.c | 199 |
1 files changed, 98 insertions, 101 deletions
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 1c6262803b94..3054d3857efa 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * arch/m68k/mvme147/config.c * @@ -7,53 +8,42 @@ * 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> +#include <linux/clocksource.h> #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 <linux/platform_device.h> +#include <linux/rtc/m48t59.h> #include <asm/bootinfo.h> -#include <asm/pgtable.h> +#include <asm/bootinfo-vme.h> +#include <asm/byteorder.h> #include <asm/setup.h> #include <asm/irq.h> #include <asm/traps.h> -#include <asm/rtc.h> #include <asm/machdep.h> #include <asm/mvme147hw.h> +#include <asm/config.h> +#include "mvme147.h" static void mvme147_get_model(char *model); -extern void mvme147_sched_init(irq_handler_t handler); -extern u32 mvme147_gettimeoffset(void); -extern int mvme147_hwclk (int, struct rtc_time *); -extern int mvme147_set_clock_mmss (unsigned long); +static void __init mvme147_sched_init(void); extern void mvme147_reset (void); -static int bcd2int (unsigned char b); - -/* Save tick handler routine pointer, will point to xtime_update() in - * kernel/time/timekeeping.c, called via mvme147_process_int() */ - -irq_handler_t tick_handler; - - -int mvme147_parse_bootinfo(const struct bi_record *bi) +int __init mvme147_parse_bootinfo(const struct bi_record *bi) { - if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO) + uint16_t tag = be16_to_cpu(bi->tag); + if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO) return 0; else return 1; @@ -61,7 +51,7 @@ int mvme147_parse_bootinfo(const struct bi_record *bi) void mvme147_reset(void) { - printk ("\r\n\nCalled mvme147_reset\r\n"); + pr_info("\r\n\nCalled mvme147_reset\r\n"); m147_pcc->watchdog = 0x0a; /* Clear timer */ m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */ while (1) @@ -78,19 +68,15 @@ static void mvme147_get_model(char *model) * the mvme147 IRQ handling routines. */ -void __init mvme147_init_IRQ(void) +static void __init mvme147_init_IRQ(void) { m68k_setup_user_interrupt(VEC_USER, 192); } void __init config_mvme147(void) { - mach_max_dma_address = 0x01000000; mach_sched_init = mvme147_sched_init; mach_init_IRQ = mvme147_init_IRQ; - arch_gettimeoffset = mvme147_gettimeoffset; - mach_hwclk = mvme147_hwclk; - mach_set_clock_mmss = mvme147_set_clock_mmss; mach_reset = mvme147_reset; mach_get_model = mvme147_get_model; @@ -99,115 +85,126 @@ void __init config_mvme147(void) vme_brdtype = VME_TYPE_MVME147; } +static struct resource m48t59_rsrc[] = { + DEFINE_RES_MEM(MVME147_RTC_BASE, 0x800), +}; + +static struct m48t59_plat_data m48t59_data = { + .type = M48T59RTC_TYPE_M48T02, + .yy_offset = 70, +}; + +static int __init mvme147_platform_init(void) +{ + if (!MACH_IS_MVME147) + return 0; + + platform_device_register_resndata(NULL, "rtc-m48t59", -1, + m48t59_rsrc, ARRAY_SIZE(m48t59_rsrc), + &m48t59_data, sizeof(m48t59_data)); + return 0; +} + +arch_initcall(mvme147_platform_init); + +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) /* Using pcc tick timer 1 */ static irqreturn_t mvme147_timer_int (int irq, void *dev_id) { - m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; - m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; - return tick_handler(irq, dev_id); + unsigned long flags; + + local_irq_save(flags); + m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN | + PCC_TIMER_TIC_EN; + m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR | + PCC_LEVEL_TIMER1; + clk_total += PCC_TIMER_CYCLES; + legacy_timer_tick(1); + local_irq_restore(flags); + + return IRQ_HANDLED; } -void mvme147_sched_init (irq_handler_t timer_routine) +static void __init mvme147_sched_init(void) { - tick_handler = timer_routine; - if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL)) + if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER, + "timer 1", NULL)) pr_err("Couldn't register timer interrupt\n"); /* Init the clock with a value */ - /* our clock goes off every 6.25us */ + /* The clock counter increments until 0xFFFF then reloads */ 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; -} + m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN | + PCC_TIMER_TIC_EN; + m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR | + PCC_LEVEL_TIMER1; -/* This is always executed with interrupts disabled. */ -/* XXX There are race hazards in this code XXX */ -u32 mvme147_gettimeoffset(void) -{ - volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012; - unsigned short n; - - n = *cp; - while (n != *cp) - n = *cp; - - n -= PCC_TIMER_PRELOAD; - return ((unsigned long)n * 25 / 4) * 1000; + clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ); } -static int bcd2int (unsigned char b) +static u64 mvme147_read_clk(struct clocksource *cs) { - return ((b>>4)*10 + (b&15)); -} + unsigned long flags; + u8 overflow, tmp; + u16 count; + u32 ticks; -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); - t->tm_mon = bcd2int (m147_rtc->bcd_mth); - 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; - } - return 0; -} + local_irq_save(flags); + 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; + local_irq_restore(flags); -int mvme147_set_clock_mmss (unsigned long nowtime) -{ - return 0; + return ticks; } -/*------------------- Serial console stuff ------------------------*/ - -static void scc_delay (void) +static void scc_delay(void) { - int n; - volatile int trash; - - for (n = 0; n < 20; n++) - trash = n; + __asm__ __volatile__ ("nop; nop;"); } -static void scc_write (char ch) +static void scc_write(char ch) { - volatile char *p = (volatile char *)M147_SCC_A_ADDR; - do { scc_delay(); - } - while (!(*p & 4)); + } while (!(in_8(M147_SCC_A_ADDR) & BIT(2))); scc_delay(); - *p = 8; + out_8(M147_SCC_A_ADDR, 8); scc_delay(); - *p = ch; + out_8(M147_SCC_A_ADDR, ch); } - -void m147_scc_write (struct console *co, const char *str, unsigned count) +void mvme147_scc_write(struct console *co, const char *str, unsigned int count) { unsigned long flags; local_irq_save(flags); - - while (count--) - { + while (count--) { if (*str == '\n') - scc_write ('\r'); - scc_write (*str++); + scc_write('\r'); + scc_write(*str++); } local_irq_restore(flags); } - -void mvme147_init_console_port (struct console *co, int cflag) -{ - co->write = m147_scc_write; -} |
