forked from Imagelibrary/rtems
156 lines
4.0 KiB
C
156 lines
4.0 KiB
C
/* PCI (Static) Configuration Library
|
|
*
|
|
* COPYRIGHT (c) 2010 Cobham Gaisler AB.
|
|
*
|
|
* The license and distribution terms for this file may be
|
|
* found in the file LICENSE in this distribution or at
|
|
* http://www.rtems.org/license/LICENSE.
|
|
*/
|
|
|
|
/*
|
|
* The Host Bridge bus must be declared by user. It contains the static
|
|
* configuration used to setup the devices/functions.
|
|
*/
|
|
|
|
/* Configure headers */
|
|
#define PCI_CFG_STATIC_LIB
|
|
|
|
#include <stdlib.h>
|
|
#include <pci.h>
|
|
#include <pci/access.h>
|
|
#include <pci/cfg.h>
|
|
|
|
#include "pci_internal.h"
|
|
|
|
#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
|
|
#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
|
|
#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
|
|
#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
|
|
#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
|
|
#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
|
|
|
|
/* Enumrate one bus if device is a bridge, and all it's subordinate buses */
|
|
static int pci_init_dev(struct pci_dev *dev, void *unused)
|
|
{
|
|
uint32_t tmp;
|
|
uint16_t tmp16, cmd;
|
|
struct pci_bus *bridge;
|
|
int maxbars, i, romofs;
|
|
pci_dev_t pcidev = dev->busdevfun;
|
|
struct pci_res *res;
|
|
|
|
/* Init Device */
|
|
|
|
/* Set command to reset values, it disables bus
|
|
* mastering and address responses.
|
|
*/
|
|
PCI_CFG_W16(pcidev, PCIR_COMMAND, 0);
|
|
|
|
/* Clear any already set status bits */
|
|
PCI_CFG_W16(pcidev, PCIR_STATUS, 0xf900);
|
|
|
|
/* Set latency timer to 64 */
|
|
PCI_CFG_W8(pcidev, PCIR_LATTIMER, 64);
|
|
|
|
/* Set System IRQ of PIN */
|
|
PCI_CFG_W8(pcidev, PCIR_INTLINE, dev->sysirq);
|
|
|
|
cmd = dev->command;
|
|
|
|
if ((dev->flags & PCI_DEV_BRIDGE) == 0) {
|
|
/* Disable Cardbus CIS Pointer */
|
|
PCI_CFG_W32(pcidev, PCIR_CIS, 0);
|
|
|
|
romofs = PCIR_BIOS;
|
|
maxbars = 6;
|
|
} else {
|
|
/* Init Bridge */
|
|
|
|
/* Configure bridge (no support for 64-bit) */
|
|
PCI_CFG_W32(pcidev, PCIR_PMBASEH_1, 0);
|
|
PCI_CFG_W32(pcidev, PCIR_PMLIMITH_1, 0);
|
|
|
|
bridge = (struct pci_bus *)dev;
|
|
tmp = (64 << 24) | (bridge->sord << 16) |
|
|
(bridge->num << 8) | bridge->pri;
|
|
PCI_CFG_W32(pcidev, PCIR_PRIBUS_1, tmp);
|
|
|
|
/*** Setup I/O Bridge Window ***/
|
|
res = &dev->resources[BRIDGE_RES_IO];
|
|
if (res->size > 0) {
|
|
tmp16 = ((res->end-1) & 0x0000f000) |
|
|
((res->start & 0x0000f000) >> 8);
|
|
tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
|
|
cmd |= PCIM_CMD_PORTEN;
|
|
} else {
|
|
tmp16 = 0x00ff;
|
|
tmp = 0;
|
|
}
|
|
/* I/O Limit and Base */
|
|
PCI_CFG_W16(pcidev, PCIR_IOBASEL_1, tmp16);
|
|
PCI_CFG_W32(pcidev, PCIR_IOBASEH_1, tmp);
|
|
|
|
/*** Setup MEMIO Bridge Window ***/
|
|
res = &dev->resources[BRIDGE_RES_MEMIO];
|
|
if (res->size > 0) {
|
|
tmp = ((res->end-1) & 0xffff0000) |
|
|
(res->start >> 16);
|
|
cmd |= PCIM_CMD_MEMEN;
|
|
} else {
|
|
tmp = 0x0000ffff;
|
|
}
|
|
/* MEMIO Limit and Base */
|
|
PCI_CFG_W32(pcidev, PCIR_MEMBASE_1, tmp);
|
|
|
|
/*** Setup MEM Bridge Window ***/
|
|
res = &dev->resources[BRIDGE_RES_MEM];
|
|
if (res->size > 0) {
|
|
tmp = ((res->end-1) & 0xffff0000) |
|
|
(res->start >> 16);
|
|
cmd |= PCIM_CMD_MEMEN;
|
|
} else {
|
|
tmp = 0x0000ffff;
|
|
}
|
|
/* MEM Limit and Base */
|
|
PCI_CFG_W32(pcidev, PCIR_PMBASEL_1, tmp);
|
|
/* 64-bit space not supported */
|
|
PCI_CFG_W32(pcidev, PCIR_PMBASEH_1, 0);
|
|
PCI_CFG_W32(pcidev, PCIR_PMLIMITH_1, 0);
|
|
|
|
cmd |= PCIM_CMD_BUSMASTEREN;
|
|
romofs = PCIR_BIOS_1;
|
|
maxbars = 2;
|
|
}
|
|
|
|
/* Init BARs */
|
|
for (i = 0; i < maxbars; i++) {
|
|
res = &dev->resources[i];
|
|
if (res->flags & PCI_RES_TYPE_MASK) {
|
|
PCI_CFG_W32(pcidev, PCIR_BAR(0) + 4*i,
|
|
res->start);
|
|
if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
|
|
cmd |= PCIM_CMD_PORTEN;
|
|
else
|
|
cmd |= PCIM_CMD_MEMEN;
|
|
}
|
|
}
|
|
res = &dev->resources[DEV_RES_ROM];
|
|
if (res->flags & PCI_RES_TYPE_MASK) {
|
|
PCI_CFG_W32(pcidev, romofs, res->start|PCIM_BIOS_ENABLE);
|
|
cmd |= PCIM_CMD_MEMEN;
|
|
}
|
|
PCI_CFG_W16(pcidev, PCIR_COMMAND, cmd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Assume that user has defined static setup array in pci_hb */
|
|
int pci_config_static(void)
|
|
{
|
|
pci_bus_cnt = pci_hb.sord + 1;
|
|
pci_system_type = PCI_SYSTEM_HOST;
|
|
|
|
/* Init all PCI devices according to depth-first search algorithm */
|
|
return pci_for_each_dev(pci_init_dev, NULL);
|
|
}
|