summaryrefslogtreecommitdiff
path: root/sys/arch/loongson
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-02-28 21:35:44 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-02-28 21:35:44 +0000
commitc7ebfc8570d09b148f276b841f5990e56da5c86e (patch)
tree43e3d204f2d31fb6080ac9d29743fdddd52382f3 /sys/arch/loongson
parent30891d165f3c9c4005a24b2c862f819c00bf52c3 (diff)
A better bus_space_map() function for bonito PCI memory space, which no
longers assumes all requested mappings fit in the three 64MB PCILO windows, but will instead check whether the requested mappings can be provided by PCILO regions or PCIHI regions (and on 2F-based systems, making sure we only use addresses which get properly routed from CPU to PCI within the 2F crossbar). This in turn requires early console code to abide the bus_space rules and get its resources from bus_space_map() rather than doing PCI BAR arithmetic by itself. No functional change on Lemote Yeeloong and Gdium Liberty; on Lemote Fuloong 2F this allows BAR set up in PCIHI space by PMON to be mapped by kernel code without having to compensate for the PCILO offset.
Diffstat (limited to 'sys/arch/loongson')
-rw-r--r--sys/arch/loongson/dev/bonito.c108
-rw-r--r--sys/arch/loongson/dev/bonitoreg.h45
-rw-r--r--sys/arch/loongson/dev/smfb.c20
-rw-r--r--sys/arch/loongson/loongson/wscons_machdep.c7
4 files changed, 147 insertions, 33 deletions
diff --git a/sys/arch/loongson/dev/bonito.c b/sys/arch/loongson/dev/bonito.c
index 9e141c78cc5..83b52cab3dd 100644
--- a/sys/arch/loongson/dev/bonito.c
+++ b/sys/arch/loongson/dev/bonito.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonito.c,v 1.11 2010/02/24 22:33:20 miod Exp $ */
+/* $OpenBSD: bonito.c,v 1.12 2010/02/28 21:35:41 miod Exp $ */
/* $NetBSD: bonito_mainbus.c,v 1.11 2008/04/28 20:23:10 martin Exp $ */
/* $NetBSD: bonito_pci.c,v 1.5 2008/04/28 20:23:28 martin Exp $ */
@@ -165,6 +165,8 @@ struct machine_bus_dma_tag bonito_bus_dma_tag = {
int bonito_io_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
+int bonito_mem_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
struct mips_bus_space bonito_pci_io_space_tag = {
.bus_base = PHYS_TO_XKPHYS(BONITO_PCIIO_BASE, CCA_NC),
@@ -189,7 +191,7 @@ struct mips_bus_space bonito_pci_io_space_tag = {
};
struct mips_bus_space bonito_pci_mem_space_tag = {
- .bus_base = PHYS_TO_XKPHYS(BONITO_PCILO_BASE, CCA_NC),
+ .bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
._space_read_1 = generic_space_read_1,
._space_write_1 = generic_space_write_1,
._space_read_2 = generic_space_read_2,
@@ -204,7 +206,7 @@ struct mips_bus_space bonito_pci_mem_space_tag = {
._space_write_raw_4 = generic_space_write_raw_4,
._space_read_raw_8 = generic_space_read_raw_8,
._space_write_raw_8 = generic_space_write_raw_8,
- ._space_map = generic_space_map,
+ ._space_map = bonito_mem_map,
._space_unmap = generic_space_unmap,
._space_subregion = generic_space_region,
._space_vaddr = generic_space_vaddr
@@ -1136,6 +1138,106 @@ bonito_io_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
}
/*
+ * PCI memory access.
+ * Things are a bit complicated here, as we can either use one of the 64MB
+ * windows in PCILO space (making sure ranges spanning multiple windows will
+ * turn contiguous), or a direct access within the PCIHI space.
+ * Note that, on 2F systems, only the PCIHI range for which CPU->PCI accesses
+ * are enabled in the crossbar is usable.
+ */
+
+int
+bonito_mem_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ uint32_t pcimap;
+ bus_addr_t pcilo_w[3];
+ bus_addr_t ws, we, w;
+ bus_addr_t end = offs + size - 1;
+ int is2f, pcilo_window;
+
+ /*
+ * Decode PCIMAP, and figure out what PCILO mappings are
+ * possible.
+ */
+
+ pcimap = REGVAL(BONITO_PCIMAP);
+ pcilo_w[0] = (pcimap & BONITO_PCIMAP_PCIMAP_LO0) >>
+ BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
+ pcilo_w[1] = (pcimap & BONITO_PCIMAP_PCIMAP_LO1) >>
+ BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
+ pcilo_w[2] = (pcimap & BONITO_PCIMAP_PCIMAP_LO2) >>
+ BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
+
+ /*
+ * Check if the 64MB areas we want to span are all available as
+ * contiguous PCILO mappings.
+ */
+
+ ws = offs >> 26;
+ we = end >> 26;
+
+ pcilo_window = -1;
+ if (ws == pcilo_w[0])
+ pcilo_window = 0;
+ else if (ws == pcilo_w[1])
+ pcilo_window = 1;
+ else if (ws == pcilo_w[2])
+ pcilo_window = 2;
+
+ if (pcilo_window >= 0) {
+ /* contiguous area test */
+ for (w = ws + 1; w <= we; w++) {
+ if (pcilo_window + (w - ws) > 2 ||
+ w != pcilo_w[pcilo_window + (w - ws)]) {
+ pcilo_window = -1;
+ break;
+ }
+ }
+ }
+
+ if (pcilo_window >= 0) {
+ *bshp = t->bus_base + BONITO_PCILO_BASE +
+ BONITO_PCIMAP_WINBASE(pcilo_window) +
+ BONITO_PCIMAP_WINOFFSET(offs);
+ return 0;
+ }
+
+ /*
+ * No luck, try a PCIHI mapping.
+ */
+
+ /* may be used before curcpu() points to valid data */
+ if ((cp0_get_prid() & 0xffff) ==
+ ((MIPS_LOONGSON2 << 8) | (0x2f - 0x2c)))
+ is2f = 1;
+ else
+ is2f = 0;
+
+ if (is2f) {
+ if (offs >= LS2F_PCIHI_BASE && end <= LS2F_PCIHI_TOP) {
+ *bshp = t->bus_base + offs;
+ return 0;
+ }
+ } else {
+ /* PCI1.5 */
+ if (offs >= BONITO_PCIHI_BASE && end <= BONITO_PCIHI_TOP) {
+ *bshp = t->bus_base + offs;
+ return 0;
+ }
+
+ /* PCI2 */
+ w = pcimap & BONITO_PCIMAP_PCIMAP_2 ? 0x80000000UL : 0;
+ if (offs >= w && end < (w + 0x80000000UL)) {
+ *bshp = t->bus_base + 0x80000000UL + (offs - w);
+ return 0;
+ }
+ }
+
+ return EINVAL;
+}
+
+/*
* PCI resource handling
*/
diff --git a/sys/arch/loongson/dev/bonitoreg.h b/sys/arch/loongson/dev/bonitoreg.h
index c0ea9a43ff0..d542523f9d5 100644
--- a/sys/arch/loongson/dev/bonitoreg.h
+++ b/sys/arch/loongson/dev/bonitoreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bonitoreg.h,v 1.5 2010/02/23 20:41:33 miod Exp $ */
+/* $OpenBSD: bonitoreg.h,v 1.6 2010/02/28 21:35:41 miod Exp $ */
/* $NetBSD: bonitoreg.h,v 1.6 2005/12/24 20:07:19 perry Exp $ */
/*
@@ -34,35 +34,35 @@
#define REGVAL(x) *((volatile u_int32_t *)PHYS_TO_XKPHYS(x, CCA_NC))
-#define BONITO_FLASH_BASE 0x1c000000
-#define BONITO_FLASH_SIZE 0x02000000
+#define BONITO_FLASH_BASE 0x1c000000UL
+#define BONITO_FLASH_SIZE 0x02000000UL
#define BONITO_FLASH_TOP (BONITO_FLASH_BASE+BONITO_FLASH_SIZE-1)
-#define BONITO_BOOT_BASE 0x1fc00000
-#define BONITO_BOOT_SIZE 0x00100000
+#define BONITO_BOOT_BASE 0x1fc00000UL
+#define BONITO_BOOT_SIZE 0x00100000UL
#define BONITO_BOOT_TOP (BONITO_BOOT_BASE+BONITO_BOOT_SIZE-1)
-#define BONITO_REG_BASE 0x1fe00000
-#define BONITO_REG_SIZE 0x00040000
+#define BONITO_REG_BASE 0x1fe00000UL
+#define BONITO_REG_SIZE 0x00040000UL
#define BONITO_REG_TOP (BONITO_REG_BASE+BONITO_REG_SIZE-1)
-#define BONITO_PCILO_BASE 0x10000000
-#define BONITO_PCILO_SIZE 0x0c000000
+#define BONITO_PCILO_BASE 0x10000000UL
+#define BONITO_PCILO_SIZE 0x0c000000UL
#define BONITO_PCILO_TOP (BONITO_PCILO_BASE+BONITO_PCILO_SIZE-1)
-#define BONITO_PCILO0_BASE 0x10000000
-#define BONITO_PCILO1_BASE 0x14000000
-#define BONITO_PCILO2_BASE 0x18000000
-#define BONITO_PCIHI_BASE 0x20000000
-#define BONITO_PCIHI_SIZE 0x20000000
+#define BONITO_PCILO0_BASE 0x10000000UL
+#define BONITO_PCILO1_BASE 0x14000000UL
+#define BONITO_PCILO2_BASE 0x18000000UL
+#define BONITO_PCIHI_BASE 0x20000000UL
+#define BONITO_PCIHI_SIZE 0x60000000UL
#define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE+BONITO_PCIHI_SIZE-1)
-#define LS2F_PCIHI_BASE 0x40000000
-#define LS2F_PCIHI_SIZE 0x40000000
+#define LS2F_PCIHI_BASE 0x40000000UL
+#define LS2F_PCIHI_SIZE 0x40000000UL
#define LS2F_PCIHI_TOP (LS2F_PCIHI_BASE+LS2F_PCIHI_SIZE-1)
-#define BONITO_PCIIO_BASE 0x1fd00000
-#define BONITO_PCIIO_LEGACY 0x00004000
-#define BONITO_PCIIO_SIZE 0x00100000
+#define BONITO_PCIIO_BASE 0x1fd00000UL
+#define BONITO_PCIIO_LEGACY 0x00004000UL
+#define BONITO_PCIIO_SIZE 0x00100000UL
#define BONITO_PCIIO_TOP (BONITO_PCIIO_BASE+BONITO_PCIIO_SIZE-1)
-#define BONITO_PCICFG_BASE 0x1fe80000
-#define BONITO_PCICFG_SIZE 0x00080000
+#define BONITO_PCICFG_BASE 0x1fe80000UL
+#define BONITO_PCICFG_SIZE 0x00080000UL
#define BONITO_PCICFG_TOP (BONITO_PCICFG_BASE+BONITO_PCICFG_SIZE-1)
/* Bonito Register Bases */
@@ -149,8 +149,9 @@
#define BONITO_PCIMAP_PCIMAP_LO1_SHIFT 6
#define BONITO_PCIMAP_PCIMAP_LO2 0x0003f000
#define BONITO_PCIMAP_PCIMAP_LO2_SHIFT 12
+#define BONITO_PCIMAP_PCIMAP_2 0x00040000 /* real bonito only */
#define BONITO_PCIMAP_WIN(WIN,ADDR) ((((ADDR)>>26) & BONITO_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
-#define BONITO_PCIMAP_WINSIZE (1<<26)
+#define BONITO_PCIMAP_WINSIZE (1UL<<26)
#define BONITO_PCIMAP_WINOFFSET(ADDR) ((ADDR) & (BONITO_PCIMAP_WINSIZE - 1))
#define BONITO_PCIMAP_WINBASE(ADDR) ((ADDR) << 26)
diff --git a/sys/arch/loongson/dev/smfb.c b/sys/arch/loongson/dev/smfb.c
index 47496d92747..aeec1208a72 100644
--- a/sys/arch/loongson/dev/smfb.c
+++ b/sys/arch/loongson/dev/smfb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smfb.c,v 1.6 2010/02/26 14:53:11 miod Exp $ */
+/* $OpenBSD: smfb.c,v 1.7 2010/02/28 21:35:41 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -543,13 +543,15 @@ smfb_wait(struct smfb *fb)
* Early console code
*/
-int smfb_cnattach(bus_space_tag_t, pcitag_t, pcireg_t);
+int smfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
int
-smfb_cnattach(bus_space_tag_t memt, pcitag_t tag, pcireg_t id)
+smfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pcitag_t tag,
+ pcireg_t id)
{
long defattr;
struct rasops_info *ri;
+ bus_space_handle_t fbh, regh;
vaddr_t fbbase, regbase;
pcireg_t bar;
int rc, is5xx;
@@ -571,13 +573,21 @@ smfb_cnattach(bus_space_tag_t memt, pcitag_t tag, pcireg_t id)
bar = pci_conf_read_early(tag, PCI_MAPREG_START);
if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
return EINVAL;
- fbbase = memt->bus_base + PCI_MAPREG_MEM_ADDR(bar);
+ rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
+ BUS_SPACE_MAP_LINEAR, &fbh);
+ if (rc != 0)
+ return rc;
+ fbbase = (vaddr_t)bus_space_vaddr(memt, fbh);
if (smfbcn.is5xx) {
bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04);
if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
return EINVAL;
- regbase = memt->bus_base + PCI_MAPREG_MEM_ADDR(bar);
+ rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
+ BUS_SPACE_MAP_LINEAR, &regh);
+ if (rc != 0)
+ return rc;
+ regbase = (vaddr_t)bus_space_vaddr(memt, regh);
} else {
regbase = 0;
}
diff --git a/sys/arch/loongson/loongson/wscons_machdep.c b/sys/arch/loongson/loongson/wscons_machdep.c
index a8187830b92..61a89057986 100644
--- a/sys/arch/loongson/loongson/wscons_machdep.c
+++ b/sys/arch/loongson/loongson/wscons_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_machdep.c,v 1.4 2010/02/12 08:14:02 miod Exp $ */
+/* $OpenBSD: wscons_machdep.c,v 1.5 2010/02/28 21:35:43 miod Exp $ */
/*
* Copyright (c) 2010 Miodrag Vallat.
@@ -64,7 +64,7 @@
#include <dev/wscons/wsdisplayvar.h>
#endif
#include "smfb.h"
-extern int smfb_cnattach(bus_space_tag_t, pcitag_t, pcireg_t);
+extern int smfb_cnattach(bus_space_tag_t, bus_space_tag_t, pcitag_t, pcireg_t);
#include "pckbc.h"
#if NPCKBC > 0
@@ -139,7 +139,8 @@ static int initted;
rc = ENXIO;
#if NSMFB > 0
if (rc != 0)
- rc = smfb_cnattach(&bonito_pci_mem_space_tag, tag, id);
+ rc = smfb_cnattach(&bonito_pci_mem_space_tag,
+ &bonito_pci_io_space_tag, tag, id);
#endif
if (rc == 0)
goto setup_kbd;