LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PPC BOOT] Find device-tree source file in default directory.
From: David Woodhouse @ 2007-12-03  2:49 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1196650083.13978.113.camel@pmac.infradead.org>

If a .dts file is given to the bootwrapper script without a full path
name, look in a sensible place for it.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -116,6 +118,9 @@ while [ "$#" -gt 0 ]; do
 done
 
 if [ -n "$dts" ]; then
+    if [ ! -r "$dts" -a -r "$object/dts/$dts" ]; then
+	dts="$object/dts/$dts"
+    fi
     if [ -z "$dtb" ]; then
 	dtb="$platform.dtb"
     fi

-- 
dwmw2

^ permalink raw reply

* [PPC BOOT] Allow for bootwrapper utilities being in different directory to objects
From: David Woodhouse @ 2007-12-03  2:52 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1196650164.13978.115.camel@pmac.infradead.org>

It's possible that the executables which are built as helpers for the
bootwrapper stuff might end up in a different place to the intermediate
object files. Handle that.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 31147a0..ef86a70 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -45,6 +45,7 @@ CROSS=
 
 # directory for object and other files used by this script
 object=arch/powerpc/boot
+objbin=$object
 
 # directory for working files
 tmpdir=.
@@ -95,6 +96,7 @@ while [ "$#" -gt 0 ]; do
 	shift
 	[ "$#" -gt 0 ] || usage
 	object="$1"
+	objbin="$1"
 	;;
     -W)
 	shift
@@ -246,11 +248,11 @@ fi
 # post-processing needed for some platforms
 case "$platform" in
 pseries|chrp)
-    $object/addnote "$ofile"
+    $objbin/addnote "$ofile"
     ;;
 coff)
     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
-    $object/hack-coff "$ofile"
+    $objbin/hack-coff "$ofile"
     ;;
 cuboot*)
     gzip -f -9 "$ofile"
@@ -259,7 +261,7 @@ cuboot*)
     ;;
 treeboot*)
     mv "$ofile" "$ofile.elf"
-    $object/mktree "$ofile.elf" "$ofile" "$base" "$entry"
+    $objbin/mktree "$ofile.elf" "$ofile" "$base" "$entry"
     if [ -z "$cacheit" ]; then
 	rm -f "$ofile.elf"
     fi

-- 
dwmw2

^ permalink raw reply related

* [PPC BOOT] 'make bootwrapper_install'
From: David Woodhouse @ 2007-12-03  2:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1196650325.13978.119.camel@pmac.infradead.org>

This adds a 'bootwrapper_install' make target for the powerpc
architecture, which installs the wrapper script, intermediate object
files and device-tree sources for later use.

This will then allow bootable zImages to be created other than in the
context of a kernel build.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 18e3271..acf3641 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -243,3 +243,51 @@ clean-kernel := vmlinux.strip vmlinux.bin
 clean-kernel += $(addsuffix .gz,$(clean-kernel))
 # If not absolute clean-files are relative to $(obj).
 clean-files += $(addprefix $(objtree)/, $(clean-kernel))
+
+WRAPPER_OBJDIR := /usr/lib/kernel-wrapper
+WRAPPER_DTSDIR := /usr/lib/kernel-wrapper/dts
+WRAPPER_BINDIR := /usr/sbin
+INSTALL := install
+
+extra-installed		:= $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y))
+hostprogs-installed	:= $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y))
+wrapper-installed	:= $(DESTDIR)$(WRAPPER_BINDIR)/wrapper
+dts-installed		:= $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts))
+
+all-installed		:= $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed)
+
+quiet_cmd_mkdir           = MKDIR   $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
+      cmd_mkdir           = mkdir -p $@
+
+quiet_cmd_install	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_OBJDIR)/%,%,$@)
+      cmd_install	  = $(INSTALL)  -m0644 $(patsubst $(DESTDIR)$(WRAPPER_OBJDIR)/%,$(obj)/%,$@) $@ 
+
+quiet_cmd_install_dts	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_DTSDIR)/%,dts/%,$@)
+      cmd_install_dts	  = $(INSTALL)  -m0644 $(patsubst $(DESTDIR)$(WRAPPER_DTSDIR)/%,$(srctree)/$(obj)/dts/%,$@) $@ 
+
+quiet_cmd_install_exe	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,%,$@)
+      cmd_install_exe	  = $(INSTALL)  -m0755 $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,$(obj)/%,$@) $@ 
+
+quiet_cmd_install_wrapper = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,%,$@)
+      cmd_install_wrapper = $(INSTALL)  -m0755 $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,$(srctree)/$(obj)/%,$@) $@ ;\
+				sed -i $@ -e 's%^object=.*%object=$(WRAPPER_OBJDIR)%' \
+					  -e 's%^objbin=.*%objbin=$(WRAPPER_BINDIR)%' \
+
+
+$(DESTDIR)$(WRAPPER_OBJDIR) $(DESTDIR)$(WRAPPER_DTSDIR) $(DESTDIR)$(WRAPPER_BINDIR):
+	$(call cmd,mkdir)
+
+$(extra-installed)	: $(DESTDIR)$(WRAPPER_OBJDIR)/% : $(obj)/% | $(DESTDIR)$(WRAPPER_OBJDIR)
+	$(call cmd,install)
+
+$(hostprogs-installed)  : $(DESTDIR)$(WRAPPER_BINDIR)/% : $(obj)/% | $(DESTDIR)$(WRAPPER_BINDIR)
+	$(call cmd,install_exe)
+
+$(dts-installed)	: $(DESTDIR)$(WRAPPER_DTSDIR)/% : $(srctree)/$(obj)/dts/% | $(DESTDIR)$(WRAPPER_DTSDIR)
+	$(call cmd,install_dts)
+
+$(wrapper-installed): $(DESTDIR)$(WRAPPER_BINDIR) $(srctree)/$(obj)/wrapper | $(DESTDIR)$(WRAPPER_BINDIR)
+	$(call cmd,install_wrapper)
+
+$(obj)/bootwrapper_install: $(all-installed)
+
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index bd87626..f70df9b 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -167,6 +167,9 @@ boot := arch/$(ARCH)/boot
 $(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
+bootwrapper_install:
+	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+
 define archhelp
   @echo '* zImage          - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
   @echo '  install         - Install kernel using'

-- 
dwmw2

^ permalink raw reply related

* Re: [PATCH 0/24] powerpc: 4xx PCI, PCI-X and PCI-Express support among others
From: Benjamin Herrenschmidt @ 2007-12-03  3:24 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <20071130141756.3aa3d38b@zod.rchland.ibm.com>


On Fri, 2007-11-30 at 14:17 -0600, Josh Boyer wrote:
> > Some of these patches are _NOT_ yet candidate for merging
> > (mostly the board support ones), but you can review them and
> > Josh can put them in an experimental tree.
> 
> I've added these to the 2.6.25-candidates branch in my tree.  Fixed up
> the few conflicts manually.  I'll expect refreshes before merging
> anyway, but I'd like to get these out there for people to play with.

BTW. You were telling me the other day about a problem with the clock
code. 

It looks like the problem is a subtle difference between 440EP /440EPx
and 440SPe / 440GX. The former has the EBC clock derived from the PLB
clock while the later has it derived from OPB... yuck.

I'm fixing that.

Cheers,
Ben.

^ permalink raw reply

* Re: [PPC BOOT] Create otheros.bld next to specified output file, not in $object directory.
From: Geoff Levand @ 2007-12-03  3:33 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linuxppc-dev
In-Reply-To: <1196650083.13978.113.camel@pmac.infradead.org>

David Woodhouse wrote:
> The bootwrapper script currently generates an 'otheros.bld' file in
> addition to the file specified by the -o option, when asked to build a
> wrapper for PS3.
> 
> It should do that in the same directory as the output, not the directory
> where the wrapper objects are kept (which might potentially not be
> writable when the script runs).


Seems reasonable for installs from read-only media.

 
> Arguably, the 'otheros.bld' ought to be created with the filename
> specified as the -o argument. But that's a more intrusive change.


Yes, I think it makes sense.  ps3-flash-util can handle any file
name, so there is no real reason to have it named otheros.bld.
 

> Signed-off-by: David Woodhouse <dwmw2@infradead.org>


Acked-by: Geoff Levand <geoffrey.levand@am.sony.com>

^ permalink raw reply

* Re: [PATCH] Add MPC837xEMDS PCIE RC mode support
From: Li Li @ 2007-12-03  3:43 UTC (permalink / raw)
  To: Gala Kumar, Wood Scott; +Cc: linuxppc-dev
In-Reply-To: <6FF36777-D91C-4B80-968B-CAEF11BC98ED@freescale.com>

On Fri, 2007-11-30 at 22:57 +0800, Gala Kumar wrote:
> 
> On Nov 30, 2007, at 3:37 AM, Li Li wrote:
> 
> > On Fri, 2007-11-30 at 17:05 +0800, Gala Kumar wrote: 
> >>>>> + 
> >>>>> +     pci2@e0009000 { 
> >>>> 
> >>>> I agree w/Olof.  This should be pcie@e0009000 
> >>>>> 
> >>>>> +             interrupt-map-mask = <f800 0 0 7>; 
> >>>>> +             msi-available-ranges = <43 4 51 52 56 57 58 59>; 
> >>>>> +             interrupt-map = < 
> >>>>> +                     0000 0 0 1 &ipic 1 8 
> >>>>> +                     0000 0 0 2 &ipic 1 8 
> >>>>> +                     0000 0 0 3 &ipic 1 8 
> >>>>> +                     0000 0 0 4 &ipic 1 8 
> >>>>> +             >; 
> >>>>> +             interrupt-parent = < &ipic >; 
> >>>>> +             interrupts = <1 8>; 
> >>>>> +             bus-range = <0 0>; 
> >>>>> +             ranges = <02000000 0 A8000000 A8000000 0 10000000 
> >>>>> +                       01000000 0 00000000 B8000000 0
> 00800000>; 
> >>>>> +             clock-frequency = <0>; 
> >>>>> +             #interrupt-cells = <1>; 
> >>>>> +             #size-cells = <2>; 
> >>>>> +             #address-cells = <3>; 
> >>>>> +             reg = <e0009000 00001000 
> >>>>> +                    a0000000 08000000>; 
> >>>> 
> >>>> Shouldn't the reg size for the cfg space be 256M? 
> >>> 
> >>> 256M is a little too big for kernel. 
> >> 
> >> what do you mean too big?  Aren't you losing access to some 
> >> bus/dev/fn 
> >> than? 
> > 
> > If do it standard, a 256M config space, at least 256M mem space
> and  
> > 16M 
> > io space are needed for each PCIE controller. 
> > To allocate PCIE window, the window size only can be 512M or 1G. 
> > If we choose 1G space, two PCIE controller needs 2G space. 
> > We do not have 2G free physical space now. Usually, we use upper
> 128M 
> > configure space. So, we have to cut down the config space.
> 
> We'll cutting config space is problematic in that its a bug since
> you  
> might not be able to talk to a given device.
> 
> Is it possible to make the outbound window for cfg space 4k and
> change  
> the region of config space its looking at?
> 

I think that is possible but it means we have to reconfigure the PCIE
controller`s outbound window at every time we want do PCI config space
access in kernel. By now, all the PCIE controller is initialized on
u-boot which like PCI controller`s case.So it is a little not compatible
with the current kernel and u-boot assignment.

> >>>>> diff --git a/arch/powerpc/platforms/83xx/Kconfig
> b/arch/powerpc/ 
> >>>>> platforms/83xx/Kconfig 
> >>>>> index 0c61e7a..00154c5 100644 
> >>>>> --- a/arch/powerpc/platforms/83xx/Kconfig 
> >>>>> +++ b/arch/powerpc/platforms/83xx/Kconfig 
> >>>>> @@ -87,3 +87,10 @@ config PPC_MPC837x 
> >>>>>     select PPC_INDIRECT_PCI 
> >>>>>     select FSL_SERDES 
> >>>>>     default y if MPC837x_MDS 
> >>>>> + 
> >>>>> +config PPC_MPC83XX_PCIE 
> >>>>> +     bool "MPC837X PCI Express support" 
> >>>>> +     depends on PCIEPORTBUS && PPC_MPC837x 
> >>>>> +     default n 
> >>>>> +     help 
> >>>>> +       Enables MPC837x PCI express RC mode 
> >>>> 
> >>>> This should be a hidden config that is just selected by 
> >> PPC_MPC837x 
> >>>> instead of a choice.  Also drop the depends on. 
> >>>> 
> >>> 
> >>> In the dts file, the PCIE is default enabled. So, we should
> provide 
> >>> another way to disable the PCIE. 
> >>> Modify and recompile the dts is a little unkind to user. 
> >> 
> >> Why do you something beyond CONFIG_PCI.  if you don't want PCIe
> but 
> >> do 
> >> want PCI the extra code for PCIe isn't going to kill you. 
> >> 
> > 
> > Here is a little complex. The MPC837xE board needs a carrier board
> to 
> > extend PCIE slot. If user does not populate carrier board onto  
> > MPC837xE 
> > board and do PCIE scan, the system will halt. 
> > I just want to provide a easy way to disable the PCIe other than  
> > modify 
> > and recompile the dts.
> 
> So I have to recompile the kernel for this case, that seems even
> more  
> painful to the user.  Can we not detect if this board isn't there
> and  
> not hang?
> 

Yes. you are right. But I think we lack of a mean to tell the user the
exact mean of each device node and how to edit it.
The linux menuconfig is more directed.

As Scott said and AMHO, the dts describes what we have not what we want.
If dts describes what we have, we must provide many dts files to provide
various cpu feature combinations.

> >>>>> diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h 
> >> b/arch/powerpc/ 
> >>>>> platforms/83xx/mpc83xx.h 
> >>>>> index b778cb4..2078da7 100644 
> >>>>> --- a/arch/powerpc/platforms/83xx/mpc83xx.h 
> >>>>> +++ b/arch/powerpc/platforms/83xx/mpc83xx.h 
> >>>>> @@ -43,12 +43,18 @@ 
> >>>>> #define PORTSCX_PTS_UTMI           0x00000000 
> >>>>> #define PORTSCX_PTS_ULPI           0x80000000 
> >>>>> 
> >>>>> +/* PCIE Registers */ 
> >>>>> +#define PEX_LTSSM_STAT               0x404 
> >>>>> +#define PEX_LTSSM_STAT_L0    0x16 
> >>>>> +#define PEX_GCLK_RATIO               0x440 
> >>>>> + 
> >>>> 
> >>>> just move these into the .c file. 
> > 
> > ok. 
> > 
> >>>> 
> >>>>> 
> >>>>> /* 
> >>>>> * Declaration for the various functions exported by the 
> >>>>> * mpc83xx_* files. Mostly for use by mpc83xx_setup 
> >>>>> */ 
> >>>>> - 
> >>>>> -extern int mpc83xx_add_bridge(struct device_node *dev); 
> >>>>> +#define PPC_83XX_PCI 0x1 
> >>>>> +#define PPC_83XX_PCIE        0x2 
> >>>>> +extern int mpc83xx_add_bridge(struct device_node *dev, int 
> >> flags); 
> >>>>> extern void mpc83xx_restart(char *cmd); 
> >>>>> extern long mpc83xx_time_init(void); 
> >>>>> extern int mpc834x_usb_cfg(void); 
> >>>>> diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/ 
> >>>>> platforms/83xx/pci.c 
> >>>>> index 80425d7..0b52b2e 100644 
> >>>>> --- a/arch/powerpc/platforms/83xx/pci.c 
> >>>>> +++ b/arch/powerpc/platforms/83xx/pci.c 
> >>>>> @@ -25,6 +25,8 @@ 
> >>>>> #include <asm/prom.h> 
> >>>>> #include <sysdev/fsl_soc.h> 
> >>>>> 
> >>>>> +#include "mpc83xx.h" 
> >>>>> + 
> >>>>> #undef DEBUG 
> >>>>> 
> >>>>> #ifdef DEBUG 
> >>>>> @@ -33,13 +35,157 @@ 
> >>>>> #define DBG(x...) 
> >>>>> #endif 
> >>>>> 
> >>>>> -int __init mpc83xx_add_bridge(struct device_node *dev) 
> >>>>> +#if defined(CONFIG_PPC_MPC83XX_PCIE) 
> >>>>> + 
> >>>>> +/* PCIE config space Read/Write routines */ 
> >>>> 
> >>>> should really be called something like mpc83xx_pciex_read_config 
> >>>>> 
> >>>>> +static int direct_read_config_pcie(struct pci_bus *bus, 
> >>>>> +                     uint devfn, int offset, int len, u32
> *val) 
> >>>>> +{ 
> >>>>> +     struct pci_controller *hose = bus->sysdata; 
> >>>>> +     void __iomem *cfg_addr; 
> >>>>> +     u32 bus_no; 
> >>>>> + 
> >>>>> +     if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK) 
> >>>>> +             return PCIBIOS_DEVICE_NOT_FOUND; 
> >>>>> + 
> >>>>> +     if (ppc_md.pci_exclude_device) 
> >>>>> +             if (ppc_md.pci_exclude_device(hose, bus->number, 
> >>>> devfn)) 
> >>>>> +                     return PCIBIOS_DEVICE_NOT_FOUND; 
> >>>>> + 
> >>>>> +     switch (len) { 
> >>>>> +     case 2: 
> >>>>> +             if (offset & 1) 
> >>>>> +                     return -EINVAL; 
> >>>>> +             break; 
> >>>>> +     case 4: 
> >>>>> +     if (offset & 3) 
> >>>>> +             return -EINVAL; 
> >>>>> +             break; 
> >>>>> +     } 
> >>>> 
> >>>> fix formatting. 
> >>>> 
> >>>>> 
> >>>>> + 
> >>>>> +     pr_debug("_read_cfg_pcie: bus=%d devfn=%x off=%x len=%x
> \n", 
> >>>>> +             bus->number, devfn, offset, len); 
> >>>>> + 
> >>>>> +     if (bus->number == hose->first_busno) { 
> >>>>> +             if (devfn & 0xf8) 
> >>>>> +                     return PCIBIOS_DEVICE_NOT_FOUND; 
> >>>> 
> >>>> what is the 0xf8 all about? 
> >>>> 
> >>> 
> >>> The pcie only have one link, so the dev number only can be 0, as 
> >> well 
> >>> the function number can be 0 ~ 7. 
> >> 
> >> I don't follow what the number of links has to do with dev number. 
> > 
> > The PCIE only have one link that mean one PCIE bus only can have
> one 
> > device populate on it. The dev number of this device must be 0. If
> the 
> > device number is not 0, we consider it is a error.
> 
> we should add a comment about that.
> 

yes

> >>>>> +     addr = mbase + (cfg_addr & ~PAGE_MASK); 
> >>>>> +     hose->cfg_addr = addr; 
> >>>>> +     hose->ops = &direct_pcie_ops; 
> >>>> 
> >>>> what's the point of this function, why not just fold it into 
> >>>> mpc83xx_setup_pcie 
> >>>> 
> >>>>> 
> >>>>> +} 
> >>>>> + 
> >>>>> +static void __init mpc83xx_setup_pcie(struct pci_controller 
> >> *hose, 
> >>>>> +                     struct resource *reg, struct resource 
> >>>> *cfg_space) 
> >>>>> +{ 
> >>>>> +     void __iomem *hose_cfg_base; 
> >>>>> +     u32 val; 
> >>>>> + 
> >>>>> +     hose_cfg_base = ioremap(reg->start, reg->end - reg->start
> + 
> >>>> 1); 
> >>>>> + 
> >>>>> +     val = in_le32(hose_cfg_base + PEX_LTSSM_STAT); 
> >>>>> +     if (val < PEX_LTSSM_STAT_L0) 
> >>>>> +             hose->indirect_type |= 
> >>>> PPC_INDIRECT_TYPE_NO_PCIE_LINK; 
> >>>>> + 
> >>>>> +     setup_direct_pcie(hose, cfg_space->start, 
> >>>>> +                     cfg_space->end - cfg_space->start + 1); 
> >>>>> +} 
> >>>>> +#endif /* CONFIG_PPC_MPC83XX_PCIE */ 
> >>>>> + 
> >>>> 
> >>>> We should do the same think fsl_pci does for primary, its passed 
> >>>> into 
> >>>> _add_bridge.  Also, can we not do what fsl_pci does and use PCI 
> >>>> capabilities to determine we are a PCIe controller (and drop 
> >> passing 
> >>>> it in via flags). 
> >>>> 
> >>> 
> >>> The mpc837x PCIE controller is a little different from mpc85xx. 
> >>> It can not be access via PCI configure read/write. It only can be 
> >>> accessed via memory-mapped read/write from core. 
> >> 
> >> You don't have access to your own config space? 
> >> 
> > 
> > I can access it but can not via standard pci configure routine. 
> > So, we use different way to access PCI and PCIE. If we want access
> PCI 
> > capabilities, we must know it is PCI controller or PCIE controller 
> > first.
> 
> Duh, your right..  we should than expand flags to also have a  
> PPC_83XX_PCI_IS_PRIMARY and let that get set by the caller.
> 

yes

> - k
> 

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Michael Ellerman @ 2007-12-03  4:02 UTC (permalink / raw)
  To: Li Li; +Cc: linuxppc-dev, Kumar Gala
In-Reply-To: <1196394519.29683.8.camel@Guyver>

[-- Attachment #1: Type: text/plain, Size: 15736 bytes --]

Hi r64360,

A few comments below :)

On Fri, 2007-11-30 at 11:48 +0800, Li Li wrote:
> The IPIC MSI is introduced on MPC837x chip.
> Implements the IPIC MSI as two level interrupt controller.
> 
> Signed-off-by: Tony Li <tony.li@freescale.com>
> ---
>  arch/powerpc/boot/dts/mpc8377_mds.dts     |   14 ++
>  arch/powerpc/boot/dts/mpc8378_mds.dts     |   14 ++
>  arch/powerpc/boot/dts/mpc8379_mds.dts     |   14 ++
>  arch/powerpc/platforms/83xx/Kconfig       |    6 +
>  arch/powerpc/platforms/83xx/mpc837x_mds.c |   11 +
>  arch/powerpc/sysdev/Makefile              |    1 +
>  arch/powerpc/sysdev/ipic_msi.c            |  359 +++++++++++++++++++++++++++++
>  include/asm-powerpc/ipic_msi.h            |   54 +++++
>  8 files changed, 473 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/sysdev/ipic_msi.c
>  create mode 100644 include/asm-powerpc/ipic_msi.h
> 
> diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
> index 1f7819e..1068fe2 100644
> --- a/arch/powerpc/boot/dts/mpc8377_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
> @@ -210,6 +210,20 @@
>  			#interrupt-cells = <2>;
>  			reg = <700 100>;
>  		};
> +
> +		ipic-msi@7c0 {
> +			compatible = "fsl,ipic-msi";
> +			reg = <7c0 40>;
> +			interrupts = < 43 8
> +				       4  8
> +				       51 8
> +				       52 8
> +				       56 8
> +				       57 8
> +				       58 8
> +				       59 8 >;
> +			interrupt-parent = < &ipic >;
> +		};
>  	};
>  
>  	pci@e0008500 {
> diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
> index 1503ae3..f12658f 100644
> --- a/arch/powerpc/boot/dts/mpc8378_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
> @@ -192,6 +192,20 @@
>  			#interrupt-cells = <2>;
>  			reg = <700 100>;
>  		};
> +
> +		ipic-msi@7c0 {
> +			compatible = "fsl,ipic-msi";
> +			reg = <7c0 40>;
> +			interrupts = < 43 8
> +				       4  8
> +				       51 8
> +				       52 8
> +				       56 8
> +				       57 8
> +				       58 8
> +				       59 8 >;
> +			interrupt-parent = < &ipic >;
> +		};
>  	};
>  
>  	pci@e0008500 {
> diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts
> index cdb4426..9fe4bd2 100644
> --- a/arch/powerpc/boot/dts/mpc8379_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc8379_mds.dts
> @@ -236,6 +236,20 @@
>  			#interrupt-cells = <2>;
>  			reg = <700 100>;
>  		};
> +
> +		ipic-msi@7c0 {
> +			compatible = "fsl,ipic-msi";
> +			reg = <7c0 40>;
> +			interrupts = < 43 8
> +				       4  8
> +				       51 8
> +				       52 8
> +				       56 8
> +				       57 8
> +				       58 8
> +				       59 8 >;
> +			interrupt-parent = < &ipic >;
> +		};
>  	};
>  
>  	pci@e0008500 {
> diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
> index 00154c5..4c51f78 100644
> --- a/arch/powerpc/platforms/83xx/Kconfig
> +++ b/arch/powerpc/platforms/83xx/Kconfig
> @@ -88,6 +88,12 @@ config PPC_MPC837x
>  	select FSL_SERDES
>  	default y if MPC837x_MDS
>  
> +config IPIC_MSI
> +	bool
> +	depends on PCI_MSI
> +	default y if PPC_MPC837x
> +	default n
> +
>  config PPC_MPC83XX_PCIE
>  	bool "MPC837X PCI Express support"
>  	depends on PCIEPORTBUS && PPC_MPC837x
> diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> index 6048f1b..dbea34b 100644
> --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
> +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> @@ -17,6 +17,9 @@
>  
>  #include <asm/time.h>
>  #include <asm/ipic.h>
> +#if CONFIG_IPIC_MSI
> +#include <asm/ipic_msi.h>
> +#endif
>  #include <asm/udbg.h>
>  #include <asm/prom.h>

I'd rather you just include it unconditionally.

> @@ -84,6 +87,14 @@ static void __init mpc837x_mds_init_IRQ(void)
>  	 * in case the boot rom changed something on us.
>  	 */
>  	ipic_set_default_priority();
> +
> +#if CONFIG_IPIC_MSI
> +	np = of_find_compatible_node(NULL, NULL, "fsl,ipic-msi");
> +	if (!np)
> +		return;
> +
> +	ipic_msi_init(np, ipic_msi_cascade);
> +#endif

If you have a no-op version of ipic_msi_init() in your header file then
you can remove the #ifdef in the C code - which I think is nicer.

Why do you pass the handler into the init routine, rather than have the
init routine just set the handler. Then you could make the handler
static.

>  }
>  
>  /*
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
> index 99a77d7..5946b6a 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -25,6 +25,7 @@ ifeq ($(CONFIG_PPC_MERGE),y)
>  obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
>  obj-$(CONFIG_PPC_I8259)		+= i8259.o
>  obj-$(CONFIG_PPC_83xx)		+= ipic.o
> +obj-$(CONFIG_IPIC_MSI)		+= ipic_msi.o
>  obj-$(CONFIG_4xx)		+= uic.o
>  obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
>  endif
> diff --git a/arch/powerpc/sysdev/ipic_msi.c b/arch/powerpc/sysdev/ipic_msi.c
> new file mode 100644
> index 0000000..57758f7
> --- /dev/null
> +++ b/arch/powerpc/sysdev/ipic_msi.c
> @@ -0,0 +1,359 @@
> +/*
> + * arch/powerpc/sysdev/ipic_msi.c
> + *
> + * IPIC MSI routines implementations.
> + *
> + * Auther: Tony Li <tony.li@freescale.com>
> + *
> + * Copyright (c) 2007 Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +
> +
> +#include <linux/pci.h>
> +#include <linux/msi.h>
> +#include <linux/irq.h>
> +
> +#include <asm/ipic_msi.h>
> +
> +#define MSIR0	0x43
> +#define MSIR1	0x4
> +#define MSIR2	0x51
> +#define MSIR3	0x52
> +#define MSIR4	0x56
> +#define MSIR5	0x57
> +#define MSIR6	0x58
> +#define MSIR7	0x59
> +
> +
> +static struct ipic_msi *ipic_msi;
> +static DEFINE_SPINLOCK(ipic_msi_lock);
> +static DEFINE_SPINLOCK(ipic_msi_bitmap_lock);
> +
> +static inline u32 ipic_msi_read(volatile u32 __iomem *base, unsigned int reg)
> +{
> +	return in_be32(base + (reg >> 2));
> +}
> +
> +static inline void ipic_msi_write(volatile u32 __iomem *base,
> +					unsigned int reg, u32 value)
> +{
> +	out_be32(base + (reg >> 2), value);
> +}
> +
> +static struct ipic_msi * ipic_msi_from_irq(unsigned int virq)
> +{
> +	return ipic_msi;
> +}
> +
> +#define	ipic_msi_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)

What's wrong with virq_to_hw() ?


> +static void ipic_msi_unmask(unsigned int virq)
> +{
> +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> +	unsigned int src = ipic_msi_irq_to_hw(virq);
> +	unsigned long flags;
> +	u32 temp;
> +
> +	spin_lock_irqsave(&ipic_msi_lock, flags);
> +	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
> +	ipic_msi_write(msi->regs, IPIC_MSIMR,
> +		temp & ~(1 << (src / msi->int_per_msir)));
> +
> +	spin_unlock_irqrestore(&ipic_msi_lock, flags);
> +}
> +
> +static void ipic_msi_mask(unsigned int virq)
> +{
> +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> +	unsigned int src = ipic_msi_irq_to_hw(virq);
> +	unsigned long flags;
> +	u32 temp;
> +
> +	spin_lock_irqsave(&ipic_msi_lock, flags);
> +
> +	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
> +	ipic_msi_write(msi->regs, IPIC_MSIMR,
> +		temp | (1 << (src / msi->int_per_msir)));
> +
> +	spin_unlock_irqrestore(&ipic_msi_lock, flags);
> +}
> +/*
> + * We do not need this actually. The MSIR register has been read once
> + * in ipic_msi_get_irq. So, this MSI interrupt has been acked
> + */
> +static void ipic_msi_ack(unsigned int virq)
> +{
> +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> +	unsigned int src = ipic_msi_irq_to_hw(virq);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ipic_msi_lock, flags);
> +
> +	ipic_msi_read(msi->regs, IPIC_MSIR0 + (4 * (src / msi->int_per_msir)));
> +
> +	spin_unlock_irqrestore(&ipic_msi_lock,flags);
> +}
> +
> +static struct irq_chip ipic_msi_chip = {
> +	.typename = " IPIC MSI ",
> +	.unmask = ipic_msi_unmask,
> +	.mask = ipic_msi_mask,
> +	.ack = ipic_msi_ack,
> +};
> +
> +static int ipic_msi_host_map(struct irq_host *h, unsigned int virq,
> +				irq_hw_number_t hw)
> +{
> +	struct ipic_msi *msi = h->host_data;
> +	struct irq_chip *chip = msi->hc_irq;
> +
> +	set_irq_chip_data(virq, msi);
> +	get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
> +
> +	set_irq_chip_and_handler(virq, chip, handle_edge_irq);
> +	return 0;
> +}
> +
> +static struct irq_host_ops ipic_msi_host_ops = {
> +	.map = ipic_msi_host_map,
> +};
> +
> +irq_hw_number_t ipic_msi_alloc_hwirqs(struct ipic_msi *msi, int num)
> +{
> +	unsigned long flags;
> +	int offset, order = get_count_order(num);
> +
> +	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
> +
> +	offset = bitmap_find_free_region(msi->ipic_msi_bitmap,
> +			msi->nr_msir * msi->int_per_msir, order);
> +
> +	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
> +
> +	pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n",
> +		__FUNCTION__, num, order, offset);
> +
> +	return offset;
> +}
> +
> +void ipic_msi_free_hwirqs(struct ipic_msi *msi, int offset, int num)
> +{
> +	unsigned long flags;
> +	int order = get_count_order(num);
> +
> +	pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n",
> +		__FUNCTION__, num, order, offset);
> +
> +	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
> +	bitmap_release_region(msi->ipic_msi_bitmap, offset, order);
> +	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
> +}
> +
> +static int ipic_msi_init_allocator(struct ipic_msi *msi)
> +{
> +	int size;
> +
> +	size = BITS_TO_LONGS(msi->nr_msir * msi->int_per_msir) * sizeof(long);
> +	msi->ipic_msi_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
> +
> +	if (msi->ipic_msi_bitmap == NULL) {
> +		pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
> +				__FUNCTION__);
> +		return -ENOMEM;
> +	}
> +	memset(msi->ipic_msi_bitmap, 0, size);
> +
> +	return 0;
> +}

The last three routines are almost identical to the mpic_msi.c ones, if
in future we have a third implementation that looks almost identical
maybe we should consolidate them.

> +
> +static void ipic_msi_compose_msg(struct ipic_msi *msi, int hwirq,
> +						struct msi_msg *msg)
> +{
> +	unsigned int srs;
> +	unsigned int ibs;
> +
> +	srs = hwirq / msi->int_per_msir;
> +	ibs = hwirq - srs * msi->int_per_msir;
> +
> +	msg->address_lo = msi->msi_addr_lo;
> +	msg->address_hi = msi->msi_addr_hi;
> +	msg->data = (srs << 5) | (ibs & 0x1F);
> +
> +	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> +		__FUNCTION__, srs, ibs);
> +
> +}
> +
> +static int ipic_msi_setup_irqs(struct pci_dev *pdev, int nvec, int type)
> +{
> +	struct ipic_msi *msi = ipic_msi;
> +	irq_hw_number_t hwirq;
> +	unsigned int virq;
> +	struct msi_desc *entry;
> +	struct msi_msg msg;
> +
> +	list_for_each_entry(entry, &pdev->msi_list, list) {
> +		hwirq = ipic_msi_alloc_hwirqs(msi, 1);
> +		if (hwirq < 0) {
> +			pr_debug("%s: fail allocating msi interrupt\n",
> +					__FUNCTION__);
> +			return hwirq;
> +		}
> +
> +		/* This hwirq belongs to the irq_host other than irq_host of IPIC
> + 		 * So, it is independent to hwirq of IPIC */
> +		virq = irq_create_mapping(msi->irqhost, hwirq);
> +		if (virq == NO_IRQ) {
> +			pr_debug("%s: fail mapping hwirq 0x%lx\n",
> +					__FUNCTION__, hwirq);
> +			ipic_msi_free_hwirqs(msi, hwirq, 1);
> +			return -ENOSPC;
> +		}
> +		set_irq_msi(virq, entry);
> +		ipic_msi_compose_msg(msi, hwirq, &msg);
> +		write_msi_msg(virq, &msg);
> +
> +		hwirq++;

                  ^^^^ this looks like my bug

> +	}
> +
> +	return 0;
> +}
> +
> +static void ipic_msi_teardown_irqs(struct pci_dev *pdev)
> +{
> +	struct msi_desc *entry;
> +	struct ipic_msi *msi = ipic_msi;
> +
> +	list_for_each_entry(entry, &pdev->msi_list, list) {
> +		if (entry->irq == NO_IRQ)
> +			continue;
> +		set_irq_msi(entry->irq, NULL);
> +		ipic_msi_free_hwirqs(msi, virq_to_hw(entry->irq), 1);
> +		irq_dispose_mapping(entry->irq);
> +	}
> +
> +	return;
> +}
> +
> +void __init ipic_msi_init(struct device_node *node,
> +			void (*handler)(unsigned int irq, struct irq_desc *desc))
> +{
> +	struct ipic_msi *msi;
> +	struct resource res;
> +	int i;
> +	int rc = 0;
> +
> +	msi = alloc_maybe_bootmem(sizeof(*msi), GFP_KERNEL);
> +	if (msi == NULL)
> +		return;
> +
> +	memset(msi, 0, sizeof(*msi));
> +
> +
> +	msi->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
> +					NR_MSIR, &ipic_msi_host_ops, 0);
> +	if (msi->irqhost == NULL) {
> +		of_node_put(node);
> +		goto out;
> +	}
> +
> +	rc = of_address_to_resource(node, 0, &res);
> +	if (rc) {
> +		of_node_put(node);
> +		goto out;
> +	}
> +
> +	msi->regs = ioremap(res.start, res.end - res.start + 1);
> +	msi->irqhost->host_data = msi;
> +	msi->hc_irq = &ipic_msi_chip;
> +
> +	msi->msi_addr_lo = 0xE00007F8;
> +	msi->msi_addr_hi = 0;
> +	msi->nr_msir = ARRAY_SIZE(msi->msir);
> +	msi->int_per_msir = 32;
> +	for (i = 0; i < msi->nr_msir; i++) {
> +		unsigned int virt_msir = irq_of_parse_and_map(node, i);
> +		if (virt_msir != NO_IRQ) {
> +			set_irq_data(virt_msir, msi);
> +			set_irq_chained_handler(virt_msir, handler);
> +			msi->msir[i] = virt_msir;
> +		} else
> +			msi->msir[i] = NO_IRQ;
> +	}
> +
> +	rc = ipic_msi_init_allocator(msi);
> +	if (rc)
		< missing of_node_put() ? >
> +		goto out;
> +
> +	ipic_msi = msi;
> +
> +	WARN_ON(ppc_md.setup_msi_irqs);
> +	ppc_md.setup_msi_irqs = ipic_msi_setup_irqs;
> +	ppc_md.teardown_msi_irqs = ipic_msi_teardown_irqs;
> +
	  return ?

> +out:
> +	if (mem_init_done)
> +		kfree(msi);
> +
> +	return;
> +}
> +
> +static int ipic_msi_get_irq(struct ipic_msi *msi, int virt_msir)
> +{
> +	int msir = -1;
> +	unsigned int temp;
> +	unsigned int offset;
> +	int i;
> +
> +	for (i = 0; i < msi->nr_msir; i++)
> +		if (virt_msir == msi->msir[i]) {
> +			msir = i;
> +			break;
> +		}
> +
> +	if (i >= msi->nr_msir)
> +		return NO_IRQ;
> +
> +	temp = ipic_msi_read(msi->regs, IPIC_MSIR0 + (i * 4));
> +	offset = ffs(temp) - 1;
> +
> +	return irq_linear_revmap(msi->irqhost, (msir * msi->int_per_msir + offset));
> +}
> +
> +void ipic_msi_cascade(unsigned int irq, struct irq_desc *desc)
> +{
> +	struct ipic_msi *msi;
> +	unsigned int cascade_irq;
> +
> +	spin_lock(&desc->lock);
> +	if (desc->chip->mask_ack)
> +		desc->chip->mask_ack(irq);
> +	else {
> +		desc->chip->mask(irq);
> +		desc->chip->ack(irq);
> +	}
> +
> +	if (unlikely(desc->status & IRQ_INPROGRESS))
> +		goto unlock;
> +
> +	desc->status |= IRQ_INPROGRESS;
> +	msi = desc->handler_data;
> +	cascade_irq = ipic_msi_get_irq(msi, irq);
> +
> +	spin_unlock(&desc->lock);
> +
> +	if (cascade_irq != NO_IRQ)
> +		generic_handle_irq(cascade_irq);
> +
> +	spin_lock(&desc->lock);
> +	desc->status &= ~IRQ_INPROGRESS;
> +	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
> +		desc->chip->unmask(irq);
> +
> +unlock:
> +	spin_unlock(&desc->lock);
> +}

I don't know your hardware, but this looks a bit weird. Doesn't the
upstream handler do most of this logic for you?


cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 0/24] powerpc: 4xx PCI, PCI-X and PCI-Express support among others
From: Grant Likely @ 2007-12-03  4:18 UTC (permalink / raw)
  To: Josh Boyer; +Cc: Olof Johansson, linuxppc-dev
In-Reply-To: <20071130185304.2ea3aad3@zod.rchland.ibm.com>

On 11/30/07, Josh Boyer <jwboyer@linux.vnet.ibm.com> wrote:
> On Fri, 30 Nov 2007 10:11:05 -0600
> Jon Loeliger <jdl@freescale.com> wrote:
>
> > Olof Johansson wrote:
> >
> > > I normally do "quilt diff | checkpatch.pl -" when use quilt. You could
> > > similarly do "git diff HEAD | checkpatch.pl -". You'd always get the
> > > warning about missing signed-off-by though.
> >
> > So do a "git log -p | checkpatch.pl -" instead? :-)
>
> That sort of defeats the purpose of running checkpatch.pl _before_ you
> commit things...

stg show | checkpatch.pl -

:-p

g.


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 0/24] powerpc: 4xx PCI, PCI-X and PCI-Express support among others
From: Josh Boyer @ 2007-12-03  4:20 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev
In-Reply-To: <1196652270.13230.192.camel@pasglop>

On Mon, 03 Dec 2007 14:24:30 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> 
> On Fri, 2007-11-30 at 14:17 -0600, Josh Boyer wrote:
> > > Some of these patches are _NOT_ yet candidate for merging
> > > (mostly the board support ones), but you can review them and
> > > Josh can put them in an experimental tree.
> > 
> > I've added these to the 2.6.25-candidates branch in my tree.  Fixed up
> > the few conflicts manually.  I'll expect refreshes before merging
> > anyway, but I'd like to get these out there for people to play with.
> 
> BTW. You were telling me the other day about a problem with the clock
> code. 
> 
> It looks like the problem is a subtle difference between 440EP /440EPx
> and 440SPe / 440GX. The former has the EBC clock derived from the PLB
> clock while the later has it derived from OPB... yuck.

Yes.

> I'm fixing that.

Ok.

josh

^ permalink raw reply

* Re: [PATCH 2/4] Use embedded dtc in kernel builds
From: David Gibson @ 2007-12-03  4:30 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20071112041524.D0C11DDED4@ozlabs.org>

This patch alters the kernel makefiles to build dtc from the sources
embedded in the previous patch.  It also changes the
arch/powerpc/boot/wrapper script to use the embedded dtc, rather than
expecting a copy of dtc already installed on the system.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---

Previous version would screw up badly if building with O=...  Fixed
now.

Index: working-2.6/arch/powerpc/boot/Makefile
===================================================================
--- working-2.6.orig/arch/powerpc/boot/Makefile	2007-10-22 13:55:49.000000000 +1000
+++ working-2.6/arch/powerpc/boot/Makefile	2007-12-03 15:23:08.000000000 +1100
@@ -108,17 +108,52 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-
 $(obj)/wrapper.a: $(obj-wlib) FORCE
 	$(call if_changed,bootar)
 
-hostprogs-y	:= addnote addRamDisk hack-coff mktree
+hostprogs-y	:= addnote addRamDisk hack-coff mktree dtc
 
 targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
 		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper		:=$(srctree)/$(src)/wrapper
-wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
+wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
 			$(wrapper) FORCE
 
 #############
+# Bits for building dtc
+# DTC_GENPARSER      := 1    # Uncomment to rebuild flex/bison output
+
+dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o
+dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+dtc-objs := $(addprefix dtc-src/, $(dtc-objs))
+
+# prerequisites on generated files needs to be explicit
+$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h
+$(obj)/dtc-src/dtc-lexer.lex.o:  $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h
+
+HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/dtc-src/libfdt/
+
+targets += dtc-src/dtc-parser.tab.c
+targets += dtc-src/dtc-lexer.lex.c
+
+ifdef DTC_GENPARSER
+BISON = bison
+FLEX = flex
+
+quiet_cmd_bison = BISON   $@
+      cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
+quiet_cmd_flex = FLEX    $@
+      cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
+
+$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
+     $(call if_changed,bison)
+
+$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
+
+$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
+     $(call if_changed,flex)
+endif
+
+#############
 # Bits for building various flavours of zImage
 
 ifneq ($(CROSS32_COMPILE),)
Index: working-2.6/arch/powerpc/boot/wrapper
===================================================================
--- working-2.6.orig/arch/powerpc/boot/wrapper	2007-12-03 13:17:20.000000000 +1100
+++ working-2.6/arch/powerpc/boot/wrapper	2007-12-03 13:47:12.000000000 +1100
@@ -119,7 +119,7 @@ if [ -n "$dts" ]; then
     if [ -z "$dtb" ]; then
 	dtb="$platform.dtb"
     fi
-    dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts"
+    $object/dtc -O dtb -o "$dtb" -b 0 "$dts"
 fi
 
 if [ -z "$kernel" ]; then

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 3/4] Use embedded libfdt in the bootwrapper
From: David Gibson @ 2007-12-03  4:30 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20071112041525.2AE33DDED7@ozlabs.org>

Use embedded libfdt in the bootwrapper

This patch incorporates libfdt (from the source embedded in an earlier
patch) into the wrapper.a library used by the bootwrapper.  This
includes adding a libfdt_env.h file, which the libfdt sources need in
order to integrate into the bootwrapper environment, and a
libfdt-wrapper.c which provides glue to connect the bootwrappers
abstract device tree callbacks to the libfdt functions.

In addition, this patch changes the various wrapper and platform files
to use libfdt functions instead of the older flatdevtree.c library.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---

Fixed for O= builds.

Index: working-2.6/arch/powerpc/boot/Makefile
===================================================================
--- working-2.6.orig/arch/powerpc/boot/Makefile	2007-12-03 15:23:08.000000000 +1100
+++ working-2.6/arch/powerpc/boot/Makefile	2007-12-03 15:24:22.000000000 +1100
@@ -33,7 +33,7 @@ ifeq ($(call cc-option-yn, -fstack-prote
 BOOTCFLAGS	+= -fno-stack-protector
 endif
 
-BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj)
+BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj) -I$(srctree)/$(src)/dtc-src/libfdt
 
 $(obj)/4xx.o: BOOTCFLAGS += -mcpu=440
 $(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
@@ -46,7 +46,9 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
 	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
+src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
+		$(addprefix dtc-src/libfdt/,$(src-libfdt)) libfdt-wrapper.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
@@ -101,8 +103,10 @@ quiet_cmd_bootar = BOOTAR  $@
       cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
 
 $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
+	$(Q)mkdir -p $(dir $@)
 	$(call if_changed_dep,bootcc)
 $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
+	$(Q)mkdir -p $(dir $@)
 	$(call if_changed_dep,bootas)
 
 $(obj)/wrapper.a: $(obj-wlib) FORCE
Index: working-2.6/arch/powerpc/boot/libfdt_env.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ working-2.6/arch/powerpc/boot/libfdt_env.h	2007-12-03 15:23:28.000000000 +1100
@@ -0,0 +1,17 @@
+#ifndef _ARCH_POWERPC_BOOT_LIBFDT_ENV_H
+#define _ARCH_POWERPC_BOOT_LIBFDT_ENV_H
+
+#include <types.h>
+#include <string.h>
+
+typedef u32 uint32_t;
+typedef u64 uint64_t;
+
+#define fdt16_to_cpu(x)		(x)
+#define cpu_to_fdt16(x)		(x)
+#define fdt32_to_cpu(x)		(x)
+#define cpu_to_fdt32(x)		(x)
+#define fdt64_to_cpu(x)		(x)
+#define cpu_to_fdt64(x)		(x)
+
+#endif /* _ARCH_POWERPC_BOOT_LIBFDT_ENV_H */
Index: working-2.6/arch/powerpc/boot/bamboo.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/bamboo.c	2007-12-03 15:20:04.000000000 +1100
+++ working-2.6/arch/powerpc/boot/bamboo.c	2007-12-03 15:23:28.000000000 +1100
@@ -42,6 +42,6 @@ void bamboo_init(void *mac0, void *mac1)
 	platform_ops.exit = ibm44x_dbcr_reset;
 	bamboo_mac0 = mac0;
 	bamboo_mac1 = mac1;
-	ft_init(_dtb_start, 0, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
Index: working-2.6/arch/powerpc/boot/cuboot-52xx.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-52xx.c	2007-12-03 15:20:04.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-52xx.c	2007-12-03 15:23:28.000000000 +1100
@@ -53,7 +53,7 @@ void platform_init(unsigned long r3, uns
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-83xx.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-83xx.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-83xx.c	2007-12-03 15:23:28.000000000 +1100
@@ -52,7 +52,7 @@ void platform_init(unsigned long r3, uns
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-85xx.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-85xx.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-85xx.c	2007-12-03 15:23:28.000000000 +1100
@@ -53,7 +53,7 @@ void platform_init(unsigned long r3, uns
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-8xx.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-8xx.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-8xx.c	2007-12-03 15:23:28.000000000 +1100
@@ -41,7 +41,7 @@ void platform_init(unsigned long r3, uns
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-hpc2.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-hpc2.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-hpc2.c	2007-12-03 15:23:28.000000000 +1100
@@ -42,7 +42,7 @@ void platform_init(unsigned long r3, uns
 		unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-pq2.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-pq2.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-pq2.c	2007-12-03 15:23:28.000000000 +1100
@@ -255,7 +255,7 @@ void platform_init(unsigned long r3, uns
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = pq2_platform_fixups;
 }
Index: working-2.6/arch/powerpc/boot/cuboot-sequoia.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/cuboot-sequoia.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/cuboot-sequoia.c	2007-12-03 15:23:28.000000000 +1100
@@ -51,6 +51,6 @@ void platform_init(unsigned long r3, uns
 	CUBOOT_INIT();
 	platform_ops.fixups = sequoia_fixups;
 	platform_ops.exit = ibm44x_dbcr_reset;
-	ft_init(_dtb_start, 0, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
Index: working-2.6/arch/powerpc/boot/ebony.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/ebony.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/ebony.c	2007-12-03 15:23:28.000000000 +1100
@@ -146,6 +146,6 @@ void ebony_init(void *mac0, void *mac1)
 	platform_ops.exit = ibm44x_dbcr_reset;
 	ebony_mac0 = mac0;
 	ebony_mac1 = mac1;
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
Index: working-2.6/arch/powerpc/boot/ep88xc.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/ep88xc.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/ep88xc.c	2007-12-03 15:23:28.000000000 +1100
@@ -45,7 +45,7 @@ void platform_init(unsigned long r3, uns
 	mem_size *= 1024 * 1024;
 	simple_alloc_init(_end, mem_size - (unsigned long)_end, 32, 64);
 
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 
 	planetcore_set_stdout_path(table);
 
Index: working-2.6/arch/powerpc/boot/holly.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/holly.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/holly.c	2007-12-03 15:23:28.000000000 +1100
@@ -28,6 +28,6 @@ void platform_init(unsigned long r3, uns
 	u32 heapsize = 0x8000000 - (u32)_end; /* 128M */
 
 	simple_alloc_init(_end, heapsize, 32, 64);
-	ft_init(_dtb_start, 0, 4);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
Index: working-2.6/arch/powerpc/boot/libfdt-wrapper.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ working-2.6/arch/powerpc/boot/libfdt-wrapper.c	2007-12-03 15:23:28.000000000 +1100
@@ -0,0 +1,182 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <page.h>
+#include <libfdt.h>
+#include "ops.h"
+
+#define DEBUG	0
+#define BAD_ERROR(err)	(((err) < 0) \
+			 && ((err) != -FDT_ERR_NOTFOUND) \
+			 && ((err) != -FDT_ERR_EXISTS))
+
+#define check_err(err) \
+	({ \
+		if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
+			printf("%s():%d  %s\n\r", __FUNCTION__, __LINE__, \
+			       fdt_strerror(err)); \
+		if (BAD_ERROR(err)) \
+			exit(); \
+		(err < 0) ? -1 : 0; \
+	})
+
+#define offset_devp(off)	\
+	({ \
+		int offset = (off); \
+		check_err(offset) ? NULL : (void *)(offset+1); \
+	})
+
+#define devp_offset(devp)	(((int)(devp))-1)
+
+static void *fdt;
+static void *buf; /* = NULL */
+
+#define EXPAND_GRANULARITY	1024
+
+static void expand_buf(int minexpand)
+{
+	int size = fdt_totalsize(fdt);
+	int rc;
+
+	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
+	buf = platform_ops.realloc(buf, size);
+	if (!buf)
+		fatal("Couldn't find %d bytes to expand device tree\n\r", size);
+	rc = fdt_open_into(fdt, buf, size);
+	if (rc != 0)
+		fatal("Couldn't expand fdt into new buffer: %s\n\r",
+		      fdt_strerror(rc));
+
+	fdt = buf;
+}
+
+static void *fdt_wrapper_finddevice(const char *path)
+{
+	return offset_devp(fdt_path_offset(fdt, path));
+}
+
+static int fdt_wrapper_getprop(const void *devp, const char *name,
+			       void *buf, const int buflen)
+{
+	const void *p;
+	int len;
+
+	p = fdt_getprop(fdt, devp_offset(devp), name, &len);
+	if (!p)
+		return check_err(len);
+	memcpy(buf, p, min(len, buflen));
+	return len;
+}
+
+static int fdt_wrapper_setprop(const void *devp, const char *name,
+			       const void *buf, const int len)
+{
+	int rc;
+
+	rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+	if (rc == -FDT_ERR_NOSPACE) {
+		expand_buf(len + 16);
+		rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+	}
+
+	return check_err(rc);
+}
+
+static void *fdt_wrapper_get_parent(const void *devp)
+{
+	return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
+}
+
+static void *fdt_wrapper_create_node(const void *devp, const char *name)
+{
+	int offset;
+
+	offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+	if (offset == -FDT_ERR_NOSPACE) {
+		expand_buf(strlen(name) + 16);
+		offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+	}
+
+	return offset_devp(offset);
+}
+
+static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
+						 const char *name,
+						 const char *val,
+						 int len)
+{
+	return offset_devp(fdt_node_offset_by_prop_value(fdt, devp_offset(prev),
+							 name, val, len));
+}
+
+static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
+{
+	int rc;
+
+	rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
+	if (check_err(rc))
+		return NULL;
+	return buf;
+}
+
+static unsigned long fdt_wrapper_finalize(void)
+{
+	int rc;
+
+	rc = fdt_pack(fdt);
+	if (rc != 0)
+		fatal("Couldn't pack flat tree: %s\n\r",
+		      fdt_strerror(rc));
+	return (unsigned long)fdt;
+}
+
+void fdt_init(void *blob)
+{
+	int err;
+
+	dt_ops.finddevice = fdt_wrapper_finddevice;
+	dt_ops.getprop = fdt_wrapper_getprop;
+	dt_ops.setprop = fdt_wrapper_setprop;
+	dt_ops.get_parent = fdt_wrapper_get_parent;
+	dt_ops.create_node = fdt_wrapper_create_node;
+	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
+	dt_ops.get_path = fdt_wrapper_get_path;
+	dt_ops.finalize = fdt_wrapper_finalize;
+
+	/* Make sure the dt blob is the right version and so forth */
+	fdt = blob;
+	err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
+	if (err == -FDT_ERR_NOSPACE) {
+		int bufsize = fdt_totalsize(fdt) + 4;
+		buf = malloc(bufsize);
+		err = fdt_open_into(fdt, buf, bufsize);
+	}
+
+	if (err != 0)
+		fatal("fdt_init(): %s\n\r", fdt_strerror(err));
+
+	if (buf)
+		fdt = buf;
+}
Index: working-2.6/arch/powerpc/boot/ops.h
===================================================================
--- working-2.6.orig/arch/powerpc/boot/ops.h	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/ops.h	2007-12-03 15:23:28.000000000 +1100
@@ -80,6 +80,7 @@ extern struct loader_info loader_info;
 
 void start(void);
 int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
+void fdt_init(void *blob);
 int serial_console_init(void);
 int ns16550_console_init(void *devp, struct serial_console_data *scdp);
 int mpsc_console_init(void *devp, struct serial_console_data *scdp);
Index: working-2.6/arch/powerpc/boot/prpmc2800.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/prpmc2800.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/prpmc2800.c	2007-12-03 15:23:28.000000000 +1100
@@ -547,8 +547,7 @@ void platform_init(unsigned long r3, uns
 	if (!dtb)
 		exit();
 	memmove(dtb, _dtb_start, dt_size);
-	if (ft_init(dtb, dt_size, 16))
-		exit();
+	fdt_init(dtb);
 
 	bridge_base = mv64x60_get_bridge_base();
 
Index: working-2.6/arch/powerpc/boot/ps3.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/ps3.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/ps3.c	2007-12-03 15:23:28.000000000 +1100
@@ -131,7 +131,7 @@ void platform_init(void)
 	printf("\n-- PS3 bootwrapper --\n");
 
 	simple_alloc_init(_end, heapsize, 32, 64);
-	ft_init(_dtb_start, 0, 4);
+	fdt_init(_dtb_start);
 
 	chosen = finddevice("/chosen");
 
Index: working-2.6/arch/powerpc/boot/treeboot-walnut.c
===================================================================
--- working-2.6.orig/arch/powerpc/boot/treeboot-walnut.c	2007-12-03 15:20:05.000000000 +1100
+++ working-2.6/arch/powerpc/boot/treeboot-walnut.c	2007-12-03 15:23:28.000000000 +1100
@@ -128,6 +128,6 @@ void platform_init(void)
 	simple_alloc_init(_end, avail_ram, 32, 32);
 	platform_ops.fixups = walnut_fixups;
 	platform_ops.exit = ibm40x_dbcr_reset;
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }


-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* [PATCH] [POWERPC] pasemi: Fix module information for gpio-mdio
From: Olof Johansson @ 2007-12-03  4:40 UTC (permalink / raw)
  To: linuxppc-dev

[POWERPC] pasemi: Fix module information for gpio-mdio
    
Fix up the module information for gpio-mdio, it wouldn't load
because of lacking license, and wouldn't auto-load because of missing
MODULE_DEVICE_TABLE.
    
Signed-off-by: Olof Johansson <olof@lixom.net>

diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index b029804..04a8686 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -318,6 +318,7 @@ static struct of_device_id gpio_mdio_match[] =
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, gpio_mdio_match);
 
 static struct of_platform_driver gpio_mdio_driver =
 {
@@ -356,3 +357,7 @@ void gpio_mdio_exit(void)
 		iounmap(gpio_regs);
 }
 module_exit(gpio_mdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("Driver for MDIO over GPIO on PA Semi PWRficient-based boards");

^ permalink raw reply related

* for-2.6.25 branch created in powerpc.git
From: Paul Mackerras @ 2007-12-03  4:45 UTC (permalink / raw)
  To: linuxppc-dev

I have created a for-2.6.25 branch in my powerpc.git repository and
added the patches listed below to it.  The master branch points to the
same place as the for-2.6.25 branch.

Paul.

Benjamin Herrenschmidt (2):
      [POWERPC] Cleanup SMT thread handling
      [POWERPC] Add xmon function to dump 44x TLB

Johannes Berg (3):
      [POWERPC] powermac: Fix warning in time.c
      [POWERPC] PMU: Don't lock_kernel()
      [POWERPC] PMU: Remove dead code

Linas Vepstas (3):
      [POWERPC] EEH: Work with device endpoint, always
      [POWERPC] EEH: Be careful when identifying "empty" slots.
      [POWERPC] EEH: Report errors as soon as possible

Nathan Lynch (1):
      [POWERPC] Remove prod_processor()

Stephen Rothwell (5):
      [POWERPC] Make global_phb_number static
      [POWERPC] iSeries: Mark two functions __init
      [POWERPC] iSeries: Declare iSeries_pci_final_fixup in pci.h
      [POWERPC] iSeries: Fix sparse warnings in setup.c
      [POWERPC] Remove redundant declaration of hose_list

joe@perches.com (2):
      [POWERPC] Add missing spaces in printk formats
      [POWERPC] Add missing spaces in printk formats in arch/ppc

 arch/powerpc/kernel/isa-bridge.c                |    4 +
 arch/powerpc/kernel/pci-common.c                |    4 -
 arch/powerpc/kernel/setup-common.c              |   78 +++++++++++++++++++----
 arch/powerpc/mm/fault.c                         |    2 -
 arch/powerpc/platforms/8xx/m8xx_setup.c         |    2 -
 arch/powerpc/platforms/cell/smp.c               |    3 +
 arch/powerpc/platforms/celleb/io-workarounds.c  |    2 -
 arch/powerpc/platforms/celleb/scc_epci.c        |    2 -
 arch/powerpc/platforms/iseries/pci.c            |    4 +
 arch/powerpc/platforms/iseries/pci.h            |    5 +
 arch/powerpc/platforms/iseries/setup.c          |   22 +++---
 arch/powerpc/platforms/iseries/setup.h          |    1 
 arch/powerpc/platforms/powermac/time.c          |    2 +
 arch/powerpc/platforms/pseries/eeh.c            |    3 +
 arch/powerpc/platforms/pseries/eeh_driver.c     |   15 ++--
 arch/powerpc/platforms/pseries/plpar_wrappers.h |    5 -
 arch/powerpc/platforms/pseries/smp.c            |    3 +
 arch/powerpc/sysdev/fsl_pci.c                   |    2 -
 arch/powerpc/xmon/xmon.c                        |   38 +++++++++++
 arch/ppc/platforms/ev64260.c                    |    4 +
 drivers/macintosh/via-pmu.c                     |   45 -------------
 include/asm-powerpc/cputhreads.h                |   71 +++++++++++++++++++++
 include/asm-powerpc/ppc-pci.h                   |    1 
 23 files changed, 218 insertions(+), 100 deletions(-)
 create mode 100644 include/asm-powerpc/cputhreads.h

^ permalink raw reply

* Re: [PATCH] [POWERPC] pasemi: Fix module information for gpio-mdio
From: Paul Mackerras @ 2007-12-03  4:46 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <20071203044016.GA24068@lixom.net>

Olof Johansson writes:

> Fix up the module information for gpio-mdio, it wouldn't load
> because of lacking license, and wouldn't auto-load because of missing
> MODULE_DEVICE_TABLE.

Needed for 2.6.24?

Paul.

^ permalink raw reply

* Re: [PATCH] [POWERPC] pasemi: Fix module information for gpio-mdio
From: Olof Johansson @ 2007-12-03  4:58 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18259.35370.588914.613689@cargo.ozlabs.ibm.com>

On Mon, Dec 03, 2007 at 03:46:34PM +1100, Paul Mackerras wrote:
> Olof Johansson writes:
> 
> > Fix up the module information for gpio-mdio, it wouldn't load
> > because of lacking license, and wouldn't auto-load because of missing
> > MODULE_DEVICE_TABLE.
> 
> Needed for 2.6.24?

It's annoying but not critical, and the workaround is simple (build it
in). I've already queued it up in my for-2.6.25 git branch, that should
be sufficient.


Thanks,

Olof

^ permalink raw reply

* Please pull pasemi.git for-2.6.25 branch
From: Olof Johansson @ 2007-12-03  5:04 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Paul,

Please do:

git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/olof/pasemi.git for-2.6.25

For the following patches queued up for 2.6.25. All but one are PA
Semi-specific (the i2c boardinfo consolidation that's a pre-req for the
platform-specific one).

 arch/powerpc/platforms/pasemi/Kconfig     |    2 
 arch/powerpc/platforms/pasemi/Makefile    |    2 
 arch/powerpc/platforms/pasemi/cpufreq.c   |   19 +++++-
 arch/powerpc/platforms/pasemi/gpio_mdio.c |   94 ++++++++++++++++++------------
 arch/powerpc/platforms/pasemi/misc.c      |   66 +++++++++++++++++++++
 arch/powerpc/platforms/pasemi/pasemi.h    |    6 +
 arch/powerpc/platforms/pasemi/powersave.S |   11 +++
 arch/powerpc/platforms/pasemi/setup.c     |   16 ++++-
 arch/powerpc/sysdev/Makefile              |    1 
 arch/powerpc/sysdev/fsl_soc.c             |   40 ------------
 arch/powerpc/sysdev/i2c_of_mapping.c      |   61 +++++++++++++++++++
 drivers/char/hw_random/Kconfig            |    2 
 drivers/char/hw_random/pasemi-rng.c       |    7 --
 drivers/edac/pasemi_edac.c                |    4 -
 include/asm-powerpc/i2c_of.h              |   14 ++++
 15 files changed, 256 insertions(+), 89 deletions(-)


Olof Johansson (7):
      [POWERPC] pasemi: clean up mdio_gpio a bit
      [POWERPC] pasemi: Broaden specific references to 1682M
      [POWERPC] pasemi: Don't enter powersaving states from elevated astates
      [POWERPC] pasemi: Move cpus to hold loop before restart
      [POWERPC] Consolidate compatible-to-i2c_boardinfo mapping code
      [POWERPC] pasemi: Register i2c_board_info
      [POWERPC] pasemi: Fix module information for gpio-mdio


Thanks,

Olof

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Li Li @ 2007-12-03  4:59 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, Gala Kumar, Li Tony
In-Reply-To: <20071203015209.GD26919@localhost.localdomain>

On Mon, 2007-12-03 at 09:52 +0800, David Gibson wrote:
> On Fri, Nov 30, 2007 at 11:48:39AM +0800, Li Li wrote: 
> > The IPIC MSI is introduced on MPC837x chip. 
> > Implements the IPIC MSI as two level interrupt controller. 
> > 
> > Signed-off-by: Tony Li <tony.li@freescale.com> 
> > --- 
> >  arch/powerpc/boot/dts/mpc8377_mds.dts     |   14 ++ 
> >  arch/powerpc/boot/dts/mpc8378_mds.dts     |   14 ++ 
> >  arch/powerpc/boot/dts/mpc8379_mds.dts     |   14 ++ 
> >  arch/powerpc/platforms/83xx/Kconfig       |    6 + 
> >  arch/powerpc/platforms/83xx/mpc837x_mds.c |   11 + 
> >  arch/powerpc/sysdev/Makefile              |    1 + 
> >  arch/powerpc/sysdev/ipic_msi.c            |  359
> +++++++++++++++++++++++++++++ 
> >  include/asm-powerpc/ipic_msi.h            |   54 +++++ 
> >  8 files changed, 473 insertions(+), 0 deletions(-) 
> >  create mode 100644 arch/powerpc/sysdev/ipic_msi.c 
> >  create mode 100644 include/asm-powerpc/ipic_msi.h 
> > 
> > diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts
> b/arch/powerpc/boot/dts/mpc8377_mds.dts 
> > index 1f7819e..1068fe2 100644 
> > --- a/arch/powerpc/boot/dts/mpc8377_mds.dts 
> > +++ b/arch/powerpc/boot/dts/mpc8377_mds.dts 
> > @@ -210,6 +210,20 @@ 
> >                       #interrupt-cells = <2>; 
> >                       reg = <700 100>; 
> >               }; 
> > + 
> > +             ipic-msi@7c0 { 
> > +                     compatible = "fsl,ipic-msi"; 
> > +                     reg = <7c0 40>; 
> > +                     interrupts = < 43 8 
> > +                                    4  8 
> > +                                    51 8 
> > +                                    52 8 
> > +                                    56 8 
> > +                                    57 8 
> > +                                    58 8 
> > +                                    59 8 >; 
> > +                     interrupt-parent = < &ipic >; 
> > +             };
> 
> I'm not sure why the MSI needs a device node of its own.  What actual 
> piece of hardware is this representing?
> 

The IPIC MSI has its own registers which control the mask and ack of MSI
interrupt. Furthermore, IPIC MSI is the second level interrupt
coontorller which connected to IPIC, to compatible with IPIC OF routine
interface, we need a device node.

> -- 
> David Gibson                    | I'll have my music baroque, and my
> code 
> david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_
> _other_ 
>                                 | _way_ _around_! 
> http://www.ozlabs.org/~dgibson
> 

- Tony

^ permalink raw reply

* Re: for-2.6.25 branch created in powerpc.git
From: Benjamin Herrenschmidt @ 2007-12-03  5:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18259.35326.516899.603549@cargo.ozlabs.ibm.com>


On Mon, 2007-12-03 at 15:45 +1100, Paul Mackerras wrote:
>       [POWERPC] Add xmon function to dump 44x TLB

That will go via jwb, there's already some updated versions of that in
my tree.

Ben.

^ permalink raw reply

* Re: Unable to Read PPC440EPx Board ID thru Board Control and Status Registers (BCSR)
From: Dell Query @ 2007-12-03  7:17 UTC (permalink / raw)
  To: Stefan Roese; +Cc: linuxppc-embedded
In-Reply-To: <200711291113.10356.sr@denx.de>

[-- Attachment #1: Type: text/plain, Size: 2160 bytes --]

Hi Stefan,

I finally got the new pdf files from other Resource CDs and used 0xc000000 address, without 0x2000 offset.

It works! Thanks a lot for the help.

But may I know why in Linux it is mapped to 0x1c000000, wherein the doc stated 0xc000000?

Thanks a lot!

Stefan Roese <sr@denx.de> wrote: Hi Dell (???),

On Thursday 29 November 2007, Dell Query wrote:
> 1. I used the 0x1c0002000 offset because I was referring to the first reply
> that I received. Now, I used the address 0x1c0002000 and tried to read from
> it. I retrieved 0x0f01c087. May I know what does this mean? How does this
> data relate to Board ID?

Please refer to the document describing the CPLD registers. They are byte 
registers and not 32bit lword registers (see below).

> 2. Referring back to "Embedded Planet 440xC" document, I tried to activate
> the USER_LED0/USER_LED1 (with new address 0x1c0000000 + 0x2 offset) by
> setting it to 0. But didn't see the led turned on. Did some experiments and
> tried 0x1c0000000 without offset, sent 0, and found that USER_LED0 (CR3)
> and USER_LED1 (CR4) are activated! This got me confused. May I know why is
> this so? Could you please refer me to some documents?

The address of the CPLD is without this 0x2000 offset as it seems. Maybe the 
Sequoia users manual is incorrect here.

Make sure that you address these registers with the correct functions. That is 
in_8()/out_8(). Here a log from U-Boot:

=> md.l c0000000 1
c0000000: 0f00c007    ....
=> md.b c0000000 4
c0000000: 0f 00 c0 07    ....

By writing 0x00 to offset 0x02 (LED control) I am able to set the user led's. 
This should work in Linux the same way:

=> mw.b c0000002 00

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
=====================================================================


       
---------------------------------
Be a better sports nut! Let your teams follow you with Yahoo Mobile. Try it now.

[-- Attachment #2: Type: text/html, Size: 2608 bytes --]

^ permalink raw reply

* Re: [PATCH 14/27] powerpc: ptrace generic resume
From: Srinivasa Ds @ 2007-12-03  8:12 UTC (permalink / raw)
  To: Roland McGrath
  Cc: Paul Mackerras, Andrew Morton, Linus Torvalds, linux-kernel,
	linuxppc-dev
In-Reply-To: <20071125220402.4C43C26F8DE@magilla.localdomain>

Roland McGrath wrote:
> This removes the handling for PTRACE_CONT et al from the powerpc
> ptrace code, so it uses the new generic code via ptrace_request.
 
   I have tested this patchset on powerpc successfully.

> 
> Signed-off-by: Roland McGrath <roland@redhat.com>
> ---
>  arch/powerpc/kernel/ptrace.c |   46 ------------------------------------------
>  1 files changed, 0 insertions(+), 46 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index b970d79..8b056d2 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -445,52 +445,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
>  		break;
>  	}


Thanks
 Srinivasa DS
 Linux Technology Centre
 IBM.

^ permalink raw reply

* Re: [PATCH] Add IPIC MSI interrupt support
From: Li Li @ 2007-12-03  9:07 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, Gala Kumar, Li Tony
In-Reply-To: <1196654521.13554.32.camel@concordia>

Hi Michael,

I emulate mpic to write this IPIC MSI routines. :)


> > diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > index 6048f1b..dbea34b 100644
> > --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
> > @@ -17,6 +17,9 @@
> >  
> >  #include <asm/time.h>
> >  #include <asm/ipic.h>
> > +#if CONFIG_IPIC_MSI
> > +#include <asm/ipic_msi.h>
> > +#endif
> >  #include <asm/udbg.h>
> >  #include <asm/prom.h>
> 
> I'd rather you just include it unconditionally.

Yes. that is ok for me.

> 
> > @@ -84,6 +87,14 @@ static void __init mpc837x_mds_init_IRQ(void)
> >  	 * in case the boot rom changed something on us.
> >  	 */
> >  	ipic_set_default_priority();
> > +
> > +#if CONFIG_IPIC_MSI
> > +	np = of_find_compatible_node(NULL, NULL, "fsl,ipic-msi");
> > +	if (!np)
> > +		return;
> > +
> > +	ipic_msi_init(np, ipic_msi_cascade);
> > +#endif
> 
> If you have a no-op version of ipic_msi_init() in your header file then
> you can remove the #ifdef in the C code - which I think is nicer.
> 

Seems you do not like #ifdef. :)  I agree it.
So, I move this #ifdef into header file.

> Why do you pass the handler into the init routine, rather than have the
> init routine just set the handler. Then you could make the handler
> static.
> 

In IPIC, the 8 MSI interrupts is handled as level intrrupt.
I just provide a versatile in case it is changed.

> >  }
> >  
> >  /*
> > diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
> > index 99a77d7..5946b6a 100644
> > --- a/arch/powerpc/sysdev/Makefile
> > +++ b/arch/powerpc/sysdev/Makefile
> > @@ -25,6 +25,7 @@ ifeq ($(CONFIG_PPC_MERGE),y)
> >  obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
> >  obj-$(CONFIG_PPC_I8259)		+= i8259.o
> >  obj-$(CONFIG_PPC_83xx)		+= ipic.o
> > +obj-$(CONFIG_IPIC_MSI)		+= ipic_msi.o
> >  obj-$(CONFIG_4xx)		+= uic.o
> >  obj-$(CONFIG_XILINX_VIRTEX)	+= xilinx_intc.o
> >  endif
> > diff --git a/arch/powerpc/sysdev/ipic_msi.c b/arch/powerpc/sysdev/ipic_msi.c
> > new file mode 100644
> > index 0000000..57758f7
> > --- /dev/null
> > +++ b/arch/powerpc/sysdev/ipic_msi.c
> > @@ -0,0 +1,359 @@
> > +/*
> > + * arch/powerpc/sysdev/ipic_msi.c
> > + *
> > + * IPIC MSI routines implementations.
> > + *
> > + * Auther: Tony Li <tony.li@freescale.com>
> > + *
> > + * Copyright (c) 2007 Freescale Semiconductor, Inc.
> > + *
> > + * This program is free software; you can redistribute  it and/or modify it
> > + * under  the terms of  the GNU General  Public License as published by the
> > + * Free Software Foundation;  either version 2 of the  License, or (at your
> > + * option) any later version.
> > + */
> > +
> > +
> > +#include <linux/pci.h>
> > +#include <linux/msi.h>
> > +#include <linux/irq.h>
> > +
> > +#include <asm/ipic_msi.h>
> > +
> > +#define MSIR0	0x43
> > +#define MSIR1	0x4
> > +#define MSIR2	0x51
> > +#define MSIR3	0x52
> > +#define MSIR4	0x56
> > +#define MSIR5	0x57
> > +#define MSIR6	0x58
> > +#define MSIR7	0x59
> > +
> > +
> > +static struct ipic_msi *ipic_msi;
> > +static DEFINE_SPINLOCK(ipic_msi_lock);
> > +static DEFINE_SPINLOCK(ipic_msi_bitmap_lock);
> > +
> > +static inline u32 ipic_msi_read(volatile u32 __iomem *base, unsigned int reg)
> > +{
> > +	return in_be32(base + (reg >> 2));
> > +}
> > +
> > +static inline void ipic_msi_write(volatile u32 __iomem *base,
> > +					unsigned int reg, u32 value)
> > +{
> > +	out_be32(base + (reg >> 2), value);
> > +}
> > +
> > +static struct ipic_msi * ipic_msi_from_irq(unsigned int virq)
> > +{
> > +	return ipic_msi;
> > +}
> > +
> > +#define	ipic_msi_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
> 
> What's wrong with virq_to_hw() ?
> 

viqr_to_hw is not __inline__.

> 
> > +static void ipic_msi_unmask(unsigned int virq)
> > +{
> > +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> > +	unsigned int src = ipic_msi_irq_to_hw(virq);
> > +	unsigned long flags;
> > +	u32 temp;
> > +
> > +	spin_lock_irqsave(&ipic_msi_lock, flags);
> > +	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
> > +	ipic_msi_write(msi->regs, IPIC_MSIMR,
> > +		temp & ~(1 << (src / msi->int_per_msir)));
> > +
> > +	spin_unlock_irqrestore(&ipic_msi_lock, flags);
> > +}
> > +
> > +static void ipic_msi_mask(unsigned int virq)
> > +{
> > +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> > +	unsigned int src = ipic_msi_irq_to_hw(virq);
> > +	unsigned long flags;
> > +	u32 temp;
> > +
> > +	spin_lock_irqsave(&ipic_msi_lock, flags);
> > +
> > +	temp = ipic_msi_read(msi->regs, IPIC_MSIMR);
> > +	ipic_msi_write(msi->regs, IPIC_MSIMR,
> > +		temp | (1 << (src / msi->int_per_msir)));
> > +
> > +	spin_unlock_irqrestore(&ipic_msi_lock, flags);
> > +}
> > +/*
> > + * We do not need this actually. The MSIR register has been read once
> > + * in ipic_msi_get_irq. So, this MSI interrupt has been acked
> > + */
> > +static void ipic_msi_ack(unsigned int virq)
> > +{
> > +	struct ipic_msi *msi = ipic_msi_from_irq(virq);
> > +	unsigned int src = ipic_msi_irq_to_hw(virq);
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&ipic_msi_lock, flags);
> > +
> > +	ipic_msi_read(msi->regs, IPIC_MSIR0 + (4 * (src / msi->int_per_msir)));
> > +
> > +	spin_unlock_irqrestore(&ipic_msi_lock,flags);
> > +}
> > +
> > +static struct irq_chip ipic_msi_chip = {
> > +	.typename = " IPIC MSI ",
> > +	.unmask = ipic_msi_unmask,
> > +	.mask = ipic_msi_mask,
> > +	.ack = ipic_msi_ack,
> > +};
> > +
> > +static int ipic_msi_host_map(struct irq_host *h, unsigned int virq,
> > +				irq_hw_number_t hw)
> > +{
> > +	struct ipic_msi *msi = h->host_data;
> > +	struct irq_chip *chip = msi->hc_irq;
> > +
> > +	set_irq_chip_data(virq, msi);
> > +	get_irq_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
> > +
> > +	set_irq_chip_and_handler(virq, chip, handle_edge_irq);
> > +	return 0;
> > +}
> > +
> > +static struct irq_host_ops ipic_msi_host_ops = {
> > +	.map = ipic_msi_host_map,
> > +};
> > +
> > +irq_hw_number_t ipic_msi_alloc_hwirqs(struct ipic_msi *msi, int num)
> > +{
> > +	unsigned long flags;
> > +	int offset, order = get_count_order(num);
> > +
> > +	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
> > +
> > +	offset = bitmap_find_free_region(msi->ipic_msi_bitmap,
> > +			msi->nr_msir * msi->int_per_msir, order);
> > +
> > +	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
> > +
> > +	pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n",
> > +		__FUNCTION__, num, order, offset);
> > +
> > +	return offset;
> > +}
> > +
> > +void ipic_msi_free_hwirqs(struct ipic_msi *msi, int offset, int num)
> > +{
> > +	unsigned long flags;
> > +	int order = get_count_order(num);
> > +
> > +	pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n",
> > +		__FUNCTION__, num, order, offset);
> > +
> > +	spin_lock_irqsave(&ipic_msi_bitmap_lock, flags);
> > +	bitmap_release_region(msi->ipic_msi_bitmap, offset, order);
> > +	spin_unlock_irqrestore(&ipic_msi_bitmap_lock, flags);
> > +}
> > +
> > +static int ipic_msi_init_allocator(struct ipic_msi *msi)
> > +{
> > +	int size;
> > +
> > +	size = BITS_TO_LONGS(msi->nr_msir * msi->int_per_msir) * sizeof(long);
> > +	msi->ipic_msi_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
> > +
> > +	if (msi->ipic_msi_bitmap == NULL) {
> > +		pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
> > +				__FUNCTION__);
> > +		return -ENOMEM;
> > +	}
> > +	memset(msi->ipic_msi_bitmap, 0, size);
> > +
> > +	return 0;
> > +}
> 
> The last three routines are almost identical to the mpic_msi.c ones, if
> in future we have a third implementation that looks almost identical
> maybe we should consolidate them.
> 

Yes. I agree.

> > +
> > +static void ipic_msi_compose_msg(struct ipic_msi *msi, int hwirq,
> > +						struct msi_msg *msg)
> > +{
> > +	unsigned int srs;
> > +	unsigned int ibs;
> > +
> > +	srs = hwirq / msi->int_per_msir;
> > +	ibs = hwirq - srs * msi->int_per_msir;
> > +
> > +	msg->address_lo = msi->msi_addr_lo;
> > +	msg->address_hi = msi->msi_addr_hi;
> > +	msg->data = (srs << 5) | (ibs & 0x1F);
> > +
> > +	pr_debug("%s: allocated srs: %d, ibs: %d\n",
> > +		__FUNCTION__, srs, ibs);
> > +
> > +}
> > +
> > +static int ipic_msi_setup_irqs(struct pci_dev *pdev, int nvec, int type)
> > +{
> > +	struct ipic_msi *msi = ipic_msi;
> > +	irq_hw_number_t hwirq;
> > +	unsigned int virq;
> > +	struct msi_desc *entry;
> > +	struct msi_msg msg;
> > +
> > +	list_for_each_entry(entry, &pdev->msi_list, list) {
> > +		hwirq = ipic_msi_alloc_hwirqs(msi, 1);
> > +		if (hwirq < 0) {
> > +			pr_debug("%s: fail allocating msi interrupt\n",
> > +					__FUNCTION__);
> > +			return hwirq;
> > +		}
> > +
> > +		/* This hwirq belongs to the irq_host other than irq_host of IPIC
> > + 		 * So, it is independent to hwirq of IPIC */
> > +		virq = irq_create_mapping(msi->irqhost, hwirq);
> > +		if (virq == NO_IRQ) {
> > +			pr_debug("%s: fail mapping hwirq 0x%lx\n",
> > +					__FUNCTION__, hwirq);
> > +			ipic_msi_free_hwirqs(msi, hwirq, 1);
> > +			return -ENOSPC;
> > +		}
> > +		set_irq_msi(virq, entry);
> > +		ipic_msi_compose_msg(msi, hwirq, &msg);
> > +		write_msi_msg(virq, &msg);
> > +
> > +		hwirq++;
> 
>                   ^^^^ this looks like my bug

I have a question here. Do we support more MSI interrupts on ONE pci
device?

> 
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ipic_msi_teardown_irqs(struct pci_dev *pdev)
> > +{
> > +	struct msi_desc *entry;
> > +	struct ipic_msi *msi = ipic_msi;
> > +
> > +	list_for_each_entry(entry, &pdev->msi_list, list) {
> > +		if (entry->irq == NO_IRQ)
> > +			continue;
> > +		set_irq_msi(entry->irq, NULL);
> > +		ipic_msi_free_hwirqs(msi, virq_to_hw(entry->irq), 1);
> > +		irq_dispose_mapping(entry->irq);
> > +	}
> > +
> > +	return;
> > +}
> > +
> > +void __init ipic_msi_init(struct device_node *node,
> > +			void (*handler)(unsigned int irq, struct irq_desc *desc))
> > +{
> > +	struct ipic_msi *msi;
> > +	struct resource res;
> > +	int i;
> > +	int rc = 0;
> > +
> > +	msi = alloc_maybe_bootmem(sizeof(*msi), GFP_KERNEL);
> > +	if (msi == NULL)
> > +		return;
> > +
> > +	memset(msi, 0, sizeof(*msi));
> > +
> > +
> > +	msi->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
> > +					NR_MSIR, &ipic_msi_host_ops, 0);
> > +	if (msi->irqhost == NULL) {
> > +		of_node_put(node);
> > +		goto out;
> > +	}
> > +
> > +	rc = of_address_to_resource(node, 0, &res);
> > +	if (rc) {
> > +		of_node_put(node);
> > +		goto out;
> > +	}
> > +
> > +	msi->regs = ioremap(res.start, res.end - res.start + 1);
> > +	msi->irqhost->host_data = msi;
> > +	msi->hc_irq = &ipic_msi_chip;
> > +
> > +	msi->msi_addr_lo = 0xE00007F8;
> > +	msi->msi_addr_hi = 0;
> > +	msi->nr_msir = ARRAY_SIZE(msi->msir);
> > +	msi->int_per_msir = 32;
> > +	for (i = 0; i < msi->nr_msir; i++) {
> > +		unsigned int virt_msir = irq_of_parse_and_map(node, i);
> > +		if (virt_msir != NO_IRQ) {
> > +			set_irq_data(virt_msir, msi);
> > +			set_irq_chained_handler(virt_msir, handler);
> > +			msi->msir[i] = virt_msir;
> > +		} else
> > +			msi->msir[i] = NO_IRQ;
> > +	}
> > +
> > +	rc = ipic_msi_init_allocator(msi);
> > +	if (rc)
> 		< missing of_node_put() ? >
> > +		goto out;
> > +
> > +	ipic_msi = msi;
> > +
> > +	WARN_ON(ppc_md.setup_msi_irqs);
> > +	ppc_md.setup_msi_irqs = ipic_msi_setup_irqs;
> > +	ppc_md.teardown_msi_irqs = ipic_msi_teardown_irqs;
> > +
> 	  return ?
> 

Sorry for that. It is a mistake.

> > +out:
> > +	if (mem_init_done)
> > +		kfree(msi);
> > +
> > +	return;
> > +}
> > +
> > +static int ipic_msi_get_irq(struct ipic_msi *msi, int virt_msir)
> > +{
> > +	int msir = -1;
> > +	unsigned int temp;
> > +	unsigned int offset;
> > +	int i;
> > +
> > +	for (i = 0; i < msi->nr_msir; i++)
> > +		if (virt_msir == msi->msir[i]) {
> > +			msir = i;
> > +			break;
> > +		}
> > +
> > +	if (i >= msi->nr_msir)
> > +		return NO_IRQ;
> > +
> > +	temp = ipic_msi_read(msi->regs, IPIC_MSIR0 + (i * 4));
> > +	offset = ffs(temp) - 1;
> > +
> > +	return irq_linear_revmap(msi->irqhost, (msir * msi->int_per_msir + offset));
> > +}
> > +
> > +void ipic_msi_cascade(unsigned int irq, struct irq_desc *desc)
> > +{
> > +	struct ipic_msi *msi;
> > +	unsigned int cascade_irq;
> > +
> > +	spin_lock(&desc->lock);
> > +	if (desc->chip->mask_ack)
> > +		desc->chip->mask_ack(irq);
> > +	else {
> > +		desc->chip->mask(irq);
> > +		desc->chip->ack(irq);
> > +	}
> > +
> > +	if (unlikely(desc->status & IRQ_INPROGRESS))
> > +		goto unlock;
> > +
> > +	desc->status |= IRQ_INPROGRESS;
> > +	msi = desc->handler_data;
> > +	cascade_irq = ipic_msi_get_irq(msi, irq);
> > +
> > +	spin_unlock(&desc->lock);
> > +
> > +	if (cascade_irq != NO_IRQ)
> > +		generic_handle_irq(cascade_irq);
> > +
> > +	spin_lock(&desc->lock);
> > +	desc->status &= ~IRQ_INPROGRESS;
> > +	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
> > +		desc->chip->unmask(irq);
> > +
> > +unlock:
> > +	spin_unlock(&desc->lock);
> > +}
> 
> I don't know your hardware, but this looks a bit weird. Doesn't the
> upstream handler do most of this logic for you?
> 

I just emulate the handle_level_irq to write this.
But I need get irq number from MSI controller (ipic_msi_get_irq) and
then call interrupt routine of that irq number.

- Tony

^ permalink raw reply

* Advice on how to add support for non-standard Ethernet PHY
From: michael.firth @ 2007-12-03  9:25 UTC (permalink / raw)
  To: linuxppc-embedded

We have a board that is using an Ethernet PHY where the registers are
accessed 'indirectly' - i.e. to read or write a given register you set a
value to one specific register, and read the results back from another
specific register.

Unfortunately, these two registers are the only ones implemented, which
means that the normal PHY detection code in Linux does not work, as the
ID registers are also indirect.

Does anyone have any advice on an elegant way of adding support for this
type of PHY, or should I just add a special case to the get_phy_device()
function?

Thanks

Michael

^ permalink raw reply

* Maximum ioremap size for ppc arch?
From: michael.firth @ 2007-12-03  9:22 UTC (permalink / raw)
  To: linuxppc-embedded

I'm trying to get am MPC834x system running that has 256MBytes of NOR
flash connected.

The physmap flash driver is failing to ioremap() that amount of space,
while on a similar system with 128Mbytes of flash, there are no
problems.

Is this a known limitation of ioremap() on the ppc architecture, or
specifically the MPC834x family, and is there any (hopefully easy) way
to increase this limit?

Thanks

Michael

^ permalink raw reply

* Re: Maximum ioremap size for ppc arch?
From: Arnd Bergmann @ 2007-12-03 10:20 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <36D7B34A3A79F84F82FA0C154F299F2505FE26D2@E03MVX1-UKDY.domain1.systemhost.net>

On Monday 03 December 2007, michael.firth@bt.com wrote:
> I'm trying to get am MPC834x system running that has 256MBytes of NOR
> flash connected.
> 
> The physmap flash driver is failing to ioremap() that amount of space,
> while on a similar system with 128Mbytes of flash, there are no
> problems.
> 
> Is this a known limitation of ioremap() on the ppc architecture, or
> specifically the MPC834x family, and is there any (hopefully easy) way
> to increase this limit?

The amount of ioremap space is very limited on 32bit systems in general,
since most people are more interested in having a large physical address
space without highmem. Look at the definition of VMALLOC_START and
VMALLOC_END if you want to change the settings on your system.

	Arnd <><

^ permalink raw reply

* [PATCH] ipic: change ack operation that register is accessed only when needed
From: Li Yang @ 2007-12-03 12:26 UTC (permalink / raw)
  To: galak, linuxppc-dev; +Cc: Li Yang

Only external interrupts in edge detect mode support ack operation.
Therefore, in most cases ack is not needed.  The patch makes ipic
ack only when it's needed.  This could boost over all system performance.

Signed-off-by: Li Yang <leoli@freescale.com>
---
Replaces patch:  [PATCH 7/9] ipic: clean up unsupported ack operations

 arch/powerpc/sysdev/ipic.c |  107 +++++++++++++++----------------------------
 arch/powerpc/sysdev/ipic.h |    3 +-
 2 files changed, 39 insertions(+), 71 deletions(-)

diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 7168b03..388fa59 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -34,7 +34,6 @@ static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
 	[1] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -42,7 +41,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[2] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -50,7 +48,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[4] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_C,
 		.force	= IPIC_SIFCR_H,
@@ -58,7 +55,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[9] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -66,7 +62,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[10] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -74,7 +69,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[11] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -82,7 +76,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[12] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -90,7 +83,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[13] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -98,7 +90,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[14] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -106,7 +97,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[15] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -114,7 +104,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[16] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -122,7 +111,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[17] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -130,7 +119,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[18] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -138,7 +127,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[19] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -146,7 +135,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[20] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -154,7 +143,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[21] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -162,7 +151,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[22] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -170,7 +159,7 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[23] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -178,7 +167,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[32] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -186,7 +174,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[33] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -194,7 +181,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[34] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -202,7 +188,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[35] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -210,7 +195,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[36] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -218,7 +202,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[37] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -226,7 +209,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[38] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -234,7 +216,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[39] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -242,7 +223,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[42] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -250,7 +230,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[44] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -258,7 +237,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[45] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -266,7 +244,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 5,
 	},
 	[46] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -274,7 +251,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 6,
 	},
 	[47] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_B,
 		.force	= IPIC_SIFCR_H,
@@ -282,7 +258,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 7,
 	},
 	[48] = {
-		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -290,7 +265,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 4,
 	},
 	[64] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -298,7 +272,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[65] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -306,7 +279,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[66] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -314,7 +286,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[67] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -322,7 +293,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[68] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -330,7 +300,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 0,
 	},
 	[69] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -338,7 +307,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 1,
 	},
 	[70] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -346,7 +314,6 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 2,
 	},
 	[71] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -354,133 +321,114 @@ static struct ipic_info ipic_info[] = {
 		.prio_mask = 3,
 	},
 	[72] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 8,
 	},
 	[73] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 9,
 	},
 	[74] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 10,
 	},
 	[75] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 11,
 	},
 	[76] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 12,
 	},
 	[77] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 13,
 	},
 	[78] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 14,
 	},
 	[79] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 15,
 	},
 	[80] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 16,
 	},
 	[81] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 17,
 	},
 	[82] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 18,
 	},
 	[84] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 20,
 	},
 	[85] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 21,
 	},
 	[86] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 22,
 	},
 	[87] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 23,
 	},
 	[88] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 24,
 	},
 	[89] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 25,
 	},
 	[90] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 26,
 	},
 	[91] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
@@ -534,23 +482,33 @@ static void ipic_mask_irq(unsigned int virq)
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
+	/* mb() can't guarantee that masking is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
+
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
 static void ipic_ack_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
 	unsigned int src = ipic_irq_to_hw(virq);
-	unsigned long flags;
-	u32 temp;
 
-	spin_lock_irqsave(&ipic_lock, flags);
+	/* Only external interrupts in edge mode support ACK */
+	if (unlikely(ipic_info[src].ack &&
+			((get_irq_desc(virq)->status & IRQ_TYPE_SENSE_MASK) ==
+			IRQ_TYPE_EDGE_FALLING))) {
+		struct ipic *ipic = ipic_from_irq(virq);
+		unsigned long flags;
+		u32 temp;
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
-	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+		spin_lock_irqsave(&ipic_lock, flags);
 
-	spin_unlock_irqrestore(&ipic_lock, flags);
+		temp = ipic_read(ipic->regs, ipic_info[src].ack);
+		temp |= (1 << (31 - ipic_info[src].bit));
+		ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+		spin_unlock_irqrestore(&ipic_lock, flags);
+	}
 }
 
 static void ipic_mask_irq_and_ack(unsigned int virq)
@@ -566,9 +524,18 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
-	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+	/* Only external interrupts in edge mode support ACK */
+	if (unlikely(ipic_info[src].ack &&
+			((get_irq_desc(virq)->status & IRQ_TYPE_SENSE_MASK) ==
+			IRQ_TYPE_EDGE_FALLING))) {
+		temp = ipic_read(ipic->regs, ipic_info[src].ack);
+		temp |= (1 << (31 - ipic_info[src].bit));
+		ipic_write(ipic->regs, ipic_info[src].ack, temp);
+	} else {
+		/* mb() can't guarantee that masking is finished.  But it does
+		 * finish for nearly all cases. */
+		mb();
+	}
 
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index 1158b8f..5c036e4 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -50,7 +50,8 @@ struct ipic {
 };
 
 struct ipic_info {
-	u8	pend;		/* pending register offset from base */
+	u8	ack;		/* pending register offset from base if the irq
+				   supports ack operation */
 	u8	mask;		/* mask register offset from base */
 	u8	prio;		/* priority register offset from base */
 	u8	force;		/* force register offset from base */
-- 
1.5.3.5.643.g40e25

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox