summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c')
-rw-r--r--c/src/lib/libcpu/powerpc/mpc8260/cpm/brg.c204
1 files changed, 204 insertions, 0 deletions
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]--;
+}