linux/arch/m68k/mvme16x/config.c
<<
>>
Prefs
   1/*
   2 *  arch/m68k/mvme16x/config.c
   3 *
   4 *  Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk]
   5 *
   6 * Based on:
   7 *
   8 *  linux/amiga/config.c
   9 *
  10 *  Copyright (C) 1993 Hamish Macdonald
  11 *
  12 * This file is subject to the terms and conditions of the GNU General Public
  13 * License.  See the file README.legal in the main directory of this archive
  14 * for more details.
  15 */
  16
  17#include <linux/types.h>
  18#include <linux/kernel.h>
  19#include <linux/mm.h>
  20#include <linux/seq_file.h>
  21#include <linux/tty.h>
  22#include <linux/console.h>
  23#include <linux/linkage.h>
  24#include <linux/init.h>
  25#include <linux/major.h>
  26#include <linux/genhd.h>
  27#include <linux/rtc.h>
  28#include <linux/interrupt.h>
  29#include <linux/module.h>
  30
  31#include <asm/bootinfo.h>
  32#include <asm/system.h>
  33#include <asm/pgtable.h>
  34#include <asm/setup.h>
  35#include <asm/irq.h>
  36#include <asm/traps.h>
  37#include <asm/rtc.h>
  38#include <asm/machdep.h>
  39#include <asm/mvme16xhw.h>
  40
  41extern t_bdid mvme_bdid;
  42
  43static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
  44
  45static void mvme16x_get_model(char *model);
  46extern void mvme16x_sched_init(irq_handler_t handler);
  47extern unsigned long mvme16x_gettimeoffset (void);
  48extern int mvme16x_hwclk (int, struct rtc_time *);
  49extern int mvme16x_set_clock_mmss (unsigned long);
  50extern void mvme16x_reset (void);
  51
  52int bcd2int (unsigned char b);
  53
  54/* Save tick handler routine pointer, will point to do_timer() in
  55 * kernel/sched.c, called via mvme16x_process_int() */
  56
  57static irq_handler_t tick_handler;
  58
  59
  60unsigned short mvme16x_config;
  61EXPORT_SYMBOL(mvme16x_config);
  62
  63
  64int mvme16x_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
  72void mvme16x_reset(void)
  73{
  74        printk ("\r\n\nCalled mvme16x_reset\r\n"
  75                        "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r");
  76        /* The string of returns is to delay the reset until the whole
  77         * message is output.  Assert reset bit in GCSR */
  78        *(volatile char *)0xfff40107 = 0x80;
  79}
  80
  81static void mvme16x_get_model(char *model)
  82{
  83    p_bdid p = &mvme_bdid;
  84    char suf[4];
  85
  86    suf[1] = p->brdsuffix[0];
  87    suf[2] = p->brdsuffix[1];
  88    suf[3] = '\0';
  89    suf[0] = suf[1] ? '-' : '\0';
  90
  91    sprintf(model, "Motorola MVME%x%s", p->brdno, suf);
  92}
  93
  94
  95static void mvme16x_get_hardware_list(struct seq_file *m)
  96{
  97    p_bdid p = &mvme_bdid;
  98
  99    if (p->brdno == 0x0162 || p->brdno == 0x0172)
 100    {
 101        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 102
 103        seq_printf (m, "VMEchip2        %spresent\n",
 104                        rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : "");
 105        seq_printf (m, "SCSI interface  %spresent\n",
 106                        rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : "");
 107        seq_printf (m, "Ethernet i/f    %spresent\n",
 108                        rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : "");
 109    }
 110}
 111
 112/*
 113 * This function is called during kernel startup to initialize
 114 * the mvme16x IRQ handling routines.  Should probably ensure
 115 * that the base vectors for the VMEChip2 and PCCChip2 are valid.
 116 */
 117
 118static void __init mvme16x_init_IRQ (void)
 119{
 120        m68k_setup_user_interrupt(VEC_USER, 192, NULL);
 121}
 122
 123#define pcc2chip        ((volatile u_char *)0xfff42000)
 124#define PccSCCMICR      0x1d
 125#define PccSCCTICR      0x1e
 126#define PccSCCRICR      0x1f
 127
 128void __init config_mvme16x(void)
 129{
 130    p_bdid p = &mvme_bdid;
 131    char id[40];
 132
 133    mach_max_dma_address = 0xffffffff;
 134    mach_sched_init      = mvme16x_sched_init;
 135    mach_init_IRQ        = mvme16x_init_IRQ;
 136    mach_gettimeoffset   = mvme16x_gettimeoffset;
 137    mach_hwclk           = mvme16x_hwclk;
 138    mach_set_clock_mmss  = mvme16x_set_clock_mmss;
 139    mach_reset           = mvme16x_reset;
 140    mach_get_model       = mvme16x_get_model;
 141    mach_get_hardware_list = mvme16x_get_hardware_list;
 142
 143    /* Report board revision */
 144
 145    if (strncmp("BDID", p->bdid, 4))
 146    {
 147        printk ("\n\nBug call .BRD_ID returned garbage - giving up\n\n");
 148        while (1)
 149                ;
 150    }
 151    /* Board type is only set by newer versions of vmelilo/tftplilo */
 152    if (vme_brdtype == 0)
 153        vme_brdtype = p->brdno;
 154
 155    mvme16x_get_model(id);
 156    printk ("\nBRD_ID: %s   BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4,
 157                                        p->rev&0xf, p->yr, p->mth, p->day);
 158    if (p->brdno == 0x0162 || p->brdno == 0x172)
 159    {
 160        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 161
 162        mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA;
 163
 164        printk ("MVME%x Hardware status:\n", p->brdno);
 165        printk ("    CPU Type           68%s040\n",
 166                        rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC");
 167        printk ("    CPU clock          %dMHz\n",
 168                        rev & MVME16x_CONFIG_SPEED_32 ? 32 : 25);
 169        printk ("    VMEchip2           %spresent\n",
 170                        rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : "");
 171        printk ("    SCSI interface     %spresent\n",
 172                        rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : "");
 173        printk ("    Ethernet interface %spresent\n",
 174                        rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : "");
 175    }
 176    else
 177    {
 178        mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401;
 179
 180        /* Dont allow any interrupts from the CD2401 until the interrupt */
 181        /* handlers are installed                                        */
 182
 183        pcc2chip[PccSCCMICR] = 0x10;
 184        pcc2chip[PccSCCTICR] = 0x10;
 185        pcc2chip[PccSCCRICR] = 0x10;
 186    }
 187}
 188
 189static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 190{
 191        p_bdid p = &mvme_bdid;
 192        unsigned long *new = (unsigned long *)vectors;
 193        unsigned long *old = (unsigned long *)0xffe00000;
 194        volatile unsigned char uc, *ucp;
 195
 196        if (p->brdno == 0x0162 || p->brdno == 0x172)
 197        {
 198                ucp = (volatile unsigned char *)0xfff42043;
 199                uc = *ucp | 8;
 200                *ucp = uc;
 201        }
 202        else
 203        {
 204                *(volatile unsigned long *)0xfff40074 = 0x40000000;
 205        }
 206        *(new+4) = *(old+4);            /* Illegal instruction */
 207        *(new+9) = *(old+9);            /* Trace */
 208        *(new+47) = *(old+47);          /* Trap #15 */
 209
 210        if (p->brdno == 0x0162 || p->brdno == 0x172)
 211                *(new+0x5e) = *(old+0x5e);      /* ABORT switch */
 212        else
 213                *(new+0x6e) = *(old+0x6e);      /* ABORT switch */
 214        return IRQ_HANDLED;
 215}
 216
 217static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 218{
 219    *(volatile unsigned char *)0xfff4201b |= 8;
 220    return tick_handler(irq, dev_id);
 221}
 222
 223void mvme16x_sched_init (irq_handler_t timer_routine)
 224{
 225    p_bdid p = &mvme_bdid;
 226    int irq;
 227
 228    tick_handler = timer_routine;
 229    /* Using PCCchip2 or MC2 chip tick timer 1 */
 230    *(volatile unsigned long *)0xfff42008 = 0;
 231    *(volatile unsigned long *)0xfff42004 = 10000;      /* 10ms */
 232    *(volatile unsigned char *)0xfff42017 |= 3;
 233    *(volatile unsigned char *)0xfff4201b = 0x16;
 234    if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0,
 235                                "timer", mvme16x_timer_int))
 236        panic ("Couldn't register timer int");
 237
 238    if (p->brdno == 0x0162 || p->brdno == 0x172)
 239        irq = MVME162_IRQ_ABORT;
 240    else
 241        irq = MVME167_IRQ_ABORT;
 242    if (request_irq(irq, mvme16x_abort_int, 0,
 243                                "abort", mvme16x_abort_int))
 244        panic ("Couldn't register abort int");
 245}
 246
 247
 248/* This is always executed with interrupts disabled.  */
 249unsigned long mvme16x_gettimeoffset (void)
 250{
 251    return (*(volatile unsigned long *)0xfff42008);
 252}
 253
 254int bcd2int (unsigned char b)
 255{
 256        return ((b>>4)*10 + (b&15));
 257}
 258
 259int mvme16x_hwclk(int op, struct rtc_time *t)
 260{
 261#warning check me!
 262        if (!op) {
 263                rtc->ctrl = RTC_READ;
 264                t->tm_year = bcd2int (rtc->bcd_year);
 265                t->tm_mon  = bcd2int (rtc->bcd_mth);
 266                t->tm_mday = bcd2int (rtc->bcd_dom);
 267                t->tm_hour = bcd2int (rtc->bcd_hr);
 268                t->tm_min  = bcd2int (rtc->bcd_min);
 269                t->tm_sec  = bcd2int (rtc->bcd_sec);
 270                rtc->ctrl = 0;
 271        }
 272        return 0;
 273}
 274
 275int mvme16x_set_clock_mmss (unsigned long nowtime)
 276{
 277        return 0;
 278}
 279
 280