Commit 37d9716b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://ppc.bkbits.net/for-linus-ppc

into home.osdl.org:/home/torvalds/v2.5/linux
parents 5b5f13cd 522b1302
......@@ -592,6 +592,11 @@ config PPC_PMAC
depends on PPC_MULTIPLATFORM
default y
config PPC_PMAC64
bool
depends on PPC_PMAC && POWER4
default y
config PPC_PREP
bool
depends on PPC_MULTIPLATFORM
......
......@@ -2239,7 +2239,7 @@ probe_motherboard(void)
break;
#else /* CONFIG_POWER4 */
case macio_keylargo2:
pmac_mb.model_id = PMAC_TYPE_POWERMAC_G5;
pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
pmac_mb.model_name = "Unknown G5";
pmac_mb.features = g5_features;
break;
......
......@@ -60,7 +60,7 @@ config PPC_ISERIES
bool "iSeries"
config PPC_PSERIES
bool "pSeries"
bool "pSeries / PowerMac G5"
endchoice
......@@ -72,6 +72,11 @@ config PPC64
bool
default y
config PPC_OF
depends on PPC_PSERIES
bool
default y
# VMX is pSeries only for now until somebody writes the iSeries
# exception vectors for it
config ALTIVEC
......@@ -79,6 +84,22 @@ config ALTIVEC
depends on PPC_PSERIES
default y
config PPC_PMAC
depends on PPC_PSERIES
bool "Apple PowerMac G5 support"
config PPC_PMAC64
bool
depends on PPC_PMAC
default y
config BOOTX_TEXT
bool "Support for early boot text console"
depends PPC_OF
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires an Open Firmware compatible video card.
config POWER4_ONLY
bool "Optimize for POWER4"
default n
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,9 +10,11 @@ obj-y := setup.o entry.o traps.o irq.o idle.o \
align.o semaphore.o bitops.o stab.o pacaData.o \
udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
ptrace32.o signal32.o pmc.o rtc.o init_task.o \
lmb.o cputable.o
lmb.o cputable.o cpu_setup_power4.o idle_power4.o
obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o
obj-$(CONFIG_PPC_OF) += of_device.o
obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o pci_dma_direct.o
ifdef CONFIG_PPC_ISERIES
obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \
......@@ -27,7 +29,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
proc_pmc.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o nvram.o rtasd.o ras.o \
eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
open_pic.o xics.o pSeries_htab.o rtas.o \
chrp_setup.o i8259.o prom.o vio.o
......@@ -39,6 +41,14 @@ obj-$(CONFIG_PPC_RTAS) += rtas-proc.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_VIOPATH) += viopath.o
obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_BOOTX_TEXT) += btext.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
ifdef CONFIG_SMP
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
endif
CFLAGS_ioctl32.o += -Ifs/
This diff is collapsed.
......@@ -67,9 +67,10 @@
void chrp_progress(char *, unsigned short);
extern void openpic_init_IRQ(void);
extern void pSeries_init_openpic(void);
extern void find_and_init_phbs(void);
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);
......@@ -178,6 +179,10 @@ chrp_setup_arch(void)
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
#ifdef CONFIG_PPC_PSERIES
pSeries_nvram_init();
#endif
}
void __init
......@@ -252,7 +257,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo;
if(naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = openpic_init_IRQ;
ppc_md.init_IRQ = pSeries_init_openpic;
ppc_md.get_irq = openpic_get_irq;
} else {
ppc_md.init_IRQ = xics_init_IRQ;
......@@ -261,6 +266,8 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.init = chrp_init2;
ppc_md.pcibios_fixup = pSeries_final_fixup;
ppc_md.restart = rtas_restart;
ppc_md.power_off = rtas_power_off;
ppc_md.halt = rtas_halt;
......@@ -272,9 +279,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.progress = chrp_progress;
ppc_md.nvram_read = pSeries_nvram_read;
ppc_md.nvram_write = pSeries_nvram_write;
/* 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().
......
/*
* This file contains low level CPU setup functions.
* Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>
#include <asm/cache.h>
_GLOBAL(__power4_cpu_preinit)
/*
* On the PPC970, we have to turn off real-mode cache inhibit
* early, before we first turn the MMU off.
*/
mfspr r0,SPRN_PVR
srwi r0,r0,16
cmpwi r0,0x39
bnelr
li r0,0
sync
mtspr SPRN_HID4,r0
isync
sync
mtspr SPRN_HID5,r0
isync
mfspr r0,SPRN_HID1
li r11,0x1200 /* enable i-fetch cacheability */
sldi r11,r11,44 /* and prefetch */
or r0,r0,r11
mtspr SPRN_HID1,r0
mtspr SPRN_HID1,r0
isync
li r0,0
sync
mtspr SPRN_HIOR,0 /* Clear interrupt prefix */
isync
blr
_GLOBAL(__setup_cpu_power4)
blr
_GLOBAL(__setup_cpu_ppc970)
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
rldimi r0,r11,52,8 /* set NAP and DPM */
mtspr SPRN_HID0,r0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
sync
isync
blr
/* Definitions for the table use to save CPU states */
#define CS_HID0 0
#define CS_HID1 8
#define CS_HID4 16
#define CS_HID5 24
#define CS_SIZE 32
.data
.balign L1_CACHE_BYTES,0
cpu_state_storage:
.space CS_SIZE
.balign L1_CACHE_BYTES,0
.text
/* Called in normal context to backup CPU 0 state. This
* does not include cache settings. This function is also
* called for machine sleep. This does not include the MMU
* setup, BATs, etc... but rather the "special" registers
* like HID0, HID1, HID4, etc...
*/
_GLOBAL(__save_cpu_setup)
/* Some CR fields are volatile, we back it up all */
mfcr r7
/* Get storage ptr */
LOADADDR(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
srwi r0,r0,16
cmpwi r0,0x39
bne 1f
/* Save HID0,1,4 and 5 */
mfspr r3,SPRN_HID0
std r3,CS_HID0(r5)
mfspr r3,SPRN_HID1
std r3,CS_HID1(r5)
mfspr r3,SPRN_HID4
std r3,CS_HID4(r5)
mfspr r3,SPRN_HID5
std r3,CS_HID5(r5)
1:
mtcr r7
blr
/* Called with no MMU context (typically MSR:IR/DR off) to
* restore CPU state as backed up by the previous
* function. This does not include cache setting
*/
_GLOBAL(__restore_cpu_setup)
/* Get storage ptr (FIXME when using anton reloc as we
* are running with translation disabled here
*/
LOADADDR(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
srwi r0,r0,16
cmpwi r0,0x39
bne 1f
/* Clear interrupt prefix */
li r0,0
sync
mtspr SPRN_HIOR,0
isync
/* Restore HID0 */
ld r3,CS_HID0(r5)
sync
isync
mtspr SPRN_HID0,r3
mfspr r3,SPRN_HID0
mfspr r3,SPRN_HID0
mfspr r3,SPRN_HID0
mfspr r3,SPRN_HID0
mfspr r3,SPRN_HID0
mfspr r3,SPRN_HID0
sync
isync
/* Restore HID1 */
ld r3,CS_HID1(r5)
sync
isync
mtspr SPRN_HID1,r3
mtspr SPRN_HID1,r3
sync
isync
/* Restore HID4 */
ld r3,CS_HID4(r5)
sync
isync
mtspr SPRN_HID4,r3
sync
isync
/* Restore HID5 */
ld r3,CS_HID5(r5)
sync
isync
mtspr SPRN_HID5,r3
sync
isync
1:
blr
......@@ -30,6 +30,7 @@ struct cpu_spec* cur_cpu_spec = NULL;
*/
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_ppc970(unsigned long offset, struct cpu_spec* spec);
/* We only set the altivec features if the kernel was compiled with altivec
......@@ -119,10 +120,10 @@ struct cpu_spec cpu_specs[] = {
{ /* PPC970 */
0xffff0000, 0x00390000, "PPC970",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP,
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP,
COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
128, 128,
__setup_cpu_power4,
__setup_cpu_ppc970,
COMMON_PPC64_FW
},
{ /* Power5 */
......
......@@ -1320,6 +1320,16 @@ _GLOBAL(__start_initialization_iSeries)
#endif
#ifdef CONFIG_PPC_PSERIES
_STATIC(mmu_off)
mfmsr r3
andi. r0,r3,MSR_IR|MSR_DR
beqlr
andc r3,r3,r0
mtspr SRR0,r4
mtspr SRR1,r3
sync
rfid
_GLOBAL(__start_initialization_pSeries)
mr r31,r3 /* save parameters */
mr r30,r4
......@@ -1339,33 +1349,27 @@ _GLOBAL(__start_initialization_pSeries)
/* Relocate the TOC from a virt addr to a real addr */
sub r2,r2,r3
/* DRENG / PPPBBB Fix the following comment!!! -Peter */
/* The following copies the first 0x100 bytes of code from the */
/* load addr to physical addr 0x0. This code causes secondary */
/* processors to spin until a flag in the PACA is set. This */
/* is done at this time rather than with the entire kernel */
/* relocation which is done below because we need to cause the */
/* processors to spin on code that is not going to move while OF */
/* is still alive. Although the spin code is not actually run on */
/* a uniprocessor, we always do this copy. */
SET_REG_TO_CONST(r4, KERNELBASE)/* Src addr */
sub r4,r4,r3 /* current address of __start */
/* the source addr */
li r3,0 /* Dest addr */
li r5,0x100 /* # bytes of memory to copy */
li r6,0 /* Destination offset */
bl .copy_and_flush /* copy the first 0x100 bytes */
/* Save parameters */
mr r3,r31
mr r4,r30
mr r5,r29
mr r6,r28
mr r7,r27
/* Do all of the interaction with OF client interface */
bl .prom_init
mr r23,r3 /* Save phys address we are running at */
/* Setup some critical 970 SPRs before switching MMU off */
bl .__power4_cpu_preinit
li r24,0 /* cpu # */
/* Switch off MMU if not already */
LOADADDR(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r23
bl .mmu_off
/*
* At this point, r3 contains the physical address we are running at,
* returned by prom_init()
......@@ -1390,6 +1394,7 @@ _STATIC(__after_prom_start)
li r3,0 /* target addr */
// XXX FIXME: Use phys returned by OF (r23)
sub r4,r27,r26 /* source addr */
/* current address of _start */
/* i.e. where we are running */
......@@ -1425,7 +1430,7 @@ _STATIC(__after_prom_start)
*
* Note: this routine *only* clobbers r0, r6 and lr
*/
_STATIC(copy_and_flush)
_GLOBAL(copy_and_flush)
addi r5,r5,-8
addi r6,r6,-8
4: li r0,16 /* Use the least common */
......@@ -1675,6 +1680,58 @@ _GLOBAL(giveup_altivec)
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_PMAC
/*
* On PowerMac, secondary processors starts from the reset vector, which
* is temporarily turned into a call to one of the functions below.
*/
.section ".text";
.align 2 ;
.globl pmac_secondary_start_1
pmac_secondary_start_1:
li r24, 1
b .pmac_secondary_start
.globl pmac_secondary_start_2
pmac_secondary_start_2:
li r24, 2
b .pmac_secondary_start
.globl pmac_secondary_start_3
pmac_secondary_start_3:
li r24, 3
b .pmac_secondary_start
_GLOBAL(pmac_secondary_start)
/* turn on 64-bit mode */
bl .enable_64b_mode
isync
/* Copy some CPU settings from CPU 0 */
bl .__restore_cpu_setup
/* pSeries do that early though I don't think we really need it */
mfmsr r3
ori r3,r3,MSR_RI
mtmsrd r3 /* RI on */
/* Set up a paca value for this processor. */
LOADADDR(r4, paca) /* Get base vaddr of paca array */
mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r4 /* for this processor. */
mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
/* Create a temp kernel stack for use before relocation is on. */
mr r1,r13
addi r1,r1,PACAGUARD
addi r1,r1,0x1000
subi r1,r1,STACK_FRAME_OVERHEAD
b .__secondary_start
#endif /* CONFIG_PPC_PMAC */
/*
* This function is called after the master CPU has released the
* secondary processors. The execution environment is relocation off.
......@@ -1870,6 +1927,12 @@ _STATIC(start_here_pSeries)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* set up the TOC (physical address) */
LOADADDR(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
sub r2,r2,r26
LOADADDR(r3,cpu_specs)
sub r3,r3,r26
LOADADDR(r4,cur_cpu_spec)
......@@ -1877,12 +1940,6 @@ _STATIC(start_here_pSeries)
mr r5,r26
bl .identify_cpu
/* set up the TOC (physical address) */
LOADADDR(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
sub r2,r2,r26
/* Get the pointer to the segment table which is used by */
/* stab_initialize */
LOADADDR(r27, boot_cpuid)
......@@ -1926,7 +1983,8 @@ _STATIC(start_here_pSeries)
li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES
/* Test if bit 0 is set (LPAR bit) */
andi. r3,r3,0x1
bne 98f
LOADADDR(r6,_SDR1) /* Only if NOT LPAR */
sub r6,r6,r26
......@@ -1938,11 +1996,12 @@ _STATIC(start_here_pSeries)
mtspr SRR0,r3
mtspr SRR1,r4
rfid
#endif /* CONFIG_PPC_PSERIES */
#endif /* CONFIG_PPC_PSERIES */
/* This is where all platforms converge execution */
_STATIC(start_here_common)
/* relocation is on at this point */
/* The following code sets up the SP and TOC now that we are */
/* running with translation enabled. */
......@@ -2013,8 +2072,6 @@ _STATIC(start_here_common)
_GLOBAL(__setup_cpu_power3)
blr
_GLOBAL(__setup_cpu_power4)
blr
_GLOBAL(hmt_init)
#ifdef CONFIG_HMT
......
......@@ -241,9 +241,9 @@ void iSeries_pcibios_init(void)
}
/*
* pcibios_final_fixup(void)
* iSeries_pci_final_fixup(void)
*/
void __init pcibios_final_fixup(void)
void __init iSeries_pci_final_fixup(void)
{
struct pci_dev *pdev = NULL;
struct iSeries_Device_Node *node;
......
......@@ -63,10 +63,11 @@ extern void tce_init_iSeries(void);
static void build_iSeries_Memory_Map(void);
static void setup_iSeries_cache_sizes(void);
static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa,
pte_t *ptep, unsigned hpteflags, unsigned bolted);
extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa,
pte_t *ptep, unsigned hpteflags, unsigned bolted);
static void iSeries_setup_dprofile(void);
void iSeries_setup_arch(void);
extern void iSeries_setup_arch(void);
extern void iSeries_pci_final_fixup(void);
/* Global Variables */
static unsigned long procFreqHz;
......@@ -318,6 +319,8 @@ void __init iSeries_init_early(void)
ppc_md.get_irq = iSeries_get_irq;
ppc_md.init = NULL;
ppc_md.pcibios_fixup = iSeries_pci_final_fixup;
ppc_md.restart = iSeries_restart;
ppc_md.power_off = iSeries_power_off;
ppc_md.halt = iSeries_halt;
......
......@@ -42,6 +42,7 @@
extern long cede_processor(void);
extern long poll_pending(void);
extern void power4_idle(void);
int (*idle_loop)(void);
......@@ -279,6 +280,17 @@ int cpu_idle(void)
return 0;
}
int native_idle(void)
{
while(1) {
if (!need_resched())
power4_idle();
if (need_resched())
schedule();
}
return 0;
}
int idle_setup(void)
{
#ifdef CONFIG_PPC_ISERIES
......@@ -297,6 +309,9 @@ int idle_setup(void)
printk("idle = default_idle\n");
idle_loop = default_idle;
}
} else if (systemcfg->platform == PLATFORM_POWERMAC) {
printk("idle = native_idle\n");
idle_loop = native_idle;
} else {
printk("idle_setup: unknown platform, use default_idle\n");
idle_loop = default_idle;
......
/*
* This file contains the power_save function for 6xx & 7xxx CPUs
* rewritten in assembler
*
* Warning ! This code assumes that if your machine has a 750fx
* it will have PLL 1 set to low speed mode (used during NAP/DOZE).
* if this is not the case some additional changes will have to
* be done to check a runtime var (a bit like powersave-nap)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>
#undef DEBUG
.text
/*
* Here is the power_save_6xx function. This could eventually be
* split into several functions & changing the function pointer
* depending on the various features.
*/
_GLOBAL(power4_idle)
BEGIN_FTR_SECTION
blr
END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
/* We must dynamically check for the NAP feature as it
* can be cleared by CPU init after the fixups are done
*/
LOADBASE(r3,cur_cpu_spec)
ld r4,cur_cpu_spec@l(r3)
ld r4,CPU_SPEC_FEATURES(r4)
andi. r0,r4,CPU_FTR_CAN_NAP
beqlr
/* Now check if user or arch enabled NAP mode */
LOADBASE(r3,powersave_nap)
lwz r4,powersave_nap@l(r3)
cmpi 0,r4,0
beqlr
/* Clear MSR:EE */
mfmsr r7
li r4,0
ori r4,r4,MSR_EE
andc r0,r7,r4
mtmsrd r0
/* Check current_thread_info()->flags */
clrrdi r4,r1,THREAD_SHIFT
ld r4,TI_FLAGS(r4)
andi. r0,r4,_TIF_NEED_RESCHED
beq 1f
mtmsrd r7 /* out of line this ? */
blr
1:
/* Go to NAP now */
BEGIN_FTR_SECTION
DSSALL
sync
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
oris r7,r7,MSR_POW@h
sync
isync
mtmsrd r7
isync
sync
blr
......@@ -763,7 +763,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_fstat64
.llong .sys32_pciconfig_read
.llong .sys32_pciconfig_write
.llong .sys_ni_syscall /* 200 - old pciconfig_iobase */
.llong .sys32_pciconfig_iobase /* 200 - pciconfig_iobase */
.llong .sys_ni_syscall /* reserved for MacOnLinux */
.llong .sys_getdents64
.llong .sys_pivot_root
......@@ -1022,7 +1022,7 @@ _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* 32bit only fstat64 */
.llong .sys_ni_syscall /* 32bit only pciconfig_read */
.llong .sys_ni_syscall /* 32bit only pciconfig_write */
.llong .sys_ni_syscall /* 200 - old pciconfig_iobase */
.llong .sys_ni_syscall /* 32bit only pciconfig_iobase */
.llong .sys_ni_syscall /* reserved for MacOnLinux */
.llong .sys_getdents64
.llong .sys_pivot_root
......
This diff is collapsed.
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/errno.h>
#include <asm/of_device.h>
/**
* of_match_device - Tell if an of_device structure has a matching
* of_match structure
* @ids: array of of device match structures to search in
* @dev: the of device structure to match against
*
* Used by a driver to check whether an of_device present in the
* system is in its list of supported devices.
*/
const struct of_match * of_match_device(const struct of_match *matches,
const struct of_device *dev)
{
if (!dev->node)
return NULL;
while (matches->name || matches->type || matches->compatible) {
int match = 1;
if (matches->name && matches->name != OF_ANY_MATCH)
match &= dev->node->name
&& !strcmp(matches->name, dev->node->name);
if (matches->type && matches->type != OF_ANY_MATCH)
match &= dev->node->type
&& !strcmp(matches->type, dev->node->type);
if (matches->compatible && matches->compatible != OF_ANY_MATCH)
match &= device_is_compatible(dev->node,
matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
const struct of_match * matches = of_drv->match_table;
if (!matches)
return 0;
return of_match_device(matches, of_dev) != NULL;
}
struct of_device *of_dev_get(struct of_device *dev)
{
struct device *tmp;
if (!dev)
return NULL;
tmp = get_device(&dev->dev);
if (tmp)
return to_of_device(tmp);
else
return NULL;
}
void of_dev_put(struct of_device *dev)
{
if (dev)
put_device(&dev->dev);
}
static int of_device_probe(struct device *dev)
{
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
const struct of_match *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
if (!drv->probe)
return error;
of_dev_get(of_dev);
match = of_match_device(drv->match_table, of_dev);
if (match)
error = drv->probe(of_dev, match);
if (error)
of_dev_put(of_dev);
return error;
}
static int of_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
static int of_device_suspend(struct device *dev, u32 state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
static int of_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
static int __init of_bus_driver_init(void)
{
return bus_register(&of_platform_bus_type);
}
postcore_initcall(of_bus_driver_init);
int of_register_driver(struct of_platform_driver *drv)
{
int count = 0;
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &of_platform_bus_type;
drv->driver.probe = of_device_probe;
drv->driver.remove = of_device_remove;
/* register with core */
count = driver_register(&drv->driver);
return count ? count : 1;
}
void of_unregister_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
}
static ssize_t dev_show_devspec(struct device *dev, char *buf)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
return sprintf(buf, "%s", ofdev->node->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
/**
* of_release_dev - free an of device structure when all users of it are finished.
* @dev: device that's been disconnected
*
* Will be called only by the device core when all users of this of device are
* done.
*/
void of_release_dev(struct device *dev)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
kfree(ofdev);
}
int of_device_register(struct of_device *ofdev)
{
int rc;
struct of_device **odprop;
BUG_ON(ofdev->node == NULL);
odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
if (!odprop) {
struct property *new_prop;
new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
GFP_KERNEL);
if (new_prop == NULL)
return -ENOMEM;
new_prop->name = "linux,device";
new_prop->length = sizeof(sizeof(struct of_device *));
new_prop->value = (unsigned char *)&new_prop[1];
odprop = (struct of_device **)new_prop->value;
*odprop = NULL;
prom_add_property(ofdev->node, new_prop);
}
*odprop = ofdev;
rc = device_register(&ofdev->dev);
if (rc)
return rc;
device_create_file(&ofdev->dev, &dev_attr_devspec);
return 0;
}
void of_device_unregister(struct of_device *ofdev)
{
struct of_device **odprop;
device_remove_file(&ofdev->dev, &dev_attr_devspec);
odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
if (odprop)
*odprop = NULL;
device_unregister(&ofdev->dev);
}
struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
{
struct of_device *dev;
u32 *reg;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
memset(dev, 0, sizeof(*dev));
dev->node = np;
dev->dma_mask = 0xffffffffUL;
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.parent = NULL;
dev->dev.bus = &of_platform_bus_type;
dev->dev.release = of_release_dev;
reg = (u32 *)get_property(np, "reg", NULL);
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
if (of_device_register(dev) != 0) {
kfree(dev);
return NULL;
}
return dev;
}
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_platform_bus_type);
EXPORT_SYMBOL(of_register_driver);
EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_device_register);
EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_platform_device_create);
EXPORT_SYMBOL(of_release_dev);
......@@ -34,7 +34,42 @@ static volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL;
void find_ISUs(void);
/*
* Local (static) OpenPIC Operations
*/
/* Global Operations */
static void openpic_reset(void);
static void openpic_enable_8259_pass_through(void);
static void openpic_disable_8259_pass_through(void);
static u_int openpic_irq(void);
static void openpic_eoi(void);
static u_int openpic_get_priority(void);
static void openpic_set_priority(u_int pri);
static u_int openpic_get_spurious(void);
static void openpic_set_spurious(u_int vector);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
struct pt_regs *regs);
#endif
/* Timer Interrupts */
static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
static void openpic_maptimer(u_int timer, u_int cpumask);
/* Interrupt Sources */
static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
static void openpic_mapirq(u_int irq, u_int cpumask);
static void openpic_set_sense(u_int irq, int sense);
static void find_ISUs(void);
static u_int NumProcessors;
static u_int NumSources;
......@@ -130,7 +165,7 @@ unsigned int openpic_vec_spurious;
#define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf]
void __init openpic_init_IRQ(void)
void __init pSeries_init_openpic(void)
{
struct device_node *np;
int i;
......@@ -359,9 +394,12 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
}
/* Init all external sources */
for (i = 1; i < NumSources; i++) {
for (i = 0; i < NumSources; i++) {
int pri, sense;
/* skip cascade if any */
if (offset && i == 0)
continue;
/* the bootloader may have left it enabled (bad !) */
openpic_disable_irq(i+offset);
......@@ -396,6 +434,9 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
*/
static int __init openpic_setup_i8259(void)
{
if (systemcfg->platform == PLATFORM_POWERMAC)
return 0;
if (naca->interrupt_controller == IC_OPEN_PIC) {
/* Initialize the cascade */
if (request_irq(NUM_8259_INTERRUPTS, no_action, SA_INTERRUPT,
......@@ -419,6 +460,14 @@ void openpic_setup_ISU(int isu_num, unsigned long addr)
void find_ISUs(void)
{
/* For PowerMac, setup ISUs on base openpic */
if (systemcfg->platform == PLATFORM_POWERMAC) {
int i;
for (i=0; i<128; i+=0x10) {
ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i];
NumISUs++;
}
}
/* Use /interrupt-controller/reg and
* /interrupt-controller/interrupt-ranges from OF device tree
* the ISU array is setup in chrp_pci.c in ibm_add_bridges
......@@ -429,11 +478,22 @@ void find_ISUs(void)
/* basically each ISU is a bus, and this assumes that
* open_pic_isu_count interrupts per bus are possible
* ISU == Interrupt Source
*
* On G5, we keep the original NumSources provided by the controller,
* it's below 128, so we have room to stuff the IPIs and timers like darwin
* does. We put the spurrious vector up at 0xff though.
*/
NumSources = NumISUs * 0x10;
openpic_vec_ipi = NumSources + open_pic_irq_offset;
openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI;
openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
if (systemcfg->platform == PLATFORM_POWERMAC) {
openpic_vec_ipi = NumSources;
openpic_vec_timer = openpic_vec_ipi + 4;
openpic_vec_spurious = 0xff;
} else {
NumSources = NumISUs * 0x10;
openpic_vec_ipi = NumSources + open_pic_irq_offset;
openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI;
openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
}
}
static inline void openpic_reset(void)
......@@ -767,8 +827,7 @@ static inline void openpic_set_sense(u_int irq, int sense)
static void openpic_end_irq(unsigned int irq_nr)
{
if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
openpic_eoi();
openpic_eoi();
}
static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
......@@ -807,9 +866,7 @@ int openpic_get_irq(struct pt_regs *regs)
int irq = openpic_irq();
/* Management of the cascade should be moved out of here */
if (open_pic_irq_offset && irq == open_pic_irq_offset)
{
if (open_pic_irq_offset && irq == open_pic_irq_offset) {
/*
* This magic address generates a PCI IACK cycle.
*/
......
......@@ -40,6 +40,8 @@ extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
extern inline int openpic_to_irq(int irq)
{
if (systemcfg->platform == PLATFORM_POWERMAC)
return irq;
return irq += NUM_8259_INTERRUPTS;
}
/*extern int open_pic_irq_offset;*/
......
......@@ -279,40 +279,6 @@ extern volatile struct OpenPIC *OpenPIC;
#define Vector_Priority _Vector_Priority.Reg
#define Destination _Destination.Reg
/*
* Local (static) OpenPIC Operations
*/
/* Global Operations */
static void openpic_reset(void);
static void openpic_enable_8259_pass_through(void);
static void openpic_disable_8259_pass_through(void);
static u_int openpic_irq(void);
static void openpic_eoi(void);
static u_int openpic_get_priority(void);
static void openpic_set_priority(u_int pri);
static u_int openpic_get_spurious(void);
static void openpic_set_spurious(u_int vector);
#ifdef CONFIG_SMP
/* Interprocessor Interrupts */
static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
struct pt_regs *regs);
#endif
/* Timer Interrupts */
static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
static void openpic_maptimer(u_int timer, u_int cpumask);
/* Interrupt Sources */
static void openpic_enable_irq(u_int irq);
static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level);
static void openpic_mapirq(u_int irq, u_int cpumask);
static void openpic_set_sense(u_int irq, int sense);
#endif /* __KERNEL__ */
......
/*
* 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, "OpenPic2 Done");
}
/*
* c 2001 PPC 64 Team, IBM Corp
*
* 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.
*
* /dev/nvram driver for PPC64
*
* This perhaps should live in drivers/char
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#include <asm/rtas.h>
#include <asm/prom.h>
#include <asm/machdep.h>
static unsigned int nvram_size;
static unsigned int nvram_fetch, nvram_store;
static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED;
static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
{
unsigned int i;
unsigned long len, done;
unsigned long flags;
char *p = buf;
if (nvram_size == 0 || nvram_fetch)
return -ENODEV;
if (*index >= nvram_size)
return 0;
i = *index;
if (i + count > nvram_size)
count = nvram_size - i;
spin_lock_irqsave(&nvram_lock, flags);
for (; count != 0; count -= len) {
len = count;
if (len > NVRW_CNT)
len = NVRW_CNT;
if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
len) != 0) || len != done) {
spin_unlock_irqrestore(&nvram_lock, flags);
return -EIO;
}
memcpy(p, nvram_buf, len);
p += len;
i += len;
}
spin_unlock_irqrestore(&nvram_lock, flags);
*index = i;
return p - buf;
}
static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index)
{
unsigned int i;
unsigned long len, done;
unsigned long flags;
const char *p = buf;
if (nvram_size == 0 || nvram_store)
return -ENODEV;
if (*index >= nvram_size)
return 0;
i = *index;
if (i + count > nvram_size)
count = nvram_size - i;
spin_lock_irqsave(&nvram_lock, flags);
for (; count != 0; count -= len) {
len = count;
if (len > NVRW_CNT)
len = NVRW_CNT;
memcpy(nvram_buf, p, len);
if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf),
len) != 0) || len != done) {
spin_unlock_irqrestore(&nvram_lock, flags);
return -EIO;
}
p += len;
i += len;
}
spin_unlock_irqrestore(&nvram_lock, flags);
*index = i;
return p - buf;
}
static ssize_t pSeries_nvram_get_size(void)
{
return nvram_size ? nvram_size : -ENODEV;
}
int __init pSeries_nvram_init(void)
{
struct device_node *nvram;
unsigned int *nbytes_p, proplen;
nvram = of_find_node_by_type(NULL, "nvram");
if (nvram == NULL)
return -ENODEV;
nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
if (nbytes_p == NULL || proplen != sizeof(unsigned int))
return -EIO;
nvram_size = *nbytes_p;
nvram_fetch = rtas_token("nvram-fetch");
nvram_store = rtas_token("nvram-store");
printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size);
of_node_put(nvram);
ppc_md.nvram_read = pSeries_nvram_read;
ppc_md.nvram_write = pSeries_nvram_write;
ppc_md.nvram_size = pSeries_nvram_get_size;
return 0;
}
......@@ -687,7 +687,7 @@ static void phbs_fixup_io(void)
extern void chrp_request_regions(void);
void __init pcibios_final_fixup(void)
void __init pSeries_final_fixup(void)
{
struct pci_dev *dev = NULL;
......
......@@ -34,6 +34,7 @@
#include <asm/ppcdebug.h>
#include <asm/naca.h>
#include <asm/pci_dma.h>
#include <asm/machdep.h>
#include "pci.h"
......@@ -58,21 +59,32 @@ void pcibios_name_device(struct pci_dev* dev);
void pcibios_final_fixup(void);
static void fixup_broken_pcnet32(struct pci_dev* dev);
static void fixup_windbond_82c105(struct pci_dev* dev);
extern void fixup_k2_sata(struct pci_dev* dev);
void iSeries_pcibios_init(void);
struct pci_controller *hose_head;
struct pci_controller **hose_tail = &hose_head;
struct pci_dma_ops pci_dma_ops;
EXPORT_SYMBOL(pci_dma_ops);
int global_phb_number; /* Global phb counter */
/* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL;
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105 },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID,
fixup_broken_pcnet32 },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
fixup_windbond_82c105 },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID,
pcibios_name_device },
#ifdef CONFIG_PPC_PMAC
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, 0x0240,
fixup_k2_sata },
#endif
{ 0 }
};
......@@ -250,6 +262,9 @@ pci_alloc_pci_controller(enum phb_types controller_type)
case phb_type_winnipeg:
model = "PHB WP";
break;
case phb_type_apple:
model = "PHB APPLE";
break;
default:
model = "PHB UK";
break;
......@@ -332,8 +347,9 @@ static int __init pcibios_init(void)
pci_assign_unassigned_resources();
#endif
/* Call machine dependent fixup */
pcibios_final_fixup();
/* Call machine dependent final fixup */
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
/* Cache the location of the ISA bridge (if we have one) */
ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
......
This diff is collapsed.
This diff is collapsed.
......@@ -181,6 +181,7 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev)
}
return dn;
}
EXPORT_SYMBOL(fetch_dev_dn);
/******************************************************************
......
#ifndef __PMAC_H__
#define __PMAC_H__
#include <linux/pci.h>
#include <linux/ide.h>
/*
* Declaration for the various functions exported by the
* pmac_* files. Mostly for use by pmac_setup
*/
extern void pmac_get_boot_time(struct rtc_time *tm);
extern void pmac_get_rtc_time(struct rtc_time *tm);
extern int pmac_set_rtc_time(struct rtc_time *tm);
extern void pmac_read_rtc_time(void);
extern void pmac_calibrate_decr(void);
extern void pmac_pcibios_fixup(void);
extern void pmac_pci_init(void);
extern void pmac_setup_pci_dma(void);
extern void fixup_k2_sata(struct pci_dev* dev);
extern void pmac_check_ht_link(void);
extern void pmac_setup_smp(void);
extern unsigned long pmac_ide_get_base(int index);
extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
unsigned long data_port, unsigned long ctrl_port, int *irq);
extern void pmac_nvram_init(void);
#endif /* __PMAC_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#include <asm-ppc/dbdma.h>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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