Skip to contentSkip to conversation

Add the MPC8641 HPCN platform files.

PATCH In review Jon Loeliger 5 participants 14 messages Jun 17, 2006 – Jun 19, 2006 PowerPC

lore
Share & tools
lore
#0 lore raw

PATCH v3 5/9 Add the MPC8641 HPCN platform files.

---

 arch/powerpc/platforms/86xx/mpc8641_hpcn.h |   54 +++++
 arch/powerpc/platforms/86xx/mpc86xx.h      |   28 ++
 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |  326 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/86xx/mpc86xx_smp.c  |  117 ++++++++++
 4 files changed, 525 insertions(+), 0 deletions(-)
arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file +54 -0
new file mode 100644
index 0000000..5042253
@@ -0,0 +1,54 @@
+/*
+ * MPC8641 HPCN board definitions
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Author: Xianghua Xiao <[email protected]>
+ */
+
+#ifndef __MPC8641_HPCN_H__
+#define __MPC8641_HPCN_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+/* PCI interrupt controller */
+#define PIRQA		3
+#define PIRQB		4
+#define PIRQC		5
+#define PIRQD		6
+#define PIRQ7		7
+#define PIRQE		9
+#define PIRQF		10
+#define PIRQG		11
+#define PIRQH		12
+
+/* PCI-Express memory map */
+#define MPC86XX_PCIE_LOWER_IO        0x00000000
+#define MPC86XX_PCIE_UPPER_IO        0x00ffffff
+
+#define MPC86XX_PCIE_LOWER_MEM       0x80000000
+#define MPC86XX_PCIE_UPPER_MEM       0x9fffffff
+
+#define MPC86XX_PCIE_IO_BASE         0xe2000000
+#define MPC86XX_PCIE_MEM_OFFSET      0x00000000
+
+#define MPC86XX_PCIE_IO_SIZE         0x01000000
+
+#define PCIE1_CFG_ADDR_OFFSET    (0x8000)
+#define PCIE1_CFG_DATA_OFFSET    (0x8004)
+
+#define PCIE2_CFG_ADDR_OFFSET    (0x9000)
+#define PCIE2_CFG_DATA_OFFSET    (0x9004)
+
+#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET
+#define MPC86xx_PCIE_SIZE	(0x1000)
+
+#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
+
+#endif	/* __MPC8641_HPCN_H__ */
arch/powerpc/platforms/86xx/mpc86xx.h new file +28 -0
new file mode 100644
index 0000000..e3c9e4f
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MPC86XX_H__
+#define __MPC86XX_H__
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc86xx_* files. Mostly for use by mpc86xx_setup().
+ */
+
+extern int __init add_bridge(struct device_node *dev);
+
+extern void __init setup_indirect_pcie(struct pci_controller *hose,
+				       u32 cfg_addr, u32 cfg_data);
+extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose,
+					     void __iomem *cfg_addr,
+					     void __iomem *cfg_data);
+
+extern void __init mpc86xx_smp_init(void);
+
+#endif	/* __MPC86XX_H__ */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +326 -0

326 lines not on this page · raw message

arch/powerpc/platforms/86xx/mpc86xx_smp.c new file +117 -0

117 lines not on this page · raw message

#1 lore raw

arch/powerpc/platforms/86xx/mpc86xx_smp.c line 110

Quoted 8 lines

struct smp_ops_t smp_86xx_ops = {

arch/powerpc/platforms/86xx/mpc86xx_smp.c new file +7 -0
+	.message_pass = smp_mpic_message_pass,
+	.probe = smp_mpic_probe,
+	.kick_cpu = smp_86xx_kick_cpu,
+	.setup_cpu = smp_86xx_setup_cpu,
+	.take_timebase = smp_generic_take_timebase,
+	.give_timebase = smp_generic_give_timebase,
+};

You don't have any way to freeze the timebase ? (No GPIO controlling TBEN ?) It's pretty nasty to rely on software sync, especially if it's supposed to be an example design ...

Ben.

#11 lore raw
In reply to Jon Loeliger
Quoted 61 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +60 -0
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ */
+
+static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO error/write-port unit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO outbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO inbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO outbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO inbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO outbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO inbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+	0x0,						/* External  4: */
+	0x0,						/* External  5: */
+	0x0,						/* External  6: */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c line 116

Quoted 10 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +10 -0
+	0x0,						/* External  7: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis FPGA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI 8259 INTR Cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad ETH PHY */
+	0x0,						/* External 11: */
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+};

So what I suggest you do with the above, rather than having this big array in the kernel, is to have a property in the interrupt controller node, let's call it "default-senses", which contains a cell for every interrupt source with the default sense value.

The interrupt mapping code that I'm working on will allow individual interrupts to carry their sense value through the device-tree, but it's useful to have some sane defaults, either because you don't have a device-tree entry for a given interrupt (oops, happens ...) or because... you don't have my new code yet :)

I'm not too fan of the big table in the kernel however. I'd rather have it in the device-tree.

I'm not forcing you here, do as you prefer, but if you decide to go toward the "default-senses" property in the DT, then I think we should add a couple of sections to my proposed patch to the booting-without-of.txt file about interrupt that describes a set of optional properties for interrupt controllers, and describe that there.

I'm toying with creating a "generic" create_interrupt_controller() function in fact that takes a device-node and would instanciate known interrupt controller types (i8259, OpenPIC, for now, maybe more later) entire based on device-tree properties (big-endian, maybe that one for default sense codes, etc...).

Cheers,
Ben.

#13 lore raw
In reply to Jon Loeliger
Quoted 341 lines · Jon Loeliger

---

 arch/powerpc/platforms/86xx/mpc8641_hpcn.h |   54 +++++
 arch/powerpc/platforms/86xx/mpc86xx.h      |   28 ++
 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |  326 +++++++++++++++++ 
+++++++++++
 arch/powerpc/platforms/86xx/mpc86xx_smp.c  |  117 ++++++++++
 4 files changed, 525 insertions(+), 0 deletions(-)
arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file +6 -0
new file mode 100644
index 0000000..5042253
@@ -0,0 +1,54 @@
+/*
+ * MPC8641 HPCN board definitions
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or  

modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Author: Xianghua Xiao <[email protected]>
+ */

arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file +42 -0
+
+#ifndef __MPC8641_HPCN_H__
+#define __MPC8641_HPCN_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+/* PCI interrupt controller */
+#define PIRQA		3
+#define PIRQB		4
+#define PIRQC		5
+#define PIRQD		6
+#define PIRQ7		7
+#define PIRQE		9
+#define PIRQF		10
+#define PIRQG		11
+#define PIRQH		12
+
+/* PCI-Express memory map */
+#define MPC86XX_PCIE_LOWER_IO        0x00000000
+#define MPC86XX_PCIE_UPPER_IO        0x00ffffff
+
+#define MPC86XX_PCIE_LOWER_MEM       0x80000000
+#define MPC86XX_PCIE_UPPER_MEM       0x9fffffff
+
+#define MPC86XX_PCIE_IO_BASE         0xe2000000
+#define MPC86XX_PCIE_MEM_OFFSET      0x00000000
+
+#define MPC86XX_PCIE_IO_SIZE         0x01000000
+
+#define PCIE1_CFG_ADDR_OFFSET    (0x8000)
+#define PCIE1_CFG_DATA_OFFSET    (0x8004)
+
+#define PCIE2_CFG_ADDR_OFFSET    (0x9000)
+#define PCIE2_CFG_DATA_OFFSET    (0x9004)
+
+#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET
+#define MPC86xx_PCIE_SIZE	(0x1000)
+
+#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
+
+#endif	/* __MPC8641_HPCN_H__ */
arch/powerpc/platforms/86xx/mpc86xx.h new file +4 -0
new file mode 100644
index 0000000..e3c9e4f
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or  

modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */

arch/powerpc/platforms/86xx/mpc86xx.h new file +14 -0
+
+#ifndef __MPC86XX_H__
+#define __MPC86XX_H__
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc86xx_* files. Mostly for use by mpc86xx_setup().
+ */
+
+extern int __init add_bridge(struct device_node *dev);
+
+extern void __init setup_indirect_pcie(struct pci_controller *hose,
+				       u32 cfg_addr, u32 cfg_data);
+extern void __init setup_indirect_pcie_nomap(struct pci_controller  

*hose,

arch/powerpc/platforms/86xx/mpc86xx.h new file +6 -0
+					     void __iomem *cfg_addr,
+					     void __iomem *cfg_data);
+
+extern void __init mpc86xx_smp_init(void);
+
+#endif	/* __MPC86XX_H__ */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +9 -0
new file mode 100644
index 0000000..483c21d
@@ -0,0 +1,326 @@
+/*
+ * MPC86xx HPCN board specific routines
+ *
+ * Recode: ZHANG WEI <[email protected]>
+ * Initial author: Xianghua Xiao <[email protected]>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or  

modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +39 -0
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+#include <asm/i8259.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ */
+
+static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0:  

Reserved */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +2 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR  

DRAM */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +8 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10:  

Reserved */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11:  

Reserved */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +2 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1  

Transmit */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1  

Receive */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3  

transmit */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3  

receive */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3  

error */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1  

Receive/Transmit Error */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2  

Transmit */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2  

Receive */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4  

transmit */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4  

receive */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4  

error */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2  

Receive/Transmit Error */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +4 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28:  

Performance Monitor */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +4 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO  

error/write-port unit */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO  

outbound doorbell */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO  

inbound doorbell */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +3 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO  

outbound message unit 1 */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO  

inbound message unit 1 */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO  

outbound message unit 2 */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO  

inbound message unit 2 */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +16 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+	0x0,						/* External  4: */
+	0x0,						/* External  5: */
+	0x0,						/* External  6: */
+	0x0,						/* External  7: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis  

FPGA */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI  

8259 INTR Cascade */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1 -0
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad  

ETH PHY */

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +51 -0
+	0x0,						/* External 11: */
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+};
+
+
+void __init
+mpc86xx_hpcn_init_irq(void)
+{
+	struct mpic *mpic1;
+	phys_addr_t openpic_paddr;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
+
+	/* Alloc mpic structure and per isu has 16 INT entries. */
+	mpic1 = mpic_alloc(openpic_paddr,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250,
+			mpc86xx_hpcn_openpic_initsenses,
+			sizeof(mpc86xx_hpcn_openpic_initsenses),
+			" MPIC     ");
+	BUG_ON(mpic1 == NULL);
+
+	/* 48 Internal Interrupts */
+	mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200);
+	mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400);
+	mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600);
+
+	/* 16 External interrupts */
+	mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000);
+
+	mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+	mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL);
+	i8259_init(0, I8259_OFFSET);
+#endif
+}
+
+
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned  

char pin)

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +28 -0
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 *      PCI IDSEL/INTPIN->INTLINE
+		 *       A      B      C      D
+		 */
+		{PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 17 -- PCI Slot 1 */
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 18 -- PCI Slot 2 */
+		{0, 0, 0, 0},			/* IDSEL 19 */
+		{0, 0, 0, 0},			/* IDSEL 20 */
+		{0, 0, 0, 0},			/* IDSEL 21 */
+		{0, 0, 0, 0},			/* IDSEL 22 */
+		{0, 0, 0, 0},			/* IDSEL 23 */
+		{0, 0, 0, 0},			/* IDSEL 24 */
+		{0, 0, 0, 0},			/* IDSEL 25 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},	/* IDSEL 26 -- PCI Bridge*/
+		{PIRQC, 0, 0, 0},		/* IDSEL 27 -- LAN */
+		{PIRQE, PIRQF, PIRQH, PIRQ7},	/* IDSEL 28 -- USB 1.1 */
+		{PIRQE, PIRQF, PIRQG, 0},	/* IDSEL 29 -- Audio & Modem */
+		{PIRQH, 0, 0, 0},		/* IDSEL 30 -- LPC & PMU*/
+		{PIRQD, 0, 0, 0},		/* IDSEL 31 -- ATA */
+	};
+
+	const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
+}
+
+

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c line 199

Quoted 10 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +10 -0
+int
+mpc86xx_exclude_device(u_char bus, u_char devfn)
+{
+#if !defined(CONFIG_PCI)
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}

any reason not to put this in pci.c its generic enough. Also, loose the #if, its pointless ;)

Quoted 69 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +69 -0
+#endif /* CONFIG_PCI */
+
+
+static void __init
+mpc86xx_hpcn_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
+
+	np = of_find_node_by_type(NULL, "cpu");
+	if (np != 0) {
+		unsigned int *fp;
+
+		fp = (int *)get_property(np, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 50000000 / HZ;
+		of_node_put(np);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc86xx_map_irq;
+	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+#endif
+
+	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
+
+#ifdef  CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_SMP
+	mpc86xx_smp_init();
+#endif
+}
+
+
+void
+mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	uint memsize = total_memory;
+	const char *model = "";
+	uint svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "Machine\t\t: %s\n", model);
+	of_node_put(root);
+
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened

arch/powerpc/platforms/86xx/mpc86xx_hpcn.c line 278

Quoted 10 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +10 -0
+ */
+static int __init mpc86xx_hpcn_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "mpc86xx"))
+		return 1;	/* Looks good */
+
+	return 0;
+}

You should make this probe actually check model or something more specific than mpc86xx. I didn't do this on 85xx or 83xx since we had pre-existing .dts that didn't setup model in a consistent way.

arch/powerpc/platforms/86xx/mpc86xx_smp.c

Quoted 53 lines
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +48 -0
+
+
+void
+mpc86xx_restart(char *cmd)
+{
+	void __iomem *rstcr;
+
+	rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
+
+	local_irq_disable();
+
+	/* Assert reset request to Reset Control Register */
+	out_be32(rstcr, 0x2);
+
+	/* not reached */
+}
+
+
+long __init
+mpc86xx_time_init(void)
+{
+	unsigned int temp;
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	temp = mfspr(SPRN_HID0);
+	temp |= HID0_TBEN;
+	mtspr(SPRN_HID0, temp);
+	asm volatile("isync");
+
+	return 0;
+}
+
+
+define_machine(mpc86xx_hpcn) {
+	.name			= "MPC86xx HPCN",
+	.probe			= mpc86xx_hpcn_probe,
+	.setup_arch		= mpc86xx_hpcn_setup_arch,
+	.init_IRQ		= mpc86xx_hpcn_init_irq,
+	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= mpc86xx_restart,
+	.time_init		= mpc86xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
arch/powerpc/platforms/86xx/mpc86xx_smp.c new file +0 -0
new file mode 100644
index 0000000..944ec4b

a nit, but any reason to not call this just smp.c?

Quoted 126 lines
arch/powerpc/platforms/86xx/mpc86xx_smp.c new file +7 -0
@@ -0,0 +1,117 @@
+/*
+ * Author: Xianghua Xiao <[email protected]>
+ *         Zhang Wei <[email protected]>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or  

modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */

arch/powerpc/platforms/86xx/mpc86xx_smp.c new file +107 -0
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/pci-bridge.h>
+#include <asm-powerpc/mpic.h>
+#include <asm/mpc86xx.h>
+#include <asm/cacheflush.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+extern void __secondary_start_mpc86xx(void);
+extern unsigned long __secondary_hold_acknowledge;
+
+
+static void __init
+smp_86xx_release_core(int nr)
+{
+	void *mcm_vaddr;
+	unsigned long vaddr, pcr;
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	/*
+	 * Startup Core #nr.
+	 */
+	mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
+			    MPC86xx_MCM_SIZE);
+	vaddr = (unsigned long)mcm_vaddr +  MCM_PORT_CONFIG_OFFSET;
+	pcr = in_be32((volatile unsigned *)vaddr);
+	pcr |= 1 << (nr + 24);
+	out_be32((volatile unsigned *)vaddr, pcr);
+}
+
+
+static void __init
+smp_86xx_kick_cpu(int nr)
+{
+	unsigned int save_vector;
+	unsigned long target, flags;
+	int n = 0;
+	volatile unsigned int *vector
+		 = (volatile unsigned int *)(KERNELBASE + 0x100);
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
+
+	local_irq_save(flags);
+	local_irq_disable();
+
+	/* Save reset vector */
+	save_vector = *vector;
+
+	/* Setup fake reset vector to call __secondary_start_mpc86xx. */
+	target = (unsigned long) __secondary_start_mpc86xx;
+	create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
+
+	/* Kick that CPU */
+	smp_86xx_release_core(nr);
+
+	/* Wait a bit for the CPU to take the exception. */
+	while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))
+		mdelay(1);
+
+	/* Restore the exception vector */
+	*vector = save_vector;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector  
+ 4);
+
+	local_irq_restore(flags);
+
+	pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
+}
+
+
+static void __init
+smp_86xx_setup_cpu(int cpu_nr)
+{
+	mpic_setup_this_cpu();
+}
+
+
+struct smp_ops_t smp_86xx_ops = {
+	.message_pass = smp_mpic_message_pass,
+	.probe = smp_mpic_probe,
+	.kick_cpu = smp_86xx_kick_cpu,
+	.setup_cpu = smp_86xx_setup_cpu,
+	.take_timebase = smp_generic_take_timebase,
+	.give_timebase = smp_generic_give_timebase,
+};
+
+
+void __init
+mpc86xx_smp_init(void)
+{
+	smp_ops = &smp_86xx_ops;
+}

_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev

#2 lore raw
In reply to Benjamin Herrenschmidt
Quoted 3 lines · Benjamin Herrenschmidt

You don't have any way to freeze the timebase ? (No GPIO controlling TBEN ?) It's pretty nasty to rely on software sync,

I will investigate this option and follow up with a patch, assuming that there is a HW solution for your suggestion.

Quoted 1 line

especially if it's supposed to be an example design ...

Who said that? ;-)

jdl

#12 lore raw
In reply to Benjamin Herrenschmidt
Quoted 2 lines · Benjamin Herrenschmidt

I'm not too fan of the big table in the kernel however. I'd rather have it in the device-tree.

We are waiting for this release to get into the mainline, and for your proposed rewrite to be accepted. We have folks here who are on deck to totally modify this to accommodate your proposal via the Device Tree file.

But we're not going to read your mind to get there. :-)

jdl

#3 lore raw
In reply to Jon Loeliger
Quoted 5 lines · Jon Loeliger
Quoted 3 lines · Benjamin Herrenschmidt

You don't have any way to freeze the timebase ? (No GPIO controlling TBEN ?) It's pretty nasty to rely on software sync,

Btw, IMNSHO, it should be the firmware's job to synchronise the timebases, even before the kernel gets started; at least as the default. We don't want to have millions of separate GPIO thingies, one for every board, unless really necessary, I think?

Segher

#4 lore raw

So, like, the other day Segher Boessenkool mumbled:

Quoted 6 lines

Btw, IMNSHO, it should be the firmware's job to synchronise the timebases, even before the kernel gets started; at least as the default. We don't want to have millions of separate GPIO thingies, one for every board, unless really necessary, I think?

The second CPU isn't even running in the firmware. It is in hard-reset until Linux says "Hey, start that secondary CPU for me!".

Thanks,
jdl

#5 lore raw
Quoted 9 lines
Quoted 5 lines

Btw, IMNSHO, it should be the firmware's job to synchronise the timebases, even before the kernel gets started; at least as the default. We don't want to have millions of separate GPIO thingies, one for every board, unless really necessary, I think?

The second CPU isn't even running in the firmware. It is in hard-reset until Linux says "Hey, start that secondary CPU for me!".

In that case you obviously need to sync the timebases, sure. The firmware could be smart and do the sync at CPU start-up time though.

On other boards, all CPUs are always running (not a desirable situation, but outside of our control, heh).

In either case, the knowledge about how to sync the timebases more properly belongs in the firmware than in the kernel. In some cases the kernel explicitly tells the firmware to start/ stop the timebases, that's better than the kernel having to handle the nitty-gritty details itself already.

Thoughts?

Segher

#6 lore raw

So, like, the other day Segher Boessenkool mumbled:

Quoted 4 lines

In that case you obviously need to sync the timebases, sure. The firmware could be smart and do the sync at CPU start-up time though.

I am investigating this and, as I indicated to Ben, submit a follow up patch to implement it if I figure out to do it.

Quoted 6 lines

In
some cases the kernel explicitly tells the firmware to start/ stop the timebases, that's better than the kernel having to handle the nitty-gritty details itself already.

Thoughts?

Well, by the time Linux is running, there is no more firmware available. Linux is essentially autononomous at this stage, and I think it will have to arrange for the TB sync itself.

jdl

#7 lore raw
Quoted 6 lines
Quoted 3 lines

In that case you obviously need to sync the timebases, sure. The firmware could be smart and do the sync at CPU start-up time though.

I am investigating this and, as I indicated to Ben, submit a follow up patch to implement it if I figure out to do it.

Great.

Quoted 10 lines
Quoted 6 lines

In
some cases the kernel explicitly tells the firmware to start/ stop the timebases, that's better than the kernel having to handle the nitty-gritty details itself already.

Thoughts?

Well, by the time Linux is running, there is no more firmware available. Linux is essentially autononomous at this stage, and I think it will have to arrange for the TB sync itself.

I'm confused now. So are or arent't all CPUs running at the time Linux is started? Are you saying Linux manually starts all non-boot CPUs?!?

Segher

#8 lore raw

So, like, the other day Segher Boessenkool mumbled:

Quoted 3 lines

I'm confused now. So are or arent't all CPUs running at the time Linux is started?

Only the boot CPU is running. The others are not.

Quoted 2 lines

Are you saying Linux manually starts
all non-boot CPUs?!?

Right. The secondary CPUs are not clocking, not able to fetch memory, not nothing until Linux gets a shot at smp_secondary_kick()'ing them into motion. And then we have the ability to start the scondary CPUs one at a time.

jdl

#9 lore raw
Quoted 7 lines
Quoted 2 lines

Are you saying Linux manually starts
all non-boot CPUs?!?

Right. The secondary CPUs are not clocking, not able to fetch memory, not nothing until Linux gets a shot at smp_secondary_kick()'ing them into motion. And then we have the ability to start the scondary CPUs one at a time.

So you start them with a GPIO? Would it be feasible to sync the time bases right there? Constrain the ugliness to just that one spot, as it were. Although it ends up with the same complexity, sigh.

Segher

#10 lore raw

So, like, the other day Segher Boessenkool mumbled:

Quoted 1 line

So you start them with a GPIO?

Yeah, magic system register write.

Quoted 4 lines

Would it be feasible to
sync the time bases right there? Constrain the ugliness to just that one spot, as it were. Although it ends up with the same complexity, sigh.

That's the sort of thing I will be investigating, yep...

jdl