LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* 2.6.13 PowerBook boot hang (was Re: 2.6.13-rc7-git2 crashes on iBook)
From: Sean Neakums @ 2005-08-29 10:56 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev, linux-kernel, Linus Torvalds
In-Reply-To: <jehdda2tqt.fsf@sykes.suse.de>

Andreas Schwab <schwab@suse.de> writes:

> The last change to drivers/pci/setup-res.c (Ignore disabled ROM resources
> at setup) is breaking radeonfb on iBook G3 (with Radeon Mobility M6 LY).
> It crashes in pci_map_rom when called from radeonfb_map_ROM.  This is
> probably a dormant bug that was just uncovered by the change.

2.6.13 hangs on boot on my PowerBook 5.4, reverting the disabled ROM
patch (appended for confirmation) fixes it.  2.6.13-rc7 was fine.


diff-tree 755528c860b05fcecda1c88a2bdaffcb50760a7f (from 26aad69e3dd854abe9028ca873fb40b410a39dd7)
Author: Linus Torvalds <torvalds@g5.osdl.org>
Date:   Fri Aug 26 10:49:22 2005 -0700

    Ignore disabled ROM resources at setup
    
    Writing even a disabled value seems to mess up some matrox graphics
    cards.  It may be a card-related issue, but we may also be writing
    reserved low bits in the result.
    
    This was a fall-out of switching x86 over to the generic PCI resource
    allocation code, and needs more debugging.  In particular, the old x86
    code defaulted to not doing any resource allocations at all for ROM
    resources.
    
    In the meantime, this has been reported to make X happier by Helge
    Hafting <helgehaf@aitel.hist.no>.
    
    Signed-off-by: Linus Torvalds <torvalds@osdl.org>

diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -53,7 +53,9 @@ pci_update_resource(struct pci_dev *dev,
 	if (resno < 6) {
 		reg = PCI_BASE_ADDRESS_0 + 4 * resno;
 	} else if (resno == PCI_ROM_RESOURCE) {
-		new |= res->flags & IORESOURCE_ROM_ENABLE;
+		if (!(res->flags & IORESOURCE_ROM_ENABLE))
+			return;
+		new |= PCI_ROM_ADDRESS_ENABLE;
 		reg = dev->rom_base_reg;
 	} else {
 		/* Hmm, non-standard resource. */

^ permalink raw reply

* serial line on mpc5200
From: Carl Ljungmark @ 2005-08-29 10:52 UTC (permalink / raw)
  To: linuxppc-embedded

Hi all!
I have 2.6.12 up and running on my mpc5200, but are experiencing a proble=
m =20
with the
serial line.
PSC1+3 are both registered as uarts during boot

Serial: MPC52xx PSC driver
ttyS0 at MMIO 0xf0002000 (irq =3D 39) is a MPC52xx PSC
ttyS2 at MMIO 0xf0002400 (irq =3D 41) is a MPC52xx PSC

, but I don't get the 2nd line to work.

# cat /proc/tty/driver/mpc52xx_psc_uart
shows
serinfo:1.0 driver revision:
0: uart:MPC52xx PSC mmio:0xF0002000 irq:39 tx:3546 rx:112 =20
RTS|CTS|DTR|DSR|CD
2: uart:MPC52xx PSC mmio:0xF0002400 irq:41 tx:0 rx:0 CTS|DSR|CD
#

(IRQ 41 isn't shown under /proc/interrupts - and no entry under =20
/proc/irq/41, but
the irq 41 count IS increased when writing to the port - as shown under =20
/proc/stat)

under 2.4.31 both serial lines work, so it's not hardware. In 2.4 the =20
serial lines show up as /dev/tts/{0,1}, whereas in 2.6 they show up as =20
/dev/tts/{0,2}.

Does anyone know what the problem might be?

thanks in advance..
/carl

^ permalink raw reply

* Re: [PATCH] ppc32: add CONFIG_HZ
From: Segher Boessenkool @ 2005-08-29 15:31 UTC (permalink / raw)
  To: Dan Malek; +Cc: Andrew Morton, linuxppc-dev, Kumar Gala
In-Reply-To: <f0351d402e64b569bbcfc16fa921d860@embeddededge.com>

>> While ppc32 has the CONFIG_HZ Kconfig option, it wasnt actually being
>> used. Connect it up and set all platforms to 250Hz.  This pretty much
>> mimics the ppc64 patch from Anton Blanchard.
>
> Why do we keep cranking up this clock frequency?  Do we really need
> it running that fast?  Is it time for someone with RTOS experience to
> implement a real scheduled clock queue in Linux instead of just
> wasting interrupts decrementing a counter waiting for the next
> event to expire?  :-)

Sure.  And some people are actually working on that.  But
on common x86 hardware, it seems to be a really really hard
thing to do.  Would be a lot easier in PowerPC of course...


Segher

^ permalink raw reply

* Re: [PATCH] 1/2 Start header file merger (Was: Re: Beginning Merger Patch)
From: Segher Boessenkool @ 2005-08-29 15:44 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc64-dev, linuxppc-dev@ozlabs.org
In-Reply-To: <1125089709.32488.35.camel@cashmere.sps.mot.com>

> Anyone care to take a semi-authoritative stand on what
> symbol to use to distinguish 32/64-bit-ness in the
> include files?

It depends on what you are testing for.

Sometimes __LP64__ would be best (when you want to know
the size of pointers etc.), sometimes __powerpc64__ (when
you need to know the available instruction set), and
I'm sure there are cases where you should use a different
symbol altogether, because you are testing something else.


Segher

^ permalink raw reply

* Re: [PATCH] ppc32 :Added PCI support for MPC83xx
From: Kumar Gala @ 2005-08-29 17:42 UTC (permalink / raw)
  To: Li Tony-r64360; +Cc: Chu hanjin-r52514, linux-kernel, linuxppc-embedded
In-Reply-To: <9FCDBA58F226D911B202000BDBAD467302BEB583@zch01exm40.ap.freescale.net>

I noticed that you aren't updating the senses array in 
mpc834x_sys_init_IRQ for the PCI interrupt lines, is this correct?  
Should they not be IRQ_SENSE_LEVEL?

Also, I've done a bit of cosmetic cleanup to the patch, take a look and 
let me know if it works.  Once we close on the IRQ sense issue I will 
send this upstream.

- kumar

---

diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -713,6 +713,12 @@ config MPC834x_SYS
 	help
 	  This option enables support for the MPC 834x SYS evaluation board.
 
+	  Be aware that PCI buses can only function when SYS board is plugged on
+	  PIB (Platform IO Board) board from Freescale which provide 3 PCI slots.
+	  Just like PC,the board level initalization is bootloader`s responsiblilty.
+	  The PCI deponds on bootloader configurate board corretly. Refer to Freescale
+	  to get more information about this.
+
 endchoice
 
 config PQ2ADS
@@ -1193,6 +1199,11 @@ config PCI
 config PCI_DOMAINS
 	bool
 	default PCI
+
+config MPC83xx_PCI2
+	bool "  Supprt for 2nd PCI host controller"
+	depends on PCI && MPC834x
+	default y if MPC834x_SYS
 
 config PCI_QSPAN
 	bool "QSpan PCI"
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -62,9 +62,29 @@ extern unsigned long total_memory;	/* in
 unsigned char __res[sizeof (bd_t)];
 
 #ifdef CONFIG_PCI
-#error "PCI is not supported"
-/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
-   see platforms/85xx/mpc85xx_ads_common.c */
+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 */
+	};
+
+	const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int
+mpc83xx_exclude_device(u_char bus, u_char devfn)
+{
+	return PCIBIOS_SUCCESSFUL;
+}
 #endif /* CONFIG_PCI */
 
 /* ************************************************************************
@@ -88,7 +108,7 @@ mpc834x_sys_setup_arch(void)
 
 #ifdef CONFIG_PCI
 	/* setup PCI host bridges */
-	mpc83xx_sys_setup_hose();
+	mpc83xx_setup_hose();
 #endif
 	mpc83xx_early_serial_map();
 
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
--- a/arch/ppc/platforms/83xx/mpc834x_sys.h
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -26,7 +26,7 @@
 #define VIRT_IMMRBAR		((uint)0xfe000000)
 
 #define BCSR_PHYS_ADDR		((uint)0xf8000000)
-#define BCSR_SIZE		((uint)(32 * 1024))
+#define BCSR_SIZE		((uint)(128 * 1024))
 
 #define BCSR_MISC_REG2_OFF	0x07
 #define BCSR_MISC_REG2_PORESET	0x01
@@ -34,23 +34,25 @@
 #define BCSR_MISC_REG3_OFF	0x08
 #define BCSR_MISC_REG3_CNFLOCK	0x80
 
-#ifdef CONFIG_PCI
-/* PCI interrupt controller */
-#define PIRQA        MPC83xx_IRQ_IRQ4
-#define PIRQB        MPC83xx_IRQ_IRQ5
-#define PIRQC        MPC83xx_IRQ_IRQ6
-#define PIRQD        MPC83xx_IRQ_IRQ7
-
-#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
-#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
-
-#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
-#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
-
-#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
-#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
-
-#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
-#endif /* CONFIG_PCI */
+#define PIRQA	MPC83xx_IRQ_EXT4
+#define PIRQB	MPC83xx_IRQ_EXT5
+#define PIRQC	MPC83xx_IRQ_EXT6
+#define PIRQD	MPC83xx_IRQ_EXT7
+
+#define MPC83xx_PCI1_LOWER_IO	0x00000000
+#define MPC83xx_PCI1_UPPER_IO	0x00ffffff
+#define MPC83xx_PCI1_LOWER_MEM	0x80000000
+#define MPC83xx_PCI1_UPPER_MEM	0x9fffffff
+#define MPC83xx_PCI1_IO_BASE	0xe2000000
+#define MPC83xx_PCI1_MEM_OFFSET	0x00000000
+#define MPC83xx_PCI1_IO_SIZE	0x01000000
+
+#define MPC83xx_PCI2_LOWER_IO	0x00000000
+#define MPC83xx_PCI2_UPPER_IO	0x00ffffff
+#define MPC83xx_PCI2_LOWER_MEM	0xa0000000
+#define MPC83xx_PCI2_UPPER_MEM	0xbfffffff
+#define MPC83xx_PCI2_IO_BASE	0xe3000000
+#define MPC83xx_PCI2_MEM_OFFSET	0x00000000
+#define MPC83xx_PCI2_IO_SIZE	0x01000000
 
 #endif                /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/ppc/syslib/ppc83xx_pci.h b/arch/ppc/syslib/ppc83xx_pci.h
new file mode 100644
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_pci.h
@@ -0,0 +1,151 @@
+/* Created by Tony Li <tony.li@freescale.com>
+ * Copyright (c) 2005 freescale semiconductor
+ *
+ * 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.
+ *
+ * This program 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 program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __PPC_SYSLIB_PPC83XX_PCI_H
+#define __PPC_SYSLIB_PPC83XX_PCI_H
+
+typedef struct immr_clk {
+	u32 spmr; /* system PLL mode Register  */
+	u32 occr; /* output clock control Register  */
+	u32 sccr; /* system clock control Register  */
+	u8 res0[0xF4];
+} immr_clk_t;
+
+/*
+ * Sequencer
+ */
+typedef struct immr_ios {
+	u32	potar0;
+	u8	res0[4];
+	u32	pobar0;
+	u8	res1[4];
+	u32	pocmr0;
+	u8	res2[4];
+	u32	potar1;
+	u8	res3[4];
+	u32	pobar1;
+	u8	res4[4];
+	u32	pocmr1;
+	u8	res5[4];
+	u32	potar2;
+	u8	res6[4];
+	u32	pobar2;
+	u8	res7[4];
+	u32	pocmr2;
+	u8	res8[4];
+	u32	potar3;
+	u8	res9[4];
+	u32	pobar3;
+	u8	res10[4];
+	u32	pocmr3;
+	u8	res11[4];
+	u32	potar4;
+	u8	res12[4];
+	u32	pobar4;
+	u8	res13[4];
+	u32	pocmr4;
+	u8	res14[4];
+	u32	potar5;
+	u8	res15[4];
+	u32	pobar5;
+	u8	res16[4];
+	u32	pocmr5;
+	u8	res17[4];
+	u8	res18[0x60];
+	u32	pmcr;
+	u8	res19[4];
+	u32	dtcr;
+	u8	res20[4];
+} immr_ios_t;
+#define POTAR_TA_MASK	0x000fffff
+#define POBAR_BA_MASK	0x000fffff
+#define POCMR_EN	0x80000000
+#define POCMR_IO	0x40000000 /* 0--memory space 1--I/O space */
+#define POCMR_SE	0x20000000 /* streaming enable */
+#define POCMR_DST	0x10000000 /* 0--PCI1 1--PCI2 */
+#define POCMR_CM_MASK	0x000fffff
+
+/*
+ * PCI Controller Control and Status Registers
+ */
+typedef struct immr_pcictrl {
+	u32	esr;
+	u32	ecdr;
+	u32	eer;
+	u32	eatcr;
+	u32	eacr;
+	u32	eeacr;
+	u32	edlcr;
+	u32	edhcr;
+	u32	gcr;
+	u32	ecr;
+	u32	gsr;
+	u8	res0[12];
+	u32	pitar2;
+	u8	res1[4];
+	u32	pibar2;
+	u32	piebar2;
+	u32	piwar2;
+	u8	res2[4];
+	u32	pitar1;
+	u8	res3[4];
+	u32	pibar1;
+	u32	piebar1;
+	u32	piwar1;
+	u8	res4[4];
+	u32	pitar0;
+	u8	res5[4];
+	u32	pibar0;
+	u8	res6[4];
+	u32	piwar0;
+	u8	res7[132];
+} immr_pcictrl_t;
+#define PITAR_TA_MASK	0x000fffff
+#define PIBAR_MASK	0xffffffff
+#define PIEBAR_EBA_MASK	0x000fffff
+#define PIWAR_EN	0x80000000
+#define PIWAR_PF	0x20000000
+#define PIWAR_RTT_MASK	0x000f0000
+#define PIWAR_RTT_NO_SNOOP	0x00040000
+#define PIWAR_RTT_SNOOP	0x00050000
+#define PIWAR_WTT_MASK	0x0000f000
+#define PIWAR_WTT_NO_SNOOP	0x00004000
+#define PIWAR_WTT_SNOOP	0x00005000
+#define PIWAR_IWS_MASK	0x0000003F
+#define PIWAR_IWS_4K	0x0000000B
+#define PIWAR_IWS_8K	0x0000000C
+#define PIWAR_IWS_16K	0x0000000D
+#define PIWAR_IWS_32K	0x0000000E
+#define PIWAR_IWS_64K	0x0000000F
+#define PIWAR_IWS_128K	0x00000010
+#define PIWAR_IWS_256K	0x00000011
+#define PIWAR_IWS_512K	0x00000012
+#define PIWAR_IWS_1M	0x00000013
+#define PIWAR_IWS_2M	0x00000014
+#define PIWAR_IWS_4M	0x00000015
+#define PIWAR_IWS_8M	0x00000016
+#define PIWAR_IWS_16M	0x00000017
+#define PIWAR_IWS_32M	0x00000018
+#define PIWAR_IWS_64M	0x00000019
+#define PIWAR_IWS_128M	0x0000001A
+#define PIWAR_IWS_256M	0x0000001B
+#define PIWAR_IWS_512M	0x0000001C
+#define PIWAR_IWS_1G	0x0000001D
+#define PIWAR_IWS_2G	0x0000001E
+
+#endif /* __PPC_SYSLIB_PPC83XX_PCI_H */
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -11,6 +11,17 @@
  * 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 program 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 program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Added PCI support -- Tony Li <tony.li@freescale.com>
  */
 
 #include <linux/config.h>
@@ -31,6 +42,10 @@
 #include <asm/delay.h>
 
 #include <syslib/ppc83xx_setup.h>
+#if defined(CONFIG_PCI)
+#include <asm/delay.h>
+#include <syslib/ppc83xx_pci.h>
+#endif
 
 phys_addr_t immrbar;
 
@@ -162,4 +177,237 @@ mpc83xx_halt(void)
 	for(;;);
 }
 
-/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
+#if defined(CONFIG_PCI)
+void __init
+mpc83xx_setup_pci1(struct pci_controller *hose)
+{
+	u16 reg16;
+	volatile immr_pcictrl_t * pci_ctrl;
+	volatile immr_ios_t * ios;
+	bd_t *binfo = (bd_t *) __res;
+
+	pci_ctrl = ioremap(binfo->bi_immr_base + 0x8500, sizeof(immr_pcictrl_t));
+	ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
+
+	/*
+	 * Configure PCI Outbound Translation Windows
+	 */
+	ios->potar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POTAR_TA_MASK;
+	ios->pobar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POBAR_BA_MASK;
+	ios->pocmr0 = POCMR_EN |
+		(((0xffffffff - (MPC83xx_PCI1_UPPER_MEM -
+				MPC83xx_PCI1_LOWER_MEM)) >> 12) & POCMR_CM_MASK);
+
+	/* mapped to PCI1 IO space */
+	ios->potar1 = (MPC83xx_PCI1_LOWER_IO >> 12) & POTAR_TA_MASK;
+	ios->pobar1 = (MPC83xx_PCI1_IO_BASE >> 12) & POBAR_BA_MASK;
+	ios->pocmr1 = POCMR_EN | POCMR_IO |
+		(((0xffffffff - (MPC83xx_PCI1_UPPER_IO -
+				MPC83xx_PCI1_LOWER_IO)) >> 12) & POCMR_CM_MASK);
+
+	/*
+	 * Configure PCI Inbound Translation Windows
+	 */
+	pci_ctrl->pitar1 = 0x0;
+	pci_ctrl->pibar1 = 0x0;
+	pci_ctrl->piebar1 = 0x0;
+	pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+
+	/*
+	 * Release PCI RST signal
+	 */
+	pci_ctrl->gcr = 0;
+	udelay(2000);
+	pci_ctrl->gcr = 1;
+	udelay(2000);
+
+	reg16 = 0xff;
+	early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS, 0xffff);
+	early_write_config_byte(hose, hose->first_busno, 0, PCI_LATENCY_TIMER, 0x80);
+
+	iounmap(pci_ctrl);
+	iounmap(ios);
+}
+
+void __init
+mpc83xx_setup_pci2(struct pci_controller *hose)
+{
+	u16 reg16;
+	volatile immr_pcictrl_t * pci_ctrl;
+	volatile immr_ios_t * ios;
+	bd_t *binfo = (bd_t *) __res;
+
+	pci_ctrl = ioremap(binfo->bi_immr_base + 0x8600, sizeof(immr_pcictrl_t));
+	ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
+
+	/*
+	 * Configure PCI Outbound Translation Windows
+	 */
+	ios->potar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POTAR_TA_MASK;
+	ios->pobar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POBAR_BA_MASK;
+	ios->pocmr3 = POCMR_EN | POCMR_DST |
+		(((0xffffffff - (MPC83xx_PCI2_UPPER_MEM -
+				MPC83xx_PCI2_LOWER_MEM)) >> 12) & POCMR_CM_MASK);
+
+	/* mapped to PCI2 IO space */
+	ios->potar4 = (MPC83xx_PCI2_LOWER_IO >> 12) & POTAR_TA_MASK;
+	ios->pobar4 = (MPC83xx_PCI2_IO_BASE >> 12) & POBAR_BA_MASK;
+	ios->pocmr4 = POCMR_EN | POCMR_DST | POCMR_IO |
+		(((0xffffffff - (MPC83xx_PCI2_UPPER_IO -
+				MPC83xx_PCI2_LOWER_IO)) >> 12) & POCMR_CM_MASK);
+
+	/*
+	 * Configure PCI Inbound Translation Windows
+	 */
+	pci_ctrl->pitar1 = 0x0;
+	pci_ctrl->pibar1 = 0x0;
+	pci_ctrl->piebar1 = 0x0;
+	pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
+
+	/*
+	 * Release PCI RST signal
+	 */
+	pci_ctrl->gcr = 0;
+	udelay(2000);
+	pci_ctrl->gcr = 1;
+	udelay(2000);
+
+	reg16 = 0xff;
+	early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND, &reg16);
+	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND, reg16);
+
+	/*
+	 * Clear non-reserved bits in status register.
+	 */
+	early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS, 0xffff);
+	early_write_config_byte(hose, hose->first_busno, 0, PCI_LATENCY_TIMER, 0x80);
+
+	iounmap(pci_ctrl);
+	iounmap(ios);
+}
+
+/*
+ * PCI buses can be enabled only if SYS board combinates with PIB
+ * (Platform IO Board) board which provide 3 PCI slots. There is 2 PCI buses
+ * and 3 PCI slots, so people must configure the routes between them before
+ * enable PCI bus. This routes are under the control of PCA9555PW device which
+ * can be accessed via I2C bus 2 and are configured by firmware. Refer to
+ * Freescale to get more information about firmware configuration.
+ */
+
+extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern int mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+		unsigned char pin);
+void __init
+mpc83xx_setup_hose(void)
+{
+	u32 val32;
+	volatile immr_clk_t * clk;
+	struct pci_controller * hose1;
+#ifdef CONFIG_MPC83xx_PCI2
+	struct pci_controller * hose2;
+#endif
+	bd_t * binfo = (bd_t *)__res;
+
+	clk = ioremap(binfo->bi_immr_base + 0xA00,
+			sizeof(immr_clk_t));
+
+	/*
+	 * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
+	 */
+	val32 = clk->occr;
+	udelay(2000);
+	clk->occr = 0xff000000;
+	udelay(2000);
+
+	iounmap(clk);
+
+	hose1 = pcibios_alloc_controller();
+	if(!hose1)
+		return;
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc83xx_map_irq;
+
+	hose1->bus_offset = 0;
+	hose1->first_busno = 0;
+	hose1->last_busno = 0xff;
+
+	setup_indirect_pci(hose1, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET,
+			binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
+	hose1->set_cfg_type = 1;
+
+	mpc83xx_setup_pci1(hose1);
+
+	hose1->pci_mem_offset = MPC83xx_PCI1_MEM_OFFSET;
+	hose1->mem_space.start = MPC83xx_PCI1_LOWER_MEM;
+	hose1->mem_space.end = MPC83xx_PCI1_UPPER_MEM;
+
+	hose1->io_base_phys = MPC83xx_PCI1_IO_BASE;
+	hose1->io_space.start = MPC83xx_PCI1_LOWER_IO;
+	hose1->io_space.end = MPC83xx_PCI1_UPPER_IO;
+#ifdef CONFIG_MPC83xx_PCI2
+	isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
+			MPC83xx_PCI1_IO_SIZE + MPC83xx_PCI2_IO_SIZE);
+#else
+	isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
+			MPC83xx_PCI1_IO_SIZE);
+#endif /* CONFIG_MPC83xx_PCI2 */
+	hose1->io_base_virt = (void *)isa_io_base;
+	/* setup resources */
+	pci_init_resource(&hose1->io_resource,
+			MPC83xx_PCI1_LOWER_IO,
+			MPC83xx_PCI1_UPPER_IO,
+			IORESOURCE_IO, "PCI host bridge 1");
+	pci_init_resource(&hose1->mem_resources[0],
+			MPC83xx_PCI1_LOWER_MEM,
+			MPC83xx_PCI1_UPPER_MEM,
+			IORESOURCE_MEM, "PCI host bridge 1");
+
+	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+	hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno);
+
+#ifdef CONFIG_MPC83xx_PCI2
+	hose2 = pcibios_alloc_controller();
+	if(!hose2)
+		return;
+
+	hose2->bus_offset = hose1->last_busno + 1;
+	hose2->first_busno = hose1->last_busno + 1;
+	hose2->last_busno = 0xff;
+	setup_indirect_pci(hose2, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET,
+			binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
+	hose2->set_cfg_type = 1;
+
+	mpc83xx_setup_pci2(hose2);
+
+	hose2->pci_mem_offset = MPC83xx_PCI2_MEM_OFFSET;
+	hose2->mem_space.start = MPC83xx_PCI2_LOWER_MEM;
+	hose2->mem_space.end = MPC83xx_PCI2_UPPER_MEM;
+
+	hose2->io_base_phys = MPC83xx_PCI2_IO_BASE;
+	hose2->io_space.start = MPC83xx_PCI2_LOWER_IO;
+	hose2->io_space.end = MPC83xx_PCI2_UPPER_IO;
+	hose2->io_base_virt = (void *)(isa_io_base + MPC83xx_PCI1_IO_SIZE);
+	/* setup resources */
+	pci_init_resource(&hose2->io_resource,
+			MPC83xx_PCI2_LOWER_IO,
+			MPC83xx_PCI2_UPPER_IO,
+			IORESOURCE_IO, "PCI host bridge 2");
+	pci_init_resource(&hose2->mem_resources[0],
+			MPC83xx_PCI2_LOWER_MEM,
+			MPC83xx_PCI2_UPPER_MEM,
+			IORESOURCE_MEM, "PCI host bridge 2");
+
+	hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
+#endif /* CONFIG_MPC83xx_PCI2 */
+}
+#endif /*CONFIG_PCI*/
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h
--- a/arch/ppc/syslib/ppc83xx_setup.h
+++ b/arch/ppc/syslib/ppc83xx_setup.h
@@ -12,6 +12,14 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  *
+ * This program 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 program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #ifndef __PPC_SYSLIB_PPC83XX_SETUP_H
@@ -19,7 +27,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#include <asm/ppcboot.h>
 
 extern unsigned long mpc83xx_find_end_of_memory(void) __init;
 extern long mpc83xx_time_init(void) __init;
@@ -31,13 +38,11 @@ extern void mpc83xx_halt(void);
 extern void mpc83xx_setup_hose(void) __init;
 
 /* PCI config */
-#if 0
-#define PCI1_CFG_ADDR_OFFSET	(FIXME)
-#define PCI1_CFG_DATA_OFFSET	(FIXME)
+#define PCI1_CFG_ADDR_OFFSET (0x8300)
+#define PCI1_CFG_DATA_OFFSET (0x8304)
 
-#define PCI2_CFG_ADDR_OFFSET	(FIXME)
-#define PCI2_CFG_DATA_OFFSET	(FIXME)
-#endif
+#define PCI2_CFG_ADDR_OFFSET (0x8380)
+#define PCI2_CFG_DATA_OFFSET (0x8384)
 
 /* Serial Config */
 #ifdef CONFIG_SERIAL_MANY_PORTS

^ permalink raw reply

* Re: [PATCH] ppc32 :Added PCI support for MPC83xx
From: Dan Malek @ 2005-08-29 18:07 UTC (permalink / raw)
  To: Kumar Gala
  Cc: linux-kernel, linuxppc-embedded, Chu hanjin-r52514,
	Li Tony-r64360
In-Reply-To: <Pine.LNX.4.61.0508291239180.30997@nylon.am.freescale.net>


On Aug 29, 2005, at 1:42 PM, Kumar Gala wrote:

> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c 
> b/arch/ppc/platforms/83xx/mpc834x_sys.c
> --- a/arch/ppc/platforms/83xx/mpc834x_sys.c
> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
> @@ -62,9 +62,29 @@ extern unsigned long total_memory;	/* in
>  unsigned char __res[sizeof (bd_t)];
>
>  #ifdef CONFIG_PCI
> -#error "PCI is not supported"
> -/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
> -   see platforms/85xx/mpc85xx_ads_common.c */
> +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 */
> +	};
> +
> +	const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4;
> +	return PCI_IRQ_TABLE_LOOKUP;
> +}
> +
> +int
> +mpc83xx_exclude_device(u_char bus, u_char devfn)
> +{
> +	return PCIBIOS_SUCCESSFUL;
> +}
>  #endif /* CONFIG_PCI */

Shouldn't this be in the PQ2FADS board specific file?  Not everyone
is going to map IDSELs and IRQs this way.

> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h 
> b/arch/ppc/platforms/83xx/mpc834x_sys.h
> --- a/arch/ppc/platforms/83xx/mpc834x_sys.h
> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
> @@ -26,7 +26,7 @@
>  #define VIRT_IMMRBAR		((uint)0xfe000000)
>
>  #define BCSR_PHYS_ADDR		((uint)0xf8000000)
> -#define BCSR_SIZE		((uint)(32 * 1024))
> +#define BCSR_SIZE		((uint)(128 * 1024))
>
>  #define BCSR_MISC_REG2_OFF	0x07
>  #define BCSR_MISC_REG2_PORESET	0x01
> @@ -34,23 +34,25 @@
>  #define BCSR_MISC_REG3_OFF	0x08
>  #define BCSR_MISC_REG3_CNFLOCK	0x80
>
> -#ifdef CONFIG_PCI
> -/* PCI interrupt controller */
> -#define PIRQA        MPC83xx_IRQ_IRQ4
> -#define PIRQB        MPC83xx_IRQ_IRQ5
> -#define PIRQC        MPC83xx_IRQ_IRQ6
> -#define PIRQD        MPC83xx_IRQ_IRQ7
> -
> -#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
> -#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
> -
> -#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
> -#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
> -
> -#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
> -#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
> -
> -#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
> -#endif /* CONFIG_PCI */
> +#define PIRQA	MPC83xx_IRQ_EXT4
> +#define PIRQB	MPC83xx_IRQ_EXT5
> +#define PIRQC	MPC83xx_IRQ_EXT6
> +#define PIRQD	MPC83xx_IRQ_EXT7

The same thing with these BCSRs and IRQ mappings ....  FADS specific.

> +
> +#define MPC83xx_PCI1_LOWER_IO	0x00000000
> +#define MPC83xx_PCI1_UPPER_IO	0x00ffffff
> +#define MPC83xx_PCI1_LOWER_MEM	0x80000000
> +#define MPC83xx_PCI1_UPPER_MEM	0x9fffffff
> +#define MPC83xx_PCI1_IO_BASE	0xe2000000
> +#define MPC83xx_PCI1_MEM_OFFSET	0x00000000
> +#define MPC83xx_PCI1_IO_SIZE	0x01000000
> +
> +#define MPC83xx_PCI2_LOWER_IO	0x00000000
> +#define MPC83xx_PCI2_UPPER_IO	0x00ffffff
> +#define MPC83xx_PCI2_LOWER_MEM	0xa0000000
> +#define MPC83xx_PCI2_UPPER_MEM	0xbfffffff
> +#define MPC83xx_PCI2_IO_BASE	0xe3000000
> +#define MPC83xx_PCI2_MEM_OFFSET	0x00000000
> +#define MPC83xx_PCI2_IO_SIZE	0x01000000

These should be generic to everyone, and could be
in the ppc83xx_pci.h file.  Maybe surround them with
#ifndef so a board specific file could move the addresses
if they wanted?  I don't think an #ifndef is needed for each
define, maybe just #fndef MPC83xx_PCI1_LOWER_MEM
and let the board define everything if they want anything different.

  Thanks.

	-- Dan

^ permalink raw reply

* linuxppc-2.4.30-pre1 crashes with root fs on Xilinx SystemACE
From: Keith J Outwater @ 2005-08-29 18:31 UTC (permalink / raw)
  To: linuxppc-embedded

Hello - 
Per a previous suggestion from this list, I rsynced the linuxppc-2.4 
kernel sources from MontaVista and modified the kernel to run on my custom 
ppc405/VirtexII Pro based system with U-Boot as the bootloader.
When I try to use the SystemACE device as the root filesystem, the kernel 
crashes with a sig 11.  Looking at the 'oops' output it appears  the 
SystemACE driver may be to blame.  The crash is random - sometimes I get 
all the way to login as root and then things crash on a file copy or a 
file read.
Before I start digging deeper, is anyone running a VirtexIIPro based 
system with the root filesystem in the CF card attached to a SystemACE? 
I'm wondering if I really have the best kernel and SystemACE driver.
BTW, I'm developing the hardware design using Xilinx EDK 7.02i.
Thanks,
Keith

^ permalink raw reply

* Re: 2.6.13 PowerBook boot hang (was Re: 2.6.13-rc7-git2 crashes on iBook)
From: Mikael Pettersson @ 2005-08-29 18:17 UTC (permalink / raw)
  To: Sean Neakums; +Cc: Linus Torvalds, linux-kernel, linuxppc-dev
In-Reply-To: <7wr7cdt3jk.fsf@frotz.zork.net>

Sean Neakums writes:
 > Andreas Schwab <schwab@suse.de> writes:
 > 
 > > The last change to drivers/pci/setup-res.c (Ignore disabled ROM resources
 > > at setup) is breaking radeonfb on iBook G3 (with Radeon Mobility M6 LY).
 > > It crashes in pci_map_rom when called from radeonfb_map_ROM.  This is
 > > probably a dormant bug that was just uncovered by the change.
 > 
 > 2.6.13 hangs on boot on my PowerBook 5.4, reverting the disabled ROM
 > patch (appended for confirmation) fixes it.  2.6.13-rc7 was fine.

Same here, on an Apple eMac with Radeon graphics. 2.6.13-rc7 worked fine,
2.6.13 vanilla hangs early in the boot when radeonfb is about to take over
from OF. Reverting the patch below eliminates the hang.

/Mikael

 > diff-tree 755528c860b05fcecda1c88a2bdaffcb50760a7f (from 26aad69e3dd854abe9028ca873fb40b410a39dd7)
 > Author: Linus Torvalds <torvalds@g5.osdl.org>
 > Date:   Fri Aug 26 10:49:22 2005 -0700
 > 
 >     Ignore disabled ROM resources at setup
 >     
 >     Writing even a disabled value seems to mess up some matrox graphics
 >     cards.  It may be a card-related issue, but we may also be writing
 >     reserved low bits in the result.
 >     
 >     This was a fall-out of switching x86 over to the generic PCI resource
 >     allocation code, and needs more debugging.  In particular, the old x86
 >     code defaulted to not doing any resource allocations at all for ROM
 >     resources.
 >     
 >     In the meantime, this has been reported to make X happier by Helge
 >     Hafting <helgehaf@aitel.hist.no>.
 >     
 >     Signed-off-by: Linus Torvalds <torvalds@osdl.org>
 > 
 > diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
 > --- a/drivers/pci/setup-res.c
 > +++ b/drivers/pci/setup-res.c
 > @@ -53,7 +53,9 @@ pci_update_resource(struct pci_dev *dev,
 >  	if (resno < 6) {
 >  		reg = PCI_BASE_ADDRESS_0 + 4 * resno;
 >  	} else if (resno == PCI_ROM_RESOURCE) {
 > -		new |= res->flags & IORESOURCE_ROM_ENABLE;
 > +		if (!(res->flags & IORESOURCE_ROM_ENABLE))
 > +			return;
 > +		new |= PCI_ROM_ADDRESS_ENABLE;
 >  		reg = dev->rom_base_reg;
 >  	} else {
 >  		/* Hmm, non-standard resource. */
 > -
 > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
 > the body of a message to majordomo@vger.kernel.org
 > More majordomo info at  http://vger.kernel.org/majordomo-info.html
 > Please read the FAQ at  http://www.tux.org/lkml/
 > 

^ permalink raw reply

* Re: [PATCH] 1/2 Start header file merger (Was: Re: Beginning Merger Patch)
From: Christopher Friesen @ 2005-08-29 18:41 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc64-dev, linuxppc-dev@ozlabs.org
In-Reply-To: <1125089709.32488.35.camel@cashmere.sps.mot.com>

Jon Loeliger wrote:

> Anyone care to take a semi-authoritative stand on what
> symbol to use to distinguish 32/64-bit-ness in the
> include files?

I vote for __powerpc64__, if only to make it easier for the people who
have to sanitize the kernel headers for use in userspace.

Chris

^ permalink raw reply

* Question regarding partitioning of hardware drivers
From: Keith J Outwater @ 2005-08-29 20:04 UTC (permalink / raw)
  To: linuxppc-embedded

Hello everyone - 
I am developing an embedded ppc system using a 2.4 series kernel and I 
have a question regarding hardware drivers.
I have 4 LEDs connected to a GPIO port.  Each LED is controlled by a bit 
on the I/O port - set a bit to zero to turn the LED on, set the bit to one 
to turn the LED off.  The state of the bits are readable, so 
read-modify-write works.  The GPIO port is implemented with a Xilinx IP 
module and I have a driver available.  The Xilinx driver supports multiple 
GPIO ports. 
I have a driver available for the heartbeat LED ('status_led' by Wolfgang 
Denk) that works.
Now to the question:
I wish to use one of the four LEDs as a 'heartbeat' and the remainder as 
user LEDs.  Since all LEDs are accessed using the same hardware resource, 
the Linux heartbeat driver and the user GPIO driver will have to 
arbitrate.  I would like to separate the status led (heartbeat) driver 
from the GPIO driver as much as I can.  Is there an effective approach for 
doing this?  I think I could brute-force things by simply combining the 
GPIO and status LED drivers and then tell the 'unified' driver which LED 
to use as the heartbeat, but that approach eliminates the benefits of 
using existing drivers 'as-is', among other things.
I'm thinking that what I need to be able to do is give each driver access 
to a mutex that the drivers can then use to coordinate access to the 
hardware, but I'm not sure how to set up the mutex or where to put the 
code that does the initialization and mapping for the hardware access.

Keith

^ permalink raw reply

* Re: [PATCH] ppc32 :Added PCI support for MPC83xx
From: Kumar Gala @ 2005-08-29 22:00 UTC (permalink / raw)
  To: Dan Malek
  Cc: linux-kernel, linuxppc-embedded, Chu hanjin-r52514,
	Gala Kumar K.-galak, Li Tony-r64360
In-Reply-To: <e62c7e8ed239c5544e044bc5f0054bf3@embeddededge.com>


On Aug 29, 2005, at 1:07 PM, Dan Malek wrote:

>
> On Aug 29, 2005, at 1:42 PM, Kumar Gala wrote:
>
>
>> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c
>> b/arch/ppc/platforms/83xx/mpc834x_sys.c
>> --- a/arch/ppc/platforms/83xx/mpc834x_sys.c
>> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
>> @@ -62,9 +62,29 @@ extern unsigned long total_memory;    /* in
>>  unsigned char __res[sizeof (bd_t)];
>>
>>  #ifdef CONFIG_PCI
>> -#error "PCI is not supported"
>> -/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
>> -   see platforms/85xx/mpc85xx_ads_common.c */
>> +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 */
>> +    };
>> +
>> +    const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot =
>>
> 4;
>
>> +    return PCI_IRQ_TABLE_LOOKUP;
>> +}
>> +
>> +int
>> +mpc83xx_exclude_device(u_char bus, u_char devfn)
>> +{
>> +    return PCIBIOS_SUCCESSFUL;
>> +}
>>  #endif /* CONFIG_PCI */
>>
>
> Shouldn't this be in the PQ2FADS board specific file?  Not everyone
> is going to map IDSELs and IRQs this way.

mpc834x_sys is a board specific file.. This is stupid freescale  
naming.  The board was called MPC8349 SYS... Not sure what its called  
now.

>> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h
>> b/arch/ppc/platforms/83xx/mpc834x_sys.h
>> --- a/arch/ppc/platforms/83xx/mpc834x_sys.h
>> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
>> @@ -26,7 +26,7 @@
>>  #define VIRT_IMMRBAR        ((uint)0xfe000000)
>>
>>  #define BCSR_PHYS_ADDR        ((uint)0xf8000000)
>> -#define BCSR_SIZE        ((uint)(32 * 1024))
>> +#define BCSR_SIZE        ((uint)(128 * 1024))
>>
>>  #define BCSR_MISC_REG2_OFF    0x07
>>  #define BCSR_MISC_REG2_PORESET    0x01
>> @@ -34,23 +34,25 @@
>>  #define BCSR_MISC_REG3_OFF    0x08
>>  #define BCSR_MISC_REG3_CNFLOCK    0x80
>>
>> -#ifdef CONFIG_PCI
>> -/* PCI interrupt controller */
>> -#define PIRQA        MPC83xx_IRQ_IRQ4
>> -#define PIRQB        MPC83xx_IRQ_IRQ5
>> -#define PIRQC        MPC83xx_IRQ_IRQ6
>> -#define PIRQD        MPC83xx_IRQ_IRQ7
>> -
>> -#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
>> -#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
>> -
>> -#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
>> -#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
>> -
>> -#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
>> -#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
>> -
>> -#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
>> -#endif /* CONFIG_PCI */
>> +#define PIRQA    MPC83xx_IRQ_EXT4
>> +#define PIRQB    MPC83xx_IRQ_EXT5
>> +#define PIRQC    MPC83xx_IRQ_EXT6
>> +#define PIRQD    MPC83xx_IRQ_EXT7
>>
>
> The same thing with these BCSRs and IRQ mappings ....  FADS specific.

Same comment as above.

>
>
>> +
>> +#define MPC83xx_PCI1_LOWER_IO    0x00000000
>> +#define MPC83xx_PCI1_UPPER_IO    0x00ffffff
>> +#define MPC83xx_PCI1_LOWER_MEM    0x80000000
>> +#define MPC83xx_PCI1_UPPER_MEM    0x9fffffff
>> +#define MPC83xx_PCI1_IO_BASE    0xe2000000
>> +#define MPC83xx_PCI1_MEM_OFFSET    0x00000000
>> +#define MPC83xx_PCI1_IO_SIZE    0x01000000
>> +
>> +#define MPC83xx_PCI2_LOWER_IO    0x00000000
>> +#define MPC83xx_PCI2_UPPER_IO    0x00ffffff
>> +#define MPC83xx_PCI2_LOWER_MEM    0xa0000000
>> +#define MPC83xx_PCI2_UPPER_MEM    0xbfffffff
>> +#define MPC83xx_PCI2_IO_BASE    0xe3000000
>> +#define MPC83xx_PCI2_MEM_OFFSET    0x00000000
>> +#define MPC83xx_PCI2_IO_SIZE    0x01000000
>>
>
> These should be generic to everyone, and could be
> in the ppc83xx_pci.h file.  Maybe surround them with
> #ifndef so a board specific file could move the addresses
> if they wanted?  I don't think an #ifndef is needed for each
> define, maybe just #fndef MPC83xx_PCI1_LOWER_MEM
> and let the board define everything if they want anything different.


This is just like how we did 85xx.  The board specific file has to  
fill out these defines for its memory map.  I'm guess this is all  
confusion based on the name, if its not just that let me know.

- kumar

^ permalink raw reply

* [PATCH 5/7] arch: pci_find_device remove (ppc/kernel/pci.c)
From: Jiri Slaby @ 2005-08-29 22:26 UTC (permalink / raw)
  To: Greg KH; +Cc: linuxppc-dev, linux-pci, Linux Kernel Mailing List
In-Reply-To: <200508292220.j7TMKbNC019793@wscnet.wsc.cz>

Generated in 2.6.13-rc6-mm2 kernel version.

Signed-off-by: Jiri Slaby <xslaby@fi.muni.cz>

 pci.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -517,7 +517,7 @@ pcibios_allocate_resources(int pass)
 	u16 command;
 	struct resource *r;
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+	for_each_pci_dev(dev) {
 		pci_read_config_word(dev, PCI_COMMAND, &command);
 		for (idx = 0; idx < 6; idx++) {
 			r = &dev->resource[idx];
@@ -554,7 +554,7 @@ pcibios_assign_resources(void)
 	int idx;
 	struct resource *r;
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+	for_each_pci_dev(dev) {
 		int class = dev->class >> 8;
 
 		/* Don't touch classless devices and host bridges */
@@ -880,14 +880,15 @@ pci_device_from_OF_node(struct device_no
 	 */
 	if (!pci_to_OF_bus_map)
 		return 0;
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (pci_to_OF_bus_map[dev->bus->number] != *bus)
-			continue;
-		if (dev->devfn != *devfn)
-			continue;
-		*bus = dev->bus->number;
-		return 0;
-	}
+
+	for_each_pci_dev(dev)
+		if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
+				dev->devfn == *devfn) {
+			*bus = dev->bus->number;
+			pci_dev_put(dev);
+			return 0;
+		}
+
 	return -ENODEV;
 }
 

^ permalink raw reply

* [PATCH 6/7] arch: pci_find_device remove (ppc/platforms/85xx/mpc85xx_cds_common.c)
From: Jiri Slaby @ 2005-08-29 22:26 UTC (permalink / raw)
  To: Greg KH; +Cc: linuxppc-dev, linux-pci, Linux Kernel Mailing List
In-Reply-To: <200508292220.j7TMKbNC019793@wscnet.wsc.cz>

Generated in 2.6.13-rc6-mm2 kernel version.

Signed-off-by: Jiri Slaby <xslaby@fi.muni.cz>

 mpc85xx_cds_common.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -354,10 +354,10 @@ mpc85xx_cds_fixup_via(struct pci_control
 void __init
 mpc85xx_cds_pcibios_fixup(void)
 {
-        struct pci_dev *dev = NULL;
+        struct pci_dev *dev;
 	u_char		c;
 
-        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                         PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
                 /*
                  * U-Boot does not set the enable bits
@@ -374,21 +374,24 @@ mpc85xx_cds_pcibios_fixup(void)
 		 */
                 dev->irq = 14;
                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		pci_dev_put(dev);
         }
 
 	/*
 	 * Force legacy USB interrupt routing
 	 */
-        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                         PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
                 dev->irq = 10;
                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+		pci_dev_put(dev);
         }
 
-        if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                         PCI_DEVICE_ID_VIA_82C586_2, dev))) {
                 dev->irq = 11;
                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		pci_dev_put(dev);
         }
 }
 #endif /* CONFIG_PCI */

^ permalink raw reply

* [PATCH] rheap.c rh_alloc_fixed
From: Rune Torgersen @ 2005-08-29 22:43 UTC (permalink / raw)
  To: linuxppc-embedded

rh_alloc_fixed() used by cpm_dpalloc_fixed incorrectly returned next
free area=20
if the requested fixed area is not available.
This fixes it to return an error if requested area is not available.

Signed-off-by Rune Torgersen <runet@innovsys.com>

Index: linux-innsys/arch/ppc/lib/rheap.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- linux-innsys/arch/ppc/lib/rheap.c	(revision 29)
+++ linux-innsys/arch/ppc/lib/rheap.c	(working copy)
@@ -522,6 +522,10 @@
 	if (blk =3D=3D NULL)
 		return ERR_PTR(-ENOMEM);
=20
+	/* make sure block actually fits */
+	if (bs > s )=20
+		return ERR_PTR(-ENOMEM);
+
 	/* Perfect fit */
 	if (bs =3D=3D s && be =3D=3D e) {
 		/* Move from free list to taken list */

^ permalink raw reply

* Re: bd_t Cleaning: Board Changes
From: Mark A. Greer @ 2005-08-29 23:46 UTC (permalink / raw)
  To: Jon Loeliger, linuxppc-embedded@ozlabs.org
In-Reply-To: <429DFA28.30509@mvista.com>

On Wed, Jun 01, 2005 at 11:10:48AM -0700, Mark A. Greer wrote:
> Jon Loeliger wrote:
> 
> ><snip>
> >
> >Part Two of Four, the Board Changes.
> >
> >ppc/platforms/4xx/ash.h                 |   21 -
...

<snip again>

> <snip>
> 
> All,
> 
> So is this patch going to go in?  I haven't seen anyone "push it up".  
> The reason I'm asking is that I have a couple patches that I would like 
> to push up but they will collide with this one so I need to know if it 
> (or a variation thereof) is going to go in or not.
> 
> Thanks,
> 
> Mark

Jon,

Any news on this patch?

Mark

^ permalink raw reply

* Re: [PATCH 00/14] ppc32: Remove board ports that are no longer maintained
From: Kumar Gala @ 2005-08-30  1:46 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, Gala Kumar K.-galak, linuxppc-embedded
In-Reply-To: <20050727125746.54329281.akpm@osdl.org>


On Jul 27, 2005, at 2:57 PM, Andrew Morton wrote:

> Kumar Gala <galak@freescale.com> wrote:
>
>>
>> The following board ports are no longer maintained or have become
>>  obsolete:
>>
>>  adir
>>  ash
>>  beech
>>  cedar
>>  ep405
>>  k2
>>  mcpn765
>>  menf1
>>  oak
>>  pcore
>>  rainier
>>  redwood
>>  sm850
>>  spd823ts
>>
>>  We are there for removing support for them.
>>
>
> I'll merge all these into -mm for now, but will hold off sending  
> any of
> them upstream pending confirmation of which patches we really want to
> proceed with.

No one has screamed about anything but ep405 so all the others should  
go to Linus now.

- kumar

^ permalink raw reply

* [PATCH] MPC8xx PCMCIA driver
From: Marcelo Tosatti @ 2005-08-30  2:48 UTC (permalink / raw)
  To: linux-ppc-embedded; +Cc: Russell King, linux-kernel


Hi,

Here goes the 8xx PCMCIA driver, originally written by Magnus Damm, with
several improvements and fixes.

The driver was merged in v2.4 but never forward ported to v2.6.

Please review, comments are welcome (including aesthetic enhancements).

Russell: The driver is using pccard_nonstatic_ops for card window
management, even though the driver its marked SS_STATIC_MAP (using
mem->static_map).

Otherwise card IO windows aren't allocated properly.

diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -154,6 +154,16 @@ config TCIC
 	  "Bridge" is the name used for the hardware inside your computer that
 	  PCMCIA cards are plugged into. If unsure, say N.
 
+config PCMCIA_M8XX
+        tristate "MPC8xx PCMCIA support"
+        depends on PCMCIA && PPC
+        select PCCARD_NONSTATIC
+        help
+        Say Y here to include support for PowerPC 8xx series PCMCIA 
+        controller.
+
+        This driver is also available as a module called m8xx_pcmcia.
+
 config HD64465_PCMCIA
 	tristate "HD64465 host bridge support"
 	depends on HD64465 && PCMCIA
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_PD6729)				+= pd6729.o
 obj-$(CONFIG_I82365)				+= i82365.o
 obj-$(CONFIG_I82092)				+= i82092.o
 obj-$(CONFIG_TCIC)				+= tcic.o
+obj-$(CONFIG_PCMCIA_M8XX)			+= m8xx_pcmcia.o
 obj-$(CONFIG_HD64465_PCMCIA)			+= hd64465_ss.o
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
new file mode 100644
--- /dev/null
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -0,0 +1,1295 @@
+/* 
+ * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
+ *
+ * (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
+ * (C) 2001-2002 Montavista Software, Inc.
+ *     <mlocke@mvista.com>
+ *
+ * Support for two slots by Cyclades Corporation
+ *     <oliver.kurth@cyclades.de>
+ * Further fixes, v2.6 kernel port
+ *     <marcelo.tosatti@cyclades.com>
+ *
+ * "The ExCA standard specifies that socket controllers should provide 
+ * two IO and five memory windows per socket, which can be independently 
+ * configured and positioned in the host address space and mapped to 
+ * arbitrary segments of card address space. " - David A Hinds. 1999
+ *
+ * This controller does _not_ meet the ExCA standard.
+ * 
+ * m8xx pcmcia controller brief info:
+ * + 8 windows (attrib, mem, i/o)
+ * + up to two slots (SLOT_A and SLOT_B)
+ * + inputpins, outputpins, event and mask registers.
+ * - no offset register. sigh.
+ *
+ * Because of the lacking offset register we must map the whole card.
+ * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
+ * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO 
+ * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
+ * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
+ * They are maximum 64KByte each...
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <asm/irq.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+module_param(pc_debug, int, 0);
+#define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);
+#else
+#define dprintk(args...)
+#endif
+
+#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
+#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
+
+static const char *version = "Version 0.06, Aug 2005";
+MODULE_LICENSE("Dual MPL/GPL");
+
+#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
+
+/* The RPX series use SLOT_B */
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+#define CONFIG_PCMCIA_SLOT_B
+#define CONFIG_BD_IS_MHZ
+#endif
+
+/* The ADS board use SLOT_A */
+#ifdef CONFIG_ADS
+#define CONFIG_PCMCIA_SLOT_A
+#define CONFIG_BD_IS_MHZ
+#endif
+
+/* The FADS series are a mess */
+#ifdef CONFIG_FADS
+#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
+#define CONFIG_PCMCIA_SLOT_A
+#else
+#define CONFIG_PCMCIA_SLOT_B
+#endif
+#endif
+
+/* Cyclades ACS uses both slots */
+#ifdef CONFIG_PRxK
+#define CONFIG_PCMCIA_SLOT_A
+#define CONFIG_PCMCIA_SLOT_B
+#endif
+
+#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+
+#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
+
+#define PCMCIA_SOCKETS_NO 2  
+/* We have only 8 windows, dualsocket support will be limited. */
+#define PCMCIA_MEM_WIN_NO 2
+#define PCMCIA_IO_WIN_NO  2
+#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
+
+#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
+
+#define PCMCIA_SOCKETS_NO 1
+/* full support for one slot */
+#define PCMCIA_MEM_WIN_NO 5
+#define PCMCIA_IO_WIN_NO  2
+
+/* define _slot_ to be able to optimize macros */
+
+#ifdef CONFIG_PCMCIA_SLOT_A
+#define _slot_ 0
+#define PCMCIA_SLOT_MSG "SLOT_A"
+#else
+#define _slot_ 1
+#define PCMCIA_SLOT_MSG "SLOT_B"
+#endif
+
+#else
+#error m8xx_pcmcia: Bad configuration!
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0   */
+#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte     */
+#define PCMCIA_IO_WIN_BASE  _IO_BASE   /* base address for io window 0       */
+
+#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level      */
+
+/* ------------------------------------------------------------------------- */
+
+/* 2.4.x and newer has this always in HZ */
+#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
+
+static int pcmcia_schlvl = PCMCIA_SCHLVL;
+
+spinlock_t events_lock = SPIN_LOCK_UNLOCKED;
+
+
+#define PCMCIA_SOCKET_KEY_5V 1
+#define PCMCIA_SOCKET_KEY_LV 2
+
+/* look up table for pgcrx registers */
+static u_int *m8xx_pgcrx[2] = {
+	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,
+	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb
+}; 
+
+/*
+ * This structure is used to address each window in the PCMCIA controller. 
+ * 
+ * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly
+ * after pcmcia_win_t[n]... 
+ */
+
+typedef struct {             
+	uint	br;           
+	uint	or;
+} pcmcia_win_t;
+
+/* 
+ * For some reason the hardware guys decided to make both slots share
+ * some registers.
+ *
+ * Could someone invent object oriented hardware ?
+ *
+ * The macros are used to get the right bit from the registers.
+ * SLOT_A : slot = 0
+ * SLOT_B : slot = 1
+ */
+
+#define M8XX_PCMCIA_VS1(slot)      (0x80000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS2(slot)      (0x40000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS_MASK(slot)  (0xc0000000 >> (slot << 4))
+#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
+
+#define M8XX_PCMCIA_WP(slot)       (0x20000000 >> (slot << 4))
+#define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))
+#define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))
+#define M8XX_PCMCIA_BVD2(slot)     (0x04000000 >> (slot << 4))
+#define M8XX_PCMCIA_BVD1(slot)     (0x02000000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY(slot)      (0x01000000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_L(slot)    (0x00800000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_H(slot)    (0x00400000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_R(slot)    (0x00200000 >> (slot << 4))
+#define M8XX_PCMCIA_RDY_F(slot)    (0x00100000 >> (slot << 4))
+#define M8XX_PCMCIA_MASK(slot)     (0xFFFF0000 >> (slot << 4))
+
+#define M8XX_PCMCIA_POR_VALID    0x00000001
+#define M8XX_PCMCIA_POR_WRPROT   0x00000002
+#define M8XX_PCMCIA_POR_ATTRMEM  0x00000010
+#define M8XX_PCMCIA_POR_IO       0x00000018
+#define M8XX_PCMCIA_POR_16BIT    0x00000040
+
+#define M8XX_PGCRX(slot)  (*m8xx_pgcrx[slot])
+
+#define M8XX_PGCRX_CXOE    0x00000080
+#define M8XX_PGCRX_CXRESET 0x00000040
+
+/* we keep one lookup table per socket to check flags */ 
+
+#define PCMCIA_EVENTS_MAX 5  /* 4 max at a time + termination */
+
+typedef struct  {
+	u_int regbit;
+	u_int eventbit;
+} event_table_t;
+
+typedef struct socket_info_t {
+	void	(*handler)(void *info, u_int events);
+	void	*info;
+
+	u_int  slot;
+
+	socket_state_t state;
+	struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
+	struct pccard_io_map  io_win[PCMCIA_IO_WIN_NO];
+	event_table_t events[PCMCIA_EVENTS_MAX]; 
+	struct pcmcia_socket socket;
+} socket_info_t;
+
+static socket_info_t socket[PCMCIA_SOCKETS_NO];
+
+/* 
+ * Search this table to see if the windowsize is
+ * supported...
+ */
+
+#define M8XX_SIZES_NO 32
+
+static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] = 
+{
+	0x00000001, 0x00000002, 0x00000008, 0x00000004,
+	0x00000080, 0x00000040, 0x00000010, 0x00000020,
+	0x00008000, 0x00004000, 0x00001000, 0x00002000,
+	0x00000100, 0x00000200, 0x00000800, 0x00000400,
+
+	0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0x01000000, 0x02000000, 0xffffffff, 0x04000000,
+	0x00010000, 0x00020000, 0x00080000, 0x00040000,
+	0x00800000, 0x00400000, 0x00100000, 0x00200000
+};
+
+/* ------------------------------------------------------------------------- */
+
+static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);
+
+#define PCMCIA_BMT_LIMIT (15*4)  /* Bus Monitor Timeout value */
+
+/* ------------------------------------------------------------------------- */
+/* board specific stuff:                                                     */
+/* voltage_set(), hardware_enable() and hardware_disable()                   */
+/* ------------------------------------------------------------------------- */
+/* RPX Boards from Embedded Planet                                           */
+
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+
+/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
+ * SYPCR is write once only, therefore must the slowest memory be faster 
+ * than the bus monitor or we will get a machine check due to the bus timeout.
+ */
+
+#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
+
+#undef PCMCIA_BMT_LIMIT
+#define PCMCIA_BMT_LIMIT (6*8) 
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	u_int reg = 0;
+
+	switch(vcc) {
+	case 0: break;
+	case 33:
+		reg |= BCSR1_PCVCTL4;
+		break;
+	case 50: 
+		reg |= BCSR1_PCVCTL5;
+		break;
+	default: 
+		return 1;
+	}
+
+	switch(vpp) {
+	case 0: break;
+	case 33: 
+	case 50:
+		if(vcc == vpp)
+			reg |= BCSR1_PCVCTL6;
+		else
+			return 1;
+		break;
+	case 120: 
+		reg |= BCSR1_PCVCTL7;
+	default:
+		return 1;
+	}
+
+	if(!((vcc == 50) || (vcc == 0)))
+		return 1;
+
+	/* first, turn off all power */
+
+	*((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
+				     | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
+
+	/* enable new powersettings */
+
+	*((uint *)RPX_CSR_ADDR) |= reg;
+
+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_RPXCLASSIC */
+
+/* FADS Boards from Motorola                                               */
+
+#if defined(CONFIG_FADS)
+
+#define PCMCIA_BOARD_MSG "FADS"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	uint reg = 0;
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= BCSR1_PCCVCC0;
+			break;
+		case 50:
+			reg |= BCSR1_PCCVCC1;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= BCSR1_PCCVPP1;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= BCSR1_PCCVPP0;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	/* first, turn off all power */
+	*((uint *)BCSR1) &= ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK);
+
+	/* enable new powersettings */
+	*((uint *)BCSR1) |= reg;
+
+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static void hardware_enable(int slot)
+{
+	*((uint *)BCSR1) &= ~BCSR1_PCCEN;
+}
+
+static void hardware_disable(int slot)
+{
+	*((uint *)BCSR1) |=  BCSR1_PCCEN;
+}
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Motorola MBX860                                                           */
+
+#if defined(CONFIG_MBX)
+
+#define PCMCIA_BOARD_MSG "MBX"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	unsigned char reg = 0;
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= CSR2_VCC_33;
+			break;
+		case 50:
+			reg |= CSR2_VCC_50;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= CSR2_VPP_VCC;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= CSR2_VPP_12;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	/* first, turn off all power */
+	*((unsigned char *)MBX_CSR2_ADDR) &= ~(CSR2_VCC_MASK | CSR2_VPP_MASK);
+
+	/* enable new powersettings */
+	*((unsigned char *)MBX_CSR2_ADDR) |= reg;
+
+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_MBX */
+
+#if defined(CONFIG_PRxK)
+#include <asm/cpld.h>
+extern volatile fpga_pc_regs *fpga_pc;
+
+#define PCMCIA_BOARD_MSG "MPC855T"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	unsigned char reg = 0;
+	unsigned char regread;
+	cpld_regs *ccpld = get_cpld();
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= PCMCIA_VCC_33;
+			break;
+		case 50:
+			reg |= PCMCIA_VCC_50;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= PCMCIA_VPP_VCC;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= PCMCIA_VPP_12;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	reg = reg >> (slot << 2);
+	regread = ccpld->fpga_pc_ctl;
+	if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
+		/* enable new powersettings */
+		regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+		ccpld->fpga_pc_ctl = reg | regread;
+		mdelay(100);
+	}
+
+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_PRxK */
+
+static void m8xx_shutdown(void)
+{
+	u_int m, i;
+	pcmcia_win_t *w;
+
+	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
+		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 
+			M8XX_PCMCIA_MASK(i); 
+		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
+			&= ~M8XX_PCMCIA_MASK(i);
+ 
+		/* turn off interrupt and disable CxOE */
+		M8XX_PGCRX(i) = M8XX_PGCRX_CXOE;
+		
+		/* turn off memory windows */
+		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+			w->or = 0;  /* set to not valid */
+			w++;
+		}
+		
+		/* turn off voltage */
+		voltage_set(i, 0, 0);
+		
+		/* disable external hardware */
+		hardware_disable(i);
+	}
+
+	free_irq(pcmcia_schlvl, NULL);
+}
+
+/* copied from tcic.c */
+
+static int m8xx_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+        int ret = 0;
+        if (level == SUSPEND_SAVE_STATE)
+                ret = pcmcia_socket_dev_suspend(dev, state);
+        return ret;
+}
+                                                                                       
+static int m8xx_drv_resume(struct device *dev, u32 level)
+{
+        int ret = 0;
+        if (level == RESUME_RESTORE_STATE)
+                ret = pcmcia_socket_dev_resume(dev);
+        return ret;
+}
+                                                                                       
+static struct device_driver m8xx_driver = {
+        .name = "m8xx-pcmcia",
+        .bus = &platform_bus_type,
+        .suspend = m8xx_drv_suspend,
+        .resume = m8xx_drv_resume,
+};
+
+static struct platform_device m8xx_device = {
+        .name = "m8xx-pcmcia",
+        .id = 0,
+};
+
+static u_int pending_events[PCMCIA_SOCKETS_NO];
+static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
+
+static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	socket_info_t *s;
+	event_table_t *e;
+	u_int i, events, pscr, pipr, per;
+
+	dprintk("Interrupt!\n");
+	/* get interrupt sources */
+
+	pscr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
+	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
+	per = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per;
+
+	for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		s = &socket[i];
+		e = &s->events[0]; 
+		events = 0;
+
+		while(e->regbit) {
+			if(pscr & e->regbit)
+				events |= e->eventbit;
+	    
+				e++;
+		}
+
+		/* 
+		 * report only if both card detect signals are the same 
+		 * not too nice done, 
+		 * we depend on that CD2 is the bit to the left of CD1...
+		 */
+		if(events & SS_DETECT)
+			if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
+				(pipr & M8XX_PCMCIA_CD1(i)))
+			{
+				events &= ~SS_DETECT;
+			}
+
+#ifdef PCMCIA_GLITCHY_CD
+		/*
+		 * I've experienced CD problems with my ADS board.
+		 * We make an extra check to see if there was a
+		 * real change of Card detection.
+		 */
+	  
+		if((events & SS_DETECT) && 
+		   ((pipr &
+		     (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
+		   (s->state.Vcc | s->state.Vpp)) {
+			events &= ~SS_DETECT;
+			/*printk( "CD glitch workaround - CD = 0x%08x!\n",
+				(pipr & (M8XX_PCMCIA_CD2(i) 
+					 | M8XX_PCMCIA_CD1(i))));*/
+		}
+#endif
+	  
+		/* call the handler */
+
+		dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
+			"pipr = 0x%08x\n", 
+			i, events, pscr, pipr);
+  
+		if(events) {
+			spin_lock(&pending_event_lock);
+			pending_events[i] |= events;
+			spin_unlock(&pending_event_lock);
+			/* 
+			 * Turn off RDY_L bits in the PER mask on 
+			 * CD interrupt receival.
+			 *
+			 * They can generate bad interrupts on the
+			 * ACS4,8,16,32.   - marcelo
+			 */
+			per &= ~M8XX_PCMCIA_RDY_L(0);
+			per &= ~M8XX_PCMCIA_RDY_L(1);
+
+			((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per = per;
+
+			if (events)
+				pcmcia_parse_events(&socket[i].socket, events);
+		}
+	}
+	
+	/* clear the interrupt sources */
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
+
+	dprintk("Interrupt done.\n");
+
+	return IRQ_HANDLED;
+}
+
+static u_int m8xx_get_graycode(u_int size)
+{
+	u_int k;
+
+	for(k = 0; k < M8XX_SIZES_NO; k++)
+		if(m8xx_size_to_gray[k] == size)
+			break;
+
+	if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
+		k = -1;
+
+	return k;
+}
+
+static u_int m8xx_get_speed(u_int ns, u_int is_io)
+{
+	u_int reg, clocks, psst, psl, psht;
+
+	if(!ns) {
+
+		/*
+		 * We get called with IO maps setup to 0ns
+		 * if not specified by the user.
+		 * They should be 255ns.
+		 */
+
+		if(is_io)
+			ns = 255;
+		else 
+			ns = 100;  /* fast memory if 0 */
+	}
+
+	/* 
+	 * In PSST, PSL, PSHT fields we tell the controller
+	 * timing parameters in CLKOUT clock cycles.
+	 * CLKOUT is the same as GCLK2_50.
+	 */
+
+/* how we want to adjust the timing - in percent */
+
+#define ADJ 180 /* 80 % longer accesstime - to be sure */
+
+	clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
+	clocks = (clocks * ADJ) / (100*1000);
+	if(clocks >= PCMCIA_BMT_LIMIT) {
+		printk( "Max access time limit reached\n");
+		clocks = PCMCIA_BMT_LIMIT-1;
+	}
+
+	psst = clocks / 7;          /* setup time */
+	psht = clocks / 7;          /* hold time */
+	psl  = (clocks * 5) / 7;    /* strobe length */
+
+	psst += clocks - (psst + psht + psl);
+
+	reg =  psst << 12;
+	reg |= psl  << 7; 
+	reg |= psht << 16;
+
+	return reg;
+}
+
+static int m8xx_get_status(struct pcmcia_socket *sock, u_int *value)
+{
+	int lsock = container_of(sock, struct socket_info_t, socket)->slot;
+	socket_info_t *s = &socket[lsock];
+	u_int pipr, reg;
+
+	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
+
+	*value  = ((pipr & (M8XX_PCMCIA_CD1(lsock) 
+			    | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
+	*value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
+
+	if (s->state.flags & SS_IOCARD)
+		*value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
+	else {
+		*value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
+		*value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
+		*value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
+	}
+	
+	if (s->state.Vcc | s->state.Vpp)
+		*value |= SS_POWERON;
+	
+	/*
+	 * Voltage detection:
+	 * This driver only supports 16-Bit pc-cards.
+	 * Cardbus is not handled here.
+	 * 
+	 * To determine what voltage to use we must read the VS1 and VS2 pin.
+	 * Depending on what socket type is present,
+	 * different combinations mean different things.
+	 *
+	 * Card Key  Socket Key   VS1   VS2   Card         Vcc for CIS parse
+	 *   
+	 * 5V        5V, LV*      NC    NC    5V only       5V (if available)
+	 *           
+	 * 5V        5V, LV*      GND   NC    5 or 3.3V     as low as possible
+	 *
+	 * 5V        5V, LV*      GND   GND   5, 3.3, x.xV  as low as possible
+	 *
+	 * LV*       5V            -     -    shall not fit into socket
+	 *
+	 * LV*       LV*          GND   NC    3.3V only     3.3V
+	 *
+	 * LV*       LV*          NC    GND   x.xV          x.xV (if avail.)
+	 *
+	 * LV*       LV*          GND   GND   3.3 or x.xV   as low as possible
+	 *
+	 * *LV means Low Voltage
+	 *
+	 *
+	 * That gives us the following table:
+	 *
+	 * Socket    VS1  VS2   Voltage
+	 *
+	 * 5V        NC   NC    5V
+	 * 5V        NC   GND   none (should not be possible)
+	 * 5V        GND  NC    >= 3.3V
+	 * 5V        GND  GND   >= x.xV 
+	 *
+	 * LV        NC   NC    5V   (if available)
+	 * LV        NC   GND   x.xV (if available)
+	 * LV        GND  NC    3.3V 
+	 * LV        GND  GND   >= x.xV 
+	 * 
+	 * So, how do I determine if I have a 5V or a LV
+	 * socket on my board?  Look at the socket!
+	 *
+	 * 
+	 * Socket with 5V key:
+	 * ++--------------------------------------------+
+	 * ||                                            |
+	 * ||                                           ||
+	 * ||                                           ||
+	 * |                                             |
+	 * +---------------------------------------------+
+	 *
+	 * Socket with LV key:
+	 * ++--------------------------------------------+
+	 * ||                                            |
+	 * |                                            ||
+	 * |                                            ||
+	 * |                                             |
+	 * +---------------------------------------------+
+	 *
+	 *
+	 * With other words - LV only cards does not fit
+	 * into the 5V socket!
+	 */
+
+	/* read out VS1 and VS2 */
+
+	reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock)) 
+		>> M8XX_PCMCIA_VS_SHIFT(lsock);
+
+	if(socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
+		switch(reg) {
+		case 1:
+			*value |= SS_3VCARD;
+			break; /* GND, NC - 3.3V only */
+		case 2:
+			*value |= SS_XVCARD;
+			break; /* NC. GND - x.xV only */
+		};
+	}
+
+	dprintk("GetStatus(%d) = %#2.2x\n", lsock, *value);
+	return 0;
+}
+  
+static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+	int lsock = container_of(sock, struct socket_info_t, socket)->slot;
+	*state = socket[lsock].state; /* copy the whole structure */
+
+	dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
+	      "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
+	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+	return 0;
+}
+
+static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+	int lsock = container_of(sock, struct socket_info_t, socket)->slot;
+	socket_info_t *s = &socket[lsock];
+	event_table_t *e;
+	u_int reg;
+	u_long flags;
+
+	dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
+	      "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
+	      state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
+
+	/* First, set voltage - bail out if invalid */
+	if(voltage_set(lsock, state->Vcc, state->Vpp))
+		return -EINVAL;
+
+	/* Take care of reset... */
+	if(state->flags & SS_RESET) 
+		M8XX_PGCRX(lsock) |=  M8XX_PGCRX_CXRESET; /* active high */
+	else
+		M8XX_PGCRX(lsock) &= ~M8XX_PGCRX_CXRESET;
+
+	/* ... and output enable. */
+
+	/* The CxOE signal is connected to a 74541 on the ADS.
+	   I guess most other boards used the ADS as a reference.
+	   I tried to control the CxOE signal with SS_OUTPUT_ENA,
+	   but the reset signal seems connected via the 541. 
+	   If the CxOE is left high are some signals tristated and
+	   no pullups are present -> the cards act wierd.
+	   So right now the buffers are enabled if the power is on. */
+
+	if(state->Vcc || state->Vpp)
+		M8XX_PGCRX(lsock) &= ~M8XX_PGCRX_CXOE; /* active low */
+	else
+		M8XX_PGCRX(lsock) |=  M8XX_PGCRX_CXOE;
+	
+	/* 
+	 * We'd better turn off interrupts before 
+	 * we mess with the events-table..
+	 */
+
+	spin_lock_irqsave(&events_lock, flags);
+
+	/*
+	 * Play around with the interrupt mask to be able to
+	 * give the events the generic pcmcia driver wants us to.
+	 */
+
+	e = &s->events[0]; 
+	reg = 0;
+
+	if(state->csc_mask & SS_DETECT) {
+		e->eventbit = SS_DETECT;
+		reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock) 
+				    | M8XX_PCMCIA_CD1(lsock));
+		e++;
+	}
+	if(state->flags & SS_IOCARD) {
+		/* 
+		 * I/O card
+		 */
+		if(state->csc_mask & SS_STSCHG) {
+			e->eventbit = SS_STSCHG;
+			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
+			e++;
+		}
+		/*
+		 * If io_irq is non-zero we should enable irq.
+		 */
+		if(state->io_irq) {
+			M8XX_PGCRX(lsock) |= 
+				mk_int_int_mask(state->io_irq) << 24;
+			/*
+			 * Strange thing here:
+			 * The manual does not tell us which interrupt
+			 * the sources generate.
+			 * Anyhow, I found out that RDY_L generates IREQLVL.
+			 *
+			 * We use level triggerd interrupts, and they don't
+			 * have to be cleared in PSCR in the interrupt handler.
+			 */
+			reg |= M8XX_PCMCIA_RDY_L(lsock);  
+		}
+		else
+			M8XX_PGCRX(lsock) &= 0x00ffffff;
+	}
+	else {
+		/*
+		 * Memory card
+		 */
+		if(state->csc_mask & SS_BATDEAD) {
+			e->eventbit = SS_BATDEAD;
+			reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
+			e++;
+		}
+		if(state->csc_mask & SS_BATWARN) {
+			e->eventbit = SS_BATWARN;
+			reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
+			e++;
+		}
+		/* What should I trigger on - low/high,raise,fall? */
+		if(state->csc_mask & SS_READY) {
+			e->eventbit = SS_READY;
+			reg |= e->regbit = 0; //??
+			e++;
+		}
+	}
+	
+	e->regbit = 0;  /* terminate list */
+	
+	/* 
+	 * Clear the status changed .
+	 * Port A and Port B share the same port.
+	 * Writing ones will clear the bits.
+	 */
+	
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = reg;
+	
+	/*
+	 * Write the mask.
+	 * Port A and Port B share the same port.
+	 * Need for read-modify-write. 
+	 * Ones will enable the interrupt.
+	 */
+
+	/*
+	  reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
+	  & M8XX_PCMCIA_MASK(lsock);
+	*/
+
+	reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
+		& ( M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1) );
+	
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per = reg;
+	
+	spin_unlock_irqrestore(&events_lock, flags);
+
+	/* copy the struct and modify the copy */
+	
+	s->state = *state;
+	
+	return 0;
+}
+
+static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+{
+	int lsock = container_of(sock, struct socket_info_t, socket)->slot;
+
+	socket_info_t *s = &socket[lsock];
+	pcmcia_win_t *w;
+	u_int reg, winnr;
+	
+
+#define M8XX_SIZE (io->stop - io->start + 1)   
+#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
+
+	dprintk( "SetIOMap(%d, %d, %#2.2x, %d ns, "
+	      "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
+	      io->speed, io->start, io->stop);
+
+	if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff) 
+	    || (io->stop > 0xffff) || (io->stop < io->start)) 
+		return -EINVAL;
+	
+	if((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
+		return -EINVAL;
+
+	if(io->flags & MAP_ACTIVE) {
+
+		dprintk( "io->flags & MAP_ACTIVE\n");
+
+		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) 
+			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;
+	
+		/* setup registers */
+
+		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w += winnr;
+	
+		w->or = 0; /* turn off window first */
+		w->br = M8XX_BASE;
+	
+		reg <<= 27;     
+  		reg |= M8XX_PCMCIA_POR_IO |(lsock << 2);
+
+		reg |= m8xx_get_speed(io->speed, 1);
+
+		if(io->flags & MAP_WRPROT) 
+			reg |= M8XX_PCMCIA_POR_WRPROT;
+		
+		/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
+		if(io->flags & MAP_16BIT)
+			reg |= M8XX_PCMCIA_POR_16BIT;
+	
+		if(io->flags & MAP_ACTIVE) 
+			reg |= M8XX_PCMCIA_POR_VALID;
+	
+		w->or = reg;
+
+		dprintk("Socket %u: Mapped io window %u at %#8.8x, "
+		      "OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+	} else {
+		/* shutdown IO window */
+		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
+			+ (lsock * PCMCIA_IO_WIN_NO) + io->map;
+
+		/* setup registers */
+
+		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+		w += winnr;
+
+		w->or = 0; /* turn off window */
+		w->br = 0; /* turn off base address */
+
+		dprintk("Socket %u: Unmapped io window %u at %#8.8x, "
+			"OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
+	}
+
+	/* copy the struct and modify the copy */
+	s->io_win[io->map] = *io; 
+	s->io_win[io->map].flags &= (MAP_WRPROT 
+				     | MAP_16BIT
+				     | MAP_ACTIVE);
+	dprintk("SetIOMap exit\n");
+
+	return 0;
+}
+
+static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+{
+	int lsock = container_of(sock, struct socket_info_t, socket)->slot;
+	socket_info_t *s = &socket[lsock];
+	pcmcia_win_t *w;
+	struct pccard_mem_map *old;
+	u_int reg, winnr;
+	
+	dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, "
+	      "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+	      mem->speed, mem->static_start, mem->card_start);
+
+	if ((mem->map >= PCMCIA_MEM_WIN_NO)
+//	    || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
+	    || (mem->card_start >= 0x04000000) 
+	    || (mem->static_start & 0xfff)                /* 4KByte resolution */
+	    || (mem->card_start & 0xfff))                   
+		return -EINVAL;
+	
+	if((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
+		printk( "Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
+		return -EINVAL;
+	}
+	reg <<= 27;
+
+	winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
+	
+	/* Setup the window in the pcmcia controller */
+	
+	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+	w += winnr;
+	
+	reg |= lsock << 2;
+	
+	reg |= m8xx_get_speed(mem->speed, 0);
+
+	if(mem->flags & MAP_ATTRIB) 
+		reg |=  M8XX_PCMCIA_POR_ATTRMEM;
+	
+	if(mem->flags & MAP_WRPROT) 
+		reg |= M8XX_PCMCIA_POR_WRPROT;
+	
+	if(mem->flags & MAP_16BIT) 
+		reg |= M8XX_PCMCIA_POR_16BIT;
+	
+	if(mem->flags & MAP_ACTIVE) 
+		reg |= M8XX_PCMCIA_POR_VALID;
+	
+	w->or = reg;
+
+	dprintk("Socket %u: Mapped memory window %u at %#8.8x, "
+	      "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
+
+	if(mem->flags & MAP_ACTIVE) {
+		/* get the new base address */
+		mem->static_start = PCMCIA_MEM_WIN_BASE + 
+			(PCMCIA_MEM_WIN_SIZE * winnr)
+			+ mem->card_start; 
+	}
+
+	dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
+	      "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
+	      mem->speed, mem->static_start, mem->card_start);
+
+	/* copy the struct and modify the copy */
+	
+	old = &s->mem_win[mem->map];
+	
+	*old = *mem;
+	old->flags &= (MAP_ATTRIB
+		       | MAP_WRPROT 
+		       | MAP_16BIT
+		       | MAP_ACTIVE);
+
+	return 0;
+}
+
+static int m8xx_sock_init(struct pcmcia_socket *sock)
+{
+	int i;
+	pccard_io_map io = { 0, 0, 0, 0, 1 };
+	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+
+	dprintk( "sock_init(%d)\n", s);
+
+	m8xx_set_socket(sock, &dead_socket);
+	for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
+		io.map = i;
+		m8xx_set_io_map(sock, &io);
+	}
+	for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
+		mem.map = i;
+		m8xx_set_mem_map(sock, &mem);
+	}
+
+	return 0;
+
+}
+
+static int m8xx_suspend(struct pcmcia_socket *sock)
+{
+	return m8xx_set_socket(sock, &dead_socket);
+}
+
+static struct pccard_operations m8xx_services = {
+	.init	= m8xx_sock_init,	
+	.suspend = m8xx_suspend,
+	.get_status = m8xx_get_status,
+	.get_socket = m8xx_get_socket,
+	.set_socket = m8xx_set_socket,
+	.set_io_map = m8xx_set_io_map,
+	.set_mem_map = m8xx_set_mem_map,
+};
+
+static int __init m8xx_init(void)
+{
+	pcmcia_win_t *w;
+	u_int i,m;
+
+	pcmcia_info("%s\n", version);
+
+	if (driver_register(&m8xx_driver))
+		return -1;
+
+	pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG 
+		    " with IRQ %u.\n", pcmcia_schlvl); 
+
+	/* Configure Status change interrupt */
+
+	if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, 
+			  "m8xx_pcmcia", NULL)) {
+		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", 
+			     pcmcia_schlvl);
+		return -1;
+	}
+
+	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 
+		M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1); 
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
+		&= ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));
+ 
+/* connect interrupt and disable CxOE */
+
+	M8XX_PGCRX(0) = M8XX_PGCRX_CXOE |
+		(mk_int_int_mask(pcmcia_schlvl) << 16);
+	M8XX_PGCRX(1) = M8XX_PGCRX_CXOE |
+		(mk_int_int_mask(pcmcia_schlvl) << 16);
+
+/* intialize the fixed memory windows */
+
+	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
+		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+			w->br = PCMCIA_MEM_WIN_BASE + 
+				(PCMCIA_MEM_WIN_SIZE 
+				 * (m + i * PCMCIA_MEM_WIN_NO));
+
+			w->or = 0;  /* set to not valid */
+
+			w++;
+		}
+	}
+
+/* turn off voltage */
+	voltage_set(0, 0, 0);
+	voltage_set(1, 0, 0);
+
+/* Enable external hardware */
+	hardware_enable(0);
+	hardware_enable(1);
+
+	platform_device_register(&m8xx_device);
+
+	for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) {
+		socket[i].slot = i;
+		socket[i].socket.owner = THIS_MODULE;
+		socket[i].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
+		socket[i].socket.irq_mask = 0x000;
+		socket[i].socket.map_size = 0x1000;
+		socket[i].socket.io_offset = 0;
+		socket[i].socket.pci_irq = i  ? 7 : 9;
+		socket[i].socket.ops = &m8xx_services;
+		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+		socket[i].socket.cb_dev = NULL;
+		socket[i].socket.dev.dev = &m8xx_device.dev;
+	}
+
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
+		pcmcia_register_socket(&socket[i].socket);
+
+	return 0;
+}
+
+static void __exit m8xx_exit(void)
+{
+	int i;
+
+	for (i = 0; i < PCMCIA_SOCKETS_NO; i++) 
+		pcmcia_unregister_socket(&socket[i].socket);
+
+	m8xx_shutdown();
+
+	platform_device_unregister(&m8xx_device);
+	driver_unregister(&m8xx_driver);
+}
+
+module_init(m8xx_init);
+module_exit(m8xx_exit);

^ permalink raw reply

* Re: [PATCH] MPC8xx PCMCIA driver
From: Jeff Garzik @ 2005-08-30  3:39 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Russell King, linux-kernel, linux-ppc-embedded
In-Reply-To: <20050830024840.GA5381@dmt.cnet>

Marcelo Tosatti wrote:
> +static int voltage_set(int slot, int vcc, int vpp)
> +{
> +	u_int reg = 0;
> +
> +	switch(vcc) {
> +	case 0: break;
> +	case 33:
> +		reg |= BCSR1_PCVCTL4;
> +		break;
> +	case 50: 
> +		reg |= BCSR1_PCVCTL5;
> +		break;
> +	default: 
> +		return 1;
> +	}
> +
> +	switch(vpp) {
> +	case 0: break;
> +	case 33: 
> +	case 50:
> +		if(vcc == vpp)
> +			reg |= BCSR1_PCVCTL6;
> +		else
> +			return 1;
> +		break;
> +	case 120: 
> +		reg |= BCSR1_PCVCTL7;
> +	default:
> +		return 1;
> +	}
> +
> +	if(!((vcc == 50) || (vcc == 0)))
> +		return 1;
> +
> +	/* first, turn off all power */
> +
> +	*((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
> +				     | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
> +
> +	/* enable new powersettings */
> +
> +	*((uint *)RPX_CSR_ADDR) |= reg;

Should use bus read/write functions, such as foo_readl() or iowrite32().

Don't use weird types in kernel code such as 'uint'.  Use the more 
explicitly-sized u32.


> +	return 0;
> +}
> +
> +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
> +#define hardware_enable(_slot_)  /* No hardware to enable */
> +#define hardware_disable(_slot_) /* No hardware to disable */
> +
> +#endif /* CONFIG_RPXCLASSIC */
> +
> +/* FADS Boards from Motorola                                               */
> +
> +#if defined(CONFIG_FADS)
> +
> +#define PCMCIA_BOARD_MSG "FADS"
> +
> +static int voltage_set(int slot, int vcc, int vpp)
> +{
> +	uint reg = 0;
> +
> +	switch(vcc) {
> +		case 0:
> +			break;
> +		case 33:
> +			reg |= BCSR1_PCCVCC0;
> +			break;
> +		case 50:
> +			reg |= BCSR1_PCCVCC1;
> +			break;
> +		default:
> +			return 1;
> +	}
> +
> +	switch(vpp) {
> +		case 0:
> +			break;
> +		case 33:
> +		case 50:
> +			if(vcc == vpp)
> +				reg |= BCSR1_PCCVPP1;
> +			else
> +				return 1;
> +			break;
> +		case 120:
> +			if ((vcc == 33) || (vcc == 50))
> +				reg |= BCSR1_PCCVPP0;
> +			else
> +				return 1;
> +		default:
> +			return 1;
> +	}
> +
> +	/* first, turn off all power */
> +	*((uint *)BCSR1) &= ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK);
> +
> +	/* enable new powersettings */
> +	*((uint *)BCSR1) |= reg;

ditto

> +	return 0;
> +}
> +
> +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
> +
> +static void hardware_enable(int slot)
> +{
> +	*((uint *)BCSR1) &= ~BCSR1_PCCEN;
> +}

ditto

> +static void hardware_disable(int slot)
> +{
> +	*((uint *)BCSR1) |=  BCSR1_PCCEN;
> +}

etc.


> +/* ------------------------------------------------------------------------- */
> +/* Motorola MBX860                                                           */
> +
> +#if defined(CONFIG_MBX)
> +
> +#define PCMCIA_BOARD_MSG "MBX"
> +
> +static int voltage_set(int slot, int vcc, int vpp)
> +{
> +	unsigned char reg = 0;
> +
> +	switch(vcc) {
> +		case 0:
> +			break;
> +		case 33:
> +			reg |= CSR2_VCC_33;
> +			break;
> +		case 50:
> +			reg |= CSR2_VCC_50;
> +			break;
> +		default:
> +			return 1;
> +	}
> +
> +	switch(vpp) {
> +		case 0:
> +			break;
> +		case 33:
> +		case 50:
> +			if(vcc == vpp)
> +				reg |= CSR2_VPP_VCC;
> +			else
> +				return 1;
> +			break;
> +		case 120:
> +			if ((vcc == 33) || (vcc == 50))
> +				reg |= CSR2_VPP_12;
> +			else
> +				return 1;
> +		default:
> +			return 1;
> +	}
> +
> +	/* first, turn off all power */
> +	*((unsigned char *)MBX_CSR2_ADDR) &= ~(CSR2_VCC_MASK | CSR2_VPP_MASK);
> +
> +	/* enable new powersettings */
> +	*((unsigned char *)MBX_CSR2_ADDR) |= reg;

ditto.

also, use u8 not unsigned char.


> +	return 0;
> +}
> +
> +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
> +#define hardware_enable(_slot_)  /* No hardware to enable */
> +#define hardware_disable(_slot_) /* No hardware to disable */
> +
> +#endif /* CONFIG_MBX */
> +
> +#if defined(CONFIG_PRxK)
> +#include <asm/cpld.h>
> +extern volatile fpga_pc_regs *fpga_pc;
> +
> +#define PCMCIA_BOARD_MSG "MPC855T"
> +
> +static int voltage_set(int slot, int vcc, int vpp)
> +{
> +	unsigned char reg = 0;
> +	unsigned char regread;
> +	cpld_regs *ccpld = get_cpld();
> +
> +	switch(vcc) {
> +		case 0:
> +			break;
> +		case 33:
> +			reg |= PCMCIA_VCC_33;
> +			break;
> +		case 50:
> +			reg |= PCMCIA_VCC_50;
> +			break;
> +		default:
> +			return 1;
> +	}
> +
> +	switch(vpp) {
> +		case 0:
> +			break;
> +		case 33:
> +		case 50:
> +			if(vcc == vpp)
> +				reg |= PCMCIA_VPP_VCC;
> +			else
> +				return 1;
> +			break;
> +		case 120:
> +			if ((vcc == 33) || (vcc == 50))
> +				reg |= PCMCIA_VPP_12;
> +			else
> +				return 1;
> +		default:
> +			return 1;
> +	}
> +
> +	reg = reg >> (slot << 2);
> +	regread = ccpld->fpga_pc_ctl;
> +	if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
> +		/* enable new powersettings */
> +		regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
> +		ccpld->fpga_pc_ctl = reg | regread;
> +		mdelay(100);

should be msleep() AFAICS


> +	return 0;
> +}
> +
> +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
> +#define hardware_enable(_slot_)  /* No hardware to enable */
> +#define hardware_disable(_slot_) /* No hardware to disable */
> +
> +#endif /* CONFIG_PRxK */
> +
> +static void m8xx_shutdown(void)
> +{
> +	u_int m, i;
> +	pcmcia_win_t *w;
> +
> +	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
> +		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
> +
> +		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 
> +			M8XX_PCMCIA_MASK(i); 
> +		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
> +			&= ~M8XX_PCMCIA_MASK(i);
> + 
> +		/* turn off interrupt and disable CxOE */
> +		M8XX_PGCRX(i) = M8XX_PGCRX_CXOE;
> +		
> +		/* turn off memory windows */
> +		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
> +			w->or = 0;  /* set to not valid */
> +			w++;
> +		}
> +		
> +		/* turn off voltage */
> +		voltage_set(i, 0, 0);
> +		
> +		/* disable external hardware */
> +		hardware_disable(i);
> +	}
> +
> +	free_irq(pcmcia_schlvl, NULL);

don't you want to free_irq() first?



> +}
> +
> +/* copied from tcic.c */
> +
> +static int m8xx_drv_suspend(struct device *dev, u32 state, u32 level)
> +{
> +        int ret = 0;
> +        if (level == SUSPEND_SAVE_STATE)
> +                ret = pcmcia_socket_dev_suspend(dev, state);
> +        return ret;
> +}
> +                                                                                       
> +static int m8xx_drv_resume(struct device *dev, u32 level)
> +{
> +        int ret = 0;
> +        if (level == RESUME_RESTORE_STATE)
> +                ret = pcmcia_socket_dev_resume(dev);
> +        return ret;
> +}
> +                                                                                       
> +static struct device_driver m8xx_driver = {
> +        .name = "m8xx-pcmcia",
> +        .bus = &platform_bus_type,
> +        .suspend = m8xx_drv_suspend,
> +        .resume = m8xx_drv_resume,
> +};
> +
> +static struct platform_device m8xx_device = {
> +        .name = "m8xx-pcmcia",
> +        .id = 0,
> +};
> +
> +static u_int pending_events[PCMCIA_SOCKETS_NO];
> +static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
> +
> +static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
> +{
> +	socket_info_t *s;
> +	event_table_t *e;
> +	u_int i, events, pscr, pipr, per;
> +
> +	dprintk("Interrupt!\n");
> +	/* get interrupt sources */
> +
> +	pscr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
> +	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
> +	per = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per;
> +
> +	for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
> +		s = &socket[i];
> +		e = &s->events[0]; 
> +		events = 0;
> +
> +		while(e->regbit) {
> +			if(pscr & e->regbit)
> +				events |= e->eventbit;
> +	    
> +				e++;
> +		}
> +
> +		/* 
> +		 * report only if both card detect signals are the same 
> +		 * not too nice done, 
> +		 * we depend on that CD2 is the bit to the left of CD1...
> +		 */
> +		if(events & SS_DETECT)
> +			if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
> +				(pipr & M8XX_PCMCIA_CD1(i)))
> +			{
> +				events &= ~SS_DETECT;
> +			}
> +
> +#ifdef PCMCIA_GLITCHY_CD
> +		/*
> +		 * I've experienced CD problems with my ADS board.
> +		 * We make an extra check to see if there was a
> +		 * real change of Card detection.
> +		 */
> +	  
> +		if((events & SS_DETECT) && 
> +		   ((pipr &
> +		     (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
> +		   (s->state.Vcc | s->state.Vpp)) {
> +			events &= ~SS_DETECT;
> +			/*printk( "CD glitch workaround - CD = 0x%08x!\n",
> +				(pipr & (M8XX_PCMCIA_CD2(i) 
> +					 | M8XX_PCMCIA_CD1(i))));*/
> +		}
> +#endif
> +	  
> +		/* call the handler */
> +
> +		dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
> +			"pipr = 0x%08x\n", 
> +			i, events, pscr, pipr);
> +  
> +		if(events) {
> +			spin_lock(&pending_event_lock);
> +			pending_events[i] |= events;
> +			spin_unlock(&pending_event_lock);
> +			/* 
> +			 * Turn off RDY_L bits in the PER mask on 
> +			 * CD interrupt receival.
> +			 *
> +			 * They can generate bad interrupts on the
> +			 * ACS4,8,16,32.   - marcelo
> +			 */
> +			per &= ~M8XX_PCMCIA_RDY_L(0);
> +			per &= ~M8XX_PCMCIA_RDY_L(1);
> +
> +			((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per = per;
> +
> +			if (events)
> +				pcmcia_parse_events(&socket[i].socket, events);
> +		}
> +	}
> +	
> +	/* clear the interrupt sources */
> +	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;

more direct memory writes which should be foo_writel()


> +	dprintk("Interrupt done.\n");
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int m8xx_suspend(struct pcmcia_socket *sock)
> +{
> +	return m8xx_set_socket(sock, &dead_socket);
> +}
> +
> +static struct pccard_operations m8xx_services = {
> +	.init	= m8xx_sock_init,	
> +	.suspend = m8xx_suspend,
> +	.get_status = m8xx_get_status,
> +	.get_socket = m8xx_get_socket,
> +	.set_socket = m8xx_set_socket,
> +	.set_io_map = m8xx_set_io_map,
> +	.set_mem_map = m8xx_set_mem_map,
> +};
> +
> +static int __init m8xx_init(void)
> +{
> +	pcmcia_win_t *w;
> +	u_int i,m;
> +
> +	pcmcia_info("%s\n", version);
> +
> +	if (driver_register(&m8xx_driver))
> +		return -1;
> +
> +	pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG 
> +		    " with IRQ %u.\n", pcmcia_schlvl); 
> +
> +	/* Configure Status change interrupt */
> +
> +	if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, 
> +			  "m8xx_pcmcia", NULL)) {
> +		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", 
> +			     pcmcia_schlvl);
> +		return -1;
> +	}
> +
> +	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
> +
> +	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 
> +		M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1); 
> +	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 
> +		&= ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));

ditto etc.

^ permalink raw reply

* Re: [PATCH] MPC8xx PCMCIA driver
From: Marcelo Tosatti @ 2005-08-30  3:53 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Russell King, linux-kernel, linux-ppc-embedded
In-Reply-To: <4313D4D6.7080108@pobox.com>

On Mon, Aug 29, 2005 at 11:39:02PM -0400, Jeff Garzik wrote:
> Marcelo Tosatti wrote:
> >+static int voltage_set(int slot, int vcc, int vpp)
> >+{
> >+	u_int reg = 0;
> >+
> >+	switch(vcc) {
> >+	case 0: break;
> >+	case 33:
> >+		reg |= BCSR1_PCVCTL4;
> >+		break;
> >+	case 50: 
> >+		reg |= BCSR1_PCVCTL5;
> >+		break;
> >+	default: 
> >+		return 1;
> >+	}
> >+
> >+	switch(vpp) {
> >+	case 0: break;
> >+	case 33: 
> >+	case 50:
> >+		if(vcc == vpp)
> >+			reg |= BCSR1_PCVCTL6;
> >+		else
> >+			return 1;
> >+		break;
> >+	case 120: 
> >+		reg |= BCSR1_PCVCTL7;
> >+	default:
> >+		return 1;
> >+	}
> >+
> >+	if(!((vcc == 50) || (vcc == 0)))
> >+		return 1;
> >+
> >+	/* first, turn off all power */
> >+
> >+	*((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
> >+				     | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
> >+
> >+	/* enable new powersettings */
> >+
> >+	*((uint *)RPX_CSR_ADDR) |= reg;
> 
> Should use bus read/write functions, such as foo_readl() or iowrite32().

The memory map structure which contains device configuration/registers
is _always_ directly mapped with pte's (the 8xx is a chip with builtin
UART/network/etc functionality).

I don't think there is a need to use read/write acessors.

> Don't use weird types in kernel code such as 'uint'.  Use the more 
> explicitly-sized u32.

OK, will fix the types and address the rest of your comments.

Thanks!

^ permalink raw reply

* Cross compile krb5 issue for ppc
From: JohnsonCheng @ 2005-08-30  4:16 UTC (permalink / raw)
  To: linux-ppc-embedded

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

When I cross compile krb5-1.4.1 for ppc on x86, I got the following error
message.

# cd krb5-1.4.1/src

#./configure -host=powerpc-linux

Checking for constructor/destructor attribute support. configure: error:
Cannot test for constructor/destructor support when cross compiling

 

Even if I have to some modifications to pass configure, but still cannot
make successfully.

Do anybody can give me advice or tell me where to get krb5 library for ppc?

 

Thanks,

Johnson Cheng


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

^ permalink raw reply

* Re: [PATCH] ppc32 :Added PCI support for MPC83xx
From: Kumar Gala @ 2005-08-30  4:27 UTC (permalink / raw)
  To: Li Tony-r64360; +Cc: Chu hanjin-r52514, linux-kernel, linuxppc-embedded
In-Reply-To: <9FCDBA58F226D911B202000BDBAD467302BEB8C6@zch01exm40.ap.freescale.net>

Hmm, well the PCI spec seems to be clear on the fact that PCI  
interrupts should be level sensitive.

- kumar

On Aug 29, 2005, at 10:02 PM, Li Tony-r64360 wrote:

> I think it is OK. The external interrupt can be edged. And it works  
> well
> in my board.
>
> Tony Li
>
> -----Original Message-----
> From: Gala Kumar K.-galak
> Sent: Tuesday, August 30, 2005 1:43 AM
> To: Li Tony-r64360
> Cc: linuxppc-embedded; linux-kernel@vger.kernel.org; Gala Kumar
> K.-galak; Chu hanjin-r52514
> Subject: Re: [PATCH] ppc32 :Added PCI support for MPC83xx
>
> I noticed that you aren't updating the senses array in
> mpc834x_sys_init_IRQ for the PCI interrupt lines, is this correct?
> Should they not be IRQ_SENSE_LEVEL?
>
> Also, I've done a bit of cosmetic cleanup to the patch, take a look  
> and
> let me know if it works.  Once we close on the IRQ sense issue I will
> send this upstream.
>
> - kumar
>
> ---
>
> diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
> --- a/arch/ppc/Kconfig
> +++ b/arch/ppc/Kconfig
> @@ -713,6 +713,12 @@ config MPC834x_SYS
>      help
>        This option enables support for the MPC 834x SYS evaluation
> board.
>
> +      Be aware that PCI buses can only function when SYS board is
> plugged on
> +      PIB (Platform IO Board) board from Freescale which provide 3
> PCI slots.
> +      Just like PC,the board level initalization is bootloader`s
> responsiblilty.
> +      The PCI deponds on bootloader configurate board corretly.
> Refer to Freescale
> +      to get more information about this.
> +
>  endchoice
>
>  config PQ2ADS
> @@ -1193,6 +1199,11 @@ config PCI
>  config PCI_DOMAINS
>      bool
>      default PCI
> +
> +config MPC83xx_PCI2
> +    bool "  Supprt for 2nd PCI host controller"
> +    depends on PCI && MPC834x
> +    default y if MPC834x_SYS
>
>  config PCI_QSPAN
>      bool "QSpan PCI"
> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c
> b/arch/ppc/platforms/83xx/mpc834x_sys.c
> --- a/arch/ppc/platforms/83xx/mpc834x_sys.c
> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
> @@ -62,9 +62,29 @@ extern unsigned long total_memory;    /* in
>  unsigned char __res[sizeof (bd_t)];
>
>  #ifdef CONFIG_PCI
> -#error "PCI is not supported"
> -/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
> -   see platforms/85xx/mpc85xx_ads_common.c */
> +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 */
> +    };
> +
> +    const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot =
> 4;
> +    return PCI_IRQ_TABLE_LOOKUP;
> +}
> +
> +int
> +mpc83xx_exclude_device(u_char bus, u_char devfn) {
> +    return PCIBIOS_SUCCESSFUL;
> +}
>  #endif /* CONFIG_PCI */
>
>  /*
> ********************************************************************** 
> **
> @@ -88,7 +108,7 @@ mpc834x_sys_setup_arch(void)
>
>  #ifdef CONFIG_PCI
>      /* setup PCI host bridges */
> -    mpc83xx_sys_setup_hose();
> +    mpc83xx_setup_hose();
>  #endif
>      mpc83xx_early_serial_map();
>
> diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h
> b/arch/ppc/platforms/83xx/mpc834x_sys.h
> --- a/arch/ppc/platforms/83xx/mpc834x_sys.h
> +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
> @@ -26,7 +26,7 @@
>  #define VIRT_IMMRBAR        ((uint)0xfe000000)
>
>  #define BCSR_PHYS_ADDR        ((uint)0xf8000000)
> -#define BCSR_SIZE        ((uint)(32 * 1024))
> +#define BCSR_SIZE        ((uint)(128 * 1024))
>
>  #define BCSR_MISC_REG2_OFF    0x07
>  #define BCSR_MISC_REG2_PORESET    0x01
> @@ -34,23 +34,25 @@
>  #define BCSR_MISC_REG3_OFF    0x08
>  #define BCSR_MISC_REG3_CNFLOCK    0x80
>
> -#ifdef CONFIG_PCI
> -/* PCI interrupt controller */
> -#define PIRQA        MPC83xx_IRQ_IRQ4
> -#define PIRQB        MPC83xx_IRQ_IRQ5
> -#define PIRQC        MPC83xx_IRQ_IRQ6
> -#define PIRQD        MPC83xx_IRQ_IRQ7
> -
> -#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
> -#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
> -
> -#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
> -#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
> -
> -#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
> -#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
> -
> -#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
> -#endif /* CONFIG_PCI */
> +#define PIRQA    MPC83xx_IRQ_EXT4
> +#define PIRQB    MPC83xx_IRQ_EXT5
> +#define PIRQC    MPC83xx_IRQ_EXT6
> +#define PIRQD    MPC83xx_IRQ_EXT7
> +
> +#define MPC83xx_PCI1_LOWER_IO    0x00000000
> +#define MPC83xx_PCI1_UPPER_IO    0x00ffffff
> +#define MPC83xx_PCI1_LOWER_MEM    0x80000000
> +#define MPC83xx_PCI1_UPPER_MEM    0x9fffffff
> +#define MPC83xx_PCI1_IO_BASE    0xe2000000
> +#define MPC83xx_PCI1_MEM_OFFSET    0x00000000
> +#define MPC83xx_PCI1_IO_SIZE    0x01000000
> +
> +#define MPC83xx_PCI2_LOWER_IO    0x00000000
> +#define MPC83xx_PCI2_UPPER_IO    0x00ffffff
> +#define MPC83xx_PCI2_LOWER_MEM    0xa0000000
> +#define MPC83xx_PCI2_UPPER_MEM    0xbfffffff
> +#define MPC83xx_PCI2_IO_BASE    0xe3000000
> +#define MPC83xx_PCI2_MEM_OFFSET    0x00000000
> +#define MPC83xx_PCI2_IO_SIZE    0x01000000
>
>  #endif                /* __MACH_MPC83XX_SYS_H__ */
> diff --git a/arch/ppc/syslib/ppc83xx_pci.h
> b/arch/ppc/syslib/ppc83xx_pci.h new file mode 100644
> --- /dev/null
> +++ b/arch/ppc/syslib/ppc83xx_pci.h
> @@ -0,0 +1,151 @@
> +/* Created by Tony Li <tony.li@freescale.com>
> + * Copyright (c) 2005 freescale semiconductor
> + *
> + * 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.
> + *
> + * This program 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 program; if not, write  to the Free Software Foundation,
> +Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#ifndef __PPC_SYSLIB_PPC83XX_PCI_H
> +#define __PPC_SYSLIB_PPC83XX_PCI_H
> +
> +typedef struct immr_clk {
> +    u32 spmr; /* system PLL mode Register  */
> +    u32 occr; /* output clock control Register  */
> +    u32 sccr; /* system clock control Register  */
> +    u8 res0[0xF4];
> +} immr_clk_t;
> +
> +/*
> + * Sequencer
> + */
> +typedef struct immr_ios {
> +    u32    potar0;
> +    u8    res0[4];
> +    u32    pobar0;
> +    u8    res1[4];
> +    u32    pocmr0;
> +    u8    res2[4];
> +    u32    potar1;
> +    u8    res3[4];
> +    u32    pobar1;
> +    u8    res4[4];
> +    u32    pocmr1;
> +    u8    res5[4];
> +    u32    potar2;
> +    u8    res6[4];
> +    u32    pobar2;
> +    u8    res7[4];
> +    u32    pocmr2;
> +    u8    res8[4];
> +    u32    potar3;
> +    u8    res9[4];
> +    u32    pobar3;
> +    u8    res10[4];
> +    u32    pocmr3;
> +    u8    res11[4];
> +    u32    potar4;
> +    u8    res12[4];
> +    u32    pobar4;
> +    u8    res13[4];
> +    u32    pocmr4;
> +    u8    res14[4];
> +    u32    potar5;
> +    u8    res15[4];
> +    u32    pobar5;
> +    u8    res16[4];
> +    u32    pocmr5;
> +    u8    res17[4];
> +    u8    res18[0x60];
> +    u32    pmcr;
> +    u8    res19[4];
> +    u32    dtcr;
> +    u8    res20[4];
> +} immr_ios_t;
> +#define POTAR_TA_MASK    0x000fffff
> +#define POBAR_BA_MASK    0x000fffff
> +#define POCMR_EN    0x80000000
> +#define POCMR_IO    0x40000000 /* 0--memory space 1--I/O space */
> +#define POCMR_SE    0x20000000 /* streaming enable */
> +#define POCMR_DST    0x10000000 /* 0--PCI1 1--PCI2 */
> +#define POCMR_CM_MASK    0x000fffff
> +
> +/*
> + * PCI Controller Control and Status Registers  */ typedef struct
> +immr_pcictrl {
> +    u32    esr;
> +    u32    ecdr;
> +    u32    eer;
> +    u32    eatcr;
> +    u32    eacr;
> +    u32    eeacr;
> +    u32    edlcr;
> +    u32    edhcr;
> +    u32    gcr;
> +    u32    ecr;
> +    u32    gsr;
> +    u8    res0[12];
> +    u32    pitar2;
> +    u8    res1[4];
> +    u32    pibar2;
> +    u32    piebar2;
> +    u32    piwar2;
> +    u8    res2[4];
> +    u32    pitar1;
> +    u8    res3[4];
> +    u32    pibar1;
> +    u32    piebar1;
> +    u32    piwar1;
> +    u8    res4[4];
> +    u32    pitar0;
> +    u8    res5[4];
> +    u32    pibar0;
> +    u8    res6[4];
> +    u32    piwar0;
> +    u8    res7[132];
> +} immr_pcictrl_t;
> +#define PITAR_TA_MASK    0x000fffff
> +#define PIBAR_MASK    0xffffffff
> +#define PIEBAR_EBA_MASK    0x000fffff
> +#define PIWAR_EN    0x80000000
> +#define PIWAR_PF    0x20000000
> +#define PIWAR_RTT_MASK    0x000f0000
> +#define PIWAR_RTT_NO_SNOOP    0x00040000
> +#define PIWAR_RTT_SNOOP    0x00050000
> +#define PIWAR_WTT_MASK    0x0000f000
> +#define PIWAR_WTT_NO_SNOOP    0x00004000
> +#define PIWAR_WTT_SNOOP    0x00005000
> +#define PIWAR_IWS_MASK    0x0000003F
> +#define PIWAR_IWS_4K    0x0000000B
> +#define PIWAR_IWS_8K    0x0000000C
> +#define PIWAR_IWS_16K    0x0000000D
> +#define PIWAR_IWS_32K    0x0000000E
> +#define PIWAR_IWS_64K    0x0000000F
> +#define PIWAR_IWS_128K    0x00000010
> +#define PIWAR_IWS_256K    0x00000011
> +#define PIWAR_IWS_512K    0x00000012
> +#define PIWAR_IWS_1M    0x00000013
> +#define PIWAR_IWS_2M    0x00000014
> +#define PIWAR_IWS_4M    0x00000015
> +#define PIWAR_IWS_8M    0x00000016
> +#define PIWAR_IWS_16M    0x00000017
> +#define PIWAR_IWS_32M    0x00000018
> +#define PIWAR_IWS_64M    0x00000019
> +#define PIWAR_IWS_128M    0x0000001A
> +#define PIWAR_IWS_256M    0x0000001B
> +#define PIWAR_IWS_512M    0x0000001C
> +#define PIWAR_IWS_1G    0x0000001D
> +#define PIWAR_IWS_2G    0x0000001E
> +
> +#endif /* __PPC_SYSLIB_PPC83XX_PCI_H */
> diff --git a/arch/ppc/syslib/ppc83xx_setup.c
> b/arch/ppc/syslib/ppc83xx_setup.c
> --- a/arch/ppc/syslib/ppc83xx_setup.c
> +++ b/arch/ppc/syslib/ppc83xx_setup.c
> @@ -11,6 +11,17 @@
>   * 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 program 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 program; if not, write  to the Free Software Foundation,
> + Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * Added PCI support -- Tony Li <tony.li@freescale.com>
>   */
>
>  #include <linux/config.h>
> @@ -31,6 +42,10 @@
>  #include <asm/delay.h>
>
>  #include <syslib/ppc83xx_setup.h>
> +#if defined(CONFIG_PCI)
> +#include <asm/delay.h>
> +#include <syslib/ppc83xx_pci.h>
> +#endif
>
>  phys_addr_t immrbar;
>
> @@ -162,4 +177,237 @@ mpc83xx_halt(void)
>      for(;;);
>  }
>
> -/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
> +#if defined(CONFIG_PCI)
> +void __init
> +mpc83xx_setup_pci1(struct pci_controller *hose) {
> +    u16 reg16;
> +    volatile immr_pcictrl_t * pci_ctrl;
> +    volatile immr_ios_t * ios;
> +    bd_t *binfo = (bd_t *) __res;
> +
> +    pci_ctrl = ioremap(binfo->bi_immr_base + 0x8500,
> sizeof(immr_pcictrl_t));
> +    ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
> +
> +    /*
> +     * Configure PCI Outbound Translation Windows
> +     */
> +    ios->potar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POTAR_TA_MASK;
> +    ios->pobar0 = (MPC83xx_PCI1_LOWER_MEM >> 12) & POBAR_BA_MASK;
> +    ios->pocmr0 = POCMR_EN |
> +        (((0xffffffff - (MPC83xx_PCI1_UPPER_MEM -
> +                MPC83xx_PCI1_LOWER_MEM)) >> 12) &
> POCMR_CM_MASK);
> +
> +    /* mapped to PCI1 IO space */
> +    ios->potar1 = (MPC83xx_PCI1_LOWER_IO >> 12) & POTAR_TA_MASK;
> +    ios->pobar1 = (MPC83xx_PCI1_IO_BASE >> 12) & POBAR_BA_MASK;
> +    ios->pocmr1 = POCMR_EN | POCMR_IO |
> +        (((0xffffffff - (MPC83xx_PCI1_UPPER_IO -
> +                MPC83xx_PCI1_LOWER_IO)) >> 12) &
> POCMR_CM_MASK);
> +
> +    /*
> +     * Configure PCI Inbound Translation Windows
> +     */
> +    pci_ctrl->pitar1 = 0x0;
> +    pci_ctrl->pibar1 = 0x0;
> +    pci_ctrl->piebar1 = 0x0;
> +    pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
> +PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
> +
> +    /*
> +     * Release PCI RST signal
> +     */
> +    pci_ctrl->gcr = 0;
> +    udelay(2000);
> +    pci_ctrl->gcr = 1;
> +    udelay(2000);
> +
> +    reg16 = 0xff;
> +    early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND,
> &reg16);
> +    reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER |
> PCI_COMMAND_MEMORY;
> +    early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND,
>
> +reg16);
> +
> +    /*
> +     * Clear non-reserved bits in status register.
> +     */
> +    early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS,
> 0xffff);
> +    early_write_config_byte(hose, hose->first_busno, 0,
> PCI_LATENCY_TIMER,
> +0x80);
> +
> +    iounmap(pci_ctrl);
> +    iounmap(ios);
> +}
> +
> +void __init
> +mpc83xx_setup_pci2(struct pci_controller *hose) {
> +    u16 reg16;
> +    volatile immr_pcictrl_t * pci_ctrl;
> +    volatile immr_ios_t * ios;
> +    bd_t *binfo = (bd_t *) __res;
> +
> +    pci_ctrl = ioremap(binfo->bi_immr_base + 0x8600,
> sizeof(immr_pcictrl_t));
> +    ios = ioremap(binfo->bi_immr_base + 0x8400, sizeof(immr_ios_t));
> +
> +    /*
> +     * Configure PCI Outbound Translation Windows
> +     */
> +    ios->potar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POTAR_TA_MASK;
> +    ios->pobar3 = (MPC83xx_PCI2_LOWER_MEM >> 12) & POBAR_BA_MASK;
> +    ios->pocmr3 = POCMR_EN | POCMR_DST |
> +        (((0xffffffff - (MPC83xx_PCI2_UPPER_MEM -
> +                MPC83xx_PCI2_LOWER_MEM)) >> 12) &
> POCMR_CM_MASK);
> +
> +    /* mapped to PCI2 IO space */
> +    ios->potar4 = (MPC83xx_PCI2_LOWER_IO >> 12) & POTAR_TA_MASK;
> +    ios->pobar4 = (MPC83xx_PCI2_IO_BASE >> 12) & POBAR_BA_MASK;
> +    ios->pocmr4 = POCMR_EN | POCMR_DST | POCMR_IO |
> +        (((0xffffffff - (MPC83xx_PCI2_UPPER_IO -
> +                MPC83xx_PCI2_LOWER_IO)) >> 12) &
> POCMR_CM_MASK);
> +
> +    /*
> +     * Configure PCI Inbound Translation Windows
> +     */
> +    pci_ctrl->pitar1 = 0x0;
> +    pci_ctrl->pibar1 = 0x0;
> +    pci_ctrl->piebar1 = 0x0;
> +    pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
> +PIWAR_WTT_SNOOP | PIWAR_IWS_2G;
> +
> +    /*
> +     * Release PCI RST signal
> +     */
> +    pci_ctrl->gcr = 0;
> +    udelay(2000);
> +    pci_ctrl->gcr = 1;
> +    udelay(2000);
> +
> +    reg16 = 0xff;
> +    early_read_config_word(hose, hose->first_busno, 0, PCI_COMMAND,
> &reg16);
> +    reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER |
> PCI_COMMAND_MEMORY;
> +    early_write_config_word(hose, hose->first_busno, 0, PCI_COMMAND,
>
> +reg16);
> +
> +    /*
> +     * Clear non-reserved bits in status register.
> +     */
> +    early_write_config_word(hose, hose->first_busno, 0, PCI_STATUS,
> 0xffff);
> +    early_write_config_byte(hose, hose->first_busno, 0,
> PCI_LATENCY_TIMER,
> +0x80);
> +
> +    iounmap(pci_ctrl);
> +    iounmap(ios);
> +}
> +
> +/*
> + * PCI buses can be enabled only if SYS board combinates with PIB
> + * (Platform IO Board) board which provide 3 PCI slots. There is 2  
> PCI
> +buses
> + * and 3 PCI slots, so people must configure the routes between them
> +before
> + * enable PCI bus. This routes are under the control of PCA9555PW
> +device which
> + * can be accessed via I2C bus 2 and are configured by firmware.  
> Refer
> +to
> + * Freescale to get more information about firmware configuration.
> + */
> +
> +extern int mpc83xx_exclude_device(u_char bus, u_char devfn);  
> extern int
>
> +mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel,
> +        unsigned char pin);
> +void __init
> +mpc83xx_setup_hose(void)
> +{
> +    u32 val32;
> +    volatile immr_clk_t * clk;
> +    struct pci_controller * hose1;
> +#ifdef CONFIG_MPC83xx_PCI2
> +    struct pci_controller * hose2;
> +#endif
> +    bd_t * binfo = (bd_t *)__res;
> +
> +    clk = ioremap(binfo->bi_immr_base + 0xA00,
> +            sizeof(immr_clk_t));
> +
> +    /*
> +     * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
> +     */
> +    val32 = clk->occr;
> +    udelay(2000);
> +    clk->occr = 0xff000000;
> +    udelay(2000);
> +
> +    iounmap(clk);
> +
> +    hose1 = pcibios_alloc_controller();
> +    if(!hose1)
> +        return;
> +
> +    ppc_md.pci_swizzle = common_swizzle;
> +    ppc_md.pci_map_irq = mpc83xx_map_irq;
> +
> +    hose1->bus_offset = 0;
> +    hose1->first_busno = 0;
> +    hose1->last_busno = 0xff;
> +
> +    setup_indirect_pci(hose1, binfo->bi_immr_base +
> PCI1_CFG_ADDR_OFFSET,
> +            binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
> +    hose1->set_cfg_type = 1;
> +
> +    mpc83xx_setup_pci1(hose1);
> +
> +    hose1->pci_mem_offset = MPC83xx_PCI1_MEM_OFFSET;
> +    hose1->mem_space.start = MPC83xx_PCI1_LOWER_MEM;
> +    hose1->mem_space.end = MPC83xx_PCI1_UPPER_MEM;
> +
> +    hose1->io_base_phys = MPC83xx_PCI1_IO_BASE;
> +    hose1->io_space.start = MPC83xx_PCI1_LOWER_IO;
> +    hose1->io_space.end = MPC83xx_PCI1_UPPER_IO; #ifdef
> +CONFIG_MPC83xx_PCI2
> +    isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
> +            MPC83xx_PCI1_IO_SIZE + MPC83xx_PCI2_IO_SIZE);
> #else
> +    isa_io_base = (unsigned long)ioremap(MPC83xx_PCI1_IO_BASE,
> +            MPC83xx_PCI1_IO_SIZE);
> +#endif /* CONFIG_MPC83xx_PCI2 */
> +    hose1->io_base_virt = (void *)isa_io_base;
> +    /* setup resources */
> +    pci_init_resource(&hose1->io_resource,
> +            MPC83xx_PCI1_LOWER_IO,
> +            MPC83xx_PCI1_UPPER_IO,
> +            IORESOURCE_IO, "PCI host bridge 1");
> +    pci_init_resource(&hose1->mem_resources[0],
> +            MPC83xx_PCI1_LOWER_MEM,
> +            MPC83xx_PCI1_UPPER_MEM,
> +            IORESOURCE_MEM, "PCI host bridge 1");
> +
> +    ppc_md.pci_exclude_device = mpc83xx_exclude_device;
> +    hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno);
> +
> +#ifdef CONFIG_MPC83xx_PCI2
> +    hose2 = pcibios_alloc_controller();
> +    if(!hose2)
> +        return;
> +
> +    hose2->bus_offset = hose1->last_busno + 1;
> +    hose2->first_busno = hose1->last_busno + 1;
> +    hose2->last_busno = 0xff;
> +    setup_indirect_pci(hose2, binfo->bi_immr_base +
> PCI2_CFG_ADDR_OFFSET,
> +            binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
> +    hose2->set_cfg_type = 1;
> +
> +    mpc83xx_setup_pci2(hose2);
> +
> +    hose2->pci_mem_offset = MPC83xx_PCI2_MEM_OFFSET;
> +    hose2->mem_space.start = MPC83xx_PCI2_LOWER_MEM;
> +    hose2->mem_space.end = MPC83xx_PCI2_UPPER_MEM;
> +
> +    hose2->io_base_phys = MPC83xx_PCI2_IO_BASE;
> +    hose2->io_space.start = MPC83xx_PCI2_LOWER_IO;
> +    hose2->io_space.end = MPC83xx_PCI2_UPPER_IO;
> +    hose2->io_base_virt = (void *)(isa_io_base +
> MPC83xx_PCI1_IO_SIZE);
> +    /* setup resources */
> +    pci_init_resource(&hose2->io_resource,
> +            MPC83xx_PCI2_LOWER_IO,
> +            MPC83xx_PCI2_UPPER_IO,
> +            IORESOURCE_IO, "PCI host bridge 2");
> +    pci_init_resource(&hose2->mem_resources[0],
> +            MPC83xx_PCI2_LOWER_MEM,
> +            MPC83xx_PCI2_UPPER_MEM,
> +            IORESOURCE_MEM, "PCI host bridge 2");
> +
> +    hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
>
> +#endif /* CONFIG_MPC83xx_PCI2 */ } #endif /*CONFIG_PCI*/
> diff --git a/arch/ppc/syslib/ppc83xx_setup.h
> b/arch/ppc/syslib/ppc83xx_setup.h
> --- a/arch/ppc/syslib/ppc83xx_setup.h
> +++ b/arch/ppc/syslib/ppc83xx_setup.h
> @@ -12,6 +12,14 @@
>   * Free Software Foundation;  either version 2 of the  License, or  
> (at
> your
>   * option) any later version.
>   *
> + * This program 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 program; if not, write  to the Free Software Foundation,
> + Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.
>   */
>
>  #ifndef __PPC_SYSLIB_PPC83XX_SETUP_H
> @@ -19,7 +27,6 @@
>
>  #include <linux/config.h>
>  #include <linux/init.h>
> -#include <asm/ppcboot.h>
>
>  extern unsigned long mpc83xx_find_end_of_memory(void) __init;  extern
> long mpc83xx_time_init(void) __init; @@ -31,13 +38,11 @@ extern void
> mpc83xx_halt(void);  extern void mpc83xx_setup_hose(void) __init;
>
>  /* PCI config */
> -#if 0
> -#define PCI1_CFG_ADDR_OFFSET    (FIXME)
> -#define PCI1_CFG_DATA_OFFSET    (FIXME)
> +#define PCI1_CFG_ADDR_OFFSET (0x8300)
> +#define PCI1_CFG_DATA_OFFSET (0x8304)
>
> -#define PCI2_CFG_ADDR_OFFSET    (FIXME)
> -#define PCI2_CFG_DATA_OFFSET    (FIXME)
> -#endif
> +#define PCI2_CFG_ADDR_OFFSET (0x8380)
> +#define PCI2_CFG_DATA_OFFSET (0x8384)
>
>  /* Serial Config */
>  #ifdef CONFIG_SERIAL_MANY_PORTS
>

^ permalink raw reply

* Re: [PATCH] MPC8xx PCMCIA driver
From: Paul Mackerras @ 2005-08-30  4:32 UTC (permalink / raw)
  To: Marcelo Tosatti
  Cc: Russell King, linux-kernel, linux-ppc-embedded, Jeff Garzik
In-Reply-To: <20050830035338.GA5755@dmt.cnet>

Marcelo Tosatti writes:

> The memory map structure which contains device configuration/registers
> is _always_ directly mapped with pte's (the 8xx is a chip with builtin
> UART/network/etc functionality).
> 
> I don't think there is a need to use read/write acessors.

Generally on PowerPC you need to use at least the eieio instruction to
prevent reordering of the loads and stores to the device.  It's
possible that 8xx is sufficiently in-order that you get away without
putting in barrier instructions (eieio or sync), but it's not good
practice to omit them.

You can use accessors such as in_be32 and in_le32 in this situation,
when you have a kernel virtual address that is already mapped to the
device.

Regards,
Paul.

^ permalink raw reply

* Re: [PATCH] MPC8xx PCMCIA driver
From: Jeff Garzik @ 2005-08-30  4:33 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: Russell King, linux-kernel, linux-ppc-embedded
In-Reply-To: <20050830035338.GA5755@dmt.cnet>

Marcelo Tosatti wrote:
> On Mon, Aug 29, 2005 at 11:39:02PM -0400, Jeff Garzik wrote:
> 
>>Marcelo Tosatti wrote:
>>
>>>+static int voltage_set(int slot, int vcc, int vpp)
>>>+{
>>>+	u_int reg = 0;
>>>+
>>>+	switch(vcc) {
>>>+	case 0: break;
>>>+	case 33:
>>>+		reg |= BCSR1_PCVCTL4;
>>>+		break;
>>>+	case 50: 
>>>+		reg |= BCSR1_PCVCTL5;
>>>+		break;
>>>+	default: 
>>>+		return 1;
>>>+	}
>>>+
>>>+	switch(vpp) {
>>>+	case 0: break;
>>>+	case 33: 
>>>+	case 50:
>>>+		if(vcc == vpp)
>>>+			reg |= BCSR1_PCVCTL6;
>>>+		else
>>>+			return 1;
>>>+		break;
>>>+	case 120: 
>>>+		reg |= BCSR1_PCVCTL7;
>>>+	default:
>>>+		return 1;
>>>+	}
>>>+
>>>+	if(!((vcc == 50) || (vcc == 0)))
>>>+		return 1;
>>>+
>>>+	/* first, turn off all power */
>>>+
>>>+	*((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
>>>+				     | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
>>>+
>>>+	/* enable new powersettings */
>>>+
>>>+	*((uint *)RPX_CSR_ADDR) |= reg;
>>
>>Should use bus read/write functions, such as foo_readl() or iowrite32().
> 
> 
> The memory map structure which contains device configuration/registers
> is _always_ directly mapped with pte's (the 8xx is a chip with builtin
> UART/network/etc functionality).
> 
> I don't think there is a need to use read/write acessors.

There are multiple reasons:

* Easier reviewing.  One cannot easily distinguish between writing to 
normal kernel virtual memory and "magic" memory that produces magicaly 
side effects such as initiating DMA of a net packet.

* Compiler safety.  As the code is written now, you have no guarantees 
that the compiler won't combine two stores to the same location, etc. 
Accessor macros are a convenient place to add compiler barriers or 
'volatile' notations that the MPC8xx code lacks.

* Maintainable.  foo_read[bwl] or foo_read{8,16,32} are preferred 
because that's the way other bus accessors look like -- yes even 
embedded SoC buses benefit from these code patterns.  You want your 
driver to look like other drivers as much as possible.

* Convenience.  The accessors can be a zero overhead memory read/write 
at a minimum.  But they can also be convenient places to use special 
memory read/write instructions that specify uncached memop, compiler 
barriers, memory barriers, etc.

Regards,

	Jeff

^ permalink raw reply

* [PATCH] cpm_uart: use schedule_timeout instead of direct call to schedule
From: Kumar Gala @ 2005-08-30  4:48 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, linuxppc-embedded

use schedule_timeout instead of direct call to schedule

Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>

---
commit 85e29936d8eab1c16120ab319cc50828f3863aba
tree a6fbb48fc860c6f5dbef0d518a500b37576caf40
parent b9ecc8e4b5db64f0b4ee36dbdd6758e4ce3c2025
author Kumar K. Gala <kumar.gala@freescale.com> Mon, 29 Aug 2005 23:46:59 -0500
committer Kumar K. Gala <kumar.gala@freescale.com> Mon, 29 Aug 2005 23:46:59 -0500

 drivers/serial/cpm_uart/cpm_uart_core.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -403,10 +403,8 @@ static int cpm_uart_startup(struct uart_
 
 inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
 {
-	unsigned long target_jiffies = jiffies + pinfo->wait_closing;
-
-	while (!time_after(jiffies, target_jiffies))
-   		schedule();
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(pinfo->wait_closing);
 }
 
 /*
@@ -425,9 +423,12 @@ static void cpm_uart_shutdown(struct uar
 	/* If the port is not the console, disable Rx and Tx. */
 	if (!(pinfo->flags & FLAG_CONSOLE)) {
 		/* Wait for all the BDs marked sent */
-		while(!cpm_uart_tx_empty(port))
+		while(!cpm_uart_tx_empty(port)) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout(2);
-		if(pinfo->wait_closing)
+		}
+
+		if (pinfo->wait_closing)
 			cpm_uart_wait_until_send(pinfo);
 
 		/* Stop uarts */

^ permalink raw reply

* [PATCH] cpm_uart: Fix baseaddress for SMC 1 and 2
From: Kumar Gala @ 2005-08-30  4:48 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, linuxppc-embedded

Base addess register for SMC 1 and 2 are never initialized.
This means that they will not work unless a bootloader already
configured them.

The DPRAM already have space reserved, this patch just makes sure
the base addess register is updated correctly on initialization.

Signed-off-by: Rune Torgersen <runet@innovsys.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>

---
commit b9ecc8e4b5db64f0b4ee36dbdd6758e4ce3c2025
tree c6d9da4a2bec187d4fc794b91441323c04642dda
parent 66256c2b92e3edafca1e86e64fcffe5c72cc39e7
author Kumar K. Gala <kumar.gala@freescale.com> Mon, 29 Aug 2005 23:30:56 -0500
committer Kumar K. Gala <kumar.gala@freescale.com> Mon, 29 Aug 2005 23:30:56 -0500

 drivers/serial/cpm_uart/cpm_uart_cpm2.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -266,6 +266,7 @@ int cpm_uart_init_portdesc(void)
 	cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
 	cpm_uart_ports[UART_SMC1].smcup =
 	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
+	*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
 	cpm_uart_ports[UART_SMC1].port.mapbase =
 	    (unsigned long)&cpm2_immr->im_smc[0];
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
@@ -278,6 +279,7 @@ int cpm_uart_init_portdesc(void)
 	cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
 	cpm_uart_ports[UART_SMC2].smcup =
 	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
+	*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
 	cpm_uart_ports[UART_SMC2].port.mapbase =
 	    (unsigned long)&cpm2_immr->im_smc[1];
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);

^ 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