Commit aa3ae27a authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/home/src/bklinux-2.6

into cantab.net:/home/src/ntfs-2.6-devel
parents 6631c357 80aca3e6
......@@ -28,7 +28,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
iSeries_iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o pSeries_nvram.o rtasd.o ras.o \
......@@ -47,12 +47,14 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
pmac_time.o pmac_nvram.o pmac_low_i2c.o \
open_pic_u3.o
pmac_time.o pmac_nvram.o pmac_low_i2c.o
obj-$(CONFIG_U3_DART) += u3_iommu.o
ifdef CONFIG_SMP
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o
endif
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
......
......@@ -156,6 +156,15 @@ _GLOBAL(__restore_cpu_setup)
cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
bne 1f
/* Before accessing memory, we make sure rm_ci is clear */
li r0,0
mfspr r3,SPRN_HID4
rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */
sync
mtspr SPRN_HID4,r3
isync
sync
/* Clear interrupt prefix */
li r0,0
sync
......
......@@ -1195,18 +1195,20 @@ unrecov_slb:
* At entry, r3 = this processor's number (in Linux terms, not hardware).
*/
_GLOBAL(pseries_secondary_smp_init)
mr r24,r3
/* turn on 64-bit mode */
bl .enable_64b_mode
isync
/* Set up a paca value for this processor. */
LOADADDR(r24, paca) /* Get base vaddr of paca array */
mulli r13,r3,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */
/* Copy some CPU settings from CPU 0 */
bl .__restore_cpu_setup
/* Set up a paca value for this processor. */
LOADADDR(r5, paca) /* Get base vaddr of paca array */
mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r5 /* for this processor. */
mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
mr r24,r3 /* __secondary_start needs cpu# */
1:
HMT_LOW
lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
......@@ -1886,19 +1888,6 @@ _STATIC(start_here_multiplatform)
91:
#endif
#ifdef CONFIG_SMP
/* All secondary cpus are now spinning on a common
* spinloop, release them all now so they can start
* to spin on their individual paca spinloops.
* For non SMP kernels, the secondary cpus never
* get out of the common spinloop.
*/
li r3,1
LOADADDR(r5,__secondary_hold_spinloop)
tophys(r4,r5)
std r3,0(r4)
#endif
/* The following gets the stack and TOC set up with the regs */
/* pointing to the real addr of the kernel stack. This is */
/* all done to support the C function call below which sets */
......@@ -1913,7 +1902,7 @@ _STATIC(start_here_multiplatform)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* set up the TOC (physical address) */
/* set up the TOC (physical address) */
LOADADDR(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
......@@ -1926,6 +1915,25 @@ _STATIC(start_here_multiplatform)
mr r5,r26
bl .identify_cpu
/* Save some low level config HIDs of CPU0 to be copied to
* other CPUs later on, or used for suspend/resume
*/
bl .__save_cpu_setup
sync
#ifdef CONFIG_SMP
/* All secondary cpus are now spinning on a common
* spinloop, release them all now so they can start
* to spin on their individual paca spinloops.
* For non SMP kernels, the secondary cpus never
* get out of the common spinloop.
*/
li r3,1
LOADADDR(r5,__secondary_hold_spinloop)
tophys(r4,r5)
std r3,0(r4)
#endif
/* Setup a valid physical PACA pointer in SPRG3 for early_setup
* note that boot_cpuid can always be 0 nowadays since there is
* nowhere it can be initialized differently before we reach this
......
......@@ -23,7 +23,8 @@ unsigned char cached_8259[2] = { 0xff, 0xff };
static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
int i8259_pic_irq_offset;
static int i8259_pic_irq_offset;
static int i8259_present;
int i8259_irq(int cpu)
{
......@@ -140,11 +141,13 @@ struct hw_interrupt_type i8259_pic = {
NULL
};
void __init i8259_init(void)
void __init i8259_init(int offset)
{
unsigned long flags;
spin_lock_irqsave(&i8259_lock, flags);
i8259_pic_irq_offset = offset;
i8259_present = 1;
/* init master interrupt controller */
outb(0x11, 0x20); /* Start init sequence */
outb(0x00, 0x21); /* Vector base */
......@@ -160,7 +163,18 @@ void __init i8259_init(void)
outb(cached_A1, 0xA1);
outb(cached_21, 0x21);
spin_unlock_irqrestore(&i8259_lock, flags);
}
static int i8259_request_cascade(void)
{
if (!i8259_present)
return -ENODEV;
request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
"82c59 secondary cascade", NULL );
return 0;
}
arch_initcall(i8259_request_cascade);
......@@ -11,7 +11,7 @@
extern struct hw_interrupt_type i8259_pic;
void i8259_init(void);
int i8259_irq(int);
extern void i8259_init(int offset);
extern int i8259_irq(int);
#endif /* _PPC_KERNEL_i8259_H */
/*
* SMP support for iSeries machines.
*
* Dave Engebretsen, Peter Bergner, and
* Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
*
* Plus various changes from other IBM teams...
*
* 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.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/err.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/naca.h>
#include <asm/paca.h>
#include <asm/iSeries/LparData.h>
#include <asm/iSeries/HvCall.h>
#include <asm/iSeries/HvCallCfg.h>
#include <asm/time.h>
#include <asm/ppcdebug.h>
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/system.h>
static unsigned long iSeries_smp_message[NR_CPUS];
void iSeries_smp_message_recv( struct pt_regs * regs )
{
int cpu = smp_processor_id();
int msg;
if ( num_online_cpus() < 2 )
return;
for ( msg = 0; msg < 4; ++msg )
if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
smp_message_recv( msg, regs );
}
static inline void smp_iSeries_do_message(int cpu, int msg)
{
set_bit(msg, &iSeries_smp_message[cpu]);
HvCall_sendIPI(&(paca[cpu]));
}
static void smp_iSeries_message_pass(int target, int msg)
{
int i;
if (target < NR_CPUS)
smp_iSeries_do_message(target, msg);
else {
for_each_online_cpu(i) {
if (target == MSG_ALL_BUT_SELF
&& i == smp_processor_id())
continue;
smp_iSeries_do_message(i, msg);
}
}
}
static int smp_iSeries_numProcs(void)
{
unsigned np, i;
np = 0;
for (i=0; i < NR_CPUS; ++i) {
if (paca[i].lppaca.xDynProcStatus < 2) {
cpu_set(i, cpu_possible_map);
cpu_set(i, cpu_present_map);
++np;
}
}
return np;
}
static int smp_iSeries_probe(void)
{
unsigned i;
unsigned np = 0;
for (i=0; i < NR_CPUS; ++i) {
if (paca[i].lppaca.xDynProcStatus < 2) {
/*paca[i].active = 1;*/
++np;
}
}
return np;
}
static void smp_iSeries_kick_cpu(int nr)
{
BUG_ON(nr < 0 || nr >= NR_CPUS);
/* Verify that our partition has a processor nr */
if (paca[nr].lppaca.xDynProcStatus >= 2)
return;
/* The processor is currently spinning, waiting
* for the cpu_start field to become non-zero
* After we set cpu_start, the processor will
* continue on to secondary_start in iSeries_head.S
*/
paca[nr].cpu_start = 1;
}
static void __devinit smp_iSeries_setup_cpu(int nr)
{
}
static struct smp_ops_t iSeries_smp_ops = {
.message_pass = smp_iSeries_message_pass,
.probe = smp_iSeries_probe,
.kick_cpu = smp_iSeries_kick_cpu,
.setup_cpu = smp_iSeries_setup_cpu,
};
/* This is called very early. */
void __init smp_init_iSeries(void)
{
smp_ops = &iSeries_smp_ops;
systemcfg->processorCount = smp_iSeries_numProcs();
}
This diff is collapsed.
#include <linux/irq.h>
/*
* Global registers
*/
#define MPIC_GREG_BASE 0x01000
#define MPIC_GREG_FEATURE_0 0x00000
#define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
#define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
#define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
#define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
#define MPIC_GREG_FEATURE_VERSION_MASK 0xff
#define MPIC_GREG_FEATURE_1 0x00010
#define MPIC_GREG_GLOBAL_CONF_0 0x00020
#define MPIC_GREG_GCONF_RESET 0x80000000
#define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000
#define MPIC_GREG_GCONF_BASE_MASK 0x000fffff
#define MPIC_GREG_GLOBAL_CONF_1 0x00030
#define MPIC_GREG_VENDOR_0 0x00040
#define MPIC_GREG_VENDOR_1 0x00050
#define MPIC_GREG_VENDOR_2 0x00060
#define MPIC_GREG_VENDOR_3 0x00070
#define MPIC_GREG_VENDOR_ID 0x00080
#define MPIC_GREG_VENDOR_ID_STEPPING_MASK 0x00ff0000
#define MPIC_GREG_VENDOR_ID_STEPPING_SHIFT 16
#define MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
#define MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT 8
#define MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
#define MPIC_GREG_PROCESSOR_INIT 0x00090
#define MPIC_GREG_IPI_VECTOR_PRI_0 0x000a0
#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_SPURIOUS 0x000e0
#define MPIC_GREG_TIMER_FREQ 0x000f0
/*
*
* Timer registers
*/
#define MPIC_TIMER_BASE 0x01100
#define MPIC_TIMER_STRIDE 0x40
#define MPIC_TIMER_CURRENT_CNT 0x00000
#define MPIC_TIMER_BASE_CNT 0x00010
#define MPIC_TIMER_VECTOR_PRI 0x00020
#define MPIC_TIMER_DESTINATION 0x00030
/*
* Per-Processor registers
*/
#define MPIC_CPU_THISBASE 0x00000
#define MPIC_CPU_BASE 0x20000
#define MPIC_CPU_STRIDE 0x01000
#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_CURRENT_TASK_PRI 0x00080
#define MPIC_CPU_TASKPRI_MASK 0x0000000f
#define MPIC_CPU_WHOAMI 0x00090
#define MPIC_CPU_WHOAMI_MASK 0x0000001f
#define MPIC_CPU_INTACK 0x000a0
#define MPIC_CPU_EOI 0x000b0
/*
* Per-source registers
*/
#define MPIC_IRQ_BASE 0x10000
#define MPIC_IRQ_STRIDE 0x00020
#define MPIC_IRQ_VECTOR_PRI 0x00000
#define MPIC_VECPRI_MASK 0x80000000
#define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
#define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
#define MPIC_VECPRI_PRIORITY_SHIFT 16
#define MPIC_VECPRI_VECTOR_MASK 0x000007ff
#define MPIC_VECPRI_POLARITY_POSITIVE 0x00800000
#define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
#define MPIC_VECPRI_POLARITY_MASK 0x00800000
#define MPIC_VECPRI_SENSE_LEVEL 0x00400000
#define MPIC_VECPRI_SENSE_EDGE 0x00000000
#define MPIC_VECPRI_SENSE_MASK 0x00400000
#define MPIC_IRQ_DESTINATION 0x00010
#define MPIC_MAX_IRQ_SOURCES 2048
#define MPIC_MAX_CPUS 32
#define MPIC_MAX_ISU 32
/*
* Special vector numbers (internal use only)
*/
#define MPIC_VEC_SPURRIOUS 255
#define MPIC_VEC_IPI_3 254
#define MPIC_VEC_IPI_2 253
#define MPIC_VEC_IPI_1 252
#define MPIC_VEC_IPI_0 251
/* unused */
#define MPIC_VEC_TIMER_3 250
#define MPIC_VEC_TIMER_2 249
#define MPIC_VEC_TIMER_1 248
#define MPIC_VEC_TIMER_0 247
/* Type definition of the cascade handler */
typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
#ifdef CONFIG_MPIC_BROKEN_U3
/* Fixup table entry */
struct mpic_irq_fixup
{
u8 __iomem *base;
unsigned int irq;
};
#endif /* CONFIG_MPIC_BROKEN_U3 */
/* The instance data of a given MPIC */
struct mpic
{
/* The "linux" controller struct */
hw_irq_controller hc_irq;
#ifdef CONFIG_SMP
hw_irq_controller hc_ipi;
#endif
const char *name;
/* Flags */
unsigned int flags;
/* How many irq sources in a given ISU */
unsigned int isu_size;
unsigned int isu_shift;
unsigned int isu_mask;
/* Offset of irq vector numbers */
unsigned int irq_offset;
unsigned int irq_count;
/* Offset of ipi vector numbers */
unsigned int ipi_offset;
/* Number of sources */
unsigned int num_sources;
/* Number of CPUs */
unsigned int num_cpus;
/* cascade handler */
mpic_cascade_t cascade;
void *cascade_data;
unsigned int cascade_vec;
/* senses array */
unsigned char *senses;
unsigned int senses_count;
#ifdef CONFIG_MPIC_BROKEN_U3
/* The fixup table */
struct mpic_irq_fixup *fixups;
spinlock_t fixup_lock;
#endif
/* The various ioremap'ed bases */
volatile u32 __iomem *gregs;
volatile u32 __iomem *tmregs;
volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
volatile u32 __iomem *isus[MPIC_MAX_ISU];
/* link */
struct mpic *next;
};
/* This is the primary controller, only that one has IPIs and
* has afinity control. A non-primary MPIC always uses CPU0
* registers only
*/
#define MPIC_PRIMARY 0x00000001
/* Set this for a big-endian MPIC */
#define MPIC_BIG_ENDIAN 0x00000002
/* Broken U3 MPIC */
#define MPIC_BROKEN_U3 0x00000004
/* Broken IPI registers (autodetected) */
#define MPIC_BROKEN_IPI 0x00000008
/* MPIC wants a reset */
#define MPIC_WANTS_RESET 0x00000010
/* Allocate the controller structure and setup the linux irq descs
* for the range if interrupts passed in. No HW initialization is
* actually performed.
*
* @phys_addr: physial base address of the MPIC
* @flags: flags, see constants above
* @isu_size: number of interrupts in an ISU. Use 0 to use a
* standard ISU-less setup (aka powermac)
* @irq_offset: first irq number to assign to this mpic
* @irq_count: number of irqs to use with this mpic IRQ sources. Pass 0
* to match the number of sources
* @ipi_offset: first irq number to assign to this mpic IPI sources,
* used only on primary mpic
* @senses: array of sense values
* @senses_num: number of entries in the array
*
* Note about the sense array. If none is passed, all interrupts are
* setup to be level negative unless MPIC_BROKEN_U3 is set in which
* case they are edge positive (and the array is ignored anyway).
* The values in the array start at the first source of the MPIC,
* that is senses[0] correspond to linux irq "irq_offset".
*/
extern struct mpic *mpic_alloc(unsigned long phys_addr,
unsigned int flags,
unsigned int isu_size,
unsigned int irq_offset,
unsigned int irq_count,
unsigned int ipi_offset,
unsigned char *senses,
unsigned int senses_num,
const char *name);
/* Assign ISUs, to call before mpic_init()
*
* @mpic: controller structure as returned by mpic_alloc()
* @isu_num: ISU number
* @phys_addr: physical address of the ISU
*/
extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
unsigned long phys_addr);
/* Initialize the controller. After this has been called, none of the above
* should be called again for this mpic
*/
extern void mpic_init(struct mpic *mpic);
/* Setup a cascade. Currently, only one cascade is supported this
* way, though you can always do a normal request_irq() and add
* other cascades this way. You should call this _after_ having
* added all the ISUs
*
* @irq_no: "linux" irq number of the cascade (that is offset'ed vector)
* @handler: cascade handler function
*/
extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
void *data);
/*
* All of the following functions must only be used after the
* ISUs have been assigned and the controller fully initialized
* with mpic_init()
*/
/* Change/Read the priority of an interrupt. Default is 8 for irqs and
* 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
* IPI number is then the offset'ed (linux irq number mapped to the IPI)
*/
extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
extern unsigned int mpic_irq_get_priority(unsigned int irq);
/* Setup a non-boot CPU */
extern void mpic_setup_this_cpu(void);
/* Request IPIs on primary mpic */
extern void mpic_request_ipis(void);
/* Send an IPI (non offseted number 0..3) */
extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
/* Fetch interrupt from a given mpic */
extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
/* This one gets to the primary mpic */
extern int mpic_get_irq(struct pt_regs *regs);
This diff is collapsed.
/*
* arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*
*/
#ifndef _PPC64_KERNEL_OPEN_PIC_H
#define _PPC64_KERNEL_OPEN_PIC_H
#include <linux/config.h>
#include <linux/cpumask.h>
#include <linux/irq.h>
#define OPENPIC_SIZE 0x40000
/* OpenPIC IRQ controller structure */
extern struct hw_interrupt_type open_pic;
/* OpenPIC IPI controller structure */
#ifdef CONFIG_SMP
extern struct hw_interrupt_type open_pic_ipi;
#endif /* CONFIG_SMP */
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
extern void* OpenPIC_Addr;
/* Exported functions */
extern void openpic_init(int, int, unsigned char *, int);
extern void openpic_request_IPIs(void);
extern void do_openpic_setup_cpu(void);
extern int openpic_get_irq(struct pt_regs *regs);
extern void openpic_init_processor(u_int cpumask);
extern void openpic_setup_ISU(int isu_num, unsigned long addr);
extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
#endif /* _PPC64_KERNEL_OPEN_PIC_H */
/*
* linux/openpic.h -- OpenPIC definitions
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is based on the following documentation:
*
* The Open Programmable Interrupt Controller (PIC)
* Register Interface Specification Revision 1.2
*
* Issue Date: October 1995
*
* Issued jointly by Advanced Micro Devices and Cyrix Corporation
*
* AMD is a registered trademark of Advanced Micro Devices, Inc.
* Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
* All Rights Reserved.
*
* To receive a copy of this documentation, send an email to openpic@amd.com.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#ifndef _LINUX_OPENPIC_H
#define _LINUX_OPENPIC_H
#ifdef __KERNEL__
#include <linux/config.h>
/*
* OpenPIC supports up to 2048 interrupt sources and up to 32 processors
*/
#define OPENPIC_MAX_SOURCES 2048
#define OPENPIC_MAX_PROCESSORS 32
#define OPENPIC_MAX_ISU 32
#define OPENPIC_NUM_TIMERS 4
#define OPENPIC_NUM_IPI 4
#define OPENPIC_NUM_PRI 16
#define OPENPIC_NUM_VECTORS OPENPIC_MAX_SOURCES
/*
* OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
*/
typedef struct _OpenPIC_Reg {
u_int Reg; /* Little endian! */
char Pad[0xc];
} OpenPIC_Reg;
/*
* Per Processor Registers
*/
typedef struct _OpenPIC_Processor {
/*
* Private Shadow Registers (for SLiC backwards compatibility)
*/
u_int IPI0_Dispatch_Shadow; /* Write Only */
char Pad1[0x4];
u_int IPI0_Vector_Priority_Shadow; /* Read/Write */
char Pad2[0x34];
/*
* Interprocessor Interrupt Command Ports
*/
OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */
/*
* Current Task Priority Register
*/
OpenPIC_Reg _Current_Task_Priority; /* Read/Write */
char Pad3[0x10];
/*
* Interrupt Acknowledge Register
*/
OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */
/*
* End of Interrupt (EOI) Register
*/
OpenPIC_Reg _EOI; /* Read/Write */
char Pad5[0xf40];
} OpenPIC_Processor;
/*
* Timer Registers
*/
typedef struct _OpenPIC_Timer {
OpenPIC_Reg _Current_Count; /* Read Only */
OpenPIC_Reg _Base_Count; /* Read/Write */
OpenPIC_Reg _Vector_Priority; /* Read/Write */
OpenPIC_Reg _Destination; /* Read/Write */
} OpenPIC_Timer;
/*
* Global Registers
*/
typedef struct _OpenPIC_Global {
/*
* Feature Reporting Registers
*/
OpenPIC_Reg _Feature_Reporting0; /* Read Only */
OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */
/*
* Global Configuration Registers
*/
OpenPIC_Reg _Global_Configuration0; /* Read/Write */
OpenPIC_Reg _Global_Configuration1; /* Future Expansion */
/*
* Vendor Specific Registers
*/
OpenPIC_Reg _Vendor_Specific[4];
/*
* Vendor Identification Register
*/
OpenPIC_Reg _Vendor_Identification; /* Read Only */
/*
* Processor Initialization Register
*/
OpenPIC_Reg _Processor_Initialization; /* Read/Write */
/*
* IPI Vector/Priority Registers
*/
OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
/*
* Spurious Vector Register
*/
OpenPIC_Reg _Spurious_Vector; /* Read/Write */
/*
* Global Timer Registers
*/
OpenPIC_Reg _Timer_Frequency; /* Read/Write */
OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
char Pad1[0xee00];
} OpenPIC_Global;
/*
* Interrupt Source Registers
*/
typedef struct _OpenPIC_Source {
OpenPIC_Reg _Vector_Priority; /* Read/Write */
OpenPIC_Reg _Destination; /* Read/Write */
} OpenPIC_Source, *OpenPIC_SourcePtr;
/*
* OpenPIC Register Map
*/
struct OpenPIC {
char Pad1[0x1000];
/*
* Global Registers
*/
OpenPIC_Global Global;
/*
* Interrupt Source Configuration Registers
*/
OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
/*
* Per Processor Registers
*/
OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
};
/*
* Current Task Priority Register
*/
#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f
/*
* Who Am I Register
*/
#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f
/*
* Feature Reporting Register 0
*/
#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000
#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16
#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00
#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8
#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff
/*
* Global Configuration Register 0
*/
#define OPENPIC_CONFIG_RESET 0x80000000
#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000
#define OPENPIC_CONFIG_BASE_MASK 0x000fffff
/*
* Vendor Identification Register
*/
#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000
#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16
#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8
#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
/*
* Vector/Priority Registers
*/
#define OPENPIC_MASK 0x80000000
#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */
#define OPENPIC_PRIORITY_MASK 0x000f0000
#define OPENPIC_PRIORITY_SHIFT 16
#define OPENPIC_VECTOR_MASK 0x000007ff
/*
* Interrupt Source Registers
*/
#define OPENPIC_POLARITY_POSITIVE 0x00800000
#define OPENPIC_POLARITY_NEGATIVE 0x00000000
#define OPENPIC_POLARITY_MASK 0x00800000
#define OPENPIC_SENSE_LEVEL 0x00400000
#define OPENPIC_SENSE_EDGE 0x00000000
#define OPENPIC_SENSE_MASK 0x00400000
/*
* Timer Registers
*/
#define OPENPIC_COUNT_MASK 0x7fffffff
#define OPENPIC_TIMER_TOGGLE 0x80000000
#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000
/*
* Aliases to make life simpler
*/
/* Per Processor Registers */
#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg
#define Current_Task_Priority _Current_Task_Priority.Reg
#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg
#define EOI _EOI.Reg
/* Global Registers */
#define Feature_Reporting0 _Feature_Reporting0.Reg
#define Feature_Reporting1 _Feature_Reporting1.Reg
#define Global_Configuration0 _Global_Configuration0.Reg
#define Global_Configuration1 _Global_Configuration1.Reg
#define Vendor_Specific(i) _Vendor_Specific[i].Reg
#define Vendor_Identification _Vendor_Identification.Reg
#define Processor_Initialization _Processor_Initialization.Reg
#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg
#define Spurious_Vector _Spurious_Vector.Reg
#define Timer_Frequency _Timer_Frequency.Reg
/* Timer Registers */
#define Current_Count _Current_Count.Reg
#define Base_Count _Base_Count.Reg
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
/* Interrupt Source Registers */
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
#endif /* __KERNEL__ */
#endif /* _LINUX_OPENPIC_H */
/*
* arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include "open_pic.h"
#include "open_pic_defs.h"
void* OpenPIC2_Addr;
static volatile struct OpenPIC *OpenPIC2 = NULL;
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
static u_int NumSources;
static int NumISUs;
static int open_pic2_irq_offset;
static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU];
unsigned int openpic2_vec_spurious;
/*
* Accesses to the current processor's openpic registers
* U3 secondary openpic has only one output
*/
#define THIS_CPU Processor[0]
#define DECL_THIS_CPU
#define CHECK_THIS_CPU
#define GET_ISU(source) ISU2[(source) >> 4][(source) & 0xf]
static inline u_int openpic2_read(volatile u_int *addr)
{
u_int val;
val = in_be32(addr);
return val;
}
static inline void openpic2_write(volatile u_int *addr, u_int val)
{
out_be32(addr, val);
}
static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
{
u_int val = openpic2_read(addr);
return val & mask;
}
static inline void openpic2_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
u_int val = openpic2_read(addr);
openpic2_write(addr, (val & ~mask) | (field & mask));
}
static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
{
openpic2_writefield(addr, mask, 0);
}
static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
{
openpic2_writefield(addr, mask, mask);
}
static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
unsigned int loops = 100000;
openpic2_setfield(addr, OPENPIC_MASK);
while (openpic2_read(addr) & OPENPIC_ACTIVITY) {
if (!loops--) {
printk(KERN_ERR "openpic2_safe_writefield timeout\n");
break;
}
}
openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
}
static inline void openpic2_reset(void)
{
openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
OPENPIC_CONFIG_RESET);
}
static void openpic2_disable_8259_pass_through(void)
{
openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
}
/*
* Find out the current interrupt
*/
static u_int openpic2_irq(void)
{
u_int vec;
DECL_THIS_CPU;
CHECK_THIS_CPU;
vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
OPENPIC_VECTOR_MASK);
return vec;
}
static void openpic2_eoi(void)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
/* Handle PCI write posting */
(void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
}
static inline u_int openpic2_get_priority(void)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
OPENPIC_CURRENT_TASK_PRIORITY_MASK);
}
static void openpic2_set_priority(u_int pri)
{
DECL_THIS_CPU;
CHECK_THIS_CPU;
openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
}
/*
* Get/set the spurious vector
*/
static inline u_int openpic2_get_spurious(void)
{
return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
OPENPIC_VECTOR_MASK);
}
static void openpic2_set_spurious(u_int vec)
{
openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
vec);
}
/*
* Enable/disable an external interrupt source
*
* Externally called, irq is an offseted system-wide interrupt number
*/
static void openpic2_enable_irq(u_int irq)
{
unsigned int loops = 100000;
openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
if (!loops--) {
printk(KERN_ERR "openpic_enable_irq timeout\n");
break;
}
mb(); /* sync is probably useless here */
} while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK));
}
static void openpic2_disable_irq(u_int irq)
{
u32 vp;
unsigned int loops = 100000;
openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK);
/* make sure mask gets to controller before we return to user */
do {
if (!loops--) {
printk(KERN_ERR "openpic_disable_irq timeout\n");
break;
}
mb(); /* sync is probably useless here */
vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
OPENPIC_MASK | OPENPIC_ACTIVITY);
} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
}
/*
* Initialize an interrupt source (and disable it!)
*
* irq: OpenPIC interrupt number
* pri: interrupt source priority
* vec: the vector it will produce
* pol: polarity (1 for positive, 0 for negative)
* sense: 1 for level, 0 for edge
*/
static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
{
openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
(pri << OPENPIC_PRIORITY_SHIFT) | vec |
(pol ? OPENPIC_POLARITY_POSITIVE :
OPENPIC_POLARITY_NEGATIVE) |
(sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
}
/*
* Map an interrupt source to one or more CPUs
*/
static void openpic2_mapirq(u_int irq, u_int physmask)
{
openpic2_write(&GET_ISU(irq).Destination, physmask);
}
/*
* Set the sense for an interrupt source (and disable it!)
*
* sense: 1 for level, 0 for edge
*/
static inline void openpic2_set_sense(u_int irq, int sense)
{
openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
OPENPIC_SENSE_LEVEL,
(sense ? OPENPIC_SENSE_LEVEL : 0));
}
static void openpic2_end_irq(unsigned int irq_nr)
{
openpic2_eoi();
}
int openpic2_get_irq(struct pt_regs *regs)
{
int irq = openpic2_irq();
if (irq == openpic2_vec_spurious)
return -1;
return irq + open_pic2_irq_offset;
}
struct hw_interrupt_type open_pic2 = {
" OpenPIC2 ",
NULL,
NULL,
openpic2_enable_irq,
openpic2_disable_irq,
NULL,
openpic2_end_irq,
};
void __init openpic2_init(int offset)
{
u_int t, i;
const char *version;
if (!OpenPIC2_Addr) {
printk(KERN_INFO "No OpenPIC2 found !\n");
return;
}
OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
ppc64_boot_msg(0x20, "OpenPic U3 Init");
t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
switch (t & OPENPIC_FEATURE_VERSION_MASK) {
case 1:
version = "1.0";
break;
case 2:
version = "1.2";
break;
case 3:
version = "1.3";
break;
default:
version = "?";
break;
}
printk(KERN_INFO "OpenPIC (U3) Version %s\n", version);
open_pic2_irq_offset = offset;
for (i=0; i<128; i+=0x10) {
ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i];
NumISUs++;
}
NumSources = NumISUs * 0x10;
openpic2_vec_spurious = NumSources;
openpic2_set_priority(0xf);
/* Init all external sources */
for (i = 0; i < NumSources; i++) {
int pri, sense;
/* the bootloader may have left it enabled (bad !) */
openpic2_disable_irq(i+offset);
pri = 8;
sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1;
if (sense)
irq_desc[i+offset].status = IRQ_LEVEL;
/* Enabled, Priority 8 or 9 */
openpic2_initirq(i, pri, i, !sense, sense);
/* Processor 0 */
openpic2_mapirq(i, 0x1);
}
/* Init descriptors */
for (i = offset; i < NumSources + offset; i++)
irq_desc[i].handler = &open_pic2;
/* Initialize the spurious interrupt */
openpic2_set_spurious(openpic2_vec_spurious);
openpic2_set_priority(0);
openpic2_disable_8259_pass_through();
ppc64_boot_msg(0x25, "OpenPic U3 Done");
}
......@@ -42,7 +42,7 @@
#include <asm/iommu.h>
#include <asm/rtas.h>
#include "open_pic.h"
#include "mpic.h"
#include "pci.h"
/* RTAS tokens */
......@@ -54,6 +54,7 @@ static int ibm_write_pci_config;
static int s7a_workaround;
extern unsigned long pci_probe_only;
extern struct mpic *pSeries_mpic;
static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
{
......@@ -399,9 +400,9 @@ unsigned long __init find_and_init_phbs(void)
pci_process_bridge_OF_ranges(phb, node);
pci_setup_phb_io(phb, index == 0);
if (naca->interrupt_controller == IC_OPEN_PIC) {
if (naca->interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
int addr = root_size_cells * (index + 2) - 1;
openpic_setup_ISU(index, opprop[addr]);
mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
}
index++;
......@@ -533,25 +534,12 @@ EXPORT_SYMBOL(pcibios_remove_root_bus);
static void __init pSeries_request_regions(void)
{
struct device_node *i8042;
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
request_region(0x00,0x20,"dma1");
request_region(0x40,0x20,"timer");
request_region(0x80,0x10,"dma page reg");
request_region(0xc0,0x20,"dma2");
#define I8042_DATA_REG 0x60
/*
* Some machines have an unterminated i8042 so check the device
* tree and reserve the region if it does not appear. Later on
* the i8042 code will try and reserve this region and fail.
*/
if (!(i8042 = of_find_node_by_type(NULL, "8042")))
request_region(I8042_DATA_REG, 16, "reserved (no i8042)");
of_node_put(i8042);
}
void __init pSeries_final_fixup(void)
......
......@@ -61,19 +61,18 @@
#include <asm/nvram.h>
#include "i8259.h"
#include "open_pic.h"
#include <asm/xics.h>
#include <asm/ppcdebug.h>
#include <asm/cputable.h>
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
extern void pSeries_init_openpic(void);
extern void find_and_init_phbs(void);
extern void pSeries_final_fixup(void);
......@@ -82,6 +81,8 @@ extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
extern int pSeries_set_rtc_time(struct rtc_time *rtc_time);
extern void find_udbg_vterm(void);
extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void); /* from head.S */
extern void generic_find_legacy_serial_ports(unsigned int *default_speed);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
......@@ -91,6 +92,9 @@ extern unsigned long loops_per_jiffy;
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
static volatile void __iomem * chrp_int_ack_special;
struct mpic *pSeries_mpic;
void pSeries_get_cpuinfo(struct seq_file *m)
{
struct device_node *root;
......@@ -120,15 +124,86 @@ static void __init fwnmi_init(void)
fwnmi_active = 1;
}
static void __init pSeries_setup_arch(void)
static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
{
if (chrp_int_ack_special)
return readb(chrp_int_ack_special);
else
return i8259_irq(smp_processor_id());
}
static void __init pSeries_init_mpic(void)
{
unsigned int *addrp;
unsigned char* chrp_int_ack_special = NULL;
struct device_node *np;
int i;
/* All ISUs are setup, complete initialization */
mpic_init(pSeries_mpic);
/* Check what kind of cascade ACK we have */
if (!(np = of_find_node_by_name(NULL, "pci"))
|| !(addrp = (unsigned int *)
get_property(np, "8259-interrupt-acknowledge", NULL)))
printk(KERN_ERR "Cannot find pci to get ack address\n");
else
chrp_int_ack_special = (unsigned char *)
ioremap(addrp[prom_n_addr_cells(np)-1], 1);
of_node_put(np);
/* Setup the legacy interrupts & controller */
for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic;
i8259_init(0);
/* Hook cascade to mpic */
mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
}
static void __init pSeries_setup_mpic(void)
{
struct device_node *root;
unsigned int *opprop;
unsigned long openpic_addr = 0;
unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
struct device_node *root;
int irq_count;
/* Find the Open PIC if present */
root = of_find_node_by_path("/");
opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
if (opprop != 0) {
int n = prom_n_addr_cells(root);
for (openpic_addr = 0; n > 0; --n)
openpic_addr = (openpic_addr << 32) + *opprop++;
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
}
of_node_put(root);
BUG_ON(openpic_addr == 0);
/* Get the sense values from OF */
prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
/* Setup the openpic driver */
irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
16, 16, irq_count, /* isu size, irq offset, irq count */
NR_IRQS - 4, /* ipi offset */
senses, irq_count, /* sense & sense size */
" MPIC ");
}
static void __init pSeries_setup_arch(void)
{
/* Fixup ppc_md depending on the type of interrupt controller */
if (naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_openpic;
ppc_md.get_irq = openpic_get_irq;
ppc_md.init_IRQ = pSeries_init_mpic;
ppc_md.get_irq = mpic_get_irq;
/* Allocate the mpic now, so that find_and_init_phbs() can
* fill the ISUs */
pSeries_setup_mpic();
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
......@@ -156,21 +231,6 @@ static void __init pSeries_setup_arch(void)
eeh_init();
find_and_init_phbs();
/* Find the Open PIC if present */
root = of_find_node_by_path("/");
opprop = (unsigned int *) get_property(root,
"platform-open-pic", NULL);
if (opprop != 0) {
int n = prom_n_addr_cells(root);
unsigned long openpic;
for (openpic = 0; n > 0; --n)
openpic = (openpic << 32) + *opprop++;
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
}
of_node_put(root);
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
......@@ -189,75 +249,6 @@ static int __init pSeries_init_panel(void)
arch_initcall(pSeries_init_panel);
void __init pSeries_find_serial_port(void)
{
struct device_node *np;
unsigned long encode_phys_size = 32;
u32 *sizeprop;
struct isa_reg_property {
u32 space;
u32 address;
u32 size;
};
struct pci_reg_property {
struct pci_address addr;
u32 size_hi;
u32 size_lo;
};
DBG(" -> pSeries_find_serial_port()\n");
naca->serialPortAddr = 0;
np = of_find_node_by_path("/");
if (!np)
return;
sizeprop = (u32 *)get_property(np, "#size-cells", NULL);
if (sizeprop != NULL)
encode_phys_size = (*sizeprop) << 5;
for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
struct device_node *isa, *pci;
struct isa_reg_property *reg;
union pci_range *rangesp;
char *typep;
typep = (char *)get_property(np, "ibm,aix-loc", NULL);
if ((typep == NULL) || (typep && strcmp(typep, "S1")))
continue;
reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
isa = of_get_parent(np);
if (!isa) {
DBG("no isa parent found\n");
break;
}
pci = of_get_parent(isa);
if (!pci) {
DBG("no pci parent found\n");
break;
}
rangesp = (union pci_range *)get_property(pci, "ranges", NULL);
if ( encode_phys_size == 32 )
naca->serialPortAddr = rangesp->pci32.phys+reg->address;
else {
naca->serialPortAddr =
((((unsigned long)rangesp->pci64.phys_hi) << 32)
|
(rangesp->pci64.phys_lo)) + reg->address;
}
break;
}
DBG(" <- pSeries_find_serial_port()\n");
}
/* Build up the firmware_features bitmask field
* using contents of device-tree/ibm,hypertas-functions.
* Ultimately this functionality may be moved into prom.c prom_init().
......@@ -330,6 +321,20 @@ static void __init pSeries_discover_pic(void)
}
}
static void pSeries_cpu_die(void)
{
local_irq_disable();
/* Some hardware requires clearing the CPPR, while other hardware does not
* it is safe either way
*/
pSeriesLP_cppr_info(0, 0);
rtas_stop_self();
/* Should never get here... */
BUG();
for(;;);
}
/*
* Early initialization. Relocation is on but do not reference unbolted pages
*/
......@@ -337,6 +342,7 @@ static void __init pSeries_init_early(void)
{
void *comport;
int iommu_off = 0;
unsigned int default_speed;
DBG(" -> pSeries_init_early()\n");
......@@ -350,14 +356,14 @@ static void __init pSeries_init_early(void)
get_property(of_chosen, "linux,iommu-off", NULL));
}
pSeries_find_serial_port();
generic_find_legacy_serial_ports(&default_speed);
if (systemcfg->platform & PLATFORM_LPAR)
find_udbg_vterm();
else if (naca->serialPortAddr) {
/* Map the uart for udbg. */
comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
udbg_init_uart(comport);
udbg_init_uart(comport, default_speed);
ppc_md.udbg_putc = udbg_putc;
ppc_md.udbg_getc = udbg_getc;
......@@ -542,6 +548,31 @@ static void __init pSeries_calibrate_decr(void)
setup_default_decr();
}
static int pSeries_check_legacy_ioport(unsigned int baseport)
{
struct device_node *np;
#define I8042_DATA_REG 0x60
#define FDC_BASE 0x3f0
switch(baseport) {
case I8042_DATA_REG:
np = of_find_node_by_type(NULL, "8042");
if (np == NULL)
return -ENODEV;
of_node_put(np);
break;
case FDC_BASE:
np = of_find_node_by_type(NULL, "fdc");
if (np == NULL)
return -ENODEV;
of_node_put(np);
break;
}
return 0;
}
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
......@@ -571,9 +602,11 @@ struct machdep_calls __initdata pSeries_md = {
.power_off = rtas_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
.cpu_die = pSeries_cpu_die,
.get_boot_time = pSeries_get_boot_time,
.get_rtc_time = pSeries_get_rtc_time,
.set_rtc_time = pSeries_set_rtc_time,
.calibrate_decr = pSeries_calibrate_decr,
.progress = pSeries_progress,
.check_legacy_ioport = pSeries_check_legacy_ioport,
};
/*
* SMP support for pSeries machines.
*
* Dave Engebretsen, Peter Bergner, and
* Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
*
* Plus various changes from other IBM teams...
*
* 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.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/err.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
#include <asm/naca.h>
#include <asm/paca.h>
#include <asm/time.h>
#include <asm/ppcdebug.h>
#include <asm/machdep.h>
#include <asm/xics.h>
#include <asm/cputable.h>
#include <asm/system.h>
#include <asm/rtas.h>
#include <asm/plpar_wrappers.h>
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
extern void pseries_secondary_smp_init(unsigned long);
static void vpa_init(int cpu)
{
unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
/* Register the Virtual Processor Area (VPA) */
flags = 1UL << (63 - 18);
register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
}
/* Get state of physical CPU.
* Return codes:
* 0 - The processor is in the RTAS stopped state
* 1 - stop-self is in progress
* 2 - The processor is not in the RTAS stopped state
* -1 - Hardware Error
* -2 - Hardware Busy, Try again later.
*/
static int query_cpu_stopped(unsigned int pcpu)
{
int cpu_status;
int status, qcss_tok;
qcss_tok = rtas_token("query-cpu-stopped-state");
if (qcss_tok == RTAS_UNKNOWN_SERVICE)
return -1;
status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
if (status != 0) {
printk(KERN_ERR
"RTAS query-cpu-stopped-state failed: %i\n", status);
return status;
}
return cpu_status;
}
#ifdef CONFIG_HOTPLUG_CPU
int __cpu_disable(void)
{
/* FIXME: go put this in a header somewhere */
extern void xics_migrate_irqs_away(void);
systemcfg->processorCount--;
/*fix boot_cpuid here*/
if (smp_processor_id() == boot_cpuid)
boot_cpuid = any_online_cpu(cpu_online_map);
/* FIXME: abstract this to not be platform specific later on */
xics_migrate_irqs_away();
return 0;
}
void __cpu_die(unsigned int cpu)
{
int tries;
int cpu_status;
unsigned int pcpu = get_hard_smp_processor_id(cpu);
for (tries = 0; tries < 25; tries++) {
cpu_status = query_cpu_stopped(pcpu);
if (cpu_status == 0 || cpu_status == -1)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/5);
}
if (cpu_status != 0) {
printk("Querying DEAD? cpu %i (%i) shows %i\n",
cpu, pcpu, cpu_status);
}
/* Isolation and deallocation are definatly done by
* drslot_chrp_cpu. If they were not they would be
* done here. Change isolate state to Isolate and
* change allocation-state to Unusable.
*/
paca[cpu].cpu_start = 0;
}
/* Search all cpu device nodes for an offline logical cpu. If a
* device node has a "ibm,my-drc-index" property (meaning this is an
* LPAR), paranoid-check whether we own the cpu. For each "thread"
* of a cpu, if it is offline and has the same hw index as before,
* grab that in preference.
*/
static unsigned int find_physical_cpu_to_start(unsigned int old_hwindex)
{
struct device_node *np = NULL;
unsigned int best = -1U;
while ((np = of_find_node_by_type(np, "cpu"))) {
int nr_threads, len;
u32 *index = (u32 *)get_property(np, "ibm,my-drc-index", NULL);
u32 *tid = (u32 *)
get_property(np, "ibm,ppc-interrupt-server#s", &len);
if (!tid)
tid = (u32 *)get_property(np, "reg", &len);
if (!tid)
continue;
/* If there is a drc-index, make sure that we own
* the cpu.
*/
if (index) {
int state;
int rc = rtas_get_sensor(9003, *index, &state);
if (rc != 0 || state != 1)
continue;
}
nr_threads = len / sizeof(u32);
while (nr_threads--) {
if (0 == query_cpu_stopped(tid[nr_threads])) {
best = tid[nr_threads];
if (best == old_hwindex)
goto out;
}
}
}
out:
of_node_put(np);
return best;
}
/**
* smp_startup_cpu() - start the given cpu
*
* At boot time, there is nothing to do. At run-time, call RTAS with
* the appropriate start location, if the cpu is in the RTAS stopped
* state.
*
* Returns:
* 0 - failure
* 1 - success
*/
static inline int __devinit smp_startup_cpu(unsigned int lcpu)
{
int status;
unsigned long start_here = __pa((u32)*((unsigned long *)
pseries_secondary_smp_init));
unsigned int pcpu;
/* At boot time the cpus are already spinning in hold
* loops, so nothing to do. */
if (system_state < SYSTEM_RUNNING)
return 1;
pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
if (pcpu == -1U) {
printk(KERN_INFO "No more cpus available, failing\n");
return 0;
}
/* Fixup atomic count: it exited inside IRQ handler. */
paca[lcpu].__current->thread_info->preempt_count = 0;
/* At boot this is done in prom.c. */
paca[lcpu].hw_cpu_id = pcpu;
status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
pcpu, start_here, lcpu);
if (status != 0) {
printk(KERN_ERR "start-cpu failed: %i\n", status);
return 0;
}
return 1;
}
#else /* ... CONFIG_HOTPLUG_CPU */
static inline int __devinit smp_startup_cpu(unsigned int lcpu)
{
return 1;
}
#endif /* CONFIG_HOTPLUG_CPU */
static inline void smp_xics_do_message(int cpu, int msg)
{
set_bit(msg, &xics_ipi_message[cpu].value);
mb();
xics_cause_IPI(cpu);
}
static void smp_xics_message_pass(int target, int msg)
{
unsigned int i;
if (target < NR_CPUS) {
smp_xics_do_message(target, msg);
} else {
for_each_online_cpu(i) {
if (target == MSG_ALL_BUT_SELF
&& i == smp_processor_id())
continue;
smp_xics_do_message(i, msg);
}
}
}
extern void xics_request_IPIs(void);
static int __init smp_xics_probe(void)
{
xics_request_IPIs();
return cpus_weight(cpu_possible_map);
}
static void __devinit smp_xics_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
xics_setup_cpu();
}
static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
static unsigned long timebase = 0;
static void __devinit pSeries_give_timebase(void)
{
spin_lock(&timebase_lock);
rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
timebase = get_tb();
spin_unlock(&timebase_lock);
while (timebase)
barrier();
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
}
static void __devinit pSeries_take_timebase(void)
{
while (!timebase)
barrier();
spin_lock(&timebase_lock);
set_tb(timebase >> 32, timebase & 0xffffffff);
timebase = 0;
spin_unlock(&timebase_lock);
}
static void __devinit pSeries_late_setup_cpu(int cpu)
{
extern unsigned int default_distrib_server;
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
vpa_init(cpu);
}
#ifdef CONFIG_IRQ_ALL_CPUS
/* Put the calling processor into the GIQ. This is really only
* necessary from a secondary thread as the OF start-cpu interface
* performs this function for us on primary threads.
*/
/* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
rtas_set_indicator(9005, default_distrib_server, 1);
#endif
}
void __devinit smp_pSeries_kick_cpu(int nr)
{
BUG_ON(nr < 0 || nr >= NR_CPUS);
if (!smp_startup_cpu(nr))
return;
/*
* The processor is currently spinning, waiting for the
* cpu_start field to become non-zero After we set cpu_start,
* the processor will continue on to secondary_start
*/
paca[nr].cpu_start = 1;
}
static struct smp_ops_t pSeries_mpic_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_mpic_setup_cpu,
.late_setup_cpu = pSeries_late_setup_cpu,
};
static struct smp_ops_t pSeries_xics_smp_ops = {
.message_pass = smp_xics_message_pass,
.probe = smp_xics_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_xics_setup_cpu,
.late_setup_cpu = pSeries_late_setup_cpu,
};
/* This is called very early */
void __init smp_init_pSeries(void)
{
int ret, i;
DBG(" -> smp_init_pSeries()\n");
if (naca->interrupt_controller == IC_OPEN_PIC)
smp_ops = &pSeries_mpic_smp_ops;
else
smp_ops = &pSeries_xics_smp_ops;
/* Start secondary threads on SMT systems; primary threads
* are already in the running state.
*/
for_each_present_cpu(i) {
if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
printk("%16.16x : starting thread\n", i);
DBG("%16.16x : starting thread\n", i);
rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
get_hard_smp_processor_id(i),
__pa((u32)*((unsigned long *)
pseries_secondary_smp_init)),
i);
}
}
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
vpa_init(boot_cpuid);
/* Non-lpar has additional take/give timebase */
if (systemcfg->platform == PLATFORM_PSERIES) {
smp_ops->give_timebase = pSeries_give_timebase;
smp_ops->take_timebase = pSeries_take_timebase;
}
DBG(" <- smp_init_pSeries()\n");
}
......@@ -11,6 +11,8 @@
* 2 of the License, or (at your option) any later version.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
......@@ -39,6 +41,12 @@
#include "pci.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
unsigned long pci_probe_only = 1;
unsigned long pci_assign_all_buses = 0;
......@@ -106,11 +114,11 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
dev->resource[i].flags &= ~IORESOURCE_IO;
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_windbond_82c105);
void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
{
unsigned long offset = 0;
struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
......@@ -215,8 +223,7 @@ static void phb_set_model(struct pci_controller *hose,
/*
* Allocate pci_controller(phb) initialized common variables.
*/
struct pci_controller * __init
pci_alloc_pci_controller(enum phb_types controller_type)
struct pci_controller * __init pci_alloc_pci_controller(enum phb_types controller_type)
{
struct pci_controller *hose;
......@@ -246,8 +253,7 @@ pci_alloc_pci_controller(enum phb_types controller_type)
/*
* Dymnamically allocate pci_controller(phb), initialize common variables.
*/
struct pci_controller *
pci_alloc_phb_dynamic(enum phb_types controller_type)
struct pci_controller * pci_alloc_phb_dynamic(enum phb_types controller_type)
{
struct pci_controller *hose;
......@@ -430,9 +436,9 @@ int pci_name_bus(char *name, struct pci_bus *bus)
*
* Returns negative error code on failure, zero on success.
*/
static __inline__ int
__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
......@@ -487,9 +493,9 @@ __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
* mapping.
*/
static __inline__ void
__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
}
......@@ -498,9 +504,10 @@ __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
static __inline__ void
__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev,
struct vm_area_struct *vma,
enum pci_mmap_state mmap_state,
int write_combine)
{
long prot = pgprot_val(vma->vm_page_prot);
......@@ -578,9 +585,11 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
int rlen = 0;
range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
if (rlen < sizeof(struct isa_range)) {
printk(KERN_ERR "unexpected isa range size: %s\n",
__FUNCTION__);
if (range == NULL || (rlen < sizeof(struct isa_range))) {
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
"mapping 64k\n");
__ioremap_explicit(phb_io_base_phys, (unsigned long)phb_io_base_virt,
0x10000, _PAGE_NO_CACHE);
return;
}
......@@ -613,7 +622,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
}
void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev)
struct device_node *dev)
{
unsigned int *ranges;
unsigned long size;
......@@ -645,8 +654,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
switch (ranges[0] >> 24) {
switch ((ranges[0] >> 24) & 0x3) {
case 1: /* I/O space */
hose->io_base_phys = cpu_phys_addr;
hose->pci_io_size = size;
......@@ -654,6 +662,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
res = &hose->io_resource;
res->flags = IORESOURCE_IO;
res->start = pci_addr;
DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
res->start, res->start + size - 1);
break;
case 2: /* memory space */
memno = 0;
......@@ -666,6 +676,8 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
res = &hose->mem_resources[memno];
res->flags = IORESOURCE_MEM;
res->start = cpu_phys_addr;
DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
res->start, res->start + size - 1);
}
break;
}
......@@ -851,6 +863,9 @@ int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
else
busdn = bus->sysdata; /* must be a phb */
if (busdn == NULL)
return 0;
/*
* Check to see if there is any of the 8 functions are in the
* device tree. If they are then we need to scan all the
......@@ -873,7 +888,8 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (dev->resource[i].flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
unsigned long offset = (unsigned long)hose->io_base_virt
- pci_io_base;
unsigned long start, end, mask;
start = dev->resource[i].start += offset;
......
......@@ -46,29 +46,13 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
{
struct pci_controller *phb = data;
u32 *regs;
char *device_type = get_property(dn, "device_type", NULL);
char *model;
dn->phb = phb;
if (device_type && (strcmp(device_type, "pci") == 0) &&
(get_property(dn, "class-code", NULL) == 0)) {
/* special case for PHB's. Sigh. */
regs = (u32 *)get_property(dn, "bus-range", NULL);
dn->busno = regs[0];
model = (char *)get_property(dn, "model", NULL);
if (strstr(model, "U3"))
dn->devfn = -1;
else
dn->devfn = 0; /* assumption */
} else {
regs = (u32 *)get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
dn->busno = (regs[0] >> 16) & 0xff;
dn->devfn = (regs[0] >> 8) & 0xff;
}
regs = (u32 *)get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
dn->busno = (regs[0] >> 16) & 0xff;
dn->devfn = (regs[0] >> 8) & 0xff;
}
return NULL;
}
......@@ -97,20 +81,25 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
struct device_node *dn, *nextdn;
void *ret;
if (pre && ((ret = pre(start, data)) != NULL))
return ret;
/* We started with a phb, iterate all childs */
for (dn = start->child; dn; dn = nextdn) {
u32 *classp, class;
nextdn = NULL;
if (get_property(dn, "class-code", NULL)) {
if (pre && ((ret = pre(dn, data)) != NULL))
return ret;
if (dn->child)
/* Depth first...do children */
nextdn = dn->child;
else if (dn->sibling)
/* ok, try next sibling instead. */
nextdn = dn->sibling;
}
classp = (u32 *)get_property(dn, "class-code", NULL);
class = classp ? *classp : 0;
if (pre && ((ret = pre(dn, data)) != NULL))
return ret;
/* If we are a PCI bridge, go down */
if (dn->child && ((class >> 8) == PCI_CLASS_BRIDGE_PCI ||
(class >> 8) == PCI_CLASS_BRIDGE_CARDBUS))
/* Depth first...do children */
nextdn = dn->child;
else if (dn->sibling)
/* ok, try next sibling instead. */
nextdn = dn->sibling;
if (!nextdn) {
/* Walk up to next valid sibling. */
do {
......@@ -124,26 +113,16 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
return NULL;
}
/*
* Same as traverse_pci_devices except this does it for all phbs.
*/
static void *traverse_all_pci_devices(traverse_func pre)
void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
{
struct pci_controller *phb, *tmp;
void *ret;
struct device_node * dn = (struct device_node *) phb->arch_data;
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
!= NULL)
return ret;
return NULL;
}
/* PHB nodes themselves must not match */
dn->devfn = dn->busno = -1;
dn->phb = phb;
void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
{
/* Update dn->phb ptrs for new phb and children devices */
traverse_pci_devices((struct device_node *)phb->arch_data,
update_dn_pci_info, phb);
traverse_pci_devices(dn, update_dn_pci_info, phb);
}
/*
......@@ -154,6 +133,7 @@ static void *is_devfn_node(struct device_node *dn, void *data)
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xff;
return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
}
......@@ -180,10 +160,8 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev)
phb_dn = phb->arch_data;
dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
if (dn) {
if (dn)
dev->sysdata = dn;
/* ToDo: call some device init hook here */
}
return dn;
}
EXPORT_SYMBOL(fetch_dev_dn);
......@@ -195,8 +173,11 @@ EXPORT_SYMBOL(fetch_dev_dn);
*/
void __init pci_devs_phb_init(void)
{
struct pci_controller *phb, *tmp;
/* This must be done first so the device nodes have valid pci info! */
traverse_all_pci_devices(update_dn_pci_info);
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
pci_devs_phb_init_dynamic(phb);
}
......
......@@ -72,6 +72,7 @@
#include <asm/lmb.h>
#include "pmac.h"
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
......@@ -319,29 +320,9 @@ void __init pmac_init_early(void)
DBG(" <- pmac_init_early\n");
}
extern void* OpenPIC_Addr;
extern void* OpenPIC2_Addr;
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
int programmer_switch_irq);
extern void openpic2_init(int offset);
extern int openpic_get_irq(struct pt_regs *regs);
extern int openpic2_get_irq(struct pt_regs *regs);
static int pmac_cascade_irq = -1;
static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs)
static int pmac_u3_cascade(struct pt_regs *regs, void *data)
{
int irq;
for (;;) {
irq = openpic2_get_irq(regs);
if (irq == -1)
break;
ppc_irq_dispatch_handler(regs, irq);
}
return IRQ_HANDLED;
return mpic_get_one_irq((struct mpic *)data, regs);
}
static __init void pmac_init_IRQ(void)
......@@ -349,6 +330,7 @@ static __init void pmac_init_IRQ(void)
struct device_node *irqctrler = NULL;
struct device_node *irqctrler2 = NULL;
struct device_node *np = NULL;
struct mpic *mpic1, *mpic2;
/* We first try to detect Apple's new Core99 chipset, since mac-io
* is quite different on those machines and contains an IBM MPIC2.
......@@ -368,44 +350,37 @@ static __init void pmac_init_IRQ(void)
(unsigned int)irqctrler->addrs[0].address);
prom_get_irq_senses(senses, 0, 128);
OpenPIC_InitSenses = senses;
OpenPIC_NumInitSenses = 128;
OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
irqctrler->addrs[0].size);
openpic_init(1, 0, NULL, -1);
mpic1 = mpic_alloc(irqctrler->addrs[0].address,
MPIC_PRIMARY | MPIC_WANTS_RESET,
0, 0, 128, 256, senses, 128, " K2-MPIC ");
BUG_ON(mpic1 == NULL);
mpic_init(mpic1);
if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
irqctrler2->n_addrs > 0) {
printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
(u32)irqctrler2->addrs[0].address,
irqctrler2->intrs[0].line);
pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
irqctrler2->addrs[0].size);
prom_get_irq_senses(senses, 128, 128 + 128);
OpenPIC_InitSenses = senses;
OpenPIC_NumInitSenses = 128;
openpic2_init(128);
pmac_cascade_irq = irqctrler2->intrs[0].line;
/* We don't need to set MPIC_BROKEN_U3 here since we don't have
* hypertransport interrupts routed to it
*/
mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
0, 128, 128, 0, senses, 128, " U3-MPIC ");
BUG_ON(mpic2 == NULL);
mpic_init(mpic2);
mpic_setup_cascade(irqctrler2->intrs[0].line,
pmac_u3_cascade, mpic2);
}
}
of_node_put(irqctrler);
of_node_put(irqctrler2);
}
/* We cannot do request_irq too early ... Right now, we get the
* cascade as a core_initcall, which should be fine for our needs
*/
static int __init pmac_irq_cascade_init(void)
{
if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0,
"U3->K2 Cascade", NULL))
printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n");
return 0;
}
core_initcall(pmac_irq_cascade_init);
static void __init pmac_progress(char *s, unsigned short hex)
{
if (sccdbg) {
......@@ -420,6 +395,15 @@ static void __init pmac_progress(char *s, unsigned short hex)
#endif /* CONFIG_BOOTX_TEXT */
}
/*
* pmac has no legacy IO, anything calling this function has to
* fail or bad things will happen
*/
static int pmac_check_legacy_ioport(unsigned int baseport)
{
return -ENODEV;
}
static int __init pmac_declare_of_platform_devices(void)
{
struct device_node *np;
......@@ -463,7 +447,7 @@ struct machdep_calls __initdata pmac_md = {
.init_early = pmac_init_early,
.get_cpuinfo = pmac_show_cpuinfo,
.init_IRQ = pmac_init_IRQ,
.get_irq = openpic_get_irq,
.get_irq = mpic_get_irq,
.pcibios_fixup = pmac_pcibios_fixup,
.restart = pmac_restart,
.power_off = pmac_power_off,
......@@ -474,4 +458,5 @@ struct machdep_calls __initdata pmac_md = {
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
.progress = pmac_progress,
.check_legacy_ioport = pmac_check_legacy_ioport
};
......@@ -21,6 +21,9 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#undef DEBUG
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
......@@ -32,6 +35,7 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
......@@ -48,14 +52,18 @@
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
#include "open_pic.h"
#include "mpic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
extern void pmac_secondary_start_1(void);
extern void pmac_secondary_start_2(void);
extern void pmac_secondary_start_3(void);
extern void smp_openpic_message_pass(int target, int msg);
extern struct smp_ops_t *smp_ops;
static int __init smp_core99_probe(void)
......@@ -75,7 +83,7 @@ static int __init smp_core99_probe(void)
printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
if (ncpus > 1)
openpic_request_IPIs();
mpic_request_ipis();
return ncpus;
}
......@@ -102,15 +110,16 @@ static void __init smp_core99_kick_cpu(int nr)
* b .pmac_secondary_start - KERNELBASE
*/
switch(nr) {
case 1:
new_vector = (unsigned long)pmac_secondary_start_1;
break;
case 2:
new_vector = (unsigned long)pmac_secondary_start_2;
break;
case 3:
new_vector = (unsigned long)pmac_secondary_start_3;
break;
case 1:
new_vector = (unsigned long)pmac_secondary_start_1;
break;
case 2:
new_vector = (unsigned long)pmac_secondary_start_2;
break;
case 3:
default:
new_vector = (unsigned long)pmac_secondary_start_3;
break;
}
*vector = 0x48000002 + (new_vector - KERNELBASE);
......@@ -138,8 +147,8 @@ static void __init smp_core99_kick_cpu(int nr)
static void __init smp_core99_setup_cpu(int cpu_nr)
{
/* Setup openpic */
do_openpic_setup_cpu();
/* Setup MPIC */
mpic_setup_this_cpu();
if (cpu_nr == 0) {
extern void g5_phy_disable_cpu1(void);
......@@ -149,15 +158,12 @@ static void __init smp_core99_setup_cpu(int cpu_nr)
*/
if (num_online_cpus() < 2)
g5_phy_disable_cpu1();
if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
if (ppc_md.progress) ppc_md.progress("smp_core99_setup_cpu 0 done", 0x349);
}
}
extern void smp_generic_give_timebase(void);
extern void smp_generic_take_timebase(void);
struct smp_ops_t core99_smp_ops __pmacdata = {
.message_pass = smp_openpic_message_pass,
.message_pass = smp_mpic_message_pass,
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,
......
......@@ -52,7 +52,6 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
#include "open_pic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
......@@ -1092,8 +1091,7 @@ prom_n_size_cells(struct device_node* np)
* Work out the sense (active-low level / active-high edge)
* of each interrupt from the device tree.
*/
void __init
prom_get_irq_senses(unsigned char *senses, int off, int max)
void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
{
struct device_node *np;
int i, j;
......@@ -1105,7 +1103,9 @@ prom_get_irq_senses(unsigned char *senses, int off, int max)
for (j = 0; j < np->n_intrs; j++) {
i = np->intrs[j].line;
if (i >= off && i < max)
senses[i-off] = np->intrs[j].sense;
senses[i-off] = np->intrs[j].sense ?
IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
}
}
}
......
......@@ -51,7 +51,6 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
#include "open_pic.h"
#ifdef CONFIG_LOGO_LINUX_CLUT224
#include <linux/linux_logo.h>
......@@ -160,8 +159,6 @@ extern void copy_and_flush(unsigned long dest, unsigned long src,
extern unsigned long klimit;
//int global_width = 640, global_height = 480, global_depth = 8, global_pitch;
//unsigned global_address;
/* prom structure */
static struct prom_t __initdata prom;
......@@ -706,46 +703,50 @@ static void __init prom_instantiate_rtas(void)
struct prom_t *_prom = PTRRELOC(&prom);
phandle prom_rtas;
u64 base, entry = 0;
u32 size;
u32 size = 0;
prom_debug("prom_instantiate_rtas: start...\n");
prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
if (prom_rtas != (phandle) -1) {
prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
if (size != 0) {
base = alloc_down(size, PAGE_SIZE, 0);
if (base == 0) {
prom_printf("RTAS allocation failed !\n");
return;
}
prom_printf("instantiating rtas at 0x%x", base);
prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
prom_printf("...");
prom_debug("prom_rtas: %x\n", prom_rtas);
if (prom_rtas == (phandle) -1)
return;
if (call_prom("call-method", 3, 2,
ADDR("instantiate-rtas"),
prom_rtas, base) != PROM_ERROR) {
entry = (long)_prom->args.rets[1];
}
if (entry == 0) {
prom_printf(" failed\n");
return;
}
prom_printf(" done\n");
prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
if (size == 0)
return;
reserve_mem(base, size);
}
base = alloc_down(size, PAGE_SIZE, 0);
if (base == 0) {
prom_printf("RTAS allocation failed !\n");
return;
}
prom_printf("instantiating rtas at 0x%x", base);
prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
prom_printf("...");
prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
prom_debug("rtas size = 0x%x\n", (long)size);
if (call_prom("call-method", 3, 2,
ADDR("instantiate-rtas"),
prom_rtas, base) != PROM_ERROR) {
entry = (long)_prom->args.rets[1];
}
if (entry == 0) {
prom_printf(" failed\n");
return;
}
prom_printf(" done\n");
reserve_mem(base, size);
prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
prom_debug("rtas size = 0x%x\n", (long)size);
prom_debug("prom_instantiate_rtas: end...\n");
}
......@@ -952,9 +953,9 @@ static void __init prom_hold_cpus(void)
continue;
/* Skip non-configured cpus. */
prom_getprop(node, "status", type, sizeof(type));
if (strcmp(type, RELOC("okay")) != 0)
continue;
if (prom_getprop(node, "status", type, sizeof(type)) > 0)
if (strcmp(type, RELOC("okay")) != 0)
continue;
reg = -1;
prom_getprop(node, "reg", &reg, sizeof(reg));
......@@ -994,7 +995,8 @@ static void __init prom_hold_cpus(void)
secondary_hold, cpuid);
for ( i = 0 ; (i < 100000000) &&
(*acknowledge == ((unsigned long)-1)); i++ ) ;
(*acknowledge == ((unsigned long)-1)); i++ )
mb();
if (*acknowledge == cpuid) {
prom_printf("done\n");
......@@ -1161,7 +1163,7 @@ static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
* So we check whether we will need to open the display,
* and if so, open it now.
*/
static unsigned long __init prom_check_displays(void)
static void __init prom_check_displays(void)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
......
......@@ -30,6 +30,8 @@
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/unistd.h>
#include <linux/serial.h>
#include <linux/8250.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/processor.h>
......@@ -51,6 +53,7 @@
#include <asm/system.h>
#include <asm/rtas.h>
#include <asm/iommu.h>
#include <asm/serial.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
......@@ -1106,6 +1109,193 @@ __setup("spread_lpevents=", set_spread_lpevents );
__setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
__setup("decr_overclock=", set_decr_overclock );
#ifndef CONFIG_PPC_ISERIES
/*
* This function can be used by platforms to "find" legacy serial ports.
* It works for "serial" nodes under an "isa" node, and will try to
* respect the "ibm,aix-loc" property if any. It works with up to 8
* ports.
*/
#define MAX_LEGACY_SERIAL_PORTS 8
static struct old_serial_port old_serial_ports[MAX_LEGACY_SERIAL_PORTS];
static unsigned int old_serial_count;
void __init generic_find_legacy_serial_ports(unsigned int *default_speed)
{
struct device_node *np;
u32 *sizeprop;
struct isa_reg_property {
u32 space;
u32 address;
u32 size;
};
struct pci_reg_property {
struct pci_address addr;
u32 size_hi;
u32 size_lo;
};
DBG(" -> generic_find_legacy_serial_port()\n");
naca->serialPortAddr = 0;
if (default_speed)
*default_speed = 0;
np = of_find_node_by_path("/");
if (!np)
return;
/* First fill our array */
for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
struct device_node *isa, *pci;
struct isa_reg_property *reg;
unsigned long phys_size, addr_size, io_base;
u32 *rangesp;
u32 *interrupts, *clk, *spd;
char *typep;
int index, rlen, rentsize;
/* Ok, first check if it's under an "isa" parent */
isa = of_get_parent(np);
if (!isa || strcmp(isa->name, "isa")) {
DBG("%s: no isa parent found\n", np->full_name);
continue;
}
/* Now look for an "ibm,aix-loc" property that gives us ordering
* if any...
*/
typep = (char *)get_property(np, "ibm,aix-loc", NULL);
/* Get the ISA port number */
reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
if (reg == NULL)
goto next_port;
/* We assume the interrupt number isn't translated ... */
interrupts = (u32 *)get_property(np, "interrupts", NULL);
/* get clock freq. if present */
clk = (u32 *)get_property(np, "clock-frequency", NULL);
/* get default speed if present */
spd = (u32 *)get_property(np, "current-speed", NULL);
/* Default to locate at end of array */
index = old_serial_count; /* end of the array by default */
/* If we have a location index, then use it */
if (typep && *typep == 'S') {
index = simple_strtol(typep+1, NULL, 0) - 1;
/* if index is out of range, use end of array instead */
if (index >= MAX_LEGACY_SERIAL_PORTS)
index = old_serial_count;
/* if our index is still out of range, that mean that
* array is full, we could scan for a free slot but that
* make little sense to bother, just skip the port
*/
if (index >= MAX_LEGACY_SERIAL_PORTS)
goto next_port;
if (index >= old_serial_count)
old_serial_count = index + 1;
/* Check if there is a port who already claimed our slot */
if (old_serial_ports[index].port != 0) {
/* if we still have some room, move it, else override */
if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
DBG("Moved legacy port %d -> %d\n", index,
old_serial_count);
old_serial_ports[old_serial_count++] =
old_serial_ports[index];
} else {
DBG("Replacing legacy port %d\n", index);
}
}
}
if (index >= MAX_LEGACY_SERIAL_PORTS)
goto next_port;
if (index >= old_serial_count)
old_serial_count = index + 1;
/* Now fill the entry */
memset(&old_serial_ports[index], 0, sizeof(struct old_serial_port));
old_serial_ports[index].uart = 0;
old_serial_ports[index].baud_base = clk ? (*clk / 16) : BASE_BAUD;
old_serial_ports[index].port = reg->address;
old_serial_ports[index].irq = interrupts ? interrupts[0] : 0;
old_serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
index,
old_serial_ports[index].port,
old_serial_ports[index].irq,
old_serial_ports[index].baud_base * 16);
/* Get phys address of IO reg for port 1 */
if (index != 0)
goto next_port;
pci = of_get_parent(isa);
if (!pci) {
DBG("%s: no pci parent found\n", np->full_name);
goto next_port;
}
rangesp = (u32 *)get_property(pci, "ranges", &rlen);
if (rangesp == NULL) {
of_node_put(pci);
goto next_port;
}
rlen /= 4;
/* we need the #size-cells of the PCI bridge node itself */
phys_size = 1;
sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
if (sizeprop != NULL)
phys_size = *sizeprop;
/* we need the parent #addr-cells */
addr_size = prom_n_addr_cells(pci);
rentsize = 3 + addr_size + phys_size;
io_base = 0;
for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
if (((rangesp[0] >> 24) & 0x3) != 1)
continue; /* not IO space */
io_base = rangesp[3];
if (addr_size == 2)
io_base = (io_base << 32) | rangesp[4];
}
if (io_base != 0) {
naca->serialPortAddr = io_base + reg->address;
if (default_speed && spd)
*default_speed = *spd;
}
of_node_put(pci);
next_port:
of_node_put(isa);
}
DBG(" <- generic_find_legacy_serial_port()\n");
}
struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
{
*count = old_serial_count;
return old_serial_ports;
}
#else
struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
{
*count = 0;
return 0;
}
#endif /* CONFIG_PPC_ISERIES */
EXPORT_SYMBOL(get_legacy_serial_ports);
int check_legacy_ioport(unsigned long base_port)
{
if (ppc_md.check_legacy_ioport == NULL)
return 0;
return ppc_md.check_legacy_ioport(base_port);
}
EXPORT_SYMBOL(check_legacy_ioport);
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
......@@ -1118,3 +1308,10 @@ static int __init early_xmon(char *p)
early_param("xmon", early_xmon);
#endif
void cpu_die(void)
{
if (ppc_md.cpu_die)
ppc_md.cpu_die();
local_irq_disable();
for (;;);
}
This diff is collapsed.
......@@ -267,6 +267,7 @@ static int dart_init(struct device_node *dart_node)
void iommu_setup_u3(void)
{
struct pci_controller *phb, *tmp;
struct pci_dev *dev = NULL;
struct device_node *dn;
......@@ -299,6 +300,11 @@ void iommu_setup_u3(void)
if (dn)
dn->iommu_table = &iommu_table_u3;
}
/* We also make sure we set all PHBs ... */
list_for_each_entry_safe(phb, tmp, &hose_list, list_node) {
dn = (struct device_node *)phb->arch_data;
dn->iommu_table = &iommu_table_u3;
}
}
void __init alloc_u3_dart_table(void)
......
......@@ -49,15 +49,28 @@ struct NS16550 {
static volatile struct NS16550 *udbg_comport;
void udbg_init_uart(void *comport)
void udbg_init_uart(void *comport, unsigned int speed)
{
u8 dll = 12;
switch(speed) {
case 115200:
dll = 1;
break;
case 57600:
dll = 2;
break;
case 38400:
dll = 3;
break;
}
if (comport) {
udbg_comport = (struct NS16550 *)comport;
udbg_comport->lcr = 0x00; eieio();
udbg_comport->ier = 0xFF; eieio();
udbg_comport->ier = 0x00; eieio();
udbg_comport->lcr = 0x80; eieio(); /* Access baud rate */
udbg_comport->dll = 12; eieio(); /* 1 = 115200, 2 = 57600, 3 = 38400, 12 = 9600 baud */
udbg_comport->dll = dll; eieio(); /* 1 = 115200, 2 = 57600, 3 = 38400, 12 = 9600 baud */
udbg_comport->dlm = 0; eieio(); /* dll >> 8 which should be zero for fast rates; */
udbg_comport->lcr = 0x03; eieio(); /* 8 data, 1 stop, no parity */
udbg_comport->mcr = 0x03; eieio(); /* RTS/DTR */
......
......@@ -578,7 +578,7 @@ static int __init xics_setup_i8259(void)
no_action, 0, "8259 cascade", NULL))
printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
"cascade\n");
i8259_init();
i8259_init(0);
}
return 0;
}
......
......@@ -4286,6 +4286,13 @@ int __init floppy_init(void)
}
use_virtual_dma = can_use_virtual_dma & 1;
#if defined(CONFIG_PPC64)
if (check_legacy_ioport(FDC1)) {
del_timer(&fd_timeout);
err = -ENODEV;
goto out_unreg_region;
}
#endif
fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) {
del_timer(&fd_timeout);
......
......@@ -5551,7 +5551,7 @@ cy_setup(char *str, int *ints)
}
for (j = 1; j <= ints[0]; j++){
if ( i < NR_ISA_ADDRS ){
cy_isa_addresses[i++] = (unsigned char *)(ints[j]);
cy_isa_addresses[i++] = ints[j];
}
}
#endif /* CONFIG_ISA */
......
......@@ -168,8 +168,7 @@ static struct tty_struct *alloc_tty_struct(void)
static inline void free_tty_struct(struct tty_struct *tty)
{
if (tty->write_buf)
kfree(tty->write_buf);
kfree(tty->write_buf);
kfree(tty);
}
......@@ -1060,6 +1059,7 @@ static inline ssize_t do_tty_write(
up(&tty->atomic_write);
return -ENOMEM;
}
kfree(tty->write_buf);
tty->write_cnt = chunk;
tty->write_buf = buf;
}
......
......@@ -339,7 +339,7 @@ config SCx200_I2C_SDA
config SCx200_ACB
tristate "NatSemi SCx200 ACCESS.bus"
depends on I2C
depends on I2C && PCI
help
Enable the use of the ACCESS.bus controllers of a SCx200 processor.
......
......@@ -35,6 +35,7 @@
# define I8042_AUX_IRQ 12
#endif
/*
* Register numbers.
*/
......@@ -96,7 +97,7 @@ static inline int i8042_platform_init(void)
* On ix86 platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on ix86 boxes.
*/
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__)
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) && !defined (CONFIG_PPC64)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
return -1;
#endif
......@@ -110,12 +111,18 @@ static inline int i8042_platform_init(void)
i8042_noloop = 1;
#endif
#if defined(CONFIG_PPC64)
if (check_legacy_ioport(I8042_DATA_REG))
return -1;
if (!request_region(I8042_DATA_REG, 16, "i8042"))
return -1;
#endif
return 0;
}
static inline void i8042_platform_exit(void)
{
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__)
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(CONFIG_PPC64)
release_region(I8042_DATA_REG, 16);
#endif
}
......
......@@ -32,6 +32,7 @@
#include <linux/serialP.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/8250.h>
#include <asm/io.h>
#include <asm/irq.h>
......@@ -41,7 +42,6 @@
#endif
#include <linux/serial_core.h>
#include "8250.h"
/*
* Configuration:
......@@ -112,11 +112,17 @@ unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
#define SERIAL_PORT_DFNS
#endif
#ifndef ARCH_HAS_GET_LEGACY_SERIAL_PORTS
static struct old_serial_port old_serial_port[] = {
SERIAL_PORT_DFNS /* defined in asm/serial.h */
};
static inline struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
{
*count = ARRAY_SIZE(old_serial_port);
return old_serial_port;
}
#define UART_NR (ARRAY_SIZE(old_serial_port) + CONFIG_SERIAL_8250_NR_UARTS)
#endif /* ARCH_HAS_DYNAMIC_LEGACY_SERIAL_PORTS */
#ifdef CONFIG_SERIAL_8250_RSA
......@@ -1958,22 +1964,27 @@ static void __init serial8250_isa_init_ports(void)
{
struct uart_8250_port *up;
static int first = 1;
struct old_serial_port *old_ports;
int count;
int i;
if (!first)
return;
first = 0;
for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
up->port.uartclk = old_serial_port[i].baud_base * 16;
up->port.flags = old_serial_port[i].flags;
up->port.hub6 = old_serial_port[i].hub6;
up->port.membase = old_serial_port[i].iomem_base;
up->port.iotype = old_serial_port[i].io_type;
up->port.regshift = old_serial_port[i].iomem_reg_shift;
old_ports = get_legacy_serial_ports(&count);
if (old_ports == NULL)
return;
for (i = 0, up = serial8250_ports; i < count; i++, up++) {
up->port.iobase = old_ports[i].port;
up->port.irq = irq_canonicalize(old_ports[i].irq);
up->port.uartclk = old_ports[i].baud_base * 16;
up->port.flags = old_ports[i].flags;
up->port.hub6 = old_ports[i].hub6;
up->port.membase = old_ports[i].iomem_base;
up->port.iotype = old_ports[i].io_type;
up->port.regshift = old_ports[i].iomem_reg_shift;
up->port.ops = &serial8250_pops;
if (share_irqs)
up->port.flags |= UPF_SHARE_IRQ;
......@@ -1990,6 +2001,13 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
for (i = 0; i < UART_NR; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
/* Don't register "empty" ports, setting "ops" on them
* makes the console driver "setup" routine to succeed,
* which is wrong. --BenH.
*/
if (!up->port.iobase)
continue;
up->port.line = i;
up->port.ops = &serial8250_pops;
up->port.dev = dev;
......
......@@ -23,13 +23,13 @@
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/serial_core.h>
#include <linux/8250_pci.h>
#include <linux/bitops.h>
#include <linux/8250.h>
#include <linux/8250_pci.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#include "8250.h"
/*
* Definitions for PCI support.
......
......@@ -26,12 +26,11 @@
#include <linux/serialP.h>
#include <linux/serial_core.h>
#include <linux/bitops.h>
#include <linux/8250.h>
#include <asm/byteorder.h>
#include <asm/serial.h>
#include "8250.h"
#define UNKNOWN_DEV 0x3000
......
......@@ -29,6 +29,7 @@
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/delay.h>
#include <linux/8250.h>
#include <asm/serial.h>
#include <asm/io.h>
......@@ -40,7 +41,6 @@
#endif
#include <linux/serial_core.h>
#include "8250.h"
/*
* Debugging.
......
......@@ -44,6 +44,7 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/major.h>
#include <linux/8250.h>
#include <asm/io.h>
#include <asm/system.h>
......@@ -55,8 +56,6 @@
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
#include "8250.h"
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
......
......@@ -2344,9 +2344,9 @@ int __init atyfb_do_init(void)
info->screen_base = ioremap(phys_vmembase[m64_num],
phys_size[m64_num]);
info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
0x10000) + 0xFC00ul;
info->fix.mmio_start = default_par->ati_regbase; /* Fake! */
default_par->ati_regbase = ioremap(phys_guiregbase[m64_num],
0x10000) + 0xFC00ul;
info->fix.mmio_start = (unsigned long)default_par->ati_regbase; /* Fake! */
aty_st_le32(CLOCK_CNTL, 0x12345678, default_par);
clock_r = aty_ld_le32(CLOCK_CNTL, default_par);
......
......@@ -24,6 +24,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/vmalloc.h>
#include "attrib.h"
#include "inode.h"
......
......@@ -11,6 +11,7 @@
#define __ASM_PPC64_FLOPPY_H
#include <linux/config.h>
#include <asm/machdep.h>
#define fd_inb(port) inb_p(port)
#define fd_outb(value,port) outb_p(value,port)
......
#ifndef _PPC64_IO_H
#ifndef _PPC64_IO_H
#define _PPC64_IO_H
/*
......@@ -436,6 +436,10 @@ static inline int check_signature(const volatile void __iomem * io_addr,
#define dma_cache_wback(_start,_size) do { } while (0)
#define dma_cache_wback_inv(_start,_size) do { } while (0)
/* Check of existence of legacy devices */
extern int check_legacy_ioport(unsigned long base_port);
#endif /* __KERNEL__ */
#endif /* _PPC64_IO_H */
......@@ -20,6 +20,19 @@
/* this number is used when no interrupt has been assigned */
#define NO_IRQ (-1)
/*
* These constants are used for passing information about interrupt
* signal polarity and level/edge sensing to the low-level PIC chip
* drivers.
*/
#define IRQ_SENSE_MASK 0x1
#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */
#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */
#define IRQ_POLARITY_MASK 0x2
#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */
#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */
#define get_irq_desc(irq) (&irq_desc[(irq)])
/* Define a way to iterate across irqs. */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*/
void udbg_init_uart(void *comport);
void udbg_init_uart(void *comport, unsigned int speed);
void udbg_putc(unsigned char c);
unsigned char udbg_getc(void);
int udbg_getc_poll(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment