1 /* 2 * arch/m68k/mvme147/config.c 3 * 4 * Copyright (C) 1996 Dave Frascone [chaos@mindspring.com] 5 * Cloned from Richard Hirst [richard@sleepie.demon.co.uk] 6 * 7 * Based on: 8 * 9 * Copyright (C) 1993 Hamish Macdonald 10 * 11 * This file is subject to the terms and conditions of the GNU General Public 12 * License. See the file README.legal in the main directory of this archive 13 * for more details. 14 */ 15 16 #include <linux/types.h> 17 #include <linux/kernel.h> 18 #include <linux/mm.h> 19 #include <linux/tty.h> 20 #include <linux/clocksource.h> 21 #include <linux/console.h> 22 #include <linux/linkage.h> 23 #include <linux/init.h> 24 #include <linux/major.h> 25 #include <linux/genhd.h> 26 #include <linux/rtc.h> 27 #include <linux/interrupt.h> 28 29 #include <asm/bootinfo.h> 30 #include <asm/bootinfo-vme.h> 31 #include <asm/byteorder.h> 32 #include <asm/pgtable.h> 33 #include <asm/setup.h> 34 #include <asm/irq.h> 35 #include <asm/traps.h> 36 #include <asm/machdep.h> 37 #include <asm/mvme147hw.h> 38 39 40 static void mvme147_get_model(char *model); 41 extern void mvme147_sched_init(irq_handler_t handler); 42 extern int mvme147_hwclk (int, struct rtc_time *); 43 extern void mvme147_reset (void); 44 45 46 static int bcd2int (unsigned char b); 47 48 49 int __init mvme147_parse_bootinfo(const struct bi_record *bi) 50 { 51 uint16_t tag = be16_to_cpu(bi->tag); 52 if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO) 53 return 0; 54 else 55 return 1; 56 } 57 58 void mvme147_reset(void) 59 { 60 pr_info("\r\n\nCalled mvme147_reset\r\n"); 61 m147_pcc->watchdog = 0x0a; /* Clear timer */ 62 m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */ 63 while (1) 64 ; 65 } 66 67 static void mvme147_get_model(char *model) 68 { 69 sprintf(model, "Motorola MVME147"); 70 } 71 72 /* 73 * This function is called during kernel startup to initialize 74 * the mvme147 IRQ handling routines. 75 */ 76 77 void __init mvme147_init_IRQ(void) 78 { 79 m68k_setup_user_interrupt(VEC_USER, 192); 80 } 81 82 void __init config_mvme147(void) 83 { 84 mach_max_dma_address = 0x01000000; 85 mach_sched_init = mvme147_sched_init; 86 mach_init_IRQ = mvme147_init_IRQ; 87 mach_hwclk = mvme147_hwclk; 88 mach_reset = mvme147_reset; 89 mach_get_model = mvme147_get_model; 90 91 /* Board type is only set by newer versions of vmelilo/tftplilo */ 92 if (!vme_brdtype) 93 vme_brdtype = VME_TYPE_MVME147; 94 } 95 96 static u64 mvme147_read_clk(struct clocksource *cs); 97 98 static struct clocksource mvme147_clk = { 99 .name = "pcc", 100 .rating = 250, 101 .read = mvme147_read_clk, 102 .mask = CLOCKSOURCE_MASK(32), 103 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 104 }; 105 106 static u32 clk_total; 107 108 #define PCC_TIMER_CLOCK_FREQ 160000 109 #define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ) 110 #define PCC_TIMER_PRELOAD (0x10000 - PCC_TIMER_CYCLES) 111 112 /* Using pcc tick timer 1 */ 113 114 static irqreturn_t mvme147_timer_int (int irq, void *dev_id) 115 { 116 irq_handler_t timer_routine = dev_id; 117 unsigned long flags; 118 119 local_irq_save(flags); 120 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; 121 m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF; 122 clk_total += PCC_TIMER_CYCLES; 123 timer_routine(0, NULL); 124 local_irq_restore(flags); 125 126 return IRQ_HANDLED; 127 } 128 129 130 void mvme147_sched_init (irq_handler_t timer_routine) 131 { 132 if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER, 133 "timer 1", timer_routine)) 134 pr_err("Couldn't register timer interrupt\n"); 135 136 /* Init the clock with a value */ 137 /* The clock counter increments until 0xFFFF then reloads */ 138 m147_pcc->t1_preload = PCC_TIMER_PRELOAD; 139 m147_pcc->t1_cntrl = 0x0; /* clear timer */ 140 m147_pcc->t1_cntrl = 0x3; /* start timer */ 141 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */ 142 m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; 143 144 clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ); 145 } 146 147 static u64 mvme147_read_clk(struct clocksource *cs) 148 { 149 unsigned long flags; 150 u8 overflow, tmp; 151 u16 count; 152 u32 ticks; 153 154 local_irq_save(flags); 155 tmp = m147_pcc->t1_cntrl >> 4; 156 count = m147_pcc->t1_count; 157 overflow = m147_pcc->t1_cntrl >> 4; 158 if (overflow != tmp) 159 count = m147_pcc->t1_count; 160 count -= PCC_TIMER_PRELOAD; 161 ticks = count + overflow * PCC_TIMER_CYCLES; 162 ticks += clk_total; 163 local_irq_restore(flags); 164 165 return ticks; 166 } 167 168 static int bcd2int (unsigned char b) 169 { 170 return ((b>>4)*10 + (b&15)); 171 } 172 173 int mvme147_hwclk(int op, struct rtc_time *t) 174 { 175 #warning check me! 176 if (!op) { 177 m147_rtc->ctrl = RTC_READ; 178 t->tm_year = bcd2int (m147_rtc->bcd_year); 179 t->tm_mon = bcd2int(m147_rtc->bcd_mth) - 1; 180 t->tm_mday = bcd2int (m147_rtc->bcd_dom); 181 t->tm_hour = bcd2int (m147_rtc->bcd_hr); 182 t->tm_min = bcd2int (m147_rtc->bcd_min); 183 t->tm_sec = bcd2int (m147_rtc->bcd_sec); 184 m147_rtc->ctrl = 0; 185 if (t->tm_year < 70) 186 t->tm_year += 100; 187 } 188 return 0; 189 } 190