diff options
author | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2005-04-28 14:05:14 +0000 |
---|---|---|
committer | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2005-04-28 14:05:14 +0000 |
commit | 0329aae1b2cd18215ac8d19cbb1a69f502eddd71 (patch) | |
tree | 84188ee210ca807c9af4393c93684ff491a789ee /c/src/lib/libbsp/powerpc/ep1a/console | |
parent | 2005-04-27 Ralf Corsepius <ralf.corsepius@rtems.org> (diff) | |
download | rtems-0329aae1b2cd18215ac8d19cbb1a69f502eddd71.tar.bz2 |
2005-04-28 Jennifer Averett <jennifer.averett@oarcorp.com>
* acinclude.m4: Initial release of ep1a bsp
* ep1a/Makefile.am, ep1a/bsp_specs, ep1a/configure.ac,
ep1a/console/alloc360.c, ep1a/console/console.c,
ep1a/console/console.h, ep1a/console/init68360.c,
ep1a/console/m68360.h, ep1a/console/mc68360_scc.c,
ep1a/console/ns16550cfg.c, ep1a/console/ns16550cfg.h,
ep1a/console/rsPMCQ1.c, ep1a/console/rsPMCQ1.h, ep1a/include/bsp.h,
ep1a/irq/irq.c, ep1a/irq/irq_init.c, ep1a/pci/no_host_bridge.c,
ep1a/start/start.S, ep1a/startup/bspstart.c, ep1a/startup/linkcmds,
ep1a/vme/vmeconfig.c: New files.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ep1a/console')
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/alloc360.c | 104 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/console.c | 350 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/console.h | 38 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/init68360.c | 670 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/m68360.h | 973 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c | 836 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.c | 47 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.h | 57 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.c | 558 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.h | 148 |
10 files changed, 3781 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/alloc360.c b/c/src/lib/libbsp/powerpc/ep1a/console/alloc360.c new file mode 100644 index 0000000000..1ed1aca3f4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/alloc360.c @@ -0,0 +1,104 @@ +/* + * MC68360 buffer descriptor allocation routines + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include "m68360.h" +#include <rtems/error.h> +#include "rsPMCQ1.h" +#include <rtems/bspIo.h> + +void M360SetupMemory( M68360_t ptr ){ + volatile m360_t *m360; + + m360 = ptr->m360; + + ptr->bdregions[0].base = (char *)&m360->dpram1[0]; + ptr->bdregions[0].size = sizeof m360->dpram1; + ptr->bdregions[0].used = 0; + + ptr->bdregions[1].base = (char *)&m360->dpram3[0]; + ptr->bdregions[1].size = sizeof m360->dpram3; + ptr->bdregions[1].used = 0; + + ptr->bdregions[2].base = (char *)&m360->dpram0[0]; + ptr->bdregions[2].size = sizeof m360->dpram0; + ptr->bdregions[2].used = 0; + + ptr->bdregions[3].base = (char *)&m360->dpram2[0]; + ptr->bdregions[3].size = sizeof m360->dpram2; + ptr->bdregions[3].used = 0; +} + + +/* + * Send a command to the CPM RISC processer + */ +void * +M360AllocateBufferDescriptors (M68360_t ptr, int count) +{ + unsigned int i; + ISR_Level level; + void *bdp = NULL; + unsigned int want = count * sizeof(m360BufferDescriptor_t); + int have; + + /* + * Running with interrupts disabled is usually considered bad + * form, but this routine is probably being run as part of an + * initialization sequence so the effect shouldn't be too severe. + */ + _ISR_Disable (level); + + for (i = 0 ; i < M360_NUM_DPRAM_REAGONS ; i++) { + + /* + * Verify that the region exists. + * This test is necessary since some chips have + * less dual-port RAM. + */ + if (ptr->bdregions[i].used == 0) { + volatile unsigned char *cp = ptr->bdregions[i].base; + *cp = 0xAA; + if (*cp != 0xAA) { + ptr->bdregions[i].used = ptr->bdregions[i].size; + continue; + } + *cp = 0x55; + if (*cp != 0x55) { + ptr->bdregions[i].used = ptr->bdregions[i].size; + continue; + } + *cp = 0x0; + } + + have = ptr->bdregions[i].size - ptr->bdregions[i].used; + if (have >= want) { + bdp = ptr->bdregions[i].base + ptr->bdregions[i].used; + ptr->bdregions[i].used += want; + break; + } + } + _ISR_Enable (level); + if (bdp == NULL){ + printk("rtems_panic can't allocate %d buffer descriptor(s).\n"); + rtems_panic ("Can't allocate %d buffer descriptor(s).\n", count); + } + return bdp; +} diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/console.c b/c/src/lib/libbsp/powerpc/ep1a/console/console.c new file mode 100644 index 0000000000..87f40d1c3c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/console.c @@ -0,0 +1,350 @@ +/* + * This file contains the TTY driver for the ep1a + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <stdlib.h> +#include <assert.h> +#include <termios.h> + +#include "console.h" +#include <rtems/bspIo.h> + +/* + * Load configuration table + */ +#include "config.c" + +#define NUM_CONSOLE_PORTS (sizeof(Console_Port_Tbl)/sizeof(console_tbl)) + +console_data Console_Port_Data[NUM_CONSOLE_PORTS]; +unsigned long Console_Port_Count; +rtems_device_minor_number Console_Port_Minor; + +/* PAGE + * + * console_open + * + * open a port as a termios console. + * + */ +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_status_code status; + rtems_libio_open_close_args_t *args = arg; + rtems_libio_ioctl_args_t IoctlArgs; + struct termios Termios; + rtems_termios_callbacks Callbacks; + console_fns *c; + + /* + * Verify the port number is valid. + */ + if(minor>Console_Port_Count) + { + return RTEMS_INVALID_NUMBER; + } + + /* + * open the port as a termios console driver. + */ + c = Console_Port_Tbl[minor].pDeviceFns; + Callbacks.firstOpen = c->deviceFirstOpen; + Callbacks.lastClose = c->deviceLastClose; + Callbacks.pollRead = c->deviceRead; + Callbacks.write = c->deviceWrite; + Callbacks.setAttributes = c->deviceSetAttributes; + Callbacks.stopRemoteTx = + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx; + Callbacks.startRemoteTx = + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx; + Callbacks.outputUsesInterrupts = c->deviceOutputUsesInterrupts; + status = rtems_termios_open ( major, minor, arg, &Callbacks); + Console_Port_Data[minor].termios_data = args->iop->data1; + + if(minor!=Console_Port_Minor) + { + /* + * If this is not the console we do not want ECHO and + * so forth + */ + IoctlArgs.iop=args->iop; + IoctlArgs.command=RTEMS_IO_GET_ATTRIBUTES; + IoctlArgs.buffer=&Termios; + rtems_termios_ioctl(&IoctlArgs); + Termios.c_lflag=ICANON; + IoctlArgs.command=RTEMS_IO_SET_ATTRIBUTES; + rtems_termios_ioctl(&IoctlArgs); + } + + if((args->iop->flags&LIBIO_FLAGS_READ) && + Console_Port_Tbl[minor].pDeviceFlow && + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx) + { + Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx(minor); + } + + return status; +} + +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_open_close_args_t *args = arg; + + if((args->iop->flags&LIBIO_FLAGS_READ) && + Console_Port_Tbl[minor].pDeviceFlow && + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx) + { + Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx(minor); + } + + return rtems_termios_close (arg); +} + +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_read (arg); +} + +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_write (arg); +} + +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_ioctl (arg); +} + +/* PAGE + * + * console_initialize + * + * Routine called to initialize the console device driver. + */ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + /* + * initialize the termio interface. + */ + rtems_termios_initialize(); + + Console_Port_Count=NUM_CONSOLE_PORTS; + + for(minor=0; + minor<Console_Port_Count; + minor++) + { + /* + * First perform the configuration dependant probe, then the + * device dependant probe + */ + if((!Console_Port_Tbl[minor].deviceProbe || + Console_Port_Tbl[minor].deviceProbe(minor)) && + Console_Port_Tbl[minor].pDeviceFns->deviceProbe(minor)) + { + /* + * Use this device for the console + */ + break; + } + } + if(minor==Console_Port_Count) + { + /* + * Failed to find a working device + */ + rtems_fatal_error_occurred(RTEMS_IO_ERROR); + } + + Console_Port_Minor=minor; + + /* + * Register Device Names + */ + + status = rtems_io_register_name("/dev/console", + major, + Console_Port_Minor ); + if (status != RTEMS_SUCCESSFUL) + { + rtems_fatal_error_occurred(status); + } + if ( Console_Port_Tbl[minor].pDeviceFns->deviceInitialize ) + Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( + Console_Port_Minor); + + for(minor++;minor<Console_Port_Count;minor++) + { + /* + * First perform the configuration dependant probe, then the + * device dependant probe + */ + if((!Console_Port_Tbl[minor].deviceProbe || + Console_Port_Tbl[minor].deviceProbe(minor)) && + Console_Port_Tbl[minor].pDeviceFns->deviceProbe(minor)) + { + status = rtems_io_register_name( + Console_Port_Tbl[minor].sDeviceName, + major, + minor ); + if (status != RTEMS_SUCCESSFUL) + { + rtems_fatal_error_occurred(status); + } + + /* + * Initialize the hardware device. + */ + if ( Console_Port_Tbl[minor].pDeviceFns->deviceInitialize ) + Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( minor); + } + } + + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * DEBUG_puts + * + * This should be safe in the event of an error. It attempts to ensure + * that no TX empty interrupts occur while it is doing polled IO. Then + * it restores the state of that external interrupt. + * + * Input parameters: + * string - pointer to debug output string + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void DEBUG_puts( + char *string +) +{ + char *s; + unsigned32 Irql; + + rtems_interrupt_disable(Irql); + + for ( s = string ; *s ; s++ ) + { + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, *s); + } + + rtems_interrupt_enable(Irql); +} + +/* PAGE + * + * DEBUG_puth + * + * This should be safe in the event of an error. It attempts to ensure + * that no TX empty interrupts occur while it is doing polled IO. Then + * it restores the state of that external interrupt. + * + * Input parameters: + * ulHexNum - value to display + * + * Output parameters: NONE + * + * Return values: NONE + */ +void +DEBUG_puth( + unsigned32 ulHexNum + ) +{ + unsigned long i,d; + unsigned32 Irql; + + rtems_interrupt_disable(Irql); + + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, '0'); + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, 'x'); + + for(i=32;i;) + { + i-=4; + d=(ulHexNum>>i)&0xf; + Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> + deviceWritePolled(Console_Port_Minor, + (d<=9) ? d+'0' : d+'a'-0xa); + } + + rtems_interrupt_enable(Irql); +} + + +/* const char arg to be compatible with BSP_output_char decl. */ +void +debug_putc_onlcr(const char c) +{ + volatile int i; + + /* + * Note: Hack to get printk to work. Depends upon bit + * and silverchip to initialize the port and just + * forces a character to be polled out of com1 + * regardless of where the console is. + */ + + volatile unsigned char *ptr = (void *)0xff800000; + + if ('\n'==c){ + *ptr = '\r'; + asm volatile("sync"); + for (i=0;i<0x0fff;i++); + } + + *ptr = c; + asm volatile("sync"); + for (i=0;i<0x0fff;i++); +} + +BSP_output_char_function_type BSP_output_char = debug_putc_onlcr; +/* const char arg to be compatible with BSP_output_char decl. */ + diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/console.h b/c/src/lib/libbsp/powerpc/ep1a/console/console.h new file mode 100644 index 0000000000..1ea45595bd --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/console.h @@ -0,0 +1,38 @@ +/* + * This file contains the TTY driver table definition for the PPCn_60x + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ +*/ + +#include <rtems/ringbuf.h> +#include <libchip/serial.h> +#include <libchip/ns16550.h> + +extern console_tbl Console_Port_Tbl[]; +extern console_data Console_Port_Data[]; +extern unsigned long Console_Port_Count; + +boolean Console_Port_Tbl_Init_ppc8245(int minor); diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/init68360.c b/c/src/lib/libbsp/powerpc/ep1a/console/init68360.c new file mode 100644 index 0000000000..1bc1be3aad --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/init68360.c @@ -0,0 +1,670 @@ +/* + * MC68360 support routines + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include "m68360.h" + +/* + * Send a command to the CPM RISC processer + */ + +void M360ExecuteRISC( volatile m360_t *m360, rtems_unsigned16 command) +{ + rtems_unsigned16 sr; + + rtems_interrupt_disable(sr); + while (m360->cr & M360_CR_FLG) + continue; + m360->cr = command | M360_CR_FLG; + rtems_interrupt_enable(sr); +} + + +#if 0 +/* + * Initialize MC68360 + */ +void _Init68360 (void) +{ + int i; + m68k_isr_entry *vbr; + unsigned long ramSize; + extern void _CopyDataClearBSSAndStart (unsigned long ramSize); + +#if (defined (__mc68040__)) + /* + ******************************************* + * Motorola 68040 and companion-mode 68360 * + ******************************************* + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x83; /* No more writes, full-power CLKO2 */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT standard M68000 family interrupt level encoding + * CF1MODE=10 (BCLRO* output) + * No RAS1* double drive + * A31 - A28 + * AMUX output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + */ + m360.pepar = 0x3440; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + */ + /* + * 512 addresses per DRAM page (256K DRAM chips) + * 70 nsec DRAM + * 180 nsec ROM (3 wait states) + */ + m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN | + M360_GMR_RCYC(0) | M360_GMR_PGS(1) | + M360_GMR_DPS_32BIT | M360_GMR_NCS | + M360_GMR_TSS40; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_32BIT; + + /* + * Step 12: Initialize the system RAM + */ + /* + * Set up option/base registers + * 1M DRAM + * 70 nsec DRAM + * Enable burst mode + * No parity checking + * Wait for chips to power up + * Perform 8 read cycles + */ + ramSize = 1 * 1024 * 1024; + m360.memc[1].or = M360_MEMC_OR_TCYC(0) | + M360_MEMC_OR_1MB | + M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&_RamBase | + M360_MEMC_BR_BACK40 | + M360_MEMC_BR_V; + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) + *((volatile unsigned long *)(unsigned long)&_RamBase); + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Bus request MC68040 Arbitration ID 3 + * Bus asynchronous timing mode (work around bug in Rev. B) + * Arbitration asynchronous timing mode + * Disable timers during FREEZE + * Disable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear in arbitration ID level 3 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x6000EC3F; + +#elif (defined (M68360_ATLAS_HSB)) + /* + ****************************************** + * Standalone Motorola 68360 -- ATLAS HSB * + ****************************************** + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a CPU32+ reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * RAS1* double drive + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0180; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + */ + m360.gmr = M360_GMR_RCNT(12) | M360_GMR_RFEN | + M360_GMR_RCYC(0) | M360_GMR_PGS(1) | + M360_GMR_DPS_32BIT | M360_GMR_DWQ | + M360_GMR_GAMX; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_8BIT; + + /* + * Step 12: Initialize the system RAM + */ + ramSize = 2 * 1024 * 1024; + /* first bank 1MByte DRAM */ + m360.memc[1].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB | + M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V; + + /* second bank 1MByte DRAM */ + m360.memc[2].or = M360_MEMC_OR_TCYC(2) | M360_MEMC_OR_1MB | + M360_MEMC_OR_PGME | M360_MEMC_OR_DRAM; + m360.memc[2].br = ((unsigned long)&_RamBase + 0x100000) | + M360_MEMC_BR_V; + + /* flash rom socket U6 on CS5 */ + m360.memc[5].br = (unsigned long)ATLASHSB_ROM_U6 | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[5].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB | + M360_MEMC_OR_8BIT; + + /* CSRs on CS7 */ + m360.memc[7].or = M360_MEMC_OR_TCYC(4) | M360_MEMC_OR_64KB | + M360_MEMC_OR_8BIT; + m360.memc[7].br = ATLASHSB_ESR | 0x01; + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) + *((volatile unsigned long *)(unsigned long)&_RamBase); + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + */ + +#elif (defined (GEN68360_WITH_SRAM)) + /* + *************************************************** + * Generic Standalone Motorola 68360 * + * As described in MC68360 User's Manual * + * But uses SRAM instead of DRAM * + * CS0* - 512kx8 flash memory * + * CS1* - 512kx32 static RAM * + * CS2* - 512kx32 static RAM * + *************************************************** + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external oscillator which + * oscillates at the system clock rate. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * IPIPE1* + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0080; + + /* + * Step 11: Set up GMR + * + */ + m360.gmr = 0x0; + + /* + * Step 11a: Remap 512Kx8 flash memory on CS0* + * 2 wait states + * Make it read-only for now + */ + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(2) | M360_MEMC_OR_512KB | + M360_MEMC_OR_8BIT; + /* + * Step 12: Set up main memory + * 512Kx32 SRAM on CS1* + * 512Kx32 SRAM on CS2* + * 0 wait states + */ + ramSize = 4 * 1024 * 1024; + m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V; + m360.memc[1].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB | + M360_MEMC_OR_32BIT; + m360.memc[2].br = ((unsigned long)&_RamBase + 0x200000) | M360_MEMC_BR_V; + m360.memc[2].or = M360_MEMC_OR_WAITS(0) | M360_MEMC_OR_2MB | + M360_MEMC_OR_32BIT; + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear interrupt service level 7 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x4C7F; + +#else + /* + *************************************************** + * Generic Standalone Motorola 68360 * + * As described in MC68360 User's Manual * + * Atlas ACE360 * + *************************************************** + */ + + /* + * Step 6: Is this a power-up reset? + * For now we just ignore this and do *all* the steps + * Someday we might want to: + * if (Hard, Loss of Clock, Power-up) + * Do all steps + * else if (Double bus fault, watchdog or soft reset) + * Skip to step 12 + * else (must be a CPU32+ reset command) + * Skip to step 14 + */ + + /* + * Step 7: Deal with clock synthesizer + * HARDWARE: + * Change if you're not using an external 25 MHz oscillator. + */ + m360.clkocr = 0x8F; /* No more writes, no clock outputs */ + m360.pllcr = 0xD000; /* PLL, no writes, no prescale, + no LPSTOP slowdown, PLL X1 */ + m360.cdvcr = 0x8000; /* No more writes, no clock division */ + + /* + * Step 8: Initialize system protection + * Enable watchdog + * Watchdog causes system reset + * Next-to-slowest watchdog timeout (21 seconds with 25 MHz oscillator) + * Enable double bus fault monitor + * Enable bus monitor for external cycles + * 1024 clocks for external timeout + */ + m360.sypcr = 0xEC; + + /* + * Step 9: Clear parameter RAM and reset communication processor module + */ + for (i = 0 ; i < 192 ; i += sizeof (long)) { + *((long *)((char *)&m360 + 0xC00 + i)) = 0; + *((long *)((char *)&m360 + 0xD00 + i)) = 0; + *((long *)((char *)&m360 + 0xE00 + i)) = 0; + *((long *)((char *)&m360 + 0xF00 + i)) = 0; + } + M360ExecuteRISC (M360_CR_RST); + + /* + * Step 10: Write PEPAR + * SINTOUT not used (CPU32+ mode) + * CF1MODE=00 (CONFIG1 input) + * RAS1* double drive + * WE0* - WE3* + * OE* output + * CAS2* - CAS3* + * CAS0* - CAS1* + * CS7* + * AVEC* + * HARDWARE: + * Change if you are using a different memory configuration + * (static RAM, external address multiplexing, etc). + */ + m360.pepar = 0x0180; + + /* + * Step 11: Remap Chip Select 0 (CS0*), set up GMR + * 32-bit DRAM + * Internal DRAM address multiplexing + * 60 nsec DRAM + * 180 nsec ROM (3 wait states) + * 15.36 usec DRAM refresh interval + * The DRAM page size selection is not modified since this + * startup code may be running in a bootstrap PROM or in + * a program downloaded by the bootstrap PROM. + */ + m360.gmr = (m360.gmr & 0x001C0000) | M360_GMR_RCNT(23) | + M360_GMR_RFEN | M360_GMR_RCYC(0) | + M360_GMR_DPS_32BIT | M360_GMR_NCS | + M360_GMR_GAMX; + m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP | + M360_MEMC_BR_V; + m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_1MB | + M360_MEMC_OR_8BIT; + + /* + * Step 12: Initialize the system RAM + * Do this only if the DRAM has not already been set up + */ + if ((m360.memc[1].br & M360_MEMC_BR_V) == 0) { + /* + * Set up GMR DRAM page size, option and base registers + * Assume 16Mbytes of DRAM + * 60 nsec DRAM + */ + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(5); + m360.memc[1].or = M360_MEMC_OR_TCYC(0) | + M360_MEMC_OR_16MB | + M360_MEMC_OR_DRAM; + m360.memc[1].br = (unsigned long)&_RamBase | M360_MEMC_BR_V; + + /* + * Wait for chips to power up + * Perform 8 read cycles + */ + for (i = 0; i < 50000; i++) + continue; + for (i = 0; i < 8; ++i) + *((volatile unsigned long *)(unsigned long)&_RamBase); + + /* + * Determine memory size (1, 4, or 16 Mbytes) + * Set GMR DRAM page size appropriately. + * The OR is left at 16 Mbytes. The bootstrap PROM places its + * .data and .bss segments at the top of the 16 Mbyte space. + * A 1 Mbyte or 4 Mbyte DRAM will show up several times in + * the memory map, but will work with the same bootstrap PROM. + */ + *(volatile char *)&_RamBase = 0; + *((volatile char *)&_RamBase+0x00C01800) = 1; + if (*(volatile char *)&_RamBase) { + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(1); + } + else { + *((volatile char *)&_RamBase+0x00801000) = 1; + if (*(volatile char *)&_RamBase) { + m360.gmr = (m360.gmr & ~0x001C0000) | M360_GMR_PGS(3); + } + } + + /* + * Enable parity checking + */ + m360.memc[1].br |= M360_MEMC_BR_PAREN; + } + switch (m360.gmr & 0x001C0000) { + default: ramSize = 4 * 1024 * 1024; break; + case M360_GMR_PGS(1): ramSize = 1 * 1024 * 1024; break; + case M360_GMR_PGS(3): ramSize = 4 * 1024 * 1024; break; + case M360_GMR_PGS(5): ramSize = 16 * 1024 * 1024; break; + } + + /* + * Step 13: Copy the exception vector table to system RAM + */ + m68k_get_vbr (vbr); + for (i = 0; i < 256; ++i) + M68Kvec[i] = vbr[i]; + m68k_set_vbr (M68Kvec); + + /* + * Step 14: More system initialization + * SDCR (Serial DMA configuration register) + * Enable SDMA during FREEZE + * Give SDMA priority over all interrupt handlers + * Set DMA arbiration level to 4 + * CICR (CPM interrupt configuration register): + * SCC1 requests at SCCa position + * SCC2 requests at SCCb position + * SCC3 requests at SCCc position + * SCC4 requests at SCCd position + * Interrupt request level 4 + * Maintain original priority order + * Vector base 128 + * SCCs priority grouped at top of table + */ + m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4; + m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) | + (4 << 13) | (0x1F << 8) | (128); + + /* + * Step 15: Set module configuration register + * Disable timers during FREEZE + * Enable bus monitor during FREEZE + * BCLRO* arbitration level 3 + * No show cycles + * User/supervisor access + * Bus clear interrupt service level 7 + * SIM60 interrupt sources higher priority than CPM + */ + m360.mcr = 0x4C7F; +#endif + + /* + * Copy data, clear BSS, switch stacks and call main() + * Must pass ramSize as argument since the data/bss segment + * may be overwritten. + */ + _CopyDataClearBSSAndStart (ramSize); +} +#endif diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/m68360.h b/c/src/lib/libbsp/powerpc/ep1a/console/m68360.h new file mode 100644 index 0000000000..b5c972107a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/m68360.h @@ -0,0 +1,973 @@ +/* + * MOTOROLA MC68360 QUAD INTEGRATED COMMUNICATIONS CONTROLLER (QUICC) + * + * HARDWARE DECLARATIONS + * + * + * Submitted By: + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * 107 North Road + * Saskatoon, Saskatchewan, CANADA + * S7N 5C6 + * + * eric@skatter.usask.ca + * + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __MC68360_h +#define __MC68360_h + +#include "rsPMCQ1.h" + +/* + ************************************************************************* + * REGISTER SUBBLOCKS * + ************************************************************************* + */ + +/* + * Memory controller registers + */ +typedef struct m360MEMCRegisters_ { + uint32_t br; + uint32_t or; + uint32_t _pad[2]; +} m360MEMCRegisters_t; + + +#define M360_GSMR_RFW 0x00000020 +#define M360_GSMR_TDCR_16X 0x00020000 +#define M360_GSMR_RDCR_16X 0x00008000 +#define M360_GSMR_MODE_UART 0x00000004 +#define M360_GSMR_DIAG_LLOOP 0x00000040 +#define M360_GSMR_ENR 0x00000020 +#define M360_GSMR_ENT 0x00000010 + +#define M360_PSMR_FLC 0x8000 +#define M360_PSMR_SL 0x4000 +#define M360_PSMR_CL8 0x3000 +#define M360_PSMR_UM_NORMAL 0x0000 +#define M360_PSMR_FRZ 0x0200 +#define M360_PSMR_RZS 0x0100 +#define M360_PSMR_SYN 0x0080 +#define M360_PSMR_DRT 0x0040 +#define M360_PSMR_PEN 0x0010 +#define M360_PSMR_RPM_ODD 0x0000 +#define M360_PSMR_RPM_LOW 0x0004 +#define M360_PSMR_RPM_EVEN 0x0008 +#define M360_PSMR_RPM_HI 0x000c +#define M360_PSMR_TPM_ODD 0x0000 +#define M360_PSMR_TPM_LOW 0x0001 +#define M360_PSMR_TPM_EVEN 0x0002 +#define M360_PSMR_TPM_HI 0x0003 + +/* + * Serial Communications Controller registers + */ +typedef struct m360SCCRegisters_ { + uint32_t gsmr_l; + uint32_t gsmr_h; + uint16_t psmr; + uint16_t _pad0; + uint16_t todr; + uint16_t dsr; + uint16_t scce; + uint16_t _pad1; + uint16_t sccm; + uint8_t _pad2; + uint8_t sccs; + uint32_t _pad3[2]; +} m360SCCRegisters_t; + +/* + * Serial Management Controller registers + */ +typedef struct m360SMCRegisters_ { + uint16_t _pad0; + uint16_t smcmr; + uint16_t _pad1; + uint8_t smce; + uint8_t _pad2; + uint16_t _pad3; + uint8_t smcm; + uint8_t _pad4; + uint32_t _pad5; +} m360SMCRegisters_t; + + +/* + ************************************************************************* + * Miscellaneous Parameters * + ************************************************************************* + */ +typedef struct m360MiscParms_ { + uint16_t rev_num; + uint16_t _res1; + uint32_t _res2; + uint32_t _res3; +} m360MiscParms_t; + +/* + ************************************************************************* + * RISC Timers * + ************************************************************************* + */ +typedef struct m360TimerParms_ { + uint16_t tm_base; + uint16_t _tm_ptr; + uint16_t _r_tmr; + uint16_t _r_tmv; + uint32_t tm_cmd; + uint32_t tm_cnt; +} m360TimerParms_t; + +/* + * RISC Controller Configuration Register (RCCR) + * All other bits in this register are either reserved or + * used only with a Motorola-supplied RAM microcode packge. + */ +#define M360_RCCR_TIME (1<<15) /* Enable timer */ +#define M360_RCCR_TIMEP(x) ((x)<<8) /* Timer period */ + +/* + * Command register + * Set up this register before issuing a M360_CR_OP_SET_TIMER command. + */ +#define M360_TM_CMD_V (1<<31) /* Set to enable timer */ +#define M360_TM_CMD_R (1<<30) /* Set for automatic restart */ +#define M360_TM_CMD_TIMER(x) ((x)<<16) /* Select timer */ +#define M360_TM_CMD_PERIOD(x) (x) /* Timer period (16 bits) */ + +/* + ************************************************************************* + * DMA Controllers * + ************************************************************************* + */ +typedef struct m360IDMAparms_ { + uint16_t ibase; + uint16_t ibptr; + uint32_t _istate; + uint32_t _itemp; +} m360IDMAparms_t; + +/* + ************************************************************************* + * Serial Communication Controllers * + ************************************************************************* + */ +typedef struct m360SCCparms_ { + uint16_t rbase; + uint16_t tbase; + uint8_t rfcr; + uint8_t tfcr; + uint16_t mrblr; + uint32_t _rstate; + uint32_t _pad0; + uint16_t _rbptr; + uint16_t _pad1; + uint32_t _pad2; + uint32_t _tstate; + uint32_t _pad3; + uint16_t _tbptr; + uint16_t _pad4; + uint32_t _pad5; + uint32_t _rcrc; + uint32_t _tcrc; + union { + struct { + uint32_t _res0; + uint32_t _res1; + uint16_t max_idl; + uint16_t _idlc; + uint16_t brkcr; + uint16_t parec; + uint16_t frmec; + uint16_t nosec; + uint16_t brkec; + uint16_t brklen; + uint16_t uaddr[2]; + uint16_t _rtemp; + uint16_t toseq; + uint16_t character[8]; + uint16_t rccm; + uint16_t rccr; + uint16_t rlbc; + } uart; + struct { + uint32_t crc_p; + uint32_t crc_c; + } transparent; + + } un; +} m360SCCparms_t; + +typedef struct m360SCCENparms_ { + uint16_t rbase; + uint16_t tbase; + uint8_t rfcr; + uint8_t tfcr; + uint16_t mrblr; + uint32_t _rstate; + uint32_t _pad0; + uint16_t _rbptr; + uint16_t _pad1; + uint32_t _pad2; + uint32_t _tstate; + uint32_t _pad3; + uint16_t _tbptr; + uint16_t _pad4; + uint32_t _pad5; + uint32_t _rcrc; + uint32_t _tcrc; + union { + struct { + uint32_t _res0; + uint32_t _res1; + uint16_t max_idl; + uint16_t _idlc; + uint16_t brkcr; + uint16_t parec; + uint16_t frmec; + uint16_t nosec; + uint16_t brkec; + uint16_t brklen; + uint16_t uaddr[2]; + uint16_t _rtemp; + uint16_t toseq; + uint16_t character[8]; + uint16_t rccm; + uint16_t rccr; + uint16_t rlbc; + } uart; + struct { + uint32_t c_pres; + uint32_t c_mask; + uint32_t crcec; + uint32_t alec; + uint32_t disfc; + uint16_t pads; + uint16_t ret_lim; + uint16_t _ret_cnt; + uint16_t mflr; + uint16_t minflr; + uint16_t maxd1; + uint16_t maxd2; + uint16_t _maxd; + uint16_t dma_cnt; + uint16_t _max_b; + uint16_t gaddr1; + uint16_t gaddr2; + uint16_t gaddr3; + uint16_t gaddr4; + uint32_t _tbuf0data0; + uint32_t _tbuf0data1; + uint32_t _tbuf0rba0; + uint32_t _tbuf0crc; + uint16_t _tbuf0bcnt; + uint16_t paddr_h; + uint16_t paddr_m; + uint16_t paddr_l; + uint16_t p_per; + uint16_t _rfbd_ptr; + uint16_t _tfbd_ptr; + uint16_t _tlbd_ptr; + uint32_t _tbuf1data0; + uint32_t _tbuf1data1; + uint32_t _tbuf1rba0; + uint32_t _tbuf1crc; + uint16_t _tbuf1bcnt; + uint16_t _tx_len; + uint16_t iaddr1; + uint16_t iaddr2; + uint16_t iaddr3; + uint16_t iaddr4; + uint16_t _boff_cnt; + uint16_t taddr_h; + uint16_t taddr_m; + uint16_t taddr_l; + } ethernet; + struct { + uint32_t crc_p; + uint32_t crc_c; + } transparent; + } un; +} m360SCCENparms_t; + +/* + * Receive and transmit function code register bits + * These apply to the function code registers of all devices, not just SCC. + */ +#define M360_RFCR_MOT (1<<4) +#define M360_RFCR_DMA_SPACE 0x8 +#define M360_TFCR_MOT (1<<4) +#define M360_TFCR_DMA_SPACE 0x8 + +/* + ************************************************************************* + * Serial Management Controllers * + ************************************************************************* + */ +typedef struct m360SMCparms_ { + uint16_t rbase; + uint16_t tbase; + uint8_t rfcr; + uint8_t tfcr; + uint16_t mrblr; + uint32_t _rstate; + uint32_t _pad0; + uint16_t _rbptr; + uint16_t _pad1; + uint32_t _pad2; + uint32_t _tstate; + uint32_t _pad3; + uint16_t _tbptr; + uint16_t _pad4; + uint32_t _pad5; + union { + struct { + uint16_t max_idl; + uint16_t _pad0; + uint16_t brklen; + uint16_t brkec; + uint16_t brkcr; + uint16_t _r_mask; + } uart; + struct { + uint16_t _pad0[5]; + } transparent; + } un; +} m360SMCparms_t; + +/* + * Mode register + */ +#define M360_SMCMR_CLEN(x) ((x)<<11) /* Character length */ +#define M360_SMCMR_2STOP (1<<10) /* 2 stop bits */ +#define M360_SMCMR_PARITY (1<<9) /* Enable parity */ +#define M360_SMCMR_EVEN (1<<8) /* Even parity */ +#define M360_SMCMR_SM_GCI (0<<4) /* GCI Mode */ +#define M360_SMCMR_SM_UART (2<<4) /* UART Mode */ +#define M360_SMCMR_SM_TRANSPARENT (3<<4) /* Transparent Mode */ +#define M360_SMCMR_DM_LOOPBACK (1<<2) /* Local loopback mode */ +#define M360_SMCMR_DM_ECHO (2<<2) /* Echo mode */ +#define M360_SMCMR_TEN (1<<1) /* Enable transmitter */ +#define M360_SMCMR_REN (1<<0) /* Enable receiver */ + +/* + * Event and mask registers (SMCE, SMCM) + */ +#define M360_SMCE_BRK (1<<4) +#define M360_SMCE_BSY (1<<2) +#define M360_SMCE_TX (1<<1) +#define M360_SMCE_RX (1<<0) + +/* + ************************************************************************* + * Serial Peripheral Interface * + ************************************************************************* + */ +typedef struct m360SPIparms_ { + uint16_t rbase; + uint16_t tbase; + uint8_t rfcr; + uint8_t tfcr; + uint16_t mrblr; + uint32_t _rstate; + uint32_t _pad0; + uint16_t _rbptr; + uint16_t _pad1; + uint32_t _pad2; + uint32_t _tstate; + uint32_t _pad3; + uint16_t _tbptr; + uint16_t _pad4; + uint32_t _pad5; +} m360SPIparms_t; + +/* + * Mode register (SPMODE) + */ +#define M360_SPMODE_LOOP (1<<14) /* Local loopback mode */ +#define M360_SPMODE_CI (1<<13) /* Clock invert */ +#define M360_SPMODE_CP (1<<12) /* Clock phase */ +#define M360_SPMODE_DIV16 (1<<11) /* Divide BRGCLK by 16 */ +#define M360_SPMODE_REV (1<<10) /* Reverse data */ +#define M360_SPMODE_MASTER (1<<9) /* SPI is master */ +#define M360_SPMODE_EN (1<<8) /* Enable SPI */ +#define M360_SPMODE_CLEN(x) ((x)<<4) /* Character length */ +#define M360_SPMODE_PM(x) (x) /* Prescaler modulus */ + +/* + * Mode register (SPCOM) + */ +#define M360_SPCOM_STR (1<<7) /* Start transmit */ + +/* + * Event and mask registers (SPIE, SPIM) + */ +#define M360_SPIE_MME (1<<5) /* Multi-master error */ +#define M360_SPIE_TXE (1<<4) /* Tx error */ +#define M360_SPIE_BSY (1<<2) /* Busy condition*/ +#define M360_SPIE_TXB (1<<1) /* Tx buffer */ +#define M360_SPIE_RXB (1<<0) /* Rx buffer */ + +/* + ************************************************************************* + * SDMA (SCC, SMC, SPI) Buffer Descriptors * + ************************************************************************* + */ +typedef struct m360BufferDescriptor_ { + uint16_t status; + uint16_t length; + uint32_t buffer; /* this is a void * to the 360 */ +} m360BufferDescriptor_t; + +/* + * Bits in receive buffer descriptor status word + */ +#define M360_BD_EMPTY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */ +#define M360_BD_WRAP (1<<13) /* Ethernet, SCC UART, SMC UART, SPI */ +#define M360_BD_INTERRUPT (1<<12) /* Ethernet, SCC UART, SMC UART, SPI */ +#define M360_BD_LAST (1<<11) /* Ethernet, SPI */ +#define M360_BD_CONTROL_CHAR (1<<11) /* SCC UART */ +#define M360_BD_FIRST_IN_FRAME (1<<10) /* Ethernet */ +#define M360_BD_ADDRESS (1<<10) /* SCC UART */ +#define M360_BD_CONTINUOUS (1<<9) /* SCC UART, SMC UART, SPI */ +#define M360_BD_MISS (1<<8) /* Ethernet */ +#define M360_BD_IDLE (1<<8) /* SCC UART, SMC UART */ +#define M360_BD_ADDRSS_MATCH (1<<7) /* SCC UART */ +#define M360_BD_LONG (1<<5) /* Ethernet */ +#define M360_BD_BREAK (1<<5) /* SCC UART, SMC UART */ +#define M360_BD_NONALIGNED (1<<4) /* Ethernet */ +#define M360_BD_FRAMING_ERROR (1<<4) /* SCC UART, SMC UART */ +#define M360_BD_SHORT (1<<3) /* Ethernet */ +#define M360_BD_PARITY_ERROR (1<<3) /* SCC UART, SMC UART */ +#define M360_BD_CRC_ERROR (1<<2) /* Ethernet */ +#define M360_BD_OVERRUN (1<<1) /* Ethernet, SCC UART, SMC UART, SPI */ +#define M360_BD_COLLISION (1<<0) /* Ethernet */ +#define M360_BD_CARRIER_LOST (1<<0) /* SCC UART */ +#define M360_BD_MASTER_ERROR (1<<0) /* SPI */ + +/* + * Bits in transmit buffer descriptor status word + * Many bits have the same meaning as those in receiver buffer descriptors. + */ +#define M360_BD_READY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */ +#define M360_BD_PAD (1<<14) /* Ethernet */ +#define M360_BD_CTS_REPORT (1<<11) /* SCC UART */ +#define M360_BD_TX_CRC (1<<10) /* Ethernet */ +#define M360_BD_DEFER (1<<9) /* Ethernet */ +#define M360_BD_HEARTBEAT (1<<8) /* Ethernet */ +#define M360_BD_PREAMBLE (1<<8) /* SCC UART, SMC UART */ +#define M360_BD_LATE_COLLISION (1<<7) /* Ethernet */ +#define M360_BD_NO_STOP_BIT (1<<7) /* SCC UART */ +#define M360_BD_RETRY_LIMIT (1<<6) /* Ethernet */ +#define M360_BD_RETRY_COUNT(x) (((x)&0x3C)>>2) /* Ethernet */ +#define M360_BD_UNDERRUN (1<<1) /* Ethernet, SPI */ +#define M360_BD_CARRIER_LOST (1<<0) /* Ethernet */ +#define M360_BD_CTS_LOST (1<<0) /* SCC UART */ + +/* + ************************************************************************* + * IDMA Buffer Descriptors * + ************************************************************************* + */ +typedef struct m360IDMABufferDescriptor_ { + uint16_t status; + uint16_t _pad; + uint32_t length; + void *source; + void *destination; +} m360IDMABufferDescriptor_t; + +/* + ************************************************************************* + * RISC Communication Processor Module Command Register (CR) * + ************************************************************************* + */ +#define M360_CR_RST (1<<15) /* Reset communication processor */ +#define M360_CR_OP_INIT_RX_TX (0<<8) /* SCC, SMC UART, SMC GCI, SPI */ +#define M360_CR_OP_INIT_RX (1<<8) /* SCC, SMC UART, SPI */ +#define M360_CR_OP_INIT_TX (2<<8) /* SCC, SMC UART, SPI */ +#define M360_CR_OP_INIT_HUNT (3<<8) /* SCC, SMC UART */ +#define M360_CR_OP_STOP_TX (4<<8) /* SCC, SMC UART */ +#define M360_CR_OP_GR_STOP_TX (5<<8) /* SCC */ +#define M360_CR_OP_INIT_IDMA (5<<8) /* IDMA */ +#define M360_CR_OP_RESTART_TX (6<<8) /* SCC, SMC UART */ +#define M360_CR_OP_CLOSE_RX_BD (7<<8) /* SCC, SMC UART, SPI */ +#define M360_CR_OP_SET_GRP_ADDR (8<<8) /* SCC */ +#define M360_CR_OP_SET_TIMER (8<<8) /* Timer */ +#define M360_CR_OP_GCI_TIMEOUT (9<<8) /* SMC GCI */ +#define M360_CR_OP_RESERT_BCS (10<<8) /* SCC */ +#define M360_CR_OP_GCI_ABORT (10<<8) /* SMC GCI */ +#define M360_CR_CHAN_SCC1 (0<<4) /* Channel selection */ +#define M360_CR_CHAN_SCC2 (4<<4) +#define M360_CR_CHAN_SPI (5<<4) +#define M360_CR_CHAN_TIMER (5<<4) +#define M360_CR_CHAN_SCC3 (8<<4) +#define M360_CR_CHAN_SMC1 (9<<4) +#define M360_CR_CHAN_IDMA1 (9<<4) +#define M360_CR_CHAN_SCC4 (12<<4) +#define M360_CR_CHAN_SMC2 (13<<4) +#define M360_CR_CHAN_IDMA2 (13<<4) +#define M360_CR_FLG (1<<0) /* Command flag */ + +/* + ************************************************************************* + * System Protection Control Register (SYPCR) * + ************************************************************************* + */ +#define M360_SYPCR_SWE (1<<7) /* Software watchdog enable */ +#define M360_SYPCR_SWRI (1<<6) /* Software watchdog reset select */ +#define M360_SYPCR_SWT1 (1<<5) /* Software watchdog timing bit 1 */ +#define M360_SYPCR_SWT0 (1<<4) /* Software watchdog timing bit 0 */ +#define M360_SYPCR_DBFE (1<<3) /* Double bus fault monitor enable */ +#define M360_SYPCR_BME (1<<2) /* Bus monitor external enable */ +#define M360_SYPCR_BMT1 (1<<1) /* Bus monitor timing bit 1 */ +#define M360_SYPCR_BMT0 (1<<0) /* Bus monitor timing bit 0 */ + +/* + ************************************************************************* + * Memory Control Registers * + ************************************************************************* + */ +#define M360_GMR_RCNT(x) ((x)<<24) /* Refresh count */ +#define M360_GMR_RFEN (1<<23) /* Refresh enable */ +#define M360_GMR_RCYC(x) ((x)<<21) /* Refresh cycle length */ +#define M360_GMR_PGS(x) ((x)<<18) /* Page size */ +#define M360_GMR_DPS_32BIT (0<<16) /* DRAM port size */ +#define M360_GMR_DPS_16BIT (1<<16) +#define M360_GMR_DPS_8BIT (2<<16) +#define M360_GMR_DPS_DSACK (3<<16) +#define M360_GMR_WBT40 (1<<15) /* Wait between 040 transfers */ +#define M360_GMR_WBTQ (1<<14) /* Wait between 360 transfers */ +#define M360_GMR_SYNC (1<<13) /* Synchronous external access */ +#define M360_GMR_EMWS (1<<12) /* External master wait state */ +#define M360_GMR_OPAR (1<<11) /* Odd parity */ +#define M360_GMR_PBEE (1<<10) /* Parity bus error enable */ +#define M360_GMR_TSS40 (1<<9) /* TS* sample for 040 */ +#define M360_GMR_NCS (1<<8) /* No CPU space */ +#define M360_GMR_DWQ (1<<7) /* Delay write for 360 */ +#define M360_GMR_DW40 (1<<6) /* Delay write for 040 */ +#define M360_GMR_GAMX (1<<5) /* Global address mux enable */ + +#define M360_MEMC_BR_FC(x) ((x)<<7) /* Function code limit */ +#define M360_MEMC_BR_TRLXQ (1<<6) /* Relax timing requirements */ +#define M360_MEMC_BR_BACK40 (1<<5) /* Burst acknowledge to 040 */ +#define M360_MEMC_BR_CSNT40 (1<<4) /* CS* negate timing for 040 */ +#define M360_MEMC_BR_CSNTQ (1<<3) /* CS* negate timing for 360 */ +#define M360_MEMC_BR_PAREN (1<<2) /* Enable parity checking */ +#define M360_MEMC_BR_WP (1<<1) /* Write Protect */ +#define M360_MEMC_BR_V (1<<0) /* Base/Option register are valid */ + +#define M360_MEMC_OR_TCYC(x) ((x)<<28) /* Cycle length (clocks) */ +#define M360_MEMC_OR_WAITS(x) M360_MEMC_OR_TCYC((x)+1) +#define M360_MEMC_OR_2KB 0x0FFFF800 /* Address range */ +#define M360_MEMC_OR_4KB 0x0FFFF000 +#define M360_MEMC_OR_8KB 0x0FFFE000 +#define M360_MEMC_OR_16KB 0x0FFFC000 +#define M360_MEMC_OR_32KB 0x0FFF8000 +#define M360_MEMC_OR_64KB 0x0FFF0000 +#define M360_MEMC_OR_128KB 0x0FFE0000 +#define M360_MEMC_OR_256KB 0x0FFC0000 +#define M360_MEMC_OR_512KB 0x0FF80000 +#define M360_MEMC_OR_1MB 0x0FF00000 +#define M360_MEMC_OR_2MB 0x0FE00000 +#define M360_MEMC_OR_4MB 0x0FC00000 +#define M360_MEMC_OR_8MB 0x0F800000 +#define M360_MEMC_OR_16MB 0x0F000000 +#define M360_MEMC_OR_32MB 0x0E000000 +#define M360_MEMC_OR_64MB 0x0C000000 +#define M360_MEMC_OR_128MB 0x08000000 +#define M360_MEMC_OR_256MB 0x00000000 +#define M360_MEMC_OR_FCMC(x) ((x)<<7) /* Function code mask */ +#define M360_MEMC_OR_BCYC(x) ((x)<<5) /* Burst cycle length (clocks) */ +#define M360_MEMC_OR_PGME (1<<3) /* Page mode enable */ +#define M360_MEMC_OR_32BIT (0<<1) /* Port size */ +#define M360_MEMC_OR_16BIT (1<<1) +#define M360_MEMC_OR_8BIT (2<<1) +#define M360_MEMC_OR_DSACK (3<<1) +#define M360_MEMC_OR_DRAM (1<<0) /* Dynamic RAM select */ + +/* + ************************************************************************* + * SI Mode Register (SIMODE) * + ************************************************************************* + */ +#define M360_SI_SMC2_BITS 0xFFFF0000 /* All SMC2 bits */ +#define M360_SI_SMC2_TDM (1<<31) /* Multiplexed SMC2 */ +#define M360_SI_SMC2_BRG1 (0<<28) /* SMC2 clock souce */ +#define M360_SI_SMC2_BRG2 (1<<28) +#define M360_SI_SMC2_BRG3 (2<<28) +#define M360_SI_SMC2_BRG4 (3<<28) +#define M360_SI_SMC2_CLK5 (0<<28) +#define M360_SI_SMC2_CLK6 (1<<28) +#define M360_SI_SMC2_CLK7 (2<<28) +#define M360_SI_SMC2_CLK8 (3<<28) +#define M360_SI_SMC1_BITS 0x0000FFFF /* All SMC1 bits */ +#define M360_SI_SMC1_TDM (1<<15) /* Multiplexed SMC1 */ +#define M360_SI_SMC1_BRG1 (0<<12) /* SMC1 clock souce */ +#define M360_SI_SMC1_BRG2 (1<<12) +#define M360_SI_SMC1_BRG3 (2<<12) +#define M360_SI_SMC1_BRG4 (3<<12) +#define M360_SI_SMC1_CLK1 (0<<12) +#define M360_SI_SMC1_CLK2 (1<<12) +#define M360_SI_SMC1_CLK3 (2<<12) +#define M360_SI_SMC1_CLK4 (3<<12) + +/* + ************************************************************************* + * SDMA Configuration Register (SDMA) * + ************************************************************************* + */ +#define M360_SDMA_FREEZE (2<<13) /* Freeze on next bus cycle */ +#define M360_SDMA_SISM_7 (7<<8) /* Normal interrupt service mask */ +#define M360_SDMA_SAID_4 (4<<4) /* Normal arbitration ID */ +#define M360_SDMA_INTE (1<<1) /* SBER interrupt enable */ +#define M360_SDMA_INTB (1<<0) /* SBKP interrupt enable */ + +/* + ************************************************************************* + * Baud (sic) Rate Generators * + ************************************************************************* + */ +#define M360_BRG_RST (1<<17) /* Reset generator */ +#define M360_BRG_EN (1<<16) /* Enable generator */ +#define M360_BRG_EXTC_BRGCLK (0<<14) /* Source is BRGCLK */ +#define M360_BRG_EXTC_CLK2 (1<<14) /* Source is CLK2 pin */ +#define M360_BRG_EXTC_CLK6 (2<<14) /* Source is CLK6 pin */ +#define M360_BRG_ATB (1<<13) /* Autobaud */ +#define M360_BRG_115200 (13<<1) /* Assume 25 MHz clock */ +#define M360_BRG_57600 (26<<1) +#define M360_BRG_38400 (40<<1) +#define M360_BRG_19200 (80<<1) +#define M360_BRG_9600 (162<<1) +#define M360_BRG_4800 (324<<1) +#define M360_BRG_2400 (650<<1) +#define M360_BRG_1200 (1301<<1) +#define M360_BRG_600 (2603<<1) +#define M360_BRG_300 ((324<<1) | 1) +#define M360_BRG_150 ((650<<1) | 1) +#define M360_BRG_75 ((1301<<1) | 1) + +/* + ************************************************************************* + * sccm Bit Settings * + ************************************************************************* + */ +#define M360_SCCE_TX 0x02 +#define M360_SCCE_RX 0x01 + +#define M360_CR_INIT_TX_RX_PARAMS 0x0000 +#define M360_CR_CH_NUM 0x0040 + +#define M360_NUM_DPRAM_REAGONS 4 +/* + ************************************************************************* + * MC68360 DUAL-PORT RAM AND REGISTERS * + ************************************************************************* + */ +typedef struct m360_ { + /* + * Dual-port RAM + */ + volatile uint8_t dpram0[0x400]; /* Microcode program */ + volatile uint8_t dpram1[0x200]; + volatile uint8_t dpram2[0x100]; /* Microcode scratch */ + volatile uint8_t dpram3[0x100]; /* Not on REV A or B masks */ + volatile uint8_t _rsv0[0xC00-0x800]; + volatile m360SCCENparms_t scc1p; + volatile uint8_t _rsv1[0xCB0-0xC00-sizeof(m360SCCENparms_t)]; + volatile m360MiscParms_t miscp; + volatile uint8_t _rsv2[0xD00-0xCB0-sizeof(m360MiscParms_t)]; + volatile m360SCCparms_t scc2p; + volatile uint8_t _rsv3[0xD80-0xD00-sizeof(m360SCCparms_t)]; + volatile m360SPIparms_t spip; + volatile uint8_t _rsv4[0xDB0-0xD80-sizeof(m360SPIparms_t)]; + volatile m360TimerParms_t tmp; + volatile uint8_t _rsv5[0xE00-0xDB0-sizeof(m360TimerParms_t)]; + volatile m360SCCparms_t scc3p; + volatile uint8_t _rsv6[0xE70-0xE00-sizeof(m360SCCparms_t)]; + volatile m360IDMAparms_t idma1p; + volatile uint8_t _rsv7[0xE80-0xE70-sizeof(m360IDMAparms_t)]; + volatile m360SMCparms_t smc1p; + volatile uint8_t _rsv8[0xF00-0xE80-sizeof(m360SMCparms_t)]; + volatile m360SCCparms_t scc4p; + volatile uint8_t _rsv9[0xF70-0xF00-sizeof(m360SCCparms_t)]; + volatile m360IDMAparms_t idma2p; + volatile uint8_t _rsv10[0xF80-0xF70-sizeof(m360IDMAparms_t)]; + volatile m360SMCparms_t smc2p; + volatile uint8_t _rsv11[0x1000-0xF80-sizeof(m360SMCparms_t)]; + + /* + * SIM Block + */ + volatile uint32_t mcr; + volatile uint32_t _pad00; + volatile uint8_t avr; + volatile uint8_t rsr; + volatile uint16_t _pad01; + volatile uint8_t clkocr; + volatile uint8_t _pad02; + volatile uint16_t _pad03; + volatile uint16_t pllcr; + volatile uint16_t _pad04; + volatile uint16_t cdvcr; + volatile uint16_t pepar; + volatile uint32_t _pad05[2]; + volatile uint16_t _pad06; + volatile uint8_t sypcr; + volatile uint8_t swiv; + volatile uint16_t _pad07; + volatile uint16_t picr; + volatile uint16_t _pad08; + volatile uint16_t pitr; + volatile uint16_t _pad09; + volatile uint8_t _pad10; + volatile uint8_t swsr; + volatile uint32_t bkar; + volatile uint32_t bcar; + volatile uint32_t _pad11[2]; + + /* + * MEMC Block + */ + volatile uint32_t gmr; + volatile uint16_t mstat; + volatile uint16_t _pad12; + volatile uint32_t _pad13[2]; + volatile m360MEMCRegisters_t memc[8]; + volatile uint8_t _pad14[0xF0-0xD0]; + volatile uint8_t _pad15[0x100-0xF0]; + volatile uint8_t _pad16[0x500-0x100]; + + /* + * IDMA1 Block + */ + volatile uint16_t iccr; + volatile uint16_t _pad17; + volatile uint16_t cmr1; + volatile uint16_t _pad18; + volatile uint32_t sapr1; + volatile uint32_t dapr1; + volatile uint32_t bcr1; + volatile uint8_t fcr1; + volatile uint8_t _pad19; + volatile uint8_t cmar1; + volatile uint8_t _pad20; + volatile uint8_t csr1; + volatile uint8_t _pad21; + volatile uint16_t _pad22; + + /* + * SDMA Block + */ + volatile uint8_t sdsr; + volatile uint8_t _pad23; + volatile uint16_t sdcr; + volatile uint32_t sdar; + + /* + * IDMA2 Block + */ + volatile uint16_t _pad24; + volatile uint16_t cmr2; + volatile uint32_t sapr2; + volatile uint32_t dapr2; + volatile uint32_t bcr2; + volatile uint8_t fcr2; + volatile uint8_t _pad26; + volatile uint8_t cmar2; + volatile uint8_t _pad27; + volatile uint8_t csr2; + volatile uint8_t _pad28; + volatile uint16_t _pad29; + volatile uint32_t _pad30; + + /* + * CPIC Block + */ + volatile uint32_t cicr; + volatile uint32_t cipr; + volatile uint32_t cimr; + volatile uint32_t cisr; + + /* + * Parallel I/O Block + */ + volatile uint16_t padir; + volatile uint16_t papar; + volatile uint16_t paodr; + volatile uint16_t padat; + volatile uint32_t _pad31[2]; + volatile uint16_t pcdir; + volatile uint16_t pcpar; + volatile uint16_t pcso; + volatile uint16_t pcdat; + volatile uint16_t pcint; + volatile uint16_t _pad32; + volatile uint32_t _pad33[5]; + + /* + * TIMER Block + */ + volatile uint16_t tgcr; + volatile uint16_t _pad34; + volatile uint32_t _pad35[3]; + volatile uint16_t tmr1; + volatile uint16_t tmr2; + volatile uint16_t trr1; + volatile uint16_t trr2; + volatile uint16_t tcr1; + volatile uint16_t tcr2; + volatile uint16_t tcn1; + volatile uint16_t tcn2; + volatile uint16_t tmr3; + volatile uint16_t tmr4; + volatile uint16_t trr3; + volatile uint16_t trr4; + volatile uint16_t tcr3; + volatile uint16_t tcr4; + volatile uint16_t tcn3; + volatile uint16_t tcn4; + volatile uint16_t ter1; + volatile uint16_t ter2; + volatile uint16_t ter3; + volatile uint16_t ter4; + volatile uint32_t _pad36[2]; + + /* + * CP Block + */ + volatile uint16_t cr; + volatile uint16_t _pad37; + volatile uint16_t rccr; + volatile uint16_t _pad38; + volatile uint32_t _pad39[3]; + volatile uint16_t _pad40; + volatile uint16_t rter; + volatile uint16_t _pad41; + volatile uint16_t rtmr; + volatile uint32_t _pad42[5]; + + /* + * BRG Block + */ + volatile uint32_t brgc1; + volatile uint32_t brgc2; + volatile uint32_t brgc3; + volatile uint32_t brgc4; + + /* + * SCC Block + */ + volatile m360SCCRegisters_t scc1; + volatile m360SCCRegisters_t scc2; + volatile m360SCCRegisters_t scc3; + volatile m360SCCRegisters_t scc4; + + /* + * SMC Block + */ + volatile m360SMCRegisters_t smc1; + volatile m360SMCRegisters_t smc2; + + /* + * SPI Block + */ + volatile uint16_t spmode; + volatile uint16_t _pad43[2]; + volatile uint8_t spie; + volatile uint8_t _pad44; + volatile uint16_t _pad45; + volatile uint8_t spim; + volatile uint8_t _pad46[2]; + volatile uint8_t spcom; + volatile uint16_t _pad47[2]; + + /* + * PIP Block + */ + volatile uint16_t pipc; + volatile uint16_t _pad48; + volatile uint16_t ptpr; + volatile uint32_t pbdir; + volatile uint32_t pbpar; + volatile uint16_t _pad49; + volatile uint16_t pbodr; + volatile uint32_t pbdat; + volatile uint32_t _pad50[6]; + + /* + * SI Block + */ + volatile uint32_t simode; + volatile uint8_t sigmr; + volatile uint8_t _pad51; + volatile uint8_t sistr; + volatile uint8_t sicmr; + volatile uint32_t _pad52; + volatile uint32_t sicr; + volatile uint16_t _pad53; + volatile uint16_t sirp[2]; + volatile uint16_t _pad54; + volatile uint32_t _pad55[2]; + volatile uint8_t siram[256]; +} m360_t; + +struct bdregions_t { + char *base; + unsigned int size; + unsigned int used; +}; + +#define M68360_RX_BUF_SIZE 1 +#define M68360_TX_BUF_SIZE 0x100 + +struct _m68360_per_chip; +typedef struct _m68360_per_chip *M68360_t; + +typedef struct _m68360_per_port { + uint32_t channel; + M68360_t chip; + volatile uint32_t *pBRGC; /* m360->brgc# */ + volatile m360SCCparms_t *pSCCB; /* m360->scc#p */ + volatile m360SCCRegisters_t *pSCCR; /* m360->scc# */ + uint32_t baud; + int minor; + volatile uint8_t *rxBuf; + volatile uint8_t *txBuf; + volatile m360BufferDescriptor_t *sccRxBd; + volatile m360BufferDescriptor_t *sccTxBd; +}m68360_per_port_t, *M68360_serial_ports_t; + +typedef struct _m68360_per_chip { + struct _m68360_per_chip *next; + struct bdregions_t bdregions[4]; + volatile m360_t *m360; /* Pointer to base Address */ + int m360_interrupt; + int m360_clock_rate; + PPMCQ1BoardData board_data; + m68360_per_port_t port[4]; +} m68360_per_chip_t; + +extern M68360_t M68360_chips; + +void M360SetupMemory( M68360_t ptr ); +void *M360AllocateBufferDescriptors (M68360_t ptr, int count); +void M360ExecuteRISC( volatile m360_t *m360, uint16_t command); +int mc68360_scc_create_chip( PPMCQ1BoardData BoardData, uint8_t int_vector ); + +#endif /* __MC68360_h */ diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c b/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c new file mode 100644 index 0000000000..773f85b93a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c @@ -0,0 +1,836 @@ +/* This file contains the termios TTY driver for the Motorola MC68360 SCC ports. + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include <stdio.h> +#include <termios.h> +#include <bsp.h> +#include <libcpu/io.h> +#include <rtems/libio.h> +#include <bsp/pci.h> +#include <bsp/irq.h> +#include <libchip/serial.h> +#include "m68360.h" +#include <libchip/sersupp.h> +#include <stdlib.h> +#include <rtems/bspIo.h> +#include <string.h> + +#define MC68360_LENGHT_SIZE 100 +int mc68360_length_array[ MC68360_LENGHT_SIZE ]; +int mc68360_length_count=0; + +void mc68360_Show_length_array() { + int i; + for (i=0; i<MC68360_LENGHT_SIZE; i++) + printf(" %d", mc68360_length_array[i] ); + printf("\n\n"); +} + +M68360_t M68360_chips = NULL; + +#define SYNC eieio + +void mc68360_scc_nullFunc() {} + +uint8_t scc_read8( + const char *name, + volatile uint8_t *address +) +{ + uint8_t value; + +#ifdef DEBUG_360 + printk( "RD8 %s 0x%08x ", name, address ); +#endif + value = *address; +#ifdef DEBUG_360 + printk( "0x%02x\n", value ); +#endif + + return value; +} + +void scc_write8( + const char *name, + volatile uint8_t *address, + uint8_t value +) +{ +#ifdef DEBUG_360 + printk( "WR8 %s 0x%08x 0x%02x\n", name, address, value ); +#endif + *address = value; +} + + +uint16_t scc_read16( + const char *name, + volatile uint16_t *address +) +{ + uint16_t value; + +#ifdef DEBUG_360 + printk( "RD16 %s 0x%08x ", name, address ); +#endif + value = *address; +#ifdef DEBUG_360 + printk( "0x%04x\n", value ); +#endif + + return value; +} + +void scc_write16( + const char *name, + volatile uint16_t *address, + uint16_t value +) +{ +#ifdef DEBUG_360 + printk( "WR16 %s 0x%08x 0x%04x\n", name, address, value ); +#endif + *address = value; +} + + +uint32_t scc_read32( + const char *name, + volatile uint32_t *address +) +{ + uint32_t value; + +#ifdef DEBUG_360 + printk( "RD32 %s 0x%08x ", name, address ); +#endif + value = *address; +#ifdef DEBUG_360 + printk( "0x%08x\n", value ); +#endif + + return value; +} + +void scc_write32( + const char *name, + volatile uint32_t *address, + uint32_t value +) +{ +#ifdef DEBUG_360 + printk( "WR32 %s 0x%08x 0x%08x\n", name, address, value ); +#endif + *address = value; +} + +void mc68360_sccShow_Regs(int minor){ + M68360_serial_ports_t ptr; + ptr = Console_Port_Tbl[minor].pDeviceParams; + + printk( "scce 0x%08x", &ptr->pSCCR->scce ); + printk( " 0x%04x\n", ptr->pSCCR->scce ); + +} + +#define TX_BUFFER_ADDRESS( _ptr ) \ + ((char *)ptr->txBuf - (char *)ptr->chip->board_data->baseaddr) +#define RX_BUFFER_ADDRESS( _ptr ) \ + ((char *)ptr->rxBuf - (char *)ptr->chip->board_data->baseaddr) + + +/************************************************************************** + * Function: mc68360_sccBRGC * + ************************************************************************** + * Description: * + * * + * This function is called to compute the divisor register values for * + * a given baud rate. * + * * + * * + * Inputs: * + * * + * int baud - Baud rate (in bps). * + * * + * Output: * + * * + * int - baud rate generator configuration. * + * * + **************************************************************************/ +static int +mc68360_sccBRGC(int baud, int m360_clock_rate) +{ + int data; + + /* + * configure baud rate generator for 16x bit rate, where..... + * b = desired baud rate + * clk = system clock (33mhz) + * d = clock dividor value + * + * for b > 300 : d = clk/(b*16) + * for b<= 300 : d = (clk/ (b*16*16))-1) + */ + + SYNC(); + if( baud > 300 ) data = 33333333 / (baud * 16 ); + else data = (33333333 / (baud * 16 * 16) ) - 1; + data *= 2; + data &= 0x00001ffe ; + + /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */ + data |= ((baud>300)? 0 : 1 ) ; + data |= 0x010000 ; + + return data; +} + + +/************************************************************************** + * Function: sccInterruptHandler * + ************************************************************************** + * Description: * + * * + * This is the interrupt service routine for the console UART. It * + * handles both receive and transmit interrupts. The bulk of the * + * work is done by termios. * + * * + * Inputs: * + * * + * chip - structure of chip specific information * + * * + * Output: * + * * + * none * + * * + **************************************************************************/ +void mc68360_sccInterruptHandler( rtems_irq_hdl_param handle ) +{ + volatile m360_t *m360; + int port; + uint16_t status; + uint16_t length; + int i; + char data; + int clear_isr; + M68360_t chip = (M68360_t)handle; + + for (port=0; port<4; port++) { + + clear_isr = FALSE; + m360 = chip->m360; + + /* + * Handle a RX interrupt. + */ + if ( scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x1) + { + clear_isr = TRUE; + scc_write16("scce", &chip->port[port].pSCCR->scce, 0x1 ); + status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status); + while ((status & M360_BD_EMPTY) == 0) + { + length= scc_read16("sccRxBd->length",&chip->port[port].sccRxBd->length); + for (i=0;i<length;i++) { + data= chip->port[port].rxBuf[i]; + rtems_termios_enqueue_raw_characters( + Console_Port_Data[ chip->port[port].minor ].termios_data, + &data, + 1); + } + scc_write16( "sccRxBd->status", &chip->port[port].sccRxBd->status, + M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT ); + status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status); + } + } + + /* + * Handle a TX interrupt. + */ + if (scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x2) + { + clear_isr = TRUE; + scc_write16("scce", &chip->port[port].pSCCR->scce, 0x2); + status = scc_read16("sccTxBd->status", &chip->port[port].sccTxBd->status); + if ((status & M360_BD_EMPTY) == 0) + { + scc_write16("sccTxBd->status",&chip->port[port].sccTxBd->status,0); + rtems_termios_dequeue_characters( + Console_Port_Data[chip->port[port].minor].termios_data, + chip->port[port].sccTxBd->length); + } + } + + /* + * Clear SCC interrupt-in-service bit. + */ + if ( clear_isr ) + scc_write32( "cisr", &m360->cisr, (0x80000000 >> chip->port[port].channel) ); + } +} + +/* + * mc68360_scc_open + * + * This function opens a port for communication. + * + * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. + */ + +int mc68360_scc_open( + int major, + int minor, + void * arg +) +{ + + return RTEMS_SUCCESSFUL; +} + +/* + * mc68360_scc_initialize_interrupts + * + * This routine initializes the console's receive and transmit + * ring buffers and loads the appropriate vectors to handle the interrupts. + */ + +void mc68360_scc_initialize_interrupts(int minor) +{ + M68360_serial_ports_t ptr; + volatile m360_t *m360; + uint32_t data; + uint32_t buffers_start; + uint32_t tmp_u32; + +#ifdef DEBUG_360 + printk("mc68360_scc_initialize_interrupts: minor %d\n", minor ); + printk("Console_Port_Tbl[minor].pDeviceParams 0x%08x\n", + Console_Port_Tbl[minor].pDeviceParams ); +#endif + + ptr = Console_Port_Tbl[minor].pDeviceParams; + m360 = ptr->chip->m360; +#ifdef DEBUG_360 + printk("m360 0x%08x baseaddr 0x%08x\n", + m360, ptr->chip->board_data->baseaddr); +#endif + + buffers_start = ptr->chip->board_data->baseaddr + 0x00200000 + + ( (M68360_RX_BUF_SIZE + M68360_TX_BUF_SIZE) * (ptr->channel-1)); + ptr->rxBuf = (uint8_t *) buffers_start; + ptr->txBuf = (uint8_t *)(buffers_start + M68360_RX_BUF_SIZE); +#ifdef DEBUG_360 + printk("rxBuf 0x%08x txBuf 0x%08x\n", ptr->rxBuf, ptr->txBuf ); +#endif + /* + * Set Channel Drive Enable bits in EPLD + */ + data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE ); + SYNC(); + data |= (PMCQ1_DRIVER_ENABLE_3 | PMCQ1_DRIVER_ENABLE_2 | + PMCQ1_DRIVER_ENABLE_1 | PMCQ1_DRIVER_ENABLE_0); + PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE, data); + data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE ); + SYNC(); + + /* + * Disable the receiver and the transmitter. + */ + + SYNC(); + tmp_u32 = scc_read32( "gsmr_l", &ptr->pSCCR->gsmr_l ); + tmp_u32 &= (~(M360_GSMR_ENR | M360_GSMR_ENT ) ) ; + scc_write32( "gsmr_l", &ptr->pSCCR->gsmr_l, tmp_u32 ); + + /* + * Disable Interrupt Error and Interrupt Breakpoint + * Set SAID to 4 XXX - Shouldn't it be 7 for slave mode + * Set SAISM to 7 + */ + SYNC(); + scc_write16( "sdcr", &m360->sdcr, 0x0740 ); + + /* + * Clear status -- reserved interrupt, SDMA channel error, SDMA breakpoint + */ + scc_write8( "sdsr", &m360->sdsr, 0x07 ); + SYNC(); + + /* + * Initialize timer information in RISC Controller Configuration Register + */ + scc_write16( "rccr", &m360->rccr, 0x8100 ); + SYNC(); + + /* + * XXX + */ + scc_write16( "papar", &m360->papar, 0xffff ); + scc_write16( "padir", &m360->padir, 0x5500 ); /* From Memo */ + scc_write16( "paodr", &m360->paodr, 0x0000 ); + SYNC(); + + /* + * XXX + */ + scc_write32( "pbpar", &m360->pbpar, 0x00000000 ); + scc_write32( "pbdir", &m360->pbdir, 0x0003ffff ); + scc_write32( "pbdat", &m360->pbdat, 0x0000003f ); + SYNC(); + + /* + * XXX + */ + scc_write16( "pcpar", &m360->pcpar, 0x0000 ); + scc_write16( "pcdir", &m360->pcdir, 0x0000 ); + scc_write16( "pcso", &m360->pcso, 0x0000 ); + SYNC(); + + /* + * configure baud rate generator for 16x bit rate, where..... + * b = desired baud rate + * clk = system clock (33mhz) + * d = clock dividor value + * + * for b > 300 : d = clk/(b*16) + * for b<= 300 : d = (clk/ (b*16*16))-1) + */ + SYNC(); + if( ptr->baud > 300 ) data = 33333333 / (ptr->baud * 16 ); + else data = (33333333 / (ptr->baud * 16 * 16) ) - 1; + data *= 2 ; + data &= 0x00001ffe ; + + /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */ + data |= ((ptr->baud>300)? 0 : 1 ) ; + data |= 0x010000 ; + + scc_write32( "pBRGC", ptr->pBRGC, data ); + + data = (((ptr->channel-1)*8) | (ptr->channel-1)) ; + data = data << ((ptr->channel-1)*8) ; + data |= scc_read32( "sicr", &m360->sicr ); + scc_write32( "sicr", &m360->sicr, data ); + + /* + * initialise SCC parameter ram + */ + SYNC(); + scc_write16( "pSCCB->rbase", &ptr->pSCCB->rbase, + (char *)(ptr->sccRxBd) - (char *)m360 ); + scc_write16( "pSCCB->tbase", &ptr->pSCCB->tbase, + (char *)(ptr->sccTxBd) - (char *)m360 ); + + scc_write8( "pSCCB->rfcr", &ptr->pSCCB->rfcr, 0x15 ); /* 0x15 0x18 */ + scc_write8( "pSCCB->tfcr", &ptr->pSCCB->tfcr, 0x15 ); /* 0x15 0x18 */ + + scc_write16( "pSCCB->mrblr", &ptr->pSCCB->mrblr, M68360_RX_BUF_SIZE ); + + /* + * initialise tx and rx scc parameters + */ + SYNC(); + data = M360_CR_INIT_TX_RX_PARAMS | 0x01; + data |= (M360_CR_CH_NUM * (ptr->channel-1) ); + scc_write16( "CR", &m360->cr, data ); + + /* + * initialise uart specific parameter RAM + */ + SYNC(); + scc_write16( "pSCCB->un.uart.max_idl", &ptr->pSCCB->un.uart.max_idl, 15000 ); + scc_write16( "pSCCB->un.uart.brkcr", &ptr->pSCCB->un.uart.brkcr, 0x0001 ); + scc_write16( "pSCCB->un.uart.parec", &ptr->pSCCB->un.uart.parec, 0x0000 ); + + scc_write16( "pSCCB->un,uart.frmec", &ptr->pSCCB->un.uart.frmec, 0x0000 ); + + scc_write16( "pSCCB->un.uart.nosec", &ptr->pSCCB->un.uart.nosec, 0x0000 ); + scc_write16( "pSCCB->un.uart.brkec", &ptr->pSCCB->un.uart.brkec, 0x0000 ); + scc_write16( "pSCCB->un.uart.uaddr0", &ptr->pSCCB->un.uart.uaddr[0], 0x0000 ); + scc_write16( "pSCCB->un.uart.uaddr1", &ptr->pSCCB->un.uart.uaddr[1], 0x0000 ); + scc_write16( "pSCCB->un.uart.toseq", &ptr->pSCCB->un.uart.toseq, 0x0000 ); + scc_write16( "pSCCB->un.uart.char0", + &ptr->pSCCB->un.uart.character[0], 0x0039 ); + scc_write16( "pSCCB->un.uart.char1", + &ptr->pSCCB->un.uart.character[1], 0x8000 ); + scc_write16( "pSCCB->un.uart.char2", + &ptr->pSCCB->un.uart.character[2], 0x8000 ); + scc_write16( "pSCCB->un.uart.char3", + &ptr->pSCCB->un.uart.character[3], 0x8000 ); + scc_write16( "pSCCB->un.uart.char4", + &ptr->pSCCB->un.uart.character[4], 0x8000 ); + scc_write16( "pSCCB->un.uart.char5", + &ptr->pSCCB->un.uart.character[5], 0x8000 ); + scc_write16( "pSCCB->un.uart.char6", + &ptr->pSCCB->un.uart.character[6], 0x8000 ); + scc_write16( "pSCCB->un.uart.char7", + &ptr->pSCCB->un.uart.character[7], 0x8000 ); + + scc_write16( "pSCCB->un.uart.rccm", &ptr->pSCCB->un.uart.rccm, 0xc0ff ); + + /* + * setup buffer descriptor stuff + */ + SYNC(); + scc_write16( "sccRxBd->status", &ptr->sccRxBd->status, 0x0000 ); + SYNC(); + scc_write16( "sccRxBd->length", &ptr->sccRxBd->length, 0x0000 ); + scc_write16( "sccRxBd->status", &ptr->sccRxBd->status, + M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT ); + /* XXX Radstone Example writes RX buffer ptr as two u16's */ + scc_write32( "sccRxBd->buffer", &ptr->sccRxBd->buffer, + RX_BUFFER_ADDRESS( ptr ) ); + + SYNC(); + scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0x0000 ); + SYNC(); + scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, 0x0000 ); + /* XXX Radstone Example writes TX buffer ptr as two u16's */ + scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer, + TX_BUFFER_ADDRESS( ptr ) ); + + /* + * clear previous events and set interrupt priorities + */ + scc_write16( "pSCCR->scce", &ptr->pSCCR->scce, 0x1bef ); /* From memo */ + SYNC(); + SYNC(); + scc_write32( "cicr", &m360->cicr, 0x001b9f40 ); + SYNC(); + + /* scc_write32( "cicr", &m360->cicr, scc_read32( "cicr", &m360->cicr ) ); */ + + scc_write16( "pSCCR->sccm", &ptr->pSCCR->sccm, M360_SCCE_TX | M360_SCCE_RX ); + + data = scc_read32("cimr", &m360->cimr); + data |= (0x80000000 >> ptr->channel); + scc_write32( "cimr", &m360->cimr, data ); + SYNC(); + scc_write32( "cipr", &m360->cipr, scc_read32( "cipr", &m360->cipr ) ); + + scc_write32( "pSCCR->gsmr_h", &ptr->pSCCR->gsmr_h, M360_GSMR_RFW ); + scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l, + (M360_GSMR_TDCR_16X | M360_GSMR_RDCR_16X | M360_GSMR_MODE_UART) ); + + scc_write16( "pSCCR->dsr", &ptr->pSCCR->dsr, 0x7e7e ); + SYNC(); + + scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr, + (M360_PSMR_CL8 | M360_PSMR_UM_NORMAL | M360_PSMR_TPM_ODD) ); + SYNC(); + + /* + * Enable the receiver and the transmitter. + */ + + SYNC(); + data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l); + scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l, + (data | M360_GSMR_ENR | M360_GSMR_ENT) ); + + data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK ); + data &= (~PMCQ1_INT_MASK_QUICC); + PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data ); + + data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS ); + data &= (~PMCQ1_INT_STATUS_QUICC); + PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data ); +} + +/* + * mc68360_scc_write_support_int + * + * Console Termios output entry point when using interrupt driven output. + */ + +int mc68360_scc_write_support_int( + int minor, + const char *buf, + int len +) +{ + rtems_interrupt_level Irql; + M68360_serial_ports_t ptr; + + mc68360_length_array[ mc68360_length_count ] = len; + mc68360_length_count++; + if ( mc68360_length_count >= MC68360_LENGHT_SIZE ) + mc68360_length_count=0; + + ptr = Console_Port_Tbl[minor].pDeviceParams; + + /* + * We are using interrupt driven output and termios only sends us + * one character at a time. + */ + + if ( !len ) + return 0; + + /* + * + */ +#ifdef DEBUG_360 + printk("mc68360_scc_write_support_int: char 0x%x length %d\n", + (unsigned int)*buf, len ); +#endif + /* + * We must copy the data from the global memory space to MC68360 space + */ + + rtems_interrupt_disable(Irql); + + scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0 ); + memcpy((void *) ptr->txBuf, buf, len); + scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer, + TX_BUFFER_ADDRESS(ptr->txBuf) ); + scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, len ); + scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, + (M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT) ); + + rtems_interrupt_enable(Irql); + + return len; +} + +/* + * mc68360_scc_write_polled + * + * This routine polls out the requested character. + */ + +void mc68360_scc_write_polled( + int minor, + char cChar +) +{ +#ifdef DEBUG_360 + printk("mc68360_scc_write_polled: %c\n", cChar); +#endif +} + +/* + * mc68681_set_attributes + * + * This function sets the DUART channel to reflect the requested termios + * port settings. + */ + +int mc68360_scc_set_attributes( + int minor, + const struct termios *t +) +{ + int baud; + volatile m360_t *m360; + M68360_serial_ports_t ptr; + + ptr = Console_Port_Tbl[minor].pDeviceParams; + m360 = ptr->chip->m360; + + switch (t->c_cflag & CBAUD) + { + 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; + default: baud = -1; break; + } + + if (baud > 0) + { + scc_write32( + "pBRGC", + ptr->pBRGC, + mc68360_sccBRGC(baud, ptr->chip->m360_clock_rate) + ); + } + + return 0; +} + +/* + * mc68360_scc_close + * + * This function shuts down the requested port. + */ + +int mc68360_scc_close( + int major, + int minor, + void *arg +) +{ + return(RTEMS_SUCCESSFUL); +} + +/* + * mc68360_scc_inbyte_nonblocking_polled + * + * Console Termios polling input entry point. + */ + +int mc68360_scc_inbyte_nonblocking_polled( + int minor +) +{ + return -1; +} + +/* + * mc68360_scc_write_support_polled + * + * Console Termios output entry point when using polled output. + * + */ + +int mc68360_scc_write_support_polled( + int minor, + const char *buf, + int len +) +{ + printk("mc68360_scc_write_support_polled: minor %d char %c len %d\n", + minor, buf, len ); + return 0; +} + +/* + * mc68360_scc_init + * + * This function initializes the DUART to a quiecsent state. + */ + +void mc68360_scc_init(int minor) +{ +#ifdef DEBUG_360 + printk("mc68360_scc_init\n"); +#endif +} + +int mc68360_scc_create_chip( PPMCQ1BoardData BoardData, uint8_t int_vector ) +{ + M68360_t chip; + int i; + +#ifdef DEBUG_360 + printk("mc68360_scc_create_chip\n"); +#endif + + /* + * Create console structure for this card + * XXX - Note Does this need to be moved up to if a QUICC is fitted + * section? + */ + if ((chip = malloc(sizeof(struct _m68360_per_chip))) == NULL) + { + printk("Error Unable to allocate memory for _m68360_per_chip\n"); + return RTEMS_IO_ERROR; + } + + chip->next = M68360_chips; + chip->m360 = (void *)BoardData->baseaddr; + chip->m360_interrupt = int_vector; + chip->m360_clock_rate = 25000000; + chip->board_data = BoardData; + M68360_chips = chip; + + for (i=1; i<=4; i++) { + chip->port[i-1].channel = i; + chip->port[i-1].chip = chip; + chip->port[i-1].baud = 9600; + + switch( i ) { + case 1: + chip->port[i-1].pBRGC = &chip->m360->brgc1; + chip->port[i-1].pSCCB = (m360SCCparms_t *) &chip->m360->scc1p; + chip->port[i-1].pSCCR = &chip->m360->scc1; + M360SetupMemory( chip ); /* Do this first time through */ + break; + case 2: + chip->port[i-1].pBRGC = &chip->m360->brgc2; + chip->port[i-1].pSCCB = &chip->m360->scc2p; + chip->port[i-1].pSCCR = &chip->m360->scc2; + break; + case 3: + chip->port[i-1].pBRGC = &chip->m360->brgc3; + chip->port[i-1].pSCCB = &chip->m360->scc3p; + chip->port[i-1].pSCCR = &chip->m360->scc3; + break; + case 4: + chip->port[i-1].pBRGC = &chip->m360->brgc4; + chip->port[i-1].pSCCB = &chip->m360->scc4p; + chip->port[i-1].pSCCR = &chip->m360->scc4; + break; + default: + printk("Invalid mc68360 channel %d\n", i); + return RTEMS_IO_ERROR; + } + + /* + * Allocate buffer descriptors. + */ + + chip->port[i-1].sccRxBd = M360AllocateBufferDescriptors(chip, 1); + chip->port[i-1].sccTxBd = M360AllocateBufferDescriptors(chip, 1); + } + + rsPMCQ1QuiccIntConnect( + chip->board_data->busNo, + chip->board_data->slotNo, + chip->board_data->funcNo, + &mc68360_sccInterruptHandler, + chip + ); + + return RTEMS_SUCCESSFUL; +} + +console_fns mc68360_scc_fns = { + libchip_serial_default_probe, /* deviceProbe */ + mc68360_scc_open, /* deviceFirstOpen */ + NULL, /* deviceLastClose */ + NULL, /* deviceRead */ + mc68360_scc_write_support_int, /* deviceWrite */ + mc68360_scc_initialize_interrupts, /* deviceInitialize */ + mc68360_scc_write_polled, /* deviceWritePolled */ + mc68360_scc_set_attributes, /* deviceSetAttributes */ + TRUE /* deviceOutputUsesInterrupts */ +}; + +console_fns mc68360_scc_polled = { + libchip_serial_default_probe, /* deviceProbe */ + mc68360_scc_open, /* deviceFirstOpen */ + mc68360_scc_close, /* deviceLastClose */ + mc68360_scc_inbyte_nonblocking_polled, /* deviceRead */ + mc68360_scc_write_support_polled, /* deviceWrite */ + mc68360_scc_init, /* deviceInitialize */ + mc68360_scc_write_polled, /* deviceWritePolled */ + mc68360_scc_set_attributes, /* deviceSetAttributes */ + FALSE /* deviceOutputUsesInterrupts */ +}; + diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.c b/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.c new file mode 100644 index 0000000000..849b10af54 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.c @@ -0,0 +1,47 @@ +/* + * This include file contains all console driver definations for the nc16550 + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include "console.h" + +typedef struct uart_reg +{ + unsigned char reg; + unsigned char pad[7]; +} uartReg; + +unsigned8 Read_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +) +{ + struct uart_reg *p = (struct uart_reg *)ulCtrlPort; + unsigned8 ucData; + ucData = p[ucRegNum].reg; + asm volatile("sync"); + return ucData; +} + +void Write_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +) +{ + struct uart_reg *p = (struct uart_reg *)ulCtrlPort; + volatile int i; + p[ucRegNum].reg = ucData; + asm volatile("sync"); + for (i=0;i<0x08ff;i++); +} diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.h b/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.h new file mode 100644 index 0000000000..c2aa368b28 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/ns16550cfg.h @@ -0,0 +1,57 @@ +/* nc16550cfg.h + * + * This include file contains all console driver definations for the nc16550 + * + * COPYRIGHT (c) 1998 by Radstone Technology + * + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 1989-1999. + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __NS16550_CONFIG_H +#define __NS16550_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Board specific register access routines + */ + +unsigned8 Read_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +); + +void Write_ns16550_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned8 ucData +); + +extern console_fns ns16550_fns_8245; +extern console_fns ns16550_fns_polled_8245; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.c b/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.c new file mode 100644 index 0000000000..088502e3b2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.c @@ -0,0 +1,558 @@ +/* rsPMCQ1.c - Radstone PMCQ1 Common Initialisation Code + * + * Copyright 2000 Radstone Technology + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 2005. + * 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.com/license/LICENSE. + * + */ + +/* +DESCRIPTION +These functions are responsible for scanning for PMCQ1's and setting up +the Motorola MC68360's if present. + +USAGE +call rsPMCQ1Init() to perform ba sic initialisation of the PMCQ1's. +*/ + +/* includes */ +#include <libcpu/io.h> +#include <bsp/irq.h> +#include <stdlib.h> +#include <rtems/bspIo.h> +#include <bsp/pci.h> +#include <bsp.h> +#include "rsPMCQ1.h" +#include "m68360.h" + +/* defines */ +#if 0 +#define DEBUG_360 +#endif + +/* Local data */ +PPMCQ1BoardData pmcq1BoardData = NULL; + +static unsigned char rsPMCQ1Initialized = FALSE; + +/* forward declarations */ + +/* local Qspan II serial eeprom table */ +static unsigned char rsPMCQ1eeprom[] = + { + 0x00, /* Byte 0 - PCI_SID */ + 0x00, /* Byte 1 - PCI_SID */ + 0x00, /* Byte 2 - PCI_SID */ + 0x00, /* Byte 3 - PCI_SID */ + 0x00, /* Byte 4 - PBROM_CTL */ + 0x00, /* Byte 5 - PBROM_CTL */ + 0x00, /* Byte 6 - PBROM_CTL */ + 0x2C, /* Byte 7 - PBTI0_CTL */ + 0xB0, /* Byte 8 - PBTI1_CTL */ + 0x00, /* Byte 9 - QBSI0_AT */ + 0x00, /* Byte 10 - QBSI0_AT */ + 0x02, /* Byte 11 - QBSI0_AT */ + 0x00, /* Byte 12 - PCI_ID */ + 0x07, /* Byte 13 - PCI_ID */ + 0x11, /* Byte 14 - PCI_ID */ + 0xB5, /* Byte 15 - PCI_ID */ + 0x06, /* Byte 16 - PCI_CLASS */ + 0x80, /* Byte 17 - PCI_CLASS */ + 0x00, /* Byte 18 - PCI_CLASS */ + 0x00, /* Byte 19 - PCI_MISC1 */ + 0x00, /* Byte 20 - PCI_MISC1 */ + 0xC0, /* Byte 21 - PCI_PMC */ + 0x00 /* Byte 22 - PCI_BST */ +}; + +void MsDelay() +{ + printk("."); +} + +void write8( int addr, int data ){ + out_8((void *)addr, (unsigned char)data); +} + +void write16( int addr, int data ) { + out_be16((void *)addr, (short)data ); +} + +void write32( int addr, int data ) { + out_be32((unsigned int *)addr, data ); +} + +int read32( int addr){ + return in_be32((unsigned int *)addr); +} + + +void rsPMCQ1_scc_nullFunc() {} + +/******************************************************************************* +* rsPMCQ1Int - handle a PMCQ1 interrupt +* +* This routine gets called when the QUICC or MA causes +* an interrupt. +* +* RETURNS: NONE. +*/ + +void rsPMCQ1Int( void *ptr ) +{ + unsigned long status; + unsigned long status1; + unsigned long mask; + PPMCQ1BoardData boardData = ptr; + + status = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS ); + mask = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_MASK ); + + if (((mask & PMCQ1_INT_MASK_QUICC) == 0) && (status & PMCQ1_INT_STATUS_QUICC)) + { + /* If there is a handler call it otherwise mask the interrupt */ + if (boardData->quiccInt) { + boardData->quiccInt(boardData->quiccArg); + } else { + *(unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_QUICC; + } + } + + if (((mask & PMCQ1_INT_MASK_MA) == 0) && (status & PMCQ1_INT_STATUS_MA)) + { + /* If there is a handler call it otherwise mask the interrupt */ + if (boardData->maInt) { + boardData->maInt(boardData->maArg); + } else { + *(unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_MA; + } + } + + /* Clear Interrupt on QSPAN */ + *(unsigned long *)(boardData->bridgeaddr + 0x600) = 0x00001000; + + /* read back the status register to ensure that the pci write has completed */ + status1 = *(volatile unsigned long *)(boardData->bridgeaddr + 0x600); +} + + +/******************************************************************************* +* +* rsPMCQ1MaIntConnect - connect a MiniAce interrupt routine +* +* This routine is called to connect a MiniAce interrupt handler +* upto a PMCQ1. +* +* RETURNS: OK if PMCQ1 found, ERROR if not. +*/ + +unsigned int rsPMCQ1MaIntConnect ( + unsigned long busNo, /* Pci Bus number of PMCQ1 */ + unsigned long slotNo, /* Pci Slot number of PMCQ1 */ + unsigned long funcNo, /* Pci Function number of PMCQ1 */ + rtems_irq_hdl routine,/* interrupt routine */ + rtems_irq_hdl_param arg /* argument to pass to interrupt routine */ +) +{ + PPMCQ1BoardData boardData; + unsigned int status = RTEMS_IO_ERROR; + + for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext) + { + if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) && + (boardData->funcNo == funcNo)) + { + boardData->maInt = routine; + boardData->maArg = arg; + status = RTEMS_SUCCESSFUL; + break; + } + } + + return (status); +} + +/******************************************************************************* +* +* rsPMCQ1MaIntDisconnect - disconnect a MiniAce interrupt routine +* +* This routine is called to disconnect a MiniAce interrupt handler +* from a PMCQ1. It also masks the interrupt source on the PMCQ1. +* +* RETURNS: OK if PMCQ1 found, ERROR if not. +*/ + +unsigned int rsPMCQ1MaIntDisconnect( + unsigned long busNo, /* Pci Bus number of PMCQ1 */ + unsigned long slotNo, /* Pci Slot number of PMCQ1 */ + unsigned long funcNo /* Pci Function number of PMCQ1 */ +) +{ + PPMCQ1BoardData boardData; + unsigned int status = RTEMS_IO_ERROR; + + for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext) { + if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) && + (boardData->funcNo == funcNo)) + { + boardData->maInt = NULL; + *(unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_MA; + status = RTEMS_SUCCESSFUL; + break; + } + } + + return (status); +} + +/******************************************************************************* +* +* rsPMCQ1QuiccIntConnect - connect a Quicc interrupt routine +* +* This routine is called to connect a Quicc interrupt handler +* upto a PMCQ1. +* +* RETURNS: OK if PMCQ1 found, ERROR if not. +*/ + +unsigned int rsPMCQ1QuiccIntConnect( + unsigned long busNo, /* Pci Bus number of PMCQ1 */ + unsigned long slotNo, /* Pci Slot number of PMCQ1 */ + unsigned long funcNo, /* Pci Function number of PMCQ1 */ + rtems_irq_hdl routine,/* interrupt routine */ + rtems_irq_hdl_param arg /* argument to pass to interrupt routine */ +) +{ + PPMCQ1BoardData boardData; + unsigned int status = RTEMS_IO_ERROR; + + for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext) + { + if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) && + (boardData->funcNo == funcNo)) + { + boardData->quiccInt = routine; + boardData->quiccArg = arg; + status = RTEMS_SUCCESSFUL; + break; + } + } + return (status); +} + +/******************************************************************************* +* +* rsPMCQ1QuiccIntDisconnect - disconnect a Quicc interrupt routine +* +* This routine is called to disconnect a Quicc interrupt handler +* from a PMCQ1. It also masks the interrupt source on the PMCQ1. +* +* RETURNS: OK if PMCQ1 found, ERROR if not. +*/ + +unsigned int rsPMCQ1QuiccIntDisconnect( + unsigned long busNo, /* Pci Bus number of PMCQ1 */ + unsigned long slotNo, /* Pci Slot number of PMCQ1 */ + unsigned long funcNo /* Pci Function number of PMCQ1 */ +) +{ + PPMCQ1BoardData boardData; + unsigned int status = RTEMS_IO_ERROR; + + for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext) + { + if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) && + (boardData->funcNo == funcNo)) + { + boardData->quiccInt = NULL; + *(unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_QUICC; + status = RTEMS_SUCCESSFUL; + break; + } + } + + return (status); +} + + +/******************************************************************************* +* +* rsPMCQ1Init - initialize the PMCQ1's +* +* This routine is called to initialize the PCI card to a quiescent state. +* +* RETURNS: OK if PMCQ1 found, ERROR if not. +*/ + +unsigned int rsPMCQ1Init() +{ + int busNo; + int slotNo; + unsigned int baseaddr = 0; + unsigned int bridgeaddr = 0; + unsigned long pbti0_ctl; + int i; + unsigned char int_vector; + int fun; + int temp; + PPMCQ1BoardData boardData; + rtems_irq_connect_data IrqData = {0, + rsPMCQ1Int, + NULL, + (rtems_irq_enable)rsPMCQ1_scc_nullFunc, + (rtems_irq_disable)rsPMCQ1_scc_nullFunc, + (rtems_irq_is_enabled)rsPMCQ1_scc_nullFunc, + NULL}; + + if (rsPMCQ1Initialized) + { + return RTEMS_SUCCESSFUL; + } + for (i=0;;i++){ + if ( pci_find_device(PCI_VEN_ID_RADSTONE, PCI_DEV_ID_PMCQ1, i, &busNo, &slotNo, &fun) != 0 ) + break; + + pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_2, &baseaddr); + pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_0, &bridgeaddr); +#ifdef DEBUG_360 + printk("PMCQ1 baseaddr 0x%08x bridgeaddr 0x%08x\n", baseaddr, bridgeaddr ); +#endif + + /* Set function code to normal mode and enable window */ + pbti0_ctl = *(unsigned long *)(bridgeaddr + 0x100) & 0xff0fffff; + eieio(); + *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00500080; + eieio(); + + /* Assert QBUS reset */ + *(unsigned long *)(bridgeaddr + 0x800) |= 0x00000080; + eieio(); + + /* + * Hold QBus in reset for 1ms + */ + MsDelay(); + + /* Take QBUS out of reset */ + *(unsigned long *)(bridgeaddr + 0x800) &= ~0x00000080; + eieio(); + + MsDelay(); + + /* If a QUICC is fitted initialise it */ + if (PMCQ1_Read_EPLD(baseaddr, PMCQ1_BUILD_OPTION) & PMCQ1_QUICC_FITTED) + { +#ifdef DEBUG_360 + printk(" Found QUICC busNo %d slotNo %d\n", busNo, slotNo); +#endif + + /* Initialise MBAR (must use function code of 7) */ + *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00700080; + eieio(); + + /* place internal 8K SRAM and registers at address 0x0 */ + *(unsigned long *)(baseaddr + Q1_360_MBAR) = 0x1; + eieio(); + + /* Set function code to normal mode */ + *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00500080; + eieio(); + + /* Disable the SWT and perform basic initialisation */ + write8(baseaddr+Q1_360_SIM_SYPCR,0); + eieio(); + + write32(baseaddr+Q1_360_SIM_MCR,0xa0001029); + write16(baseaddr+Q1_360_SIM_PICR,0); + write16(baseaddr+Q1_360_SIM_PITR,0); + + write16(baseaddr+Q1_360_CPM_ICCR,0x770); + write16(baseaddr+Q1_360_CPM_SDCR,0x770); + write32(baseaddr+Q1_360_CPM_CICR,0x00e49f00); + write16(baseaddr+Q1_360_SIM_PEPAR,0x2080); + eieio(); + + /* Enable SRAM */ + write32(baseaddr+Q1_360_SIM_GMR,0x00001000); /* external master wait state */ + eieio(); + write32(baseaddr+Q1_360_SIM_OR0,0x1ff00000); /*| MEMC_OR_FC*/ + eieio(); + write32(baseaddr+Q1_360_SIM_BR0,0); + eieio(); + write32(baseaddr+Q1_360_SIM_OR1,(0x5ff00000 | 0x00000780)); /*| MEMC_OR_FC*/ + eieio(); + write32(baseaddr+Q1_360_SIM_BR1,(0x00000040 | 0x00000001 | 0x00200280) ); + eieio(); + } + + /* + * If a second PCI window is present then make it opposite + * endian to simplify 1553 integration. + */ + pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_3, &temp); + if (temp) { + *(unsigned long *)(bridgeaddr + 0x110) |= 0x00500880; + } + + /* + * Create descriptor structure for this card + */ + if ((boardData = malloc(sizeof(struct _PMCQ1BoardData))) == NULL) + { + printk("Error Unable to allocate memory for _PMCQ1BoardData\n"); + return(RTEMS_IO_ERROR); + } + + boardData->pNext = pmcq1BoardData; + boardData->busNo = busNo; + boardData->slotNo = slotNo; + boardData->funcNo = 0; + boardData->baseaddr = baseaddr; + boardData->bridgeaddr = bridgeaddr; + boardData->quiccInt = NULL; + boardData->maInt = NULL; + pmcq1BoardData = boardData; + mc68360_scc_create_chip( boardData, int_vector ); + + /* + * Connect PMCQ1 interrupt handler. + */ + pci_read_config_byte(busNo, slotNo, 0, 0x3c, &int_vector); +#ifdef DEBUG_360 + printk("PMCQ1 int_vector %d\n", int_vector); +#endif + IrqData.name = (rtems_irq_symbolic_name)((unsigned int)BSP_PCI_IRQ0 + int_vector); + IrqData.handle = boardData; + if (!BSP_install_rtems_shared_irq_handler (&IrqData)) { + printk("Error installing interrupt handler!\n"); + rtems_fatal_error_occurred(1); + } + + /* + * Enable PMCQ1 Interrupts from QSPAN-II + */ + + *(unsigned long *)(bridgeaddr + 0x600) = 0x00001000; + eieio(); + *(unsigned long *)(bridgeaddr + 0x604) |= 0x00001000; + + eieio(); + } + + if (i > 0) + { + rsPMCQ1Initialized = TRUE; + } + return((i > 0) ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR); +} + +/******************************************************************************* +* +* rsPMCQ1Commission - initialize the serial EEPROM on the QSPAN +* +* This routine is called to initialize the EEPROM attached to the QSPAN +* on the PMCQ1 module. It will load standard settings into any QSPAN's +* found with apparently uninitialised EEPROM's or PMCQ1's (to allow +* EEPROM modifications to be performed). +*/ + +unsigned int rsPMCQ1Commission( unsigned long busNo, unsigned long slotNo ) +{ + unsigned int status = RTEMS_IO_ERROR; + unsigned int bridgeaddr = 0; + unsigned long val; + int i; + int venId1; + int venId2; + + pci_read_config_dword(busNo, slotNo, 0, PCI_VENDOR_ID, &venId1); + pci_read_config_dword(busNo, slotNo, 0, PCI_VENDOR_ID, &venId2); + if ((venId1 == 0x086210e3) || + (venId2 == PCI_ID(PCI_VEN_ID_RADSTONE, PCI_DEV_ID_PMCQ1))) + { + pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_0, &bridgeaddr); + status = RTEMS_SUCCESSFUL; + + /* + * The On board PMCQ1 on an EP1A has a subVendor ID of 0. + * A real PMCQ1 also has the sub vendor ID set up. + */ + if ((busNo == 0) && (slotNo == 1)) { + *(unsigned long *)rsPMCQ1eeprom = 0; + } else { + *(unsigned long *)rsPMCQ1eeprom = PCI_ID(PCI_VEN_ID_RADSTONE, PCI_DEV_ID_PMCQ1); + } + + for (i = 0; i < 23; i++) { + /* Wait until interface not active */ + while(read32(bridgeaddr + 0x804) & 0x80000000) { + rtems_bsp_delay(1); + } + + /* Write value */ + write32(bridgeaddr + 0x804, (rsPMCQ1eeprom[i] << 8) | i); + + /* delay for > 31 usec to allow active bit to become set */ + rtems_bsp_delay(100); + + /* Wait until interface not active */ + while(read32(bridgeaddr + 0x804) & 0x80000000) { + rtems_bsp_delay(1); + } + + /* Re-read value */ + write32(bridgeaddr + 0x804, 0x40000000 | i); + + /* delay for > 31 usec to allow active bit to become set */ + rtems_bsp_delay(100); + + /* Wait until interface not active */ + while((val = read32(bridgeaddr + 0x804)) & 0x80000000) { + rtems_bsp_delay(1); + } + + if (((val >> 8) & 0xff) != rsPMCQ1eeprom[i]) { + printk("Error writing byte %d expected 0x%02x got 0x%02x\n", + i, rsPMCQ1eeprom[i], (unsigned char)(val >> 8)); + status = RTEMS_IO_ERROR; + break; + } + } + } + return(status); +} + +uint32_t PMCQ1_Read_EPLD( uint32_t base, uint32_t reg ) +{ + uint32_t data; + + data = ( *((unsigned long *) (base + reg)) ); +#ifdef DEBUG_360 + printk("EPLD Read 0x%x: 0x%08x\n", reg + base, data ); +#endif + return data; +} + +void PMCQ1_Write_EPLD( uint32_t base, uint32_t reg, uint32_t data ) +{ + *((unsigned long *) (base + reg)) = data; +#ifdef DEBUG_360 + printk("EPLD Write 0x%x: 0x%08x\n", reg+base, data ); +#endif +} + diff --git a/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.h b/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.h new file mode 100644 index 0000000000..a38d24db35 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.h @@ -0,0 +1,148 @@ +/* rsPMCQ1.h - Radstone PMCQ1 private header + * + * Copyright 2000 Radstone Technology + * + * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. + * + * You are hereby granted permission to use, copy, modify, and distribute + * this file, provided that this notice, plus the above copyright notice + * and disclaimer, appears in all copies. Radstone Technology will provide + * no support for this code. + * + * COPYRIGHT (c) 2005. + * 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.com/license/LICENSE. + * + */ + +/* + modification history + -------------------- + 01a,20Dec00,jpb created + */ + +#ifndef __INCPMCQ1H +#define __INCPMCQ1H + +#include <libcpu/io.h> +#include <bsp/irq.h> + +/* + * PMCQ1 definitions + */ + +/* + * 360 definitions + */ + +#define Q1_360_MBAR 0x0003ff00 /* master base address register */ + +#define REG_B_OFFSET 0x1000 /* offset to the internal registers */ + +#define Q1_360_SIM_MCR (REG_B_OFFSET+0x00) +#define Q1_360_SIM_PEPAR (REG_B_OFFSET+0x16) +#define Q1_360_SIM_SYPCR (REG_B_OFFSET+0x22) +#define Q1_360_SIM_PICR (REG_B_OFFSET+0x26) +#define Q1_360_SIM_PITR (REG_B_OFFSET+0x2A) +#define Q1_360_SIM_GMR (REG_B_OFFSET+0x40) +#define Q1_360_SIM_BR0 (REG_B_OFFSET+0x50) +#define Q1_360_SIM_OR0 (REG_B_OFFSET+0x54) +#define Q1_360_SIM_BR1 (REG_B_OFFSET+0x60) +#define Q1_360_SIM_OR1 (REG_B_OFFSET+0x64) + +#define Q1_360_CPM_ICCR (REG_B_OFFSET+0x500) +#define Q1_360_CPM_SDCR (REG_B_OFFSET+0x51E) +#define Q1_360_CPM_CICR (REG_B_OFFSET+0x540) + +/* + * EPLD offsets + * + * Only top 4 data bits are used + */ +#define PMCQ1_CODE_VERSION 0x00040000 /* Code Version */ + +#define PMCQ1_BOARD_REVISION 0x00040004 /* Board Revision */ + +#define PMCQ1_BUILD_OPTION 0x00040008 /* Build Option */ +#define PMCQ1_ACE_FITTED 0x80000000 +#define PMCQ1_QUICC_FITTED 0x40000000 +#define PMCQ1_SRAM_SIZE 0x30000000 /* 01 - 1MB */ +#define PMCQ1_SRAM_FITTED 0x20000000 + +#define PMCQ1_INT_STATUS 0x0004000c /* Interrupt Status */ +#define PMCQ1_INT_STATUS_MA 0x20000000 +#define PMCQ1_INT_STATUS_QUICC 0x10000000 + +#define PMCQ1_INT_MASK 0x00040010 /* Interrupt Mask */ +#define PMCQ1_INT_MASK_QUICC 0x20000000 +#define PMCQ1_INT_MASK_MA 0x10000000 + +#define PMCQ1_RT_ADDRESS 0x00040014 /* RT Address Latch */ + +#define PMCQ1_DRIVER_ENABLE 0x0004001c /* Channel Drive Enable */ +#define PMCQ1_DRIVER_ENABLE_3 0x80000000 +#define PMCQ1_DRIVER_ENABLE_2 0x40000000 +#define PMCQ1_DRIVER_ENABLE_1 0x20000000 +#define PMCQ1_DRIVER_ENABLE_0 0x10000000 + +#define PMCQ1_MINIACE_REGS 0x000c0000 +#define PMCQ1_MINIACE_MEM 0x00100000 +#define PMCQ1_RAM 0x00200000 + +/* +#define PMCQ1_Read_EPLD( _base, _reg ) ( *((unsigned long *) ((unsigned32)_base + _reg)) ) +#define PMCQ1_Write_EPLD( _base, _reg, _data ) *((unsigned long *) ((unsigned32)_base + _reg)) = _data +*/ +uint32_t PMCQ1_Read_EPLD( uint32_t base, uint32_t reg ); +void PMCQ1_Write_EPLD( uint32_t base, uint32_t reg, uint32_t data ); + +/* + * QSPAN-II register offsets + */ + +#define QSPAN2_INT_STATUS 0x00000600 + + +#define PCI_ID(v, d) ((d << 16) | v) + + +#define PCI_VEN_ID_RADSTONE 0x11b5 +#define PCI_DEV_ID_PMC1553 0x0001 +#define PCI_DEV_ID_PMCF1 0x0002 +#define PCI_DEV_ID_PMCMMA 0x0003 +#define PCI_DEV_ID_PMCQ1 0x0007 +#define PCI_DEV_ID_PMCQ2 0x0008 +#define PCI_DEV_ID_PMCF1V2 0x0012 + + + +typedef struct _PMCQ1BoardData +{ + struct _PMCQ1BoardData *pNext; + unsigned long busNo; + unsigned long slotNo; + unsigned long funcNo; + unsigned long baseaddr; + unsigned long bridgeaddr; + rtems_irq_hdl quiccInt; + rtems_irq_hdl_param quiccArg; + rtems_irq_hdl maInt; + rtems_irq_hdl_param maArg; +} PMCQ1BoardData, *PPMCQ1BoardData; + +extern PPMCQ1BoardData pmcq1BoardData; + +/* + * Function declarations + */ +extern unsigned int rsPMCQ1QuiccIntConnect( + unsigned long busNo, unsigned long slotNo,unsigned long funcNo, rtems_irq_hdl routine,rtems_irq_hdl_param arg ); +unsigned int rsPMCQ1Init(); + +#endif /* __INCPMCQ1H */ |