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->dp_alloc_base = CPM_DATAONLY_BASE; 47 gd->dp_alloc_top = gd->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->dp_alloc_base; 73 74 if ((off = (gd->dp_alloc_base & align_mask)) != 0) 75 gd->dp_alloc_base += (align - off); 76 77 if ((off = size & align_mask) != 0) 78 size += align - off; 79 80 if ((gd->dp_alloc_base + size) >= gd->dp_alloc_top) { 81 gd->dp_alloc_base = savebase; 82 panic("m8560_cpm_dpalloc: ran out of dual port ram!"); 83 } 84 85 retloc = gd->dp_alloc_base; 86 gd->dp_alloc_base += size; 87 88 memset((void *)&(cpm->im_dprambase[retloc]), 0, size); 89 90 return(retloc); 91 } 92 93 /* We also own one page of host buffer space for the allocation of 94 * UART "fifos" and the like. 95 */ 96 uint 97 m8560_cpm_hostalloc(uint size, uint align) 98 { 99 /* the host might not even have RAM yet - just use dual port RAM */ 100 return (m8560_cpm_dpalloc(size, align)); 101 } 102 103 /* Set a baud rate generator. This needs lots of work. There are 104 * eight BRGs, which can be connected to the CPM channels or output 105 * as clocks. The BRGs are in two different block of internal 106 * memory mapped space. 107 * The baud rate clock is the system clock divided by something. 108 * It was set up long ago during the initial boot phase and is 109 * is given to us. 110 * Baud rate clocks are zero-based in the driver code (as that maps 111 * to port numbers). Documentation uses 1-based numbering. 112 */ 113 #define BRG_INT_CLK gd->brg_clk 114 #define BRG_UART_CLK ((BRG_INT_CLK + 15) / 16) 115 116 /* This function is used by UARTS, or anything else that uses a 16x 117 * oversampled clock. 118 */ 119 void 120 m8560_cpm_setbrg(uint brg, uint rate) 121 { 122 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 123 volatile uint *bp; 124 125 /* This is good enough to get SMCs running..... 126 */ 127 if (brg < 4) { 128 bp = (uint *)&(cpm->im_cpm_brg1.brgc1); 129 } 130 else { 131 bp = (uint *)&(cpm->im_cpm_brg2.brgc5); 132 brg -= 4; 133 } 134 bp += brg; 135 *bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN; 136 } 137 138 /* This function is used to set high speed synchronous baud rate 139 * clocks. 140 */ 141 void 142 m8560_cpm_fastbrg(uint brg, uint rate, int div16) 143 { 144 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 145 volatile uint *bp; 146 147 /* This is good enough to get SMCs running..... 148 */ 149 if (brg < 4) { 150 bp = (uint *)&(cpm->im_cpm_brg1.brgc1); 151 } 152 else { 153 bp = (uint *)&(cpm->im_cpm_brg2.brgc5); 154 brg -= 4; 155 } 156 bp += brg; 157 *bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN; 158 if (div16) 159 *bp |= CPM_BRG_DIV16; 160 } 161 162 /* This function is used to set baud rate generators using an external 163 * clock source and 16x oversampling. 164 */ 165 166 void 167 m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel) 168 { 169 volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR; 170 volatile uint *bp; 171 172 if (brg < 4) { 173 bp = (uint *)&(cpm->im_cpm_brg1.brgc1); 174 } 175 else { 176 bp = (uint *)&(cpm->im_cpm_brg2.brgc5); 177 brg -= 4; 178 } 179 bp += brg; 180 *bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN; 181 if (pinsel == 0) 182 *bp |= CPM_BRG_EXTC_CLK3_9; 183 else 184 *bp |= CPM_BRG_EXTC_CLK5_15; 185 } 186 187 #ifdef CONFIG_POST 188 189 void post_word_store (ulong a) 190 { 191 volatile ulong *save_addr = 192 (volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR); 193 194 *save_addr = a; 195 } 196 197 ulong post_word_load (void) 198 { 199 volatile ulong *save_addr = 200 (volatile ulong *)(CONFIG_SYS_IMMR + CPM_POST_WORD_ADDR); 201 202 return *save_addr; 203 } 204 205 #endif /* CONFIG_POST */ 206