u-boot/arch/powerpc/cpu/mpc85xx/commproc.c
Stefan Roese a47a12becf Move arch/ppc to arch/powerpc
As discussed on the list, move "arch/ppc" to "arch/powerpc" to
better match the Linux directory structure.

Please note that this patch also changes the "ppc" target in
MAKEALL to "powerpc" to match this new infrastructure. But "ppc"
is kept as an alias for now, to not break compatibility with
scripts using this name.

Signed-off-by: Stefan Roese <sr@denx.de>
Acked-by: Wolfgang Denk <wd@denx.de>
Acked-by: Detlev Zundel <dzu@denx.de>
Acked-by: Kim Phillips <kim.phillips@freescale.com>
Cc: Peter Tyser <ptyser@xes-inc.com>
Cc: Anatolij Gustschin <agust@denx.de>
2010-04-21 23:42:38 +02:00

205 lines
5.1 KiB
C

/*
* Adapted for Motorola MPC8560 chips
* Xianghua Xiao <x.xiao@motorola.com>
*
* This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
* copyright notice:
*
* General Purpose functions for the global management of the
* 8220 Communication Processor Module.
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
* Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
* 2.3.99 Updates
* Copyright (c) 2003 Motorola,Inc.
*
* 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.
*/
#include <common.h>
#include <asm/cpm_85xx.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* because we have stack and init data in dual port ram
* we must reduce the size
*/
#undef CPM_DATAONLY_SIZE
#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
void
m8560_cpm_reset(void)
{
volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
volatile ulong count;
gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
/* Reclaim the DP memory for our use.
*/
gd->dp_alloc_base = CPM_DATAONLY_BASE;
gd->dp_alloc_top = gd->dp_alloc_base + CPM_DATAONLY_SIZE;
/*
* Reset CPM
*/
cpm->im_cpm_cp.cpcr = CPM_CR_RST;
count = 0;
do { /* Spin until command processed */
__asm__ __volatile__ ("eieio");
} while ((cpm->im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
}
/* Allocate some memory from the dual ported ram.
* To help protocols with object alignment restrictions, we do that
* if they ask.
*/
uint
m8560_cpm_dpalloc(uint size, uint align)
{
volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
uint retloc;
uint align_mask, off;
uint savebase;
align_mask = align - 1;
savebase = gd->dp_alloc_base;
if ((off = (gd->dp_alloc_base & align_mask)) != 0)
gd->dp_alloc_base += (align - off);
if ((off = size & align_mask) != 0)
size += align - off;
if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) {
gd->dp_alloc_base = savebase;
panic("m8560_cpm_dpalloc: ran out of dual port ram!");
}
retloc = gd->dp_alloc_base;
gd->dp_alloc_base += size;
memset((void *)&(cpm->im_dprambase[retloc]), 0, size);
return(retloc);
}
/* We also own one page of host buffer space for the allocation of
* UART "fifos" and the like.
*/
uint
m8560_cpm_hostalloc(uint size, uint align)
{
/* the host might not even have RAM yet - just use dual port RAM */
return (m8560_cpm_dpalloc(size, align));
}
/* Set a baud rate generator. This needs lots of work. There are
* eight BRGs, which can be connected to the CPM channels or output
* as clocks. The BRGs are in two different block of internal
* memory mapped space.
* The baud rate clock is the system clock divided by something.
* It was set up long ago during the initial boot phase and is
* is given to us.
* Baud rate clocks are zero-based in the driver code (as that maps
* to port numbers). Documentation uses 1-based numbering.
*/
#define BRG_INT_CLK gd->brg_clk
#define BRG_UART_CLK ((BRG_INT_CLK + 15) / 16)
/* This function is used by UARTS, or anything else that uses a 16x
* oversampled clock.
*/
void
m8560_cpm_setbrg(uint brg, uint rate)
{
volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
volatile uint *bp;
/* This is good enough to get SMCs running.....
*/
if (brg < 4) {
bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
}
/* This function is used to set high speed synchronous baud rate
* clocks.
*/
void
m8560_cpm_fastbrg(uint brg, uint rate, int div16)
{
volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
volatile uint *bp;
/* This is good enough to get SMCs running.....
*/
if (brg < 4) {
bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
if (div16)
*bp |= CPM_BRG_DIV16;
}
/* This function is used to set baud rate generators using an external
* clock source and 16x oversampling.
*/
void
m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
{
volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
volatile uint *bp;
if (brg < 4) {
bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
}
else {
bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
brg -= 4;
}
bp += brg;
*bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
if (pinsel == 0)
*bp |= CPM_BRG_EXTC_CLK3_9;
else
*bp |= CPM_BRG_EXTC_CLK5_15;
}
#ifdef CONFIG_POST
void post_word_store (ulong a)
{
volatile ulong *save_addr =
(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
*save_addr = a;
}
ulong post_word_load (void)
{
volatile ulong *save_addr =
(volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR);
return *save_addr;
}
#endif /* CONFIG_POST */