1 /* 2 * Adapted for Motorola MPC8560 chips 3 * Xianghua Xiao <x.xiao@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@jlc.net) 11 * Copyright (c) 2000 MontaVista Software, Inc (source@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