Add PCI support for TQM834x Boards

Wolfgang Denk wd at denx.de
Sun Oct 23 08:36:58 EST 2005


The following patch (against latest 2.6 tree) adds  PCI  support  for
the TQ Systems TQM834x Boards. Verified on TQM8349L.

Note: for TQM834x board support actually to compile and  work,  three
previously submitted patches are required. See postings:

Sat, 22 Oct 2005   [PATCH 2.6] Add generic support for DS1377 RTC
Sat, 22 Oct 2005   [PATCH] Cleanup mpc83xx_restart() code
Sat, 22 Oct 2005   [Patch] Add support for TQM834x Boards


---
PCI support for the TQM834x boards.

Signed-off-by: Rafal Jaworowski <raj at semihalf.com>
Signed-off-by: Wolfgang Denk <wd at denx.de>


---
commit 5108607a56824e025fda5efe9f68ff310545adb9
tree 4e3b67d3e9f4188f69de9715da68781fb7eebc84
parent 0af38510e829b6d397128269fe194898924ab534
author Rafal Jaworowski <raj at pollux.denx.de> Wed, 19 Oct 2005 12:32:42 +0200
committer Rafal Jaworowski <raj at pollux.denx.de> Wed, 19 Oct 2005 12:32:42 +0200

 arch/ppc/platforms/83xx/mpc834x_sys.c |    7 +++
 arch/ppc/platforms/83xx/tqm834x.c     |   37 ++++++++++-----
 arch/ppc/platforms/83xx/tqm834x.h     |   10 ++--
 arch/ppc/syslib/ppc83xx_pci.h         |   41 +++++++++++++++++
 arch/ppc/syslib/ppc83xx_setup.c       |   79 ++++++++++++++++++++++++++++-----
 arch/ppc/syslib/ppc83xx_setup.h       |    1 
 include/linux/pci_ids.h               |   10 ++++
 7 files changed, 157 insertions(+), 28 deletions(-)

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
@@ -364,6 +364,13 @@ platform_init(unsigned long r3, unsigned
 	ppc_md.progress = gen550_progress;
 #endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
 
+#ifdef CONFIG_PCI
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc83xx_map_irq; 
+	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+	ppc_md.pcibios_fixup = mpc834x_pcibios_fixup;
+#endif /* CONFIG_PCI */
+
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_sys_init(): exit", 0);
 
diff --git a/arch/ppc/platforms/83xx/tqm834x.c b/arch/ppc/platforms/83xx/tqm834x.c
--- a/arch/ppc/platforms/83xx/tqm834x.c
+++ b/arch/ppc/platforms/83xx/tqm834x.c
@@ -61,28 +61,33 @@ unsigned char __res[sizeof (bd_t)];
 
 #ifdef CONFIG_PCI
 int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+tqm834x_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
+	int irq;
 	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 */
+		{PIRQA, PIRQB,  PIRQC,  PIRQD}, /* idsel 0x1c */
+		{PIRQB, PIRQC,  PIRQD,  PIRQA}, /* idsel 0x1d */
+		{PIRQC, PIRQD,  0,  0}  	/* idsel 0x1e */
 	};
 
-	const long min_idsel = 0x11, max_idsel = 0x13, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
+	const long min_idsel = 0x1c, max_idsel = 0x1e, irqs_per_slot = 4;
+	irq = PCI_IRQ_TABLE_LOOKUP;
+	if (!irq)
+		irq = 0;
+	return (irq);
 }
 
 int
-mpc83xx_exclude_device(u_char bus, u_char devfn)
+tqm834x_exclude_device(u_char bus, u_char devfn)
 {
 	return PCIBIOS_SUCCESSFUL;
 }
+
 #endif /* CONFIG_PCI */
 
 /* ************************************************************************
@@ -190,19 +195,20 @@ tqm834x_init_IRQ(void)
 	u8 senses[8] = {
 		0,			/* EXT 0 */
 		0,			/* EXT 1 */
-		0,			/* EXT 2 */
-		0,			/* EXT 3 */
 #ifdef CONFIG_PCI
-		IRQ_SENSE_LEVEL,	/* EXT 4 */
+		IRQ_SENSE_LEVEL,	/* EXT 2 */
+		IRQ_SENSE_LEVEL,	/* EXT 3 */
+		0,			/* EXT 4 */
 		IRQ_SENSE_LEVEL,	/* EXT 5 */
 		IRQ_SENSE_LEVEL,	/* EXT 6 */
-		IRQ_SENSE_LEVEL,	/* EXT 7 */
 #else
+		0,			/* EXT 2 */
+		0,			/* EXT 3 */
 		0,			/* EXT 4 */
 		0,			/* EXT 5 */
 		0,			/* EXT 6 */
-		0,			/* EXT 7 */
 #endif
+		IRQ_SENSE_LEVEL,	/* EXT 7 */
 	};
 
 	ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
@@ -329,6 +335,13 @@ platform_init(unsigned long r3, unsigned
 	ppc_md.progress = gen550_progress;
 #endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
 
+#ifdef CONFIG_PCI
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = tqm834x_map_irq;
+	ppc_md.pci_exclude_device = tqm834x_exclude_device;
+	ppc_md.pcibios_fixup = mpc834x_pcibios_fixup;
+#endif /* CONFIG_PCI */
+
 	if (ppc_md.progress)
 		ppc_md.progress("tqm834x_init(): exit", 0);
 
diff --git a/arch/ppc/platforms/83xx/tqm834x.h b/arch/ppc/platforms/83xx/tqm834x.h
--- a/arch/ppc/platforms/83xx/tqm834x.h
+++ b/arch/ppc/platforms/83xx/tqm834x.h
@@ -24,15 +24,15 @@
 
 #define VIRT_IMMRBAR		((uint)0xfe000000)
 
-#define PIRQA	MPC83xx_IRQ_EXT4
-#define PIRQB	MPC83xx_IRQ_EXT5
+#define PIRQA	MPC83xx_IRQ_EXT2
+#define PIRQB	MPC83xx_IRQ_EXT3
 #define PIRQC	MPC83xx_IRQ_EXT6
-#define PIRQD	MPC83xx_IRQ_EXT7
+#define PIRQD	MPC83xx_IRQ_EXT5
 
 #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_LOWER_MEM	0xc0000000
+#define MPC83xx_PCI1_UPPER_MEM	0xdfffffff
 #define MPC83xx_PCI1_IO_BASE	0xe2000000
 #define MPC83xx_PCI1_MEM_OFFSET	0x00000000
 #define MPC83xx_PCI1_IO_SIZE	0x01000000
diff --git a/arch/ppc/syslib/ppc83xx_pci.h b/arch/ppc/syslib/ppc83xx_pci.h
--- a/arch/ppc/syslib/ppc83xx_pci.h
+++ b/arch/ppc/syslib/ppc83xx_pci.h
@@ -25,6 +25,47 @@ typedef struct immr_clk {
 	u32 sccr; /* system clock control Register  */
 	u8 res0[0xF4];
 } immr_clk_t;
+#define SPMR_LBIUCM  0x80000000 /* LBIUCM  */
+#define SPMR_DDRCM   0x40000000 /* DDRCM  */
+#define SPMR_SVCOD   0x30000000 /* SVCOD  */
+#define SPMR_SPMF    0x0F000000 /* SPMF  */
+#define SPMR_CKID    0x00800000 /* CKID  */
+#define SPMR_CKID_SHIFT 23
+#define SPMR_COREPLL 0x007F0000 /* COREPLL  */
+#define SPMR_CEVCOD  0x000000C0 /* CEVCOD  */
+#define SPMR_CEPDF   0x00000020 /* CEPDF  */
+#define SPMR_CEPMF   0x0000001F /* CEPMF  */
+
+#define OCCR_PCICOE0 0x80000000 /* PCICOE0  */
+#define OCCR_PCICOE1 0x40000000 /* PCICOE1  */
+#define OCCR_PCICOE2 0x20000000 /* PCICOE2  */
+#define OCCR_PCICOE3 0x10000000 /* PCICOE3  */
+#define OCCR_PCICOE4 0x08000000 /* PCICOE4  */
+#define OCCR_PCICOE5 0x04000000 /* PCICOE5  */
+#define OCCR_PCICOE6 0x02000000 /* PCICOE6  */
+#define OCCR_PCICOE7 0x01000000 /* PCICOE7  */
+#define OCCR_PCICD0  0x00800000 /* PCICD0  */
+#define OCCR_PCICD1  0x00400000 /* PCICD1  */
+#define OCCR_PCICD2  0x00200000 /* PCICD2  */
+#define OCCR_PCICD3  0x00100000 /* PCICD3  */
+#define OCCR_PCICD4  0x00080000 /* PCICD4  */
+#define OCCR_PCICD5  0x00040000 /* PCICD5  */
+#define OCCR_PCICD6  0x00020000 /* PCICD6  */
+#define OCCR_PCICD7  0x00010000 /* PCICD7  */
+#define OCCR_PCI1CR  0x00000002 /* PCI1CR  */
+#define OCCR_PCI2CR  0x00000001 /* PCI2CR  */
+
+#define SCCR_TSEC1CM  0xc0000000 /* TSEC1CM  */
+#define SCCR_TSEC1CM_SHIFT 30
+#define SCCR_TSEC2CM  0x30000000 /* TSEC2CM  */
+#define SCCR_TSEC2CM_SHIFT 28
+#define SCCR_ENCCM    0x03000000 /* ENCCM  */
+#define SCCR_ENCCM_SHIFT 24
+#define SCCR_USBMPHCM 0x00c00000 /* USBMPHCM  */
+#define SCCR_USBMPHCM_SHIFT 22
+#define SCCR_USBDRCM  0x00300000 /* USBDRCM  */
+#define SCCR_USBDRCM_SHIFT 20
+#define SCCR_PCICM    0x00010000 /* PCICM  */
 
 /*
  * Sequencer
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
@@ -221,6 +221,7 @@ mpc83xx_setup_pci1(struct pci_controller
 	iounmap(ios);
 }
 
+#ifdef CONFIG_MPC83xx_PCI2
 void __init
 mpc83xx_setup_pci2(struct pci_controller *hose)
 {
@@ -278,8 +279,11 @@ mpc83xx_setup_pci2(struct pci_controller
 	iounmap(pci_ctrl);
 	iounmap(ios);
 }
+#endif
 
 /*
+ * NOTICE for the MPC83xx SYS Freescale evaluation board:
+ *
  * 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
@@ -287,10 +291,6 @@ mpc83xx_setup_pci2(struct pci_controller
  * 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)
 {
@@ -306,22 +306,46 @@ mpc83xx_setup_hose(void)
 			sizeof(immr_clk_t));
 
 	/*
-	 * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
+	 * Configure PCI_CLK_OUTPUT
 	 */
 	val32 = clk->occr;
 	udelay(2000);
-	clk->occr = 0xff000000;
+	
+#ifdef CONFIG_TQM834x
+	/*
+	 * WARNING! only PCI_CLK_OUTPUT1 is enabled for the TQM834x as this is
+	 * the one line actually used for clocking all external PCI devices in
+	 * current setup of the STK85xx.  Enabling other PCI_CLK_OUTPUT lines
+	 * may lead to board's hang for unknown reasons - particularly
+	 * PCI_CLK_OUTPUT6 and PCI_CLK_OUTPUT7 are known to hang the board;
+	 * this issue is under investigation (18 oct 05)
+	 */
+	val32 = OCCR_PCICOE1; 
+#else
+	/* enable all PCI_CLK_OUTs */
+	val32 = (OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2 | OCCR_PCICOE3 \
+		 | OCCR_PCICOE4 | OCCR_PCICOE5 | OCCR_PCICOE6 | OCCR_PCICOE7);
+#endif
+	/* set frequency of the PCI and clock outputs for external devicesc
+	 * according to system clocking settings */
+	if (clk->spmr & SPMR_CKID) {
+		/* PCI Clock is 1/2 of CONFIG_83XX_CLKIN so need to set up OCCR
+		 * fields accordingly */
+		val32 |= (OCCR_PCI1CR | OCCR_PCI2CR);
+		
+		val32 |= (OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 \
+			  | OCCR_PCICD3 | OCCR_PCICD4 | OCCR_PCICD5 \
+			  | OCCR_PCICD6 | OCCR_PCICD7);
+	}
+	
+	clk->occr = val32;
 	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;
@@ -357,7 +381,6 @@ mpc83xx_setup_hose(void)
 			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
@@ -395,4 +418,38 @@ mpc83xx_setup_hose(void)
 	hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno);
 #endif /* CONFIG_MPC83xx_PCI2 */
 }
+
+
+void __init
+mpc834x_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+	unsigned int class;
+	int i;
+	
+	if ((dev = pci_find_device(PCI_VENDOR_ID_FREESCALE,
+				   PCI_DEVICE_ID_FREESCALE_MPC8349E, NULL))) {
+		class = dev->class >> 8;
+		if (class == PCI_CLASS_BRIDGE_OTHER) {
+			/*
+			 * at least rev 1.1 of the MPC8349E chip has the class
+			 * wrongly set in the host/PCI bridge config space
+			 * register; this leads to the host/PCI bridge being
+			 * treated as a regular client device, trying to assign
+			 * PCI resources to it etc.
+			 *
+			 */
+			dev->class = (PCI_CLASS_BRIDGE_HOST << 8) & ~0xf;
+
+			/* for some odd reasons the host/PCI bridge behaves
+			 * like an agent device and would claim PCI mem/io/irq
+			 * resources, so we make these resources inactive (i.e.
+			 * the bridge will not claim resources from itself)
+			 */
+			for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) 
+				dev->resource[i].flags = IORESOURCE_UNSET;
+		}
+	}	
+	
+}
 #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
@@ -36,6 +36,7 @@ extern void mpc83xx_restart(char *cmd);
 extern void mpc83xx_power_off(void);
 extern void mpc83xx_halt(void);
 extern void mpc83xx_setup_hose(void) __init;
+extern void mpc834x_pcibios_fixup(void);
 
 /* PCI config */
 #define PCI1_CFG_ADDR_OFFSET (0x8300)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2278,6 +2278,16 @@
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
+#define PCI_VENDOR_ID_FREESCALE			0x1957
+#define PCI_DEVICE_ID_FREESCALE_MPC8349E	0x0080
+#define PCI_DEVICE_ID_FREESCALE_MPC8349		0x0081
+#define PCI_DEVICE_ID_FREESCALE_MPC8347E_1	0x0082
+#define PCI_DEVICE_ID_FREESCALE_MPC8347_1	0x0083
+#define PCI_DEVICE_ID_FREESCALE_MPC8347E_2	0x0084
+#define PCI_DEVICE_ID_FREESCALE_MPC8347_2	0x0085
+#define PCI_DEVICE_ID_FREESCALE_MPC8343E	0x0086
+#define PCI_DEVICE_ID_FREESCALE_MPC8343		0x0087
+
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 



!-------------------------------------------------------------flip-



Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The first 90% of a project takes 90% of the time, the last 10%  takes
the other 90% of the time.



More information about the Linuxppc-dev mailing list