mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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:
commit
489de30259
@ -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.
|
||||
|
@ -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
|
||||
|
||||
---------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
35
arch/powerpc/boot/cuboot.c
Normal file
35
arch/powerpc/boot/cuboot.c
Normal 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);
|
||||
}
|
14
arch/powerpc/boot/cuboot.h
Normal file
14
arch/powerpc/boot/cuboot.h
Normal 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_ */
|
@ -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
|
||||
|
@ -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>;
|
||||
|
||||
|
@ -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";
|
||||
};
|
||||
};
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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 >;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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 >;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -309,7 +309,7 @@
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "ip=on console=ttyMM0";
|
||||
bootargs = "ip=on";
|
||||
linux,stdout-path = "/mv64x60@f1000000/mpsc@8000";
|
||||
};
|
||||
};
|
||||
|
68
arch/powerpc/boot/dts/ps3.dts
Normal file
68
arch/powerpc/boot/dts/ps3.dts
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
21
arch/powerpc/boot/of.h
Normal 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_ */
|
45
arch/powerpc/boot/ofconsole.c
Normal file
45
arch/powerpc/boot/ofconsole.c
Normal 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
202
arch/powerpc/boot/oflib.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
80
arch/powerpc/boot/ps3-head.S
Normal file
80
arch/powerpc/boot/ps3-head.S
Normal 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
|
184
arch/powerpc/boot/ps3-hvcall.S
Normal file
184
arch/powerpc/boot/ps3-hvcall.S
Normal 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
161
arch/powerpc/boot/ps3.c
Normal 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();
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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') {
|
||||
|
@ -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); \
|
||||
|
@ -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
|
||||
|
50
arch/powerpc/boot/zImage.ps3.lds.S
Normal file
50
arch/powerpc/boot/zImage.ps3.lds.S
Normal 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 = . ;
|
||||
}
|
@ -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
|
||||
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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--;
|
||||
|
@ -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);
|
||||
|
271
arch/powerpc/kernel/isa-bridge.c
Normal file
271
arch/powerpc/kernel/isa-bridge.c
Normal 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);
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
454
arch/powerpc/kernel/pci-common.c
Normal file
454
arch/powerpc/kernel/pci-common.c
Normal 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;
|
||||
}
|
@ -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 &&
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 = ¤t->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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
180
arch/powerpc/kernel/signal.c
Normal file
180
arch/powerpc/kernel/signal.c
Normal 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(¤t->sighand->siglock);
|
||||
current->blocked = *set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->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, ¤t->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(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka.sa.sa_mask);
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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]);
|
||||
}
|
55
arch/powerpc/kernel/signal.h
Normal file
55
arch/powerpc/kernel/signal.h
Normal 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 */
|
@ -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(¤t->sighand->siglock);
|
||||
current->blocked = *set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->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, ¤t->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(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka.sa.sa_mask);
|
||||
if (!(ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, signr);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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;
|
||||
}
|
||||
|
@ -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(¤t->sighand->siglock);
|
||||
current->blocked = *set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->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, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(do_signal);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 = .;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user