Browse Source

Loongson2K: add pci probe only to support card need large pci spaces.

verify_dtb add pci bridge check for PCI_PROBE_ONLY.

Change-Id: I3a2d961390e2f3d74c61a4ff360c353731534d62
Signed-off-by: QiaoChong <qiaochong@loongson.cn>
master
QiaoChong 6 years ago
parent
commit
b8809cd0a9
  1. 164
      Targets/LS2K/dev/load_dtb.c
  2. 24
      Targets/LS2K/pci/pci_machdep.c

164
Targets/LS2K/dev/load_dtb.c

@ -1,5 +1,13 @@
#include "target/load_dtb.h"
#include <libfdt.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/nppbreg.h>
#ifdef PCI_PROBE_ONLY
int pci_probe_only = 2; /*0:nothing, 1:dtb pci use pmon allcated, kernel pci probe only, 2: dtb pci use pmon allocated,kernel pci reassigned.*/
#else
int pci_probe_only = 0;
#endif
int dtb_cksum(void *p, size_t s, int set)
{
@ -56,7 +64,130 @@ static int check_mac_ok(void)
return 1;
}
static int check_dma_ok(void)
static int check_pci_bridge_ok(void)
{
const void *nodep; /* property node pointer */
int nodeoffset; /* node offset from libfdt */
int len, id, i; /* length of the property */
char *ethernet_name[]={"/soc/pcie0_port0@40100000", "/soc/pcie0_port1@50000000", "/soc/pcie0_port2@54000000", "/soc/pcie0_port3@58000000", "/soc/pcie1_port0@60000000", "/soc/pcie1_port1@78000000"};
pcitag_t tag;
unsigned int val, val1, d, start, end;
int dev;
unsigned int data[12];
if (!pci_probe_only) return 1;
for(id = 0, dev=9;id < sizeof(ethernet_name)/sizeof(ethernet_name[0]);id++,dev++) {
nodeoffset = fdt_path_offset (working_fdt, ethernet_name[id]);
if (nodeoffset < 0) {
return 1; //no ethernet device, do nothing
}
nodep = fdt_getprop (working_fdt, nodeoffset, (const char* )"ranges", &len);
if(len <= 0) {
return 1; //no mac prop in ethernet, do nothing
}
memcpy(data, nodep, 12*4);
/*pci foarmat(name/len) is flag/1 pciaddr/2 cpuaddr/1 len/2*/
tag = _pci_make_tag(0, dev, 0);
val = _pci_conf_read32(dev, 0x00);
if ( val != 0xffffffff){
val =_pci_conf_read32(tag, 0x20);
start = (val & 0xfff0) << 16;
end = val & 0xfff00000;
d = cpu_to_be32(start);
if(data[2] != data[3] || data[2] != d)
return 0;
d = cpu_to_be32(end - start + 0x100000);
if(data[5] != d)
return 0;
val =_pci_conf_read32(tag, 0x30);
val1 =_pci_conf_read32(tag, 0x1c);
start = ((val&0xffff)<<16)+((val1&0xf0)<<8) + 0x18000000;
end = (val&0xffff0000)+(val1&0xf000) + 0x18000000;
d = cpu_to_be32(start);
if(data[6+3] != data[6+2] || data[6+2] != d)
return 0;
d = cpu_to_be32(end - start + 0x1000);
if(data[6+5] != d)
return 0;
}
else
{
if(data[5] != 0 || data[6+5] != 0)
return 0;
}
}
return 1;
}
static int update_pci_bridge(void * ssp)
{
const void *nodep; /* property node pointer */
int nodeoffset; /* node offset from libfdt */
int len, id, i; /* length of the property */
u8 mac_addr[6] = {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}; //default mac address
char *ethernet_name[]={"/soc/pcie0_port0@40100000", "/soc/pcie0_port1@50000000", "/soc/pcie0_port2@54000000", "/soc/pcie0_port3@58000000", "/soc/pcie1_port0@60000000", "/soc/pcie1_port1@78000000"};
pcitag_t tag;
unsigned int val, val1, start, end;
int dev;
unsigned int data[12];
unsigned nmem=0x18000000, nio=0x1a000000;
if (!pci_probe_only) return 0;
for (id = 0, dev=9;id < sizeof(ethernet_name)/sizeof(ethernet_name[0]);id++,dev++) {
nodeoffset = fdt_path_offset (ssp, ethernet_name[id]);
if (nodeoffset < 0) {
return 1; //no ethernet device, do nothing
}
nodep = fdt_getprop (ssp, nodeoffset, (const char* )"ranges", &len);
if(len <= 0) {
return 1; //no mac prop in ethernet, do nothing
}
memcpy(data, nodep, 12*4);
/*pci foarmat(name/len) is flag/1 pciaddr/2 cpuaddr/1 len/2*/
tag = _pci_make_tag(0, dev, 0);
val = _pci_conf_read32(tag, 0x00);
if ( val != 0xffffffff){
val =_pci_conf_read32(tag, 0x20);
start = (val & 0xfff0) << 16;
end = val & 0xfff00000;
data[3] = data[2] = cpu_to_be32(start);
data[5] = cpu_to_be32(end - start + 0x100000);
val =_pci_conf_read32(tag, 0x30);
val1 =_pci_conf_read32(tag, 0x1c);
start = ((val&0xffff)<<16)+((val1&0xf0)<<8) + 0x18000000;
end = (val&0xffff0000)+(val1&0xf000) + 0x18000000;
data[6+3] = data[6+2] = cpu_to_be32(start);
data[6+5] = cpu_to_be32(end - start + 0x1000);
}
else
{
nmem -= 0x100000;
nio -= 0x1000;
data[3] = data[2] = cpu_to_be32(nmem);
data[5] = cpu_to_be32(0x100000);
data[6+3] = data[6+2] = cpu_to_be32(nio);
data[6+5] = cpu_to_be32(0x1000);
}
if (fdt_setprop(ssp, nodeoffset, "ranges", data, 12*4))
{
printf("set ranges error\n");
}
}
return 0;
}
static int check_prop_ok(char *propname, int wanted)
{
int nodeoffset, len;
const void *nodep; /* property node pointer */
@ -68,9 +199,9 @@ static int check_dma_ok(void)
*/
return 1; //do nothing
}
nodep = fdt_getprop (working_fdt, nodeoffset, "dma-coherent", &len);
nodep = fdt_getprop (working_fdt, nodeoffset, propname, &len);
if(ls2k_version()) {
if(wanted) {
if(!nodep)
return 0; //should be reset
} else
@ -107,7 +238,7 @@ static int update_mac(void * ssp, int id)
return 0;
}
static int update_dma_flag(void * ssp)
static int update_prop_flag(void * ssp, char *propname, int wanted)
{
int nodeoffset, len;
const void *nodep; /* property node pointer */
@ -120,21 +251,21 @@ static int update_dma_flag(void * ssp)
printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset));
return 1;
}
nodep = fdt_getprop (ssp, nodeoffset, "dma-coherent", &len);
nodep = fdt_getprop (ssp, nodeoffset, propname, &len);
if(ls2k_version()) {
if(wanted) {
if(!nodep) {
if(fdt_setprop(ssp, nodeoffset, "dma-coherent", NULL, 0))
printf("Add property \"dma-coherent\" error\n");
if(fdt_setprop(ssp, nodeoffset, propname, NULL, 0))
printf("Add property \"%s\" error\n", propname);
else
printf("Add property \"dma-coherent\"\n");
printf("Add property \"%s\"\n", propname);
}
} else {
if(nodep) {
if(fdt_delprop(ssp, nodeoffset, "dma-coherent"))
printf("Delete property \"dma-coherent\" error\n");
if(fdt_delprop(ssp, nodeoffset, propname))
printf("Delete property \"%s\" error\n", propname);
else
printf("Delete property \"dma-coherent\"\n");
printf("Delete property \"%s\"\n", propname);
}
}
return 0;
@ -155,12 +286,14 @@ void verify_dtb(void)
return;
}
printf("dtb verify ok!!!\n");
if(!check_mac_ok() || !check_dma_ok()) {
if(!check_mac_ok() || !check_prop_ok("dma-coherent", ls2k_version()) || !check_prop_ok("pci-probe-only", pci_probe_only == 1) || !check_pci_bridge_ok()) {
u8 buff[DTB_SIZE] = {0};
fdt_open_into(working_fdt, buff + 4, DTB_SIZE - 8);
update_dma_flag(buff + 4);
update_prop_flag(buff + 4, "dma-coherent", ls2k_version());
update_prop_flag(buff + 4, "pci-probe-only", pci_probe_only == 1);
update_mac(buff + 4, 0);
update_mac(buff + 4, 1);
update_pci_bridge(buff + 4);
dtb_cksum(buff, DTB_SIZE - 4, 1);
tgt_flashprogram((char *)working_fdt - 4, DTB_SIZE, buff, 0);
}
@ -507,7 +640,8 @@ int load_dtb(int argc,char **argv)
printf("dtb has a bad bad magic, please reload dtb file!!!\n");
return 0;
}
update_dma_flag(heaptop + 4);
update_prop_flag(heaptop + 4, "dma-coherent", ls2k_version());
update_prop_flag(heaptop + 4, "pci-probe-only", pci_probe_only);
update_mac(heaptop + 4, 0);
update_mac(heaptop + 4, 1);
dtb_cksum(heaptop, DTB_SIZE - 4, 1);

24
Targets/LS2K/pci/pci_machdep.c

@ -60,6 +60,7 @@ extern int _pciverbose;
extern char hwethadr[6];
struct pci_device *_pci_bus[16];
int _max_pci_bus = 0;
extern int pci_probe_only;
/* PCI mem regions in PCI space */
@ -82,9 +83,13 @@ _pci_hwinit(initialise, iot, memt)
struct pci_device *pd;
struct pci_bus *pb;
int newcfg=0;
char *env;
SBD_DISPLAY ("HW-0", 0);
if(getenv("newcfg"))newcfg=1;
if ((env = getenv("pci_probe_only")))
pci_probe_only = strtoul(env, 0, 0);
if (!initialise) {
return(0);
}
@ -117,13 +122,17 @@ _pci_hwinit(initialise, iot, memt)
_pci_head = pd;
SBD_DISPLAY ("HW-3", 0);
#undef BONITO_PCILO0_BASE
#undef BONITO_PCILO_SIZE;
#define BONITO_PCILO0_BASE 0x10000000
#define BONITO_PCILO_SIZE 0x08000000
if(pci_probe_only)
{
pb->minpcimemaddr = 0x40100000;
pb->nextpcimemaddr = 0x80000000;
}
else
{
pb->minpcimemaddr = 0x10000000;
pb->nextpcimemaddr = 0x18000000;
}
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;
@ -321,6 +330,9 @@ pcireg_t pci_alloc_fixmemio(struct pci_win *pm)
}
else
{
if(pci_probe_only)
return -1;
if(reg == PCI_MEMBASE_1)
{
size = pci_config_array[idx].mem_end - pci_config_array[idx].mem_start + 1;

Loading…
Cancel
Save