📄 picasso_pci.c
字号:
//==========================================================================
//
// picasso_pci.c
//
// HAL support code for NMI uEngine picasso PCI
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas <gary@mind.be>
//
// 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): msalter
// Contributors: msalter, gthomas, David Mazur <david@mind.be>
// Date: 2002-01-04
// Purpose: PCI support
// Description: Implementations of HAL PCI interfaces
//
//####DESCRIPTIONEND####
//
//========================================================================*/
#include <pkgconf/hal.h>
#include <pkgconf/system.h>
#include CYGBLD_HAL_PLATFORM_H
#include CYGHWR_MEMORY_LAYOUT_H
#include <cyg/infra/cyg_type.h> // base types
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/infra/diag.h> // diag_printf()
#include <cyg/hal/hal_io.h> // IO macros
#include <cyg/hal/hal_if.h> // calling interface API
#include <cyg/hal/hal_arch.h> // Register state info
#include <cyg/hal/hal_diag.h>
#include <cyg/hal/hal_intr.h> // Interrupt names
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/plf_io.h>
#include <cyg/io/pci_hw.h>
#include <cyg/io/pci.h>
#ifdef CYGPKG_IO_PCI
#ifdef CYGSEM_HAL_LOAD_PCI_FPGA
static unsigned char picasso_pci_bitstream[] = {
#include "picasso_pci_bitstream.h"
};
externC void load_fpga(void *bitstream, int len);
#endif
void
cyg_hal_plf_pci_init(void)
{
cyg_uint8 next_bus;
static bool _done = false;
if (_done) return;
_done = true;
diag_printf("Initializing PCI.\n");
#ifdef CYGSEM_HAL_LOAD_PCI_FPGA
// Set MSC0 for FPGA configuration
*PXA2X0_MSC1 = (*PXA2X0_MSC1 & 0x0000FFFF);
// Program FPGA
load_fpga(picasso_pci_bitstream, sizeof(picasso_pci_bitstream));
#endif
*PXA2X0_MSC0 = (*PXA2X0_MSC0 & 0x0000FFFF) | 0x7ff10000;
*PXA2X0_MSC1 = (*PXA2X0_MSC1 & 0x0000FFFF) | 0x70e40000;
*PXA2X0_MSC2 = 0x70e470e4;
*PXA2X0_MDREFR = 0x0009c018;
*PXA2X0_MDCNFG = 0x03001bc9;
// FIXME: Change MSC values ??
// Set FPGA to 110.6 MHz
*PXA2X0_GPDR0 |= (0x01 << 7);
*PXA2X0_GPSR0 |= (0x01 << 7);
*PXA2X0_GPDR1 |= (0x01 << (45-32));
*PXA2X0_GPCR1 |= (0x01 << (45-32));
// Set busmastering
diag_printf("Activating PCI bridge.\n");
PCICTL_MISC |= (1 | PCI_SDRAM_128) | PCI_TIMER;
// Set command master
cyg_hal_plf_pci_cfg_write_byte(0,0, CYG_PCI_CFG_COMMAND, CYG_PCI_CFG_COMMAND_MASTER);
diag_printf("Scanning PCI bridge...\n");
// Initialize PCI support
cyg_pci_init();
// Configure PCI bus.
next_bus = 1;
cyg_pci_configure_bus(0, &next_bus);
if (1){
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]);
}
}
}
}
void
_picasso_pci_translate_interrupt(int bus, int devfn, int *vector, int *valid)
{
int dev = CYG_PCI_DEV_GET_DEV(devfn);
if (dev <= 5) {
*vector = _uPCI_BASE_INTERRUPT+(dev-1);
valid = true;;
} else {
valid = false;
}
}
static void
cyg_hal_plf_pci_clear_idsel(void)
{
// Clear any active idsels
PCICTL_MISC &= ~PCI_IDSEL_OFF;
PCICTL_STATUS_REG = 0;
}
void
cyg_hal_plf_pci_select_idsel(cyg_uint32 dev)
{
cyg_hal_plf_pci_clear_idsel();
// PCICTL_STATUS_REG = 0x0;
PCICTL_MISC |= 1 + (((dev + 1) << PCI_IDSEL_SHIFT));
}
#define _PCI_ADDR(bus, devfn) (PCI_CONFIG_BASE | \
(bus << 16) | \
(CYG_PCI_DEV_GET_DEV(devfn) << 11) | \
(CYG_PCI_DEV_GET_FN(devfn) << 8))
cyg_uint32
cyg_hal_plf_pci_cfg_read_dword(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset)
{
cyg_uint32 config_data;
volatile cyg_uint32 *address = (cyg_uint32 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
config_data = address[offset >> 2];
if ((PCICTL_STATUS_REG & 0x0020) == 0x0020) {
// Configuration cycle failed
config_data = 0xFFFFFFFF;
}
cyg_hal_plf_pci_clear_idsel();
return config_data;
}
void
cyg_hal_plf_pci_cfg_write_dword(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset, cyg_uint32 data)
{
volatile cyg_uint32 *address = (cyg_uint32 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
address[offset >> 2] = data;
cyg_hal_plf_pci_clear_idsel();
}
cyg_uint16
cyg_hal_plf_pci_cfg_read_word(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset)
{
cyg_uint16 config_data;
volatile cyg_uint16 *address = (cyg_uint16 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
config_data = address[offset >> 1];
if ((PCICTL_STATUS_REG & 0x0020) == 0x0020) {
// Configuration cycle failed
config_data = 0xFFFF;
}
cyg_hal_plf_pci_clear_idsel();
return config_data;
}
void
cyg_hal_plf_pci_cfg_write_word(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset, cyg_uint16 data)
{
volatile cyg_uint16 *address = (cyg_uint16 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
address[offset >> 1] = data;
cyg_hal_plf_pci_clear_idsel();
}
cyg_uint8
cyg_hal_plf_pci_cfg_read_byte(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset)
{
cyg_uint8 config_data;
volatile cyg_uint8 *address = (cyg_uint8 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
config_data = address[offset];
if ((PCICTL_STATUS_REG & 0x0020) == 0x0020) {
// Configuration cycle failed
config_data = 0xFF;
}
cyg_hal_plf_pci_clear_idsel();
return config_data;
}
void
cyg_hal_plf_pci_cfg_write_byte(cyg_uint32 bus, cyg_uint32 devfn,
cyg_uint32 offset, cyg_uint8 data)
{
volatile cyg_uint8 *address = (cyg_uint8 *)_PCI_ADDR(bus, devfn);
cyg_hal_plf_pci_select_idsel(CYG_PCI_DEV_GET_DEV(devfn));
address[offset] = data;
cyg_hal_plf_pci_clear_idsel();
}
//
// Note: PCI I/O space reads on this platform require additional
// addressing gymnastics
/**
* Reads an 8 bit value (byte) from the given address of the PCI
* IO space.
**/
cyg_uint8 pci_io_read_8(cyg_uint32 address)
{
volatile cyg_uint8 *addr = (volatile cyg_uint8 *)(((address & 0x00000003) << 22) |
address | _PCI_READ_8);
cyg_uint8 val = *addr;
#ifdef _PCI_DEBUG
diag_printf("READ PCI.8 [%p/%p] => %02x\n", address, addr, val);
#endif
return val;
}
/**
* * Reads a 16 bit value (word) from the given address of the PCI
* * IO space.
* */
cyg_uint16 pci_io_read_16(cyg_uint32 address)
{
volatile cyg_uint16 *addr = (volatile cyg_uint16 *)(((address & 0x00000002) << 21) |
address | _PCI_READ_16);
cyg_uint16 val = *addr;
#ifdef _PCI_DEBUG
diag_printf("READ PCI.16 [%p/%p] => %04x\n", address, addr, val);
#endif
return val;
}
/**
* * Reads a 32 bit value (double word) from the given address of the PCI
* * IO space.
* */
cyg_uint32 pci_io_read_32(cyg_uint32 address)
{
volatile cyg_uint32 *addr = (volatile cyg_uint32 *)(address | _PCI_READ_32);
cyg_uint32 val = *addr;
#ifdef _PCI_DEBUG
diag_printf("READ PCI.32 [%p/%p] => %02x\n", address, addr, val);
#endif
return val;
}
/**
* * Writes an 8 bit value (byte) into the given address of the PCI
* * IO space.
* */
void pci_io_write_8(cyg_uint32 address, cyg_uint8 value)
{
*((volatile cyg_uint8 *)(address | _PCI_WRITE_X)) = value;
#ifdef _PCI_DEBUG
diag_printf("WRITE PCI.8[%p] <= %02x\n", address | _PCI_WRITE_X, value);
#endif
}
/**
* * Writes a 16 bit value (single word) into the given address of the PCI
* * IO space.
* */
void pci_io_write_16(cyg_uint32 address, cyg_uint16 value)
{
*((volatile cyg_uint16 *)(address | _PCI_WRITE_X)) = value;
#ifdef _PCI_DEBUG
diag_printf("WRITE PCI.16[%p] <= %04x\n", address | _PCI_WRITE_X, value);
#endif
}
/**
* * Writes a 32 bit value (double word) into the given address of the PCI
* * IO space.
* */
void pci_io_write_32(cyg_uint32 address, cyg_uint32 value)
{
*((volatile cyg_uint32 *)(address | _PCI_WRITE_X)) = value;
#ifdef _PCI_DEBUG
diag_printf("WRITE PCI.32[%p] <= %08x\n", address | _PCI_WRITE_X, value);
#endif
}
#endif // CYGPKG_IO_PCI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -