📄 hal_aux.c
字号:
//=============================================================================
//
// hal_aux.c
//
// HAL auxiliary objects and code; per platform
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2002, 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors:hmt, gthomas
// Date: 1999-06-08
// Purpose: HAL aux objects: startup tables.
// Description: Tables for per-platform initialization
//
//####DESCRIPTIONEND####
//
//=============================================================================
#include <pkgconf/hal.h>
#include <pkgconf/io_pci.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_mem.h> // HAL memory definitions
#include <cyg/hal/ppc_regs.h> // Platform registers
#include <cyg/hal/hal_if.h> // hal_if_init
#include <cyg/hal/hal_intr.h> // interrupt definitions
#include <cyg/hal/hal_cache.h>
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/io/pci.h>
#include <cyg/hal/hal_io.h> // I/O macros
#include CYGHWR_MEMORY_LAYOUT_H
// Functions defined in this module
void _csb281_fs6377_init(int mode);
static void _csb281_i2c_init(void);
// The memory map is weakly defined, allowing the application to redefine
// it if necessary. The regions defined below are the minimum requirements.
CYGARC_MEMDESC_TABLE CYGBLD_ATTRIB_WEAK = {
// Mapping for the Cogent CSB281 development boards
CYGARC_MEMDESC_NOCACHE( 0x70000000, 0x10000000 ), // FLASH region, LCD, PS/2
CYGARC_MEMDESC_NOCACHE( 0xf0000000, 0x10000000 ), // PCI space, LEDS, control
CYGARC_MEMDESC_CACHE( CYGMEM_REGION_ram, CYGMEM_REGION_ram_SIZE ), // Main memory
// Main memory, mapped non-cacheable for PCI use
CYGARC_MEMDESC_NOCACHE_PA(CYGMEM_SECTION_pci_window,
CYGARC_PHYSICAL_ADDRESS(CYGMEM_SECTION_pci_window),
CYGMEM_SECTION_pci_window_SIZE),
CYGARC_MEMDESC_TABLE_END
};
//--------------------------------------------------------------------------
// Platform init code.
void
hal_platform_init(void)
{
cyg_uint32 bcsr, gcr, frr, eicr, iack;
int vec;
// Initialize I/O interfaces
hal_if_init();
// Reset interrupt controller/state
HAL_READ_UINT32LE(_CSB281_EPIC_GCR, gcr);
HAL_READ_UINT32LE(_CSB281_EPIC_FRR, frr);
HAL_WRITE_UINT32LE(_CSB281_EPIC_GCR, gcr | _CSB281_EPIC_GCR_R);
do {
HAL_READ_UINT32LE(_CSB281_EPIC_GCR, gcr);
} while ((gcr & _CSB281_EPIC_GCR_R) != 0);
HAL_WRITE_UINT32LE(_CSB281_EPIC_GCR, gcr | _CSB281_EPIC_GCR_M);
HAL_READ_UINT32LE(_CSB281_EPIC_EICR, eicr); // Force direct interrupts
eicr &= ~_CSB281_EPIC_EICR_SIE;
HAL_WRITE_UINT32LE(_CSB281_EPIC_EICR, eicr);
for (vec = CYGNUM_HAL_INTERRUPT_IRQ0; vec <= CYGNUM_HAL_ISR_MAX; vec++) {
HAL_INTERRUPT_CONFIGURE(vec, 0, 0); // Default to low-edge
HAL_INTERRUPT_SET_LEVEL(vec, 0x0F); // Priority
}
vec = (frr & 0x0FFF0000) >> 16; // Number of interrupt sources
while (vec-- > 0) {
HAL_READ_UINT32LE(_CSB281_EPIC_IACK, iack);
HAL_WRITE_UINT32LE(_CSB281_EPIC_EOI, 0);
}
HAL_WRITE_UINT32LE(_CSB281_EPIC_PCTPR, 1); // Enables interrupts
#ifndef CYGSEM_HAL_USE_ROM_MONITOR
// Reset peripherals
HAL_READ_UINT32(_CSB281_BCSR, bcsr);
HAL_WRITE_UINT32(_CSB281_BCSR, _zero_bit(bcsr, _CSB281_BCSR_PRESET));
HAL_WRITE_UINT32(_CSB281_BCSR, _one_bit(bcsr, _CSB281_BCSR_PRESET));
_csb281_i2c_init();
_csb281_fs6377_init(0);
#endif
#ifdef CYGSEM_CSB281_LCD_COMM
lcd_comm_init();
#endif
_csb281_pci_init();
}
//--------------------------------------------------------------------------
// Interrupt support
CYG_ADDRWORD _pvrs[] = {
_CSB281_EPIC_IVPR0, // CYGNUM_HAL_INTERRUPT_IRQ0 0x02
_CSB281_EPIC_IVPR1, // CYGNUM_HAL_INTERRUPT_IRQ1 0x03
_CSB281_EPIC_IVPR2, // CYGNUM_HAL_INTERRUPT_IRQ2 0x04
_CSB281_EPIC_IVPR3, // CYGNUM_HAL_INTERRUPT_IRQ3 0x05
_CSB281_EPIC_IVPR4, // CYGNUM_HAL_INTERRUPT_IRQ4 0x06
_CSB281_EPIC_UART0VPR, // CYGNUM_HAL_INTERRUPT_UART0 0x07
_CSB281_EPIC_UART1VPR, // CYGNUM_HAL_INTERRUPT_UART1 0x08
_CSB281_EPIC_GTVPR0, // CYGNUM_HAL_INTERRUPT_TIMER0 0x09
_CSB281_EPIC_GTVPR1, // CYGNUM_HAL_INTERRUPT_TIMER1 0x0A
_CSB281_EPIC_GTVPR2, // CYGNUM_HAL_INTERRUPT_TIMER2 0x0B
_CSB281_EPIC_GTVPR3, // CYGNUM_HAL_INTERRUPT_TIMER3 0x0C
_CSB281_EPIC_I2CVPR, // CYGNUM_HAL_INTERRUPT_I2C 0x0D
_CSB281_EPIC_DMA0VPR, // CYGNUM_HAL_INTERRUPT_DMA0 0x0E
_CSB281_EPIC_DMA1VPR, // CYGNUM_HAL_INTERRUPT_DMA1 0x0F
_CSB281_EPIC_MSGVPR, // CYGNUM_HAL_INTERRUPT_MSG 0x10
};
void
hal_interrupt_mask(int vector)
{
cyg_uint32 pvr;
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
if (vector < CYGNUM_HAL_INTERRUPT_IRQ0) {
// Can't do much with non-external interrupts
return;
}
HAL_READ_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
pvr |= _CSB281_EPIC_PVR_M;
HAL_WRITE_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
// diag_printf("%s(%d)\n", __FUNCTION__, vector);
}
void
hal_interrupt_unmask(int vector)
{
cyg_uint32 pvr;
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
if (vector < CYGNUM_HAL_INTERRUPT_IRQ0) {
// Can't do much with non-external interrupts
return;
}
HAL_READ_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
pvr &= ~_CSB281_EPIC_PVR_M;
HAL_WRITE_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
// diag_printf("%s(%d)\n", __FUNCTION__, vector);
}
void
hal_interrupt_acknowledge(int vector)
{
}
void
hal_interrupt_configure(int vector, int level, int up)
{
cyg_uint32 pvr;
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
if (vector < CYGNUM_HAL_INTERRUPT_IRQ0) {
// Can't do much with non-external interrupts
return;
}
// diag_printf("%s(%d, %d, %d)\n", __FUNCTION__, vector, level, up);
HAL_READ_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
pvr &= _CSB281_EPIC_PVR_M; // Preserve mask
pvr |= vector;
if (level) {
pvr |= _CSB281_EPIC_PVR_S;
} else {
pvr &= ~_CSB281_EPIC_PVR_S;
}
if (up) {
pvr |= _CSB281_EPIC_PVR_P;
} else {
pvr &= ~_CSB281_EPIC_PVR_P;
}
HAL_WRITE_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
}
void
hal_interrupt_set_level(int vector, int level)
{
cyg_uint32 pvr;
CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
if (vector < CYGNUM_HAL_INTERRUPT_IRQ0) {
// Can't do much with non-external interrupts
return;
}
HAL_READ_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
pvr &= ~(_CSB281_EPIC_PVR_PRIO_MASK<<_CSB281_EPIC_PVR_PRIO_SHIFT);
pvr |= (level<<_CSB281_EPIC_PVR_PRIO_SHIFT);
HAL_WRITE_UINT32LE(_pvrs[vector-CYGNUM_HAL_INTERRUPT_IRQ0], pvr);
}
//--------------------------------------------------------------------------
// PCI support
externC void
_csb281_pci_init(void)
{
static int _init = 0;
cyg_uint8 next_bus;
cyg_uint32 cmd_state;
if (_init) return;
_init = 1;
// Initialize PCI support
cyg_pci_init();
// Setup for bus mastering
HAL_PCI_CFG_READ_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
CYG_PCI_CFG_COMMAND, cmd_state);
if ((cmd_state & CYG_PCI_CFG_COMMAND_MEMORY) == 0) {
// Force PCI-side window to 0
HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
CYG_PCI_CFG_BAR_0, 0x01);
// Enable bus mastering from host
HAL_PCI_CFG_WRITE_UINT32(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
CYG_PCI_CFG_COMMAND,
CYG_PCI_CFG_COMMAND_MEMORY |
CYG_PCI_CFG_COMMAND_MASTER |
CYG_PCI_CFG_COMMAND_PARITY |
CYG_PCI_CFG_COMMAND_SERR);
// Setup latency timer field
HAL_PCI_CFG_WRITE_UINT8(0, CYG_PCI_DEV_MAKE_DEVFN(0,0),
CYG_PCI_CFG_LATENCY_TIMER, 32);
// Configure PCI bus.
next_bus = 1;
cyg_pci_configure_bus(0, &next_bus);
}
if (0){
cyg_uint8 devfn;
cyg_pci_device_id devid;
cyg_pci_device dev_info;
int i;
devid = CYG_PCI_DEV_MAKE_ID(next_bus-1, 0) | CYG_PCI_NULL_DEVFN;
while (cyg_pci_find_next(devid, &devid)) {
devfn = CYG_PCI_DEV_GET_DEVFN(devid);
cyg_pci_get_device_info(devid, &dev_info);
diag_printf("\n");
diag_printf("Bus: %d\n", CYG_PCI_DEV_GET_BUS(devid));
diag_printf("PCI Device: %d\n", CYG_PCI_DEV_GET_DEV(devfn));
diag_printf("PCI Func : %d\n", CYG_PCI_DEV_GET_FN(devfn));
diag_printf("Vendor Id : 0x%08X\n", dev_info.vendor);
diag_printf("Device Id : 0x%08X\n", dev_info.device);
for (i = 0; i < dev_info.num_bars; i++) {
diag_printf(" BAR[%d] 0x%08x /", i, dev_info.base_address[i]);
diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
dev_info.base_size[i], dev_info.base_map[i]);
}
}
}
// Configure interrupts (high level)?
HAL_INTERRUPT_CONFIGURE(CYGNUM_HAL_INTERRUPT_PCI0, 1, 1);
HAL_INTERRUPT_CONFIGURE(CYGNUM_HAL_INTERRUPT_PCI1, 1, 1);
HAL_INTERRUPT_CONFIGURE(CYGNUM_HAL_INTERRUPT_LAN, 1, 1);
}
externC void
_csb281_pci_translate_interrupt(int bus, int devfn, int *vec, int *valid)
{
cyg_uint8 dev = CYG_PCI_DEV_GET_DEV(devfn);
// Purely slot based
if (dev >= CYG_PCI_MIN_DEV) {
CYG_ADDRWORD __translation[] = {
CYGNUM_HAL_INTERRUPT_PCI0,
CYGNUM_HAL_INTERRUPT_PCI1,
CYGNUM_HAL_INTERRUPT_LAN
};
*vec = __translation[dev-CYG_PCI_MIN_DEV];
*valid = true;
} else {
*valid = false;
}
#if 0
diag_printf("Int - dev: %d, vector: %d [%s]\n",
dev, *vec, *valid ? "OK" : "BAD");
#endif
}
// PCI configuration space access
#define _EXT_ENABLE 0x80000000
//
// Prepare for a config cycle on the PCI bus
//
static __inline__ cyg_uint32
_cfg_sel(int bus, int devfn, int offset)
{
cyg_uint32 cfg_addr, addr;
cyg_uint32 bcsr;
HAL_READ_UINT32(_CSB281_BCSR, bcsr);
bcsr = (bcsr & ~0x07) | (1<<(CYG_PCI_DEV_GET_DEV(devfn)-CYG_PCI_MIN_DEV));
HAL_WRITE_UINT32(_CSB281_BCSR, bcsr);
cfg_addr = _EXT_ENABLE |
(bus << 16) |
(CYG_PCI_DEV_GET_DEV(devfn) << 11) |
(CYG_PCI_DEV_GET_FN(devfn) << 8) |
((offset & 0xFF) << 0);
HAL_WRITE_UINT32LE(_CSB281_PCI_CONFIG_ADDR, cfg_addr);
addr = _CSB281_PCI_CONFIG_DATA + (offset & 0x03);
return addr;
}
externC cyg_uint8
_csb281_pci_cfg_read_uint8(int bus, int devfn, int offset)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -