Commit 24665cd0 authored by Linus Torvalds's avatar Linus Torvalds
parents fed2fc18 d7152fe1
...@@ -504,6 +504,13 @@ L: bonding-devel@lists.sourceforge.net ...@@ -504,6 +504,13 @@ L: bonding-devel@lists.sourceforge.net
W: http://sourceforge.net/projects/bonding/ W: http://sourceforge.net/projects/bonding/
S: Supported S: Supported
BROADBAND PROCESSOR ARCHITECTURE
P: Arnd Bergmann
M: arnd@arndb.de
L: linuxppc64-dev@ozlabs.org
W: http://linuxppc64.org
S: Supported
BTTV VIDEO4LINUX DRIVER BTTV VIDEO4LINUX DRIVER
P: Gerd Knorr P: Gerd Knorr
M: kraxel@bytesex.org M: kraxel@bytesex.org
......
...@@ -77,6 +77,10 @@ config PPC_PSERIES ...@@ -77,6 +77,10 @@ config PPC_PSERIES
bool " IBM pSeries & new iSeries" bool " IBM pSeries & new iSeries"
default y default y
config PPC_BPA
bool " Broadband Processor Architecture"
depends on PPC_MULTIPLATFORM
config PPC_PMAC config PPC_PMAC
depends on PPC_MULTIPLATFORM depends on PPC_MULTIPLATFORM
bool " Apple G5 based machines" bool " Apple G5 based machines"
...@@ -106,6 +110,21 @@ config PPC_OF ...@@ -106,6 +110,21 @@ config PPC_OF
bool bool
default y default y
config XICS
depends on PPC_PSERIES
bool
default y
config MPIC
depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE
bool
default y
config BPA_IIC
depends on PPC_BPA
bool
default y
# VMX is pSeries only for now until somebody writes the iSeries # VMX is pSeries only for now until somebody writes the iSeries
# exception vectors for it # exception vectors for it
config ALTIVEC config ALTIVEC
...@@ -292,7 +311,7 @@ config MSCHUNKS ...@@ -292,7 +311,7 @@ config MSCHUNKS
config PPC_RTAS config PPC_RTAS
bool bool
depends on PPC_PSERIES depends on PPC_PSERIES || PPC_BPA
default y default y
config RTAS_PROC config RTAS_PROC
......
...@@ -90,12 +90,14 @@ boot := arch/ppc64/boot ...@@ -90,12 +90,14 @@ boot := arch/ppc64/boot
boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd
boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd
boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
boottarget-$(CONFIG_PPC_BPA) := zImage zImage.initrd
$(boottarget-y): vmlinux $(boottarget-y): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
bootimage-$(CONFIG_PPC_PMAC) := vmlinux bootimage-$(CONFIG_PPC_PMAC) := vmlinux
bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
bootimage-$(CONFIG_PPC_BPA) := zImage
bootimage-$(CONFIG_PPC_ISERIES) := vmlinux bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
BOOTIMAGE := $(bootimage-y) BOOTIMAGE := $(bootimage-y)
install: vmlinux install: vmlinux
......
...@@ -27,17 +27,21 @@ obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \ ...@@ -27,17 +27,21 @@ obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
iSeries_iommu.o iSeries_iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
xics.o rtas.o pSeries_setup.o pSeries_iommu.o pSeries_setup.o pSeries_iommu.o
obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
bpa_iic.o spider-pic.o
obj-$(CONFIG_EEH) += eeh.o obj-$(CONFIG_EEH) += eeh.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas_pci.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_VIOPATH) += viopath.o
...@@ -46,6 +50,8 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o ...@@ -46,6 +50,8 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_MPIC) += mpic.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
pmac_time.o pmac_nvram.o pmac_low_i2c.o pmac_time.o pmac_nvram.o pmac_low_i2c.o
...@@ -58,6 +64,7 @@ ifdef CONFIG_SMP ...@@ -58,6 +64,7 @@ ifdef CONFIG_SMP
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o
obj-$(CONFIG_PPC_BPA) += pSeries_smp.o
obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o
endif endif
......
/*
* BPA Internal Interrupt Controller
*
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
*
* Author: Arnd Bergmann <arndb@de.ibm.com>
*
* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/percpu.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
#include "bpa_iic.h"
struct iic_pending_bits {
u32 data;
u8 flags;
u8 class;
u8 source;
u8 prio;
};
enum iic_pending_flags {
IIC_VALID = 0x80,
IIC_IPI = 0x40,
};
struct iic_regs {
struct iic_pending_bits pending;
struct iic_pending_bits pending_destr;
u64 generate;
u64 prio;
};
struct iic {
struct iic_regs __iomem *regs;
};
static DEFINE_PER_CPU(struct iic, iic);
void iic_local_enable(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
}
void iic_local_disable(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
}
static unsigned int iic_startup(unsigned int irq)
{
return 0;
}
static void iic_enable(unsigned int irq)
{
iic_local_enable();
}
static void iic_disable(unsigned int irq)
{
}
static void iic_end(unsigned int irq)
{
iic_local_enable();
}
static struct hw_interrupt_type iic_pic = {
.typename = " BPA-IIC ",
.startup = iic_startup,
.enable = iic_enable,
.disable = iic_disable,
.end = iic_end,
};
static int iic_external_get_irq(struct iic_pending_bits pending)
{
int irq;
unsigned char node, unit;
node = pending.source >> 4;
unit = pending.source & 0xf;
irq = -1;
/*
* This mapping is specific to the Broadband
* Engine. We might need to get the numbers
* from the device tree to support future CPUs.
*/
switch (unit) {
case 0x00:
case 0x0b:
/*
* One of these units can be connected
* to an external interrupt controller.
*/
if (pending.prio > 0x3f ||
pending.class != 2)
break;
irq = IIC_EXT_OFFSET
+ spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+ node * IIC_NODE_STRIDE;
break;
case 0x01 ... 0x04:
case 0x07 ... 0x0a:
/*
* These units are connected to the SPEs
*/
if (pending.class > 2)
break;
irq = IIC_SPE_OFFSET
+ pending.class * IIC_CLASS_STRIDE
+ node * IIC_NODE_STRIDE
+ unit;
break;
}
if (irq == -1)
printk(KERN_WARNING "Unexpected interrupt class %02x, "
"source %02x, prio %02x, cpu %02x\n", pending.class,
pending.source, pending.prio, smp_processor_id());
return irq;
}
/* Get an IRQ number from the pending state register of the IIC */
int iic_get_irq(struct pt_regs *regs)
{
struct iic *iic;
int irq;
struct iic_pending_bits pending;
iic = &__get_cpu_var(iic);
*(unsigned long *) &pending =
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
irq = -1;
if (pending.flags & IIC_VALID) {
if (pending.flags & IIC_IPI) {
irq = IIC_IPI_OFFSET + (pending.prio >> 4);
/*
if (irq > 0x80)
printk(KERN_WARNING "Unexpected IPI prio %02x"
"on CPU %02x\n", pending.prio,
smp_processor_id());
*/
} else {
irq = iic_external_get_irq(pending);
}
}
return irq;
}
static struct iic_regs __iomem *find_iic(int cpu)
{
struct device_node *np;
int nodeid = cpu / 2;
unsigned long regs;
struct iic_regs __iomem *iic_regs;
for (np = of_find_node_by_type(NULL, "cpu");
np;
np = of_find_node_by_type(np, "cpu")) {
if (nodeid == *(int *)get_property(np, "node-id", NULL))
break;
}
if (!np) {
printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
iic_regs = NULL;
} else {
regs = *(long *)get_property(np, "iic", NULL);
/* hack until we have decided on the devtree info */
regs += 0x400;
if (cpu & 1)
regs += 0x20;
printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
iic_regs = __ioremap(regs, sizeof(struct iic_regs),
_PAGE_NO_CACHE);
}
return iic_regs;
}
#ifdef CONFIG_SMP
void iic_setup_cpu(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
}
void iic_cause_IPI(int cpu, int mesg)
{
out_be64(&per_cpu(iic, cpu).regs->generate, mesg);
}
static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
smp_message_recv(irq - IIC_IPI_OFFSET, regs);
return IRQ_HANDLED;
}
static void iic_request_ipi(int irq, const char *name)
{
/* IPIs are marked SA_INTERRUPT as they must run with irqs
* disabled */
get_irq_desc(irq)->handler = &iic_pic;
get_irq_desc(irq)->status |= IRQ_PER_CPU;
request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);
}
void iic_request_IPIs(void)
{
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");
#ifdef CONFIG_DEBUGGER
iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
#endif /* CONFIG_DEBUGGER */
}
#endif /* CONFIG_SMP */
static void iic_setup_spe_handlers(void)
{
int be, isrc;
/* Assume two threads per BE are present */
for (be=0; be < num_present_cpus() / 2; be++) {
for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
get_irq_desc(irq)->handler = &iic_pic;
}
}
}
void iic_init_IRQ(void)
{
int cpu, irq_offset;
struct iic *iic;
irq_offset = 0;
for_each_cpu(cpu) {
iic = &per_cpu(iic, cpu);
iic->regs = find_iic(cpu);
if (iic->regs)
out_be64(&iic->regs->prio, 0xff);
}
iic_setup_spe_handlers();
}
#ifndef ASM_BPA_IIC_H
#define ASM_BPA_IIC_H
#ifdef __KERNEL__
/*
* Mapping of IIC pending bits into per-node
* interrupt numbers.
*
* IRQ FF CC SS PP FF CC SS PP Description
*
* 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge
* 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge
* 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0
* 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1
* 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2
* 70-7f C0 ** ** 00 - C0 ** ** 0f IPI
*
* F flags
* C class
* S source
* P Priority
* + node number
* * don't care
*
* A node consists of a Broadband Engine and an optional
* south bridge device providing a maximum of 64 IRQs.
* The south bridge may be connected to either IOIF0
* or IOIF1.
* Each SPE is represented as three IRQ lines, one per
* interrupt class.
* 16 IRQ numbers are reserved for inter processor
* interruptions, although these are only used in the
* range of the first node.
*
* This scheme needs 128 IRQ numbers per BIF node ID,
* which means that with the total of 512 lines
* available, we can have a maximum of four nodes.
*/
enum {
IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */
IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */
IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */
IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */
IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */
IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */
};
extern void iic_init_IRQ(void);
extern int iic_get_irq(struct pt_regs *regs);
extern void iic_cause_IPI(int cpu, int mesg);
extern void iic_request_IPIs(void);
extern void iic_setup_cpu(void);
extern void iic_local_enable(void);
extern void iic_local_disable(void);
extern void spider_init_IRQ(void);
extern int spider_get_irq(unsigned long int_pending);
#endif
#endif /* ASM_BPA_IIC_H */
This diff is collapsed.
#ifndef BPA_IOMMU_H
#define BPA_IOMMU_H
/* some constants */
enum {
/* segment table entries */
IOST_VALID_MASK = 0x8000000000000000ul,
IOST_TAG_MASK = 0x3000000000000000ul,
IOST_PT_BASE_MASK = 0x000003fffffff000ul,
IOST_NNPT_MASK = 0x0000000000000fe0ul,
IOST_PS_MASK = 0x000000000000000ful,
IOST_PS_4K = 0x1,
IOST_PS_64K = 0x3,
IOST_PS_1M = 0x5,
IOST_PS_16M = 0x7,
/* iopt tag register */
IOPT_VALID_MASK = 0x0000000200000000ul,
IOPT_TAG_MASK = 0x00000001fffffffful,
/* iopt cache register */
IOPT_PROT_MASK = 0xc000000000000000ul,
IOPT_PROT_NONE = 0x0000000000000000ul,
IOPT_PROT_READ = 0x4000000000000000ul,
IOPT_PROT_WRITE = 0x8000000000000000ul,
IOPT_PROT_RW = 0xc000000000000000ul,
IOPT_COHERENT = 0x2000000000000000ul,
IOPT_ORDER_MASK = 0x1800000000000000ul,
/* order access to same IOID/VC on same address */
IOPT_ORDER_ADDR = 0x0800000000000000ul,
/* similar, but only after a write access */
IOPT_ORDER_WRITES = 0x1000000000000000ul,
/* Order all accesses to same IOID/VC */
IOPT_ORDER_VC = 0x1800000000000000ul,
IOPT_RPN_MASK = 0x000003fffffff000ul,
IOPT_HINT_MASK = 0x0000000000000800ul,
IOPT_IOID_MASK = 0x00000000000007fful,
IOSTO_ENABLE = 0x8000000000000000ul,
IOSTO_ORIGIN = 0x000003fffffff000ul,
IOSTO_HW = 0x0000000000000800ul,
IOSTO_SW = 0x0000000000000400ul,
IOCMD_CONF_TE = 0x0000800000000000ul,
/* memory mapped registers */
IOC_PT_CACHE_DIR = 0x000,
IOC_ST_CACHE_DIR = 0x800,
IOC_PT_CACHE_REG = 0x910,
IOC_ST_ORIGIN = 0x918,
IOC_CONF = 0x930,
/* The high bit needs to be set on every DMA address,
only 2GB are addressable */
BPA_DMA_VALID = 0x80000000,
BPA_DMA_MASK = 0x7fffffff,
};
void bpa_init_iommu(void);
#endif
/*
* NVRAM for CPBW
*
* (C) Copyright IBM Corp. 2005
*
* Authors : Utz Bacher <utz.bacher@de.ibm.com>
*
* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/machdep.h>
#include <asm/nvram.h>
#include <asm/prom.h>
static void __iomem *bpa_nvram_start;
static long bpa_nvram_len;
static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED;
static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index)
{
unsigned long flags;
if (*index >= bpa_nvram_len)
return 0;
if (*index + count > bpa_nvram_len)
count = bpa_nvram_len - *index;
spin_lock_irqsave(&bpa_nvram_lock, flags);
memcpy_fromio(buf, bpa_nvram_start + *index, count);
spin_unlock_irqrestore(&bpa_nvram_lock, flags);
*index += count;
return count;
}
static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index)
{
unsigned long flags;
if (*index >= bpa_nvram_len)
return 0;
if (*index + count > bpa_nvram_len)
count = bpa_nvram_len - *index;
spin_lock_irqsave(&bpa_nvram_lock, flags);
memcpy_toio(bpa_nvram_start + *index, buf, count);
spin_unlock_irqrestore(&bpa_nvram_lock, flags);
*index += count;
return count;
}
static ssize_t bpa_nvram_get_size(void)
{
return bpa_nvram_len;
}
int __init bpa_nvram_init(void)
{
struct device_node *nvram_node;
unsigned long *buffer;
int proplen;
unsigned long nvram_addr;
int ret;
ret = -ENODEV;
nvram_node = of_find_node_by_type(NULL, "nvram");
if (!nvram_node)
goto out;
ret = -EIO;
buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen);
if (proplen != 2*sizeof(unsigned long))
goto out;
ret = -ENODEV;
nvram_addr = buffer[0];
bpa_nvram_len = buffer[1];
if ( (!bpa_nvram_len) || (!nvram_addr) )
goto out;
bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len);
if (!bpa_nvram_start)
goto out;
printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n",
bpa_nvram_len >> 10, bpa_nvram_start);
ppc_md.nvram_read = bpa_nvram_read;
ppc_md.nvram_write = bpa_nvram_write;
ppc_md.nvram_size = bpa_nvram_get_size;
out:
of_node_put(nvram_node);
return ret;
}
/*
* linux/arch/ppc/kernel/bpa_setup.c
*
* Copyright (C) 1995 Linus Torvalds
* Adapted from 'alpha' version by Gary Thomas
* Modified by Cort Dougan (cort@cs.nmt.edu)
* Modified by PPC64 Team, IBM Corp
* Modified by BPA Team, IBM Deutschland Entwicklung GmbH
*
* 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/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/console.h>
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/pci-bridge.h>
#include <asm/iommu.h>
#include <asm/dma.h>
#include <asm/machdep.h>
#include <asm/time.h>
#include <asm/nvram.h>
#include <asm/cputable.h>
#include "pci.h"
#include "bpa_iic.h"
#include "bpa_iommu.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
void bpa_get_cpuinfo(struct seq_file *m)
{
struct device_node *root;
const char *model = "";
root = of_find_node_by_path("/");
if (root)
model = get_property(root, "model", NULL);
seq_printf(m, "machine\t\t: BPA %s\n", model);
of_node_put(root);
}
static void bpa_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
}
static void __init bpa_setup_arch(void)
{
ppc_md.init_IRQ = iic_init_IRQ;
ppc_md.get_irq = iic_get_irq;
#ifdef CONFIG_SMP
smp_init_pSeries();
#endif
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
if (ROOT_DEV == 0) {
printk("No ramdisk, default root is /dev/hda2\n");
ROOT_DEV = Root_HDA2;
}
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
find_and_init_phbs();
spider_init_IRQ();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
bpa_nvram_init();
}
/*
* Early initialization. Relocation is on but do not reference unbolted pages
*/
static void __init bpa_init_early(void)
{
DBG(" -> bpa_init_early()\n");
hpte_init_native();
bpa_init_iommu();
ppc64_interrupt_controller = IC_BPA_IIC;
DBG(" <- bpa_init_early()\n");
}
static int __init bpa_probe(int platform)
{
if (platform != PLATFORM_BPA)
return 0;
return 1;
}
struct machdep_calls __initdata bpa_md = {
.probe = bpa_probe,
.setup_arch = bpa_setup_arch,
.init_early = bpa_init_early,
.get_cpuinfo = bpa_get_cpuinfo,
.restart = rtas_restart,
.power_off = rtas_power_off,
.halt = rtas_halt,
.get_boot_time = rtas_get_boot_time,
.get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
.progress = bpa_progress,
};
...@@ -73,7 +73,21 @@ _GLOBAL(__970_cpu_preinit) ...@@ -73,7 +73,21 @@ _GLOBAL(__970_cpu_preinit)
_GLOBAL(__setup_cpu_power4) _GLOBAL(__setup_cpu_power4)
blr blr
_GLOBAL(__setup_cpu_be)
/* Set large page sizes LP=0: 16MB, LP=1: 64KB */
addi r3, 0, 0
ori r3, r3, HID6_LB
sldi r3, r3, 32
nor r3, r3, r3
mfspr r4, SPRN_HID6
and r4, r4, r3
addi r3, 0, 0x02000
sldi r3, r3, 32
or r4, r4, r3
mtspr SPRN_HID6, r4
blr
_GLOBAL(__setup_cpu_ppc970) _GLOBAL(__setup_cpu_ppc970)
mfspr r0,SPRN_HID0 mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */ li r11,5 /* clear DOZE and SLEEP */
......
...@@ -34,6 +34,7 @@ EXPORT_SYMBOL(cur_cpu_spec); ...@@ -34,6 +34,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
/* We only set the altivec features if the kernel was compiled with altivec /* We only set the altivec features if the kernel was compiled with altivec
...@@ -162,6 +163,16 @@ struct cpu_spec cpu_specs[] = { ...@@ -162,6 +163,16 @@ struct cpu_spec cpu_specs[] = {
__setup_cpu_power4, __setup_cpu_power4,
COMMON_PPC64_FW COMMON_PPC64_FW
}, },
{ /* BE DD1.x */
0xffff0000, 0x00700000, "Broadband Engine",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
CPU_FTR_SMT,
COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
128, 128,
__setup_cpu_be,
COMMON_PPC64_FW
},
{ /* default match */ { /* default match */
0x00000000, 0x00000000, "POWER4 (compatible)", 0x00000000, 0x00000000, "POWER4 (compatible)",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
......
...@@ -671,9 +671,6 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr) ...@@ -671,9 +671,6 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
} }
} }
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
/* /*
* Document me. * Document me.
*/ */
...@@ -772,8 +769,6 @@ static void iSeries_halt(void) ...@@ -772,8 +769,6 @@ static void iSeries_halt(void)
mf_power_off(); mf_power_off();
} }
extern void setup_default_decr(void);
/* /*
* void __init iSeries_calibrate_decr() * void __init iSeries_calibrate_decr()
* *
......
...@@ -395,6 +395,9 @@ int virt_irq_create_mapping(unsigned int real_irq) ...@@ -395,6 +395,9 @@ int virt_irq_create_mapping(unsigned int real_irq)
if (ppc64_interrupt_controller == IC_OPEN_PIC) if (ppc64_interrupt_controller == IC_OPEN_PIC)
return real_irq; /* no mapping for openpic (for now) */ return real_irq; /* no mapping for openpic (for now) */
if (ppc64_interrupt_controller == IC_BPA_IIC)
return real_irq; /* no mapping for iic either */
/* don't map interrupts < MIN_VIRT_IRQ */ /* don't map interrupts < MIN_VIRT_IRQ */
if (real_irq < MIN_VIRT_IRQ) { if (real_irq < MIN_VIRT_IRQ) {
virt_irq_to_real_map[real_irq] = real_irq; virt_irq_to_real_map[real_irq] = real_irq;
......
...@@ -78,17 +78,77 @@ extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); ...@@ -78,17 +78,77 @@ extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
extern void generic_find_legacy_serial_ports(u64 *physport, extern void generic_find_legacy_serial_ports(u64 *physport,
unsigned int *default_speed); unsigned int *default_speed);
static void maple_restart(char *cmd) static void maple_restart(char *cmd)
{ {
unsigned int maple_nvram_base;
unsigned int maple_nvram_offset;
unsigned int maple_nvram_command;
struct device_node *rtcs;
/* find NVRAM device */
rtcs = find_compatible_devices("nvram", "AMD8111");
if (rtcs && rtcs->addrs) {
maple_nvram_base = rtcs->addrs[0].address;
} else {
printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
printk(KERN_EMERG "Maple: Manual Restart Required\n");
return;
}
/* find service processor device */
rtcs = find_devices("service-processor");
if (!rtcs) {
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
printk(KERN_EMERG "Maple: Manual Restart Required\n");
return;
}
maple_nvram_offset = *(unsigned int*) get_property(rtcs,
"restart-addr", NULL);
maple_nvram_command = *(unsigned int*) get_property(rtcs,
"restart-value", NULL);
/* send command */
outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
for (;;) ;
} }
static void maple_power_off(void) static void maple_power_off(void)
{ {
unsigned int maple_nvram_base;
unsigned int maple_nvram_offset;
unsigned int maple_nvram_command;
struct device_node *rtcs;
/* find NVRAM device */
rtcs = find_compatible_devices("nvram", "AMD8111");
if (rtcs && rtcs->addrs) {
maple_nvram_base = rtcs->addrs[0].address;
} else {
printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
return;
}
/* find service processor device */
rtcs = find_devices("service-processor");
if (!rtcs) {
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
return;
}
maple_nvram_offset = *(unsigned int*) get_property(rtcs,
"power-off-addr", NULL);
maple_nvram_command = *(unsigned int*) get_property(rtcs,
"power-off-value", NULL);
/* send command */
outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
for (;;) ;
} }
static void maple_halt(void) static void maple_halt(void)
{ {
maple_power_off();
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -235,6 +295,6 @@ struct machdep_calls __initdata maple_md = { ...@@ -235,6 +295,6 @@ struct machdep_calls __initdata maple_md = {
.get_boot_time = maple_get_boot_time, .get_boot_time = maple_get_boot_time,
.set_rtc_time = maple_set_rtc_time, .set_rtc_time = maple_set_rtc_time,
.get_rtc_time = maple_get_rtc_time, .get_rtc_time = maple_get_rtc_time,
.calibrate_decr = maple_calibrate_decr, .calibrate_decr = generic_calibrate_decr,
.progress = maple_progress, .progress = maple_progress,
}; };
...@@ -42,11 +42,8 @@ ...@@ -42,11 +42,8 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
extern void setup_default_decr(void);
extern void GregorianDay(struct rtc_time * tm); extern void GregorianDay(struct rtc_time * tm);
extern unsigned long ppc_tb_freq;
extern unsigned long ppc_proc_freq;
static int maple_rtc_addr; static int maple_rtc_addr;
static int maple_clock_read(int addr) static int maple_clock_read(int addr)
...@@ -176,51 +173,3 @@ void __init maple_get_boot_time(struct rtc_time *tm) ...@@ -176,51 +173,3 @@ void __init maple_get_boot_time(struct rtc_time *tm)
maple_get_rtc_time(tm); maple_get_rtc_time(tm);
} }
/* XXX FIXME: Some sane defaults: 125 MHz timebase, 1GHz processor */
#define DEFAULT_TB_FREQ 125000000UL
#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
void __init maple_calibrate_decr(void)
{
struct device_node *cpu;
struct div_result divres;
unsigned int *fp = NULL;
/*
* The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts.
*/
cpu = of_find_node_by_type(NULL, "cpu");
ppc_tb_freq = DEFAULT_TB_FREQ;
if (cpu != 0)
fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL);
if (fp != NULL)
ppc_tb_freq = *fp;
else
printk(KERN_ERR "WARNING: Estimating decrementer frequency (not found)\n");
fp = NULL;
ppc_proc_freq = DEFAULT_PROC_FREQ;
if (cpu != 0)
fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
if (fp != NULL)
ppc_proc_freq = *fp;
else
printk(KERN_ERR "WARNING: Estimating processor frequency (not found)\n");
of_node_put(cpu);
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
ppc_tb_freq/1000000, ppc_tb_freq%1000000);
printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
ppc_proc_freq/1000000, ppc_proc_freq%1000000);
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
tb_to_xs = divres.result_low;
setup_default_decr();
}
...@@ -265,3 +265,6 @@ extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask); ...@@ -265,3 +265,6 @@ extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
/* This one gets to the primary mpic */ /* This one gets to the primary mpic */
extern int mpic_get_irq(struct pt_regs *regs); extern int mpic_get_irq(struct pt_regs *regs);
/* global mpic for pSeries */
extern struct mpic *pSeries_mpic;
This diff is collapsed.
...@@ -71,11 +71,6 @@ ...@@ -71,11 +71,6 @@
#define DBG(fmt...) #define DBG(fmt...)
#endif #endif
extern void pSeries_final_fixup(void);
extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
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 find_udbg_vterm(void);
extern void system_reset_fwnmi(void); /* from head.S */ extern void system_reset_fwnmi(void); /* from head.S */
extern void machine_check_fwnmi(void); /* from head.S */ extern void machine_check_fwnmi(void); /* from head.S */
...@@ -84,9 +79,6 @@ extern void generic_find_legacy_serial_ports(u64 *physport, ...@@ -84,9 +79,6 @@ extern void generic_find_legacy_serial_ports(u64 *physport,
int fwnmi_active; /* TRUE if an FWNMI handler is present */ int fwnmi_active; /* TRUE if an FWNMI handler is present */
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
extern void pSeries_system_reset_exception(struct pt_regs *regs); extern void pSeries_system_reset_exception(struct pt_regs *regs);
extern int pSeries_machine_check_exception(struct pt_regs *regs); extern int pSeries_machine_check_exception(struct pt_regs *regs);
...@@ -381,171 +373,6 @@ static void __init pSeries_init_early(void) ...@@ -381,171 +373,6 @@ static void __init pSeries_init_early(void)
} }
static void pSeries_progress(char *s, unsigned short hex)
{
struct device_node *root;
int width, *p;
char *os;
static int display_character, set_indicator;
static int max_width;
static DEFINE_SPINLOCK(progress_lock);
static int pending_newline = 0; /* did last write end with unprinted newline? */
if (!rtas.base)
return;
if (max_width == 0) {
if ((root = find_path_device("/rtas")) &&
(p = (unsigned int *)get_property(root,
"ibm,display-line-length",
NULL)))
max_width = *p;
else
max_width = 0x10;
display_character = rtas_token("display-character");
set_indicator = rtas_token("set-indicator");
}
if (display_character == RTAS_UNKNOWN_SERVICE) {
/* use hex display if available */
if (set_indicator != RTAS_UNKNOWN_SERVICE)
rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
return;
}
spin_lock(&progress_lock);
/*
* Last write ended with newline, but we didn't print it since
* it would just clear the bottom line of output. Print it now
* instead.
*
* If no newline is pending, print a CR to start output at the
* beginning of the line.
*/
if (pending_newline) {
rtas_call(display_character, 1, 1, NULL, '\r');
rtas_call(display_character, 1, 1, NULL, '\n');
pending_newline = 0;
} else {
rtas_call(display_character, 1, 1, NULL, '\r');
}
width = max_width;
os = s;
while (*os) {
if (*os == '\n' || *os == '\r') {
/* Blank to end of line. */
while (width-- > 0)
rtas_call(display_character, 1, 1, NULL, ' ');
/* If newline is the last character, save it
* until next call to avoid bumping up the
* display output.
*/
if (*os == '\n' && !os[1]) {
pending_newline = 1;
spin_unlock(&progress_lock);
return;
}
/* RTAS wants CR-LF, not just LF */
if (*os == '\n') {
rtas_call(display_character, 1, 1, NULL, '\r');
rtas_call(display_character, 1, 1, NULL, '\n');
} else {
/* CR might be used to re-draw a line, so we'll
* leave it alone and not add LF.
*/
rtas_call(display_character, 1, 1, NULL, *os);
}
width = max_width;
} else {
width--;
rtas_call(display_character, 1, 1, NULL, *os);
}
os++;
/* if we overwrite the screen length */
if (width <= 0)
while ((*os != 0) && (*os != '\n') && (*os != '\r'))
os++;
}
/* Blank to end of line. */
while (width-- > 0)
rtas_call(display_character, 1, 1, NULL, ' ');
spin_unlock(&progress_lock);
}
extern void setup_default_decr(void);
/* Some sane defaults: 125 MHz timebase, 1GHz processor */
#define DEFAULT_TB_FREQ 125000000UL
#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
static void __init pSeries_calibrate_decr(void)
{
struct device_node *cpu;
struct div_result divres;
unsigned int *fp;
int node_found;
/*
* The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts.
*/
cpu = of_find_node_by_type(NULL, "cpu");
ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
node_found = 0;
if (cpu != 0) {
fp = (unsigned int *)get_property(cpu, "timebase-frequency",
NULL);
if (fp != 0) {
node_found = 1;
ppc_tb_freq = *fp;
}
}
if (!node_found)
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
ppc_proc_freq = DEFAULT_PROC_FREQ;
node_found = 0;
if (cpu != 0) {
fp = (unsigned int *)get_property(cpu, "clock-frequency",
NULL);
if (fp != 0) {
node_found = 1;
ppc_proc_freq = *fp;
}
}
if (!node_found)
printk(KERN_ERR "WARNING: Estimating processor frequency "
"(not found)\n");
of_node_put(cpu);
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
ppc_tb_freq/1000000, ppc_tb_freq%1000000);
printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
ppc_proc_freq/1000000, ppc_proc_freq%1000000);
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
tb_to_xs = divres.result_low;
setup_default_decr();
}
static int pSeries_check_legacy_ioport(unsigned int baseport) static int pSeries_check_legacy_ioport(unsigned int baseport)
{ {
struct device_node *np; struct device_node *np;
...@@ -596,16 +423,17 @@ struct machdep_calls __initdata pSeries_md = { ...@@ -596,16 +423,17 @@ struct machdep_calls __initdata pSeries_md = {
.get_cpuinfo = pSeries_get_cpuinfo, .get_cpuinfo = pSeries_get_cpuinfo,
.log_error = pSeries_log_error, .log_error = pSeries_log_error,
.pcibios_fixup = pSeries_final_fixup, .pcibios_fixup = pSeries_final_fixup,
.irq_bus_setup = pSeries_irq_bus_setup,
.restart = rtas_restart, .restart = rtas_restart,
.power_off = rtas_power_off, .power_off = rtas_power_off,
.halt = rtas_halt, .halt = rtas_halt,
.panic = rtas_os_term, .panic = rtas_os_term,
.cpu_die = pSeries_mach_cpu_die, .cpu_die = pSeries_mach_cpu_die,
.get_boot_time = pSeries_get_boot_time, .get_boot_time = rtas_get_boot_time,
.get_rtc_time = pSeries_get_rtc_time, .get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = pSeries_set_rtc_time, .set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = pSeries_calibrate_decr, .calibrate_decr = generic_calibrate_decr,
.progress = pSeries_progress, .progress = rtas_progress,
.check_legacy_ioport = pSeries_check_legacy_ioport, .check_legacy_ioport = pSeries_check_legacy_ioport,
.system_reset_exception = pSeries_system_reset_exception, .system_reset_exception = pSeries_system_reset_exception,
.machine_check_exception = pSeries_machine_check_exception, .machine_check_exception = pSeries_machine_check_exception,
......
/* /*
* SMP support for pSeries machines. * SMP support for pSeries and BPA machines.
* *
* Dave Engebretsen, Peter Bergner, and * Dave Engebretsen, Peter Bergner, and
* Mike Corrigan {engebret|bergner|mikec}@us.ibm.com * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <asm/pSeries_reconfig.h> #include <asm/pSeries_reconfig.h>
#include "mpic.h" #include "mpic.h"
#include "bpa_iic.h"
#ifdef DEBUG #ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt) #define DBG(fmt...) udbg_printf(fmt)
...@@ -286,6 +287,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) ...@@ -286,6 +287,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
return 1; return 1;
} }
#ifdef CONFIG_XICS
static inline void smp_xics_do_message(int cpu, int msg) static inline void smp_xics_do_message(int cpu, int msg)
{ {
set_bit(msg, &xics_ipi_message[cpu].value); set_bit(msg, &xics_ipi_message[cpu].value);
...@@ -327,6 +329,37 @@ static void __devinit smp_xics_setup_cpu(int cpu) ...@@ -327,6 +329,37 @@ static void __devinit smp_xics_setup_cpu(int cpu)
cpu_clear(cpu, of_spin_map); cpu_clear(cpu, of_spin_map);
} }
#endif /* CONFIG_XICS */
#ifdef CONFIG_BPA_IIC
static void smp_iic_message_pass(int target, int msg)
{
unsigned int i;
if (target < NR_CPUS) {
iic_cause_IPI(target, msg);
} else {
for_each_online_cpu(i) {
if (target == MSG_ALL_BUT_SELF
&& i == smp_processor_id())
continue;
iic_cause_IPI(i, msg);
}
}
}
static int __init smp_iic_probe(void)
{
iic_request_IPIs();
return cpus_weight(cpu_possible_map);
}
static void __devinit smp_iic_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
iic_setup_cpu();
}
#endif /* CONFIG_BPA_IIC */
static DEFINE_SPINLOCK(timebase_lock); static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase = 0; static unsigned long timebase = 0;
...@@ -381,14 +414,15 @@ static int smp_pSeries_cpu_bootable(unsigned int nr) ...@@ -381,14 +414,15 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
return 1; return 1;
} }
#ifdef CONFIG_MPIC
static struct smp_ops_t pSeries_mpic_smp_ops = { static struct smp_ops_t pSeries_mpic_smp_ops = {
.message_pass = smp_mpic_message_pass, .message_pass = smp_mpic_message_pass,
.probe = smp_mpic_probe, .probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu, .kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_mpic_setup_cpu, .setup_cpu = smp_mpic_setup_cpu,
}; };
#endif
#ifdef CONFIG_XICS
static struct smp_ops_t pSeries_xics_smp_ops = { static struct smp_ops_t pSeries_xics_smp_ops = {
.message_pass = smp_xics_message_pass, .message_pass = smp_xics_message_pass,
.probe = smp_xics_probe, .probe = smp_xics_probe,
...@@ -396,6 +430,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = { ...@@ -396,6 +430,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
.setup_cpu = smp_xics_setup_cpu, .setup_cpu = smp_xics_setup_cpu,
.cpu_bootable = smp_pSeries_cpu_bootable, .cpu_bootable = smp_pSeries_cpu_bootable,
}; };
#endif
#ifdef CONFIG_BPA_IIC
static struct smp_ops_t bpa_iic_smp_ops = {
.message_pass = smp_iic_message_pass,
.probe = smp_iic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_iic_setup_cpu,
.cpu_bootable = smp_pSeries_cpu_bootable,
};
#endif
/* This is called very early */ /* This is called very early */
void __init smp_init_pSeries(void) void __init smp_init_pSeries(void)
...@@ -404,10 +448,25 @@ void __init smp_init_pSeries(void) ...@@ -404,10 +448,25 @@ void __init smp_init_pSeries(void)
DBG(" -> smp_init_pSeries()\n"); DBG(" -> smp_init_pSeries()\n");
if (ppc64_interrupt_controller == IC_OPEN_PIC) switch (ppc64_interrupt_controller) {
#ifdef CONFIG_MPIC
case IC_OPEN_PIC:
smp_ops = &pSeries_mpic_smp_ops; smp_ops = &pSeries_mpic_smp_ops;
else break;
#endif
#ifdef CONFIG_XICS
case IC_PPC_XIC:
smp_ops = &pSeries_xics_smp_ops; smp_ops = &pSeries_xics_smp_ops;
break;
#endif
#ifdef CONFIG_BPA_IIC
case IC_BPA_IIC:
smp_ops = &bpa_iic_smp_ops;
break;
#endif
default:
panic("Invalid interrupt controller");
}
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
smp_ops->cpu_disable = pSeries_cpu_disable; smp_ops->cpu_disable = pSeries_cpu_disable;
......
...@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) ...@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) list_for_each_entry(dev, &bus->devices, bus_list)
ppc_md.iommu_dev_setup(dev); ppc_md.iommu_dev_setup(dev);
if (ppc_md.irq_bus_setup)
ppc_md.irq_bus_setup(bus);
if (!pci_probe_only) if (!pci_probe_only)
return; return;
......
...@@ -40,10 +40,14 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev); ...@@ -40,10 +40,14 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev);
void pci_addr_cache_insert_device(struct pci_dev *dev); void pci_addr_cache_insert_device(struct pci_dev *dev);
void pci_addr_cache_remove_device(struct pci_dev *dev); void pci_addr_cache_remove_device(struct pci_dev *dev);
/* From pSeries_pci.h */ /* From rtas_pci.h */
void init_pci_config_tokens (void); void init_pci_config_tokens (void);
unsigned long get_phb_buid (struct device_node *); unsigned long get_phb_buid (struct device_node *);
/* From pSeries_pci.h */
extern void pSeries_final_fixup(void);
extern void pSeries_irq_bus_setup(struct pci_bus *bus);
extern unsigned long pci_probe_only; extern unsigned long pci_probe_only;
extern unsigned long pci_assign_all_buses; extern unsigned long pci_assign_all_buses;
extern int pci_read_irq_line(struct pci_dev *pci_dev); extern int pci_read_irq_line(struct pci_dev *pci_dev);
......
...@@ -40,11 +40,6 @@ ...@@ -40,11 +40,6 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
extern void setup_default_decr(void);
extern unsigned long ppc_tb_freq;
extern unsigned long ppc_proc_freq;
/* Apparently the RTC stores seconds since 1 Jan 1904 */ /* Apparently the RTC stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800 #define RTC_OFFSET 2082844800
...@@ -161,8 +156,7 @@ void __init pmac_get_boot_time(struct rtc_time *tm) ...@@ -161,8 +156,7 @@ void __init pmac_get_boot_time(struct rtc_time *tm)
/* /*
* Query the OF and get the decr frequency. * Query the OF and get the decr frequency.
* This was taken from the pmac time_init() when merging the prep/pmac * FIXME: merge this with generic_calibrate_decr
* time functions.
*/ */
void __init pmac_calibrate_decr(void) void __init pmac_calibrate_decr(void)
{ {
......
...@@ -53,7 +53,7 @@ static int __init proc_ppc64_create(void) ...@@ -53,7 +53,7 @@ static int __init proc_ppc64_create(void)
if (!root) if (!root)
return 1; return 1;
if (!(systemcfg->platform & PLATFORM_PSERIES)) if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_BPA)))
return 0; return 0;
if (!proc_mkdir("rtas", root)) if (!proc_mkdir("rtas", root))
......
...@@ -1915,9 +1915,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long ...@@ -1915,9 +1915,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
prom_send_capabilities(); prom_send_capabilities();
/* /*
* On pSeries, copy the CPU hold code * On pSeries and BPA, copy the CPU hold code
*/ */
if (RELOC(of_platform) & PLATFORM_PSERIES) if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))
copy_and_flush(0, KERNELBASE - offset, 0x100, 0); copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
/* /*
......
...@@ -371,11 +371,11 @@ static ssize_t ppc_rtas_progress_write(struct file *file, ...@@ -371,11 +371,11 @@ static ssize_t ppc_rtas_progress_write(struct file *file,
/* Lets see if the user passed hexdigits */ /* Lets see if the user passed hexdigits */
hex = simple_strtoul(progress_led, NULL, 10); hex = simple_strtoul(progress_led, NULL, 10);
ppc_md.progress ((char *)progress_led, hex); rtas_progress ((char *)progress_led, hex);
return count; return count;
/* clear the line */ /* clear the line */
/* ppc_md.progress(" ", 0xffff);*/ /* rtas_progress(" ", 0xffff);*/
} }
/* ****************************************************************** */ /* ****************************************************************** */
static int ppc_rtas_progress_show(struct seq_file *m, void *v) static int ppc_rtas_progress_show(struct seq_file *m, void *v)
......
...@@ -91,6 +91,123 @@ call_rtas_display_status_delay(unsigned char c) ...@@ -91,6 +91,123 @@ call_rtas_display_status_delay(unsigned char c)
} }
} }
void
rtas_progress(char *s, unsigned short hex)
{
struct device_node *root;
int width, *p;
char *os;
static int display_character, set_indicator;
static int display_width, display_lines, *row_width, form_feed;
static DEFINE_SPINLOCK(progress_lock);
static int current_line;
static int pending_newline = 0; /* did last write end with unprinted newline? */
if (!rtas.base)
return;
if (display_width == 0) {
display_width = 0x10;
if ((root = find_path_device("/rtas"))) {
if ((p = (unsigned int *)get_property(root,
"ibm,display-line-length", NULL)))
display_width = *p;
if ((p = (unsigned int *)get_property(root,
"ibm,form-feed", NULL)))
form_feed = *p;
if ((p = (unsigned int *)get_property(root,
"ibm,display-number-of-lines", NULL)))
display_lines = *p;
row_width = (unsigned int *)get_property(root,
"ibm,display-truncation-length", NULL);
}
display_character = rtas_token("display-character");
set_indicator = rtas_token("set-indicator");
}
if (display_character == RTAS_UNKNOWN_SERVICE) {
/* use hex display if available */
if (set_indicator != RTAS_UNKNOWN_SERVICE)
rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
return;
}
spin_lock(&progress_lock);
/*
* Last write ended with newline, but we didn't print it since
* it would just clear the bottom line of output. Print it now
* instead.
*
* If no newline is pending and form feed is supported, clear the
* display with a form feed; otherwise, print a CR to start output
* at the beginning of the line.
*/
if (pending_newline) {
rtas_call(display_character, 1, 1, NULL, '\r');
rtas_call(display_character, 1, 1, NULL, '\n');
pending_newline = 0;
} else {
current_line = 0;
if (form_feed)
rtas_call(display_character, 1, 1, NULL,
(char)form_feed);
else
rtas_call(display_character, 1, 1, NULL, '\r');
}
if (row_width)
width = row_width[current_line];
else
width = display_width;
os = s;
while (*os) {
if (*os == '\n' || *os == '\r') {
/* If newline is the last character, save it
* until next call to avoid bumping up the
* display output.
*/
if (*os == '\n' && !os[1]) {
pending_newline = 1;
current_line++;
if (current_line > display_lines-1)
current_line = display_lines-1;
spin_unlock(&progress_lock);
return;
}
/* RTAS wants CR-LF, not just LF */
if (*os == '\n') {
rtas_call(display_character, 1, 1, NULL, '\r');
rtas_call(display_character, 1, 1, NULL, '\n');
} else {
/* CR might be used to re-draw a line, so we'll
* leave it alone and not add LF.
*/
rtas_call(display_character, 1, 1, NULL, *os);
}
if (row_width)
width = row_width[current_line];
else
width = display_width;
} else {
width--;
rtas_call(display_character, 1, 1, NULL, *os);
}
os++;
/* if we overwrite the screen length */
if (width <= 0)
while ((*os != 0) && (*os != '\n') && (*os != '\r'))
os++;
}
spin_unlock(&progress_lock);
}
int int
rtas_token(const char *service) rtas_token(const char *service)
{ {
...@@ -425,8 +542,8 @@ rtas_flash_firmware(void) ...@@ -425,8 +542,8 @@ rtas_flash_firmware(void)
printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
printk(KERN_ALERT "FLASH: performing flash and reboot\n"); printk(KERN_ALERT "FLASH: performing flash and reboot\n");
ppc_md.progress("Flashing \n", 0x0); rtas_progress("Flashing \n", 0x0);
ppc_md.progress("Please Wait... ", 0x0); rtas_progress("Please Wait... ", 0x0);
printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
switch (status) { /* should only get "bad" status */ switch (status) { /* should only get "bad" status */
......
This diff is collapsed.
...@@ -301,7 +301,7 @@ void iSeries_get_boot_time(struct rtc_time *tm) ...@@ -301,7 +301,7 @@ void iSeries_get_boot_time(struct rtc_time *tm)
#ifdef CONFIG_PPC_RTAS #ifdef CONFIG_PPC_RTAS
#define MAX_RTC_WAIT 5000 /* 5 sec */ #define MAX_RTC_WAIT 5000 /* 5 sec */
#define RTAS_CLOCK_BUSY (-2) #define RTAS_CLOCK_BUSY (-2)
void pSeries_get_boot_time(struct rtc_time *rtc_tm) void rtas_get_boot_time(struct rtc_time *rtc_tm)
{ {
int ret[8]; int ret[8];
int error, wait_time; int error, wait_time;
...@@ -336,7 +336,7 @@ void pSeries_get_boot_time(struct rtc_time *rtc_tm) ...@@ -336,7 +336,7 @@ void pSeries_get_boot_time(struct rtc_time *rtc_tm)
* and if a delay is needed to read the clock. In this case we just * and if a delay is needed to read the clock. In this case we just
* silently return without updating rtc_tm. * silently return without updating rtc_tm.
*/ */
void pSeries_get_rtc_time(struct rtc_time *rtc_tm) void rtas_get_rtc_time(struct rtc_time *rtc_tm)
{ {
int ret[8]; int ret[8];
int error, wait_time; int error, wait_time;
...@@ -371,7 +371,7 @@ void pSeries_get_rtc_time(struct rtc_time *rtc_tm) ...@@ -371,7 +371,7 @@ void pSeries_get_rtc_time(struct rtc_time *rtc_tm)
rtc_tm->tm_year = ret[0] - 1900; rtc_tm->tm_year = ret[0] - 1900;
} }
int pSeries_set_rtc_time(struct rtc_time *tm) int rtas_set_rtc_time(struct rtc_time *tm)
{ {
int error, wait_time; int error, wait_time;
unsigned long max_wait_tb; unsigned long max_wait_tb;
......
...@@ -344,6 +344,7 @@ static void __init setup_cpu_maps(void) ...@@ -344,6 +344,7 @@ static void __init setup_cpu_maps(void)
extern struct machdep_calls pSeries_md; extern struct machdep_calls pSeries_md;
extern struct machdep_calls pmac_md; extern struct machdep_calls pmac_md;
extern struct machdep_calls maple_md; extern struct machdep_calls maple_md;
extern struct machdep_calls bpa_md;
/* Ultimately, stuff them in an elf section like initcalls... */ /* Ultimately, stuff them in an elf section like initcalls... */
static struct machdep_calls __initdata *machines[] = { static struct machdep_calls __initdata *machines[] = {
...@@ -356,6 +357,9 @@ static struct machdep_calls __initdata *machines[] = { ...@@ -356,6 +357,9 @@ static struct machdep_calls __initdata *machines[] = {
#ifdef CONFIG_PPC_MAPLE #ifdef CONFIG_PPC_MAPLE
&maple_md, &maple_md,
#endif /* CONFIG_PPC_MAPLE */ #endif /* CONFIG_PPC_MAPLE */
#ifdef CONFIG_PPC_BPA
&bpa_md,
#endif
NULL NULL
}; };
...@@ -679,6 +683,12 @@ void machine_restart(char *cmd) ...@@ -679,6 +683,12 @@ void machine_restart(char *cmd)
if (ppc_md.nvram_sync) if (ppc_md.nvram_sync)
ppc_md.nvram_sync(); ppc_md.nvram_sync();
ppc_md.restart(cmd); ppc_md.restart(cmd);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
printk(KERN_EMERG "System Halted, OK to turn off power\n");
local_irq_disable();
while (1) ;
} }
EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_restart);
...@@ -688,6 +698,12 @@ void machine_power_off(void) ...@@ -688,6 +698,12 @@ void machine_power_off(void)
if (ppc_md.nvram_sync) if (ppc_md.nvram_sync)
ppc_md.nvram_sync(); ppc_md.nvram_sync();
ppc_md.power_off(); ppc_md.power_off();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
printk(KERN_EMERG "System Halted, OK to turn off power\n");
local_irq_disable();
while (1) ;
} }
EXPORT_SYMBOL(machine_power_off); EXPORT_SYMBOL(machine_power_off);
...@@ -697,13 +713,16 @@ void machine_halt(void) ...@@ -697,13 +713,16 @@ void machine_halt(void)
if (ppc_md.nvram_sync) if (ppc_md.nvram_sync)
ppc_md.nvram_sync(); ppc_md.nvram_sync();
ppc_md.halt(); ppc_md.halt();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
printk(KERN_EMERG "System Halted, OK to turn off power\n");
local_irq_disable();
while (1) ;
} }
EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_halt);
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
static int ppc64_panic_event(struct notifier_block *this, static int ppc64_panic_event(struct notifier_block *this,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
...@@ -1080,11 +1099,11 @@ void __init setup_arch(char **cmdline_p) ...@@ -1080,11 +1099,11 @@ void __init setup_arch(char **cmdline_p)
static void ppc64_do_msg(unsigned int src, const char *msg) static void ppc64_do_msg(unsigned int src, const char *msg)
{ {
if (ppc_md.progress) { if (ppc_md.progress) {
char buf[32]; char buf[128];
sprintf(buf, "%08x \n", src); sprintf(buf, "%08X\n", src);
ppc_md.progress(buf, 0); ppc_md.progress(buf, 0);
sprintf(buf, "%-16s", msg); snprintf(buf, 128, "%s", msg);
ppc_md.progress(buf, 0); ppc_md.progress(buf, 0);
} }
} }
...@@ -1118,7 +1137,7 @@ void ppc64_dump_msg(unsigned int src, const char *msg) ...@@ -1118,7 +1137,7 @@ void ppc64_dump_msg(unsigned int src, const char *msg)
} }
/* This should only be called on processor 0 during calibrate decr */ /* This should only be called on processor 0 during calibrate decr */
void setup_default_decr(void) void __init setup_default_decr(void)
{ {
struct paca_struct *lpaca = get_paca(); struct paca_struct *lpaca = get_paca();
......
...@@ -71,7 +71,7 @@ void smp_call_function_interrupt(void); ...@@ -71,7 +71,7 @@ void smp_call_function_interrupt(void);
int smt_enabled_at_boot = 1; int smt_enabled_at_boot = 1;
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_MPIC
void smp_mpic_message_pass(int target, int msg) void smp_mpic_message_pass(int target, int msg)
{ {
/* make sure we're sending something that translates to an IPI */ /* make sure we're sending something that translates to an IPI */
...@@ -128,7 +128,7 @@ void __devinit smp_generic_kick_cpu(int nr) ...@@ -128,7 +128,7 @@ void __devinit smp_generic_kick_cpu(int nr)
smp_mb(); smp_mb();
} }
#endif /* CONFIG_PPC_MULTIPLATFORM */ #endif /* CONFIG_MPIC */
static void __init smp_space_timers(unsigned int max_cpus) static void __init smp_space_timers(unsigned int max_cpus)
{ {
......
/*
* External Interrupt Controller on Spider South Bridge
*
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
*
* Author: Arnd Bergmann <arndb@de.ibm.com>
*
* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/io.h>
#include "bpa_iic.h"
/* register layout taken from Spider spec, table 7.4-4 */
enum {
TIR_DEN = 0x004, /* Detection Enable Register */
TIR_MSK = 0x084, /* Mask Level Register */
TIR_EDC = 0x0c0, /* Edge Detection Clear Register */
TIR_PNDA = 0x100, /* Pending Register A */
TIR_PNDB = 0x104, /* Pending Register B */
TIR_CS = 0x144, /* Current Status Register */
TIR_LCSA = 0x150, /* Level Current Status Register A */
TIR_LCSB = 0x154, /* Level Current Status Register B */
TIR_LCSC = 0x158, /* Level Current Status Register C */
TIR_LCSD = 0x15c, /* Level Current Status Register D */
TIR_CFGA = 0x200, /* Setting Register A0 */
TIR_CFGB = 0x204, /* Setting Register B0 */
/* 0x208 ... 0x3ff Setting Register An/Bn */
TIR_PPNDA = 0x400, /* Packet Pending Register A */
TIR_PPNDB = 0x404, /* Packet Pending Register B */
TIR_PIERA = 0x408, /* Packet Output Error Register A */
TIR_PIERB = 0x40c, /* Packet Output Error Register B */
TIR_PIEN = 0x444, /* Packet Output Enable Register */
TIR_PIPND = 0x454, /* Packet Output Pending Register */
TIRDID = 0x484, /* Spider Device ID Register */
REISTIM = 0x500, /* Reissue Command Timeout Time Setting */
REISTIMEN = 0x504, /* Reissue Command Timeout Setting */
REISWAITEN = 0x508, /* Reissue Wait Control*/
};
static void __iomem *spider_pics[4];
static void __iomem *spider_get_pic(int irq)
{
int node = irq / IIC_NODE_STRIDE;
irq %= IIC_NODE_STRIDE;
if (irq >= IIC_EXT_OFFSET &&
irq < IIC_EXT_OFFSET + IIC_NUM_EXT &&
spider_pics)
return spider_pics[node];
return NULL;
}
static int spider_get_nr(unsigned int irq)
{
return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET;
}
static void __iomem *spider_get_irq_config(int irq)
{
void __iomem *pic;
pic = spider_get_pic(irq);
return pic + TIR_CFGA + 8 * spider_get_nr(irq);
}
static void spider_enable_irq(unsigned int irq)
{
void __iomem *cfg = spider_get_irq_config(irq);
irq = spider_get_nr(irq);
out_be32(cfg, in_be32(cfg) | 0x3107000eu);
out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
}
static void spider_disable_irq(unsigned int irq)
{
void __iomem *cfg = spider_get_irq_config(irq);
irq = spider_get_nr(irq);
out_be32(cfg, in_be32(cfg) & ~0x30000000u);
}
static unsigned int spider_startup_irq(unsigned int irq)
{
spider_enable_irq(irq);
return 0;
}
static void spider_shutdown_irq(unsigned int irq)
{
spider_disable_irq(irq);
}
static void spider_end_irq(unsigned int irq)
{
spider_enable_irq(irq);
}
static void spider_ack_irq(unsigned int irq)
{
spider_disable_irq(irq);
iic_local_enable();
}
static struct hw_interrupt_type spider_pic = {
.typename = " SPIDER ",
.startup = spider_startup_irq,
.shutdown = spider_shutdown_irq,
.enable = spider_enable_irq,
.disable = spider_disable_irq,
.ack = spider_ack_irq,
.end = spider_end_irq,
};
int spider_get_irq(unsigned long int_pending)
{
void __iomem *regs = spider_get_pic(int_pending);
unsigned long cs;
int irq;
cs = in_be32(regs + TIR_CS);
irq = cs >> 24;
if (irq != 63)
return irq;
return -1;
}
void spider_init_IRQ(void)
{
int node;
struct device_node *dn;
unsigned int *property;
long spiderpic;
int n;
/* FIXME: detect multiple PICs as soon as the device tree has them */
for (node = 0; node < 1; node++) {
dn = of_find_node_by_path("/");
n = prom_n_addr_cells(dn);
property = (unsigned int *) get_property(dn,
"platform-spider-pic", NULL);
if (!property)
continue;
for (spiderpic = 0; n > 0; --n)
spiderpic = (spiderpic << 32) + *property++;
printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
for (n = 0; n < IIC_NUM_EXT; n++) {
int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
get_irq_desc(irq)->handler = &spider_pic;
/* do not mask any interrupts because of level */
out_be32(spider_pics[node] + TIR_MSK, 0x0);
/* disable edge detection clear */
/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
/* enable interrupt packets to be output */
out_be32(spider_pics[node] + TIR_PIEN,
in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
/* Enable the interrupt detection enable bit. Do this last! */
out_be32(spider_pics[node] + TIR_DEN,
in_be32(spider_pics[node] +TIR_DEN) | 0x1);
}
}
}
...@@ -107,6 +107,9 @@ void ppc_adjtimex(void); ...@@ -107,6 +107,9 @@ void ppc_adjtimex(void);
static unsigned adjusting_time = 0; static unsigned adjusting_time = 0;
unsigned long ppc_proc_freq;
unsigned long ppc_tb_freq;
static __inline__ void timer_check_rtc(void) static __inline__ void timer_check_rtc(void)
{ {
/* /*
...@@ -472,6 +475,66 @@ int do_settimeofday(struct timespec *tv) ...@@ -472,6 +475,66 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday); EXPORT_SYMBOL(do_settimeofday);
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
void __init generic_calibrate_decr(void)
{
struct device_node *cpu;
struct div_result divres;
unsigned int *fp;
int node_found;
/*
* The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts.
*/
cpu = of_find_node_by_type(NULL, "cpu");
ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
node_found = 0;
if (cpu != 0) {
fp = (unsigned int *)get_property(cpu, "timebase-frequency",
NULL);
if (fp != 0) {
node_found = 1;
ppc_tb_freq = *fp;
}
}
if (!node_found)
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
ppc_proc_freq = DEFAULT_PROC_FREQ;
node_found = 0;
if (cpu != 0) {
fp = (unsigned int *)get_property(cpu, "clock-frequency",
NULL);
if (fp != 0) {
node_found = 1;
ppc_proc_freq = *fp;
}
}
if (!node_found)
printk(KERN_ERR "WARNING: Estimating processor frequency "
"(not found)\n");
of_node_put(cpu);
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
ppc_tb_freq/1000000, ppc_tb_freq%1000000);
printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
ppc_proc_freq/1000000, ppc_proc_freq%1000000);
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
tb_to_xs = divres.result_low;
setup_default_decr();
}
#endif
void __init time_init(void) void __init time_init(void)
{ {
/* This function is only called on the boot processor */ /* This function is only called on the boot processor */
......
...@@ -126,6 +126,10 @@ int die(const char *str, struct pt_regs *regs, long err) ...@@ -126,6 +126,10 @@ int die(const char *str, struct pt_regs *regs, long err)
printk("POWERMAC "); printk("POWERMAC ");
nl = 1; nl = 1;
break; break;
case PLATFORM_BPA:
printk("BPA ");
nl = 1;
break;
} }
if (nl) if (nl)
printk("\n"); printk("\n");
......
...@@ -414,6 +414,16 @@ config WATCHDOG_RIO ...@@ -414,6 +414,16 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter. can be changed with a boot-time parameter.
# ppc64 RTAS watchdog
config WATCHDOG_RTAS
tristate "RTAS watchdog"
depends on WATCHDOG && PPC_RTAS
help
This driver adds watchdog support for the RTAS watchdog.
To compile this driver as a module, choose M here. The module
will be called wdrtas.
# #
# ISA-based Watchdog Cards # ISA-based Watchdog Cards
# #
......
...@@ -33,6 +33,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o ...@@ -33,6 +33,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
# Only one watchdog can succeed. We probe the hardware watchdog # Only one watchdog can succeed. We probe the hardware watchdog
# drivers first, then the softdog driver. This means if your hardware # drivers first, then the softdog driver. This means if your hardware
......
This diff is collapsed.
...@@ -76,6 +76,7 @@ struct machdep_calls { ...@@ -76,6 +76,7 @@ struct machdep_calls {
void (*tce_flush)(struct iommu_table *tbl); void (*tce_flush)(struct iommu_table *tbl);
void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_dev_setup)(struct pci_dev *dev);
void (*iommu_bus_setup)(struct pci_bus *bus); void (*iommu_bus_setup)(struct pci_bus *bus);
void (*irq_bus_setup)(struct pci_bus *bus);
int (*probe)(int platform); int (*probe)(int platform);
void (*setup_arch)(void); void (*setup_arch)(void);
......
...@@ -47,9 +47,10 @@ ...@@ -47,9 +47,10 @@
#define SLB_VSID_KS ASM_CONST(0x0000000000000800) #define SLB_VSID_KS ASM_CONST(0x0000000000000800)
#define SLB_VSID_KP ASM_CONST(0x0000000000000400) #define SLB_VSID_KP ASM_CONST(0x0000000000000400)
#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ #define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage 16M */ #define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage */
#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ #define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
#define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */
#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C) #define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C)
#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS) #define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS)
......
...@@ -70,6 +70,7 @@ extern struct nvram_partition *nvram_find_partition(int sig, const char *name); ...@@ -70,6 +70,7 @@ extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
extern int pSeries_nvram_init(void); extern int pSeries_nvram_init(void);
extern int pmac_nvram_init(void); extern int pmac_nvram_init(void);
extern int bpa_nvram_init(void);
/* PowerMac specific nvram stuffs */ /* PowerMac specific nvram stuffs */
......
...@@ -138,8 +138,16 @@ ...@@ -138,8 +138,16 @@
#define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */ #define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */
#define SPRN_HID4 0x3F4 /* 970 HID4 */ #define SPRN_HID4 0x3F4 /* 970 HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */ #define SPRN_HID5 0x3F6 /* 970 HID5 */
#define SPRN_TSC 0x3FD /* Thread switch control */ #define SPRN_HID6 0x3F9 /* BE HID 6 */
#define SPRN_TST 0x3FC /* Thread switch timeout */ #define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
#define SPRN_TSCR 0x399 /* Thread switch control on BE */
#define SPRN_TTR 0x39A /* Thread switch timeout on BE */
#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */
#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */
#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */
#define SPRN_TSC 0x3FD /* Thread switch control on others */
#define SPRN_TST 0x3FC /* Thread switch timeout on others */
#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */ #define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
#define SPRN_LR 0x008 /* Link Register */ #define SPRN_LR 0x008 /* Link Register */
#define SPRN_PIR 0x3FF /* Processor Identification Register */ #define SPRN_PIR 0x3FF /* Processor Identification Register */
...@@ -259,6 +267,7 @@ ...@@ -259,6 +267,7 @@
#define PV_970FX 0x003C #define PV_970FX 0x003C
#define PV_630 0x0040 #define PV_630 0x0040
#define PV_630p 0x0041 #define PV_630p 0x0041
#define PV_BE 0x0070
/* Platforms supported by PPC64 */ /* Platforms supported by PPC64 */
#define PLATFORM_PSERIES 0x0100 #define PLATFORM_PSERIES 0x0100
...@@ -267,6 +276,7 @@ ...@@ -267,6 +276,7 @@
#define PLATFORM_LPAR 0x0001 #define PLATFORM_LPAR 0x0001
#define PLATFORM_POWERMAC 0x0400 #define PLATFORM_POWERMAC 0x0400
#define PLATFORM_MAPLE 0x0500 #define PLATFORM_MAPLE 0x0500
#define PLATFORM_BPA 0x1000
/* Compatibility with drivers coming from PPC32 world */ /* Compatibility with drivers coming from PPC32 world */
#define _machine (systemcfg->platform) #define _machine (systemcfg->platform)
...@@ -278,6 +288,7 @@ ...@@ -278,6 +288,7 @@
#define IC_INVALID 0 #define IC_INVALID 0
#define IC_OPEN_PIC 1 #define IC_OPEN_PIC 1
#define IC_PPC_XIC 2 #define IC_PPC_XIC 2
#define IC_BPA_IIC 3
#define XGLUE(a,b) a##b #define XGLUE(a,b) a##b
#define GLUE(a,b) XGLUE(a,b) #define GLUE(a,b) XGLUE(a,b)
......
...@@ -186,8 +186,14 @@ extern int rtas_get_sensor(int sensor, int index, int *state); ...@@ -186,8 +186,14 @@ extern int rtas_get_sensor(int sensor, int index, int *state);
extern int rtas_get_power_level(int powerdomain, int *level); extern int rtas_get_power_level(int powerdomain, int *level);
extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
extern int rtas_set_indicator(int indicator, int index, int new_value); extern int rtas_set_indicator(int indicator, int index, int new_value);
extern void rtas_progress(char *s, unsigned short hex);
extern void rtas_initialize(void); extern void rtas_initialize(void);
struct rtc_time;
extern void rtas_get_boot_time(struct rtc_time *rtc_time);
extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
/* Given an RTAS status code of 9900..9905 compute the hinted delay */ /* Given an RTAS status code of 9900..9905 compute the hinted delay */
unsigned int rtas_extended_busy_delay_time(int status); unsigned int rtas_extended_busy_delay_time(int status);
static inline int rtas_is_extended_busy(int status) static inline int rtas_is_extended_busy(int status)
......
...@@ -85,6 +85,14 @@ extern void smp_generic_take_timebase(void); ...@@ -85,6 +85,14 @@ extern void smp_generic_take_timebase(void);
extern struct smp_ops_t *smp_ops; extern struct smp_ops_t *smp_ops;
#ifdef CONFIG_PPC_PSERIES
void vpa_init(int cpu);
#else
static inline void vpa_init(int cpu)
{
}
#endif /* CONFIG_PPC_PSERIES */
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* !(_PPC64_SMP_H) */ #endif /* !(_PPC64_SMP_H) */
......
...@@ -34,6 +34,15 @@ struct rtc_time; ...@@ -34,6 +34,15 @@ struct rtc_time;
extern void to_tm(int tim, struct rtc_time * tm); extern void to_tm(int tim, struct rtc_time * tm);
extern time_t last_rtc_update; extern time_t last_rtc_update;
void generic_calibrate_decr(void);
void setup_default_decr(void);
/* Some sane defaults: 125 MHz timebase, 1GHz processor */
extern unsigned long ppc_proc_freq;
#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
extern unsigned long ppc_tb_freq;
#define DEFAULT_TB_FREQ 125000000UL
/* /*
* By putting all of this stuff into a single struct we * By putting all of this stuff into a single struct we
* reduce the number of cache lines touched by do_gettimeofday. * reduce the number of cache lines touched by do_gettimeofday.
......
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