Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (209 commits)
  [POWERPC] Create add_rtc() function to enable the RTC CMOS driver
  [POWERPC] Add H_ILLAN_ATTRIBUTES hcall number
  [POWERPC] xilinxfb: Parameterize xilinxfb platform device registration
  [POWERPC] Oprofile support for Power 5++
  [POWERPC] Enable arbitary speed tty ioctls and split input/output speed
  [POWERPC] Make drivers/char/hvc_console.c:khvcd() static
  [POWERPC] Remove dead code for preventing pread() and pwrite() calls
  [POWERPC] Remove unnecessary #undef printk from prom.c
  [POWERPC] Fix typo in Ebony default DTS
  [POWERPC] Check for NULL ppc_md.init_IRQ() before calling
  [POWERPC] Remove extra return statement
  [POWERPC] pasemi: Don't auto-select CONFIG_EMBEDDED
  [POWERPC] pasemi: Rename platform
  [POWERPC] arch/powerpc/kernel/sysfs.c: Move NUMA exports
  [POWERPC] Add __read_mostly support for powerpc
  [POWERPC] Modify sched_clock() to make CONFIG_PRINTK_TIME more sane
  [POWERPC] Create a dummy zImage if no valid platform has been selected
  [POWERPC] PS3: Bootwrapper support.
  [POWERPC] powermac i2c: Use mutex
  [POWERPC] Schedule removal of arch/ppc
  ...

Fixed up conflicts manually in:

	Documentation/feature-removal-schedule.txt
	arch/powerpc/kernel/pci_32.c
	arch/powerpc/kernel/pci_64.c
	include/asm-powerpc/pci.h

and asked the powerpc people to double-check the result..
This commit is contained in:
Linus Torvalds 2007-07-16 17:58:08 -07:00
commit 489de30259
280 changed files with 11020 additions and 7030 deletions

View File

@ -253,7 +253,7 @@ Here are the routines, one by one:
The first of these two routines is invoked after map_vm_area()
has installed the page table entries. The second is invoked
before unmap_vm_area() deletes the page table entries.
before unmap_kernel_range() deletes the page table entries.
There exists another whole class of cpu cache issues which currently
require a whole different set of interfaces to handle properly.

View File

@ -297,3 +297,16 @@ Why: Obsolete for multiple years now, NAT core provides the same behaviour.
Who: Patrick McHardy <kaber@trash.net>
---------------------------
What: The arch/ppc and include/asm-ppc directories
When: Jun 2008
Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64
platforms. Currently there are efforts underway to port the remaining
arch/ppc platforms to the merged tree. New submissions to the arch/ppc
tree have been frozen with the 2.6.22 kernel release and that tree will
remain in bug-fix only mode until its scheduled removal. Platforms
that are not ported by June 2008 will be removed due to the lack of an
interested maintainer.
Who: linuxppc-dev@ozlabs.org
---------------------------

View File

@ -42,15 +42,16 @@ Table of Contents
1) Defining child nodes of an SOC
2) Representing devices without a current OF specification
a) MDIO IO device
c) PHY nodes
b) Gianfar-compatible ethernet nodes
c) PHY nodes
d) Interrupt controllers
e) I2C
f) Freescale SOC USB controllers
g) Freescale SOC SEC Security Engines
h) Board Control and Status (BCSR)
i) Freescale QUICC Engine module (QE)
g) Flash chip nodes
j) Flash chip nodes
k) Global Utilities Block
VII - Specifying interrupt information for devices
1) interrupts property
@ -626,6 +627,14 @@ So the node content can be summarized as a start token, a full path,
a list of properties, a list of child nodes, and an end token. Every
child node is a full node structure itself as defined above.
NOTE: The above definition requires that all property definitions for
a particular node MUST precede any subnode definitions for that node.
Although the structure would not be ambiguous if properties and
subnodes were intermingled, the kernel parser requires that the
properties come first (up until at least 2.6.22). Any tools
manipulating a flattened tree must take care to preserve this
constraint.
4) Device tree "strings" block
In order to save space, property names, which are generally redundant,
@ -1782,6 +1791,33 @@ platforms are moved over to use the flattened-device-tree model.
partition-names = "fs\0firmware";
};
k) Global Utilities Block
The global utilities block controls power management, I/O device
enabling, power-on-reset configuration monitoring, general-purpose
I/O signal configuration, alternate function selection for multiplexed
signals, and clock control.
Required properties:
- compatible : Should define the compatible device type for
global-utilities.
- reg : Offset and length of the register set for the device.
Recommended properties:
- fsl,has-rstcr : Indicates that the global utilities register set
contains a functioning "reset control register" (i.e. the board
is wired to reset upon setting the HRESET_REQ bit in this register).
Example:
global-utilities@e0000 { /* global utilities block */
compatible = "fsl,mpc8548-guts";
reg = <e0000 1000>;
fsl,has-rstcr;
};
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices

View File

@ -4,17 +4,7 @@
mainmenu "Linux/PowerPC Kernel Configuration"
config PPC64
bool "64-bit kernel"
default n
help
This option selects whether a 32-bit or a 64-bit kernel
will be built.
config PPC_PM_NEEDS_RTC_LIB
bool
select RTC_LIB
default y if PM
source "arch/powerpc/platforms/Kconfig.cputype"
config PPC32
bool
@ -135,123 +125,6 @@ config PPC64_SWSUSP
depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
default y
menu "Processor support"
choice
prompt "Processor Type"
depends on PPC32
default 6xx
config CLASSIC32
bool "52xx/6xx/7xx/74xx"
select PPC_FPU
select 6xx
help
There are four families of PowerPC chips supported. The more common
types (601, 603, 604, 740, 750, 7400), the Motorola embedded
versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC
embedded versions (403 and 405) and the high end 64 bit Power
processors (POWER 3, POWER4, and IBM PPC970 also known as G5).
This option is the catch-all for 6xx types, including some of the
embedded versions. Unless there is see an option for the specific
chip family you are using, you want this option.
You do not want this if you are building a kernel for a 64 bit
IBM RS/6000 or an Apple G5, choose 6xx.
If unsure, select this option
Note that the kernel runs in 32-bit mode even on 64-bit chips.
config PPC_82xx
bool "Freescale 82xx"
select 6xx
select PPC_FPU
config PPC_83xx
bool "Freescale 83xx"
select 6xx
select FSL_SOC
select 83xx
select PPC_FPU
select WANT_DEVICE_TREE
config PPC_85xx
bool "Freescale 85xx"
select E500
select FSL_SOC
select 85xx
select WANT_DEVICE_TREE
config PPC_86xx
bool "Freescale 86xx"
select 6xx
select FSL_SOC
select FSL_PCIE
select PPC_FPU
select ALTIVEC
help
The Freescale E600 SoCs have 74xx cores.
config PPC_8xx
bool "Freescale 8xx"
select FSL_SOC
select 8xx
config 40x
bool "AMCC 40x"
select PPC_DCR_NATIVE
config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
select WANT_DEVICE_TREE
config E200
bool "Freescale e200"
endchoice
config POWER4_ONLY
bool "Optimize for POWER4"
depends on PPC64
default n
---help---
Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
The resulting binary will not work on POWER3 or RS64 processors
when compiled with binutils 2.15 or later.
config POWER3
bool
depends on PPC64
default y if !POWER4_ONLY
config POWER4
depends on PPC64
def_bool y
config 6xx
bool
# this is temp to handle compat with arch=ppc
config 8xx
bool
# this is temp to handle compat with arch=ppc
config 83xx
bool
# this is temp to handle compat with arch=ppc
config 85xx
bool
config E500
bool
config PPC_FPU
bool
default y if PPC64
config PPC_DCR_NATIVE
bool
default n
@ -270,134 +143,6 @@ config PPC_OF_PLATFORM_PCI
depends on PPC64 # not supported on 32 bits yet
default n
config 4xx
bool
depends on 40x || 44x
default y
config BOOKE
bool
depends on E200 || E500 || 44x
default y
config FSL_BOOKE
bool
depends on E200 || E500
default y
config PTE_64BIT
bool
depends on 44x || E500
default y if 44x
default y if E500 && PHYS_64BIT
config PHYS_64BIT
bool 'Large physical address support' if E500
depends on 44x || E500
select RESOURCES_64BIT
default y if 44x
---help---
This option enables kernel support for larger than 32-bit physical
addresses. This features is not be available on all e500 cores.
If in doubt, say N here.
config ALTIVEC
bool "AltiVec Support"
depends on CLASSIC32 || POWER4
---help---
This option enables kernel support for the Altivec extensions to the
PowerPC processor. The kernel currently supports saving and restoring
altivec registers, and turning on the 'altivec enable' bit so user
processes can execute altivec instructions.
This option is only usefully if you have a processor that supports
altivec (G4, otherwise known as 74xx series), but does not have
any affect on a non-altivec cpu (it does, however add code to the
kernel).
If in doubt, say Y here.
config SPE
bool "SPE Support"
depends on E200 || E500
default y
---help---
This option enables kernel support for the Signal Processing
Extensions (SPE) to the PowerPC processor. The kernel currently
supports saving and restoring SPE registers, and turning on the
'spe enable' bit so user processes can execute SPE instructions.
This option is only useful if you have a processor that supports
SPE (e500, otherwise known as 85xx series), but does not have any
effect on a non-spe cpu (it does, however add code to the kernel).
If in doubt, say Y here.
config PPC_STD_MMU
bool
depends on 6xx || POWER3 || POWER4 || PPC64
default y
config PPC_STD_MMU_32
def_bool y
depends on PPC_STD_MMU && PPC32
config PPC_MM_SLICES
bool
default y if HUGETLB_PAGE
default n
config VIRT_CPU_ACCOUNTING
bool "Deterministic task and CPU time accounting"
depends on PPC64
default y
help
Select this option to enable more accurate task and CPU time
accounting. This is done by reading a CPU counter on each
kernel entry and exit and on transitions within the kernel
between system, softirq and hardirq state, so there is a
small performance impact. This also enables accounting of
stolen time on logically-partitioned systems running on
IBM POWER5-based machines.
If in doubt, say Y here.
config SMP
depends on PPC_STD_MMU
bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
than one CPU, say Y. Note that the kernel does not currently
support SMP machines with 603/603e/603ev or PPC750 ("G3") processors
since they have inadequate hardware support for multiprocessor
operation.
If you say N here, the kernel will run on single and multiprocessor
machines, but will use only one CPU of a multiprocessor machine. If
you say Y here, the kernel will run on single-processor machines.
On a single-processor machine, the kernel will run faster if you say
N here.
If you don't know what to do here, say N.
config NR_CPUS
int "Maximum number of CPUs (2-128)"
range 2 128
depends on SMP
default "32" if PPC64
default "4"
config NOT_COHERENT_CACHE
bool
depends on 4xx || 8xx || E200
default y
config CONFIG_CHECK_CACHE_COHERENCY
bool
endmenu
source "init/Kconfig"
source "arch/powerpc/platforms/Kconfig"
@ -677,10 +422,6 @@ config SBUS
config FSL_SOC
bool
config FSL_PCIE
bool
depends on PPC_86xx
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
@ -688,10 +429,10 @@ config MCA
config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
|| MPC7448HPC2 || PPC_PS3 || PPC_HOLLY
default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
|| PPC_PS3
default y if !40x && !CPM2 && !8xx && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
default PCI_QSPAN if !4xx && !CPM2 && 8xx
select ARCH_SUPPORTS_MSI
help

View File

@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
CPPFLAGS_vmlinux.lds := -Upowerpc
BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage
BOOT_TARGETS = zImage zImage.initrd uImage
PHONY += $(BOOT_TARGETS)

View File

@ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void)
dt_fixup_memory(0, memsize);
}
#define SPRN_DBCR0 0x134
#define DBCR0_RST_SYSTEM 0x30000000
void ibm44x_dbcr_reset(void)
{
unsigned long tmp;
asm volatile (
"mfspr %0,%1\n"
"oris %0,%0,%2@h\n"
"mtspr %1,%0"
: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
);
}
/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
* banks into the OPB address space */
void ibm4xx_fixup_ebc_ranges(const char *ebc)
{
void *devp;
u32 bxcr;
u32 ranges[EBC_NUM_BANKS*4];
u32 *p = ranges;
int i;
for (i = 0; i < EBC_NUM_BANKS; i++) {
mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
bxcr = mfdcr(DCRN_EBC0_CFGDATA);
if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
*p++ = i;
*p++ = 0;
*p++ = bxcr & EBC_BXCR_BAS;
*p++ = EBC_BXCR_BANK_SIZE(bxcr);
}
}
devp = finddevice(ebc);
if (! devp)
fatal("Couldn't locate EBC node %s\n\r", ebc);
setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
}

View File

@ -11,6 +11,9 @@
#define _PPC_BOOT_44X_H_
void ibm44x_fixup_memsize(void);
void ibm4xx_fixup_ebc_ranges(const char *ebc);
void ibm44x_dbcr_reset(void);
void ebony_init(void *mac0, void *mac1);
#endif /* _PPC_BOOT_44X_H_ */

View File

@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c \
44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c treeboot-ebony.c prpmc2800.c
cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
ps3-head.S ps3-hvcall.S ps3.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
$(obj)/empty.c:
@touch $@
$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
empty.c zImage.coff.lds zImage.lds
empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
$(obj)/zImage.lds $(obj)/zImage.coff.lds
$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
wrapper :=$(srctree)/$(src)/wrapper
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
@ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf
image-$(CONFIG_PPC_HOLLY) += zImage.holly
image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
image-$(CONFIG_PPC_ISERIES) += zImage.iseries
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
@ -157,55 +158,43 @@ targets += $(image-y) $(initrd-y)
$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-))
dts-y := $(patsubst zImage%, zImage.dts%, $(image-y))
dts-y := $(filter-out $(image-y), $(dts-y))
targets += $(image-y) $(dts-y)
dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-))
dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y))
dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y))
targets += $(image-y) $(dts_initrd-y)
$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz
# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
# empty string, define 'dts' to be path to the dts
# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
ifneq ($(CONFIG_DEVICE_TREE),"")
dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
endif
endif
# Don't put the ramdisk on the pattern rule; when its missing make will try
# the pattern rule with less dependencies that also matches (even with the
# hard dependency listed).
$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz
$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
$(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts)
$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
$(call if_changed,wrap,$*,$(dts))
$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
$(obj)/zImage.%: vmlinux $(wrapperbits)
$(call if_changed,wrap,$*)
# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
# prefix
$(obj)/vmlinux.strip: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/zImage.iseries: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
$(STRIP) -s -R .comment $< -o vmlinux.strip
$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
$(obj)/zImage.initrd.ps3: vmlinux
@echo " WARNING zImage.initrd.ps3 not supported (yet)"
$(obj)/zImage.holly-elf: vmlinux $(wrapperbits)
$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,)
$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz
$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz)
$(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
$(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
$(call if_changed,wrap,cuboot-$*,$(dts))
@ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits)
$(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
$(call if_changed,wrap,treeboot-$*,$(dts))
# If there isn't a platform selected then just strip the vmlinux.
ifeq (,$(image-y))
image-y := vmlinux.strip
endif
$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
@rm -f $@; ln $< $@
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
@rm -f $@; ln $< $@
$(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y))
@rm -f $@; ln $< $@
$(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y))
@rm -f $@; ln $< $@
install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
# anything not in $(targets)
clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
treeImage.* zImage.dts zImage.dts_initrd
clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
otheros.bld
# clean up files cached by wrapper
clean-kernel := vmlinux.strip vmlinux.bin

View File

@ -12,12 +12,12 @@
#include "ops.h"
#include "stdio.h"
#include "cuboot.h"
#define TARGET_83xx
#include "ppcboot.h"
static bd_t bd;
extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
@ -52,16 +52,7 @@ static void platform_fixups(void)
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
memcpy(&bd, (bd_t *)r3, sizeof(bd));
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 - r4 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
CUBOOT_INIT();
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;

View File

@ -12,12 +12,12 @@
#include "ops.h"
#include "stdio.h"
#include "cuboot.h"
#define TARGET_85xx
#include "ppcboot.h"
static bd_t bd;
extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
@ -53,16 +53,7 @@ static void platform_fixups(void)
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
memcpy(&bd, (bd_t *)r3, sizeof(bd));
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 - r4 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
CUBOOT_INIT();
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;

View File

@ -15,28 +15,16 @@
#include "ops.h"
#include "stdio.h"
#include "44x.h"
#include "cuboot.h"
#define TARGET_44x
#include "ppcboot.h"
static bd_t bd;
extern char _end[];
BSS_STACK(4096);
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
memcpy(&bd, (bd_t *)r3, sizeof(bd));
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram, 32, 64);
CUBOOT_INIT();
ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr);
}

View File

@ -0,0 +1,35 @@
/*
* Compatibility for old (not device tree aware) U-Boot versions
*
* Author: Scott Wood <scottwood@freescale.com>
* Consolidated using macros by David Gibson <david@gibson.dropbear.id.au>
*
* Copyright 2007 David Gibson, IBM Corporation.
* Copyright (c) 2007 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include "ops.h"
#include "stdio.h"
#include "ppcboot.h"
extern char _end[];
extern char _dtb_start[], _dtb_end[];
void cuboot_init(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
unsigned long end_of_ram)
{
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 - r4 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
}

View File

@ -0,0 +1,14 @@
#ifndef _PPC_BOOT_CUBOOT_H_
#define _PPC_BOOT_CUBOOT_H_
void cuboot_init(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
unsigned long end_of_ram);
#define CUBOOT_INIT() \
do { \
memcpy(&bd, (bd_t *)r3, sizeof(bd)); \
cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \
} while (0)
#endif /* _PPC_BOOT_CUBOOT_H_ */

View File

@ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C
#define SDRAM_CONFIG_BANK_SIZE(reg) \
(0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17))
/* 440GP External Bus Controller (EBC) */
#define DCRN_EBC0_CFGADDR 0x012
#define DCRN_EBC0_CFGDATA 0x013
#define EBC_NUM_BANKS 8
#define EBC_B0CR 0x00
#define EBC_B1CR 0x01
#define EBC_B2CR 0x02
#define EBC_B3CR 0x03
#define EBC_B4CR 0x04
#define EBC_B5CR 0x05
#define EBC_B6CR 0x06
#define EBC_B7CR 0x07
#define EBC_BXCR(n) (n)
#define EBC_BXCR_BAS 0xfff00000
#define EBC_BXCR_BS 0x000e0000
#define EBC_BXCR_BANK_SIZE(reg) \
(0x100000 << (((reg) & EBC_BXCR_BS) >> 17))
#define EBC_BXCR_BU 0x00018000
#define EBC_BXCR_BU_OFF 0x00000000
#define EBC_BXCR_BU_RO 0x00008000
#define EBC_BXCR_BU_WO 0x00010000
#define EBC_BXCR_BU_RW 0x00018000
#define EBC_BXCR_BW 0x00006000
#define EBC_B0AP 0x10
#define EBC_B1AP 0x11
#define EBC_B2AP 0x12
#define EBC_B3AP 0x13
#define EBC_B4AP 0x14
#define EBC_B5AP 0x15
#define EBC_B6AP 0x16
#define EBC_B7AP 0x17
#define EBC_BXAP(n) (0x10+(n))
#define EBC_BEAR 0x20
#define EBC_BESR 0x21
#define EBC_CFG 0x23
#define EBC_CID 0x24
/* 440GP Clock, PM, chip control */
#define DCRN_CPC0_SR 0x0b0
#define DCRN_CPC0_ER 0x0b1

View File

@ -31,8 +31,8 @@
reg = <0>;
clock-frequency = <0>; // Filled in by zImage
timebase-frequency = <0>; // Filled in by zImage
i-cache-line-size = <32>;
d-cache-line-size = <32>;
i-cache-line-size = <20>;
d-cache-line-size = <20>;
i-cache-size = <8000>; /* 32 kB */
d-cache-size = <8000>; /* 32 kB */
dcr-controller;
@ -135,11 +135,9 @@
#address-cells = <2>;
#size-cells = <1>;
clock-frequency = <0>; // Filled in by zImage
ranges = <0 00000000 fff00000 100000
1 00000000 48000000 100000
2 00000000 ff800000 400000
3 00000000 48200000 100000
7 00000000 48300000 100000>;
// ranges property is supplied by zImage
// based on firmware's configuration of the
// EBC bridge
interrupts = <5 4>;
interrupt-parent = <&UIC1>;

View File

@ -46,7 +46,7 @@
tsi109@c0000000 {
device_type = "tsi-bridge";
compatible = "tsi-bridge";
compatible = "tsi109-bridge", "tsi108-bridge";
#address-cells = <1>;
#size-cells = <1>;
ranges = <00000000 c0000000 00010000>;
@ -54,52 +54,55 @@
i2c@7000 {
device_type = "i2c";
compatible = "tsi-i2c";
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
compatible = "tsi109-i2c", "tsi108-i2c";
interrupt-parent = <&MPIC>;
interrupts = <e 2>;
reg = <7000 400>;
};
mdio@6000 {
MDIO: mdio@6000 {
device_type = "mdio";
compatible = "tsi-ethernet";
PHY1: ethernet-phy@6000 {
device_type = "ethernet-phy";
compatible = "bcm54xx";
compatible = "tsi109-mdio", "tsi108-mdio";
reg = <6000 50>;
phy-id = <1>;
#address-cells = <1>;
#size-cells = <0>;
PHY1: ethernet-phy@1 {
compatible = "bcm5461a";
reg = <1>;
txc-rxc-delay-disable;
};
PHY2: ethernet-phy@6400 {
device_type = "ethernet-phy";
compatible = "bcm54xx";
reg = <6000 50>;
phy-id = <2>;
PHY2: ethernet-phy@2 {
compatible = "bcm5461a";
reg = <2>;
txc-rxc-delay-disable;
};
};
ethernet@6200 {
device_type = "network";
compatible = "tsi-ethernet";
compatible = "tsi109-ethernet", "tsi108-ethernet";
#address-cells = <1>;
#size-cells = <0>;
reg = <6000 200>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
interrupts = <10 2>;
mdio-handle = <&MDIO>;
phy-handle = <&PHY1>;
};
ethernet@6600 {
device_type = "network";
compatible = "tsi-ethernet";
compatible = "tsi109-ethernet", "tsi108-ethernet";
#address-cells = <1>;
#size-cells = <0>;
reg = <6400 200>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
interrupts = <11 2>;
mdio-handle = <&MDIO>;
phy-handle = <&PHY2>;
};
@ -110,7 +113,7 @@
virtual-reg = <c0007808>;
clock-frequency = <3F9C6000>;
current-speed = <1c200>;
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
interrupts = <c 2>;
};
@ -121,7 +124,7 @@
virtual-reg = <c0007c08>;
clock-frequency = <3F9C6000>;
current-speed = <1c200>;
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
interrupts = <d 2>;
};
@ -136,7 +139,7 @@
pci@1000 {
device_type = "pci";
compatible = "tsi109";
compatible = "tsi109-pci", "tsi108-pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@ -150,7 +153,7 @@
ranges = <02000000 0 40000000 40000000 0 10000000
01000000 0 00000000 7e000000 0 00010000>;
clock-frequency = <7f28154>;
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
interrupts = <17 2>;
interrupt-map-mask = <f800 0 0 7>;
/*----------------------------------------------------+
@ -186,13 +189,12 @@
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <17 2>;
interrupt-parent = < &/tsi109@c0000000/pic@7400 >;
interrupt-parent = <&MPIC>;
};
};
};
chosen {
linux,stdout-path = "/tsi109@c0000000/serial@7808";
bootargs = "console=ttyS0,115200";
};
};

View File

@ -45,7 +45,7 @@
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "tsi-bridge";
device_type = "tsi108-bridge";
ranges = <00000000 c0000000 00010000>;
reg = <c0000000 00010000>;
bus-frequency = <0>;
@ -55,27 +55,26 @@
interrupts = <E 0>;
reg = <7000 400>;
device_type = "i2c";
compatible = "tsi-i2c";
compatible = "tsi108-i2c";
};
mdio@6000 {
MDIO: mdio@6000 {
device_type = "mdio";
compatible = "tsi-ethernet";
compatible = "tsi108-mdio";
reg = <6000 50>;
#address-cells = <1>;
#size-cells = <0>;
phy8: ethernet-phy@6000 {
phy8: ethernet-phy@8 {
interrupt-parent = <&mpic>;
interrupts = <2 1>;
reg = <6000 50>;
phy-id = <8>;
device_type = "ethernet-phy";
reg = <8>;
};
phy9: ethernet-phy@6400 {
phy9: ethernet-phy@9 {
interrupt-parent = <&mpic>;
interrupts = <2 1>;
reg = <6000 50>;
phy-id = <9>;
device_type = "ethernet-phy";
reg = <9>;
};
};
@ -83,12 +82,12 @@
ethernet@6200 {
#size-cells = <0>;
device_type = "network";
model = "TSI-ETH";
compatible = "tsi-ethernet";
compatible = "tsi108-ethernet";
reg = <6000 200>;
address = [ 00 06 D2 00 00 01 ];
interrupts = <10 2>;
interrupt-parent = <&mpic>;
mdio-handle = <&MDIO>;
phy-handle = <&phy8>;
};
@ -96,12 +95,12 @@
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
model = "TSI-ETH";
compatible = "tsi-ethernet";
compatible = "tsi108-ethernet";
reg = <6400 200>;
address = [ 00 06 D2 00 00 02 ];
interrupts = <11 2>;
interrupt-parent = <&mpic>;
mdio-handle = <&MDIO>;
phy-handle = <&phy9>;
};
@ -135,7 +134,7 @@
big-endian;
};
pci@1000 {
compatible = "tsi10x";
compatible = "tsi108-pci";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;

View File

@ -14,12 +14,10 @@
compatible = "MPC8260ADS";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;
PowerPC,8272@0 {
device_type = "cpu";
@ -32,12 +30,10 @@
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
linux,phandle = <201>;
};
};
interrupt-controller@f8200000 {
linux,phandle = <f8200000>;
pci_pic: interrupt-controller@f8200000 {
#address-cells = <0>;
#interrupt-cells = <2>;
interrupt-controller;
@ -47,15 +43,13 @@
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 4000000 f4500000 00000020>;
};
chosen {
name = "chosen";
linux,platform = <0>;
interrupt-controller = <10c00>;
linux,phandle = <400>;
interrupt-controller = <&Cpm_pic>;
};
soc8272@f0000000 {
@ -70,20 +64,17 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <0 0>;
linux,phandle = <24520>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
linux,phandle = <2452000>;
interrupt-parent = <10c00>;
phy0:ethernet-phy@0 {
interrupt-parent = <&Cpm_pic>;
interrupts = <17 4>;
reg = <0>;
bitbang = [ 12 12 13 02 02 01 ];
device_type = "ethernet-phy";
};
ethernet-phy@1 {
linux,phandle = <2452001>;
interrupt-parent = <10c00>;
phy1:ethernet-phy@1 {
interrupt-parent = <&Cpm_pic>;
interrupts = <17 4>;
bitbang = [ 12 12 13 02 02 01 ];
reg = <3>;
@ -101,8 +92,8 @@
reg = <11300 20 8400 100 11380 30>;
mac-address = [ 00 11 2F 99 43 54 ];
interrupts = <20 2>;
interrupt-parent = <10c00>;
phy-handle = <2452000>;
interrupt-parent = <&Cpm_pic>;
phy-handle = <&Phy0>;
rx-clock = <13>;
tx-clock = <12>;
};
@ -115,14 +106,13 @@
reg = <11320 20 8500 100 113b0 30>;
mac-address = [ 00 11 2F 99 44 54 ];
interrupts = <21 2>;
interrupt-parent = <10c00>;
phy-handle = <2452001>;
interrupt-parent = <&Cpm_pic>;
phy-handle = <&Phy1>;
rx-clock = <17>;
tx-clock = <18>;
};
cpm@f0000000 {
linux,phandle = <f0000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@ -142,7 +132,7 @@
reg = <11a00 20 8000 100>;
current-speed = <1c200>;
interrupts = <28 2>;
interrupt-parent = <10c00>;
interrupt-parent = <&Cpm_pic>;
clock-setup = <0 00ffffff>;
rx-clock = <1>;
tx-clock = <1>;
@ -156,15 +146,14 @@
reg = <11a60 20 8300 100>;
current-speed = <1c200>;
interrupts = <2b 2>;
interrupt-parent = <10c00>;
interrupt-parent = <&Cpm_pic>;
clock-setup = <1b ffffff00>;
rx-clock = <4>;
tx-clock = <4>;
};
};
interrupt-controller@10c00 {
linux,phandle = <10c00>;
cpm_pic:interrupt-controller@10c00 {
#address-cells = <0>;
#interrupt-cells = <2>;
interrupt-controller;
@ -174,7 +163,6 @@
compatible = "CPM2";
};
pci@0500 {
linux,phandle = <0500>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@ -202,7 +190,7 @@
c000 0 0 2 f8200000 43 8
c000 0 0 3 f8200000 40 8
c000 0 0 4 f8200000 41 8>;
interrupt-parent = <10c00>;
interrupt-parent = <&Cpm_pic>;
interrupts = <14 8>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 40000000
@ -216,7 +204,7 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 2>;
interrupt-parent = <10c00>;
interrupt-parent = <&Cpm_pic>;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;

View File

@ -272,7 +272,13 @@
reg = <2200 200>;
interrupts = <22>;
interrupt-parent = < &qeic >;
mac-address = [ 00 04 9f 00 23 23 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <19>;
tx-clock = <1a>;
phy-handle = < &phy3 >;
@ -287,7 +293,13 @@
reg = <3000 200>;
interrupts = <23>;
interrupt-parent = < &qeic >;
mac-address = [ 00 11 22 33 44 55 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <17>;
tx-clock = <18>;
phy-handle = < &phy4 >;

View File

@ -231,7 +231,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f ef 03 02 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <20>;
tx-clock = <13>;
phy-handle = <&phy00>;
@ -246,7 +252,13 @@
reg = <2200 200>;
interrupts = <22>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f ef 03 01 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <19>;
tx-clock = <1a>;
phy-handle = <&phy04>;

View File

@ -131,6 +131,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
@ -145,6 +150,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;

View File

@ -136,6 +136,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
@ -150,6 +155,11 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;

View File

@ -301,7 +301,13 @@
reg = <2000 200>;
interrupts = <20>;
interrupt-parent = < &qeic >;
mac-address = [ 00 04 9f 00 23 23 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <19>;
phy-handle = < &phy0 >;
@ -317,7 +323,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = < &qeic >;
mac-address = [ 00 11 22 33 44 55 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <14>;
phy-handle = < &phy1 >;

View File

@ -52,7 +52,7 @@
compatible = "fsl,8540-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -81,19 +81,19 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <35 1>;
interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <35 1>;
interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
interrupts = <37 1>;
interrupts = <7 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -106,9 +106,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
address = [ 00 E0 0C 00 73 00 ];
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -120,9 +125,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
address = [ 00 E0 0C 00 73 01 ];
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -134,9 +144,14 @@
model = "FEC";
compatible = "gianfar";
reg = <26000 1000>;
address = [ 00 E0 0C 00 73 02 ];
local-mac-address = [ 00 E0 0C 00 73 02 ];
interrupts = <19 2>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <29 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@ -146,7 +161,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -155,7 +170,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
pci@8000 {
@ -163,78 +178,78 @@
interrupt-map = <
/* IDSEL 0x02 */
1000 0 0 1 &mpic 31 1
1000 0 0 2 &mpic 32 1
1000 0 0 3 &mpic 33 1
1000 0 0 4 &mpic 34 1
1000 0 0 1 &mpic 1 1
1000 0 0 2 &mpic 2 1
1000 0 0 3 &mpic 3 1
1000 0 0 4 &mpic 4 1
/* IDSEL 0x03 */
1800 0 0 1 &mpic 34 1
1800 0 0 2 &mpic 31 1
1800 0 0 3 &mpic 32 1
1800 0 0 4 &mpic 33 1
1800 0 0 1 &mpic 4 1
1800 0 0 2 &mpic 1 1
1800 0 0 3 &mpic 2 1
1800 0 0 4 &mpic 3 1
/* IDSEL 0x04 */
2000 0 0 1 &mpic 33 1
2000 0 0 2 &mpic 34 1
2000 0 0 3 &mpic 31 1
2000 0 0 4 &mpic 32 1
2000 0 0 1 &mpic 3 1
2000 0 0 2 &mpic 4 1
2000 0 0 3 &mpic 1 1
2000 0 0 4 &mpic 2 1
/* IDSEL 0x05 */
2800 0 0 1 &mpic 32 1
2800 0 0 2 &mpic 33 1
2800 0 0 3 &mpic 34 1
2800 0 0 4 &mpic 31 1
2800 0 0 1 &mpic 2 1
2800 0 0 2 &mpic 3 1
2800 0 0 3 &mpic 4 1
2800 0 0 4 &mpic 1 1
/* IDSEL 0x0c */
6000 0 0 1 &mpic 31 1
6000 0 0 2 &mpic 32 1
6000 0 0 3 &mpic 33 1
6000 0 0 4 &mpic 34 1
6000 0 0 1 &mpic 1 1
6000 0 0 2 &mpic 2 1
6000 0 0 3 &mpic 3 1
6000 0 0 4 &mpic 4 1
/* IDSEL 0x0d */
6800 0 0 1 &mpic 34 1
6800 0 0 2 &mpic 31 1
6800 0 0 3 &mpic 32 1
6800 0 0 4 &mpic 33 1
6800 0 0 1 &mpic 4 1
6800 0 0 2 &mpic 1 1
6800 0 0 3 &mpic 2 1
6800 0 0 4 &mpic 3 1
/* IDSEL 0x0e */
7000 0 0 1 &mpic 33 1
7000 0 0 2 &mpic 34 1
7000 0 0 3 &mpic 31 1
7000 0 0 4 &mpic 32 1
7000 0 0 1 &mpic 3 1
7000 0 0 2 &mpic 4 1
7000 0 0 3 &mpic 1 1
7000 0 0 4 &mpic 2 1
/* IDSEL 0x0f */
7800 0 0 1 &mpic 32 1
7800 0 0 2 &mpic 33 1
7800 0 0 3 &mpic 34 1
7800 0 0 4 &mpic 31 1
7800 0 0 1 &mpic 2 1
7800 0 0 2 &mpic 3 1
7800 0 0 3 &mpic 4 1
7800 0 0 4 &mpic 1 1
/* IDSEL 0x12 */
9000 0 0 1 &mpic 31 1
9000 0 0 2 &mpic 32 1
9000 0 0 3 &mpic 33 1
9000 0 0 4 &mpic 34 1
9000 0 0 1 &mpic 1 1
9000 0 0 2 &mpic 2 1
9000 0 0 3 &mpic 3 1
9000 0 0 4 &mpic 4 1
/* IDSEL 0x13 */
9800 0 0 1 &mpic 34 1
9800 0 0 2 &mpic 31 1
9800 0 0 3 &mpic 32 1
9800 0 0 4 &mpic 33 1
9800 0 0 1 &mpic 4 1
9800 0 0 2 &mpic 1 1
9800 0 0 3 &mpic 2 1
9800 0 0 4 &mpic 3 1
/* IDSEL 0x14 */
a000 0 0 1 &mpic 33 1
a000 0 0 2 &mpic 34 1
a000 0 0 3 &mpic 31 1
a000 0 0 4 &mpic 32 1
a000 0 0 1 &mpic 3 1
a000 0 0 2 &mpic 4 1
a000 0 0 3 &mpic 1 1
a000 0 0 4 &mpic 2 1
/* IDSEL 0x15 */
a800 0 0 1 &mpic 32 1
a800 0 0 2 &mpic 33 1
a800 0 0 3 &mpic 34 1
a800 0 0 4 &mpic 31 1>;
a800 0 0 1 &mpic 2 1
a800 0 0 2 &mpic 3 1
a800 0 0 3 &mpic 4 1
a800 0 0 4 &mpic 1 1>;
interrupt-parent = <&mpic>;
interrupts = <08 2>;
interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;

View File

@ -52,7 +52,7 @@
compatible = "fsl,8541-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@ -100,8 +100,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -113,8 +113,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -142,49 +142,49 @@
interrupt-map = <
/* IDSEL 0x10 */
08000 0 0 1 &mpic 30 1
08000 0 0 2 &mpic 31 1
08000 0 0 3 &mpic 32 1
08000 0 0 4 &mpic 33 1
08000 0 0 1 &mpic 0 1
08000 0 0 2 &mpic 1 1
08000 0 0 3 &mpic 2 1
08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
08800 0 0 1 &mpic 30 1
08800 0 0 2 &mpic 31 1
08800 0 0 3 &mpic 32 1
08800 0 0 4 &mpic 33 1
08800 0 0 1 &mpic 0 1
08800 0 0 2 &mpic 1 1
08800 0 0 3 &mpic 2 1
08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
09000 0 0 1 &mpic 30 1
09000 0 0 2 &mpic 31 1
09000 0 0 3 &mpic 32 1
09000 0 0 4 &mpic 33 1
09000 0 0 1 &mpic 0 1
09000 0 0 2 &mpic 1 1
09000 0 0 3 &mpic 2 1
09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
09800 0 0 1 &mpic 31 1
09800 0 0 2 &mpic 32 1
09800 0 0 3 &mpic 33 1
09800 0 0 4 &mpic 30 1
09800 0 0 1 &mpic 1 1
09800 0 0 2 &mpic 2 1
09800 0 0 3 &mpic 3 1
09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
0a000 0 0 1 &mpic 32 1
0a000 0 0 2 &mpic 33 1
0a000 0 0 3 &mpic 30 1
0a000 0 0 4 &mpic 31 1
0a000 0 0 1 &mpic 2 1
0a000 0 0 2 &mpic 3 1
0a000 0 0 3 &mpic 0 1
0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
0a800 0 0 1 &mpic 33 1
0a800 0 0 2 &mpic 30 1
0a800 0 0 3 &mpic 31 1
0a800 0 0 4 &mpic 32 1
0a800 0 0 1 &mpic 3 1
0a800 0 0 2 &mpic 0 1
0a800 0 0 3 &mpic 1 1
0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
19000 0 0 1 &mpic 30 1
19000 0 0 2 &mpic 31 1
19000 0 0 3 &mpic 32 1
19000 0 0 4 &mpic 33 1>;
19000 0 0 1 &mpic 0 1
19000 0 0 2 &mpic 1 1
19000 0 0 3 &mpic 2 1
19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
interrupts = <08 2>;
interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@ -216,12 +216,12 @@
interrupt-map = <
/* IDSEL 0x15 */
a800 0 0 1 &mpic 3b 1
a800 0 0 2 &mpic 3b 1
a800 0 0 3 &mpic 3b 1
a800 0 0 4 &mpic 3b 1>;
a800 0 0 1 &mpic b 1
a800 0 0 2 &mpic b 1
a800 0 0 3 &mpic b 1
a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
interrupts = <09 2>;
interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;

View File

@ -52,7 +52,7 @@
compatible = "fsl,8544-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <3a 1>;
interrupts = <a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <3a 1>;
interrupts = <a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@ -101,7 +101,7 @@
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <d 2 e 2 12 2>;
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -114,7 +114,7 @@
compatible = "gianfar";
reg = <26000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <f 2 10 2 11 2>;
interrupts = <1f 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};

View File

@ -52,7 +52,7 @@
compatible = "fsl,8548-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <80000>; // L2, 512K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -81,25 +81,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -112,8 +112,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -125,8 +125,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -139,8 +139,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <26000 1000>;
local-mac-address = [ 00 E0 0C 00 73 02 ];
interrupts = <f 2 10 2 11 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1f 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
};
@ -152,8 +152,8 @@
model = "eTSEC";
compatible = "gianfar";
reg = <27000 1000>;
local-mac-address = [ 00 E0 0C 00 73 03 ];
interrupts = <15 2 16 2 17 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <25 2 26 2 27 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@ -164,7 +164,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -173,58 +173,64 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
global-utilities@e0000 { //global utilities reg
compatible = "fsl,mpc8548-guts";
reg = <e0000 1000>;
fsl,has-rstcr;
};
pci1: pci@8000 {
interrupt-map-mask = <1f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 */
08000 0 0 1 &mpic 30 1
08000 0 0 2 &mpic 31 1
08000 0 0 3 &mpic 32 1
08000 0 0 4 &mpic 33 1
08000 0 0 1 &mpic 0 1
08000 0 0 2 &mpic 1 1
08000 0 0 3 &mpic 2 1
08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
08800 0 0 1 &mpic 30 1
08800 0 0 2 &mpic 31 1
08800 0 0 3 &mpic 32 1
08800 0 0 4 &mpic 33 1
08800 0 0 1 &mpic 0 1
08800 0 0 2 &mpic 1 1
08800 0 0 3 &mpic 2 1
08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
09000 0 0 1 &mpic 30 1
09000 0 0 2 &mpic 31 1
09000 0 0 3 &mpic 32 1
09000 0 0 4 &mpic 33 1
09000 0 0 1 &mpic 0 1
09000 0 0 2 &mpic 1 1
09000 0 0 3 &mpic 2 1
09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
09800 0 0 1 &mpic 31 1
09800 0 0 2 &mpic 32 1
09800 0 0 3 &mpic 33 1
09800 0 0 4 &mpic 30 1
09800 0 0 1 &mpic 1 1
09800 0 0 2 &mpic 2 1
09800 0 0 3 &mpic 3 1
09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
0a000 0 0 1 &mpic 32 1
0a000 0 0 2 &mpic 33 1
0a000 0 0 3 &mpic 30 1
0a000 0 0 4 &mpic 31 1
0a000 0 0 1 &mpic 2 1
0a000 0 0 2 &mpic 3 1
0a000 0 0 3 &mpic 0 1
0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
0a800 0 0 1 &mpic 33 1
0a800 0 0 2 &mpic 30 1
0a800 0 0 3 &mpic 31 1
0a800 0 0 4 &mpic 32 1
0a800 0 0 1 &mpic 3 1
0a800 0 0 2 &mpic 0 1
0a800 0 0 3 &mpic 1 1
0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
19000 0 0 1 &mpic 30 1
19000 0 0 2 &mpic 31 1
19000 0 0 3 &mpic 32 1
19000 0 0 4 &mpic 33 1>;
19000 0 0 1 &mpic 0 1
19000 0 0 2 &mpic 1 1
19000 0 0 3 &mpic 2 1
19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
interrupts = <08 2>;
interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@ -256,12 +262,12 @@
interrupt-map = <
/* IDSEL 0x15 */
a800 0 0 1 &mpic 3b 1
a800 0 0 2 &mpic 3b 1
a800 0 0 3 &mpic 3b 1
a800 0 0 4 &mpic 3b 1>;
a800 0 0 1 &mpic b 1
a800 0 0 2 &mpic b 1
a800 0 0 3 &mpic b 1
a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
interrupts = <09 2>;
interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;

View File

@ -52,7 +52,7 @@
compatible = "fsl,8555-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,14 +61,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -81,13 +81,13 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <35 0>;
interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
@ -100,8 +100,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <0d 2 0e 2 12 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -113,8 +113,8 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -124,7 +124,7 @@
compatible = "ns16550";
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -133,7 +133,7 @@
compatible = "ns16550";
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -142,49 +142,49 @@
interrupt-map = <
/* IDSEL 0x10 */
08000 0 0 1 &mpic 30 1
08000 0 0 2 &mpic 31 1
08000 0 0 3 &mpic 32 1
08000 0 0 4 &mpic 33 1
08000 0 0 1 &mpic 0 1
08000 0 0 2 &mpic 1 1
08000 0 0 3 &mpic 2 1
08000 0 0 4 &mpic 3 1
/* IDSEL 0x11 */
08800 0 0 1 &mpic 30 1
08800 0 0 2 &mpic 31 1
08800 0 0 3 &mpic 32 1
08800 0 0 4 &mpic 33 1
08800 0 0 1 &mpic 0 1
08800 0 0 2 &mpic 1 1
08800 0 0 3 &mpic 2 1
08800 0 0 4 &mpic 3 1
/* IDSEL 0x12 (Slot 1) */
09000 0 0 1 &mpic 30 1
09000 0 0 2 &mpic 31 1
09000 0 0 3 &mpic 32 1
09000 0 0 4 &mpic 33 1
09000 0 0 1 &mpic 0 1
09000 0 0 2 &mpic 1 1
09000 0 0 3 &mpic 2 1
09000 0 0 4 &mpic 3 1
/* IDSEL 0x13 (Slot 2) */
09800 0 0 1 &mpic 31 1
09800 0 0 2 &mpic 32 1
09800 0 0 3 &mpic 33 1
09800 0 0 4 &mpic 30 1
09800 0 0 1 &mpic 1 1
09800 0 0 2 &mpic 2 1
09800 0 0 3 &mpic 3 1
09800 0 0 4 &mpic 0 1
/* IDSEL 0x14 (Slot 3) */
0a000 0 0 1 &mpic 32 1
0a000 0 0 2 &mpic 33 1
0a000 0 0 3 &mpic 30 1
0a000 0 0 4 &mpic 31 1
0a000 0 0 1 &mpic 2 1
0a000 0 0 2 &mpic 3 1
0a000 0 0 3 &mpic 0 1
0a000 0 0 4 &mpic 1 1
/* IDSEL 0x15 (Slot 4) */
0a800 0 0 1 &mpic 33 1
0a800 0 0 2 &mpic 30 1
0a800 0 0 3 &mpic 31 1
0a800 0 0 4 &mpic 32 1
0a800 0 0 1 &mpic 3 1
0a800 0 0 2 &mpic 0 1
0a800 0 0 3 &mpic 1 1
0a800 0 0 4 &mpic 2 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
19000 0 0 1 &mpic 30 1
19000 0 0 2 &mpic 31 1
19000 0 0 3 &mpic 32 1
19000 0 0 4 &mpic 33 1>;
19000 0 0 1 &mpic 0 1
19000 0 0 2 &mpic 1 1
19000 0 0 3 &mpic 2 1
19000 0 0 4 &mpic 3 1>;
interrupt-parent = <&mpic>;
interrupts = <08 2>;
interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
@ -216,12 +216,12 @@
interrupt-map = <
/* IDSEL 0x15 */
a800 0 0 1 &mpic 3b 1
a800 0 0 2 &mpic 3b 1
a800 0 0 3 &mpic 3b 1
a800 0 0 4 &mpic 3b 1>;
a800 0 0 1 &mpic b 1
a800 0 0 2 &mpic b 1
a800 0 0 3 &mpic b 1
a800 0 0 4 &mpic b 1>;
interrupt-parent = <&mpic>;
interrupts = <09 2>;
interrupts = <19 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;

View File

@ -52,7 +52,7 @@
compatible = "fsl,8540-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -61,7 +61,7 @@
cache-line-size = <20>; // 32 bytes
cache-size = <40000>; // L2, 256K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
mdio@24520 {
@ -72,25 +72,25 @@
#size-cells = <0>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <35 1>;
interrupts = <5 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <35 1>;
interrupts = <5 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
interrupts = <37 1>;
interrupts = <7 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
interrupts = <37 1>;
interrupts = <7 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -101,8 +101,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
address = [ 00 00 0C 00 00 FD ];
interrupts = <d 2 e 2 12 2>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
@ -114,8 +120,14 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
address = [ 00 00 0C 00 01 FD ];
interrupts = <13 2 14 2 18 2>;
/*
* address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
@ -132,79 +144,79 @@
interrupt-map = <
/* IDSEL 0x2 */
1000 0 0 1 &mpic 31 1
1000 0 0 2 &mpic 32 1
1000 0 0 3 &mpic 33 1
1000 0 0 4 &mpic 34 1
1000 0 0 1 &mpic 1 1
1000 0 0 2 &mpic 2 1
1000 0 0 3 &mpic 3 1
1000 0 0 4 &mpic 4 1
/* IDSEL 0x3 */
1800 0 0 1 &mpic 34 1
1800 0 0 2 &mpic 31 1
1800 0 0 3 &mpic 32 1
1800 0 0 4 &mpic 33 1
1800 0 0 1 &mpic 4 1
1800 0 0 2 &mpic 1 1
1800 0 0 3 &mpic 2 1
1800 0 0 4 &mpic 3 1
/* IDSEL 0x4 */
2000 0 0 1 &mpic 33 1
2000 0 0 2 &mpic 34 1
2000 0 0 3 &mpic 31 1
2000 0 0 4 &mpic 32 1
2000 0 0 1 &mpic 3 1
2000 0 0 2 &mpic 4 1
2000 0 0 3 &mpic 1 1
2000 0 0 4 &mpic 2 1
/* IDSEL 0x5 */
2800 0 0 1 &mpic 32 1
2800 0 0 2 &mpic 33 1
2800 0 0 3 &mpic 34 1
2800 0 0 4 &mpic 31 1
2800 0 0 1 &mpic 2 1
2800 0 0 2 &mpic 3 1
2800 0 0 3 &mpic 4 1
2800 0 0 4 &mpic 1 1
/* IDSEL 12 */
6000 0 0 1 &mpic 31 1
6000 0 0 2 &mpic 32 1
6000 0 0 3 &mpic 33 1
6000 0 0 4 &mpic 34 1
6000 0 0 1 &mpic 1 1
6000 0 0 2 &mpic 2 1
6000 0 0 3 &mpic 3 1
6000 0 0 4 &mpic 4 1
/* IDSEL 13 */
6800 0 0 1 &mpic 34 1
6800 0 0 2 &mpic 31 1
6800 0 0 3 &mpic 32 1
6800 0 0 4 &mpic 33 1
6800 0 0 1 &mpic 4 1
6800 0 0 2 &mpic 1 1
6800 0 0 3 &mpic 2 1
6800 0 0 4 &mpic 3 1
/* IDSEL 14*/
7000 0 0 1 &mpic 33 1
7000 0 0 2 &mpic 34 1
7000 0 0 3 &mpic 31 1
7000 0 0 4 &mpic 32 1
7000 0 0 1 &mpic 3 1
7000 0 0 2 &mpic 4 1
7000 0 0 3 &mpic 1 1
7000 0 0 4 &mpic 2 1
/* IDSEL 15 */
7800 0 0 1 &mpic 32 1
7800 0 0 2 &mpic 33 1
7800 0 0 3 &mpic 34 1
7800 0 0 4 &mpic 31 1
7800 0 0 1 &mpic 2 1
7800 0 0 2 &mpic 3 1
7800 0 0 3 &mpic 4 1
7800 0 0 4 &mpic 1 1
/* IDSEL 18 */
9000 0 0 1 &mpic 31 1
9000 0 0 2 &mpic 32 1
9000 0 0 3 &mpic 33 1
9000 0 0 4 &mpic 34 1
9000 0 0 1 &mpic 1 1
9000 0 0 2 &mpic 2 1
9000 0 0 3 &mpic 3 1
9000 0 0 4 &mpic 4 1
/* IDSEL 19 */
9800 0 0 1 &mpic 34 1
9800 0 0 2 &mpic 31 1
9800 0 0 3 &mpic 32 1
9800 0 0 4 &mpic 33 1
9800 0 0 1 &mpic 4 1
9800 0 0 2 &mpic 1 1
9800 0 0 3 &mpic 2 1
9800 0 0 4 &mpic 3 1
/* IDSEL 20 */
a000 0 0 1 &mpic 33 1
a000 0 0 2 &mpic 34 1
a000 0 0 3 &mpic 31 1
a000 0 0 4 &mpic 32 1
a000 0 0 1 &mpic 3 1
a000 0 0 2 &mpic 4 1
a000 0 0 3 &mpic 1 1
a000 0 0 4 &mpic 2 1
/* IDSEL 21 */
a800 0 0 1 &mpic 32 1
a800 0 0 2 &mpic 33 1
a800 0 0 3 &mpic 34 1
a800 0 0 4 &mpic 31 1>;
a800 0 0 1 &mpic 2 1
a800 0 0 2 &mpic 3 1
a800 0 0 3 &mpic 4 1
a800 0 0 4 &mpic 1 1>;
interrupt-parent = <&mpic>;
interrupts = <8 0>;
interrupts = <18 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 01000000>;
@ -234,7 +246,7 @@
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <1e 0>;
interrupts = <2e 2>;
interrupt-parent = <&mpic>;
reg = <90c00 80>;
built-in;
@ -275,7 +287,13 @@
model = "FCC";
device-id = <2>;
reg = <91320 20 88500 100 913a0 30>;
mac-address = [ 00 00 0C 00 02 FD ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
clock-setup = <ff00ffff 250000>;
rx-clock = <15>;
tx-clock = <16>;
@ -290,7 +308,13 @@
model = "FCC";
device-id = <3>;
reg = <91340 20 88600 100 913d0 30>;
mac-address = [ 00 00 0C 00 03 FD ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
clock-setup = <ffff00ff 3700>;
rx-clock = <17>;
tx-clock = <18>;

View File

@ -61,7 +61,7 @@
compatible = "fsl,8568-memory-controller";
reg = <2000 1000>;
interrupt-parent = <&mpic>;
interrupts = <2 2>;
interrupts = <12 2>;
};
l2-cache-controller@20000 {
@ -70,14 +70,14 @@
cache-line-size = <20>; // 32 bytes
cache-size = <80000>; // L2, 512K
interrupt-parent = <&mpic>;
interrupts = <0 2>;
interrupts = <10 2>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -86,7 +86,7 @@
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <1b 2>;
interrupts = <2b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
@ -99,25 +99,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <31 1>;
interrupts = <1 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
interrupts = <2 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
interrupts = <31 1>;
interrupts = <1 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
interrupts = <2 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -130,8 +130,14 @@
model = "eTSEC";
compatible = "gianfar";
reg = <24000 1000>;
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
interrupts = <d 2 e 2 12 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
};
@ -143,8 +149,14 @@
model = "eTSEC";
compatible = "gianfar";
reg = <25000 1000>;
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
interrupts = <13 2 14 2 18 2>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
};
@ -154,7 +166,7 @@
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -163,7 +175,7 @@
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupts = <2a 2>;
interrupt-parent = <&mpic>;
};
@ -172,7 +184,7 @@
model = "SEC2";
compatible = "talitos";
reg = <30000 f000>;
interrupts = <1d 2>;
interrupts = <2d 2>;
interrupt-parent = <&mpic>;
num-channels = <4>;
channel-fifo-len = <18>;
@ -300,7 +312,13 @@
reg = <2000 200>;
interrupts = <20>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f 00 23 23 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <19>;
phy-handle = <&qe_phy0>;
@ -316,7 +334,13 @@
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
mac-address = [ 00 11 22 33 44 55 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
rx-clock = <0>;
tx-clock = <14>;
phy-handle = <&qe_phy1>;
@ -335,25 +359,25 @@
* gianfar's MDIO bus */
qe_phy0: ethernet-phy@00 {
interrupt-parent = <&mpic>;
interrupts = <31 1>;
interrupts = <1 1>;
reg = <0>;
device_type = "ethernet-phy";
};
qe_phy1: ethernet-phy@01 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
interrupts = <2 1>;
reg = <1>;
device_type = "ethernet-phy";
};
qe_phy2: ethernet-phy@02 {
interrupt-parent = <&mpic>;
interrupts = <31 1>;
interrupts = <1 1>;
reg = <2>;
device_type = "ethernet-phy";
};
qe_phy3: ethernet-phy@03 {
interrupt-parent = <&mpic>;
interrupts = <32 1>;
interrupts = <2 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -367,7 +391,7 @@
reg = <80 80>;
built-in;
big-endian;
interrupts = <1e 2 1e 2>; //high:30 low:30
interrupts = <2e 2 2e 2>; //high:30 low:30
interrupt-parent = <&mpic>;
};

View File

@ -56,8 +56,12 @@
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
ranges = <0 f8000000 00100000>;
reg = <f8000000 00100000>; // CCSRBAR 1M
ranges = <00001000 f8001000 000ff000
80000000 80000000 20000000
e2000000 e2000000 00100000
a0000000 a0000000 20000000
e3000000 e3000000 00100000>;
reg = <f8000000 00001000>; // CCSRBAR
bus-frequency = <0>;
i2c@3000 {
@ -86,25 +90,25 @@
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <4a 1>;
interrupts = <a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <4a 1>;
interrupts = <a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
phy2: ethernet-phy@2 {
interrupt-parent = <&mpic>;
interrupts = <4a 1>;
interrupts = <a 1>;
reg = <2>;
device_type = "ethernet-phy";
};
phy3: ethernet-phy@3 {
interrupt-parent = <&mpic>;
interrupts = <4a 1>;
interrupts = <a 1>;
reg = <3>;
device_type = "ethernet-phy";
};
@ -117,7 +121,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
mac-address = [ 00 E0 0C 00 73 00 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1d 2 1e 2 22 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
@ -130,7 +140,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
mac-address = [ 00 E0 0C 00 73 01 ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 2 24 2 28 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
@ -143,7 +159,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <26000 1000>;
mac-address = [ 00 E0 0C 00 02 FD ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <1F 2 20 2 21 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy2>;
@ -156,7 +178,13 @@
model = "TSEC";
compatible = "gianfar";
reg = <27000 1000>;
mac-address = [ 00 E0 0C 00 03 FD ];
/*
* mac-address is deprecated and will be removed
* in 2.6.25. Only recent versions of
* U-Boot support local-mac-address, however.
*/
mac-address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <25 2 26 2 27 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy3>;
@ -186,7 +214,7 @@
#size-cells = <2>;
#address-cells = <3>;
reg = <8000 1000>;
bus-range = <0 fe>;
bus-range = <0 ff>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
clock-frequency = <1fca055>;
@ -285,7 +313,42 @@
f800 0 0 3 &i8259 0 0
f800 0 0 4 &i8259 0 0
>;
i8259: i8259@4d0 {
uli1575@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
#address-cells = <3>;
ranges = <02000000 0 80000000
02000000 0 80000000
0 20000000
01000000 0 00000000
01000000 0 00000000
0 00100000>;
pci_bridge@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
#address-cells = <3>;
ranges = <02000000 0 80000000
02000000 0 80000000
0 20000000
01000000 0 00000000
01000000 0 00000000
0 00100000>;
isa@1e {
device_type = "isa";
#interrupt-cells = <2>;
#size-cells = <1>;
#address-cells = <2>;
reg = <f000 0 0 0 0>;
ranges = <1 0 01000000 0 0
00001000>;
interrupt-parent = <&i8259>;
i8259: interrupt-controller@20 {
reg = <1 20 2
1 a0 2
1 4d0 2>;
clock-frequency = <0>;
interrupt-controller;
device_type = "interrupt-controller";
@ -293,9 +356,41 @@
#interrupt-cells = <2>;
built-in;
compatible = "chrp,iic";
big-endian;
interrupts = <49 2>;
interrupt-parent = <&mpic>;
interrupts = <9 2>;
interrupt-parent =
<&mpic>;
};
i8042@60 {
#size-cells = <0>;
#address-cells = <1>;
reg = <1 60 1 1 64 1>;
interrupts = <1 3 c 3>;
interrupt-parent =
<&i8259>;
keyboard@0 {
reg = <0>;
compatible = "pnpPNP,303";
};
mouse@1 {
reg = <1>;
compatible = "pnpPNP,f03";
};
};
rtc@70 {
compatible =
"pnpPNP,b00";
reg = <1 70 2>;
};
gpio@400 {
reg = <1 400 80>;
};
};
};
};
};
@ -316,10 +411,10 @@
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0 */
0000 0 0 1 &mpic 44 1
0000 0 0 2 &mpic 45 1
0000 0 0 3 &mpic 46 1
0000 0 0 4 &mpic 47 1
0000 0 0 1 &mpic 4 1
0000 0 0 2 &mpic 5 1
0000 0 0 3 &mpic 6 1
0000 0 0 4 &mpic 7 1
>;
};

View File

@ -15,12 +15,10 @@
compatible = "mpc8xx";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;
PowerPC,866@0 {
device_type = "cpu";
@ -34,14 +32,12 @@
clock-frequency = <0>;
32-bit;
interrupts = <f 2>; // decrementer interrupt
interrupt-parent = <ff000000>;
linux,phandle = <201>;
interrupt-parent = <&Mpc8xx_pic>;
};
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 800000>;
};
@ -57,11 +53,9 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <e80 8>;
linux,phandle = <e80>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@f {
linux,phandle = <e800f>;
phy: ethernet-phy@f {
reg = <f>;
device_type = "ethernet-phy";
};
@ -75,12 +69,11 @@
reg = <e00 188>;
mac-address = [ 00 00 0C 00 01 FD ];
interrupts = <3 1>;
interrupt-parent = <ff000000>;
phy-handle = <e800f>;
interrupt-parent = <&Mpc8xx_pic>;
phy-handle = <&Phy>;
};
pic@ff000000 {
linux,phandle = <ff000000>;
mpc8xx_pic: pic@ff000000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@ -91,7 +84,6 @@
};
cpm@ff000000 {
linux,phandle = <ff000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@ -102,15 +94,14 @@
command-proc = <9c0>;
brg-frequency = <0>;
interrupts = <0 2>; // cpm error interrupt
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
pic@930 {
linux,phandle = <930>;
cpm_pic: pic@930 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <5 2 0 2>;
interrupt-parent = <ff000000>;
interrupt-parent = <&Mpc8xx_pic>;
reg = <930 20>;
built-in;
device_type = "cpm-pic";
@ -128,7 +119,7 @@
tx-clock = <1>;
current-speed = <0>;
interrupts = <4 3>;
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
};
smc@a90 {
@ -142,7 +133,7 @@
tx-clock = <2>;
current-speed = <0>;
interrupts = <3 3>;
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
};
scc@a00 {
@ -153,7 +144,7 @@
reg = <a00 18 3c00 80>;
mac-address = [ 00 00 0C 00 03 FD ];
interrupts = <1e 3>;
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
};
};
};

View File

@ -15,12 +15,10 @@
compatible = "mpc8xx";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;
PowerPC,885@0 {
device_type = "cpu";
@ -34,14 +32,12 @@
clock-frequency = <0>;
32-bit;
interrupts = <f 2>; // decrementer interrupt
interrupt-parent = <ff000000>;
linux,phandle = <201>;
interrupt-parent = <&Mpc8xx_pic>;
};
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 800000>;
};
@ -57,21 +53,17 @@
device_type = "mdio";
compatible = "fs_enet";
reg = <e80 8>;
linux,phandle = <e80>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
linux,phandle = <e8000>;
Phy0: ethernet-phy@0 {
reg = <0>;
device_type = "ethernet-phy";
};
ethernet-phy@1 {
linux,phandle = <e8001>;
Phy1: ethernet-phy@1 {
reg = <1>;
device_type = "ethernet-phy";
};
ethernet-phy@2 {
linux,phandle = <e8002>;
Phy2: ethernet-phy@2 {
reg = <2>;
device_type = "ethernet-phy";
};
@ -85,8 +77,8 @@
reg = <e00 188>;
mac-address = [ 00 00 0C 00 01 FD ];
interrupts = <3 1>;
interrupt-parent = <ff000000>;
phy-handle = <e8000>;
interrupt-parent = <&Mpc8xx_pic>;
phy-handle = <&Phy1>;
};
fec@1e00 {
@ -97,12 +89,11 @@
reg = <1e00 188>;
mac-address = [ 00 00 0C 00 02 FD ];
interrupts = <7 1>;
interrupt-parent = <ff000000>;
phy-handle = <e8001>;
interrupt-parent = <&Mpc8xx_pic>;
phy-handle = <&Phy2>;
};
pic@ff000000 {
linux,phandle = <ff000000>;
Mpc8xx_pic: pic@ff000000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@ -112,8 +103,18 @@
compatible = "CPM";
};
pcmcia@0080 {
#address-cells = <3>;
#interrupt-cells = <1>;
#size-cells = <2>;
compatible = "fsl,pq-pcmcia";
device_type = "pcmcia";
reg = <80 80>;
interrupt-parent = <&Mpc8xx_pic>;
interrupts = <d 1>;
};
cpm@ff000000 {
linux,phandle = <ff000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@ -124,15 +125,14 @@
command-proc = <9c0>;
brg-frequency = <0>;
interrupts = <0 2>; // cpm error interrupt
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
pic@930 {
linux,phandle = <930>;
Cpm_pic: pic@930 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <5 2 0 2>;
interrupt-parent = <ff000000>;
interrupt-parent = <&Mpc8xx_pic>;
reg = <930 20>;
built-in;
device_type = "cpm-pic";
@ -150,7 +150,7 @@
tx-clock = <1>;
current-speed = <0>;
interrupts = <4 3>;
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
};
smc@a90 {
@ -164,7 +164,7 @@
tx-clock = <2>;
current-speed = <0>;
interrupts = <3 3>;
interrupt-parent = <930>;
interrupt-parent = <&Cpm_pic>;
};
scc@a40 {
@ -175,8 +175,8 @@
reg = <a40 18 3e00 80>;
mac-address = [ 00 00 0C 00 03 FD ];
interrupts = <1c 3>;
interrupt-parent = <930>;
phy-handle = <e8002>;
interrupt-parent = <&Cpm_pic>;
phy-handle = <&Phy2>;
};
};
};

View File

@ -309,7 +309,7 @@
};
chosen {
bootargs = "ip=on console=ttyMM0";
bootargs = "ip=on";
linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
};
};

View File

@ -0,0 +1,68 @@
/*
* PS3 Game Console device tree.
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/ {
model = "SonyPS3";
compatible = "sony,ps3";
#size-cells = <2>;
#address-cells = <2>;
chosen {
};
/*
* We'll get the size of the bootmem block from lv1 after startup,
* so we'll put a null entry here.
*/
memory {
device_type = "memory";
reg = <0 0 0 0>;
};
/*
* The boot cpu is always zero for PS3.
*
* dtc expects a clock-frequency and timebase-frequency entries, so
* we'll put a null entries here. These will be initialized after
* startup with data from lv1.
*
* Seems the only way currently to indicate a processor has multiple
* threads is with an ibm,ppc-interrupt-server#s entry. We'll put one
* here so we can bring up both of ours. See smp_setup_cpu_maps().
*/
cpus {
#size-cells = <0>;
#address-cells = <1>;
cpu@0 {
device_type = "cpu";
reg = <0>;
ibm,ppc-interrupt-server#s = <0 1>;
clock-frequency = <0>;
timebase-frequency = <0>;
i-cache-size = <8000>;
d-cache-size = <8000>;
i-cache-line-size = <80>;
d-cache-line-size = <80>;
};
};
};

View File

@ -100,28 +100,13 @@ static void ebony_fixups(void)
ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
ibm44x_fixup_memsize();
dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
}
#define SPRN_DBCR0 0x134
#define DBCR0_RST_SYSTEM 0x30000000
static void ebony_exit(void)
{
unsigned long tmp;
asm volatile (
"mfspr %0,%1\n"
"oris %0,%0,%2@h\n"
"mtspr %1,%0"
: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM)
);
ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
}
void ebony_init(void *mac0, void *mac1)
{
platform_ops.fixups = ebony_fixups;
platform_ops.exit = ebony_exit;
platform_ops.exit = ibm44x_dbcr_reset;
ebony_mac0 = mac0;
ebony_mac1 = mac1;
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);

View File

@ -36,8 +36,6 @@ struct addr_range {
unsigned long size;
};
typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
#undef DEBUG
static struct addr_range prep_kernel(void)

View File

@ -15,8 +15,7 @@
#include "page.h"
#include "ops.h"
typedef void *ihandle;
typedef void *phandle;
#include "of.h"
extern char _end[];
@ -25,154 +24,10 @@ extern char _end[];
#define RAM_END (512<<20) /* Fixme: use OF */
#define ONE_MB 0x100000
int (*prom) (void *);
static unsigned long claim_base;
static int call_prom(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (prom(&args) < 0)
return -1;
return (nret > 0)? args.args[nargs]: 0;
}
static int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, rets);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (prom(&args) < 0)
return -1;
if (rets != (void *) 0)
for (i = 1; i < nret; ++i)
rets[i-1] = args.args[nargs+i];
return (nret > 0)? args.args[nargs]: 0;
}
/*
* Older OF's require that when claiming a specific range of addresses,
* we claim the physical space in the /memory node and the virtual
* space in the chosen mmu node, and then do a map operation to
* map virtual to physical.
*/
static int need_map = -1;
static ihandle chosen_mmu;
static phandle memory;
/* returns true if s2 is a prefix of s1 */
static int string_match(const char *s1, const char *s2)
{
for (; *s2; ++s2)
if (*s1++ != *s2)
return 0;
return 1;
}
static int check_of_version(void)
{
phandle oprom, chosen;
char version[64];
oprom = finddevice("/openprom");
if (oprom == (phandle) -1)
return 0;
if (getprop(oprom, "model", version, sizeof(version)) <= 0)
return 0;
version[sizeof(version)-1] = 0;
printf("OF version = '%s'\r\n", version);
if (!string_match(version, "Open Firmware, 1.")
&& !string_match(version, "FirmWorks,3."))
return 0;
chosen = finddevice("/chosen");
if (chosen == (phandle) -1) {
chosen = finddevice("/chosen@0");
if (chosen == (phandle) -1) {
printf("no chosen\n");
return 0;
}
}
if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
printf("no mmu\n");
return 0;
}
memory = (ihandle) call_prom("open", 1, 1, "/memory");
if (memory == (ihandle) -1) {
memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
if (memory == (ihandle) -1) {
printf("no memory node\n");
return 0;
}
}
printf("old OF detected\r\n");
return 1;
}
static void *claim(unsigned long virt, unsigned long size, unsigned long align)
{
int ret;
unsigned int result;
if (need_map < 0)
need_map = check_of_version();
if (align || !need_map)
return (void *) call_prom("claim", 3, 1, virt, size, align);
ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
align, size, virt);
if (ret != 0 || result == -1)
return (void *) -1;
ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
align, size, virt);
/* 0x12 == coherent + read/write */
ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
0x12, size, virt, virt);
return (void *) virt;
}
static void *of_try_claim(unsigned long size)
{
unsigned long addr = 0;
@ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size)
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_base);
#endif
addr = (unsigned long)claim(claim_base, size, 0);
addr = (unsigned long)of_claim(claim_base, size, 0);
if ((void *)addr != (void *)-1)
break;
}
@ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr)
}
}
static void *of_vmlinux_alloc(unsigned long size)
{
void *p = malloc(size);
if (!p)
fatal("Can't allocate memory for kernel image!\n\r");
return p;
}
static void of_exit(void)
{
call_prom("exit", 0, 0);
}
/*
* OF device tree routines
*/
static void *of_finddevice(const char *name)
{
return (phandle) call_prom("finddevice", 1, 1, name);
}
static int of_getprop(const void *phandle, const char *name, void *buf,
const int buflen)
{
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
static int of_setprop(const void *phandle, const char *name, const void *buf,
const int buflen)
{
return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
}
/*
* OF console routines
*/
static void *of_stdout_handle;
static int of_console_open(void)
{
void *devp;
if (((devp = finddevice("/chosen")) != NULL)
&& (getprop(devp, "stdout", &of_stdout_handle,
sizeof(of_stdout_handle))
== sizeof(of_stdout_handle)))
return 0;
return -1;
}
static void of_console_write(char *buf, int len)
{
call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
void platform_init(unsigned long a1, unsigned long a2, void *promptr)
{
platform_ops.image_hdr = of_image_hdr;
@ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr)
dt_ops.getprop = of_getprop;
dt_ops.setprop = of_setprop;
console_ops.open = of_console_open;
console_ops.write = of_console_write;
of_console_init();
prom = (int (*)(void *))promptr;
of_init(promptr);
loader_info.promptr = promptr;
if (a1 && a2 && a2 != 0xdeadbeef) {
loader_info.initrd_addr = a1;

21
arch/powerpc/boot/of.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _PPC_BOOT_OF_H_
#define _PPC_BOOT_OF_H_
typedef void *phandle;
typedef void *ihandle;
void of_init(void *promptr);
int of_call_prom(const char *service, int nargs, int nret, ...);
void *of_claim(unsigned long virt, unsigned long size, unsigned long align);
void *of_vmlinux_alloc(unsigned long size);
void of_exit(void);
void *of_finddevice(const char *name);
int of_getprop(const void *phandle, const char *name, void *buf,
const int buflen);
int of_setprop(const void *phandle, const char *name, const void *buf,
const int buflen);
/* Console functions */
void of_console_init(void);
#endif /* _PPC_BOOT_OF_H_ */

View File

@ -0,0 +1,45 @@
/*
* OF console routines
*
* Copyright (C) Paul Mackerras 1997.
*
* 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 <stddef.h>
#include "types.h"
#include "elf.h"
#include "string.h"
#include "stdio.h"
#include "page.h"
#include "ops.h"
#include "of.h"
static void *of_stdout_handle;
static int of_console_open(void)
{
void *devp;
if (((devp = of_finddevice("/chosen")) != NULL)
&& (of_getprop(devp, "stdout", &of_stdout_handle,
sizeof(of_stdout_handle))
== sizeof(of_stdout_handle)))
return 0;
return -1;
}
static void of_console_write(const char *buf, int len)
{
of_call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
void of_console_init(void)
{
console_ops.open = of_console_open;
console_ops.write = of_console_write;
}

202
arch/powerpc/boot/oflib.c Normal file
View File

@ -0,0 +1,202 @@
/*
* Copyright (C) Paul Mackerras 1997.
*
* 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 <stddef.h>
#include "types.h"
#include "elf.h"
#include "string.h"
#include "stdio.h"
#include "page.h"
#include "ops.h"
#include "of.h"
static int (*prom) (void *);
void of_init(void *promptr)
{
prom = (int (*)(void *))promptr;
}
int of_call_prom(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (prom(&args) < 0)
return -1;
return (nret > 0)? args.args[nargs]: 0;
}
static int of_call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...)
{
int i;
struct prom_args {
const char *service;
int nargs;
int nret;
unsigned int args[12];
} args;
va_list list;
args.service = service;
args.nargs = nargs;
args.nret = nret;
va_start(list, rets);
for (i = 0; i < nargs; i++)
args.args[i] = va_arg(list, unsigned int);
va_end(list);
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
if (prom(&args) < 0)
return -1;
if (rets != (void *) 0)
for (i = 1; i < nret; ++i)
rets[i-1] = args.args[nargs+i];
return (nret > 0)? args.args[nargs]: 0;
}
/* returns true if s2 is a prefix of s1 */
static int string_match(const char *s1, const char *s2)
{
for (; *s2; ++s2)
if (*s1++ != *s2)
return 0;
return 1;
}
/*
* Older OF's require that when claiming a specific range of addresses,
* we claim the physical space in the /memory node and the virtual
* space in the chosen mmu node, and then do a map operation to
* map virtual to physical.
*/
static int need_map = -1;
static ihandle chosen_mmu;
static phandle memory;
static int check_of_version(void)
{
phandle oprom, chosen;
char version[64];
oprom = of_finddevice("/openprom");
if (oprom == (phandle) -1)
return 0;
if (of_getprop(oprom, "model", version, sizeof(version)) <= 0)
return 0;
version[sizeof(version)-1] = 0;
printf("OF version = '%s'\r\n", version);
if (!string_match(version, "Open Firmware, 1.")
&& !string_match(version, "FirmWorks,3."))
return 0;
chosen = of_finddevice("/chosen");
if (chosen == (phandle) -1) {
chosen = of_finddevice("/chosen@0");
if (chosen == (phandle) -1) {
printf("no chosen\n");
return 0;
}
}
if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
printf("no mmu\n");
return 0;
}
memory = (ihandle) of_call_prom("open", 1, 1, "/memory");
if (memory == (ihandle) -1) {
memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0");
if (memory == (ihandle) -1) {
printf("no memory node\n");
return 0;
}
}
printf("old OF detected\r\n");
return 1;
}
void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
{
int ret;
unsigned int result;
if (need_map < 0)
need_map = check_of_version();
if (align || !need_map)
return (void *) of_call_prom("claim", 3, 1, virt, size, align);
ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory,
align, size, virt);
if (ret != 0 || result == -1)
return (void *) -1;
ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
align, size, virt);
/* 0x12 == coherent + read/write */
ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu,
0x12, size, virt, virt);
return (void *) virt;
}
void *of_vmlinux_alloc(unsigned long size)
{
void *p = malloc(size);
if (!p)
fatal("Can't allocate memory for kernel image!\n\r");
return p;
}
void of_exit(void)
{
of_call_prom("exit", 0, 0);
}
/*
* OF device tree routines
*/
void *of_finddevice(const char *name)
{
return (phandle) of_call_prom("finddevice", 1, 1, name);
}
int of_getprop(const void *phandle, const char *name, void *buf,
const int buflen)
{
return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
int of_setprop(const void *phandle, const char *name, const void *buf,
const int buflen)
{
return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
}

View File

@ -19,6 +19,8 @@
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
/* Platform specific operations */
struct platform_ops {
void (*fixups)(void);
@ -51,7 +53,7 @@ extern struct dt_ops dt_ops;
/* Console operations */
struct console_ops {
int (*open)(void);
void (*write)(char *buf, int len);
void (*write)(const char *buf, int len);
void (*edit_cmdline)(char *buf, int len);
void (*close)(void);
void *data;

View File

@ -0,0 +1,80 @@
/*
* PS3 bootwrapper entry.
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ppc_asm.h"
.text
/*
* __system_reset_overlay - The PS3 first stage entry.
*
* The bootwraper build script copies the 0x100 bytes at symbol
* __system_reset_overlay to offset 0x100 of the rom image.
*
* The PS3 has a single processor with two threads.
*/
.globl __system_reset_overlay
__system_reset_overlay:
/* Switch to 32-bit mode. */
mfmsr r9
clrldi r9,r9,1
mtmsrd r9
nop
/* Get thread number in r3 and branch. */
mfspr r3, 0x88
cntlzw. r3, r3
li r4, 0
li r5, 0
beq 1f
/* Secondary goes to __secondary_hold in kernel. */
li r4, 0x60
mtctr r4
bctr
/* Primary delays then goes to _zimage_start in wrapper. */
1:
or 31, 31, 31 /* db16cyc */
or 31, 31, 31 /* db16cyc */
lis r4, _zimage_start@ha
addi r4, r4, _zimage_start@l
mtctr r4
bctr
/*
* __system_reset_kernel - Place holder for the kernel reset vector.
*
* The bootwrapper build script copies 0x100 bytes from offset 0x100
* of the rom image to the symbol __system_reset_kernel. At runtime
* the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
* to ram address 0x100. This symbol must occupy 0x100 bytes.
*/
.globl __system_reset_kernel
__system_reset_kernel:
. = __system_reset_kernel + 0x100

View File

@ -0,0 +1,184 @@
/*
* PS3 bootwrapper hvcalls.
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ppc_asm.h"
/*
* The PS3 hypervisor uses a 64 bit "C" language calling convention.
* The routines here marshal arguments between the 32 bit wrapper
* program and the 64 bit hvcalls.
*
* wrapper lv1
* 32-bit (h,l) 64-bit
*
* 1: r3,r4 <-> r3
* 2: r5,r6 <-> r4
* 3: r7,r8 <-> r5
* 4: r9,r10 <-> r6
* 5: 8(r1),12(r1) <-> r7
* 6: 16(r1),20(r1) <-> r8
* 7: 24(r1),28(r1) <-> r9
* 8: 32(r1),36(r1) <-> r10
*
*/
.macro GLOBAL name
.section ".text"
.balign 4
.globl \name
\name:
.endm
.macro NO_SUPPORT name
GLOBAL \name
b ps3_no_support
.endm
.macro HVCALL num
li r11, \num
.long 0x44000022
extsw r3, r3
.endm
.macro SAVE_LR offset=4
mflr r0
stw r0, \offset(r1)
.endm
.macro LOAD_LR offset=4
lwz r0, \offset(r1)
mtlr r0
.endm
.macro LOAD_64_REG target,high,low
sldi r11, \high, 32
or \target, r11, \low
.endm
.macro LOAD_64_STACK target,offset
ld \target, \offset(r1)
.endm
.macro LOAD_R3
LOAD_64_REG r3,r3,r4
.endm
.macro LOAD_R4
LOAD_64_REG r4,r5,r6
.endm
.macro LOAD_R5
LOAD_64_REG r5,r7,r8
.endm
.macro LOAD_R6
LOAD_64_REG r6,r9,r10
.endm
.macro LOAD_R7
LOAD_64_STACK r7,8
.endm
.macro LOAD_R8
LOAD_64_STACK r8,16
.endm
.macro LOAD_R9
LOAD_64_STACK r9,24
.endm
.macro LOAD_R10
LOAD_64_STACK r10,32
.endm
.macro LOAD_REGS_0
stwu 1,-16(1)
stw 3, 8(1)
.endm
.macro LOAD_REGS_5
LOAD_R3
LOAD_R4
LOAD_R5
LOAD_R6
LOAD_R7
.endm
.macro LOAD_REGS_6
LOAD_REGS_5
LOAD_R8
.endm
.macro LOAD_REGS_8
LOAD_REGS_6
LOAD_R9
LOAD_R10
.endm
.macro STORE_REGS_0_1
lwz r11, 8(r1)
std r4, 0(r11)
mr r4, r3
li r3, 0
addi r1,r1,16
.endm
.macro STORE_REGS_5_2
lwz r11, 16(r1)
std r4, 0(r11)
lwz r11, 24(r1)
std r5, 0(r11)
.endm
.macro STORE_REGS_6_1
lwz r11, 24(r1)
std r4, 0(r11)
.endm
GLOBAL lv1_get_logical_ppe_id
SAVE_LR
LOAD_REGS_0
HVCALL 69
STORE_REGS_0_1
LOAD_LR
blr
GLOBAL lv1_get_logical_partition_id
SAVE_LR
LOAD_REGS_0
HVCALL 74
STORE_REGS_0_1
LOAD_LR
blr
GLOBAL lv1_get_repository_node_value
SAVE_LR
LOAD_REGS_5
HVCALL 91
STORE_REGS_5_2
LOAD_LR
blr
GLOBAL lv1_panic
SAVE_LR
LOAD_REGS_8
HVCALL 255
LOAD_LR
blr

161
arch/powerpc/boot/ps3.c Normal file
View File

@ -0,0 +1,161 @@
/*
* PS3 bootwrapper support.
*
* Copyright (C) 2007 Sony Computer Entertainment Inc.
* Copyright 2007 Sony 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "elf.h"
#include "string.h"
#include "stdio.h"
#include "page.h"
#include "ops.h"
extern s64 lv1_panic(u64 in_1);
extern s64 lv1_get_logical_partition_id(u64 *out_1);
extern s64 lv1_get_logical_ppe_id(u64 *out_1);
extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
#ifdef DEBUG
#define DBG(fmt...) printf(fmt)
#else
static inline int __attribute__ ((format (printf, 1, 2))) DBG(
const char *fmt, ...) {return 0;}
#endif
BSS_STACK(4096);
/* A buffer that may be edited by tools operating on a zImage binary so as to
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
* The buffer is put in it's own section so that tools may locate it easier.
*/
static char cmdline[COMMAND_LINE_SIZE]
__attribute__((__section__("__builtin_cmdline")));
static void prep_cmdline(void *chosen)
{
if (cmdline[0] == '\0')
getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
else
setprop_str(chosen, "bootargs", cmdline);
printf("cmdline: '%s'\n", cmdline);
}
static void ps3_console_write(const char *buf, int len)
{
}
static void ps3_exit(void)
{
printf("ps3_exit\n");
/* lv1_panic will shutdown the lpar. */
lv1_panic(0); /* zero = do not reboot */
while (1);
}
static int ps3_repository_read_rm_size(u64 *rm_size)
{
s64 result;
u64 lpar_id;
u64 ppe_id;
u64 v2;
result = lv1_get_logical_partition_id(&lpar_id);
if (result)
return -1;
result = lv1_get_logical_ppe_id(&ppe_id);
if (result)
return -1;
/*
* n1: 0000000062690000 : ....bi..
* n2: 7075000000000000 : pu......
* n3: 0000000000000001 : ........
* n4: 726d5f73697a6500 : rm_size.
*/
result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
&v2);
printf("%s:%d: ppe_id %lu \n", __func__, __LINE__,
(unsigned long)ppe_id);
printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
(unsigned long)lpar_id);
printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
return result ? -1 : 0;
}
void ps3_copy_vectors(void)
{
extern char __system_reset_kernel[];
memcpy((void *)0x100, __system_reset_kernel, 0x100);
flush_cache((void *)0x100, 0x100);
}
void platform_init(void)
{
extern char _end[];
extern char _dtb_start[];
extern char _initrd_start[];
extern char _initrd_end[];
const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
void *chosen;
unsigned long ft_addr;
u64 rm_size;
console_ops.write = ps3_console_write;
platform_ops.exit = ps3_exit;
printf("\n-- PS3 bootwrapper --\n");
simple_alloc_init(_end, heapsize, 32, 64);
ft_init(_dtb_start, 0, 4);
chosen = finddevice("/chosen");
ps3_repository_read_rm_size(&rm_size);
dt_fixup_memory(0, rm_size);
if (_initrd_end > _initrd_start) {
setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
}
prep_cmdline(chosen);
ft_addr = dt_ops.finalize();
ps3_copy_vectors();
printf(" flat tree at 0x%lx\n\r", ft_addr);
((kernel_entry_t)0)(ft_addr, 0, NULL);
ps3_exit();
}

View File

@ -27,7 +27,7 @@ static int serial_open(void)
return scdp->open();
}
static void serial_write(char *buf, int len)
static void serial_write(const char *buf, int len)
{
struct serial_console_data *scdp = console_ops.data;

View File

@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args)
/* get the conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
if (*fmt == 'l' && *(fmt + 1) == 'l') {
qualifier = 'q';
fmt += 2;
} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
|| *fmt == 'Z') {
qualifier = *fmt;
++fmt;
}
@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
num = va_arg(args, unsigned long);
if (flags & SIGN)
num = (signed long) num;
} else if (qualifier == 'q') {
num = va_arg(args, unsigned long long);
if (flags & SIGN)
num = (signed long long) num;
} else if (qualifier == 'Z') {
num = va_arg(args, size_t);
} else if (qualifier == 'h') {

View File

@ -7,6 +7,10 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
#define min(x,y) ({ \
typeof(x) _x = (x); \

View File

@ -144,6 +144,15 @@ miboot|uboot)
cuboot*)
gzip=
;;
ps3)
platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
lds=$object/zImage.ps3.lds
gzip=
ext=bin
objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data"
ksection=.kernel:vmlinux.bin
isection=.kernel:initrd
;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
@ -239,4 +248,50 @@ treeboot*)
fi
exit 0
;;
ps3)
# The ps3's loader supports loading gzipped binary images from flash
# rom to addr zero. The loader enters the image at addr 0x100. A
# bootwrapper overlay is use to arrange for the kernel to be loaded
# to addr zero and to have a suitable bootwrapper entry at 0x100.
# To construct the rom image, 0x100 bytes from offset 0x100 in the
# kernel is copied to the bootwrapper symbol __system_reset_kernel.
# The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
# then copied to offset 0x100. At runtime the bootwrapper program
# copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
system_reset_overlay=0x`${CROSS}nm "$ofile" \
| grep ' __system_reset_overlay$' \
| cut -d' ' -f1`
system_reset_overlay=`printf "%d" $system_reset_overlay`
system_reset_kernel=0x`${CROSS}nm "$ofile" \
| grep ' __system_reset_kernel$' \
| cut -d' ' -f1`
system_reset_kernel=`printf "%d" $system_reset_kernel`
overlay_dest="256"
overlay_size="256"
rm -f "$object/otheros.bld"
${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
skip=$overlay_dest seek=$system_reset_kernel \
count=$overlay_size bs=1 2>&1)
if [ $? -ne "0" ]; then
echo $msg
exit 1
fi
msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \
skip=$system_reset_overlay seek=$overlay_dest \
count=$overlay_size bs=1 2>&1)
if [ $? -ne "0" ]; then
echo $msg
exit 2
fi
gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
;;
esac

View File

@ -0,0 +1,50 @@
OUTPUT_ARCH(powerpc:common)
ENTRY(_zimage_start)
EXTERN(_zimage_start)
SECTIONS
{
_vmlinux_start = .;
.kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) }
_vmlinux_end = .;
. = ALIGN(4096);
_dtb_start = .;
.kernel:dtb : { *(.kernel:dtb) }
_dtb_end = .;
. = ALIGN(4096);
_initrd_start = .;
.kernel:initrd : { *(.kernel:initrd) }
_initrd_end = .;
_start = .;
.text :
{
*(.text)
*(.fixup)
}
_etext = .;
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.data*)
*(.sdata*)
__got2_start = .;
*(.got2)
__got2_end = .;
}
. = ALIGN(4096);
_edata = .;
. = ALIGN(4096);
__bss_start = .;
.bss :
{
*(.sbss)
*(.bss)
}
. = ALIGN(4096);
_end = . ;
}

View File

@ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyS0,115200"
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_WANT_DEVICE_TREE=y
CONFIG_DEVICE_TREE="holly.dts"
CONFIG_ISA_DMA_API=y
#

View File

@ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20
CONFIG_PS3_USE_LPAR_ADDR=y
CONFIG_PS3_VUART=y
CONFIG_PS3_PS3AV=y
CONFIG_PS3_SYS_MANAGER=y
CONFIG_PS3_SYS_MANAGER=m
CONFIG_PS3_STORAGE=y
CONFIG_PS3_DISK=y
CONFIG_PS3_ROM=y
CONFIG_PS3_FLASH=y
CONFIG_PPC_CELL=y
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
@ -335,7 +339,7 @@ CONFIG_BT=m
CONFIG_BT_L2CAP=m
CONFIG_BT_SCO=m
CONFIG_BT_RFCOMM=m
# CONFIG_BT_RFCOMM_TTY is not set
CONFIG_BT_RFCOMM_TTY=y
# CONFIG_BT_BNEP is not set
CONFIG_BT_HIDP=m
@ -344,7 +348,9 @@ CONFIG_BT_HIDP=m
#
CONFIG_BT_HCIUSB=m
CONFIG_BT_HCIUSB_SCO=y
# CONFIG_BT_HCIUART is not set
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_BCSP=y
# CONFIG_BT_HCIBCM203X is not set
# CONFIG_BT_HCIBPA10X is not set
# CONFIG_BT_HCIBFUSB is not set
@ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
@ -479,6 +485,7 @@ CONFIG_NETDEVICES=y
CONFIG_MII=m
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
CONFIG_GELIC_NET=y
#
# Wireless LAN
@ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
CONFIG_INPUT_JOYSTICK=y
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
# CONFIG_JOYSTICK_ADI is not set
# CONFIG_JOYSTICK_COBRA is not set
# CONFIG_JOYSTICK_GF2K is not set
# CONFIG_JOYSTICK_GRIP is not set
# CONFIG_JOYSTICK_GRIP_MP is not set
# CONFIG_JOYSTICK_GUILLEMOT is not set
# CONFIG_JOYSTICK_INTERACT is not set
# CONFIG_JOYSTICK_SIDEWINDER is not set
# CONFIG_JOYSTICK_TMDC is not set
# CONFIG_JOYSTICK_IFORCE is not set
# CONFIG_JOYSTICK_WARRIOR is not set
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not set
# CONFIG_JOYSTICK_SPACEBALL is not set
# CONFIG_JOYSTICK_STINGER is not set
# CONFIG_JOYSTICK_TWIDJOY is not set
# CONFIG_JOYSTICK_JOYDUMP is not set
# CONFIG_JOYSTICK_XPAD is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
@ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y
#
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
@ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUGGER is not set
CONFIG_IRQSTACKS=y
# CONFIG_BOOTX_TEXT is not set
CONFIG_PPC_EARLY_DEBUG=y
# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
# CONFIG_PPC_EARLY_DEBUG_G5 is not set
# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
# CONFIG_PPC_EARLY_DEBUG_44x is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options

View File

@ -12,7 +12,8 @@ endif
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
irq.o align.o signal_32.o pmc.o vdso.o \
init_task.o process.o systbl.o idle.o
init_task.o process.o systbl.o idle.o \
signal.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o \
@ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y)
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o
pci32-$(CONFIG_PPC32) := pci_32.o
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o
obj-$(CONFIG_PCI_MSI) += msi.o
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
kexec-$(CONFIG_PPC32) := machine_kexec_32.o

View File

@ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = {
.oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5",
},
{ /* Power5++ */
.pvr_mask = 0xffffff00,
.pvr_value = 0x003b0300,
.cpu_name = "POWER5+ (gs)",
.cpu_features = CPU_FTRS_POWER5,
.cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
.oprofile_cpu_type = "ppc64/power5++",
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = MMCRA_SIHV,
.oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5+",
},
{ /* Power5 GS */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003b0000,
@ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = {
.platform = "ppc440",
},
{ /* 440SP Rev. A */
.pvr_mask = 0xff000fff,
.pvr_value = 0x53000891,
.pvr_mask = 0xfff00fff,
.pvr_value = 0x53200891,
.cpu_name = "440SP Rev. A",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
@ -1188,8 +1203,8 @@ static struct cpu_spec cpu_specs[] = {
.platform = "ppc440",
},
{ /* 440SPe Rev. A */
.pvr_mask = 0xff000fff,
.pvr_value = 0x53000890,
.pvr_mask = 0xfff00fff,
.pvr_value = 0x53400890,
.cpu_name = "440SPe Rev. A",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
@ -1197,6 +1212,16 @@ static struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
.platform = "ppc440",
},
{ /* 440SPe Rev. B */
.pvr_mask = 0xfff00fff,
.pvr_value = 0x53400891,
.cpu_name = "440SPe Rev. B",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
.platform = "ppc440",
},
#endif /* CONFIG_44x */
#ifdef CONFIG_FSL_BOOKE
{ /* e200z5 */

View File

@ -9,7 +9,6 @@
* rewritten by Paul Mackerras.
* Copyright (C) 1996 Paul Mackerras.
* MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* This file contains the low-level support and setup for the
* PowerPC platform, including trap and interrupt dispatch.
@ -32,10 +31,6 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#ifdef CONFIG_APUS
#include <asm/amigappc.h>
#endif
/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
@ -92,11 +87,6 @@ _start:
* r4: virtual address of boot_infos_t
* r5: 0
*
* APUS
* r3: 'APUS'
* r4: physical address of memory base
* Linux/m68k style BootInfo structure at &_end.
*
* PREP
* This is jumped to on prep systems right after the kernel is relocated
* to its proper place in memory by the boot loader. The expected layout
@ -150,14 +140,6 @@ __start:
*/
bl early_init
#ifdef CONFIG_APUS
/* On APUS the __va/__pa constants need to be set to the correct
* values before continuing.
*/
mr r4,r30
bl fix_mem_constants
#endif /* CONFIG_APUS */
/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
* the physical address we are running at, returned by early_init()
*/
@ -167,7 +149,7 @@ __after_mmu_off:
bl flush_tlbs
bl initial_bats
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
#if defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
@ -183,7 +165,6 @@ __after_mmu_off:
#endif /* CONFIG_6xx */
#ifndef CONFIG_APUS
/*
* We need to run with _start at physical address 0.
* On CHRP, we are loaded at 0x10000 since OF on CHRP uses
@ -196,7 +177,6 @@ __after_mmu_off:
addis r4,r3,KERNELBASE@h /* current address of _start */
cmpwi 0,r4,0 /* are we already running at 0? */
bne relocate_kernel
#endif /* CONFIG_APUS */
/*
* we now have the 1st 16M of ram mapped with the bats.
* prep needs the mmu to be turned on here, but pmac already has it on.
@ -881,85 +861,6 @@ _GLOBAL(copy_and_flush)
addi r6,r6,4
blr
#ifdef CONFIG_APUS
/*
* On APUS the physical base address of the kernel is not known at compile
* time, which means the __pa/__va constants used are incorrect. In the
* __init section is recorded the virtual addresses of instructions using
* these constants, so all that has to be done is fix these before
* continuing the kernel boot.
*
* r4 = The physical address of the kernel base.
*/
fix_mem_constants:
mr r10,r4
addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */
neg r11,r10 /* phys_to_virt constant */
lis r12,__vtop_table_begin@h
ori r12,r12,__vtop_table_begin@l
add r12,r12,r10 /* table begin phys address */
lis r13,__vtop_table_end@h
ori r13,r13,__vtop_table_end@l
add r13,r13,r10 /* table end phys address */
subi r12,r12,4
subi r13,r13,4
1: lwzu r14,4(r12) /* virt address of instruction */
add r14,r14,r10 /* phys address of instruction */
lwz r15,0(r14) /* instruction, now insert top */
rlwimi r15,r10,16,16,31 /* half of vp const in low half */
stw r15,0(r14) /* of instruction and restore. */
dcbst r0,r14 /* write it to memory */
sync
icbi r0,r14 /* flush the icache line */
cmpw r12,r13
bne 1b
sync /* additional sync needed on g4 */
isync
/*
* Map the memory where the exception handlers will
* be copied to when hash constants have been patched.
*/
#ifdef CONFIG_APUS_FAST_EXCEPT
lis r8,0xfff0
#else
lis r8,0
#endif
ori r8,r8,0x2 /* 128KB, supervisor */
mtspr SPRN_DBAT3U,r8
mtspr SPRN_DBAT3L,r8
lis r12,__ptov_table_begin@h
ori r12,r12,__ptov_table_begin@l
add r12,r12,r10 /* table begin phys address */
lis r13,__ptov_table_end@h
ori r13,r13,__ptov_table_end@l
add r13,r13,r10 /* table end phys address */
subi r12,r12,4
subi r13,r13,4
1: lwzu r14,4(r12) /* virt address of instruction */
add r14,r14,r10 /* phys address of instruction */
lwz r15,0(r14) /* instruction, now insert top */
rlwimi r15,r11,16,16,31 /* half of pv const in low half*/
stw r15,0(r14) /* of instruction and restore. */
dcbst r0,r14 /* write it to memory */
sync
icbi r0,r14 /* flush the icache line */
cmpw r12,r13
bne 1b
sync /* additional sync needed on g4 */
isync /* No speculative loading until now */
blr
/***********************************************************************
* Please note that on APUS the exception handlers are located at the
* physical address 0xfff0000. For this reason, the exception handlers
* cannot use relative branches to access the code below.
***********************************************************************/
#endif /* CONFIG_APUS */
#ifdef CONFIG_SMP
#ifdef CONFIG_GEMINI
.globl __secondary_start_gemini
@ -1135,19 +1036,6 @@ start_here:
bl __save_cpu_setup
bl MMU_init
#ifdef CONFIG_APUS
/* Copy exception code to exception vector base on APUS. */
lis r4,KERNELBASE@h
#ifdef CONFIG_APUS_FAST_EXCEPT
lis r3,0xfff0 /* Copy to 0xfff00000 */
#else
lis r3,0 /* Copy to 0x00000000 */
#endif
li r5,0x4000 /* # bytes of memory to copy */
li r6,0
bl copy_and_flush /* copy the first 0x4000 bytes */
#endif /* CONFIG_APUS */
/*
* Go back to running unmapped so we can load up new values
* for SDR1 (hash table pointer) and the segment registers
@ -1324,11 +1212,7 @@ initial_bats:
#else
ori r8,r8,2 /* R/W access */
#endif /* CONFIG_SMP */
#ifdef CONFIG_APUS
ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */
#else
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
#endif /* CONFIG_APUS */
mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
@ -1338,7 +1222,7 @@ initial_bats:
blr
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
#ifdef CONFIG_BOOTX_TEXT
setup_disp_bat:
/*
* setup the display bat prepared for us in prom.c
@ -1362,7 +1246,7 @@ setup_disp_bat:
1: mtspr SPRN_IBAT3L,r8
mtspr SPRN_IBAT3U,r11
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
#endif /* CONFIG_BOOTX_TEXT */
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.

View File

@ -103,8 +103,8 @@ __secondary_hold_acknowledge:
. = 0x60
/*
* The following code is used on pSeries to hold secondary processors
* in a spin loop after they have been freed from OpenFirmware, but
* The following code is used to hold secondary processors
* in a spin loop after they have entered the kernel, but
* before the bulk of the kernel has been relocated. This code
* is relocated to physical address 0x60 before prom_init is run.
* All of it must fit below the first exception vector at 0x100.

View File

@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
asm volatile("eieio");
eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
asm volatile("eieio");
eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
asm volatile("sync");
do {
tmp = *port;
asm volatile("eieio");
eieio();
*tbuf++ = tmp;
} while (--count != 0);
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src,
__asm__ __volatile__ ("sync" : : : "memory");
while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
eieio();
vsrc++;
dest++;
n--;
}
while(n > 4) {
*((u32 *)dest) = *((volatile u32 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
eieio();
vsrc += 4;
dest += 4;
n -= 4;
}
while(n) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
eieio();
vsrc++;
dest++;
n--;

View File

@ -7,7 +7,6 @@
* Copyright (C) 1996-2001 Cort Dougan
* Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -337,6 +336,7 @@ void do_IRQ(struct pt_regs *regs)
void __init init_IRQ(void)
{
if (ppc_md.init_IRQ)
ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
irq_ctx_init();
@ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags)
local_irq_restore(flags);
}
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
irq_hw_number_t hwirq)
{
/* Clear IRQ_NOREQUEST flag */
get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
/* map it */
smp_wmb();
irq_map[virq].hwirq = hwirq;
smp_mb();
if (host->ops->map(host, virq, hwirq)) {
pr_debug("irq: -> mapping failed, freeing\n");
irq_free_virt(virq, 1);
return -1;
}
return 0;
}
unsigned int irq_create_direct_mapping(struct irq_host *host)
{
unsigned int virq;
if (host == NULL)
host = irq_default_host;
BUG_ON(host == NULL);
WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
virq = irq_alloc_virt(host, 1, 0);
if (virq == NO_IRQ) {
pr_debug("irq: create_direct virq allocation failed\n");
return NO_IRQ;
}
pr_debug("irq: create_direct obtained virq %d\n", virq);
if (irq_setup_virq(host, virq, virq))
return NO_IRQ;
return virq;
}
unsigned int irq_create_mapping(struct irq_host *host,
irq_hw_number_t hwirq)
@ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host,
}
pr_debug("irq: -> obtained virq %d\n", virq);
/* Clear IRQ_NOREQUEST flag */
get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
/* map it */
smp_wmb();
irq_map[virq].hwirq = hwirq;
smp_mb();
if (host->ops->map(host, virq, hwirq)) {
pr_debug("irq: -> mapping failed, freeing\n");
irq_free_virt(virq, 1);
if (irq_setup_virq(host, virq, hwirq))
return NO_IRQ;
}
return virq;
}
EXPORT_SYMBOL_GPL(irq_create_mapping);

View File

@ -0,0 +1,271 @@
/*
* Routines for tracking a legacy ISA bridge
*
* Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
*
* Some bits and pieces moved over from pci_64.c
*
* Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, 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.
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/notifier.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/ppc-pci.h>
#include <asm/firmware.h>
unsigned long isa_io_base; /* NULL if no ISA bus */
EXPORT_SYMBOL(isa_io_base);
/* Cached ISA bridge dev. */
static struct device_node *isa_bridge_devnode;
struct pci_dev *isa_bridge_pcidev;
EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
#define ISA_SPACE_MASK 0x1
#define ISA_SPACE_IO 0x1
static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
unsigned long phb_io_base_phys)
{
/* We should get some saner parsing here and remove these structs */
struct pci_address {
u32 a_hi;
u32 a_mid;
u32 a_lo;
};
struct isa_address {
u32 a_hi;
u32 a_lo;
};
struct isa_range {
struct isa_address isa_addr;
struct pci_address pci_addr;
unsigned int size;
};
const struct isa_range *range;
unsigned long pci_addr;
unsigned int isa_addr;
unsigned int size;
int rlen = 0;
range = of_get_property(isa_node, "ranges", &rlen);
if (range == NULL || (rlen < sizeof(struct isa_range)))
goto inval_range;
/* From "ISA Binding to 1275"
* The ranges property is laid out as an array of elements,
* each of which comprises:
* cells 0 - 1: an ISA address
* cells 2 - 4: a PCI address
* (size depending on dev->n_addr_cells)
* cell 5: the size of the range
*/
if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
range++;
rlen -= sizeof(struct isa_range);
if (rlen < sizeof(struct isa_range))
goto inval_range;
}
if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
goto inval_range;
isa_addr = range->isa_addr.a_lo;
pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
range->pci_addr.a_lo;
/* Assume these are both zero. Note: We could fix that and
* do a proper parsing instead ... oh well, that will do for
* now as nobody uses fancy mappings for ISA bridges
*/
if ((pci_addr != 0) || (isa_addr != 0)) {
printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
__FUNCTION__);
return;
}
/* Align size and make sure it's cropped to 64K */
size = PAGE_ALIGN(range->size);
if (size > 0x10000)
size = 0x10000;
printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
"mapping 64k\n");
__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
size, _PAGE_NO_CACHE|_PAGE_GUARDED);
return;
inval_range:
printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
"mapping 64k\n");
__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
}
/**
* isa_bridge_find_early - Find and map the ISA IO space early before
* main PCI discovery. This is optionally called by
* the arch code when adding PCI PHBs to get early
* access to ISA IO ports
*/
void __init isa_bridge_find_early(struct pci_controller *hose)
{
struct device_node *np, *parent = NULL, *tmp;
/* If we already have an ISA bridge, bail off */
if (isa_bridge_devnode != NULL)
return;
/* For each "isa" node in the system. Note : we do a search by
* type and not by name. It might be better to do by name but that's
* what the code used to do and I don't want to break too much at
* once. We can look into changing that separately
*/
for_each_node_by_type(np, "isa") {
/* Look for our hose being a parent */
for (parent = of_get_parent(np); parent;) {
if (parent == hose->arch_data) {
of_node_put(parent);
break;
}
tmp = parent;
parent = of_get_parent(parent);
of_node_put(tmp);
}
if (parent != NULL)
break;
}
if (np == NULL)
return;
isa_bridge_devnode = np;
/* Now parse the "ranges" property and setup the ISA mapping */
pci_process_ISA_OF_ranges(np, hose->io_base_phys);
/* Set the global ISA io base to indicate we have an ISA bridge */
isa_io_base = ISA_IO_BASE;
pr_debug("ISA bridge (early) is %s\n", np->full_name);
}
/**
* isa_bridge_find_late - Find and map the ISA IO space upon discovery of
* a new ISA bridge
*/
static void __devinit isa_bridge_find_late(struct pci_dev *pdev,
struct device_node *devnode)
{
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
/* Store ISA device node and PCI device */
isa_bridge_devnode = of_node_get(devnode);
isa_bridge_pcidev = pdev;
/* Now parse the "ranges" property and setup the ISA mapping */
pci_process_ISA_OF_ranges(devnode, hose->io_base_phys);
/* Set the global ISA io base to indicate we have an ISA bridge */
isa_io_base = ISA_IO_BASE;
pr_debug("ISA bridge (late) is %s on %s\n",
devnode->full_name, pci_name(pdev));
}
/**
* isa_bridge_remove - Remove/unmap an ISA bridge
*/
static void isa_bridge_remove(void)
{
pr_debug("ISA bridge removed !\n");
/* Clear the global ISA io base to indicate that we have no more
* ISA bridge. Note that drivers don't quite handle that, though
* we should probably do something about it. But do we ever really
* have ISA bridges being removed on machines using legacy devices ?
*/
isa_io_base = ISA_IO_BASE;
/* Clear references to the bridge */
of_node_put(isa_bridge_devnode);
isa_bridge_devnode = NULL;
isa_bridge_pcidev = NULL;
/* Unmap the ISA area */
__iounmap_at((void *)ISA_IO_BASE, 0x10000);
}
/**
* isa_bridge_notify - Get notified of PCI devices addition/removal
*/
static int __devinit isa_bridge_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
struct pci_dev *pdev = to_pci_dev(dev);
struct device_node *devnode = pci_device_to_OF_node(pdev);
switch(action) {
case BUS_NOTIFY_ADD_DEVICE:
/* Check if we have an early ISA device, without PCI dev */
if (isa_bridge_devnode && isa_bridge_devnode == devnode &&
!isa_bridge_pcidev) {
pr_debug("ISA bridge PCI attached: %s\n",
pci_name(pdev));
isa_bridge_pcidev = pdev;
}
/* Check if we have no ISA device, and this happens to be one,
* register it as such if it has an OF device
*/
if (!isa_bridge_devnode && devnode && devnode->type &&
!strcmp(devnode->type, "isa"))
isa_bridge_find_late(pdev, devnode);
return 0;
case BUS_NOTIFY_DEL_DEVICE:
/* Check if this our existing ISA device */
if (pdev == isa_bridge_pcidev ||
(devnode && devnode == isa_bridge_devnode))
isa_bridge_remove();
return 0;
}
return 0;
}
static struct notifier_block isa_bridge_notifier = {
.notifier_call = isa_bridge_notify
};
/**
* isa_bridge_init - register to be notified of ISA bridge addition/removal
*
*/
static int __init isa_bridge_init(void)
{
if (firmware_has_feature(FW_FEATURE_ISERIES))
return 0;
bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
return 0;
}
arch_initcall(isa_bridge_init);

View File

@ -392,7 +392,7 @@ BEGIN_FTR_SECTION
mtspr SPRN_L1CSR0,r3
isync
blr
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
mfspr r3,SPRN_L1CSR1
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
@ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_icache_range)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
li r5,L1_CACHE_BYTES-1
andc r3,r3,r5
subf r4,r3,r4
@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range)
*/
_GLOBAL(__flush_dcache_icache)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
blr
END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */
mtctr r4
@ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
_GLOBAL(__flush_dcache_icache_phys)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
mfmsr r10
rlwinm r0,r10,0,28,26 /* clear DR */
mtmsr r0

View File

@ -646,6 +646,19 @@ _GLOBAL(kexec_sequence)
/* turn off mmu */
bl real_mode
/* copy 0x100 bytes starting at start to 0 */
li r3,0
mr r4,r30 /* start, aka phys mem offset */
li r5,0x100
li r6,0
bl .copy_and_flush /* (dest, src, copy limit, start offset) */
1: /* assume normal blr return */
/* release other cpus to the new kernel secondary start at 0x60 */
mflr r5
li r6,1
stw r6,kexec_flag-1b(5)
/* clear out hardware hash page table and tlb */
ld r5,0(r27) /* deref function descriptor */
mtctr r5
@ -676,19 +689,6 @@ _GLOBAL(kexec_sequence)
* are the boot cpu ?????
* other device tree differences (prop sizes, va vs pa, etc)...
*/
/* copy 0x100 bytes starting at start to 0 */
li r3,0
mr r4,r30
li r5,0x100
li r6,0
bl .copy_and_flush /* (dest, src, copy limit, start offset) */
1: /* assume normal blr return */
/* release other cpus to the new kernel secondary start at 0x60 */
mflr r5
li r6,1
stw r6,kexec_flag-1b(5)
mr r3,r25 # my phys cpu
mr r4,r30 # start, aka phys mem offset
mtlr 4

View File

@ -427,14 +427,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
/* Process "ranges" property */
pci_process_bridge_OF_ranges(phb, dev->node, 0);
/* Setup IO space. We use the non-dynamic version of that code here,
* which doesn't quite support unplugging. Next kernel release will
* have a better fix for this.
* Note also that we don't do ISA, this will also be fixed with a
* more massive rework.
*/
pci_setup_phb_io(phb, pci_io_base == 0);
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic(phb);

View File

@ -0,0 +1,454 @@
/*
* Contains common pci routines for ALL ppc platform
* (based on pci_32.c and pci_64.c)
*
* Port for PPC64 David Engebretsen, IBM Corp.
* Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
*
* Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
* Rework, based on alpha PCI code.
*
* Common pmac/prep/chrp pci routines. -- Cort
*
* 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/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <linux/vmalloc.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/byteorder.h>
#include <asm/machdep.h>
#include <asm/ppc-pci.h>
#include <asm/firmware.h>
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) printk(fmt)
#else
#define DBG(fmt...)
#endif
static DEFINE_SPINLOCK(hose_spinlock);
/* XXX kill that some day ... */
int global_phb_number; /* Global phb counter */
extern struct list_head hose_list;
/*
* pci_controller(phb) initialized common variables.
*/
static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
{
memset(hose, 0, sizeof(struct pci_controller));
spin_lock(&hose_spinlock);
hose->global_number = global_phb_number++;
list_add_tail(&hose->list_node, &hose_list);
spin_unlock(&hose_spinlock);
}
struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
{
struct pci_controller *phb;
if (mem_init_done)
phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
else
phb = alloc_bootmem(sizeof (struct pci_controller));
if (phb == NULL)
return NULL;
pci_setup_pci_controller(phb);
phb->arch_data = dev;
phb->is_dynamic = mem_init_done;
#ifdef CONFIG_PPC64
if (dev) {
int nid = of_node_to_nid(dev);
if (nid < 0 || !node_online(nid))
nid = -1;
PHB_SET_NODE(phb, nid);
}
#endif
return phb;
}
void pcibios_free_controller(struct pci_controller *phb)
{
spin_lock(&hose_spinlock);
list_del(&phb->list_node);
spin_unlock(&hose_spinlock);
if (phb->is_dynamic)
kfree(phb);
}
/*
* Return the domain number for this bus.
*/
int pci_domain_nr(struct pci_bus *bus)
{
if (firmware_has_feature(FW_FEATURE_ISERIES))
return 0;
else {
struct pci_controller *hose = pci_bus_to_host(bus);
return hose->global_number;
}
}
EXPORT_SYMBOL(pci_domain_nr);
#ifdef CONFIG_PPC_OF
/* This routine is meant to be used early during boot, when the
* PCI bus numbers have not yet been assigned, and you need to
* issue PCI config cycles to an OF device.
* It could also be used to "fix" RTAS config cycles if you want
* to set pci_assign_all_buses to 1 and still use RTAS for PCI
* config cycles.
*/
struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
{
if (!have_of)
return NULL;
while(node) {
struct pci_controller *hose, *tmp;
list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
if (hose->arch_data == node)
return hose;
node = node->parent;
}
return NULL;
}
static ssize_t pci_show_devspec(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
pdev = to_pci_dev (dev);
np = pci_device_to_OF_node(pdev);
if (np == NULL || np->full_name == NULL)
return 0;
return sprintf(buf, "%s", np->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
#endif /* CONFIG_PPC_OF */
/* Add sysfs properties */
void pcibios_add_platform_entries(struct pci_dev *pdev)
{
#ifdef CONFIG_PPC_OF
device_create_file(&pdev->dev, &dev_attr_devspec);
#endif /* CONFIG_PPC_OF */
}
char __init *pcibios_setup(char *str)
{
return str;
}
/*
* Reads the interrupt pin to determine if interrupt is use by card.
* If the interrupt is used, then gets the interrupt line from the
* openfirmware and sets it in the pci_dev and pci_config line.
*/
int pci_read_irq_line(struct pci_dev *pci_dev)
{
struct of_irq oirq;
unsigned int virq;
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
#ifdef DEBUG
memset(&oirq, 0xff, sizeof(oirq));
#endif
/* Try to get a mapping from the device-tree */
if (of_irq_map_pci(pci_dev, &oirq)) {
u8 line, pin;
/* If that fails, lets fallback to what is in the config
* space and map that through the default controller. We
* also set the type to level low since that's what PCI
* interrupts are. If your platform does differently, then
* either provide a proper interrupt tree or don't use this
* function.
*/
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
return -1;
if (pin == 0)
return -1;
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
line == 0xff) {
return -1;
}
DBG(" -> no map ! Using irq line %d from PCI config\n", line);
virq = irq_create_mapping(NULL, line);
if (virq != NO_IRQ)
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
} else {
DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.specifier[1],
oirq.controller->full_name);
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
}
if(virq == NO_IRQ) {
DBG(" -> failed to map !\n");
return -1;
}
DBG(" -> mapped to linux irq %d\n", virq);
pci_dev->irq = virq;
return 0;
}
EXPORT_SYMBOL(pci_read_irq_line);
/*
* Platform support for /proc/bus/pci/X/Y mmap()s,
* modelled on the sparc64 implementation by Dave Miller.
* -- paulus.
*/
/*
* Adjust vm_pgoff of VMA such that it is the physical page offset
* corresponding to the 32-bit pci bus offset for DEV requested by the user.
*
* Basically, the user finds the base address for his device which he wishes
* to mmap. They read the 32-bit value from the config space base register,
* add whatever PAGE_SIZE multiple offset they wish, and feed this into the
* offset parameter of mmap on /proc/bus/pci/XXX for that device.
*
* Returns negative error code on failure, zero on success.
*/
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
unsigned long io_offset = 0;
int i, res_bit;
if (hose == 0)
return NULL; /* should never happen */
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
/*
* Check that the offset requested corresponds to one of the
* resources of the device.
*/
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &dev->resource[i];
int flags = rp->flags;
/* treat ROM as memory (should be already) */
if (i == PCI_ROM_RESOURCE)
flags |= IORESOURCE_MEM;
/* Active and same type? */
if ((flags & res_bit) == 0)
continue;
/* In the range of this resource? */
if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
continue;
/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
*offset += hose->io_base_phys - io_offset;
return rp;
}
return NULL;
}
/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
pgprot_t protection,
enum pci_mmap_state mmap_state,
int write_combine)
{
unsigned long prot = pgprot_val(protection);
/* Write combine is always 0 on non-memory space mappings. On
* memory space, if the user didn't pass 1, we check for a
* "prefetchable" resource. This is a bit hackish, but we use
* this to workaround the inability of /sysfs to provide a write
* combine bit
*/
if (mmap_state != pci_mmap_mem)
write_combine = 0;
else if (write_combine == 0) {
if (rp->flags & IORESOURCE_PREFETCH)
write_combine = 1;
}
/* XXX would be nice to have a way to ask for write-through */
prot |= _PAGE_NO_CACHE;
if (write_combine)
prot &= ~_PAGE_GUARDED;
else
prot |= _PAGE_GUARDED;
return __pgprot(prot);
}
/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
*/
pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
unsigned long size,
pgprot_t protection)
{
struct pci_dev *pdev = NULL;
struct resource *found = NULL;
unsigned long prot = pgprot_val(protection);
unsigned long offset = pfn << PAGE_SHIFT;
int i;
if (page_is_ram(pfn))
return __pgprot(prot);
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
for_each_pci_dev(pdev) {
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &pdev->resource[i];
int flags = rp->flags;
/* Active and same type? */
if ((flags & IORESOURCE_MEM) == 0)
continue;
/* In the range of this resource? */
if (offset < (rp->start & PAGE_MASK) ||
offset > rp->end)
continue;
found = rp;
break;
}
if (found)
break;
}
if (found) {
if (found->flags & IORESOURCE_PREFETCH)
prot &= ~_PAGE_GUARDED;
pci_dev_put(pdev);
}
DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
return __pgprot(prot);
}
/*
* Perform the actual remap of the pages for a PCI device mapping, as
* appropriate for this architecture. The region in the process to map
* is described by vm_start and vm_end members of VMA, the base physical
* address is found in vm_pgoff.
* The pci device structure is provided so that architectures may make mapping
* decisions on a per-device or per-bus basis.
*
* Returns a negative error code on failure, zero on success.
*/
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
if (rp == NULL)
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
vma->vm_page_prot,
mmap_state, write_combine);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
return ret;
}
void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
/* We pass a fully fixed up address to userland for MMIO instead of
* a BAR value because X is lame and expects to be able to use that
* to pass to /dev/mem !
*
* That means that we'll have potentially 64 bits values where some
* userland apps only expect 32 (like X itself since it thinks only
* Sparc has 64 bits MMIO) but if we don't do that, we break it on
* 32 bits CHRPs :-(
*
* Hopefully, the sysfs insterface is immune to that gunk. Once X
* has been fixed (and the fix spread enough), we can re-enable the
* 2 lines below and pass down a BAR value to userland. In that case
* we'll also have to re-enable the matching code in
* __pci_mmap_make_offset().
*
* BenH.
*/
#if 0
else if (rsrc->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
#endif
*start = rsrc->start - offset;
*end = rsrc->end - offset;
}

View File

@ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map;
*/
int pci_assign_all_buses;
struct pci_controller* hose_head;
struct pci_controller** hose_tail = &hose_head;
LIST_HEAD(hose_list);
static int pci_bus_count;
@ -573,58 +572,6 @@ pcibios_assign_resources(void)
}
}
int
pcibios_enable_resources(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
struct resource *r;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx=0; idx<6; idx++) {
/* Only set up the requested stuff */
if (!(mask & (1<<idx)))
continue;
r = &dev->resource[idx];
if (r->flags & IORESOURCE_UNSET) {
printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (r->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (dev->resource[PCI_ROM_RESOURCE].start)
cmd |= PCI_COMMAND_MEMORY;
if (cmd != old_cmd) {
printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0;
}
static int next_controller_index;
struct pci_controller * __init
pcibios_alloc_controller(void)
{
struct pci_controller *hose;
hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
memset(hose, 0, sizeof(struct pci_controller));
*hose_tail = hose;
hose_tail = &hose->next;
hose->index = next_controller_index++;
return hose;
}
#ifdef CONFIG_PPC_OF
/*
* Functions below are used on OpenFirmware machines.
@ -670,7 +617,7 @@ void
pcibios_make_OF_bus_map(void)
{
int i;
struct pci_controller* hose;
struct pci_controller *hose, *tmp;
struct property *map_prop;
struct device_node *dn;
@ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void)
pci_to_OF_bus_map[i] = 0xff;
/* For each hose, we begin searching bridges */
for(hose=hose_head; hose; hose=hose->next) {
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
struct device_node* node;
node = (struct device_node *)hose->arch_data;
if (!node)
@ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
/* Are we a root bus ? */
if (bus->self == NULL || bus->parent == NULL) {
struct pci_controller *hose = pci_bus_to_hose(bus->number);
struct pci_controller *hose = pci_bus_to_host(bus);
if (hose == NULL)
return NULL;
return of_node_get(hose->arch_data);
@ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev)
}
EXPORT_SYMBOL(pci_device_to_OF_node);
/* This routine is meant to be used early during boot, when the
* PCI bus numbers have not yet been assigned, and you need to
* issue PCI config cycles to an OF device.
* It could also be used to "fix" RTAS config cycles if you want
* to set pci_assign_all_buses to 1 and still use RTAS for PCI
* config cycles.
*/
struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
{
if (!have_of)
return NULL;
while(node) {
struct pci_controller* hose;
for (hose=hose_head;hose;hose=hose->next)
if (hose->arch_data == node)
return hose;
node=node->parent;
}
return NULL;
}
static int
find_OF_pci_device_filter(struct device_node* node, void* data)
{
@ -1027,34 +953,12 @@ pci_create_OF_bus_map(void)
}
}
static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
pdev = to_pci_dev (dev);
np = pci_device_to_OF_node(pdev);
if (np == NULL || np->full_name == NULL)
return 0;
return sprintf(buf, "%s", np->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
#else /* CONFIG_PPC_OF */
void pcibios_make_OF_bus_map(void)
{
}
#endif /* CONFIG_PPC_OF */
/* Add sysfs properties */
int pcibios_add_platform_entries(struct pci_dev *pdev)
{
#ifdef CONFIG_PPC_OF
return device_create_file(&pdev->dev, &dev_attr_devspec);
#endif /* CONFIG_PPC_OF */
}
#ifdef CONFIG_PPC_PMAC
/*
* This set of routines checks for PCI<->PCI bridges that have closed
@ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void)
static int __init
pcibios_init(void)
{
struct pci_controller *hose;
struct pci_controller *hose, *tmp;
struct pci_bus *bus;
int next_busno;
int next_busno = 0;
printk(KERN_INFO "PCI: Probing PCI hardware\n");
/* Scan all of the recorded PCI controllers. */
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
if (pci_assign_all_buses)
hose->first_busno = next_busno;
hose->last_busno = 0xff;
@ -1319,12 +1223,6 @@ pcibios_init(void)
subsys_initcall(pcibios_init);
unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
unsigned long start, unsigned long size)
{
return start;
}
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
if (!res->flags) {
if (io_offset)
printk(KERN_ERR "I/O resource not set for host"
" bridge %d\n", hose->index);
" bridge %d\n", hose->global_number);
res->start = 0;
res->end = IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
@ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
if (i > 0)
continue;
printk(KERN_ERR "Memory resource not set for "
"host bridge %d\n", hose->index);
"host bridge %d\n", hose->global_number);
res->start = hose->pci_mem_offset;
res->end = ~0U;
res->flags = IORESOURCE_MEM;
@ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
for (i = 0; i < 4; ++i) {
if ((res = bus->resource[i]) == NULL)
continue;
if (!res->flags)
if (!res->flags || bus->self->transparent)
continue;
if (io_offset && (res->flags & IORESOURCE_IO)) {
res->start += io_offset;
@ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
}
}
char __init *pcibios_setup(char *str)
{
return str;
}
/* the next one is stolen from the alpha port... */
void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
@ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
/* XXX FIXME - update OF device tree node interrupt property */
}
#ifdef CONFIG_PPC_MERGE
/* XXX This is a copy of the ppc64 version. This is temporary until we start
* merging the 2 PCI layers
*/
/*
* Reads the interrupt pin to determine if interrupt is use by card.
* If the interrupt is used, then gets the interrupt line from the
* openfirmware and sets it in the pci_dev and pci_config line.
*/
int pci_read_irq_line(struct pci_dev *pci_dev)
{
struct of_irq oirq;
unsigned int virq;
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
/* Try to get a mapping from the device-tree */
if (of_irq_map_pci(pci_dev, &oirq)) {
u8 line, pin;
/* If that fails, lets fallback to what is in the config
* space and map that through the default controller. We
* also set the type to level low since that's what PCI
* interrupts are. If your platform does differently, then
* either provide a proper interrupt tree or don't use this
* function.
*/
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
return -1;
if (pin == 0)
return -1;
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
line == 0xff) {
return -1;
}
DBG(" -> no map ! Using irq line %d from PCI config\n", line);
virq = irq_create_mapping(NULL, line);
if (virq != NO_IRQ)
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
} else {
DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.controller->full_name);
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
}
if(virq == NO_IRQ) {
DBG(" -> failed to map !\n");
return -1;
}
pci_dev->irq = virq;
return 0;
}
EXPORT_SYMBOL(pci_read_irq_line);
#endif /* CONFIG_PPC_MERGE */
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
@ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
struct pci_controller*
static struct pci_controller*
pci_bus_to_hose(int bus)
{
struct pci_controller* hose = hose_head;
struct pci_controller *hose, *tmp;
for (; hose; hose = hose->next)
list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
if (bus >= hose->first_busno && bus <= hose->last_busno)
return hose;
return NULL;
}
void __iomem *
pci_bus_io_base(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return NULL;
return hose->io_base_virt;
}
unsigned long
pci_bus_io_base_phys(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return 0;
return hose->io_base_phys;
}
unsigned long
pci_bus_mem_base_phys(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return 0;
return hose->pci_mem_offset;
}
unsigned long
pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
{
/* Hack alert again ! See comments in chrp_pci.c
*/
struct pci_controller* hose =
(struct pci_controller *)pdev->sysdata;
if (hose && res->flags & IORESOURCE_MEM)
return res->start - hose->pci_mem_offset;
/* We may want to do something with IOs here... */
return res->start;
}
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
unsigned long io_offset = 0;
int i, res_bit;
if (hose == 0)
return NULL; /* should never happen */
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
/*
* Check that the offset requested corresponds to one of the
* resources of the device.
*/
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &dev->resource[i];
int flags = rp->flags;
/* treat ROM as memory (should be already) */
if (i == PCI_ROM_RESOURCE)
flags |= IORESOURCE_MEM;
/* Active and same type? */
if ((flags & res_bit) == 0)
continue;
/* In the range of this resource? */
if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
continue;
/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
*offset += hose->io_base_phys - io_offset;
return rp;
}
return NULL;
}
/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
pgprot_t protection,
enum pci_mmap_state mmap_state,
int write_combine)
{
unsigned long prot = pgprot_val(protection);
/* Write combine is always 0 on non-memory space mappings. On
* memory space, if the user didn't pass 1, we check for a
* "prefetchable" resource. This is a bit hackish, but we use
* this to workaround the inability of /sysfs to provide a write
* combine bit
*/
if (mmap_state != pci_mmap_mem)
write_combine = 0;
else if (write_combine == 0) {
if (rp->flags & IORESOURCE_PREFETCH)
write_combine = 1;
}
/* XXX would be nice to have a way to ask for write-through */
prot |= _PAGE_NO_CACHE;
if (write_combine)
prot &= ~_PAGE_GUARDED;
else
prot |= _PAGE_GUARDED;
return __pgprot(prot);
}
/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
*/
pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
unsigned long size,
pgprot_t protection)
{
struct pci_dev *pdev = NULL;
struct resource *found = NULL;
unsigned long prot = pgprot_val(protection);
unsigned long offset = pfn << PAGE_SHIFT;
int i;
if (page_is_ram(pfn))
return __pgprot(prot);
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
for_each_pci_dev(pdev) {
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &pdev->resource[i];
int flags = rp->flags;
/* Active and same type? */
if ((flags & IORESOURCE_MEM) == 0)
continue;
/* In the range of this resource? */
if (offset < (rp->start & PAGE_MASK) ||
offset > rp->end)
continue;
found = rp;
break;
}
if (found)
break;
}
if (found) {
if (found->flags & IORESOURCE_PREFETCH)
prot &= ~_PAGE_GUARDED;
pci_dev_put(pdev);
}
DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
return __pgprot(prot);
}
/*
* Perform the actual remap of the pages for a PCI device mapping, as
* appropriate for this architecture. The region in the process to map
* is described by vm_start and vm_end members of VMA, the base physical
* address is found in vm_pgoff.
* The pci device structure is provided so that architectures may make mapping
* decisions on a per-device or per-bus basis.
*
* Returns a negative error code on failure, zero on success.
*/
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state,
int write_combine)
{
resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
if (rp == NULL)
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
vma->vm_page_prot,
mmap_state, write_combine);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
return ret;
}
/* Obsolete functions. Should be removed once the symbios driver
* is fixed
*/
unsigned long
phys_to_bus(unsigned long pa)
{
struct pci_controller *hose;
int i;
for (hose = hose_head; hose; hose = hose->next) {
for (i = 0; i < 3; ++i) {
if (pa >= hose->mem_resources[i].start
&& pa <= hose->mem_resources[i].end) {
/*
* XXX the hose->pci_mem_offset really
* only applies to mem_resources[0].
* We need a way to store an offset for
* the others. -- paulus
*/
if (i == 0)
pa -= hose->pci_mem_offset;
return pa;
}
}
}
/* hmmm, didn't find it */
return 0;
}
unsigned long
pci_phys_to_bus(unsigned long pa, int busnr)
{
struct pci_controller* hose = pci_bus_to_hose(busnr);
if (!hose)
return pa;
return pa - hose->pci_mem_offset;
}
unsigned long
pci_bus_to_phys(unsigned int ba, int busnr)
{
struct pci_controller* hose = pci_bus_to_hose(busnr);
if (!hose)
return ba;
return ba + hose->pci_mem_offset;
}
/* Provide information on locations of various I/O regions in physical
* memory. Do this on a per-card basis so that we choose the right
* root bridge.
@ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
return result;
}
void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
/* We pass a fully fixed up address to userland for MMIO instead of
* a BAR value because X is lame and expects to be able to use that
* to pass to /dev/mem !
*
* That means that we'll have potentially 64 bits values where some
* userland apps only expect 32 (like X itself since it thinks only
* Sparc has 64 bits MMIO) but if we don't do that, we break it on
* 32 bits CHRPs :-(
*
* Hopefully, the sysfs insterface is immune to that gunk. Once X
* has been fixed (and the fix spread enough), we can re-enable the
* 2 lines below and pass down a BAR value to userland. In that case
* we'll also have to re-enable the matching code in
* __pci_mmap_make_offset().
*
* BenH.
*/
#if 0
else if (rsrc->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
#endif
*start = rsrc->start - offset;
*end = rsrc->end - offset;
}
void __init pci_init_resource(struct resource *res, resource_size_t start,
resource_size_t end, int flags, char *name)
{
res->start = start;
res->end = end;
res->flags = flags;
res->name = name;
res->parent = NULL;
res->sibling = NULL;
res->child = NULL;
}
unsigned long pci_address_to_pio(phys_addr_t address)
{
struct pci_controller* hose = hose_head;
struct pci_controller *hose, *tmp;
for (; hose; hose = hose->next) {
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
unsigned int size = hose->io_resource.end -
hose->io_resource.start + 1;
if (address >= hose->io_base_phys &&

View File

@ -22,6 +22,7 @@
#include <linux/list.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <linux/vmalloc.h>
#include <asm/processor.h>
#include <asm/io.h>
@ -41,35 +42,23 @@
unsigned long pci_probe_only = 1;
int pci_assign_all_buses = 0;
static int pci_initial_scan_done;
static void fixup_resource(struct resource *res, struct pci_dev *dev);
static void do_bus_setup(struct pci_bus *bus);
static void phbs_remap_io(void);
/* pci_io_base -- the base address from which io bars are offsets.
* This is the lowest I/O base address (so bar values are always positive),
* and it *must* be the start of ISA space if an ISA bus exists because
* ISA drivers use hard coded offsets. If no ISA bus exists a dummy
* page is mapped and isa_io_limit prevents access to it.
* ISA drivers use hard coded offsets. If no ISA bus exists nothing
* is mapped on the first 64K of IO space
*/
unsigned long isa_io_base; /* NULL if no ISA bus */
EXPORT_SYMBOL(isa_io_base);
unsigned long pci_io_base;
unsigned long pci_io_base = ISA_IO_BASE;
EXPORT_SYMBOL(pci_io_base);
void iSeries_pcibios_init(void);
LIST_HEAD(hose_list);
static struct dma_mapping_ops *pci_dma_ops;
int global_phb_number; /* Global phb counter */
/* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL;
EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
{
pci_dma_ops = dma_ops;
@ -100,7 +89,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region
return;
if (res->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - pci_io_base;
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
@ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
return;
if (res->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - pci_io_base;
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
if (res->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
@ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res,
if (res->flags & IORESOURCE_IO) {
unsigned long offset = (unsigned long)hose->io_base_virt -
pci_io_base;
_IO_BASE;
/* Make sure we start at our min on all hoses */
if (start - offset < PCIBIOS_MIN_IO)
start = PCIBIOS_MIN_IO + offset;
@ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res,
res->start = start;
}
static DEFINE_SPINLOCK(hose_spinlock);
/*
* pci_controller(phb) initialized common variables.
*/
static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
{
memset(hose, 0, sizeof(struct pci_controller));
spin_lock(&hose_spinlock);
hose->global_number = global_phb_number++;
list_add_tail(&hose->list_node, &hose_list);
spin_unlock(&hose_spinlock);
}
struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
{
struct pci_controller *phb;
if (mem_init_done)
phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
else
phb = alloc_bootmem(sizeof (struct pci_controller));
if (phb == NULL)
return NULL;
pci_setup_pci_controller(phb);
phb->arch_data = dev;
phb->is_dynamic = mem_init_done;
if (dev) {
int nid = of_node_to_nid(dev);
if (nid < 0 || !node_online(nid))
nid = -1;
PHB_SET_NODE(phb, nid);
}
return phb;
}
void pcibios_free_controller(struct pci_controller *phb)
{
spin_lock(&hose_spinlock);
list_del(&phb->list_node);
spin_unlock(&hose_spinlock);
if (phb->is_dynamic)
kfree(phb);
}
void __devinit pcibios_claim_one_bus(struct pci_bus *b)
{
struct pci_dev *dev;
@ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0)
return flags;
}
#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
{
@ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
flags = pci_parse_of_flags(addrs[0]);
if (!flags)
continue;
base = GET_64BIT(addrs, 1);
size = GET_64BIT(addrs, 3);
base = of_read_number(&addrs[1], 2);
size = of_read_number(&addrs[3], 2);
if (!size)
continue;
i = addrs[0] & 0xff;
@ -479,7 +418,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
flags = pci_parse_of_flags(ranges[0]);
size = GET_64BIT(ranges, 6);
size = of_read_number(&ranges[6], 2);
if (flags == 0 || size == 0)
continue;
if (flags & IORESOURCE_IO) {
@ -498,7 +437,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
res = bus->resource[i];
++i;
}
res->start = GET_64BIT(ranges, 1);
res->start = of_read_number(&ranges[1], 2);
res->end = res->start + size - 1;
res->flags = flags;
fixup_resource(res, dev);
@ -537,10 +476,16 @@ void __devinit scan_phb(struct pci_controller *hose)
bus->secondary = hose->first_busno;
hose->bus = bus;
if (!firmware_has_feature(FW_FEATURE_ISERIES))
pcibios_map_io_space(bus);
bus->resource[0] = res = &hose->io_resource;
if (res->flags && request_resource(&ioport_resource, res))
if (res->flags && request_resource(&ioport_resource, res)) {
printk(KERN_ERR "Failed to request PCI IO region "
"on PCI domain %04x\n", hose->global_number);
DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
res->start, res->end);
}
for (i = 0; i < 3; ++i) {
res = &hose->mem_resources[i];
@ -598,17 +543,6 @@ static int __init pcibios_init(void)
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
/* Cache the location of the ISA bridge (if we have one) */
ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
if (ppc64_isabridge_dev != NULL)
printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
if (!firmware_has_feature(FW_FEATURE_ISERIES))
/* map in PCI I/O space */
phbs_remap_io();
pci_initial_scan_done = 1;
printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
return 0;
@ -616,11 +550,6 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init);
char __init *pcibios_setup(char *str)
{
return str;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, oldcmd;
@ -651,22 +580,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
/*
* Return the domain number for this bus.
*/
int pci_domain_nr(struct pci_bus *bus)
{
if (firmware_has_feature(FW_FEATURE_ISERIES))
return 0;
else {
struct pci_controller *hose = pci_bus_to_host(bus);
return hose->global_number;
}
}
EXPORT_SYMBOL(pci_domain_nr);
/* Decide whether to display the domain number in /proc */
int pci_proc_domain(struct pci_bus *bus)
{
@ -678,281 +591,6 @@ int pci_proc_domain(struct pci_bus *bus)
}
}
/*
* Platform support for /proc/bus/pci/X/Y mmap()s,
* modelled on the sparc64 implementation by Dave Miller.
* -- paulus.
*/
/*
* Adjust vm_pgoff of VMA such that it is the physical page offset
* corresponding to the 32-bit pci bus offset for DEV requested by the user.
*
* Basically, the user finds the base address for his device which he wishes
* to mmap. They read the 32-bit value from the config space base register,
* add whatever PAGE_SIZE multiple offset they wish, and feed this into the
* offset parameter of mmap on /proc/bus/pci/XXX for that device.
*
* Returns negative error code on failure, zero on success.
*/
static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
resource_size_t *offset,
enum pci_mmap_state mmap_state)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
unsigned long io_offset = 0;
int i, res_bit;
if (hose == 0)
return NULL; /* should never happen */
/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
*offset += hose->pci_mem_offset;
#endif
res_bit = IORESOURCE_MEM;
} else {
io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
/*
* Check that the offset requested corresponds to one of the
* resources of the device.
*/
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &dev->resource[i];
int flags = rp->flags;
/* treat ROM as memory (should be already) */
if (i == PCI_ROM_RESOURCE)
flags |= IORESOURCE_MEM;
/* Active and same type? */
if ((flags & res_bit) == 0)
continue;
/* In the range of this resource? */
if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
continue;
/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
*offset += hose->io_base_phys - io_offset;
return rp;
}
return NULL;
}
/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
pgprot_t protection,
enum pci_mmap_state mmap_state,
int write_combine)
{
unsigned long prot = pgprot_val(protection);
/* Write combine is always 0 on non-memory space mappings. On
* memory space, if the user didn't pass 1, we check for a
* "prefetchable" resource. This is a bit hackish, but we use
* this to workaround the inability of /sysfs to provide a write
* combine bit
*/
if (mmap_state != pci_mmap_mem)
write_combine = 0;
else if (write_combine == 0) {
if (rp->flags & IORESOURCE_PREFETCH)
write_combine = 1;
}
/* XXX would be nice to have a way to ask for write-through */
prot |= _PAGE_NO_CACHE;
if (write_combine)
prot &= ~_PAGE_GUARDED;
else
prot |= _PAGE_GUARDED;
return __pgprot(prot);
}
/*
* This one is used by /dev/mem and fbdev who have no clue about the
* PCI device, it tries to find the PCI device first and calls the
* above routine
*/
pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
unsigned long size,
pgprot_t protection)
{
struct pci_dev *pdev = NULL;
struct resource *found = NULL;
unsigned long prot = pgprot_val(protection);
unsigned long offset = pfn << PAGE_SHIFT;
int i;
if (page_is_ram(pfn))
return __pgprot(prot);
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
for_each_pci_dev(pdev) {
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &pdev->resource[i];
int flags = rp->flags;
/* Active and same type? */
if ((flags & IORESOURCE_MEM) == 0)
continue;
/* In the range of this resource? */
if (offset < (rp->start & PAGE_MASK) ||
offset > rp->end)
continue;
found = rp;
break;
}
if (found)
break;
}
if (found) {
if (found->flags & IORESOURCE_PREFETCH)
prot &= ~_PAGE_GUARDED;
pci_dev_put(pdev);
}
DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
return __pgprot(prot);
}
/*
* Perform the actual remap of the pages for a PCI device mapping, as
* appropriate for this architecture. The region in the process to map
* is described by vm_start and vm_end members of VMA, the base physical
* address is found in vm_pgoff.
* The pci device structure is provided so that architectures may make mapping
* decisions on a per-device or per-bus basis.
*
* Returns a negative error code on failure, zero on success.
*/
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
int ret;
rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
if (rp == NULL)
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
vma->vm_page_prot,
mmap_state, write_combine);
ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
return ret;
}
static ssize_t pci_show_devspec(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
pdev = to_pci_dev (dev);
np = pci_device_to_OF_node(pdev);
if (np == NULL || np->full_name == NULL)
return 0;
return sprintf(buf, "%s", np->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
int pcibios_add_platform_entries(struct pci_dev *pdev)
{
return device_create_file(&pdev->dev, &dev_attr_devspec);
}
#define ISA_SPACE_MASK 0x1
#define ISA_SPACE_IO 0x1
static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
unsigned long phb_io_base_phys,
void __iomem * phb_io_base_virt)
{
/* Remove these asap */
struct pci_address {
u32 a_hi;
u32 a_mid;
u32 a_lo;
};
struct isa_address {
u32 a_hi;
u32 a_lo;
};
struct isa_range {
struct isa_address isa_addr;
struct pci_address pci_addr;
unsigned int size;
};
const struct isa_range *range;
unsigned long pci_addr;
unsigned int isa_addr;
unsigned int size;
int rlen = 0;
range = of_get_property(isa_node, "ranges", &rlen);
if (range == NULL || (rlen < sizeof(struct isa_range))) {
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
"mapping 64k\n");
__ioremap_explicit(phb_io_base_phys,
(unsigned long)phb_io_base_virt,
0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED);
return;
}
/* From "ISA Binding to 1275"
* The ranges property is laid out as an array of elements,
* each of which comprises:
* cells 0 - 1: an ISA address
* cells 2 - 4: a PCI address
* (size depending on dev->n_addr_cells)
* cell 5: the size of the range
*/
if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
isa_addr = range->isa_addr.a_lo;
pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |
range->pci_addr.a_lo;
/* Assume these are both zero */
if ((pci_addr != 0) || (isa_addr != 0)) {
printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
__FUNCTION__);
return;
}
size = PAGE_ALIGN(range->size);
__ioremap_explicit(phb_io_base_phys,
(unsigned long) phb_io_base_virt,
size, _PAGE_NO_CACHE | _PAGE_GUARDED);
}
}
void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev, int prim)
{
@ -1047,155 +685,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
}
}
void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
#ifdef CONFIG_HOTPLUG
int pcibios_unmap_io_space(struct pci_bus *bus)
{
unsigned long size = hose->pci_io_size;
unsigned long io_virt_offset;
struct resource *res;
struct device_node *isa_dn;
struct pci_controller *hose;
if (size == 0)
return;
WARN_ON(bus == NULL);
hose->io_base_virt = reserve_phb_iospace(size);
DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
hose->global_number, hose->io_base_phys,
(unsigned long) hose->io_base_virt);
if (primary) {
pci_io_base = (unsigned long)hose->io_base_virt;
isa_dn = of_find_node_by_type(NULL, "isa");
if (isa_dn) {
isa_io_base = pci_io_base;
pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
hose->io_base_virt);
of_node_put(isa_dn);
}
}
io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
res = &hose->io_resource;
res->start += io_virt_offset;
res->end += io_virt_offset;
/* If this is called after the initial PCI scan, then we need to
* proceed to IO mappings now
/* If this is not a PHB, we only flush the hash table over
* the area mapped by this bridge. We don't play with the PTE
* mappings since we might have to deal with sub-page alignemnts
* so flushing the hash table is the only sane way to make sure
* that no hash entries are covering that removed bridge area
* while still allowing other busses overlapping those pages
*/
if (pci_initial_scan_done)
__ioremap_explicit(hose->io_base_phys,
(unsigned long)hose->io_base_virt,
hose->pci_io_size,
_PAGE_NO_CACHE | _PAGE_GUARDED);
if (bus->self) {
struct resource *res = bus->resource[0];
DBG("IO unmapping for PCI-PCI bridge %s\n",
pci_name(bus->self));
__flush_hash_table_range(&init_mm, res->start + _IO_BASE,
res->end - res->start + 1);
return 0;
}
void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
int primary)
/* Get the host bridge */
hose = pci_bus_to_host(bus);
/* Check if we have IOs allocated */
if (hose->io_base_alloc == 0)
return 0;
DBG("IO unmapping for PHB %s\n",
((struct device_node *)hose->arch_data)->full_name);
DBG(" alloc=0x%p\n", hose->io_base_alloc);
/* This is a PHB, we fully unmap the IO area */
vunmap(hose->io_base_alloc);
return 0;
}
EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
#endif /* CONFIG_HOTPLUG */
int __devinit pcibios_map_io_space(struct pci_bus *bus)
{
unsigned long size = hose->pci_io_size;
struct vm_struct *area;
unsigned long phys_page;
unsigned long size_page;
unsigned long io_virt_offset;
struct resource *res;
struct pci_controller *hose;
if (size == 0)
return;
hose->io_base_virt = __ioremap(hose->io_base_phys, size,
_PAGE_NO_CACHE | _PAGE_GUARDED);
DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
hose->global_number, hose->io_base_phys,
(unsigned long) hose->io_base_virt);
if (primary)
pci_io_base = (unsigned long)hose->io_base_virt;
io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
res = &hose->io_resource;
res->start += io_virt_offset;
res->end += io_virt_offset;
}
static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
unsigned long *start_virt, unsigned long *size)
{
struct pci_controller *hose = pci_bus_to_host(bus);
struct resource *res;
if (bus->self)
res = bus->resource[0];
else
/* Root Bus */
res = &hose->io_resource;
if (res->end == 0 && res->start == 0)
return 1;
*start_virt = pci_io_base + res->start;
*start_phys = *start_virt + hose->io_base_phys
- (unsigned long) hose->io_base_virt;
if (res->end > res->start)
*size = res->end - res->start + 1;
else {
printk("%s(): unexpected region 0x%lx->0x%lx\n",
__FUNCTION__, res->start, res->end);
return 1;
}
WARN_ON(bus == NULL);
/* If this not a PHB, nothing to do, page tables still exist and
* thus HPTEs will be faulted in when needed
*/
if (bus->self) {
DBG("IO mapping for PCI-PCI bridge %s\n",
pci_name(bus->self));
DBG(" virt=0x%016lx...0x%016lx\n",
bus->resource[0]->start + _IO_BASE,
bus->resource[0]->end + _IO_BASE);
return 0;
}
int unmap_bus_range(struct pci_bus *bus)
{
unsigned long start_phys;
unsigned long start_virt;
unsigned long size;
/* Get the host bridge */
hose = pci_bus_to_host(bus);
phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
if (!bus) {
printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
return 1;
}
/* Make sure IO area address is clear */
hose->io_base_alloc = NULL;
if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
return 1;
if (__iounmap_explicit((void __iomem *) start_virt, size))
return 1;
/* If there's no IO to map on that bus, get away too */
if (hose->pci_io_size == 0 || hose->io_base_phys == 0)
return 0;
/* Let's allocate some IO space for that guy. We don't pass
* VM_IOREMAP because we don't care about alignment tricks that
* the core does in that case. Maybe we should due to stupid card
* with incomplete address decoding but I'd rather not deal with
* those outside of the reserved 64K legacy region.
*/
area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
if (area == NULL)
return -ENOMEM;
hose->io_base_alloc = area->addr;
hose->io_base_virt = (void __iomem *)(area->addr +
hose->io_base_phys - phys_page);
DBG("IO mapping for PHB %s\n",
((struct device_node *)hose->arch_data)->full_name);
DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
DBG(" size=0x%016lx (alloc=0x%016lx)\n",
hose->pci_io_size, size_page);
/* Establish the mapping */
if (__ioremap_at(phys_page, area->addr, size_page,
_PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
return -ENOMEM;
/* Fixup hose IO resource */
io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
hose->io_resource.start += io_virt_offset;
hose->io_resource.end += io_virt_offset;
DBG(" hose->io_resource=0x%016lx...0x%016lx\n",
hose->io_resource.start, hose->io_resource.end);
return 0;
}
EXPORT_SYMBOL(unmap_bus_range);
int remap_bus_range(struct pci_bus *bus)
{
unsigned long start_phys;
unsigned long start_virt;
unsigned long size;
if (!bus) {
printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
return 1;
}
if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
return 1;
if (start_phys == 0)
return 1;
printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
if (__ioremap_explicit(start_phys, start_virt, size,
_PAGE_NO_CACHE | _PAGE_GUARDED))
return 1;
return 0;
}
EXPORT_SYMBOL(remap_bus_range);
static void phbs_remap_io(void)
{
struct pci_controller *hose, *tmp;
list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
remap_bus_range(hose->bus);
}
EXPORT_SYMBOL_GPL(pcibios_map_io_space);
static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
{
@ -1203,8 +808,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
unsigned long offset;
if (res->flags & IORESOURCE_IO) {
offset = (unsigned long)hose->io_base_virt - pci_io_base;
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
res->start += offset;
res->end += offset;
} else if (res->flags & IORESOURCE_MEM) {
@ -1219,9 +823,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
/* Update device resources. */
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++)
if (dev->resource[i].flags)
fixup_resource(&dev->resource[i], dev);
DBG("%s: Fixup resources:\n", pci_name(dev));
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = &dev->resource[i];
if (!res->flags)
continue;
DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n",
i, res->flags, res->start, res->end);
fixup_resource(res, dev);
DBG(" > %08lx:0x%016lx...0x%016lx\n",
res->flags, res->start, res->end);
}
}
EXPORT_SYMBOL(pcibios_fixup_device_resources);
@ -1291,119 +906,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL(pcibios_fixup_bus);
/*
* Reads the interrupt pin to determine if interrupt is use by card.
* If the interrupt is used, then gets the interrupt line from the
* openfirmware and sets it in the pci_dev and pci_config line.
*/
int pci_read_irq_line(struct pci_dev *pci_dev)
{
struct of_irq oirq;
unsigned int virq;
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
#ifdef DEBUG
memset(&oirq, 0xff, sizeof(oirq));
#endif
/* Try to get a mapping from the device-tree */
if (of_irq_map_pci(pci_dev, &oirq)) {
u8 line, pin;
/* If that fails, lets fallback to what is in the config
* space and map that through the default controller. We
* also set the type to level low since that's what PCI
* interrupts are. If your platform does differently, then
* either provide a proper interrupt tree or don't use this
* function.
*/
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
return -1;
if (pin == 0)
return -1;
if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
line == 0xff) {
return -1;
}
DBG(" -> no map ! Using irq line %d from PCI config\n", line);
virq = irq_create_mapping(NULL, line);
if (virq != NO_IRQ)
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
} else {
DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.specifier[1],
oirq.controller->full_name);
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
}
if(virq == NO_IRQ) {
DBG(" -> failed to map !\n");
return -1;
}
DBG(" -> mapped to linux irq %d\n", virq);
pci_dev->irq = virq;
return 0;
}
EXPORT_SYMBOL(pci_read_irq_line);
void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
resource_size_t offset = 0;
if (hose == NULL)
return;
if (rsrc->flags & IORESOURCE_IO)
offset = (unsigned long)hose->io_base_virt - pci_io_base;
/* We pass a fully fixed up address to userland for MMIO instead of
* a BAR value because X is lame and expects to be able to use that
* to pass to /dev/mem !
*
* That means that we'll have potentially 64 bits values where some
* userland apps only expect 32 (like X itself since it thinks only
* Sparc has 64 bits MMIO) but if we don't do that, we break it on
* 32 bits CHRPs :-(
*
* Hopefully, the sysfs insterface is immune to that gunk. Once X
* has been fixed (and the fix spread enough), we can re-enable the
* 2 lines below and pass down a BAR value to userland. In that case
* we'll also have to re-enable the matching code in
* __pci_mmap_make_offset().
*
* BenH.
*/
#if 0
else if (rsrc->flags & IORESOURCE_MEM)
offset = hose->pci_mem_offset;
#endif
*start = rsrc->start - offset;
*end = rsrc->end - offset;
}
struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
{
if (!have_of)
return NULL;
while(node) {
struct pci_controller *hose, *tmp;
list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
if (hose->arch_data == node)
return hose;
node = node->parent;
}
return NULL;
}
unsigned long pci_address_to_pio(phys_addr_t address)
{
struct pci_controller *hose, *tmp;
@ -1412,7 +914,7 @@ unsigned long pci_address_to_pio(phys_addr_t address)
if (address >= hose->io_base_phys &&
address < (hose->io_base_phys + hose->pci_io_size)) {
unsigned long base =
(unsigned long)hose->io_base_virt - pci_io_base;
(unsigned long)hose->io_base_virt - _IO_BASE;
return base + (address - hose->io_base_phys);
}
}

View File

@ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
EXPORT_SYMBOL(DMA_MODE_READ);
EXPORT_SYMBOL(DMA_MODE_WRITE);
EXPORT_SYMBOL(do_signal);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(machine_check_exception);
@ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_dram_offset);
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
EXPORT_SYMBOL(pci_bus_io_base);
EXPORT_SYMBOL(pci_bus_io_base_phys);
EXPORT_SYMBOL(pci_bus_mem_base_phys);
EXPORT_SYMBOL(pci_bus_to_hose);
#endif /* CONFIG_PCI */
EXPORT_SYMBOL(start_thread);

View File

@ -219,22 +219,26 @@ void discard_lazy_cpu_state(void)
}
#endif /* CONFIG_SMP */
#ifdef CONFIG_PPC_MERGE /* XXX for now */
int set_dabr(unsigned long dabr)
{
#ifdef CONFIG_PPC_MERGE /* XXX for now */
if (ppc_md.set_dabr)
return ppc_md.set_dabr(dabr);
#endif
/* XXX should we have a CPU_FTR_HAS_DABR ? */
#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
mtspr(SPRN_DABR, dabr);
#endif
return 0;
}
#endif
#ifdef CONFIG_PPC64
DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
static DEFINE_PER_CPU(unsigned long, current_dabr);
#endif
static DEFINE_PER_CPU(unsigned long, current_dabr);
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
{
@ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
#endif /* CONFIG_SMP */
#ifdef CONFIG_PPC64 /* for now */
if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
set_dabr(new->thread.dabr);
__get_cpu_var(current_dabr) = new->thread.dabr;
}
#endif /* CONFIG_PPC64 */
new_thread = &new->thread;
old_thread = &current->thread;
@ -473,12 +475,10 @@ void flush_thread(void)
discard_lazy_cpu_state();
#ifdef CONFIG_PPC64 /* for now */
if (current->thread.dabr) {
current->thread.dabr = 0;
set_dabr(0);
}
#endif
}
void

View File

@ -52,6 +52,7 @@
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
#include <asm/kexec.h>
#include <asm/system.h>
#ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt)
@ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void)
void __init early_init_devtree(void *params)
{
DBG(" -> early_init_devtree()\n");
DBG(" -> early_init_devtree(%p)\n", params);
/* Setup flat device-tree pointer */
initial_boot_params = params;
@ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params)
DBG(" <- early_init_devtree()\n");
}
#undef printk
int of_n_addr_cells(struct device_node* np)
{
const int *ip;
@ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref)
struct device_node *node = kref_to_device_node(kref);
struct property *prop = node->properties;
if (!OF_IS_DYNAMIC(node))
/* We should never be releasing nodes that haven't been detached. */
if (!of_node_check_flag(node, OF_DETACHED)) {
printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
dump_stack();
kref_init(&node->kref);
return;
}
if (!of_node_check_flag(node, OF_DYNAMIC))
return;
while (prop) {
struct property *next = prop->next;
kfree(prop->name);
@ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np)
write_lock(&devtree_lock);
parent = np->parent;
if (!parent)
goto out_unlock;
if (allnodes == np)
allnodes = np->allnext;
@ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np)
prevsib->sibling = np->sibling;
}
of_node_set_flag(np, OF_DETACHED);
out_unlock:
write_unlock(&devtree_lock);
}
@ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
}
EXPORT_SYMBOL(of_get_cpu_node);
#ifdef DEBUG
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
static struct debugfs_blob_wrapper flat_dt_blob;
static int __init export_flat_device_tree(void)
{
struct dentry *d;
d = debugfs_create_dir("powerpc", NULL);
if (!d)
return 1;
flat_dt_blob.data = initial_boot_params;
flat_dt_blob.size = initial_boot_params->totalsize;
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
d, &flat_dt_blob);
powerpc_debugfs_root, &flat_dt_blob);
if (!d)
return 1;

View File

@ -635,6 +635,7 @@ static void __init early_cmdline_parse(void)
/* ibm,dynamic-reconfiguration-memory property supported */
#define OV5_DRCONF_MEMORY 0x20
#define OV5_LARGE_PAGES 0x10 /* large pages supported */
#define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */
/* PCIe/MSI support. Without MSI full PCIe is not supported */
#ifdef CONFIG_PCI_MSI
#define OV5_MSI 0x01 /* PCIe/MSI support */
@ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = {
/* option vector 5: PAPR/OF options */
3 - 2, /* length */
0, /* don't ignore, don't halt */
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI,
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
OV5_DONATE_DEDICATE_CPU | OV5_MSI,
};
/* Old method - ELF header with PT_NOTE sections */

View File

@ -1,161 +0,0 @@
/*
* Copyright (c) 2002 Stephen Rothwell, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/
#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H
#include <asm/system.h>
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
{
unsigned long tmp = 0;
/*
* Put the correct FP bits in, they might be wrong as a result
* of our lazy FP restore.
*/
if (regno == PT_MSR) {
tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
tmp |= task->thread.fpexc_mode;
} else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
tmp = ((unsigned long *)task->thread.regs)[regno];
}
return tmp;
}
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
if (regno < PT_SOFTE) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
static inline void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
static inline void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
#ifdef CONFIG_ALTIVEC
/*
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
* The transfer totals 34 quadword. Quadwords 0-31 contain the
* corresponding vector registers. Quadword 32 contains the vscr as the
* last word (offset 12) within that quadword. Quadword 33 contains the
* vrsave as the first word (offset 0) within the quadword.
*
* This definition of the VMX state is compatible with the current PPC32
* ptrace interface. This allows signal handling and ptrace to use the
* same structures. This also simplifies the implementation of a bi-arch
* (combined (32- and 64-bit) gdb.
*/
/*
* Get contents of AltiVec register state in task TASK
*/
static inline int get_vrregs(unsigned long __user *data,
struct task_struct *task)
{
unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
regsize = 32 * sizeof(vector128);
if (copy_to_user(data, task->thread.vr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VSCR */
regsize = 1 * sizeof(vector128);
if (copy_to_user(data, &task->thread.vscr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VRSAVE */
if (put_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
}
/*
* Write contents of AltiVec register state into task TASK.
*/
static inline int set_vrregs(struct task_struct *task,
unsigned long __user *data)
{
unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
regsize = 32 * sizeof(vector128);
if (copy_from_user(task->thread.vr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VSCR */
regsize = 1 * sizeof(vector128);
if (copy_from_user(&task->thread.vscr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VRSAVE */
if (get_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
}
#endif
static inline int ptrace_set_debugreg(struct task_struct *task,
unsigned long addr, unsigned long data)
{
/* We only support one DABR and no IABRS at the moment */
if (addr > 0)
return -EINVAL;
/* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;
/* Ensure translation is on */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
task->thread.dabr = data;
return 0;
}
#endif /* _PPC64_PTRACE_COMMON_H */

View File

@ -35,11 +35,11 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#ifdef CONFIG_PPC64
#include "ptrace-common.h"
#endif
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
#ifdef CONFIG_PPC32
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
@ -48,65 +48,117 @@
#else
#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE)
#endif
#endif /* CONFIG_PPC32 */
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
* Max register writeable via put_reg
*/
#ifdef CONFIG_PPC32
#define PT_MAX_PUT_REG PT_MQ
#else
#define PT_MAX_PUT_REG PT_CCR
#endif
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
unsigned long ptrace_get_reg(struct task_struct *task, int regno)
{
if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)
&& task->thread.regs != NULL)
unsigned long tmp = 0;
if (task->thread.regs == NULL)
return -EIO;
if (regno == PT_MSR) {
tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
return tmp | task->thread.fpexc_mode;
}
if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
return ((unsigned long *)task->thread.regs)[regno];
return (0);
return -EIO;
}
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
{
if (regno <= PT_MQ && task->thread.regs != NULL) {
if (task->thread.regs == NULL)
return -EIO;
if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
/* We prevent mucking around with the reserved area of trap
* which are used internally by the kernel
*/
if (regno == PT_TRAP)
data &= 0xfff0;
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
static int get_fpregs(void __user *data, struct task_struct *task,
int has_fpscr)
{
unsigned int count = has_fpscr ? 33 : 32;
if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
return -EFAULT;
return 0;
}
static int set_fpregs(void __user *data, struct task_struct *task,
int has_fpscr)
{
unsigned int count = has_fpscr ? 33 : 32;
if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
return -EFAULT;
return 0;
}
#ifdef CONFIG_ALTIVEC
/*
* Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
* The transfer totals 34 quadword. Quadwords 0-31 contain the
* corresponding vector registers. Quadword 32 contains the vscr as the
* last word (offset 12) within that quadword. Quadword 33 contains the
* vrsave as the first word (offset 0) within the quadword.
*
* This definition of the VMX state is compatible with the current PPC32
* ptrace interface. This allows signal handling and ptrace to use the
* same structures. This also simplifies the implementation of a bi-arch
* (combined (32- and 64-bit) gdb.
*/
/*
* Get contents of AltiVec register state in task TASK
*/
static inline int get_vrregs(unsigned long __user *data, struct task_struct *task)
static int get_vrregs(unsigned long __user *data, struct task_struct *task)
{
int i, j;
if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long)))
return -EFAULT;
unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
for (i = 0; i < 32; i++)
for (j = 0; j < 4; j++, data++)
if (__put_user(task->thread.vr[i].u[j], data))
regsize = 32 * sizeof(vector128);
if (copy_to_user(data, task->thread.vr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VSCR */
for (i = 0; i < 4; i++, data++)
if (__put_user(task->thread.vscr.u[i], data))
regsize = 1 * sizeof(vector128);
if (copy_to_user(data, &task->thread.vscr, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VRSAVE */
if (__put_user(task->thread.vrsave, data))
if (put_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
@ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas
/*
* Write contents of AltiVec register state into task TASK.
*/
static inline int set_vrregs(struct task_struct *task, unsigned long __user *data)
static int set_vrregs(struct task_struct *task, unsigned long __user *data)
{
int i, j;
if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long)))
return -EFAULT;
unsigned long regsize;
/* copy AltiVec registers VR[0] .. VR[31] */
for (i = 0; i < 32; i++)
for (j = 0; j < 4; j++, data++)
if (__get_user(task->thread.vr[i].u[j], data))
regsize = 32 * sizeof(vector128);
if (copy_from_user(task->thread.vr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VSCR */
for (i = 0; i < 4; i++, data++)
if (__get_user(task->thread.vscr.u[i], data))
regsize = 1 * sizeof(vector128);
if (copy_from_user(&task->thread.vscr, data, regsize))
return -EFAULT;
data += (regsize / sizeof(unsigned long));
/* copy VRSAVE */
if (__get_user(task->thread.vrsave, data))
if (get_user(task->thread.vrsave, (u32 __user *)data))
return -EFAULT;
return 0;
}
#endif
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SPE
@ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat
/*
* Get contents of SPE register state in task TASK.
*/
static inline int get_evrregs(unsigned long *data, struct task_struct *task)
static int get_evrregs(unsigned long *data, struct task_struct *task)
{
int i;
@ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task)
/*
* Write contents of SPE register state into task TASK.
*/
static inline int set_evrregs(struct task_struct *task, unsigned long *data)
static int set_evrregs(struct task_struct *task, unsigned long *data)
{
int i;
@ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data)
}
#endif /* CONFIG_SPE */
static inline void
set_single_step(struct task_struct *task)
static void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@ -221,8 +271,7 @@ set_single_step(struct task_struct *task)
set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
static inline void
clear_single_step(struct task_struct *task)
static void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
@ -236,7 +285,25 @@ clear_single_step(struct task_struct *task)
}
clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
#endif /* CONFIG_PPC32 */
static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
unsigned long data)
{
/* We only support one DABR and no IABRS at the moment */
if (addr > 0)
return -EINVAL;
/* The bottom 3 bits are flags */
if ((data & ~0x7UL) >= TASK_SIZE)
return -EIO;
/* Ensure translation is on */
if (data && !(data & DABR_TRANSLATION))
return -EIO;
task->thread.dabr = data;
return 0;
}
/*
* Called by kernel/ptrace.c when detaching..
@ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child)
clear_single_step(child);
}
/*
* Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
* we mark them as obsolete now, they will be removed in a future version
*/
static long arch_ptrace_old(struct task_struct *child, long request, long addr,
long data)
{
int ret = -EPERM;
switch(request) {
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
flush_fp_to_thread(child);
ret = get_fpregs((void __user *)addr, child, 0);
break;
}
case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
flush_fp_to_thread(child);
ret = set_fpregs((void __user *)addr, child, 0);
break;
}
}
return ret;
}
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret = -EPERM;
@ -284,11 +407,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
break;
#ifdef CONFIG_PPC32
CHECK_FULL_REGS(child->thread.regs);
#endif
if (index < PT_FPR0) {
tmp = get_reg(child, (int) index);
tmp = ptrace_get_reg(child, (int) index);
} else {
flush_fp_to_thread(child);
tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
@ -323,13 +444,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
break;
#ifdef CONFIG_PPC32
CHECK_FULL_REGS(child->thread.regs);
#endif
if (index == PT_ORIG_R3)
break;
if (index < PT_FPR0) {
ret = put_reg(child, index, data);
ret = ptrace_put_reg(child, index, data);
} else {
flush_fp_to_thread(child);
((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
@ -384,7 +501,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
#ifdef CONFIG_PPC64
case PTRACE_GET_DEBUGREG: {
ret = -EINVAL;
/* We only support one DABR and no IABRS at the moment */
@ -398,73 +514,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_SET_DEBUGREG:
ret = ptrace_set_debugreg(child, addr, data);
break;
#endif
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
#ifdef CONFIG_PPC64
case PTRACE_GETREGS64:
#endif
case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
int ui;
if (!access_ok(VERIFY_WRITE, (void __user *)data,
sizeof(struct pt_regs))) {
ret = -EIO;
break;
}
ret = 0;
for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
ret |= __put_user(ptrace_get_reg(child, ui),
(unsigned long __user *) data);
data += sizeof(long);
}
break;
}
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
#ifdef CONFIG_PPC64
case PTRACE_SETREGS64:
#endif
case PTRACE_SETREGS: { /* Set all gp regs in the child. */
unsigned long tmp;
int ui;
if (!access_ok(VERIFY_READ, (void __user *)data,
sizeof(struct pt_regs))) {
ret = -EIO;
break;
}
ret = 0;
for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
ret = __get_user(tmp, (unsigned long __user *) data);
if (ret)
break;
reg++;
tmp++;
ptrace_put_reg(child, ui, tmp);
data += sizeof(long);
}
break;
}
case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
flush_fp_to_thread(child);
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
ret = get_fpregs((void __user *)data, child, 1);
break;
}
case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned long __user *tmp = (unsigned long __user *)addr;
case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
flush_fp_to_thread(child);
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
ret = set_fpregs((void __user *)data, child, 1);
break;
}
@ -499,11 +603,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
#endif
/* Old reverse args ptrace callss */
case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
ret = arch_ptrace_old(child, request, addr, data);
break;
default:
ret = ptrace_request(child, request, addr, data);
break;
}
return ret;
}

View File

@ -33,13 +33,55 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#include "ptrace-common.h"
/*
* does not yet catch signals sent when the child dies.
* in exit.c or in signal.c.
*/
/*
* Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
* we mark them as obsolete now, they will be removed in a future version
*/
static long compat_ptrace_old(struct task_struct *child, long request,
long addr, long data)
{
int ret = -EPERM;
switch(request) {
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
}
return ret;
}
long compat_sys_ptrace(int request, int pid, unsigned long addr,
unsigned long data)
{
@ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
if (index < PT_FPR0) {
tmp = get_reg(child, index);
tmp = ptrace_get_reg(child, index);
} else {
flush_fp_to_thread(child);
/*
@ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
else
part = 0; /* want the 1st half of the register (left-most). */
/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
/* Validate the input - check to see if address is on the wrong boundary
* or beyond the end of the user area
*/
if ((addr & 3) || numReg > PT_FPSCR)
break;
@ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
flush_fp_to_thread(child);
tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
} else { /* register within PT_REGS struct */
tmp = get_reg(child, numReg);
tmp = ptrace_get_reg(child, numReg);
}
reg32bits = ((u32*)&tmp)[part];
ret = put_user(reg32bits, (u32 __user *)data);
@ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
if ((addr & 3) || (index > PT_FPSCR32))
break;
if (index == PT_ORIG_R3)
break;
if (index < PT_FPR0) {
ret = put_reg(child, index, data);
ret = ptrace_put_reg(child, index, data);
} else {
flush_fp_to_thread(child);
/*
@ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
/* Determine which register the user wants */
index = (u64)addr >> 2;
numReg = index / 2;
/*
* Validate the input - check to see if address is on the
* wrong boundary or beyond the end of the user area
*/
if ((addr & 3) || (numReg > PT_FPSCR))
break;
/* Insure it is a register we let them change */
if ((numReg == PT_ORIG_R3)
|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
break;
if (numReg >= PT_FPR0) {
flush_fp_to_thread(child);
}
if (numReg == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
((u32*)child->thread.regs)[index] = data;
ret = 0;
break;
}
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
if (numReg < PT_FPR0) {
unsigned long freg = ptrace_get_reg(child, numReg);
if (index % 2)
freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
/* make sure the single step bit is not set. */
clear_single_step(child);
wake_up_process(child);
freg = (freg & 0xfffffffful) | (data << 32);
ret = ptrace_put_reg(child, numReg, freg);
} else {
flush_fp_to_thread(child);
((unsigned int *)child->thread.regs)[index] = data;
ret = 0;
break;
}
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
clear_single_step(child);
wake_up_process(child);
break;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
ret = -EIO;
if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
set_single_step(child);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
ret = 0;
break;
}
@ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
}
case PTRACE_SET_DEBUGREG:
ret = ptrace_set_debugreg(child, addr, data);
break;
case PTRACE_DETACH:
ret = ptrace_detach(child, data);
break;
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
flush_fp_to_thread(child);
for (i = 0; i < 32; i++) {
ret = put_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
unsigned int __user *tmp = (unsigned int __user *)addr;
flush_fp_to_thread(child);
for (i = 0; i < 32; i++) {
ret = get_user(*reg, tmp);
if (ret)
break;
reg++;
tmp++;
}
break;
}
case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
break;
#ifdef CONFIG_ALTIVEC
case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
int ui;
if (!access_ok(VERIFY_WRITE, (void __user *)data,
PT_REGS_COUNT * sizeof(int))) {
ret = -EIO;
break;
}
ret = 0;
for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
ret |= __put_user(ptrace_get_reg(child, ui),
(unsigned int __user *) data);
data += sizeof(int);
}
break;
}
case PTRACE_SETREGS: { /* Set all gp regs in the child. */
unsigned long tmp;
int ui;
if (!access_ok(VERIFY_READ, (void __user *)data,
PT_REGS_COUNT * sizeof(int))) {
ret = -EIO;
break;
}
ret = 0;
for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
ret = __get_user(tmp, (unsigned int __user *) data);
if (ret)
break;
ptrace_put_reg(child, ui, tmp);
data += sizeof(int);
}
break;
}
case PTRACE_GETFPREGS:
case PTRACE_SETFPREGS:
case PTRACE_GETVRREGS:
/* Get the child altivec register state. */
flush_altivec_to_thread(child);
ret = get_vrregs((unsigned long __user *)data, child);
case PTRACE_SETVRREGS:
case PTRACE_GETREGS64:
case PTRACE_SETREGS64:
case PPC_PTRACE_GETFPREGS:
case PPC_PTRACE_SETFPREGS:
case PTRACE_KILL:
case PTRACE_SINGLESTEP:
case PTRACE_DETACH:
case PTRACE_SET_DEBUGREG:
case PTRACE_SYSCALL:
case PTRACE_CONT:
ret = arch_ptrace(child, request, addr, data);
break;
case PTRACE_SETVRREGS:
/* Set the child altivec register state. */
flush_altivec_to_thread(child);
ret = set_vrregs(child, (unsigned long __user *)data);
/* Old reverse args ptrace callss */
case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
ret = compat_ptrace_old(child, request, addr, data);
break;
#endif
default:
ret = ptrace_request(child, request, addr, data);

View File

@ -278,10 +278,8 @@ void __init find_and_init_phbs(void)
{
struct device_node *node;
struct pci_controller *phb;
unsigned int index;
struct device_node *root = of_find_node_by_path("/");
index = 0;
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
@ -295,8 +293,7 @@ void __init find_and_init_phbs(void)
continue;
rtas_setup_phb(phb);
pci_process_bridge_OF_ranges(phb, node, 0);
pci_setup_phb_io(phb, index == 0);
index++;
isa_bridge_find_early(phb);
}
of_node_put(root);
@ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
return 1;
}
rc = unmap_bus_range(b);
rc = pcibios_unmap_io_space(b);
if (rc) {
printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
__FUNCTION__, b->name);

View File

@ -32,6 +32,7 @@
#include <linux/unistd.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/debugfs.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/processor.h>
@ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port)
switch(base_port) {
case I8042_DATA_REG:
if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303")))
np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03");
if (np) {
parent = of_get_parent(np);
of_node_put(np);
np = parent;
break;
}
np = of_find_node_by_type(NULL, "8042");
break;
case FDC_BASE: /* FDC1 */
@ -571,3 +580,15 @@ static int __init check_cache_coherency(void)
late_initcall(check_cache_coherency);
#endif /* CONFIG_CHECK_CACHE_COHERENCY */
#ifdef CONFIG_DEBUG_FS
struct dentry *powerpc_debugfs_root;
static int powerpc_debugfs_init(void)
{
powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL);
return powerpc_debugfs_root == NULL;
}
arch_initcall(powerpc_debugfs_init);
#endif

View File

@ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
dcache_bsize = cur_cpu_spec->dcache_bsize;
icache_bsize = cur_cpu_spec->icache_bsize;
ucache_bsize = 0;
} else
ucache_bsize = dcache_bsize = icache_bsize
= cur_cpu_spec->dcache_bsize;
if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
ucache_bsize = icache_bsize = dcache_bsize;
/* reboot on panic */
panic_timeout = 180;

View File

@ -350,13 +350,11 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");
/* Apply the CPUs-specific and firmware specific fixups to kernel
* text (nop out sections not relevant to this CPU or this firmware)
/* Apply CPUs-specific fixups to kernel text (nop out sections
* not relevant to this CPU)
*/
do_feature_fixups(cur_cpu_spec->cpu_features,
&__start___ftr_fixup, &__stop___ftr_fixup);
do_feature_fixups(powerpc_firmware_features,
&__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
/*
* Unflatten the device-tree passed by prom_init or kexec
@ -394,6 +392,12 @@ void __init setup_system(void)
if (ppc_md.init_early)
ppc_md.init_early();
/* Apply firmware specific fixups to kernel text (nop out
* sections not relevant to this firmware)
*/
do_feature_fixups(powerpc_firmware_features,
&__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
/*
* We can discover serial ports now since the above did setup the
* hash table management for us, thus ioremap works. We do that early

View File

@ -0,0 +1,180 @@
/*
* Common signal handling code for both 32 and 64 bits
*
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
* Extracted from signal_32.c and signal_64.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/
#include <linux/ptrace.h>
#include <linux/signal.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include "signal.h"
/*
* Allocate space for the signal frame
*/
void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
{
unsigned long oldsp, newsp;
/* Default to using normal stack */
oldsp = regs->gpr[1];
/* Check for alt stack */
if ((ka->sa.sa_flags & SA_ONSTACK) &&
current->sas_ss_size && !on_sig_stack(oldsp))
oldsp = (current->sas_ss_sp + current->sas_ss_size);
/* Get aligned frame */
newsp = (oldsp - frame_size) & ~0xFUL;
/* Check access */
if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
return NULL;
return (void __user *)newsp;
}
/*
* Restore the user process's signal mask
*/
void restore_sigmask(sigset_t *set)
{
sigdelsetmask(set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = *set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
int has_handler)
{
unsigned long ret = regs->gpr[3];
int restart = 1;
/* syscall ? */
if (TRAP(regs) != 0x0C00)
return;
/* error signalled ? */
if (!(regs->ccr & 0x10000000))
return;
switch (ret) {
case ERESTART_RESTARTBLOCK:
case ERESTARTNOHAND:
/* ERESTARTNOHAND means that the syscall should only be
* restarted if there was no handler for the signal, and since
* we only get here if there is a handler, we dont restart.
*/
restart = !has_handler;
break;
case ERESTARTSYS:
/* ERESTARTSYS means to restart the syscall if there is no
* handler or the handler was registered with SA_RESTART
*/
restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
break;
case ERESTARTNOINTR:
/* ERESTARTNOINTR means that the syscall should be
* called again after the signal handler returns.
*/
break;
default:
return;
}
if (restart) {
if (ret == ERESTART_RESTARTBLOCK)
regs->gpr[0] = __NR_restart_syscall;
else
regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4;
regs->result = 0;
} else {
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
}
}
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
int ret;
int is32 = is_32bit_task();
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* Is there any syscall restart business here ? */
check_syscall_restart(regs, &ka, signr > 0);
if (signr <= 0) {
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0; /* no signals delivered */
}
/*
* Reenable the DABR before delivering the signal to
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
if (current->thread.dabr)
set_dabr(current->thread.dabr);
if (is32) {
if (ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal32(signr, &ka, &info, oldset,
regs);
else
ret = handle_signal32(signr, &ka, &info, oldset,
regs);
} else {
ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
}
if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka.sa.sa_mask);
if (!(ka.sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
/*
* A signal was successfully delivered; the saved sigmask is in
* its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return ret;
}
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r5, unsigned long r6, unsigned long r7,
unsigned long r8, struct pt_regs *regs)
{
return do_sigaltstack(uss, uoss, regs->gpr[1]);
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
* Extracted from signal_32.c and signal_64.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/
#ifndef _POWERPC_ARCH_SIGNAL_H
#define _POWERPC_ARCH_SIGNAL_H
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size);
extern void restore_sigmask(sigset_t *set);
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs);
extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs);
#ifdef CONFIG_PPC64
static inline int is_32bit_task(void)
{
return test_thread_flag(TIF_32BIT);
}
extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs);
#else /* CONFIG_PPC64 */
static inline int is_32bit_task(void)
{
return 1;
}
static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs)
{
return -EFAULT;
}
#endif /* !defined(CONFIG_PPC64) */
#endif /* _POWERPC_ARCH_SIGNAL_H */

View File

@ -51,12 +51,11 @@
#include <asm/pgtable.h>
#endif
#include "signal.h"
#undef DEBUG_SIG
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#ifdef CONFIG_PPC64
#define do_signal do_signal32
#define sys_sigsuspend compat_sys_sigsuspend
#define sys_rt_sigsuspend compat_sys_rt_sigsuspend
#define sys_rt_sigreturn compat_sys_rt_sigreturn
@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
#endif /* CONFIG_PPC64 */
int do_signal(sigset_t *oldset, struct pt_regs *regs);
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
@ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask)
return -ERESTARTNOHAND;
}
#ifdef CONFIG_PPC32
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5,
int r6, int r7, int r8, struct pt_regs *regs)
{
return do_sigaltstack(uss, uoss, regs->gpr[1]);
}
#endif
long sys_sigaction(int sig, struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
@ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* an ABI gap of 56 words
* an mcontext struct
* a sigcontext struct
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
* Each of these things must be a multiple of 16 bytes in size. The following
* structure represent all of this except the __SIGNAL_FRAMESIZE gap
*
*/
struct sigregs {
struct sigframe {
struct sigcontext sctx; /* the sigcontext */
struct mcontext mctx; /* all the register values */
/*
* Programs using the rs6000/xcoff abi can save up to 19 gp
@ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
}
#endif /* CONFIG_PPC64 */
/*
* Restore the user process's signal mask
*/
#ifdef CONFIG_PPC64
extern void restore_sigmask(sigset_t *set);
#else /* CONFIG_PPC64 */
static void restore_sigmask(sigset_t *set)
{
sigdelsetmask(set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = *set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
#endif
/*
* Set up a signal frame for a "real-time" signal handler
* (one which gets siginfo).
*/
static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, unsigned long newsp)
struct pt_regs *regs)
{
struct rt_sigframe __user *rt_sf;
struct mcontext __user *frame;
unsigned long origsp = newsp;
unsigned long newsp = 0;
/* Set up Signal Frame */
/* Put a Real Time Context onto stack */
newsp -= sizeof(*rt_sf);
rt_sf = (struct rt_sigframe __user *)newsp;
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE + 16;
if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
if (unlikely(rt_sf == NULL))
goto badframe;
/* Put the siginfo & fill in most of the ucontext */
@ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
current->thread.fpscr.val = 0; /* turn off all fp exceptions */
/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;
/* Fill registers for signal handler */
regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) &rt_sf->info;
@ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
/*
* OK, we're invoking a handler
*/
static int handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
unsigned long newsp)
int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
struct sigcontext __user *sc;
struct sigregs __user *frame;
unsigned long origsp = newsp;
struct sigframe __user *frame;
unsigned long newsp = 0;
/* Set up Signal Frame */
newsp -= sizeof(struct sigregs);
frame = (struct sigregs __user *) newsp;
/* Put a sigcontext on the stack */
newsp -= sizeof(*sc);
sc = (struct sigcontext __user *) newsp;
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE;
if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
frame = get_sigframe(ka, regs, sizeof(*frame));
if (unlikely(frame == NULL))
goto badframe;
sc = (struct sigcontext __user *) &frame->sctx;
#if _NSIG != 64
#error "Please adjust handle_signal()"
@ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
#else
|| __put_user(oldset->sig[1], &sc->_unused[3])
#endif
|| __put_user(to_user_ptr(frame), &sc->regs)
|| __put_user(to_user_ptr(&frame->mctx), &sc->regs)
|| __put_user(sig, &sc->signal))
goto badframe;
@ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
current->thread.fpscr.val = 0; /* turn off all fp exceptions */
/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;
regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
@ -1126,106 +1094,3 @@ badframe:
force_sig(SIGSEGV, current);
return 0;
}
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
struct k_sigaction ka;
unsigned int newsp;
int signr, ret;
#ifdef CONFIG_PPC32
if (try_to_freeze()) {
signr = 0;
if (!signal_pending(current))
goto no_signal;
}
#endif
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
#ifdef CONFIG_PPC32
no_signal:
#endif
if (TRAP(regs) == 0x0C00 /* System Call! */
&& regs->ccr & 0x10000000 /* error signalled */
&& ((ret = regs->gpr[3]) == ERESTARTSYS
|| ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
|| ret == ERESTART_RESTARTBLOCK)) {
if (signr > 0
&& (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
|| (ret == ERESTARTSYS
&& !(ka.sa.sa_flags & SA_RESTART)))) {
/* make the system call return an EINTR error */
regs->result = -EINTR;
regs->gpr[3] = EINTR;
/* note that the cr0.SO bit is already set */
} else {
regs->nip -= 4; /* Back up & retry system call */
regs->result = 0;
regs->trap = 0;
if (ret == ERESTART_RESTARTBLOCK)
regs->gpr[0] = __NR_restart_syscall;
else
regs->gpr[3] = regs->orig_gpr3;
}
}
if (signr == 0) {
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0; /* no signals delivered */
}
if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
&& !on_sig_stack(regs->gpr[1]))
newsp = current->sas_ss_sp + current->sas_ss_size;
else
newsp = regs->gpr[1];
newsp &= ~0xfUL;
#ifdef CONFIG_PPC64
/*
* Reenable the DABR before delivering the signal to
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
if (current->thread.dabr)
set_dabr(current->thread.dabr);
#endif
/* Whee! Actually deliver the signal. */
if (ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
else
ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka.sa.sa_mask);
if (!(ka.sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
/* A signal was successfully delivered; the saved sigmask is in
its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return ret;
}

View File

@ -34,9 +34,9 @@
#include <asm/syscalls.h>
#include <asm/vdso.h>
#define DEBUG_SIG 0
#include "signal.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define DEBUG_SIG 0
#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
#define FP_REGS_SIZE sizeof(elf_fpregset_t)
@ -64,14 +64,6 @@ struct rt_sigframe {
char abigap[288];
} __attribute__ ((aligned (16)));
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
{
return do_sigaltstack(uss, uoss, regs->gpr[1]);
}
/*
* Set up the sigcontext for the signal frame.
*/
@ -207,25 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
return err;
}
/*
* Allocate space for the signal frame
*/
static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
{
unsigned long newsp;
/* Default to using normal stack */
newsp = regs->gpr[1];
if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
if (! on_sig_stack(regs->gpr[1]))
newsp = (current->sas_ss_sp + current->sas_ss_size);
}
return (void __user *)((newsp - frame_size) & -16ul);
}
/*
* Setup the trampoline code on the stack
*/
@ -252,19 +225,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
return err;
}
/*
* Restore the user process's signal mask (also used by signal32.c)
*/
void restore_sigmask(sigset_t *set)
{
sigdelsetmask(set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = *set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
/*
* Handle {get,set,swap}_context operations
*/
@ -359,7 +319,7 @@ badframe:
return 0;
}
static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
/* Handler is *really* a pointer to the function descriptor for
@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
long err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
if (unlikely(frame == NULL))
goto badframe;
err |= __put_user(&frame->info, &frame->pinfo);
@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
/* Allocate a dummy caller frame for the signal handler. */
newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
/* Set up "regs" so we "return" to the signal handler. */
@ -442,134 +401,3 @@ badframe:
force_sigsegv(signr, current);
return 0;
}
/*
* OK, we're invoking a handler
*/
static int handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
int ret;
/* Set up Signal Frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs);
if (ret) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret;
}
static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
{
switch ((int)regs->result) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
/* ERESTARTNOHAND means that the syscall should only be
* restarted if there was no handler for the signal, and since
* we only get here if there is a handler, we dont restart.
*/
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
break;
case -ERESTARTSYS:
/* ERESTARTSYS means to restart the syscall if there is no
* handler or the handler was registered with SA_RESTART
*/
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->result = -EINTR;
regs->gpr[3] = EINTR;
regs->ccr |= 0x10000000;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
/* ERESTARTNOINTR means that the syscall should be
* called again after the signal handler returns.
*/
regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4;
regs->result = 0;
break;
}
}
/*
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
/*
* If the current thread is 32 bit - invoke the
* 32 bit signal handling code
*/
if (test_thread_flag(TIF_32BIT))
return do_signal32(oldset, regs);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
int ret;
/* Whee! Actually deliver the signal. */
if (TRAP(regs) == 0x0C00)
syscall_restart(regs, &ka);
/*
* Reenable the DABR before delivering the signal to
* user space. The DABR will have been cleared if it
* triggered inside the kernel.
*/
if (current->thread.dabr)
set_dabr(current->thread.dabr);
ret = handle_signal(signr, &ka, &info, oldset, regs);
/* If a signal was successfully delivered, the saved sigmask is in
its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return ret;
}
if (TRAP(regs) == 0x0C00) { /* System Call! */
if ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR) {
regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4; /* Back up & retry system call */
regs->result = 0;
} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
regs->gpr[0] = __NR_restart_syscall;
regs->nip -= 4;
regs->result = 0;
}
}
/* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
}
EXPORT_SYMBOL(do_signal);

View File

@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid)
return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
kobject_name(&dev->kobj));
}
EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
{
struct node *node = &node_devices[nid];
sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
}
EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
#else
static void register_nodes(void)
@ -457,9 +459,6 @@ static void register_nodes(void)
#endif
EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
/* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf)
{

View File

@ -77,9 +77,8 @@
/* keep track of when we need to update the rtc */
time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES
unsigned long iSeries_recal_titan = 0;
unsigned long iSeries_recal_tb = 0;
static unsigned long first_settimeofday = 1;
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
#endif
/* The decrementer counts down by 128 every 128ns on a 601. */
@ -113,8 +112,9 @@ u64 ticklen_to_xs; /* 0.64 fraction */
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL_GPL(rtc_lock);
u64 tb_to_ns_scale;
unsigned tb_to_ns_shift;
static u64 tb_to_ns_scale __read_mostly;
static unsigned tb_to_ns_shift __read_mostly;
static unsigned long boot_tb __read_mostly;
struct gettimeofday_struct do_gtod;
@ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs)
run_posix_cpu_timers(current);
}
#ifdef CONFIG_PPC_SPLPAR
/*
* Stuff for accounting stolen time.
*/
@ -222,19 +221,28 @@ struct cpu_purr_data {
int initialized; /* thread is running */
u64 tb; /* last TB value read */
u64 purr; /* last PURR value read */
spinlock_t lock;
};
/*
* Each entry in the cpu_purr_data array is manipulated only by its
* "owner" cpu -- usually in the timer interrupt but also occasionally
* in process context for cpu online. As long as cpus do not touch
* each others' cpu_purr_data, disabling local interrupts is
* sufficient to serialize accesses.
*/
static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data);
static void snapshot_tb_and_purr(void *data)
{
unsigned long flags;
struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
local_irq_save(flags);
p->tb = mftb();
p->purr = mfspr(SPRN_PURR);
wmb();
p->initialized = 1;
local_irq_restore(flags);
}
/*
@ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data)
*/
void snapshot_timebases(void)
{
int cpu;
if (!cpu_has_feature(CPU_FTR_PURR))
return;
for_each_possible_cpu(cpu)
spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock);
on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
}
/*
* Must be called with interrupts disabled.
*/
void calculate_steal_time(void)
{
u64 tb, purr;
@ -262,7 +269,6 @@ void calculate_steal_time(void)
pme = &per_cpu(cpu_purr_data, smp_processor_id());
if (!pme->initialized)
return; /* this can happen in early boot */
spin_lock(&pme->lock);
tb = mftb();
purr = mfspr(SPRN_PURR);
stolen = (tb - pme->tb) - (purr - pme->purr);
@ -270,9 +276,9 @@ void calculate_steal_time(void)
account_steal_time(current, stolen);
pme->tb = tb;
pme->purr = purr;
spin_unlock(&pme->lock);
}
#ifdef CONFIG_PPC_SPLPAR
/*
* Must be called before the cpu is added to the online map when
* a cpu is being brought up at runtime.
@ -284,12 +290,12 @@ static void snapshot_purr(void)
if (!cpu_has_feature(CPU_FTR_PURR))
return;
local_irq_save(flags);
pme = &per_cpu(cpu_purr_data, smp_processor_id());
spin_lock_irqsave(&pme->lock, flags);
pme->tb = mftb();
pme->purr = mfspr(SPRN_PURR);
pme->initialized = 1;
spin_unlock_irqrestore(&pme->lock, flags);
local_irq_restore(flags);
}
#endif /* CONFIG_PPC_SPLPAR */
@ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc);
* returned by the service processor for the timebase frequency.
*/
static void iSeries_tb_recal(void)
static int __init iSeries_tb_recal(void)
{
struct div_result divres;
unsigned long titan, tb;
/* Make sure we only run on iSeries */
if (!firmware_has_feature(FW_FEATURE_ISERIES))
return -ENODEV;
tb = get_tb();
titan = HvCallXm_loadTod();
if ( iSeries_recal_titan ) {
@ -594,8 +605,18 @@ static void iSeries_tb_recal(void)
}
iSeries_recal_titan = titan;
iSeries_recal_tb = tb;
return 0;
}
#endif
late_initcall(iSeries_tb_recal);
/* Called from platform early init */
void __init iSeries_time_init_early(void)
{
iSeries_recal_tb = get_tb();
iSeries_recal_titan = HvCallXm_loadTod();
}
#endif /* CONFIG_PPC_ISERIES */
/*
* For iSeries shared processors, we have to let the hypervisor
@ -735,7 +756,7 @@ unsigned long long sched_clock(void)
{
if (__USE_RTC())
return get_rtc();
return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
}
int do_settimeofday(struct timespec *tv)
@ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv)
* to the RTC again, or write to the RTC but then they don't call
* settimeofday to perform this operation.
*/
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
iSeries_tb_recal();
first_settimeofday = 0;
}
#endif
/* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count;
@ -960,6 +975,8 @@ void __init time_init(void)
}
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
boot_tb = get_tb();
tm = get_boot_time();

View File

@ -670,7 +670,7 @@ static int __init vdso_init(void)
/*
* Fill up the "systemcfg" stuff for backward compatiblity
*/
strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64");
vdso_data->version.major = SYSTEMCFG_MAJOR;
vdso_data->version.minor = SYSTEMCFG_MINOR;
vdso_data->processor = mfspr(SPRN_PVR);

View File

@ -7,6 +7,7 @@
#define PROVIDE32(x) PROVIDE(x)
#endif
#include <asm-generic/vmlinux.lds.h>
#include <asm/cache.h>
ENTRY(_stext)
@ -211,6 +212,11 @@ SECTIONS
*(.data.cacheline_aligned)
}
. = ALIGN(L1_CACHE_BYTES);
.data.read_mostly : {
*(.data.read_mostly)
}
. = ALIGN(PAGE_SIZE);
__data_nosave : {
__nosave_begin = .;

View File

@ -12,7 +12,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds

View File

@ -9,7 +9,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds

View File

@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \
hash_utils_64.o hash_low_64.o tlb_64.o \
slb_low.o slb.o stab.o mmap.o imalloc.o \
$(hash-y)
slb_low.o slb.o stab.o mmap.o $(hash-y)
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o
obj-$(CONFIG_40x) += 4xx_mmu.o
obj-$(CONFIG_44x) += 44x_mmu.o

View File

@ -380,7 +380,7 @@ out_of_memory:
}
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
do_exit(SIGKILL);
do_group_exit(SIGKILL);
return SIGKILL;
do_sigbus:

View File

@ -14,7 +14,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds

View File

@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local)
spin_unlock(&native_tlbie_lock);
}
static inline void native_lock_hpte(hpte_t *hptep)
static inline void native_lock_hpte(struct hash_pte *hptep)
{
unsigned long *word = &hptep->v;
@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep)
}
}
static inline void native_unlock_hpte(hpte_t *hptep)
static inline void native_unlock_hpte(struct hash_pte *hptep)
{
unsigned long *word = &hptep->v;
@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long pa, unsigned long rflags,
unsigned long vflags, int psize)
{
hpte_t *hptep = htab_address + hpte_group;
struct hash_pte *hptep = htab_address + hpte_group;
unsigned long hpte_v, hpte_r;
int i;
@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
hptep->r = hpte_r;
/* Guarantee the second dword is visible before the valid bit */
__asm__ __volatile__ ("eieio" : : : "memory");
eieio();
/*
* Now set the first dword including the valid bit
* NOTE: this also unlocks the hpte
@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
static long native_hpte_remove(unsigned long hpte_group)
{
hpte_t *hptep;
struct hash_pte *hptep;
int i;
int slot_offset;
unsigned long hpte_v;
@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group)
static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long va, int psize, int local)
{
hpte_t *hptep = htab_address + slot;
struct hash_pte *hptep = htab_address + slot;
unsigned long hpte_v, want_v;
int ret = 0;
@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
/* Even if we miss, we need to invalidate the TLB */
if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) {
DBG_LOW(" -> miss\n");
native_unlock_hpte(hptep);
ret = -1;
} else {
DBG_LOW(" -> hit\n");
/* Update the HPTE */
hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
native_unlock_hpte(hptep);
}
native_unlock_hpte(hptep);
/* Ensure it is out of the tlb too. */
tlbie(va, psize, local);
@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
static long native_hpte_find(unsigned long va, int psize)
{
hpte_t *hptep;
struct hash_pte *hptep;
unsigned long hash;
unsigned long i, j;
long slot;
@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
{
unsigned long vsid, va;
long slot;
hpte_t *hptep;
struct hash_pte *hptep;
vsid = get_kernel_vsid(ea);
va = (vsid << 28) | (ea & 0x0fffffff);
@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
static void native_hpte_invalidate(unsigned long slot, unsigned long va,
int psize, int local)
{
hpte_t *hptep = htab_address + slot;
struct hash_pte *hptep = htab_address + slot;
unsigned long hpte_v;
unsigned long want_v;
unsigned long flags;
@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
#define LP_BITS 8
#define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT)
static void hpte_decode(hpte_t *hpte, unsigned long slot,
static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
int *psize, unsigned long *va)
{
unsigned long hpte_r = hpte->r;
@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot,
static void native_hpte_clear(void)
{
unsigned long slot, slots, flags;
hpte_t *hptep = htab_address;
struct hash_pte *hptep = htab_address;
unsigned long hpte_v, va;
unsigned long pteg_count;
int psize;
@ -462,7 +461,7 @@ static void native_hpte_clear(void)
static void native_flush_hash_range(unsigned long number, int local)
{
unsigned long va, hash, index, hidx, shift, slot;
hpte_t *hptep;
struct hash_pte *hptep;
unsigned long hpte_v;
unsigned long want_v;
unsigned long flags;

View File

@ -87,7 +87,7 @@ extern unsigned long dart_tablebase;
static unsigned long _SDR1;
struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
hpte_t *htab_address;
struct hash_pte *htab_address;
unsigned long htab_size_bytes;
unsigned long htab_hash_mask;
int mmu_linear_psize = MMU_PAGE_4K;

View File

@ -1,313 +0,0 @@
/*
* 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.
*/
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <linux/mutex.h>
#include <asm/cacheflush.h>
#include "mmu_decl.h"
static DEFINE_MUTEX(imlist_mutex);
struct vm_struct * imlist = NULL;
static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
{
unsigned long addr;
struct vm_struct **p, *tmp;
addr = ioremap_bot;
for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
if (size + addr < (unsigned long) tmp->addr)
break;
if ((unsigned long)tmp->addr >= ioremap_bot)
addr = tmp->size + (unsigned long) tmp->addr;
if (addr >= IMALLOC_END-size)
return 1;
}
*im_addr = addr;
return 0;
}
/* Return whether the region described by v_addr and size is a subset
* of the region described by parent
*/
static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
struct vm_struct *parent)
{
return (int) (v_addr >= (unsigned long) parent->addr &&
v_addr < (unsigned long) parent->addr + parent->size &&
size < parent->size);
}
/* Return whether the region described by v_addr and size is a superset
* of the region described by child
*/
static int im_region_is_superset(unsigned long v_addr, unsigned long size,
struct vm_struct *child)
{
struct vm_struct parent;
parent.addr = (void *) v_addr;
parent.size = size;
return im_region_is_subset((unsigned long) child->addr, child->size,
&parent);
}
/* Return whether the region described by v_addr and size overlaps
* the region described by vm. Overlapping regions meet the
* following conditions:
* 1) The regions share some part of the address space
* 2) The regions aren't identical
* 3) Neither region is a subset of the other
*/
static int im_region_overlaps(unsigned long v_addr, unsigned long size,
struct vm_struct *vm)
{
if (im_region_is_superset(v_addr, size, vm))
return 0;
return (v_addr + size > (unsigned long) vm->addr + vm->size &&
v_addr < (unsigned long) vm->addr + vm->size) ||
(v_addr < (unsigned long) vm->addr &&
v_addr + size > (unsigned long) vm->addr);
}
/* Determine imalloc status of region described by v_addr and size.
* Can return one of the following:
* IM_REGION_UNUSED - Entire region is unallocated in imalloc space.
* IM_REGION_SUBSET - Region is a subset of a region that is already
* allocated in imalloc space.
* vm will be assigned to a ptr to the parent region.
* IM_REGION_EXISTS - Exact region already allocated in imalloc space.
* vm will be assigned to a ptr to the existing imlist
* member.
* IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space.
* IM_REGION_SUPERSET - Region is a superset of a region that is already
* allocated in imalloc space.
*/
static int im_region_status(unsigned long v_addr, unsigned long size,
struct vm_struct **vm)
{
struct vm_struct *tmp;
for (tmp = imlist; tmp; tmp = tmp->next)
if (v_addr < (unsigned long) tmp->addr + tmp->size)
break;
*vm = NULL;
if (tmp) {
if (im_region_overlaps(v_addr, size, tmp))
return IM_REGION_OVERLAP;
*vm = tmp;
if (im_region_is_subset(v_addr, size, tmp)) {
/* Return with tmp pointing to superset */
return IM_REGION_SUBSET;
}
if (im_region_is_superset(v_addr, size, tmp)) {
/* Return with tmp pointing to first subset */
return IM_REGION_SUPERSET;
}
else if (v_addr == (unsigned long) tmp->addr &&
size == tmp->size) {
/* Return with tmp pointing to exact region */
return IM_REGION_EXISTS;
}
}
return IM_REGION_UNUSED;
}
static struct vm_struct * split_im_region(unsigned long v_addr,
unsigned long size, struct vm_struct *parent)
{
struct vm_struct *vm1 = NULL;
struct vm_struct *vm2 = NULL;
struct vm_struct *new_vm = NULL;
vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL);
if (vm1 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
return NULL;
}
if (v_addr == (unsigned long) parent->addr) {
/* Use existing parent vm_struct to represent child, allocate
* new one for the remainder of parent range
*/
vm1->size = parent->size - size;
vm1->addr = (void *) (v_addr + size);
vm1->next = parent->next;
parent->size = size;
parent->next = vm1;
new_vm = parent;
} else if (v_addr + size == (unsigned long) parent->addr +
parent->size) {
/* Allocate new vm_struct to represent child, use existing
* parent one for remainder of parent range
*/
vm1->size = size;
vm1->addr = (void *) v_addr;
vm1->next = parent->next;
new_vm = vm1;
parent->size -= size;
parent->next = vm1;
} else {
/* Allocate two new vm_structs for the new child and
* uppermost remainder, and use existing parent one for the
* lower remainder of parent range
*/
vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL);
if (vm2 == NULL) {
printk(KERN_ERR "%s() out of memory\n", __FUNCTION__);
kfree(vm1);
return NULL;
}
vm1->size = size;
vm1->addr = (void *) v_addr;
vm1->next = vm2;
new_vm = vm1;
vm2->size = ((unsigned long) parent->addr + parent->size) -
(v_addr + size);
vm2->addr = (void *) v_addr + size;
vm2->next = parent->next;
parent->size = v_addr - (unsigned long) parent->addr;
parent->next = vm1;
}
return new_vm;
}
static struct vm_struct * __add_new_im_area(unsigned long req_addr,
unsigned long size)
{
struct vm_struct **p, *tmp, *area;
for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
if (req_addr + size <= (unsigned long)tmp->addr)
break;
}
area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
area->flags = 0;
area->addr = (void *)req_addr;
area->size = size;
area->next = *p;
*p = area;
return area;
}
static struct vm_struct * __im_get_area(unsigned long req_addr,
unsigned long size,
int criteria)
{
struct vm_struct *tmp;
int status;
status = im_region_status(req_addr, size, &tmp);
if ((criteria & status) == 0) {
return NULL;
}
switch (status) {
case IM_REGION_UNUSED:
tmp = __add_new_im_area(req_addr, size);
break;
case IM_REGION_SUBSET:
tmp = split_im_region(req_addr, size, tmp);
break;
case IM_REGION_EXISTS:
/* Return requested region */
break;
case IM_REGION_SUPERSET:
/* Return first existing subset of requested region */
break;
default:
printk(KERN_ERR "%s() unexpected imalloc region status\n",
__FUNCTION__);
tmp = NULL;
}
return tmp;
}
struct vm_struct * im_get_free_area(unsigned long size)
{
struct vm_struct *area;
unsigned long addr;
mutex_lock(&imlist_mutex);
if (get_free_im_addr(size, &addr)) {
printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n",
__FUNCTION__, size);
area = NULL;
goto next_im_done;
}
area = __im_get_area(addr, size, IM_REGION_UNUSED);
if (area == NULL) {
printk(KERN_ERR
"%s() cannot obtain area for addr 0x%lx size 0x%lx\n",
__FUNCTION__, addr, size);
}
next_im_done:
mutex_unlock(&imlist_mutex);
return area;
}
struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
int criteria)
{
struct vm_struct *area;
mutex_lock(&imlist_mutex);
area = __im_get_area(v_addr, size, criteria);
mutex_unlock(&imlist_mutex);
return area;
}
void im_free(void * addr)
{
struct vm_struct **p, *tmp;
if (!addr)
return;
if ((unsigned long) addr & ~PAGE_MASK) {
printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
return;
}
mutex_lock(&imlist_mutex);
for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
unmap_vm_area(tmp);
kfree(tmp);
mutex_unlock(&imlist_mutex);
return;
}
}
mutex_unlock(&imlist_mutex);
printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
addr);
}

View File

@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
* PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
*
* Derived from "arch/i386/mm/init.c"

View File

@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds

View File

@ -5,7 +5,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
* PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
*
* Derived from "arch/i386/mm/init.c"
@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size)
zone = pgdata->node_zones;
return __add_pages(zone, start_pfn, nr_pages);
return 0;
}
/*

View File

@ -11,7 +11,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds

View File

@ -8,7 +8,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@ -40,8 +39,8 @@ extern int __map_without_bats;
extern unsigned long ioremap_base;
extern unsigned int rtas_data, rtas_size;
struct _PTE;
extern struct _PTE *Hash, *Hash_end;
struct hash_pte;
extern struct hash_pte *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern unsigned int num_tlbcam_entries;
@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va,
else
_tlbie(va);
}
#else /* CONFIG_PPC64 */
/* imalloc region types */
#define IM_REGION_UNUSED 0x1
#define IM_REGION_SUBSET 0x2
#define IM_REGION_EXISTS 0x4
#define IM_REGION_OVERLAP 0x8
#define IM_REGION_SUPERSET 0x10
extern struct vm_struct * im_get_free_area(unsigned long size);
extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
int region_type);
extern void im_free(void *addr);
#endif

View File

@ -8,7 +8,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@ -37,7 +36,6 @@
unsigned long ioremap_base;
unsigned long ioremap_bot;
EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
int io_bat_index;
#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
#define HAVE_BATS 1
@ -300,51 +298,6 @@ void __init mapin_ram(void)
}
}
/* is x a power of 4? */
#define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1)
/*
* Set up a mapping for a block of I/O.
* virt, phys, size must all be page-aligned.
* This should only be called before ioremap is called.
*/
void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
unsigned int size, int flags)
{
int i;
if (virt > KERNELBASE && virt < ioremap_bot)
ioremap_bot = ioremap_base = virt;
#ifdef HAVE_BATS
/*
* Use a BAT for this if possible...
*/
if (io_bat_index < 2 && is_power_of_2(size)
&& (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
setbat(io_bat_index, virt, phys, size, flags);
++io_bat_index;
return;
}
#endif /* HAVE_BATS */
#ifdef HAVE_TLBCAM
/*
* Use a CAM for this if possible...
*/
if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size)
&& (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
settlbcam(tlbcam_index, virt, phys, size, flags, 0);
++tlbcam_index;
return;
}
#endif /* HAVE_TLBCAM */
/* No BATs available, put it in the page tables. */
for (i = 0; i < size; i += PAGE_SIZE)
map_page(virt + i, phys + i, flags);
}
/* Scan the real Linux page tables and return a PTE pointer for
* a virtual address in a context.
* Returns true (1) if PTE was found, zero otherwise. The pointer to
@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
return(retval);
}
/* Find physical address for this virtual address. Normally used by
* I/O functions, but anyone can call it.
*/
unsigned long iopa(unsigned long addr)
{
unsigned long pa;
/* I don't know why this won't work on PMacs or CHRP. It
* appears there is some bug, or there is some implicit
* mapping done not properly represented by BATs or in page
* tables.......I am actively working on resolving this, but
* can't hold up other stuff. -- Dan
*/
pte_t *pte;
struct mm_struct *mm;
/* Check the BATs */
pa = v_mapped_by_bats(addr);
if (pa)
return pa;
/* Allow mapping of user addresses (within the thread)
* for DMA if necessary.
*/
if (addr < TASK_SIZE)
mm = current->mm;
else
mm = &init_mm;
pa = 0;
if (get_pteptr(mm, addr, &pte, NULL)) {
pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
pte_unmap(pte);
}
return(pa);
}
/* This is will find the virtual address for a physical one....
* Swiped from APUS, could be dangerous :-).
* This is only a placeholder until I really find a way to make this
* work. -- Dan
*/
unsigned long
mm_ptov (unsigned long paddr)
{
unsigned long ret;
#if 0
if (paddr < 16*1024*1024)
ret = ZTWO_VADDR(paddr);
else {
int i;
for (i = 0; i < kmap_chunk_count;){
unsigned long phys = kmap_chunks[i++];
unsigned long size = kmap_chunks[i++];
unsigned long virt = kmap_chunks[i++];
if (paddr >= phys
&& paddr < (phys + size)){
ret = virt + paddr - phys;
goto exit;
}
}
ret = (unsigned long) __va(paddr);
}
exit:
#ifdef DEBUGPV
printk ("PTOV(%lx)=%lx\n", paddr, ret);
#endif
#else
ret = (unsigned long)paddr + KERNELBASE;
#endif
return ret;
}
#ifdef CONFIG_DEBUG_PAGEALLOC
static int __change_page_attr(struct page *page, pgprot_t prot)

View File

@ -7,7 +7,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@samba.org)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@ -34,41 +33,27 @@
#include <linux/stddef.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <linux/idr.h>
#include <linux/nodemask.h>
#include <linux/module.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/lmb.h>
#include <asm/rtas.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/mmu.h>
#include <asm/uaccess.h>
#include <asm/smp.h>
#include <asm/machdep.h>
#include <asm/tlb.h>
#include <asm/eeh.h>
#include <asm/processor.h>
#include <asm/mmzone.h>
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/system.h>
#include <asm/iommu.h>
#include <asm/abs_addr.h>
#include <asm/vdso.h>
#include <asm/firmware.h>
#include "mmu_decl.h"
unsigned long ioremap_bot = IMALLOC_BASE;
static unsigned long phbs_io_bot = PHBS_IO_BASE;
unsigned long ioremap_bot = IOREMAP_BASE;
/*
* map_io_page currently only called by __ioremap
@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
* entry in the hardware page table.
*
*/
if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
mmu_io_psize)) {
if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE,
pa, flags, mmu_io_psize)) {
printk(KERN_ERR "Failed to do bolted mapping IO "
"memory at %016lx !\n", pa);
return -ENOMEM;
@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
}
static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
unsigned long ea, unsigned long size,
/**
* __ioremap_at - Low level function to establish the page tables
* for an IO mapping
*/
void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size,
unsigned long flags)
{
unsigned long i;
@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
if ((flags & _PAGE_PRESENT) == 0)
flags |= pgprot_val(PAGE_KERNEL);
WARN_ON(pa & ~PAGE_MASK);
WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
WARN_ON(size & ~PAGE_MASK);
for (i = 0; i < size; i += PAGE_SIZE)
if (map_io_page(ea+i, pa+i, flags))
if (map_io_page((unsigned long)ea+i, pa+i, flags))
return NULL;
return (void __iomem *) (ea + (addr & ~PAGE_MASK));
return (void __iomem *)ea;
}
/**
* __iounmap_from - Low level function to tear down the page tables
* for an IO mapping. This is used for mappings that
* are manipulated manually, like partial unmapping of
* PCI IOs or ISA space.
*/
void __iounmap_at(void *ea, unsigned long size)
{
WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
WARN_ON(size & ~PAGE_MASK);
unmap_kernel_range((unsigned long)ea, size);
}
void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
unsigned long pa, ea;
phys_addr_t paligned;
void __iomem *ret;
/*
@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
* IMALLOC_END
*
*/
pa = addr & PAGE_MASK;
size = PAGE_ALIGN(addr + size) - pa;
paligned = addr & PAGE_MASK;
size = PAGE_ALIGN(addr + size) - paligned;
if ((size == 0) || (pa == 0))
if ((size == 0) || (paligned == 0))
return NULL;
if (mem_init_done) {
struct vm_struct *area;
area = im_get_free_area(size);
area = __get_vm_area(size, VM_IOREMAP,
ioremap_bot, IOREMAP_END);
if (area == NULL)
return NULL;
ea = (unsigned long)(area->addr);
ret = __ioremap_com(addr, pa, ea, size, flags);
ret = __ioremap_at(paligned, area->addr, size, flags);
if (!ret)
im_free(area->addr);
vunmap(area->addr);
} else {
ea = ioremap_bot;
ret = __ioremap_com(addr, pa, ea, size, flags);
ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags);
if (ret)
ioremap_bot += size;
}
if (ret)
ret += addr & ~PAGE_MASK;
return ret;
}
@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
}
#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
unsigned long size, unsigned long flags)
{
struct vm_struct *area;
void __iomem *ret;
/* For now, require page-aligned values for pa, ea, and size */
if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
!IS_PAGE_ALIGNED(size)) {
printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__);
return 1;
}
if (!mem_init_done) {
/* Two things to consider in this case:
* 1) No records will be kept (imalloc, etc) that the region
* has been remapped
* 2) It won't be easy to iounmap() the region later (because
* of 1)
*/
;
} else {
area = im_get_area(ea, size,
IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
if (area == NULL) {
/* Expected when PHB-dlpar is in play */
return 1;
}
if (ea != (unsigned long) area->addr) {
printk(KERN_ERR "unexpected addr return from "
"im_get_area\n");
return 1;
}
}
ret = __ioremap_com(pa, pa, ea, size, flags);
if (ret == NULL) {
printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
return 1;
}
if (ret != (void *) ea) {
printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
return 1;
}
return 0;
}
/*
* Unmap an IO region and remove it from imalloc'd list.
* Access to IO memory should be serialized by driver.
* This code is modeled after vmalloc code - unmap_vm_area()
*
* XXX what about calls before mem_init_done (ie python_countermeasures())
*/
void __iounmap(volatile void __iomem *token)
{
@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token)
if (!mem_init_done)
return;
addr = (void *) ((unsigned long __force) token & PAGE_MASK);
im_free(addr);
addr = (void *) ((unsigned long __force)
PCI_FIX_ADDR(token) & PAGE_MASK);
if ((unsigned long)addr < ioremap_bot) {
printk(KERN_WARNING "Attempt to iounmap early bolted mapping"
" at 0x%p\n", addr);
return;
}
vunmap(addr);
}
void iounmap(volatile void __iomem *token)
@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token)
__iounmap(token);
}
static int iounmap_subset_regions(unsigned long addr, unsigned long size)
{
struct vm_struct *area;
/* Check whether subsets of this region exist */
area = im_get_area(addr, size, IM_REGION_SUPERSET);
if (area == NULL)
return 1;
while (area) {
iounmap((void __iomem *) area->addr);
area = im_get_area(addr, size,
IM_REGION_SUPERSET);
}
return 0;
}
int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
{
struct vm_struct *area;
unsigned long addr;
int rc;
addr = (unsigned long __force) start & PAGE_MASK;
/* Verify that the region either exists or is a subset of an existing
* region. In the latter case, split the parent region to create
* the exact region
*/
area = im_get_area(addr, size,
IM_REGION_EXISTS | IM_REGION_SUBSET);
if (area == NULL) {
/* Determine whether subset regions exist. If so, unmap */
rc = iounmap_subset_regions(addr, size);
if (rc) {
printk(KERN_ERR
"%s() cannot unmap nonexistent range 0x%lx\n",
__FUNCTION__, addr);
return 1;
}
} else {
iounmap((void __iomem *) area->addr);
}
/*
* FIXME! This can't be right:
iounmap(area->addr);
* Maybe it should be "iounmap(area);"
*/
return 0;
}
EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(ioremap_flags);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__iounmap);
static DEFINE_SPINLOCK(phb_io_lock);
void __iomem * reserve_phb_iospace(unsigned long size)
{
void __iomem *virt_addr;
if (phbs_io_bot >= IMALLOC_BASE)
panic("reserve_phb_iospace(): phb io space overflow\n");
spin_lock(&phb_io_lock);
virt_addr = (void __iomem *) phbs_io_bot;
phbs_io_bot += size;
spin_unlock(&phb_io_lock);
return virt_addr;
}

View File

@ -11,7 +11,6 @@
* Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
* and Cort Dougan (PReP) (cort@cs.nmt.edu)
* Copyright (C) 1996 Paul Mackerras
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
*
* Derived from "arch/i386/mm/init.c"
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
@ -35,12 +34,12 @@
#include "mmu_decl.h"
PTE *Hash, *Hash_end;
struct hash_pte *Hash, *Hash_end;
unsigned long Hash_size, Hash_mask;
unsigned long _SDR1;
union ubat { /* BAT register values to be loaded */
BAT bat;
struct ppc_bat bat;
u32 word[2];
} BATS[8][2]; /* 8 pairs of IBAT, DBAT */
@ -245,7 +244,7 @@ void __init MMU_init_hw(void)
cacheable_memzero(Hash, Hash_size);
_SDR1 = __pa(Hash) | SDR1_LOW_BITS;
Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
total_memory >> 20, Hash_size >> 10, Hash);

Some files were not shown because too many files have changed in this diff Show More