config.c 4.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *  config.c - non-mmu 68360 platform initialization code
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13
 *
 *  Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
 *  Copyright (C) 1993 Hamish Macdonald
 *  Copyright (C) 1999 D. Jeff Dionne <jeff@uclinux.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 */

#include <stdarg.h>
14
#include <linux/init.h>
L
Linus Torvalds 已提交
15 16 17
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
18
#include <linux/interrupt.h>
19
#include <linux/irq.h>
L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

#include <asm/setup.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
#include <asm/m68360.h>

#ifdef CONFIG_UCQUICC
#include <asm/bootstd.h>
#endif

extern void m360_cpm_reset(void);

// Mask to select if the PLL prescaler is enabled.
#define MCU_PREEN   ((unsigned short)(0x0001 << 13))

#if defined(CONFIG_UCQUICC)
#define OSCILLATOR  (unsigned long int)33000000
#endif

39
static irq_handler_t timer_interrupt;
L
Linus Torvalds 已提交
40 41 42 43 44 45 46 47 48
unsigned long int system_clock;

extern QUICC *pquicc;

/* TODO  DON"T Hard Code this */
/* calculate properly using the right PLL and prescaller */
// unsigned int system_clock = 33000000l;
extern unsigned long int system_clock; //In kernel setup.c

49 50 51 52 53 54 55 56

static irqreturn_t hw_tick(int irq, void *dummy)
{
  /* Reset Timer1 */
  /* TSTAT &= 0; */

  pquicc->timer_ter1 = 0x0002; /* clear timer event */

57
  return timer_interrupt(irq, dummy);
58
}
L
Linus Torvalds 已提交
59

60
static struct irqaction m68360_timer_irq = {
61
	.name	 = "timer",
62
	.flags	 = IRQF_TIMER,
63
	.handler = hw_tick,
64 65
};

66
void hw_timer_init(irq_handler_t handler)
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75 76 77 78
{
  unsigned char prescaler;
  unsigned short tgcr_save;

#if 0
  /* Restart mode, Enable int, 32KHz, Enable timer */
  TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
  /* Set prescaler (Divide 32KHz by 32)*/
  TPRER = 31;
  /* Set compare register  32Khz / 32 / 10 = 100 */
  TCMP = 10;                                                              

79
  request_irq(IRQ_MACHSPEC | 1, timer_routine, 0, "timer", NULL);
L
Linus Torvalds 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#endif

  /* General purpose quicc timers: MC68360UM p7-20 */

  /* Set up timer 1 (in [1..4]) to do 100Hz */
  tgcr_save = pquicc->timer_tgcr & 0xfff0;
  pquicc->timer_tgcr  = tgcr_save; /* stop and reset timer 1 */
  /* pquicc->timer_tgcr |= 0x4444; */ /* halt timers when FREEZE (ie bdm freeze) */

  prescaler = 8;
  pquicc->timer_tmr1 = 0x001a | /* or=1, frr=1, iclk=01b */
                           (unsigned short)((prescaler - 1) << 8);
    
  pquicc->timer_tcn1 = 0x0000; /* initial count */
  /* calculate interval for 100Hz based on the _system_clock: */
  pquicc->timer_trr1 = (system_clock/ prescaler) / HZ; /* reference count */

  pquicc->timer_ter1 = 0x0003; /* clear timer events */

99 100
  timer_interrupt = handler;

L
Linus Torvalds 已提交
101
  /* enable timer 1 interrupt in CIMR */
102
  setup_irq(CPMVEC_TIMER1, &m68360_timer_irq);
L
Linus Torvalds 已提交
103 104 105 106 107 108 109 110 111

  /* Start timer 1: */
  tgcr_save = (pquicc->timer_tgcr & 0xfff0) | 0x0001;
  pquicc->timer_tgcr  = tgcr_save;
}

void BSP_reset (void)
{
  local_irq_disable();
112 113 114 115 116 117 118
  asm volatile (
    "moveal #_start, %a0;\n"
    "moveb #0, 0xFFFFF300;\n"
    "moveal 0(%a0), %sp;\n"
    "moveal 4(%a0), %a0;\n"
    "jmp (%a0);\n"
    );
L
Linus Torvalds 已提交
119 120 121 122 123 124 125 126 127 128 129 130
}

unsigned char *scc1_hwaddr;
static int errno;

#if defined (CONFIG_UCQUICC)
_bsc0(char *, getserialnum)
_bsc1(unsigned char *, gethwaddr, int, a)
_bsc1(char *, getbenv, char *, a)
#endif


131
void __init config_BSP(char *command, int len)
L
Linus Torvalds 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
{
  unsigned char *p;

  m360_cpm_reset();

  /* Calculate the real system clock value. */
  {
     unsigned int local_pllcr = (unsigned int)(pquicc->sim_pllcr);
     if( local_pllcr & MCU_PREEN ) // If the prescaler is dividing by 128
     {
         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
         system_clock = (OSCILLATOR / 128) * (mf + 1);
     }
     else
     {
         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
         system_clock = (OSCILLATOR) * (mf + 1);
     }
  }

  printk(KERN_INFO "\n68360 QUICC support (C) 2000 Lineo Inc.\n");

#if defined(CONFIG_UCQUICC) && 0
  printk(KERN_INFO "uCquicc serial string [%s]\n",getserialnum());
  p = scc1_hwaddr = gethwaddr(0);
  printk(KERN_INFO "uCquicc hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
         p[0], p[1], p[2], p[3], p[4], p[5]);

  p = getbenv("APPEND");
  if (p)
    strcpy(p,command);
  else
    command[0] = 0;
#else
  scc1_hwaddr = "\00\01\02\03\04\05";
#endif
 
169
  mach_reset = BSP_reset;
L
Linus Torvalds 已提交
170
}