Add the MPC8641 HPCN platform files.
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
@@ -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
@@ -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
arch/powerpc/platforms/86xx/mpc86xx_smp.c line 110
Quoted 8 lines
struct
smp_ops_tsmp_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.
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.
Quoted 341 lines · Jon Loeliger
Signed-off-by Xianghua Xiao <[email protected]>Signed-off-by Haiying Wang <[email protected]>Signed-off-by Wei Zhang <[email protected]>Signed-off-by Jon Loeliger <[email protected]>---
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@@ -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@@ -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@@ -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: DDRDRAM */
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 1Transmit */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 1Receive */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: TSEC 3transmit */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: TSEC 3receive */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: TSEC 3error */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 1Receive/Transmit Error */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 2Transmit */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 2Receive */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: TSEC 4transmit */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: TSEC 4receive */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: TSEC 4error */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 2Receive/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: SRIOerror/write-port unit */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 33: SRIOoutbound doorbell */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 34: SRIOinbound 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: SRIOoutbound message unit 1 */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 38: SRIOinbound message unit 1 */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 39: SRIOoutbound message unit 2 */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 40: SRIOinbound 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: ULI8259 INTR Cascade */
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file +1
-0+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 10: QuadETH 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, unsignedchar 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); + asmvolatile ("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
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
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
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
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
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
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
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
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
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
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
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