Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc

* master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc: (194 commits)
  [POWERPC] Add missing EXPORTS for mpc52xx support
  [POWERPC] Remove obsolete PPC_52xx and update CLASSIC32 comment
  [POWERPC] ps3: add a default zImage target
  [POWERPC] Add of_platform_bus support to mpc52xx psc uart driver
  [POWERPC] typo fix and whitespace cleanup on mpc52xx-uart driver
  [POWERPC] Fix debug printks for 32-bit resources in the PCI code
  [POWERPC] Replace kmalloc+memset with kzalloc
  [POWERPC] Linkstation / kurobox support
  [POWERPC] Add the e300c3 core to the CPU table.
  [POWERPC] ppc: m48t35 add missing bracket
  [POWERPC] iSeries: don't build head_64.o unnecessarily
  [POWERPC] iSeries: stop dt_mod.o being rebuilt unnecessarily
  [POWERPC] Fix cputable.h for combined build
  [POWERPC] Allow CONFIG_BOOTX_TEXT on iSeries
  [POWERPC] Allow xmon to build on legacy iSeries
  [POWERPC] Change ppc64_defconfig to use AUTOFS_V4 not V3
  [POWERPC] Tell firmware we can handle POWER6 compatible mode
  [POWERPC] Clean images in arch/powerpc/boot
  [POWERPC] Fix OF pci flags parsing
  [POWERPC] defconfig for lite5200 board
  ...
This commit is contained in:
Linus Torvalds 2006-12-04 19:22:33 -08:00
commit 15a4cb9c25
298 changed files with 25533 additions and 5120 deletions

View File

@ -6,6 +6,8 @@
IBM Corp.
(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
Freescale Semiconductor, FSL SOC and 32-bit additions
(c) 2006 MontaVista Software, Inc.
Flash chip node definition
May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
@ -1693,6 +1695,43 @@ platforms are moved over to use the flattened-device-tree model.
};
};
g) Flash chip nodes
Flash chips (Memory Technology Devices) are often used for solid state
file systems on embedded devices.
Required properties:
- device_type : has to be "rom"
- compatible : Should specify what this ROM device is compatible with
(i.e. "onenand"). Currently, this is most likely to be "direct-mapped"
(which corresponds to the MTD physmap mapping driver).
- regs : Offset and length of the register set (or memory mapping) for
the device.
Recommended properties :
- bank-width : Width of the flash data bus in bytes. Required
for the NOR flashes (compatible == "direct-mapped" and others) ONLY.
- partitions : Several pairs of 32-bit values where the first value is
partition's offset from the start of the device and the second one is
partition size in bytes with LSB used to signify a read only
partititon (so, the parition size should always be an even number).
- partition-names : The list of concatenated zero terminated strings
representing the partition names.
Example:
flash@ff000000 {
device_type = "rom";
compatible = "direct-mapped";
regs = <ff000000 01000000>;
bank-width = <4>;
partitions = <00000000 00f80000
00f80000 00080001>;
partition-names = "fs\0firmware";
};
More devices will be defined as this spec matures.

View File

@ -0,0 +1,189 @@
MPC52xx Device Tree Bindings
----------------------------
(c) 2006 Secret Lab Technologies Ltd
Grant Likely <grant.likely at secretlab.ca>
I - Introduction
================
Boards supported by the arch/powerpc architecture require device tree be
passed by the boot loader to the kernel at boot time. The device tree
describes what devices are present on the board and how they are
connected. The device tree can either be passed as a binary blob (as
described in Documentation/powerpc/booting-without-of.txt), or passed
by Open Firmare (IEEE 1275) compatible firmware using an OF compatible
client interface API.
This document specifies the requirements on the device-tree for mpc52xx
based boards. These requirements are above and beyond the details
specified in either the OpenFirmware spec or booting-without-of.txt
All new mpc52xx-based boards are expected to match this document. In
cases where this document is not sufficient to support a new board port,
this document should be updated as part of adding the new board support.
II - Philosophy
===============
The core of this document is naming convention. The whole point of
defining this convention is to reduce or eliminate the number of
special cases required to support a 52xx board. If all 52xx boards
follow the same convention, then generic 52xx support code will work
rather than coding special cases for each new board.
This section tries to capture the thought process behind why the naming
convention is what it is.
1. Node names
-------------
There is strong convention/requirements already established for children
of the root node. 'cpus' describes the processor cores, 'memory'
describes memory, and 'chosen' provides boot configuration. Other nodes
are added to describe devices attached to the processor local bus.
Following convention already established with other system-on-chip
processors, MPC52xx boards must have an 'soc5200' node as a child of the
root node.
The soc5200 node holds child nodes for all on chip devices. Child nodes
are typically named after the configured function. ie. the FEC node is
named 'ethernet', and a PSC in uart mode is named 'serial'.
2. device_type property
-----------------------
similar to the node name convention above; the device_type reflects the
configured function of a device. ie. 'serial' for a uart and 'spi' for
an spi controller. However, while node names *should* reflect the
configured function, device_type *must* match the configured function
exactly.
3. compatible property
----------------------
Since device_type isn't enough to match devices to drivers, there also
needs to be a naming convention for the compatible property. Compatible
is an list of device descriptions sorted from specific to generic. For
the mpc52xx, the required format for each compatible value is
<chip>-<device>[-<mode>]. At the minimum, the list shall contain two
items; the first specifying the exact chip, and the second specifying
mpc52xx for the chip.
ie. ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc52xx-ethernet"
The idea here is that most drivers will match to the most generic field
in the compatible list (mpc52xx-*), but can also test the more specific
field for enabling bug fixes or extra features.
Modal devices, like PSCs, also append the configured function to the
end of the compatible field. ie. A PSC in i2s mode would specify
"mpc52xx-psc-i2s", not "mpc52xx-i2s". This convention is chosen to
avoid naming conflicts with non-psc devices providing the same
function. For example, "mpc52xx-spi" and "mpc52xx-psc-spi" describe
the mpc5200 simple spi device and a PSC spi mode respectively.
If the soc device is more generic and present on other SOCs, the
compatible property can specify the more generic device type also.
ie. mscan: compatible = "mpc5200-mscan\0mpc52xx-mscan\0fsl,mscan";
At the time of writing, exact chip may be either 'mpc5200' or
'mpc5200b'.
Device drivers should always try to match as generically as possible.
III - Structure
===============
The device tree for an mpc52xx board follows the structure defined in
booting-without-of.txt with the following additional notes:
0) the root node
----------------
Typical root description node; see booting-without-of
1) The cpus node
----------------
The cpus node follows the basic layout described in booting-without-of.
The bus-frequency property holds the XLB bus frequency
The clock-frequency property holds the core frequency
2) The memory node
------------------
Typical memory description node; see booting-without-of.
3) The soc5200 node
-------------------
This node describes the on chip SOC peripherals. Every mpc52xx based
board will have this node, and as such there is a common naming
convention for SOC devices.
Required properties:
name type description
---- ---- -----------
device_type string must be "soc"
ranges int should be <0 baseaddr baseaddr+10000>
reg int must be <baseaddr 10000>
Recommended properties:
name type description
---- ---- -----------
compatible string should be "<chip>-soc\0mpc52xx-soc"
ie. "mpc5200b-soc\0mpc52xx-soc"
#interrupt-cells int must be <3>. If it is not defined
here then it must be defined in every
soc device node.
bus-frequency int IPB bus frequency in HZ. Clock rate
used by most of the soc devices.
Defining it here avoids needing it
added to every device node.
4) soc5200 child nodes
----------------------
Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
Note: in the tables below, '*' matches all <chip> values. ie.
*-pic would translate to "mpc5200-pic\0mpc52xx-pic"
Required soc5200 child nodes:
name device_type compatible Description
---- ----------- ---------- -----------
cdm@<addr> cdm *-cmd Clock Distribution
pic@<addr> interrupt-controller *-pic need an interrupt
controller to boot
bestcomm@<addr> dma-controller *-bestcomm 52xx pic also requires
the bestcomm device
Recommended soc5200 child nodes; populate as needed for your board
name device_type compatible Description
---- ----------- ---------- -----------
gpt@<addr> gpt *-gpt General purpose timers
rtc@<addr> rtc *-rtc Real time clock
mscan@<addr> mscan *-mscan CAN bus controller
pci@<addr> pci *-pci PCI bridge
serial@<addr> serial *-psc-uart PSC in serial mode
i2s@<addr> i2s *-psc-i2s PSC in i2s mode
ac97@<addr> ac97 *-psc-ac97 PSC in ac97 mode
spi@<addr> spi *-psc-spi PSC in spi mode
irda@<addr> irda *-psc-irda PSC in IrDA mode
spi@<addr> spi *-spi MPC52xx spi device
ethernet@<addr> network *-fec MPC52xx ethernet device
ata@<addr> ata *-ata IDE ATA interface
i2c@<addr> i2c *-i2c I2C controller
usb@<addr> usb-ohci-be *-ohci,ohci-be USB controller
xlb@<addr> xlb *-xlb XLB arbritrator
IV - Extra Notes
================
1. Interrupt mapping
--------------------
The mpc52xx pic driver splits hardware IRQ numbers into two levels. The
split reflects the layout of the PIC hardware itself, which groups
interrupts into one of three groups; CRIT, MAIN or PERP. Also, the
Bestcomm dma engine has it's own set of interrupt sources which are
cascaded off of peripheral interrupt 0, which the driver interprets as a
fourth group, SDMA.
The interrupts property for device nodes using the mpc52xx pic consists
of three cells; <L1 L2 level>
L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
L2 := interrupt number; directly mapped from the value in the
"ICTL PerStat, MainStat, CritStat Encoded Register"
level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]

View File

@ -2438,6 +2438,13 @@ M: promise@pnd-pc.demon.co.uk
W: http://www.pnd-pc.demon.co.uk/promise/
S: Maintained
PS3 PLATFORM SUPPORT
P: Geoff Levand
M: geoffrey.levand@am.sony.com
L: linuxppc-dev@ozlabs.org
L: cbe-oss-dev@ozlabs.org
S: Supported
PVRUSB2 VIDEO4LINUX DRIVER
P: Mike Isely
M: isely@pobox.com

1
arch/powerpc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
include

View File

@ -112,7 +112,7 @@ choice
default 6xx
config CLASSIC32
bool "6xx/7xx/74xx"
bool "52xx/6xx/7xx/74xx"
select PPC_FPU
select 6xx
help
@ -121,16 +121,18 @@ config CLASSIC32
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
Unless you are building a kernel for one of the embedded processor
systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
Note that the kernel runs in 32-bit mode even on 64-bit chips.
config PPC_52xx
bool "Freescale 52xx"
select 6xx
select PPC_FPU
config PPC_82xx
bool "Freescale 82xx"
select 6xx
@ -160,9 +162,11 @@ config PPC_86xx
config 40x
bool "AMCC 40x"
select PPC_DCR_NATIVE
config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
config 8xx
bool "Freescale 8xx"
@ -208,6 +212,24 @@ config PPC_FPU
bool
default y if PPC64
config PPC_DCR_NATIVE
bool
default n
config PPC_DCR_MMIO
bool
default n
config PPC_DCR
bool
depends on PPC_DCR_NATIVE || PPC_DCR_MMIO
default y
config PPC_OF_PLATFORM_PCI
bool
depends on PPC64 # not supported on 32 bits yet
default n
config BOOKE
bool
depends on E200 || E500
@ -227,6 +249,7 @@ config PTE_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
@ -369,11 +392,13 @@ config PPC_PSERIES
select PPC_RTAS
select RTAS_ERROR_LOGGING
select PPC_UDBG_16550
select PPC_NATIVE
default y
config PPC_ISERIES
bool "IBM Legacy iSeries"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_INDIRECT_IO
config PPC_CHRP
bool "Common Hardware Reference Platform (CHRP) based machines"
@ -384,14 +409,35 @@ config PPC_CHRP
select PPC_RTAS
select PPC_MPC106
select PPC_UDBG_16550
select PPC_NATIVE
default y
config PPC_MPC52xx
bool
default n
config PPC_EFIKA
bool "bPlan Efika 5k2. MPC5200B based computer"
depends on PPC_MULTIPLATFORM && PPC32
select PPC_RTAS
select RTAS_PROC
select PPC_MPC52xx
select PPC_NATIVE
default y
config PPC_LITE5200
bool "Freescale Lite5200 Eval Board"
depends on PPC_MULTIPLATFORM && PPC32
select PPC_MPC52xx
default n
config PPC_PMAC
bool "Apple PowerMac based machines"
depends on PPC_MULTIPLATFORM
select MPIC
select PPC_INDIRECT_PCI if PPC32
select PPC_MPC106 if PPC32
select PPC_NATIVE
default y
config PPC_PMAC64
@ -411,6 +457,7 @@ config PPC_PREP
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_UDBG_16550
select PPC_NATIVE
default y
config PPC_MAPLE
@ -422,6 +469,7 @@ config PPC_MAPLE
select GENERIC_TBSYNC
select PPC_UDBG_16550
select PPC_970_NAP
select PPC_NATIVE
default n
help
This option enables support for the Maple 970FX Evaluation Board.
@ -434,6 +482,7 @@ config PPC_PASEMI
select MPIC
select PPC_UDBG_16550
select GENERIC_TBSYNC
select PPC_NATIVE
help
This option enables support for PA Semi's PWRficient line
of SoC processors, including PA6T-1682M
@ -445,6 +494,11 @@ config PPC_CELL
config PPC_CELL_NATIVE
bool
select PPC_CELL
select PPC_DCR_MMIO
select PPC_OF_PLATFORM_PCI
select PPC_INDIRECT_IO
select PPC_NATIVE
select MPIC
default n
config PPC_IBM_CELL_BLADE
@ -456,6 +510,22 @@ config PPC_IBM_CELL_BLADE
select PPC_UDBG_16550
select UDBG_RTAS_CONSOLE
config PPC_PS3
bool "Sony PS3"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor.
config PPC_NATIVE
bool
depends on PPC_MULTIPLATFORM
help
Support for running natively on the hardware, i.e. without
a hypervisor. This option is not user-selectable but should
be selected by all platforms that need it.
config UDBG_RTAS_CONSOLE
bool "RTAS based debug console"
depends on PPC_RTAS
@ -517,6 +587,15 @@ config PPC_970_NAP
bool
default n
config PPC_INDIRECT_IO
bool
select GENERIC_IOMAP
default n
config GENERIC_IOMAP
bool
default n
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_PMAC
@ -594,12 +673,6 @@ config TAU_AVERAGE
If in doubt, say N here.
config PPC_TODC
depends on EMBEDDED6xx
bool "Generic Time-of-day Clock (TODC) support"
---help---
This adds support for many TODC/RTC chips.
endmenu
source arch/powerpc/platforms/embedded6xx/Kconfig
@ -610,6 +683,7 @@ source arch/powerpc/platforms/85xx/Kconfig
source arch/powerpc/platforms/86xx/Kconfig
source arch/powerpc/platforms/8xx/Kconfig
source arch/powerpc/platforms/cell/Kconfig
source arch/powerpc/platforms/ps3/Kconfig
menu "Kernel options"
@ -790,7 +864,6 @@ source "arch/powerpc/platforms/prep/Kconfig"
config CMDLINE_BOOL
bool "Default bootloader kernel arguments"
depends on !PPC_ISERIES
config CMDLINE
string "Initial kernel command string"
@ -880,7 +953,7 @@ config MCA
config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2
|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3
default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS

View File

@ -77,7 +77,7 @@ config KGDB_CONSOLE
config XMON
bool "Include xmon kernel debugger"
depends on DEBUGGER && !PPC_ISERIES
depends on DEBUGGER
help
Include in-kernel hooks for the xmon kernel monitor/debugger.
Unless you are intending to debug the kernel, say N here.
@ -98,6 +98,15 @@ config XMON_DEFAULT
xmon is normally disabled unless booted with 'xmon=on'.
Use 'xmon=off' to disable xmon init during runtime.
config XMON_DISASSEMBLY
bool "Include disassembly support in xmon"
depends on XMON
default y
help
Include support for disassembling in xmon. You probably want
to say Y here, unless you're building for a memory-constrained
system.
config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
depends on PPC64
@ -116,7 +125,7 @@ config BDI_SWITCH
config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
depends PPC_OF && !PPC_ISERIES
depends PPC_OF
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires either BootX or Open Firmware.

View File

@ -1,19 +1,32 @@
addnote
empty.c
hack-coff
infblock.c
infblock.h
infcodes.c
infcodes.h
inffast.c
inffast.h
inffixed.h
inflate.c
inflate.h
inftrees.c
inftrees.h
infutil.c
infutil.h
kernel-vmlinux.strip.c
kernel-vmlinux.strip.gz
mktree
uImage
zImage
zImage.chrp
zImage.coff
zImage.coff.lds
zImage.lds
zImage.miboot
zImage.pmac
zImage.pseries
zImage.sandpoint
zImage.vmode
zconf.h
zlib.h

View File

@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
$(addprefix $(obj)/,$(zlibheader))
src-wlib := string.S stdio.c main.c div64.S $(zlib)
src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib)
src-plat := of.c
src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
@ -74,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
$(obj)/empty.c
empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
quiet_cmd_bootcc = BOOTCC $@
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@ -93,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
$(obj)/wrapper.a: $(obj-wlib)
$(call cmd,bootar)
hostprogs-y := addnote addRamDisk hack-coff
hostprogs-y := addnote addRamDisk hack-coff mktree
extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
$(obj)/zImage.lds $(obj)/zImage.coff.lds
wrapper :=$(srctree)/$(src)/wrapper
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff)
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree)
#############
# Bits for building various flavours of zImage
@ -148,13 +149,18 @@ $(obj)/zImage.miboot: vmlinux $(wrapperbits)
$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,miboot)
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/uImage: vmlinux $(wrapperbits)
$(call cmd,wrap,uboot)
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
image-$(CONFIG_PPC_MAPLE) += zImage.pseries
image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
image-$(CONFIG_PPC_PS3) += zImage.ps3
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
@ -176,3 +182,4 @@ install: $(CONFIGURE) $(image-y)
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz)
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz)
clean-files += $(image-)

View File

@ -0,0 +1,148 @@
/*
* Device Tree Souce for Buffalo KuroboxHG
*
* Choose CONFIG_LINKSTATION to build a kernel for KuroboxHG, or use
* the default configuration linkstation_defconfig.
*
* Based on sandpoint.dts
*
* 2006 (c) G. Liakhovetski <g.liakhovetski@gmx.de>
*
* This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
XXXX add flash parts, rtc, ??
build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
*/
/ {
linux,phandle = <1000>;
model = "KuroboxHG";
compatible = "linkstation";
#address-cells = <1>;
#size-cells = <1>;
cpus {
linux,phandle = <2000>;
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,603e { /* Really 8241 */
linux,phandle = <2100>;
linux,boot-cpu;
device_type = "cpu";
reg = <0>;
clock-frequency = <fdad680>; /* Fixed by bootwrapper */
timebase-frequency = <1F04000>; /* Fixed by bootwrapper */
bus-frequency = <0>; /* From bootloader */
/* Following required by dtc but not used */
i-cache-line-size = <0>;
d-cache-line-size = <0>;
i-cache-size = <4000>;
d-cache-size = <4000>;
};
};
memory {
linux,phandle = <3000>;
device_type = "memory";
reg = <00000000 08000000>;
};
soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
linux,phandle = <4000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
compatible = "mpc10x";
store-gathering = <0>; /* 0 == off, !0 == on */
reg = <80000000 00100000>;
ranges = <80000000 80000000 70000000 /* pci mem space */
fc000000 fc000000 00100000 /* EUMB */
fe000000 fe000000 00c00000 /* pci i/o space */
fec00000 fec00000 00300000 /* pci cfg regs */
fef00000 fef00000 00100000>; /* pci iack */
i2c@80003000 {
linux,phandle = <4300>;
device_type = "i2c";
compatible = "fsl-i2c";
reg = <80003000 1000>;
interrupts = <5 2>;
interrupt-parent = <4400>;
};
serial@80004500 {
linux,phandle = <4511>;
device_type = "serial";
compatible = "ns16550";
reg = <80004500 8>;
clock-frequency = <7c044a8>;
current-speed = <2580>;
interrupts = <9 2>;
interrupt-parent = <4400>;
};
serial@80004600 {
linux,phandle = <4512>;
device_type = "serial";
compatible = "ns16550";
reg = <80004600 8>;
clock-frequency = <7c044a8>;
current-speed = <e100>;
interrupts = <a 0>;
interrupt-parent = <4400>;
};
pic@80040000 {
linux,phandle = <4400>;
#interrupt-cells = <2>;
#address-cells = <0>;
device_type = "open-pic";
compatible = "chrp,open-pic";
interrupt-controller;
reg = <80040000 40000>;
built-in;
};
pci@fec00000 {
linux,phandle = <4500>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
device_type = "pci";
compatible = "mpc10x-pci";
reg = <fec00000 400000>;
ranges = <01000000 0 0 fe000000 0 00c00000
02000000 0 80000000 80000000 0 70000000>;
bus-range = <0 ff>;
clock-frequency = <7f28155>;
interrupt-parent = <4400>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 - IRQ0 ETH */
5800 0 0 1 4400 0 1
5800 0 0 2 4400 1 1
5800 0 0 3 4400 2 1
5800 0 0 4 4400 3 1
/* IDSEL 0x12 - IRQ1 IDE0 */
6000 0 0 1 4400 1 1
6000 0 0 2 4400 2 1
6000 0 0 3 4400 3 1
6000 0 0 4 4400 0 1
/* IDSEL 0x14 - IRQ3 USB2.0 */
7000 0 0 1 4400 3 1
7000 0 0 2 4400 3 1
7000 0 0 3 4400 3 1
7000 0 0 4 4400 3 1
>;
};
};
};

View File

@ -0,0 +1,313 @@
/*
* Lite5200 board Device Tree Source
*
* Copyright 2006 Secret Lab Technologies Ltd.
* Grant Likely <grant.likely@secretlab.ca>
*
* 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.
*/
/ {
model = "Lite5200";
compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,5200@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>;
i-cache-line-size = <20>;
d-cache-size = <4000>; // L1, 16K
i-cache-size = <4000>; // L1, 16K
timebase-frequency = <0>; // from bootloader
bus-frequency = <0>; // from bootloader
clock-frequency = <0>; // from bootloader
32-bit;
};
};
memory {
device_type = "memory";
reg = <00000000 04000000>; // 64MB
};
soc5200@f0000000 {
#interrupt-cells = <3>;
device_type = "soc";
ranges = <0 f0000000 f0010000>;
reg = <f0000000 00010000>;
bus-frequency = <0>; // from bootloader
cdm@200 {
compatible = "mpc5200-cdm\0mpc52xx-cdm";
reg = <200 38>;
};
pic@500 {
// 5200 interrupts are encoded into two levels;
linux,phandle = <500>;
interrupt-controller;
#interrupt-cells = <3>;
device_type = "interrupt-controller";
compatible = "mpc5200-pic\0mpc52xx-pic";
reg = <500 80>;
built-in;
};
gpt@600 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <500>;
};
gpt@610 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <610 10>;
interrupts = <1 a 0>;
interrupt-parent = <500>;
};
gpt@620 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <620 10>;
interrupts = <1 b 0>;
interrupt-parent = <500>;
};
gpt@630 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <630 10>;
interrupts = <1 c 0>;
interrupt-parent = <500>;
};
gpt@640 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <640 10>;
interrupts = <1 d 0>;
interrupt-parent = <500>;
};
gpt@650 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <650 10>;
interrupts = <1 e 0>;
interrupt-parent = <500>;
};
gpt@660 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <660 10>;
interrupts = <1 f 0>;
interrupt-parent = <500>;
};
gpt@670 { // General Purpose Timer
compatible = "mpc5200-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <670 10>;
interrupts = <1 10 0>;
interrupt-parent = <500>;
};
rtc@800 { // Real time clock
compatible = "mpc5200-rtc\0mpc52xx-rtc";
device_type = "rtc";
reg = <800 100>;
interrupts = <1 5 0 1 6 0>;
interrupt-parent = <500>;
};
mscan@900 {
device_type = "mscan";
compatible = "mpc5200-mscan\0mpc52xx-mscan";
interrupts = <2 11 0>;
interrupt-parent = <500>;
reg = <900 80>;
};
mscan@980 {
device_type = "mscan";
compatible = "mpc5200-mscan\0mpc52xx-mscan";
interrupts = <1 12 0>;
interrupt-parent = <500>;
reg = <980 80>;
};
gpio@b00 {
compatible = "mpc5200-gpio\0mpc52xx-gpio";
reg = <b00 40>;
interrupts = <1 7 0>;
interrupt-parent = <500>;
};
gpio-wkup@b00 {
compatible = "mpc5200-gpio-wkup\0mpc52xx-gpio-wkup";
reg = <c00 40>;
interrupts = <1 8 0 0 3 0>;
interrupt-parent = <500>;
};
pci@0d00 {
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
compatible = "mpc5200-pci\0mpc52xx-pci";
reg = <d00 100>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <c000 0 0 1 500 0 0 3
c000 0 0 2 500 0 0 3
c000 0 0 3 500 0 0 3
c000 0 0 4 500 0 0 3>;
clock-frequency = <0>; // From boot loader
interrupts = <2 8 0 2 9 0 2 a 0>;
interrupt-parent = <500>;
bus-range = <0 0>;
ranges = <42000000 0 80000000 80000000 0 20000000
02000000 0 a0000000 a0000000 0 10000000
01000000 0 00000000 b0000000 0 01000000>;
};
spi@f00 {
device_type = "spi";
compatible = "mpc5200-spi\0mpc52xx-spi";
reg = <f00 20>;
interrupts = <2 d 0 2 e 0>;
interrupt-parent = <500>;
};
usb@1000 {
device_type = "usb-ohci-be";
compatible = "mpc5200-ohci\0mpc52xx-ohci\0ohci-be";
reg = <1000 ff>;
interrupts = <2 6 0>;
interrupt-parent = <500>;
};
bestcomm@1200 {
device_type = "dma-controller";
compatible = "mpc5200-bestcomm\0mpc52xx-bestcomm";
reg = <1200 80>;
interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
3 4 0 3 5 0 3 6 0 3 7 0
3 8 0 3 9 0 3 a 0 3 b 0
3 c 0 3 d 0 3 e 0 3 f 0>;
interrupt-parent = <500>;
};
xlb@1f00 {
compatible = "mpc5200-xlb\0mpc52xx-xlb";
reg = <1f00 100>;
};
serial@2000 { // PSC1
device_type = "serial";
compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
port-number = <0>; // Logical port assignment
reg = <2000 100>;
interrupts = <2 1 0>;
interrupt-parent = <500>;
};
// PSC2 in spi mode example
spi@2200 { // PSC2
device_type = "spi";
compatible = "mpc5200-psc-spi\0mpc52xx-psc-spi";
reg = <2200 100>;
interrupts = <2 2 0>;
interrupt-parent = <500>;
};
// PSC3 in CODEC mode example
i2s@2400 { // PSC3
device_type = "i2s";
compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s";
reg = <2400 100>;
interrupts = <2 3 0>;
interrupt-parent = <500>;
};
// PSC4 unconfigured
//serial@2600 { // PSC4
// device_type = "serial";
// compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
// reg = <2600 100>;
// interrupts = <2 b 0>;
// interrupt-parent = <500>;
//};
// PSC5 unconfigured
//serial@2800 { // PSC5
// device_type = "serial";
// compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart";
// reg = <2800 100>;
// interrupts = <2 c 0>;
// interrupt-parent = <500>;
//};
// PSC6 in AC97 mode example
ac97@2c00 { // PSC6
device_type = "ac97";
compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97";
reg = <2c00 100>;
interrupts = <2 4 0>;
interrupt-parent = <500>;
};
ethernet@3000 {
device_type = "network";
compatible = "mpc5200-fec\0mpc52xx-fec";
reg = <3000 800>;
mac-address = [ 02 03 04 05 06 07 ]; // Bad!
interrupts = <2 5 0>;
interrupt-parent = <500>;
};
ata@3a00 {
device_type = "ata";
compatible = "mpc5200-ata\0mpc52xx-ata";
reg = <3a00 100>;
interrupts = <2 7 0>;
interrupt-parent = <500>;
};
i2c@3d00 {
device_type = "i2c";
compatible = "mpc5200-i2c\0mpc52xx-i2c";
reg = <3d00 40>;
interrupts = <2 f 0>;
interrupt-parent = <500>;
};
i2c@3d40 {
device_type = "i2c";
compatible = "mpc5200-i2c\0mpc52xx-i2c";
reg = <3d40 40>;
interrupts = <2 10 0>;
interrupt-parent = <500>;
};
sram@8000 {
device_type = "sram";
compatible = "mpc5200-sram\0mpc52xx-sram\0sram";
reg = <8000 4000>;
};
};
};

View File

@ -0,0 +1,318 @@
/*
* Lite5200B board Device Tree Source
*
* Copyright 2006 Secret Lab Technologies Ltd.
* Grant Likely <grant.likely@secretlab.ca>
*
* 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.
*/
/ {
model = "Lite5200b";
compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,5200@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>;
i-cache-line-size = <20>;
d-cache-size = <4000>; // L1, 16K
i-cache-size = <4000>; // L1, 16K
timebase-frequency = <0>; // from bootloader
bus-frequency = <0>; // from bootloader
clock-frequency = <0>; // from bootloader
32-bit;
};
};
memory {
device_type = "memory";
reg = <00000000 10000000>; // 256MB
};
soc5200@f0000000 {
#interrupt-cells = <3>;
device_type = "soc";
ranges = <0 f0000000 f0010000>;
reg = <f0000000 00010000>;
bus-frequency = <0>; // from bootloader
cdm@200 {
compatible = "mpc5200b-cdm\0mpc52xx-cdm";
reg = <200 38>;
};
pic@500 {
// 5200 interrupts are encoded into two levels;
linux,phandle = <500>;
interrupt-controller;
#interrupt-cells = <3>;
device_type = "interrupt-controller";
compatible = "mpc5200b-pic\0mpc52xx-pic";
reg = <500 80>;
built-in;
};
gpt@600 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <500>;
};
gpt@610 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <610 10>;
interrupts = <1 a 0>;
interrupt-parent = <500>;
};
gpt@620 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <620 10>;
interrupts = <1 b 0>;
interrupt-parent = <500>;
};
gpt@630 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <630 10>;
interrupts = <1 c 0>;
interrupt-parent = <500>;
};
gpt@640 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <640 10>;
interrupts = <1 d 0>;
interrupt-parent = <500>;
};
gpt@650 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <650 10>;
interrupts = <1 e 0>;
interrupt-parent = <500>;
};
gpt@660 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <660 10>;
interrupts = <1 f 0>;
interrupt-parent = <500>;
};
gpt@670 { // General Purpose Timer
compatible = "mpc5200b-gpt\0mpc52xx-gpt";
device_type = "gpt";
reg = <670 10>;
interrupts = <1 10 0>;
interrupt-parent = <500>;
};
rtc@800 { // Real time clock
compatible = "mpc5200b-rtc\0mpc52xx-rtc";
device_type = "rtc";
reg = <800 100>;
interrupts = <1 5 0 1 6 0>;
interrupt-parent = <500>;
};
mscan@900 {
device_type = "mscan";
compatible = "mpc5200b-mscan\0mpc52xx-mscan";
interrupts = <2 11 0>;
interrupt-parent = <500>;
reg = <900 80>;
};
mscan@980 {
device_type = "mscan";
compatible = "mpc5200b-mscan\0mpc52xx-mscan";
interrupts = <1 12 0>;
interrupt-parent = <500>;
reg = <980 80>;
};
gpio@b00 {
compatible = "mpc5200b-gpio\0mpc52xx-gpio";
reg = <b00 40>;
interrupts = <1 7 0>;
interrupt-parent = <500>;
};
gpio-wkup@b00 {
compatible = "mpc5200b-gpio-wkup\0mpc52xx-gpio-wkup";
reg = <c00 40>;
interrupts = <1 8 0 0 3 0>;
interrupt-parent = <500>;
};
pci@0d00 {
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
compatible = "mpc5200b-pci\0mpc52xx-pci";
reg = <d00 100>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <c000 0 0 1 500 0 0 3 // 1st slot
c000 0 0 2 500 1 1 3
c000 0 0 3 500 1 2 3
c000 0 0 4 500 1 3 3
c800 0 0 1 500 1 1 3 // 2nd slot
c800 0 0 2 500 1 2 3
c800 0 0 3 500 1 3 3
c800 0 0 4 500 0 0 3>;
clock-frequency = <0>; // From boot loader
interrupts = <2 8 0 2 9 0 2 a 0>;
interrupt-parent = <500>;
bus-range = <0 0>;
ranges = <42000000 0 80000000 80000000 0 20000000
02000000 0 a0000000 a0000000 0 10000000
01000000 0 00000000 b0000000 0 01000000>;
};
spi@f00 {
device_type = "spi";
compatible = "mpc5200b-spi\0mpc52xx-spi";
reg = <f00 20>;
interrupts = <2 d 0 2 e 0>;
interrupt-parent = <500>;
};
usb@1000 {
device_type = "usb-ohci-be";
compatible = "mpc5200b-ohci\0mpc52xx-ohci\0ohci-be";
reg = <1000 ff>;
interrupts = <2 6 0>;
interrupt-parent = <500>;
};
bestcomm@1200 {
device_type = "dma-controller";
compatible = "mpc5200b-bestcomm\0mpc52xx-bestcomm";
reg = <1200 80>;
interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
3 4 0 3 5 0 3 6 0 3 7 0
3 8 0 3 9 0 3 a 0 3 b 0
3 c 0 3 d 0 3 e 0 3 f 0>;
interrupt-parent = <500>;
};
xlb@1f00 {
compatible = "mpc5200b-xlb\0mpc52xx-xlb";
reg = <1f00 100>;
};
serial@2000 { // PSC1
device_type = "serial";
compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
port-number = <0>; // Logical port assignment
reg = <2000 100>;
interrupts = <2 1 0>;
interrupt-parent = <500>;
};
// PSC2 in spi mode example
spi@2200 { // PSC2
device_type = "spi";
compatible = "mpc5200b-psc-spi\0mpc52xx-psc-spi";
reg = <2200 100>;
interrupts = <2 2 0>;
interrupt-parent = <500>;
};
// PSC3 in CODEC mode example
i2s@2400 { // PSC3
device_type = "i2s";
compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s";
reg = <2400 100>;
interrupts = <2 3 0>;
interrupt-parent = <500>;
};
// PSC4 unconfigured
//serial@2600 { // PSC4
// device_type = "serial";
// compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
// reg = <2600 100>;
// interrupts = <2 b 0>;
// interrupt-parent = <500>;
//};
// PSC5 unconfigured
//serial@2800 { // PSC5
// device_type = "serial";
// compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart";
// reg = <2800 100>;
// interrupts = <2 c 0>;
// interrupt-parent = <500>;
//};
// PSC6 in AC97 mode example
ac97@2c00 { // PSC6
device_type = "ac97";
compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97";
reg = <2c00 100>;
interrupts = <2 4 0>;
interrupt-parent = <500>;
};
ethernet@3000 {
device_type = "network";
compatible = "mpc5200b-fec\0mpc52xx-fec";
reg = <3000 800>;
mac-address = [ 02 03 04 05 06 07 ]; // Bad!
interrupts = <2 5 0>;
interrupt-parent = <500>;
};
ata@3a00 {
device_type = "ata";
compatible = "mpc5200b-ata\0mpc52xx-ata";
reg = <3a00 100>;
interrupts = <2 7 0>;
interrupt-parent = <500>;
};
i2c@3d00 {
device_type = "i2c";
compatible = "mpc5200b-i2c\0mpc52xx-i2c";
reg = <3d00 40>;
interrupts = <2 f 0>;
interrupt-parent = <500>;
};
i2c@3d40 {
device_type = "i2c";
compatible = "mpc5200b-i2c\0mpc52xx-i2c";
reg = <3d40 40>;
interrupts = <2 10 0>;
interrupt-parent = <500>;
};
sram@8000 {
device_type = "sram";
compatible = "mpc5200b-sram\0mpc52xx-sram\0sram";
reg = <8000 4000>;
};
};
};

View File

@ -161,29 +161,41 @@
interrupt-map = <
/* IDSEL 0x11 */
0800 0 0 1 7400 24 0
0800 0 0 2 7400 25 0
0800 0 0 3 7400 26 0
0800 0 0 4 7400 27 0
0800 0 0 1 1180 24 0
0800 0 0 2 1180 25 0
0800 0 0 3 1180 26 0
0800 0 0 4 1180 27 0
/* IDSEL 0x12 */
1000 0 0 1 7400 25 0
1000 0 0 2 7400 26 0
1000 0 0 3 7400 27 0
1000 0 0 4 7400 24 0
1000 0 0 1 1180 25 0
1000 0 0 2 1180 26 0
1000 0 0 3 1180 27 0
1000 0 0 4 1180 24 0
/* IDSEL 0x13 */
1800 0 0 1 7400 26 0
1800 0 0 2 7400 27 0
1800 0 0 3 7400 24 0
1800 0 0 4 7400 25 0
1800 0 0 1 1180 26 0
1800 0 0 2 1180 27 0
1800 0 0 3 1180 24 0
1800 0 0 4 1180 25 0
/* IDSEL 0x14 */
2000 0 0 1 7400 27 0
2000 0 0 2 7400 24 0
2000 0 0 3 7400 25 0
2000 0 0 4 7400 26 0
2000 0 0 1 1180 27 0
2000 0 0 2 1180 24 0
2000 0 0 3 1180 25 0
2000 0 0 4 1180 26 0
>;
router@1180 {
linux,phandle = <1180>;
clock-frequency = <0>;
interrupt-controller;
device_type = "pic-router";
#address-cells = <0>;
#interrupt-cells = <2>;
built-in;
big-endian;
interrupts = <17 2>;
interrupt-parent = <7400>;
};
};
};

View File

@ -0,0 +1,880 @@
/*
* 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.
*
* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright Pantelis Antoniou 2006
* Copyright (C) IBM Corporation 2006
*
* Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
* Hollis Blanchard <hollisb@us.ibm.com>
* Mark A. Greer <mgreer@mvista.com>
* Paul Mackerras <paulus@samba.org>
*/
#include <string.h>
#include <stddef.h>
#include "flatdevtree.h"
#include "flatdevtree_env.h"
#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
/* Routines for keeping node ptrs returned by ft_find_device current */
/* First entry not used b/c it would return 0 and be taken as NULL/error */
static void *ft_node_add(struct ft_cxt *cxt, char *node)
{
unsigned int i;
for (i = 1; i < cxt->nodes_used; i++) /* already there? */
if (cxt->node_tbl[i] == node)
return (void *)i;
if (cxt->nodes_used < cxt->node_max) {
cxt->node_tbl[cxt->nodes_used] = node;
return (void *)cxt->nodes_used++;
}
return NULL;
}
static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
{
unsigned int i = (unsigned int)phandle;
if (i < cxt->nodes_used)
return cxt->node_tbl[i];
return NULL;
}
static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
{
unsigned int i;
if (shift == 0)
return;
for (i = 1; i < cxt->nodes_used; i++)
if (cxt->node_tbl[i] < addr)
cxt->node_tbl[i] += shift;
}
static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
{
unsigned int i;
if (shift == 0)
return;
for (i = 1; i < cxt->nodes_used; i++)
if (cxt->node_tbl[i] >= addr)
cxt->node_tbl[i] += shift;
}
/* Struct used to return info from ft_next() */
struct ft_atom {
u32 tag;
const char *name;
void *data;
u32 size;
};
/* Set ptrs to current one's info; return addr of next one */
static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
{
u32 sz;
if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
return NULL;
ret->tag = be32_to_cpu(*(u32 *) p);
p += 4;
switch (ret->tag) { /* Tag */
case OF_DT_BEGIN_NODE:
ret->name = p;
ret->data = (void *)(p - 4); /* start of node */
p += _ALIGN(strlen(p) + 1, 4);
break;
case OF_DT_PROP:
ret->size = sz = be32_to_cpu(*(u32 *) p);
ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
ret->data = (void *)(p + 8);
p += 8 + _ALIGN(sz, 4);
break;
case OF_DT_END_NODE:
case OF_DT_NOP:
break;
case OF_DT_END:
default:
p = NULL;
break;
}
return p;
}
#define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8)
#define EXPAND_INCR 1024 /* alloc this much extra when expanding */
/* See if the regions are in the standard order and non-overlapping */
static int ft_ordered(struct ft_cxt *cxt)
{
char *p = (char *)cxt->bph + HDR_SIZE;
enum ft_rgn_id r;
for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
if (p > cxt->rgn[r].start)
return 0;
p = cxt->rgn[r].start + cxt->rgn[r].size;
}
return p <= (char *)cxt->bph + cxt->max_size;
}
/* Copy the tree to a newly-allocated region and put things in order */
static int ft_reorder(struct ft_cxt *cxt, int nextra)
{
unsigned long tot;
enum ft_rgn_id r;
char *p, *pend;
int stroff;
tot = HDR_SIZE + EXPAND_INCR;
for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
tot += cxt->rgn[r].size;
if (nextra > 0)
tot += nextra;
tot = _ALIGN(tot, 8);
if (!cxt->realloc)
return 0;
p = cxt->realloc(NULL, tot);
if (!p)
return 0;
memcpy(p, cxt->bph, sizeof(struct boot_param_header));
/* offsets get fixed up later */
cxt->bph = (struct boot_param_header *)p;
cxt->max_size = tot;
pend = p + tot;
p += HDR_SIZE;
memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
cxt->rgn[FT_RSVMAP].start = p;
p += cxt->rgn[FT_RSVMAP].size;
memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
p - cxt->rgn[FT_STRUCT].start);
cxt->p += p - cxt->rgn[FT_STRUCT].start;
cxt->rgn[FT_STRUCT].start = p;
p = pend - cxt->rgn[FT_STRINGS].size;
memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
cxt->rgn[FT_STRINGS].start = p;
cxt->str_anchor = p + stroff;
cxt->isordered = 1;
return 1;
}
static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
{
if (r > FT_RSVMAP)
return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
return (char *)cxt->bph + HDR_SIZE;
}
static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
{
if (r < FT_STRINGS)
return cxt->rgn[r + 1].start;
return (char *)cxt->bph + cxt->max_size;
}
/*
* See if we can expand region rgn by nextra bytes by using up
* free space after or before the region.
*/
static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
int nextra)
{
char *p = *pp;
char *rgn_start, *rgn_end;
rgn_start = cxt->rgn[rgn].start;
rgn_end = rgn_start + cxt->rgn[rgn].size;
if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
/* move following stuff */
if (p < rgn_end) {
if (nextra < 0)
memmove(p, p - nextra, rgn_end - p + nextra);
else
memmove(p + nextra, p, rgn_end - p);
if (rgn == FT_STRUCT)
ft_node_update_after(cxt, p, nextra);
}
cxt->rgn[rgn].size += nextra;
if (rgn == FT_STRINGS)
/* assumes strings only added at beginning */
cxt->str_anchor += nextra;
return 1;
}
if (prev_end(cxt, rgn) <= rgn_start - nextra) {
/* move preceding stuff */
if (p > rgn_start) {
memmove(rgn_start - nextra, rgn_start, p - rgn_start);
if (rgn == FT_STRUCT)
ft_node_update_before(cxt, p, -nextra);
}
*p -= nextra;
cxt->rgn[rgn].start -= nextra;
cxt->rgn[rgn].size += nextra;
return 1;
}
return 0;
}
static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
int nextra)
{
unsigned long size, ssize, tot;
char *str, *next;
enum ft_rgn_id r;
if (!cxt->isordered && !ft_reorder(cxt, nextra))
return 0;
if (ft_shuffle(cxt, pp, rgn, nextra))
return 1;
/* See if there is space after the strings section */
ssize = cxt->rgn[FT_STRINGS].size;
if (cxt->rgn[FT_STRINGS].start + ssize
< (char *)cxt->bph + cxt->max_size) {
/* move strings up as far as possible */
str = (char *)cxt->bph + cxt->max_size - ssize;
cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
cxt->rgn[FT_STRINGS].start = str;
/* enough space now? */
if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
return 1;
}
/* how much total free space is there following this region? */
tot = 0;
for (r = rgn; r < FT_STRINGS; ++r) {
char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
tot += next_start(cxt, rgn) - r_end;
}
/* cast is to shut gcc up; we know nextra >= 0 */
if (tot < (unsigned int)nextra) {
/* have to reallocate */
char *newp, *new_start;
int shift;
if (!cxt->realloc)
return 0;
size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
newp = cxt->realloc(cxt->bph, size);
if (!newp)
return 0;
cxt->max_size = size;
shift = newp - (char *)cxt->bph;
if (shift) { /* realloc can return same addr */
cxt->bph = (struct boot_param_header *)newp;
ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
shift);
for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
new_start = cxt->rgn[r].start + shift;
cxt->rgn[r].start = new_start;
}
*pp += shift;
cxt->str_anchor += shift;
}
/* move strings up to the end */
str = newp + size - ssize;
cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
cxt->rgn[FT_STRINGS].start = str;
if (ft_shuffle(cxt, pp, rgn, nextra))
return 1;
}
/* must be FT_RSVMAP and we need to move FT_STRUCT up */
if (rgn == FT_RSVMAP) {
next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+ nextra;
ssize = cxt->rgn[FT_STRUCT].size;
if (next + ssize >= cxt->rgn[FT_STRINGS].start)
return 0; /* "can't happen" */
memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
cxt->rgn[FT_STRUCT].start = next;
if (ft_shuffle(cxt, pp, rgn, nextra))
return 1;
}
return 0; /* "can't happen" */
}
static void ft_put_word(struct ft_cxt *cxt, u32 v)
{
*(u32 *) cxt->p = cpu_to_be32(v);
cxt->p += 4;
}
static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
{
unsigned long sza = _ALIGN(sz, 4);
/* zero out the alignment gap if necessary */
if (sz < sza)
*(u32 *) (cxt->p + sza - 4) = 0;
/* copy in the data */
memcpy(cxt->p, data, sz);
cxt->p += sza;
}
int ft_begin_node(struct ft_cxt *cxt, const char *name)
{
unsigned long nlen = strlen(name) + 1;
unsigned long len = 8 + _ALIGN(nlen, 4);
if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
return -1;
ft_put_word(cxt, OF_DT_BEGIN_NODE);
ft_put_bin(cxt, name, strlen(name) + 1);
return 0;
}
void ft_end_node(struct ft_cxt *cxt)
{
ft_put_word(cxt, OF_DT_END_NODE);
}
void ft_nop(struct ft_cxt *cxt)
{
if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
ft_put_word(cxt, OF_DT_NOP);
}
#define NO_STRING 0x7fffffff
static int lookup_string(struct ft_cxt *cxt, const char *name)
{
char *p, *end;
p = cxt->rgn[FT_STRINGS].start;
end = p + cxt->rgn[FT_STRINGS].size;
while (p < end) {
if (strcmp(p, (char *)name) == 0)
return p - cxt->str_anchor;
p += strlen(p) + 1;
}
return NO_STRING;
}
/* lookup string and insert if not found */
static int map_string(struct ft_cxt *cxt, const char *name)
{
int off;
char *p;
off = lookup_string(cxt, name);
if (off != NO_STRING)
return off;
p = cxt->rgn[FT_STRINGS].start;
if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
return NO_STRING;
strcpy(p, name);
return p - cxt->str_anchor;
}
int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
unsigned int sz)
{
int off, len;
off = lookup_string(cxt, name);
if (off == NO_STRING)
return -1;
len = 12 + _ALIGN(sz, 4);
if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
return -1;
ft_put_word(cxt, OF_DT_PROP);
ft_put_word(cxt, sz);
ft_put_word(cxt, off);
ft_put_bin(cxt, data, sz);
return 0;
}
int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
{
return ft_prop(cxt, name, str, strlen(str) + 1);
}
int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
{
u32 v = cpu_to_be32((u32) val);
return ft_prop(cxt, name, &v, 4);
}
/* Calculate the size of the reserved map */
static unsigned long rsvmap_size(struct ft_cxt *cxt)
{
struct ft_reserve *res;
res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
while (res->start || res->len)
++res;
return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
}
/* Calculate the size of the struct region by stepping through it */
static unsigned long struct_size(struct ft_cxt *cxt)
{
char *p = cxt->rgn[FT_STRUCT].start;
char *next;
struct ft_atom atom;
/* make check in ft_next happy */
if (cxt->rgn[FT_STRUCT].size == 0)
cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
while ((next = ft_next(cxt, p, &atom)) != NULL)
p = next;
return p + 4 - cxt->rgn[FT_STRUCT].start;
}
/* add `adj' on to all string offset values in the struct area */
static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
{
char *p = cxt->rgn[FT_STRUCT].start;
char *next;
struct ft_atom atom;
int off;
while ((next = ft_next(cxt, p, &atom)) != NULL) {
if (atom.tag == OF_DT_PROP) {
off = be32_to_cpu(*(u32 *) (p + 8));
*(u32 *) (p + 8) = cpu_to_be32(off + adj);
}
p = next;
}
}
/* start construction of the flat OF tree from scratch */
void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
void *(*realloc_fn) (void *, unsigned long))
{
struct boot_param_header *bph = blob;
char *p;
struct ft_reserve *pres;
/* clear the cxt */
memset(cxt, 0, sizeof(*cxt));
cxt->bph = bph;
cxt->max_size = max_size;
cxt->realloc = realloc_fn;
cxt->isordered = 1;
/* zero everything in the header area */
memset(bph, 0, sizeof(*bph));
bph->magic = cpu_to_be32(OF_DT_HEADER);
bph->version = cpu_to_be32(0x10);
bph->last_comp_version = cpu_to_be32(0x10);
/* start pointers */
cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
pres = (struct ft_reserve *)p;
cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
cxt->rgn[FT_STRUCT].size = 4;
cxt->rgn[FT_STRINGS].start = blob + max_size;
cxt->rgn[FT_STRINGS].size = 0;
/* init rsvmap and struct */
pres->start = 0;
pres->len = 0;
*(u32 *) p = cpu_to_be32(OF_DT_END);
cxt->str_anchor = blob;
}
/* open up an existing blob to be examined or modified */
int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
unsigned int max_find_device,
void *(*realloc_fn) (void *, unsigned long))
{
struct boot_param_header *bph = blob;
/* can't cope with version < 16 */
if (be32_to_cpu(bph->version) < 16)
return -1;
/* clear the cxt */
memset(cxt, 0, sizeof(*cxt));
/* alloc node_tbl to track node ptrs returned by ft_find_device */
++max_find_device;
cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
if (!cxt->node_tbl)
return -1;
memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
cxt->node_max = max_find_device;
cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */
cxt->bph = bph;
cxt->max_size = max_size;
cxt->realloc = realloc_fn;
cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
cxt->rgn[FT_STRUCT].size = struct_size(cxt);
cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
/* Leave as '0' to force first ft_make_space call to do a ft_reorder
* and move dt to an area allocated by realloc.
cxt->isordered = ft_ordered(cxt);
*/
cxt->p = cxt->rgn[FT_STRUCT].start;
cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
return 0;
}
/* add a reserver physical area to the rsvmap */
int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
{
char *p;
struct ft_reserve *pres;
p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
- sizeof(struct ft_reserve);
if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
return -1;
pres = (struct ft_reserve *)p;
pres->start = cpu_to_be64(physaddr);
pres->len = cpu_to_be64(size);
return 0;
}
void ft_begin_tree(struct ft_cxt *cxt)
{
cxt->p = cxt->rgn[FT_STRUCT].start;
}
void ft_end_tree(struct ft_cxt *cxt)
{
struct boot_param_header *bph = cxt->bph;
char *p, *oldstr, *str, *endp;
unsigned long ssize;
int adj;
if (!cxt->isordered)
return; /* we haven't touched anything */
/* adjust string offsets */
oldstr = cxt->rgn[FT_STRINGS].start;
adj = cxt->str_anchor - oldstr;
if (adj)
adjust_string_offsets(cxt, adj);
/* make strings end on 8-byte boundary */
ssize = cxt->rgn[FT_STRINGS].size;
endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
+ cxt->rgn[FT_STRUCT].size + ssize, 8);
str = endp - ssize;
/* move strings down to end of structs */
memmove(str, oldstr, ssize);
cxt->str_anchor = str;
cxt->rgn[FT_STRINGS].start = str;
/* fill in header fields */
p = (char *)bph;
bph->totalsize = cpu_to_be32(endp - p);
bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
bph->dt_strings_size = cpu_to_be32(ssize);
}
void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
{
char *node;
/* require absolute path */
if (srch_path[0] != '/')
return NULL;
node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
return ft_node_add(cxt, node);
}
void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
{
struct ft_atom atom;
char *p;
const char *cp, *q;
int cl;
int depth = -1;
int dmatch = 0;
const char *path_comp[FT_MAX_DEPTH];
cp = srch_path;
cl = 0;
p = top;
while ((p = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
++depth;
if (depth != dmatch)
break;
cxt->genealogy[depth] = atom.data;
cxt->genealogy[depth + 1] = NULL;
if (depth && !(strncmp(atom.name, cp, cl) == 0
&& (atom.name[cl] == '/'
|| atom.name[cl] == '\0'
|| atom.name[cl] == '@')))
break;
path_comp[dmatch] = cp;
/* it matches so far, advance to next path component */
cp += cl;
/* skip slashes */
while (*cp == '/')
++cp;
/* we're done if this is the end of the string */
if (*cp == 0)
return atom.data;
/* look for end of this component */
q = strchr(cp, '/');
if (q)
cl = q - cp;
else
cl = strlen(cp);
++dmatch;
break;
case OF_DT_END_NODE:
if (depth == 0)
return NULL;
if (dmatch > depth) {
--dmatch;
cl = cp - path_comp[dmatch] - 1;
cp = path_comp[dmatch];
while (cl > 0 && cp[cl - 1] == '/')
--cl;
}
--depth;
break;
}
}
return NULL;
}
void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
{
void *node;
int d;
struct ft_atom atom;
char *p;
node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return NULL;
for (d = 0; cxt->genealogy[d] != NULL; ++d)
if (cxt->genealogy[d] == node)
return cxt->genealogy[d > 0 ? d - 1 : 0];
/* have to do it the hard way... */
p = cxt->rgn[FT_STRUCT].start;
d = 0;
while ((p = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
cxt->genealogy[d] = atom.data;
if (node == atom.data) {
/* found it */
cxt->genealogy[d + 1] = NULL;
return d > 0 ? cxt->genealogy[d - 1] : node;
}
++d;
break;
case OF_DT_END_NODE:
--d;
break;
}
}
return NULL;
}
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
void *buf, const unsigned int buflen)
{
struct ft_atom atom;
void *node;
char *p;
int depth;
unsigned int size;
node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return -1;
depth = 0;
p = (char *)node;
while ((p = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
++depth;
break;
case OF_DT_PROP:
if ((depth != 1) || strcmp(atom.name, propname))
break;
size = min(atom.size, buflen);
memcpy(buf, atom.data, size);
return atom.size;
case OF_DT_END_NODE:
if (--depth <= 0)
return -1;
}
}
return -1;
}
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
const void *buf, const unsigned int buflen)
{
struct ft_atom atom;
void *node;
char *p, *next;
int nextra, depth;
node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return -1;
depth = 0;
p = node;
while ((next = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
++depth;
break;
case OF_DT_END_NODE:
if (--depth > 0)
break;
/* haven't found the property, insert here */
cxt->p = p;
return ft_prop(cxt, propname, buf, buflen);
case OF_DT_PROP:
if ((depth != 1) || strcmp(atom.name, propname))
break;
/* found an existing property, overwrite it */
nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
cxt->p = atom.data;
if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
nextra))
return -1;
*(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
ft_put_bin(cxt, buf, buflen);
return 0;
}
p = next;
}
return -1;
}
int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
{
struct ft_atom atom;
void *node;
char *p, *next;
int size;
node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return -1;
p = node;
while ((next = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
case OF_DT_END_NODE:
return -1;
case OF_DT_PROP:
if (strcmp(atom.name, propname))
break;
/* found the property, remove it */
size = 12 + -_ALIGN(atom.size, 4);
cxt->p = p;
if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
return -1;
return 0;
}
p = next;
}
return -1;
}
void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
{
struct ft_atom atom;
char *p, *next;
int depth = 0;
p = cxt->rgn[FT_STRUCT].start;
while ((next = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
++depth;
if (depth == 1 && strcmp(atom.name, path) == 0)
/* duplicate node path, return error */
return NULL;
break;
case OF_DT_END_NODE:
--depth;
if (depth > 0)
break;
/* end of node, insert here */
cxt->p = p;
ft_begin_node(cxt, path);
ft_end_node(cxt);
return p;
}
p = next;
}
return NULL;
}

View File

@ -17,7 +17,7 @@
#ifndef FLATDEVTREE_H
#define FLATDEVTREE_H
#include "types.h"
#include "flatdevtree_env.h"
/* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */
@ -43,4 +43,64 @@ struct boot_param_header {
u32 dt_strings_size; /* size of the DT strings block */
};
struct ft_reserve {
u64 start;
u64 len;
};
struct ft_region {
char *start;
unsigned long size;
};
enum ft_rgn_id {
FT_RSVMAP,
FT_STRUCT,
FT_STRINGS,
FT_N_REGION
};
#define FT_MAX_DEPTH 50
struct ft_cxt {
struct boot_param_header *bph;
int max_size; /* maximum size of tree */
int isordered; /* everything in standard order */
void *(*realloc)(void *, unsigned long);
char *str_anchor;
char *p; /* current insertion point in structs */
struct ft_region rgn[FT_N_REGION];
void *genealogy[FT_MAX_DEPTH+1];
char **node_tbl;
unsigned int node_max;
unsigned int nodes_used;
};
int ft_begin_node(struct ft_cxt *cxt, const char *name);
void ft_end_node(struct ft_cxt *cxt);
void ft_begin_tree(struct ft_cxt *cxt);
void ft_end_tree(struct ft_cxt *cxt);
void ft_nop(struct ft_cxt *cxt);
int ft_prop(struct ft_cxt *cxt, const char *name,
const void *data, unsigned int sz);
int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
void *(*realloc_fn)(void *, unsigned long));
int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
unsigned int max_find_device,
void *(*realloc_fn)(void *, unsigned long));
int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
void ft_dump_blob(const void *bphp);
void ft_merge_blob(struct ft_cxt *cxt, void *blob);
void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
void *buf, const unsigned int buflen);
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
const void *buf, const unsigned int buflen);
#endif /* FLATDEVTREE_H */

View File

@ -0,0 +1,47 @@
/*
* This file adds the header file glue so that the shared files
* flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
*
* strncmp & strchr copied from <file:lib/strings.c>
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Maintained by: Mark A. Greer <mgreer@mvista.com>
*/
#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
#define _PPC_BOOT_FLATDEVTREE_ENV_H_
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "string.h"
#include "stdio.h"
#include "ops.h"
#define be16_to_cpu(x) (x)
#define cpu_to_be16(x) (x)
#define be32_to_cpu(x) (x)
#define cpu_to_be32(x) (x)
#define be64_to_cpu(x) (x)
#define cpu_to_be64(x) (x)
static inline int strncmp(const char *cs, const char *ct, size_t count)
{
signed char __res = 0;
while (count) {
if ((__res = *cs - *ct++) != 0 || !*cs++)
break;
count--;
}
return __res;
}
static inline char *strchr(const char *s, int c)
{
for (; *s != (char)c; ++s)
if (*s == '\0')
return NULL;
return (char *)s;
}
#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */

View File

@ -0,0 +1,51 @@
/*
* This file does the necessary interface mapping between the bootwrapper
* device tree operations and the interface provided by shared source
* files flatdevicetree.[ch].
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <stddef.h>
#include "flatdevtree.h"
#include "ops.h"
static struct ft_cxt cxt;
static void *ft_finddevice(const char *name)
{
return ft_find_device(&cxt, name);
}
static int ft_getprop(const void *phandle, const char *propname, void *buf,
const int buflen)
{
return ft_get_prop(&cxt, phandle, propname, buf, buflen);
}
static int ft_setprop(const void *phandle, const char *propname,
const void *buf, const int buflen)
{
return ft_set_prop(&cxt, phandle, propname, buf, buflen);
}
static unsigned long ft_finalize(void)
{
ft_end_tree(&cxt);
return (unsigned long)cxt.bph;
}
int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
{
dt_ops.finddevice = ft_finddevice;
dt_ops.getprop = ft_getprop;
dt_ops.setprop = ft_setprop;
dt_ops.finalize = ft_finalize;
return ft_open(&cxt, dt_blob, max_size, max_find_device,
platform_ops.realloc);
}

53
arch/powerpc/boot/io.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef _IO_H
#define __IO_H
/*
* Low-level I/O routines.
*
* Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
*/
static inline int in_8(const volatile unsigned char *addr)
{
int ret;
__asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "m" (*addr));
return ret;
}
static inline void out_8(volatile unsigned char *addr, int val)
{
__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}
static inline unsigned in_le32(const volatile unsigned *addr)
{
unsigned ret;
__asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "r" (addr), "m" (*addr));
return ret;
}
static inline unsigned in_be32(const volatile unsigned *addr)
{
unsigned ret;
__asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
: "=r" (ret) : "m" (*addr));
return ret;
}
static inline void out_le32(volatile unsigned *addr, int val)
{
__asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
: "r" (val), "r" (addr));
}
static inline void out_be32(volatile unsigned *addr, int val)
{
__asm__ __volatile__("stw%U0%X0 %1,%0; sync"
: "=m" (*addr) : "r" (val));
}
#endif /* _IO_H */

View File

@ -27,6 +27,8 @@ extern char _vmlinux_start[];
extern char _vmlinux_end[];
extern char _initrd_start[];
extern char _initrd_end[];
extern char _dtb_start[];
extern char _dtb_end[];
struct addr_range {
unsigned long addr;
@ -167,7 +169,7 @@ static int is_elf32(void *hdr)
return 1;
}
static void prep_kernel(unsigned long *a1, unsigned long *a2)
static void prep_kernel(unsigned long a1, unsigned long a2)
{
int len;
@ -203,11 +205,14 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
}
/*
* Now we try to alloc memory for the initrd (and copy it there)
* Now find the initrd
*
* First see if we have an image attached to us. If so
* allocate memory for it and copy it there.
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
if (initrd.size > 0) {
printf("Allocating 0x%lx bytes for initrd ...\n\r",
initrd.size);
initrd.addr = (unsigned long)malloc((u32)initrd.size);
@ -216,8 +221,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
"ramdisk !\n\r");
exit();
}
*a1 = initrd.addr;
*a2 = initrd.size;
printf("initial ramdisk moving 0x%lx <- 0x%lx "
"(0x%lx bytes)\n\r", initrd.addr,
(unsigned long)_initrd_start, initrd.size);
@ -225,6 +228,12 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
initrd.size);
printf("initrd head: 0x%lx\n\r",
*((unsigned long *)initrd.addr));
} else if (a2 != 0) {
/* Otherwise, see if yaboot or another loader gave us an initrd */
initrd.addr = a1;
initrd.memsize = initrd.size = a2;
printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r",
initrd.addr, initrd.size);
}
/* Eventually gunzip the kernel */
@ -250,10 +259,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2)
flush_cache((void *)vmlinux.addr, vmlinux.size);
}
void __attribute__ ((weak)) ft_init(void *dt_blob)
{
}
/* 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.
@ -285,36 +290,22 @@ static void set_cmdline(char *buf)
setprop(devp, "bootargs", buf, strlen(buf) + 1);
}
/* Section where ft can be tacked on after zImage is built */
union blobspace {
struct boot_param_header hdr;
char space[8*1024];
} dt_blob __attribute__((__section__("__builtin_ft")));
struct platform_ops platform_ops;
struct dt_ops dt_ops;
struct console_ops console_ops;
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
{
int have_dt = 0;
kernel_entry_t kentry;
char cmdline[COMMAND_LINE_SIZE];
unsigned long ft_addr = 0;
memset(__bss_start, 0, _end - __bss_start);
memset(&platform_ops, 0, sizeof(platform_ops));
memset(&dt_ops, 0, sizeof(dt_ops));
memset(&console_ops, 0, sizeof(console_ops));
/* Override the dt_ops and device tree if there was an flat dev
* tree attached to the zImage.
*/
if (dt_blob.hdr.magic == OF_DT_HEADER) {
have_dt = 1;
ft_init(&dt_blob);
}
if (platform_init(promptr))
if (platform_init(promptr, _dtb_start, _dtb_end))
exit();
if (console_ops.open && (console_ops.open() < 0))
exit();
@ -324,7 +315,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
_start, sp);
prep_kernel(&a1, &a2);
prep_kernel(a1, a2);
/* If cmdline came from zimage wrapper or if we can edit the one
* in the dt, print it out and edit it, if possible.
@ -338,15 +329,23 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
set_cmdline(cmdline);
}
printf("Finalizing device tree...");
if (dt_ops.finalize)
ft_addr = dt_ops.finalize();
if (ft_addr)
printf(" flat tree at 0x%lx\n\r", ft_addr);
else
printf(" using OF tree (promptr=%p)\n\r", promptr);
if (console_ops.close)
console_ops.close();
kentry = (kernel_entry_t) vmlinux.addr;
if (have_dt)
kentry(dt_ops.ft_addr(), 0, NULL);
if (ft_addr)
kentry(ft_addr, 0, NULL);
else
/* XXX initrd addr/size should be passed in properties */
kentry(a1, a2, promptr);
kentry(initrd.addr, initrd.size, promptr);
/* console closed so printf below may not work */
printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");

152
arch/powerpc/boot/mktree.c Normal file
View File

@ -0,0 +1,152 @@
/*
* Makes a tree bootable image for IBM Evaluation boards.
* Basically, just take a zImage, skip the ELF header, and stuff
* a 32 byte header on the front.
*
* We use htonl, which is a network macro, to make sure we're doing
* The Right Thing on an LE machine. It's non-obvious, but it should
* work on anything BSD'ish.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netinet/in.h>
#ifdef __sun__
#include <inttypes.h>
#else
#include <stdint.h>
#endif
/* This gets tacked on the front of the image. There are also a few
* bytes allocated after the _start label used by the boot rom (see
* head.S for details).
*/
typedef struct boot_block {
uint32_t bb_magic; /* 0x0052504F */
uint32_t bb_dest; /* Target address of the image */
uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
uint32_t bb_debug_flag; /* Run debugger or image after load */
uint32_t bb_entry_point; /* The image address to start */
uint32_t bb_checksum; /* 32 bit checksum including header */
uint32_t reserved[2];
} boot_block_t;
#define IMGBLK 512
char tmpbuf[IMGBLK];
int main(int argc, char *argv[])
{
int in_fd, out_fd;
int nblks, i;
uint cksum, *cp;
struct stat st;
boot_block_t bt;
if (argc < 3) {
fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]);
exit(1);
}
if (stat(argv[1], &st) < 0) {
perror("stat");
exit(2);
}
nblks = (st.st_size + IMGBLK) / IMGBLK;
bt.bb_magic = htonl(0x0052504F);
/* If we have the optional entry point parameter, use it */
if (argc == 4)
bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0));
else
bt.bb_dest = bt.bb_entry_point = htonl(0x500000);
/* We know these from the linker command.
* ...and then move it up into memory a little more so the
* relocation can happen.
*/
bt.bb_num_512blocks = htonl(nblks);
bt.bb_debug_flag = 0;
bt.bb_checksum = 0;
/* To be neat and tidy :-).
*/
bt.reserved[0] = 0;
bt.reserved[1] = 0;
if ((in_fd = open(argv[1], O_RDONLY)) < 0) {
perror("zImage open");
exit(3);
}
if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
perror("bootfile open");
exit(3);
}
cksum = 0;
cp = (void *)&bt;
for (i=0; i<sizeof(bt)/sizeof(uint); i++)
cksum += *cp++;
/* Assume zImage is an ELF file, and skip the 64K header.
*/
if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) {
fprintf(stderr, "%s is too small to be an ELF image\n",
argv[1]);
exit(4);
}
if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) {
fprintf(stderr, "%s is not an ELF image\n", argv[1]);
exit(4);
}
if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) {
fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]);
exit(4);
}
nblks -= (64 * 1024) / IMGBLK;
/* And away we go......
*/
if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
perror("boot-image write");
exit(5);
}
while (nblks-- > 0) {
if (read(in_fd, tmpbuf, IMGBLK) < 0) {
perror("zImage read");
exit(5);
}
cp = (uint *)tmpbuf;
for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++)
cksum += *cp++;
if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) {
perror("boot-image write");
exit(5);
}
}
/* rewrite the header with the computed checksum.
*/
bt.bb_checksum = htonl(cksum);
if (lseek(out_fd, 0, SEEK_SET) < 0) {
perror("rewrite seek");
exit(1);
}
if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) {
perror("boot-image rewrite");
exit(1);
}
exit(0);
}

View File

@ -0,0 +1,74 @@
/*
* 16550 serial console support.
*
* Original copied from <file:arch/ppc/boot/common/ns16550.c>
* (which had no copyright)
* Modifications: 2006 (c) MontaVista Software, Inc.
*
* Modified by: Mark A. Greer <mgreer@mvista.com>
*/
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "string.h"
#include "stdio.h"
#include "io.h"
#include "ops.h"
#define UART_DLL 0 /* Out: Divisor Latch Low */
#define UART_DLM 1 /* Out: Divisor Latch High */
#define UART_FCR 2 /* Out: FIFO Control Register */
#define UART_LCR 3 /* Out: Line Control Register */
#define UART_MCR 4 /* Out: Modem Control Register */
#define UART_LSR 5 /* In: Line Status Register */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_DR 0x01 /* Receiver data ready */
#define UART_MSR 6 /* In: Modem Status Register */
#define UART_SCR 7 /* I/O: Scratch Register */
static unsigned char *reg_base;
static u32 reg_shift;
static int ns16550_open(void)
{
out_8(reg_base + (UART_FCR << reg_shift), 0x06);
return 0;
}
static void ns16550_putc(unsigned char c)
{
while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
out_8(reg_base, c);
}
static unsigned char ns16550_getc(void)
{
while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
return in_8(reg_base);
}
static u8 ns16550_tstc(void)
{
return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
}
int ns16550_console_init(void *devp, struct serial_console_data *scdp)
{
int n;
n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
if (n != sizeof(reg_base))
return -1;
n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
if (n != sizeof(reg_shift))
reg_shift = 0;
scdp->open = ns16550_open;
scdp->putc = ns16550_putc;
scdp->getc = ns16550_getc;
scdp->tstc = ns16550_tstc;
scdp->close = NULL;
return 0;
}

View File

@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len)
call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
int platform_init(void *promptr)
int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
{
platform_ops.fixups = NULL;
platform_ops.image_hdr = of_image_hdr;
platform_ops.malloc = of_try_claim;
platform_ops.free = NULL;
platform_ops.exit = of_exit;
dt_ops.finddevice = of_finddevice;
dt_ops.getprop = of_getprop;
dt_ops.setprop = of_setprop;
dt_ops.translate_addr = NULL;
console_ops.open = of_console_open;
console_ops.write = of_console_write;
console_ops.edit_cmdline = NULL;
console_ops.close = NULL;
console_ops.data = NULL;
prom = (int (*)(void *))promptr;
return 0;

View File

@ -22,7 +22,8 @@ struct platform_ops {
void (*fixups)(void);
void (*image_hdr)(const void *);
void * (*malloc)(u32 size);
void (*free)(void *ptr, u32 size);
void (*free)(void *ptr);
void * (*realloc)(void *ptr, unsigned long size);
void (*exit)(void);
};
extern struct platform_ops platform_ops;
@ -30,13 +31,11 @@ extern struct platform_ops platform_ops;
/* Device Tree operations */
struct dt_ops {
void * (*finddevice)(const char *name);
int (*getprop)(const void *node, const char *name, void *buf,
int (*getprop)(const void *phandle, const char *name, void *buf,
const int buflen);
int (*setprop)(const void *node, const char *name,
int (*setprop)(const void *phandle, const char *name,
const void *buf, const int buflen);
u64 (*translate_addr)(const char *path, const u32 *in_addr,
const u32 addr_len);
unsigned long (*ft_addr)(void);
unsigned long (*finalize)(void);
};
extern struct dt_ops dt_ops;
@ -59,10 +58,13 @@ struct serial_console_data {
void (*close)(void);
};
extern int platform_init(void *promptr);
extern void simple_alloc_init(void);
extern void ft_init(void *dt_blob);
extern int serial_console_init(void);
int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
int serial_console_init(void);
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
u32 max_allocs);
static inline void *finddevice(const char *name)
{
@ -84,10 +86,10 @@ static inline void *malloc(u32 size)
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
}
static inline void free(void *ptr, u32 size)
static inline void free(void *ptr)
{
if (platform_ops.free)
platform_ops.free(ptr, size);
platform_ops.free(ptr);
}
static inline void exit(void)

142
arch/powerpc/boot/serial.c Normal file
View File

@ -0,0 +1,142 @@
/*
* Generic serial console support
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
* and was written by Matt Porter <mporter@kernel.crashing.org>.
*
* 2001,2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "string.h"
#include "stdio.h"
#include "io.h"
#include "ops.h"
extern void udelay(long delay);
static int serial_open(void)
{
struct serial_console_data *scdp = console_ops.data;
return scdp->open();
}
static void serial_write(char *buf, int len)
{
struct serial_console_data *scdp = console_ops.data;
while (*buf != '\0')
scdp->putc(*buf++);
}
static void serial_edit_cmdline(char *buf, int len)
{
int timer = 0, count;
char ch, *cp;
struct serial_console_data *scdp = console_ops.data;
cp = buf;
count = strlen(buf);
cp = &buf[count];
count++;
while (timer++ < 5*1000) {
if (scdp->tstc()) {
while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
/* Test for backspace/delete */
if ((ch == '\b') || (ch == '\177')) {
if (cp != buf) {
cp--;
count--;
printf("\b \b");
}
/* Test for ^x/^u (and wipe the line) */
} else if ((ch == '\030') || (ch == '\025')) {
while (cp != buf) {
cp--;
count--;
printf("\b \b");
}
} else if (count < len) {
*cp++ = ch;
count++;
scdp->putc(ch);
}
}
break; /* Exit 'timer' loop */
}
udelay(1000); /* 1 msec */
}
*cp = 0;
}
static void serial_close(void)
{
struct serial_console_data *scdp = console_ops.data;
if (scdp->close)
scdp->close();
}
static void *serial_get_stdout_devp(void)
{
void *devp;
char devtype[MAX_PROP_LEN];
char path[MAX_PATH_LEN];
devp = finddevice("/chosen");
if (devp == NULL)
goto err_out;
if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
devp = finddevice(path);
if (devp == NULL)
goto err_out;
if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
&& !strcmp(devtype, "serial"))
return devp;
}
err_out:
return NULL;
}
static struct serial_console_data serial_cd;
/* Node's "compatible" property determines which serial driver to use */
int serial_console_init(void)
{
void *devp;
int rc = -1;
char compat[MAX_PROP_LEN];
devp = serial_get_stdout_devp();
if (devp == NULL)
goto err_out;
if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
goto err_out;
if (!strcmp(compat, "ns16550"))
rc = ns16550_console_init(devp, &serial_cd);
/* Add other serial console driver calls here */
if (!rc) {
console_ops.open = serial_open;
console_ops.write = serial_write;
console_ops.edit_cmdline = serial_edit_cmdline;
console_ops.close = serial_close;
console_ops.data = &serial_cd;
return 0;
}
err_out:
return -1;
}

View File

@ -0,0 +1,149 @@
/*
* Implement primitive realloc(3) functionality.
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 2006 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <stddef.h>
#include "types.h"
#include "page.h"
#include "string.h"
#include "ops.h"
#define ENTRY_BEEN_USED 0x01
#define ENTRY_IN_USE 0x02
static struct alloc_info {
u32 flags;
u32 base;
u32 size;
} *alloc_tbl;
static u32 tbl_entries;
static u32 alloc_min;
static u32 next_base;
static u32 space_left;
/*
* First time an entry is used, its base and size are set.
* An entry can be freed and re-malloc'd but its base & size don't change.
* Should be smart enough for needs of bootwrapper.
*/
static void *simple_malloc(u32 size)
{
u32 i;
struct alloc_info *p = alloc_tbl;
if (size == 0)
goto err_out;
size = _ALIGN_UP(size, alloc_min);
for (i=0; i<tbl_entries; i++, p++)
if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
if (size <= space_left) {
p->base = next_base;
p->size = size;
p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
next_base += size;
space_left -= size;
return (void *)p->base;
}
goto err_out; /* not enough space left */
}
/* reuse an entry keeping same base & size */
else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
p->flags |= ENTRY_IN_USE;
return (void *)p->base;
}
err_out:
return NULL;
}
static struct alloc_info *simple_find_entry(void *ptr)
{
u32 i;
struct alloc_info *p = alloc_tbl;
for (i=0; i<tbl_entries; i++,p++) {
if (!(p->flags & ENTRY_BEEN_USED))
break;
if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
return p;
}
return NULL;
}
static void simple_free(void *ptr)
{
struct alloc_info *p = simple_find_entry(ptr);
if (p != NULL)
p->flags &= ~ENTRY_IN_USE;
}
/*
* Change size of area pointed to by 'ptr' to 'size'.
* If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free().
* 'ptr' must be NULL or a pointer to a non-freed area previously returned by
* simple_realloc() or simple_malloc().
*/
static void *simple_realloc(void *ptr, unsigned long size)
{
struct alloc_info *p;
void *new;
if (size == 0) {
simple_free(ptr);
return NULL;
}
if (ptr == NULL)
return simple_malloc(size);
p = simple_find_entry(ptr);
if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
return NULL;
if (size <= p->size) /* fits in current block */
return ptr;
new = simple_malloc(size);
memcpy(new, ptr, p->size);
simple_free(ptr);
return new;
}
/*
* Returns addr of first byte after heap so caller can see if it took
* too much space. If so, change args & try again.
*/
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
u32 max_allocs)
{
u32 heap_base, tbl_size;
heap_size = _ALIGN_UP(heap_size, granularity);
alloc_min = granularity;
tbl_entries = max_allocs;
tbl_size = tbl_entries * sizeof(struct alloc_info);
alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
memset(alloc_tbl, 0, tbl_size);
heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
next_base = heap_base;
space_left = heap_size;
platform_ops.malloc = simple_malloc;
platform_ops.free = simple_free;
platform_ops.realloc = simple_realloc;
return (void *)(heap_base + heap_size);
}

View File

@ -320,6 +320,7 @@ printf(const char *fmt, ...)
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
console_ops.write(sprint_buf, n);
if (console_ops.write)
console_ops.write(sprint_buf, n);
return n;
}

88
arch/powerpc/boot/util.S Normal file
View File

@ -0,0 +1,88 @@
/*
* Copied from <file:arch/powerpc/kernel/misc_32.S>
*
* This file contains miscellaneous low-level functions.
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
*
* kexec bits:
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
*
* 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 "ppc_asm.h"
#define SPRN_PVR 0x11F /* Processor Version Register */
.text
/* udelay (on non-601 processors) needs to know the period of the
* timebase in nanoseconds. This used to be hardcoded to be 60ns
* (period of 66MHz/4). Now a variable is used that is initialized to
* 60 for backward compatibility, but it can be overridden as necessary
* with code something like this:
* extern unsigned long timebase_period_ns;
* timebase_period_ns = 1000000000 / bd->bi_tbfreq;
*/
.data
.globl timebase_period_ns
timebase_period_ns:
.long 60
.text
/*
* Delay for a number of microseconds
*/
.globl udelay
udelay:
mfspr r4,SPRN_PVR
srwi r4,r4,16
cmpwi 0,r4,1 /* 601 ? */
bne .udelay_not_601
00: li r0,86 /* Instructions / microsecond? */
mtctr r0
10: addi r0,r0,0 /* NOP */
bdnz 10b
subic. r3,r3,1
bne 00b
blr
.udelay_not_601:
mulli r4,r3,1000 /* nanoseconds */
/* Change r4 to be the number of ticks using:
* (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
* timebase_period_ns defaults to 60 (16.6MHz) */
mflr r5
bl 0f
0: mflr r6
mtlr r5
lis r5,0b@ha
addi r5,r5,0b@l
subf r5,r5,r6 /* In case we're relocated */
addis r5,r5,timebase_period_ns@ha
lwz r5,timebase_period_ns@l(r5)
add r4,r4,r5
addi r4,r4,-1
divw r4,r4,r5 /* BUS ticks */
1: mftbu r5
mftb r6
mftbu r7
cmpw 0,r5,r7
bne 1b /* Get [synced] base time */
addc r9,r6,r4 /* Compute end time */
addze r8,r5
2: mftbu r5
cmpw 0,r5,r8
blt 2b
bgt 3f
mftb r6
cmpw 0,r6,r9
blt 2b
3: blr

View File

@ -184,6 +184,9 @@ fi
if [ -n "$dtb" ]; then
addsec $tmp "$dtb" .kernel:dtb
if [ -n "$dts" ]; then
rm $dtb
fi
fi
if [ "$platform" != "miboot" ]; then

View File

@ -21,6 +21,10 @@ SECTIONS
*(.got2)
__got2_end = .;
_dtb_start = .;
*(.kernel:dtb)
_dtb_end = .;
_vmlinux_start = .;
*(.kernel:vmlinux.strip)
_vmlinux_end = .;

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.18
# Wed Oct 4 15:30:50 2006
# Linux kernel version: 2.6.19-rc6
# Wed Nov 22 15:33:04 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@ -32,6 +32,10 @@ CONFIG_AUDIT_ARCH=y
CONFIG_POWER3=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_NATIVE is not set
CONFIG_PPC_DCR_MMIO=y
CONFIG_PPC_DCR=y
CONFIG_PPC_OF_PLATFORM_PCI=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
@ -67,7 +71,7 @@ CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@ -131,6 +135,7 @@ CONFIG_PPC_CELL=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_PPC_PS3=y
# CONFIG_U3_DART is not set
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
@ -139,9 +144,23 @@ CONFIG_RTAS_FLASH=y
CONFIG_MMIO_NVRAM=y
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_CPU_FREQ is not set
CONFIG_PPC_INDIRECT_IO=y
CONFIG_GENERIC_IOMAP=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CONFIG_CPU_FREQ_PMAC64 is not set
# CONFIG_WANT_EARLY_SERIAL is not set
# CONFIG_MPIC is not set
CONFIG_MPIC=y
#
# Cell Broadband Engine options
@ -149,6 +168,15 @@ CONFIG_MMIO_NVRAM=y
CONFIG_SPU_FS=m
CONFIG_SPU_BASE=y
CONFIG_CBE_RAS=y
CONFIG_CBE_THERM=m
CONFIG_CBE_CPUFREQ=m
#
# PS3 Platform Options
#
CONFIG_PS3_HTAB_SIZE=20
# CONFIG_PS3_DYNAMIC_DMA is not set
CONFIG_PS3_USE_LPAR_ADDR=y
#
# Kernel options
@ -166,13 +194,14 @@ CONFIG_BINFMT_MISC=m
CONFIG_FORCE_MAX_ZONEORDER=9
# CONFIG_IOMMU_VMERGE is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_KEXEC=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_IRQ_ALL_CPUS=y
CONFIG_NUMA=y
CONFIG_NODES_SHIFT=4
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
@ -189,6 +218,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_NODES_SPAN_OTHER_NODES=y
CONFIG_PPC_64K_PAGES=y
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
@ -207,7 +237,6 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCI_MULTITHREAD_PROBE is not set
# CONFIG_PCI_DEBUG is not set
#
@ -280,7 +309,6 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
# CONFIG_IPV6_SIT is not set
CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_SUBTREES is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
@ -1107,7 +1135,8 @@ CONFIG_PLIST=y
#
# Instrumentation Support
#
# CONFIG_PROFILING is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
# CONFIG_KPROBES is not set
#
@ -1142,6 +1171,7 @@ CONFIG_DEBUG_FS=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
CONFIG_XMON_DISASSEMBLY=y
CONFIG_IRQSTACKS=y
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@ -1159,7 +1189,7 @@ CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=m
CONFIG_CRYPTO_HASH=y
# CONFIG_CRYPTO_MANAGER is not set
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,931 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc6
# Mon Nov 27 11:08:20 2006
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
CONFIG_CLASSIC32=y
# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# Block layer
#
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
# CONFIG_PPC_CHRP is not set
CONFIG_PPC_MPC52xx=y
# CONFIG_PPC_EFIKA is not set
CONFIG_PPC_LITE5200=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
# CONFIG_WANT_EARLY_SERIAL is not set
# CONFIG_MPIC is not set
#
# Kernel options
#
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_PM=y
# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
# CONFIG_PM_SYSFS_DEPRECATED is not set
# CONFIG_SOFTWARE_SUSPEND is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
#
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
#
# Default settings for advanced configuration options are used
#
CONFIG_HIGHMEM_START=0xfe000000
CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START=0xc0000000
CONFIG_TASK_SIZE=0x80000000
CONFIG_BOOT_LOAD=0x00800000
#
# Networking
#
CONFIG_NET=y
#
# Networking options
#
# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
# DCCP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_DCCP is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
#
# TIPC Configuration (EXPERIMENTAL)
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
#
# Device Drivers
#
#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play support
#
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_SCSI_PROC_FS is not set
#
# SCSI support type (disk, tape, CD-ROM)
#
# CONFIG_BLK_DEV_SD is not set
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set
# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
#
# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
#
CONFIG_ATA=y
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
# CONFIG_SATA_MV is not set
# CONFIG_SATA_NV is not set
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
# CONFIG_SATA_SIL24 is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_ATA_GENERIC is not set
# CONFIG_PATA_HPT366 is not set
# CONFIG_PATA_HPT37X is not set
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RZ1000 is not set
# CONFIG_PATA_SC1200 is not set
# CONFIG_PATA_SERVERWORKS is not set
# CONFIG_PATA_PDC2027X is not set
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
# CONFIG_FUSION_SPI is not set
# CONFIG_FUSION_FC is not set
# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
#
# Macintosh device drivers
#
# CONFIG_WINDFARM is not set
#
# Network device support
#
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
#
# PHY device support
#
#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
#
# Input device support
#
# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_MPC52xx=y
CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
#
# I2C support
#
# CONFIG_I2C is not set
#
# SPI support
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
#
# Hardware Monitoring support
#
# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
#
# Graphics support
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
#
# CONFIG_MMC is not set
#
# LED devices
#
# CONFIG_NEW_LEDS is not set
#
# LED drivers
#
#
# LED Triggers
#
#
# InfiniBand support
#
# CONFIG_INFINIBAND is not set
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set
#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
#
# DMA Clients
#
#
# DMA Devices
#
#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4DEV_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
# CONFIG_NLS is not set
#
# Library routines
#
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
#
# Instrumentation Support
#
# CONFIG_PROFILING is not set
#
# Kernel hacking
#
CONFIG_PRINTK_TIME=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set

View File

@ -1386,8 +1386,8 @@ CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=m
# CONFIG_FUSE_FS is not set
#

View File

@ -0,0 +1,837 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.19-rc6
# Tue Nov 21 19:38:53 2006
#
CONFIG_PPC64=y
CONFIG_64BIT=y
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
# CONFIG_DEFAULT_UIMAGE is not set
#
# Processor support
#
# CONFIG_POWER4_ONLY is not set
CONFIG_POWER3=y
CONFIG_POWER4=y
CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
# CONFIG_PPC_OF_PLATFORM_PCI is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
# CONFIG_CPUSETS is not set
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
#
# Block layer
#
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
#
# Platform support
#
CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
CONFIG_PPC_CELL=y
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
CONFIG_PPC_PS3=y
# CONFIG_U3_DART is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
# CONFIG_MPIC is not set
#
# Cell Broadband Engine options
#
CONFIG_SPU_FS=y
CONFIG_SPU_BASE=y
# CONFIG_CBE_RAS is not set
#
# PS3 Platform Options
#
CONFIG_PS3_HTAB_SIZE=20
CONFIG_PS3_DYNAMIC_DMA=y
CONFIG_PS3_USE_LPAR_ADDR=y
#
# Kernel options
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_PREEMPT_BKL is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_FORCE_MAX_ZONEORDER=9
# CONFIG_IOMMU_VMERGE is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
# CONFIG_IRQ_ALL_CPUS is not set
# CONFIG_NUMA is not set
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_PPC_64K_PAGES=y
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="root=/dev/nfs rw ip=dhcp"
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
#
# PCI Hotplug Support
#
CONFIG_KERNEL_START=0xc000000000000000
#
# Networking
#
CONFIG_NET=y
#
# Networking options
#
# CONFIG_NETDEBUG is not set
# CONFIG_PACKET is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
# DCCP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_DCCP is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
#
# TIPC Configuration (EXPERIMENTAL)
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
#
# Device Drivers
#
#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play support
#
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
#
# SCSI device support
#
# CONFIG_RAID_ATTRS is not set
CONFIG_SCSI=y
# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
#
# CONFIG_BLK_DEV_SD is not set
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set
# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
#
# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
#
# Serial ATA (prod) and Parallel ATA (experimental) drivers
#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
#
# I2O device support
#
#
# Macintosh device drivers
#
# CONFIG_WINDFARM is not set
#
# Network device support
#
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
# PHY device support
#
#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
#
# Ethernet (1000 Mbit)
#
#
# Ethernet (10000 Mbit)
#
#
# Token Ring devices
#
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# Ftape, the floppy tape device driver
#
# CONFIG_RAW_DRIVER is not set
# CONFIG_HANGCHECK_TIMER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
#
# I2C support
#
# CONFIG_I2C is not set
#
# SPI support
#
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
#
# Hardware Monitoring support
#
# CONFIG_HWMON is not set
# CONFIG_HWMON_VID is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
#
# Graphics support
#
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB is not set
#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
#
# CONFIG_MMC is not set
#
# LED devices
#
# CONFIG_NEW_LEDS is not set
#
# LED drivers
#
#
# LED Triggers
#
#
# InfiniBand support
#
#
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
#
# Real Time Clock
#
# CONFIG_RTC_CLASS is not set
#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
#
# DMA Clients
#
#
# DMA Devices
#
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
# CONFIG_NLS is not set
#
# Library routines
#
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
#
# Instrumentation Support
#
# CONFIG_PROFILING is not set
# CONFIG_KPROBES is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_RWSEMS is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
CONFIG_DEBUG_LIST=y
CONFIG_FORCED_INLINING=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# 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
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set

View File

@ -17,11 +17,11 @@ obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o \
paca.o cpu_setup_ppc970.o \
firmware.o sysfs.o
firmware.o sysfs.o nvram_64.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64) := rtas_pci.o
@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o
@ -59,11 +58,11 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
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 pci_iommu.o \
pci_direct_iommu.o iomap.o
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
pci32-$(CONFIG_PPC32) := pci_32.o
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
@ -72,8 +71,12 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o
ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
obj-y += iomap.o
endif
ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s
extra-y += lparmap.s
AFLAGS_head_64.o += -I$(obj)
endif

View File

@ -118,7 +118,8 @@ int main(void)
DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled));
DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));

View File

@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970)
rldimi r0,r11,52,8 /* set NAP and DPM */
li r11,0
rldimi r0,r11,32,31 /* clear EN_ATTN */
b load_hids /* Jump to shared code */
_GLOBAL(__setup_cpu_ppc970MP)
/* Do nothing if not running in HV mode */
mfmsr r0
rldicl. r0,r0,4,63
beqlr
mfspr r0,SPRN_HID0
li r11,0x15 /* clear DOZE and SLEEP */
rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */
li r11,0
rldimi r0,r11,32,31 /* clear EN_ATTN */
load_hids:
mtspr SPRN_HID0,r0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0

View File

@ -42,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
extern void __restore_cpu_ppc970(void);
#endif /* CONFIG_PPC64 */
@ -222,9 +223,9 @@ static struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
.cpu_setup = __setup_cpu_ppc970MP,
.cpu_restore = __restore_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_cpu_type = "ppc64/970MP",
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "ppc970",
},
@ -276,10 +277,45 @@ static struct cpu_spec cpu_specs[] = {
.oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5+",
},
{ /* POWER6 in P5+ mode; 2.04-compliant processor */
.pvr_mask = 0xffffffff,
.pvr_value = 0x0f000001,
.cpu_name = "POWER5+",
.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/power6",
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
.oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
.oprofile_mmcra_clear = POWER6_MMCRA_THRM |
POWER6_MMCRA_OTHER,
.platform = "power5+",
},
{ /* Power6 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003e0000,
.cpu_name = "POWER6",
.cpu_name = "POWER6 (raw)",
.cpu_features = CPU_FTRS_POWER6,
.cpu_user_features = COMMON_USER_POWER6 |
PPC_FEATURE_POWER6_EXT,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
.oprofile_cpu_type = "ppc64/power6",
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
.oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
.oprofile_mmcra_clear = POWER6_MMCRA_THRM |
POWER6_MMCRA_OTHER,
.platform = "power6x",
},
{ /* 2.05-compliant processor, i.e. Power6 "architected" mode */
.pvr_mask = 0xffffffff,
.pvr_value = 0x0f000002,
.cpu_name = "POWER6 (architected)",
.cpu_features = CPU_FTRS_POWER6,
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
@ -303,6 +339,9 @@ static struct cpu_spec cpu_specs[] = {
PPC_FEATURE_SMT,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc64/cell-be",
.oprofile_type = PPC_OPROFILE_CELL,
.platform = "ppc-cell-be",
},
{ /* PA Semi PA6T */
@ -801,6 +840,17 @@ static struct cpu_spec cpu_specs[] = {
.cpu_setup = __setup_cpu_603,
.platform = "ppc603",
},
{ /* e300c3 on 83xx */
.pvr_mask = 0x7fff0000,
.pvr_value = 0x00850000,
.cpu_name = "e300c3",
.cpu_features = CPU_FTRS_E300,
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
.platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
.pvr_mask = 0x00000000,
.pvr_value = 0x00000000,
@ -1169,19 +1219,15 @@ static struct cpu_spec cpu_specs[] = {
#endif /* CONFIG_PPC32 */
};
struct cpu_spec *identify_cpu(unsigned long offset)
struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr)
{
struct cpu_spec *s = cpu_specs;
struct cpu_spec **cur = &cur_cpu_spec;
unsigned int pvr = mfspr(SPRN_PVR);
int i;
s = PTRRELOC(s);
cur = PTRRELOC(cur);
if (*cur != NULL)
return PTRRELOC(*cur);
for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
if ((pvr & s->pvr_mask) == s->pvr_value) {
*cur = cpu_specs + i;

View File

@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs)
if (!cpu_online(cpu))
return;
local_irq_disable();
hard_irq_disable();
if (!cpu_isset(cpu, cpus_in_crash))
crash_save_this_cpu(regs, cpu);
cpu_set(cpu, cpus_in_crash);
@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
* an SMP system.
* The kernel is broken so disable interrupts.
*/
local_irq_disable();
hard_irq_disable();
for_each_irq(irq) {
struct irq_desc *desc = irq_desc + irq;

View File

@ -1,151 +1,194 @@
/*
* Copyright (C) 2004 IBM Corporation
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
*
* Implements the generic device dma API for ppc64. Handles
* the pci and vio busses
* Provide default implementations of the DMA mapping callbacks for
* directly mapped busses and busses using the iommu infrastructure
*/
#include <linux/device.h>
#include <linux/dma-mapping.h>
/* Include the busses we support */
#include <linux/pci.h>
#include <asm/vio.h>
#include <asm/ibmebus.h>
#include <asm/scatterlist.h>
#include <asm/bug.h>
#include <asm/iommu.h>
#include <asm/abs_addr.h>
static struct dma_mapping_ops *get_dma_ops(struct device *dev)
/*
* Generic iommu implementation
*/
static inline unsigned long device_to_mask(struct device *dev)
{
#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
return &pci_dma_ops;
#endif
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
return &vio_dma_ops;
#endif
#ifdef CONFIG_IBMEBUS
if (dev->bus == &ibmebus_bus_type)
return &ibmebus_dma_ops;
#endif
return NULL;
if (dev->dma_mask && *dev->dma_mask)
return *dev->dma_mask;
/* Assume devices without mask can take 32 bit addresses */
return 0xfffffffful;
}
int dma_supported(struct device *dev, u64 mask)
/* Allocates a contiguous real buffer and creates mappings over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->dma_supported(dev, mask);
return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
device_to_mask(dev), flag,
dev->archdata.numa_node);
}
EXPORT_SYMBOL(dma_supported);
int dma_set_mask(struct device *dev, u64 dma_mask)
static void dma_iommu_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
#endif
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
return -EIO;
#endif /* CONFIG_IBMVIO */
#ifdef CONFIG_IBMEBUS
if (dev->bus == &ibmebus_bus_type)
return -EIO;
#endif
BUG();
return 0;
iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
}
EXPORT_SYMBOL(dma_set_mask);
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address of the buffer
* passed here is the kernel (virtual) address of the buffer. The buffer
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
size_t size,
enum dma_data_direction direction)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
return iommu_map_single(dev->archdata.dma_data, vaddr, size,
device_to_mask(dev), direction);
}
EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
size_t size,
enum dma_data_direction direction)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction);
}
EXPORT_SYMBOL(dma_free_coherent);
dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->map_single(dev, cpu_addr, size, direction);
return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
device_to_mask(dev), direction);
}
EXPORT_SYMBOL(dma_map_single);
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->unmap_single(dev, dma_addr, size, direction);
iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction);
}
EXPORT_SYMBOL(dma_unmap_single);
dma_addr_t dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction)
/* We support DMA to/from any memory page via the iommu */
static int dma_iommu_dma_supported(struct device *dev, u64 mask)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
struct iommu_table *tbl = dev->archdata.dma_data;
BUG_ON(!dma_ops);
return dma_ops->map_single(dev, page_address(page) + offset, size,
direction);
if (!tbl || tbl->it_offset > mask) {
printk(KERN_INFO
"Warning: IOMMU offset too big for device mask\n");
if (tbl)
printk(KERN_INFO
"mask: 0x%08lx, table offset: 0x%08lx\n",
mask, tbl->it_offset);
else
printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
mask);
return 0;
} else
return 1;
}
EXPORT_SYMBOL(dma_map_page);
void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
enum dma_data_direction direction)
struct dma_mapping_ops dma_iommu_ops = {
.alloc_coherent = dma_iommu_alloc_coherent,
.free_coherent = dma_iommu_free_coherent,
.map_single = dma_iommu_map_single,
.unmap_single = dma_iommu_unmap_single,
.map_sg = dma_iommu_map_sg,
.unmap_sg = dma_iommu_unmap_sg,
.dma_supported = dma_iommu_dma_supported,
};
EXPORT_SYMBOL(dma_iommu_ops);
/*
* Generic direct DMA implementation
*
* This implementation supports a global offset that can be applied if
* the address at which memory is visible to devices is not 0.
*/
unsigned long dma_direct_offset;
static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
struct page *page;
void *ret;
int node = dev->archdata.numa_node;
BUG_ON(!dma_ops);
/* TODO: Maybe use the numa node here too ? */
page = alloc_pages_node(node, flag, get_order(size));
if (page == NULL)
return NULL;
ret = page_address(page);
memset(ret, 0, size);
*dma_handle = virt_to_abs(ret) | dma_direct_offset;
dma_ops->unmap_single(dev, dma_address, size, direction);
return ret;
}
EXPORT_SYMBOL(dma_unmap_page);
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
static void dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->map_sg(dev, sg, nents, direction);
free_pages((unsigned long)vaddr, get_order(size));
}
EXPORT_SYMBOL(dma_map_sg);
void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
enum dma_data_direction direction)
static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
size_t size,
enum dma_data_direction direction)
{
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->unmap_sg(dev, sg, nhwentries, direction);
return virt_to_abs(ptr) | dma_direct_offset;
}
EXPORT_SYMBOL(dma_unmap_sg);
static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
size_t size,
enum dma_data_direction direction)
{
}
static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
int i;
for (i = 0; i < nents; i++, sg++) {
sg->dma_address = (page_to_phys(sg->page) + sg->offset) |
dma_direct_offset;
sg->dma_length = sg->length;
}
return nents;
}
static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
}
static int dma_direct_dma_supported(struct device *dev, u64 mask)
{
/* Could be improved to check for memory though it better be
* done via some global so platforms can set the limit in case
* they have limited DMA windows
*/
return mask >= DMA_32BIT_MASK;
}
struct dma_mapping_ops dma_direct_ops = {
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
.map_single = dma_direct_map_single,
.unmap_single = dma_direct_unmap_single,
.map_sg = dma_direct_map_sg,
.unmap_sg = dma_direct_unmap_sg,
.dma_supported = dma_direct_dma_supported,
};
EXPORT_SYMBOL(dma_direct_ops);

View File

@ -87,15 +87,19 @@ system_call_common:
addi r9,r1,STACK_FRAME_OVERHEAD
ld r11,exception_marker@toc(r2)
std r11,-16(r9) /* "regshere" marker */
li r10,1
stb r10,PACASOFTIRQEN(r13)
stb r10,PACAHARDIRQEN(r13)
std r10,SOFTE(r1)
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
/* Hack for handling interrupts when soft-enabling on iSeries */
cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
andi. r10,r12,MSR_PR /* from kernel */
crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
beq hardware_interrupt_entry
lbz r10,PACAPROCENABLED(r13)
std r10,SOFTE(r1)
bne 2f
b hardware_interrupt_entry
2:
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
mfmsr r11
@ -460,9 +464,9 @@ _GLOBAL(ret_from_except_lite)
#endif
restore:
ld r5,SOFTE(r1)
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
ld r5,SOFTE(r1)
cmpdi 0,r5,0
beq 4f
/* Check for pending interrupts (iSeries) */
@ -472,21 +476,25 @@ BEGIN_FW_FTR_SECTION
beq+ 4f /* skip do_IRQ if no interrupts */
li r3,0
stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */
stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */
ori r10,r10,MSR_EE
mtmsrd r10 /* hard-enable again */
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_IRQ
b .ret_from_except_lite /* loop back and handle more */
4: stb r5,PACAPROCENABLED(r13)
4:
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
stb r5,PACASOFTIRQEN(r13)
ld r3,_MSR(r1)
andi. r0,r3,MSR_RI
beq- unrecov_restore
/* extract EE bit and use it to restore paca->hard_enabled */
rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
stb r4,PACAHARDIRQEN(r13)
andi. r0,r3,MSR_PR
/*
@ -538,25 +546,15 @@ do_work:
/* Check that preempt_count() == 0 and interrupts are enabled */
lwz r8,TI_PREEMPT(r9)
cmpwi cr1,r8,0
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
ld r0,SOFTE(r1)
cmpdi r0,0
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
BEGIN_FW_FTR_SECTION
andi. r0,r3,MSR_EE
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
crandc eq,cr1*4+eq,eq
bne restore
/* here we are preempting the current task */
1:
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
li r0,1
stb r0,PACAPROCENABLED(r13)
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
stb r0,PACASOFTIRQEN(r13)
stb r0,PACAHARDIRQEN(r13)
ori r10,r10,MSR_EE
mtmsrd r10,1 /* reenable interrupts */
bl .preempt_schedule
@ -639,8 +637,7 @@ _GLOBAL(enter_rtas)
/* There is no way it is acceptable to get here with interrupts enabled,
* check it with the asm equivalent of WARN_ON
*/
mfmsr r6
andi. r0,r6,MSR_EE
lbz r0,PACASOFTIRQEN(r13)
1: tdnei r0,0
.section __bug_table,"a"
.llong 1b,__LINE__ + 0x1000000, 1f, 2f
@ -649,7 +646,13 @@ _GLOBAL(enter_rtas)
1: .asciz __FILE__
2: .asciz "enter_rtas"
.previous
/* Hard-disable interrupts */
mfmsr r6
rldicl r7,r6,48,1
rotldi r7,r7,16
mtmsrd r7,1
/* Unfortunately, the stack pointer and the MSR are also clobbered,
* so they are saved in the PACA which allows us to restore
* our original state after RTAS returns.
@ -735,8 +738,6 @@ _STATIC(rtas_restore_regs)
#endif /* CONFIG_PPC_RTAS */
#ifdef CONFIG_PPC_MULTIPLATFORM
_GLOBAL(enter_prom)
mflr r0
std r0,16(r1)
@ -821,5 +822,3 @@ _GLOBAL(enter_prom)
ld r0,16(r1)
mtlr r0
blr
#endif /* CONFIG_PPC_MULTIPLATFORM */

View File

@ -35,9 +35,7 @@
#include <asm/thread_info.h>
#include <asm/firmware.h>
#ifdef CONFIG_PPC_ISERIES
#define DO_SOFT_DISABLE
#endif
/*
* We layout physical memory as follows:
@ -74,13 +72,11 @@
.text
.globl _stext
_stext:
#ifdef CONFIG_PPC_MULTIPLATFORM
_GLOBAL(__start)
/* NOP this out unconditionally */
BEGIN_FTR_SECTION
b .__start_initialization_multiplatform
END_FTR_SECTION(0, 1)
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* Catch branch to 0 in real mode */
trap
@ -308,7 +304,9 @@ exception_marker:
std r9,_LINK(r1); \
mfctr r10; /* save CTR in stackframe */ \
std r10,_CTR(r1); \
lbz r10,PACASOFTIRQEN(r13); \
mfspr r11,SPRN_XER; /* save XER in stackframe */ \
std r10,SOFTE(r1); \
std r11,_XER(r1); \
li r9,(n)+1; \
std r9,_TRAP(r1); /* set trap number */ \
@ -343,6 +341,34 @@ label##_pSeries: \
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
#define MASKABLE_EXCEPTION_PSERIES(n, label) \
. = n; \
.globl label##_pSeries; \
label##_pSeries: \
HMT_MEDIUM; \
mtspr SPRN_SPRG1,r13; /* save r13 */ \
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
std r10,PACA_EXGEN+EX_R10(r13); \
lbz r10,PACASOFTIRQEN(r13); \
mfcr r9; \
cmpwi r10,0; \
beq masked_interrupt; \
mfspr r10,SPRN_SPRG1; \
std r10,PACA_EXGEN+EX_R13(r13); \
std r11,PACA_EXGEN+EX_R11(r13); \
std r12,PACA_EXGEN+EX_R12(r13); \
clrrdi r12,r13,32; /* get high part of &label */ \
mfmsr r10; \
mfspr r11,SPRN_SRR0; /* save SRR0 */ \
LOAD_HANDLER(r12,label##_common) \
ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
mtspr SPRN_SRR0,r12; \
mfspr r12,SPRN_SRR1; /* and SRR1 */ \
mtspr SPRN_SRR1,r10; \
rfid; \
b . /* prevent speculative execution */
#define STD_EXCEPTION_ISERIES(n, label, area) \
.globl label##_iSeries; \
label##_iSeries: \
@ -358,40 +384,32 @@ label##_iSeries: \
HMT_MEDIUM; \
mtspr SPRN_SPRG1,r13; /* save r13 */ \
EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \
lbz r10,PACAPROCENABLED(r13); \
lbz r10,PACASOFTIRQEN(r13); \
cmpwi 0,r10,0; \
beq- label##_iSeries_masked; \
EXCEPTION_PROLOG_ISERIES_2; \
b label##_common; \
#ifdef DO_SOFT_DISABLE
#ifdef CONFIG_PPC_ISERIES
#define DISABLE_INTS \
BEGIN_FW_FTR_SECTION; \
lbz r10,PACAPROCENABLED(r13); \
li r11,0; \
std r10,SOFTE(r1); \
stb r11,PACASOFTIRQEN(r13); \
BEGIN_FW_FTR_SECTION; \
stb r11,PACAHARDIRQEN(r13); \
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
BEGIN_FW_FTR_SECTION; \
mfmsr r10; \
stb r11,PACAPROCENABLED(r13); \
ori r10,r10,MSR_EE; \
mtmsrd r10,1; \
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#define ENABLE_INTS \
BEGIN_FW_FTR_SECTION; \
lbz r10,PACAPROCENABLED(r13); \
mfmsr r11; \
std r10,SOFTE(r1); \
ori r11,r11,MSR_EE; \
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
BEGIN_FW_FTR_SECTION; \
ld r12,_MSR(r1); \
mfmsr r11; \
rlwimi r11,r12,0,MSR_EE; \
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
mtmsrd r11,1
#else
#define DISABLE_INTS \
li r11,0; \
stb r11,PACASOFTIRQEN(r13); \
stb r11,PACAHARDIRQEN(r13)
#else /* hard enable/disable interrupts */
#define DISABLE_INTS
#endif /* CONFIG_PPC_ISERIES */
#define ENABLE_INTS \
ld r12,_MSR(r1); \
@ -399,8 +417,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
rlwimi r11,r12,0,MSR_EE; \
mtmsrd r11,1
#endif
#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
.align 7; \
.globl label##_common; \
@ -541,11 +557,11 @@ instruction_access_slb_pSeries:
mfspr r12,SPRN_SRR1 /* and SRR1 */
b .slb_miss_realmode /* Rel. branch works in real mode */
STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
STD_EXCEPTION_PSERIES(0x600, alignment)
STD_EXCEPTION_PSERIES(0x700, program_check)
STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
STD_EXCEPTION_PSERIES(0x900, decrementer)
MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
STD_EXCEPTION_PSERIES(0xa00, trap_0a)
STD_EXCEPTION_PSERIES(0xb00, trap_0b)
@ -597,7 +613,24 @@ system_call_pSeries:
/*** pSeries interrupt support ***/
/* moved from 0xf00 */
STD_EXCEPTION_PSERIES(., performance_monitor)
MASKABLE_EXCEPTION_PSERIES(., performance_monitor)
/*
* An interrupt came in while soft-disabled; clear EE in SRR1,
* clear paca->hard_enabled and return.
*/
masked_interrupt:
stb r10,PACAHARDIRQEN(r13)
mtcrf 0x80,r9
ld r9,PACA_EXGEN+EX_R9(r13)
mfspr r10,SPRN_SRR1
rldicl r10,r10,48,1 /* clear MSR_EE */
rotldi r10,r10,16
mtspr SPRN_SRR1,r10
ld r10,PACA_EXGEN+EX_R10(r13)
mfspr r13,SPRN_SPRG1
rfid
b .
.align 7
do_stab_bolted_pSeries:
@ -792,7 +825,7 @@ system_reset_iSeries:
cmpwi 0,r23,0
beq iSeries_secondary_smp_loop /* Loop until told to go */
bne .__secondary_start /* Loop until told to go */
bne __secondary_start /* Loop until told to go */
iSeries_secondary_smp_loop:
/* Let the Hypervisor know we are alive */
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
@ -813,7 +846,6 @@ iSeries_secondary_smp_loop:
b 1b /* If SMP not configured, secondaries
* loop forever */
.globl decrementer_iSeries_masked
decrementer_iSeries_masked:
/* We may not have a valid TOC pointer in here. */
li r11,1
@ -824,7 +856,6 @@ decrementer_iSeries_masked:
mtspr SPRN_DEC,r12
/* fall through */
.globl hardware_interrupt_iSeries_masked
hardware_interrupt_iSeries_masked:
mtcrf 0x80,r9 /* Restore regs */
ld r12,PACALPPACAPTR(r13)
@ -926,10 +957,18 @@ bad_stack:
* any task or sent any task a signal, you should use
* ret_from_except or ret_from_except_lite instead of this.
*/
fast_exc_return_irq: /* restores irq state too */
ld r3,SOFTE(r1)
ld r12,_MSR(r1)
stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */
rldicl r4,r12,49,63 /* get MSR_EE to LSB */
stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
b 1f
.globl fast_exception_return
fast_exception_return:
ld r12,_MSR(r1)
ld r11,_NIP(r1)
1: ld r11,_NIP(r1)
andi. r3,r12,MSR_RI /* check if RI is set */
beq- unrecov_fer
@ -952,7 +991,8 @@ fast_exception_return:
REST_8GPRS(2, r1)
mfmsr r10
clrrdi r10,r10,2 /* clear RI (LE is 0 already) */
rldicl r10,r10,48,1 /* clear EE */
rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */
mtmsrd r10,1
mtspr SPRN_SRR1,r12
@ -1326,6 +1366,16 @@ BEGIN_FW_FTR_SECTION
* interrupts if necessary.
*/
beq 13f
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
BEGIN_FW_FTR_SECTION
/*
* Here we have interrupts hard-disabled, so it is sufficient
* to restore paca->{soft,hard}_enable and get out.
*/
beq fast_exc_return_irq /* Return from exception on success */
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
/* For a hash failure, we don't bother re-enabling interrupts */
ble- 12f
@ -1337,14 +1387,6 @@ BEGIN_FW_FTR_SECTION
ld r3,SOFTE(r1)
bl .local_irq_restore
b 11f
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
BEGIN_FW_FTR_SECTION
beq fast_exception_return /* Return from exception on success */
ble- 12f /* Failure return from hash_page */
/* fall through */
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
/* Here we have a page fault that hash_page can't handle. */
handle_page_fault:
@ -1362,6 +1404,8 @@ handle_page_fault:
bl .bad_page_fault
b .ret_from_except
13: b .ret_from_except_lite
/* We have a page fault that hash_page could handle but HV refused
* the PTE insertion
*/
@ -1371,8 +1415,6 @@ handle_page_fault:
bl .low_hash_fault
b .ret_from_except
13: b .ret_from_except_lite
/* here we have a segment miss */
do_ste_alloc:
bl .ste_allocate /* try to insert stab entry */
@ -1560,7 +1602,7 @@ _GLOBAL(generic_secondary_smp_init)
ld r1,PACAEMERGSP(r13)
subi r1,r1,STACK_FRAME_OVERHEAD
b .__secondary_start
b __secondary_start
#endif
#ifdef CONFIG_PPC_ISERIES
@ -1595,7 +1637,6 @@ _STATIC(__start_initialization_iSeries)
b .start_here_common
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(__mmu_off)
mfmsr r3
@ -1621,13 +1662,11 @@ _STATIC(__mmu_off)
*
*/
_GLOBAL(__start_initialization_multiplatform)
#ifdef CONFIG_PPC_MULTIPLATFORM
/*
* Are we booted from a PROM Of-type client-interface ?
*/
cmpldi cr0,r5,0
bne .__boot_from_prom /* yes -> prom */
#endif
/* Save parameters */
mr r31,r3
@ -1656,7 +1695,6 @@ _GLOBAL(__start_initialization_multiplatform)
bl .__mmu_off
b .__after_prom_start
#ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(__boot_from_prom)
/* Save parameters */
mr r31,r3
@ -1696,7 +1734,6 @@ _STATIC(__boot_from_prom)
bl .prom_init
/* We never return */
trap
#endif
/*
* At this point, r3 contains the physical address we are running at,
@ -1752,8 +1789,6 @@ _STATIC(__after_prom_start)
bl .copy_and_flush /* copy the rest */
b .start_here_multiplatform
#endif /* CONFIG_PPC_MULTIPLATFORM */
/*
* Copy routine used to copy the kernel to start at physical address 0
* and flush and invalidate the caches as needed.
@ -1836,7 +1871,7 @@ _GLOBAL(pmac_secondary_start)
ld r1,PACAEMERGSP(r13)
subi r1,r1,STACK_FRAME_OVERHEAD
b .__secondary_start
b __secondary_start
#endif /* CONFIG_PPC_PMAC */
@ -1853,7 +1888,7 @@ _GLOBAL(pmac_secondary_start)
* r13 = paca virtual address
* SPRG3 = paca virtual address
*/
_GLOBAL(__secondary_start)
__secondary_start:
/* Set thread priority to MEDIUM */
HMT_MEDIUM
@ -1877,11 +1912,16 @@ _GLOBAL(__secondary_start)
/* enable MMU and jump to start_secondary */
LOAD_REG_ADDR(r3, .start_secondary_prolog)
LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
#ifdef DO_SOFT_DISABLE
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
ori r4,r4,MSR_EE
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
BEGIN_FW_FTR_SECTION
stb r7,PACASOFTIRQEN(r13)
stb r7,PACAHARDIRQEN(r13)
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
mtspr SPRN_SRR0,r3
mtspr SPRN_SRR1,r4
rfid
@ -1913,7 +1953,6 @@ _GLOBAL(enable_64b_mode)
isync
blr
#ifdef CONFIG_PPC_MULTIPLATFORM
/*
* This is where the main kernel code starts.
*/
@ -1977,7 +2016,6 @@ _STATIC(start_here_multiplatform)
mtspr SPRN_SRR1,r4
rfid
b . /* prevent speculative execution */
#endif /* CONFIG_PPC_MULTIPLATFORM */
/* This is where all platforms converge execution */
_STATIC(start_here_common)
@ -2005,15 +2043,18 @@ _STATIC(start_here_common)
/* Load up the kernel context */
5:
#ifdef DO_SOFT_DISABLE
BEGIN_FW_FTR_SECTION
li r5,0
stb r5,PACAPROCENABLED(r13) /* Soft Disabled */
stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */
#ifdef CONFIG_PPC_ISERIES
BEGIN_FW_FTR_SECTION
mfmsr r5
ori r5,r5,MSR_EE /* Hard Enabled */
mtmsrd r5
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
#endif
BEGIN_FW_FTR_SECTION
stb r5,PACAHARDIRQEN(r13)
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
bl .start_kernel

View File

@ -112,7 +112,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask)
return 1;
}
struct dma_mapping_ops ibmebus_dma_ops = {
static struct dma_mapping_ops ibmebus_dma_ops = {
.alloc_coherent = ibmebus_alloc_coherent,
.free_coherent = ibmebus_free_coherent,
.map_single = ibmebus_map_single,
@ -176,6 +176,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common(
dev->ofdev.dev.bus = &ibmebus_bus_type;
dev->ofdev.dev.release = ibmebus_dev_release;
dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
/* An ibmebusdev is based on a of_device. We have to change the
* bus type to use our own DMA mapping operations.
*/
@ -210,11 +214,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
return NULL;
}
dev = kmalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
if (!dev) {
return NULL;
}
memset(dev, 0, sizeof(struct ibmebus_dev));
dev->ofdev.node = of_node_get(dn);

View File

@ -39,6 +39,13 @@
#define cpu_should_die() 0
#endif
static int __init powersave_off(char *arg)
{
ppc_md.power_save = NULL;
return 0;
}
__setup("powersave=off", powersave_off);
/*
* The body of the idle task.
*/

View File

@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
beqlr
/* Go to NAP now */
mfmsr r7
rldicl r0,r7,48,1
rotldi r0,r0,16
mtmsrd r0,1 /* hard-disable interrupts */
li r0,1
stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
stb r0,PACAHARDIRQEN(r13)
BEGIN_FTR_SECTION
DSSALL
sync
@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */
ori r8,r8,_TLF_NAPPING /* so when we take an exception */
std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */
mfmsr r7
ori r7,r7,MSR_EE
oris r7,r7,MSR_POW@h
1: sync

View File

@ -25,13 +25,11 @@
#include <asm/firmware.h>
#include <asm/bug.h>
void _insb(volatile u8 __iomem *port, void *buf, long count)
void _insb(const volatile u8 __iomem *port, void *buf, long count)
{
u8 *tbuf = buf;
u8 tmp;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
{
const u8 *tbuf = buf;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -60,13 +56,11 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count)
}
EXPORT_SYMBOL(_outsb);
void _insw_ns(volatile u16 __iomem *port, void *buf, long count)
void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
{
u16 *tbuf = buf;
u16 tmp;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
{
const u16 *tbuf = buf;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -95,13 +87,11 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
}
EXPORT_SYMBOL(_outsw_ns);
void _insl_ns(volatile u32 __iomem *port, void *buf, long count)
void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
{
u32 *tbuf = buf;
u32 tmp;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
{
const u32 *tbuf = buf;
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
if (unlikely(count <= 0))
return;
asm volatile("sync");
@ -129,3 +117,90 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
asm volatile("sync");
}
EXPORT_SYMBOL(_outsl_ns);
#define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0)
void _memset_io(volatile void __iomem *addr, int c, unsigned long n)
{
void *p = (void __force *)addr;
u32 lc = c;
lc |= lc << 8;
lc |= lc << 16;
__asm__ __volatile__ ("sync" : : : "memory");
while(n && !IO_CHECK_ALIGN(p, 4)) {
*((volatile u8 *)p) = c;
p++;
n--;
}
while(n >= 4) {
*((volatile u32 *)p) = lc;
p += 4;
n -= 4;
}
while(n) {
*((volatile u8 *)p) = c;
p++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
}
EXPORT_SYMBOL(_memset_io);
void _memcpy_fromio(void *dest, const volatile void __iomem *src,
unsigned long n)
{
void *vsrc = (void __force *) 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");
vsrc++;
dest++;
n--;
}
while(n > 4) {
*((u32 *)dest) = *((volatile u32 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
vsrc += 4;
dest += 4;
n -= 4;
}
while(n) {
*((u8 *)dest) = *((volatile u8 *)vsrc);
__asm__ __volatile__ ("eieio" : : : "memory");
vsrc++;
dest++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
}
EXPORT_SYMBOL(_memcpy_fromio);
void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
{
void *vdest = (void __force *) dest;
__asm__ __volatile__ ("sync" : : : "memory");
while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) {
*((volatile u8 *)vdest) = *((u8 *)src);
src++;
vdest++;
n--;
}
while(n > 4) {
*((volatile u32 *)vdest) = *((volatile u32 *)src);
src += 4;
vdest += 4;
n-=4;
}
while(n) {
*((volatile u8 *)vdest) = *((u8 *)src);
src++;
vdest++;
n--;
}
__asm__ __volatile__ ("sync" : : : "memory");
}
EXPORT_SYMBOL(_memcpy_toio);

View File

@ -106,7 +106,7 @@ EXPORT_SYMBOL(iowrite32_rep);
void __iomem *ioport_map(unsigned long port, unsigned int len)
{
return (void __iomem *) (port+pci_io_base);
return (void __iomem *) (port + _IO_BASE);
}
void ioport_unmap(void __iomem *addr)

View File

@ -258,9 +258,9 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
unsigned long mask, enum dma_data_direction direction)
int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, unsigned long mask,
enum dma_data_direction direction)
{
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;

View File

@ -64,8 +64,9 @@
#include <asm/ptrace.h>
#include <asm/machdep.h>
#include <asm/udbg.h>
#ifdef CONFIG_PPC_ISERIES
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#include <asm/firmware.h>
#endif
int __irq_offset_value;
@ -95,6 +96,74 @@ extern atomic_t ipi_sent;
EXPORT_SYMBOL(irq_desc);
int distribute_irqs = 1;
static inline unsigned long get_hard_enabled(void)
{
unsigned long enabled;
__asm__ __volatile__("lbz %0,%1(13)"
: "=r" (enabled) : "i" (offsetof(struct paca_struct, hard_enabled)));
return enabled;
}
static inline void set_soft_enabled(unsigned long enable)
{
__asm__ __volatile__("stb %0,%1(13)"
: : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
}
void local_irq_restore(unsigned long en)
{
/*
* get_paca()->soft_enabled = en;
* Is it ever valid to use local_irq_restore(0) when soft_enabled is 1?
* That was allowed before, and in such a case we do need to take care
* that gcc will set soft_enabled directly via r13, not choose to use
* an intermediate register, lest we're preempted to a different cpu.
*/
set_soft_enabled(en);
if (!en)
return;
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
/*
* Do we need to disable preemption here? Not really: in the
* unlikely event that we're preempted to a different cpu in
* between getting r13, loading its lppaca_ptr, and loading
* its any_int, we might call iseries_handle_interrupts without
* an interrupt pending on the new cpu, but that's no disaster,
* is it? And the business of preempting us off the old cpu
* would itself involve a local_irq_restore which handles the
* interrupt to that cpu.
*
* But use "local_paca->lppaca_ptr" instead of "get_lppaca()"
* to avoid any preemption checking added into get_paca().
*/
if (local_paca->lppaca_ptr->int_dword.any_int)
iseries_handle_interrupts();
return;
}
/*
* if (get_paca()->hard_enabled) return;
* But again we need to take care that gcc gets hard_enabled directly
* via r13, not choose to use an intermediate register, lest we're
* preempted to a different cpu in between the two instructions.
*/
if (get_hard_enabled())
return;
/*
* Need to hard-enable interrupts here. Since currently disabled,
* no need to take further asm precautions against preemption; but
* use local_paca instead of get_paca() to avoid preemption checking.
*/
local_paca->hard_enabled = en;
if ((int)mfspr(SPRN_DEC) < 0)
mtspr(SPRN_DEC, 1);
hard_irq_enable();
}
#endif /* CONFIG_PPC64 */
int show_interrupts(struct seq_file *p, void *v)
@ -246,7 +315,8 @@ void do_IRQ(struct pt_regs *regs)
set_irq_regs(old_regs);
#ifdef CONFIG_PPC_ISERIES
if (get_lppaca()->int_dword.fields.decr_int) {
if (firmware_has_feature(FW_FEATURE_ISERIES) &&
get_lppaca()->int_dword.fields.decr_int) {
get_lppaca()->int_dword.fields.decr_int = 0;
/* Signal a fake decrementer interrupt */
timer_interrupt(regs);
@ -626,10 +696,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
void irq_dispose_mapping(unsigned int virq)
{
struct irq_host *host = irq_map[virq].host;
struct irq_host *host;
irq_hw_number_t hwirq;
unsigned long flags;
if (virq == NO_IRQ)
return;
host = irq_map[virq].host;
WARN_ON (host == NULL);
if (host == NULL)
return;

View File

@ -8,6 +8,34 @@
#include <asm/errno.h>
#include <asm/of_device.h>
/**
* of_match_node - Tell if an device_node has a matching of_match structure
* @ids: array of of device match structures to search in
* @node: the of device structure to match against
*
* Low level utility function used by device matching.
*/
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
match &= node->name
&& !strcmp(matches->name, node->name);
if (matches->type[0])
match &= node->type
&& !strcmp(matches->type, node->type);
if (matches->compatible[0])
match &= device_is_compatible(node,
matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
/**
* of_match_device - Tell if an of_device structure has a matching
* of_match structure
@ -22,34 +50,7 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches,
{
if (!dev->node)
return NULL;
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
match &= dev->node->name
&& !strcmp(matches->name, dev->node->name);
if (matches->type[0])
match &= dev->node->type
&& !strcmp(matches->type, dev->node->type);
if (matches->compatible[0])
match &= device_is_compatible(dev->node,
matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
const struct of_device_id * matches = of_drv->match_table;
if (!matches)
return 0;
return of_match_device(matches, of_dev) != NULL;
return of_match_node(matches, dev->node);
}
struct of_device *of_dev_get(struct of_device *dev)
@ -71,96 +72,8 @@ void of_dev_put(struct of_device *dev)
put_device(&dev->dev);
}
static int of_device_probe(struct device *dev)
{
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
const struct of_device_id *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
if (!drv->probe)
return error;
of_dev_get(of_dev);
match = of_match_device(drv->match_table, of_dev);
if (match)
error = drv->probe(of_dev, match);
if (error)
of_dev_put(of_dev);
return error;
}
static int of_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
static int of_device_suspend(struct device *dev, pm_message_t state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
static int of_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
static int __init of_bus_driver_init(void)
{
return bus_register(&of_platform_bus_type);
}
postcore_initcall(of_bus_driver_init);
int of_register_driver(struct of_platform_driver *drv)
{
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &of_platform_bus_type;
/* register with core */
return driver_register(&drv->driver);
}
void of_unregister_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
}
static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t dev_show_devspec(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
@ -208,41 +121,11 @@ void of_device_unregister(struct of_device *ofdev)
device_unregister(&ofdev->dev);
}
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent)
{
struct of_device *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
memset(dev, 0, sizeof(*dev));
dev->node = of_node_get(np);
dev->dma_mask = 0xffffffffUL;
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.parent = parent;
dev->dev.bus = &of_platform_bus_type;
dev->dev.release = of_release_dev;
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
if (of_device_register(dev) != 0) {
kfree(dev);
return NULL;
}
return dev;
}
EXPORT_SYMBOL(of_match_node);
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_platform_bus_type);
EXPORT_SYMBOL(of_register_driver);
EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_device_register);
EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_platform_device_create);
EXPORT_SYMBOL(of_release_dev);

View File

@ -0,0 +1,489 @@
/*
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
* <benh@kernel.crashing.org>
* and Arnd Bergmann, 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.
*
*/
#undef DEBUG
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <asm/errno.h>
#include <asm/dcr.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
#include <asm/topology.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
#include <asm/atomic.h>
/*
* The list of OF IDs below is used for matching bus types in the
* system whose devices are to be exposed as of_platform_devices.
*
* This is the default list valid for most platforms. This file provides
* functions who can take an explicit list if necessary though
*
* The search is always performed recursively looking for children of
* the provided device_node and recursively if such a children matches
* a bus type in the list
*/
static struct of_device_id of_default_bus_ids[] = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .type = "spider", },
{ .type = "axon", },
{ .type = "plb5", },
{ .type = "plb4", },
{ .type = "opb", },
{},
};
static atomic_t bus_no_reg_magic;
/*
*
* OF platform device type definition & base infrastructure
*
*/
static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
const struct of_device_id * matches = of_drv->match_table;
if (!matches)
return 0;
return of_match_device(matches, of_dev) != NULL;
}
static int of_platform_device_probe(struct device *dev)
{
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
const struct of_device_id *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
if (!drv->probe)
return error;
of_dev_get(of_dev);
match = of_match_device(drv->match_table, of_dev);
if (match)
error = drv->probe(of_dev, match);
if (error)
of_dev_put(of_dev);
return error;
}
static int of_platform_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
static int of_platform_device_suspend(struct device *dev, pm_message_t state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
static int of_platform_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
.probe = of_platform_device_probe,
.remove = of_platform_device_remove,
.suspend = of_platform_device_suspend,
.resume = of_platform_device_resume,
};
EXPORT_SYMBOL(of_platform_bus_type);
static int __init of_bus_driver_init(void)
{
return bus_register(&of_platform_bus_type);
}
postcore_initcall(of_bus_driver_init);
int of_register_platform_driver(struct of_platform_driver *drv)
{
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &of_platform_bus_type;
/* register with core */
return driver_register(&drv->driver);
}
EXPORT_SYMBOL(of_register_platform_driver);
void of_unregister_platform_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(of_unregister_platform_driver);
static void of_platform_make_bus_id(struct of_device *dev)
{
struct device_node *node = dev->node;
char *name = dev->dev.bus_id;
const u32 *reg;
u64 addr;
long magic;
/*
* If it's a DCR based device, use 'd' for native DCRs
* and 'D' for MMIO DCRs.
*/
#ifdef CONFIG_PPC_DCR
reg = get_property(node, "dcr-reg", NULL);
if (reg) {
#ifdef CONFIG_PPC_DCR_NATIVE
snprintf(name, BUS_ID_SIZE, "d%x.%s",
*reg, node->name);
#else /* CONFIG_PPC_DCR_NATIVE */
addr = of_translate_dcr_address(node, *reg, NULL);
if (addr != OF_BAD_ADDR) {
snprintf(name, BUS_ID_SIZE,
"D%llx.%s", (unsigned long long)addr,
node->name);
return;
}
#endif /* !CONFIG_PPC_DCR_NATIVE */
}
#endif /* CONFIG_PPC_DCR */
/*
* For MMIO, get the physical address
*/
reg = get_property(node, "reg", NULL);
if (reg) {
addr = of_translate_address(node, reg);
if (addr != OF_BAD_ADDR) {
snprintf(name, BUS_ID_SIZE,
"%llx.%s", (unsigned long long)addr,
node->name);
return;
}
}
/*
* No BusID, use the node name and add a globally incremented
* counter (and pray...)
*/
magic = atomic_add_return(1, &bus_no_reg_magic);
snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
}
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent)
{
struct of_device *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
memset(dev, 0, sizeof(*dev));
dev->node = of_node_get(np);
dev->dma_mask = 0xffffffffUL;
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.parent = parent;
dev->dev.bus = &of_platform_bus_type;
dev->dev.release = of_release_dev;
dev->dev.archdata.of_node = np;
dev->dev.archdata.numa_node = of_node_to_nid(np);
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
*/
if (bus_id)
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
else
of_platform_make_bus_id(dev);
if (of_device_register(dev) != 0) {
kfree(dev);
return NULL;
}
return dev;
}
EXPORT_SYMBOL(of_platform_device_create);
/**
* of_platform_bus_create - Create an OF device for a bus node and all its
* children. Optionally recursively instanciate matching busses.
* @bus: device node of the bus to instanciate
* @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
* disallow recursive creation of child busses
*/
static int of_platform_bus_create(struct device_node *bus,
struct of_device_id *matches,
struct device *parent)
{
struct device_node *child;
struct of_device *dev;
int rc = 0;
for (child = NULL; (child = of_get_next_child(bus, child)); ) {
pr_debug(" create child: %s\n", child->full_name);
dev = of_platform_device_create(child, NULL, parent);
if (dev == NULL)
rc = -ENOMEM;
else if (!of_match_node(matches, child))
continue;
if (rc == 0) {
pr_debug(" and sub busses\n");
rc = of_platform_bus_create(child, matches, &dev->dev);
} if (rc) {
of_node_put(child);
break;
}
}
return rc;
}
/**
* of_platform_bus_probe - Probe the device-tree for platform busses
* @root: parent of the first level to probe or NULL for the root of the tree
* @matches: match table, NULL to use the default
* @parent: parent to hook devices from, NULL for toplevel
*
* Note that children of the provided root are not instanciated as devices
* unless the specified root itself matches the bus list and is not NULL.
*/
int of_platform_bus_probe(struct device_node *root,
struct of_device_id *matches,
struct device *parent)
{
struct device_node *child;
struct of_device *dev;
int rc = 0;
if (matches == NULL)
matches = of_default_bus_ids;
if (matches == OF_NO_DEEP_PROBE)
return -EINVAL;
if (root == NULL)
root = of_find_node_by_path("/");
else
of_node_get(root);
pr_debug("of_platform_bus_probe()\n");
pr_debug(" starting at: %s\n", root->full_name);
/* Do a self check of bus type, if there's a match, create
* children
*/
if (of_match_node(matches, root)) {
pr_debug(" root match, create all sub devices\n");
dev = of_platform_device_create(root, NULL, parent);
if (dev == NULL) {
rc = -ENOMEM;
goto bail;
}
pr_debug(" create all sub busses\n");
rc = of_platform_bus_create(root, matches, &dev->dev);
goto bail;
}
for (child = NULL; (child = of_get_next_child(root, child)); ) {
if (!of_match_node(matches, child))
continue;
pr_debug(" match: %s\n", child->full_name);
dev = of_platform_device_create(child, NULL, parent);
if (dev == NULL)
rc = -ENOMEM;
else
rc = of_platform_bus_create(child, matches, &dev->dev);
if (rc) {
of_node_put(child);
break;
}
}
bail:
of_node_put(root);
return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);
static int of_dev_node_match(struct device *dev, void *data)
{
return to_of_device(dev)->node == data;
}
struct of_device *of_find_device_by_node(struct device_node *np)
{
struct device *dev;
dev = bus_find_device(&of_platform_bus_type,
NULL, np, of_dev_node_match);
if (dev)
return to_of_device(dev);
return NULL;
}
EXPORT_SYMBOL(of_find_device_by_node);
static int of_dev_phandle_match(struct device *dev, void *data)
{
phandle *ph = data;
return to_of_device(dev)->node->linux_phandle == *ph;
}
struct of_device *of_find_device_by_phandle(phandle ph)
{
struct device *dev;
dev = bus_find_device(&of_platform_bus_type,
NULL, &ph, of_dev_phandle_match);
if (dev)
return to_of_device(dev);
return NULL;
}
EXPORT_SYMBOL(of_find_device_by_phandle);
#ifdef CONFIG_PPC_OF_PLATFORM_PCI
/* The probing of PCI controllers from of_platform is currently
* 64 bits only, mostly due to gratuitous differences between
* the 32 and 64 bits PCI code on PowerPC and the 32 bits one
* lacking some bits needed here.
*/
static int __devinit of_pci_phb_probe(struct of_device *dev,
const struct of_device_id *match)
{
struct pci_controller *phb;
/* Check if we can do that ... */
if (ppc_md.pci_setup_phb == NULL)
return -ENODEV;
printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name);
/* Alloc and setup PHB data structure */
phb = pcibios_alloc_controller(dev->node);
if (!phb)
return -ENODEV;
/* Setup parent in sysfs */
phb->parent = &dev->dev;
/* Setup the PHB using arch provided callback */
if (ppc_md.pci_setup_phb(phb)) {
pcibios_free_controller(phb);
return -ENODEV;
}
/* Process "ranges" property */
pci_process_bridge_OF_ranges(phb, dev->node, 0);
/* Setup IO space.
* This will not work properly for ISA IOs, something needs to be done
* about it if we ever generalize that way of probing PCI brigdes
*/
pci_setup_phb_io_dynamic(phb, 0);
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic(phb);
/* Register devices with EEH */
#ifdef CONFIG_EEH
if (dev->node->child)
eeh_add_device_tree_early(dev->node);
#endif /* CONFIG_EEH */
/* Scan the bus */
scan_phb(phb);
/* Claim resources. This might need some rework as well depending
* wether we are doing probe-only or not, like assigning unassigned
* resources etc...
*/
pcibios_claim_one_bus(phb->bus);
/* Finish EEH setup */
#ifdef CONFIG_EEH
eeh_add_device_tree_late(phb->bus);
#endif
/* Add probed PCI devices to the device model */
pci_bus_add_devices(phb->bus);
return 0;
}
static struct of_device_id of_pci_phb_ids[] = {
{ .type = "pci", },
{ .type = "pcix", },
{ .type = "pcie", },
{ .type = "pciex", },
{ .type = "ht", },
{}
};
static struct of_platform_driver of_pci_phb_driver = {
.name = "of-pci",
.match_table = of_pci_phb_ids,
.probe = of_pci_phb_probe,
.driver = {
.multithread_probe = 1,
},
};
static __init int of_pci_phb_init(void)
{
return of_register_platform_driver(&of_pci_phb_driver);
}
device_initcall(of_pci_phb_init);
#endif /* CONFIG_PPC_OF_PLATFORM_PCI */

View File

@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
#include <linux/list.h>
#include <asm/processor.h>
#include <asm/io.h>
@ -99,7 +100,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
continue;
if (res->end == 0xffffffff) {
DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
pci_name(dev), i, res->start, res->end);
pci_name(dev), i, (u64)res->start, (u64)res->end);
res->end -= res->start;
res->start = 0;
res->flags |= IORESOURCE_UNSET;
@ -115,11 +116,9 @@ pcibios_fixup_resources(struct pci_dev *dev)
if (offset != 0) {
res->start += offset;
res->end += offset;
#ifdef DEBUG
printk("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
res->start - offset, res->start);
#endif
DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
(u64)res->start - offset, (u64)res->start);
}
}
@ -255,7 +254,7 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
}
DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
res->start, res->end, res->flags, pr);
(u64)res->start, (u64)res->end, res->flags, pr);
if (pr) {
if (request_resource(pr, res) == 0)
continue;
@ -306,7 +305,7 @@ reparent_resources(struct resource *parent, struct resource *res)
for (p = res->child; p != NULL; p = p->sibling) {
p->parent = res;
DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
p->name, p->start, p->end, res->name);
p->name, (u64)p->start, (u64)p->end, res->name);
}
return 0;
}
@ -362,7 +361,7 @@ pci_relocate_bridge_resource(struct pci_bus *bus, int i)
}
if (request_resource(pr, res)) {
DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
res->start, res->end);
(u64)res->start, (u64)res->end);
return -1; /* "can't happen" */
}
update_bridge_base(bus, i);
@ -480,14 +479,14 @@ static inline void alloc_resource(struct pci_dev *dev, int idx)
struct resource *pr, *r = &dev->resource[idx];
DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
pci_name(dev), idx, r->start, r->end, r->flags);
pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate resource region %d"
" of device %s\n", idx, pci_name(dev));
if (pr)
DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
pr, pr->start, pr->end, pr->flags);
pr, (u64)pr->start, (u64)pr->end, pr->flags);
/* We'll assign a new address later */
r->flags |= IORESOURCE_UNSET;
r->end -= r->start;
@ -960,7 +959,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
res->flags = IORESOURCE_IO;
res->start = ranges[2];
DBG("PCI: IO 0x%llx -> 0x%llx\n",
res->start, res->start + size - 1);
(u64)res->start, (u64)res->start + size - 1);
break;
case 2: /* memory space */
memno = 0;
@ -982,7 +981,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
res->flags |= IORESOURCE_PREFETCH;
res->start = ranges[na+2];
DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
res->start, res->start + size - 1);
(u64)res->start, (u64)res->start + size - 1);
}
break;
}
@ -1268,7 +1267,10 @@ pcibios_init(void)
if (pci_assign_all_buses)
hose->first_busno = next_busno;
hose->last_busno = 0xff;
bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
bus = pci_scan_bus_parented(hose->parent, hose->first_busno,
hose->ops, hose);
if (bus)
pci_bus_add_devices(bus);
hose->last_busno = bus->subordinate;
if (pci_assign_all_buses || next_busno <= hose->last_busno)
next_busno = hose->last_busno + pcibios_assign_bus_offset;
@ -1282,10 +1284,6 @@ pcibios_init(void)
if (pci_assign_all_buses && have_of)
pcibios_make_OF_bus_map();
/* Do machine dependent PCI interrupt routing */
if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
/* Call machine dependent fixup */
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
@ -1308,25 +1306,6 @@ pcibios_init(void)
subsys_initcall(pcibios_init);
unsigned char __init
common_swizzle(struct pci_dev *dev, unsigned char *pinp)
{
struct pci_controller *hose = dev->sysdata;
if (dev->bus->number != hose->first_busno) {
u8 pin = *pinp;
do {
pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
/* Move up the chain of bridges. */
dev = dev->bus->self;
} while (dev->bus->self);
*pinp = pin;
/* The slot is the idsel of the last bridge. */
}
return PCI_SLOT(dev->devfn);
}
unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
unsigned long start, unsigned long size)
{
@ -1338,6 +1317,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
unsigned long io_offset;
struct resource *res;
struct pci_dev *dev;
int i;
io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
@ -1390,8 +1370,16 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
}
}
/* Platform specific bus fixups */
if (ppc_md.pcibios_fixup_bus)
ppc_md.pcibios_fixup_bus(bus);
/* Read default IRQs and fixup if necessary */
list_for_each_entry(dev, &bus->devices, bus_list) {
pci_read_irq_line(dev);
if (ppc_md.pci_irq_fixup)
ppc_md.pci_irq_fixup(dev);
}
}
char __init *pcibios_setup(char *str)
@ -1571,7 +1559,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
*offset += hose->pci_mem_offset;
res_bit = IORESOURCE_MEM;
} else {
io_offset = hose->io_base_virt - ___IO_BASE;
io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE;
*offset += io_offset;
res_bit = IORESOURCE_IO;
}
@ -1826,7 +1814,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
return;
if (rsrc->flags & IORESOURCE_IO)
offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
offset = (void __iomem *)_IO_BASE - hose->io_base_virt
+ hose->io_base_phys;
*start = rsrc->start + offset;
*end = rsrc->end + offset;
@ -1845,35 +1834,6 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
res->child = NULL;
}
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
{
unsigned long start = pci_resource_start(dev, bar);
unsigned long len = pci_resource_len(dev, bar);
unsigned long flags = pci_resource_flags(dev, bar);
if (!len)
return NULL;
if (max && len > max)
len = max;
if (flags & IORESOURCE_IO)
return ioport_map(start, len);
if (flags & IORESOURCE_MEM)
/* Not checking IORESOURCE_CACHEABLE because PPC does
* not currently distinguish between ioremap and
* ioremap_nocache.
*/
return ioremap(start, len);
/* What? */
return NULL;
}
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
/* Nothing to do */
}
EXPORT_SYMBOL(pci_iomap);
EXPORT_SYMBOL(pci_iounmap);
unsigned long pci_address_to_pio(phys_addr_t address)
{
struct pci_controller* hose = hose_head;

View File

@ -42,11 +42,9 @@
unsigned long pci_probe_only = 1;
int pci_assign_all_buses = 0;
#ifdef CONFIG_PPC_MULTIPLATFORM
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);
#endif
/* 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),
@ -63,7 +61,7 @@ void iSeries_pcibios_init(void);
LIST_HEAD(hose_list);
struct dma_mapping_ops pci_dma_ops;
struct dma_mapping_ops *pci_dma_ops;
EXPORT_SYMBOL(pci_dma_ops);
int global_phb_number; /* Global phb counter */
@ -212,6 +210,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
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);
}
@ -251,7 +253,6 @@ static void __init pcibios_claim_of_setup(void)
pcibios_claim_one_bus(b);
}
#ifdef CONFIG_PPC_MULTIPLATFORM
static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
{
const u32 *prop;
@ -329,7 +330,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
struct pci_dev *dev;
const char *type;
dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev)
return NULL;
type = get_property(node, "device_type", NULL);
@ -338,7 +339,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
DBG(" create device, devfn: %x, type: %s\n", devfn, type);
memset(dev, 0, sizeof(struct pci_dev));
dev->bus = bus;
dev->sysdata = node;
dev->dev.parent = bus->bridge;
@ -506,7 +506,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
pci_scan_child_bus(bus);
}
EXPORT_SYMBOL(of_scan_pci_bridge);
#endif /* CONFIG_PPC_MULTIPLATFORM */
void __devinit scan_phb(struct pci_controller *hose)
{
@ -517,7 +516,7 @@ void __devinit scan_phb(struct pci_controller *hose)
DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
if (bus == NULL) {
printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
hose->global_number);
@ -540,7 +539,7 @@ void __devinit scan_phb(struct pci_controller *hose)
}
mode = PCI_PROBE_NORMAL;
#ifdef CONFIG_PPC_MULTIPLATFORM
if (node && ppc_md.pci_probe_mode)
mode = ppc_md.pci_probe_mode(bus);
DBG(" probe mode: %d\n", mode);
@ -548,7 +547,7 @@ void __devinit scan_phb(struct pci_controller *hose)
bus->subordinate = hose->last_busno;
of_scan_bus(node, bus);
}
#endif /* CONFIG_PPC_MULTIPLATFORM */
if (mode == PCI_PROBE_NORMAL)
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
}
@ -592,11 +591,9 @@ static int __init pcibios_init(void)
if (ppc64_isabridge_dev != NULL)
printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
#ifdef CONFIG_PPC_MULTIPLATFORM
if (!firmware_has_feature(FW_FEATURE_ISERIES))
/* map in PCI I/O space */
phbs_remap_io();
#endif
printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
@ -873,8 +870,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev)
device_create_file(&pdev->dev, &dev_attr_devspec);
}
#ifdef CONFIG_PPC_MULTIPLATFORM
#define ISA_SPACE_MASK 0x1
#define ISA_SPACE_IO 0x1
@ -975,11 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
res = NULL;
pci_space = ranges[0];
pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
cpu_phys_addr = ranges[3];
if (na >= 2)
cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
cpu_phys_addr = of_translate_address(dev, &ranges[3]);
size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
ranges += np;
if (size == 0)
@ -1145,7 +1136,7 @@ int unmap_bus_range(struct pci_bus *bus)
if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
return 1;
if (iounmap_explicit((void __iomem *) start_virt, size))
if (__iounmap_explicit((void __iomem *) start_virt, size))
return 1;
return 0;
@ -1213,23 +1204,52 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
}
EXPORT_SYMBOL(pcibios_fixup_device_resources);
void __devinit pcibios_setup_new_device(struct pci_dev *dev)
{
struct dev_archdata *sd = &dev->dev.archdata;
sd->of_node = pci_device_to_OF_node(dev);
DBG("PCI device %s OF node: %s\n", pci_name(dev),
sd->of_node ? sd->of_node->full_name : "<none>");
sd->dma_ops = pci_dma_ops;
#ifdef CONFIG_NUMA
sd->numa_node = pcibus_to_node(dev->bus);
#else
sd->numa_node = -1;
#endif
if (ppc_md.pci_dma_dev_setup)
ppc_md.pci_dma_dev_setup(dev);
}
EXPORT_SYMBOL(pcibios_setup_new_device);
static void __devinit do_bus_setup(struct pci_bus *bus)
{
struct pci_dev *dev;
ppc_md.iommu_bus_setup(bus);
if (ppc_md.pci_dma_bus_setup)
ppc_md.pci_dma_bus_setup(bus);
list_for_each_entry(dev, &bus->devices, bus_list)
ppc_md.iommu_dev_setup(dev);
pcibios_setup_new_device(dev);
if (ppc_md.irq_bus_setup)
ppc_md.irq_bus_setup(bus);
/* Read default IRQs and fixup if necessary */
list_for_each_entry(dev, &bus->devices, bus_list) {
pci_read_irq_line(dev);
if (ppc_md.pci_irq_fixup)
ppc_md.pci_irq_fixup(dev);
}
}
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_dev *dev = bus->self;
struct device_node *np;
np = pci_bus_to_OF_node(bus);
DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>");
if (dev && pci_probe_only &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
@ -1343,8 +1363,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
return NULL;
}
#endif /* CONFIG_PPC_MULTIPLATFORM */
unsigned long pci_address_to_pio(phys_addr_t address)
{
struct pci_controller *hose, *tmp;

View File

@ -1,98 +0,0 @@
/*
* Support for DMA from PCI devices to main memory on
* machines without an iommu or with directly addressable
* RAM (typically a pmac with 2Gb of RAM or less)
*
* Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/pmac_feature.h>
#include <asm/abs_addr.h>
#include <asm/ppc-pci.h>
static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
void *ret;
ret = (void *)__get_free_pages(flag, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
*dma_handle = virt_to_abs(ret);
}
return ret;
}
static void pci_direct_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
free_pages((unsigned long)vaddr, get_order(size));
}
static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr,
size_t size, enum dma_data_direction direction)
{
return virt_to_abs(ptr);
}
static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction)
{
}
static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
int i;
for (i = 0; i < nents; i++, sg++) {
sg->dma_address = page_to_phys(sg->page) + sg->offset;
sg->dma_length = sg->length;
}
return nents;
}
static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
}
static int pci_direct_dma_supported(struct device *dev, u64 mask)
{
return mask < 0x100000000ull;
}
static struct dma_mapping_ops pci_direct_ops = {
.alloc_coherent = pci_direct_alloc_coherent,
.free_coherent = pci_direct_free_coherent,
.map_single = pci_direct_map_single,
.unmap_single = pci_direct_unmap_single,
.map_sg = pci_direct_map_sg,
.unmap_sg = pci_direct_unmap_sg,
.dma_supported = pci_direct_dma_supported,
};
void __init pci_direct_iommu_init(void)
{
pci_dma_ops = pci_direct_ops;
}

View File

@ -1,164 +0,0 @@
/*
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
*
* Rewrite, cleanup, new allocation schemes:
* Copyright (C) 2004 Olof Johansson, IBM Corporation
*
* Dynamic DMA mapping support, platform-independent parts.
*
* 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.
*
* 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 <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/ppc-pci.h>
/*
* We can use ->sysdata directly and avoid the extra work in
* pci_device_to_OF_node since ->sysdata will have been initialised
* in the iommu init code for all devices.
*/
#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
static inline struct iommu_table *device_to_table(struct device *hwdev)
{
struct pci_dev *pdev;
if (!hwdev) {
pdev = ppc64_isabridge_dev;
if (!pdev)
return NULL;
} else
pdev = to_pci_dev(hwdev);
return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
}
static inline unsigned long device_to_mask(struct device *hwdev)
{
struct pci_dev *pdev;
if (!hwdev) {
pdev = ppc64_isabridge_dev;
if (!pdev) /* This is the best guess we can do */
return 0xfffffffful;
} else
pdev = to_pci_dev(hwdev);
if (pdev->dma_mask)
return pdev->dma_mask;
/* Assume devices without mask can take 32 bit addresses */
return 0xfffffffful;
}
/* Allocates a contiguous real buffer and creates mappings over it.
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
device_to_mask(hwdev), flag,
pcibus_to_node(to_pci_dev(hwdev)->bus));
}
static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
}
/* Creates TCEs for a user provided buffer. The user buffer must be
* contiguous real kernel storage (not vmalloc). The address of the buffer
* passed here is the kernel (virtual) address of the buffer. The buffer
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
return iommu_map_single(device_to_table(hwdev), vaddr, size,
device_to_mask(hwdev), direction);
}
static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
}
static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(pdev, device_to_table(pdev), sglist,
nelems, device_to_mask(pdev), direction);
}
static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
}
/* We support DMA to/from any memory page via the iommu */
static int pci_iommu_dma_supported(struct device *dev, u64 mask)
{
struct iommu_table *tbl = device_to_table(dev);
if (!tbl || tbl->it_offset > mask) {
printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
if (tbl)
printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
mask, tbl->it_offset);
else
printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
mask);
return 0;
} else
return 1;
}
struct dma_mapping_ops pci_iommu_ops = {
.alloc_coherent = pci_iommu_alloc_coherent,
.free_coherent = pci_iommu_free_coherent,
.map_single = pci_iommu_map_single,
.unmap_single = pci_iommu_unmap_single,
.map_sg = pci_iommu_map_sg,
.unmap_sg = pci_iommu_unmap_sg,
.dma_supported = pci_iommu_dma_supported,
};
void pci_iommu_init(void)
{
pci_dma_ops = pci_iommu_ops;
}

View File

@ -49,6 +49,10 @@
#include <asm/commproc.h>
#endif
#ifdef CONFIG_PPC64
EXPORT_SYMBOL(local_irq_restore);
#endif
#ifdef CONFIG_PPC32
extern void transfer_to_handler(void);
extern void do_IRQ(struct pt_regs *regs);

View File

@ -538,35 +538,31 @@ static struct ibm_pa_feature {
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
};
static void __init check_cpu_pa_features(unsigned long node)
static void __init scan_features(unsigned long node, unsigned char *ftrs,
unsigned long tablelen,
struct ibm_pa_feature *fp,
unsigned long ft_size)
{
unsigned char *pa_ftrs;
unsigned long len, tablelen, i, bit;
pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
if (pa_ftrs == NULL)
return;
unsigned long i, len, bit;
/* find descriptor with type == 0 */
for (;;) {
if (tablelen < 3)
return;
len = 2 + pa_ftrs[0];
len = 2 + ftrs[0];
if (tablelen < len)
return; /* descriptor 0 not found */
if (pa_ftrs[1] == 0)
if (ftrs[1] == 0)
break;
tablelen -= len;
pa_ftrs += len;
ftrs += len;
}
/* loop over bits we know about */
for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) {
struct ibm_pa_feature *fp = &ibm_pa_features[i];
if (fp->pabyte >= pa_ftrs[0])
for (i = 0; i < ft_size; ++i, ++fp) {
if (fp->pabyte >= ftrs[0])
continue;
bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
if (bit ^ fp->invert) {
cur_cpu_spec->cpu_features |= fp->cpu_features;
cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
@ -577,16 +573,59 @@ static void __init check_cpu_pa_features(unsigned long node)
}
}
static void __init check_cpu_pa_features(unsigned long node)
{
unsigned char *pa_ftrs;
unsigned long tablelen;
pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
if (pa_ftrs == NULL)
return;
scan_features(node, pa_ftrs, tablelen,
ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
}
static struct feature_property {
const char *name;
u32 min_value;
unsigned long cpu_feature;
unsigned long cpu_user_ftr;
} feature_properties[] __initdata = {
#ifdef CONFIG_ALTIVEC
{"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
{"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_PPC64
{"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP},
{"ibm,purr", 1, CPU_FTR_PURR, 0},
{"ibm,spurr", 1, CPU_FTR_SPURR, 0},
#endif /* CONFIG_PPC64 */
};
static void __init check_cpu_feature_properties(unsigned long node)
{
unsigned long i;
struct feature_property *fp = feature_properties;
const u32 *prop;
for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {
prop = of_get_flat_dt_prop(node, fp->name, NULL);
if (prop && *prop >= fp->min_value) {
cur_cpu_spec->cpu_features |= fp->cpu_feature;
cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr;
}
}
}
static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth,
void *data)
{
static int logical_cpuid = 0;
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
#ifdef CONFIG_ALTIVEC
u32 *prop;
#endif
u32 *intserv;
const u32 *prop;
const u32 *intserv;
int i, nthreads;
unsigned long len;
int found = 0;
@ -643,24 +682,27 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
intserv[i]);
boot_cpuid = logical_cpuid;
set_hard_smp_processor_id(boot_cpuid, intserv[i]);
/*
* PAPR defines "logical" PVR values for cpus that
* meet various levels of the architecture:
* 0x0f000001 Architecture version 2.04
* 0x0f000002 Architecture version 2.05
* If the cpu-version property in the cpu node contains
* such a value, we call identify_cpu again with the
* logical PVR value in order to use the cpu feature
* bits appropriate for the architecture level.
*
* A POWER6 partition in "POWER6 architected" mode
* uses the 0x0f000002 PVR value; in POWER5+ mode
* it uses 0x0f000001.
*/
prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
if (prop && (*prop & 0xff000000) == 0x0f000000)
identify_cpu(0, *prop);
}
#ifdef CONFIG_ALTIVEC
/* Check if we have a VMX and eventually update CPU features */
prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL);
if (prop && (*prop) > 0) {
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
}
/* Same goes for Apple's "altivec" property */
prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL);
if (prop) {
cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
}
#endif /* CONFIG_ALTIVEC */
check_cpu_feature_properties(node);
check_cpu_pa_features(node);
#ifdef CONFIG_PPC_PSERIES
@ -1674,6 +1716,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
}
return NULL;
}
EXPORT_SYMBOL(of_get_cpu_node);
#ifdef DEBUG
static struct debugfs_blob_wrapper flat_dt_blob;

View File

@ -173,8 +173,8 @@ static unsigned long __initdata dt_string_start, dt_string_end;
static unsigned long __initdata prom_initrd_start, prom_initrd_end;
#ifdef CONFIG_PPC64
static int __initdata iommu_force_on;
static int __initdata ppc64_iommu_off;
static int __initdata prom_iommu_force_on;
static int __initdata prom_iommu_off;
static unsigned long __initdata prom_tce_alloc_start;
static unsigned long __initdata prom_tce_alloc_end;
#endif
@ -582,9 +582,9 @@ static void __init early_cmdline_parse(void)
while (*opt && *opt == ' ')
opt++;
if (!strncmp(opt, RELOC("off"), 3))
RELOC(ppc64_iommu_off) = 1;
RELOC(prom_iommu_off) = 1;
else if (!strncmp(opt, RELOC("force"), 5))
RELOC(iommu_force_on) = 1;
RELOC(prom_iommu_force_on) = 1;
}
#endif
}
@ -627,6 +627,7 @@ static void __init early_cmdline_parse(void)
/* Option vector 3: processor options supported */
#define OV3_FP 0x80 /* floating point */
#define OV3_VMX 0x40 /* VMX/Altivec */
#define OV3_DFP 0x20 /* decimal FP */
/* Option vector 5: PAPR/OF options supported */
#define OV5_LPAR 0x80 /* logical partitioning supported */
@ -642,6 +643,7 @@ static void __init early_cmdline_parse(void)
static unsigned char ibm_architecture_vec[] = {
W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
W(0xffff0000), W(0x003e0000), /* POWER6 */
W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
5 - 1, /* 5 option vectors */
@ -668,7 +670,7 @@ static unsigned char ibm_architecture_vec[] = {
/* option vector 3: processor options supported */
3 - 2, /* length */
0, /* don't ignore, don't halt */
OV3_FP | OV3_VMX,
OV3_FP | OV3_VMX | OV3_DFP,
/* option vector 4: IBM PAPR implementation */
2 - 2, /* length */
@ -1167,7 +1169,7 @@ static void __init prom_initialize_tce_table(void)
u64 local_alloc_top, local_alloc_bottom;
u64 i;
if (RELOC(ppc64_iommu_off))
if (RELOC(prom_iommu_off))
return;
prom_debug("starting prom_initialize_tce_table\n");
@ -2283,11 +2285,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* Fill in some infos for use by the kernel later on
*/
#ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off))
if (RELOC(prom_iommu_off))
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
NULL, 0);
if (RELOC(iommu_force_on))
if (RELOC(prom_iommu_force_on))
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
NULL, 0);

View File

@ -25,6 +25,12 @@
#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
(ns) > 0)
static struct of_bus *of_match_bus(struct device_node *np);
static int __of_address_to_resource(struct device_node *dev,
const u32 *addrp, u64 size, unsigned int flags,
struct resource *r);
/* Debug utility */
#ifdef DEBUG
static void of_dump_addr(const char *s, const u32 *addr, int na)
@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr)
}
#ifdef CONFIG_PCI
/*
* PCI bus specific translator
*/
@ -153,15 +160,156 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr)
switch((w >> 24) & 0x03) {
case 0x01:
flags |= IORESOURCE_IO;
break;
case 0x02: /* 32 bits */
case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM;
break;
}
if (w & 0x40000000)
flags |= IORESOURCE_PREFETCH;
return flags;
}
const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
unsigned int *flags)
{
const u32 *prop;
unsigned int psize;
struct device_node *parent;
struct of_bus *bus;
int onesize, i, na, ns;
/* Get parent & match bus type */
parent = of_get_parent(dev);
if (parent == NULL)
return NULL;
bus = of_match_bus(parent);
if (strcmp(bus->name, "pci")) {
of_node_put(parent);
return NULL;
}
bus->count_cells(dev, &na, &ns);
of_node_put(parent);
if (!OF_CHECK_COUNTS(na, ns))
return NULL;
/* Get "reg" or "assigned-addresses" property */
prop = get_property(dev, bus->addresses, &psize);
if (prop == NULL)
return NULL;
psize /= 4;
onesize = na + ns;
for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
if (size)
*size = of_read_number(prop + na, ns);
if (flags)
*flags = bus->get_flags(prop);
return prop;
}
return NULL;
}
EXPORT_SYMBOL(of_get_pci_address);
int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r)
{
const u32 *addrp;
u64 size;
unsigned int flags;
addrp = of_get_pci_address(dev, bar, &size, &flags);
if (addrp == NULL)
return -EINVAL;
return __of_address_to_resource(dev, addrp, size, flags, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
{
return (((pin - 1) + slot) % 4) + 1;
}
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
{
struct device_node *dn, *ppnode;
struct pci_dev *ppdev;
u32 lspec;
u32 laddr[3];
u8 pin;
int rc;
/* Check if we have a device node, if yes, fallback to standard OF
* parsing
*/
dn = pci_device_to_OF_node(pdev);
if (dn)
return of_irq_map_one(dn, 0, out_irq);
/* Ok, we don't, time to have fun. Let's start by building up an
* interrupt spec. we assume #interrupt-cells is 1, which is standard
* for PCI. If you do different, then don't use that routine.
*/
rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
if (rc != 0)
return rc;
/* No pin, exit */
if (pin == 0)
return -ENODEV;
/* Now we walk up the PCI tree */
lspec = pin;
for (;;) {
/* Get the pci_dev of our parent */
ppdev = pdev->bus->self;
/* Ouch, it's a host bridge... */
if (ppdev == NULL) {
#ifdef CONFIG_PPC64
ppnode = pci_bus_to_OF_node(pdev->bus);
#else
struct pci_controller *host;
host = pci_bus_to_host(pdev->bus);
ppnode = host ? host->arch_data : NULL;
#endif
/* No node for host bridge ? give up */
if (ppnode == NULL)
return -EINVAL;
} else
/* We found a P2P bridge, check if it has a node */
ppnode = pci_device_to_OF_node(ppdev);
/* Ok, we have found a parent with a device-node, hand over to
* the OF parsing code.
* We build a unit address from the linux device to be used for
* resolution. Note that we use the linux bus number which may
* not match your firmware bus numbering.
* Fortunately, in most cases, interrupt-map-mask doesn't include
* the bus number as part of the matching.
* You should still be careful about that though if you intend
* to rely on this function (you ship a firmware that doesn't
* create device nodes for all PCI devices).
*/
if (ppnode)
break;
/* We can only get here if we hit a P2P bridge with no node,
* let's do standard swizzling and try again
*/
lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
pdev = ppdev;
}
laddr[0] = (pdev->bus->number << 16)
| (pdev->devfn << 8);
laddr[1] = laddr[2] = 0;
return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
}
EXPORT_SYMBOL_GPL(of_irq_map_pci);
#endif /* CONFIG_PCI */
/*
* ISA bus specific translator
*/
@ -223,6 +371,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr)
*/
static struct of_bus of_busses[] = {
#ifdef CONFIG_PCI
/* PCI */
{
.name = "pci",
@ -233,6 +382,7 @@ static struct of_bus of_busses[] = {
.translate = of_bus_pci_translate,
.get_flags = of_bus_pci_get_flags,
},
#endif /* CONFIG_PCI */
/* ISA */
{
.name = "isa",
@ -445,48 +595,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
}
EXPORT_SYMBOL(of_get_address);
const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
unsigned int *flags)
{
const u32 *prop;
unsigned int psize;
struct device_node *parent;
struct of_bus *bus;
int onesize, i, na, ns;
/* Get parent & match bus type */
parent = of_get_parent(dev);
if (parent == NULL)
return NULL;
bus = of_match_bus(parent);
if (strcmp(bus->name, "pci")) {
of_node_put(parent);
return NULL;
}
bus->count_cells(dev, &na, &ns);
of_node_put(parent);
if (!OF_CHECK_COUNTS(na, ns))
return NULL;
/* Get "reg" or "assigned-addresses" property */
prop = get_property(dev, bus->addresses, &psize);
if (prop == NULL)
return NULL;
psize /= 4;
onesize = na + ns;
for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
if (size)
*size = of_read_number(prop + na, ns);
if (flags)
*flags = bus->get_flags(prop);
return prop;
}
return NULL;
}
EXPORT_SYMBOL(of_get_pci_address);
static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
u64 size, unsigned int flags,
struct resource *r)
@ -529,20 +637,6 @@ int of_address_to_resource(struct device_node *dev, int index,
}
EXPORT_SYMBOL_GPL(of_address_to_resource);
int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r)
{
const u32 *addrp;
u64 size;
unsigned int flags;
addrp = of_get_pci_address(dev, bar, &size, &flags);
if (addrp == NULL)
return -EINVAL;
return __of_address_to_resource(dev, addrp, size, flags, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
unsigned long *busno, unsigned long *phys, unsigned long *size)
{
@ -898,87 +992,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
return res;
}
EXPORT_SYMBOL_GPL(of_irq_map_one);
#ifdef CONFIG_PCI
static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
{
return (((pin - 1) + slot) % 4) + 1;
}
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
{
struct device_node *dn, *ppnode;
struct pci_dev *ppdev;
u32 lspec;
u32 laddr[3];
u8 pin;
int rc;
/* Check if we have a device node, if yes, fallback to standard OF
* parsing
*/
dn = pci_device_to_OF_node(pdev);
if (dn)
return of_irq_map_one(dn, 0, out_irq);
/* Ok, we don't, time to have fun. Let's start by building up an
* interrupt spec. we assume #interrupt-cells is 1, which is standard
* for PCI. If you do different, then don't use that routine.
*/
rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
if (rc != 0)
return rc;
/* No pin, exit */
if (pin == 0)
return -ENODEV;
/* Now we walk up the PCI tree */
lspec = pin;
for (;;) {
/* Get the pci_dev of our parent */
ppdev = pdev->bus->self;
/* Ouch, it's a host bridge... */
if (ppdev == NULL) {
#ifdef CONFIG_PPC64
ppnode = pci_bus_to_OF_node(pdev->bus);
#else
struct pci_controller *host;
host = pci_bus_to_host(pdev->bus);
ppnode = host ? host->arch_data : NULL;
#endif
/* No node for host bridge ? give up */
if (ppnode == NULL)
return -EINVAL;
} else
/* We found a P2P bridge, check if it has a node */
ppnode = pci_device_to_OF_node(ppdev);
/* Ok, we have found a parent with a device-node, hand over to
* the OF parsing code.
* We build a unit address from the linux device to be used for
* resolution. Note that we use the linux bus number which may
* not match your firmware bus numbering.
* Fortunately, in most cases, interrupt-map-mask doesn't include
* the bus number as part of the matching.
* You should still be careful about that though if you intend
* to rely on this function (you ship a firmware that doesn't
* create device nodes for all PCI devices).
*/
if (ppnode)
break;
/* We can only get here if we hit a P2P bridge with no node,
* let's do standard swizzling and try again
*/
lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
pdev = ppdev;
}
laddr[0] = (pdev->bus->number << 16)
| (pdev->devfn << 8);
laddr[1] = laddr[2] = 0;
return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
}
EXPORT_SYMBOL_GPL(of_irq_map_pci);
#endif /* CONFIG_PCI */

View File

@ -810,9 +810,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
/* This version can't take the spinlock, because it never returns */
struct rtas_args rtas_stop_self_args = {
static struct rtas_args rtas_stop_self_args = {
/* The token is initialized for real in setup_system() */
.token = RTAS_UNKNOWN_SERVICE,
.nargs = 0,
@ -834,6 +834,7 @@ void rtas_stop_self(void)
panic("Alas, I survived.\n");
}
#endif
/*
* Call early during boot, before mem init or bootmem, to retrieve the RTAS

View File

@ -681,14 +681,12 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
int *status;
int token;
dp->data = kmalloc(buf_size, GFP_KERNEL);
dp->data = kzalloc(buf_size, GFP_KERNEL);
if (dp->data == NULL) {
remove_flash_pde(dp);
return -ENOMEM;
}
memset(dp->data, 0, buf_size);
/*
* This code assumes that the status int is the first member of the
* struct

View File

@ -38,6 +38,7 @@
#include <asm/rtas.h>
#include <asm/mpic.h>
#include <asm/ppc-pci.h>
#include <asm/eeh.h>
/* RTAS tokens */
static int read_pci_config;
@ -231,32 +232,13 @@ void __init init_pci_config_tokens (void)
unsigned long __devinit get_phb_buid (struct device_node *phb)
{
int addr_cells;
const unsigned int *buid_vals;
unsigned int len;
unsigned long buid;
struct resource r;
if (ibm_read_pci_config == -1) return 0;
/* PHB's will always be children of the root node,
* or so it is promised by the current firmware. */
if (phb->parent == NULL)
if (ibm_read_pci_config == -1)
return 0;
if (phb->parent->parent)
if (of_address_to_resource(phb, 0, &r))
return 0;
buid_vals = get_property(phb, "reg", &len);
if (buid_vals == NULL)
return 0;
addr_cells = prom_n_addr_cells(phb);
if (addr_cells == 1) {
buid = (unsigned long) buid_vals[0];
} else {
buid = (((unsigned long)buid_vals[0]) << 32UL) |
(((unsigned long)buid_vals[1]) & 0xffffffff);
}
return buid;
return r.start;
}
static int phb_set_bus_ranges(struct device_node *dev,
@ -276,8 +258,10 @@ static int phb_set_bus_ranges(struct device_node *dev,
return 0;
}
int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb)
int __devinit rtas_setup_phb(struct pci_controller *phb)
{
struct device_node *dev = phb->arch_data;
if (is_python(dev))
python_countermeasures(dev);
@ -309,7 +293,7 @@ unsigned long __init find_and_init_phbs(void)
phb = pcibios_alloc_controller(node);
if (!phb)
continue;
setup_phb(node, phb);
rtas_setup_phb(phb);
pci_process_bridge_OF_ranges(phb, node, 0);
pci_setup_phb_io(phb, index == 0);
index++;
@ -381,7 +365,6 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
}
}
list_del(&phb->list_node);
pcibios_free_controller(phb);
return 0;

View File

@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE;
int have_of = 1;
#ifdef CONFIG_PPC_MULTIPLATFORM
dev_t boot_dev;
#endif /* CONFIG_PPC_MULTIPLATFORM */
#ifdef CONFIG_VGA_CONSOLE
unsigned long vgacon_remap_base;
#endif
@ -101,7 +97,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
* Identify the CPU type and fix up code sections
* that depend on which cpu we have.
*/
spec = identify_cpu(offset);
spec = identify_cpu(offset, mfspr(SPRN_PVR));
do_feature_fixups(spec->cpu_features,
PTRRELOC(&__start___ftr_fixup),

View File

@ -33,6 +33,7 @@
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/bootmem.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/kdump.h>
#include <asm/prom.h>
@ -71,7 +72,6 @@
int have_of = 1;
int boot_cpuid = 0;
dev_t boot_dev;
u64 ppc64_pft_size;
/* Pick defaults since we might want to patch instructions
@ -171,7 +171,7 @@ void __init setup_paca(int cpu)
void __init early_setup(unsigned long dt_ptr)
{
/* Identify CPU type */
identify_cpu(0);
identify_cpu(0, mfspr(SPRN_PVR));
/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
setup_paca(0);
@ -226,8 +226,8 @@ void early_setup_secondary(void)
{
struct paca_struct *lpaca = get_paca();
/* Mark enabled in PACA */
lpaca->proc_enabled = 0;
/* Mark interrupts enabled in PACA */
lpaca->soft_enabled = 0;
/* Initialize hash table for that CPU */
htab_initialize_secondary();
@ -392,7 +392,8 @@ void __init setup_system(void)
* setting up the hash table pointers. It also sets up some interrupt-mapping
* related options that will be used by finish_device_tree()
*/
ppc_md.init_early();
if (ppc_md.init_early)
ppc_md.init_early();
/*
* We can discover serial ports now since the above did setup the
@ -598,3 +599,10 @@ void __init setup_per_cpu_areas(void)
}
}
#endif
#ifdef CONFIG_PPC_INDIRECT_IO
struct ppc_pci_io ppc_pci_io;
EXPORT_SYMBOL(ppc_pci_io);
#endif /* CONFIG_PPC_INDIRECT_IO */

View File

@ -78,7 +78,7 @@ static int __devinit start_contest(int cmd, long offset, int num)
{
int i, score=0;
u64 tb;
long mark;
u64 mark;
tbsync->cmd = cmd;
@ -116,8 +116,7 @@ void __devinit smp_generic_give_timebase(void)
printk("Synchronizing timebase\n");
/* if this fails then this kernel won't work anyway... */
tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL );
memset( tbsync, 0, sizeof(*tbsync) );
tbsync = kzalloc( sizeof(*tbsync), GFP_KERNEL );
mb();
running = 1;

View File

@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(cpu_sibling_map);
/* SMP operations for this machine */
struct smp_ops_t *smp_ops;

View File

@ -51,6 +51,7 @@
#include <asm/time.h>
#include <asm/mmu_context.h>
#include <asm/ppc-pci.h>
#include <asm/syscalls.h>
/* readdir & getdents */
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))

View File

@ -200,10 +200,9 @@ static void register_cpu_online(unsigned int cpu)
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
#ifndef CONFIG_PPC_ISERIES
if (cpu_has_feature(CPU_FTR_SMT))
if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
cpu_has_feature(CPU_FTR_SMT))
sysdev_create_file(s, &attr_smt_snooze_delay);
#endif
/* PMC stuff */
@ -242,10 +241,9 @@ static void unregister_cpu_online(unsigned int cpu)
BUG_ON(c->no_control);
#ifndef CONFIG_PPC_ISERIES
if (cpu_has_feature(CPU_FTR_SMT))
if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_smt_snooze_delay);
#endif
/* PMC stuff */
@ -299,6 +297,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
.notifier_call = sysfs_cpu_notify,
};
static DEFINE_MUTEX(cpu_mutex);
int cpu_add_sysdev_attr(struct sysdev_attribute *attr)
{
int cpu;
mutex_lock(&cpu_mutex);
for_each_possible_cpu(cpu) {
sysdev_create_file(get_cpu_sysdev(cpu), attr);
}
mutex_unlock(&cpu_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr);
int cpu_add_sysdev_attr_group(struct attribute_group *attrs)
{
int cpu;
struct sys_device *sysdev;
mutex_lock(&cpu_mutex);
for_each_possible_cpu(cpu) {
sysdev = get_cpu_sysdev(cpu);
sysfs_create_group(&sysdev->kobj, attrs);
}
mutex_unlock(&cpu_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group);
void cpu_remove_sysdev_attr(struct sysdev_attribute *attr)
{
int cpu;
mutex_lock(&cpu_mutex);
for_each_possible_cpu(cpu) {
sysdev_remove_file(get_cpu_sysdev(cpu), attr);
}
mutex_unlock(&cpu_mutex);
}
EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr);
void cpu_remove_sysdev_attr_group(struct attribute_group *attrs)
{
int cpu;
struct sys_device *sysdev;
mutex_lock(&cpu_mutex);
for_each_possible_cpu(cpu) {
sysdev = get_cpu_sysdev(cpu);
sysfs_remove_group(&sysdev->kobj, attrs);
}
mutex_unlock(&cpu_mutex);
}
EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group);
/* NUMA stuff */
#ifdef CONFIG_NUMA

View File

@ -631,7 +631,8 @@ void timer_interrupt(struct pt_regs * regs)
calculate_steal_time();
#ifdef CONFIG_PPC_ISERIES
get_lppaca()->int_dword.fields.decr_int = 0;
if (firmware_has_feature(FW_FEATURE_ISERIES))
get_lppaca()->int_dword.fields.decr_int = 0;
#endif
while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
@ -674,7 +675,7 @@ void timer_interrupt(struct pt_regs * regs)
set_dec(next_dec);
#ifdef CONFIG_PPC_ISERIES
if (hvlpevent_is_pending())
if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
process_hvlpevents();
#endif
@ -774,7 +775,7 @@ int do_settimeofday(struct timespec *tv)
* settimeofday to perform this operation.
*/
#ifdef CONFIG_PPC_ISERIES
if (first_settimeofday) {
if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
iSeries_tb_recal();
first_settimeofday = 0;
}

View File

@ -53,10 +53,6 @@
#endif
#include <asm/kexec.h>
#ifdef CONFIG_PPC64 /* XXX */
#define _IO_BASE pci_io_base
#endif
#ifdef CONFIG_DEBUGGER
int (*__debugger)(struct pt_regs *regs);
int (*__debugger_ipi)(struct pt_regs *regs);
@ -241,7 +237,7 @@ void system_reset_exception(struct pt_regs *regs)
*/
static inline int check_io_access(struct pt_regs *regs)
{
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
#ifdef CONFIG_PPC32
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
@ -274,7 +270,7 @@ static inline int check_io_access(struct pt_regs *regs)
return 1;
}
}
#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
#endif /* CONFIG_PPC32 */
return 0;
}

View File

@ -81,15 +81,15 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
struct iommu_table *tbl;
unsigned long offset, size;
dma_window = get_property(dev->dev.platform_data,
"ibm,my-dma-window", NULL);
dma_window = get_property(dev->dev.archdata.of_node,
"ibm,my-dma-window", NULL);
if (!dma_window)
return NULL;
tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
of_parse_dma_window(dev->dev.platform_data, dma_window,
&tbl->it_index, &offset, &size);
of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
&tbl->it_index, &offset, &size);
/* TCE table size - measured in tce entries */
tbl->it_size = size >> IOMMU_PAGE_SHIFT;
@ -117,7 +117,8 @@ static const struct vio_device_id *vio_match_device(
{
while (ids->type[0] != '\0') {
if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
device_is_compatible(dev->dev.platform_data, ids->compat))
device_is_compatible(dev->dev.archdata.of_node,
ids->compat))
return ids;
ids++;
}
@ -198,9 +199,9 @@ EXPORT_SYMBOL(vio_unregister_driver);
/* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev)
{
if (dev->platform_data) {
/* XXX free TCE table */
of_node_put(dev->platform_data);
if (dev->archdata.of_node) {
/* XXX should free TCE table */
of_node_put(dev->archdata.of_node);
}
kfree(to_vio_dev(dev));
}
@ -210,7 +211,7 @@ static void __devinit vio_dev_release(struct device *dev)
* @of_node: The OF node for this device.
*
* Creates and initializes a vio_dev structure from the data in
* of_node (dev.platform_data) and adds it to the list of virtual devices.
* of_node and adds it to the list of virtual devices.
* Returns a pointer to the created vio_dev or NULL if node has
* NULL device_type or compatible fields.
*/
@ -240,8 +241,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
if (viodev == NULL)
return NULL;
viodev->dev.platform_data = of_node_get(of_node);
viodev->irq = irq_of_parse_and_map(of_node, 0);
snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
@ -254,7 +253,10 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
if (unit_address != NULL)
viodev->unit_address = *unit_address;
}
viodev->iommu_table = vio_build_iommu_table(viodev);
viodev->dev.archdata.of_node = of_node_get(of_node);
viodev->dev.archdata.dma_ops = &dma_iommu_ops;
viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
/* init generic 'struct device' fields: */
viodev->dev.parent = &vio_bus_device.dev;
@ -285,10 +287,11 @@ static int __init vio_bus_init(void)
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
iommu_vio_init();
vio_bus_device.iommu_table = &vio_iommu_table;
vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
iSeries_vio_dev = &vio_bus_device.dev;
}
#endif
#endif /* CONFIG_PPC_ISERIES */
err = bus_register(&vio_bus_type);
if (err) {
@ -336,7 +339,7 @@ static ssize_t name_show(struct device *dev,
static ssize_t devspec_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct device_node *of_node = dev->platform_data;
struct device_node *of_node = dev->archdata.of_node;
return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
}
@ -353,62 +356,6 @@ void __devinit vio_unregister_device(struct vio_dev *viodev)
}
EXPORT_SYMBOL(vio_unregister_device);
static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
~0ul, direction);
}
static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
direction);
}
static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
nelems, ~0ul, direction);
}
static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
}
static void *vio_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
dma_handle, ~0ul, flag, -1);
}
static void vio_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
dma_handle);
}
static int vio_dma_supported(struct device *dev, u64 mask)
{
return 1;
}
struct dma_mapping_ops vio_dma_ops = {
.alloc_coherent = vio_alloc_coherent,
.free_coherent = vio_free_coherent,
.map_single = vio_map_single,
.unmap_single = vio_unmap_single,
.map_sg = vio_map_sg,
.unmap_sg = vio_unmap_sg,
.dma_supported = vio_dma_supported,
};
static int vio_bus_match(struct device *dev, struct device_driver *drv)
{
const struct vio_dev *vio_dev = to_vio_dev(dev);
@ -422,13 +369,14 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
const struct vio_dev *vio_dev = to_vio_dev(dev);
struct device_node *dn = dev->platform_data;
struct device_node *dn;
const char *cp;
int length;
if (!num_envp)
return -ENOMEM;
dn = dev->archdata.of_node;
if (!dn)
return -ENODEV;
cp = get_property(dn, "compatible", &length);
@ -465,7 +413,7 @@ struct bus_type vio_bus_type = {
*/
const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
{
return get_property(vdev->dev.platform_data, which, length);
return get_property(vdev->dev.archdata.of_node, which, length);
}
EXPORT_SYMBOL(vio_get_attribute);

View File

@ -8,7 +8,7 @@ endif
obj-y := fault.o mem.o lmb.o
obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o
hash-$(CONFIG_PPC_MULTIPLATFORM) := hash_native_64.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 \

View File

@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
/* kernel has accessed a bad area */
printk(KERN_ALERT "Unable to handle kernel paging request for ");
switch (regs->trap) {
case 0x300:
case 0x380:
printk("data at address 0x%08lx\n", regs->dar);
break;
case 0x400:
case 0x480:
printk("instruction fetch\n");
break;
default:
printk("unknown fault\n");
case 0x300:
case 0x380:
printk(KERN_ALERT "Unable to handle kernel paging request for "
"data at address 0x%08lx\n", regs->dar);
break;
case 0x400:
case 0x480:
printk(KERN_ALERT "Unable to handle kernel paging request for "
"instruction fetch\n");
break;
default:
printk(KERN_ALERT "Unable to handle kernel paging request for "
"unknown fault\n");
break;
}
printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n",
regs->nip);

View File

@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep)
clear_bit(HPTE_LOCK_BIT, word);
}
long native_hpte_insert(unsigned long hpte_group, unsigned long va,
static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long pa, unsigned long rflags,
unsigned long vflags, int psize)
{

View File

@ -277,7 +277,7 @@ static void __init htab_init_page_sizes(void)
* Not in the device-tree, let's fallback on known size
* list for 16M capable GP & GR
*/
if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries))
if (cpu_has_feature(CPU_FTR_16M_PAGE))
memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
sizeof(mmu_psize_defaults_gp));
found:

View File

@ -130,7 +130,7 @@ static int __init setup_kcore(void)
/* GFP_ATOMIC to avoid might_sleep warnings during boot */
kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
if (!kcore_mem)
panic("mem_init: kmalloc failed\n");
panic("%s: kmalloc failed\n", __FUNCTION__);
kclist_add(kcore_mem, __va(base), size);
}

View File

@ -141,30 +141,20 @@ void pte_free(struct page *ptepage)
__free_page(ptepage);
}
#ifndef CONFIG_PHYS_64BIT
void __iomem *
ioremap(phys_addr_t addr, unsigned long size)
{
return __ioremap(addr, size, _PAGE_NO_CACHE);
}
#else /* CONFIG_PHYS_64BIT */
void __iomem *
ioremap64(unsigned long long addr, unsigned long size)
{
return __ioremap(addr, size, _PAGE_NO_CACHE);
}
EXPORT_SYMBOL(ioremap64);
void __iomem *
ioremap(phys_addr_t addr, unsigned long size)
{
phys_addr_t addr64 = fixup_bigphys_addr(addr, size);
return ioremap64(addr64, size);
}
#endif /* CONFIG_PHYS_64BIT */
EXPORT_SYMBOL(ioremap);
void __iomem *
ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags)
{
return __ioremap(addr, size, flags);
}
EXPORT_SYMBOL(ioremap_flags);
void __iomem *
__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
{
@ -264,20 +254,7 @@ void iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(iounmap);
void __iomem *ioport_map(unsigned long port, unsigned int len)
{
return (void __iomem *) (port + _IO_BASE);
}
void ioport_unmap(void __iomem *addr)
{
/* Nothing to do */
}
EXPORT_SYMBOL(ioport_map);
EXPORT_SYMBOL(ioport_unmap);
int
map_page(unsigned long va, phys_addr_t pa, int flags)
int map_page(unsigned long va, phys_addr_t pa, int flags)
{
pmd_t *pd;
pte_t *pg;

View File

@ -113,7 +113,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
}
static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa,
unsigned long ea, unsigned long size,
unsigned long flags)
{
@ -129,22 +129,12 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
return (void __iomem *) (ea + (addr & ~PAGE_MASK));
}
void __iomem *
ioremap(unsigned long addr, unsigned long size)
{
return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
}
void __iomem * __ioremap(unsigned long addr, unsigned long size,
void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
unsigned long pa, ea;
void __iomem *ret;
if (firmware_has_feature(FW_FEATURE_ISERIES))
return (void __iomem *)addr;
/*
* Choose an address to map it to.
* Once the imalloc system is running, we use it.
@ -178,9 +168,28 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
return ret;
}
void __iomem * ioremap(phys_addr_t addr, unsigned long size)
{
unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
if (ppc_md.ioremap)
return ppc_md.ioremap(addr, size, flags);
return __ioremap(addr, size, flags);
}
void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
if (ppc_md.ioremap)
return ppc_md.ioremap(addr, size, flags);
return __ioremap(addr, size, flags);
}
#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
int __ioremap_explicit(unsigned long pa, unsigned long ea,
int __ioremap_explicit(phys_addr_t pa, unsigned long ea,
unsigned long size, unsigned long flags)
{
struct vm_struct *area;
@ -235,13 +244,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
*
* XXX what about calls before mem_init_done (ie python_countermeasures())
*/
void iounmap(volatile void __iomem *token)
void __iounmap(volatile void __iomem *token)
{
void *addr;
if (firmware_has_feature(FW_FEATURE_ISERIES))
return;
if (!mem_init_done)
return;
@ -250,6 +256,14 @@ void iounmap(volatile void __iomem *token)
im_free(addr);
}
void iounmap(volatile void __iomem *token)
{
if (ppc_md.iounmap)
ppc_md.iounmap(token);
else
__iounmap(token);
}
static int iounmap_subset_regions(unsigned long addr, unsigned long size)
{
struct vm_struct *area;
@ -268,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size)
return 0;
}
int iounmap_explicit(volatile void __iomem *start, unsigned long size)
int __iounmap_explicit(volatile void __iomem *start, unsigned long size)
{
struct vm_struct *area;
unsigned long addr;
@ -303,8 +317,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size)
}
EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(ioremap_flags);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__iounmap);
void __iomem * reserve_phb_iospace(unsigned long size)
{

View File

@ -23,6 +23,7 @@
#include <asm/cputable.h>
#include <asm/cacheflush.h>
#include <asm/smp.h>
#include <asm/firmware.h>
#include <linux/compiler.h>
#ifdef DEBUG
@ -193,6 +194,7 @@ static inline void patch_slb_encoding(unsigned int *insn_addr,
void slb_initialize(void)
{
unsigned long linear_llp, vmalloc_llp, io_llp;
unsigned long lflags, vflags;
static int slb_encoding_inited;
extern unsigned int *slb_miss_kernel_load_linear;
extern unsigned int *slb_miss_kernel_load_io;
@ -225,11 +227,12 @@ void slb_initialize(void)
#endif
}
get_paca()->stab_rr = SLB_NUM_BOLTED;
/* On iSeries the bolted entries have already been set up by
* the hypervisor from the lparMap data in head.S */
#ifndef CONFIG_PPC_ISERIES
{
unsigned long lflags, vflags;
if (firmware_has_feature(FW_FEATURE_ISERIES))
return;
lflags = SLB_VSID_KERNEL | linear_llp;
vflags = SLB_VSID_KERNEL | vmalloc_llp;
@ -247,8 +250,4 @@ void slb_initialize(void)
* elsewhere, we'll call _switch() which will bolt in the new
* one. */
asm volatile("isync":::"memory");
}
#endif /* CONFIG_PPC_ISERIES */
get_paca()->stab_rr = SLB_NUM_BOLTED;
}

View File

@ -11,6 +11,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
timer_int.o )
oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
oprofile-$(CONFIG_6xx) += op_model_7450.o

View File

@ -69,7 +69,10 @@ static void op_powerpc_cpu_start(void *dummy)
static int op_powerpc_start(void)
{
on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1);
if (model->global_start)
model->global_start(ctr);
if (model->start)
on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1);
return 0;
}
@ -80,7 +83,10 @@ static inline void op_powerpc_cpu_stop(void *dummy)
static void op_powerpc_stop(void)
{
on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1);
if (model->stop)
on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1);
if (model->global_stop)
model->global_stop();
}
static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
@ -141,6 +147,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
switch (cur_cpu_spec->oprofile_type) {
#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC_CELL_NATIVE
case PPC_OPROFILE_CELL:
model = &op_model_cell;
break;
#endif
case PPC_OPROFILE_RS64:
model = &op_model_rs64;
break;

View File

@ -0,0 +1,724 @@
/*
* Cell Broadband Engine OProfile Support
*
* (C) Copyright IBM Corporation 2006
*
* Author: David Erb (djerb@us.ibm.com)
* Modifications:
* Carl Love <carll@us.ibm.com>
* Maynard Johnson <maynardj@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kthread.h>
#include <linux/oprofile.h>
#include <linux/percpu.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <asm/cell-pmu.h>
#include <asm/cputable.h>
#include <asm/firmware.h>
#include <asm/io.h>
#include <asm/oprofile_impl.h>
#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
#include <asm/reg.h>
#include <asm/rtas.h>
#include <asm/system.h>
#include "../platforms/cell/interrupt.h"
#define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */
#define CBE_COUNT_ALL_CYCLES 0x42800000 /* PPU cycle event specifier */
#define NUM_THREADS 2
#define VIRT_CNTR_SW_TIME_NS 100000000 // 0.5 seconds
struct pmc_cntrl_data {
unsigned long vcntr;
unsigned long evnts;
unsigned long masks;
unsigned long enabled;
};
/*
* ibm,cbe-perftools rtas parameters
*/
struct pm_signal {
u16 cpu; /* Processor to modify */
u16 sub_unit; /* hw subunit this applies to (if applicable) */
u16 signal_group; /* Signal Group to Enable/Disable */
u8 bus_word; /* Enable/Disable on this Trace/Trigger/Event
* Bus Word(s) (bitmask)
*/
u8 bit; /* Trigger/Event bit (if applicable) */
};
/*
* rtas call arguments
*/
enum {
SUBFUNC_RESET = 1,
SUBFUNC_ACTIVATE = 2,
SUBFUNC_DEACTIVATE = 3,
PASSTHRU_IGNORE = 0,
PASSTHRU_ENABLE = 1,
PASSTHRU_DISABLE = 2,
};
struct pm_cntrl {
u16 enable;
u16 stop_at_max;
u16 trace_mode;
u16 freeze;
u16 count_mode;
};
static struct {
u32 group_control;
u32 debug_bus_control;
struct pm_cntrl pm_cntrl;
u32 pm07_cntrl[NR_PHYS_CTRS];
} pm_regs;
#define GET_SUB_UNIT(x) ((x & 0x0000f000) >> 12)
#define GET_BUS_WORD(x) ((x & 0x000000f0) >> 4)
#define GET_BUS_TYPE(x) ((x & 0x00000300) >> 8)
#define GET_POLARITY(x) ((x & 0x00000002) >> 1)
#define GET_COUNT_CYCLES(x) (x & 0x00000001)
#define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2)
static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values);
static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS];
/* Interpetation of hdw_thread:
* 0 - even virtual cpus 0, 2, 4,...
* 1 - odd virtual cpus 1, 3, 5, ...
*/
static u32 hdw_thread;
static u32 virt_cntr_inter_mask;
static struct timer_list timer_virt_cntr;
/* pm_signal needs to be global since it is initialized in
* cell_reg_setup at the time when the necessary information
* is available.
*/
static struct pm_signal pm_signal[NR_PHYS_CTRS];
static int pm_rtas_token;
static u32 reset_value[NR_PHYS_CTRS];
static int num_counters;
static int oprofile_running;
static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED;
static u32 ctr_enabled;
static unsigned char trace_bus[4];
static unsigned char input_bus[2];
/*
* Firmware interface functions
*/
static int
rtas_ibm_cbe_perftools(int subfunc, int passthru,
void *address, unsigned long length)
{
u64 paddr = __pa(address);
return rtas_call(pm_rtas_token, 5, 1, NULL, subfunc, passthru,
paddr >> 32, paddr & 0xffffffff, length);
}
static void pm_rtas_reset_signals(u32 node)
{
int ret;
struct pm_signal pm_signal_local;
/* The debug bus is being set to the passthru disable state.
* However, the FW still expects atleast one legal signal routing
* entry or it will return an error on the arguments. If we don't
* supply a valid entry, we must ignore all return values. Ignoring
* all return values means we might miss an error we should be
* concerned about.
*/
/* fw expects physical cpu #. */
pm_signal_local.cpu = node;
pm_signal_local.signal_group = 21;
pm_signal_local.bus_word = 1;
pm_signal_local.sub_unit = 0;
pm_signal_local.bit = 0;
ret = rtas_ibm_cbe_perftools(SUBFUNC_RESET, PASSTHRU_DISABLE,
&pm_signal_local,
sizeof(struct pm_signal));
if (ret)
printk(KERN_WARNING "%s: rtas returned: %d\n",
__FUNCTION__, ret);
}
static void pm_rtas_activate_signals(u32 node, u32 count)
{
int ret;
int j;
struct pm_signal pm_signal_local[NR_PHYS_CTRS];
for (j = 0; j < count; j++) {
/* fw expects physical cpu # */
pm_signal_local[j].cpu = node;
pm_signal_local[j].signal_group = pm_signal[j].signal_group;
pm_signal_local[j].bus_word = pm_signal[j].bus_word;
pm_signal_local[j].sub_unit = pm_signal[j].sub_unit;
pm_signal_local[j].bit = pm_signal[j].bit;
}
ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE,
pm_signal_local,
count * sizeof(struct pm_signal));
if (ret)
printk(KERN_WARNING "%s: rtas returned: %d\n",
__FUNCTION__, ret);
}
/*
* PM Signal functions
*/
static void set_pm_event(u32 ctr, int event, u32 unit_mask)
{
struct pm_signal *p;
u32 signal_bit;
u32 bus_word, bus_type, count_cycles, polarity, input_control;
int j, i;
if (event == PPU_CYCLES_EVENT_NUM) {
/* Special Event: Count all cpu cycles */
pm_regs.pm07_cntrl[ctr] = CBE_COUNT_ALL_CYCLES;
p = &(pm_signal[ctr]);
p->signal_group = 21;
p->bus_word = 1;
p->sub_unit = 0;
p->bit = 0;
goto out;
} else {
pm_regs.pm07_cntrl[ctr] = 0;
}
bus_word = GET_BUS_WORD(unit_mask);
bus_type = GET_BUS_TYPE(unit_mask);
count_cycles = GET_COUNT_CYCLES(unit_mask);
polarity = GET_POLARITY(unit_mask);
input_control = GET_INPUT_CONTROL(unit_mask);
signal_bit = (event % 100);
p = &(pm_signal[ctr]);
p->signal_group = event / 100;
p->bus_word = bus_word;
p->sub_unit = unit_mask & 0x0000f000;
pm_regs.pm07_cntrl[ctr] = 0;
pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
pm_regs.pm07_cntrl[ctr] |= PM07_CTR_POLARITY(polarity);
pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_CONTROL(input_control);
if (input_control == 0) {
if (signal_bit > 31) {
signal_bit -= 32;
if (bus_word == 0x3)
bus_word = 0x2;
else if (bus_word == 0xc)
bus_word = 0x8;
}
if ((bus_type == 0) && p->signal_group >= 60)
bus_type = 2;
if ((bus_type == 1) && p->signal_group >= 50)
bus_type = 0;
pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_MUX(signal_bit);
} else {
pm_regs.pm07_cntrl[ctr] = 0;
p->bit = signal_bit;
}
for (i = 0; i < 4; i++) {
if (bus_word & (1 << i)) {
pm_regs.debug_bus_control |=
(bus_type << (31 - (2 * i) + 1));
for (j = 0; j < 2; j++) {
if (input_bus[j] == 0xff) {
input_bus[j] = i;
pm_regs.group_control |=
(i << (31 - i));
break;
}
}
}
}
out:
;
}
static void write_pm_cntrl(int cpu, struct pm_cntrl *pm_cntrl)
{
/* Oprofile will use 32 bit counters, set bits 7:10 to 0 */
u32 val = 0;
if (pm_cntrl->enable == 1)
val |= CBE_PM_ENABLE_PERF_MON;
if (pm_cntrl->stop_at_max == 1)
val |= CBE_PM_STOP_AT_MAX;
if (pm_cntrl->trace_mode == 1)
val |= CBE_PM_TRACE_MODE_SET(pm_cntrl->trace_mode);
if (pm_cntrl->freeze == 1)
val |= CBE_PM_FREEZE_ALL_CTRS;
/* Routine set_count_mode must be called previously to set
* the count mode based on the user selection of user and kernel.
*/
val |= CBE_PM_COUNT_MODE_SET(pm_cntrl->count_mode);
cbe_write_pm(cpu, pm_control, val);
}
static inline void
set_count_mode(u32 kernel, u32 user, struct pm_cntrl *pm_cntrl)
{
/* The user must specify user and kernel if they want them. If
* neither is specified, OProfile will count in hypervisor mode
*/
if (kernel) {
if (user)
pm_cntrl->count_mode = CBE_COUNT_ALL_MODES;
else
pm_cntrl->count_mode = CBE_COUNT_SUPERVISOR_MODE;
} else {
if (user)
pm_cntrl->count_mode = CBE_COUNT_PROBLEM_MODE;
else
pm_cntrl->count_mode = CBE_COUNT_HYPERVISOR_MODE;
}
}
static inline void enable_ctr(u32 cpu, u32 ctr, u32 * pm07_cntrl)
{
pm07_cntrl[ctr] |= PM07_CTR_ENABLE(1);
cbe_write_pm07_control(cpu, ctr, pm07_cntrl[ctr]);
}
/*
* Oprofile is expected to collect data on all CPUs simultaneously.
* However, there is one set of performance counters per node. There are
* two hardware threads or virtual CPUs on each node. Hence, OProfile must
* multiplex in time the performance counter collection on the two virtual
* CPUs. The multiplexing of the performance counters is done by this
* virtual counter routine.
*
* The pmc_values used below is defined as 'per-cpu' but its use is
* more akin to 'per-node'. We need to store two sets of counter
* values per node -- one for the previous run and one for the next.
* The per-cpu[NR_PHYS_CTRS] gives us the storage we need. Each odd/even
* pair of per-cpu arrays is used for storing the previous and next
* pmc values for a given node.
* NOTE: We use the per-cpu variable to improve cache performance.
*/
static void cell_virtual_cntr(unsigned long data)
{
/* This routine will alternate loading the virtual counters for
* virtual CPUs
*/
int i, prev_hdw_thread, next_hdw_thread;
u32 cpu;
unsigned long flags;
/* Make sure that the interrupt_hander and
* the virt counter are not both playing with
* the counters on the same node.
*/
spin_lock_irqsave(&virt_cntr_lock, flags);
prev_hdw_thread = hdw_thread;
/* switch the cpu handling the interrupts */
hdw_thread = 1 ^ hdw_thread;
next_hdw_thread = hdw_thread;
/* The following is done only once per each node, but
* we need cpu #, not node #, to pass to the cbe_xxx functions.
*/
for_each_online_cpu(cpu) {
if (cbe_get_hw_thread_id(cpu))
continue;
/* stop counters, save counter values, restore counts
* for previous thread
*/
cbe_disable_pm(cpu);
cbe_disable_pm_interrupts(cpu);
for (i = 0; i < num_counters; i++) {
per_cpu(pmc_values, cpu + prev_hdw_thread)[i]
= cbe_read_ctr(cpu, i);
if (per_cpu(pmc_values, cpu + next_hdw_thread)[i]
== 0xFFFFFFFF)
/* If the cntr value is 0xffffffff, we must
* reset that to 0xfffffff0 when the current
* thread is restarted. This will generate a new
* interrupt and make sure that we never restore
* the counters to the max value. If the counters
* were restored to the max value, they do not
* increment and no interrupts are generated. Hence
* no more samples will be collected on that cpu.
*/
cbe_write_ctr(cpu, i, 0xFFFFFFF0);
else
cbe_write_ctr(cpu, i,
per_cpu(pmc_values,
cpu +
next_hdw_thread)[i]);
}
/* Switch to the other thread. Change the interrupt
* and control regs to be scheduled on the CPU
* corresponding to the thread to execute.
*/
for (i = 0; i < num_counters; i++) {
if (pmc_cntrl[next_hdw_thread][i].enabled) {
/* There are some per thread events.
* Must do the set event, enable_cntr
* for each cpu.
*/
set_pm_event(i,
pmc_cntrl[next_hdw_thread][i].evnts,
pmc_cntrl[next_hdw_thread][i].masks);
enable_ctr(cpu, i,
pm_regs.pm07_cntrl);
} else {
cbe_write_pm07_control(cpu, i, 0);
}
}
/* Enable interrupts on the CPU thread that is starting */
cbe_enable_pm_interrupts(cpu, next_hdw_thread,
virt_cntr_inter_mask);
cbe_enable_pm(cpu);
}
spin_unlock_irqrestore(&virt_cntr_lock, flags);
mod_timer(&timer_virt_cntr, jiffies + HZ / 10);
}
static void start_virt_cntrs(void)
{
init_timer(&timer_virt_cntr);
timer_virt_cntr.function = cell_virtual_cntr;
timer_virt_cntr.data = 0UL;
timer_virt_cntr.expires = jiffies + HZ / 10;
add_timer(&timer_virt_cntr);
}
/* This function is called once for all cpus combined */
static void
cell_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys, int num_ctrs)
{
int i, j, cpu;
pm_rtas_token = rtas_token("ibm,cbe-perftools");
if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) {
printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n",
__FUNCTION__);
goto out;
}
num_counters = num_ctrs;
pm_regs.group_control = 0;
pm_regs.debug_bus_control = 0;
/* setup the pm_control register */
memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl));
pm_regs.pm_cntrl.stop_at_max = 1;
pm_regs.pm_cntrl.trace_mode = 0;
pm_regs.pm_cntrl.freeze = 1;
set_count_mode(sys->enable_kernel, sys->enable_user,
&pm_regs.pm_cntrl);
/* Setup the thread 0 events */
for (i = 0; i < num_ctrs; ++i) {
pmc_cntrl[0][i].evnts = ctr[i].event;
pmc_cntrl[0][i].masks = ctr[i].unit_mask;
pmc_cntrl[0][i].enabled = ctr[i].enabled;
pmc_cntrl[0][i].vcntr = i;
for_each_possible_cpu(j)
per_cpu(pmc_values, j)[i] = 0;
}
/* Setup the thread 1 events, map the thread 0 event to the
* equivalent thread 1 event.
*/
for (i = 0; i < num_ctrs; ++i) {
if ((ctr[i].event >= 2100) && (ctr[i].event <= 2111))
pmc_cntrl[1][i].evnts = ctr[i].event + 19;
else if (ctr[i].event == 2203)
pmc_cntrl[1][i].evnts = ctr[i].event;
else if ((ctr[i].event >= 2200) && (ctr[i].event <= 2215))
pmc_cntrl[1][i].evnts = ctr[i].event + 16;
else
pmc_cntrl[1][i].evnts = ctr[i].event;
pmc_cntrl[1][i].masks = ctr[i].unit_mask;
pmc_cntrl[1][i].enabled = ctr[i].enabled;
pmc_cntrl[1][i].vcntr = i;
}
for (i = 0; i < 4; i++)
trace_bus[i] = 0xff;
for (i = 0; i < 2; i++)
input_bus[i] = 0xff;
/* Our counters count up, and "count" refers to
* how much before the next interrupt, and we interrupt
* on overflow. So we calculate the starting value
* which will give us "count" until overflow.
* Then we set the events on the enabled counters.
*/
for (i = 0; i < num_counters; ++i) {
/* start with virtual counter set 0 */
if (pmc_cntrl[0][i].enabled) {
/* Using 32bit counters, reset max - count */
reset_value[i] = 0xFFFFFFFF - ctr[i].count;
set_pm_event(i,
pmc_cntrl[0][i].evnts,
pmc_cntrl[0][i].masks);
/* global, used by cell_cpu_setup */
ctr_enabled |= (1 << i);
}
}
/* initialize the previous counts for the virtual cntrs */
for_each_online_cpu(cpu)
for (i = 0; i < num_counters; ++i) {
per_cpu(pmc_values, cpu)[i] = reset_value[i];
}
out:
;
}
/* This function is called once for each cpu */
static void cell_cpu_setup(struct op_counter_config *cntr)
{
u32 cpu = smp_processor_id();
u32 num_enabled = 0;
int i;
/* There is one performance monitor per processor chip (i.e. node),
* so we only need to perform this function once per node.
*/
if (cbe_get_hw_thread_id(cpu))
goto out;
if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) {
printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n",
__FUNCTION__);
goto out;
}
/* Stop all counters */
cbe_disable_pm(cpu);
cbe_disable_pm_interrupts(cpu);
cbe_write_pm(cpu, pm_interval, 0);
cbe_write_pm(cpu, pm_start_stop, 0);
cbe_write_pm(cpu, group_control, pm_regs.group_control);
cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control);
write_pm_cntrl(cpu, &pm_regs.pm_cntrl);
for (i = 0; i < num_counters; ++i) {
if (ctr_enabled & (1 << i)) {
pm_signal[num_enabled].cpu = cbe_cpu_to_node(cpu);
num_enabled++;
}
}
pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled);
out:
;
}
static void cell_global_start(struct op_counter_config *ctr)
{
u32 cpu;
u32 interrupt_mask = 0;
u32 i;
/* This routine gets called once for the system.
* There is one performance monitor per node, so we
* only need to perform this function once per node.
*/
for_each_online_cpu(cpu) {
if (cbe_get_hw_thread_id(cpu))
continue;
interrupt_mask = 0;
for (i = 0; i < num_counters; ++i) {
if (ctr_enabled & (1 << i)) {
cbe_write_ctr(cpu, i, reset_value[i]);
enable_ctr(cpu, i, pm_regs.pm07_cntrl);
interrupt_mask |=
CBE_PM_CTR_OVERFLOW_INTR(i);
} else {
/* Disable counter */
cbe_write_pm07_control(cpu, i, 0);
}
}
cbe_clear_pm_interrupts(cpu);
cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask);
cbe_enable_pm(cpu);
}
virt_cntr_inter_mask = interrupt_mask;
oprofile_running = 1;
smp_wmb();
/* NOTE: start_virt_cntrs will result in cell_virtual_cntr() being
* executed which manipulates the PMU. We start the "virtual counter"
* here so that we do not need to synchronize access to the PMU in
* the above for-loop.
*/
start_virt_cntrs();
}
static void cell_global_stop(void)
{
int cpu;
/* This routine will be called once for the system.
* There is one performance monitor per node, so we
* only need to perform this function once per node.
*/
del_timer_sync(&timer_virt_cntr);
oprofile_running = 0;
smp_wmb();
for_each_online_cpu(cpu) {
if (cbe_get_hw_thread_id(cpu))
continue;
cbe_sync_irq(cbe_cpu_to_node(cpu));
/* Stop the counters */
cbe_disable_pm(cpu);
/* Deactivate the signals */
pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
/* Deactivate interrupts */
cbe_disable_pm_interrupts(cpu);
}
}
static void
cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr)
{
u32 cpu;
u64 pc;
int is_kernel;
unsigned long flags = 0;
u32 interrupt_mask;
int i;
cpu = smp_processor_id();
/* Need to make sure the interrupt handler and the virt counter
* routine are not running at the same time. See the
* cell_virtual_cntr() routine for additional comments.
*/
spin_lock_irqsave(&virt_cntr_lock, flags);
/* Need to disable and reenable the performance counters
* to get the desired behavior from the hardware. This
* is hardware specific.
*/
cbe_disable_pm(cpu);
interrupt_mask = cbe_clear_pm_interrupts(cpu);
/* If the interrupt mask has been cleared, then the virt cntr
* has cleared the interrupt. When the thread that generated
* the interrupt is restored, the data count will be restored to
* 0xffffff0 to cause the interrupt to be regenerated.
*/
if ((oprofile_running == 1) && (interrupt_mask != 0)) {
pc = regs->nip;
is_kernel = is_kernel_addr(pc);
for (i = 0; i < num_counters; ++i) {
if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i))
&& ctr[i].enabled) {
oprofile_add_pc(pc, is_kernel, i);
cbe_write_ctr(cpu, i, reset_value[i]);
}
}
/* The counters were frozen by the interrupt.
* Reenable the interrupt and restart the counters.
* If there was a race between the interrupt handler and
* the virtual counter routine. The virutal counter
* routine may have cleared the interrupts. Hence must
* use the virt_cntr_inter_mask to re-enable the interrupts.
*/
cbe_enable_pm_interrupts(cpu, hdw_thread,
virt_cntr_inter_mask);
/* The writes to the various performance counters only writes
* to a latch. The new values (interrupt setting bits, reset
* counter value etc.) are not copied to the actual registers
* until the performance monitor is enabled. In order to get
* this to work as desired, the permormance monitor needs to
* be disabled while writting to the latches. This is a
* HW design issue.
*/
cbe_enable_pm(cpu);
}
spin_unlock_irqrestore(&virt_cntr_lock, flags);
}
struct op_powerpc_model op_model_cell = {
.reg_setup = cell_reg_setup,
.cpu_setup = cell_cpu_setup,
.global_start = cell_global_start,
.global_stop = cell_global_stop,
.handle_interrupt = cell_handle_interrupt,
};

View File

@ -0,0 +1,9 @@
#
# Makefile for 52xx based boards
#
ifeq ($(CONFIG_PPC_MERGE),y)
obj-y += mpc52xx_pic.o mpc52xx_common.o
endif
obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o
obj-$(CONFIG_PPC_LITE5200) += lite5200.o

View File

@ -0,0 +1,119 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/sections.h>
#include <asm/pci-bridge.h>
#include <asm/rtas.h>
#include "efika.h"
#ifdef CONFIG_PCI
/*
* Access functions for PCI config space using RTAS calls.
*/
static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 * val)
{
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
| (hose->index << 24);
int ret = -1;
int rval;
rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
*val = ret;
return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
}
static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose = bus->sysdata;
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| (((bus->number - hose->first_busno) & 0xff) << 16)
| (hose->index << 24);
int rval;
rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
addr, len, val);
return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
}
static struct pci_ops rtas_pci_ops = {
rtas_read_config,
rtas_write_config
};
void __init efika_pcisetup(void)
{
const int *bus_range;
int len;
struct pci_controller *hose;
struct device_node *root;
struct device_node *pcictrl;
root = of_find_node_by_path("/");
if (root == NULL) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Unable to find the root node\n");
return;
}
for (pcictrl = NULL;;) {
pcictrl = of_get_next_child(root, pcictrl);
if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
break;
}
of_node_put(root);
if (pcictrl == NULL) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Unable to find the PCI bridge node\n");
return;
}
bus_range = get_property(pcictrl, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't get bus-range for %s\n", pcictrl->full_name);
return;
}
if (bus_range[1] == bus_range[0])
printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
bus_range[0]);
else
printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
bus_range[0], bus_range[1]);
printk(" controlled by %s\n", pcictrl->full_name);
printk("\n");
hose = pcibios_alloc_controller();
if (!hose) {
printk(KERN_WARNING EFIKA_PLATFORM_NAME
": Can't allocate PCI controller structure for %s\n",
pcictrl->full_name);
return;
}
hose->arch_data = of_node_get(pcictrl);
hose->first_busno = bus_range[0];
hose->last_busno = bus_range[1];
hose->ops = &rtas_pci_ops;
pci_process_bridge_OF_ranges(hose, pcictrl, 0);
}
#else
void __init efika_pcisetup(void)
{}
#endif

View File

@ -0,0 +1,150 @@
/*
*
* Efika 5K2 platform setup
* Some code really inspired from the lite5200b platform.
*
* Copyright (C) 2006 bplan GmbH
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/utsrelease.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/timer.h>
#include <linux/pci.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/rtas.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
#include "efika.h"
static void efika_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
const char *revision = NULL;
const char *codegendescription = NULL;
const char *codegenvendor = NULL;
root = of_find_node_by_path("/");
if (root) {
revision = get_property(root, "revision", NULL);
codegendescription =
get_property(root, "CODEGEN,description", NULL);
codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
of_node_put(root);
}
if (codegendescription)
seq_printf(m, "machine\t\t: %s\n", codegendescription);
else
seq_printf(m, "machine\t\t: Efika\n");
if (revision)
seq_printf(m, "revision\t: %s\n", revision);
if (codegenvendor)
seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
of_node_put(root);
}
static void __init efika_setup_arch(void)
{
rtas_initialize();
#ifdef CONFIG_BLK_DEV_INITRD
initrd_below_start_ok = 1;
if (initrd_start)
ROOT_DEV = Root_RAM0;
else
#endif
ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
efika_pcisetup();
if (ppc_md.progress)
ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
}
static void __init efika_init(void)
{
struct device_node *np;
struct device_node *cnp = NULL;
const u32 *base;
/* Find every child of the SOC node and add it to of_platform */
np = of_find_node_by_name(NULL, "builtin");
if (np) {
char name[BUS_ID_SIZE];
while ((cnp = of_get_next_child(np, cnp))) {
strcpy(name, cnp->name);
base = get_property(cnp, "reg", NULL);
if (base == NULL)
continue;
snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
of_platform_device_create(cnp, name, NULL);
printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
}
}
if (ppc_md.progress)
ppc_md.progress(" Have fun with your Efika! ", 0x7777);
}
static int __init efika_probe(void)
{
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
"model", NULL);
if (model == NULL)
return 0;
if (strcmp(model, "EFIKA5K2"))
return 0;
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;
return 1;
}
define_machine(efika)
{
.name = EFIKA_PLATFORM_NAME,
.probe = efika_probe,
.setup_arch = efika_setup_arch,
.init = efika_init,
.show_cpuinfo = efika_show_cpuinfo,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
.restart = rtas_restart,
.power_off = rtas_power_off,
.halt = rtas_halt,
.set_rtc_time = rtas_set_rtc_time,
.get_rtc_time = rtas_get_rtc_time,
.progress = rtas_progress,
.get_boot_time = rtas_get_boot_time,
.calibrate_decr = generic_calibrate_decr,
.phys_mem_access_prot = pci_phys_mem_access_prot,
};

View File

@ -0,0 +1,19 @@
/*
* Efika 5K2 platform setup - Header file
*
* Copyright (C) 2006 bplan GmbH
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef __ARCH_POWERPC_EFIKA__
#define __ARCH_POWERPC_EFIKA__
#define EFIKA_PLATFORM_NAME "Efika"
extern void __init efika_pcisetup(void);
#endif

View File

@ -0,0 +1,162 @@
/*
* Freescale Lite5200 board support
*
* Written by: Grant Likely <grant.likely@secretlab.ca>
*
* Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved.
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
*
* Description:
* 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/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/reboot.h>
#include <linux/pci.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/ipic.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
#include <asm/qe.h>
#include <asm/qe_ic.h>
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
/* ************************************************************************
*
* Setup the architecture
*
*/
static void __init
lite52xx_setup_cpu(void)
{
struct mpc52xx_gpio __iomem *gpio;
u32 port_config;
/* Map zones */
gpio = mpc52xx_find_and_map("mpc52xx-gpio");
if (!gpio) {
printk(KERN_ERR __FILE__ ": "
"Error while mapping GPIO register for port config. "
"Expect some abnormal behavior\n");
goto error;
}
/* Set port config */
port_config = in_be32(&gpio->port_config);
port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */
port_config &= ~0x00007000; /* USB port : Differential mode */
port_config |= 0x00001000; /* USB 1 only */
port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */
port_config |= 0x01000000;
pr_debug("port_config: old:%x new:%x\n",
in_be32(&gpio->port_config), port_config);
out_be32(&gpio->port_config, port_config);
/* Unmap zone */
error:
iounmap(gpio);
}
static void __init lite52xx_setup_arch(void)
{
struct device_node *np;
if (ppc_md.progress)
ppc_md.progress("lite52xx_setup_arch()", 0);
np = of_find_node_by_type(NULL, "cpu");
if (np) {
unsigned int *fp =
(int *)get_property(np, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
loops_per_jiffy = 50000000 / HZ;
of_node_put(np);
}
/* CPU & Port mux setup */
mpc52xx_setup_cpu(); /* Generic */
lite52xx_setup_cpu(); /* Platorm specific */
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
ROOT_DEV = Root_RAM0;
else
#endif
#ifdef CONFIG_ROOT_NFS
ROOT_DEV = Root_NFS;
#else
ROOT_DEV = Root_HDA1;
#endif
}
void lite52xx_show_cpuinfo(struct seq_file *m)
{
struct device_node* np = of_find_all_nodes(NULL);
const char *model = NULL;
if (np)
model = get_property(np, "model", NULL);
seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown");
of_node_put(np);
}
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
static int __init lite52xx_probe(void)
{
unsigned long node = of_get_flat_dt_root();
const char *model = of_get_flat_dt_prop(node, "model", NULL);
if (!of_flat_dt_is_compatible(node, "lite52xx"))
return 0;
pr_debug("%s board w/ mpc52xx found\n", model ? model : "unknown");
return 1;
}
define_machine(lite52xx) {
.name = "lite52xx",
.probe = lite52xx_probe,
.setup_arch = lite52xx_setup_arch,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
.show_cpuinfo = lite52xx_show_cpuinfo,
.calibrate_decr = generic_calibrate_decr,
};

View File

@ -0,0 +1,126 @@
/*
*
* Utility functions for the Freescale MPC52xx.
*
* Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#undef DEBUG
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
void __iomem *
mpc52xx_find_and_map(const char *compatible)
{
struct device_node *ofn;
const u32 *regaddr_p;
u64 regaddr64, size64;
ofn = of_find_compatible_node(NULL, NULL, compatible);
if (!ofn)
return NULL;
regaddr_p = of_get_address(ofn, 0, &size64, NULL);
if (!regaddr_p) {
of_node_put(ofn);
return NULL;
}
regaddr64 = of_translate_address(ofn, regaddr_p);
of_node_put(ofn);
return ioremap((u32)regaddr64, (u32)size64);
}
EXPORT_SYMBOL(mpc52xx_find_and_map);
/**
* mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
* @node: device node
*
* Returns IPB bus frequency, or 0 if the bus frequency cannot be found.
*/
unsigned int
mpc52xx_find_ipb_freq(struct device_node *node)
{
struct device_node *np;
const unsigned int *p_ipb_freq = NULL;
of_node_get(node);
while (node) {
p_ipb_freq = get_property(node, "bus-frequency", NULL);
if (p_ipb_freq)
break;
np = of_get_parent(node);
of_node_put(node);
node = np;
}
if (node)
of_node_put(node);
return p_ipb_freq ? *p_ipb_freq : 0;
}
EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
void __init
mpc52xx_setup_cpu(void)
{
struct mpc52xx_cdm __iomem *cdm;
struct mpc52xx_xlb __iomem *xlb;
/* Map zones */
cdm = mpc52xx_find_and_map("mpc52xx-cdm");
xlb = mpc52xx_find_and_map("mpc52xx-xlb");
if (!cdm || !xlb) {
printk(KERN_ERR __FILE__ ": "
"Error while mapping CDM/XLB during mpc52xx_setup_cpu. "
"Expect some abnormal behavior\n");
goto unmap_regs;
}
/* Use internal 48 Mhz */
out_8(&cdm->ext_48mhz_en, 0x00);
out_8(&cdm->fd_enable, 0x01);
if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
out_be16(&cdm->fd_counters, 0x0001);
else
out_be16(&cdm->fd_counters, 0x5555);
/* Configure the XLB Arbiter priorities */
out_be32(&xlb->master_pri_enable, 0xff);
out_be32(&xlb->master_priority, 0x11111111);
/* Disable XLB pipelining */
/* (cfr errate 292. We could do this only just before ATA PIO
transaction and re-enable it afterwards ...) */
out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
/* Unmap zones */
unmap_regs:
if (cdm) iounmap(cdm);
if (xlb) iounmap(xlb);
}
static int __init
mpc52xx_declare_of_platform_devices(void)
{
/* Find every child of the SOC node and add it to of_platform */
return of_platform_bus_probe(NULL, NULL, NULL);
}
device_initcall(mpc52xx_declare_of_platform_devices);

View File

@ -0,0 +1,473 @@
/*
*
* Programmable Interrupt Controller functions for the Freescale MPC52xx.
*
* Copyright (C) 2006 bplan GmbH
*
* Based on the code from the 2.4 kernel by
* Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
*
* Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 Montavista Software, Inc
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#undef DEBUG
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/stddef.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/hardirq.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/mpc52xx.h>
#include "mpc52xx_pic.h"
/*
*
*/
static struct mpc52xx_intr __iomem *intr;
static struct mpc52xx_sdma __iomem *sdma;
static struct irq_host *mpc52xx_irqhost = NULL;
static unsigned char mpc52xx_map_senses[4] = {
IRQ_TYPE_LEVEL_HIGH,
IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_FALLING,
IRQ_TYPE_LEVEL_LOW,
};
/*
*
*/
static inline void io_be_setbit(u32 __iomem *addr, int bitno)
{
out_be32(addr, in_be32(addr) | (1 << bitno));
}
static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
{
out_be32(addr, in_be32(addr) & ~(1 << bitno));
}
/*
* IRQ[0-3] interrupt irq_chip
*/
static void mpc52xx_extirq_mask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_clrbit(&intr->ctrl, 11 - l2irq);
}
static void mpc52xx_extirq_unmask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_setbit(&intr->ctrl, 11 - l2irq);
}
static void mpc52xx_extirq_ack(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_setbit(&intr->ctrl, 27-l2irq);
}
static struct irq_chip mpc52xx_extirq_irqchip = {
.typename = " MPC52xx IRQ[0-3] ",
.mask = mpc52xx_extirq_mask,
.unmask = mpc52xx_extirq_unmask,
.ack = mpc52xx_extirq_ack,
};
/*
* Main interrupt irq_chip
*/
static void mpc52xx_main_mask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_setbit(&intr->main_mask, 15 - l2irq);
}
static void mpc52xx_main_unmask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_clrbit(&intr->main_mask, 15 - l2irq);
}
static struct irq_chip mpc52xx_main_irqchip = {
.typename = "MPC52xx Main",
.mask = mpc52xx_main_mask,
.mask_ack = mpc52xx_main_mask,
.unmask = mpc52xx_main_unmask,
};
/*
* Peripherals interrupt irq_chip
*/
static void mpc52xx_periph_mask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_setbit(&intr->per_mask, 31 - l2irq);
}
static void mpc52xx_periph_unmask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_clrbit(&intr->per_mask, 31 - l2irq);
}
static struct irq_chip mpc52xx_periph_irqchip = {
.typename = "MPC52xx Peripherals",
.mask = mpc52xx_periph_mask,
.mask_ack = mpc52xx_periph_mask,
.unmask = mpc52xx_periph_unmask,
};
/*
* SDMA interrupt irq_chip
*/
static void mpc52xx_sdma_mask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_setbit(&sdma->IntMask, l2irq);
}
static void mpc52xx_sdma_unmask(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
io_be_clrbit(&sdma->IntMask, l2irq);
}
static void mpc52xx_sdma_ack(unsigned int virq)
{
int irq;
int l2irq;
irq = irq_map[virq].hwirq;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
out_be32(&sdma->IntPend, 1 << l2irq);
}
static struct irq_chip mpc52xx_sdma_irqchip = {
.typename = "MPC52xx SDMA",
.mask = mpc52xx_sdma_mask,
.unmask = mpc52xx_sdma_unmask,
.ack = mpc52xx_sdma_ack,
};
/*
* irq_host
*/
static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
{
pr_debug("%s: node=%p\n", __func__, node);
return mpc52xx_irqhost->host_data == node;
}
static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
u32 * intspec, unsigned int intsize,
irq_hw_number_t * out_hwirq,
unsigned int *out_flags)
{
int intrvect_l1;
int intrvect_l2;
int intrvect_type;
int intrvect_linux;
if (intsize != 3)
return -1;
intrvect_l1 = (int)intspec[0];
intrvect_l2 = (int)intspec[1];
intrvect_type = (int)intspec[2];
intrvect_linux =
(intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
intrvect_linux |=
(intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
intrvect_l2);
*out_hwirq = intrvect_linux;
*out_flags = mpc52xx_map_senses[intrvect_type];
return 0;
}
/*
* this function retrieves the correct IRQ type out
* of the MPC regs
* Only externals IRQs needs this
*/
static int mpc52xx_irqx_gettype(int irq)
{
int type;
u32 ctrl_reg;
ctrl_reg = in_be32(&intr->ctrl);
type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
return mpc52xx_map_senses[type];
}
static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t irq)
{
int l1irq;
int l2irq;
struct irq_chip *good_irqchip;
void *good_handle;
int type;
l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
/*
* Most of ours IRQs will be level low
* Only external IRQs on some platform may be others
*/
type = IRQ_TYPE_LEVEL_LOW;
switch (l1irq) {
case MPC52xx_IRQ_L1_CRIT:
pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
BUG_ON(l2irq != 0);
type = mpc52xx_irqx_gettype(l2irq);
good_irqchip = &mpc52xx_extirq_irqchip;
break;
case MPC52xx_IRQ_L1_MAIN:
pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
if ((l2irq >= 1) && (l2irq <= 3)) {
type = mpc52xx_irqx_gettype(l2irq);
good_irqchip = &mpc52xx_extirq_irqchip;
} else {
good_irqchip = &mpc52xx_main_irqchip;
}
break;
case MPC52xx_IRQ_L1_PERP:
pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
good_irqchip = &mpc52xx_periph_irqchip;
break;
case MPC52xx_IRQ_L1_SDMA:
pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
good_irqchip = &mpc52xx_sdma_irqchip;
break;
default:
pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
printk(KERN_ERR "Unknow IRQ!\n");
return -EINVAL;
}
switch (type) {
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_EDGE_RISING:
good_handle = handle_edge_irq;
break;
default:
good_handle = handle_level_irq;
}
set_irq_chip_and_handler(virq, good_irqchip, good_handle);
pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
(int)irq, type);
return 0;
}
static struct irq_host_ops mpc52xx_irqhost_ops = {
.match = mpc52xx_irqhost_match,
.xlate = mpc52xx_irqhost_xlate,
.map = mpc52xx_irqhost_map,
};
/*
* init (public)
*/
void __init mpc52xx_init_irq(void)
{
u32 intr_ctrl;
struct device_node *picnode;
/* Remap the necessary zones */
picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic");
intr = mpc52xx_find_and_map("mpc52xx-pic");
if (!intr)
panic(__FILE__ ": find_and_map failed on 'mpc52xx-pic'. "
"Check node !");
sdma = mpc52xx_find_and_map("mpc52xx-bestcomm");
if (!sdma)
panic(__FILE__ ": find_and_map failed on 'mpc52xx-bestcomm'. "
"Check node !");
/* Disable all interrupt sources. */
out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
intr_ctrl = in_be32(&intr->ctrl);
intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
0x00001000 | /* MEE master external enable */
0x00000000 | /* 0 means disable IRQ 0-3 */
0x00000001; /* CEb route critical normally */
out_be32(&intr->ctrl, intr_ctrl);
/* Zero a bunch of the priority settings. */
out_be32(&intr->per_pri1, 0);
out_be32(&intr->per_pri2, 0);
out_be32(&intr->per_pri3, 0);
out_be32(&intr->main_pri1, 0);
out_be32(&intr->main_pri2, 0);
/*
* As last step, add an irq host to translate the real
* hw irq information provided by the ofw to linux virq
*/
mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
MPC52xx_IRQ_HIGHTESTHWIRQ,
&mpc52xx_irqhost_ops, -1);
if (!mpc52xx_irqhost)
panic(__FILE__ ": Cannot allocate the IRQ host\n");
mpc52xx_irqhost->host_data = picnode;
printk(KERN_INFO "MPC52xx PIC is up and running!\n");
}
/*
* get_irq (public)
*/
unsigned int mpc52xx_get_irq(void)
{
u32 status;
int irq = NO_IRQ_IGNORE;
status = in_be32(&intr->enc_status);
if (status & 0x00000400) { /* critical */
irq = (status >> 8) & 0x3;
if (irq == 2) /* high priority peripheral */
goto peripheral;
irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
MPC52xx_IRQ_L1_MASK;
} else if (status & 0x00200000) { /* main */
irq = (status >> 16) & 0x1f;
if (irq == 4) /* low priority peripheral */
goto peripheral;
irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
MPC52xx_IRQ_L1_MASK;
} else if (status & 0x20000000) { /* peripheral */
peripheral:
irq = (status >> 24) & 0x1f;
if (irq == 0) { /* bestcomm */
status = in_be32(&sdma->IntPend);
irq = ffs(status) - 1;
irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
MPC52xx_IRQ_L1_MASK;
} else {
irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
MPC52xx_IRQ_L1_MASK;
}
}
pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
irq_linear_revmap(mpc52xx_irqhost, irq));
return irq_linear_revmap(mpc52xx_irqhost, irq);
}

View File

@ -0,0 +1,53 @@
/*
* Header file for Freescale MPC52xx Interrupt controller
*
* Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef __POWERPC_SYSDEV_MPC52xx_PIC_H__
#define __POWERPC_SYSDEV_MPC52xx_PIC_H__
#include <asm/types.h>
/* HW IRQ mapping */
#define MPC52xx_IRQ_L1_CRIT (0)
#define MPC52xx_IRQ_L1_MAIN (1)
#define MPC52xx_IRQ_L1_PERP (2)
#define MPC52xx_IRQ_L1_SDMA (3)
#define MPC52xx_IRQ_L1_OFFSET (6)
#define MPC52xx_IRQ_L1_MASK (0x00c0)
#define MPC52xx_IRQ_L2_OFFSET (0)
#define MPC52xx_IRQ_L2_MASK (0x003f)
#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
/* Interrupt controller Register set */
struct mpc52xx_intr {
u32 per_mask; /* INTR + 0x00 */
u32 per_pri1; /* INTR + 0x04 */
u32 per_pri2; /* INTR + 0x08 */
u32 per_pri3; /* INTR + 0x0c */
u32 ctrl; /* INTR + 0x10 */
u32 main_mask; /* INTR + 0x14 */
u32 main_pri1; /* INTR + 0x18 */
u32 main_pri2; /* INTR + 0x1c */
u32 reserved1; /* INTR + 0x20 */
u32 enc_status; /* INTR + 0x24 */
u32 crit_status; /* INTR + 0x28 */
u32 main_status; /* INTR + 0x2c */
u32 per_status; /* INTR + 0x30 */
u32 reserved2; /* INTR + 0x34 */
u32 per_error; /* INTR + 0x38 */
};
#endif /* __POWERPC_SYSDEV_MPC52xx_PIC_H__ */

View File

@ -515,16 +515,6 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_SUCCESSFUL;
}
static void
__init mpc82xx_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
for_each_pci_dev(dev) {
pci_read_irq_line(dev);
}
}
void __init add_bridge(struct device_node *np)
{
int len;
@ -597,9 +587,6 @@ static void __init mpc82xx_ads_setup_arch(void)
add_bridge(np);
of_node_put(np);
ppc_md.pci_map_irq = NULL;
ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup;
ppc_md.pcibios_fixup_bus = NULL;
#endif
#ifdef CONFIG_ROOT_NFS

View File

@ -97,8 +97,6 @@ static void __init mpc832x_sys_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif

View File

@ -118,7 +118,4 @@ define_machine(mpc834x_itx) {
.time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
#ifdef CONFIG_PCI
.pcibios_fixup = mpc83xx_pcibios_fixup,
#endif
};

View File

@ -137,7 +137,4 @@ define_machine(mpc834x_sys) {
.time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
#ifdef CONFIG_PCI
.pcibios_fixup = mpc83xx_pcibios_fixup,
#endif
};

View File

@ -102,8 +102,6 @@ static void __init mpc8360_sys_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif

View File

@ -11,7 +11,6 @@
extern int add_bridge(struct device_node *dev);
extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
extern void mpc83xx_pcibios_fixup(void);
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);

View File

@ -45,15 +45,6 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_SUCCESSFUL;
}
void __init mpc83xx_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
/* map all the PCI irqs */
for_each_pci_dev(dev)
pci_read_irq_line(dev);
}
int __init add_bridge(struct device_node *dev)
{
int len;

View File

@ -21,11 +21,3 @@ void mpc85xx_restart(char *cmd)
local_irq_disable();
abort();
}
/* For now this is a pass through */
phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
{
return addr;
};
EXPORT_SYMBOL(fixup_bigphys_addr);

View File

@ -53,15 +53,6 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
else
return PCIBIOS_SUCCESSFUL;
}
void __init
mpc85xx_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
for_each_pci_dev(dev)
pci_read_irq_line(dev);
}
#endif /* CONFIG_PCI */
#ifdef CONFIG_CPM2
@ -253,8 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void)
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif

View File

@ -398,15 +398,6 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
}
void __init mpc86xx_hpcn_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
for_each_pci_dev(dev)
pci_read_irq_line(dev);
}
/*
* Called very early, device-tree isn't unflattened
*/
@ -461,7 +452,6 @@ define_machine(mpc86xx_hpcn) {
.setup_arch = mpc86xx_hpcn_setup_arch,
.init_IRQ = mpc86xx_hpcn_init_irq,
.show_cpuinfo = mpc86xx_hpcn_show_cpuinfo,
.pcibios_fixup = mpc86xx_hpcn_pcibios_fixup,
.get_irq = mpic_get_irq,
.restart = mpc86xx_restart,
.time_init = mpc86xx_time_init,

View File

@ -7,12 +7,14 @@ endif
endif
obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_4xx) += 4xx/
obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_PPC_85xx) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
obj-$(CONFIG_PPC_PSERIES) += pseries/
obj-$(CONFIG_PPC_ISERIES) += iseries/
obj-$(CONFIG_PPC_MAPLE) += maple/
obj-$(CONFIG_PPC_PASEMI) += pasemi/
obj-$(CONFIG_PPC_PASEMI) += pasemi/
obj-$(CONFIG_PPC_CELL) += cell/
obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/

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