diff options
author | Thomas Huth <thuth@linux.vnet.ibm.com> | 2011-11-17 10:57:37 +0100 |
---|---|---|
committer | Thomas Huth <thuth@linux.vnet.ibm.com> | 2011-11-24 10:21:56 +0100 |
commit | 2d3eabca483fcab04c00efa456aa77f48f6efc0e (patch) | |
tree | dc60cb046321e213fe8bce42c7487c06496863c8 | |
parent | 0be6560d6589781867a11d3a3847842cf1d9f935 (diff) | |
download | SLOF-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/Makefile | 1 | ||||
-rw-r--r-- | board-qemu/slof/pci-device-dma.fs | 95 | ||||
-rw-r--r-- | board-qemu/slof/pci-phb.fs | 124 | ||||
-rw-r--r-- | slof/fs/instance.fs | 19 | ||||
-rw-r--r-- | slof/fs/pci-device.fs | 12 |
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 ; |