summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc8260/cpm
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc8260/cpm')
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/.cvsignore2
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/Makefile.am29
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c204
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/cp.c35
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/dpram.c91
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;
+}