LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/10 v2] Add the MPC8641 HPCN platform files.
From: Kumar Gala @ 2006-06-09  0:12 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1149803821.23938.278.camel@cashmere.sps.mot.com>


On Jun 8, 2006, at 4:57 PM, Jon Loeliger wrote:

>
> Signed-off-by: Xianghua Xiao <x.xiao@freescale.com>
> Signed-off-by: Wei Zhang <Wei.Zhang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
>
> ---
>
>  arch/powerpc/platforms/86xx/misc.c         |   51 +++++
>  arch/powerpc/platforms/86xx/mpc8641_hpcn.c |   52 +++++
>  arch/powerpc/platforms/86xx/mpc8641_hpcn.h |   54 +++++
>  arch/powerpc/platforms/86xx/mpc86xx.h      |   31 +++
>  arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |  304 +++++++++++++++++ 
> +++++++++++
>  5 files changed, 492 insertions(+), 0 deletions(-)
>
>
> diff --git a/arch/powerpc/platforms/86xx/misc.c b/arch/powerpc/ 
> platforms/86xx/misc.c
> new file mode 100644
> index 0000000..01c5e9b
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/misc.c
> @@ -0,0 +1,51 @@
> +/*
> + * MPC86XX generic code
> + *
> + * Author: Xianghua Xiao <x.xiao@freescale.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <asm/irq.h>
> +#include <asm/io.h>
> +
> +#include <sysdev/fsl_soc.h>
> +
> +void
> +mpc86xx_restart(char *cmd)
> +{
> +	void __iomem *rstcr;
> +
> +	local_irq_disable();
> +
> +	/* Assert reset request to Reset Control Register */
> +	rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
> +	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;
> +}
> diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.c b/arch/ 
> powerpc/platforms/86xx/mpc8641_hpcn.c
> new file mode 100644
> index 0000000..655e2b8
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.c
> @@ -0,0 +1,52 @@

how about renaming this smp.c and make it for config'd generic on  
86xx & SMP

> +/*
> + * MPC8641 HPCN board specific routines
> + *
> + * Author: Xianghua Xiao <x.xiao@freescale.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +
> +#include <asm/pgtable.h>
> +#include <asm/page.h>
> +#include <asm/pci-bridge.h>
> +#include <asm-powerpc/mpic.h>
> +#include <asm/mpc86xx.h>
> +
> +#include "mpc86xx.h"
> +
> +
> +#ifdef CONFIG_SMP
> +static void __init
> +smp_8641_kick_cpu(int nr)
> +{
> +	*(unsigned long *)KERNELBASE = nr;
> +	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
> +	printk("CPU%d released, waiting\n",nr);
> +}
> +
> +static void __init
> +smp_8641_setup_cpu(int cpu_nr)
> +{
> +	mpic_setup_this_cpu();
> +}
> +
> +
> +struct smp_ops_t smp_8641_ops = {
> +	.message_pass = smp_mpic_message_pass,
> +	.probe = smp_mpic_probe,
> +	.kick_cpu = smp_8641_kick_cpu,
> +	.setup_cpu = smp_8641_setup_cpu,
> +	.take_timebase = smp_generic_take_timebase,
> +	.give_timebase = smp_generic_give_timebase,
> +};
> +#endif /* CONFIG_SMP */
> diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/ 
> powerpc/platforms/86xx/mpc8641_hpcn.h
> new file mode 100644
> index 0000000..4ba5b4c
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
> @@ -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 <x.xiao@freescale.com>
> + */
> +
> +#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
> +
> +/* PEX memory map */
> +#define MPC86XX_PEX_LOWER_IO        0x00000000
> +#define MPC86XX_PEX_UPPER_IO        0x00ffffff
> +
> +#define MPC86XX_PEX_LOWER_MEM       0x80000000
> +#define MPC86XX_PEX_UPPER_MEM       0x9fffffff
> +
> +#define MPC86XX_PEX_IO_BASE         0xe2000000
> +#define MPC86XX_PEX_MEM_OFFSET      0x00000000
> +
> +#define MPC86XX_PEX_IO_SIZE         0x01000000
> +

PEX offsets are generic and should be moved to such a more generic  
86xx location.

> +#define PEX1_CFG_ADDR_OFFSET    (0x8000)
> +#define PEX1_CFG_DATA_OFFSET    (0x8004)
> +
> +#define PEX2_CFG_ADDR_OFFSET    (0x9000)
> +#define PEX2_CFG_DATA_OFFSET    (0x9004)
> +
> +#define MPC86xx_PEX_OFFSET PEX1_CFG_ADDR_OFFSET
> +#define MPC86xx_PEX_SIZE	(0x1000)
> +

this also seems 86xx & not hpcn specific.

> +#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
> +
> +#endif	/* __MPC8641_HPCN_H__ */
> diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/ 
> platforms/86xx/mpc86xx.h
> new file mode 100644
> index 0000000..7cc45d4
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc86xx.h
> @@ -0,0 +1,31 @@
> +/*
> + * 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 void mpc86xx_restart(char *cmd);
> +extern long __init mpc86xx_time_init(void);
> +
> +extern int __init add_bridge(struct device_node *dev);
> +
> +extern void __init setup_indirect_pex(struct pci_controller* hose,
> +				      u32 cfg_addr, u32 cfg_data);
> +extern void __init setup_indirect_pex_nomap(struct pci_controller*  
> hose,
> +					    void __iomem * cfg_addr,
> +					    void __iomem * cfg_data);
> +
> +extern struct smp_ops_t smp_8641_ops;
> +
> +#endif	/* __MPC86XX_H__ */
> diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/ 
> powerpc/platforms/86xx/mpc86xx_hpcn.c
> new file mode 100644
> index 0000000..d413e95
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
> @@ -0,0 +1,304 @@
> +/*
> + * MPC86xx HPCN board specific routines
> + *
> + * Recode: ZHANG WEI <wei.zhang@freescale.com>
> + * Initial author: Xianghua Xiao <x.xiao@freescale.com>
> + *
> + * 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.
> + */
> +
> +#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 */
> +	(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: PEX1 */
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PEX2 */
> +	(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: */
> +	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,
> +};
> +
> +
> +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_PEX
> +	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)
> +{
> +	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 */
> +		{0, 0, 0, 0},			/* IDSEL 26 */
> +		{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;
> +}
> +
> +
> +int
> +mpc86xx_exclude_device(u_char bus, u_char devfn)
> +{
> +#if !defined(CONFIG_PEX)
> +	if (bus == 0 && PCI_SLOT(devfn) == 0)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +#endif
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +#endif /* CONFIG_PCI */
> +
> +
> +static void __init
> +mpc86xx_hpcn_setup_arch(void)
> +{
> +	struct device_node *np;
> +
> +#ifdef CONFIG_SMP
> +	phys_addr_t mcm_paddr;
> +	void *mcm_vaddr = NULL;
> +	unsigned long vaddr;
> +#endif
> +
> +	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_PEX
> +	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("HPCN board with 86xx from Freescale Semiconductor\n");
> +
> +#ifdef  CONFIG_ROOT_NFS
> +	ROOT_DEV = Root_NFS;
> +#else
> +	ROOT_DEV = Root_HDA1;
> +#endif
> +
> +#ifdef CONFIG_SMP
> +  	/* Release Core 1 in boot holdoff */
> +	mcm_paddr = get_immrbase() + MPC86xx_MCM_OFFSET;
> +	mcm_vaddr = ioremap(mcm_paddr, MPC86xx_MCM_SIZE);
> +
> +	vaddr = (unsigned long)mcm_vaddr +  MCM_PORT_CONFIG_OFFSET;
> +	out_be32((volatile unsigned *)vaddr, CPU_ALL_RELEASED);

uugh, clean this up.

> +	smp_ops = &smp_8641_ops;
> +#endif
> +}
> +
> +
> +void
> +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
> +{
> +	uint pvid, svid, phid1;
> +	uint memsize = total_memory;
> +
> +	pvid = mfspr(SPRN_PVR);
> +	svid = mfspr(SPRN_SVR);
> +
> +	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
> +	seq_printf(m, "Machine\t\t: MPC86xx HPCN Board\n");
> +	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
> +	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
> +
> +	/* Display cpu Pll setting */
> +	phid1 = mfspr(SPRN_HID1);
> +	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
> +
> +	/* Display the amount of memory */
> +	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));

What does 'cat /proc/cpuinfo' look like?

> +}
> +
> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +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;
> +}
> +
> +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,
> +};
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Help -- failed to boot up kernel on PPC40 5
From: Denny @ 2006-06-09  2:11 UTC (permalink / raw)
  To: wolfgang denk; +Cc: linuxppc-embedded
In-Reply-To: <20060608214239.A71EE35265D@atlas.denx.de>

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

Dear Denk,
 
      I use the linux 2.6.14 of your website, and compile it with the ELDK4.0 succesfully, but when I download it to my PPC405 board, it stopped after initialized the MMU, and encounter an exception in "_start_here".
 
Logs:
u-boot => tftpboot 0x6000000 uImage
miiphy_register: non unique device name 'ppc_4xx_eth0'
ENET Speed is 100 Mbps - FULL duplex connection
TFTP from server 192.168.65.235; our IP address is 192.168.65.239
Filename 'uImage'.
Load address: 0x6000000
Loading: #################################################################
         #####################################
done
Bytes transferred = 521637 (7f5a5 hex)
u-boot => bootm 0x6000000
## Booting image at 0x06000000 ...
   Image Name:   Linux-2.6.14
   Created:      2006-06-09   1:00:37 UTC
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    521573 Bytes = 509.3 kB
   Load Address: 0x00100000
   Entry Point:  0x00100000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Now starting to boot the kernel...
## Current stack ends at 0x07F81A90 => set upper limit to 0x00800000
## cmdline at 0x007FFF00 ... 0x007FFF00
memstart    = 0x00000000
memsize     = 0x08000000
flashstart  = 0xFFFA0000
flashsize   = 0x01080000
flashoffset = 0x00029300
sramstart   = 0x00000000
sramsize    = 0x00000000
bootflags   = 0x0000A000
procfreq    =    200 MHz
plb_busfreq =    100 MHz
pci_busfreq = 33.333 MHz
ethaddr     = 00:01:02:54:12:47
IP addr     = 192.168.65.239
baudrate    =   9600 bps
Ramdisk image not found, no initrd!
## Transferring control to Linux (at address 0x00100000) ...
booting kernel with FLAT_TREE...
NIP: C000221C XER: 20000000 LR: 00100018 REGS: 07f819a0 TRAP: 0700 DAR: 07FC31D0
MSR: 00021030 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 11
GPR00: C0002218 07F81A90 00000000 C00003C0 C0000000 00000000 007FFF00 007FFF00 
GPR08: 07FAB560 0BEBC200 00000000 00000000 20BDE736 00000000 07FD0D00 007FFF00 
GPR16: 00100000 07FCF70C FFFFFFFF 00000000 00800000 007FFF00 07FCAE20 00000002 
GPR24: 07F81B50 007FFE70 00780000 007FFF00 007FFF00 00000000 00000000 007FFE70 
** Illegal Instruction **
Call backtrace: 
Program Check Exception

U-Boot 1.1.4 (Jun  9 2006 - 09:36:28)
...
...
My objdump file is as the following:
...
c0002208: 7c 00 04 ac  sync    
c000220c: 4c 00 00 64  rfi
c0002210: 48 00 00 00  b       c0002210 <finish_tlb_load+0x48>
c0002214 <giveup_fpu>:
c0002214: 4e 80 00 20  blr
c0002218 <start_here>:
c0002218: 3c 40 c0 0f  lis     r2,-16369
c000221c: 60 42 17 60  ori     r2,r2,5984
c0002220: 3c 82 40 00  addis   r4,r2,16384
c0002224: 38 84 01 c8  addi    r4,r4,456
...
 
Best Regards!
- Denny
 

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

^ permalink raw reply

* RE: does Gianfar Ethernet Controller Version 1.1 support MARVELL 88E1111?
From: Liu Dave-r63238 @ 2006-06-09  3:35 UTC (permalink / raw)
  To: Fleming Andy-afleming, Guo Jaffe; +Cc: Linuxppc-embedded

> On Jun 8, 2006, at 12:51, Guo Jaffe wrote:
> 
> > Hi Andy,
> >
> > Thank you for your information. So the driver is not the issue, but
> > better to upgraded.
> >
> > I will check the board once more. The PHY doesn't work because the
> > 8bit bus between MAC and PHY is locked(TX_EN and RX_DV all 
> disabled  
> > from the scope's view) and also you can't see any signals exist at  
> > the Magnetic side(nor LED signals). It seems that only 
> MDC/MDIO and  
> > CLOCK reference pin works. The PHY's ID must be read from MDC/MDIO  
> > interface and Clocks are right showed on the scope.
> 
> 
> But what error are you getting?  What are the symptoms of your  
> problem?  The GMII interface (the 8-bit bus) is inconsequential to  
> PHY configuration and management.  Only the MDC/MDIO bus is used.   
> Therefore the PHY id should be quite readable.  What version 
> of Linux  
> are you using?  Please describe what the kernel prints out when you  
> boot, and when you try to bring up the interface (assuming you don't  
> do that at boot).
> 
> Andy

As you said, the MDIO bus looks like well. If the PHY address it is right,
You can read the PHY ID from PHY. What is the PHY ID you read?

Please check the hardware status

1) 8540 hardware reset configuration for GMII interface;
Make sure it is GMII interface.

2) MARVELL 88E1111 configuration and GMII interface connection.
You can reference the 8540 ref board.
 
3)TSEC and PHY power

4)The 125M reference clock---GTX_CLK125, This looks
well as you said.

5)The GTX_CLK for GMII transmit clock, and TX_CLK for MII transmit clock.
What speed ethernet does the TSEC  connect to? 1000Mbps or 100Mbps?

6) The RX_CLK for receive clock.

7)Of cause, need check the RX_DV and TX_EN to see if have some traffic.

-Dave

^ permalink raw reply

* Re: [PATCH 2/10 v2] Add the MPC8641 HPCN platform files.
From: Benjamin Herrenschmidt @ 2006-06-09  4:15 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1149803821.23938.278.camel@cashmere.sps.mot.com>

On Thu, 2006-06-08 at 16:57 -0500, Jon Loeliger wrote:

> +void
> +mpc86xx_restart(char *cmd)
> +{
> +	void __iomem *rstcr;
> +
> +	local_irq_disable();
> +
> +	/* Assert reset request to Reset Control Register */
> +	rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
> +	out_be32(rstcr, 0x2);
> +
> +	/* not reached */
> +}

ioremap with irq disabled isn't great....  You should do the ioremap
once at boot.

> +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;
> +}

Overall, that file is too small :) Move those into your setup.c and make
those static... Also time_init() is too late to enable the timebase
imho. You should have it enabled as soon as possible, possibly as soon
as the cpu setup gets run (though you don't have to initialize it to 0)

> +#ifdef CONFIG_SMP
> +static void __init
> +smp_8641_kick_cpu(int nr)
> +{
> +	*(unsigned long *)KERNELBASE = nr;
> +	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
> +	printk("CPU%d released, waiting\n",nr);
> +}
> +
> +static void __init
> +smp_8641_setup_cpu(int cpu_nr)
> +{
> +	mpic_setup_this_cpu();
> +}
> +
> +
> +struct smp_ops_t smp_8641_ops = {
> +	.message_pass = smp_mpic_message_pass,
> +	.probe = smp_mpic_probe,
> +	.kick_cpu = smp_8641_kick_cpu,
> +	.setup_cpu = smp_8641_setup_cpu,
> +	.take_timebase = smp_generic_take_timebase,
> +	.give_timebase = smp_generic_give_timebase,
> +};
> +#endif /* CONFIG_SMP */

This file could/should be called *_smp.c and not need #ifdef's :)

> diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
> new file mode 100644
> index 0000000..4ba5b4c
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
> @@ -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 <x.xiao@freescale.com>
> + */
> +
> +#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
> +
> +/* PEX memory map */
> +#define MPC86XX_PEX_LOWER_IO        0x00000000
> +#define MPC86XX_PEX_UPPER_IO        0x00ffffff
> +
> +#define MPC86XX_PEX_LOWER_MEM       0x80000000
> +#define MPC86XX_PEX_UPPER_MEM       0x9fffffff
> +
> +#define MPC86XX_PEX_IO_BASE         0xe2000000
> +#define MPC86XX_PEX_MEM_OFFSET      0x00000000
> +
> +#define MPC86XX_PEX_IO_SIZE         0x01000000
> +
> +#define PEX1_CFG_ADDR_OFFSET    (0x8000)
> +#define PEX1_CFG_DATA_OFFSET    (0x8004)
> +
> +#define PEX2_CFG_ADDR_OFFSET    (0x9000)
> +#define PEX2_CFG_DATA_OFFSET    (0x9004)
> +
> +#define MPC86xx_PEX_OFFSET PEX1_CFG_ADDR_OFFSET
> +#define MPC86xx_PEX_SIZE	(0x1000)
> +
> +#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */

Most of the values above should probably be retreived from the
device-tree.

> +#endif	/* __MPC8641_HPCN_H__ */
> diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
> new file mode 100644
> index 0000000..7cc45d4
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc86xx.h
> @@ -0,0 +1,31 @@
> +/*
> + * 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 void mpc86xx_restart(char *cmd);
> +extern long __init mpc86xx_time_init(void);

As I suggested before, the 2 above should be static in your setup file.

> +extern int __init add_bridge(struct device_node *dev);

Aren't we exposing that already via some header ?

> +extern void __init setup_indirect_pex(struct pci_controller* hose,
> +				      u32 cfg_addr, u32 cfg_data);
> +extern void __init setup_indirect_pex_nomap(struct pci_controller* hose,
> +					    void __iomem * cfg_addr,
> +					    void __iomem * cfg_data);
> +
> +extern struct smp_ops_t smp_8641_ops;

See my comments about the PCI stuff with the PCI patch.

> +#endif	/* __MPC86XX_H__ */
> diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
> new file mode 100644
> index 0000000..d413e95
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
> @@ -0,0 +1,304 @@
> +/*
> + * MPC86xx HPCN board specific routines
> + *
> + * Recode: ZHANG WEI <wei.zhang@freescale.com>
> + * Initial author: Xianghua Xiao <x.xiao@freescale.com>
> + *
> + * 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.
> + */
> +
> +#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 */
> +	(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: PEX1 */
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PEX2 */
> +	(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: */
> +	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,
> +};

All of the above should of course come from the device-tree. 2.6.18 will
have the support for having interrupt routing from it without having
nodes for all devices. I'll post it to the list in a week or so, I'm
coding right now :)

> +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;

Do you really _need_ studly caps ? I know we did that before but you
don't have to copy ugly stuff :)

In general, you -need- a device node for the interrupt controller. It
will be made mandatory by the new code. You'll have to provide proper
interrupt informations in your device-tree (it's easy, really). Your
host PCI bridge shall have the interrupt-map for all the slots lines and
your on chip devices have proper interrupt routing info, and all shall
have your interrupt controller node as the interrupt parent.

If you get that right, it will be very easy to "just work" with my new
code.

> +	/* 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);

I haven't looked in detail at your memory map, but do you need separate
ISUs ? They seem to be quite close together to me... Also, you should
invent properties in the mpic node for some of those things, like
big-endian (like apple does) indicating it's a big endian openpic,
etc... If you manage to get close enough to spec & common usage, you
might not even need your own init function at all in the future.

> +	/* 16 External interrupts */
> +	mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10000);

That looks like you used ISUs in order to "re-order" them... why ?

> +	mpic_init(mpic1);
> +
> +#ifdef CONFIG_PEX
> +	mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL);
> +	i8259_init(0, I8259_OFFSET);
> +#endif
> +}

Cascade handling is changing with my genirq port. It will be easy to
adapt though. Same comments howveer, you should have a device-tree node
for the 8259 (under an ISA bridge, those shall really be in the
device-tree). In general, on-board bridges should be in the device-tree,
only slots or standardly routed child PCI devices need not.

> +int
> +mpc86xx_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 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 */
> +		{0, 0, 0, 0},			/* IDSEL 26 */
> +		{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;
> +}

All of the above shall be in the device-tree.

> +
> +int
> +mpc86xx_exclude_device(u_char bus, u_char devfn)
> +{
> +#if !defined(CONFIG_PEX)
> +	if (bus == 0 && PCI_SLOT(devfn) == 0)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +#endif
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +#endif /* CONFIG_PCI */

Hrm... not sure I like that much but let's ignore it for now.
> +
> +static void __init
> +mpc86xx_hpcn_setup_arch(void)
> +{
> +	struct device_node *np;
> +
> +#ifdef CONFIG_SMP
> +	phys_addr_t mcm_paddr;
> +	void *mcm_vaddr = NULL;
> +	unsigned long vaddr;
> +#endif
> +
> +	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);
> +	}

The above looks dodgy... powerpc uses the timebase frequency for delays
anyway, lpj will be initialized by the bogomips code, and should but
unused mostly nowadays anyway.

> +#ifdef CONFIG_PEX
> +	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

I'm not sure I like this CONFIG_PEX (in general). Just use CONFIG_PCI
for now all over the place. PCI-E has it's own binding that we don't
quite respect yet but will do and all of that will be in the
device-tree. However, as far as the kernel is concerned, this is all
under CONFIG_PCI.

> +	printk("HPCN board with 86xx from Freescale Semiconductor\n");
> +
> +#ifdef  CONFIG_ROOT_NFS
> +	ROOT_DEV = Root_NFS;
> +#else
> +	ROOT_DEV = Root_HDA1;
> +#endif
> +
> +#ifdef CONFIG_SMP
> +  	/* Release Core 1 in boot holdoff */
> +	mcm_paddr = get_immrbase() + MPC86xx_MCM_OFFSET;
> +	mcm_vaddr = ioremap(mcm_paddr, MPC86xx_MCM_SIZE);
> +
> +	vaddr = (unsigned long)mcm_vaddr +  MCM_PORT_CONFIG_OFFSET;
> +	out_be32((volatile unsigned *)vaddr, CPU_ALL_RELEASED);
> +	smp_ops = &smp_8641_ops;
> +#endif
> +}

Instead of ifdef's, just do a mpc86xx_smp_init() and put it somewhere
with the other SMP things in the file that contains them (and remove the
#ifdef's there too, just only build the file if CONFIG_SMP is set).

> +
> +void
> +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
> +{
> +	uint pvid, svid, phid1;
> +	uint memsize = total_memory;
> +
> +	pvid = mfspr(SPRN_PVR);
> +	svid = mfspr(SPRN_SVR);
>
> +	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
> +	seq_printf(m, "Machine\t\t: MPC86xx HPCN Board\n");
> +	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
> +	seq_printf(m, "SVR\t\t: 0x%x\n", svid);

The PVR is probably a duplicate and the SVR should be added to per-cpu
info instead.

> +	/* Display cpu Pll setting */
> +	phid1 = mfspr(SPRN_HID1);
> +	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
> +
> +	/* Display the amount of memory */
> +	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
> +}
> +
> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +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;
> +}
> +
> +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,
> +};
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 4/10 v2] Guard L3CR references with CPU_FTR_L3CR.
From: Benjamin Herrenschmidt @ 2006-06-09  4:17 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1149803912.23938.282.camel@cashmere.sps.mot.com>

On Thu, 2006-06-08 at 16:58 -0500, Jon Loeliger wrote:
> Signed-off-by: Jon Loeliger <jdl@freescale.com>

Beware about this one... the CPU setup code might run before the feature
fixup in the future... you should probably do a separate setup function
for your core or go read the feature bit directly in the structure
rather than relying on the fixup mecanism.

> ---
> 
>  arch/powerpc/kernel/cpu_setup_6xx.S |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> 
> diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
> index 55ed771..365381f 100644
> --- a/arch/powerpc/kernel/cpu_setup_6xx.S
> +++ b/arch/powerpc/kernel/cpu_setup_6xx.S
> @@ -210,9 +210,11 @@ setup_745x_specifics:
>  	 * the firmware. If any, we disable NAP capability as
>  	 * it's known to be bogus on rev 2.1 and earlier
>  	 */
> +BEGIN_FTR_SECTION
>  	mfspr	r11,SPRN_L3CR
>  	andis.	r11,r11,L3CR_L3E@h
>  	beq	1f
> +END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
>  	lwz	r6,CPU_SPEC_FEATURES(r5)
>  	andi.	r0,r6,CPU_FTR_L3_DISABLE_NAP
>  	beq	1f
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 5/10 v2] Add 8641 CPU and i8259 Setup
From: Benjamin Herrenschmidt @ 2006-06-09  4:23 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1149803956.23938.284.camel@cashmere.sps.mot.com>


> --- a/arch/powerpc/kernel/head_32.S
> +++ b/arch/powerpc/kernel/head_32.S
> @@ -224,6 +224,10 @@ turn_on_mmu:
>  	li	r3,1			/* MTX only has 1 cpu */
>  	.globl	__secondary_hold
>  __secondary_hold:
> +#ifdef CONFIG_PPC_86xx
> +	/* get the cpu id */
> +	mfspr	r3, SPRN_PIR
> +#endif

The above is wrong, it prevents using the same kernel image on another
platform. If you need a separate hold loop, then go for it but don't
change the existing one in a non-compatible way. Alternatively, you can
do like powermac, that is have several "entrypoints" to the same hold
loop providing different CPU IDs.

>  	/* tell the master we're here */
>  	stw	r3,__secondary_hold_acknowledge@l(0)
>  #ifdef CONFIG_SMP
> @@ -348,6 +352,16 @@ #define EXC_XFER_EE_LITE(n, hdlr)	\
>  #if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
>  	. = 0x100
>  	b	__secondary_start_gemini
> +#endif
> +/* we need to ensure that the address translation is disabled */
> +#if defined(CONFIG_PPC_86xx) && defined(CONFIG_SMP)
> +        . = 0x100
> +        mfmsr   r3
> +        andi.   r0, r3, (MSR_IR | MSR_DR)
> +        andc    r3, r3, r0
> +        mtmsr   r3
> +        isync
> +        b       __secondary_hold
>  #else
>  	EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
>  #endif

Same comment above... #ifdef is bad. You are entering from 0x100 with
address translation not disabled ? How is that possible ? If it's your
firmware, then fix it :) If not possible, then have a real good
explanation why and how you end up in 0x100 that way. At worse, do like
pmac does and "patch" the 0x100 vector to point to some machine specific
code dynamically at runtime. 

> @@ -1019,6 +1033,7 @@ #endif /* CONFIG_6xx */
>  	stw	r0,0(r3)
>  
>  	/* load up the MMU */
> +	bl	clear_bats
>  	bl	load_up_mmu

Why do you need to call clear_bats here ? load_up_mmu should load BATs.
If it doesn't handle the high BATs, then fix it :) 

>  	/* ptr to phys current thread */
> diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
> index b7ac32f..9b755e1 100644
> --- a/arch/powerpc/sysdev/i8259.c
> +++ b/arch/powerpc/sysdev/i8259.c
> @@ -201,6 +201,11 @@ void __init i8259_init(unsigned long int
>  	outb(0x0B, 0x20);
>  	outb(0x0B, 0xA0);
>  
> +#ifdef CONFIG_I8259_LEVEL_TRIGGER
> +	outb(0xfa, 0x4d0); /* level triggered */
> +	outb(0xde, 0x4d1);
> +#endif

Another change that breaks multiplatform... Can you explain precisely
what you are trying to acheive here ? If necessary, we can add an
argument to i8259_init. Or you could do the above in your platform
code ... though I agree it would be a bit ugly :) 

>  	/* Mask all interrupts */
>  	outb(cached_A1, 0xA1);
>  	outb(cached_21, 0x21);

^ permalink raw reply

* Re: [PATCH 3/10 v2] Add MPC8641 HPCN PCI and PCI-Express files.
From: Benjamin Herrenschmidt @ 2006-06-09  4:33 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1149803866.23938.280.camel@cashmere.sps.mot.com>

On Thu, 2006-06-08 at 16:57 -0500, Jon Loeliger wrote:
> Signed-off-by: Xianghua Xiao <x.xiao@freescale.com>
> Signed-off-by: Wei Zhang <Wei.Zhang@freescale.com>
> Signed-off-by: Haiying Wang <Haiying.Wang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>

There are various things in this code that duplicate names used by other
platforms and thus makes the board unsuitable for use in a common
kernel. That needs to be fixed. Try avoiding too generic names. Also,
PCI Express shall be named "pcie" and not "pex" :)

I don't have time at the moment to go too deep in the details here.

Ben.

> ---
> 
>  arch/powerpc/platforms/86xx/pci.c |  213 +++++++++++++++++++++++++++++++++++++
>  arch/powerpc/platforms/86xx/pex.c |  173 ++++++++++++++++++++++++++++++
>  2 files changed, 386 insertions(+), 0 deletions(-)
> 
> 
> diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
> new file mode 100644
> index 0000000..eff6f28
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/pci.c
> @@ -0,0 +1,213 @@
> +/*
> + * MPC86XX pci setup code
> + *
> + * Recode: ZHANG WEI <wei.zhang@freescale.com>
> + * Initial author: Xianghua Xiao <x.xiao@freescale.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/serial.h>
> +
> +#include <asm/system.h>
> +#include <asm/atomic.h>
> +#include <asm/io.h>
> +#include <asm/prom.h>
> +#include <asm/immap_86xx.h>
> +#include <asm/pci-bridge.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#include "mpc86xx.h"
> +
> +
> +#ifdef CONFIG_PEX
> +static void __init
> +mpc86xx_setup_pex(struct pci_controller *hose)
> +{
> +	volatile struct ccsr_pex *pex;
> +	u16 cmd;
> +	unsigned int temps;
> +	phys_addr_t immr;
> +
> +	immr = get_immrbase();
> +
> +	pex = ioremap(immr + MPC86xx_PEX_OFFSET, MPC86xx_PEX_SIZE);
> +
> +	early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
> +	cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
> +	    | PCI_COMMAND_IO;
> +	early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
> +
> +	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
> +
> +	/* PEX Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
> +	early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
> +	temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
> +	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
> +
> +	/* Disable all windows (except pexowar0 since its ignored) */
> +	pex->pexowar1 = 0;
> +	pex->pexowar2 = 0;
> +	pex->pexowar3 = 0;
> +	pex->pexowar4 = 0;
> +	pex->pexiwar1 = 0;
> +	pex->pexiwar2 = 0;
> +	pex->pexiwar3 = 0;
> +
> +	/* Setup Phys:PEX 1:1 outbound mem window @ MPC86XX_PEX_LOWER_MEM */
> +	pex->pexotar1 = (MPC86XX_PEX_LOWER_MEM >> 12) & 0x000fffff;
> +	pex->pexotear1 = 0x00000000;
> +	pex->pexowbar1 = (MPC86XX_PEX_LOWER_MEM >> 12) & 0x000fffff;
> +	/* Enable, Mem R/W */
> +	pex->pexowar1 = 0x80044000 |
> +		(__ilog2(MPC86XX_PEX_UPPER_MEM - MPC86XX_PEX_LOWER_MEM + 1) - 1);
> +
> +	/* Setup outboud IO windows @ MPC86XX_PEX_IO_BASE */
> +	pex->pexotar2 = (MPC86XX_PEX_LOWER_IO >> 12) & 0x000fffff;
> +	pex->pexotear2 = 0x00000000;
> +	pex->pexowbar2 = (MPC86XX_PEX_IO_BASE >> 12) & 0x000fffff;
> +	/* Enable, IO R/W */
> +	pex->pexowar2 = 0x80088000 | (__ilog2(MPC86XX_PEX_IO_SIZE) - 1);
> +
> +	/* Setup 2G inbound Memory Window @ 0 */
> +	pex->pexitar1 = 0x00000000;
> +	pex->pexiwbar1 = 0x00000000;
> +	/* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
> +	pex->pexiwar1 = 0xa0f5501e;
> +}
> +
> +int __init add_bridge(struct device_node *dev)
> +{
> +	int len;
> +	struct pci_controller *hose;
> +	struct resource rsrc;
> +	int *bus_range;
> +	int has_address = 0;
> +
> +	pr_debug("Adding PEX host bridge %s\n", dev->full_name);
> +
> +	/* Fetch host bridge registers address */
> +	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
> +
> +	/* Get bus range if any */
> +	bus_range = (int *) get_property(dev, "bus-range", &len);
> +	if (bus_range == NULL || len < 2 * sizeof(int))
> +		printk(KERN_WARNING "Can't get bus-range for %s, assume"
> +		       " bus 0\n", dev->full_name);
> +
> +	hose = pcibios_alloc_controller();
> +	if (!hose)
> +		return -ENOMEM;
> +	hose->arch_data = dev;
> +	hose->set_cfg_type = 1;
> +
> +	/* last_busno = 0xfe cause by PEX bug */
> +	hose->first_busno = bus_range ? bus_range[0] : 0x0;
> +	hose->last_busno = bus_range ? bus_range[1] : 0xfe;
> +
> +	setup_indirect_pex(hose, rsrc.start, rsrc.start + 0x4);
> +
> +	/* Setup the first PEX controller. */
> +	if ((rsrc.start & 0xfffff) == 0x8000)
> +		mpc86xx_setup_pex(hose);
> +
> +	printk(KERN_INFO "Found MPC86xx PEX host bridge at 0x%08lx. "
> +	       "Firmware bus number: %d->%d\n",
> +		rsrc.start, hose->first_busno, hose->last_busno);
> +
> +	pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
> +		hose, hose->cfg_addr, hose->cfg_data);
> +
> +	/* Interpret the "ranges" property */
> +	/* This also maps the I/O region and sets isa_io/mem_base */
> +	pci_process_bridge_OF_ranges(hose, dev, 1);
> +
> +	return 0;
> +}
> +#endif /* CONFIG_PEX */
> +
> +static void __devinit quirk_ali1575(struct pci_dev *dev)
> +{
> +	/*
> +	 * ALI1575 interrupts route table setup:
> +	 *
> +	 * IRQ pin   IRQ#
> +	 * PIRQA ---- 3
> +	 * PIRQB ---- 4
> +	 * PIRQC ---- 5
> +	 * PIRQD ---- 6
> +	 * PIRQE ---- 9
> +	 * PIRQF ---- 10
> +	 * PIRQG ---- 11
> +	 * PIRQH ---- 12
> +	 *
> +	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
> +	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
> +	 */
> +	pci_write_config_dword(dev, 0x48, 0xb9317542);
> +
> +	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
> +	pci_write_config_byte(dev, 0x86, 0x0c);
> +
> +	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
> +	pci_write_config_byte(dev, 0x87, 0x0d);
> +
> +	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
> +	pci_write_config_byte(dev, 0x88, 0x0f);
> +
> +	/* USB 2.0 controller, interrupt: PIRQ7 */
> +	pci_write_config_byte(dev, 0x74, 0x06);
> +
> +	/* Audio controller, interrupt: PIRQE */
> +	pci_write_config_byte(dev, 0x8a, 0x0c);
> +
> +	/* Modem controller, interrupt: PIRQF */
> +	pci_write_config_byte(dev, 0x8b, 0x0d);
> +
> +	/* HD audio controller, interrupt: PIRQG */
> +	pci_write_config_byte(dev, 0x8c, 0x0e);
> +
> +	/* Serial ATA interrupt: PIRQD */
> +	pci_write_config_byte(dev, 0x8d, 0x0b);
> +
> +	/* SMB interrupt: PIRQH */
> +	pci_write_config_byte(dev, 0x8e, 0x0f);
> +
> +	/* PMU ACPI SCI interrupt: PIRQH */
> +	pci_write_config_byte(dev, 0x8f, 0x0f);
> +
> +}
> +
> +static void __devinit quirk_uli5288(struct pci_dev *dev)
> +{
> +	unsigned char c;
> +
> +	pci_read_config_byte(dev,0x83,&c);
> +	c |= 0x80;
> +	pci_write_config_byte(dev, 0x83, c);
> +
> +	pci_write_config_byte(dev, 0x09, 0x01);
> +	pci_write_config_byte(dev, 0x0a, 0x06);
> +
> +	pci_read_config_byte(dev,0x83,&c);
> +	c &= 0x7f;
> +	pci_write_config_byte(dev, 0x83, c);
> +
> +	pci_read_config_byte(dev,0x84,&c);
> +	c |= 0x01;
> +	pci_write_config_byte(dev, 0x84, c);
> +}
> +
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
> +
> diff --git a/arch/powerpc/platforms/86xx/pex.c b/arch/powerpc/platforms/86xx/pex.c
> new file mode 100644
> index 0000000..2624d3c
> --- /dev/null
> +++ b/arch/powerpc/platforms/86xx/pex.c
> @@ -0,0 +1,173 @@
> +/*
> + * Support for indirect PCI bridges.
> + *
> + * Copyright (C) 1998 Gabriel Paubert.
> + *
> + * 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.
> + *
> + * "Temporary" MPC8548 Errata file -
> + * The standard indirect_pci code should work with future silicon versions.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/delay.h>
> +#include <linux/string.h>
> +#include <linux/init.h>
> +#include <linux/bootmem.h>
> +
> +#include <asm/io.h>
> +#include <asm/prom.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/machdep.h>
> +
> +#include "mpc86xx.h"
> +
> +#define PCI_CFG_OUT out_be32
> +
> +/* ERRATA PCI-Ex 14 PEX Controller timeout */
> +#define PEX_FIX		out_be32(hose->cfg_addr+0x4, 0x0400ffff)
> +
> +
> +static int
> +indirect_read_config_pex(struct pci_bus *bus, unsigned int devfn, int offset,
> +		     int len, u32 *val)
> +{
> +	struct pci_controller *hose = bus->sysdata;
> +	volatile void __iomem *cfg_data;
> +	u32 temp;
> +
> +	if (ppc_md.pci_exclude_device)
> +		if (ppc_md.pci_exclude_device(bus->number, devfn))
> +			return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	/* Possible artifact of CDCpp50937 needs further investigation */
> +	if (devfn != 0x0 && bus->number == 0xff)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	PEX_FIX;
> +	if (bus->number == 0xff) {
> +		PCI_CFG_OUT(hose->cfg_addr,
> +			    (0x80000000 | ((offset & 0xf00) << 16) |
> +			     ((bus->number - hose->bus_offset) << 16)
> +			     | (devfn << 8) | ((offset & 0xfc) )));
> +	} else {
> +		PCI_CFG_OUT(hose->cfg_addr,
> +			    (0x80000001 | ((offset & 0xf00) << 16) |
> +			     ((bus->number - hose->bus_offset) << 16)
> +			     | (devfn << 8) | ((offset & 0xfc) )));
> +	}
> +
> +	/*
> +	 * Note: the caller has already checked that offset is
> +	 * suitably aligned and that len is 1, 2 or 4.
> +	 */
> +	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
> +	cfg_data = hose->cfg_data;
> +	PEX_FIX;
> +	temp = in_le32(cfg_data);
> +	switch (len) {
> +	case 1:
> +		*val = (temp >> (((offset & 3))*8)) & 0xff;
> +		break;
> +	case 2:
> +		*val = (temp >> (((offset & 3))*8)) & 0xffff;
> +		break;
> +	default:
> +		*val = temp;
> +		break;
> +	}
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int
> +indirect_write_config_pex(struct pci_bus *bus, unsigned int devfn, int offset,
> +		      int len, u32 val)
> +{
> +	struct pci_controller *hose = bus->sysdata;
> +	volatile void __iomem *cfg_data;
> +	u32 temp;
> +
> +	if (ppc_md.pci_exclude_device)
> +		if (ppc_md.pci_exclude_device(bus->number, devfn))
> +			return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	/* Possible artifact of CDCpp50937 needs further investigation */
> +	if (devfn != 0x0 && bus->number == 0xff)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	PEX_FIX;
> +	if (bus->number == 0xff) {
> +		PCI_CFG_OUT(hose->cfg_addr,
> +			    (0x80000000 | ((offset & 0xf00) << 16) |
> +			     ((bus->number - hose->bus_offset) << 16)
> +			     | (devfn << 8) | ((offset & 0xfc) )));
> +	} else {
> +		PCI_CFG_OUT(hose->cfg_addr,
> +			    (0x80000001 | ((offset & 0xf00) << 16) |
> +			     ((bus->number - hose->bus_offset) << 16)
> +			     | (devfn << 8) | ((offset & 0xfc) )));
> +        }
> +
> +	/*
> +	 * Note: the caller has already checked that offset is
> +	 * suitably aligned and that len is 1, 2 or 4.
> +	 */
> +	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
> +	cfg_data = hose->cfg_data;
> +	switch (len) {
> +	case 1:
> +		PEX_FIX;
> +		temp = in_le32(cfg_data);
> +		temp = (temp & ~(0xff << ((offset & 3) * 8))) |
> +			(val << ((offset & 3) * 8));
> +		PEX_FIX;
> +		out_le32(cfg_data, temp);
> +		break;
> +	case 2:
> +		PEX_FIX;
> +		temp = in_le32(cfg_data);
> +		temp = (temp & ~(0xffff << ((offset & 3) * 8)));
> +		temp |= (val << ((offset & 3) * 8)) ;
> +		PEX_FIX;
> +		out_le32(cfg_data, temp);
> +		break;
> +	default:
> +		PEX_FIX;
> +		out_le32(cfg_data, val);
> +		break;
> +	}
> +	PEX_FIX;
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static struct pci_ops indirect_pex_ops = {
> +	indirect_read_config_pex,
> +	indirect_write_config_pex
> +};
> +
> +void __init
> +setup_indirect_pex_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
> +	void __iomem * cfg_data)
> +{
> +	hose->cfg_addr = cfg_addr;
> +	hose->cfg_data = cfg_data;
> +	hose->ops = &indirect_pex_ops;
> +}
> +
> +void __init
> +setup_indirect_pex(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
> +{
> +	unsigned long base = cfg_addr & PAGE_MASK;
> +	void __iomem *mbase, *addr, *data;
> +
> +	mbase = ioremap(base, PAGE_SIZE);
> +	addr = mbase + (cfg_addr & ~PAGE_MASK);
> +	if ((cfg_data & PAGE_MASK) != base)
> +		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
> +	data = mbase + (cfg_data & ~PAGE_MASK);
> +	setup_indirect_pex_nomap(hose, addr, data);
> +}
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: Linux kernel 2.6 on IBM RS/6000 7025-F40
From: Benjamin Herrenschmidt @ 2006-06-09  4:38 UTC (permalink / raw)
  To: Christophe Simon; +Cc: linuxppc-dev
In-Reply-To: <BAY109-F5B7EE1B27D613DA2C4281AC8A0@phx.gbl>

On Wed, 2006-06-07 at 15:30 +0000, Christophe Simon wrote:
> Hi there,
> 
> Did someone succeeded in compiling a running 2.6 kernel on an IBM RS/6000 
> 7025-F40 (PReP arch) ? I have one of these machines, and it runs with a 
> 2.4.22 kernel built using the instructions gathered on 
> http://www.solinno.co.uk/7043-140/
> 
> It seems that this machine is quite problematic.
> 
> I tried to compile my own kernel with a stock 2.6.16.19, and after that 
> 2.6.7 patched with the files I found for the 2.6.7 (at 
> http://www.solinno.co.uk/7043-140/files/2.6.7/), but the system refuses to 
> boot with those twoo kernels  (the machine reboots or freezes before writing 
> any piece of information on the console...).
> 
> The site seems not to move anymore, and I'd like to have a 2.6 kernel 
> running because of his better performances ans extended functionalities, and 
> I'd like not to be stalled on 2.4.22 kernel...
> 
> I crawled the web hours and hours (Google is my friend, but it didn't help 
> me...) and I didn't find anything...

I've successfully booted a 43p, I don't know about F40 though. What is
the last message on the console when you try to boot the kernel ?

Ben.

^ permalink raw reply

* Re: Help -- failed to boot up kernel on PPC40 5
From: Wolfgang Denk @ 2006-06-09  7:40 UTC (permalink / raw)
  To: Denny; +Cc: linuxppc-embedded
In-Reply-To: <4488D8D1.00003F.15159@bj163app14.163.com>

In message <4488D8D1.00003F.15159@bj163app14.163.com> you wrote:
> 
>       I use the linux 2.6.14 of your website, and compile it with the ELDK4.0 succesfully, but when I download it to my PPC405 board, it stopped after initialized the MMU, and encounter an exception in "_start_here".

Is this a standard AMCC eval board, or a custom board? Which one?

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Those who hate and fight must stop themselves -- otherwise it is  not
stopped.
	-- Spock, "Day of the Dove", stardate unknown

^ permalink raw reply

* [RFC] I2C-MPC: Fix up error handling
From: Jean Delvare @ 2006-06-09  7:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Sylvain Munaut

Hi all,

Could anyone please comment on this i2c-mpc patch, and give it some
testing on different systems? I'm fine with the error propagation
fixes, but less fine with the random resets being added, and rather
unhappy with the "retry once more just in case" thing, which I think,
if really needed, should instead be implemented using the standard
i2c_adapter.retries mechanism.

Thanks.

From: Kumar Gala <galak@kernel.crashing.org>

* If we have an Unfinished (MCF) or Arbitration Lost (MAL) error and
  the bus is still busy reset the controller.  This prevents the
  controller from getting in a hung state for transactions for other
  devices.

* Fixed up propogating the errors from i2c_wait.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/i2c/busses/i2c-mpc.c |   43 +++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 12 deletions(-)

diff -puN drivers/i2c/busses/i2c-mpc.c~i2c-mpc-fix-up-error-handling drivers/i2c/busses/i2c-mpc.c
--- devel/drivers/i2c/busses/i2c-mpc.c~i2c-mpc-fix-up-error-handling	2006-06-01 20:22:55.000000000 -0700
+++ devel-akpm/drivers/i2c/busses/i2c-mpc.c	2006-06-01 20:22:55.000000000 -0700
@@ -115,11 +115,20 @@ static int i2c_wait(struct mpc_i2c *i2c,
 
 	if (!(x & CSR_MCF)) {
 		pr_debug("I2C: unfinished\n");
+
+		/* reset the controller if the bus is still busy */
+		if (x & CSR_MBB)
+			writeccr(i2c, 0);
+
 		return -EIO;
 	}
 
 	if (x & CSR_MAL) {
 		pr_debug("I2C: MAL\n");
+
+		/* reset the controller if the bus is still busy */
+		if (x & CSR_MBB)
+			writeccr(i2c, 0);
 		return -EIO;
 	}
 
@@ -160,7 +169,7 @@ static void mpc_i2c_stop(struct mpc_i2c 
 static int mpc_write(struct mpc_i2c *i2c, int target,
 		     const u8 * data, int length, int restart)
 {
-	int i;
+	int i, ret;
 	unsigned timeout = i2c->adap.timeout;
 	u32 flags = restart ? CCR_RSTA : 0;
 
@@ -172,15 +181,17 @@ static int mpc_write(struct mpc_i2c *i2c
 	/* Write target byte */
 	writeb((target << 1), i2c->base + MPC_I2C_DR);
 
-	if (i2c_wait(i2c, timeout, 1) < 0)
-		return -1;
+	ret = i2c_wait(i2c, timeout, 1);
+	if (ret < 0)
+		return ret;
 
 	for (i = 0; i < length; i++) {
 		/* Write data byte */
 		writeb(data[i], i2c->base + MPC_I2C_DR);
 
-		if (i2c_wait(i2c, timeout, 1) < 0)
-			return -1;
+		ret = i2c_wait(i2c, timeout, 1);
+		if (ret < 0)
+			return ret;
 	}
 
 	return 0;
@@ -190,7 +201,7 @@ static int mpc_read(struct mpc_i2c *i2c,
 		    u8 * data, int length, int restart)
 {
 	unsigned timeout = i2c->adap.timeout;
-	int i;
+	int i, ret;
 	u32 flags = restart ? CCR_RSTA : 0;
 
 	/* Start with MEN */
@@ -201,8 +212,9 @@ static int mpc_read(struct mpc_i2c *i2c,
 	/* Write target address byte - this time with the read flag set */
 	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
 
-	if (i2c_wait(i2c, timeout, 1) < 0)
-		return -1;
+	ret = i2c_wait(i2c, timeout, 1);
+	if (ret < 0)
+		return ret;
 
 	if (length) {
 		if (length == 1)
@@ -214,8 +226,9 @@ static int mpc_read(struct mpc_i2c *i2c,
 	}
 
 	for (i = 0; i < length; i++) {
-		if (i2c_wait(i2c, timeout, 0) < 0)
-			return -1;
+		ret = i2c_wait(i2c, timeout, 0);
+		if (ret < 0)
+			return ret;
 
 		/* Generate txack on next to last byte */
 		if (i == length - 2)
@@ -246,8 +259,13 @@ static int mpc_xfer(struct i2c_adapter *
 			return -EINTR;
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
-			pr_debug("I2C: timeout\n");
-			return -EIO;
+			writeccr(i2c, 0);
+
+			/* try one more time before we error */
+			if (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
+				pr_debug("I2C: timeout\n");
+				return -EIO;
+			}
 		}
 		schedule();
 	}
@@ -325,6 +343,7 @@ static int fsl_i2c_probe(struct platform
 			goto fail_irq;
 		}
 
+	writeccr(i2c, 0);
 	mpc_i2c_setclock(i2c);
 	platform_set_drvdata(pdev, i2c);
 
_


-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH 10/10 v2] Document I2C_MPC option for 86xx too.
From: Jean Delvare @ 2006-06-09  7:37 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev
In-Reply-To: <1149804296.23938.298.camel@cashmere.sps.mot.com>

Hi Jon,

Please add a paragraph explaining what the patch does. It will be used
as the git commit message.

> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> 
> ---
>  drivers/i2c/busses/Kconfig |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index d6d4494..fbeae82 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -252,12 +252,12 @@ config I2C_POWERMAC
>  	  will be called i2c-powermac.
>  
>  config I2C_MPC
> -	tristate "MPC107/824x/85xx/52xx"
> +	tristate "MPC107/824x/85xx/52xx/86xx"

Maybe leave 52xx at the end, as it seems to be special?

>  	depends on I2C && PPC32
>  	help
>  	  If you say yes to this option, support will be included for the
>  	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
> -	  MPC85xx family processors. The driver may also work on 52xx
> +	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
>  	  family processors, though interrupts are known not to work.
>  
>  	  This driver can also be built as a module.  If so, the module
> 

This isn't very consistent, you first say 86xx as if several chips were
supported, then only list the MPC8641. Also, "MPC85xx family" made
sense but "MPC8641 family" doesn't.

When fixed, do you expect me to take that patch, or will it be merged
through the powerpc git tree?

-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH] force 64bit mode in system_reset_fwnmi for broken POWER4 firmware
From: Paul Mackerras @ 2006-06-09  8:11 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev
In-Reply-To: <20060523130717.GA22364@suse.de>

Olaf Hering writes:

> The reason is that system_reset_fwnmi is called in 32bit mode. Forcing
> 64bit mode fixes the corrupt NIP for me. JS20 and p690 are affected,
> seems to work on p550 and JS21.

What was the LTC bugzilla number for this again?

Paul.

^ permalink raw reply

* Re: [PATCH] hugetlb: powerpc: Actively close unused htlb regions on vma close
From: David Gibson @ 2006-06-09  8:49 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: linux-mm, linuxppc-dev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0606021407580.6179@schroedinger.engr.sgi.com>


On Fri, Jun 02, 2006 at 02:08:27PM -0700, Christoph Lameter wrote:
> On Fri, 2 Jun 2006, Adam Litke wrote:
> 
> > The real reason I want to "close" hugetlb regions (even on 64bit
> > platforms) is so a process can replace a previous hugetlb mapping with
> > normal pages when huge pages become scarce.  An example would be the
> > hugetlb morecore (malloc) feature in libhugetlbfs :)
> 
> Well that approach wont work on IA64 it seems.

Yes, but there's not much that can be done about that.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: a problem of kernel-module version mismatch.
From: Ming Liu @ 2006-06-09  8:58 UTC (permalink / raw)
  To: arnd.bergmann; +Cc: linuxppc-embedded
In-Reply-To: <200606081725.37621.arnd.bergmann@de.ibm.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=gb2312; format=flowed, Size: 4664 bytes --]

Hello Arnd,
I found a problem on unsolved symbol XIo_In32 and XIo_Out32: in the linux 
kernel directory of <kernel>/arch/ppc/platforms/xilinx_ocp, the original 
xio.h file lying there is provided by MontaVista. But when I use xilinx EDK 
to generate the driver for my perapheral, it generates such a file which is 
provided by Xilinx. There are some differneces between these two files. One 
is in the MVista version, the XIo_In32 or XIo_Out32 are defined as 'u32' 
type while in the Xilinx version as 'xuint32'. When I compiled the driver 
module, if I refered the header file to MVista xio.h, an error will appear 
which is 'xuint32' undeclared. If I refered to the Xilinx xio.h, the 
compilation succeeded. Do you think is that the reason why these two 
symbols cannot be resolved by Linux? Shall I use the MVista version xio.h 
and define XIo_In32 and XIo_out32 as 'u32' type and then the linux could 
recognize these two symbols? Waiting for your help. Thanks a lot.

Any information about this problem is also appreciated.

Regards
Ming


>From: Arnd Bergmann <arnd.bergmann@de.ibm.com>
>To: "Ming Liu" <eemingliu@hotmail.com>
>CC: linuxppc-embedded@ozlabs.org
>Subject: Re: a problem of kernel-module version mismatch.
>Date: Thu, 8 Jun 2006 17:25:37 +0200
>
>On Thursday 08 June 2006 15:52, Ming Liu wrote:
> > >The easiest way is usually to put the driver in your source tree
> > >and compile everything together. That also makes it easier to
> > >distribute the complete source tree to your users.
> >
> > Sorry that I am a novice in Linux. I don't know how can I put the 
driver in
> > my source tree and compile everything together. It looks like that 
there is
> > no option in the menuconfig to choose a specially customed peripheral. 
So I
> > think I only can include the customed peripheral as a module. Could you
> > please say in a detail on how to do that?
>
>The most simple way would be to put it into linux/drivers/misc and add it
>to the Makefile in there.
>
> > > > insmod: unresolved symbol XIo_In32
> > > > insmod: unresolved symbol XIO_Out32
> > >
> > >that looks like part of your module is missing. Try to find where 
thses
> > >functions are defined in there and why that isn't compiled.
> >
> > It's very strange because I have checked the source. In the header file 
of
> > xio.h, there are the following sentences,
> >
> > /************************** Function Prototypes
> > ******************************/
> >
> > /* The following functions allow the software to be transportable 
across
> > ? processors which may use memory mapped I/O or I/O which is mapped 
into a
> > ? seperate address space such as X86.  The functions are better suited 
for
> > ? debugging and are therefore the default implementation. Macros can
> > instead
> > ? be used if USE_IO_MACROS is defined.
> > ?/
> > #ifndef USE_IO_MACROS
>
>The comment tells you that you either need to implement these functions
>youself or #define USE_IO_MACROS in the code before this.
>
> > /* Functions */
> > Xuint8 XIo_In8(XIo_Address InAddress);
> > Xuint16 XIo_In16(XIo_Address InAddress);
> > Xuint32 XIo_In32(XIo_Address InAddress);
> >
> > void XIo_Out8(XIo_Address OutAddress, Xuint8 Value);
> > void XIo_Out16(XIo_Address OutAddress, Xuint16 Value);
> > void XIo_Out32(XIo_Address OutAddress, Xuint32 Value);
> >
> > #else
> >
> > /* The following macros allow optimized I/O operations for memory 
mapped
> > I/O
> > ? Note that the SYNCHRONIZE_IO may be moved by the compiler during
> > ? optimization.
> > ?/
> >
> > #define XIo_In8(InputPtr) ?*(volatile Xuint8 ?)(InputPtr));
> > SYNCHRONIZE_IO;
> > #define XIo_In16(InputPtr) (*(volatile Xuint16 *)(InputPtr));
> > SYNCHRONIZE_IO;
> > #define XIo_In32(InputPtr) (*(volatile Xuint32 *)(InputPtr));
> > SYNCHRONIZE_IO;
> >
> > #define XIo_Out8(OutputPtr, Value)  \
> > ??{ (*(volatile Xuint8 ?)(OutputPtr) = Value); SYNCHRONIZE_IO; }
> > #define XIo_Out16(OutputPtr, Value) \
> > ??{ (*(volatile Xuint16 *)(OutputPtr) = Value); SYNCHRONIZE_IO; }
> > #define XIo_Out32(OutputPtr, Value) \
> > ??{ (*(volatile Xuint32 *)(OutputPtr) = Value); SYNCHRONIZE_IO; }
> >
> > #endif
>
>These macros are probably broken on powerpc.
>
> >
> > I think these are the defination of XIo_In32 and XIo_Out32. Also, 
during
> > the compilation, there is no error to complain that "XIo_In32 or 
XIo_Out32
> > undeclared".
> >
>
>I would suggest you remove that part of the header file completely, and
>replace it with:
>
>#define XIo_In32(p) in_le32(x)
>#define XIO_Out32(p,v) out_le32(p, v)
>
>	Arnd <><

_________________________________________________________________
Ãâ·ÑÏÂÔØ MSN Explorer:   http://explorer.msn.com/lccn/  

^ permalink raw reply

* Re: [PATCH] force 64bit mode in system_reset_fwnmi for broken POWER4 firmware
From: Olaf Hering @ 2006-06-09  9:04 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17545.11572.518355.586057@cargo.ozlabs.ibm.com>

 On Fri, Jun 09, Paul Mackeras wrote:

> Olaf Hering writes:
> 
> > The reason is that system_reset_fwnmi is called in 32bit mode. Forcing
> > 64bit mode fixes the corrupt NIP for me. JS20 and p690 are affected,
> > seems to work on p550 and JS21.
> 
> What was the LTC bugzilla number for this again?

LTC22581, the last comments confirm that firmware leaves the cpu in
32bit mode.

^ permalink raw reply

* Re: [RFC/PATCH] powersave_nap cleanup
From: Paul Mackerras @ 2006-06-09  9:14 UTC (permalink / raw)
  To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <20060526140227.GE8934@localdomain>

Nathan Lynch writes:

> Rename machdep_calls.power_save to machdep_calls.powersave_nap to make
> more apparent the connection with the powersave_nap sysctl.

Hmmm, it's possibly a bit confusing to have a variable and a function
with the same name...

Paul.

^ permalink raw reply

* unsubscribe
From: rohitash panda @ 2006-06-09  9:19 UTC (permalink / raw)
  To: Linuxppc-dev

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

  


Ability is what you are capable of doing. 

Motivation determines what you do. 

Attitude determines how well you do it. 

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

^ permalink raw reply

* RE: [PATCH/2.6.17-rc4 4/10]Powerpc:  Add tsi108 pic support
From: Zang Roy-r61911 @ 2006-06-09  9:25 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Alexandre Bounine
  Cc: linuxppc-dev list, Paul Mackerras, Yang Xin-Xin-r48390

> 
> On Tue, 2006-06-06 at 10:45 -0400, Alexandre Bounine wrote:
> 
> > We have a level-signalled irq from the cascaded PCI interrupt 
> > controller. If I do EOI at this time, level request will not have 
> > chance to be cleared (unless all PCI interrupts have an 
> SA_INTERRUPT flag) and result in recurring interrupts.
> 
> Hrm... Ok, when the cascade is a 8259 or an MPIC, we don't 
> have that problem despite the output also being level... I 
> think that's because the cascade handler itself will mask the 
> cascade interrupt (on MPIC, reading the irq does an ack which 
> will mask that priority level). If your cascaded controller 
> doesn't act this way, you may need something a bit different 
> in your cascade handler rather than changing mpic.
> 
> However, I wouldn't bother too much. As I said, this is all 
> changing a lot at the moment as I'm porting powerpc to Ingo 
> Molnar and Thomas Gleixner's new "genirq" layer. Cascade 
> handling will be different and taken out of MPIC, so you'll 
> be able to implement it the way your want (with much greater 
> control on what happens) without changing the MPIC driver.
> 
> I'll have patches posted on the list in a few days hopefully.
> 
> > I chose to have an individual flag instead of checking model ID to 
> > avoid multiple checks within ISR (in case if we have more 
> that one mpic version requiring this option). I also expect 
> that it may be
> > useful for any external level-signalling cascades connected 
> to MPIC.      
> 
> As I said above, I think it can just go away with the port to genirq.
> 
> > Motivation is the same as above - I just do not want to 
> have multiple 
> > ID checks here. I agree that it is driven by mpic type (model ID) 
> > only. I can remove this one if you do not expect any new 
> "broken" MPICs on horizon.
> 
> Well, I do expect broken ones but not with that specific issue :)
> 
> Cheers,
> Ben.
> 
update mpic support for tsi108 .
Any comment?

diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index db5dc10..efee7da 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -43,7 +43,16 @@ #include <asm/pci-bridge.h>  #include <asm/reg.h>  #include <mm/mmu_decl.h>  #include "mpc7448_hpc2.h"
-#include <asm/tsi108_pic.h>
+#include <asm/tsi108_irq.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0) #else #define 
+DBG(fmt...) do { } while(0) #endif
 
 #ifndef CONFIG_PCI
 isa_io_base = MPC7448_HPC2_ISA_IO_BASE; @@ -53,20 +62,8 @@ #endif
 
 extern int add_bridge(struct device_node *dev);  extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
-
-#ifdef TSI108_ETH
-hw_info hw_info_table[TSI108_ETH_MAX_PORTS + 1] = {
-	{TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
-	 TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
-	 TSI108_PHY0_ADDR, IRQ_TSI108_GIGE0},
-
-	{TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET + 0x400,
-	 TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
-	 TSI108_PHY1_ADDR, IRQ_TSI108_GIGE1},
-
-	{TBL_END, TBL_END, TBL_END, TBL_END}
-};
-#endif
+extern void tsi108_pci_int_init(void);
+extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
 
 /*
  * Define all of the IRQ senses and polarities.  Taken from the @@ -76,10 +73,32 @@ #endif
  */
 
 static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
+	/* External on-board sources */
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[0] XINT0 from FPGA */
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[1] XINT1 from FPGA */
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[2] PHY_INT from both GIGE */
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[3] RESERVED */
+	/* Internal Tsi108/109 interrupt sources */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA0 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA2 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA3 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART0 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* I2C */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* GPIO */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* HLP */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* SDC */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Processor IF */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* PCI/X block */
 };
 
 /*
@@ -196,18 +215,43 @@ #endif
  */
 static void __init mpc7448_hpc2_init_IRQ(void)  {
+	struct mpic *mpic;
+	phys_addr_t mpic_paddr = 0;
+	struct device_node *tsi_pic;
+
+	tsi_pic = of_find_node_by_type(NULL, "open-pic");
+	if (tsi_pic) {
+		unsigned int size;
+		void *prop = get_property(tsi_pic, "reg", &size);
+		mpic_paddr = of_translate_address(tsi_pic, prop);
+	}
 
-	tsi108_pic_init(mpc7448_hpc2_pic_initsenses);
+	if (mpic_paddr == 0) {
+		printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
+		return;
+	}
 
-	/* Configure MPIC outputs to CPU0 */
-	tsi108_pic_set_output(0, IRQ_SENSE_EDGE, IRQ_POLARITY_NEGATIVE);
-}
+	DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
+	    (u32) mpic_paddr);
 
-static void __init mpc7448_hpc2_map_io(void) -{
-	/* Tsi108 CSR mapping */
-	io_block_mapping(TSI108_CSR_ADDR_VIRT, TSI108_CSR_ADDR_PHYS,
-			 0x100000, _PAGE_IO);
+	mpic = mpic_alloc(mpic_paddr,
+			MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
+			MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
+			0, /* num_sources used */
+			TSI108_IRQ_BASE,
+			0, /* num_sources used */
+			NR_IRQS - 4 /* XXXX */,
+			mpc7448_hpc2_pic_initsenses,
+			sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
+
+	BUG_ON(mpic == NULL); /* XXXX */
+
+	mpic_init(mpic);
+	mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
+	tsi108_pci_int_init();
+
+	/* Configure MPIC outputs to CPU0 */
+	tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
 }
 
 void mpc7448_hpc2_show_cpuinfo(struct seq_file *m) @@ -269,10 +313,9 @@ define_machine(mpc7448_hpc2){
 	.setup_arch 		= mpc7448_hpc2_setup_arch,
 	.init_IRQ 		= mpc7448_hpc2_init_IRQ,
 	.show_cpuinfo 		= mpc7448_hpc2_show_cpuinfo,
-	.get_irq 		= tsi108_pic_get_irq,
+	.get_irq 		= mpic_get_irq,
 	.restart 		= mpc7448_hpc2_restart,
 	.calibrate_decr 	= generic_calibrate_decr,
-	.setup_io_mappings 	= mpc7448_hpc2_map_io,
 	.machine_check_exception= mpc7448_machine_check_exception,
 	.progress 		= udbg_progress,
 };
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 8c0afb7..048e1f6 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
-obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_common.o tsi108_pic.o
+obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_common.o tsi108_pci_int.o
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7dcdfcb..fc21e47 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -55,6 +55,78 @@ #define distribute_irqs	(0)
 #endif
 #endif
 
+static struct mpic_info mpic_infos[] = {
+	[0] = {	/* Original OpenPIC compatible MPIC */
+	.greg_base	= MPIC_GREG_BASE,
+	.greg_frr0	= MPIC_GREG_FEATURE_0,
+	.greg_config0	= MPIC_GREG_GLOBAL_CONF_0,
+	.greg_vendor_id	= MPIC_GREG_VENDOR_ID,
+	.greg_ipi_vp0	= MPIC_GREG_IPI_VECTOR_PRI_0,
+	.greg_ipi_stride	= MPIC_GREG_IPI_STRIDE,
+	.greg_spurious	= MPIC_GREG_SPURIOUS,
+	.greg_tfrr	= MPIC_GREG_TIMER_FREQ,
+
+	.timer_base	= MPIC_TIMER_BASE,
+	.timer_stride	= MPIC_TIMER_STRIDE,
+	.timer_ccr	= MPIC_TIMER_CURRENT_CNT,
+	.timer_bcr	= MPIC_TIMER_BASE_CNT,
+	.timer_vpr	= MPIC_TIMER_VECTOR_PRI,
+	.timer_dest	= MPIC_TIMER_DESTINATION,
+
+	.cpu_base	= MPIC_CPU_BASE,
+	.cpu_stride	= MPIC_CPU_STRIDE,
+	.cpu_ipi_disp0	= MPIC_CPU_IPI_DISPATCH_0,
+	.cpu_ipi_disp_stride	= MPIC_CPU_IPI_DISPATCH_STRIDE,
+	.cpu_task_pri	= MPIC_CPU_CURRENT_TASK_PRI,
+	.cpu_whoami	= MPIC_CPU_WHOAMI,
+	.cpu_intack	= MPIC_CPU_INTACK,
+	.cpu_eoi	= MPIC_CPU_EOI,
+
+	.irq_base	= MPIC_IRQ_BASE,
+	.irq_stride	= MPIC_IRQ_STRIDE,
+	.irq_vpr	= MPIC_IRQ_VECTOR_PRI,
+	.irq_vpr_vector	= MPIC_VECPRI_VECTOR_MASK,
+	.irq_vpr_polpos	= MPIC_VECPRI_POLARITY_POSITIVE,
+	.irq_vpr_senlvl	= MPIC_VECPRI_SENSE_LEVEL,
+	.irq_dest	= MPIC_IRQ_DESTINATION,
+	},
+
+	[1] = {	/* Tsi108/109 PIC */
+	.greg_base	= TSI108_GREG_BASE,
+	.greg_frr0	= TSI108_GREG_FEATURE_0,
+	.greg_config0	= TSI108_GREG_GLOBAL_CONF_0,
+	.greg_vendor_id	= TSI108_GREG_VENDOR_ID,
+	.greg_ipi_vp0	= TSI108_GREG_IPI_VECTOR_PRI_0,
+	.greg_ipi_stride	= TSI108_GREG_IPI_STRIDE,
+	.greg_spurious	= TSI108_GREG_SPURIOUS,
+	.greg_tfrr	= TSI108_GREG_TIMER_FREQ,
+
+	.timer_base	= TSI108_TIMER_BASE,
+	.timer_stride	= TSI108_TIMER_STRIDE,
+	.timer_ccr	= TSI108_TIMER_CURRENT_CNT,
+	.timer_bcr	= TSI108_TIMER_BASE_CNT,
+	.timer_vpr	= TSI108_TIMER_VECTOR_PRI,
+	.timer_dest	= TSI108_TIMER_DESTINATION,
+
+	.cpu_base	= TSI108_CPU_BASE,
+	.cpu_stride	= TSI108_CPU_STRIDE,
+	.cpu_ipi_disp0	= TSI108_CPU_IPI_DISPATCH_0,
+	.cpu_ipi_disp_stride	= TSI108_CPU_IPI_DISPATCH_STRIDE,
+	.cpu_task_pri	= TSI108_CPU_CURRENT_TASK_PRI,
+	.cpu_whoami	= 0xFFFFFFFF,
+	.cpu_intack	= TSI108_CPU_INTACK,
+	.cpu_eoi	= TSI108_CPU_EOI,
+
+	.irq_base	= TSI108_IRQ_REG_BASE,
+	.irq_stride	= TSI108_IRQ_STRIDE,
+	.irq_vpr	= TSI108_IRQ_VECTOR_PRI,
+	.irq_vpr_vector = TSI108_VECPRI_VECTOR_MASK,
+	.irq_vpr_polpos = TSI108_VECPRI_POLARITY_POSITIVE,
+	.irq_vpr_senlvl = TSI108_VECPRI_SENSE_LEVEL,
+	.irq_dest	= TSI108_IRQ_DESTINATION,
+	},
+};
+
 /*
  * Register accessor functions
  */
@@ -81,7 +153,8 @@ static inline void _mpic_write(unsigned  static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)  {
 	unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
-	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+	unsigned int offset = mpic->hw_set->greg_ipi_vp0 +
+			      (ipi * mpic->hw_set->greg_ipi_stride);
 
 	if (mpic->flags & MPIC_BROKEN_IPI)
 		be = !be;
@@ -90,7 +163,8 @@ static inline u32 _mpic_ipi_read(struct 
 
 static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)  {
-	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+	unsigned int offset = mpic->hw_set->greg_ipi_vp0 +
+			      (ipi * mpic->hw_set->greg_ipi_stride);
 
 	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);  } @@ -121,7 +195,7 @@ static inline u32 _mpic_irq_read(struct 
 	unsigned int	idx = src_no & mpic->isu_mask;
 
 	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
-			  reg + (idx * MPIC_IRQ_STRIDE));
+			  reg + (idx * mpic->hw_set->irq_stride));
 }
 
 static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, @@ -131,7 +205,7 @@ static inline void _mpic_irq_write(struc
 	unsigned int	idx = src_no & mpic->isu_mask;
 
 	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
-		    reg + (idx * MPIC_IRQ_STRIDE), value);
+		    reg + (idx * mpic->hw_set->irq_stride), value);
 }
 
 #define mpic_read(b,r)		_mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
@@ -157,8 +231,8 @@ static void __init mpic_test_broken_ipi(  {
 	u32 r;
 
-	mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
-	r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+	mpic_write(mpic->gregs, mpic->hw_set->greg_ipi_vp0, MPIC_VECPRI_MASK);
+	r = mpic_read(mpic->gregs, mpic->hw_set->greg_ipi_vp0);
 
 	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
 		printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); @@ -392,8 +466,8 @@ static inline struct mpic * mpic_from_ir
 /* Send an EOI */
 static inline void mpic_eoi(struct mpic *mpic)  {
-	mpic_cpu_write(MPIC_CPU_EOI, 0);
-	(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+	mpic_cpu_write(mpic->hw_set->cpu_eoi, 0);
+	(void)mpic_cpu_read(mpic->hw_set->cpu_task_pri);
 }
 
 #ifdef CONFIG_SMP
@@ -419,8 +493,8 @@ static void mpic_enable_irq(unsigned int
 
 	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
 
-	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
-		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+	mpic_irq_write(src, mpic->hw_set->irq_vpr,
+		       mpic_irq_read(src, mpic->hw_set->irq_vpr) &
 		       ~MPIC_VECPRI_MASK);
 
 	/* make sure mask gets to controller before we return to user */ @@ -429,7 +503,7 @@ static void mpic_enable_irq(unsigned int
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+	} while(mpic_irq_read(src, mpic->hw_set->irq_vpr) & MPIC_VECPRI_MASK);	
 
 #ifdef CONFIG_MPIC_BROKEN_U3
 	if (mpic->flags & MPIC_BROKEN_U3) {
@@ -466,8 +540,8 @@ static void mpic_disable_irq(unsigned in
 
 	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
 
-	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
-		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+	mpic_irq_write(src, mpic->hw_set->irq_vpr,
+		       mpic_irq_read(src, mpic->hw_set->irq_vpr) |
 		       MPIC_VECPRI_MASK);
 
 	/* make sure mask gets to controller before we return to user */ @@ -476,7 +550,7 @@ static void mpic_disable_irq(unsigned in
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+	} while(!(mpic_irq_read(src, mpic->hw_set->irq_vpr) & 
+MPIC_VECPRI_MASK));
 }
 
 static void mpic_shutdown_irq(unsigned int irq) @@ -557,7 +631,7 @@ static void mpic_set_affinity(unsigned i
 
 	cpus_and(tmp, cpumask, cpu_online_map);
 
-	mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+	mpic_irq_write(irq - mpic->irq_offset, mpic->hw_set->irq_dest,
 		       mpic_physmask(cpus_addr(tmp)[0]));	
 }
 
@@ -613,18 +687,20 @@ #endif /* CONFIG_SMP */
 	mpic->num_sources = 0; /* so far */
 	mpic->senses = senses;
 	mpic->senses_count = senses_count;
+	mpic->hw_set = &mpic_infos[MPIC_GET_MOD_ID(flags)];
 
 	/* Map the global registers */
-	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
-	mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+	mpic->gregs = ioremap(phys_addr + mpic->hw_set->greg_base, 0x1000);
+	mpic->tmregs = mpic->gregs +
+		       ((mpic->hw_set->timer_base - mpic->hw_set->greg_base) >> 2);
 	BUG_ON(mpic->gregs == NULL);
 
 	/* Reset */
 	if (flags & MPIC_WANTS_RESET) {
-		mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
-			   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		mpic_write(mpic->gregs, mpic->hw_set->greg_config0,
+			   mpic_read(mpic->gregs, mpic->hw_set->greg_config0)
 			   | MPIC_GREG_GCONF_RESET);
-		while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		while( mpic_read(mpic->gregs, mpic->hw_set->greg_config0)
 		       & MPIC_GREG_GCONF_RESET)
 			mb();
 	}
@@ -633,7 +709,7 @@ #endif /* CONFIG_SMP */
 	 * MPICs, num sources as well. On ISU MPICs, sources are counted
 	 * as ISUs are added
 	 */
-	reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+	reg = mpic_read(mpic->gregs, mpic->hw_set->greg_frr0);
 	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
 			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 	if (isu_size == 0)
@@ -642,16 +718,16 @@ #endif /* CONFIG_SMP */
 
 	/* Map the per-CPU registers */
 	for (i = 0; i < mpic->num_cpus; i++) {
-		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
-					   i * MPIC_CPU_STRIDE, 0x1000);
+		mpic->cpuregs[i] = ioremap(phys_addr + mpic->hw_set->cpu_base +
+					   i * mpic->hw_set->cpu_stride, 0x1000);
 		BUG_ON(mpic->cpuregs[i] == NULL);
 	}
 
 	/* Initialize main ISU if none provided */
 	if (mpic->isu_size == 0) {
 		mpic->isu_size = mpic->num_sources;
-		mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
-					MPIC_IRQ_STRIDE * mpic->isu_size);
+		mpic->isus[0] = ioremap(phys_addr + mpic->hw_set->irq_base,
+					mpic->hw_set->irq_stride * mpic->isu_size);
 		BUG_ON(mpic->isus[0] == NULL);
 	}
 	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); @@ -693,7 +769,8 @@ void __init mpic_assign_isu(struct mpic 
 
 	BUG_ON(isu_num >= MPIC_MAX_ISU);
 
-	mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+	mpic->isus[isu_num] = ioremap(phys_addr,
+				      mpic->hw_set->irq_stride * mpic->isu_size);
 	if ((isu_first + mpic->isu_size) > mpic->num_sources)
 		mpic->num_sources = isu_first + mpic->isu_size;  } @@ -729,14 +806,15 @@ void __init mpic_init(struct mpic *mpic)
 	printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
 
 	/* Set current processor priority to max */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+	mpic_cpu_write(mpic->hw_set->cpu_task_pri, 0xf);
 
 	/* Initialize timers: just disable them all */
 	for (i = 0; i < 4; i++) {
 		mpic_write(mpic->tmregs,
-			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+			   i * mpic->hw_set->timer_stride +
+			   mpic->hw_set->timer_dest, 0);
 		mpic_write(mpic->tmregs,
-			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+			   i * mpic->hw_set->timer_stride + mpic->hw_set->timer_vpr,
 			   MPIC_VECPRI_MASK |
 			   (MPIC_VEC_TIMER_0 + i));
 	}
@@ -780,14 +858,14 @@ #endif /* CONFIG_MPIC_BROKEN_U3 */
 		/* do senses munging */
 		if (mpic->senses && i < mpic->senses_count) {
 			if (mpic->senses[i] & IRQ_SENSE_LEVEL)
-				vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+				vecpri |= mpic->hw_set->irq_vpr_senlvl;
 			if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
-				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+				vecpri |= mpic->hw_set->irq_vpr_polpos;
 		} else
-			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+			vecpri |= mpic->hw_set->irq_vpr_senlvl;
 
 		/* remember if it was a level interrupts */
-		level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+		level = (vecpri & mpic->hw_set->irq_vpr_senlvl);
 
 		/* deal with broken U3 */
 		if (mpic->flags & MPIC_BROKEN_U3) {
@@ -795,7 +873,7 @@ #ifdef CONFIG_MPIC_BROKEN_U3
 			if (mpic_is_ht_interrupt(mpic, i)) {
 				vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
 					    MPIC_VECPRI_POLARITY_MASK);
-				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+				vecpri |= mpic->hw_set->irq_vpr_polpos;
 			}
 #else
 			printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n"); @@ -806,8 +884,8 @@ #endif
 		    (level != 0));
 
 		/* init hw */
-		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
-		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+		mpic_irq_write(i, mpic->hw_set->irq_vpr, vecpri);
+		mpic_irq_write(i, mpic->hw_set->irq_dest,
 			       1 << hard_smp_processor_id());
 
 		/* init linux descriptors */
@@ -818,15 +896,16 @@ #endif
 	}
 	
 	/* Init spurrious vector */
-	mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+	mpic_write(mpic->gregs, mpic->hw_set->greg_spurious, 
+MPIC_VEC_SPURRIOUS);
 
-	/* Disable 8259 passthrough */
-	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
-		   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
-		   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+	/* Disable 8259 passthrough, if supported */
+	if (MPIC_GET_MOD_ID(mpic->flags) != MPIC_ID_TSI108)
+		mpic_write(mpic->gregs, mpic->hw_set->greg_config0,
+			   mpic_read(mpic->gregs, mpic->hw_set->greg_config0)
+			   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
 
 	/* Set current processor priority to 0 */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+	mpic_cpu_write(mpic->hw_set->cpu_task_pri, 0);
 }
 
 
@@ -845,9 +924,9 @@ void mpic_irq_set_priority(unsigned int 
 		mpic_ipi_write(irq - mpic->ipi_offset,
 			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
 	} else {
-		reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI)
+		reg = mpic_irq_read(irq - mpic->irq_offset,mpic->hw_set->irq_vpr)
 			& ~MPIC_VECPRI_PRIORITY_MASK;
-		mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+		mpic_irq_write(irq - mpic->irq_offset, mpic->hw_set->irq_vpr,
 			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
 	}
 	spin_unlock_irqrestore(&mpic_lock, flags); @@ -864,7 +943,7 @@ unsigned int mpic_irq_get_priority(unsig
 	if (is_ipi)
 		reg = mpic_ipi_read(irq - mpic->ipi_offset);
 	else
-		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
+		reg = mpic_irq_read(irq - mpic->irq_offset, mpic->hw_set->irq_vpr);
 	spin_unlock_irqrestore(&mpic_lock, flags);
 	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;  } @@ -890,12 +969,12 @@ #ifdef CONFIG_SMP
  	 */
 	if (distribute_irqs) {
 	 	for (i = 0; i < mpic->num_sources ; i++)
-			mpic_irq_write(i, MPIC_IRQ_DESTINATION,
-				mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+			mpic_irq_write(i, mpic->hw_set->irq_dest,
+				mpic_irq_read(i, mpic->hw_set->irq_dest) | msk);
 	}
 
 	/* Set current processor priority to 0 */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+	mpic_cpu_write(mpic->hw_set->cpu_task_pri, 0);
 
 	spin_unlock_irqrestore(&mpic_lock, flags);  #endif /* CONFIG_SMP */ @@ -905,7 +984,7 @@ int mpic_cpu_get_priority(void)  {
 	struct mpic *mpic = mpic_primary;
 
-	return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+	return mpic_cpu_read(mpic->hw_set->cpu_task_pri);
 }
 
 void mpic_cpu_set_priority(int prio)
@@ -913,7 +992,7 @@ void mpic_cpu_set_priority(int prio)
 	struct mpic *mpic = mpic_primary;
 
 	prio &= MPIC_CPU_TASKPRI_MASK;
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+	mpic_cpu_write(mpic->hw_set->cpu_task_pri, prio);
 }
 
 /*
@@ -935,11 +1014,11 @@ void mpic_teardown_this_cpu(int secondar
 
 	/* let the mpic know we don't want intrs.  */
 	for (i = 0; i < mpic->num_sources ; i++)
-		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
-			mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+		mpic_irq_write(i, mpic->hw_set->irq_dest,
+			mpic_irq_read(i, mpic->hw_set->irq_dest) & ~msk);
 
 	/* Set current processor priority to max */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+	mpic_cpu_write(mpic->hw_set->cpu_task_pri, 0xf);
 
 	spin_unlock_irqrestore(&mpic_lock, flags);  } @@ -955,7 +1034,8 @@ #ifdef DEBUG_IPI
 	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);  #endif
 
-	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+	mpic_cpu_write(mpic->hw_set->cpu_ipi_disp0 +
+		       ipi_no * mpic->hw_set->cpu_ipi_disp_stride,
 		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));  }
 
@@ -963,7 +1043,7 @@ int mpic_get_one_irq(struct mpic *mpic,  {
 	u32 irq;
 
-	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+	irq = mpic_cpu_read(mpic->hw_set->cpu_intack) & 
+mpic->hw_set->irq_vpr_vector;
 #ifdef DEBUG_LOW
 	DBG("%s: get_one_irq(): %d\n", mpic->name, irq);  #endif @@ -972,11 +1052,17 @@ #ifdef DEBUG_LOW
 		DBG("%s: cascading ...\n", mpic->name);  #endif
 		irq = mpic->cascade(regs, mpic->cascade_data);
+#ifdef DEBUG_LOW
+		DBG("%s: cascaded irq: %d\n", mpic->name, irq); #endif
 		mpic_eoi(mpic);
 		return irq;
 	}
-	if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+	if (unlikely(irq == MPIC_VEC_SPURRIOUS)) {
+		if (mpic->flags & MPIC_SPV_EOI)
+			mpic_eoi(mpic);
 		return -1;
+	}
 	if (irq < MPIC_VEC_IPI_0) {
 #ifdef DEBUG_IRQ
 		DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset); diff --git a/arch/powerpc/sysdev/tsi108_common.c b/arch/powerpc/sysdev/tsi108_common.c
index 3c55f99..03b5d8f 100644
--- a/arch/powerpc/sysdev/tsi108_common.c
+++ b/arch/powerpc/sysdev/tsi108_common.c
@@ -90,9 +90,13 @@ tsi108_direct_write_config(struct pci_bu  {
 	volatile unsigned char *cfg_addr;
 
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfunc))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
 							devfunc, offset) |
-				     (offset & 0x03));
+							(offset & 0x03));
 
 #ifdef TSI108_PCI_DEBUG
 	printk("PCI CFG write : ");
@@ -172,6 +176,10 @@ tsi108_direct_read_config(struct pci_bus
 	volatile unsigned char *cfg_addr;
 	u32 temp;
 
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
 	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
 							devfn,
 							offset) | (offset &
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index 6b9e781..72131a4 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -37,6 +37,7 @@ #define MPIC_GREG_IPI_VECTOR_PRI_0	0x000
 #define MPIC_GREG_IPI_VECTOR_PRI_1	0x000b0
 #define MPIC_GREG_IPI_VECTOR_PRI_2	0x000c0
 #define MPIC_GREG_IPI_VECTOR_PRI_3	0x000d0
+#define MPIC_GREG_IPI_STRIDE		0x10
 #define MPIC_GREG_SPURIOUS		0x000e0
 #define MPIC_GREG_TIMER_FREQ		0x000f0
 
@@ -64,6 +65,7 @@ #define MPIC_CPU_IPI_DISPATCH_0		0x00040
 #define MPIC_CPU_IPI_DISPATCH_1		0x00050
 #define MPIC_CPU_IPI_DISPATCH_2		0x00060
 #define MPIC_CPU_IPI_DISPATCH_3		0x00070
+#define MPIC_CPU_IPI_DISPATCH_STRIDE	0x00010
 #define MPIC_CPU_CURRENT_TASK_PRI	0x00080
 #define 	MPIC_CPU_TASKPRI_MASK			0x0000000f
 #define MPIC_CPU_WHOAMI			0x00090
@@ -91,6 +93,55 @@ #define 	MPIC_VECPRI_SENSE_EDGE			0x0000
 #define 	MPIC_VECPRI_SENSE_MASK			0x00400000
 #define MPIC_IRQ_DESTINATION		0x00010
 
+/**********************************************************************
+********
+ * Tsi108 implementation of MPIC has many differences form the original 
+one  */
+
+/*
+ * Global registers
+ */
+
+#define TSI108_GREG_BASE		0x00000
+#define TSI108_GREG_FEATURE_0		0x00000
+#define TSI108_GREG_GLOBAL_CONF_0	0x00004
+#define TSI108_GREG_VENDOR_ID		0x0000c
+#define TSI108_GREG_IPI_VECTOR_PRI_0	0x00204		/* Doorbell 0 */
+#define TSI108_GREG_IPI_STRIDE		0x0c
+#define TSI108_GREG_SPURIOUS		0x00010
+#define TSI108_GREG_TIMER_FREQ		0x00014
+
+/*
+ * Timer registers
+ */
+#define TSI108_TIMER_BASE		0x0030
+#define TSI108_TIMER_STRIDE		0x10
+#define TSI108_TIMER_CURRENT_CNT	0x00000
+#define TSI108_TIMER_BASE_CNT		0x00004
+#define TSI108_TIMER_VECTOR_PRI		0x00008
+#define TSI108_TIMER_DESTINATION	0x0000c
+
+/*
+ * Per-Processor registers
+ */
+#define TSI108_CPU_BASE			0x00300
+#define TSI108_CPU_STRIDE		0x00040
+#define TSI108_CPU_IPI_DISPATCH_0	0x00200
+#define TSI108_CPU_IPI_DISPATCH_STRIDE	0x00000
+#define TSI108_CPU_CURRENT_TASK_PRI	0x00000
+#define TSI108_CPU_INTACK		0x00004
+#define TSI108_CPU_EOI			0x00008
+
+/*
+ * Per-source registers
+ */
+#define TSI108_IRQ_REG_BASE		0x00100
+#define TSI108_IRQ_STRIDE		0x00008
+#define TSI108_IRQ_VECTOR_PRI		0x00000
+#define 	TSI108_VECPRI_VECTOR_MASK		0x000000ff
+#define 	TSI108_VECPRI_POLARITY_POSITIVE		0x01000000
+#define 	TSI108_VECPRI_SENSE_LEVEL		0x02000000
+#define TSI108_IRQ_DESTINATION		0x00004
+
 #define MPIC_MAX_IRQ_SOURCES	2048
 #define MPIC_MAX_CPUS		32
 #define MPIC_MAX_ISU		32
@@ -124,6 +175,40 @@ struct mpic_irq_fixup  };  #endif /* CONFIG_MPIC_BROKEN_U3 */
 
+struct mpic_info {
+	u32	greg_base;	/* offset of global registers from MPIC base */
+	u32	greg_frr0;	/* FRR0 offset from base */
+	u32	greg_config0;	/* Global Config register offset from base */
+	u32	greg_vendor_id;	/* VID register offset from base */
+	u32	greg_ipi_vp0;	/* IPI Vector/Priority Registers */
+	u32	greg_ipi_stride; /* IPI Vector/Priority Registers spacing */
+	u32	greg_spurious;	/* Spurious Vector Register */
+	u32	greg_tfrr;	/* Global Timer Frequency Reporting Register */
+
+	u32	timer_base;	/* Global Timer Registers base */
+	u32	timer_stride;	/* Global Timer Registers spacing */
+	u32	timer_ccr;	/* Global Timer Current Count Register */
+	u32	timer_bcr;	/* Global Timer Base Count Register */
+	u32	timer_vpr;	/* Global Timer Vector/Priority Register */
+	u32	timer_dest;	/* Global Timer Destination Register */
+
+	u32	cpu_base;	/* Global Timer Destination Register */
+	u32	cpu_stride;	/* Global Timer Destination Register */
+	u32	cpu_ipi_disp0;	/* IPI 0 Dispatch Command Register */
+	u32	cpu_ipi_disp_stride;	/* IPI Dispatch spacing */
+	u32	cpu_task_pri;	/* Processor Current Task Priority Register */
+	u32	cpu_whoami;	/* Who Am I Register */
+	u32	cpu_intack;	/* Interrupt Acknowledge Register */
+	u32	cpu_eoi;	/* End of Interrupt Register */
+
+	u32	irq_base;	/* Interrupt registers base */
+	u32	irq_stride;	/* Interrupt registers spacing */
+	u32	irq_vpr;	/* Interrupt Vector/Priority Register */
+	u32	irq_vpr_vector;	/* Interrupt Vector Mask */
+	u32	irq_vpr_polpos;	/* Interrupt Positive Polarity bit */
+	u32	irq_vpr_senlvl;	/* Interrupt Level Sense bit */
+	u32	irq_dest;	/* Interrupt Destination Register */
+};
 
 /* The instance data of a given MPIC */  struct mpic @@ -168,6 +253,8 @@ #endif
 	volatile u32 __iomem	*tmregs;
 	volatile u32 __iomem	*cpuregs[MPIC_MAX_CPUS];
 	volatile u32 __iomem	*isus[MPIC_MAX_ISU];
+	/* Pointer to HW info structure */
+	struct mpic_info	*hw_set;
 
 	/* link */
 	struct mpic		*next;
@@ -186,6 +273,14 @@ #define MPIC_BROKEN_U3			0x00000004
 #define MPIC_BROKEN_IPI			0x00000008
 /* MPIC wants a reset */
 #define MPIC_WANTS_RESET		0x00000010
+/* Spurious vector requires EOI */
+#define MPIC_SPV_EOI			0x00000020
+/* MPIC HW modification ID */
+#define MPIC_MOD_ID_MASK		0x00000f00
+#define MPIC_MOD_ID(val)		(((val) << 8) & MPIC_MOD_ID_MASK)
+#define MPIC_GET_MOD_ID(flags)		(((flags) & MPIC_MOD_ID_MASK) >> 8)
+#define		MPIC_ID_MPIC		0	/* Original MPIC */
+#define		MPIC_ID_TSI108		1	/* Tsi108/109 PIC */
 
 /* Allocate the controller structure and setup the linux irq descs
  * for the range if interrupts passed in. No HW initialization is diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h index ed9ec36..850c56d 100644
--- a/include/asm-powerpc/tsi108.h
+++ b/include/asm-powerpc/tsi108.h
@@ -55,6 +55,7 @@ #define TSI108_PCI_IRP_ENABLE	(0x188)
 #define TSI108_PCI_IRP_INTAD	(0x18C)
 
 #define TSI108_PCI_IRP_STAT_P_INT	(0x00400000)
+#define TSI108_PCI_IRP_ENABLE_P_INT	(0x00400000)
 
 #define TSI108_CG_PWRUP_STATUS	(0x234)
diff --git a/arch/powerpc/sysdev/tsi108_pci_int.c b/arch/powerpc/sysdev/tsi108_pci_int.c
index e69de29..c1ca187 100644
--- a/arch/powerpc/sysdev/tsi108_pci_int.c
+++ b/arch/powerpc/sysdev/tsi108_pci_int.c
@@ -0,0 +1,232 @@
+/*
+ * (C) Copyright 2005 Tundra Semiconductor Corp.
+ * Alex Bounine, <alexandreb@tundra.com).
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Tsi108 PCI Interrupt Handling (cascaded to MPIC)  */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/hardirq.h>
+#include <asm/machdep.h>
+
+#include <asm/tsi108.h>
+#include <asm/tsi108_irq.h>
+
+#undef DEBUG
+#undef DBG_TSI108_INTERRUPT
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0) #else #define 
+DBG(fmt...) do { } while(0) #endif
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_read_reg(u32 reg_offset); extern void 
+tsi108_write_reg(u32 reg_offset, u32 val);
+
+/*
+ * Low level utility functions
+ */
+
+static void tsi108_pci_int_mask(u_int irq) {
+	u_int irp_cfg;
+	int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+	mb();
+	irp_cfg |= (1 << int_line);	/* INTx_DIR = output */
+	irp_cfg &= ~(3 << (8 + (int_line * 2)));	/* INTx_TYPE = unused */
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+	mb();
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL); 
+}
+
+static void tsi108_pci_int_unmask(u_int irq) {
+	u_int irp_cfg;
+	int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+	mb();
+	irp_cfg &= ~(1 << int_line);
+	irp_cfg |= (3 << (8 + (int_line * 2)));
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+	mb();
+}
+
+static void init_pci_source(void)
+{
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
+			0x0000ff00);
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, 
+			TSI108_PCI_IRP_ENABLE_P_INT);
+	mb();
+}
+
+static inline int get_pci_source(void)
+{
+	u_int temp = 0;
+	int irq = -1;
+	int i;
+	u_int pci_irp_stat;
+	static int mask = 0;
+
+	/* Read PCI/X block interrupt status register */
+	pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+	mb();
+
+	if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
+		/* Process Interrupt from PCI bus INTA# - INTD# lines */
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET +
+				    TSI108_PCI_IRP_INTAD) & 0xf;
+		mb();
+		for (i = 0; i < 4; i++, mask++) {
+			if (temp & (1 << mask % 4)) {
+				irq = IRQ_PCI_INTA + mask % 4;
+				mask++;
+				break;
+			}
+		}
+
+		/* Disable interrupts from PCI block */
+		temp = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, 
+				temp & ~TSI108_PCI_IRP_ENABLE_P_INT);
+		mb();
+		(void)tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		mb();
+	}
+#ifdef DBG_TSI108_INTERRUPT
+	else {
+		printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
+		pci_irp_stat =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
+		mb();
+		printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+		mb();
+		printk("cfg_ctl=0x%08x ", temp);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		mb();
+		printk("irp_enable=0x%08x\n", temp);
+	}
+#endif	/* DBG_TSI108_INTERRUPT */
+
+	return irq;
+}
+
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+static void tsi108_pci_irq_enable(u_int irq) {
+	tsi108_pci_int_unmask(irq);
+}
+
+static void tsi108_pci_irq_disable(u_int irq) {
+	tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_ack(u_int irq) {
+	tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_end(u_int irq) {
+	tsi108_pci_int_unmask(irq);
+
+	/* Enable interrupts from PCI block */
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, 
+			 tsi108_read_reg(TSI108_PCI_OFFSET + 
+					 TSI108_PCI_IRP_ENABLE) |
+			 TSI108_PCI_IRP_ENABLE_P_INT);
+	mb();
+}
+
+/*
+ * Interrupt controller descriptor for cascaded PCI interrupt controller.
+ */
+
+struct hw_interrupt_type tsi108_pci_irq = {
+	.typename = "tsi108_PCI_int",
+	.enable = tsi108_pci_irq_enable,
+	.disable = tsi108_pci_irq_disable,
+	.ack = tsi108_pci_irq_ack,
+	.end = tsi108_pci_irq_end,
+};
+
+/*
+ * Exported functions
+ */
+
+/*
+ * The Tsi108 PCI interrupts initialization routine.
+ *
+ * The INTA# - INTD# interrupts on the PCI bus are reported by the PCI 
+block
+ * to the MPIC using single interrupt source (IRQ_TSI108_PCI). 
+Therefore the
+ * PCI block has to be treated as a cascaded interrupt controller 
+connected
+ * to the MPIC.
+ */
+
+void __init tsi108_pci_int_init(void)
+{
+	u_int i;
+
+	DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
+
+	for (i = 0; i < NUM_PCI_IRQS; i++) {
+		irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
+		irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
+	}
+
+	init_pci_source();
+}
+
+int tsi108_irq_cascade(struct pt_regs *regs, void *unused) {
+	return get_pci_source();
+}

^ permalink raw reply related

* Re: [PATCH] Compile failure fix for ppc on 2.6.17-rc4-mm3 (2nd attempt)
From: Paul Mackerras @ 2006-06-09  9:36 UTC (permalink / raw)
  To: Mel Gorman; +Cc: Andrew Morton, linuxppc-dev, vgoyal, linux-kernel
In-Reply-To: <20060529190515.GA17608@skynet.ie>

Mel Gorman writes:

> +	res->end = -(-res->end & ~(unsigned long)mask); \
> +	res->end += mask; \

I think this is equivalent to

	res->end = (res->end + mask) | mask;

and I have to say the latter seems more understandable to me (and
doesn't need a cast) ...

Regards,
Paul.

^ permalink raw reply

* Re: [PATCH] Provide mechanism for editing builtin command-line in zImage binary.
From: Paul Mackerras @ 2006-06-09  9:47 UTC (permalink / raw)
  To: mostrows; +Cc: linuxppc-dev
In-Reply-To: <11489544631499-git-send-email-mostrows@watson.ibm.com>

Michal Ostrowski writes:

> -BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj)
> +BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj) -I$(O)/include -I$(O)/include2\
> +			-D__KERNEL__

I don't like this; we are trying to keep the boot wrapper separate,
not make it more dependent on the rest of the kernel.

> +#include <linux/autoconf.h>
> +#include <asm/setup.h>

We don't really need COMMAND_LINE_SIZE here - nothing says the command
line from the firmware or the boot wrapper *has* to be the same size
as the kernel's command-line buffer.

> +static char builtin_cmdline[COMMAND_LINE_SIZE]
> +		__attribute__((section("__builtin_cmdline"))) = CONFIG_CMDLINE;
> +#endif

If CONFIG_CMDLINE is set, then the kernel image *already* has the
default in it, and we don't need another copy here.  Just make your
buffer here some fixed, known size and uninitialized (i.e. all
zeroes).  Do the setprop if the /chosen/bootargs is empty and your
buffer has been edited to be non-null.

Paul.

^ permalink raw reply

* Re: pmf_register_irq_client gives sleep with locks held warning
From: Johannes Berg @ 2006-06-08 18:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Andrew Morton, linuxppc-dev list
In-Reply-To: <1149123574.15446.15.camel@localhost.localdomain>

On Thu, 2006-06-01 at 10:59 +1000, Benjamin Herrenschmidt wrote:

> This fixes request_irq() potentially called from atomic context.
> [...]

Sorry, almost forgot about this.

I don't think your patch is right, it seems to me that now
pmf_unregister_irq_client races against pmf_do_irq: what happens when an
interrupt comes in right in the middle of the list_del()?

It might actually not do any harm due to the way list_del() and
pmf_do_irq() work and the fact that client->handler() must still be
prepared to be called... But I'd rather make it explicit.

By the way, what do I do when like this I change a patch? Do I rely on
your Signed-off-by and simply put mine instead (like I did now)?

Anyway, here's a changed patch that illustrates my point. I've tested it
and it works and as expected fixes the problem :)
---
This fixes request_irq() being called with interrupts disabled in the
powermac platform function code when registering the first irq client
for a given platform function.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -11,6 +11,7 @@ #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 #include <asm/semaphore.h>
 #include <asm/prom.h>
@@ -546,6 +547,7 @@ struct pmf_device {
 
 static LIST_HEAD(pmf_devices);
 static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_MUTEX(pmf_irq_mutex);
 
 static void pmf_release_device(struct kref *kref)
 {
@@ -864,16 +866,25 @@ int pmf_register_irq_client(struct devic
 
 	spin_lock_irqsave(&pmf_lock, flags);
 	func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
-	if (func == NULL) {
-		spin_unlock_irqrestore(&pmf_lock, flags);
+	if (func)
+		func = pmf_get_function(func);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+	if (func == NULL)
 		return -ENODEV;
-	}
+
+	/* guard against manipulations of list */
+	mutex_lock(&pmf_irq_mutex);
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_enable(func);
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_add(&client->link, &func->irq_clients);
-	client->func = func;
 	spin_unlock_irqrestore(&pmf_lock, flags);
 
+	client->func = func;
+	mutex_unlock(&pmf_irq_mutex);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pmf_register_irq_client);
@@ -885,12 +896,19 @@ void pmf_unregister_irq_client(struct pm
 
 	BUG_ON(func == NULL);
 
-	spin_lock_irqsave(&pmf_lock, flags);
+	/* guard against manipulations of list */
+	mutex_lock(&pmf_irq_mutex);
 	client->func = NULL;
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_del(&client->link);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_disable(func);
-	spin_unlock_irqrestore(&pmf_lock, flags);
+	mutex_unlock(&pmf_irq_mutex);
+	pmf_put_function(func);
 }
 EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
 

^ permalink raw reply

* Re: [PATCH] convert powermac ide blink to new led infrastructure
From: Johannes Berg @ 2006-06-09 11:47 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1149726524.23790.5.camel@localhost.localdomain>

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

On Thu, 2006-06-08 at 10:28 +1000, Benjamin Herrenschmidt wrote:

> No objection, but a question: how do you bind the led to the hard disk
> by default ? some userland stuff ? can't be automatic at boot by
> default ?

The way it usually works is via sysfs. Automatic at boot could be
default by assigning a default name somewhere IIRC, but since I don't
use the LED I optimised for that case ;)
I'd say having a script that *enables* it at boot is probably cleaner
than having one that *disables* it, and having a Kconfig option just for
the default seems overkill.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [PATCH] convert powermac ide blink to new led infrastructure
From: Anton Blanchard @ 2006-06-09 11:56 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev list
In-Reply-To: <1149853629.3864.9.camel@johannes.berg>


> The way it usually works is via sysfs. Automatic at boot could be
> default by assigning a default name somewhere IIRC, but since I don't
> use the LED I optimised for that case ;)
> I'd say having a script that *enables* it at boot is probably cleaner
> than having one that *disables* it, and having a Kconfig option just for
> the default seems overkill.

On the other hand, Ive come to expect it on my laptop :)

Anton

^ permalink raw reply

* Re: [PATCH] convert powermac ide blink to new led infrastructure
From: Johannes Berg @ 2006-06-09 12:01 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev list
In-Reply-To: <20060609115608.GE23891@krispykreme>

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

On Fri, 2006-06-09 at 21:56 +1000, Anton Blanchard wrote:

> On the other hand, Ive come to expect it on my laptop :)

With my patch, just put

echo -n ide-disk > /sys/class/leds/pmu-front-led/trigger

into some startup script then :)

Do we really want the old Kconfig option in there selecting the new led
option, the ide-disk trigger and modifying the code to make this the
default trigger for the LED? I mean...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC 03/12] snd-aoa: add aoa core
From: Johannes Berg @ 2006-06-09 12:10 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel, netstar
In-Reply-To: <s5hk67s4ywh.wl%tiwai@suse.de>

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

On Wed, 2006-06-07 at 20:13 +0200, Takashi Iwai wrote:
> At Wed, 07 Jun 2006 15:09:12 +0200,
> Johannes Berg wrote:
> > 
> > --- /dev/null
> > +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
> (snip)
> > +void pmf_handle_notify_irq(void *data)
> > +{
> 
> Missing static.

Added, thanks.

> > --- /dev/null
> > +++ b/sound/aoa/core/snd-aoa-gpio-feature.c
> (snip)
> > +static struct device_node *get_gpio(
> > +	char *name, char *altname, int *gpioptr, int *gpioactiveptr)
> 
> Unconventional style.

Heh ok, fixed.

> > +irqreturn_t ftr_handle_notify_irq(int xx, void *data, struct pt_regs *regs)
> > +{
> 
> Missing static.

Added.

> > +static int ftr_set_notify(struct gpio_runtime *rt,
> > +			  enum notify_type type,
> > +			  notify_func_t notify,
> > +			  void *data)
> (snip)
> > +	if (old && !notify) {
> > +		free_irq(irq, notif);
> > +	}
> > +	if (!old && notify) {
> > +		request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
> > +	}
> 
> Remove braces.  

Right.

> Any error check from request_irq()?

Ah, I figured it didn't matter, but it indeed does. Fixed.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ 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