Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3595962 authored by Greg Ungerer's avatar Greg Ungerer
Browse files

m68knommu: remove obsolete 68360 support



Remove the obsolete Motorola/Freescale 68360 SoC support. It has been
bit rotting for many years with little active use in mainlne. There has
been no serial driver support for many years, so it is largely not
useful in its current state.

Signed-off-by: default avatarGreg Ungerer <gerg@uclinux.org>
parent ca6fafd1
Loading
Loading
Loading
Loading

arch/m68k/68360/Makefile

deleted100644 → 0
+0 −12
Original line number Diff line number Diff line
#
# Makefile for 68360 machines.
#
model-y			  := ram
model-$(CONFIG_ROMKERNEL) := rom

obj-y := config.o commproc.o entry.o ints.o

extra-y := head.o

$(obj)/head.o: $(obj)/head-$(model-y).o
	ln -sf head-$(model-y).o $(obj)/head.o

arch/m68k/68360/commproc.c

deleted100644 → 0
+0 −309
Original line number Diff line number Diff line
/*
 * General Purpose functions for the global management of the
 * Communication Processor Module.
 *
 * Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
 * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
 *
 * In addition to the individual control of the communication
 * channels, there are a few functions that globally affect the
 * communication processor.
 *
 * Buffer descriptors must be allocated from the dual ported memory
 * space.  The allocator for that is here.  When the communication
 * process is reset, we reclaim the memory available.  There is
 * currently no deallocator for this memory.
 * The amount of space available is platform dependent.  On the
 * MBX, the EPPC software loads additional microcode into the
 * communication processor, and uses some of the DP ram for this
 * purpose.  Current, the first 512 bytes and the last 256 bytes of
 * memory are used.  Right now I am conservative and only use the
 * memory that can never be used for microcode.  If there are
 * applications that require more DP ram, we can expand the boundaries
 * but then we have to be careful of any downloaded microcode.
 *
 */

/*
 * Michael Leslie <mleslie@lineo.com>
 * adapted Dan Malek's ppc8xx drivers to M68360
 *
 */

#include <linux/errno.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/m68360.h>
#include <asm/commproc.h>

/* #include <asm/page.h> */
/* #include <asm/pgtable.h> */
extern void *_quicc_base;
extern unsigned int system_clock;


static uint dp_alloc_base;	/* Starting offset in DP ram */
static uint dp_alloc_top;	/* Max offset + 1 */

#if 0
static	void	*host_buffer;	/* One page of host buffer */
static	void	*host_end;	    /* end + 1 */
#endif

/* struct  cpm360_t *cpmp; */         /* Pointer to comm processor space */

QUICC  *pquicc;
/* QUICC  *quicc_dpram; */ /* mleslie - temporary; use extern pquicc elsewhere instead */


/* CPM interrupt vector functions. */
struct	cpm_action {
	irq_handler_t	handler;
	void		*dev_id;
};
static	struct	cpm_action cpm_vecs[CPMVEC_NR];
static	void	cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
static	void	cpm_error_interrupt(void *);

/* prototypes: */
void cpm_install_handler(int vec, irq_handler_t handler, void *dev_id);
void m360_cpm_reset(void);




void __init m360_cpm_reset()
{
/* 	pte_t		   *pte; */

	pquicc = (struct quicc *)(_quicc_base); /* initialized in crt0_rXm.S */

	/* Perform a CPM reset. */
	pquicc->cp_cr = (SOFTWARE_RESET | CMD_FLAG);

	/* Wait for CPM to become ready (should be 2 clocks). */
	while (pquicc->cp_cr & CMD_FLAG);

	/* On the recommendation of the 68360 manual, p. 7-60
	 * - Set sdma interrupt service mask to 7
	 * - Set sdma arbitration ID to 4
	 */
	pquicc->sdma_sdcr = 0x0740;


	/* Claim the DP memory for our use.
	 */
	dp_alloc_base = CPM_DATAONLY_BASE;
	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;


	/* Set the host page for allocation.
	 */
	/* 	host_buffer = host_page_addr; */
	/* 	host_end = host_page_addr + PAGE_SIZE; */

	/* 	pte = find_pte(&init_mm, host_page_addr); */
	/* 	pte_val(*pte) |= _PAGE_NO_CACHE; */
	/* 	flush_tlb_page(current->mm->mmap, host_buffer); */

	/* Tell everyone where the comm processor resides.
	*/
/* 	cpmp = (cpm360_t *)commproc; */
}


/* This is called during init_IRQ.  We used to do it above, but this
 * was too early since init_IRQ was not yet called.
 */
void
cpm_interrupt_init(void)
{
	/* Initialize the CPM interrupt controller.
	 * NOTE THAT pquicc had better have been initialized!
	 * reference: MC68360UM p. 7-377
	 */
	pquicc->intr_cicr =
		(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
		(CPM_INTERRUPT << 13) |
		CICR_HP_MASK |
		(CPM_VECTOR_BASE << 5) |
		CICR_SPS;

	/* mask all CPM interrupts from reaching the cpu32 core: */
	pquicc->intr_cimr = 0;


	/* mles - If I understand correctly, the 360 just pops over to the CPM
	 * specific vector, obviating the necessity to vector through the IRQ
	 * whose priority the CPM is set to. This needs a closer look, though.
	 */

	/* Set our interrupt handler with the core CPU. */
/* 	if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) */
/* 		panic("Could not allocate CPM IRQ!"); */

	/* Install our own error handler.
	 */
	/* I think we want to hold off on this one for the moment - mles */
	/* cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); */

	/* master CPM interrupt enable */
	/* pquicc->intr_cicr |= CICR_IEN; */ /* no such animal for 360 */
}



/* CPM interrupt controller interrupt.
*/
static	void
cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
{
	/* uint	vec; */

	/* mles: Note that this stuff is currently being performed by
	 * M68360_do_irq(int vec, struct pt_regs *fp), in ../ints.c  */

	/* figure out the vector */
	/* call that vector's handler */
	/* clear the irq's bit in the service register */

#if 0 /* old 860 stuff: */
	/* Get the vector by setting the ACK bit and then reading
	 * the register.
	 */
	((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
	vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
	vec >>= 11;


	if (cpm_vecs[vec].handler != 0)
		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
	else
		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);

	/* After servicing the interrupt, we have to remove the status
	 * indicator.
	 */
	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
#endif

}

/* The CPM can generate the error interrupt when there is a race condition
 * between generating and masking interrupts.  All we have to do is ACK it
 * and return.  This is a no-op function so we don't need any special
 * tests in the interrupt handler.
 */
static	void
cpm_error_interrupt(void *dev)
{
}

/* Install a CPM interrupt handler.
*/
void
cpm_install_handler(int vec, irq_handler_t handler, void *dev_id)
{

	request_irq(vec, handler, 0, "timer", dev_id);

/* 	if (cpm_vecs[vec].handler != 0) */
/* 		printk(KERN_INFO "CPM interrupt %x replacing %x\n", */
/* 			(uint)handler, (uint)cpm_vecs[vec].handler); */
/* 	cpm_vecs[vec].handler = handler; */
/* 	cpm_vecs[vec].dev_id = dev_id; */

	/*              ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); */
/* 	pquicc->intr_cimr |= (1 << vec); */

}

/* Free a CPM interrupt handler.
*/
void
cpm_free_handler(int vec)
{
	cpm_vecs[vec].handler = NULL;
	cpm_vecs[vec].dev_id = NULL;
	/* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); */
	pquicc->intr_cimr &= ~(1 << vec);
}




/* Allocate some memory from the dual ported ram.  We may want to
 * enforce alignment restrictions, but right now everyone is a good
 * citizen.
 */
uint
m360_cpm_dpalloc(uint size)
{
        uint    retloc;

        if ((dp_alloc_base + size) >= dp_alloc_top)
                return(CPM_DP_NOSPACE);

        retloc = dp_alloc_base;
        dp_alloc_base += size;

        return(retloc);
}


#if 0 /* mleslie - for now these are simply kmalloc'd */
/* We also own one page of host buffer space for the allocation of
 * UART "fifos" and the like.
 */
uint
m360_cpm_hostalloc(uint size)
{
	uint	retloc;

	if ((host_buffer + size) >= host_end)
		return(0);

	retloc = host_buffer;
	host_buffer += size;

	return(retloc);
}
#endif


/* Set a baud rate generator.  This needs lots of work.  There are
 * four BRGs, any of which can be wired to any channel.
 * The internal baud rate clock is the system clock divided by 16.
 * This assumes the baudrate is 16x oversampled by the uart.
 */
/* #define BRG_INT_CLK	(((bd_t *)__res)->bi_intfreq * 1000000) */
#define BRG_INT_CLK		system_clock
#define BRG_UART_CLK	(BRG_INT_CLK/16)

void
m360_cpm_setbrg(uint brg, uint rate)
{
	volatile uint	*bp;

	/* This is good enough to get SMCs running.....
	 */
	/* bp = (uint *)&cpmp->cp_brgc1; */
	bp = (volatile uint *)(&pquicc->brgc[0].l);
	bp += brg;
	*bp = ((BRG_UART_CLK / rate - 1) << 1) | CPM_BRG_EN;
}


/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 */

arch/m68k/68360/config.c

deleted100644 → 0
+0 −169
Original line number Diff line number Diff line
/*
 *  config.c - non-mmu 68360 platform initialization code
 *
 *  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>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>

#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

static irq_handler_t timer_interrupt;
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


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

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

  return timer_interrupt(irq, dummy);
}

static struct irqaction m68360_timer_irq = {
	.name	 = "timer",
	.flags	 = IRQF_TIMER,
	.handler = hw_tick,
};

void hw_timer_init(irq_handler_t handler)
{
  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;                                                              

  request_irq(IRQ_MACHSPEC | 1, timer_routine, 0, "timer", NULL);
#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 */

  timer_interrupt = handler;

  /* enable timer 1 interrupt in CIMR */
  setup_irq(CPMVEC_TIMER1, &m68360_timer_irq);

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

void BSP_reset (void)
{
  local_irq_disable();
  asm volatile (
    "moveal #_start, %a0;\n"
    "moveb #0, 0xFFFFF300;\n"
    "moveal 0(%a0), %sp;\n"
    "moveal 4(%a0), %a0;\n"
    "jmp (%a0);\n"
    );
}

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


void __init config_BSP(char *command, int len)
{
  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 %pM\n", p);

  p = getbenv("APPEND");
  if (p)
    strcpy(p,command);
  else
    command[0] = 0;
#else
  scc1_hwaddr = "\00\01\02\03\04\05";
#endif
 
  mach_reset = BSP_reset;
}

arch/m68k/68360/entry.S

deleted100644 → 0
+0 −164
Original line number Diff line number Diff line
/*
 *  entry.S - non-mmu 68360 interrupt and exceptions entry points
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 2001 SED Systems, a Division of Calian Ltd.
 *
 * 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.
 *
 * Linux/m68k support by Hamish Macdonald
 * M68360 Port by SED Systems, and Lineo.
 */

#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/traps.h>
#include <asm/asm-offsets.h>
#include <asm/entry.h>

.text

.globl system_call
.globl resume
.globl ret_from_exception
.globl ret_from_signal
.globl sys_call_table
.globl bad_interrupt
.globl inthandler

badsys:
	movel	#-ENOSYS,%sp@(PT_OFF_D0)
	jra	ret_from_exception

do_trace:
	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
	subql	#4,%sp
	SAVE_SWITCH_STACK
	jbsr	syscall_trace_enter
	RESTORE_SWITCH_STACK
	addql	#4,%sp
	movel	%sp@(PT_OFF_ORIG_D0),%d1
	movel	#-ENOSYS,%d0
	cmpl	#NR_syscalls,%d1
	jcc	1f
	lsl	#2,%d1
	lea	sys_call_table, %a0
	jbsr	%a0@(%d1)

1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
	subql	#4,%sp			/* dummy return address */
	SAVE_SWITCH_STACK
	jbsr	syscall_trace_leave

ret_from_signal:
	RESTORE_SWITCH_STACK
	addql	#4,%sp
	jra	ret_from_exception

ENTRY(system_call)
	SAVE_ALL_SYS

	/* save top of frame*/
	pea	%sp@
	jbsr	set_esp0
	addql	#4,%sp

	movel	%sp@(PT_OFF_ORIG_D0),%d0

	movel	%sp,%d1			/* get thread_info pointer */
	andl	#-THREAD_SIZE,%d1
	movel	%d1,%a2
	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TINFO_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
	jne	do_trace
	cmpl	#NR_syscalls,%d0
	jcc	badsys
	lsl	#2,%d0
	lea	sys_call_table,%a0
	movel	%a0@(%d0), %a0
	jbsr	%a0@
	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/

ret_from_exception:
	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
	jeq	Luser_return		/* if so, skip resched, signals*/

Lkernel_return:
	RESTORE_ALL

Luser_return:
	/* only allow interrupts when we are really the last one on the*/
	/* kernel stack, otherwise stack overflow can occur during*/
	/* heavy interrupt load*/
	andw	#ALLOWINT,%sr

	movel	%sp,%d1			/* get thread_info pointer */
	andl	#-THREAD_SIZE,%d1
	movel	%d1,%a2
1:
	move	%a2@(TINFO_FLAGS),%d1	/* thread_info->flags */
	jne	Lwork_to_do
	RESTORE_ALL

Lwork_to_do:
	movel	%a2@(TINFO_FLAGS),%d1	/* thread_info->flags */
	btst	#TIF_NEED_RESCHED,%d1
	jne	reschedule

Lsignal_return:
	subql	#4,%sp			/* dummy return address*/
	SAVE_SWITCH_STACK
	pea	%sp@(SWITCH_STACK_SIZE)
	bsrw	do_notify_resume
	addql	#4,%sp
	RESTORE_SWITCH_STACK
	addql	#4,%sp
	jra	1b

/*
 * This is the main interrupt handler, responsible for calling do_IRQ()
 */
inthandler:
	SAVE_ALL_INT
	movew	%sp@(PT_OFF_FORMATVEC), %d0
	and.l	#0x3ff, %d0
	lsr.l   #0x02,  %d0

	movel	%sp,%sp@-
	movel	%d0,%sp@- 		/*  put vector # on stack*/
	jbsr	do_IRQ			/*  process the IRQ */
	addql	#8,%sp			/*  pop parameters off stack*/
	jra	ret_from_exception

/*
 * Handler for uninitialized and spurious interrupts.
 */
bad_interrupt:
	addql	#1,irq_err_count
	rte

/*
 * Beware - when entering resume, prev (the current task) is
 * in a0, next (the new task) is in a1, so don't change these
 * registers until their contents are no longer needed.
 */
ENTRY(resume)
	movel	%a0,%d1				/* save prev thread in d1 */
	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
	SAVE_SWITCH_STACK
	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
	movel	%usp,%a3			/* save usp */
	movel	%a3,%a0@(TASK_THREAD+THREAD_USP)

	movel	%a1@(TASK_THREAD+THREAD_USP),%a3 /* restore user stack */
	movel	%a3,%usp
	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
	RESTORE_SWITCH_STACK
	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
	rts

arch/m68k/68360/head-ram.S

deleted100644 → 0
+0 −402

File deleted.

Preview size limit exceeded, changes collapsed.

Loading