LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH ] powerpc: mpc7448hpc2 device tree source file
From: Zang Roy-r61911 @ 2006-08-25  8:43 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Yang Xin-Xin-r48390
In-Reply-To: <7EA18FDD2DC2154AA3BD6D2F22A62A0E19E353@zch01exm23.fsl.freescale.net>

This patch adds the mpc7448hpc2 device tree source file.

Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>


---
 arch/powerpc/boot/dts/mpc7448hpc2.dts |  190 +++++++++++++++++++++++++++++++++
 1 files changed, 190 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
new file mode 100644
index 0000000..d7b985e
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -0,0 +1,190 @@
+/*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at freescale.com>.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "mpc7448hpc2";
+	compatible = "mpc74xx";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells =<0>;
+		linux,phandle = <200>;
+				
+		PowerPC,7448@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K bytes
+			i-cache-size = <8000>;		// L1, 32K bytes
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			clock-frequency = <0>;		// From U-Boot
+			bus-frequency = <0>;		// From U-Boot
+			32-bit;
+			linux,phandle = <201>;
+			linux,boot-cpu;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 20000000	// DDR2   512M at 0
+		       >;
+	};
+
+  	tsi108@c0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "tsi-bridge";
+		ranges = <00000000 c0000000 00010000>;
+		reg = <c0000000 00010000>;
+		bus-frequency = <0>;
+
+		i2c@7000 {
+			interrupt-parent = <7400>;
+			interrupts = <E 0>;
+			reg = <7000 400>;
+			device_type = "i2c";
+			compatible  = "tsi-i2c";
+		};
+
+		mdio@6000 {
+			device_type = "mdio";
+			compatible = "tsi-ethernet";
+
+			ethernet-phy@6000 {
+				linux,phandle = <6000>;
+				interrupt-parent = <7400>;
+				interrupts = <2 1>;
+				reg = <6000 50>;
+				phy-id = <8>;
+				device_type = "ethernet-phy";
+			};
+
+			ethernet-phy@6400 {
+				linux,phandle = <6400>;
+				interrupt-parent = <7400>;
+				interrupts = <2 1>;
+				reg = <6000 50>;
+				phy-id = <9>;
+				device_type = "ethernet-phy";
+			};
+
+		};
+
+		ethernet@6200 {
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSI-ETH";
+			compatible = "tsi-ethernet";
+			reg = <6000 200>;
+			address = [ 00 06 D2 00 00 01 ];
+			interrupts = <10 2>;
+			interrupt-parent = <7400>;
+			phy-handle = <6000>;
+		};
+
+		ethernet@6600 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSI-ETH";
+			compatible = "tsi-ethernet";
+			reg = <6400 200>;
+			address = [ 00 06 D2 00 00 02 ];
+			interrupts = <11 2>;
+			interrupt-parent = <7400>;
+			phy-handle = <6400>;
+		};
+
+		serial@7808 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <7808 200>;
+			clock-frequency = <3f6b5a00>;
+			interrupts = <c 0>;
+			interrupt-parent = <7400>;
+		};
+
+		serial@7c08 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <7c08 200>;
+			clock-frequency = <3f6b5a00>;
+			interrupts = <d 0>;
+			interrupt-parent = <7400>;
+		};
+
+	  	pic@7400 {
+			linux,phandle = <7400>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <7400 400>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                       	big-endian;
+		};
+		pci@1000 {
+			compatible = "tsi10x";
+			device_type = "pci";
+			linux,phandle = <1000>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <1000 1000>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 e0000000 e0000000 0 1A000000	
+				  01000000 0 00000000 fa000000 0 00010000>;
+			clock-frequency = <7f28154>;
+			interrupt-parent = <7400>;
+			interrupts = <17 2>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x11 */
+				0800 0 0 1 7400 24 0
+				0800 0 0 2 7400 25 0
+				0800 0 0 3 7400 26 0
+				0800 0 0 4 7400 27 0
+
+				/* IDSEL 0x12 */
+				1000 0 0 1 7400 25 0
+				1000 0 0 2 7400 26 0
+				1000 0 0 3 7400 27 0
+				1000 0 0 4 7400 24 0
+
+				/* IDSEL 0x13 */
+				1800 0 0 1 7400 26 0
+				1800 0 0 2 7400 27 0
+				1800 0 0 3 7400 24 0
+				1800 0 0 4 7400 25 0
+
+				/* IDSEL 0x14 */
+				2000 0 0 1 7400 27 0
+				2000 0 0 2 7400 24 0
+				2000 0 0 3 7400 25 0
+				2000 0 0 4 7400 26 0
+				>;
+		};
+	};
+
+};
-- 
1.4.0

^ permalink raw reply related

* pci_id_table and mid_idsel?
From: Parav Pandit @ 2006-08-25  8:56 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hi,
   
  Can someone please explain me pci_irq_table and how to select the value of min_idsel , max_idsel for my 85xx boards?
   
  I am facing issues in registering the interrupt handler.
   
  On what basis we have to select the min_idsel and max_idsel value??
   
  Currently common_swizzle function retuns slot number 11, if I hard-code the value of 11 in the min_idsel and max_idsel because I have only one slot, I am able to register the interrupt handler.
   
  PCI_SLOT in common_swizzle returns 11 because device function number (devfn) has value of 88  ( I am wondering why 88 instead of from 0-7).
  (( 88>> 8) && 0x1f) = 11
   
  Since max functions we can have 8. (0-7). Why OS assign the value of 88 inside?
  Configuration transaction uses only 3 bits of function number in the CONFIG_ADDRESS as per PCI local bus specification 2.2.
   
  Regards,
  Parav Pandit
   

 		
---------------------------------
 All-new Yahoo! Mail - Fire up a more powerful email and get things done faster.

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

^ permalink raw reply

* RE: pci_id_table and mid_idsel?
From: Liu Dave-r63238 @ 2006-08-25  8:59 UTC (permalink / raw)
  To: Parav Pandit, linuxppc-embedded
In-Reply-To: <20060825085643.47078.qmail@web36606.mail.mud.yahoo.com>

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

Parav,
 
Please self study the existing source code. It can help you.
 
-DAve


________________________________

	From: linuxppc-embedded-bounces+daveliu=freescale.com@ozlabs.org
[mailto:linuxppc-embedded-bounces+daveliu=freescale.com@ozlabs.org] On
Behalf Of Parav Pandit
	Sent: Friday, August 25, 2006 4:57 PM
	To: linuxppc-embedded@ozlabs.org
	Subject: pci_id_table and mid_idsel?
	
	
	Hi,
	 
	Can someone please explain me pci_irq_table and how to select
the value of min_idsel , max_idsel for my 85xx boards?
	 
	I am facing issues in registering the interrupt handler.
	 
	On what basis we have to select the min_idsel and max_idsel
value??
	 
	Currently common_swizzle function retuns slot number 11, if I
hard-code the value of 11 in the min_idsel and max_idsel because I have
only one slot, I am able to register the interrupt handler.
	 
	PCI_SLOT in common_swizzle returns 11 because device function
number (devfn) has value of 88  ( I am wondering why 88 instead of from
0-7).
	(( 88>> 8) && 0x1f) = 11
	 
	Since max functions we can have 8. (0-7). Why OS assign the
value of 88 inside?
	Configuration transaction uses only 3 bits of function number in
the CONFIG_ADDRESS as per PCI local bus specification 2.2.
	 
	Regards,
	Parav Pandit
	 

	
________________________________

	All-new Yahoo! Mail
<http://us.rd.yahoo.com/evt=43256/*http://advision.webevents.yahoo.com/m
ailbeta> - Fire up a more powerful email and get things done faster.


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

^ permalink raw reply

* When mounting using USB-CDROM, segment fault is called and system hangon
From: "gjkwon(권기준)" @ 2006-08-25  9:12 UTC (permalink / raw)
  To: linuxppc-dev

Hello.
I am KiJun Kwon who lives in South Korea. 
Nice to meet your group. Now, I really want to fix the bellow problem. ^^ 


Most recent kernel where this bug did not occur: 
For 2.6.15, 2.6.17, it is occurred 

Hardware Environment: bamboo board(PPC440EP Rev.B)

Software Environment: debian

Problem Description:
To read the files in the cdrom, I used USB-CDROM device(it is not specific to 
a vendor, model). When I try to mount, below dmesg is printed and system is 
hangon or segmentation fault is called. 

juno-nfs:~# mount -o ro -t iso9660 /dev/sr0 /mnt
Oops: kernel access of bad area, sig: 11 [#1]
NIP: 7C0802A4 LR: D101CB7C CTR: 7C0802A6
REGS: cb747990 TRAP: 0400   Not tainted  (2.6.17)
MSR: 00029000 <EE,ME>  CR: 22002428  XER: 00000000
TASK = cbe2e830[377] 'mount' THREAD: cb746000
GPR00: 7C0802A6 CB747A40 CBE2E830 C062E1F8 00000000 CB747A00 00000000 C027E130
GPR08: CB646B3C 0000000C C02FA100 C04BC02C 0000825F 1002A544 10024B18 10024AE8
GPR16: 10024AC8 00000000 00000000 10024AB8 00000000 10020000 00000000 10024AF8
GPR24: C04AFC08 CB747A58 CB747CB8 D1020000 D102A144 00000000 D1020000 C062E1F8
NIP [7C0802A4] 0x7c0802a4
LR [D101CB7C] cdrom_open+0x3a0/0xad8 [cdrom]
Call Trace:
[CB747A40] [D101CB18] cdrom_open+0x33c/0xad8 [cdrom] (unreliable)
[CB747BD0] [D1029DF0] sr_block_open+0x8c/0xd8 [sr_mod]
[CB747BF0] [C0060444] do_open+0x94/0x398
[CB747C30] [C0060840] blkdev_get+0x64/0x78
[CB747D70] [C00608A4] open_bdev_excl+0x50/0xd8
[CB747D90] [C005F1F4] get_sb_bdev+0x30/0x188
[CB747DE0] [C00E4B08] isofs_get_sb+0x18/0x28
[CB747DF0] [C005E60C] do_kern_mount+0x58/0x10c
[CB747E10] [C007701C] do_mount+0x254/0x704
[CB747F10] [C007755C] sys_mount+0x90/0xe4
[CB747F40] [C0001C88] ret_from_syscall+0x0/0x3c
Instruction dump:
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Segmentation fault



After this error, when I try to remount, system is freezed without any mesg.
But, for a IDE-CDROM device, it works fine. 
For x86 cpu, same kernel version, configuration, it wasn't happened. So, it 
seems that ppc32-usb cdrom combination has a bug. 


kkj-nfs:~# lsmod
Module                  Size  Used by
sg                     32768  0
sr_mod                 15684  0
cdrom                  45180  1 sr_mod
ehci_hcd               46760  0
ohci_hcd               30628  0
usb_storage            38276  0
 
kkj-nfs:~# lspci -v
0000:00:04.0 USB Controller: NEC Corporation USB (rev 43) (prog-if 10 [OHCI])
        Subsystem: NEC Corporation USB
        Flags: bus master, medium devsel, latency 128, IRQ 25
        Memory at cffff000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [40] Power Management version 2

0000:00:04.1 USB Controller: NEC Corporation USB (rev 43) (prog-if 10 [OHCI])
        Subsystem: NEC Corporation USB
        Flags: bus master, medium devsel, latency 128, IRQ 25
        Memory at cfffe000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [40] Power Management version 2

0000:00:04.2 USB Controller: NEC Corporation USB 2.0 (rev 04) (prog-if 20 
[EHCI]
)
        Subsystem: NEC Corporation USB 2.0
        Flags: bus master, medium devsel, latency 128, IRQ 25
        Memory at cfffdf00 (32-bit, non-prefetchable) [size=256]
        Capabilities: [40] Power Management version 2

kkj-nfs:~# cat /proc/scsi/scsi
Attached devices:
Host: scsi1 Channel: 00 Id: 00 Lun: 00
  Vendor: IOMEGA   Model: CDRW9602EXT-B    Rev: 8OS4
  Type:   CD-ROM                           ANSI SCSI revision: 02


USB-CDROM model, vendor doesn't matter.
 
Board is booted with nfs.


Steps to reproduce:
1. Attach USB-CDROM(non-empty iso9660 formatted file cd exist) to usb jack of 
board.
2. Power On
3. insert some modules - sr_mod, sg, usb-storage, ohci_hcd, ehci_hcd
4. mount -o ro -t iso9660 /dev/sr0 /media
5. segmentation fault is called

^ permalink raw reply

* Re: [PATCH] powerpc: emulate power5 popcntb instruction
From: Gabriel Paubert @ 2006-08-25  9:59 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras, segher, arnd
In-Reply-To: <9FF8F72E-5990-4AED-A826-9E1C9C889DB6@kernel.crashing.org>

On Thu, Aug 24, 2006 at 05:53:56PM +0200, Segher Boessenkool wrote:
> > Also it would be really nice if you could figure out a way to
> > avoid doing the unnecessary 64-bit logical operations on 32-bit
> > machines
> 
> Like I asked before -- should we run this emulation on 32-bit
> machines at all?  The instruction only exists in the 64-bit
> architecture after all.

It's useless for now, but I would not be surprised if someone 
creates a new 32 bit processor which includes this instruction.

	Gabriel

^ permalink raw reply

* IBM eHEA Device Driver upstream inclusion
From: Jan-Bernd Themann @ 2006-08-25 10:36 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel, linux-ppc,
	Christoph Raisch, Marcus Eder

Hi Jeff,

the IBM eHEA Device Driver has been discussed on the netdev, linux-ppc and 
kernel mailing list for some time. The latest patch set we posted can be
found at:

http://www.spinics.net/lists/netdev/msg12820.html

As the discussion seems to have settled, please consider our driver for
upstream inclusion.

Thanks,

Jan-Bernd Themann & Christoph Raisch

^ permalink raw reply

* m8260_cpm_dpalloc -> m8260_cpm_dpfree ?
From: Keinen Namen @ 2006-08-25 12:19 UTC (permalink / raw)
  To: linuxppc-embedded

Hi

Simple Question, I allocate Memory for my BDs with m8260_cpm_dpalloc, but there are no dpfree in Linux 2.4.25. In Linux 2.6 are a funktion to free dp memory.

Are there no funktion in Linux 2.4 ? 

Regards
Fred
-- 


Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer

^ permalink raw reply

* How to boot powerPC linux-2.6.10 from diifferent address other than 0x0000
From: Reddy Suneel-ASR125 @ 2006-08-25 12:45 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hi,
    We are working on MPC 8540, Linux kernel version is 2.6.10 from
Montavista. The bootloader used in Uboot and currently it loads the
uImage at physical memory address 0x0 and transfers control to it. We
want to load the kernel at a different address say 0x8000 and for this
we made the following changes.
 
1) Altered the Makefile to linked the kernel at virtual address
0xc0008000 ( the default was 0xc000:0000)
2) Modified Uboot to load kernel at 0x8000 instead of 0x0
The kernel space still starts from 0xc000:0000

 
When we transferred control to the kernel (loaded at 0x8000) we found
that the execution proceeds only till the mapping and invalidation on
TLBs. We do not know where the control goes after this as the further
instructions does not seems to get executed. Currently we do not have
the provision to connect a debugger and hence we are unable to make out
what is happening.
 
Can some one give us any clue as to what we might have done wrong? This
is our first experience on PowerPC.
 
 
Thanks&regards
Suneel

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

^ permalink raw reply

* Re: [PATCH] powerpc: emulate power5 popcntb instruction
From: Paul Mackerras @ 2006-08-25 12:57 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, arnd, segher
In-Reply-To: <9FF8F72E-5990-4AED-A826-9E1C9C889DB6@kernel.crashing.org>

Segher Boessenkool writes:

> Like I asked before -- should we run this emulation on 32-bit
> machines at all?  The instruction only exists in the 64-bit
> architecture after all.

It could be argued either way, but on the whole I would prefer to
minimize the number of things which could cause a 32-bit program that
runs quite happily on a 64-bit CPU to fail on a 32-bit CPU...

Paul.

^ permalink raw reply

* GPIO Control Driver
From: Gabe.Johnson @ 2006-08-25 13:47 UTC (permalink / raw)
  To: linuxppc-embedded

I am working on a PowerQuickIII processor that has a GPIO port, port C. 
Connect to this port are buffer enables for various devices on the 
product.  I am trying to write a driver to control certain GPIO lines. Any 
suggestions on the best way to implement this?  Currently I have created a 
module that creates character devices but I am now feeling it would have 
been better to create sysfs entries.  Looking at the structs from the 
Linux device model bus_type, device_driver, and device I am having 
troubles determining what needs to be declared?  What I think I would like 
to create in sysfs is:

/sys/module/<MODULE NAME>/rtm_enable
                                 /rtm_reset
                                 /clk1a_enable
                                 /clk1b_enable
                                 /clk2a_enable
                                 /clk2b_enable

^ permalink raw reply

* Re: m8260_cpm_dpalloc -> m8260_cpm_dpfree ?
From: Alex Zeffertt @ 2006-08-25 14:34 UTC (permalink / raw)
  To: Keinen Namen; +Cc: linuxppc-embedded
In-Reply-To: <20060825121947.88490@gmx.net>

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

Keinen Namen wrote:
> Hi
> 
> Simple Question, I allocate Memory for my BDs with m8260_cpm_dpalloc, but there are no dpfree in Linux 2.4.25. In Linux 2.6 are a funktion to free dp memory.
> 
> Are there no funktion in Linux 2.4 ? 
> 

I've implemented the free function for my own benefit.  See attached patch
which should work against ELDK 3.1

Alex


[-- Attachment #2: patch-2006-08-25-m8260_cpm_dpfree --]
[-- Type: text/plain, Size: 7592 bytes --]

Index: commproc.c
===================================================================
RCS file: /newcvs/pq2-linux/kernel/arch/ppc/8260_io/commproc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- commproc.c	24 Aug 2005 12:05:13 -0000	1.1.1.1
+++ commproc.c	11 May 2006 13:14:31 -0000	1.3
@@ -29,12 +29,264 @@
 #include <asm/immap_8260.h>
 #include <asm/cpm_8260.h>
 
+#define DPFREE
+
+#ifdef DPFREE
+typedef struct	cpm_dpalloc_entry_s {
+	u_short				start_addr;
+    u_short             retloc;    /* This is start_addr + alignment offset: only valid in alloc list */
+	u_short				size;
+	struct	cpm_dpalloc_entry_s *	next_entr;
+} cpm_dpalloc_entry_t;
+
+static	void	cpm_dpalloc_init(void);
+static	void	cpm_dpalloc_data_init(cpm_dpalloc_entry_t  *);
+static	int	    cpm_dpalloc_cl(cpm_dpalloc_entry_t *);
+static	int  	cpm_dpalloc_rem(cpm_dpalloc_entry_t **, cpm_dpalloc_entry_t *);
+static	void	cpm_dpalloc_ins(cpm_dpalloc_entry_t **, cpm_dpalloc_entry_t *);
+# define CPM_DPALLOC_COUNT (CPM_DATAONLY_SIZE / sizeof(cbd_t) + 1)  
+/* Dynamic lists of allocated and free DPRAM */
+static	cpm_dpalloc_entry_t  *cpm_dpalloc_free;
+static	cpm_dpalloc_entry_t  *cpm_dpalloc_alloc;
+static	cpm_dpalloc_entry_t	cpm_dpalloc_list[CPM_DPALLOC_COUNT];
+#else
 static	uint	dp_alloc_base;	/* Starting offset in DP ram */
 static	uint	dp_alloc_top;	/* Max offset + 1 */
+#endif
 static	uint	host_buffer;	/* One page of host buffer */
 static	uint	host_end;	/* end + 1 */
 cpm8260_t	*cpmp;		/* Pointer to comm processor space */
 
+#ifdef DPFREE
+/* Initialize dynamic lists
+ */
+static void cpm_dpalloc_init(void)
+{
+	int i;
+
+	cpm_dpalloc_free = cpm_dpalloc_list;
+	cpm_dpalloc_free->start_addr = CPM_DATAONLY_BASE;
+	cpm_dpalloc_free->size = CPM_DATAONLY_SIZE;
+	cpm_dpalloc_free->next_entr = NULL;
+	cpm_dpalloc_alloc = NULL;
+
+	for(i = 1; i <= CPM_DPALLOC_COUNT; i++) {
+		cpm_dpalloc_data_init (cpm_dpalloc_list + i);
+	}
+}
+
+/* Initialize element in list of DPRAM
+ */
+static void cpm_dpalloc_data_init(cpm_dpalloc_entry_t * ptr)
+{
+	ptr->retloc = ptr->start_addr = 0;
+	ptr->size = 0;
+	ptr->next_entr = NULL;
+}
+
+static int cpm_dpalloc_cl(cpm_dpalloc_entry_t * head)
+{
+	cpm_dpalloc_entry_t	* curr;
+	cpm_dpalloc_entry_t	* next;
+	int			  retloc;
+
+	curr = head;
+	retloc = -1;
+
+	if (curr) {
+		retloc = 0;
+
+		while ((next = curr->next_entr)) {
+			if (curr->start_addr + curr->size == next->start_addr) {
+				curr->size = curr->size + next->size;
+				curr->next_entr = next->next_entr;
+				cpm_dpalloc_data_init(next);
+			} else {
+				curr = next;
+			}
+		 }
+	}
+
+	return retloc;
+}
+
+/* Remove element from dynamic list of DPRAM
+ */
+static int cpm_dpalloc_rem(cpm_dpalloc_entry_t ** head, cpm_dpalloc_entry_t * ptr)
+{
+	cpm_dpalloc_entry_t	* prev;
+	cpm_dpalloc_entry_t	* curr;
+	int			  retloc;
+
+	retloc = -1;
+	for (prev = NULL , curr = *head;
+	     curr != NULL && ptr != curr;
+	     prev = curr , curr = curr->next_entr)
+		/* EMPTY */ ;
+
+	if (curr) {
+		if (prev) {
+			prev->next_entr = curr->next_entr;
+		} else {
+			*head = curr->next_entr;
+		}
+		retloc = 0;
+	}
+
+	return retloc;
+}
+
+/* Insert element in dynamic list of DPRAM
+ */
+static void cpm_dpalloc_ins(cpm_dpalloc_entry_t ** head, cpm_dpalloc_entry_t * ptr)
+{
+	cpm_dpalloc_entry_t	* prev;
+	cpm_dpalloc_entry_t	* curr;
+
+	for (prev = NULL , curr = *head;
+	     curr != NULL && ptr->start_addr >= curr->start_addr;
+	     prev = curr , curr = curr->next_entr)
+		/* EMPTY */ ;
+
+	ptr->next_entr = curr;
+
+	if (prev) {
+		prev->next_entr = ptr;
+	} else {
+		*head = ptr;
+	}
+}
+/* Allocate some memory from the dual ported ram.  We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint m8260_cpm_dpalloc(uint size, uint align)
+{
+    cpm_dpalloc_entry_t   * new_el;
+    cpm_dpalloc_entry_t   * p;
+    cpm_dpalloc_entry_t   * p1;
+    uint			retloc;
+    u_short			max;
+    unsigned long		flags;
+    int			i;
+    uint align_mask;
+    uint off;
+
+    size = (size + 7) & ~7;
+    align_mask = align - 1;
+    max = CPM_DATAONLY_SIZE;
+    retloc = CPM_DP_NOSPACE;
+    new_el = NULL;
+
+    if (size == 0) goto DONE;
+
+    save_flags(flags);
+    cli();
+
+    /* Find free area in DPRAM
+     */
+    for (p = cpm_dpalloc_free; p != NULL; p = p->next_entr) {
+        if (p->size <= max) {
+            off = ((p->start_addr + align_mask) & (~align_mask)) - p->start_addr;
+            if (p->size >= size + off) {
+                new_el = p;
+                max = p->size;
+                retloc = p->start_addr + off;
+            }
+        }
+    }
+
+    if (new_el == NULL) goto DONE1;
+
+    /* Insert new element in the list of allocated DPRAM
+     */
+    p1 = cpm_dpalloc_list;
+    p = NULL;
+    i = 0;
+    while (i < CPM_DPALLOC_COUNT) {
+        if (p1->start_addr == 0 && !p1->size && !p1->next_entr) {
+            p = p1;
+            break;
+        }
+        i ++;
+        p1 ++;
+    }
+
+    if (p == NULL) {
+        panic ("m8xx_cpm_dpalloc: INTERNAL ERROR\n");
+    }
+
+    off = retloc - new_el->start_addr;
+
+    p->start_addr = new_el->start_addr;
+    p->retloc = retloc;
+    p->size = size + off;
+
+    if (new_el->size >  (size+off)) {
+        new_el->size -= (size+off);
+        new_el->start_addr += (size+off);
+        cpm_dpalloc_ins(&cpm_dpalloc_alloc, p);
+    } else {
+        cpm_dpalloc_ins(&cpm_dpalloc_alloc, p);
+        i = cpm_dpalloc_rem(&cpm_dpalloc_free, new_el);
+
+        if ( i == -1) {
+            panic ("m8xx_cpm_dpalloc: INTERNAL ERROR\n");
+        }
+
+        cpm_dpalloc_data_init(new_el);
+    }
+
+ DONE1:
+    restore_flags(flags);
+ DONE:
+    return retloc;
+}
+
+int m8260_cpm_dpfree(uint retloc)
+{
+	cpm_dpalloc_entry_t   * r;
+	int			retval;
+	unsigned long		flags;
+
+	retval = -1;
+
+	if ((retloc < CPM_DATAONLY_BASE) ||
+	    (retloc > CPM_DATAONLY_SIZE + CPM_DATAONLY_BASE)) {
+		goto DONE;
+	}
+
+	save_flags(flags);
+	cli();
+
+	for (r = cpm_dpalloc_alloc;
+	     (r != NULL) && (r->retloc != retloc);
+	     r = r->next_entr)
+		/* EMPTY */ ;
+
+	if (r) {
+		retval = cpm_dpalloc_rem(&cpm_dpalloc_alloc, r);
+
+		if (retval == -1) {
+			panic("m8xx_cpm_dpfree: INTERNAL ERROR\n");
+		}
+		cpm_dpalloc_ins(&cpm_dpalloc_free, r);
+		retval = cpm_dpalloc_cl(cpm_dpalloc_free);
+
+		if (retval == -1) {
+			panic("m8xx_cpm_dpfree: INTERNAL ERROR\n");
+		}
+		retval = 0;
+	} else {
+	  printk(KERN_ERR "m8xx_cpm_dpfree: address not found in alloc list\n");
+	}
+
+	restore_flags(flags);
+DONE:
+	return retval;
+}
+#endif /* DPFREE */
+
 /* We allocate this here because it is used almost exclusively for
  * the communication processor devices.
  */
@@ -50,11 +302,14 @@
 	immr = imp = (volatile immap_t *)IMAP_ADDR;
 	commproc = &imp->im_cpm;
 
+#ifdef DPFREE
+	cpm_dpalloc_init();
+#else
 	/* Reclaim the DP memory for our use.
 	*/
 	dp_alloc_base = CPM_DATAONLY_BASE;
 	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
-
+#endif
 	/* Set the host page for allocation.
 	*/
 	host_buffer =
@@ -68,6 +323,7 @@
 	cpmp = (cpm8260_t *)commproc;
 }
 
+#ifndef DPFREE
 /* Allocate some memory from the dual ported ram.
  * To help protocols with object alignment restrictions, we do that
  * if they ask.
@@ -95,6 +351,12 @@
 
 	return(retloc);
 }
+int m8260_cpm_dpfree(uint start_addr)
+{
+    printk(KERN_ERR "%s() not implemented\n", __FUNCTION__);
+    return -1;
+}
+#endif /*ifndef DPFREE*/
 
 /* We also own one page of host buffer space for the allocation of
  * UART "fifos" and the like.

^ permalink raw reply

* Fwd: When mounting using USB-CDROM, segment fault is called and system hangon
From: Milton Miller @ 2006-08-25 14:39 UTC (permalink / raw)
  To: KiJun Kwon, linuxppc-dev

Ooops sent to -request somehow.

Begin forwarded message:

> From: Milton Miller <miltonm@bga.com>
> Date: August 25, 2006 8:55:54 AM CDT
> To: KiJun Kwon <gjkwon@idis.co.kr>
> Cc: linuxppc-dev-request@ozlabs.org
> Subject: Re: When mounting using USB-CDROM,  segment fault is called 
> and system hangon
>
> On Fri Aug 25 19:12:18 EST 2006, KiJun Kwon wrote:
>> Most recent kernel where this bug did not occur:
>> For 2.6.15, 2.6.17, it is occurred
>>
>> Hardware Environment: bamboo board(PPC440EP Rev.B)
>>
>> Software Environment: debian
>>
>> Problem Description:
>> To read the files in the cdrom, I used USB-CDROM device(it is not 
>> specific to
>> a vendor, model). When I try to mount, below dmesg is printed and 
>> system is
>> hangon or segmentation fault is called.
>>
>> juno-nfs:~# mount -o ro -t iso9660 /dev/sr0 /mnt
>> Oops: kernel access of bad area, sig: 11 [#1]
>> NIP: 7C0802A4 LR: D101CB7C CTR: 7C0802A6
>> REGS: cb747990 TRAP: 0400   Not tainted  (2.6.17)
>> MSR: 00029000 <EE,ME>  CR: 22002428  XER: 00000000
>> TASK = cbe2e830[377] 'mount' THREAD: cb746000
>> GPR00: 7C0802A6 CB747A40 CBE2E830 C062E1F8 00000000 CB747A00 00000000 
>> C027E130
>> GPR08: CB646B3C 0000000C C02FA100 C04BC02C 0000825F 1002A544 10024B18 
>> 10024AE8
>> GPR16: 10024AC8 00000000 00000000 10024AB8 00000000 10020000 00000000 
>> 10024AF8
>> GPR24: C04AFC08 CB747A58 CB747CB8 D1020000 D102A144 00000000 D1020000 
>> C062E1F8
>> NIP [7C0802A4] 0x7c0802a4
>> LR [D101CB7C] cdrom_open+0x3a0/0xad8 [cdrom]
>> Call Trace:
>> [CB747A40] [D101CB18] cdrom_open+0x33c/0xad8 [cdrom] (unreliable)
>> [CB747BD0] [D1029DF0] sr_block_open+0x8c/0xd8 [sr_mod]
>> [CB747BF0] [C0060444] do_open+0x94/0x398
>> [CB747C30] [C0060840] blkdev_get+0x64/0x78
>> [CB747D70] [C00608A4] open_bdev_excl+0x50/0xd8
>> [CB747D90] [C005F1F4] get_sb_bdev+0x30/0x188
>> [CB747DE0] [C00E4B08] isofs_get_sb+0x18/0x28
>> [CB747DF0] [C005E60C] do_kern_mount+0x58/0x10c
>> [CB747E10] [C007701C] do_mount+0x254/0x704
>> [CB747F10] [C007755C] sys_mount+0x90/0xe4
>> [CB747F40] [C0001C88] ret_from_syscall+0x0/0x3c
>> Instruction dump:
>> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX 
>> XXXXXXXX
>> XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX 
>> XXXXXXXX
>> Segmentation fault
>>
>
> Your system tried to execute an instruction at an invalid address (trap
> 400).  The NIA is the same as the CTR (truncating the bottom 2 bits), 
> so
> it was probably from following a function pointer in C.  The address in
> the CTR (counter) register is the opcode for "mflr r0", which is the
> first instruction in just about every non-leaf function.
>
> It appears that someone dereferenced a function pointer before 
> assigning
> it.  The stack trace shows it was called about 30 % of the way in
> cdrom_open, which was called from  called from sr_block_open.  That
> should give you a good indication what structure contains the bad
> pointer.
>
>> After this error, when I try to remount, system is freezed without 
>> any mesg.
>
> The oops means the kernel terminated this thread of execution without
> cleaning up the locks.  The new attempt encounters a locked resource
> and waits for it to be unlocked, which will not happen because of
> the first bug.
>
>
> milton
>

^ permalink raw reply

* Re: [PATCH] powerpc: Improve IRQ radix tree locking
From: Milton Miller @ 2006-08-25 14:42 UTC (permalink / raw)
  To: linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras, Anton Blanchard

On Fri Aug 25 16:04:52 EST 2006,  Benjamin Herrenschmidt wrote:
> When reworking the powerpc irq code, I figured out that we were using
> the radix tree in a racy way. As a temporary fix, I put a spinlock in
> there. However, this can have a significant impact on performances. 
> This
> patch reworks that to use a smarter technique based on the fact that
> what we need is in fact a rwlock with extremely rare writers (thus
> optimized for the read path).


> +static void irq_radix_wrlock(unsigned long *flags)
> +{
> +       unsigned int cpu, ok;
> +
> +       spin_lock_irqsave(&irq_big_lock, *flags);
> +       irq_radix_writer = 1;

I think the smp_mb() is needed after here

> +       do {
> +               ok = 1;
> +               smp_mb();

but not every time we poll the cpus.  We are only
updating our local variable ok which we have not
given anyone else.   It could even be a register.


> +               for_each_possible_cpu(cpu) {
> +                       if (per_cpu(irq_radix_reader, cpu)) {
> +                               ok = 0;
> +                               break;
> +                       }
> +               }
> +               if (!ok)
> +                       cpu_relax();

Hmmm.  the gcc barrier is conditional.   How about putting
barrier() before the ok=1 at the top, to avoid any optimization
blockage but still telling gcc you must read every time?

> +       } while(!ok);
> +}
> +

Oh, and how about some (un)likely in irq_radix_rdlock ?  It
could happen by default by why not show our expected path?


And, while I'm thinking of changes, when set ok=0 above add:
#ifdef CONFIG_SPINLOCK_DEBUG
                               BUG_ON(cpu == smp_processor_id());
#endif


Hmm... just thought of something .... we are spinning under
irq lock.  We are waiting on some other thread, but not
telling the hypervisor.   Should we confer our execution
over to the cpu we are waiting on?  I know, it sounds ugly
to call that code.   I guess we would want a
cpu_waiting_on(cpu) that calls cpu_relax and/or hypervisor.

milton

^ permalink raw reply

* RE: Cache coherency question
From: Martin, Tim @ 2006-08-25 16:05 UTC (permalink / raw)
  To: Liu Dave-r63238, ppc

>=20
> Tim> I'm using an MVME6100 with Linux 2.6.14 and experiencing what I=20
> Tim> think is a cache coherency problem.  An external PCIX master=20
> Tim> performs a DMA transfer of a well known data pattern into SDRAM,=20
> Tim> but when the device driver goes to look at the data it is mostly=20
> Tim> okay, but occasionally has garbage.
>=20
> If the hardware is reliable, I think you are right. The cache=20
> coherency problem.

The hardware is reliable.

>=20
> Tim> 1) Should the processor bus cache snooping actually work on an=20
> Tim> MVME6100?
> Tim> E.g. is it correct that CONFIG_NOT_COHERENT_CACHE is undefined?
>=20
> Yes, you can undefine the CONFIG_NOT_COHERENT_CACHE, but you=20
> must make sure the host bridge did the snooping setup for PCI=20
> inbound transaction.
> If you setup the snooping window, I think the host bridge=20
> will assert /GLB signal to processor. The processor will=20
> snoop the 60x/MPX bus to keep cache coherence.
>=20

Ah.  This must be the problem.  I have a few PCI devices, and on one of
them it looked like snooping was working.  I just assumed the other
device was setup correctly.

> Also, you can define the CONFIG_NOT_COHERENT_CACHE, then you=20
> are assuming The system has not hardware coherency. You need=20
> use the software to keep the cache coherency.
>=20

I tried this, and got compiler errors.

>=20
> Tim> 2) If this really is a cache coherency problem, are there other=20
> Tim> cache management functions available in ppc linux besides the=20
> Tim> dma_cache_inv, dma_cache_wback, dma_cache_wback_inv=20
> macros I should=20
> Tim> be looking at?
>=20
> I think it is a cache coherency problem, if you define the=20
> CONFIG_NOT_COHERENT_CACHE You can get these functions, dma_map_single
>=20

I added some inline assembly dcbi/dcbf (invalidate/flush) instructions
to the particular code in question, and the problems went away.  So
definitely a cache problem.  As I said above, defining
CONFIG_NOT_COHERENT_CACHE causes compiler errors, so I'm going to look
into this more.  I suppose whatever file implements the
include/linux/dma-mapping.h stuff isn't BSP specific, so its probably
just not being compiled in?  Will look into it.

Thanks for you help,
Tim

^ permalink raw reply

* Re: MPC8555 PCI interrupts are not coming
From: Andy Fleming @ 2006-08-25 16:08 UTC (permalink / raw)
  To: Parav Pandit; +Cc: linuxppc-embedded
In-Reply-To: <20060824125206.18305.qmail@web36612.mail.mud.yahoo.com>


On Aug 24, 2006, at 07:52, Parav Pandit wrote:

> Hi,
>
> Can someone give light on PCI interrupts routing to the OS from the  
> openPIC?


The routing depends on your board.  On the CDS board, PCI interrupts  
are mapped to ext[0-3].  On the ADS, they are mapped to ext[1-4].   
There are four PCI interrupts (A,B,C,D), and they are usually  
swizzled so that different slots have a different mapping (this way,  
two cards in different slots which use interrupt A don't conflict).


>
> Basically I am able to talk to PCI end device connected on MPC8555  
> board in 2.6.13 but not getting interrupts reported by my device.
>
> When I read the INTERRUPT_LINE byte, it comes as 0. pdev->irq is  
> also reporting 0.
> Due to that request_irq() fails. But now I request for IRQ line 8 +  
> openPIC offset.
> Handler gets registered but still not getting the interrupts. (PCI  
> interrupt line is 8,9 in case of MPC8555).


When are you trying to read the interrupt_line byte?  In 2.6.13, you  
need to have an IRQ mapping function, which takes the idsel reported  
by the slot, and converts it to the interrupt number for the PIC.   
That code also writes the INTERRUPT_LINE byte.


>
> Can anyone please guide me, what are the different things need be  
> configure in the platform code to receive the PCI interrupts in the  
> driver?
>
> I don't understand the pci_irq_table, and what it should represent?
> Currrently no one is writing the INTERRUPT LINE value in the config  
> space.
> In which function I should configure that value? pcibios_fixup??
>
> Regards,
> Parav Pandit
>
>
> Do you Yahoo!?
> Get on board. You're invited to try the new Yahoo! Mail.
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: m8260_cpm_dpalloc -> m8260_cpm_dpfree ?
From: Alex Zeffertt @ 2006-08-25 14:37 UTC (permalink / raw)
  To: Alex Zeffertt; +Cc: Keinen Namen, linuxppc-embedded
In-Reply-To: <44EF0A61.3050205@cambridgebroadband.com>

Alex Zeffertt wrote:
> Keinen Namen wrote:
>> Hi
>>
>> Simple Question, I allocate Memory for my BDs with m8260_cpm_dpalloc, 
>> but there are no dpfree in Linux 2.4.25. In Linux 2.6 are a funktion 
>> to free dp memory.
>>
>> Are there no funktion in Linux 2.4 ?
> 
> I've implemented the free function for my own benefit.  See attached patch
> which should work against ELDK 3.1
> 

On the other hand I may have just ported it from somewhere else.  I can't remember
now, but anyway it works for me.

Alex

^ permalink raw reply

* Re: CompactFlash on PQII Pro
From: Kumar Gala @ 2006-08-25 16:39 UTC (permalink / raw)
  To: bwarren; +Cc: linuxppc-embedded
In-Reply-To: <1156444531.17977.59.camel@saruman.qstreams.net>


On Aug 24, 2006, at 1:35 PM, Ben Warren wrote:

> Kumar,
>
> On Thu, 2006-08-24 at 13:25 -0500, Kumar Gala wrote:
>
>> The only code in u-boot was the UPM setup code, I'm happy to send
>> that to you.
>>
> If it's no trouble, that would be great.  My HW guy is calculating the
> settings, but this stuff can be frustrating to debug.  BTW - was the
> system bus speed for your CPU 33 or 66 MHz?  We're targeting for a
> 400MHz 8349 which has a 33MHz system bus.

I think we were running @ 66Mhz, but I've run the FSL ref board @ 33MHZ.

- k

^ permalink raw reply

* [PATCH 1/4] back up old school ipic.[hc] to arch/ppc
From: Kim Phillips @ 2006-08-25 16:58 UTC (permalink / raw)
  To: linuxppc-dev

Keep from breaking 83xx arch/ppc build.  Back up old school arch/powerpc/sysdev/ipic.[hc] to arch/ppc/syslib.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---

please apply to 2.6.18

 arch/powerpc/sysdev/Makefile |    4 
 arch/ppc/syslib/Makefile     |    2 
 arch/ppc/syslib/ipic.c       |  646 ++++++++++++++++++++++++++++++++++++++++++
 arch/ppc/syslib/ipic.h       |   47 +++
 include/asm-powerpc/ipic.h   |   12 +
 5 files changed, 705 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index cebfae2..e5e999e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE)		+= dcr.o
 obj-$(CONFIG_40x)		+= dcr.o
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
-obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
- endif
+obj-$(CONFIG_PPC_83xx)		+= ipic.o
+endif
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 2497bbc..dca23f2 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -93,7 +93,7 @@ obj-$(CONFIG_PCI)		+= pci_auto.o
 endif
 obj-$(CONFIG_RAPIDIO)		+= ppc85xx_rio.o
 obj-$(CONFIG_83xx)		+= ppc83xx_setup.o ppc_sys.o \
-					mpc83xx_sys.o mpc83xx_devices.o
+					mpc83xx_sys.o mpc83xx_devices.o ipic.o
 ifeq ($(CONFIG_83xx),y)
 obj-$(CONFIG_PCI)		+= pci_auto.o
 endif
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 0000000..46801f5
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 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/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+	[9] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 24,
+		.prio_mask = 0,
+	},
+	[10] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 25,
+		.prio_mask = 1,
+	},
+	[11] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 26,
+		.prio_mask = 2,
+	},
+	[14] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 29,
+		.prio_mask = 5,
+	},
+	[15] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 30,
+		.prio_mask = 6,
+	},
+	[16] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 31,
+		.prio_mask = 7,
+	},
+	[17] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 1,
+		.prio_mask = 5,
+	},
+	[18] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 2,
+		.prio_mask = 6,
+	},
+	[19] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 3,
+		.prio_mask = 7,
+	},
+	[20] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[21] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[22] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[23] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[32] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[33] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[34] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[35] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[36] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[37] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[38] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[39] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[48] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 0,
+		.prio_mask = 4,
+	},
+	[64] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[65] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[66] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[67] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[68] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 4,
+		.prio_mask = 0,
+	},
+	[69] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 5,
+		.prio_mask = 1,
+	},
+	[70] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 6,
+		.prio_mask = 2,
+	},
+	[71] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 7,
+		.prio_mask = 3,
+	},
+	[72] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 8,
+	},
+	[73] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 9,
+	},
+	[74] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 10,
+	},
+	[75] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 11,
+	},
+	[76] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 12,
+	},
+	[77] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 13,
+	},
+	[78] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 14,
+	},
+	[79] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 15,
+	},
+	[80] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 16,
+	},
+	[84] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 20,
+	},
+	[85] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 21,
+	},
+	[90] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 26,
+	},
+	[91] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 27,
+	},
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+	return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+	out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+	return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp &= ~(1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	ipic_disable_irq(irq);
+
+	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);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+	.typename = " IPIC  ",
+	.enable = ipic_enable_irq,
+	.disable = ipic_disable_irq,
+	.ack = ipic_disable_irq_and_ack,
+	.end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+		unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses,
+		unsigned int senses_count)
+{
+	u32 i, temp = 0;
+
+	primary_ipic = &p_ipic;
+	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+	primary_ipic->irq_offset = irq_offset;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+	/* default priority scheme is grouped. If spread mode is required
+	 * configure SICFR accordingly */
+	if (flags & IPIC_SPREADMODE_GRP_A)
+		temp |= SICFR_IPSA;
+	if (flags & IPIC_SPREADMODE_GRP_D)
+		temp |= SICFR_IPSD;
+	if (flags & IPIC_SPREADMODE_MIX_A)
+		temp |= SICFR_MPSA;
+	if (flags & IPIC_SPREADMODE_MIX_B)
+		temp |= SICFR_MPSB;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+	/* handle MCP route */
+	temp = 0;
+	if (flags & IPIC_DISABLE_MCP_OUT)
+		temp = SERCR_MCPR;
+	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+	/* handle routing of IRQ0 to MCP */
+	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+	if (flags & IPIC_IRQ0_MCP)
+		temp |= SEMSR_SIRQ0;
+	else
+		temp &= ~SEMSR_SIRQ0;
+
+	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+		irq_desc[i+irq_offset].chip = &ipic;
+		irq_desc[i+irq_offset].status = IRQ_LEVEL;
+	}
+
+	temp = 0;
+	for (i = 0 ; i < senses_count ; i++) {
+		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+			temp |= 1 << (15 - i);
+			if (i != 0)
+				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+			else
+				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+		}
+	}
+	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+			senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	if (priority > 7)
+		return -EINVAL;
+	if (src > 127)
+		return -EINVAL;
+	if (ipic_info[src].prio == 0)
+		return -EINVAL;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+	if (priority < 4) {
+		temp &= ~(0x7 << (20 + (3 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+	} else {
+		temp &= ~(0x7 << (4 + (7 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+	}
+
+	ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+	return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+	/* clear and set HPI */
+	temp &= 0x7f000000;
+	temp |= (src & 0x7f) << 24;
+
+	ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+	ipic_set_priority(MPC83xx_IRQ_MU, 1);
+	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp |= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp &= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+	return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+	if (irq == 0)    /* 0 --> no irq is pending */
+		irq = -1;
+
+	return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+	set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+	.id		= 0,
+	.cls		= &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+	int rc;
+
+	if (!primary_ipic->regs)
+		return -ENODEV;
+	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+	rc = sysdev_class_register(&ipic_sysclass);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys class\n");
+		return -ENODEV;
+	}
+	rc = sysdev_register(&device_ipic);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys device\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 0000000..a60c9d1
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,47 @@
+/*
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2005 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.
+ */
+#ifndef __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE	(0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define	SICFR_IPSA	0x00010000
+#define	SICFR_IPSD	0x00080000
+#define	SICFR_MPSA	0x00200000
+#define	SICFR_MPSB	0x00400000
+
+/* System External Interrupt Mask Register */
+#define	SEMSR_SIRQ0	0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR	0x00000001
+
+struct ipic {
+	volatile u32 __iomem	*regs;
+	unsigned int		irq_offset;
+};
+
+struct ipic_info {
+	u8	pend;		/* pending register offset from base */
+	u8	mask;		/* mask register offset from base */
+	u8	prio;		/* priority register offset from base */
+	u8	force;		/* force register offset from base */
+	u8	bit;		/* register bit position (as per doc)
+				   bit mask = 1 << (31 - bit) */
+	u8	prio_mask;	/* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
index 0fe396a..53079ec 100644
--- a/include/asm-powerpc/ipic.h
+++ b/include/asm-powerpc/ipic.h
@@ -69,9 +69,6 @@ enum ipic_mcp_irq {
 	IPIC_MCP_MU   = 7,
 };
 
-extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
-		unsigned int irq_offset,
-		unsigned char *senses, unsigned int senses_count);
 extern int ipic_set_priority(unsigned int irq, unsigned int priority);
 extern void ipic_set_highest_priority(unsigned int irq);
 extern void ipic_set_default_priority(void);
@@ -79,7 +76,16 @@ extern void ipic_enable_mcp(enum ipic_mc
 extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
 extern u32 ipic_get_mcp_status(void);
 extern void ipic_clear_mcp_status(u32 mask);
+
+#ifdef CONFIG_PPC_MERGE
+extern void ipic_init(struct device_node *node, unsigned int flags);
+extern unsigned int ipic_get_irq(struct pt_regs *regs);
+#else
+extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses, unsigned int senses_count);
 extern int ipic_get_irq(struct pt_regs *regs);
+#endif
 
 #endif /* __ASM_IPIC_H__ */
 #endif /* __KERNEL__ */
-- 
1.4.1

^ permalink raw reply related

* [PATCH 3/4] modify mpc83xx platforms to use new IRQ layer
From: Kim Phillips @ 2006-08-25 16:59 UTC (permalink / raw)
  To: linuxppc-dev

This fixes MPC834x MDS (formerly SYS) and ITX platform code to get IRQ data (including PCI) from the device tree, and to use the new IPIC code.

renamed defconfig (sys -> mds), left one redundant NULL assignment in mpc83xx_pcibios_fixup to keep the compiler happy.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>

---

please apply to 2.6.18

 ...mpc834x_sys_defconfig => mpc834x_mds_defconfig} |    0 
 arch/powerpc/platforms/83xx/mpc834x_itx.c          |   49 +++---------------
 arch/powerpc/platforms/83xx/mpc834x_sys.c          |   56 +++-----------------
 arch/powerpc/platforms/83xx/mpc83xx.h              |    1 
 arch/powerpc/platforms/83xx/pci.c                  |    9 +++
 5 files changed, 28 insertions(+), 87 deletions(-)

diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
similarity index 100%
rename from arch/powerpc/configs/mpc834x_sys_defconfig
rename to arch/powerpc/configs/mpc834x_mds_defconfig
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index d9675f9..969fbb6 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,26 +46,6 @@ unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
 #endif
 
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	    /*
-	     *      PCI IDSEL/INTPIN->INTLINE
-	     *       A      B      C      D
-	     */
-	{
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* idsel 0x0e */
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x0f */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x10 */
-	};
-
-	const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif				/* CONFIG_PCI */
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -92,8 +72,6 @@ #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc83xx_map_irq;
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
@@ -106,25 +84,13 @@ #endif
 
 void __init mpc834x_itx_init_IRQ(void)
 {
-	u8 senses[8] = {
-		0,			/* EXT 0 */
-		IRQ_SENSE_LEVEL,	/* EXT 1 */
-		IRQ_SENSE_LEVEL,	/* EXT 2 */
-		0,			/* EXT 3 */
-#ifdef CONFIG_PCI
-		IRQ_SENSE_LEVEL,	/* EXT 4 */
-		IRQ_SENSE_LEVEL,	/* EXT 5 */
-		IRQ_SENSE_LEVEL,	/* EXT 6 */
-		IRQ_SENSE_LEVEL,	/* EXT 7 */
-#else
-		0,			/* EXT 4 */
-		0,			/* EXT 5 */
-		0,			/* EXT 6 */
-		0,			/* EXT 7 */
-#endif
-	};
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
 
-	ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+	ipic_init(np, 0);
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
@@ -153,4 +119,7 @@ define_machine(mpc834x_itx) {
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup		= mpc83xx_pcibios_fixup,
+#endif
 };
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 5eadf9d..6771961 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -43,33 +43,6 @@ unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
 #endif
 
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	    /*
-	     *      PCI IDSEL/INTPIN->INTLINE
-	     *       A      B      C      D
-	     */
-	{
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x11 */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x12 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x13 */
-		{0, 0, 0, 0},
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x15 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x16 */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x17 */
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* idsel 0x18 */
-		{0, 0, 0, 0},			/* idsel 0x19 */
-		{0, 0, 0, 0},			/* idsel 0x20 */
-	};
-
-	const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif				/* CONFIG_PCI */
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -96,8 +69,6 @@ #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc83xx_map_irq;
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
@@ -110,25 +81,13 @@ #endif
 
 void __init mpc834x_sys_init_IRQ(void)
 {
-	u8 senses[8] = {
-		0,			/* EXT 0 */
-		IRQ_SENSE_LEVEL,	/* EXT 1 */
-		IRQ_SENSE_LEVEL,	/* EXT 2 */
-		0,			/* EXT 3 */
-#ifdef CONFIG_PCI
-		IRQ_SENSE_LEVEL,	/* EXT 4 */
-		IRQ_SENSE_LEVEL,	/* EXT 5 */
-		IRQ_SENSE_LEVEL,	/* EXT 6 */
-		IRQ_SENSE_LEVEL,	/* EXT 7 */
-#else
-		0,			/* EXT 4 */
-		0,			/* EXT 5 */
-		0,			/* EXT 6 */
-		0,			/* EXT 7 */
-#endif
-	};
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
 
-	ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+	ipic_init(np, 0);
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
@@ -178,4 +137,7 @@ define_machine(mpc834x_sys) {
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup		= mpc83xx_pcibios_fixup,
+#endif
 };
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 01cae10..2c82bca 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -11,6 +11,7 @@ #include <linux/device.h>
 
 extern int add_bridge(struct device_node *dev);
 extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern void mpc83xx_pcibios_fixup(void);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 9c36505..4557ac5 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -45,6 +45,15 @@ int mpc83xx_exclude_device(u_char bus, u
 	return PCIBIOS_SUCCESSFUL;
 }
 
+void __init mpc83xx_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	/* map all the PCI irqs */
+	for_each_pci_dev(dev)
+		pci_read_irq_line(dev);
+}
+
 int __init add_bridge(struct device_node *dev)
 {
 	int len;
-- 
1.4.1

^ permalink raw reply related

* [PATCH 2/4] Adapt ipic driver to new host_ops interface, add set_irq_type to set IRQ sense
From: Kim Phillips @ 2006-08-25 16:59 UTC (permalink / raw)
  To: linuxppc-dev

This converts ipic code to Benh's IRQ mods.  For the IPIC, IRQ sense values in the device tree equal those in include/linux/irq.h; that's 8 for low assertion (most internal IRQs on mpc83xx), and 2 for high-to-low change.

spinlocks added to [un]mask, ack operations; default handler and type now set in host_map; and redundant condition check eliminated.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>

---

please apply to 2.6.18

 arch/powerpc/sysdev/ipic.c |  303 ++++++++++++++++++++++++++++++--------------
 arch/powerpc/sysdev/ipic.h |   23 +++
 2 files changed, 228 insertions(+), 98 deletions(-)

diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 46801f5..70e7077 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -19,15 +19,18 @@ #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/sysdev.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/prom.h>
 #include <asm/ipic.h>
-#include <asm/mpc83xx.h>
 
 #include "ipic.h"
 
-static struct ipic p_ipic;
 static struct ipic * primary_ipic;
+static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
 	[9] = {
@@ -373,74 +376,220 @@ static inline void ipic_write(volatile u
 	out_be32(base + (reg >> 2), value);
 }
 
-static inline struct ipic * ipic_from_irq(unsigned int irq)
+static inline struct ipic * ipic_from_irq(unsigned int virq)
 {
 	return primary_ipic;
 }
 
-static void ipic_enable_irq(unsigned int irq)
+#define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
+
+static void ipic_unmask_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	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);
+
 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
 	temp |= (1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_disable_irq(unsigned int irq)
+static void ipic_mask_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	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);
+
 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_disable_irq_and_ack(unsigned int irq)
+static void ipic_ack_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned long flags;
 	u32 temp;
 
-	ipic_disable_irq(irq);
+	spin_lock_irqsave(&ipic_lock, flags);
 
 	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_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_end_irq(unsigned int irq)
+static void ipic_mask_irq_and_ack(unsigned int virq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		ipic_enable_irq(irq);
+	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);
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	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);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-struct hw_interrupt_type ipic = {
-	.typename = " IPIC  ",
-	.enable = ipic_enable_irq,
-	.disable = ipic_disable_irq,
-	.ack = ipic_disable_irq_and_ack,
-	.end = ipic_end_irq,
+static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	struct irq_desc *desc = get_irq_desc(virq);
+	unsigned int vold, vnew, edibit;
+
+	if (flow_type == IRQ_TYPE_NONE)
+		flow_type = IRQ_TYPE_LEVEL_LOW;
+
+	/* ipic supports only low assertion and high-to-low change senses
+	 */
+	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
+		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
+			flow_type);
+		return -EINVAL;
+	}
+
+	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
+		desc->status |= IRQ_LEVEL;
+		set_irq_handler(virq, handle_level_irq);
+	} else {
+		set_irq_handler(virq, handle_edge_irq);
+	}
+
+	/* only EXT IRQ senses are programmable on ipic
+	 * internal IRQ senses are LEVEL_LOW
+	 */
+	if (src == IPIC_IRQ_EXT0)
+		edibit = 15;
+	else
+		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
+			edibit = (14 - (src - IPIC_IRQ_EXT1));
+		else
+			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
+
+	vold = ipic_read(ipic->regs, IPIC_SECNR);
+	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
+		vnew = vold | (1 << edibit);
+	} else {
+		vnew = vold & ~(1 << edibit);
+	}
+	if (vold != vnew)
+		ipic_write(ipic->regs, IPIC_SECNR, vnew);
+	return 0;
+}
+
+static struct irq_chip ipic_irq_chip = {
+	.typename	= " IPIC  ",
+	.unmask		= ipic_unmask_irq,
+	.mask		= ipic_mask_irq,
+	.mask_ack	= ipic_mask_irq_and_ack,
+	.ack		= ipic_ack_irq,
+	.set_type	= ipic_set_irq_type,
+};
+
+static int ipic_host_match(struct irq_host *h, struct device_node *node)
+{
+	struct ipic *ipic = h->host_data;
+
+	/* Exact match, unless ipic node is NULL */
+	return ipic->of_node == NULL || ipic->of_node == node;
+}
+
+static int ipic_host_map(struct irq_host *h, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	struct ipic *ipic = h->host_data;
+	struct irq_chip *chip;
+
+	/* Default chip */
+	chip = &ipic->hc_irq;
+
+	set_irq_chip_data(virq, ipic);
+	set_irq_chip_and_handler(virq, chip, handle_level_irq);
+
+	/* Set default irq type */
+	set_irq_type(virq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
+			   u32 *intspec, unsigned int intsize,
+			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+	/* interrupt sense values coming from the device tree equal either
+	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
+	 */
+	*out_hwirq = intspec[0];
+	if (intsize > 1)
+		*out_flags = intspec[1];
+	else
+		*out_flags = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_host_ops ipic_host_ops = {
+	.match	= ipic_host_match,
+	.map	= ipic_host_map,
+	.xlate	= ipic_host_xlate,
 };
 
-void __init ipic_init(phys_addr_t phys_addr,
-		unsigned int flags,
-		unsigned int irq_offset,
-		unsigned char *senses,
-		unsigned int senses_count)
+void __init ipic_init(struct device_node *node,
+		unsigned int flags)
 {
-	u32 i, temp = 0;
+	struct ipic	*ipic;
+	struct resource res;
+	u32 temp = 0, ret;
+
+	ipic = alloc_bootmem(sizeof(struct ipic));
+	if (ipic == NULL)
+		return;
+
+	memset(ipic, 0, sizeof(struct ipic));
+	ipic->of_node = node ? of_node_get(node) : NULL;
+
+	ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+				       NR_IPIC_INTS,
+				       &ipic_host_ops, 0);
+	if (ipic->irqhost == NULL) {
+		of_node_put(node);
+		return;
+	}
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret)
+		return;
 
-	primary_ipic = &p_ipic;
-	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+	ipic->regs = ioremap(res.start, res.end - res.start + 1);
 
-	primary_ipic->irq_offset = irq_offset;
+	ipic->irqhost->host_data = ipic;
+	ipic->hc_irq = ipic_irq_chip;
 
-	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+	/* init hw */
+	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
 
 	/* default priority scheme is grouped. If spread mode is required
 	 * configure SICFR accordingly */
@@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_a
 	if (flags & IPIC_SPREADMODE_MIX_B)
 		temp |= SICFR_MPSB;
 
-	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+	ipic_write(ipic->regs, IPIC_SICNR, temp);
 
 	/* handle MCP route */
 	temp = 0;
 	if (flags & IPIC_DISABLE_MCP_OUT)
 		temp = SERCR_MCPR;
-	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+	ipic_write(ipic->regs, IPIC_SERCR, temp);
 
 	/* handle routing of IRQ0 to MCP */
-	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+	temp = ipic_read(ipic->regs, IPIC_SEMSR);
 
 	if (flags & IPIC_IRQ0_MCP)
 		temp |= SEMSR_SIRQ0;
 	else
 		temp &= ~SEMSR_SIRQ0;
 
-	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+	ipic_write(ipic->regs, IPIC_SEMSR, temp);
 
-	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
-		irq_desc[i+irq_offset].chip = &ipic;
-		irq_desc[i+irq_offset].status = IRQ_LEVEL;
-	}
+	primary_ipic = ipic;
+	irq_set_default_host(primary_ipic->irqhost);
 
-	temp = 0;
-	for (i = 0 ; i < senses_count ; i++) {
-		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
-			temp |= 1 << (15 - i);
-			if (i != 0)
-				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
-			else
-				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
-		}
-	}
-	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
-
-	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
-			senses_count, primary_ipic->regs);
+	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
+			primary_ipic->regs);
 }
 
-int ipic_set_priority(unsigned int irq, unsigned int priority)
+int ipic_set_priority(unsigned int virq, unsigned int priority)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
 	u32 temp;
 
 	if (priority > 7)
@@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, 
 	return 0;
 }
 
-void ipic_set_highest_priority(unsigned int irq)
+void ipic_set_highest_priority(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
 	u32 temp;
 
 	temp = ipic_read(ipic->regs, IPIC_SICFR);
@@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned 
 
 void ipic_set_default_priority(void)
 {
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
-	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
-	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
-
-	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
-	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
-	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
-	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
-	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
-	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
-	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
-	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
-	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
-	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
-	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
-	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
-	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
-	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
-	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
-	ipic_set_priority(MPC83xx_IRQ_MU, 1);
-	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
-	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
-	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
-	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
-	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
-	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
 }
 
 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
@@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask)
 	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
 }
 
-/* Return an interrupt vector or -1 if no interrupt is pending. */
-int ipic_get_irq(struct pt_regs *regs)
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int ipic_get_irq(struct pt_regs *regs)
 {
 	int irq;
 
-	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+	BUG_ON(primary_ipic == NULL);
+
+#define IPIC_SIVCR_VECTOR_MASK	0x7f
+	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
 
 	if (irq == 0)    /* 0 --> no irq is pending */
-		irq = -1;
+		return NO_IRQ;
 
-	return irq;
+	return irq_linear_revmap(primary_ipic->irqhost, irq);
 }
 
 static struct sysdev_class ipic_sysclass = {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index a60c9d1..c28e589 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -15,7 +15,18 @@ #define __IPIC_H__
 
 #include <asm/ipic.h>
 
-#define MPC83xx_IPIC_SIZE	(0x00100)
+#define NR_IPIC_INTS 128
+
+/* External IRQS */
+#define IPIC_IRQ_EXT0 48
+#define IPIC_IRQ_EXT1 17
+#define IPIC_IRQ_EXT7 23
+
+/* Default Priority Registers */
+#define IPIC_SIPRR_A_DEFAULT 0x05309770
+#define IPIC_SIPRR_D_DEFAULT 0x05309770
+#define IPIC_SMPRR_A_DEFAULT 0x05309770
+#define IPIC_SMPRR_B_DEFAULT 0x05309770
 
 /* System Global Interrupt Configuration Register */
 #define	SICFR_IPSA	0x00010000
@@ -31,7 +42,15 @@ #define SERCR_MCPR	0x00000001
 
 struct ipic {
 	volatile u32 __iomem	*regs;
-	unsigned int		irq_offset;
+
+	/* The remapper for this IPIC */
+	struct irq_host		*irqhost;
+
+	/* The "linux" controller struct */
+	struct irq_chip		hc_irq;
+
+	/* The device node of the interrupt controller */
+	struct device_node	*of_node;
 };
 
 struct ipic_info {
-- 
1.4.1

^ permalink raw reply related

* [PATCH 4/4] Add MPC8349E MDS device tree source file to arch/powerpc/boot/dts
From: Kim Phillips @ 2006-08-25 16:59 UTC (permalink / raw)
  To: linuxppc-dev

Add MPC8349E MDS device tree source file to arch/powerpc/boot/dts, aptly indicating new school sense values definition.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>

---

 arch/powerpc/boot/dts/mpc8349emds.dts |  328 +++++++++++++++++++++++++++++++++
 1 files changed, 328 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts
new file mode 100644
index 0000000..7e4508b
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emds.dts
@@ -0,0 +1,328 @@
+/*
+ * MPC8349E MDS Device Tree Source
+ *
+ * Copyright 2005, 2006 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.
+ */
+
+/ {
+	model = "MPC8349EMDS";
+	compatible = "MPC834xMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;	// 256MB at 0
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = <700>;
+			mode = <0>;
+		};
+
+		/* phy type (ULPI or SERIAL) are only types supportted for MPH */
+		/* port = 0 or 1 */
+		usb@22000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-mph";
+			reg = <22000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <27 2>;
+			phy_type = "ulpi";
+			port1;
+		};
+		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <26 2>;
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <700>;
+				interrupts = <11 2>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = <700>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 8 24 8 25 8>;
+			interrupt-parent = <700>;
+			phy-handle = <2452001>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <9 8>;
+			interrupt-parent = <700>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <a 8>;
+			interrupt-parent = <700>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 700 14 0
+					 8800 0 0 2 700 15 0
+					 8800 0 0 3 700 16 0
+					 8800 0 0 4 700 17 0
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 700 16 0
+					 9000 0 0 2 700 17 0
+					 9000 0 0 3 700 14 0
+					 9000 0 0 4 700 15 0
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 700 17 0
+					 9800 0 0 2 700 14 0
+					 9800 0 0 3 700 15 0
+					 9800 0 0 4 700 16 0
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 700 14 0
+					 a800 0 0 2 700 15 0
+					 a800 0 0 3 700 16 0
+					 a800 0 0 4 700 17 0
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 700 17 0
+					 b000 0 0 2 700 14 0
+					 b000 0 0 3 700 15 0
+					 b000 0 0 4 700 16 0
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 700 16 0
+					 b800 0 0 2 700 17 0
+					 b800 0 0 3 700 14 0
+					 b800 0 0 4 700 15 0
+
+					/* IDSEL 0x18 */
+					 b000 0 0 1 700 15 0
+					 b000 0 0 2 700 16 0
+					 b000 0 0 3 700 17 0
+					 b000 0 0 4 700 14 0>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 10000000
+				  42000000 0 80000000 80000000 0 10000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 700 14 0
+					 8800 0 0 2 700 15 0
+					 8800 0 0 3 700 16 0
+					 8800 0 0 4 700 17 0
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 700 16 0
+					 9000 0 0 2 700 17 0
+					 9000 0 0 3 700 14 0
+					 9000 0 0 4 700 15 0
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 700 17 0
+					 9800 0 0 2 700 14 0
+					 9800 0 0 3 700 15 0
+					 9800 0 0 4 700 16 0
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 700 14 0
+					 a800 0 0 2 700 15 0
+					 a800 0 0 3 700 16 0
+					 a800 0 0 4 700 17 0
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 700 17 0
+					 b000 0 0 2 700 14 0
+					 b000 0 0 3 700 15 0
+					 b000 0 0 4 700 16 0
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 700 16 0
+					 b800 0 0 2 700 17 0
+					 b800 0 0 3 700 14 0
+					 b800 0 0 4 700 15 0
+
+					/* IDSEL 0x18 */
+					 b000 0 0 1 700 15 0
+					 b000 0 0 2 700 16 0
+					 b000 0 0 3 700 17 0
+					 b000 0 0 4 700 14 0>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 b0000000 b0000000 0 10000000
+				  42000000 0 90000000 90000000 0 10000000
+				  01000000 0 00000000 e2100000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		/* May need to remove if on a part without crypto engine */
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = <700>;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			/* desc mask is for rev2.0,
+			 * we need runtime fixup for >2.0 */
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		/* IPIC
+		 * interrupts cell = <intr #, sense>
+		 * sense values match linux IORESOURCE_IRQ_* defines:
+		 * sense == 8: Level, low assertion
+		 * sense == 2: Edge, high-to-low change
+		 */
+		pic@700 {
+			linux,phandle = <700>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
-- 
1.4.1

^ permalink raw reply related

* Re: [PATCH] powerpc: Make OF irq map code detect more error cases
From: Segher Boessenkool @ 2006-08-25 17:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1156481183.8433.300.camel@localhost.localdomain>

> Device-tree bugs on js20 with some versions of SLOF were causing the
> interrupt for IDE to not be parsed correctly and fail to boot. This
> patch adds a bit more sanity checking to the parser to detet some of
> those errors and fail instead of returning bogus informations. The
> powerpc PCI code can then trigger a fallback that works on those
> machines.

Quite similar to my patch you have been refusing, so I'll just

ACK

it, irrespective of if we need it or not (anymore) -- it's a good,
useful, cheap sanity check.  The patch looks good, too.


Segher

^ permalink raw reply

* Help for re-building powerpc-linux-gdb
From: wei.li4 @ 2006-08-25 18:23 UTC (permalink / raw)
  To: linuxppc-embedded

Hi All,

I am trying to build powerpc-linux-gdb with gdb-5.0.tar.gz and 
mpcbdm-1.2.3.tar.gz packages under Fedora 2, but it is failed, I guess 
my gcc is too new, I am using BDM4GDB from www.denx.com, is there 
anyone who has the same experience and can help me? Thanks.

Wei

^ permalink raw reply

* Re: [PATCH] reboot when panic_timout is set
From: Mike Strosaker @ 2006-08-25 18:33 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev, Paul Mackeras
In-Reply-To: <20060821161132.GA31085@aepfle.de>

Olaf Hering wrote:

>Only call into RTAS when booted with panic=0 because the RTAS call does not return.
>The system has to be rebooted via the HMC or via the management console right now.
>This is cumbersome and not what the default panic=180 is supposed to do.
>  
>
The os-term call is supposed to indicate to the platform that it should 
follow it's abnormal OS termination policy.  I normally set my 
partitions to reboot immediately after an os-term call.  I believe that 
"/usr/sbin/serv_config -b" (installed with powerpc-utils-papr) is used 
to set that policy from the command line.

In general, I think it's best to have the OS follow the policy stored on 
the platform whenever possible.  Some systems can be configured to 
perform system administrator calls/pages, and there may be some other 
configurable options, too; it would be a shame to have a sysadmin set up 
an automatic reboot and a page, and have neither happen because he 
didn't know that the default OS policy of a three-minute reboot overrode 
the policy he just defined.

Thanks,
Mike

>Signed-off-by: Olaf Hering <olh@suse.de>
>
>---
> arch/powerpc/kernel/rtas.c |    3 +++
> 1 file changed, 3 insertions(+)
>
>Index: linux-2.6.18-rc4/arch/powerpc/kernel/rtas.c
>===================================================================
>--- linux-2.6.18-rc4.orig/arch/powerpc/kernel/rtas.c
>+++ linux-2.6.18-rc4/arch/powerpc/kernel/rtas.c
>@@ -628,6 +628,9 @@ void rtas_os_term(char *str)
> {
> 	int status;
> 
>+	if (panic_timeout)
>+		return;
>+
> 	if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
> 		return;
> 
>_______________________________________________
>Linuxppc-dev mailing list
>Linuxppc-dev@ozlabs.org
>https://ozlabs.org/mailman/listinfo/linuxppc-dev
>  
>

^ permalink raw reply

* Re: [PATCH] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-08-25 18:52 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17645.19790.527223.207556@cargo.ozlabs.ibm.com>

On Thu, Aug 24, 2006 at 04:55:10PM +1000, Paul Mackerras wrote:
> > +	/* calculate address of stat structure */		\
> > +	ld	r4,STK_PARM(r3)(r1);	/* use opcode as */	\
> > +	rldicl	r4,r4,62,2;		/* index into array */	\
> > +	mulli	r4,r4,HCALL_STAT_SIZE;				\
> 
> It's a pity our multiplies are slow (6 cycles).  The rldicl would I
> think be more clearly expressed as srdi r4,r4,2.  We could use a shift
> and add instead of the multiply if we put a big fat comment in the
> header that defines the structure warning people to adjust the
> assembly if they change the structure.  Might not be worth it though.

I would rather keep the multiply and minimal safety it provides when
people change the structure.

> BTW are we going to die horribly if someone uses an hcall greater than
> MAX_HCALL_OPCODES?  The hcall functions are available to modules, so
> it would be quite possible for a module to come along and try to use
> some new hcalls that weren't known about when the kernel was built.

Yes, bad things would happen.  This is/was a bad assumption on my part
that all callers would pass in valid opcodes.  I'll put in a simple check
for that.

-- 
Mike

^ permalink raw reply


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