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