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