You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

350 lines
8.7 KiB

/* $Id: pci_machdep.c,v 1.1.1.1 2006/09/14 01:59:09 root Exp $ */
/*
* Copyright (c) 2001 Opsycon AB (www.opsycon.se)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Opsycon AB, Sweden.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <stdbool.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/nppbreg.h>
#include <machine/bus.h>
#include "include/bonito.h"
#include <pmon.h>
#ifdef PCIE_GRAPHIC_CARD
extern bool is_pcie_vga_card();
#endif
extern void *pmalloc __P((size_t ));
#if (PCI_IDSEL_CS5536 != 0)
#include <include/cs5536_pci.h>
extern pcireg_t cs5536_pci_conf_readn(int function, int reg, int width);
extern int cs5536_pci_conf_writen(int function, int reg, int width, pcireg_t value);
#endif
extern void *pmalloc __P((size_t ));
extern int _pciverbose;
extern char hwethadr[6];
struct pci_device *_pci_bus[16];
int _max_pci_bus = 0;
/* PCI mem regions in PCI space */
/* soft versions of above */
static pcireg_t pci_local_mem_pci_base;
/****************************/
/*initial PCI */
/****************************/
int
_pci_hwinit(initialise, iot, memt)
int initialise;
bus_space_tag_t iot;
bus_space_tag_t memt;
{
/*pcireg_t stat;*/
struct pci_device *pd;
struct pci_bus *pb;
int newcfg=0;
int i,k;
if(getenv("newcfg"))newcfg=1;
if (!initialise) {
return(0);
}
/*
* Allocate and initialize PCI bus heads.
*/
/*
* PCI Bus 0
*/
#ifdef PCIE_GRAPHIC_CARD
if ( is_x4_mode() || is_pcie_vga_card() )
#else
if (is_x4_mode())
#endif
k = 1;
else
k = 4;
for (i = 0;i < k;i++) {
pd = pmalloc(sizeof(struct pci_device));
pb = pmalloc(sizeof(struct pci_bus));
if(pd == NULL || pb == NULL) {
printf("pci: can't alloc memory. pci not initialized\n");
return(-1);
}
pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));
pd->pa.pa_iot->bus_reverse = 1;
pd->pa.pa_iot->bus_base = BONITO_PCIIO_BASE_VA;
//printf("pd->pa.pa_iot=%p,bus_base=0x%x\n",pd->pa.pa_iot,pd->pa.pa_iot->bus_base);
pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));
pd->pa.pa_memt->bus_reverse = 1;
//pd->pa.pa_memt->bus_base = PCI_LOCAL_MEM_PCI_BASE;
pd->pa.pa_memt->bus_base = 0xb0000000;
pd->pa.pa_dmat = &bus_dmamap_tag;
pd->bridge.secbus = pb;
if (i == 0) {
_pci_head = pd;
} else if (i == 1){
_pci_head->next = pd;
} else if (i == 2){
_pci_head->next->next = pd;
} else if (i == 3){
_pci_head->next->next->next = pd;
}
#ifdef LS3_HT /* whd */
if (i == 0) {
#ifdef PCIE_GRAPHIC_CARD
if( is_pcie_vga_card() ) {
pb->minpcimemaddr = BONITO_PCILO0_BASE; // 0x4000_0000
pb->nextpcimemaddr = BONITO_PCILO0_BASE+BONITO_PCILO_SIZE; // 0x4000_0000 + 0x4000_0000
pb->minpciioaddr = PCI_IO_SPACE_BASE+0x0004000;
pb->nextpciioaddr = PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE; // 0 + 0x0200_0000
pb->pci_mem_base = BONITO_PCILO_BASE_VA;
pb->pci_io_base = BONITO_PCIIO_BASE_VA;
} else {
#endif
pb->minpcimemaddr = 0x10000000;
pb->nextpcimemaddr = 0x12000000;
pb->minpciioaddr = 0x18100000;
pb->nextpciioaddr = 0x18110000;
pb->pci_mem_base = 0x10000000;
pb->pci_io_base = 0x18100000;
#ifdef PCIE_GRAPHIC_CARD
}
#endif
} else if (i == 1){
pb->minpcimemaddr = 0x12000000;
pb->nextpcimemaddr = 0x14000000;
pb->minpciioaddr = 0x18500000;
pb->nextpciioaddr = 0x18510000;
pb->pci_mem_base = 0x12000000;
pb->pci_io_base = 0x18500000;
} else if (i == 2){
pb->minpcimemaddr = 0x14000000;
pb->nextpcimemaddr = 0x16000000;
pb->minpciioaddr = 0x18900000;
pb->nextpciioaddr = 0x18910000;
pb->pci_mem_base = 0x14000000;
pb->pci_io_base = 0x18900000;
} else if (i == 3){
pb->minpcimemaddr = 0x16000000;
pb->nextpcimemaddr = 0x18000000;
pb->minpciioaddr = 0x18d00000;
pb->nextpciioaddr = 0x18e10000;
pb->pci_mem_base = 0x16000000;
pb->pci_io_base = 0x18d00000;
}
#else
if(newcfg)
{
pb->minpcimemaddr = BONITO_PCILO1_BASE;//??????,???ܺ?linux??????ʼ??ַһ??,????xwindow????ʾ??????
pb->nextpcimemaddr = BONITO_PCIHI_BASE;
pd->pa.pa_memt->bus_base = 0xa0000000;
BONITO_PCIMAP =
BONITO_PCIMAP_WIN(0, PCI_MEM_SPACE_PCI_BASE+0x00000000) |
BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x14000000) |
BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x18000000) |
BONITO_PCIMAP_PCIMAP_2;
}
else
{
/*pci??ַ??cpu??ַ????,????pci memʱҪioreamapת??,ֱ??or 0xb0000000*/
pb->minpcimemaddr = 0x04000000;
pb->nextpcimemaddr = 0x08000000;
pd->pa.pa_memt->bus_base = 0xb0000000;
BONITO_PCIMAP =
BONITO_PCIMAP_WIN(0, PCI_MEM_SPACE_PCI_BASE+0x00000000) |
BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x04000000) |
BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x08000000) |
BONITO_PCIMAP_PCIMAP_2;
}
pb->minpciioaddr = 0x0004000;
pb->nextpciioaddr = BONITO_PCIIO_SIZE;
pb->pci_mem_base = BONITO_PCILO_BASE_VA;
pb->pci_io_base = BONITO_PCIIO_BASE_VA;
#endif
pb->max_lat = 255;
pb->fast_b2b = 1;
pb->prefetch = 1;
pb->bandwidth = 4000000;
pb->ndev = 1;
if (i == 0)
_pci_bushead = pb;
else if (i == 1)
_pci_bushead->next = pb;
else if (i == 2)
_pci_bushead->next->next = pb;
else if (i == 3)
_pci_bushead->next->next->next = pb;
_pci_bus[_max_pci_bus++] = pd;
bus_dmamap_tag._dmamap_offs = 0;
/*set pci base0 address and window size*/
pci_local_mem_pci_base = 0x0;
#ifdef LS3_HT
#else
BONITO_PCIBASE0 = 0x80000000;
#endif
}
#ifdef PCIE_GRAPHIC_CARD
if ( is_x4_mode() || is_pcie_vga_card() )
#else
if (is_x4_mode())
#endif
return(1);
else
return 4;
}
/*
* Called to reinitialise the bridge after we've scanned each PCI device
* and know what is possible. We also set up the interrupt controller
* routing and level control registers.
*/
void
_pci_hwreinit (void)
{
}
void
_pci_flush (void)
{
}
/*
* Map the CPU virtual address of an area of local memory to a PCI
* address that can be used by a PCI bus master to access it.
*/
vm_offset_t
_pci_dmamap(va, len)
vm_offset_t va;
unsigned int len;
{
#if 0
return(VA_TO_PA(va) + bus_dmamap_tag._dmamap_offs);
#endif
return(pci_local_mem_pci_base + VA_TO_PA (va));
}
/*
* Map the PCI address of an area of local memory to a CPU physical
* address.
*/
vm_offset_t
_pci_cpumap(pcia, len)
vm_offset_t pcia;
unsigned int len;
{
return PA_TO_VA(pcia - pci_local_mem_pci_base);
}
/*
* Make pci tag from bus, device and function data.
*/
pcitag_t
_pci_make_tag(bus, device, function)
int bus;
int device;
int function;
{
pcitag_t tag;
tag = (bus << 16) | (device << 11) | (function << 8);
return(tag);
}
/*
* Break up a pci tag to bus, device function components.
*/
void
_pci_break_tag(tag, busp, devicep, functionp)
pcitag_t tag;
int *busp;
int *devicep;
int *functionp;
{
if (busp) {
*busp = (tag >> 16) & 255;
}
if (devicep) {
*devicep = (tag >> 11) & 31;
}
if (functionp) {
*functionp = (tag >> 8) & 7;
}
}
int
_pci_canscan (pcitag_t tag)
{
int bus, device, function;
_pci_break_tag (tag, &bus, &device, &function);
return (1);
}
void
pci_sync_cache(p, adr, size, rw)
void *p;
vm_offset_t adr;
size_t size;
int rw;
{
CPU_IOFlushDCache(adr, size, rw);
}