summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2010-07-11 21:08:29 +0000
committerraj <raj@FreeBSD.org>2010-07-11 21:08:29 +0000
commit6496d826ccfca6b78860dfa86efcb3f96cb6053f (patch)
tree827f9dce3768613a609f3a9e594b123936ec2e0e /sys/powerpc
parent710dc13ac9dfbfa4fead6e52f9efb9e7b6af119e (diff)
downloadFreeBSD-src-6496d826ccfca6b78860dfa86efcb3f96cb6053f.zip
FreeBSD-src-6496d826ccfca6b78860dfa86efcb3f96cb6053f.tar.gz
Convert Freescale PowerPC platforms to FDT convention.
The following systems are affected: - MPC8555CDS - MPC8572DS This overhaul covers the following major changes: - All integrated peripherals drivers for Freescale MPC85XX SoC, which are currently in the FreeBSD source tree are reworked and adjusted so they derive config data out of the device tree blob (instead of hard coded / tabelarized values). - This includes: LBC, PCI / PCI-Express, I2C, DS1553, OpenPIC, TSEC, SEC, QUICC, UART, CFI. - Thanks to the common FDT infrastrucutre (fdtbus, simplebus) we retire ocpbus(4) driver, which was based on hard-coded config data. Note that world for these platforms has to be built WITH_FDT. Reviewed by: imp Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/booke/locore.S1
-rw-r--r--sys/powerpc/booke/machdep.c96
-rw-r--r--sys/powerpc/booke/platform_bare.c69
-rw-r--r--sys/powerpc/booke/pmap.c16
-rw-r--r--sys/powerpc/conf/MPC85XX6
-rw-r--r--sys/powerpc/include/bootinfo.h72
-rw-r--r--sys/powerpc/include/fdt.h54
-rw-r--r--sys/powerpc/include/metadata.h3
-rw-r--r--sys/powerpc/include/ocpbus.h51
-rw-r--r--sys/powerpc/mpc85xx/atpic.c2
-rw-r--r--sys/powerpc/mpc85xx/ds1553_bus_fdt.c (renamed from sys/powerpc/mpc85xx/ds1553_bus_lbc.c)19
-rw-r--r--sys/powerpc/mpc85xx/i2c.c22
-rw-r--r--sys/powerpc/mpc85xx/lbc.c642
-rw-r--r--sys/powerpc/mpc85xx/lbc.h52
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c37
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h52
-rw-r--r--sys/powerpc/mpc85xx/nexus.c9
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c622
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.h112
-rw-r--r--sys/powerpc/mpc85xx/openpic_fdt.c93
-rw-r--r--sys/powerpc/mpc85xx/opic.c105
-rw-r--r--sys/powerpc/mpc85xx/pci_fdt.c1067
-rw-r--r--sys/powerpc/mpc85xx/pci_ocp.c850
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c2
24 files changed, 1834 insertions, 2220 deletions
diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S
index 86dff00..b5b5090 100644
--- a/sys/powerpc/booke/locore.S
+++ b/sys/powerpc/booke/locore.S
@@ -39,7 +39,6 @@
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <machine/tlb.h>
-#include <machine/bootinfo.h>
#define TMPSTACKSZ 16384
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index 274fe6e..054b0ed 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -130,13 +130,14 @@ __FBSDID("$FreeBSD$");
#include <machine/mmuvar.h>
#include <machine/sigframe.h>
#include <machine/metadata.h>
-#include <machine/bootinfo.h>
#include <machine/platform.h>
#include <sys/linker.h>
#include <sys/reboot.h>
-#include <powerpc/mpc85xx/ocpbus.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
#include <powerpc/mpc85xx/mpc85xx.h>
#ifdef DDB
@@ -169,8 +170,6 @@ int cold = 1;
long realmem = 0;
long Maxmem = 0;
-struct bootinfo *bootinfo;
-
char machine[] = "powerpc";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
@@ -185,7 +184,6 @@ static void cpu_e500_startup(void *);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL);
void print_kernel_section_addr(void);
-void print_bootinfo(void);
void print_kenv(void);
u_int e500_init(u_int32_t, u_int32_t, void *);
@@ -259,40 +257,6 @@ print_kenv(void)
}
void
-print_bootinfo(void)
-{
- struct bi_mem_region *mr;
- struct bi_eth_addr *eth;
- int i, j;
-
- debugf("bootinfo:\n");
- if (bootinfo == NULL) {
- debugf(" no bootinfo, null ptr\n");
- return;
- }
-
- debugf(" version = 0x%08x\n", bootinfo->bi_version);
- debugf(" ccsrbar = 0x%08x\n", bootinfo->bi_bar_base);
- debugf(" cpu_clk = 0x%08x\n", bootinfo->bi_cpu_clk);
- debugf(" bus_clk = 0x%08x\n", bootinfo->bi_bus_clk);
-
- debugf(" mem regions:\n");
- mr = (struct bi_mem_region *)bootinfo->bi_data;
- for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++)
- debugf(" #%d, base = 0x%08x, size = 0x%08x\n", i,
- mr->mem_base, mr->mem_size);
-
- debugf(" eth addresses:\n");
- eth = (struct bi_eth_addr *)mr;
- for (i = 0; i < bootinfo->bi_eth_addr_no; i++, eth++) {
- debugf(" #%d, addr = ", i);
- for (j = 0; j < 6; j++)
- debugf("%02x ", eth->mac_addr[j]);
- debugf("\n");
- }
-}
-
-void
print_kernel_section_addr(void)
{
@@ -306,54 +270,29 @@ print_kernel_section_addr(void)
debugf(" _end = 0x%08x\n", (uint32_t)_end);
}
-struct bi_mem_region *
-bootinfo_mr(void)
-{
-
- return ((struct bi_mem_region *)bootinfo->bi_data);
-}
-
-struct bi_eth_addr *
-bootinfo_eth(void)
-{
- struct bi_mem_region *mr;
- struct bi_eth_addr *eth;
- int i;
-
- /* Advance to the eth section */
- mr = bootinfo_mr();
- for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++)
- ;
-
- eth = (struct bi_eth_addr *)mr;
- return (eth);
-}
-
u_int
e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
{
struct pcpu *pc;
void *kmdp;
- vm_offset_t end;
+ vm_offset_t dtbp, end;
uint32_t csr;
kmdp = NULL;
end = endkernel;
+ dtbp = (vm_offset_t)NULL;
/*
- * Parse metadata and fetch parameters. This must be done as the first
- * step as we need bootinfo data to at least init the console
+ * Parse metadata and fetch parameters.
*/
if (mdp != NULL) {
preload_metadata = mdp;
kmdp = preload_search_by_type("elf kernel");
if (kmdp != NULL) {
- bootinfo = (struct bootinfo *)preload_search_info(kmdp,
- MODINFO_METADATA | MODINFOMD_BOOTINFO);
-
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+ dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
@@ -362,8 +301,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
}
} else {
/*
- * We should scream but how? - without CCSR bar (in bootinfo)
- * cannot even output anything...
+ * We should scream but how? Cannot even output anything...
*/
/*
@@ -372,11 +310,22 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
* restore everything as the TLB have all been reprogrammed
* in the locore etc...)
*/
- while(1);
+ while (1);
}
+ if (OF_install(OFW_FDT, 0) == FALSE)
+ while (1);
+
+ if (OF_init((void *)dtbp) != 0)
+ while (1);
+
+ if (fdt_immr_addr() != 0)
+ while (1);
+
+ OF_interpret("perform-fixup", 0);
+
/* Initialize TLB1 handling */
- tlb1_init(bootinfo->bi_bar_base);
+ tlb1_init(fdt_immr_pa);
/* Reset Time Base */
mttb(0);
@@ -417,7 +366,8 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
csr = ccsr_read4(OCP85XX_L2CTL);
debugf(" L2CTL = 0x%08x\n", csr);
- print_bootinfo();
+ debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp);
+
print_kernel_section_addr();
print_kenv();
//tlb1_print_entries();
diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c
index 92d8ec8..627470d 100644
--- a/sys/powerpc/booke/platform_bare.c
+++ b/sys/powerpc/booke/platform_bare.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/smp.h>
-#include <machine/bootinfo.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/hid.h>
@@ -45,8 +44,12 @@ __FBSDID("$FreeBSD$");
#include <machine/spr.h>
#include <machine/vmparam.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
#include <powerpc/mpc85xx/mpc85xx.h>
-#include <powerpc/mpc85xx/ocpbus.h>
#include "platform_if.h"
@@ -91,7 +94,8 @@ PLATFORM_DEF(bare_platform);
static int
bare_probe(platform_t plat)
{
- uint32_t ver;
+ uint32_t ver, sr;
+ int i, law_max, tgt;
ver = SVR_VER(mfspr(SPR_SVR));
if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
@@ -99,6 +103,23 @@ bare_probe(platform_t plat)
else
maxcpu = 1;
+ /*
+ * Clear local access windows. Skip DRAM entries, so we don't shoot
+ * ourselves in the foot.
+ */
+ law_max = law_getmax();
+ for (i = 0; i < law_max; i++) {
+ sr = ccsr_read4(OCP85XX_LAWSR(i));
+ if ((sr & 0x80000000) == 0)
+ continue;
+ tgt = (sr & 0x01f00000) >> 20;
+ if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
+ tgt == OCP85XX_TGTIF_RAM_INTL)
+ continue;
+
+ ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
+ }
+
return (BUS_PROBE_GENERIC);
}
@@ -109,24 +130,22 @@ void
bare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
struct mem_region **avail, int *availsz)
{
- struct bi_mem_region *mr;
- int i;
-
- /* Initialize memory regions table */
- mr = bootinfo_mr();
- for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) {
- if (i == MEM_REGIONS)
- break;
- if (mr->mem_base < 1048576) {
+ uint32_t memsize;
+ int i, rv;
+
+ rv = fdt_get_mem_regions(avail_regions, availsz, &memsize);
+
+ if (rv != 0)
+ return;
+
+ for (i = 0; i < *availsz; i++) {
+ if (avail_regions[i].mr_start < 1048576) {
+ avail_regions[i].mr_size =
+ avail_regions[i].mr_size -
+ (1048576 - avail_regions[i].mr_start);
avail_regions[i].mr_start = 1048576;
- avail_regions[i].mr_size = mr->mem_size -
- (1048576 - mr->mem_base);
- } else {
- avail_regions[i].mr_start = mr->mem_base;
- avail_regions[i].mr_size = mr->mem_size;
}
}
- *availsz = i;
*avail = avail_regions;
/* On the bare metal platform phys == avail memory */
@@ -138,12 +157,24 @@ static u_long
bare_timebase_freq(platform_t plat, struct cpuref *cpuref)
{
u_long ticks = -1;
+ phandle_t cpus, child;
+ pcell_t freq;
+
+ if ((cpus = OF_finddevice("/cpus")) == 0)
+ goto out;
+
+ if ((child = OF_child(cpus)) == 0)
+ goto out;
+ if (OF_getprop(child, "bus-frequency", (void *)&freq,
+ sizeof(freq)) <= 0)
+ goto out;
/*
* Time Base and Decrementer are updated every 8 CCB bus clocks.
* HID0[SEL_TBCLK] = 0
*/
- ticks = bootinfo->bi_bus_clk / 8;
+ ticks = freq / 8;
+out:
if (ticks <= 0)
panic("Unable to determine timebase frequency!");
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 11a67af..7f2feb9 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/uma.h>
-#include <machine/bootinfo.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <machine/platform.h>
@@ -2507,7 +2506,6 @@ struct pmap_md *
mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
{
static struct pmap_md md;
- struct bi_mem_region *mr;
pte_t *pte;
vm_offset_t va;
@@ -2565,16 +2563,18 @@ mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
return (NULL);
}
} else { /* minidumps */
- mr = bootinfo_mr();
+ mem_regions(&physmem_regions, &physmem_regions_sz,
+ &availmem_regions, &availmem_regions_sz);
+
if (prev == NULL) {
/* first physical chunk. */
- md.md_paddr = mr->mem_base;
- md.md_size = mr->mem_size;
+ md.md_paddr = physmem_regions[0].mr_start;
+ md.md_size = physmem_regions[0].mr_size;
md.md_vaddr = ~0UL;
md.md_index = 1;
- } else if (md.md_index < bootinfo->bi_mem_reg_no) {
- md.md_paddr = mr[md.md_index].mem_base;
- md.md_size = mr[md.md_index].mem_size;
+ } else if (md.md_index < physmem_regions_sz) {
+ md.md_paddr = physmem_regions[md.md_index].mr_start;
+ md.md_size = physmem_regions[md.md_index].mr_size;
md.md_vaddr = ~0UL;
md.md_index++;
} else {
diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX
index a2a8de4..ef36ab5 100644
--- a/sys/powerpc/conf/MPC85XX
+++ b/sys/powerpc/conf/MPC85XX
@@ -24,8 +24,10 @@ options COMPAT_43
options DDB
#options DEADLKRES
options DEVICE_POLLING
-options HZ=1000
#options DIAGNOSTIC
+options FDT
+makeoptions FDT_DTS_FILE=mpc8572ds.dts
+#makeoptions FDT_DTS_FILE=mpc8555cds.dts
options FFS
options GDB
options GEOM_PART_GPT
@@ -64,7 +66,7 @@ device ether
device fxp
device iic
device iicbus
-device isa
+#device isa
device loop
device md
device miibus
diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h
deleted file mode 100644
index 599516e..0000000
--- a/sys/powerpc/include/bootinfo.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (C) 2006-2008 Semihalf, Marian Balakowicz <m8@semihalf.com>
- * All rights reserved.
- *
- * 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. 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_BOOTINFO_H_
-#define _MACHINE_BOOTINFO_H_
-
-#if !defined(LOCORE)
-
-/* Platform hardware spec, received from loader(8) */
-
-#define BI_VERSION 1
-
-struct bi_mem_region {
- vm_paddr_t mem_base;
- vm_size_t mem_size;
-};
-
-struct bi_eth_addr {
- u_int8_t mac_addr[6];
-};
-
-struct bootinfo {
- u_int32_t bi_version;
- vm_offset_t bi_bar_base;
- u_int32_t bi_cpu_clk;
- u_int32_t bi_bus_clk;
- u_int8_t bi_mem_reg_no;
- u_int8_t bi_eth_addr_no;
-
- u_int8_t bi_data[1];
- /*
- * The bi_data container is allocated in run time and has the
- * following layout:
- *
- * - bi_mem_reg_no elements of struct bi_mem_region
- * - bi_eth_addr_no elements of struct bi_eth_addr
- */
-};
-
-extern struct bootinfo *bootinfo;
-
-struct bi_mem_region *bootinfo_mr(void);
-struct bi_eth_addr *bootinfo_eth(void);
-#endif
-
-#endif /* _MACHINE_BOOTINFO_H_ */
diff --git a/sys/powerpc/include/fdt.h b/sys/powerpc/include/fdt.h
new file mode 100644
index 0000000..ea29d68
--- /dev/null
+++ b/sys/powerpc/include/fdt.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_FDT_H_
+#define _MACHINE_FDT_H_
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/platform.h>
+#include <machine/vmparam.h>
+
+/*
+ * This is the base virtual address the internal mem-mapped registers (IMMR)
+ * range is available at.
+ */
+#define FDT_IMMR_VA CCSRBAR_VA
+
+/* Max interrupt number */
+#define FDT_INTR_MAX INTR_VECTORS
+
+/*
+ * Bus space tag. XXX endianess info needs to be derived from the blob.
+ */
+#define fdtbus_bs_tag (&bs_be_tag)
+
+#endif /* _MACHINE_FDT_H_ */
diff --git a/sys/powerpc/include/metadata.h b/sys/powerpc/include/metadata.h
index 8c15e6a..5a58839 100644
--- a/sys/powerpc/include/metadata.h
+++ b/sys/powerpc/include/metadata.h
@@ -32,7 +32,6 @@
#define MODINFOMD_ENVP 0x1001
#define MODINFOMD_HOWTO 0x1002
#define MODINFOMD_KERNEND 0x1003
-#define MODINFOMD_BOOTINFO 0x1004
-#define MODINFOMD_DTBP 0x1005
+#define MODINFOMD_DTBP 0x1004
#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/powerpc/include/ocpbus.h b/sys/powerpc/include/ocpbus.h
deleted file mode 100644
index daa952b..0000000
--- a/sys/powerpc/include/ocpbus.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 2006 Juniper Networks
- * All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_OCPBUS_H_
-#define _MACHINE_OCPBUS_H_
-
-#define OCPBUS_IVAR_DEVTYPE 1
-#define OCPBUS_IVAR_CLOCK 2
-#define OCPBUS_IVAR_HWUNIT 3
-#define OCPBUS_IVAR_MACADDR 4
-
-/* Device types. */
-#define OCPBUS_DEVTYPE_PIC 1
-#define OCPBUS_DEVTYPE_TSEC 2
-#define OCPBUS_DEVTYPE_UART 3
-#define OCPBUS_DEVTYPE_QUICC 4
-#define OCPBUS_DEVTYPE_PCIB 5
-#define OCPBUS_DEVTYPE_LBC 6
-#define OCPBUS_DEVTYPE_I2C 7
-#define OCPBUS_DEVTYPE_SEC 8
-
-/* PIC IDs */
-#define OPIC_ID 0
-#define ATPIC_ID 1
-
-#endif /* _MACHINE_OCPBUS_H_ */
diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c
index 3a749c7..e903dbc 100644
--- a/sys/powerpc/mpc85xx/atpic.c
+++ b/sys/powerpc/mpc85xx/atpic.c
@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
#include <machine/ocpbus.h>
#include <machine/pio.h>
-#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
#include <dev/ic/i8259.h>
diff --git a/sys/powerpc/mpc85xx/ds1553_bus_lbc.c b/sys/powerpc/mpc85xx/ds1553_bus_fdt.c
index 419a8a8..ffbbee1 100644
--- a/sys/powerpc/mpc85xx/ds1553_bus_lbc.c
+++ b/sys/powerpc/mpc85xx/ds1553_bus_fdt.c
@@ -23,6 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/ds1553_bus_lbc.c,v 1.2 2009/06/24 15:48:20 raj
*/
#include <sys/cdefs.h>
@@ -43,9 +44,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
-#include <powerpc/mpc85xx/ds1553_reg.h>
-#include <powerpc/mpc85xx/lbc.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include "ds1553_reg.h"
#include "clock_if.h"
static devclass_t rtc_devclass;
@@ -76,20 +77,12 @@ DRIVER_MODULE(rtc, lbc, rtc_driver, rtc_devclass, 0, 0);
static int
rtc_probe(device_t dev)
{
- uintptr_t devtype;
- int error;
-
- error = BUS_READ_IVAR(device_get_parent(dev), dev, LBC_IVAR_DEVTYPE,
- &devtype);
- if (error)
- return (error);
- if (devtype != LBC_DEVTYPE_RTC)
- return (EINVAL);
+ if (!ofw_bus_is_compatible(dev, "dallas,ds1553"))
+ return (ENXIO);
device_set_desc(dev, "Dallas Semiconductor DS1553 RTC");
-
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
static int
diff --git a/sys/powerpc/mpc85xx/i2c.c b/sys/powerpc/mpc85xx/i2c.c
index 003bd6f..5b698f1 100644
--- a/sys/powerpc/mpc85xx/i2c.c
+++ b/sys/powerpc/mpc85xx/i2c.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
-#include <machine/ocpbus.h>
#include <sys/rman.h>
#include <sys/lock.h>
@@ -46,7 +45,8 @@ __FBSDID("$FreeBSD$");
#include <dev/iicbus/iicbus.h>
#include "iicbus_if.h"
-#include <powerpc/mpc85xx/ocpbus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#define I2C_ADDR_REG 0x00 /* I2C slave address register */
#define I2C_FDR_REG 0x04 /* I2C frequency divider register */
@@ -124,7 +124,7 @@ static driver_t i2c_driver = {
};
static devclass_t i2c_devclass;
-DRIVER_MODULE(i2c, ocpbus, i2c_driver, i2c_devclass, 0, 0);
+DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
static __inline void
@@ -157,7 +157,7 @@ i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start)
int err;
uint8_t status;
- status = i2c_read_reg(sc,I2C_STATUS_REG);
+ status = i2c_read_reg(sc, I2C_STATUS_REG);
if (status & I2CSR_MIF) {
if (write && start && (status & I2CSR_RXAK)) {
debugf("no ack %s", start ?
@@ -188,19 +188,9 @@ error:
static int
i2c_probe(device_t dev)
{
- device_t parent;
struct i2c_softc *sc;
- uintptr_t devtype;
- int error;
-
- parent = device_get_parent(dev);
-
- error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
- if (error)
- return (error);
-
- if (devtype != OCPBUS_DEVTYPE_I2C)
+ if (!ofw_bus_is_compatible(dev, "fsl-i2c"))
return (ENXIO);
sc = device_get_softc(dev);
@@ -209,7 +199,7 @@ i2c_probe(device_t dev)
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
RF_ACTIVE);
if (sc->res == NULL) {
- device_printf(dev, "could not allocate resources");
+ device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c
index 2267245..e993bce 100644
--- a/sys/powerpc/mpc85xx/lbc.c
+++ b/sys/powerpc/mpc85xx/lbc.c
@@ -1,8 +1,12 @@
/*-
* Copyright (c) 2006-2008, Juniper Networks, Inc.
* Copyright (c) 2008 Semihalf, Rafal Czubak
+ * Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -39,70 +43,54 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/rman.h>
#include <machine/bus.h>
-#include <machine/ocpbus.h>
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <powerpc/mpc85xx/lbc.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
#include <powerpc/mpc85xx/mpc85xx.h>
-#include <powerpc/mpc85xx/ocpbus.h>
-struct lbc_softc {
- device_t sc_dev;
+#include "ofw_bus_if.h"
+#include "lbc.h"
- struct resource *sc_res;
- bus_space_handle_t sc_bsh;
- bus_space_tag_t sc_bst;
- int sc_rid;
+#define DEBUG
+#undef DEBUG
- struct rman sc_rman;
- vm_offset_t sc_kva[LBC_DEV_MAX];
-};
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
+ printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
-struct lbc_devinfo {
- int lbc_devtype;
- /* LBC child unit. It also represents resource table entry number */
- int lbc_unit;
-};
+static __inline void
+lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val)
+{
-/* Resources for MPC8555CDS system */
-const struct lbc_resource mpc85xx_lbc_resources[] = {
- /* Boot flash bank */
- {
- LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16,
- LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
- LBCRES_ATOM_DISABLED, 0
- },
-
- /* Second flash bank */
- {
- LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16,
- LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
- LBCRES_ATOM_DISABLED, 0
- },
-
- /* DS1553 RTC/NVRAM */
- {
- LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8,
- LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
- LBCRES_ATOM_DISABLED, 0
- },
-
- {0}
-};
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
+}
+
+static __inline uint32_t
+lbc_read_reg(struct lbc_softc *sc, bus_size_t off)
+{
+
+ return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
+}
+
+static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information");
static int lbc_probe(device_t);
static int lbc_attach(device_t);
static int lbc_shutdown(device_t);
-static int lbc_get_resource(device_t, device_t, int, int, u_long *,
- u_long *);
static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
u_long, u_long, u_long, u_int);
static int lbc_print_child(device_t, device_t);
static int lbc_release_resource(device_t, device_t, int, int,
struct resource *);
-static int lbc_read_ivar(device_t, device_t, int, uintptr_t *);
+static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t);
/*
* Bus interface definition
@@ -115,16 +103,22 @@ static device_method_t lbc_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, lbc_print_child),
- DEVMETHOD(bus_read_ivar, lbc_read_ivar),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, NULL),
- DEVMETHOD(bus_get_resource, NULL),
DEVMETHOD(bus_alloc_resource, lbc_alloc_resource),
DEVMETHOD(bus_release_resource, lbc_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
{ 0, 0 }
};
@@ -133,22 +127,10 @@ static driver_t lbc_driver = {
lbc_methods,
sizeof(struct lbc_softc)
};
-devclass_t lbc_devclass;
-DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0);
-
-static __inline void
-lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val)
-{
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
-}
-
-static __inline uint32_t
-lbc_read_reg(struct lbc_softc *sc, bus_size_t off)
-{
+devclass_t lbc_devclass;
- return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
-}
+DRIVER_MODULE(lbc, fdtbus, lbc_driver, lbc_devclass, 0, 0);
/*
* Calculate address mask used by OR(n) registers. Use memory region size to
@@ -176,103 +158,101 @@ lbc_address_mask(uint32_t size)
return (0xffff8000 << (n - 15));
}
-static device_t
-lbc_mk_child(device_t dev, const struct lbc_resource *lbcres)
+static void
+lbc_banks_unmap(struct lbc_softc *sc)
{
- struct lbc_devinfo *dinfo;
- device_t child;
+ int i;
- if (lbcres->lbr_unit > LBC_DEV_MAX - 1)
- return (NULL);
+ for (i = 0; i < LBC_DEV_MAX; i++) {
+ if (sc->sc_banks[i].size == 0)
+ continue;
- child = device_add_child(dev, NULL, -1);
- if (child == NULL) {
- device_printf(dev, "could not add LBC child device\n");
- return (NULL);
+ law_disable(OCP85XX_TGTIF_LBC, sc->sc_banks[i].pa,
+ sc->sc_banks[i].size);
+ pmap_unmapdev(sc->sc_banks[i].va, sc->sc_banks[i].size);
}
- dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
- dinfo->lbc_devtype = lbcres->lbr_devtype;
- dinfo->lbc_unit = lbcres->lbr_unit;
- device_set_ivars(child, dinfo);
- return (child);
}
static int
-lbc_init_child(device_t dev, device_t child)
+lbc_banks_map(struct lbc_softc *sc)
{
- struct lbc_softc *sc;
- struct lbc_devinfo *dinfo;
- const struct lbc_resource *res;
u_long start, size;
- uint32_t regbuff;
- int error, unit;
-
- sc = device_get_softc(dev);
- dinfo = device_get_ivars(child);
+ int error, i;
- res = mpc85xx_lbc_resources;
-
- regbuff = 0;
- unit = -1;
- for (; res->lbr_devtype; res++) {
- if (res->lbr_unit != dinfo->lbc_unit)
+ for (i = 0; i < LBC_DEV_MAX; i++) {
+ if (sc->sc_banks[i].size == 0)
continue;
- start = res->lbr_base_addr;
- size = res->lbr_size;
- unit = res->lbr_unit;
+ /* Physical address start/size. */
+ start = sc->sc_banks[i].pa;
+ size = sc->sc_banks[i].size;
/*
- * Configure LAW for this LBC device and map its physical
- * memory region into KVA
+ * Configure LAW for this LBC bank (CS) and map its physical
+ * memory region into KVA.
*/
error = law_enable(OCP85XX_TGTIF_LBC, start, size);
if (error)
return (error);
- sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size);
- if (sc->sc_kva[unit] == 0) {
- law_disable(OCP85XX_TGTIF_LBC, start, size);
+ sc->sc_banks[i].va = (vm_offset_t)pmap_mapdev(start, size);
+ if (sc->sc_banks[i].va == 0) {
+ lbc_banks_unmap(sc);
return (ENOSPC);
}
+ }
+ return (0);
+}
+
+static int
+lbc_banks_enable(struct lbc_softc *sc)
+{
+ u_long size;
+ uint32_t regval;
+ int error, i;
+ for (i = 0; i < LBC_DEV_MAX; i++) {
+ size = sc->sc_banks[i].size;
+ if (size == 0)
+ continue;
/*
- * Compute and program BR value
+ * Compute and program BR value.
*/
- regbuff |= start;
+ regval = 0;
+ regval |= sc->sc_banks[i].pa;
- switch (res->lbr_port_size) {
+ switch (sc->sc_banks[i].width) {
case 8:
- regbuff |= (1 << 11);
+ regval |= (1 << 11);
break;
case 16:
- regbuff |= (2 << 11);
+ regval |= (2 << 11);
break;
case 32:
- regbuff |= (3 << 11);
+ regval |= (3 << 11);
break;
default:
error = EINVAL;
goto fail;
}
- regbuff |= (res->lbr_decc << 9);
- regbuff |= (res->lbr_wp << 8);
- regbuff |= (res->lbr_msel << 5);
- regbuff |= (res->lbr_atom << 2);
- regbuff |= 1;
+ regval |= (sc->sc_banks[i].decc << 9);
+ regval |= (sc->sc_banks[i].wp << 8);
+ regval |= (sc->sc_banks[i].msel << 5);
+ regval |= (sc->sc_banks[i].atom << 2);
+ regval |= 1;
- lbc_write_reg(sc, LBC85XX_BR(unit), regbuff);
+ lbc_write_reg(sc, LBC85XX_BR(i), regval);
/*
- * Compute and program OR value
+ * Compute and program OR value.
*/
- regbuff = 0;
- regbuff |= lbc_address_mask(size);
+ regval = 0;
+ regval |= lbc_address_mask(size);
- switch (res->lbr_msel) {
+ switch (sc->sc_banks[i].msel) {
case LBCRES_MSEL_GPCM:
/* TODO Add flag support for option registers */
- regbuff |= 0x00000ff7;
+ regval |= 0x00000ff7;
break;
case LBCRES_MSEL_FCM:
printf("FCM mode not supported yet!");
@@ -285,35 +265,114 @@ lbc_init_child(device_t dev, device_t child)
error = ENOSYS;
goto fail;
}
+ lbc_write_reg(sc, LBC85XX_OR(i), regval);
+ }
- lbc_write_reg(sc, LBC85XX_OR(unit), regbuff);
+ /*
+ * Initialize configuration register:
+ * - enable Local Bus
+ * - set data buffer control signal function
+ * - disable parity byte select
+ * - set ECC parity type
+ * - set bus monitor timing and timer prescale
+ */
+ lbc_write_reg(sc, LBC85XX_LBCR, 0);
+
+ /*
+ * Initialize clock ratio register:
+ * - disable PLL bypass mode
+ * - configure LCLK delay cycles for the assertion of LALE
+ * - set system clock divider
+ */
+ lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);
+
+ return (0);
+
+fail:
+ lbc_banks_unmap(sc);
+ return (error);
+}
+
+static void
+fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di)
+{
+ pcell_t width;
+ int bank;
+ if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0)
+ return;
+
+ bank = di->di_bank;
+ if (sc->sc_banks[bank].size == 0)
+ return;
+
+ /* Express width in bits. */
+ sc->sc_banks[bank].width = width * 8;
+}
+
+static int
+fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
+ struct lbc_devinfo *di)
+{
+ u_long start, end, count;
+ pcell_t *reg, *regptr;
+ pcell_t addr_cells, size_cells;
+ int tuple_size, tuples;
+ int i, rv, bank;
+
+ if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
+ return (ENXIO);
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
+ tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
+ debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
+ debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
+ if (tuples <= 0)
+ /* No 'reg' property in this node. */
return (0);
+
+ regptr = reg;
+ for (i = 0; i < tuples; i++) {
+
+ bank = fdt_data_get((void *)reg, 1);
+ di->di_bank = bank;
+ reg += 1;
+
+ /* Get address/size. */
+ rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start,
+ &count);
+ if (rv != 0) {
+ resource_list_free(&di->di_res);
+ goto out;
+ }
+ reg += addr_cells - 1 + size_cells;
+
+ /* Calculate address range relative to VA base. */
+ start = sc->sc_banks[bank].va + start;
+ end = start + count - 1;
+
+ debugf("reg addr bank = %d, start = %lx, end = %lx, "
+ "count = %lx\n", bank, start, end, count);
+
+ /* Use bank (CS) cell as rid. */
+ resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
+ end, count);
}
-fail:
- if (unit != -1) {
- law_disable(OCP85XX_TGTIF_LBC, start, size);
- pmap_unmapdev(sc->sc_kva[unit], size);
- return (error);
- } else
- return (ENOENT);
+ rv = 0;
+out:
+ free(regptr, M_OFWPROP);
+ return (rv);
}
static int
lbc_probe(device_t dev)
{
- device_t parent;
- uintptr_t devtype;
- int error;
- parent = device_get_parent(dev);
- error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
- if (error)
- return (error);
- if (devtype != OCPBUS_DEVTYPE_LBC)
+ if (!(ofw_bus_is_compatible(dev, "fsl,lbc") ||
+ ofw_bus_is_compatible(dev, "fsl,elbc")))
return (ENXIO);
- device_set_desc(dev, "Freescale MPC85xx Local Bus Controller");
+ device_set_desc(dev, "Freescale Local Bus Controller");
return (BUS_PROBE_DEFAULT);
}
@@ -321,9 +380,15 @@ static int
lbc_attach(device_t dev)
{
struct lbc_softc *sc;
+ struct lbc_devinfo *di;
struct rman *rm;
- const struct lbc_resource *lbcres;
- int error;
+ u_long offset, start, size;
+ device_t cdev;
+ phandle_t node, child;
+ pcell_t *ranges, *rangesptr;
+ int tuple_size, tuples;
+ int par_addr_cells;
+ int bank, error, i;
sc = device_get_softc(dev);
sc->sc_dev = dev;
@@ -336,10 +401,11 @@ lbc_attach(device_t dev)
sc->sc_bst = rman_get_bustag(sc->sc_res);
sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+ rangesptr = NULL;
rm = &sc->sc_rman;
rm->rm_type = RMAN_ARRAY;
- rm->rm_descr = "MPC85XX Local Bus Space";
+ rm->rm_descr = "Local Bus Space";
rm->rm_start = 0UL;
rm->rm_end = ~0UL;
error = rman_init(rm);
@@ -353,34 +419,139 @@ lbc_attach(device_t dev)
}
/*
- * Initialize configuration register:
- * - enable Local Bus
- * - set data buffer control signal function
- * - disable parity byte select
- * - set ECC parity type
- * - set bus monitor timing and timer prescale
+ * Process 'ranges' property.
*/
- lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);
+ node = ofw_bus_get_node(dev);
+ if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
+ &sc->sc_size_cells)) != 0) {
+ error = ENXIO;
+ goto fail;
+ }
+
+ par_addr_cells = fdt_parent_addr_cells(node);
+ if (par_addr_cells > 2) {
+ device_printf(dev, "unsupported parent #addr-cells\n");
+ error = ERANGE;
+ goto fail;
+ }
+ tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
+ sc->sc_size_cells);
+
+ tuples = OF_getprop_alloc(node, "ranges", tuple_size,
+ (void **)&ranges);
+ if (tuples < 0) {
+ device_printf(dev, "could not retrieve 'ranges' property\n");
+ error = ENXIO;
+ goto fail;
+ }
+ rangesptr = ranges;
+
+ debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
+ "tuple_size = %d, tuples = %d\n", par_addr_cells,
+ sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);
+
+ start = 0;
+ size = 0;
+ for (i = 0; i < tuples; i++) {
+
+ /* The first cell is the bank (chip select) number. */
+ bank = fdt_data_get((void *)ranges, 1);
+ if (bank < 0 || bank > LBC_DEV_MAX) {
+ device_printf(dev, "bank out of range: %d\n", bank);
+ error = ERANGE;
+ goto fail;
+ }
+ ranges += 1;
+
+ /*
+ * Remaining cells of the child address define offset into
+ * this CS.
+ */
+ offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1);
+ ranges += sc->sc_addr_cells - 1;
+
+ /* Parent bus start address of this bank. */
+ start = fdt_data_get((void *)ranges, par_addr_cells);
+ ranges += par_addr_cells;
+
+ size = fdt_data_get((void *)ranges, sc->sc_size_cells);
+ ranges += sc->sc_size_cells;
+ debugf("bank = %d, start = %lx, size = %lx\n", bank,
+ start, size);
+
+ sc->sc_banks[bank].pa = start + offset;
+ sc->sc_banks[bank].size = size;
+
+ /*
+ * Attributes for the bank.
+ *
+ * XXX Note there are no DT bindings defined for them at the
+ * moment, so we need to provide some defaults.
+ */
+ sc->sc_banks[bank].width = 16;
+ sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
+ sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
+ sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
+ sc->sc_banks[bank].wp = 0;
+ }
/*
- * Initialize clock ratio register:
- * - disable PLL bypass mode
- * - configure LCLK delay cycles for the assertion of LALE
- * - set system clock divider
+ * Initialize mem-mappings for the LBC banks (i.e. chip selects).
*/
- lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);
+ error = lbc_banks_map(sc);
+ if (error)
+ goto fail;
- lbcres = mpc85xx_lbc_resources;
+ /*
+ * Walk the localbus and add direct subordinates as our children.
+ */
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- for (; lbcres->lbr_devtype; lbcres++)
- if (!lbc_mk_child(dev, lbcres)) {
- error = ENXIO;
- goto fail;
+ di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);
+
+ if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
+ free(di, M_LBC);
+ device_printf(dev, "could not set up devinfo\n");
+ continue;
+ }
+
+ resource_list_init(&di->di_res);
+
+ if (fdt_lbc_reg_decode(child, sc, di)) {
+ device_printf(dev, "could not process 'reg' "
+ "property\n");
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_LBC);
+ continue;
+ }
+
+ fdt_lbc_fixup(child, sc, di);
+
+ /* Add newbus device for this FDT node */
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev == NULL) {
+ device_printf(dev, "could not add child: %s\n",
+ di->di_ofw.obd_name);
+ resource_list_free(&di->di_res);
+ ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+ free(di, M_LBC);
+ continue;
}
+ debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name,
+ (void *)child);
+ device_set_ivars(cdev, di);
+ }
+
+ /*
+ * Enable the LBC.
+ */
+ lbc_banks_enable(sc);
+ free(rangesptr, M_OFWPROP);
return (bus_generic_attach(dev));
fail:
+ free(rangesptr, M_OFWPROP);
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
return (error);
}
@@ -394,137 +565,114 @@ lbc_shutdown(device_t dev)
}
static struct resource *
-lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
+lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct lbc_softc *sc;
- struct lbc_devinfo *dinfo;
- struct resource *rv;
+ struct lbc_devinfo *di;
+ struct resource_list_entry *rle;
+ struct resource *res;
struct rman *rm;
- int error;
-
- sc = device_get_softc(dev);
- dinfo = device_get_ivars(child);
-
- if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ)
- return (NULL);
+ int needactivate;
/* We only support default allocations. */
if (start != 0ul || end != ~0ul)
return (NULL);
+ sc = device_get_softc(bus);
if (type == SYS_RES_IRQ)
- return (bus_alloc_resource(dev, type, rid, start, end, count,
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
flags));
- if (!sc->sc_kva[dinfo->lbc_unit]) {
- error = lbc_init_child(dev, child);
- if (error)
- return (NULL);
- }
-
- error = lbc_get_resource(dev, child, type, *rid, &start, &count);
- if (error)
+ /*
+ * Request for the default allocation with a given rid: use resource
+ * list stored in the local device info.
+ */
+ if ((di = device_get_ivars(child)) == NULL)
return (NULL);
- rm = &sc->sc_rman;
- end = start + count - 1;
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
- if (rv != NULL) {
- rman_set_bustag(rv, &bs_be_tag);
- rman_set_bushandle(rv, rman_get_start(rv));
+ if (type == SYS_RES_IOPORT)
+ type = SYS_RES_MEMORY;
+
+ rid = &di->di_bank;
+
+ rle = resource_list_find(&di->di_res, type, *rid);
+ if (rle == NULL) {
+ device_printf(bus, "no default resources for "
+ "rid = %d, type = %d\n", *rid, type);
+ return (NULL);
}
- return (rv);
-}
+ start = rle->start;
+ count = rle->count;
+ end = start + count - 1;
-static int
-lbc_print_child(device_t dev, device_t child)
-{
- u_long size, start;
- int error, retval, rid;
+ sc = device_get_softc(bus);
- retval = bus_print_child_header(dev, child);
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
- rid = 0;
- while (1) {
- error = lbc_get_resource(dev, child, SYS_RES_MEMORY, rid,
- &start, &size);
- if (error)
- break;
- retval += (rid == 0) ? printf(" iomem ") : printf(",");
- retval += printf("%#lx", start);
- if (size > 1)
- retval += printf("-%#lx", start + size - 1);
- rid++;
+ rm = &sc->sc_rman;
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL) {
+ device_printf(bus, "failed to reserve resource %#lx - %#lx "
+ "(%#lx)\n", start, end, count);
+ return (NULL);
}
- retval += bus_print_child_footer(dev, child);
- return (retval);
+ rman_set_rid(res, *rid);
+ rman_set_bustag(res, &bs_be_tag);
+ rman_set_bushandle(res, rman_get_start(res));
+
+ if (needactivate)
+ if (bus_activate_resource(child, type, *rid, res)) {
+ device_printf(child, "resource activation failed\n");
+ rman_release_resource(res);
+ return (NULL);
+ }
+
+ return (res);
}
static int
-lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
+lbc_print_child(device_t dev, device_t child)
{
- struct lbc_devinfo *dinfo;
+ struct lbc_devinfo *di;
+ struct resource_list *rl;
+ int rv;
- if (device_get_parent(child) != dev)
- return (EINVAL);
+ di = device_get_ivars(child);
+ rl = &di->di_res;
- dinfo = device_get_ivars(child);
+ rv = 0;
+ rv += bus_print_child_header(dev, child);
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += bus_print_child_footer(dev, child);
- switch (index) {
- case LBC_IVAR_DEVTYPE:
- *result = dinfo->lbc_devtype;
- return (0);
- default:
- break;
- }
- return (EINVAL);
+ return (rv);
}
static int
lbc_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *res)
{
+ int err;
+
+ if (rman_get_flags(res) & RF_ACTIVE) {
+ err = bus_deactivate_resource(child, type, rid, res);
+ if (err)
+ return (err);
+ }
return (rman_release_resource(res));
}
-static int
-lbc_get_resource(device_t dev, device_t child, int type, int rid,
- u_long *startp, u_long *countp)
+static const struct ofw_bus_devinfo *
+lbc_get_devinfo(device_t bus, device_t child)
{
- struct lbc_softc *sc;
- struct lbc_devinfo *dinfo;
- const struct lbc_resource *lbcres;
-
- if (type != SYS_RES_MEMORY)
- return (ENOENT);
-
- /* Currently all LBC devices have a single RID per type. */
- if (rid != 0)
- return (ENOENT);
-
- sc = device_get_softc(dev);
- dinfo = device_get_ivars(child);
-
- if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1)))
- return (EINVAL);
+ struct lbc_devinfo *di;
- lbcres = mpc85xx_lbc_resources;
-
- switch (dinfo->lbc_devtype) {
- case LBC_DEVTYPE_CFI:
- case LBC_DEVTYPE_RTC:
- for (; lbcres->lbr_devtype; lbcres++) {
- if (dinfo->lbc_unit == lbcres->lbr_unit) {
- *startp = sc->sc_kva[lbcres->lbr_unit];
- *countp = lbcres->lbr_size;
- return (0);
- }
- }
- default:
- return (EDOOFUS);
- }
- return (0);
+ di = device_get_ivars(child);
+ return (&di->di_ofw);
}
diff --git a/sys/powerpc/mpc85xx/lbc.h b/sys/powerpc/mpc85xx/lbc.h
index c5d19e2..ee58607 100644
--- a/sys/powerpc/mpc85xx/lbc.h
+++ b/sys/powerpc/mpc85xx/lbc.h
@@ -29,15 +29,9 @@
#ifndef _MACHINE_LBC_H_
#define _MACHINE_LBC_H_
-#define LBC_IVAR_DEVTYPE 1
-
/* Maximum number of devices on Local Bus */
#define LBC_DEV_MAX 8
-/* Device types. */
-#define LBC_DEVTYPE_CFI 1
-#define LBC_DEVTYPE_RTC 2
-
/* Local access registers */
#define LBC85XX_BR(n) (8 * n)
#define LBC85XX_OR(n) (4 + (8 * n))
@@ -61,18 +55,42 @@
#define LBCRES_ATOM_RAWA 1
#define LBCRES_ATOM_WARA 2
-struct lbc_resource {
- int lbr_devtype; /* LBC device type */
- int lbr_unit; /* Resource table entry number */
- vm_paddr_t lbr_base_addr; /* Device mem region base address */
- size_t lbr_size; /* Device mem region size */
- int lbr_port_size; /* Data bus width */
- uint8_t lbr_msel; /* LBC machine select */
- uint8_t lbr_decc; /* Data error checking mode */
- uint8_t lbr_atom; /* Atomic operation mode */
- uint8_t lbr_wp; /* Write protect */
+struct lbc_bank {
+ u_long pa; /* physical addr of the bank */
+ u_long size; /* bank size */
+ vm_offset_t va; /* VA of the bank */
+
+ /*
+ * XXX the following bank attributes do not have properties specified
+ * in the LBC DTS bindings yet (11.2009), so they are mainly a
+ * placeholder for future extensions.
+ */
+ int width; /* data bus width */
+ uint8_t msel; /* machine select */
+ uint8_t atom; /* atomic op mode */
+ uint8_t wp; /* write protect */
+ uint8_t decc; /* data error checking */
};
-extern const struct lbc_resource mpc85xx_lbc_resources[];
+struct lbc_softc {
+ device_t sc_dev;
+ struct resource *sc_res;
+ bus_space_handle_t sc_bsh;
+ bus_space_tag_t sc_bst;
+ int sc_rid;
+
+ struct rman sc_rman;
+
+ int sc_addr_cells;
+ int sc_size_cells;
+
+ struct lbc_bank sc_banks[LBC_DEV_MAX];
+};
+
+struct lbc_devinfo {
+ struct ofw_bus_devinfo di_ofw;
+ struct resource_list di_res;
+ int di_bank;
+};
#endif /* _MACHINE_LBC_H_ */
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index b6de50d..7530449 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -29,6 +29,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -37,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/spr.h>
-#include <powerpc/mpc85xx/ocpbus.h>
#include <powerpc/mpc85xx/mpc85xx.h>
/*
@@ -129,6 +131,39 @@ law_disable(int trgt, u_long addr, u_long size)
return (ENOENT);
}
+int
+law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
+{
+ u_long start;
+ uint32_t ver;
+ int trgt, rv;
+
+ ver = SVR_VER(mfspr(SPR_SVR));
+
+ start = rman_get_start(res) & 0xf000;
+
+ rv = 0;
+ trgt = -1;
+ switch (start) {
+ case 0x8000:
+ trgt = 0;
+ break;
+ case 0x9000:
+ trgt = 1;
+ break;
+ case 0xa000:
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
+ trgt = 2;
+ else
+ rv = EINVAL;
+ break;
+ default:
+ rv = ENXIO;
+ }
+ *trgt_mem = *trgt_io = trgt;
+ return (rv);
+}
+
void
cpu_reset(void)
{
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
index e558489..7621f2c 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.h
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -1,5 +1,6 @@
/*-
* Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * Copyright 2006 by Juniper Networks.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,10 +30,61 @@
#ifndef _MPC85XX_H_
#define _MPC85XX_H_
+/*
+ * Configuration control and status registers
+ */
+#define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0)
+#define OCP85XX_BPTR (CCSRBAR_VA + 0x20)
+
+/*
+ * E500 Coherency Module registers
+ */
+#define OCP85XX_EEBPCR (CCSRBAR_VA + 0x1010)
+
+/*
+ * Local access registers
+ */
+#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x20 * (n))
+#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x20 * (n))
+
+#define OCP85XX_TGTIF_LBC 4
+#define OCP85XX_TGTIF_RAM_INTL 11
+#define OCP85XX_TGTIF_RIO 12
+#define OCP85XX_TGTIF_RAM1 15
+#define OCP85XX_TGTIF_RAM2 22
+
+/*
+ * L2 cache registers
+ */
+#define OCP85XX_L2CTL (CCSRBAR_VA + 0x20000)
+
+/*
+ * Power-On Reset configuration
+ */
+#define OCP85XX_PORDEVSR (CCSRBAR_VA + 0xe000c)
+#define OCP85XX_PORDEVSR_IO_SEL 0x00780000
+#define OCP85XX_PORDEVSR_IO_SEL_SHIFT 19
+
+#define OCP85XX_PORDEVSR2 (CCSRBAR_VA + 0xe0014)
+
+#define OCP85XX_DEVDISR (CCSRBAR_VA + 0xe0070)
+#define OCP85XX_DEVDISR_PCIE0 0x20000000
+#define OCP85XX_DEVDISR_PCIE1 0x04000000
+#define OCP85XX_DEVDISR_PCIE2 0x02000000
+
+/*
+ * Status Registers.
+ */
+#define OCP85XX_RSTCR (CCSRBAR_VA + 0xe00b0)
+
+/*
+ * Prototypes.
+ */
uint32_t ccsr_read4(uintptr_t addr);
void ccsr_write4(uintptr_t addr, uint32_t val);
int law_enable(int trgt, u_long addr, u_long size);
int law_disable(int trgt, u_long addr, u_long size);
int law_getmax(void);
+int law_pci_target(struct resource *, int *, int *);
#endif /* _MPC85XX_H_ */
diff --git a/sys/powerpc/mpc85xx/nexus.c b/sys/powerpc/mpc85xx/nexus.c
index fa07247..6b07b10 100644
--- a/sys/powerpc/mpc85xx/nexus.c
+++ b/sys/powerpc/mpc85xx/nexus.c
@@ -112,13 +112,10 @@ static int
nexus_probe (device_t dev)
{
- /*
- * Add OCP (on-chip peripheral) bus
- */
- device_add_child(dev, "ocpbus", 0);
+ device_add_child(dev, "fdtbus", 0);
+ device_quiet(dev);
- device_set_desc(dev, "MPC85xx Nexus device");
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
static int
diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c
deleted file mode 100644
index 483c620..0000000
--- a/sys/powerpc/mpc85xx/ocpbus.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*-
- * Copyright 2006 by Juniper Networks. All rights reserved.
- *
- * 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. 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/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ktr.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-
-#include <machine/spr.h>
-#include <machine/ocpbus.h>
-#include <machine/intr_machdep.h>
-#include <machine/md_var.h>
-#include <machine/vmparam.h>
-#include <machine/bootinfo.h>
-
-#include <powerpc/mpc85xx/ocpbus.h>
-#include <powerpc/mpc85xx/mpc85xx.h>
-
-#include "pic_if.h"
-
-extern struct bus_space bs_be_tag;
-
-struct ocpbus_softc {
- struct rman sc_mem;
- struct rman sc_irq;
-};
-
-struct ocp_devinfo {
- int ocp_devtype;
- int ocp_unit;
-};
-
-static int ocpbus_probe(device_t);
-static int ocpbus_attach(device_t);
-static int ocpbus_shutdown(device_t);
-static int ocpbus_get_resource(device_t, device_t, int, int, u_long *,
- u_long *);
-static struct resource *ocpbus_alloc_resource(device_t, device_t, int, int *,
- u_long, u_long, u_long, u_int);
-static int ocpbus_print_child(device_t, device_t);
-static int ocpbus_release_resource(device_t, device_t, int, int,
- struct resource *);
-static int ocpbus_read_ivar(device_t, device_t, int, uintptr_t *);
-static int ocpbus_setup_intr(device_t, device_t, struct resource *, int,
- driver_filter_t *, driver_intr_t *, void *, void **);
-static int ocpbus_teardown_intr(device_t, device_t, struct resource *, void *);
-static int ocpbus_config_intr(device_t, int, enum intr_trigger,
- enum intr_polarity);
-
-/*
- * Bus interface definition
- */
-static device_method_t ocpbus_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ocpbus_probe),
- DEVMETHOD(device_attach, ocpbus_attach),
- DEVMETHOD(device_shutdown, ocpbus_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, ocpbus_print_child),
- DEVMETHOD(bus_read_ivar, ocpbus_read_ivar),
- DEVMETHOD(bus_setup_intr, ocpbus_setup_intr),
- DEVMETHOD(bus_teardown_intr, ocpbus_teardown_intr),
- DEVMETHOD(bus_config_intr, ocpbus_config_intr),
-
- DEVMETHOD(bus_get_resource, ocpbus_get_resource),
- DEVMETHOD(bus_alloc_resource, ocpbus_alloc_resource),
- DEVMETHOD(bus_release_resource, ocpbus_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-
- { 0, 0 }
-};
-
-static driver_t ocpbus_driver = {
- "ocpbus",
- ocpbus_methods,
- sizeof(struct ocpbus_softc)
-};
-
-devclass_t ocpbus_devclass;
-
-DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0);
-
-static device_t
-ocpbus_mk_child(device_t dev, int type, int unit)
-{
- struct ocp_devinfo *dinfo;
- device_t child;
-
- child = device_add_child(dev, NULL, -1);
- if (child == NULL) {
- device_printf(dev, "could not add child device\n");
- return (NULL);
- }
- dinfo = malloc(sizeof(struct ocp_devinfo), M_DEVBUF, M_WAITOK|M_ZERO);
- dinfo->ocp_devtype = type;
- dinfo->ocp_unit = unit;
- device_set_ivars(child, dinfo);
- return (child);
-}
-
-static int
-ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
-{
- u_long addr, size;
-
- switch (type) {
- case SYS_RES_MEMORY:
- switch (trgt) {
- case OCP85XX_TGTIF_PCI0:
- addr = 0x80000000;
- size = 0x10000000;
- break;
- case OCP85XX_TGTIF_PCI1:
- addr = 0x90000000;
- size = 0x10000000;
- break;
- case OCP85XX_TGTIF_PCI2:
- addr = 0xA0000000;
- size = 0x10000000;
- break;
- case OCP85XX_TGTIF_PCI3:
- addr = 0xB0000000;
- size = 0x10000000;
- break;
- default:
- return (EINVAL);
- }
- break;
- case SYS_RES_IOPORT:
- switch (trgt) {
- case OCP85XX_TGTIF_PCI0:
- addr = 0xfee00000;
- size = 0x00010000;
- break;
- case OCP85XX_TGTIF_PCI1:
- addr = 0xfee10000;
- size = 0x00010000;
- break;
- case OCP85XX_TGTIF_PCI2:
- addr = 0xfee20000;
- size = 0x00010000;
- break;
- case OCP85XX_TGTIF_PCI3:
- addr = 0xfee30000;
- size = 0x00010000;
- break;
- default:
- return (EINVAL);
- }
- break;
- default:
- return (EINVAL);
- }
-
- *startp = addr;
- *countp = size;
-
- return (law_enable(trgt, *startp, *countp));
-}
-
-static int
-ocpbus_probe(device_t dev)
-{
-
- device_set_desc(dev, "Freescale on-chip peripherals bus");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-ocpbus_attach(device_t dev)
-{
- struct ocpbus_softc *sc;
- int error, i, tgt, law_max;
- uint32_t sr;
- u_long start, end;
-
- sc = device_get_softc(dev);
-
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 1);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 1);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_LBC, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 1);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 2);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 3);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 1);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 2);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 3);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PIC, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_QUICC, 0);
- ocpbus_mk_child(dev, OCPBUS_DEVTYPE_SEC, 0);
-
- /* Set up IRQ rman */
- start = 0;
- end = INTR_VECTORS - 1;
- sc->sc_irq.rm_start = start;
- sc->sc_irq.rm_end = end;
- sc->sc_irq.rm_type = RMAN_ARRAY;
- sc->sc_irq.rm_descr = "Interrupt request lines";
- if (rman_init(&sc->sc_irq) ||
- rman_manage_region(&sc->sc_irq, start, end))
- panic("ocpbus_attach IRQ rman");
-
- /* Set up I/O mem rman */
- sc->sc_mem.rm_type = RMAN_ARRAY;
- sc->sc_mem.rm_descr = "OCPBus Device Memory";
- error = rman_init(&sc->sc_mem);
- if (error) {
- device_printf(dev, "rman_init() failed. error = %d\n", error);
- return (error);
- }
-
- error = rman_manage_region(&sc->sc_mem, CCSRBAR_VA,
- CCSRBAR_VA + CCSRBAR_SIZE - 1);
- if (error) {
- device_printf(dev, "rman_manage_region() failed. error = %d\n",
- error);
- return (error);
- }
-
- /*
- * Clear local access windows. Skip DRAM entries, so we don't shoot
- * ourselves in the foot.
- */
- law_max = law_getmax();
- for (i = 0; i < law_max; i++) {
- sr = ccsr_read4(OCP85XX_LAWSR(i));
- if ((sr & 0x80000000) == 0)
- continue;
- tgt = (sr & 0x01f00000) >> 20;
- if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
- tgt == OCP85XX_TGTIF_RAM_INTL)
- continue;
-
- ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
- }
-
- if (bootverbose)
- device_printf(dev, "PORDEVSR=%08x, PORDEVSR2=%08x\n",
- ccsr_read4(OCP85XX_PORDEVSR),
- ccsr_read4(OCP85XX_PORDEVSR2));
-
- /*
- * Internal interrupt are always active-high. Since the sense cannot
- * be specified, we program as edge-triggered to make sure we write
- * a 0 value to the reserved bit in the OpenPIC compliant PIC. This
- * is not to say anything about the sense of any of the internal
- * interrupt sources.
- */
- for (i = PIC_IRQ_INT(0); i < PIC_IRQ_INT(32); i++)
- powerpc_config_intr(i, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
-
- return (bus_generic_attach(dev));
-}
-
-static int
-ocpbus_shutdown(device_t dev)
-{
-
- return(0);
-}
-
-struct ocp_resource {
- int sr_devtype;
- int sr_unit;
- int sr_resource;
- int sr_rid;
- int sr_offset;
- int sr_size;
-};
-
-const struct ocp_resource mpc8555_resources[] = {
- {OCPBUS_DEVTYPE_PIC, 0, SYS_RES_MEMORY, 0, OCP85XX_OPENPIC_OFF,
- OCP85XX_OPENPIC_SIZE},
-
- {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_MEMORY, 0, OCP85XX_QUICC_OFF,
- OCP85XX_QUICC_SIZE},
- {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, 30, 1},
-
- {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_MEMORY, 0, OCP85XX_TSEC0_OFF,
- OCP85XX_TSEC_SIZE},
- {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, 13, 1},
- {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, 14, 1},
- {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, 18, 1},
- {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_MEMORY, 0, OCP85XX_TSEC1_OFF,
- OCP85XX_TSEC_SIZE},
- {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, 19, 1},
- {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, 20, 1},
- {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, 24, 1},
- {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_MEMORY, 0, OCP85XX_TSEC2_OFF,
- OCP85XX_TSEC_SIZE},
- {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, 15, 1},
- {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, 16, 1},
- {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, 17, 1},
- {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_MEMORY, 0, OCP85XX_TSEC3_OFF,
- OCP85XX_TSEC_SIZE},
- {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, 21, 1},
- {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, 22, 1},
- {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, 23, 1},
-
- {OCPBUS_DEVTYPE_UART, 0, SYS_RES_MEMORY, 0, OCP85XX_UART0_OFF,
- OCP85XX_UART_SIZE},
- {OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, 26, 1},
- {OCPBUS_DEVTYPE_UART, 1, SYS_RES_MEMORY, 0, OCP85XX_UART1_OFF,
- OCP85XX_UART_SIZE},
- {OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, 26, 1},
-
- {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 0, OCP85XX_PCI0_OFF,
- OCP85XX_PCI_SIZE},
- {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI0},
- {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI0},
- {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 0, OCP85XX_PCI1_OFF,
- OCP85XX_PCI_SIZE},
- {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI1},
- {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI1},
- {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 0, OCP85XX_PCI2_OFF,
- OCP85XX_PCI_SIZE},
- {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI2},
- {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI2},
- {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 0, OCP85XX_PCI3_OFF,
- OCP85XX_PCI_SIZE},
- {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI3},
- {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI3},
-
- {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF,
- OCP85XX_LBC_SIZE},
-
- {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF,
- OCP85XX_I2C_SIZE},
- {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, 27, 1},
- {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_MEMORY, 0, OCP85XX_I2C1_OFF,
- OCP85XX_I2C_SIZE},
- {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, 27, 1},
-
- {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_MEMORY, 0, OCP85XX_SEC_OFF,
- OCP85XX_SEC_SIZE},
- {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, 29, 1},
- {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, 42, 1},
-
- {0}
-};
-
-static int
-ocpbus_get_resource(device_t dev, device_t child, int type, int rid,
- u_long *startp, u_long *countp)
-{
- const struct ocp_resource *res;
- struct ocp_devinfo *dinfo;
- u_long start = 0, count = 0;
- int error;
-
- dinfo = device_get_ivars(child);
-
- /*
- * Lookup the correct values.
- */
- res = mpc8555_resources;
- for (; res->sr_devtype; res++) {
- if (res->sr_devtype != dinfo->ocp_devtype)
- continue;
- if (res->sr_unit != dinfo->ocp_unit)
- continue;
- if (res->sr_rid != rid)
- continue;
- if (res->sr_resource != type)
- continue;
-
- if (res->sr_offset != 0) {
- error = 0;
- switch (type) {
- case SYS_RES_MEMORY:
- start = res->sr_offset + CCSRBAR_VA;
- break;
- case SYS_RES_IRQ:
- start = PIC_IRQ_INT(res->sr_offset);
- break;
- default:
- error = EINVAL;
- break;
- }
- count = res->sr_size;
- } else
- error = ocpbus_write_law(res->sr_size, type, &start,
- &count);
-
- if (!error) {
- if (startp != NULL)
- *startp = start;
- if (countp != NULL)
- *countp = count;
- }
- return (error);
- }
-
- return (ENOENT);
-}
-
-static struct resource *
-ocpbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct ocpbus_softc *sc;
- struct resource *rv;
- int error;
-
- sc = device_get_softc(dev);
-
- switch (type) {
- case SYS_RES_IRQ:
- if (start == 0ul && end == ~0ul) {
- error = ocpbus_get_resource(dev, child, type, *rid,
- &start, &count);
- if (error)
- return (NULL);
- }
-
- rv = rman_reserve_resource(&sc->sc_irq, start,
- start + count - 1, count, flags, child);
- if (rv == NULL)
- return (NULL);
- break;
-
- case SYS_RES_MEMORY:
- if (start != 0ul || end != ~0ul)
- return (NULL);
-
- error = ocpbus_get_resource(dev, child, type, *rid, &start,
- &count);
- if (error)
- return (NULL);
-
- rv = rman_reserve_resource(&sc->sc_mem, start,
- start + count - 1, count, flags, child);
- if (rv == NULL)
- return (NULL);
-
- rman_set_bustag(rv, &bs_be_tag);
- rman_set_bushandle(rv, rman_get_start(rv));
- break;
-
- default:
- return (NULL);
- }
-
- rman_set_rid(rv, *rid);
- return (rv);
-}
-
-static int
-ocpbus_print_child(device_t dev, device_t child)
-{
- u_long size, start;
- int error, retval, rid;
-
- retval = bus_print_child_header(dev, child);
-
- rid = 0;
- while (1) {
- error = ocpbus_get_resource(dev, child, SYS_RES_MEMORY, rid,
- &start, &size);
- if (error)
- break;
- retval += (rid == 0) ? printf(" iomem ") : printf(",");
- retval += printf("%#lx", start);
- if (size > 1)
- retval += printf("-%#lx", start + size - 1);
- rid++;
- }
-
- /*
- * The SYS_RES_IOPORT resource of the PCIB has rid 1 because the
- * the SYS_RES_MEMORY resource related to the decoding window also
- * has rid 1. This is friendlier for the PCIB child...
- */
- rid = 1;
- while (1) {
- error = ocpbus_get_resource(dev, child, SYS_RES_IOPORT, rid,
- &start, &size);
- if (error)
- break;
- retval += (rid == 1) ? printf(" ioport ") : printf(",");
- retval += printf("%#lx", start);
- if (size > 1)
- retval += printf("-%#lx", start + size - 1);
- rid++;
- }
-
- rid = 0;
- while (1) {
- error = ocpbus_get_resource(dev, child, SYS_RES_IRQ, rid,
- &start, &size);
- if (error)
- break;
- retval += (rid == 0) ? printf(" irq ") : printf(",");
- retval += printf("%ld", start);
- rid++;
- }
-
- retval += bus_print_child_footer(dev, child);
- return (retval);
-}
-
-static int
-ocpbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
-{
- struct ocp_devinfo *dinfo;
- struct bi_eth_addr *eth;
- int unit;
-
- if (device_get_parent(child) != dev)
- return (EINVAL);
-
- dinfo = device_get_ivars(child);
-
- switch (index) {
- case OCPBUS_IVAR_CLOCK:
- *result = bootinfo->bi_bus_clk;
- return (0);
- case OCPBUS_IVAR_DEVTYPE:
- *result = dinfo->ocp_devtype;
- return (0);
- case OCPBUS_IVAR_HWUNIT:
- *result = dinfo->ocp_unit;
- return (0);
- case OCPBUS_IVAR_MACADDR:
- unit = device_get_unit(child);
- if (unit > bootinfo->bi_eth_addr_no - 1)
- return (EINVAL);
- eth = bootinfo_eth() + unit;
- *result = (uintptr_t)eth;
- return (0);
- }
-
- return (EINVAL);
-}
-
-static int
-ocpbus_release_resource(device_t dev, device_t child, int type, int rid,
- struct resource *res)
-{
-
- return (rman_release_resource(res));
-}
-
-static int
-ocpbus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
- driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep)
-{
- int error;
-
- if (res == NULL)
- panic("ocpbus_setup_intr: NULL irq resource!");
-
- *cookiep = 0;
- if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
- flags |= INTR_EXCL;
-
- /*
- * We depend here on rman_activate_resource() being idempotent.
- */
- error = rman_activate_resource(res);
- if (error)
- return (error);
-
- error = powerpc_setup_intr(device_get_nameunit(child),
- rman_get_start(res), filter, ihand, arg, flags, cookiep);
-
- return (error);
-}
-
-static int
-ocpbus_teardown_intr(device_t dev, device_t child, struct resource *res,
- void *cookie)
-{
-
- return (powerpc_teardown_intr(cookie));
-}
-
-static int
-ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig,
- enum intr_polarity pol)
-{
-
- return (powerpc_config_intr(irq, trig, pol));
-}
diff --git a/sys/powerpc/mpc85xx/ocpbus.h b/sys/powerpc/mpc85xx/ocpbus.h
deleted file mode 100644
index 69c9569..0000000
--- a/sys/powerpc/mpc85xx/ocpbus.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*-
- * Copyright 2006 by Juniper Networks. All rights reserved.
- *
- * 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. 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_OCP85XX_H_
-#define _MACHINE_OCP85XX_H_
-
-/*
- * Configuration control and status registers
- */
-#define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0)
-#define OCP85XX_BPTR (CCSRBAR_VA + 0x20)
-
-/*
- * E500 Coherency Module registers
- */
-#define OCP85XX_EEBPCR (CCSRBAR_VA + 0x1010)
-
-/*
- * Local access registers
- */
-#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x20 * (n))
-#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x20 * (n))
-
-#define OCP85XX_TGTIF_PCI0 0
-#define OCP85XX_TGTIF_PCI1 1
-#define OCP85XX_TGTIF_PCI2 2
-#define OCP85XX_TGTIF_PCI3 3
-#define OCP85XX_TGTIF_LBC 4
-#define OCP85XX_TGTIF_RAM_INTL 11
-#define OCP85XX_TGTIF_RIO 12
-#define OCP85XX_TGTIF_RAM1 15
-#define OCP85XX_TGTIF_RAM2 22
-
-/*
- * L2 cache registers
- */
-#define OCP85XX_L2CTL (CCSRBAR_VA + 0x20000)
-
-/*
- * Power-On Reset configuration
- */
-#define OCP85XX_PORDEVSR (CCSRBAR_VA + 0xe000c)
-#define OCP85XX_PORDEVSR2 (CCSRBAR_VA + 0xe0014)
-
-/*
- * Status Registers.
- */
-#define OCP85XX_RSTCR (CCSRBAR_VA + 0xe00b0)
-
-/*
- * OCP Bus Definitions
- */
-#define OCP85XX_I2C0_OFF 0x03000
-#define OCP85XX_I2C1_OFF 0x03100
-#define OCP85XX_I2C_SIZE 0x16
-#define OCP85XX_UART0_OFF 0x04500
-#define OCP85XX_UART1_OFF 0x04600
-#define OCP85XX_UART_SIZE 0x10
-#define OCP85XX_LBC_OFF 0x05000
-#define OCP85XX_LBC_SIZE 0x1000
-#define OCP85XX_PCI0_OFF 0x08000
-#define OCP85XX_PCI1_OFF 0x09000
-#define OCP85XX_PCI2_OFF 0x0A000
-#define OCP85XX_PCI3_OFF 0x0B000
-#define OCP85XX_PCI_SIZE 0x1000
-#define OCP85XX_TSEC0_OFF 0x24000
-#define OCP85XX_TSEC1_OFF 0x25000
-#define OCP85XX_TSEC2_OFF 0x26000
-#define OCP85XX_TSEC3_OFF 0x27000
-#define OCP85XX_TSEC_SIZE 0x1000
-#define OCP85XX_OPENPIC_OFF 0x40000
-#define OCP85XX_OPENPIC_SIZE 0x200B4
-#define OCP85XX_QUICC_OFF 0x80000
-#define OCP85XX_QUICC_SIZE 0x20000
-#define OCP85XX_SEC_OFF 0x30000
-#define OCP85XX_SEC_SIZE 0x10000
-
-/*
- * PIC definitions
- */
-
-#define ISA_IRQ(n) (INTR_VEC(ATPIC_ID, n))
-#define PIC_IRQ_EXT(n) (INTR_VEC(OPIC_ID, (n)))
-#define PIC_IRQ_INT(n) (INTR_VEC(OPIC_ID, (16 + (n))))
-
-#endif /* _MACHINE_OCP85XX_H */
diff --git a/sys/powerpc/mpc85xx/openpic_fdt.c b/sys/powerpc/mpc85xx/openpic_fdt.c
new file mode 100644
index 0000000..da70542
--- /dev/null
+++ b/sys/powerpc/mpc85xx/openpic_fdt.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/openpicvar.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
+static int openpic_fdt_probe(device_t);
+static uint32_t openpic_fdt_id(device_t);
+
+static device_method_t openpic_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, openpic_fdt_probe),
+ DEVMETHOD(device_attach, openpic_attach),
+
+ /* PIC interface */
+ DEVMETHOD(pic_bind, openpic_bind),
+ DEVMETHOD(pic_config, openpic_config),
+ DEVMETHOD(pic_dispatch, openpic_dispatch),
+ DEVMETHOD(pic_enable, openpic_enable),
+ DEVMETHOD(pic_eoi, openpic_eoi),
+ DEVMETHOD(pic_ipi, openpic_ipi),
+ DEVMETHOD(pic_mask, openpic_mask),
+ DEVMETHOD(pic_unmask, openpic_unmask),
+ DEVMETHOD(pic_id, openpic_fdt_id),
+
+ { 0, 0 },
+};
+
+static driver_t openpic_fdt_driver = {
+ "openpic",
+ openpic_fdt_methods,
+ sizeof(struct openpic_softc)
+};
+
+DRIVER_MODULE(openpic, simplebus, openpic_fdt_driver, openpic_devclass, 0, 0);
+
+static int
+openpic_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "chrp,open-pic"))
+ return (ENXIO);
+
+ device_set_desc(dev, OPENPIC_DEVSTR);
+ return (BUS_PROBE_DEFAULT);
+}
+
+static uint32_t
+openpic_fdt_id(device_t dev)
+{
+
+ return (ofw_bus_get_node(dev));
+}
diff --git a/sys/powerpc/mpc85xx/opic.c b/sys/powerpc/mpc85xx/opic.c
deleted file mode 100644
index 3bd5db0..0000000
--- a/sys/powerpc/mpc85xx/opic.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * Copyright 2006 by Juniper Networks. All rights reserved.
- *
- * 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. 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/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/bus.h>
-
-#include <machine/bus.h>
-#include <machine/intr_machdep.h>
-#include <machine/openpicvar.h>
-#include <machine/ocpbus.h>
-
-#include "pic_if.h"
-
-/*
- * OpenPIC attachment to ocpbus
- */
-static int openpic_ocpbus_probe(device_t);
-static uint32_t openpic_ocpbus_id(device_t);
-
-static device_method_t openpic_ocpbus_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, openpic_ocpbus_probe),
- DEVMETHOD(device_attach, openpic_attach),
-
- /* PIC interface */
- DEVMETHOD(pic_bind, openpic_bind),
- DEVMETHOD(pic_config, openpic_config),
- DEVMETHOD(pic_dispatch, openpic_dispatch),
- DEVMETHOD(pic_enable, openpic_enable),
- DEVMETHOD(pic_eoi, openpic_eoi),
- DEVMETHOD(pic_ipi, openpic_ipi),
- DEVMETHOD(pic_mask, openpic_mask),
- DEVMETHOD(pic_unmask, openpic_unmask),
- DEVMETHOD(pic_id, openpic_ocpbus_id),
-
- { 0, 0 },
-};
-
-static driver_t openpic_ocpbus_driver = {
- "openpic",
- openpic_ocpbus_methods,
- sizeof(struct openpic_softc)
-};
-
-DRIVER_MODULE(openpic, ocpbus, openpic_ocpbus_driver, openpic_devclass, 0, 0);
-
-static int
-openpic_ocpbus_probe (device_t dev)
-{
- device_t parent;
- uintptr_t devtype;
- int error;
-
- parent = device_get_parent(dev);
-
- error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
- if (error)
- return (error);
- if (devtype != OCPBUS_DEVTYPE_PIC)
- return (ENXIO);
-
- device_set_desc(dev, OPENPIC_DEVSTR);
- return (BUS_PROBE_DEFAULT);
-}
-
-static uint32_t
-openpic_ocpbus_id (device_t dev)
-{
- return (OPIC_ID);
-}
-
-
diff --git a/sys/powerpc/mpc85xx/pci_fdt.c b/sys/powerpc/mpc85xx/pci_fdt.c
new file mode 100644
index 0000000..9d67aae
--- /dev/null
+++ b/sys/powerpc/mpc85xx/pci_fdt.c
@@ -0,0 +1,1067 @@
+/*-
+ * Copyright 2006-2007 by Juniper Networks.
+ * Copyright 2008 Semihalf.
+ * Copyright 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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. 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.
+ *
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include "ofw_bus_if.h"
+#include "pcib_if.h"
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#define REG_CFG_ADDR 0x0000
+#define CONFIG_ACCESS_ENABLE 0x80000000
+
+#define REG_CFG_DATA 0x0004
+#define REG_INT_ACK 0x0008
+
+#define REG_POTAR(n) (0x0c00 + 0x20 * (n))
+#define REG_POTEAR(n) (0x0c04 + 0x20 * (n))
+#define REG_POWBAR(n) (0x0c08 + 0x20 * (n))
+#define REG_POWAR(n) (0x0c10 + 0x20 * (n))
+
+#define REG_PITAR(n) (0x0e00 - 0x20 * (n))
+#define REG_PIWBAR(n) (0x0e08 - 0x20 * (n))
+#define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n))
+#define REG_PIWAR(n) (0x0e10 - 0x20 * (n))
+
+#define REG_PEX_MES_DR 0x0020
+#define REG_PEX_MES_IER 0x0028
+#define REG_PEX_ERR_DR 0x0e00
+#define REG_PEX_ERR_EN 0x0e08
+
+#define PCIR_LTSSM 0x404
+#define LTSSM_STAT_L0 0x16
+
+#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f)
+
+struct fsl_pcib_softc {
+ device_t sc_dev;
+
+ struct rman sc_iomem;
+ bus_addr_t sc_iomem_va; /* Virtual mapping. */
+ bus_addr_t sc_iomem_size;
+ bus_addr_t sc_iomem_alloc; /* Next allocation. */
+ int sc_iomem_target;
+ struct rman sc_ioport;
+ bus_addr_t sc_ioport_va; /* Virtual mapping. */
+ bus_addr_t sc_ioport_size;
+ bus_addr_t sc_ioport_alloc; /* Next allocation. */
+ int sc_ioport_target;
+
+ struct resource *sc_res;
+ bus_space_handle_t sc_bsh;
+ bus_space_tag_t sc_bst;
+ int sc_rid;
+
+ int sc_busnr;
+ int sc_pcie;
+ uint8_t sc_pcie_capreg; /* PCI-E Capability Reg Set */
+
+ /* Devices that need special attention. */
+ int sc_devfn_tundra;
+ int sc_devfn_via_ide;
+
+ struct fdt_pci_intr sc_intr_info;
+};
+
+/* Local forward declerations. */
+static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int,
+ u_int, int);
+static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int,
+ u_int, uint32_t, int);
+static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
+static void fsl_pcib_err_init(device_t);
+static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long,
+ u_long, u_long);
+static int fsl_pcib_init(struct fsl_pcib_softc *, int, int, int);
+static int fsl_pcib_intr_info(phandle_t, struct fsl_pcib_softc *);
+static int fsl_pcib_set_range(struct fsl_pcib_softc *, int, int, u_long,
+ u_long);
+static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, u_long,
+ u_long, u_long);
+
+/* Forward declerations. */
+static int fsl_pcib_attach(device_t);
+static int fsl_pcib_detach(device_t);
+static int fsl_pcib_probe(device_t);
+
+static struct resource *fsl_pcib_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int fsl_pcib_read_ivar(device_t, device_t, int, uintptr_t *);
+static int fsl_pcib_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static int fsl_pcib_write_ivar(device_t, device_t, int, uintptr_t);
+
+static int fsl_pcib_maxslots(device_t);
+static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
+static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
+ uint32_t, int);
+
+static int next_busnr = 0;
+
+/* Configuration r/w mutex. */
+struct mtx pcicfg_mtx;
+static int mtx_initialized = 0;
+
+/*
+ * Bus interface definitions.
+ */
+static device_method_t fsl_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, fsl_pcib_probe),
+ DEVMETHOD(device_attach, fsl_pcib_attach),
+ DEVMETHOD(device_detach, fsl_pcib_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, fsl_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, fsl_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, fsl_pcib_alloc_resource),
+ DEVMETHOD(bus_release_resource, fsl_pcib_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, fsl_pcib_maxslots),
+ DEVMETHOD(pcib_read_config, fsl_pcib_read_config),
+ DEVMETHOD(pcib_write_config, fsl_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ { 0, 0 }
+};
+
+static driver_t fsl_pcib_driver = {
+ "pcib",
+ fsl_pcib_methods,
+ sizeof(struct fsl_pcib_softc),
+};
+
+devclass_t pcib_devclass;
+
+DRIVER_MODULE(pcib, fdtbus, fsl_pcib_driver, pcib_devclass, 0, 0);
+
+static int
+fsl_pcib_probe(device_t dev)
+{
+ phandle_t parnode;
+
+ /*
+ * The PCI subnode does not have the 'compatible' property, so we need
+ * to check in the parent PCI node. However the parent is not
+ * represented by a separate ofw_bus child, and therefore
+ * ofw_bus_is_compatible() cannot be used, but direct fdt equivalent.
+ */
+ parnode = OF_parent(ofw_bus_get_node(dev));
+ if (parnode == 0)
+ return (ENXIO);
+ if (!(fdt_is_compatible(parnode, "fsl,mpc8548-pcie") ||
+ fdt_is_compatible(parnode, "fsl,mpc8548-pcie")))
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fsl_pcib_attach(device_t dev)
+{
+ struct fsl_pcib_softc *sc;
+ phandle_t node;
+ uint32_t cfgreg;
+ int maxslot, subbus;
+ uint8_t ltssm, capptr;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ sc->sc_rid = 0;
+ sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
+ RF_ACTIVE);
+ if (sc->sc_res == NULL) {
+ device_printf(dev, "could not map I/O memory\n");
+ return (ENXIO);
+ }
+ sc->sc_bst = rman_get_bustag(sc->sc_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+ sc->sc_busnr = 0;
+
+ if (!mtx_initialized) {
+ mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
+ mtx_initialized = 1;
+ }
+
+ cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2);
+ if (cfgreg != 0x1057 && cfgreg != 0x1957)
+ goto err;
+
+ capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1);
+ while (capptr != 0) {
+ cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2);
+ switch (cfgreg & 0xff) {
+ case PCIY_PCIX:
+ break;
+ case PCIY_EXPRESS:
+ sc->sc_pcie = 1;
+ sc->sc_pcie_capreg = capptr;
+ break;
+ }
+ capptr = (cfgreg >> 8) & 0xff;
+ }
+
+ node = ofw_bus_get_node(dev);
+ /*
+ * Get PCI interrupt info.
+ */
+ if (fsl_pcib_intr_info(node, sc) != 0) {
+ device_printf(dev, "could not retrieve interrupt info\n");
+ goto err;
+ }
+
+ /*
+ * Configure decode windows for PCI(E) access.
+ */
+ if (fsl_pcib_decode_win(node, sc) != 0)
+ goto err;
+
+ cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
+ cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
+ PCIM_CMD_PORTEN;
+ fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2);
+
+ sc->sc_devfn_tundra = -1;
+ sc->sc_devfn_via_ide = -1;
+
+ maxslot = (sc->sc_pcie) ? 1 : 31;
+
+ /*
+ * Scan bus using firmware configured, 0 based bus numbering,
+ * let fsl_pcib_init() shift bus number by next_busnr offset.
+ */
+ sc->sc_busnr = 1;
+ subbus = fsl_pcib_init(sc, 0, next_busnr, maxslot);
+
+ if (bootverbose)
+ printf("PCI: domain %d, busnr = %d, next_busnr = %d\n",
+ device_get_unit(dev), next_busnr + 1,
+ next_busnr + subbus + 1);
+
+ /* Set final busnr */
+ sc->sc_busnr = next_busnr + 1;
+ next_busnr += subbus + 1;
+
+ if (sc->sc_pcie) {
+ ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
+ if (ltssm < LTSSM_STAT_L0) {
+ if (bootverbose)
+ printf("PCI %d: no PCIE link, skipping\n",
+ device_get_unit(dev));
+ return (0);
+ }
+ }
+
+ fsl_pcib_err_init(dev);
+
+ device_add_child(dev, "pci", -1);
+ return (bus_generic_attach(dev));
+
+err:
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
+ return (ENXIO);
+}
+
+static uint32_t
+fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ uint32_t addr, data;
+
+ if (bus == sc->sc_busnr - 1)
+ bus = 0;
+
+ addr = CONFIG_ACCESS_ENABLE;
+ addr |= (bus & 0xff) << 16;
+ addr |= (slot & 0x1f) << 11;
+ addr |= (func & 0x7) << 8;
+ addr |= reg & 0xfc;
+ if (sc->sc_pcie)
+ addr |= (reg & 0xf00) << 16;
+
+ mtx_lock_spin(&pcicfg_mtx);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+ switch (bytes) {
+ case 1:
+ data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA + (reg & 3));
+ break;
+ case 2:
+ data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA + (reg & 2)));
+ break;
+ case 4:
+ data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA));
+ break;
+ default:
+ data = ~0;
+ break;
+ }
+ mtx_unlock_spin(&pcicfg_mtx);
+ return (data);
+}
+
+static void
+fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t data, int bytes)
+{
+ uint32_t addr;
+
+ if (bus == sc->sc_busnr - 1)
+ bus = 0;
+
+ addr = CONFIG_ACCESS_ENABLE;
+ addr |= (bus & 0xff) << 16;
+ addr |= (slot & 0x1f) << 11;
+ addr |= (func & 0x7) << 8;
+ addr |= reg & 0xfc;
+ if (sc->sc_pcie)
+ addr |= (reg & 0xf00) << 16;
+
+ mtx_lock_spin(&pcicfg_mtx);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+ switch (bytes) {
+ case 1:
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA + (reg & 3), data);
+ break;
+ case 2:
+ bus_space_write_2(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA + (reg & 2), htole16(data));
+ break;
+ case 4:
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ REG_CFG_DATA, htole32(data));
+ break;
+ }
+ mtx_unlock_spin(&pcicfg_mtx);
+}
+
+#if 0
+static void
+dump(struct fsl_pcib_softc *sc)
+{
+ unsigned int i;
+
+#define RD(o) bus_space_read_4(sc->sc_bst, sc->sc_bsh, o)
+ for (i = 0; i < 5; i++) {
+ printf("POTAR%u =0x%08x\n", i, RD(REG_POTAR(i)));
+ printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i)));
+ printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i)));
+ printf("POWAR%u =0x%08x\n", i, RD(REG_POWAR(i)));
+ }
+ printf("\n");
+ for (i = 1; i < 4; i++) {
+ printf("PITAR%u =0x%08x\n", i, RD(REG_PITAR(i)));
+ printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i)));
+ printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i)));
+ printf("PIWAR%u =0x%08x\n", i, RD(REG_PIWAR(i)));
+ }
+ printf("\n");
+#undef RD
+
+ for (i = 0; i < 0x48; i += 4) {
+ printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0,
+ i, 4));
+ }
+}
+#endif
+
+static int
+fsl_pcib_maxslots(device_t dev)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+ return ((sc->sc_pcie) ? 1 : 31);
+}
+
+static uint32_t
+fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+ u_int devfn;
+
+ if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+ return (~0);
+ devfn = DEVFN(bus, slot, func);
+ if (devfn == sc->sc_devfn_tundra)
+ return (~0);
+ if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN)
+ return (1);
+ return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes));
+}
+
+static void
+fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t val, int bytes)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+ if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+ return;
+ fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes);
+}
+
+static void
+fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus,
+ int slot, int fn)
+{
+
+ if (device == 0x0686) {
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1);
+ } else if (device == 0x0571) {
+ sc->sc_devfn_via_ide = DEVFN(bus, slot, fn);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1);
+ }
+}
+
+static int
+fsl_pcib_init_bar(struct fsl_pcib_softc *sc, int bus, int slot, int func,
+ int barno)
+{
+ bus_addr_t *allocp;
+ uint32_t addr, mask, size;
+ int reg, width;
+
+ reg = PCIR_BAR(barno);
+
+ if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) {
+ switch (barno) {
+ case 0: addr = 0x1f0; break;
+ case 1: addr = 0x3f4; break;
+ case 2: addr = 0x170; break;
+ case 3: addr = 0x374; break;
+ case 4: addr = 0xcc0; break;
+ default: return (1);
+ }
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
+ return (1);
+ }
+
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
+ size = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
+ if (size == 0)
+ return (1);
+ width = ((size & 7) == 4) ? 2 : 1;
+
+ if (size & 1) { /* I/O port */
+ allocp = &sc->sc_ioport_alloc;
+ size &= ~3;
+ if ((size & 0xffff0000) == 0)
+ size |= 0xffff0000;
+ } else { /* memory */
+ allocp = &sc->sc_iomem_alloc;
+ size &= ~15;
+ }
+ mask = ~size;
+ size = mask + 1;
+ /* Sanity check (must be a power of 2). */
+ if (size & mask)
+ return (width);
+
+ addr = (*allocp + mask) & ~mask;
+ *allocp = addr + size;
+
+ if (bootverbose)
+ printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n",
+ device_get_unit(sc->sc_dev), bus, slot, func, reg,
+ size, addr);
+
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
+ if (width == 2)
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
+ 0, 4);
+ return (width);
+}
+
+static u_int
+fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+ u_int intpin)
+{
+ int err, unit;
+ u_int devfn, intline;
+
+ unit = device_get_unit(sc->sc_dev);
+
+ devfn = DEVFN(bus, slot, func);
+ if (devfn == sc->sc_devfn_via_ide)
+#if 0
+ intline = INTR_VEC(ATPIC_ID, 14);
+ else if (devfn == sc->sc_devfn_via_ide + 1)
+ intline = INTR_VEC(ATPIC_ID, 10);
+ else if (devfn == sc->sc_devfn_via_ide + 2)
+ intline = INTR_VEC(ATPIC_ID, 10);
+#endif
+ ;
+ else {
+ if (intpin != 0)
+ err = fdt_pci_route_intr(bus, slot, func, intpin,
+ &sc->sc_intr_info, &intline);
+ else
+ intline = 0xff;
+ }
+
+ if (bootverbose)
+ printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n",
+ unit, bus, slot, func, intpin, intline);
+
+ return (intline);
+}
+
+static int
+fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset,
+ int maxslot)
+{
+ int secbus, subbus;
+ int old_pribus, old_secbus, old_subbus;
+ int new_pribus, new_secbus, new_subbus;
+ int slot, func, maxfunc;
+ int bar, maxbar;
+ uint16_t vendor, device;
+ uint8_t command, hdrtype, class, subclass;
+ uint8_t intline, intpin;
+
+ subbus = bus;
+ for (slot = 0; slot <= maxslot; slot++) {
+ maxfunc = 0;
+ for (func = 0; func <= maxfunc; func++) {
+
+ hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_HDRTYPE, 1);
+
+ if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+ continue;
+
+ if (func == 0 && (hdrtype & PCIM_MFDEV))
+ maxfunc = PCI_FUNCMAX;
+
+ vendor = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_VENDOR, 2);
+ device = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_DEVICE, 2);
+
+ if (vendor == 0x1957 && device == 0x3fff) {
+ sc->sc_devfn_tundra = DEVFN(bus, slot, func);
+ continue;
+ }
+
+ command = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_COMMAND, 1);
+ command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_COMMAND, command, 1);
+
+ if (vendor == 0x1106)
+ fsl_pcib_init_via(sc, device, bus, slot, func);
+
+ /* Program the base address registers. */
+ maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6;
+ bar = 0;
+ while (bar < maxbar)
+ bar += fsl_pcib_init_bar(sc, bus, slot, func,
+ bar);
+
+ /* Perform interrupt routing. */
+ intpin = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_INTPIN, 1);
+ intline = fsl_pcib_route_int(sc, bus, slot, func,
+ intpin);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_INTLINE, intline, 1);
+
+ command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_COMMAND, command, 1);
+
+ /*
+ * Handle PCI-PCI bridges
+ */
+ class = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_CLASS, 1);
+ subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+ func, PCIR_SUBCLASS, 1);
+#if 0
+ /* Allow only proper PCI-PCI briges */
+ if (class != PCIC_BRIDGE)
+ continue;
+ if (subclass != PCIS_BRIDGE_PCI)
+ continue;
+#endif
+ /* Allow all DEVTYPE 1 devices */
+ if (hdrtype != PCIM_HDRTYPE_BRIDGE)
+ continue;
+
+ subbus++;
+ secbus = subbus;
+
+ /* Program I/O decoder. */
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2);
+
+ /* Program (non-prefetchable) memory decoder. */
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2);
+
+ /* Program prefetchable memory decoder. */
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_PMBASEL_1, 0x0010, 2);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_PMLIMITL_1, 0x000f, 2);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_PMBASEH_1, 0x00000000, 4);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_PMLIMITH_1, 0x00000000, 4);
+
+ /* Read currect bus register configuration */
+ old_pribus = fsl_pcib_read_config(sc->sc_dev, bus,
+ slot, func, PCIR_PRIBUS_1, 1);
+ old_secbus = fsl_pcib_read_config(sc->sc_dev, bus,
+ slot, func, PCIR_SECBUS_1, 1);
+ old_subbus = fsl_pcib_read_config(sc->sc_dev, bus,
+ slot, func, PCIR_SUBBUS_1, 1);
+
+ if (bootverbose)
+ printf("PCI: reading firmware bus numbers for "
+ "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
+ secbus + busnr_offset, old_pribus,
+ old_secbus, old_subbus);
+
+ /* Skip unconfigured devices */
+ if ((old_pribus == 0) &&
+ (old_secbus == 0) && (old_subbus == 0))
+ continue;
+
+ subbus += fsl_pcib_init(sc, secbus, busnr_offset,
+ (subclass == PCIS_BRIDGE_PCI) ? 31 : 1);
+
+ new_pribus = bus + busnr_offset;
+ new_secbus = secbus + busnr_offset;
+ new_subbus = subbus + busnr_offset;
+
+ /* Fixup pribus for MPC8572 PCIE controller */
+ if ((vendor == 0x1957) && ((device = 0x0040) ||
+ (device == 0x0041)))
+ new_pribus = 0;
+
+ if (bootverbose)
+ printf("PCI: translate firmware bus numbers for "
+ "secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
+ secbus + busnr_offset,
+ old_pribus, old_secbus, old_subbus,
+ new_pribus, new_secbus, new_subbus);
+
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_PRIBUS_1, new_pribus, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_SECBUS_1, new_secbus, 1);
+ fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+ PCIR_SUBBUS_1, new_subbus, 1);
+ }
+ }
+
+ if (bootverbose)
+ printf("PCI: bus %d, #subbus = %d\n",
+ bus + busnr_offset, subbus - bus);
+
+ return (subbus - bus);
+}
+
+static void
+fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, u_long start,
+ u_long size, u_long pci_start)
+{
+ uint32_t attr, bar, tar;
+
+ KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__));
+
+ switch (tgt) {
+ /* XXX OCP85XX_TGTIF_RAM2, OCP85XX_TGTIF_RAM_INTL should be handled */
+ case OCP85XX_TGTIF_RAM1:
+ attr = 0xa0f55000 | (ffsl(size) - 2);
+ break;
+ default:
+ attr = 0;
+ break;
+ }
+ tar = start >> 12;
+ bar = pci_start >> 12;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr);
+}
+
+static void
+fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, u_long start,
+ u_long size, u_long pci_start)
+{
+ uint32_t attr, bar, tar;
+
+ switch (res) {
+ case SYS_RES_MEMORY:
+ attr = 0x80044000 | (ffsl(size) - 2);
+ break;
+ case SYS_RES_IOPORT:
+ attr = 0x80088000 | (ffsl(size) - 2);
+ break;
+ default:
+ attr = 0x0004401f;
+ break;
+ }
+ bar = start >> 12;
+ tar = pci_start >> 12;
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr);
+}
+
+static int
+fsl_pcib_set_range(struct fsl_pcib_softc *sc, int type, int wnd, u_long start,
+ u_long size)
+{
+ struct rman *rm;
+ u_long end, alloc;
+ bus_addr_t pci_start, pci_end;
+ bus_addr_t *vap, *allocp;
+ int error;
+
+ end = start + size - 1;
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_ioport;
+ pci_start = 0x0000;
+ pci_end = 0xffff;
+ alloc = 0x1000;
+ vap = &sc->sc_ioport_va;
+ allocp = &sc->sc_ioport_alloc;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_iomem;
+ pci_start = start;
+ pci_end = end;
+ alloc = 0;
+ vap = &sc->sc_iomem_va;
+ allocp = &sc->sc_iomem_alloc;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ rm->rm_type = RMAN_ARRAY;
+ rm->rm_start = pci_start;
+ rm->rm_end = pci_end;
+ error = rman_init(rm);
+ if (error)
+ return (error);
+
+ error = rman_manage_region(rm, pci_start, pci_end);
+ if (error) {
+ rman_fini(rm);
+ return (error);
+ }
+
+ *allocp = pci_start + alloc;
+ *vap = (uintptr_t)pmap_mapdev(start, size);
+ fsl_pcib_outbound(sc, wnd, type, start, size, pci_start);
+ return (0);
+}
+
+static void
+fsl_pcib_err_init(device_t dev)
+{
+ struct fsl_pcib_softc *sc;
+ uint16_t sec_stat, dsr;
+ uint32_t dcr, err_en;
+
+ sc = device_get_softc(dev);
+
+ sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2);
+ if (sec_stat)
+ fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2);
+ if (sc->sc_pcie) {
+ /* Clear error bits */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER,
+ 0xffffffff);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR,
+ 0xffffffff);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR,
+ 0xffffffff);
+
+ dsr = fsl_pcib_cfgread(sc, 0, 0, 0,
+ sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA, 2);
+ if (dsr)
+ fsl_pcib_cfgwrite(sc, 0, 0, 0,
+ sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA,
+ 0xffff, 2);
+
+ /* Enable all errors reporting */
+ err_en = 0x00bfff00;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN,
+ err_en);
+
+ /* Enable error reporting: URR, FER, NFER */
+ dcr = fsl_pcib_cfgread(sc, 0, 0, 0,
+ sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, 4);
+ dcr |= PCIM_EXP_CTL_URR_ENABLE | PCIM_EXP_CTL_FER_ENABLE |
+ PCIM_EXP_CTL_NFER_ENABLE;
+ fsl_pcib_cfgwrite(sc, 0, 0, 0,
+ sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, dcr, 4);
+ }
+}
+
+static int
+fsl_pcib_detach(device_t dev)
+{
+
+ if (mtx_initialized) {
+ mtx_destroy(&pcicfg_mtx);
+ mtx_initialized = 0;
+ }
+ return (bus_generic_detach(dev));
+}
+
+static struct resource *
+fsl_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+ struct rman *rm;
+ struct resource *res;
+ bus_addr_t va;
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_ioport;
+ va = sc->sc_ioport_va;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_iomem;
+ va = sc->sc_iomem_va;
+ break;
+ case SYS_RES_IRQ:
+#if 0
+ if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) {
+ device_printf(dev, "%s requested ISA interrupt %lu\n",
+ device_get_nameunit(child), start);
+ }
+#endif
+ flags |= RF_SHAREABLE;
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ type, rid, start, end, count, flags));
+ default:
+ return (NULL);
+ }
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL)
+ return (NULL);
+
+ rman_set_bustag(res, &bs_le_tag);
+ rman_set_bushandle(res, va + rman_get_start(res) - rm->rm_start);
+ return (res);
+}
+
+static int
+fsl_pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ return (rman_release_resource(res));
+}
+
+static int
+fsl_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_busnr;
+ return (0);
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static int
+fsl_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ sc->sc_busnr = value;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static int
+fsl_pcib_intr_info(phandle_t node, struct fsl_pcib_softc *sc)
+{
+ int error;
+
+ if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0)
+ return (error);
+
+ return (0);
+}
+
+static int
+fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
+{
+ struct fdt_pci_range io_space, mem_space;
+ device_t dev;
+ int error;
+
+ dev = sc->sc_dev;
+
+ if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) {
+ device_printf(dev, "could not retrieve 'ranges' data\n");
+ return (error);
+ }
+
+ /*
+ * Configure LAW decode windows.
+ */
+ error = law_pci_target(sc->sc_res, &sc->sc_iomem_target,
+ &sc->sc_ioport_target);
+ if (error != 0) {
+ device_printf(dev, "could not retrieve PCI LAW target info\n");
+ return (error);
+ }
+ error = law_enable(sc->sc_iomem_target, mem_space.base_parent,
+ mem_space.len);
+ if (error != 0) {
+ device_printf(dev, "could not program LAW for PCI MEM range\n");
+ return (error);
+ }
+ error = law_enable(sc->sc_ioport_target, io_space.base_parent,
+ io_space.len);
+ if (error != 0) {
+ device_printf(dev, "could not program LAW for PCI IO range\n");
+ return (error);
+ }
+
+ /*
+ * Set outbout and inbound windows.
+ */
+ fsl_pcib_outbound(sc, 0, -1, 0, 0, 0);
+ if ((error = fsl_pcib_set_range(sc, SYS_RES_MEMORY, 1,
+ mem_space.base_parent, mem_space.len)) != 0)
+ return (error);
+ if ((error = fsl_pcib_set_range(sc, SYS_RES_IOPORT, 2,
+ io_space.base_parent, io_space.len)) != 0)
+ return (error);
+
+ fsl_pcib_outbound(sc, 3, -1, 0, 0, 0);
+ fsl_pcib_outbound(sc, 4, -1, 0, 0, 0);
+
+ fsl_pcib_inbound(sc, 1, -1, 0, 0, 0);
+ fsl_pcib_inbound(sc, 2, -1, 0, 0, 0);
+ fsl_pcib_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0,
+ 2U * 1024U * 1024U * 1024U, 0);
+
+ return (0);
+}
diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c
deleted file mode 100644
index 857f222..0000000
--- a/sys/powerpc/mpc85xx/pci_ocp.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/*-
- * Copyright 2006-2007 by Juniper Networks.
- * All rights reserved.
- *
- * 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. 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/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ktr.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-#include <sys/endian.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcib_private.h>
-
-#include "pcib_if.h"
-
-#include <machine/resource.h>
-#include <machine/bus.h>
-#include <machine/intr_machdep.h>
-#include <machine/ocpbus.h>
-#include <machine/spr.h>
-
-#include <powerpc/mpc85xx/ocpbus.h>
-
-#define REG_CFG_ADDR 0x0000
-#define CONFIG_ACCESS_ENABLE 0x80000000
-
-#define REG_CFG_DATA 0x0004
-#define REG_INT_ACK 0x0008
-
-#define REG_POTAR(n) (0x0c00 + 0x20 * (n))
-#define REG_POTEAR(n) (0x0c04 + 0x20 * (n))
-#define REG_POWBAR(n) (0x0c08 + 0x20 * (n))
-#define REG_POWAR(n) (0x0c10 + 0x20 * (n))
-
-#define REG_PITAR(n) (0x0e00 - 0x20 * (n))
-#define REG_PIWBAR(n) (0x0e08 - 0x20 * (n))
-#define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n))
-#define REG_PIWAR(n) (0x0e10 - 0x20 * (n))
-
-#define PCIR_FSL_LTSSM 0x404
-#define FSL_LTSSM_L0 0x16
-
-#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f)
-
-struct pci_ocp_softc {
- device_t sc_dev;
-
- struct rman sc_iomem;
- bus_addr_t sc_iomem_va; /* Virtual mapping. */
- bus_addr_t sc_iomem_alloc; /* Next allocation. */
- struct rman sc_ioport;
- bus_addr_t sc_ioport_va; /* Virtual mapping. */
- bus_addr_t sc_ioport_alloc; /* Next allocation. */
-
- struct resource *sc_res;
- bus_space_handle_t sc_bsh;
- bus_space_tag_t sc_bst;
- int sc_rid;
-
- int sc_busnr;
- uint8_t sc_pcie_cap;
-
- /* Devices that need special attention. */
- int sc_devfn_tundra;
- int sc_devfn_via_ide;
-};
-
-static int pci_ocp_attach(device_t);
-static int pci_ocp_probe(device_t);
-
-static struct resource *pci_ocp_alloc_resource(device_t, device_t, int, int *,
- u_long, u_long, u_long, u_int);
-static int pci_ocp_read_ivar(device_t, device_t, int, uintptr_t *);
-static int pci_ocp_release_resource(device_t, device_t, int, int,
- struct resource *);
-static int pci_ocp_write_ivar(device_t, device_t, int, uintptr_t);
-
-static int pci_ocp_maxslots(device_t);
-static uint32_t pci_ocp_read_config(device_t, u_int, u_int, u_int, u_int, int);
-static void pci_ocp_write_config(device_t, u_int, u_int, u_int, u_int,
- uint32_t, int);
-
-/*
- * Bus interface definitions.
- */
-static device_method_t pci_ocp_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, pci_ocp_probe),
- DEVMETHOD(device_attach, pci_ocp_attach),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_read_ivar, pci_ocp_read_ivar),
- DEVMETHOD(bus_write_ivar, pci_ocp_write_ivar),
- DEVMETHOD(bus_alloc_resource, pci_ocp_alloc_resource),
- DEVMETHOD(bus_release_resource, pci_ocp_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
-
- /* pcib interface */
- DEVMETHOD(pcib_maxslots, pci_ocp_maxslots),
- DEVMETHOD(pcib_read_config, pci_ocp_read_config),
- DEVMETHOD(pcib_write_config, pci_ocp_write_config),
- DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
-
- { 0, 0 }
-};
-
-static driver_t pci_ocp_driver = {
- "pcib",
- pci_ocp_methods,
- sizeof(struct pci_ocp_softc),
-};
-
-devclass_t pcib_devclass;
-
-DRIVER_MODULE(pcib, ocpbus, pci_ocp_driver, pcib_devclass, 0, 0);
-
-static uint32_t
-pci_ocp_cfgread(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func,
- u_int reg, int bytes)
-{
- uint32_t addr, data;
-
- if (bus == sc->sc_busnr)
- bus = 0;
-
- addr = CONFIG_ACCESS_ENABLE;
- addr |= (bus & 0xff) << 16;
- addr |= (slot & 0x1f) << 11;
- addr |= (func & 0x7) << 8;
- addr |= reg & 0xfc;
- if (sc->sc_pcie_cap)
- addr |= (reg & 0xf00) << 16;
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
-
- switch (bytes) {
- case 1:
- data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA + (reg & 3));
- break;
- case 2:
- data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA + (reg & 2)));
- break;
- case 4:
- data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA));
- break;
- default:
- data = ~0;
- break;
- }
- return (data);
-}
-
-static void
-pci_ocp_cfgwrite(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func,
- u_int reg, uint32_t data, int bytes)
-{
- uint32_t addr;
-
- if (bus == sc->sc_busnr)
- bus = 0;
-
- addr = CONFIG_ACCESS_ENABLE;
- addr |= (bus & 0xff) << 16;
- addr |= (slot & 0x1f) << 11;
- addr |= (func & 0x7) << 8;
- addr |= reg & 0xfc;
- if (sc->sc_pcie_cap)
- addr |= (reg & 0xf00) << 16;
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
-
- switch (bytes) {
- case 1:
- bus_space_write_1(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA + (reg & 3), data);
- break;
- case 2:
- bus_space_write_2(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA + (reg & 2), htole16(data));
- break;
- case 4:
- bus_space_write_4(sc->sc_bst, sc->sc_bsh,
- REG_CFG_DATA, htole32(data));
- break;
- }
-}
-
-#if 0
-static void
-dump(struct pci_ocp_softc *sc)
-{
- unsigned int i;
-
-#define RD(o) bus_space_read_4(sc->sc_bst, sc->sc_bsh, o)
- for (i = 0; i < 5; i++) {
- printf("POTAR%u =0x%08x\n", i, RD(REG_POTAR(i)));
- printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i)));
- printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i)));
- printf("POWAR%u =0x%08x\n", i, RD(REG_POWAR(i)));
- }
- printf("\n");
- for (i = 1; i < 4; i++) {
- printf("PITAR%u =0x%08x\n", i, RD(REG_PITAR(i)));
- printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i)));
- printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i)));
- printf("PIWAR%u =0x%08x\n", i, RD(REG_PIWAR(i)));
- }
- printf("\n");
-#undef RD
-
- for (i = 0; i < 0x48; i += 4) {
- printf("cfg%02x=0x%08x\n", i, pci_ocp_cfgread(sc, 0, 0, 0,
- i, 4));
- }
-}
-#endif
-
-static int
-pci_ocp_maxslots(device_t dev)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
-
- return ((sc->sc_pcie_cap) ? 0 : 31);
-}
-
-static uint32_t
-pci_ocp_read_config(device_t dev, u_int bus, u_int slot, u_int func,
- u_int reg, int bytes)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
- u_int devfn;
-
- if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10)
- return (~0);
- devfn = DEVFN(bus, slot, func);
- /*
- * For the host controller itself, pretend to be a standard
- * PCI bridge, rather than a PowerPC processor. That way the
- * generic PCI code will enumerate all subordinate busses
- * and devices as usual.
- */
- if (sc->sc_pcie_cap && devfn == 0) {
- if (reg == PCIR_CLASS && bytes == 1)
- return (PCIC_BRIDGE);
- if (reg == PCIR_SUBCLASS && bytes == 1)
- return (PCIS_BRIDGE_PCI);
- }
- if (devfn == sc->sc_devfn_tundra)
- return (~0);
- if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN)
- return (1);
- return (pci_ocp_cfgread(sc, bus, slot, func, reg, bytes));
-}
-
-static void
-pci_ocp_write_config(device_t dev, u_int bus, u_int slot, u_int func,
- u_int reg, uint32_t val, int bytes)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
-
- if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10)
- return;
- pci_ocp_cfgwrite(sc, bus, slot, func, reg, val, bytes);
-}
-
-static int
-pci_ocp_probe(device_t dev)
-{
- char buf[128];
- struct pci_ocp_softc *sc;
- const char *type;
- device_t parent;
- u_long start, size;
- uintptr_t devtype;
- uint32_t cfgreg;
- uint8_t capptr;
- int error;
-
- parent = device_get_parent(dev);
- error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
- if (error)
- return (error);
- if (devtype != OCPBUS_DEVTYPE_PCIB)
- return (ENXIO);
-
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
-
- sc->sc_rid = 0;
- sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
- RF_ACTIVE);
- if (sc->sc_res == NULL)
- return (ENXIO);
-
- sc->sc_bst = rman_get_bustag(sc->sc_res);
- sc->sc_bsh = rman_get_bushandle(sc->sc_res);
- sc->sc_busnr = 0;
-
- error = ENOENT;
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2);
- if (cfgreg != 0x1057 && cfgreg != 0x1957)
- goto out;
-
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_CLASS, 1);
- if (cfgreg != PCIC_PROCESSOR)
- goto out;
-
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_SUBCLASS, 1);
- if (cfgreg != PCIS_PROCESSOR_POWERPC)
- goto out;
-
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_PROGIF, 1);
- if (cfgreg != 0) /* RC mode = 0, EP mode = 1 */
- goto out;
-
- type = "PCI";
- capptr = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1);
- while (capptr != 0) {
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, capptr, 2);
- switch (cfgreg & 0xff) {
- case PCIY_PCIX: /* PCI-X */
- type = "PCI-X";
- break;
- case PCIY_EXPRESS: /* PCI Express */
- type = "PCI Express";
- sc->sc_pcie_cap = capptr;
- break;
- }
- capptr = (cfgreg >> 8) & 0xff;
- }
-
- error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size);
- if (error || start == 0 || size == 0)
- goto out;
-
- snprintf(buf, sizeof(buf),
- "Freescale on-chip %s host controller", type);
- device_set_desc_copy(dev, buf);
- error = BUS_PROBE_DEFAULT;
-
-out:
- bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
- return (error);
-}
-
-static void
-pci_ocp_init_via(struct pci_ocp_softc *sc, uint16_t device, int bus,
- int slot, int fn)
-{
-
- if (device == 0x0686) {
- pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1);
- } else if (device == 0x0571) {
- sc->sc_devfn_via_ide = DEVFN(bus, slot, fn);
- pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1);
- }
-}
-
-static int
-pci_ocp_init_bar(struct pci_ocp_softc *sc, int bus, int slot, int func,
- int barno)
-{
- bus_addr_t *allocp;
- uint32_t addr, mask, size;
- int reg, width;
-
- reg = PCIR_BAR(barno);
-
- if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) {
- switch (barno) {
- case 0: addr = 0x1f0; break;
- case 1: addr = 0x3f4; break;
- case 2: addr = 0x170; break;
- case 3: addr = 0x374; break;
- case 4: addr = 0xcc0; break;
- default: return (1);
- }
- pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
- return (1);
- }
-
- pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
- size = pci_ocp_read_config(sc->sc_dev, bus, slot, func, reg, 4);
- if (size == 0)
- return (1);
- width = ((size & 7) == 4) ? 2 : 1;
-
- if (size & 1) { /* I/O port */
- allocp = &sc->sc_ioport_alloc;
- size &= ~3;
- if ((size & 0xffff0000) == 0)
- size |= 0xffff0000;
- } else { /* memory */
- allocp = &sc->sc_iomem_alloc;
- size &= ~15;
- }
- mask = ~size;
- size = mask + 1;
- /* Sanity check (must be a power of 2). */
- if (size & mask)
- return (width);
-
- addr = (*allocp + mask) & ~mask;
- *allocp = addr + size;
-
- if (bootverbose)
- printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n",
- device_get_unit(sc->sc_dev), bus, slot, func, reg,
- size, addr);
-
- pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
- if (width == 2)
- pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg + 4,
- 0, 4);
- return (width);
-}
-
-static u_int
-pci_ocp_route_int(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func,
- u_int intpin)
-{
- u_int devfn, intline;
-
- devfn = DEVFN(bus, slot, func);
- if (devfn == sc->sc_devfn_via_ide)
- intline = INTR_VEC(ATPIC_ID, 14);
- else if (devfn == sc->sc_devfn_via_ide + 1)
- intline = INTR_VEC(ATPIC_ID, 10);
- else if (devfn == sc->sc_devfn_via_ide + 2)
- intline = INTR_VEC(ATPIC_ID, 10);
- else {
- if (intpin != 0) {
- intline = intpin - 1;
- intline += (bus != sc->sc_busnr) ? slot : 0;
- intline = PIC_IRQ_EXT(intline & 3);
- } else
- intline = 0xff;
- }
-
- if (bootverbose)
- printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n",
- device_get_unit(sc->sc_dev), bus, slot, func,
- intpin, intline);
-
- return (intline);
-}
-
-static int
-pci_ocp_init(struct pci_ocp_softc *sc, int bus, int nslots)
-{
- int secbus, slot;
- int func, maxfunc;
- int bar, maxbar;
- uint16_t vendor, device;
- uint8_t command, hdrtype, class, subclass;
- uint8_t intline, intpin;
-
- secbus = bus;
- for (slot = 0; slot < nslots; slot++) {
- maxfunc = 0;
- for (func = 0; func <= maxfunc; func++) {
- hdrtype = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_HDRTYPE, 1);
- if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
- continue;
-
- if (func == 0 && (hdrtype & PCIM_MFDEV))
- maxfunc = PCI_FUNCMAX;
-
- vendor = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_VENDOR, 2);
- device = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_DEVICE, 2);
-
- if (vendor == 0x1957 && device == 0x3fff) {
- sc->sc_devfn_tundra = DEVFN(bus, slot, func);
- continue;
- }
-
- command = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_COMMAND, 1);
- command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_COMMAND, command, 1);
-
- if (vendor == 0x1106)
- pci_ocp_init_via(sc, device, bus, slot, func);
-
- /* Program the base address registers. */
- maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6;
- bar = 0;
- while (bar < maxbar)
- bar += pci_ocp_init_bar(sc, bus, slot, func,
- bar);
-
- /* Perform interrupt routing. */
- intpin = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_INTPIN, 1);
- intline = pci_ocp_route_int(sc, bus, slot, func,
- intpin);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_INTLINE, intline, 1);
-
- command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_COMMAND, command, 1);
-
- /*
- * Handle PCI-PCI bridges
- */
- class = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_CLASS, 1);
- if (class != PCIC_BRIDGE)
- continue;
- subclass = pci_ocp_read_config(sc->sc_dev, bus, slot,
- func, PCIR_SUBCLASS, 1);
- if (subclass != PCIS_BRIDGE_PCI)
- continue;
-
- secbus++;
-
- /* Program I/O decoder. */
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2);
-
- /* Program (non-prefetchable) memory decoder. */
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2);
-
- /* Program prefetchable memory decoder. */
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_PMBASEL_1, 0x0010, 2);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_PMLIMITL_1, 0x000f, 2);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_PMBASEH_1, 0x00000000, 4);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_PMLIMITH_1, 0x00000000, 4);
-
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_PRIBUS_1, bus, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_SECBUS_1, secbus, 1);
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_SUBBUS_1, 0xff, 1);
-
- secbus = pci_ocp_init(sc, secbus,
- (subclass == PCIS_BRIDGE_PCI) ? 32 : 1);
-
- pci_ocp_write_config(sc->sc_dev, bus, slot, func,
- PCIR_SUBBUS_1, secbus, 1);
- }
- }
-
- return (secbus);
-}
-
-static void
-pci_ocp_inbound(struct pci_ocp_softc *sc, int wnd, int tgt, u_long start,
- u_long size, u_long pci_start)
-{
- uint32_t attr, bar, tar;
-
- KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__));
-
- switch (tgt) {
- case OCP85XX_TGTIF_RAM1:
- attr = 0xa0f55000 | (ffsl(size) - 2);
- break;
- default:
- attr = 0;
- break;
- }
- tar = start >> 12;
- bar = pci_start >> 12;
-
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr);
-}
-
-static void
-pci_ocp_outbound(struct pci_ocp_softc *sc, int wnd, int res, u_long start,
- u_long size, u_long pci_start)
-{
- uint32_t attr, bar, tar;
-
- switch (res) {
- case SYS_RES_MEMORY:
- attr = 0x80044000 | (ffsl(size) - 2);
- break;
- case SYS_RES_IOPORT:
- attr = 0x80088000 | (ffsl(size) - 2);
- break;
- default:
- attr = 0x0004401f;
- break;
- }
- bar = start >> 12;
- tar = pci_start >> 12;
-
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr);
-}
-
-static int
-pci_ocp_iorange(struct pci_ocp_softc *sc, int type, int wnd)
-{
- struct rman *rm;
- u_long start, end, size, alloc;
- bus_addr_t pci_start, pci_end;
- bus_addr_t *vap, *allocp;
- int error;
-
- error = bus_get_resource(sc->sc_dev, type, 1, &start, &size);
- if (error)
- return (error);
-
- end = start + size - 1;
-
- switch (type) {
- case SYS_RES_IOPORT:
- rm = &sc->sc_ioport;
- pci_start = 0x0000;
- pci_end = 0xffff;
- alloc = 0x1000;
- vap = &sc->sc_ioport_va;
- allocp = &sc->sc_ioport_alloc;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->sc_iomem;
- pci_start = start;
- pci_end = end;
- alloc = 0;
- vap = &sc->sc_iomem_va;
- allocp = &sc->sc_iomem_alloc;
- break;
- default:
- return (EINVAL);
- }
-
- rm->rm_type = RMAN_ARRAY;
- rm->rm_start = pci_start;
- rm->rm_end = pci_end;
- error = rman_init(rm);
- if (error)
- return (error);
-
- error = rman_manage_region(rm, pci_start, pci_end);
- if (error) {
- rman_fini(rm);
- return (error);
- }
-
- *allocp = pci_start + alloc;
- *vap = (uintptr_t)pmap_mapdev(start, size);
- if (wnd != -1)
- pci_ocp_outbound(sc, wnd, type, start, size, pci_start);
- return (0);
-}
-
-static int
-pci_ocp_attach(device_t dev)
-{
- struct pci_ocp_softc *sc;
- uint32_t cfgreg;
- int error, nslots;
-
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
-
- sc->sc_rid = 0;
- sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
- RF_ACTIVE);
- if (sc->sc_res == NULL) {
- device_printf(dev, "could not map I/O memory\n");
- return (ENXIO);
- }
- sc->sc_bst = rman_get_bustag(sc->sc_res);
- sc->sc_bsh = rman_get_bushandle(sc->sc_res);
-
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
- cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
- PCIM_CMD_PORTEN;
- pci_ocp_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2);
-
- pci_ocp_outbound(sc, 0, -1, 0, 0, 0);
- error = pci_ocp_iorange(sc, SYS_RES_MEMORY, 1);
- error = pci_ocp_iorange(sc, SYS_RES_IOPORT, 2);
- pci_ocp_outbound(sc, 3, -1, 0, 0, 0);
- pci_ocp_outbound(sc, 4, -1, 0, 0, 0);
-
- pci_ocp_inbound(sc, 1, -1, 0, 0, 0);
- pci_ocp_inbound(sc, 2, -1, 0, 0, 0);
- pci_ocp_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0, 2U*1024U*1024U*1024U, 0);
-
- sc->sc_devfn_tundra = -1;
- sc->sc_devfn_via_ide = -1;
-
- /*
- * PCI Express host controllers require a link. We don't
- * fail the attach if there's no link, but we also don't
- * create a child pci(4) device.
- */
- if (sc->sc_pcie_cap) {
- cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_FSL_LTSSM, 4);
- if (cfgreg < FSL_LTSSM_L0)
- return (0);
- }
-
- nslots = (sc->sc_pcie_cap) ? 1 : 32;
- pci_ocp_init(sc, sc->sc_busnr, nslots);
-
- device_add_child(dev, "pci", -1);
- return (bus_generic_attach(dev));
-}
-
-static struct resource *
-pci_ocp_alloc_resource(device_t dev, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
- struct rman *rm;
- struct resource *res;
- bus_addr_t va;
-
- switch (type) {
- case SYS_RES_IOPORT:
- rm = &sc->sc_ioport;
- va = sc->sc_ioport_va;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->sc_iomem;
- va = sc->sc_iomem_va;
- break;
- case SYS_RES_IRQ:
- if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) {
- device_printf(dev, "%s requested ISA interrupt %lu\n",
- device_get_nameunit(child), start);
- }
- flags |= RF_SHAREABLE;
- return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
- type, rid, start, end, count, flags));
- default:
- return (NULL);
- }
-
- res = rman_reserve_resource(rm, start, end, count, flags, child);
- if (res == NULL)
- return (NULL);
-
- rman_set_bustag(res, &bs_le_tag);
- rman_set_bushandle(res, va + rman_get_start(res) - rm->rm_start);
- return (res);
-}
-
-static int
-pci_ocp_release_resource(device_t dev, device_t child, int type, int rid,
- struct resource *res)
-{
-
- return (rman_release_resource(res));
-}
-
-static int
-pci_ocp_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_BUS:
- *result = sc->sc_busnr;
- return (0);
- case PCIB_IVAR_DOMAIN:
- *result = device_get_unit(dev);
- return (0);
- }
- return (ENOENT);
-}
-
-static int
-pci_ocp_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
-{
- struct pci_ocp_softc *sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_BUS:
- sc->sc_busnr = value;
- return (0);
- }
- return (ENOENT);
-}
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index 697f4b0..5a0ff8c 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -60,8 +60,6 @@
* $FreeBSD$
*/
-#include "opt_platform.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
OpenPOWER on IntegriCloud