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/console.h> 21 #include <linux/linkage.h> 22 #include <linux/init.h> 23 #include <linux/major.h> 24 #include <linux/genhd.h> 25 #include <linux/rtc.h> 26 #include <linux/interrupt.h> 27 28 #include <asm/bootinfo.h> 29 #include <asm/system.h> 30 #include <asm/pgtable.h> 31 #include <asm/setup.h> 32 #include <asm/irq.h> 33 #include <asm/traps.h> 34 #include <asm/rtc.h> 35 #include <asm/machdep.h> 36 #include <asm/mvme147hw.h> 37 38 39 extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs); 40 extern void mvme147_init_IRQ (void); 41 extern void mvme147_free_irq (unsigned int, void *); 42 extern int show_mvme147_interrupts (struct seq_file *, void *); 43 extern void mvme147_enable_irq (unsigned int); 44 extern void mvme147_disable_irq (unsigned int); 45 static void mvme147_get_model(char *model); 46 static int mvme147_get_hardware_list(char *buffer); 47 extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); 48 extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); 49 extern unsigned long mvme147_gettimeoffset (void); 50 extern int mvme147_hwclk (int, struct rtc_time *); 51 extern int mvme147_set_clock_mmss (unsigned long); 52 extern void mvme147_reset (void); 53 extern void mvme147_waitbut(void); 54 55 56 static int bcd2int (unsigned char b); 57 58 /* Save tick handler routine pointer, will point to do_timer() in 59 * kernel/sched.c, called via mvme147_process_int() */ 60 61 irqreturn_t (*tick_handler)(int, void *, struct pt_regs *); 62 63 64 int mvme147_parse_bootinfo(const struct bi_record *bi) 65 { 66 if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO) 67 return 0; 68 else 69 return 1; 70 } 71 72 void mvme147_reset(void) 73 { 74 printk ("\r\n\nCalled mvme147_reset\r\n"); 75 m147_pcc->watchdog = 0x0a; /* Clear timer */ 76 m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */ 77 while (1) 78 ; 79 } 80 81 static void mvme147_get_model(char *model) 82 { 83 sprintf(model, "Motorola MVME147"); 84 } 85 86 87 static int mvme147_get_hardware_list(char *buffer) 88 { 89 *buffer = '\0'; 90 91 return 0; 92 } 93 94 95 void __init config_mvme147(void) 96 { 97 mach_max_dma_address = 0x01000000; 98 mach_sched_init = mvme147_sched_init; 99 mach_init_IRQ = mvme147_init_IRQ; 100 mach_gettimeoffset = mvme147_gettimeoffset; 101 mach_hwclk = mvme147_hwclk; 102 mach_set_clock_mmss = mvme147_set_clock_mmss; 103 mach_reset = mvme147_reset; 104 mach_free_irq = mvme147_free_irq; 105 mach_process_int = mvme147_process_int; 106 mach_get_irq_list = show_mvme147_interrupts; 107 mach_request_irq = mvme147_request_irq; 108 enable_irq = mvme147_enable_irq; 109 disable_irq = mvme147_disable_irq; 110 mach_get_model = mvme147_get_model; 111 mach_get_hardware_list = mvme147_get_hardware_list; 112 113 /* Board type is only set by newer versions of vmelilo/tftplilo */ 114 if (!vme_brdtype) 115 vme_brdtype = VME_TYPE_MVME147; 116 } 117 118 119 /* Using pcc tick timer 1 */ 120 121 static irqreturn_t mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp) 122 { 123 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; 124 m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; 125 return tick_handler(irq, dev_id, fp); 126 } 127 128 129 void mvme147_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) 130 { 131 tick_handler = timer_routine; 132 request_irq (PCC_IRQ_TIMER1, mvme147_timer_int, 133 IRQ_FLG_REPLACE, "timer 1", NULL); 134 135 /* Init the clock with a value */ 136 /* our clock goes off every 6.25us */ 137 m147_pcc->t1_preload = PCC_TIMER_PRELOAD; 138 m147_pcc->t1_cntrl = 0x0; /* clear timer */ 139 m147_pcc->t1_cntrl = 0x3; /* start timer */ 140 m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */ 141 m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; 142 } 143 144 /* This is always executed with interrupts disabled. */ 145 /* XXX There are race hazards in this code XXX */ 146 unsigned long mvme147_gettimeoffset (void) 147 { 148 volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012; 149 unsigned short n; 150 151 n = *cp; 152 while (n != *cp) 153 n = *cp; 154 155 n -= PCC_TIMER_PRELOAD; 156 return (unsigned long)n * 25 / 4; 157 } 158 159 static int bcd2int (unsigned char b) 160 { 161 return ((b>>4)*10 + (b&15)); 162 } 163 164 int mvme147_hwclk(int op, struct rtc_time *t) 165 { 166 #warning check me! 167 if (!op) { 168 m147_rtc->ctrl = RTC_READ; 169 t->tm_year = bcd2int (m147_rtc->bcd_year); 170 t->tm_mon = bcd2int (m147_rtc->bcd_mth); 171 t->tm_mday = bcd2int (m147_rtc->bcd_dom); 172 t->tm_hour = bcd2int (m147_rtc->bcd_hr); 173 t->tm_min = bcd2int (m147_rtc->bcd_min); 174 t->tm_sec = bcd2int (m147_rtc->bcd_sec); 175 m147_rtc->ctrl = 0; 176 } 177 return 0; 178 } 179 180 int mvme147_set_clock_mmss (unsigned long nowtime) 181 { 182 return 0; 183 } 184 185 /*------------------- Serial console stuff ------------------------*/ 186 187 static void scc_delay (void) 188 { 189 int n; 190 volatile int trash; 191 192 for (n = 0; n < 20; n++) 193 trash = n; 194 } 195 196 static void scc_write (char ch) 197 { 198 volatile char *p = (volatile char *)M147_SCC_A_ADDR; 199 200 do { 201 scc_delay(); 202 } 203 while (!(*p & 4)); 204 scc_delay(); 205 *p = 8; 206 scc_delay(); 207 *p = ch; 208 } 209 210 211 void m147_scc_write (struct console *co, const char *str, unsigned count) 212 { 213 unsigned long flags; 214 215 local_irq_save(flags); 216 217 while (count--) 218 { 219 if (*str == '\n') 220 scc_write ('\r'); 221 scc_write (*str++); 222 } 223 local_irq_restore(flags); 224 } 225 226 void mvme147_init_console_port (struct console *co, int cflag) 227 { 228 co->write = m147_scc_write; 229 } 230