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