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