diff options
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc8260/cpm')
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc8260/cpm/.cvsignore | 2 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc8260/cpm/Makefile.am | 29 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c | 204 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc8260/cpm/cp.c | 35 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc8260/cpm/dpram.c | 91 |
5 files changed, 361 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc8260/cpm/.cvsignore b/c/src/lib/libcpu/powerpc/mpc8260/cpm/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc8260/cpm/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libcpu/powerpc/mpc8260/cpm/Makefile.am b/c/src/lib/libcpu/powerpc/mpc8260/cpm/Makefile.am new file mode 100644 index 0000000000..55cd146dff --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc8260/cpm/Makefile.am @@ -0,0 +1,29 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = ${ARCH}/cp.rel + +## C sources +C_FILES = cp.c dpram.c brg.c + +cpm_rel_OBJECTS = $(C_FILES:%.c=${ARCH}/%.o) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../automake/compile.am +include $(top_srcdir)/../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(cpm_rel_OBJECTS) + $(make-rel) + +all-local: ${ARCH} $(PGM) + +EXTRA_DIST = $(C_FILES) + +include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c b/c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c new file mode 100644 index 0000000000..c6e48be0b0 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c @@ -0,0 +1,204 @@ +/* + * Baud rate generator management functions. + * + * This file contains routines for allocating baud rate generators + * and clock sources to the SCCs and FCCs on the MPC8260. The + * allocation is a little more complex on this processor because + * there are restrictions on which brgs and clks can be assigned to + * a particular port. Rather than coming up with a fixed assignment + * these routines try to allocate resources sensibly. + * + * *** All attempts to allocate a BRG or CLK line should be made via + * calls to these routines or they simply won't work. + * + * Author: Andy Dachs <a.dachs@sstl.co.uk> + * Copyright Surrey Satellite Technology Limited (SSTL), 2001 + * + * Derived in part from work by: + * + * Author: Jay Monkman (jmonkman@frasca.com) + * Copyright (C) 1998 by Frasca International, Inc. + * and + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <rtems.h> +#include <mpc8260.h> +#include <mpc8260/cpm.h> +#include <bspIo.h> + +#define NUM_BRGS 8 +#define NUM_CLKS 20 + +/* Used to track the usage of the baud rate generators */ +/* (initialised to zeros) */ +static unsigned long brg_spd[NUM_BRGS]; +static unsigned int brg_use_count[NUM_BRGS]; + + +/* Used to track the usage of the clock inputs */ +/* (initialised to zeros) */ +static unsigned int clk_use_count[NUM_BRGS]; + + +extern rtems_cpu_table Cpu_table; + +/* + * Compute baud-rate-generator configuration register value + */ +int +m8xx_get_brg_cd (int baud) +{ + int divisor; + int div16 = 0; + + divisor = ((Cpu_table.serial_per_sec) + (baud / 2)) / baud; + if (divisor > 4096) { + div16 = 1; + divisor = (divisor + 8) / 16; + } + return M8260_BRG_EN | M8260_BRG_EXTC_BRGCLK | + ((divisor - 1) << 1) | div16; +} + + +/* + * Allocates an existing brg if one is already programmed for the same + * baud rate. Otherwise a new brg is assigned + * AFD: on the mpc8260 only some combinations of SCC/SMC and BRG are allowed + * so add a mask which specifies which of the BRGs we can choose from + */ +int +m8xx_get_brg(unsigned brgmask, int baud) +{ + int i; + + /* first try to find a BRG that is already at the right speed */ + for ( i = 0; i < NUM_BRGS; i++ ) { + if( (1 << i) & brgmask ) /* is this brg allowed? */ + if ( brg_spd[i] == baud ) { + break; + } + } + + if ( i == NUM_BRGS ) { /* I guess we didn't find one */ + for ( i = 0; i < NUM_BRGS; i++ ) { + if (((1<<i) & brgmask) && (brg_use_count[i] == 0)) { + break; + } + } + } + if (i != NUM_BRGS) { + brg_use_count[i]++; + brg_spd[i]=baud; + switch (i) { + case 0: + m8260.brgc1 = M8260_BRG_RST; + m8260.brgc1 = m8xx_get_brg_cd(baud); + break; + case 1: + m8260.brgc2 = M8260_BRG_RST; + m8260.brgc2 = m8xx_get_brg_cd(baud); + break; + case 2: + m8260.brgc3 = M8260_BRG_RST; + m8260.brgc3 = m8xx_get_brg_cd(baud); + break; + case 3: + m8260.brgc4 = M8260_BRG_RST; + m8260.brgc4 = m8xx_get_brg_cd(baud); + break; + case 4: + m8260.brgc5 = M8260_BRG_RST; + m8260.brgc5 = m8xx_get_brg_cd(baud); + break; + case 5: + m8260.brgc6 = M8260_BRG_RST; + m8260.brgc6 = m8xx_get_brg_cd(baud); + break; + case 6: + m8260.brgc7 = M8260_BRG_RST; + m8260.brgc7 = m8xx_get_brg_cd(baud); + break; + case 7: + m8260.brgc8 = M8260_BRG_RST; + m8260.brgc8 = m8xx_get_brg_cd(baud); + break; + } + return i; + } + + else { + printk( "Could not assign a brg for %d\n", baud ); + return -1; + } +} + + +/* + * When the brg is no longer needed call this routine to free the + * resource for re--use. + */ +void +m8xx_free_brg( int brg_num ) +{ + if( (brg_num>=0) && (brg_num<NUM_BRGS) ) + if(brg_use_count[brg_num] > 0 ) + brg_use_count[brg_num]--; +} + + +void m8xx_dump_brgs( void ) +{ + int i; + for(i=0; i<NUM_BRGS; i++ ) + printk( "Brg[%d]: %d %d\n", i, brg_use_count[i], brg_spd[i] ); +} + + +/* + * Reserve one of a range of clock inputs + */ +int +m8xx_get_clk( unsigned clkmask ) +{ + int i; + + for ( i = 0; i < NUM_CLKS; i++ ) { + if (((1<<i) & clkmask) && (clk_use_count[i] == 0)) { + break; + } + } + + if (i != NUM_CLKS) { + clk_use_count[i]++; + return i; + } else { + printk( "Could not assign clock in the range %X\n", clkmask ); + return -1; + } +} + + +/* + * When the clock is no longer needed call this routine to free the + * resource for re--use. + */ +void +m8xx_free_clk( int clk_num ) +{ + if( (clk_num>=0) && (clk_num<NUM_BRGS) ) + if(clk_use_count[clk_num] > 0 ) + clk_use_count[clk_num]--; +} diff --git a/c/src/lib/libcpu/powerpc/mpc8260/cpm/cp.c b/c/src/lib/libcpu/powerpc/mpc8260/cpm/cp.c new file mode 100644 index 0000000000..cfcae7b325 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc8260/cpm/cp.c @@ -0,0 +1,35 @@ +/* + * cp.c + * + * MPC8xx CPM RISC Communication Processor routines. + * + * Based on code (alloc860.c in eth_comm port) by + * Jay Monkman (jmonkman@frasca.com), + * which, in turn, is based on code by + * W. Eric Norum (eric@skatter.usask.ca). + * + * Modifications by Darlene Stewart (Darlene.Stewart@iit.nrc.ca): + * Copyright (c) 1999, National Research Council of Canada + */ + +#include <rtems.h> +#include <mpc8260.h> +#include <mpc8260/cpm.h> + +/* + * Send a command to the CPM RISC processer + */ + +void m8xx_cp_execute_cmd( unsigned32 command ) +{ + rtems_unsigned16 lvl; + + rtems_interrupt_disable(lvl); + while (m8260.cpcr & M8260_CR_FLG) { + continue; + } + + m8260.cpcr = command | M8260_CR_FLG; + rtems_interrupt_enable (lvl); +} + diff --git a/c/src/lib/libcpu/powerpc/mpc8260/cpm/dpram.c b/c/src/lib/libcpu/powerpc/mpc8260/cpm/dpram.c new file mode 100644 index 0000000000..7fb8f512a6 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc8260/cpm/dpram.c @@ -0,0 +1,91 @@ +/* + * dpram.c + * + * MPC8260 dual-port RAM allocation routines + * + * Based on code in mpc8xx which is + * Based on code (alloc860.c in eth_comm port) by + * Jay Monkman (jmonkman@frasca.com), + * which, in turn, is based on code by + * W. Eric Norum (eric@skatter.usask.ca). + * + * + * Modifications : + * Copyright (c) 1999, National Research Council of Canada + * + * MPC8260 modifications Andy Dachs, <a.dachs@sstl.co.uk> + * Surrey Satellite Technology Limited, 2001 + */ + +#include <rtems.h> +#include <mpc8260.h> +#include <mpc8260/cpm.h> + +/* + * Allocation order: + * - Dual-Port RAM section 0 + * - Dual-Port RAM section 1 + * - Dual-Port RAM section 2 + * - Dual-Port RAM section 3 + */ +static struct { + unsigned8 *base; + unsigned int size; + unsigned int used; +} dpram_regions[] = { +/* { (char *)&m8260.dpram0[0], sizeof m8260.dpram0, 0 },*/ + { (char *)&m8260.dpram1[0], sizeof m8260.dpram1, 0 }, +/* { (char *)&m8260.dpram2[0], sizeof m8260.dpram2, 0 },*/ + { (char *)&m8260.dpram3[0], sizeof m8260.dpram3, 0 } +}; + +#define NUM_DPRAM_REGIONS (sizeof(dpram_regions) / sizeof(dpram_regions[0])) + +void * +m8xx_dpram_allocate( unsigned int byte_count ) +{ + unsigned int i; + ISR_Level level; + void *blockp = NULL; + + byte_count = (byte_count + 3) & ~0x3; + + /* + * Running with interrupts disabled is usually considered bad + * form, but this routine is probably being run as part of an + * initialization sequence so the effect shouldn't be too severe. + */ + _ISR_Disable (level); + + for ( i = 0; i < NUM_DPRAM_REGIONS; i++ ) { + /* + * Verify that the region is available for use. + * This test is necessary because if extra microcode modules + * are installed, some regions are locked and unavailable. + * See MPC860 User's Manual Pages 19-9 to 19-11. + */ + if (dpram_regions[i].used == 0) { + volatile unsigned char *cp = dpram_regions[i].base; + *cp = 0xAA; + if (*cp != 0xAA) + dpram_regions[i].used = dpram_regions[i].size; + else { + *cp = 0x55; + if (*cp != 0x55) + dpram_regions[i].used = dpram_regions[i].size; + } + *cp = 0x0; + } + if (dpram_regions[i].size - dpram_regions[i].used >= byte_count) { + blockp = dpram_regions[i].base + dpram_regions[i].used; + dpram_regions[i].used += byte_count; + break; + } + } + + _ISR_Enable(level); + + if (blockp == NULL) + rtems_panic("Can't allocate %d bytes of dual-port RAM.\n", byte_count); + return blockp; +} |