aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2011-11-17 10:57:37 +0100
committerThomas Huth <thuth@linux.vnet.ibm.com>2011-11-24 10:21:56 +0100
commit2d3eabca483fcab04c00efa456aa77f48f6efc0e (patch)
treedc60cb046321e213fe8bce42c7487c06496863c8
parent0be6560d6589781867a11d3a3847842cf1d9f935 (diff)
downloadSLOF-2d3eabca483fcab04c00efa456aa77f48f6efc0e.zip
SLOF-2d3eabca483fcab04c00efa456aa77f48f6efc0e.tar.gz
SLOF-2d3eabca483fcab04c00efa456aa77f48f6efc0e.tar.bz2
Provide PCI memory mapping and dma memory handling in PHB node on board-qemu
According to the PCI Bus Binding to IEEE 1275, the dma-alloc, dma-free, dma-map-in, dma-map-out and dma-sync functions have to be provided by the PCI bus node, not by the PCI device node, so I moved these functions to the PHB node now. Since the "ibm,dma-window" property is still located in the device node instead, I had to add a little hack to the $call-parent method to remember the calling child, so that the parent node (the PHB node) can access that property of the calling child. Also added map-in and map-out functions now according the the PCI Bus Binding. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
-rw-r--r--board-qemu/slof/Makefile1
-rw-r--r--board-qemu/slof/pci-device-dma.fs95
-rw-r--r--board-qemu/slof/pci-phb.fs124
-rw-r--r--slof/fs/instance.fs19
-rw-r--r--slof/fs/pci-device.fs12
5 files changed, 144 insertions, 107 deletions
diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile
index 75a19a6..8c66cec 100644
--- a/board-qemu/slof/Makefile
+++ b/board-qemu/slof/Makefile
@@ -81,7 +81,6 @@ OF_FFS_FILES = \
$(SLOFCMNDIR)/fs/xmodem.fs \
$(SLOFBRDDIR)/default-font.bin \
$(SLOFBRDDIR)/pci-phb.fs \
- $(SLOFBRDDIR)/pci-device-dma.fs \
$(SLOFBRDDIR)/rtas.fs \
$(FCODE_FFS_FILES)
diff --git a/board-qemu/slof/pci-device-dma.fs b/board-qemu/slof/pci-device-dma.fs
deleted file mode 100644
index 3b35dda..0000000
--- a/board-qemu/slof/pci-device-dma.fs
+++ /dev/null
@@ -1,95 +0,0 @@
-\ *****************************************************************************
-\ * Copyright (c) 2011 IBM Corporation
-\ * All rights reserved.
-\ * This program and the accompanying materials
-\ * are made available under the terms of the BSD License
-\ * which accompanies this distribution, and is available at
-\ * http://www.opensource.org/licenses/bsd-license.php
-\ *
-\ * Contributors:
-\ * IBM Corporation - initial implementation
-\ ****************************************************************************/
-\ * Open Firmware 1275 DMA transfer mapping functions
-\ *****************************************************************************
-
-0 VALUE dma-debug?
-
-0 VALUE dma-window-liobn \ Logical I/O bus number
-0 VALUE dma-window-base \ Start address of window
-0 VALUE dma-window-size \ Size of the window
-
-
-\ Read DMA window base and size from ibm,dma-window property
-: update-dma-window-vars ( -- )
- s" ibm,dma-window" get-node get-property 0= IF
- decode-int TO dma-window-liobn
- decode-64 TO dma-window-base
- decode-64 TO dma-window-size
- 2drop
- THEN
-;
-update-dma-window-vars
-
-
-: dma-alloc ( size -- virt )
- dma-debug? IF cr ." dma-alloc called: " .s cr THEN
- fff + fff not and \ Align size to next 4k boundary
- alloc-mem
- \ alloc-mem always returns aligned memory - double check just to be sure
- dup fff and IF
- ." Warning: dma-alloc got unaligned memory!" cr
- THEN
-;
-
-: dma-free ( virt size -- )
- dma-debug? IF cr ." dma-free called: " .s cr THEN
- fff + fff not and \ Align size to next 4k boundary
- free-mem
-;
-
-
-\ We assume that firmware never maps more than the whole dma-window-size
-\ so we cheat by calculating the remainder of addr/windowsize instead
-\ of taking care to maintain a list of assigned device addresses
-: dma-virt2dev ( virt -- devaddr )
- dma-window-size mod dma-window-base +
-;
-
-: dma-map-in ( virt size cachable? -- devaddr )
- dma-debug? IF cr ." dma-map-in called: " .s cr THEN
- drop ( virt size )
- bounds dup >r ( v+s virt R: virt )
- swap fff + fff not and \ Align end to next 4k boundary
- swap fff not and ( v+s' virt' R: virt )
- ?DO
- \ ." mapping " i . cr
- dma-window-liobn \ liobn
- i dma-virt2dev \ ioba
- i 3 OR \ Make a read- & writeable TCE
- ( liobn ioba tce R: virt )
- hv-put-tce ABORT" H_PUT_TCE failed"
- 1000 +LOOP
- r> dma-virt2dev
-;
-
-: dma-map-out ( virt devaddr size -- )
- dma-debug? IF cr ." dma-map-out called: " .s cr THEN
- nip ( virt size )
- bounds ( v+s virt )
- swap fff + fff not and \ Align end to next 4k boundary
- swap fff not and ( v+s' virt' )
- ?DO
- \ ." unmapping " i . cr
- dma-window-liobn \ liobn
- i dma-virt2dev \ ioba
- i \ Lowest bits not set => invalid TCE
- ( liobn ioba tce )
- hv-put-tce ABORT" H_PUT_TCE failed"
- 1000 +LOOP
-;
-
-: dma-sync ( virt devaddr size -- )
- dma-debug? IF cr ." dma-sync called: " .s cr THEN
- \ TODO: Call flush-cache or sync here?
- 3drop
-;
diff --git a/board-qemu/slof/pci-phb.fs b/board-qemu/slof/pci-phb.fs
index cb93c87..08eaba1 100644
--- a/board-qemu/slof/pci-phb.fs
+++ b/board-qemu/slof/pci-phb.fs
@@ -12,6 +12,9 @@
\ PAPR PCI host bridge.
+0 VALUE phb-debug?
+
+
." Populating " pwd cr
\ needed to find the right path in the device tree
@@ -53,6 +56,126 @@ setup-puid
: config-w! puid >r my-puid TO puid rtas-config-w! r> TO puid ;
: config-l! puid >r my-puid TO puid rtas-config-l! r> TO puid ;
+
+: map-in ( phys.lo phys.mid phys.hi size -- virt )
+ phb-debug? IF cr ." map-in called: " .s cr THEN
+ \ Ignore the size, phys.lo and phys.mid, get BAR from config space
+ drop nip nip ( phys.hi )
+ \ Sanity check whether config address is in expected range:
+ dup FF AND 10 28 WITHIN NOT IF
+ cr ." phys.hi = " . cr
+ ABORT" map-in with illegal config space address"
+ THEN
+ 00FFFFFF AND \ Need only bus-dev-fn+register bits
+ dup config-l@ ( phys.hi' bar.lo )
+ dup 7 AND 4 = IF \ Is it a 64-bit BAR?
+ swap 4 + config-l@ lxjoin \ Add upper part of 64-bit BAR
+ ELSE
+ nip
+ THEN
+ F NOT AND \ Clear indicator bits
+ translate-my-address
+ phb-debug? IF ." map-in done: " .s cr THEN
+;
+
+: map-out ( virt size -- )
+ phb-debug? IF ." map-out called: " .s cr THEN
+ 2drop
+;
+
+
+: dma-alloc ( size -- virt )
+ phb-debug? IF cr ." dma-alloc called: " .s cr THEN
+ fff + fff not and \ Align size to next 4k boundary
+ alloc-mem
+ \ alloc-mem always returns aligned memory - double check just to be sure
+ dup fff and IF
+ ." Warning: dma-alloc got unaligned memory!" cr
+ THEN
+;
+
+: dma-free ( virt size -- )
+ phb-debug? IF cr ." dma-free called: " .s cr THEN
+ fff + fff not and \ Align size to next 4k boundary
+ free-mem
+;
+
+
+\ Helper variables for dma-map-in and dma-map-out
+0 VALUE dma-window-liobn \ Logical I/O bus number
+0 VALUE dma-window-base \ Start address of window
+0 VALUE dma-window-size \ Size of the window
+
+\ Read helper variables (LIOBN, DMA window base and size) from the
+\ "ibm,dma-window" property. This property is unfortunately currently located
+\ in the PCI device node instead of the bus node, so we've got to use the
+\ "calling-child" variable here to get to the node that initiated the call.
+: (init-dma-window-vars) ( -- )
+ s" ibm,dma-window" calling-child ihandle>phandle
+ get-property ABORT" no dma-window property available"
+ decode-int TO dma-window-liobn
+ decode-64 TO dma-window-base
+ decode-64 TO dma-window-size
+ 2drop
+;
+
+: (clear-dma-window-vars) ( -- )
+ 0 TO dma-window-liobn
+ 0 TO dma-window-base
+ 0 TO dma-window-size
+;
+
+\ We assume that firmware never maps more than the whole dma-window-size
+\ so we cheat by calculating the remainder of addr/windowsize instead
+\ of taking care to maintain a list of assigned device addresses
+: dma-virt2dev ( virt -- devaddr )
+ dma-window-size mod dma-window-base +
+;
+
+: dma-map-in ( virt size cachable? -- devaddr )
+ phb-debug? IF cr ." dma-map-in called: " .s cr THEN
+ (init-dma-window-vars)
+ drop ( virt size )
+ bounds dup >r ( v+s virt R: virt )
+ swap fff + fff not and \ Align end to next 4k boundary
+ swap fff not and ( v+s' virt' R: virt )
+ ?DO
+ \ ." mapping " i . cr
+ dma-window-liobn \ liobn
+ i dma-virt2dev \ ioba
+ i 3 OR \ Make a read- & writeable TCE
+ ( liobn ioba tce R: virt )
+ hv-put-tce ABORT" H_PUT_TCE failed"
+ 1000 +LOOP
+ r> dma-virt2dev
+ (clear-dma-window-vars)
+;
+
+: dma-map-out ( virt devaddr size -- )
+ phb-debug? IF cr ." dma-map-out called: " .s cr THEN
+ (init-dma-window-vars)
+ nip ( virt size )
+ bounds ( v+s virt )
+ swap fff + fff not and \ Align end to next 4k boundary
+ swap fff not and ( v+s' virt' )
+ ?DO
+ \ ." unmapping " i . cr
+ dma-window-liobn \ liobn
+ i dma-virt2dev \ ioba
+ i \ Lowest bits not set => invalid TCE
+ ( liobn ioba tce )
+ hv-put-tce ABORT" H_PUT_TCE failed"
+ 1000 +LOOP
+ (clear-dma-window-vars)
+;
+
+: dma-sync ( virt devaddr size -- )
+ phb-debug? IF cr ." dma-sync called: " .s cr THEN
+ \ TODO: Call flush-cache or sync here?
+ 3drop
+;
+
+
: open true ;
: close ;
@@ -71,7 +194,6 @@ setup-puid
dup set-node
\ Include the PCI device functions:
s" pci-device.fs" included
- s" pci-device-dma.fs" included
peer ( next-child-phandle )
REPEAT
drop
diff --git a/slof/fs/instance.fs b/slof/fs/instance.fs
index 38e1414..4ba42e5 100644
--- a/slof/fs/instance.fs
+++ b/slof/fs/instance.fs
@@ -139,6 +139,19 @@ CONSTANT <instancevariable>
\ cr ." call for " 3dup -rot type ." on node " .
find-method IF execute ELSE -1 throw THEN
;
-: $call-my-method ( str len -- ) my-self ihandle>phandle $call-static ;
-: $call-method push-my-self $call-my-method pop-my-self ;
-: $call-parent my-parent $call-method ;
+
+: $call-my-method ( str len -- )
+ my-self ihandle>phandle $call-static
+;
+
+: $call-method ( str len ihandle -- )
+ push-my-self $call-my-method pop-my-self
+;
+
+0 VALUE calling-child
+
+: $call-parent
+ my-self TO calling-child
+ my-parent $call-method
+ 0 TO calling-child
+;
diff --git a/slof/fs/pci-device.fs b/slof/fs/pci-device.fs
index 191135c..3e90464 100644
--- a/slof/fs/pci-device.fs
+++ b/slof/fs/pci-device.fs
@@ -10,10 +10,8 @@
\ * IBM Corporation - initial implementation
\ ****************************************************************************/
-get-node parent CONSTANT node-parent
-
\ get the PUID from the node above
-s" my-puid" node-parent $call-static CONSTANT my-puid
+s" my-puid" get-node parent $call-static CONSTANT my-puid
\ define the config reads
: config-b@ puid >r my-puid TO puid my-space + rtas-config-b@ r> TO puid ;
@@ -56,19 +54,19 @@ s" my-puid" node-parent $call-static CONSTANT my-puid
\ DMA memory allocation functions
: dma-alloc ( size -- virt )
- s" dma-alloc" node-parent $call-static
+ s" dma-alloc" $call-parent
;
: dma-free ( virt size -- )
- s" dma-free" node-parent $call-static
+ s" dma-free" $call-parent
;
: dma-map-in ( virt size cacheable? -- devaddr )
- s" dma-map-in" node-parent $call-static
+ s" dma-map-in" $call-parent
;
: dma-map-out ( virt devaddr size -- )
- s" dma-map-out" node-parent $call-static
+ s" dma-map-out" $call-parent
;