Home | History | Annotate | Download | only in mpc85xx
      1 /*
      2  * Adapted for Motorola MPC8560 chips
      3  * Xianghua Xiao <x.xiao (at) motorola.com>
      4  *
      5  * This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
      6  * copyright notice:
      7  *
      8  * General Purpose functions for the global management of the
      9  * 8220 Communication Processor Module.
     10  * Copyright (c) 1999 Dan Malek (dmalek (at) jlc.net)
     11  * Copyright (c) 2000 MontaVista Software, Inc (source (at) mvista.com)
     12  *	2.3.99 Updates
     13  * Copyright (c) 2003 Motorola,Inc.
     14  *
     15  * In addition to the individual control of the communication
     16  * channels, there are a few functions that globally affect the
     17  * communication processor.
     18  *
     19  * Buffer descriptors must be allocated from the dual ported memory
     20  * space.  The allocator for that is here.  When the communication
     21  * process is reset, we reclaim the memory available.  There is
     22  * currently no deallocator for this memory.
     23  */
     24 #include <common.h>
     25 #include <asm/cpm_85xx.h>
     26 
     27 DECLARE_GLOBAL_DATA_PTR;
     28 
     29 /*
     30  * because we have stack and init data in dual port ram
     31  * we must reduce the size
     32  */
     33 #undef	CPM_DATAONLY_SIZE
     34 #define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
     35 
     36 void
     37 m8560_cpm_reset(void)
     38 {
     39 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
     40 	volatile ulong count;
     41 
     42 	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
     43 
     44 	/* Reclaim the DP memory for our use.
     45 	*/
     46 	gd->arch.dp_alloc_base = CPM_DATAONLY_BASE;
     47 	gd->arch.dp_alloc_top = gd->arch.dp_alloc_base + CPM_DATAONLY_SIZE;
     48 
     49 	/*
     50 	 * Reset CPM
     51 	 */
     52 	cpm->im_cpm_cp.cpcr = CPM_CR_RST;
     53 	count = 0;
     54 	do {			/* Spin until command processed		*/
     55 		__asm__ __volatile__ ("eieio");
     56 	} while ((cpm->im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
     57 }
     58 
     59 /* Allocate some memory from the dual ported ram.
     60  * To help protocols with object alignment restrictions, we do that
     61  * if they ask.
     62  */
     63 uint
     64 m8560_cpm_dpalloc(uint size, uint align)
     65 {
     66 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
     67 	uint	retloc;
     68 	uint	align_mask, off;
     69 	uint	savebase;
     70 
     71 	align_mask = align - 1;
     72 	savebase = gd->arch.dp_alloc_base;
     73 
     74 	off = gd->arch.dp_alloc_base & align_mask;
     75 	if (off != 0)
     76 		gd->arch.dp_alloc_base += (align - off);
     77 
     78 	if ((off = size & align_mask) != 0)
     79 		size += align - off;
     80 
     81 	if ((gd->arch.dp_alloc_base + size) >= gd->arch.dp_alloc_top) {
     82 		gd->arch.dp_alloc_base = savebase;
     83 		panic("m8560_cpm_dpalloc: ran out of dual port ram!");
     84 	}
     85 
     86 	retloc = gd->arch.dp_alloc_base;
     87 	gd->arch.dp_alloc_base += size;
     88 
     89 	memset((void *)&(cpm->im_dprambase[retloc]), 0, size);
     90 
     91 	return(retloc);
     92 }
     93 
     94 /* We also own one page of host buffer space for the allocation of
     95  * UART "fifos" and the like.
     96  */
     97 uint
     98 m8560_cpm_hostalloc(uint size, uint align)
     99 {
    100 	/* the host might not even have RAM yet - just use dual port RAM */
    101 	return (m8560_cpm_dpalloc(size, align));
    102 }
    103 
    104 /* Set a baud rate generator.  This needs lots of work.  There are
    105  * eight BRGs, which can be connected to the CPM channels or output
    106  * as clocks.  The BRGs are in two different block of internal
    107  * memory mapped space.
    108  * The baud rate clock is the system clock divided by something.
    109  * It was set up long ago during the initial boot phase and is
    110  * is given to us.
    111  * Baud rate clocks are zero-based in the driver code (as that maps
    112  * to port numbers).  Documentation uses 1-based numbering.
    113  */
    114 #define BRG_INT_CLK	gd->arch.brg_clk
    115 #define BRG_UART_CLK	((BRG_INT_CLK + 15) / 16)
    116 
    117 /* This function is used by UARTS, or anything else that uses a 16x
    118  * oversampled clock.
    119  */
    120 void
    121 m8560_cpm_setbrg(uint brg, uint rate)
    122 {
    123 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
    124 	volatile uint	*bp;
    125 
    126 	/* This is good enough to get SMCs running.....
    127 	*/
    128 	if (brg < 4) {
    129 		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
    130 	}
    131 	else {
    132 		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
    133 		brg -= 4;
    134 	}
    135 	bp += brg;
    136 	*bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
    137 }
    138 
    139 /* This function is used to set high speed synchronous baud rate
    140  * clocks.
    141  */
    142 void
    143 m8560_cpm_fastbrg(uint brg, uint rate, int div16)
    144 {
    145 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
    146 	volatile uint	*bp;
    147 
    148 	/* This is good enough to get SMCs running.....
    149 	*/
    150 	if (brg < 4) {
    151 		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
    152 	}
    153 	else {
    154 		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
    155 		brg -= 4;
    156 	}
    157 	bp += brg;
    158 	*bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
    159 	if (div16)
    160 		*bp |= CPM_BRG_DIV16;
    161 }
    162 
    163 /* This function is used to set baud rate generators using an external
    164  * clock source and 16x oversampling.
    165  */
    166 
    167 void
    168 m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
    169 {
    170 	volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
    171 	volatile uint	*bp;
    172 
    173 	if (brg < 4) {
    174 		bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
    175 	}
    176 	else {
    177 		bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
    178 		brg -= 4;
    179 	}
    180 	bp += brg;
    181 	*bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
    182 	if (pinsel == 0)
    183 		*bp |= CPM_BRG_EXTC_CLK3_9;
    184 	else
    185 		*bp |= CPM_BRG_EXTC_CLK5_15;
    186 }
    187