From b8c468bc9a1442dfe834a211ff473b0907964f0d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 23 Mar 2018 16:11:55 +0100 Subject: bsp/tqm8xx: Move libcpu content to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/powerpc/tqm8xx/dev/clock.c | 207 ++++ bsps/powerpc/tqm8xx/dev/console-generic.c | 1073 ++++++++++++++++++++ bsps/powerpc/tqm8xx/start/cp.c | 34 + bsps/powerpc/tqm8xx/start/dpram.c | 91 ++ bsps/powerpc/tqm8xx/start/mmu.c | 126 +++ c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am | 10 +- c/src/lib/libcpu/powerpc/Makefile.am | 27 - c/src/lib/libcpu/powerpc/mpc8xx/README | 15 - c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c | 207 ---- .../mpc8xx/console-generic/console-generic.c | 1073 -------------------- c/src/lib/libcpu/powerpc/mpc8xx/cpm/cp.c | 34 - c/src/lib/libcpu/powerpc/mpc8xx/cpm/dpram.c | 91 -- c/src/lib/libcpu/powerpc/mpc8xx/mmu/mmu.c | 126 --- 13 files changed, 1535 insertions(+), 1579 deletions(-) create mode 100644 bsps/powerpc/tqm8xx/dev/clock.c create mode 100644 bsps/powerpc/tqm8xx/dev/console-generic.c create mode 100644 bsps/powerpc/tqm8xx/start/cp.c create mode 100644 bsps/powerpc/tqm8xx/start/dpram.c create mode 100644 bsps/powerpc/tqm8xx/start/mmu.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/README delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/console-generic/console-generic.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/cpm/cp.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/cpm/dpram.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc8xx/mmu/mmu.c diff --git a/bsps/powerpc/tqm8xx/dev/clock.c b/bsps/powerpc/tqm8xx/dev/clock.c new file mode 100644 index 0000000000..49500fedd1 --- /dev/null +++ b/bsps/powerpc/tqm8xx/dev/clock.c @@ -0,0 +1,207 @@ +/* clock.c + * + * This routine initializes the PIT on the MPC8xx. + * The tick frequency is specified by the bsp. + */ + +/* + * Author: Jay Monkman (jmonkman@frasca.com) + * Copyright (C) 1998 by Frasca International, Inc. + * + * Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c: + * + * Author: Andrew Bray + * + * COPYRIGHT (c) 1995 by i-cubed ltd. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of i-cubed limited not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * i-cubed limited makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libcpu/hppa1_1/clock/clock.c: + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include + +#include /* for atexit() */ +#include +#include + +volatile uint32_t Clock_driver_ticks; +extern volatile m8xx_t m8xx; +extern int BSP_get_clock_irq_level(void); +extern uint32_t bsp_clicks_per_usec; + +/* + * Prototypes + */ +rtems_isr Clock_isr(rtems_vector_number vector); +void Clock_exit( void ); +void clockOn(void* unused); +void clockOff(void* unused); +int clockIsOn(void* unused); +void Install_clock(rtems_isr_entry clock_isr); +void ReInstall_clock(rtems_isr_entry new_clock_isr); + +/* + * ISR Handler + */ +rtems_isr Clock_isr(rtems_vector_number vector) +{ + m8xx.piscr |= M8xx_PISCR_PS; + Clock_driver_ticks++; + rtems_clock_tick(); +} + +void clockOn(void* unused) +{ + unsigned desiredLevel; + uint32_t pit_value; + uint32_t extclk; + bool force_prescaler = false; + uint32_t immr_val; + + if (bsp_clicks_per_usec == 0) { + /* + * oscclk is too low for PIT, compute extclk and derive PIT from there + */ + /* + * determine external input clock by examining the PLL settings + * this must be done differently depending on type of PLL + */ + _mfspr(immr_val,M8xx_IMMR); + if (8 == ((immr_val & 0x0000FF00) >> 8)) { + /* + * for MPC866: complex PLL + */ + uint32_t plprcr_val; + uint32_t mfn_value; + uint32_t mfd_value; + uint32_t mfi_value; + uint32_t pdf_value; + uint32_t s_value; + + plprcr_val = m8xx.plprcr; + mfn_value = (plprcr_val & (0xf8000000)) >> (31- 4); + mfd_value = (plprcr_val & (0x07c00000)) >> (31- 9); + s_value = (plprcr_val & (0x00300000)) >> (31-11); + mfi_value = (plprcr_val & (0x000f0000)) >> (31-15); + pdf_value = (plprcr_val & (0x00000006)) >> (31-30); + extclk = (((uint64_t)bsp_clock_speed) + * ((pdf_value + 1) * (mfd_value + 1)) + / (mfi_value * (mfd_value + 1) + mfn_value) + * (1 << s_value)); + } + else { + /* + * for MPC860/850 etc: simple PLL + */ + uint32_t mf_value; + mf_value = m8xx.plprcr >> 20; + extclk = bsp_clock_speed / (mf_value+1); + } + pit_value = (extclk + / 1000 + / 4 + * rtems_configuration_get_microseconds_per_tick() + / 1000); + m8xx.sccr |= (1<<23); + force_prescaler = true; + } + else { + pit_value = (rtems_configuration_get_microseconds_per_tick() * + bsp_clicks_per_usec); + + m8xx.sccr &= ~(1<<23); + } + + if ((pit_value > 0xffff) || force_prescaler) { + /* + * try to activate prescaler + * NOTE: divider generates odd values now... + */ + pit_value = pit_value / 128; + m8xx.sccr |= (1<<24); + } + else { + m8xx.sccr &= ~(1<<24); + } + + if (pit_value > 0xffff) { /* pit is only 16 bits long */ + rtems_fatal_error_occurred(-1); + } + m8xx.pitc = pit_value - 1; + + desiredLevel = BSP_get_clock_irq_level(); + /* set PIT irq level, enable PIT, PIT interrupts */ + /* and clear int. status */ + m8xx.piscr = M8xx_PISCR_PIRQ(desiredLevel) | + M8xx_PISCR_PTE | M8xx_PISCR_PS | M8xx_PISCR_PIE; +} + +/* + * Called via atexit() + * Remove the clock interrupt handler by setting handler to NULL + */ +void clockOff(void* unused) +{ + /* disable PIT and PIT interrupts */ + m8xx.piscr &= ~(M8xx_PISCR_PTE | M8xx_PISCR_PIE); +} + +int clockIsOn(void* unused) +{ + if (m8xx.piscr & M8xx_PISCR_PIE) + return 1; + return 0; +} + +/* + * Called via atexit() + * Remove the clock interrupt handler by setting handler to NULL + */ +void Clock_exit(void) +{ + (void) BSP_disconnect_clock_handler (); +} + +void Install_clock(rtems_isr_entry clock_isr) +{ + Clock_driver_ticks = 0; + + BSP_connect_clock_handler (clock_isr); + atexit(Clock_exit); +} + +void ReInstall_clock(rtems_isr_entry new_clock_isr) +{ + BSP_connect_clock_handler (new_clock_isr); +} + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + Install_clock( Clock_isr ); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/tqm8xx/dev/console-generic.c b/bsps/powerpc/tqm8xx/dev/console-generic.c new file mode 100644 index 0000000000..e015a6497b --- /dev/null +++ b/bsps/powerpc/tqm8xx/dev/console-generic.c @@ -0,0 +1,1073 @@ +/* + * General Serial I/O functions. + * + * This file contains the functions for performing serial I/O. + * The actual system calls (console_*) should be in the BSP part + * of the source tree. That way different BSPs can use whichever + * SMCs and SCCs they want. Originally, all the stuff was in + * this file, and it caused problems with one BSP using SCC2 + * as /dev/console, others using SMC1 for /dev/console, etc. + * + * On-chip resources used: + * resource minor note + * SMC1 0 + * SMC2 1 + * SCC1 2 N/A. Hardwired as ethernet port + * SCC2 3 + * SCC3 4 + * SCC4 5 + * BRG1 + * BRG2 + * BRG3 + * BRG4 + * Author: Jay Monkman (jmonkman@frasca.com) + * Copyright (C) 1998 by Frasca International, Inc. + * + * Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by: + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * Modifications by Darlene Stewart + * and Charles-Antoine Gauthier + * Copyright (c) 1999, National Research Council of Canada + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for printk */ + +/* + * Interrupt-driven input buffer + */ +#define RXBUFSIZE 16 + +/* + * I/O buffers and pointers to buffer descriptors. + * Currently, single buffered input is done. This will work only + * if the Rx interrupts are serviced quickly. + * + * TODO: Add a least double buffering for safety. + */ +static volatile char rxBuf[NUM_PORTS][RXBUFSIZE]; +static volatile char txBuf[NUM_PORTS]; + +/* SCC/SMC buffer descriptors */ +static volatile m8xxBufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS]; + +/* Used to track the usage of the baud rate generators */ +static unsigned long brg_spd[4]; +static char brg_used[4]; + +/* Used to track termios private data for callbacks */ +struct rtems_termios_tty *ttyp[NUM_PORTS]; + +/* + * Device-specific routines + */ +static int m8xx_get_brg_cd(int); +static unsigned char m8xx_get_brg_clk(int); +static int m8xx_smc_set_attributes(int, const struct termios*); +static int m8xx_scc_set_attributes(int, const struct termios*); +static void m8xx_smc1_interrupt_handler(void *unused); +static void m8xx_smc2_interrupt_handler(void *unused); +static void m8xx_scc2_interrupt_handler(void *unused); +#if defined(mpc860) +static void m8xx_scc3_interrupt_handler(void *unused); +static void m8xx_scc4_interrupt_handler(void *unused); +#endif + +/* + * Compute baud-rate-generator configuration register value + */ +static int +m8xx_get_brg_cd (int baud) +{ + int divisor; + int div16 = 0; + + divisor = ((bsp_clock_speed / 16) + (baud / 2)) / baud; + if (divisor > 4096) { + div16 = 1; + divisor = (divisor + 8) / 16; + } + return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK | + ((divisor - 1) << 1) | div16; +} + + +/* + * This function will fail if more that 4 baud rates have been selected + * at any time since the OS started. It needs to be fixed. FIXME + */ +static unsigned +char m8xx_get_brg_clk(int baud) +{ + int i; + + /* first try to find a BRG that is already at the right speed */ + for ( i = 0; i < 4; i++ ) { + if ( brg_spd[i] == baud ) { + break; + } + } + + if ( i == 4 ) { /* I guess we didn't find one */ + for ( i = 0; i < 4; i++ ) { + if ( brg_used[i] == 0 ) { + break; + } + } + } + if (i != 4) { + brg_used[i]++; + brg_spd[i]=baud; + switch (i) { + case 0: + m8xx.brgc1 = M8xx_BRG_RST; + m8xx.brgc1 = m8xx_get_brg_cd(baud); + break; + case 1: + m8xx.brgc2 = M8xx_BRG_RST; + m8xx.brgc2 = m8xx_get_brg_cd(baud); + break; + case 2: + m8xx.brgc3 = M8xx_BRG_RST; + m8xx.brgc3 = m8xx_get_brg_cd(baud); + break; + case 3: + m8xx.brgc4 = M8xx_BRG_RST; + m8xx.brgc4 = m8xx_get_brg_cd(baud); + break; + } + return i; + } + + else + return 0xff; +} + + +/* + * Hardware-dependent portion of tcsetattr(). + */ +static int +m8xx_smc_set_attributes (int minor, const struct termios *t) +{ + int baud, brg=0, csize=0, ssize, psize; + uint16_t clen=0, cstopb, parenb, parodd, cread; + + /* Baud rate */ + switch (t->c_ospeed) { + default: baud = -1; break; + case B50: baud = 50; break; + case B75: baud = 75; break; + case B110: baud = 110; break; + case B134: baud = 134; break; + case B150: baud = 150; break; + case B200: baud = 200; break; + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B1800: baud = 1800; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B230400: baud = 230400; break; + case B460800: baud = 460800; break; + } + if (baud > 0) + brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 6 serial ports - hopefully */ + /* at least 2 ports will be the same */ + + /* Number of data bits */ + switch ( t->c_cflag & CSIZE ) { + case CS5: csize = 5; break; + case CS6: csize = 6; break; + case CS7: csize = 7; break; + case CS8: csize = 8; break; + } + + /* Stop bits */ + if ( t->c_cflag & CSTOPB ) { + cstopb = 0x0400; /* Two stop bits */ + ssize = 2; + } else { + cstopb = 0x0000; /* One stop bit */ + ssize = 1; + } + + /* Parity */ + if ( t->c_cflag & PARENB ) { + parenb = 0x0200; /* Parity enabled on Tx and Rx */ + psize = 1; + } else { + parenb = 0x0000; /* No parity on Tx and Rx */ + psize = 0; + } + + if ( t->c_cflag & PARODD ) + parodd = 0x0000; /* Odd parity */ + else + parodd = 0x0100; + + /* + * Character Length = start + data + parity + stop - 1 + */ + switch ( 1 + csize + psize + ssize - 1 ) { + case 6: clen = 0x3000; break; + case 7: clen = 0x3800; break; + case 8: clen = 0x4000; break; + case 9: clen = 0x4800; break; + case 10: clen = 0x5000; break; + case 11: clen = 0x5800; break; + } + + if ( t->c_cflag & CREAD ) + cread = 0x0023; /* UART normal operation, enable Rx and Tx */ + else + cread = 0x0021; /* UART normal operation, enable Tx */ + + /* Write the SIMODE/SMCMR registers */ + switch (minor) { + case SMC1_MINOR: + m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) ); + m8xx.smc1.smcmr = clen | cstopb | parenb | parodd | cread; + break; + case SMC2_MINOR: + m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) ); + m8xx.smc2.smcmr = clen | cstopb | parenb | parodd | cread; + break; + } + return 0; +} + + +static int +m8xx_scc_set_attributes (int minor, const struct termios *t) +{ + int baud, brg=0; + uint16_t csize=0, cstopb, parenb, parodd; + + /* Baud rate */ + switch (t->c_ospeed) { + default: baud = -1; break; + case B50: baud = 50; break; + case B75: baud = 75; break; + case B110: baud = 110; break; + case B134: baud = 134; break; + case B150: baud = 150; break; + case B200: baud = 200; break; + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B1800: baud = 1800; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + case B57600: baud = 57600; break; + case B115200: baud = 115200; break; + case B230400: baud = 230400; break; + case B460800: baud = 460800; break; + } + if (baud > 0) + brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 5 serial ports - hopefully */ + /* at least 2 ports will be the same */ + /* Write the SICR register below */ + + /* Number of data bits */ + switch ( t->c_cflag & CSIZE ) { + case CS5: csize = 0x0000; break; + case CS6: csize = 0x1000; break; + case CS7: csize = 0x2000; break; + case CS8: csize = 0x3000; break; + } + + /* Stop bits */ + if ( t->c_cflag & CSTOPB ) + cstopb = 0x4000; /* Two stop bits */ + else + cstopb = 0x0000; /* One stop bit */ + + /* Parity */ + if ( t->c_cflag & PARENB ) + parenb = 0x0010; /* Parity enabled on Tx and Rx */ + else + parenb = 0x0000; /* No parity on Tx and Rx */ + + if ( t->c_cflag & PARODD ) + parodd = 0x0000; /* Odd parity */ + else + parodd = 0x000a; + + /* Write the SICR/PSMR Registers */ + switch (minor) { + case SCC2_MINOR: + m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) ); + m8xx.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc2.psmr & 0x8fe0) ); + break; + #if defined(mpc860) + case SCC3_MINOR: + m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) ); + m8xx.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc3.psmr & 0x8fe0) ); + break; + case SCC4_MINOR: + m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) ); + m8xx.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc4.psmr & 0x8fe0) ); + break; + #endif + } + + return 0; +} + + +int +m8xx_uart_setAttributes( + int minor, + const struct termios *t +) +{ + /* + * Check that port number is valid + */ + if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) ) + return 0; + + switch (minor) { + case SMC1_MINOR: + case SMC2_MINOR: + return m8xx_smc_set_attributes( minor, t ); + + case SCC2_MINOR: + case SCC3_MINOR: + case SCC4_MINOR: + return m8xx_scc_set_attributes( minor, t ); + } + return 0; +} + + +/* + * Interrupt handlers + */ +static void m8xx_scc2_interrupt_handler (void *unused) +{ + /* + * Buffer received? + */ + if ((m8xx.scc2.sccm & M8xx_SCCE_RX) && (m8xx.scc2.scce & M8xx_SCCE_RX)) { + m8xx.scc2.scce = M8xx_SCCE_RX; /* Clear the event */ + + + /* Check that the buffer is ours */ + if ((RxBd[SCC2_MINOR]->status & M8xx_BD_EMPTY) == 0) { + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[SCC2_MINOR]->buffer, + RxBd[SCC2_MINOR]->length ); + rtems_termios_enqueue_raw_characters( + (void *)ttyp[SCC2_MINOR], + (char *)RxBd[SCC2_MINOR]->buffer, + (int)RxBd[SCC2_MINOR]->length ); + RxBd[SCC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | + M8xx_BD_INTERRUPT; + } + } + + /* + * Buffer transmitted? + */ + if (m8xx.scc2.scce & M8xx_SCCE_TX) { + m8xx.scc2.scce = M8xx_SCCE_TX; /* Clear the event */ + + /* Check that the buffer is ours */ + if ((TxBd[SCC2_MINOR]->status & M8xx_BD_READY) == 0) + rtems_termios_dequeue_characters ( + (void *)ttyp[SCC2_MINOR], + (int)TxBd[SCC2_MINOR]->length); + } +} + + +#ifdef mpc860 +static void +m8xx_scc3_interrupt_handler (void *unused) +{ + /* + * Buffer received? + */ + if ((m8xx.scc3.sccm & M8xx_SCCE_RX) && (m8xx.scc3.scce & M8xx_SCCE_RX)) { + m8xx.scc3.scce = M8xx_SCCE_RX; /* Clear the event */ + + + /* Check that the buffer is ours */ + if ((RxBd[SCC3_MINOR]->status & M8xx_BD_EMPTY) == 0) { + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[SCC3_MINOR]->buffer, + RxBd[SCC3_MINOR]->length ); + rtems_termios_enqueue_raw_characters( + (void *)ttyp[SCC3_MINOR], + (char *)RxBd[SCC3_MINOR]->buffer, + (int)RxBd[SCC3_MINOR]->length ); + RxBd[SCC3_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | + M8xx_BD_INTERRUPT; + } + } + + /* + * Buffer transmitted? + */ + if (m8xx.scc3.scce & M8xx_SCCE_TX) { + m8xx.scc3.scce = M8xx_SCCE_TX; /* Clear the event */ + + /* Check that the buffer is ours */ + if ((TxBd[SCC3_MINOR]->status & M8xx_BD_READY) == 0) + rtems_termios_dequeue_characters ( + (void *)ttyp[SCC3_MINOR], + (int)TxBd[SCC3_MINOR]->length); + } +} + + +static void +m8xx_scc4_interrupt_handler (void *unused) +{ + /* + * Buffer received? + */ + if ((m8xx.scc4.sccm & M8xx_SCCE_RX) && (m8xx.scc4.scce & M8xx_SCCE_RX)) { + m8xx.scc4.scce = M8xx_SCCE_RX; /* Clear the event */ + + + /* Check that the buffer is ours */ + if ((RxBd[SCC4_MINOR]->status & M8xx_BD_EMPTY) == 0) { + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[SCC4_MINOR]->buffer, + RxBd[SCC4_MINOR]->length ); + rtems_termios_enqueue_raw_characters( + (void *)ttyp[SCC4_MINOR], + (char *)RxBd[SCC4_MINOR]->buffer, + (int)RxBd[SCC4_MINOR]->length ); + RxBd[SCC4_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | + M8xx_BD_INTERRUPT; + } + } + + /* + * Buffer transmitted? + */ + if (m8xx.scc4.scce & M8xx_SCCE_TX) { + m8xx.scc4.scce = M8xx_SCCE_TX; /* Clear the event */ + + /* Check that the buffer is ours */ + if ((TxBd[SCC4_MINOR]->status & M8xx_BD_READY) == 0) + rtems_termios_dequeue_characters ( + (void *)ttyp[SCC4_MINOR], + (int)TxBd[SCC4_MINOR]->length); + } +} +#endif + +static void +m8xx_smc1_interrupt_handler (void *unused) +{ + /* + * Buffer received? + */ + if (m8xx.smc1.smce & M8xx_SMCE_RX) { + m8xx.smc1.smce = M8xx_SMCE_RX; /* Clear the event */ + + + /* Check that the buffer is ours */ + if ((RxBd[SMC1_MINOR]->status & M8xx_BD_EMPTY) == 0) { + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[SMC1_MINOR]->buffer, + RxBd[SMC1_MINOR]->length ); + rtems_termios_enqueue_raw_characters( + (void *)ttyp[SMC1_MINOR], + (char *)RxBd[SMC1_MINOR]->buffer, + (int)RxBd[SMC1_MINOR]->length ); + RxBd[SMC1_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | + M8xx_BD_INTERRUPT; + } + } + + /* + * Buffer transmitted? + */ + if (m8xx.smc1.smce & M8xx_SMCE_TX) { + m8xx.smc1.smce = M8xx_SMCE_TX; /* Clear the event */ + + /* Check that the buffer is ours */ + if ((TxBd[SMC1_MINOR]->status & M8xx_BD_READY) == 0) + rtems_termios_dequeue_characters ( + (void *)ttyp[SMC1_MINOR], + (int)TxBd[SMC1_MINOR]->length); + } +} + + +static void +m8xx_smc2_interrupt_handler (void *unused) +{ + /* + * Buffer received? + */ + if (m8xx.smc2.smce & M8xx_SMCE_RX) { + m8xx.smc2.smce = M8xx_SMCE_RX; /* Clear the event */ + + + /* Check that the buffer is ours */ + if ((RxBd[SMC2_MINOR]->status & M8xx_BD_EMPTY) == 0) { + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[SMC2_MINOR]->buffer, + RxBd[SMC2_MINOR]->length ); + rtems_termios_enqueue_raw_characters( + (void *)ttyp[SMC2_MINOR], + (char *)RxBd[SMC2_MINOR]->buffer, + (int)RxBd[SMC2_MINOR]->length ); + RxBd[SMC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | + M8xx_BD_INTERRUPT; + } + } + + /* + * Buffer transmitted? + */ + if (m8xx.smc2.smce & M8xx_SMCE_TX) { + m8xx.smc2.smce = M8xx_SMCE_TX; /* Clear the event */ + + /* Check that the buffer is ours */ + if ((TxBd[SMC2_MINOR]->status & M8xx_BD_READY) == 0) + rtems_termios_dequeue_characters ( + (void *)ttyp[SMC2_MINOR], + (int)TxBd[SMC2_MINOR]->length); + } +} + +static void m8xx_scc_enable(const rtems_irq_connect_data* ptr) +{ + volatile m8xxSCCRegisters_t *sccregs = 0; + switch (ptr->name) { +#if defined(mpc860) + case BSP_CPM_IRQ_SCC4 : + sccregs = &m8xx.scc4; + break; + case BSP_CPM_IRQ_SCC3 : + sccregs = &m8xx.scc3; + break; +#endif + case BSP_CPM_IRQ_SCC2 : + sccregs = &m8xx.scc2; + break; + case BSP_CPM_IRQ_SCC1 : + sccregs = &m8xx.scc1; + break; + default: + break; + } + sccregs->sccm = 3; +} + +static void m8xx_scc_disable(const rtems_irq_connect_data* ptr) +{ + volatile m8xxSCCRegisters_t *sccregs = 0; + switch (ptr->name) { +#if defined(mpc860) + case BSP_CPM_IRQ_SCC4 : + sccregs = &m8xx.scc4; + break; + case BSP_CPM_IRQ_SCC3 : + sccregs = &m8xx.scc3; + break; +#endif + case BSP_CPM_IRQ_SCC2 : + sccregs = &m8xx.scc2; + break; + case BSP_CPM_IRQ_SCC1 : + sccregs = &m8xx.scc1; + break; + default: + break; + } + sccregs->sccm &= (~3); +} + +static int m8xx_scc_isOn(const rtems_irq_connect_data* ptr) +{ + return BSP_irq_enabled_at_cpm (ptr->name); +} + +static rtems_irq_connect_data consoleIrqData; + +void +m8xx_uart_scc_initialize (int minor) +{ + unsigned char brg; + volatile m8xxSCCparms_t *sccparms = 0; + volatile m8xxSCCRegisters_t *sccregs = 0; + + /* + * Check that minor number is valid + */ + if ( (minor < SCC2_MINOR) || (minor > NUM_PORTS-1) ) + return; + + /* Get the sicr clock source bit values for 9600 bps */ + brg = m8xx_get_brg_clk(9600); + + /* + * Allocate buffer descriptors + */ + RxBd[minor] = m8xx_bd_allocate(1); + TxBd[minor] = m8xx_bd_allocate(1); + + /* + * Get the address of the parameter RAM for the specified port, + * configure I/O port A,C & D and put SMC in NMSI mode, connect + * the SCC to the appropriate BRG. + * + * SCC2 TxD is shared with port A bit 12 + * SCC2 RxD is shared with port A bit 13 + * SCC1 TxD is shared with port A bit 14 + * SCC1 RxD is shared with port A bit 15 + * SCC4 DCD is shared with port C bit 4 + * SCC4 CTS is shared with port C bit 5 + * SCC3 DCD is shared with port C bit 6 + * SCC3 CTS is shared with port C bit 7 + * SCC2 DCD is shared with port C bit 8 + * SCC2 CTS is shared with port C bit 9 + * SCC1 DCD is shared with port C bit 10 + * SCC1 CTS is shared with port C bit 11 + * SCC2 RTS is shared with port C bit 14 + * SCC1 RTS is shared with port C bit 15 + * SCC4 RTS is shared with port D bit 6 + * SCC3 RTS is shared with port D bit 7 + * SCC4 TxD is shared with port D bit 8 + * SCC4 RxD is shared with port D bit 9 + * SCC3 TxD is shared with port D bit 10 + * SCC3 RxD is shared with port D bit 11 + */ + switch (minor) { + case SCC2_MINOR: + sccparms = &m8xx.scc2p; + sccregs = &m8xx.scc2; + + m8xx.papar |= 0x000C; /* PA12 & PA13 are dedicated peripheral pins */ + m8xx.padir &= ~0x000C; /* PA13 & PA12 must not drive the UART lines */ + m8xx.paodr &= ~0x000C; /* PA12 & PA13 are not open drain */ + m8xx.pcpar |= 0x0002; /* PC14 is SCC2 RTS */ + m8xx.pcpar &= ~0x00C0; /* PC8 & PC9 are SCC2 DCD and CTS */ + m8xx.pcdir &= ~0x00C2; /* PC8, PC9 & PC14 must not drive the UART lines */ + m8xx.pcso |= 0x00C0; /* Enable DCD and CTS inputs */ + + m8xx.sicr &= 0xFFFF00FF; /* Clear TCS2 & RCS2, GR2=no grant, SC2=NMSI mode */ + m8xx.sicr |= (brg<<11) | (brg<<8); /* TCS2 = RCS2 = brg */ + break; + +#ifdef mpc860 + case SCC3_MINOR: + sccparms = &m8xx.scc3p; + sccregs = &m8xx.scc3; + + m8xx.pcpar &= ~0x0300; /* PC6 & PC7 are SCC3 DCD and CTS */ + m8xx.pcdir &= ~0x0300; /* PC6 & PC7 must not drive the UART lines */ + m8xx.pcso |= 0x0300; /* Enable DCD and CTS inputs */ + m8xx.pdpar |= 0x0130; /* PD7, PD10 & PD11 are dedicated peripheral pins */ + + m8xx.sicr &= 0xFF00FFFF; /* Clear TCS3 & RCS3, GR3=no grant, SC3=NMSI mode */ + m8xx.sicr |= (brg<<19) | (brg<<16); /* TCS3 = RCS3 = brg */ + break; + + case SCC4_MINOR: + sccparms = &m8xx.scc4p; + sccregs = &m8xx.scc4; + + m8xx.pcpar &= ~0x0C00; /* PC4 & PC5 are SCC4 DCD and CTS */ + m8xx.pcdir &= ~0x0C00; /* PC4 & PC5 must not drive the UART lines */ + m8xx.pcso |= 0x0C00; /* Enable DCD and CTS inputs */ + m8xx.pdpar |= 0x02C0; /* PD6, PD8 & PD9 are dedicated peripheral pins */ + + m8xx.sicr &= 0x00FFFFFF; /* Clear TCS4 & RCS4, GR4=no grant, SC4=NMSI mode */ + m8xx.sicr |= (brg<<27) | (brg<<24); /* TCS4 = RCS4 = brg */ + break; +#endif + } + + /* + * Set up SDMA + */ + m8xx.sdcr = 0x01; /* as per section 16.10.2.1 MPC821UM/AD */ + + /* + * Set up the SCC parameter RAM. + */ + sccparms->rbase = (char *)RxBd[minor] - (char *)&m8xx; + sccparms->tbase = (char *)TxBd[minor] - (char *)&m8xx; + + sccparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); + sccparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0); + if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) + sccparms->mrblr = RXBUFSIZE; /* Maximum Rx buffer size */ + else + sccparms->mrblr = 1; /* Maximum Rx buffer size */ + sccparms->un.uart.max_idl = 10; /* Set nb of idle chars to close buffer */ + sccparms->un.uart.brkcr = 0; /* Set nb of breaks to send for STOP Tx */ + + sccparms->un.uart.parec = 0; /* Clear parity error counter */ + sccparms->un.uart.frmec = 0; /* Clear framing error counter */ + sccparms->un.uart.nosec = 0; /* Clear noise counter */ + sccparms->un.uart.brkec = 0; /* Clear break counter */ + + sccparms->un.uart.uaddr[0] = 0; /* Not in multidrop mode, so clear */ + sccparms->un.uart.uaddr[1] = 0; /* Not in multidrop mode, so clear */ + sccparms->un.uart.toseq = 0; /* Tx Out-Of-SEQuence--no XON/XOFF now */ + + sccparms->un.uart.character[0] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[1] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[2] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[3] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[4] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[5] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[6] = 0x8000; /* Entry is invalid */ + sccparms->un.uart.character[7] = 0x8000; /* Entry is invalid */ + + + sccparms->un.uart.rccm = 0xc0ff; /* No masking */ + + /* + * Set up the Receive Buffer Descriptor + */ + RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; + RxBd[minor]->length = 0; + RxBd[minor]->buffer = rxBuf[minor]; + + /* + * Setup the Transmit Buffer Descriptor + */ + TxBd[minor]->status = M8xx_BD_WRAP; + + /* + * Set up SCCx general and protocol-specific mode registers + */ + sccregs->gsmr_h = 0x00000020; /* RFW=low latency operation */ + sccregs->gsmr_l = 0x00028004; /* TDCR=RDCR=16x clock mode, MODE=uart*/ + sccregs->scce = ~0; /* Clear any pending event */ + sccregs->sccm = 0; /* Mask all interrupt/event sources */ + sccregs->psmr = 0x3000; /* Normal operation & mode, 1 stop bit, + 8 data bits, no parity */ + sccregs->dsr = 0x7E7E; /* No fractional stop bits */ + sccregs->gsmr_l = 0x00028034; /* ENT=enable Tx, ENR=enable Rx */ + + /* + * Initialize the Rx and Tx with the new parameters. + */ + switch (minor) { + case SCC2_MINOR: + m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC2); + break; + +#ifdef mpc860 + case SCC3_MINOR: + m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC3); + break; + case SCC4_MINOR: + m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC4); + break; +#endif + } + if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) { + consoleIrqData.on = m8xx_scc_enable; + consoleIrqData.off = m8xx_scc_disable; + consoleIrqData.isOn = m8xx_scc_isOn; + + switch (minor) { + case SCC2_MINOR: + consoleIrqData.name = BSP_CPM_IRQ_SCC2; + consoleIrqData.hdl = m8xx_scc2_interrupt_handler; + break; + +#ifdef mpc860 + case SCC3_MINOR: + consoleIrqData.name = BSP_CPM_IRQ_SCC3; + consoleIrqData.hdl = m8xx_scc3_interrupt_handler; + break; + + case SCC4_MINOR: + consoleIrqData.name = BSP_CPM_IRQ_SCC4; + consoleIrqData.hdl = m8xx_scc4_interrupt_handler; + break; +#endif /* mpc860 */ + } + if (!BSP_install_rtems_irq_handler (&consoleIrqData)) { + printk("Unable to connect SCC Irq handler\n"); + rtems_fatal_error_occurred(1); + } + } +} + +static void m8xx_smc_enable(const rtems_irq_connect_data* ptr) +{ + volatile m8xxSMCRegisters_t *smcregs = 0; + switch (ptr->name) { + case BSP_CPM_IRQ_SMC1 : + smcregs = &m8xx.smc1; + break; + case BSP_CPM_IRQ_SMC2_OR_PIP : + smcregs = &m8xx.smc2; + break; + default: + break; + } + smcregs->smcm = 3; +} + +static void m8xx_smc_disable(const rtems_irq_connect_data* ptr) +{ + volatile m8xxSMCRegisters_t *smcregs = 0; + switch (ptr->name) { + case BSP_CPM_IRQ_SMC1 : + smcregs = &m8xx.smc1; + break; + case BSP_CPM_IRQ_SMC2_OR_PIP : + smcregs = &m8xx.smc2; + break; + default: + break; + } + smcregs->smcm &= (~3); +} + +static int m8xx_smc_isOn(const rtems_irq_connect_data* ptr) +{ + return BSP_irq_enabled_at_cpm (ptr->name); +} + +void +m8xx_uart_smc_initialize (int minor) +{ + unsigned char brg; + volatile m8xxSMCparms_t *smcparms = 0; + volatile m8xxSMCRegisters_t *smcregs = 0; + + /* + * Check that minor number is valid + */ + if ( (minor < SMC1_MINOR) || (minor > SMC2_MINOR) ) + return; + + m8xx.sdcr = 0x01; /* as per section 16.10.2.1 MPC821UM/AD */ + /* Get the simode clock source bit values for 9600 bps */ + brg = m8xx_get_brg_clk(9600); + + /* + * Allocate buffer descriptors + */ + RxBd[minor] = m8xx_bd_allocate (1); + TxBd[minor] = m8xx_bd_allocate (1); + + /* + * Get the address of the parameter RAM for the specified port, + * configure I/O port B and put SMC in NMSI mode, connect the + * SMC to the appropriate BRG. + * + * SMC2 RxD is shared with port B bit 20 + * SMC2 TxD is shared with port B bit 21 + * SMC1 RxD is shared with port B bit 24 + * SMC1 TxD is shared with port B bit 25 + */ + switch (minor) { + case SMC1_MINOR: + smcparms = &m8xx.smc1p; + smcregs = &m8xx.smc1; + + m8xx.pbpar |= 0x000000C0; /* PB24 & PB25 are dedicated peripheral pins */ + m8xx.pbdir &= ~0x000000C0; /* PB24 & PB25 must not drive UART lines */ + m8xx.pbodr &= ~0x000000C0; /* PB24 & PB25 are not open drain */ + + m8xx.simode &= 0xFFFF0FFF; /* Clear SMC1CS & SMC1 for NMSI mode */ + m8xx.simode |= brg << 12; /* SMC1CS = brg */ + break; + + case SMC2_MINOR: + smcparms = &m8xx.smc2p; + smcregs = &m8xx.smc2; + + m8xx.pbpar |= 0x00000C00; /* PB20 & PB21 are dedicated peripheral pins */ + m8xx.pbdir &= ~0x00000C00; /* PB20 & PB21 must not drive the UART lines */ + m8xx.pbodr &= ~0x00000C00; /* PB20 & PB21 are not open drain */ + + m8xx.simode &= 0x0FFFFFFF; /* Clear SMC2CS & SMC2 for NMSI mode */ + m8xx.simode |= brg << 28; /* SMC2CS = brg */ + break; + } + + /* + * Set up SMC1 parameter RAM common to all protocols + */ + smcparms->rbase = (char *)RxBd[minor] - (char *)&m8xx; + smcparms->tbase = (char *)TxBd[minor] - (char *)&m8xx; + smcparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); + smcparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0); + if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) + smcparms->mrblr = RXBUFSIZE; /* Maximum Rx buffer size */ + else + smcparms->mrblr = 1; /* Maximum Rx buffer size */ + + /* + * Set up SMC1 parameter RAM UART-specific parameters + */ + smcparms->un.uart.max_idl = 10; /* Set nb of idle chars to close buffer */ + smcparms->un.uart.brkcr = 0; /* Set nb of breaks to send for STOP Tx */ + smcparms->un.uart.brkec = 0; /* Clear break counter */ + + /* + * Set up the Receive Buffer Descriptor + */ + RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; + RxBd[minor]->length = 0; + RxBd[minor]->buffer = rxBuf[minor]; + + /* + * Setup the Transmit Buffer Descriptor + */ + TxBd[minor]->status = M8xx_BD_WRAP; + + /* + * Set up SMCx general and protocol-specific mode registers + */ + smcregs->smce = ~0; /* Clear any pending events */ + smcregs->smcm = 0; /* Enable SMC Rx & Tx interrupts */ + smcregs->smcmr = M8xx_SMCMR_CLEN(9) | M8xx_SMCMR_SM_UART; + + /* + * Send "Init parameters" command + */ + switch (minor) { + case SMC1_MINOR: + m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC1); + break; + + case SMC2_MINOR: + m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC2); + break; + } + + /* + * Enable receiver and transmitter + */ + smcregs->smcmr |= M8xx_SMCMR_TEN | M8xx_SMCMR_REN; + if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) { + consoleIrqData.on = m8xx_smc_enable; + consoleIrqData.off = m8xx_smc_disable; + consoleIrqData.isOn = m8xx_smc_isOn; + switch (minor) { + case SMC1_MINOR: + consoleIrqData.name = BSP_CPM_IRQ_SMC1; + consoleIrqData.hdl = m8xx_smc1_interrupt_handler; + break; + + case SMC2_MINOR: + consoleIrqData.name = BSP_CPM_IRQ_SMC2_OR_PIP; + consoleIrqData.hdl = m8xx_smc2_interrupt_handler; + break; + } + if (!BSP_install_rtems_irq_handler (&consoleIrqData)) { + printk("Unable to connect SMC Irq handler\n"); + rtems_fatal_error_occurred(1); + } + } +} + +void +m8xx_uart_initialize(void) +{ + int i; + + for (i=0; i < 4; i++) { + brg_spd[i] = 0; + brg_used[i] = 0; + } +} + + + +int +m8xx_uart_pollRead( + int minor +) +{ + unsigned char c; + + if (RxBd[minor]->status & M8xx_BD_EMPTY) { + return -1; + } + rtems_cache_invalidate_multiple_data_lines( + (const void *) RxBd[minor]->buffer, + RxBd[minor]->length + ); + c = ((char *)RxBd[minor]->buffer)[0]; + RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP; + return c; +} + + +/* + * TODO: Get a free buffer and set it up. + */ +ssize_t +m8xx_uart_write( + int minor, + const char *buf, + size_t len +) +{ + rtems_cache_flush_multiple_data_lines( buf, len ); + TxBd[minor]->buffer = (char *) buf; + TxBd[minor]->length = len; + TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; + return 0; +} + + +ssize_t +m8xx_uart_pollWrite( + int minor, + const char *buf, + size_t len +) +{ + while (len--) { + while (TxBd[minor]->status & M8xx_BD_READY) + continue; + txBuf[minor] = *buf++; + rtems_cache_flush_multiple_data_lines( (void *)&txBuf[minor], 1 ); + TxBd[minor]->buffer = &txBuf[minor]; + TxBd[minor]->length = 1; + TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP; + } + return len; +} diff --git a/bsps/powerpc/tqm8xx/start/cp.c b/bsps/powerpc/tqm8xx/start/cp.c new file mode 100644 index 0000000000..de38f0a5df --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/cp.c @@ -0,0 +1,34 @@ +/* + * 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 +#include +#include + +/* + * Send a command to the CPM RISC processer + */ + +void m8xx_cp_execute_cmd( uint16_t command ) +{ + rtems_interrupt_level lvl; + + rtems_interrupt_disable(lvl); + while (m8xx.cpcr & M8xx_CR_FLG) { + continue; + } + + m8xx.cpcr = command | M8xx_CR_FLG; + rtems_interrupt_enable (lvl); +} diff --git a/bsps/powerpc/tqm8xx/start/dpram.c b/bsps/powerpc/tqm8xx/start/dpram.c new file mode 100644 index 0000000000..4f6cb6d94a --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/dpram.c @@ -0,0 +1,91 @@ +/* + * dpram.c + * + * MPC8xx dual-port RAM allocation 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 : + * Copyright (c) 1999, National Research Council of Canada + */ + +#include +#include + +#include +#include + +/* + * Allocation order: + * - Dual-Port RAM section 0 + * - Dual-Port RAM section 1 + * - Dual-Port RAM section 2 + * - Dual-Port RAM section 3 + * - Dual-Port RAM section 4 + */ +static struct { + uint8_t *base; + size_t size; + unsigned int used; +} dpram_regions[] = { + { (uint8_t *) &m8xx.dpram0[0], sizeof m8xx.dpram0, 0 }, + { (uint8_t *) &m8xx.dpram1[0], sizeof m8xx.dpram1, 0 }, + { (uint8_t *) &m8xx.dpram2[0], sizeof m8xx.dpram2, 0 }, + { (uint8_t *) &m8xx.dpram3[0], sizeof m8xx.dpram3, 0 }, + { (uint8_t *) &m8xx.dpram4[0], sizeof m8xx.dpram4, 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_Local_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_Local_enable(level); + + if (blockp == NULL) + rtems_panic("Can't allocate %d bytes of dual-port RAM.\n", byte_count); + return blockp; +} diff --git a/bsps/powerpc/tqm8xx/start/mmu.c b/bsps/powerpc/tqm8xx/start/mmu.c new file mode 100644 index 0000000000..78743c6250 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/mmu.c @@ -0,0 +1,126 @@ +/* + * mmu.c + * + * This file contains routines for initializing + * and manipulating the MMU on the MPC8xx. + * + * Copyright (c) 1999, National Research Council of Canada + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#include +#include + +/* + * mmu_init + * + * This routine sets up the virtual memory maps on an MPC8xx. + * The MPC8xx does not support block address translation (BATs) + * and does not have segment registers. Thus, we must set up page + * translation. However, its MMU supports variable size pages + * (1-, 4-, 16-, 512-Kbyte or 8-Mbyte), which simplifies the task. + * + * The MPC8xx has separate data and instruction 32-entry translation + * lookaside buffers (TLB). By mapping all of DRAM as one huge page, + * we can preload the TLBs and not have to be concerned with taking + * TLB miss exceptions. + * + * We set up the virtual memory map so that virtual address of a + * location is equal to its real address. + */ +void mmu_init( void ) +{ + register uint32_t reg1, i; + + /* + * Initialize the TLBs + * + * Instruction address translation and data address translation + * must be disabled during initialization (IR=0, DR=0 in MSR). + * We can assume the MSR has already been set this way. + */ + + /* + * Initialize IMMU & DMMU Control Registers (MI_CTR & MD_CTR) + * GPM [0] 0b0 = PowerPC mode + * PPM [1] 0b0 = Page resolution of protection + * CIDEF [2] 0b0/0b0 = Default cache-inhibit attribute = + * NO for IMMU, NO for DMMU + * NOTE: it is vital that data caching is ON, when + * DMMU is off, otherwise valid/dirty values in + * cache would be ignored during exception entry + * reserved/WTDEF [3] 0b0 = Default write-through attribute = not + * RSV4x [4] 0b0 = 4 entries not reserved + * reserved/TWAM [5] 0b0/0b1 = 4-Kbyte page hardware assist + * PPCS [6] 0b0 = Ignore user/supervisor state + * reserved [7-18] 0x00 + * xTLB_INDX [19-23] 31 = 0x1F + * reserved [24-31] 0x00 + * + * Note: It is important that cache-inhibit be set as the default for the + * data cache when the DMMU is disabled in order to prevent internal memory + * mapped registers from being cached accidentally when address translation + * is turned off at the start of exception processing. + */ + reg1 = M8xx_MI_CTR_ITLB_INDX(31); + _mtspr( M8xx_MI_CTR, reg1 ); + reg1 = M8xx_MD_CTR_TWAM | M8xx_MD_CTR_DTLB_INDX(31); + _mtspr( M8xx_MD_CTR, reg1 ); + _isync; + + /* + * Invalidate all TLB entries in both TLBs. + * Note: We rely on the RSV4 bit in MI_CTR and MD_CTR being 0b0, so + * all 32 entries are invalidated. + */ + __asm__ volatile ("tlbia\n"::); + _isync; + + /* + * Set Current Address Space ID Register (M_CASID). + * Supervisor: CASID = 0 + */ + reg1 = 0; + _mtspr( M8xx_M_CASID, reg1 ); + + /* + * Initialize the MMU Access Protection Registers (MI_AP, MD_AP) + * We ignore the Access Protection Group (APG) mechanism globally + * by setting all of the Mx_AP fields to 0b01 : client access + * permission is defined by page protection bits. + */ + reg1 = 0x55555555; + _mtspr( M8xx_MI_AP, reg1 ); + _mtspr( M8xx_MD_AP, reg1 ); + + /* + * Load both 32-entry TLBs with values from the MMU_TLB_table + * which is defined in the BSP. + * Note the _TLB_Table must have at most 32 entries. This code + * makes no effort to enforce this restriction. + */ + for( i = 0; i < MMU_N_TLB_Table_Entries; ++i ) { + reg1 = MMU_TLB_table[i].mmu_epn; + _mtspr( M8xx_MI_EPN, reg1 ); + _mtspr( M8xx_MD_EPN, reg1 ); + reg1 = MMU_TLB_table[i].mmu_twc; + _mtspr( M8xx_MI_TWC, reg1 ); + _mtspr( M8xx_MD_TWC, reg1 ); + reg1 = MMU_TLB_table[i].mmu_rpn; /* RPN must be written last! */ + _mtspr( M8xx_MI_RPN, reg1 ); + _mtspr( M8xx_MD_RPN, reg1 ); + } + + /* + * Turn on address translation by setting MSR[IR] and MSR[DR]. + */ + _CPU_MSR_GET( reg1 ); + reg1 |= PPC_MSR_IR | PPC_MSR_DR; + _CPU_MSR_SET( reg1 ); +} diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am index f04ed45748..f7ec310224 100644 --- a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am @@ -64,12 +64,10 @@ endif libbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/cache/cache.c libbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/ppc-dec-timer.c - -libbsp_a_LIBADD = \ - ../../../libcpu/@RTEMS_CPU@/mpc8xx/console-generic.rel \ - ../../../libcpu/@RTEMS_CPU@/mpc8xx/cpm.rel \ - ../../../libcpu/@RTEMS_CPU@/mpc8xx/clock.rel \ - ../../../libcpu/@RTEMS_CPU@/mpc8xx/mmu.rel +libbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/dev/console-generic.c +libbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/start/cp.c +libbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/start/dpram.c +libbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/start/mmu.c include $(top_srcdir)/../../../../automake/local.am include $(srcdir)/../../../../../../bsps/powerpc/shared/shared.am diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am index c7d5f16886..5f5813d350 100644 --- a/c/src/lib/libcpu/powerpc/Makefile.am +++ b/c/src/lib/libcpu/powerpc/Makefile.am @@ -79,31 +79,4 @@ e500_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS) e500_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) endif -EXTRA_DIST += mpc8xx/README -if mpc8xx -# mpc8xx/clock -noinst_PROGRAMS += mpc8xx/clock.rel -mpc8xx_clock_rel_SOURCES = mpc8xx/clock/clock.c -mpc8xx_clock_rel_CPPFLAGS = $(AM_CPPFLAGS) -mpc8xx_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -# mpc8xx/console-generic -noinst_PROGRAMS += mpc8xx/console-generic.rel -mpc8xx_console_generic_rel_SOURCES = mpc8xx/console-generic/console-generic.c -mpc8xx_console_generic_rel_CPPFLAGS = $(AM_CPPFLAGS) -mpc8xx_console_generic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -# mpc8xx/cpm -noinst_PROGRAMS += mpc8xx/cpm.rel -mpc8xx_cpm_rel_SOURCES = mpc8xx/cpm/cp.c mpc8xx/cpm/dpram.c -mpc8xx_cpm_rel_CPPFLAGS = $(AM_CPPFLAGS) -mpc8xx_cpm_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -# mpc8xx/mmu -noinst_PROGRAMS += mpc8xx/mmu.rel -mpc8xx_mmu_rel_SOURCES = mpc8xx/mmu/mmu.c -mpc8xx_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS) -mpc8xx_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) -endif - include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/README b/c/src/lib/libcpu/powerpc/mpc8xx/README deleted file mode 100644 index 3d852d0785..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/README +++ /dev/null @@ -1,15 +0,0 @@ -Various non BSP dependant support routines. - -clock - Uses the MPC860/MPC821 PIT (Programmable interval timer) to - generate RTEMS clock ticks. - -console_generic - Uses the MPC860/MPC821 SCCs and SMCs to to serial I/O. - -include - console.h: function declarations for console related functions - -timer - Uses the MPC860/MPC821 timebase register for timing - tests. It only uses the lower 32 bits - -vectors - MPC860/MPC821 specific vector entry points. - Includes CPU dependant, application independant - handlers: alignment. diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c b/c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c deleted file mode 100644 index 49500fedd1..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/clock/clock.c +++ /dev/null @@ -1,207 +0,0 @@ -/* clock.c - * - * This routine initializes the PIT on the MPC8xx. - * The tick frequency is specified by the bsp. - */ - -/* - * Author: Jay Monkman (jmonkman@frasca.com) - * Copyright (C) 1998 by Frasca International, Inc. - * - * Derived from c/src/lib/libcpu/ppc/ppc403/clock/clock.c: - * - * Author: Andrew Bray - * - * COPYRIGHT (c) 1995 by i-cubed ltd. - * - * To anyone who acknowledges that this file is provided "AS IS" - * without any express or implied warranty: - * permission to use, copy, modify, and distribute this file - * for any purpose is hereby granted without fee, provided that - * the above copyright notice and this notice appears in all - * copies, and that the name of i-cubed limited not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * i-cubed limited makes no representations about the suitability - * of this software for any purpose. - * - * Derived from c/src/lib/libcpu/hppa1_1/clock/clock.c: - * - * COPYRIGHT (c) 1989-2007. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include /* for atexit() */ -#include -#include - -volatile uint32_t Clock_driver_ticks; -extern volatile m8xx_t m8xx; -extern int BSP_get_clock_irq_level(void); -extern uint32_t bsp_clicks_per_usec; - -/* - * Prototypes - */ -rtems_isr Clock_isr(rtems_vector_number vector); -void Clock_exit( void ); -void clockOn(void* unused); -void clockOff(void* unused); -int clockIsOn(void* unused); -void Install_clock(rtems_isr_entry clock_isr); -void ReInstall_clock(rtems_isr_entry new_clock_isr); - -/* - * ISR Handler - */ -rtems_isr Clock_isr(rtems_vector_number vector) -{ - m8xx.piscr |= M8xx_PISCR_PS; - Clock_driver_ticks++; - rtems_clock_tick(); -} - -void clockOn(void* unused) -{ - unsigned desiredLevel; - uint32_t pit_value; - uint32_t extclk; - bool force_prescaler = false; - uint32_t immr_val; - - if (bsp_clicks_per_usec == 0) { - /* - * oscclk is too low for PIT, compute extclk and derive PIT from there - */ - /* - * determine external input clock by examining the PLL settings - * this must be done differently depending on type of PLL - */ - _mfspr(immr_val,M8xx_IMMR); - if (8 == ((immr_val & 0x0000FF00) >> 8)) { - /* - * for MPC866: complex PLL - */ - uint32_t plprcr_val; - uint32_t mfn_value; - uint32_t mfd_value; - uint32_t mfi_value; - uint32_t pdf_value; - uint32_t s_value; - - plprcr_val = m8xx.plprcr; - mfn_value = (plprcr_val & (0xf8000000)) >> (31- 4); - mfd_value = (plprcr_val & (0x07c00000)) >> (31- 9); - s_value = (plprcr_val & (0x00300000)) >> (31-11); - mfi_value = (plprcr_val & (0x000f0000)) >> (31-15); - pdf_value = (plprcr_val & (0x00000006)) >> (31-30); - extclk = (((uint64_t)bsp_clock_speed) - * ((pdf_value + 1) * (mfd_value + 1)) - / (mfi_value * (mfd_value + 1) + mfn_value) - * (1 << s_value)); - } - else { - /* - * for MPC860/850 etc: simple PLL - */ - uint32_t mf_value; - mf_value = m8xx.plprcr >> 20; - extclk = bsp_clock_speed / (mf_value+1); - } - pit_value = (extclk - / 1000 - / 4 - * rtems_configuration_get_microseconds_per_tick() - / 1000); - m8xx.sccr |= (1<<23); - force_prescaler = true; - } - else { - pit_value = (rtems_configuration_get_microseconds_per_tick() * - bsp_clicks_per_usec); - - m8xx.sccr &= ~(1<<23); - } - - if ((pit_value > 0xffff) || force_prescaler) { - /* - * try to activate prescaler - * NOTE: divider generates odd values now... - */ - pit_value = pit_value / 128; - m8xx.sccr |= (1<<24); - } - else { - m8xx.sccr &= ~(1<<24); - } - - if (pit_value > 0xffff) { /* pit is only 16 bits long */ - rtems_fatal_error_occurred(-1); - } - m8xx.pitc = pit_value - 1; - - desiredLevel = BSP_get_clock_irq_level(); - /* set PIT irq level, enable PIT, PIT interrupts */ - /* and clear int. status */ - m8xx.piscr = M8xx_PISCR_PIRQ(desiredLevel) | - M8xx_PISCR_PTE | M8xx_PISCR_PS | M8xx_PISCR_PIE; -} - -/* - * Called via atexit() - * Remove the clock interrupt handler by setting handler to NULL - */ -void clockOff(void* unused) -{ - /* disable PIT and PIT interrupts */ - m8xx.piscr &= ~(M8xx_PISCR_PTE | M8xx_PISCR_PIE); -} - -int clockIsOn(void* unused) -{ - if (m8xx.piscr & M8xx_PISCR_PIE) - return 1; - return 0; -} - -/* - * Called via atexit() - * Remove the clock interrupt handler by setting handler to NULL - */ -void Clock_exit(void) -{ - (void) BSP_disconnect_clock_handler (); -} - -void Install_clock(rtems_isr_entry clock_isr) -{ - Clock_driver_ticks = 0; - - BSP_connect_clock_handler (clock_isr); - atexit(Clock_exit); -} - -void ReInstall_clock(rtems_isr_entry new_clock_isr) -{ - BSP_connect_clock_handler (new_clock_isr); -} - -rtems_device_driver Clock_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *pargp -) -{ - Install_clock( Clock_isr ); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/console-generic/console-generic.c b/c/src/lib/libcpu/powerpc/mpc8xx/console-generic/console-generic.c deleted file mode 100644 index e015a6497b..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/console-generic/console-generic.c +++ /dev/null @@ -1,1073 +0,0 @@ -/* - * General Serial I/O functions. - * - * This file contains the functions for performing serial I/O. - * The actual system calls (console_*) should be in the BSP part - * of the source tree. That way different BSPs can use whichever - * SMCs and SCCs they want. Originally, all the stuff was in - * this file, and it caused problems with one BSP using SCC2 - * as /dev/console, others using SMC1 for /dev/console, etc. - * - * On-chip resources used: - * resource minor note - * SMC1 0 - * SMC2 1 - * SCC1 2 N/A. Hardwired as ethernet port - * SCC2 3 - * SCC3 4 - * SCC4 5 - * BRG1 - * BRG2 - * BRG3 - * BRG4 - * Author: Jay Monkman (jmonkman@frasca.com) - * Copyright (C) 1998 by Frasca International, Inc. - * - * Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by: - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - * - * COPYRIGHT (c) 1989-2007. - * On-Line Applications Research Corporation (OAR). - * - * Modifications by Darlene Stewart - * and Charles-Antoine Gauthier - * Copyright (c) 1999, National Research Council of Canada - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for printk */ - -/* - * Interrupt-driven input buffer - */ -#define RXBUFSIZE 16 - -/* - * I/O buffers and pointers to buffer descriptors. - * Currently, single buffered input is done. This will work only - * if the Rx interrupts are serviced quickly. - * - * TODO: Add a least double buffering for safety. - */ -static volatile char rxBuf[NUM_PORTS][RXBUFSIZE]; -static volatile char txBuf[NUM_PORTS]; - -/* SCC/SMC buffer descriptors */ -static volatile m8xxBufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS]; - -/* Used to track the usage of the baud rate generators */ -static unsigned long brg_spd[4]; -static char brg_used[4]; - -/* Used to track termios private data for callbacks */ -struct rtems_termios_tty *ttyp[NUM_PORTS]; - -/* - * Device-specific routines - */ -static int m8xx_get_brg_cd(int); -static unsigned char m8xx_get_brg_clk(int); -static int m8xx_smc_set_attributes(int, const struct termios*); -static int m8xx_scc_set_attributes(int, const struct termios*); -static void m8xx_smc1_interrupt_handler(void *unused); -static void m8xx_smc2_interrupt_handler(void *unused); -static void m8xx_scc2_interrupt_handler(void *unused); -#if defined(mpc860) -static void m8xx_scc3_interrupt_handler(void *unused); -static void m8xx_scc4_interrupt_handler(void *unused); -#endif - -/* - * Compute baud-rate-generator configuration register value - */ -static int -m8xx_get_brg_cd (int baud) -{ - int divisor; - int div16 = 0; - - divisor = ((bsp_clock_speed / 16) + (baud / 2)) / baud; - if (divisor > 4096) { - div16 = 1; - divisor = (divisor + 8) / 16; - } - return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK | - ((divisor - 1) << 1) | div16; -} - - -/* - * This function will fail if more that 4 baud rates have been selected - * at any time since the OS started. It needs to be fixed. FIXME - */ -static unsigned -char m8xx_get_brg_clk(int baud) -{ - int i; - - /* first try to find a BRG that is already at the right speed */ - for ( i = 0; i < 4; i++ ) { - if ( brg_spd[i] == baud ) { - break; - } - } - - if ( i == 4 ) { /* I guess we didn't find one */ - for ( i = 0; i < 4; i++ ) { - if ( brg_used[i] == 0 ) { - break; - } - } - } - if (i != 4) { - brg_used[i]++; - brg_spd[i]=baud; - switch (i) { - case 0: - m8xx.brgc1 = M8xx_BRG_RST; - m8xx.brgc1 = m8xx_get_brg_cd(baud); - break; - case 1: - m8xx.brgc2 = M8xx_BRG_RST; - m8xx.brgc2 = m8xx_get_brg_cd(baud); - break; - case 2: - m8xx.brgc3 = M8xx_BRG_RST; - m8xx.brgc3 = m8xx_get_brg_cd(baud); - break; - case 3: - m8xx.brgc4 = M8xx_BRG_RST; - m8xx.brgc4 = m8xx_get_brg_cd(baud); - break; - } - return i; - } - - else - return 0xff; -} - - -/* - * Hardware-dependent portion of tcsetattr(). - */ -static int -m8xx_smc_set_attributes (int minor, const struct termios *t) -{ - int baud, brg=0, csize=0, ssize, psize; - uint16_t clen=0, cstopb, parenb, parodd, cread; - - /* Baud rate */ - switch (t->c_ospeed) { - default: baud = -1; break; - case B50: baud = 50; break; - case B75: baud = 75; break; - case B110: baud = 110; break; - case B134: baud = 134; break; - case B150: baud = 150; break; - case B200: baud = 200; break; - case B300: baud = 300; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - case B230400: baud = 230400; break; - case B460800: baud = 460800; break; - } - if (baud > 0) - brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 6 serial ports - hopefully */ - /* at least 2 ports will be the same */ - - /* Number of data bits */ - switch ( t->c_cflag & CSIZE ) { - case CS5: csize = 5; break; - case CS6: csize = 6; break; - case CS7: csize = 7; break; - case CS8: csize = 8; break; - } - - /* Stop bits */ - if ( t->c_cflag & CSTOPB ) { - cstopb = 0x0400; /* Two stop bits */ - ssize = 2; - } else { - cstopb = 0x0000; /* One stop bit */ - ssize = 1; - } - - /* Parity */ - if ( t->c_cflag & PARENB ) { - parenb = 0x0200; /* Parity enabled on Tx and Rx */ - psize = 1; - } else { - parenb = 0x0000; /* No parity on Tx and Rx */ - psize = 0; - } - - if ( t->c_cflag & PARODD ) - parodd = 0x0000; /* Odd parity */ - else - parodd = 0x0100; - - /* - * Character Length = start + data + parity + stop - 1 - */ - switch ( 1 + csize + psize + ssize - 1 ) { - case 6: clen = 0x3000; break; - case 7: clen = 0x3800; break; - case 8: clen = 0x4000; break; - case 9: clen = 0x4800; break; - case 10: clen = 0x5000; break; - case 11: clen = 0x5800; break; - } - - if ( t->c_cflag & CREAD ) - cread = 0x0023; /* UART normal operation, enable Rx and Tx */ - else - cread = 0x0021; /* UART normal operation, enable Tx */ - - /* Write the SIMODE/SMCMR registers */ - switch (minor) { - case SMC1_MINOR: - m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) ); - m8xx.smc1.smcmr = clen | cstopb | parenb | parodd | cread; - break; - case SMC2_MINOR: - m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) ); - m8xx.smc2.smcmr = clen | cstopb | parenb | parodd | cread; - break; - } - return 0; -} - - -static int -m8xx_scc_set_attributes (int minor, const struct termios *t) -{ - int baud, brg=0; - uint16_t csize=0, cstopb, parenb, parodd; - - /* Baud rate */ - switch (t->c_ospeed) { - default: baud = -1; break; - case B50: baud = 50; break; - case B75: baud = 75; break; - case B110: baud = 110; break; - case B134: baud = 134; break; - case B150: baud = 150; break; - case B200: baud = 200; break; - case B300: baud = 300; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - case B230400: baud = 230400; break; - case B460800: baud = 460800; break; - } - if (baud > 0) - brg = m8xx_get_brg_clk(baud); /* 4 BRGs, 5 serial ports - hopefully */ - /* at least 2 ports will be the same */ - /* Write the SICR register below */ - - /* Number of data bits */ - switch ( t->c_cflag & CSIZE ) { - case CS5: csize = 0x0000; break; - case CS6: csize = 0x1000; break; - case CS7: csize = 0x2000; break; - case CS8: csize = 0x3000; break; - } - - /* Stop bits */ - if ( t->c_cflag & CSTOPB ) - cstopb = 0x4000; /* Two stop bits */ - else - cstopb = 0x0000; /* One stop bit */ - - /* Parity */ - if ( t->c_cflag & PARENB ) - parenb = 0x0010; /* Parity enabled on Tx and Rx */ - else - parenb = 0x0000; /* No parity on Tx and Rx */ - - if ( t->c_cflag & PARODD ) - parodd = 0x0000; /* Odd parity */ - else - parodd = 0x000a; - - /* Write the SICR/PSMR Registers */ - switch (minor) { - case SCC2_MINOR: - m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) ); - m8xx.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc2.psmr & 0x8fe0) ); - break; - #if defined(mpc860) - case SCC3_MINOR: - m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) ); - m8xx.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc3.psmr & 0x8fe0) ); - break; - case SCC4_MINOR: - m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) ); - m8xx.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc4.psmr & 0x8fe0) ); - break; - #endif - } - - return 0; -} - - -int -m8xx_uart_setAttributes( - int minor, - const struct termios *t -) -{ - /* - * Check that port number is valid - */ - if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) ) - return 0; - - switch (minor) { - case SMC1_MINOR: - case SMC2_MINOR: - return m8xx_smc_set_attributes( minor, t ); - - case SCC2_MINOR: - case SCC3_MINOR: - case SCC4_MINOR: - return m8xx_scc_set_attributes( minor, t ); - } - return 0; -} - - -/* - * Interrupt handlers - */ -static void m8xx_scc2_interrupt_handler (void *unused) -{ - /* - * Buffer received? - */ - if ((m8xx.scc2.sccm & M8xx_SCCE_RX) && (m8xx.scc2.scce & M8xx_SCCE_RX)) { - m8xx.scc2.scce = M8xx_SCCE_RX; /* Clear the event */ - - - /* Check that the buffer is ours */ - if ((RxBd[SCC2_MINOR]->status & M8xx_BD_EMPTY) == 0) { - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[SCC2_MINOR]->buffer, - RxBd[SCC2_MINOR]->length ); - rtems_termios_enqueue_raw_characters( - (void *)ttyp[SCC2_MINOR], - (char *)RxBd[SCC2_MINOR]->buffer, - (int)RxBd[SCC2_MINOR]->length ); - RxBd[SCC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | - M8xx_BD_INTERRUPT; - } - } - - /* - * Buffer transmitted? - */ - if (m8xx.scc2.scce & M8xx_SCCE_TX) { - m8xx.scc2.scce = M8xx_SCCE_TX; /* Clear the event */ - - /* Check that the buffer is ours */ - if ((TxBd[SCC2_MINOR]->status & M8xx_BD_READY) == 0) - rtems_termios_dequeue_characters ( - (void *)ttyp[SCC2_MINOR], - (int)TxBd[SCC2_MINOR]->length); - } -} - - -#ifdef mpc860 -static void -m8xx_scc3_interrupt_handler (void *unused) -{ - /* - * Buffer received? - */ - if ((m8xx.scc3.sccm & M8xx_SCCE_RX) && (m8xx.scc3.scce & M8xx_SCCE_RX)) { - m8xx.scc3.scce = M8xx_SCCE_RX; /* Clear the event */ - - - /* Check that the buffer is ours */ - if ((RxBd[SCC3_MINOR]->status & M8xx_BD_EMPTY) == 0) { - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[SCC3_MINOR]->buffer, - RxBd[SCC3_MINOR]->length ); - rtems_termios_enqueue_raw_characters( - (void *)ttyp[SCC3_MINOR], - (char *)RxBd[SCC3_MINOR]->buffer, - (int)RxBd[SCC3_MINOR]->length ); - RxBd[SCC3_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | - M8xx_BD_INTERRUPT; - } - } - - /* - * Buffer transmitted? - */ - if (m8xx.scc3.scce & M8xx_SCCE_TX) { - m8xx.scc3.scce = M8xx_SCCE_TX; /* Clear the event */ - - /* Check that the buffer is ours */ - if ((TxBd[SCC3_MINOR]->status & M8xx_BD_READY) == 0) - rtems_termios_dequeue_characters ( - (void *)ttyp[SCC3_MINOR], - (int)TxBd[SCC3_MINOR]->length); - } -} - - -static void -m8xx_scc4_interrupt_handler (void *unused) -{ - /* - * Buffer received? - */ - if ((m8xx.scc4.sccm & M8xx_SCCE_RX) && (m8xx.scc4.scce & M8xx_SCCE_RX)) { - m8xx.scc4.scce = M8xx_SCCE_RX; /* Clear the event */ - - - /* Check that the buffer is ours */ - if ((RxBd[SCC4_MINOR]->status & M8xx_BD_EMPTY) == 0) { - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[SCC4_MINOR]->buffer, - RxBd[SCC4_MINOR]->length ); - rtems_termios_enqueue_raw_characters( - (void *)ttyp[SCC4_MINOR], - (char *)RxBd[SCC4_MINOR]->buffer, - (int)RxBd[SCC4_MINOR]->length ); - RxBd[SCC4_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | - M8xx_BD_INTERRUPT; - } - } - - /* - * Buffer transmitted? - */ - if (m8xx.scc4.scce & M8xx_SCCE_TX) { - m8xx.scc4.scce = M8xx_SCCE_TX; /* Clear the event */ - - /* Check that the buffer is ours */ - if ((TxBd[SCC4_MINOR]->status & M8xx_BD_READY) == 0) - rtems_termios_dequeue_characters ( - (void *)ttyp[SCC4_MINOR], - (int)TxBd[SCC4_MINOR]->length); - } -} -#endif - -static void -m8xx_smc1_interrupt_handler (void *unused) -{ - /* - * Buffer received? - */ - if (m8xx.smc1.smce & M8xx_SMCE_RX) { - m8xx.smc1.smce = M8xx_SMCE_RX; /* Clear the event */ - - - /* Check that the buffer is ours */ - if ((RxBd[SMC1_MINOR]->status & M8xx_BD_EMPTY) == 0) { - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[SMC1_MINOR]->buffer, - RxBd[SMC1_MINOR]->length ); - rtems_termios_enqueue_raw_characters( - (void *)ttyp[SMC1_MINOR], - (char *)RxBd[SMC1_MINOR]->buffer, - (int)RxBd[SMC1_MINOR]->length ); - RxBd[SMC1_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | - M8xx_BD_INTERRUPT; - } - } - - /* - * Buffer transmitted? - */ - if (m8xx.smc1.smce & M8xx_SMCE_TX) { - m8xx.smc1.smce = M8xx_SMCE_TX; /* Clear the event */ - - /* Check that the buffer is ours */ - if ((TxBd[SMC1_MINOR]->status & M8xx_BD_READY) == 0) - rtems_termios_dequeue_characters ( - (void *)ttyp[SMC1_MINOR], - (int)TxBd[SMC1_MINOR]->length); - } -} - - -static void -m8xx_smc2_interrupt_handler (void *unused) -{ - /* - * Buffer received? - */ - if (m8xx.smc2.smce & M8xx_SMCE_RX) { - m8xx.smc2.smce = M8xx_SMCE_RX; /* Clear the event */ - - - /* Check that the buffer is ours */ - if ((RxBd[SMC2_MINOR]->status & M8xx_BD_EMPTY) == 0) { - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[SMC2_MINOR]->buffer, - RxBd[SMC2_MINOR]->length ); - rtems_termios_enqueue_raw_characters( - (void *)ttyp[SMC2_MINOR], - (char *)RxBd[SMC2_MINOR]->buffer, - (int)RxBd[SMC2_MINOR]->length ); - RxBd[SMC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | - M8xx_BD_INTERRUPT; - } - } - - /* - * Buffer transmitted? - */ - if (m8xx.smc2.smce & M8xx_SMCE_TX) { - m8xx.smc2.smce = M8xx_SMCE_TX; /* Clear the event */ - - /* Check that the buffer is ours */ - if ((TxBd[SMC2_MINOR]->status & M8xx_BD_READY) == 0) - rtems_termios_dequeue_characters ( - (void *)ttyp[SMC2_MINOR], - (int)TxBd[SMC2_MINOR]->length); - } -} - -static void m8xx_scc_enable(const rtems_irq_connect_data* ptr) -{ - volatile m8xxSCCRegisters_t *sccregs = 0; - switch (ptr->name) { -#if defined(mpc860) - case BSP_CPM_IRQ_SCC4 : - sccregs = &m8xx.scc4; - break; - case BSP_CPM_IRQ_SCC3 : - sccregs = &m8xx.scc3; - break; -#endif - case BSP_CPM_IRQ_SCC2 : - sccregs = &m8xx.scc2; - break; - case BSP_CPM_IRQ_SCC1 : - sccregs = &m8xx.scc1; - break; - default: - break; - } - sccregs->sccm = 3; -} - -static void m8xx_scc_disable(const rtems_irq_connect_data* ptr) -{ - volatile m8xxSCCRegisters_t *sccregs = 0; - switch (ptr->name) { -#if defined(mpc860) - case BSP_CPM_IRQ_SCC4 : - sccregs = &m8xx.scc4; - break; - case BSP_CPM_IRQ_SCC3 : - sccregs = &m8xx.scc3; - break; -#endif - case BSP_CPM_IRQ_SCC2 : - sccregs = &m8xx.scc2; - break; - case BSP_CPM_IRQ_SCC1 : - sccregs = &m8xx.scc1; - break; - default: - break; - } - sccregs->sccm &= (~3); -} - -static int m8xx_scc_isOn(const rtems_irq_connect_data* ptr) -{ - return BSP_irq_enabled_at_cpm (ptr->name); -} - -static rtems_irq_connect_data consoleIrqData; - -void -m8xx_uart_scc_initialize (int minor) -{ - unsigned char brg; - volatile m8xxSCCparms_t *sccparms = 0; - volatile m8xxSCCRegisters_t *sccregs = 0; - - /* - * Check that minor number is valid - */ - if ( (minor < SCC2_MINOR) || (minor > NUM_PORTS-1) ) - return; - - /* Get the sicr clock source bit values for 9600 bps */ - brg = m8xx_get_brg_clk(9600); - - /* - * Allocate buffer descriptors - */ - RxBd[minor] = m8xx_bd_allocate(1); - TxBd[minor] = m8xx_bd_allocate(1); - - /* - * Get the address of the parameter RAM for the specified port, - * configure I/O port A,C & D and put SMC in NMSI mode, connect - * the SCC to the appropriate BRG. - * - * SCC2 TxD is shared with port A bit 12 - * SCC2 RxD is shared with port A bit 13 - * SCC1 TxD is shared with port A bit 14 - * SCC1 RxD is shared with port A bit 15 - * SCC4 DCD is shared with port C bit 4 - * SCC4 CTS is shared with port C bit 5 - * SCC3 DCD is shared with port C bit 6 - * SCC3 CTS is shared with port C bit 7 - * SCC2 DCD is shared with port C bit 8 - * SCC2 CTS is shared with port C bit 9 - * SCC1 DCD is shared with port C bit 10 - * SCC1 CTS is shared with port C bit 11 - * SCC2 RTS is shared with port C bit 14 - * SCC1 RTS is shared with port C bit 15 - * SCC4 RTS is shared with port D bit 6 - * SCC3 RTS is shared with port D bit 7 - * SCC4 TxD is shared with port D bit 8 - * SCC4 RxD is shared with port D bit 9 - * SCC3 TxD is shared with port D bit 10 - * SCC3 RxD is shared with port D bit 11 - */ - switch (minor) { - case SCC2_MINOR: - sccparms = &m8xx.scc2p; - sccregs = &m8xx.scc2; - - m8xx.papar |= 0x000C; /* PA12 & PA13 are dedicated peripheral pins */ - m8xx.padir &= ~0x000C; /* PA13 & PA12 must not drive the UART lines */ - m8xx.paodr &= ~0x000C; /* PA12 & PA13 are not open drain */ - m8xx.pcpar |= 0x0002; /* PC14 is SCC2 RTS */ - m8xx.pcpar &= ~0x00C0; /* PC8 & PC9 are SCC2 DCD and CTS */ - m8xx.pcdir &= ~0x00C2; /* PC8, PC9 & PC14 must not drive the UART lines */ - m8xx.pcso |= 0x00C0; /* Enable DCD and CTS inputs */ - - m8xx.sicr &= 0xFFFF00FF; /* Clear TCS2 & RCS2, GR2=no grant, SC2=NMSI mode */ - m8xx.sicr |= (brg<<11) | (brg<<8); /* TCS2 = RCS2 = brg */ - break; - -#ifdef mpc860 - case SCC3_MINOR: - sccparms = &m8xx.scc3p; - sccregs = &m8xx.scc3; - - m8xx.pcpar &= ~0x0300; /* PC6 & PC7 are SCC3 DCD and CTS */ - m8xx.pcdir &= ~0x0300; /* PC6 & PC7 must not drive the UART lines */ - m8xx.pcso |= 0x0300; /* Enable DCD and CTS inputs */ - m8xx.pdpar |= 0x0130; /* PD7, PD10 & PD11 are dedicated peripheral pins */ - - m8xx.sicr &= 0xFF00FFFF; /* Clear TCS3 & RCS3, GR3=no grant, SC3=NMSI mode */ - m8xx.sicr |= (brg<<19) | (brg<<16); /* TCS3 = RCS3 = brg */ - break; - - case SCC4_MINOR: - sccparms = &m8xx.scc4p; - sccregs = &m8xx.scc4; - - m8xx.pcpar &= ~0x0C00; /* PC4 & PC5 are SCC4 DCD and CTS */ - m8xx.pcdir &= ~0x0C00; /* PC4 & PC5 must not drive the UART lines */ - m8xx.pcso |= 0x0C00; /* Enable DCD and CTS inputs */ - m8xx.pdpar |= 0x02C0; /* PD6, PD8 & PD9 are dedicated peripheral pins */ - - m8xx.sicr &= 0x00FFFFFF; /* Clear TCS4 & RCS4, GR4=no grant, SC4=NMSI mode */ - m8xx.sicr |= (brg<<27) | (brg<<24); /* TCS4 = RCS4 = brg */ - break; -#endif - } - - /* - * Set up SDMA - */ - m8xx.sdcr = 0x01; /* as per section 16.10.2.1 MPC821UM/AD */ - - /* - * Set up the SCC parameter RAM. - */ - sccparms->rbase = (char *)RxBd[minor] - (char *)&m8xx; - sccparms->tbase = (char *)TxBd[minor] - (char *)&m8xx; - - sccparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); - sccparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0); - if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) - sccparms->mrblr = RXBUFSIZE; /* Maximum Rx buffer size */ - else - sccparms->mrblr = 1; /* Maximum Rx buffer size */ - sccparms->un.uart.max_idl = 10; /* Set nb of idle chars to close buffer */ - sccparms->un.uart.brkcr = 0; /* Set nb of breaks to send for STOP Tx */ - - sccparms->un.uart.parec = 0; /* Clear parity error counter */ - sccparms->un.uart.frmec = 0; /* Clear framing error counter */ - sccparms->un.uart.nosec = 0; /* Clear noise counter */ - sccparms->un.uart.brkec = 0; /* Clear break counter */ - - sccparms->un.uart.uaddr[0] = 0; /* Not in multidrop mode, so clear */ - sccparms->un.uart.uaddr[1] = 0; /* Not in multidrop mode, so clear */ - sccparms->un.uart.toseq = 0; /* Tx Out-Of-SEQuence--no XON/XOFF now */ - - sccparms->un.uart.character[0] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[1] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[2] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[3] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[4] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[5] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[6] = 0x8000; /* Entry is invalid */ - sccparms->un.uart.character[7] = 0x8000; /* Entry is invalid */ - - - sccparms->un.uart.rccm = 0xc0ff; /* No masking */ - - /* - * Set up the Receive Buffer Descriptor - */ - RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; - RxBd[minor]->length = 0; - RxBd[minor]->buffer = rxBuf[minor]; - - /* - * Setup the Transmit Buffer Descriptor - */ - TxBd[minor]->status = M8xx_BD_WRAP; - - /* - * Set up SCCx general and protocol-specific mode registers - */ - sccregs->gsmr_h = 0x00000020; /* RFW=low latency operation */ - sccregs->gsmr_l = 0x00028004; /* TDCR=RDCR=16x clock mode, MODE=uart*/ - sccregs->scce = ~0; /* Clear any pending event */ - sccregs->sccm = 0; /* Mask all interrupt/event sources */ - sccregs->psmr = 0x3000; /* Normal operation & mode, 1 stop bit, - 8 data bits, no parity */ - sccregs->dsr = 0x7E7E; /* No fractional stop bits */ - sccregs->gsmr_l = 0x00028034; /* ENT=enable Tx, ENR=enable Rx */ - - /* - * Initialize the Rx and Tx with the new parameters. - */ - switch (minor) { - case SCC2_MINOR: - m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC2); - break; - -#ifdef mpc860 - case SCC3_MINOR: - m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC3); - break; - case SCC4_MINOR: - m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC4); - break; -#endif - } - if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) { - consoleIrqData.on = m8xx_scc_enable; - consoleIrqData.off = m8xx_scc_disable; - consoleIrqData.isOn = m8xx_scc_isOn; - - switch (minor) { - case SCC2_MINOR: - consoleIrqData.name = BSP_CPM_IRQ_SCC2; - consoleIrqData.hdl = m8xx_scc2_interrupt_handler; - break; - -#ifdef mpc860 - case SCC3_MINOR: - consoleIrqData.name = BSP_CPM_IRQ_SCC3; - consoleIrqData.hdl = m8xx_scc3_interrupt_handler; - break; - - case SCC4_MINOR: - consoleIrqData.name = BSP_CPM_IRQ_SCC4; - consoleIrqData.hdl = m8xx_scc4_interrupt_handler; - break; -#endif /* mpc860 */ - } - if (!BSP_install_rtems_irq_handler (&consoleIrqData)) { - printk("Unable to connect SCC Irq handler\n"); - rtems_fatal_error_occurred(1); - } - } -} - -static void m8xx_smc_enable(const rtems_irq_connect_data* ptr) -{ - volatile m8xxSMCRegisters_t *smcregs = 0; - switch (ptr->name) { - case BSP_CPM_IRQ_SMC1 : - smcregs = &m8xx.smc1; - break; - case BSP_CPM_IRQ_SMC2_OR_PIP : - smcregs = &m8xx.smc2; - break; - default: - break; - } - smcregs->smcm = 3; -} - -static void m8xx_smc_disable(const rtems_irq_connect_data* ptr) -{ - volatile m8xxSMCRegisters_t *smcregs = 0; - switch (ptr->name) { - case BSP_CPM_IRQ_SMC1 : - smcregs = &m8xx.smc1; - break; - case BSP_CPM_IRQ_SMC2_OR_PIP : - smcregs = &m8xx.smc2; - break; - default: - break; - } - smcregs->smcm &= (~3); -} - -static int m8xx_smc_isOn(const rtems_irq_connect_data* ptr) -{ - return BSP_irq_enabled_at_cpm (ptr->name); -} - -void -m8xx_uart_smc_initialize (int minor) -{ - unsigned char brg; - volatile m8xxSMCparms_t *smcparms = 0; - volatile m8xxSMCRegisters_t *smcregs = 0; - - /* - * Check that minor number is valid - */ - if ( (minor < SMC1_MINOR) || (minor > SMC2_MINOR) ) - return; - - m8xx.sdcr = 0x01; /* as per section 16.10.2.1 MPC821UM/AD */ - /* Get the simode clock source bit values for 9600 bps */ - brg = m8xx_get_brg_clk(9600); - - /* - * Allocate buffer descriptors - */ - RxBd[minor] = m8xx_bd_allocate (1); - TxBd[minor] = m8xx_bd_allocate (1); - - /* - * Get the address of the parameter RAM for the specified port, - * configure I/O port B and put SMC in NMSI mode, connect the - * SMC to the appropriate BRG. - * - * SMC2 RxD is shared with port B bit 20 - * SMC2 TxD is shared with port B bit 21 - * SMC1 RxD is shared with port B bit 24 - * SMC1 TxD is shared with port B bit 25 - */ - switch (minor) { - case SMC1_MINOR: - smcparms = &m8xx.smc1p; - smcregs = &m8xx.smc1; - - m8xx.pbpar |= 0x000000C0; /* PB24 & PB25 are dedicated peripheral pins */ - m8xx.pbdir &= ~0x000000C0; /* PB24 & PB25 must not drive UART lines */ - m8xx.pbodr &= ~0x000000C0; /* PB24 & PB25 are not open drain */ - - m8xx.simode &= 0xFFFF0FFF; /* Clear SMC1CS & SMC1 for NMSI mode */ - m8xx.simode |= brg << 12; /* SMC1CS = brg */ - break; - - case SMC2_MINOR: - smcparms = &m8xx.smc2p; - smcregs = &m8xx.smc2; - - m8xx.pbpar |= 0x00000C00; /* PB20 & PB21 are dedicated peripheral pins */ - m8xx.pbdir &= ~0x00000C00; /* PB20 & PB21 must not drive the UART lines */ - m8xx.pbodr &= ~0x00000C00; /* PB20 & PB21 are not open drain */ - - m8xx.simode &= 0x0FFFFFFF; /* Clear SMC2CS & SMC2 for NMSI mode */ - m8xx.simode |= brg << 28; /* SMC2CS = brg */ - break; - } - - /* - * Set up SMC1 parameter RAM common to all protocols - */ - smcparms->rbase = (char *)RxBd[minor] - (char *)&m8xx; - smcparms->tbase = (char *)TxBd[minor] - (char *)&m8xx; - smcparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); - smcparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0); - if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) - smcparms->mrblr = RXBUFSIZE; /* Maximum Rx buffer size */ - else - smcparms->mrblr = 1; /* Maximum Rx buffer size */ - - /* - * Set up SMC1 parameter RAM UART-specific parameters - */ - smcparms->un.uart.max_idl = 10; /* Set nb of idle chars to close buffer */ - smcparms->un.uart.brkcr = 0; /* Set nb of breaks to send for STOP Tx */ - smcparms->un.uart.brkec = 0; /* Clear break counter */ - - /* - * Set up the Receive Buffer Descriptor - */ - RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; - RxBd[minor]->length = 0; - RxBd[minor]->buffer = rxBuf[minor]; - - /* - * Setup the Transmit Buffer Descriptor - */ - TxBd[minor]->status = M8xx_BD_WRAP; - - /* - * Set up SMCx general and protocol-specific mode registers - */ - smcregs->smce = ~0; /* Clear any pending events */ - smcregs->smcm = 0; /* Enable SMC Rx & Tx interrupts */ - smcregs->smcmr = M8xx_SMCMR_CLEN(9) | M8xx_SMCMR_SM_UART; - - /* - * Send "Init parameters" command - */ - switch (minor) { - case SMC1_MINOR: - m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC1); - break; - - case SMC2_MINOR: - m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC2); - break; - } - - /* - * Enable receiver and transmitter - */ - smcregs->smcmr |= M8xx_SMCMR_TEN | M8xx_SMCMR_REN; - if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) { - consoleIrqData.on = m8xx_smc_enable; - consoleIrqData.off = m8xx_smc_disable; - consoleIrqData.isOn = m8xx_smc_isOn; - switch (minor) { - case SMC1_MINOR: - consoleIrqData.name = BSP_CPM_IRQ_SMC1; - consoleIrqData.hdl = m8xx_smc1_interrupt_handler; - break; - - case SMC2_MINOR: - consoleIrqData.name = BSP_CPM_IRQ_SMC2_OR_PIP; - consoleIrqData.hdl = m8xx_smc2_interrupt_handler; - break; - } - if (!BSP_install_rtems_irq_handler (&consoleIrqData)) { - printk("Unable to connect SMC Irq handler\n"); - rtems_fatal_error_occurred(1); - } - } -} - -void -m8xx_uart_initialize(void) -{ - int i; - - for (i=0; i < 4; i++) { - brg_spd[i] = 0; - brg_used[i] = 0; - } -} - - - -int -m8xx_uart_pollRead( - int minor -) -{ - unsigned char c; - - if (RxBd[minor]->status & M8xx_BD_EMPTY) { - return -1; - } - rtems_cache_invalidate_multiple_data_lines( - (const void *) RxBd[minor]->buffer, - RxBd[minor]->length - ); - c = ((char *)RxBd[minor]->buffer)[0]; - RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP; - return c; -} - - -/* - * TODO: Get a free buffer and set it up. - */ -ssize_t -m8xx_uart_write( - int minor, - const char *buf, - size_t len -) -{ - rtems_cache_flush_multiple_data_lines( buf, len ); - TxBd[minor]->buffer = (char *) buf; - TxBd[minor]->length = len; - TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT; - return 0; -} - - -ssize_t -m8xx_uart_pollWrite( - int minor, - const char *buf, - size_t len -) -{ - while (len--) { - while (TxBd[minor]->status & M8xx_BD_READY) - continue; - txBuf[minor] = *buf++; - rtems_cache_flush_multiple_data_lines( (void *)&txBuf[minor], 1 ); - TxBd[minor]->buffer = &txBuf[minor]; - TxBd[minor]->length = 1; - TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP; - } - return len; -} diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/cpm/cp.c b/c/src/lib/libcpu/powerpc/mpc8xx/cpm/cp.c deleted file mode 100644 index de38f0a5df..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/cpm/cp.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 -#include -#include - -/* - * Send a command to the CPM RISC processer - */ - -void m8xx_cp_execute_cmd( uint16_t command ) -{ - rtems_interrupt_level lvl; - - rtems_interrupt_disable(lvl); - while (m8xx.cpcr & M8xx_CR_FLG) { - continue; - } - - m8xx.cpcr = command | M8xx_CR_FLG; - rtems_interrupt_enable (lvl); -} diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/cpm/dpram.c b/c/src/lib/libcpu/powerpc/mpc8xx/cpm/dpram.c deleted file mode 100644 index 4f6cb6d94a..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/cpm/dpram.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * dpram.c - * - * MPC8xx dual-port RAM allocation 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 : - * Copyright (c) 1999, National Research Council of Canada - */ - -#include -#include - -#include -#include - -/* - * Allocation order: - * - Dual-Port RAM section 0 - * - Dual-Port RAM section 1 - * - Dual-Port RAM section 2 - * - Dual-Port RAM section 3 - * - Dual-Port RAM section 4 - */ -static struct { - uint8_t *base; - size_t size; - unsigned int used; -} dpram_regions[] = { - { (uint8_t *) &m8xx.dpram0[0], sizeof m8xx.dpram0, 0 }, - { (uint8_t *) &m8xx.dpram1[0], sizeof m8xx.dpram1, 0 }, - { (uint8_t *) &m8xx.dpram2[0], sizeof m8xx.dpram2, 0 }, - { (uint8_t *) &m8xx.dpram3[0], sizeof m8xx.dpram3, 0 }, - { (uint8_t *) &m8xx.dpram4[0], sizeof m8xx.dpram4, 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_Local_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_Local_enable(level); - - if (blockp == NULL) - rtems_panic("Can't allocate %d bytes of dual-port RAM.\n", byte_count); - return blockp; -} diff --git a/c/src/lib/libcpu/powerpc/mpc8xx/mmu/mmu.c b/c/src/lib/libcpu/powerpc/mpc8xx/mmu/mmu.c deleted file mode 100644 index 78743c6250..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc8xx/mmu/mmu.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * mmu.c - * - * This file contains routines for initializing - * and manipulating the MMU on the MPC8xx. - * - * Copyright (c) 1999, National Research Council of Canada - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#include -#include - -/* - * mmu_init - * - * This routine sets up the virtual memory maps on an MPC8xx. - * The MPC8xx does not support block address translation (BATs) - * and does not have segment registers. Thus, we must set up page - * translation. However, its MMU supports variable size pages - * (1-, 4-, 16-, 512-Kbyte or 8-Mbyte), which simplifies the task. - * - * The MPC8xx has separate data and instruction 32-entry translation - * lookaside buffers (TLB). By mapping all of DRAM as one huge page, - * we can preload the TLBs and not have to be concerned with taking - * TLB miss exceptions. - * - * We set up the virtual memory map so that virtual address of a - * location is equal to its real address. - */ -void mmu_init( void ) -{ - register uint32_t reg1, i; - - /* - * Initialize the TLBs - * - * Instruction address translation and data address translation - * must be disabled during initialization (IR=0, DR=0 in MSR). - * We can assume the MSR has already been set this way. - */ - - /* - * Initialize IMMU & DMMU Control Registers (MI_CTR & MD_CTR) - * GPM [0] 0b0 = PowerPC mode - * PPM [1] 0b0 = Page resolution of protection - * CIDEF [2] 0b0/0b0 = Default cache-inhibit attribute = - * NO for IMMU, NO for DMMU - * NOTE: it is vital that data caching is ON, when - * DMMU is off, otherwise valid/dirty values in - * cache would be ignored during exception entry - * reserved/WTDEF [3] 0b0 = Default write-through attribute = not - * RSV4x [4] 0b0 = 4 entries not reserved - * reserved/TWAM [5] 0b0/0b1 = 4-Kbyte page hardware assist - * PPCS [6] 0b0 = Ignore user/supervisor state - * reserved [7-18] 0x00 - * xTLB_INDX [19-23] 31 = 0x1F - * reserved [24-31] 0x00 - * - * Note: It is important that cache-inhibit be set as the default for the - * data cache when the DMMU is disabled in order to prevent internal memory - * mapped registers from being cached accidentally when address translation - * is turned off at the start of exception processing. - */ - reg1 = M8xx_MI_CTR_ITLB_INDX(31); - _mtspr( M8xx_MI_CTR, reg1 ); - reg1 = M8xx_MD_CTR_TWAM | M8xx_MD_CTR_DTLB_INDX(31); - _mtspr( M8xx_MD_CTR, reg1 ); - _isync; - - /* - * Invalidate all TLB entries in both TLBs. - * Note: We rely on the RSV4 bit in MI_CTR and MD_CTR being 0b0, so - * all 32 entries are invalidated. - */ - __asm__ volatile ("tlbia\n"::); - _isync; - - /* - * Set Current Address Space ID Register (M_CASID). - * Supervisor: CASID = 0 - */ - reg1 = 0; - _mtspr( M8xx_M_CASID, reg1 ); - - /* - * Initialize the MMU Access Protection Registers (MI_AP, MD_AP) - * We ignore the Access Protection Group (APG) mechanism globally - * by setting all of the Mx_AP fields to 0b01 : client access - * permission is defined by page protection bits. - */ - reg1 = 0x55555555; - _mtspr( M8xx_MI_AP, reg1 ); - _mtspr( M8xx_MD_AP, reg1 ); - - /* - * Load both 32-entry TLBs with values from the MMU_TLB_table - * which is defined in the BSP. - * Note the _TLB_Table must have at most 32 entries. This code - * makes no effort to enforce this restriction. - */ - for( i = 0; i < MMU_N_TLB_Table_Entries; ++i ) { - reg1 = MMU_TLB_table[i].mmu_epn; - _mtspr( M8xx_MI_EPN, reg1 ); - _mtspr( M8xx_MD_EPN, reg1 ); - reg1 = MMU_TLB_table[i].mmu_twc; - _mtspr( M8xx_MI_TWC, reg1 ); - _mtspr( M8xx_MD_TWC, reg1 ); - reg1 = MMU_TLB_table[i].mmu_rpn; /* RPN must be written last! */ - _mtspr( M8xx_MI_RPN, reg1 ); - _mtspr( M8xx_MD_RPN, reg1 ); - } - - /* - * Turn on address translation by setting MSR[IR] and MSR[DR]. - */ - _CPU_MSR_GET( reg1 ); - reg1 |= PPC_MSR_IR | PPC_MSR_DR; - _CPU_MSR_SET( reg1 ); -} -- cgit v1.2.3