Merge branch 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (255 commits)
  [POWERPC] Remove dev_dbg redefinition in drivers/ps3/vuart.c
  [POWERPC] remove kernel module option for booke wdt
  [POWERPC] Avoid putting cpu node twice
  [POWERPC] Spinlock initializer cleanup
  [POWERPC] ppc4xx_sgdma needs dma-mapping.h
  [POWERPC] arch/powerpc/sysdev/timer.c build fix
  [POWERPC] get_property cleanups
  [POWERPC] Remove the unused HTDMSOUND driver
  [POWERPC] cell: cbe_cpufreq cleanup and crash fix
  [POWERPC] Declare enable_kernel_spe in a header
  [POWERPC] Add dt_xlate_addr() to bootwrapper
  [POWERPC] bootwrapper: CONFIG_ -> CONFIG_DEVICE_TREE
  [POWERPC] Don't define a custom bd_t for Xilixn Virtex based boards.
  [POWERPC] Add sane defaults for Xilinx EDK generated xparameters files
  [POWERPC] Add uartlite boot console driver for the zImage wrapper
  [POWERPC] Stop using ppc_sys for Xilinx Virtex boards
  [POWERPC] New registration for common Xilinx Virtex ppc405 platform devices
  [POWERPC] Merge common virtex header files
  [POWERPC] Rework Kconfig dependancies for Xilinx Virtex ppc405 platform
  [POWERPC] Clean up cpufreq Kconfig dependencies
  ...
This commit is contained in:
Linus Torvalds 2007-04-30 08:10:12 -07:00
commit 24a77daf3d
376 changed files with 11566 additions and 7912 deletions

View File

@ -39,7 +39,7 @@
and property data. The old style variable
alignment would make it impossible to do
"simple" insertion of properties using
memove (thanks Milton for
memmove (thanks Milton for
noticing). Updated kernel patch as well
- Correct a few more alignment constraints
- Add a chapter about the device-tree
@ -55,7 +55,7 @@
ToDo:
- Add some definitions of interrupt tree (simple/complex)
- Add some definitions for pci host bridges
- Add some definitions for PCI host bridges
- Add some common address format examples
- Add definitions for standard properties and "compatible"
names for cells that are not already defined by the existing
@ -114,7 +114,7 @@ it with special cases.
forth words isn't required), you can enter the kernel with:
r5 : OF callback pointer as defined by IEEE 1275
bindings to powerpc. Only the 32 bit client interface
bindings to powerpc. Only the 32-bit client interface
is currently supported
r3, r4 : address & length of an initrd if any or 0
@ -194,7 +194,7 @@ it with special cases.
for this is to keep kernels on embedded systems small and efficient;
part of this is due to the fact the code is already that way. In the
future, a kernel may support multiple platforms, but only if the
platforms feature the same core architectire. A single kernel build
platforms feature the same core architecture. A single kernel build
cannot support both configurations with Book E and configurations
with classic Powerpc architectures.
@ -215,7 +215,7 @@ of the boot sequences.... someone speak up if this is wrong!
enable another config option to select the specific board
supported.
NOTE: If ben doesn't merge the setup files, may need to change this to
NOTE: If Ben doesn't merge the setup files, may need to change this to
point to setup_32.c
@ -265,6 +265,9 @@ struct boot_param_header {
booting on */
/* version 3 fields below */
u32 size_dt_strings; /* size of the strings block */
/* version 17 fields below */
u32 size_dt_struct; /* size of the DT structure block */
};
Along with the constants:
@ -310,9 +313,8 @@ struct boot_param_header {
- off_mem_rsvmap
This is an offset from the beginning of the header to the start
of the reserved memory map. This map is a list of pairs of 64
of the reserved memory map. This map is a list of pairs of 64-
bit integers. Each pair is a physical address and a size. The
list is terminated by an entry of size 0. This map provides the
kernel with a list of physical memory areas that are "reserved"
and thus not to be used for memory allocations, especially during
@ -325,7 +327,7 @@ struct boot_param_header {
contain _at least_ this DT block itself (header,total_size). If
you are passing an initrd to the kernel, you should reserve it as
well. You do not need to reserve the kernel image itself. The map
should be 64 bit aligned.
should be 64-bit aligned.
- version
@ -335,10 +337,13 @@ struct boot_param_header {
to reallocate it easily at boot and free up the unused flattened
structure after expansion. Version 16 introduces a new more
"compact" format for the tree itself that is however not backward
compatible. You should always generate a structure of the highest
version defined at the time of your implementation. Currently
that is version 16, unless you explicitly aim at being backward
compatible.
compatible. Version 17 adds an additional field, size_dt_struct,
allowing it to be reallocated or moved more easily (this is
particularly useful for bootloaders which need to make
adjustments to a device tree based on probed information). You
should always generate a structure of the highest version defined
at the time of your implementation. Currently that is version 17,
unless you explicitly aim at being backward compatible.
- last_comp_version
@ -347,7 +352,7 @@ struct boot_param_header {
is backward compatible with version 1 (that is, a kernel build
for version 1 will be able to boot with a version 2 format). You
should put a 1 in this field if you generate a device tree of
version 1 to 3, or 0x10 if you generate a tree of version 0x10
version 1 to 3, or 16 if you generate a tree of version 16 or 17
using the new unit name format.
- boot_cpuid_phys
@ -360,6 +365,17 @@ struct boot_param_header {
point (see further chapters for more informations on the required
device-tree contents)
- size_dt_strings
This field only exists on version 3 and later headers. It
gives the size of the "strings" section of the device tree (which
starts at the offset given by off_dt_strings).
- size_dt_struct
This field only exists on version 17 and later headers. It gives
the size of the "structure" section of the device tree (which
starts at the offset given by off_dt_struct).
So the typical layout of a DT block (though the various parts don't
need to be in that order) looks like this (addresses go from top to
@ -417,7 +433,7 @@ root node who has no parent.
A node has 2 names. The actual node name is generally contained in a
property of type "name" in the node property list whose value is a
zero terminated string and is mandatory for version 1 to 3 of the
format definition (as it is in Open Firmware). Version 0x10 makes it
format definition (as it is in Open Firmware). Version 16 makes it
optional as it can generate it from the unit name defined below.
There is also a "unit name" that is used to differentiate nodes with
@ -461,7 +477,7 @@ referencing another node via "phandle" is when laying out the
interrupt tree which will be described in a further version of this
document.
This "linux, phandle" property is a 32 bit value that uniquely
This "linux, phandle" property is a 32-bit value that uniquely
identifies a node. You are free to use whatever values or system of
values, internal pointers, or whatever to generate these, the only
requirement is that every node for which you provide that property has
@ -471,7 +487,7 @@ Here is an example of a simple device-tree. In this example, an "o"
designates a node followed by the node unit name. Properties are
presented with their name followed by their content. "content"
represents an ASCII string (zero terminated) value, while <content>
represents a 32 bit hexadecimal value. The various nodes in this
represents a 32-bit hexadecimal value. The various nodes in this
example will be discussed in a later chapter. At this point, it is
only meant to give you a idea of what a device-tree looks like. I have
purposefully kept the "name" and "linux,phandle" properties which
@ -543,15 +559,15 @@ Here's the basic structure of a single node:
* [align gap to next 4 bytes boundary]
* for each property:
* token OF_DT_PROP (that is 0x00000003)
* 32 bit value of property value size in bytes (or 0 of no
* value)
* 32 bit value of offset in string block of property name
* 32-bit value of property value size in bytes (or 0 if no
value)
* 32-bit value of offset in string block of property name
* property value data if any
* [align gap to next 4 bytes boundary]
* [child nodes if any]
* token OF_DT_END_NODE (that is 0x00000002)
So the node content can be summarised as a start token, a full path,
So the node content can be summarized as a start token, a full path,
a list of properties, a list of child nodes, and an end token. Every
child node is a full node structure itself as defined above.
@ -583,7 +599,7 @@ provide those properties yourself.
----------------------------------------------
The general rule is documented in the various Open Firmware
documentations. If you chose to describe a bus with the device-tree
documentations. If you choose to describe a bus with the device-tree
and there exist an OF bus binding, then you should follow the
specification. However, the kernel does not require every single
device or bus to be described by the device tree.
@ -596,9 +612,9 @@ those properties defining addresses format for devices directly mapped
on the processor bus.
Those 2 properties define 'cells' for representing an address and a
size. A "cell" is a 32 bit number. For example, if both contain 2
size. A "cell" is a 32-bit number. For example, if both contain 2
like the example tree given above, then an address and a size are both
composed of 2 cells, and each is a 64 bit number (cells are
composed of 2 cells, and each is a 64-bit number (cells are
concatenated and expected to be in big endian format). Another example
is the way Apple firmware defines them, with 2 cells for an address
and one cell for a size. Most 32-bit implementations should define
@ -632,7 +648,7 @@ prom_parse.c file of the recent kernels for your bus type.
The "reg" property only defines addresses and sizes (if #size-cells
is non-0) within a given bus. In order to translate addresses upward
(that is into parent bus addresses, and possibly into cpu physical
(that is into parent bus addresses, and possibly into CPU physical
addresses), all busses must contain a "ranges" property. If the
"ranges" property is missing at a given level, it's assumed that
translation isn't possible. The format of the "ranges" property for a
@ -648,9 +664,9 @@ example, for a PCI host controller, that would be a CPU address. For a
PCI<->ISA bridge, that would be a PCI address. It defines the base
address in the parent bus where the beginning of that range is mapped.
For a new 64 bit powerpc board, I recommend either the 2/2 format or
For a new 64-bit powerpc board, I recommend either the 2/2 format or
Apple's 2/1 format which is slightly more compact since sizes usually
fit in a single 32 bit word. New 32 bit powerpc boards should use a
fit in a single 32-bit word. New 32-bit powerpc boards should use a
1/1 format, unless the processor supports physical addresses greater
than 32-bits, in which case a 2/1 format is recommended.
@ -764,7 +780,7 @@ address which can extend beyond that limit.
Required properties:
- device_type : has to be "cpu"
- reg : This is the physical cpu number, it's a single 32 bit cell
- reg : This is the physical CPU number, it's a single 32-bit cell
and is also used as-is as the unit number for constructing the
unit name in the full path. For example, with 2 CPUs, you would
have the full path:
@ -785,7 +801,7 @@ address which can extend beyond that limit.
the kernel timebase/decrementer calibration based on this
value.
- clock-frequency : a cell indicating the CPU core clock frequency
in Hz. A new property will be defined for 64 bit values, but if
in Hz. A new property will be defined for 64-bit values, but if
your frequency is < 4Ghz, one cell is enough. Here as well as
for the above, the common code doesn't use that property, but
you are welcome to re-use the pSeries or Maple one. A future
@ -832,8 +848,7 @@ address which can extend beyond that limit.
This node is a bit "special". Normally, that's where open firmware
puts some variable environment information, like the arguments, or
phandle pointers to nodes like the main interrupt controller, or the
default input/output devices.
the default input/output devices.
This specification makes a few of these mandatory, but also defines
some linux-specific properties that would be normally constructed by
@ -853,14 +868,14 @@ address which can extend beyond that limit.
that the kernel tries to find out the default console and has
knowledge of various types like 8250 serial ports. You may want
to extend this function to add your own.
- interrupt-controller : This is one cell containing a phandle
value that matches the "linux,phandle" property of your main
interrupt controller node. May be used for interrupt routing.
Note that u-boot creates and fills in the chosen node for platforms
that use it.
(Note: a practice that is now obsolete was to include a property
under /chosen called interrupt-controller which had a phandle value
that pointed to the main interrupt controller)
f) the /soc<SOCname> node
This node is used to represent a system-on-a-chip (SOC) and must be
@ -908,8 +923,7 @@ address which can extend beyond that limit.
The SOC node may contain child nodes for each SOC device that the
platform uses. Nodes should not be created for devices which exist
on the SOC but are not used by a particular platform. See chapter VI
for more information on how to specify devices that are part of an
SOC.
for more information on how to specify devices that are part of a SOC.
Example SOC node for the MPC8540:
@ -972,7 +986,7 @@ The syntax of the dtc tool is
[-o output-filename] [-V output_version] input_filename
The "output_version" defines what versio of the "blob" format will be
The "output_version" defines what version of the "blob" format will be
generated. Supported versions are 1,2,3 and 16. The default is
currently version 3 but that may change in the future to version 16.
@ -994,12 +1008,12 @@ supported currently at the toplevel.
*/
property2 = <1234abcd>; /* define a property containing a
* numerical 32 bits value (hexadecimal)
* numerical 32-bit value (hexadecimal)
*/
property3 = <12345678 12345678 deadbeef>;
/* define a property containing 3
* numerical 32 bits values (cells) in
* numerical 32-bit values (cells) in
* hexadecimal
*/
property4 = [0a 0b 0c 0d de ea ad be ef];
@ -1068,7 +1082,7 @@ while all this has been defined and implemented.
its usage in early_init_devtree(), and the corresponding various
early_init_dt_scan_*() callbacks. That code can be re-used in a
GPL bootloader, and as the author of that code, I would be happy
to discuss possible free licencing to any vendor who wishes to
to discuss possible free licensing to any vendor who wishes to
integrate all or part of this code into a non-GPL bootloader.
@ -1077,7 +1091,7 @@ VI - System-on-a-chip devices and nodes
=======================================
Many companies are now starting to develop system-on-a-chip
processors, where the processor core (cpu) and many peripheral devices
processors, where the processor core (CPU) and many peripheral devices
exist on a single piece of silicon. For these SOCs, an SOC node
should be used that defines child nodes for the devices that make
up the SOC. While platforms are not required to use this model in
@ -1109,42 +1123,7 @@ See appendix A for an example partial SOC node definition for the
MPC8540.
2) Specifying interrupt information for SOC devices
---------------------------------------------------
Each device that is part of an SOC and which generates interrupts
should have the following properties:
- interrupt-parent : contains the phandle of the interrupt
controller which handles interrupts for this device
- interrupts : a list of tuples representing the interrupt
number and the interrupt sense and level for each interrupt
for this device.
This information is used by the kernel to build the interrupt table
for the interrupt controllers in the system.
Sense and level information should be encoded as follows:
Devices connected to openPIC-compatible controllers should encode
sense and polarity as follows:
0 = low to high edge sensitive type enabled
1 = active low level sensitive type enabled
2 = active high level sensitive type enabled
3 = high to low edge sensitive type enabled
ISA PIC interrupt controllers should adhere to the ISA PIC
encodings listed below:
0 = active low level sensitive type enabled
1 = active high level sensitive type enabled
2 = high to low edge sensitive type enabled
3 = low to high edge sensitive type enabled
3) Representing devices without a current OF specification
2) Representing devices without a current OF specification
----------------------------------------------------------
Currently, there are many devices on SOCs that do not have a standard
@ -1201,6 +1180,13 @@ platforms are moved over to use the flattened-device-tree model.
- phy-handle : The phandle for the PHY connected to this ethernet
controller.
Recommended properties:
- linux,network-index : This is the intended "index" of this
network device. This is used by the bootwrapper to interpret
MAC addresses passed by the firmware when no information other
than indices is available to associate an address with a device.
Example:
ethernet@24000 {
@ -1312,10 +1298,10 @@ platforms are moved over to use the flattened-device-tree model.
and additions :
Required properties :
- compatible : Should be "fsl-usb2-mph" for multi port host usb
controllers, or "fsl-usb2-dr" for dual role usb controllers
- phy_type : For multi port host usb controllers, should be one of
"ulpi", or "serial". For dual role usb controllers, should be
- compatible : Should be "fsl-usb2-mph" for multi port host USB
controllers, or "fsl-usb2-dr" for dual role USB controllers
- phy_type : For multi port host USB controllers, should be one of
"ulpi", or "serial". For dual role USB controllers, should be
one of "ulpi", "utmi", "utmi_wide", or "serial".
- reg : Offset and length of the register set for the device
- port0 : boolean; if defined, indicates port0 is connected for
@ -1339,7 +1325,7 @@ platforms are moved over to use the flattened-device-tree model.
- interrupt-parent : the phandle for the interrupt controller that
services interrupts for this device.
Example multi port host usb controller device node :
Example multi port host USB controller device node :
usb@22000 {
device_type = "usb";
compatible = "fsl-usb2-mph";
@ -1353,7 +1339,7 @@ platforms are moved over to use the flattened-device-tree model.
port1;
};
Example dual role usb controller device node :
Example dual role USB controller device node :
usb@23000 {
device_type = "usb";
compatible = "fsl-usb2-dr";
@ -1387,7 +1373,7 @@ platforms are moved over to use the flattened-device-tree model.
- channel-fifo-len : An integer representing the number of
descriptor pointers each channel fetch fifo can hold.
- exec-units-mask : The bitmask representing what execution units
(EUs) are available. It's a single 32 bit cell. EU information
(EUs) are available. It's a single 32-bit cell. EU information
should be encoded following the SEC's Descriptor Header Dword
EU_SEL0 field documentation, i.e. as follows:
@ -1403,7 +1389,7 @@ platforms are moved over to use the flattened-device-tree model.
bits 8 through 31 are reserved for future SEC EUs.
- descriptor-types-mask : The bitmask representing what descriptors
are available. It's a single 32 bit cell. Descriptor type
are available. It's a single 32-bit cell. Descriptor type
information should be encoded following the SEC's Descriptor
Header Dword DESC_TYPE field documentation, i.e. as follows:
@ -1492,7 +1478,7 @@ platforms are moved over to use the flattened-device-tree model.
Required properties:
- device_type : should be "spi".
- compatible : should be "fsl_spi".
- mode : the spi operation mode, it can be "cpu" or "qe".
- mode : the SPI operation mode, it can be "cpu" or "qe".
- reg : Offset and length of the register set for the device
- interrupts : <a b> where a is the interrupt number and b is a
field that represents an encoding of the sense and level
@ -1569,6 +1555,12 @@ platforms are moved over to use the flattened-device-tree model.
- mac-address : list of bytes representing the ethernet address.
- phy-handle : The phandle for the PHY connected to this controller.
Recommended properties:
- linux,network-index : This is the intended "index" of this
network device. This is used by the bootwrapper to interpret
MAC addresses passed by the firmware when no information other
than indices is available to associate an address with a device.
Example:
ucc@2000 {
device_type = "network";
@ -1712,7 +1704,7 @@ platforms are moved over to use the flattened-device-tree model.
- 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
partition (so, the parition size should always be an even number).
partition (so, the partition size should always be an even number).
- partition-names : The list of concatenated zero terminated strings
representing the partition names.
- probe-type : The type of probe which should be done for the chip
@ -1733,6 +1725,92 @@ platforms are moved over to use the flattened-device-tree model.
More devices will be defined as this spec matures.
VII - Specifying interrupt information for devices
===================================================
The device tree represents the busses and devices of a hardware
system in a form similar to the physical bus topology of the
hardware.
In addition, a logical 'interrupt tree' exists which represents the
hierarchy and routing of interrupts in the hardware.
The interrupt tree model is fully described in the
document "Open Firmware Recommended Practice: Interrupt
Mapping Version 0.9". The document is available at:
<http://playground.sun.com/1275/practice>.
1) interrupts property
----------------------
Devices that generate interrupts to a single interrupt controller
should use the conventional OF representation described in the
OF interrupt mapping documentation.
Each device which generates interrupts must have an 'interrupt'
property. The interrupt property value is an arbitrary number of
of 'interrupt specifier' values which describe the interrupt or
interrupts for the device.
The encoding of an interrupt specifier is determined by the
interrupt domain in which the device is located in the
interrupt tree. The root of an interrupt domain specifies in
its #interrupt-cells property the number of 32-bit cells
required to encode an interrupt specifier. See the OF interrupt
mapping documentation for a detailed description of domains.
For example, the binding for the OpenPIC interrupt controller
specifies an #interrupt-cells value of 2 to encode the interrupt
number and level/sense information. All interrupt children in an
OpenPIC interrupt domain use 2 cells per interrupt in their interrupts
property.
The PCI bus binding specifies a #interrupt-cell value of 1 to encode
which interrupt pin (INTA,INTB,INTC,INTD) is used.
2) interrupt-parent property
----------------------------
The interrupt-parent property is specified to define an explicit
link between a device node and its interrupt parent in
the interrupt tree. The value of interrupt-parent is the
phandle of the parent node.
If the interrupt-parent property is not defined for a node, it's
interrupt parent is assumed to be an ancestor in the node's
_device tree_ hierarchy.
3) OpenPIC Interrupt Controllers
--------------------------------
OpenPIC interrupt controllers require 2 cells to encode
interrupt information. The first cell defines the interrupt
number. The second cell defines the sense and level
information.
Sense and level information should be encoded as follows:
0 = low to high edge sensitive type enabled
1 = active low level sensitive type enabled
2 = active high level sensitive type enabled
3 = high to low edge sensitive type enabled
4) ISA Interrupt Controllers
----------------------------
ISA PIC interrupt controllers require 2 cells to encode
interrupt information. The first cell defines the interrupt
number. The second cell defines the sense and level
information.
ISA PIC interrupt controllers should adhere to the ISA PIC
encodings listed below:
0 = active low level sensitive type enabled
1 = active high level sensitive type enabled
2 = high to low edge sensitive type enabled
3 = low to high edge sensitive type enabled
Appendix A - Sample SOC node for MPC8540
========================================

View File

@ -11,6 +11,11 @@ config PPC64
This option selects whether a 32-bit or a 64-bit kernel
will be built.
config PPC_PM_NEEDS_RTC_LIB
bool
select RTC_LIB
default y if PM
config PPC32
bool
default y if !PPC64
@ -89,7 +94,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
config ARCH_MAY_HAVE_PC_FDC
bool
default y
default !PPC_PSERIES || PCI
config PPC_OF
def_bool y
@ -157,17 +162,20 @@ config PPC_83xx
select FSL_SOC
select 83xx
select PPC_FPU
select WANT_DEVICE_TREE
config PPC_85xx
bool "Freescale 85xx"
select E500
select FSL_SOC
select 85xx
select WANT_DEVICE_TREE
config PPC_86xx
bool "Freescale 86xx"
select 6xx
select FSL_SOC
select FSL_PCIE
select PPC_FPU
select ALTIVEC
help
@ -186,7 +194,6 @@ config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
config E200
bool "Freescale e200"
@ -367,394 +374,7 @@ endmenu
source "init/Kconfig"
menu "Platform support"
depends on PPC64 || CLASSIC32
choice
prompt "Machine type"
default PPC_MULTIPLATFORM
config PPC_MULTIPLATFORM
bool "Generic desktop/server/laptop"
help
Select this option if configuring for an IBM pSeries or
RS/6000 machine, an Apple machine, or a PReP, CHRP,
Maple or Cell-based machine.
config EMBEDDED6xx
bool "Embedded 6xx/7xx/7xxx-based board"
depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
config APUS
bool "Amiga-APUS"
depends on PPC32 && BROKEN
help
Select APUS if configuring for a PowerUP Amiga.
More information is available at:
<http://linux-apus.sourceforge.net/>.
endchoice
config QUICC_ENGINE
bool
depends on PPC_MPC836x || PPC_MPC832x
default y
help
The QUICC Engine (QE) is a new generation of communications
coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
Selecting this option means that you wish to build a kernel
for a machine with a QE coprocessor.
config PPC_PSERIES
depends on PPC_MULTIPLATFORM && PPC64
bool "IBM pSeries & new (POWER5-based) iSeries"
select MPIC
select PPC_I8259
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"
depends on PPC_MULTIPLATFORM && PPC32
select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_RTAS
select PPC_MPC106
select PPC_UDBG_16550
select PPC_NATIVE
default y
config PPC_MPC52xx
bool
default n
config PPC_MPC5200
bool
select PPC_MPC52xx
default n
config PPC_MPC5200_BUGFIX
bool "MPC5200 (L25R) bugfix support"
depends on PPC_MPC5200
default n
help
Enable workarounds for original MPC5200 errata. This is not required
for MPC5200B based boards.
It is safe to say 'Y' here
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 n
config PPC_LITE5200
bool "Freescale Lite5200 Eval Board"
depends on PPC_MULTIPLATFORM && PPC32
select PPC_MPC5200
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
bool
depends on PPC_PMAC && POWER4
select MPIC
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
select PPC_970_NAP
default y
config PPC_PREP
bool "PowerPC Reference Platform (PReP) based machines"
depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
select MPIC
select PPC_I8259
select PPC_INDIRECT_PCI
select PPC_UDBG_16550
select PPC_NATIVE
default n
config PPC_MAPLE
depends on PPC_MULTIPLATFORM && PPC64
bool "Maple 970FX Evaluation Board"
select MPIC
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
select PPC_UDBG_16550
select PPC_970_NAP
select PPC_NATIVE
select PPC_RTAS
select MMIO_NVRAM
select ATA_NONSTANDARD if ATA
default n
help
This option enables support for the Maple 970FX Evaluation Board.
For more information, refer to <http://www.970eval.com>
config PPC_PASEMI
depends on PPC_MULTIPLATFORM && PPC64
bool "PA Semi SoC-based platforms"
default n
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
config PPC_CELL
bool
default n
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
bool "IBM Cell Blade"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL_NATIVE
select PPC_RTAS
select MMIO_NVRAM
select PPC_UDBG_16550
select UDBG_RTAS_CONSOLE
config PPC_PS3
bool "Sony PS3 (incomplete)"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
select USB_ARCH_HAS_OHCI
select USB_OHCI_LITTLE_ENDIAN
select USB_OHCI_BIG_ENDIAN_MMIO
select USB_ARCH_HAS_EHCI
select USB_EHCI_BIG_ENDIAN_MMIO
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor.
Support for this platform is not yet complete, so
enabling this will not result in a bootable kernel on a
PS3 system.
config PPC_CELLEB
bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
select PPC_OF_PLATFORM_PCI
select HAS_TXX9_SERIAL
select PPC_UDBG_BEAT
select USB_OHCI_BIG_ENDIAN_MMIO
select USB_EHCI_BIG_ENDIAN_MMIO
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
default n
config PPC_UDBG_BEAT
bool "BEAT based debug console"
depends on PPC_CELLEB
default n
config XICS
depends on PPC_PSERIES
bool
default y
config U3_DART
bool
depends on PPC_MULTIPLATFORM && PPC64
default n
config PPC_RTAS
bool
default n
config RTAS_ERROR_LOGGING
bool
depends on PPC_RTAS
default n
config RTAS_PROC
bool "Proc interface to RTAS"
depends on PPC_RTAS
default y
config RTAS_FLASH
tristate "Firmware flash interface"
depends on PPC64 && RTAS_PROC
config PPC_PMI
tristate "Support for PMI"
depends PPC_IBM_CELL_BLADE
help
PMI (Platform Management Interrupt) is a way to
communicate with the BMC (Baseboard Mangement Controller).
It is used in some IBM Cell blades.
default m
config MMIO_NVRAM
bool
default n
config MPIC_BROKEN_U3
bool
depends on PPC_MAPLE
default y
config IBMVIO
depends on PPC_PSERIES || PPC_ISERIES
bool
default y
config IBMEBUS
depends on PPC_PSERIES
bool "Support for GX bus based adapters"
help
Bus device driver for GX bus based adapters.
config PPC_MPC106
bool
default n
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
bool "Support for Apple PowerBooks"
depends on CPU_FREQ && ADB_PMU && PPC32
select CPU_FREQ_TABLE
help
This adds support for frequency switching on Apple PowerBooks,
this currently includes some models of iBook & Titanium
PowerBook.
config CPU_FREQ_PMAC64
bool "Support for some Apple G5s"
depends on CPU_FREQ && PPC64
select CPU_FREQ_TABLE
help
This adds support for frequency switching on Apple iMac G5,
and some of the more recent desktop G5 machines as well.
config PPC601_SYNC_FIX
bool "Workarounds for PPC601 bugs"
depends on 6xx && (PPC_PREP || PPC_PMAC)
help
Some versions of the PPC601 (the first PowerPC chip) have bugs which
mean that extra synchronization instructions are required near
certain instructions, typically those that make major changes to the
CPU state. These extra instructions reduce performance slightly.
If you say N here, these extra instructions will not be included,
resulting in a kernel which will run faster but may not run at all
on some systems with the PPC601 chip.
If in doubt, say Y here.
config TAU
bool "On-chip CPU temperature sensor support"
depends on 6xx
help
G3 and G4 processors have an on-chip temperature sensor called the
'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
temperature within 2-4 degrees Celsius. This option shows the current
on-die temperature in /proc/cpuinfo if the cpu supports it.
Unfortunately, on some chip revisions, this sensor is very inaccurate
and in many cases, does not work at all, so don't assume the cpu
temp is actually what /proc/cpuinfo says it is.
config TAU_INT
bool "Interrupt driven TAU driver (DANGEROUS)"
depends on TAU
---help---
The TAU supports an interrupt driven mode which causes an interrupt
whenever the temperature goes out of range. This is the fastest way
to get notified the temp has exceeded a range. With this option off,
a timer is used to re-check the temperature periodically.
However, on some cpus it appears that the TAU interrupt hardware
is buggy and can cause a situation which would lead unexplained hard
lockups.
Unless you are extending the TAU driver, or enjoy kernel/hardware
debugging, leave this option off.
config TAU_AVERAGE
bool "Average high and low temp"
depends on TAU
---help---
The TAU hardware can compare the temperature to an upper and lower
bound. The default behavior is to show both the upper and lower
bound in /proc/cpuinfo. If the range is large, the temperature is
either changing a lot, or the TAU hardware is broken (likely on some
G4's). If the range is small (around 4 degrees), the temperature is
relatively stable. If you say Y here, a single temperature value,
halfway between the upper and lower bounds, will be reported in
/proc/cpuinfo.
If in doubt, say N here.
endmenu
source arch/powerpc/platforms/embedded6xx/Kconfig
source arch/powerpc/platforms/4xx/Kconfig
source arch/powerpc/platforms/82xx/Kconfig
source arch/powerpc/platforms/83xx/Kconfig
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
source arch/powerpc/platforms/pasemi/Kconfig
source "arch/powerpc/platforms/Kconfig"
menu "Kernel options"
@ -837,15 +457,6 @@ config CRASH_DUMP
Don't change this unless you know what you are doing.
config EMBEDDEDBOOT
bool
depends on 8xx || 8260
default y
config PC_KEYBOARD
bool "PC PS/2 style Keyboard"
depends on 4xx || CPM2
config PPCBUG_NVRAM
bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
default y if PPC_PREP
@ -859,8 +470,6 @@ config IRQ_ALL_CPUS
CPU. Generally saying Y is safe, although some problems have been
reported with SMP Power Macintoshes with this option enabled.
source "arch/powerpc/platforms/pseries/Kconfig"
config NUMA
bool "NUMA support"
depends on PPC64
@ -931,8 +540,6 @@ config PROC_DEVICETREE
an image of the device tree that the kernel copies from Open
Firmware or other boot firmware. If unsure, say Y here.
source "arch/powerpc/platforms/prep/Kconfig"
config CMDLINE_BOOL
bool "Default bootloader kernel arguments"
@ -967,6 +574,29 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
config WANT_DEVICE_TREE
bool
default n
config DEVICE_TREE
string "Static device tree source file"
depends on WANT_DEVICE_TREE
help
This specifies the device tree source (.dts) file to be
compiled and included when building the bootwrapper. If a
relative filename is given, then it will be relative to
arch/powerpc/boot/dts. If you are not using the bootwrapper,
or do not need to build a dts into the bootwrapper, this
field is ignored.
For example, this is required when building a cuImage target
for an older U-Boot, which cannot pass a device tree itself.
Such a kernel will not work with a newer U-Boot that tries to
pass a device tree (unless you tell it not to). If your U-Boot
does not mention a device tree in "help bootm", then use the
cuImage target and specify a device tree here. Otherwise, use
the uImage target and leave this field blank.
endmenu
config ISA_DMA_API
@ -995,24 +625,17 @@ config GENERIC_ISA_DMA
depends on PPC64 || POWER4 || 6xx && !CPM2
default y
config MPIC
bool
default n
config MPIC_WEIRD
bool
default n
config PPC_I8259
bool
default n
config PPC_INDIRECT_PCI
bool
depends on PCI
default y if 40x || 44x
default n
config PPC_INDIRECT_PCI_BE
bool
depends PPC_INDIRECT_PCI
default n
config EISA
bool
@ -1022,13 +645,18 @@ config SBUS
config FSL_SOC
bool
config FSL_PCIE
bool
depends on PPC_86xx
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3
|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || 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
@ -1228,8 +856,6 @@ source "fs/Kconfig"
source "arch/powerpc/sysdev/qe_lib/Kconfig"
source "arch/powerpc/platforms/iseries/Kconfig"
source "lib/Kconfig"
menu "Instrumentation Support"

View File

@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
config DEBUG_PAGEALLOC
bool "Debug page memory allocations"
depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
of memory corruptions.
config HCALL_STATS
bool "Hypervisor call instrumentation"
depends on PPC_PSERIES && DEBUG_FS
@ -132,8 +141,7 @@ config BOOTX_TEXT
config SERIAL_TEXT_DEBUG
bool "Support for early boot texts over serial port"
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
PPC_GEN550 || PPC_MPC52xx
depends on 4xx
config PPC_EARLY_DEBUG
bool "Early debugging (dangerous)"

View File

@ -102,9 +102,9 @@ CFLAGS += $(call cc-option,-mno-altivec)
# kernel considerably.
CFLAGS += $(call cc-option,-funit-at-a-time)
ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
# Never use string load/store instructions as they are
# often slow when they are implemented at all
CFLAGS += -mno-string
ifeq ($(CONFIG_6xx),y)
CFLAGS += -mcpu=powerpc
@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
CPPFLAGS_vmlinux.lds := -Upowerpc
BOOT_TARGETS = zImage zImage.initrd uImage
BOOT_TARGETS = zImage zImage.initrd uImage cuImage
PHONY += $(BOOT_TARGETS)
@ -166,6 +166,9 @@ define archhelp
@echo ' *_defconfig - Select default config from arch/$(ARCH)/configs'
endef
install:
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
archclean:
$(Q)$(MAKE) $(clean)=$(boot)

View File

@ -18,6 +18,9 @@ kernel-vmlinux.strip.c
kernel-vmlinux.strip.gz
mktree
uImage
cuImage
cuImage.bin.gz
cuImage.elf
zImage
zImage.chrp
zImage.coff

View File

@ -40,10 +40,11 @@ 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 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
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@ -75,7 +76,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
empty.c zImage.coff.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@ -84,23 +85,25 @@ quiet_cmd_bootas = BOOTAS $@
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
quiet_cmd_bootar = BOOTAR $@
cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $^; mv $@.$$$$ $@
cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
$(call if_changed_dep,bootcc)
$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
$(call if_changed_dep,bootas)
$(obj)/wrapper.a: $(obj-wlib)
$(call cmd,bootar)
$(obj)/wrapper.a: $(obj-wlib) FORCE
$(call if_changed,bootar)
hostprogs-y := addnote addRamDisk hack-coff mktree
extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(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 mktree)
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
$(wrapper) FORCE
#############
# Bits for building various flavours of zImage
@ -113,50 +116,10 @@ CROSSWRAP := -C "$(CROSS_COMPILE)"
endif
endif
# args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd
quiet_cmd_wrap = WRAP $@
cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux
quiet_cmd_wrap_initrd = WRAP $@
cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
-i $(obj)/ramdisk.image.gz vmlinux
$(obj)/zImage.chrp: vmlinux $(wrapperbits)
$(call cmd,wrap,chrp)
$(obj)/zImage.initrd.chrp: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,chrp)
$(obj)/zImage.pseries: vmlinux $(wrapperbits)
$(call cmd,wrap,pseries)
$(obj)/zImage.initrd.pseries: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,pseries)
$(obj)/zImage.pmac: vmlinux $(wrapperbits)
$(call cmd,wrap,pmac)
$(obj)/zImage.initrd.pmac: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,pmac)
$(obj)/zImage.coff: vmlinux $(wrapperbits)
$(call cmd,wrap,pmaccoff)
$(obj)/zImage.initrd.coff: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,pmaccoff)
$(obj)/zImage.miboot: vmlinux $(wrapperbits)
$(call cmd,wrap,miboot)
$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits)
$(call cmd,wrap_initrd,miboot)
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/zImage.initrd.ps3: vmlinux
@echo " WARNING zImage.initrd.ps3 not supported (yet)"
$(obj)/uImage: vmlinux $(wrapperbits)
$(call cmd,wrap,uboot)
cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
image-$(CONFIG_PPC_MAPLE) += zImage.pseries
@ -166,7 +129,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
image-$(CONFIG_DEFAULT_UIMAGE) += uImage cuImage
# For 32-bit powermacs, build the COFF and miboot images
# as well as the ELF images.
@ -174,16 +137,55 @@ ifeq ($(CONFIG_PPC32),y)
image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot
endif
initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y))
initrd-y := $(filter-out $(image-y), $(initrd-y))
targets += $(image-y) $(initrd-y)
$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
# Don't put the ramdisk on the pattern rule; when its missing make will try
# the pattern rule with less dependencies that also matches (even with the
# hard dependency listed).
$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
$(obj)/zImage.%: vmlinux $(wrapperbits)
$(call if_changed,wrap,$*)
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
$(obj)/zImage.initrd.ps3: vmlinux
@echo " WARNING zImage.initrd.ps3 not supported (yet)"
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
cuboot-plat-$(CONFIG_83xx) += 83xx
cuboot-plat-$(CONFIG_85xx) += 85xx
cuboot-plat-y += unknown-platform
dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE)
$(obj)/cuImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts))
$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
@rm -f $@; ln $< $@
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
@rm -f $@; ln $< $@
install: $(CONFIGURE) $(image-y)
install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz)
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz)
clean-files += $(image-)
# anything not in $(targets)
clean-files += $(image-) $(initrd-) zImage zImage.initrd \
cuImage.elf cuImage.bin.gz
# clean up files cached by wrapper
clean-kernel := vmlinux.strip vmlinux.bin
clean-kernel += $(addsuffix .gz,$(clean-kernel))
# If not absolute clean-files are relative to $(obj).
clean-files += $(addprefix $(objtree)/, $(clean-kernel))

View File

@ -16,8 +16,11 @@
_zimage_start_opd:
.long _zimage_start, 0, 0, 0
.weak _zimage_start
.globl _zimage_start
_zimage_start:
.globl _zimage_start_lib
_zimage_start_lib:
/* Work out the offset between the address we were linked at
and the address where we're running. */
bl 1f
@ -44,7 +47,7 @@ _zimage_start:
addi r9,r9,4
bdnz 2b
/* Do a cache flush for our text, in case OF didn't */
/* Do a cache flush for our text, in case the loader didn't */
3: lis r9,_start@ha
addi r9,r9,_start@l
add r9,r0,r9
@ -59,6 +62,34 @@ _zimage_start:
sync
isync
mr r6,r1
b start
/* Clear the BSS */
lis r9,__bss_start@ha
addi r9,r9,__bss_start@l
add r9,r0,r9
lis r8,_end@ha
addi r8,r8,_end@l
add r8,r0,r8
li r10,0
5: stw r10,0(r9)
addi r9,r9,4
cmplw cr0,r9,r8
blt 5b
/* Possibly set up a custom stack */
.weak _platform_stack_top
lis r8,_platform_stack_top@ha
addi r8,r8,_platform_stack_top@l
cmpwi r8,0
beq 6f
add r8,r0,r8
lwz r1,0(r8)
add r1,r0,r1
li r0,0
stwu r0,-16(r1) /* establish a stack frame */
6:
/* Call platform_init() */
bl platform_init
/* Call start */
b start

View File

@ -0,0 +1,68 @@
/*
* Old U-boot compatibility for 83xx
*
* Author: Scott Wood <scottwood@freescale.com>
*
* Copyright (c) 2007 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include "ops.h"
#include "stdio.h"
#define TARGET_83xx
#include "ppcboot.h"
static bd_t bd;
extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
{
void *soc;
dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);
/* Unfortunately, the specific model number is encoded in the
* soc node name in existing dts files -- once that is fixed,
* this can do a simple path lookup.
*/
soc = find_node_by_devtype(NULL, "soc");
if (soc) {
void *serial = NULL;
setprop(soc, "bus-frequency", &bd.bi_busfreq,
sizeof(bd.bi_busfreq));
while ((serial = find_node_by_devtype(serial, "serial"))) {
if (get_parent(serial) != soc)
continue;
setprop(serial, "clock-frequency", &bd.bi_busfreq,
sizeof(bd.bi_busfreq));
}
}
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
memcpy(&bd, (bd_t *)r3, sizeof(bd));
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;
}

View File

@ -0,0 +1,69 @@
/*
* Old U-boot compatibility for 85xx
*
* Author: Scott Wood <scottwood@freescale.com>
*
* Copyright (c) 2007 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include "ops.h"
#include "stdio.h"
#define TARGET_85xx
#include "ppcboot.h"
static bd_t bd;
extern char _end[];
extern char _dtb_start[], _dtb_end[];
static void platform_fixups(void)
{
void *soc;
dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr,
bd.bi_enet2addr);
dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 8, bd.bi_busfreq);
/* Unfortunately, the specific model number is encoded in the
* soc node name in existing dts files -- once that is fixed,
* this can do a simple path lookup.
*/
soc = find_node_by_devtype(NULL, "soc");
if (soc) {
void *serial = NULL;
setprop(soc, "bus-frequency", &bd.bi_busfreq,
sizeof(bd.bi_busfreq));
while ((serial = find_node_by_devtype(serial, "serial"))) {
if (get_parent(serial) != soc)
continue;
setprop(serial, "clock-frequency", &bd.bi_busfreq,
sizeof(bd.bi_busfreq));
}
}
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
unsigned long avail_ram = end_of_ram - (unsigned long)_end;
memcpy(&bd, (bd_t *)r3, sizeof(bd));
loader_info.initrd_addr = r4;
loader_info.initrd_size = r4 ? r5 : 0;
loader_info.cmdline = (char *)r6;
loader_info.cmdline_len = r7 - r6;
simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
serial_console_init();
platform_ops.fixups = platform_fixups;
}

307
arch/powerpc/boot/devtree.c Normal file
View File

@ -0,0 +1,307 @@
/*
* devtree.c - convenience functions for device tree manipulation
* Copyright 2007 David Gibson, IBM Corporation.
* Copyright (c) 2007 Freescale Semiconductor, Inc.
*
* Authors: David Gibson <david@gibson.dropbear.id.au>
* Scott Wood <scottwood@freescale.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 <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "string.h"
#include "stdio.h"
#include "ops.h"
void dt_fixup_memory(u64 start, u64 size)
{
void *root, *memory;
int naddr, nsize, i;
u32 memreg[4];
root = finddevice("/");
if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0)
naddr = 2;
if (naddr < 1 || naddr > 2)
fatal("Can't cope with #address-cells == %d in /\n\r", naddr);
if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0)
nsize = 1;
if (nsize < 1 || nsize > 2)
fatal("Can't cope with #size-cells == %d in /\n\r", nsize);
i = 0;
if (naddr == 2)
memreg[i++] = start >> 32;
memreg[i++] = start & 0xffffffff;
if (nsize == 2)
memreg[i++] = size >> 32;
memreg[i++] = size & 0xffffffff;
memory = finddevice("/memory");
if (! memory) {
memory = create_node(NULL, "memory");
setprop_str(memory, "device_type", "memory");
}
printf("Memory <- <0x%x", memreg[0]);
for (i = 1; i < (naddr + nsize); i++)
printf(" 0x%x", memreg[i]);
printf("> (%ldMB)\n\r", (unsigned long)(size >> 20));
setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32));
}
#define MHZ(x) ((x + 500000) / 1000000)
void dt_fixup_cpu_clocks(u32 cpu, u32 tb, u32 bus)
{
void *devp = NULL;
printf("CPU clock-frequency <- 0x%x (%dMHz)\n\r", cpu, MHZ(cpu));
printf("CPU timebase-frequency <- 0x%x (%dMHz)\n\r", tb, MHZ(tb));
if (bus > 0)
printf("CPU bus-frequency <- 0x%x (%dMHz)\n\r", bus, MHZ(bus));
while ((devp = find_node_by_devtype(devp, "cpu"))) {
setprop_val(devp, "clock-frequency", cpu);
setprop_val(devp, "timebase-frequency", tb);
if (bus > 0)
setprop_val(devp, "bus-frequency", bus);
}
}
void dt_fixup_clock(const char *path, u32 freq)
{
void *devp = finddevice(path);
if (devp) {
printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq));
setprop_val(devp, "clock-frequency", freq);
}
}
void __dt_fixup_mac_addresses(u32 startindex, ...)
{
va_list ap;
u32 index = startindex;
void *devp;
const u8 *addr;
va_start(ap, startindex);
while ((addr = va_arg(ap, const u8 *))) {
devp = find_node_by_prop_value(NULL, "linux,network-index",
(void*)&index, sizeof(index));
printf("ENET%d: local-mac-address <-"
" %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
if (devp)
setprop(devp, "local-mac-address", addr, 6);
index++;
}
va_end(ap);
}
#define MAX_ADDR_CELLS 4
#define MAX_RANGES 8
static void get_reg_format(void *node, u32 *naddr, u32 *nsize)
{
if (getprop(node, "#address-cells", naddr, 4) != 4)
*naddr = 2;
if (getprop(node, "#size-cells", nsize, 4) != 4)
*nsize = 1;
}
static void copy_val(u32 *dest, u32 *src, int naddr)
{
int pad = MAX_ADDR_CELLS - naddr;
memset(dest, 0, pad * 4);
memcpy(dest + pad, src, naddr * 4);
}
static int sub_reg(u32 *reg, u32 *sub)
{
int i, borrow = 0;
for (i = MAX_ADDR_CELLS - 1; i >= 0; i--) {
int prev_borrow = borrow;
borrow = reg[i] < sub[i] + prev_borrow;
reg[i] -= sub[i] + prev_borrow;
}
return !borrow;
}
static int add_reg(u32 *reg, u32 *add, int naddr)
{
int i, carry = 0;
for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) {
u64 tmp = (u64)reg[i] + add[i] + carry;
carry = tmp >> 32;
reg[i] = (u32)tmp;
}
return !carry;
}
/* It is assumed that if the first byte of reg fits in a
* range, then the whole reg block fits.
*/
static int compare_reg(u32 *reg, u32 *range, u32 *rangesize)
{
int i;
u32 end;
for (i = 0; i < MAX_ADDR_CELLS; i++) {
if (reg[i] < range[i])
return 0;
if (reg[i] > range[i])
break;
}
for (i = 0; i < MAX_ADDR_CELLS; i++) {
end = range[i] + rangesize[i];
if (reg[i] < end)
break;
if (reg[i] > end)
return 0;
}
return reg[i] != end;
}
/* reg must be MAX_ADDR_CELLS */
static int find_range(u32 *reg, u32 *ranges, int nregaddr,
int naddr, int nsize, int buflen)
{
int nrange = nregaddr + naddr + nsize;
int i;
for (i = 0; i + nrange <= buflen; i += nrange) {
u32 range_addr[MAX_ADDR_CELLS];
u32 range_size[MAX_ADDR_CELLS];
copy_val(range_addr, ranges + i, naddr);
copy_val(range_size, ranges + i + nregaddr + naddr, nsize);
if (compare_reg(reg, range_addr, range_size))
return i;
}
return -1;
}
/* Currently only generic buses without special encodings are supported.
* In particular, PCI is not supported. Also, only the beginning of the
* reg block is tracked; size is ignored except in ranges.
*/
static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3];
static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
unsigned long *size)
{
u32 last_addr[MAX_ADDR_CELLS];
u32 this_addr[MAX_ADDR_CELLS];
void *parent;
u64 ret_addr, ret_size;
u32 naddr, nsize, prev_naddr;
int buflen, offset;
parent = get_parent(node);
if (!parent)
return 0;
get_reg_format(parent, &naddr, &nsize);
if (nsize > 2)
return 0;
offset = (naddr + nsize) * res;
if (reglen < offset + naddr + nsize ||
sizeof(dt_xlate_buf) < offset + naddr + nsize)
return 0;
copy_val(last_addr, dt_xlate_buf + offset, naddr);
ret_size = dt_xlate_buf[offset + naddr];
if (nsize == 2) {
ret_size <<= 32;
ret_size |= dt_xlate_buf[offset + naddr + 1];
}
while ((node = get_parent(node))) {
prev_naddr = naddr;
get_reg_format(node, &naddr, &nsize);
buflen = getprop(node, "ranges", dt_xlate_buf,
sizeof(dt_xlate_buf));
if (buflen < 0)
continue;
if (buflen > sizeof(dt_xlate_buf))
return 0;
offset = find_range(last_addr, dt_xlate_buf, prev_naddr,
naddr, nsize, buflen / 4);
if (offset < 0)
return 0;
copy_val(this_addr, dt_xlate_buf + offset, prev_naddr);
if (!sub_reg(last_addr, this_addr))
return 0;
copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr);
if (!add_reg(last_addr, this_addr, naddr))
return 0;
}
if (naddr > 2)
return 0;
ret_addr = ((u64)last_addr[2] << 32) | last_addr[3];
if (sizeof(void *) == 4 &&
(ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL ||
ret_addr + ret_size > 0x100000000ULL))
return 0;
*addr = ret_addr;
if (size)
*size = ret_size;
return 1;
}
int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size)
{
int reglen;
reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4;
return dt_xlate(node, res, reglen, addr, size);
}
int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr)
{
if (buflen > sizeof(dt_xlate_buf))
return 0;
memcpy(dt_xlate_buf, buf, buflen);
return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL);
}

View File

@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
cpus {
linux,phandle = <2000>;
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
interrupt-parent = <4400>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 - IRQ0 ETH */
/* IDSEL 11 - 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 */
/* IDSEL 12 - 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 */
/* IDSEL 14 - IRQ3 USB2.0 */
7000 0 0 1 4400 3 1
7000 0 0 2 4400 3 1
7000 0 0 3 4400 3 1

View File

@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
cpus {
linux,phandle = <2000>;
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
interrupt-parent = <4400>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 - IRQ0 ETH */
/* IDSEL 11 - 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 */
/* IDSEL 12 - 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 */
/* IDSEL 14 - IRQ3 USB2.0 */
7000 0 0 1 4400 3 1
7000 0 0 2 4400 3 1
7000 0 0 3 4400 3 1

View File

@ -24,7 +24,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -24,7 +24,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -19,7 +19,6 @@
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells =<0>;
linux,phandle = <200>;

View File

@ -17,7 +17,6 @@
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;

View File

@ -16,7 +16,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -16,7 +16,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -0,0 +1,291 @@
/*
* MPC832x RDB Device Tree Source
*
* Copyright 2007 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/ {
model = "MPC8323ERDB";
compatible = "MPC8323ERDB", "MPC832xRDB", "MPC83xxRDB";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,8323@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; // 32 bytes
i-cache-line-size = <20>; // 32 bytes
d-cache-size = <4000>; // L1, 16K
i-cache-size = <4000>; // L1, 16K
timebase-frequency = <0>;
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
};
};
memory {
device_type = "memory";
reg = <00000000 04000000>;
};
soc8323@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
ranges = <0 e0000000 00100000>;
reg = <e0000000 00000200>;
bus-frequency = <0>;
wdt@200 {
device_type = "watchdog";
compatible = "mpc83xx_wdt";
reg = <200 100>;
};
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
interrupt-parent = <&pic>;
dfsrr;
};
serial@4500 {
device_type = "serial";
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <9 8>;
interrupt-parent = <&pic>;
};
serial@4600 {
device_type = "serial";
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <a 8>;
interrupt-parent = <&pic>;
};
crypto@30000 {
device_type = "crypto";
model = "SEC2";
compatible = "talitos";
reg = <30000 7000>;
interrupts = <b 8>;
interrupt-parent = <&pic>;
/* Rev. 2.2 */
num-channels = <1>;
channel-fifo-len = <18>;
exec-units-mask = <0000004c>;
descriptor-types-mask = <0122003f>;
};
pci@8500 {
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 AD16 (USB) */
8000 0 0 1 &pic 11 8
/* IDSEL 0x11 AD17 (Mini1)*/
8800 0 0 1 &pic 12 8
8800 0 0 2 &pic 13 8
8800 0 0 3 &pic 14 8
8800 0 0 4 &pic 30 8
/* IDSEL 0x12 AD18 (PCI/Mini2) */
9000 0 0 1 &pic 13 8
9000 0 0 2 &pic 14 8
9000 0 0 3 &pic 30 8
9000 0 0 4 &pic 11 8>;
interrupt-parent = <&pic>;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <42000000 0 80000000 80000000 0 10000000
02000000 0 90000000 90000000 0 10000000
01000000 0 d0000000 d0000000 0 04000000>;
clock-frequency = <0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <8500 100>;
compatible = "83xx";
device_type = "pci";
};
pic:pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <700 100>;
built-in;
device_type = "ipic";
};
par_io@1400 {
reg = <1400 100>;
device_type = "par_io";
num-ports = <7>;
ucc2pio:ucc_pin@02 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
3 4 3 0 2 0 /* MDIO */
3 5 1 0 2 0 /* MDC */
3 15 2 0 1 0 /* RX_CLK (CLK16) */
3 17 2 0 1 0 /* TX_CLK (CLK3) */
0 12 1 0 1 0 /* TxD0 */
0 13 1 0 1 0 /* TxD1 */
0 14 1 0 1 0 /* TxD2 */
0 15 1 0 1 0 /* TxD3 */
0 16 2 0 1 0 /* RxD0 */
0 17 2 0 1 0 /* RxD1 */
0 18 2 0 1 0 /* RxD2 */
0 19 2 0 1 0 /* RxD3 */
0 1a 2 0 1 0 /* RX_ER */
0 1b 1 0 1 0 /* TX_ER */
0 1c 2 0 1 0 /* RX_DV */
0 1d 2 0 1 0 /* COL */
0 1e 1 0 1 0 /* TX_EN */
0 1f 2 0 1 0>; /* CRS */
};
ucc3pio:ucc_pin@03 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0 d 2 0 1 0 /* RX_CLK (CLK9) */
3 18 2 0 1 0 /* TX_CLK (CLK10) */
1 0 1 0 1 0 /* TxD0 */
1 1 1 0 1 0 /* TxD1 */
1 2 1 0 1 0 /* TxD2 */
1 3 1 0 1 0 /* TxD3 */
1 4 2 0 1 0 /* RxD0 */
1 5 2 0 1 0 /* RxD1 */
1 6 2 0 1 0 /* RxD2 */
1 7 2 0 1 0 /* RxD3 */
1 8 2 0 1 0 /* RX_ER */
1 9 1 0 1 0 /* TX_ER */
1 a 2 0 1 0 /* RX_DV */
1 b 2 0 1 0 /* COL */
1 c 1 0 1 0 /* TX_EN */
1 d 2 0 1 0>; /* CRS */
};
};
};
qe@e0100000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "qe";
model = "QE";
ranges = <0 e0100000 00100000>;
reg = <e0100000 480>;
brg-frequency = <0>;
bus-frequency = <BCD3D80>;
muram@10000 {
device_type = "muram";
ranges = <0 00010000 00004000>;
data-only@0 {
reg = <0 4000>;
};
};
spi@4c0 {
device_type = "spi";
compatible = "fsl_spi";
reg = <4c0 40>;
interrupts = <2>;
interrupt-parent = <&qeic>;
mode = "cpu";
};
spi@500 {
device_type = "spi";
compatible = "fsl_spi";
reg = <500 40>;
interrupts = <1>;
interrupt-parent = <&qeic>;
mode = "cpu";
};
ucc@3000 {
device_type = "network";
compatible = "ucc_geth";
model = "UCC";
device-id = <2>;
reg = <3000 200>;
interrupts = <21>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f ef 03 02 ];
rx-clock = <20>;
tx-clock = <13>;
phy-handle = <&phy00>;
pio-handle = <&ucc2pio>;
};
ucc@2200 {
device_type = "network";
compatible = "ucc_geth";
model = "UCC";
device-id = <3>;
reg = <2200 200>;
interrupts = <22>;
interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f ef 03 01 ];
rx-clock = <19>;
tx-clock = <1a>;
phy-handle = <&phy04>;
pio-handle = <&ucc3pio>;
};
mdio@3120 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3120 18>;
device_type = "mdio";
compatible = "ucc_geth_phy";
phy00:ethernet-phy@00 {
interrupt-parent = <&pic>;
interrupts = <0>;
reg = <0>;
device_type = "ethernet-phy";
interface = <3>; //ENET_100_MII
};
phy04:ethernet-phy@04 {
interrupt-parent = <&pic>;
interrupts = <0>;
reg = <4>;
device_type = "ethernet-phy";
interface = <3>;
};
};
qeic:qeic@80 {
interrupt-controller;
device_type = "qeic";
#address-cells = <0>;
#interrupt-cells = <1>;
reg = <80 80>;
built-in;
big-endian;
interrupts = <20 8 21 8>; //high:32 low:33
interrupt-parent = <&pic>;
};
};
};

View File

@ -15,7 +15,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -15,7 +15,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -16,7 +16,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -21,7 +21,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -0,0 +1,136 @@
/*
* MPC8544 DS Device Tree Source
*
* Copyright 2007 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/ {
model = "MPC8544DS";
compatible = "MPC8544DS", "MPC85xxDS";
#address-cells = <1>;
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,8544@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; // 32 bytes
i-cache-line-size = <20>; // 32 bytes
d-cache-size = <8000>; // L1, 32K
i-cache-size = <8000>; // L1, 32K
timebase-frequency = <0>;
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
};
};
memory {
device_type = "memory";
reg = <00000000 00000000>; // Filled by U-Boot
};
soc8544@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
ranges = <0 e0000000 00100000>;
reg = <e0000000 00100000>; // CCSRBAR 1M
bus-frequency = <0>; // Filled out by uboot.
i2c@3000 {
device_type = "i2c";
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
interrupt-parent = <&mpic>;
dfsrr;
};
mdio@24520 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
phy0: ethernet-phy@0 {
interrupt-parent = <&mpic>;
interrupts = <3a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
phy1: ethernet-phy@1 {
interrupt-parent = <&mpic>;
interrupts = <3a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
};
ethernet@24000 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <d 2 e 2 12 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy0>;
};
ethernet@26000 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <26000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <f 2 10 2 11 2>;
interrupt-parent = <&mpic>;
phy-handle = <&phy1>;
};
serial@4500 {
device_type = "serial";
compatible = "ns16550";
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupt-parent = <&mpic>;
};
serial@4600 {
device_type = "serial";
compatible = "ns16550";
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
interrupt-parent = <&mpic>;
};
mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <40000 40000>;
built-in;
compatible = "chrp,open-pic";
device_type = "open-pic";
big-endian;
};
};
};

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -21,7 +21,6 @@
#size-cells = <1>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -17,7 +17,6 @@
#size-cells = <1>;
cpus {
#cpus = <2>;
#address-cells = <1>;
#size-cells = <0>;
@ -300,6 +299,30 @@
};
};
pci@9000 {
compatible = "86xx";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <9000 1000>;
bus-range = <0 ff>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
01000000 0 00000000 e3000000 0 00100000>;
clock-frequency = <1fca055>;
interrupt-parent = <&mpic>;
interrupts = <19 2>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0 */
0000 0 0 1 &mpic 44 1
0000 0 0 2 &mpic 45 1
0000 0 0 3 &mpic 46 1
0000 0 0 4 &mpic 47 1
>;
};
mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;

View File

@ -18,7 +18,6 @@
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;

View File

@ -18,7 +18,6 @@
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;

View File

@ -146,4 +146,12 @@ typedef struct elf64_phdr {
#define ELFOSABI_NONE 0
#define ELFOSABI_LINUX 3
struct elf_info {
unsigned long loadsize;
unsigned long memsize;
unsigned long elfoffset;
};
int parse_elf64(void *hdr, struct elf_info *info);
int parse_elf32(void *hdr, struct elf_info *info);
#endif /* _PPC_BOOT_ELF_H_ */

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) Paul Mackerras 1997.
*
* Updates for PPC64 by Todd Inglett, Dave Engebretsen & Peter Bergner.
*
* 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 <stdarg.h>
#include <stddef.h>
#include "elf.h"
#include "page.h"
#include "string.h"
#include "stdio.h"
int parse_elf64(void *hdr, struct elf_info *info)
{
Elf64_Ehdr *elf64 = hdr;
Elf64_Phdr *elf64ph;
unsigned int i;
if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 &&
elf64->e_ident[EI_MAG1] == ELFMAG1 &&
elf64->e_ident[EI_MAG2] == ELFMAG2 &&
elf64->e_ident[EI_MAG3] == ELFMAG3 &&
elf64->e_ident[EI_CLASS] == ELFCLASS64 &&
elf64->e_ident[EI_DATA] == ELFDATA2MSB &&
elf64->e_type == ET_EXEC &&
elf64->e_machine == EM_PPC64))
return 0;
elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
(unsigned long)elf64->e_phoff);
for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++)
if (elf64ph->p_type == PT_LOAD)
break;
if (i >= (unsigned int)elf64->e_phnum)
return 0;
info->loadsize = (unsigned long)elf64ph->p_filesz;
info->memsize = (unsigned long)elf64ph->p_memsz;
info->elfoffset = (unsigned long)elf64ph->p_offset;
return 1;
}
int parse_elf32(void *hdr, struct elf_info *info)
{
Elf32_Ehdr *elf32 = hdr;
Elf32_Phdr *elf32ph;
unsigned int i;
if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 &&
elf32->e_ident[EI_MAG1] == ELFMAG1 &&
elf32->e_ident[EI_MAG2] == ELFMAG2 &&
elf32->e_ident[EI_MAG3] == ELFMAG3 &&
elf32->e_ident[EI_CLASS] == ELFCLASS32 &&
elf32->e_ident[EI_DATA] == ELFDATA2MSB &&
elf32->e_type == ET_EXEC &&
elf32->e_machine == EM_PPC))
return 0;
elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
for (i = 0; i < elf32->e_phnum; i++, elf32ph++)
if (elf32ph->p_type == PT_LOAD)
break;
if (i >= elf32->e_phnum)
return 0;
info->loadsize = elf32ph->p_filesz;
info->memsize = elf32ph->p_memsz;
info->elfoffset = elf32ph->p_offset;
return 1;
}

View File

@ -29,12 +29,20 @@
#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
static char *ft_root_node(struct ft_cxt *cxt)
{
return cxt->rgn[FT_STRUCT].start;
}
/* 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)
static void *ft_get_phandle(struct ft_cxt *cxt, char *node)
{
unsigned int i;
if (!node)
return NULL;
for (i = 1; i < cxt->nodes_used; i++) /* already there? */
if (cxt->node_tbl[i] == node)
return (void *)i;
@ -238,7 +246,7 @@ static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
if (rgn == FT_STRUCT)
ft_node_update_before(cxt, p, -nextra);
}
*p -= nextra;
*pp -= nextra;
cxt->rgn[rgn].start -= nextra;
cxt->rgn[rgn].size += nextra;
return 1;
@ -253,8 +261,14 @@ static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
char *str, *next;
enum ft_rgn_id r;
if (!cxt->isordered && !ft_reorder(cxt, nextra))
if (!cxt->isordered) {
unsigned long rgn_off = *pp - cxt->rgn[rgn].start;
if (!ft_reorder(cxt, nextra))
return 0;
*pp = cxt->rgn[rgn].start + rgn_off;
}
if (ft_shuffle(cxt, pp, rgn, nextra))
return 1;
@ -415,7 +429,7 @@ int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
{
int off, len;
off = lookup_string(cxt, name);
off = map_string(cxt, name);
if (off == NO_STRING)
return -1;
@ -590,7 +604,7 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
void ft_begin_tree(struct ft_cxt *cxt)
{
cxt->p = cxt->rgn[FT_STRUCT].start;
cxt->p = ft_root_node(cxt);
}
void ft_end_tree(struct ft_cxt *cxt)
@ -636,8 +650,21 @@ void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
/* 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);
node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path);
return ft_get_phandle(cxt, node);
}
void *ft_find_device_rel(struct ft_cxt *cxt, const void *top,
const char *srch_path)
{
char *node;
node = ft_node_ph2node(cxt, top);
if (node == NULL)
return NULL;
node = ft_find_descendent(cxt, node, srch_path);
return ft_get_phandle(cxt, node);
}
void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
@ -701,23 +728,18 @@ void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
return NULL;
}
void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
void *__ft_get_parent(struct ft_cxt *cxt, void *node)
{
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];
return d > 0 ? cxt->genealogy[d - 1] : NULL;
/* have to do it the hard way... */
p = cxt->rgn[FT_STRUCT].start;
p = ft_root_node(cxt);
d = 0;
while ((p = ft_next(cxt, p, &atom)) != NULL) {
switch (atom.tag) {
@ -726,7 +748,7 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
if (node == atom.data) {
/* found it */
cxt->genealogy[d + 1] = NULL;
return d > 0 ? cxt->genealogy[d - 1] : node;
return d > 0 ? cxt->genealogy[d - 1] : NULL;
}
++d;
break;
@ -738,39 +760,129 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
return NULL;
}
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
void *buf, const unsigned int buflen)
void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
{
void *node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return NULL;
node = __ft_get_parent(cxt, node);
return ft_get_phandle(cxt, node);
}
static const void *__ft_get_prop(struct ft_cxt *cxt, void *node,
const char *propname, unsigned int *len)
{
struct ft_atom atom;
void *node;
char *p;
int depth;
unsigned int size;
int depth = 0;
node = ft_node_ph2node(cxt, phandle);
if (node == NULL)
return -1;
depth = 0;
p = (char *)node;
while ((p = ft_next(cxt, p, &atom)) != NULL) {
while ((node = ft_next(cxt, node, &atom)) != NULL) {
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
++depth;
break;
case OF_DT_PROP:
if ((depth != 1) || strcmp(atom.name, propname))
if (depth != 1 || strcmp(atom.name, propname))
break;
size = min(atom.size, buflen);
memcpy(buf, atom.data, size);
return atom.size;
if (len)
*len = atom.size;
return atom.data;
case OF_DT_END_NODE:
if (--depth <= 0)
return -1;
return NULL;
}
}
return NULL;
}
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
void *buf, const unsigned int buflen)
{
const void *data;
unsigned int size;
void *node = ft_node_ph2node(cxt, phandle);
if (!node)
return -1;
data = __ft_get_prop(cxt, node, propname, &size);
if (data) {
unsigned int clipped_size = min(size, buflen);
memcpy(buf, data, clipped_size);
return size;
}
return -1;
}
void *__ft_find_node_by_prop_value(struct ft_cxt *cxt, void *prev,
const char *propname, const char *propval,
unsigned int proplen)
{
struct ft_atom atom;
char *p = ft_root_node(cxt);
char *next;
int past_prev = prev ? 0 : 1;
int depth = -1;
while ((next = ft_next(cxt, p, &atom)) != NULL) {
const void *data;
unsigned int size;
switch (atom.tag) {
case OF_DT_BEGIN_NODE:
depth++;
if (prev == p) {
past_prev = 1;
break;
}
if (!past_prev || depth < 1)
break;
data = __ft_get_prop(cxt, p, propname, &size);
if (!data || size != proplen)
break;
if (memcmp(data, propval, size))
break;
return p;
case OF_DT_END_NODE:
if (depth-- == 0)
return NULL;
break;
}
p = next;
}
return NULL;
}
void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
const char *propname, const char *propval,
int proplen)
{
void *node = NULL;
if (prev) {
node = ft_node_ph2node(cxt, prev);
if (!node)
return NULL;
}
node = __ft_find_node_by_prop_value(cxt, node, propname,
propval, proplen);
return ft_get_phandle(cxt, node);
}
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
@ -849,19 +961,26 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
return -1;
}
void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name)
{
struct ft_atom atom;
char *p, *next;
int depth = 0;
p = cxt->rgn[FT_STRUCT].start;
if (parent) {
p = ft_node_ph2node(cxt, parent);
if (!p)
return NULL;
} else {
p = ft_root_node(cxt);
}
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 */
if (depth == 1 && strcmp(atom.name, name) == 0)
/* duplicate node name, return error */
return NULL;
break;
case OF_DT_END_NODE:
@ -870,7 +989,7 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
break;
/* end of node, insert here */
cxt->p = p;
ft_begin_node(cxt, path);
ft_begin_node(cxt, name);
ft_end_node(cxt);
return p;
}

View File

@ -97,10 +97,17 @@ 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_device_rel(struct ft_cxt *cxt, const void *top,
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);
void *ft_get_parent(struct ft_cxt *cxt, const void *phandle);
void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
const char *propname, const char *propval,
int proplen);
void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name);
#endif /* FLATDEVTREE_H */

View File

@ -16,24 +16,43 @@
static struct ft_cxt cxt;
static void *ft_finddevice(const char *name)
static void *fdtm_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)
static int fdtm_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,
static int fdtm_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)
static void *fdtm_get_parent(const void *phandle)
{
return ft_get_parent(&cxt, phandle);
}
static void *fdtm_create_node(const void *phandle, const char *name)
{
return ft_create_node(&cxt, phandle, name);
}
static void *fdtm_find_node_by_prop_value(const void *prev,
const char *propname,
const char *propval,
int proplen)
{
return ft_find_node_by_prop_value(&cxt, prev, propname,
propval, proplen);
}
static unsigned long fdtm_finalize(void)
{
ft_end_tree(&cxt);
return (unsigned long)cxt.bph;
@ -41,10 +60,13 @@ static unsigned long ft_finalize(void)
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;
dt_ops.finddevice = fdtm_finddevice;
dt_ops.getprop = fdtm_getprop;
dt_ops.setprop = fdtm_setprop;
dt_ops.get_parent = fdtm_get_parent;
dt_ops.create_node = fdtm_create_node;
dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value;
dt_ops.finalize = fdtm_finalize;
return ft_open(&cxt, dt_blob, max_size, max_find_device,
platform_ops.realloc);

View File

@ -0,0 +1,206 @@
/*
* Copyright 2007 David Gibson, IBM Corporation.
* Based on earlier work, Copyright (C) Paul Mackerras 1997.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <stddef.h>
#include "string.h"
#include "stdio.h"
#include "ops.h"
#include "gunzip_util.h"
#define HEAD_CRC 2
#define EXTRA_FIELD 4
#define ORIG_NAME 8
#define COMMENT 0x10
#define RESERVED 0xe0
/**
* gunzip_start - prepare to decompress gzip data
* @state: decompressor state structure to be initialized
* @src: buffer containing gzip compressed or uncompressed data
* @srclen: size in bytes of the buffer at src
*
* If the buffer at @src contains a gzip header, this function
* initializes zlib to decompress the data, storing the decompression
* state in @state. The other functions in this file can then be used
* to decompress data from the gzipped stream.
*
* If the buffer at @src does not contain a gzip header, it is assumed
* to contain uncompressed data. The buffer information is recorded
* in @state and the other functions in this file will simply copy
* data from the uncompressed data stream at @src.
*
* Any errors, such as bad compressed data, cause an error to be
* printed an the platform's exit() function to be called.
*/
void gunzip_start(struct gunzip_state *state, void *src, int srclen)
{
char *hdr = src;
int hdrlen = 0;
memset(state, 0, sizeof(*state));
/* Check for gzip magic number */
if ((hdr[0] == 0x1f) && (hdr[1] == 0x8b)) {
/* gzip data, initialize zlib parameters */
int r, flags;
state->s.workspace = state->scratch;
if (zlib_inflate_workspacesize() > sizeof(state->scratch))
fatal("insufficient scratch space for gunzip\n\r");
/* skip header */
hdrlen = 10;
flags = hdr[3];
if (hdr[2] != Z_DEFLATED || (flags & RESERVED) != 0)
fatal("bad gzipped data\n\r");
if ((flags & EXTRA_FIELD) != 0)
hdrlen = 12 + hdr[10] + (hdr[11] << 8);
if ((flags & ORIG_NAME) != 0)
while (hdr[hdrlen++] != 0)
;
if ((flags & COMMENT) != 0)
while (hdr[hdrlen++] != 0)
;
if ((flags & HEAD_CRC) != 0)
hdrlen += 2;
if (hdrlen >= srclen)
fatal("gunzip_start: ran out of data in header\n\r");
r = zlib_inflateInit2(&state->s, -MAX_WBITS);
if (r != Z_OK)
fatal("inflateInit2 returned %d\n\r", r);
}
state->s.next_in = src + hdrlen;
state->s.avail_in = srclen - hdrlen;
}
/**
* gunzip_partial - extract bytes from a gzip data stream
* @state: gzip state structure previously initialized by gunzip_start()
* @dst: buffer to store extracted data
* @dstlen: maximum number of bytes to extract
*
* This function extracts at most @dstlen bytes from the data stream
* previously associated with @state by gunzip_start(), decompressing
* if necessary. Exactly @dstlen bytes are extracted unless the data
* stream doesn't contain enough bytes, in which case the entire
* remainder of the stream is decompressed.
*
* Returns the actual number of bytes extracted. If any errors occur,
* such as a corrupted compressed stream, an error is printed an the
* platform's exit() function is called.
*/
int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen)
{
int len;
if (state->s.workspace) {
/* gunzipping */
int r;
state->s.next_out = dst;
state->s.avail_out = dstlen;
r = zlib_inflate(&state->s, Z_FULL_FLUSH);
if (r != Z_OK && r != Z_STREAM_END)
fatal("inflate returned %d msg: %s\n\r", r, state->s.msg);
len = state->s.next_out - (unsigned char *)dst;
} else {
/* uncompressed image */
len = min(state->s.avail_in, (unsigned)dstlen);
memcpy(dst, state->s.next_in, len);
state->s.next_in += len;
state->s.avail_in -= len;
}
return len;
}
/**
* gunzip_exactly - extract a fixed number of bytes from a gzip data stream
* @state: gzip state structure previously initialized by gunzip_start()
* @dst: buffer to store extracted data
* @dstlen: number of bytes to extract
*
* This function extracts exactly @dstlen bytes from the data stream
* previously associated with @state by gunzip_start(), decompressing
* if necessary.
*
* If there are less @dstlen bytes available in the data stream, or if
* any other errors occur, such as a corrupted compressed stream, an
* error is printed an the platform's exit() function is called.
*/
void gunzip_exactly(struct gunzip_state *state, void *dst, int dstlen)
{
int len;
len = gunzip_partial(state, dst, dstlen);
if (len < dstlen)
fatal("\n\rgunzip_exactly: ran out of data!"
" Wanted %d, got %d.\n\r", dstlen, len);
}
/**
* gunzip_discard - discard bytes from a gzip data stream
* @state: gzip state structure previously initialized by gunzip_start()
* @len: number of bytes to discard
*
* This function extracts, then discards exactly @len bytes from the
* data stream previously associated with @state by gunzip_start().
* Subsequent gunzip_partial(), gunzip_exactly() or gunzip_finish()
* calls will extract the data following the discarded bytes in the
* data stream.
*
* If there are less @len bytes available in the data stream, or if
* any other errors occur, such as a corrupted compressed stream, an
* error is printed an the platform's exit() function is called.
*/
void gunzip_discard(struct gunzip_state *state, int len)
{
static char discard_buf[128];
while (len > sizeof(discard_buf)) {
gunzip_exactly(state, discard_buf, sizeof(discard_buf));
len -= sizeof(discard_buf);
}
if (len > 0)
gunzip_exactly(state, discard_buf, len);
}
/**
* gunzip_finish - extract all remaining bytes from a gzip data stream
* @state: gzip state structure previously initialized by gunzip_start()
* @dst: buffer to store extracted data
* @dstlen: maximum number of bytes to extract
*
* This function extracts all remaining data, or at most @dstlen
* bytes, from the stream previously associated with @state by
* gunzip_start(). zlib is then shut down, so it is an error to use
* any of the functions in this file on @state until it is
* re-initialized with another call to gunzip_start().
*
* If any errors occur, such as a corrupted compressed stream, an
* error is printed an the platform's exit() function is called.
*/
int gunzip_finish(struct gunzip_state *state, void *dst, int dstlen)
{
int len;
if (state->s.workspace) {
len = gunzip_partial(state, dst, dstlen);
zlib_inflateEnd(&state->s);
} else {
/* uncompressed image */
len = min(state->s.avail_in, (unsigned)dstlen);
memcpy(dst, state->s.next_in, len);
}
return len;
}

View File

@ -0,0 +1,45 @@
/*
* Decompression convenience functions
*
* Copyright 2007 David Gibson, IBM Corporation.
*
* 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 _PPC_BOOT_GUNZIP_UTIL_H_
#define _PPC_BOOT_GUNZIP_UTIL_H_
#include "zlib.h"
/*
* These functions are designed to make life easy for decompressing
* kernel images, initrd images or any other gzip compressed image,
* particularly if its useful to decompress part of the image (e.g. to
* examine headers) before decompressing the remainder.
*
* To use:
* - declare a gunzip_state structure
* - use gunzip_start() to initialize the state, associating it
* with a stream of compressed data
* - use gunzip_partial(), gunzip_exactly() and gunzip_discard()
* in any combination to extract pieces of data from the stream
* - Finally use gunzip_finish() to extract the tail of the
* compressed stream and wind up zlib
*/
/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
#define GUNZIP_SCRATCH_SIZE 46912
struct gunzip_state {
z_stream s;
char scratch[46912];
};
void gunzip_start(struct gunzip_state *state, void *src, int srclen);
int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen);
void gunzip_exactly(struct gunzip_state *state, void *dst, int len);
void gunzip_discard(struct gunzip_state *state, int len);
int gunzip_finish(struct gunzip_state *state, void *dst, int len);
#endif /* _PPC_BOOT_GUNZIP_UTIL_H_ */

View File

@ -14,11 +14,10 @@
#include "page.h"
#include "string.h"
#include "stdio.h"
#include "zlib.h"
#include "ops.h"
#include "gunzip_util.h"
#include "flatdevtree.h"
extern void flush_cache(void *, unsigned long);
#include "reg.h"
extern char _start[];
extern char __bss_start[];
@ -30,304 +29,173 @@ extern char _initrd_end[];
extern char _dtb_start[];
extern char _dtb_end[];
static struct gunzip_state gzstate;
struct addr_range {
unsigned long addr;
void *addr;
unsigned long size;
unsigned long memsize;
};
static struct addr_range vmlinux;
static struct addr_range vmlinuz;
static struct addr_range initrd;
static unsigned long elfoffset;
static int is_64bit;
/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
static char scratch[46912];
static char elfheader[256];
typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
#undef DEBUG
#define HEAD_CRC 2
#define EXTRA_FIELD 4
#define ORIG_NAME 8
#define COMMENT 0x10
#define RESERVED 0xe0
static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
{
z_stream s;
int r, i, flags;
/* skip header */
i = 10;
flags = src[3];
if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
printf("bad gzipped data\n\r");
exit();
}
if ((flags & EXTRA_FIELD) != 0)
i = 12 + src[10] + (src[11] << 8);
if ((flags & ORIG_NAME) != 0)
while (src[i++] != 0)
;
if ((flags & COMMENT) != 0)
while (src[i++] != 0)
;
if ((flags & HEAD_CRC) != 0)
i += 2;
if (i >= *lenp) {
printf("gunzip: ran out of data in header\n\r");
exit();
}
if (zlib_inflate_workspacesize() > sizeof(scratch)) {
printf("gunzip needs more mem\n");
exit();
}
memset(&s, 0, sizeof(s));
s.workspace = scratch;
r = zlib_inflateInit2(&s, -MAX_WBITS);
if (r != Z_OK) {
printf("inflateInit2 returned %d\n\r", r);
exit();
}
s.next_in = src + i;
s.avail_in = *lenp - i;
s.next_out = dst;
s.avail_out = dstlen;
r = zlib_inflate(&s, Z_FULL_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) {
printf("inflate returned %d msg: %s\n\r", r, s.msg);
exit();
}
*lenp = s.next_out - (unsigned char *) dst;
zlib_inflateEnd(&s);
}
static int is_elf64(void *hdr)
{
Elf64_Ehdr *elf64 = hdr;
Elf64_Phdr *elf64ph;
unsigned int i;
if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 &&
elf64->e_ident[EI_MAG1] == ELFMAG1 &&
elf64->e_ident[EI_MAG2] == ELFMAG2 &&
elf64->e_ident[EI_MAG3] == ELFMAG3 &&
elf64->e_ident[EI_CLASS] == ELFCLASS64 &&
elf64->e_ident[EI_DATA] == ELFDATA2MSB &&
elf64->e_type == ET_EXEC &&
elf64->e_machine == EM_PPC64))
return 0;
elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
(unsigned long)elf64->e_phoff);
for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++)
if (elf64ph->p_type == PT_LOAD)
break;
if (i >= (unsigned int)elf64->e_phnum)
return 0;
elfoffset = (unsigned long)elf64ph->p_offset;
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
is_64bit = 1;
return 1;
}
static int is_elf32(void *hdr)
{
Elf32_Ehdr *elf32 = hdr;
Elf32_Phdr *elf32ph;
unsigned int i;
if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 &&
elf32->e_ident[EI_MAG1] == ELFMAG1 &&
elf32->e_ident[EI_MAG2] == ELFMAG2 &&
elf32->e_ident[EI_MAG3] == ELFMAG3 &&
elf32->e_ident[EI_CLASS] == ELFCLASS32 &&
elf32->e_ident[EI_DATA] == ELFDATA2MSB &&
elf32->e_type == ET_EXEC &&
elf32->e_machine == EM_PPC))
return 0;
elf32 = (Elf32_Ehdr *)elfheader;
elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
for (i = 0; i < elf32->e_phnum; i++, elf32ph++)
if (elf32ph->p_type == PT_LOAD)
break;
if (i >= elf32->e_phnum)
return 0;
elfoffset = elf32ph->p_offset;
vmlinux.size = elf32ph->p_filesz + elf32ph->p_offset;
vmlinux.memsize = elf32ph->p_memsz + elf32ph->p_offset;
return 1;
}
static void prep_kernel(unsigned long a1, unsigned long a2)
static struct addr_range prep_kernel(void)
{
char elfheader[256];
void *vmlinuz_addr = _vmlinux_start;
unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
void *addr = 0;
struct elf_info ei;
int len;
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
/* gunzip the ELF header of the kernel */
if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
len = vmlinuz.size;
gunzip(elfheader, sizeof(elfheader),
(unsigned char *)vmlinuz.addr, &len);
} else
memcpy(elfheader, (const void *)vmlinuz.addr,
sizeof(elfheader));
gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
exit();
}
if (platform_ops.image_hdr)
platform_ops.image_hdr(elfheader);
/* We need to alloc the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
* be claimed (it will be zero'd by the kernel itself)
/* We need to alloc the memsize: gzip will expand the kernel
* text/data, then possible rubbish we don't care about. But
* the kernel bss must be claimed (it will be zero'd by the
* kernel itself)
*/
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r");
exit();
printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize);
if (platform_ops.vmlinux_alloc) {
addr = platform_ops.vmlinux_alloc(ei.memsize);
} else {
if ((unsigned long)_start < ei.memsize)
fatal("Insufficient memory for kernel at address 0!"
" (_start=%p)\n\r", _start);
}
/* Finally, gunzip the kernel */
printf("gunzipping (0x%p <- 0x%p:0x%p)...", addr,
vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
/* discard up to the actual load data */
gunzip_discard(&gzstate, ei.elfoffset - sizeof(elfheader));
len = gunzip_finish(&gzstate, addr, ei.loadsize);
if (len != ei.loadsize)
fatal("ran out of data! only got 0x%x of 0x%lx bytes.\n\r",
len, ei.loadsize);
printf("done 0x%x bytes\n\r", len);
flush_cache(addr, ei.loadsize);
return (struct addr_range){addr, ei.memsize};
}
static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
unsigned long initrd_addr,
unsigned long initrd_size)
{
/* If we have an image attached to us, it overrides anything
* supplied by the loader. */
if (_initrd_end > _initrd_start) {
printf("Attached initrd image at 0x%p-0x%p\n\r",
_initrd_start, _initrd_end);
initrd_addr = (unsigned long)_initrd_start;
initrd_size = _initrd_end - _initrd_start;
} else if (initrd_size > 0) {
printf("Using loader supplied ramdisk at 0x%lx-0x%lx\n\r",
initrd_addr, initrd_addr + initrd_size);
}
/* If there's no initrd at all, we're done */
if (! initrd_size)
return (struct addr_range){0, 0};
/*
* Now find the initrd
*
* First see if we have an image attached to us. If so
* allocate memory for it and copy it there.
* If the initrd is too low it will be clobbered when the
* kernel relocates to its final location. In this case,
* allocate a safer place and move it.
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if (initrd.size > 0) {
if (initrd_addr < vmlinux.size) {
void *old_addr = (void *)initrd_addr;
printf("Allocating 0x%lx bytes for initrd ...\n\r",
initrd.size);
initrd.addr = (unsigned long)malloc((u32)initrd.size);
if (initrd.addr == 0) {
printf("Can't allocate memory for initial "
initrd_size);
initrd_addr = (unsigned long)malloc(initrd_size);
if (! initrd_addr)
fatal("Can't allocate memory for initial "
"ramdisk !\n\r");
exit();
}
printf("initial ramdisk moving 0x%lx <- 0x%lx "
"(0x%lx bytes)\n\r", initrd.addr,
(unsigned long)_initrd_start, initrd.size);
memmove((void *)initrd.addr, (void *)_initrd_start,
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);
printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r",
initrd_addr, old_addr, initrd_size);
memmove((void *)initrd_addr, old_addr, initrd_size);
}
/* Eventually gunzip the kernel */
if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
len = vmlinuz.size;
gunzip((void *)vmlinux.addr, vmlinux.memsize,
(unsigned char *)vmlinuz.addr, &len);
printf("done 0x%lx bytes\n\r", len);
} else {
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
vmlinuz.size);
}
printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr));
/* Skip over the ELF header */
#ifdef DEBUG
printf("... skipping 0x%lx bytes of ELF header\n\r",
elfoffset);
#endif
vmlinux.addr += elfoffset;
/* Tell the kernel initrd address via device tree */
setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr));
setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size));
flush_cache((void *)vmlinux.addr, vmlinux.size);
return (struct addr_range){(void *)initrd_addr, initrd_size};
}
/* A buffer that may be edited by tools operating on a zImage binary so as to
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
* The buffer is put in it's own section so that tools may locate it easier.
*/
static char builtin_cmdline[COMMAND_LINE_SIZE]
static char cmdline[COMMAND_LINE_SIZE]
__attribute__((__section__("__builtin_cmdline")));
static void get_cmdline(char *buf, int size)
static void prep_cmdline(void *chosen)
{
void *devp;
int len = strlen(builtin_cmdline);
if (cmdline[0] == '\0')
getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
buf[0] = '\0';
printf("\n\rLinux/PowerPC load: %s", cmdline);
/* If possible, edit the command line */
if (console_ops.edit_cmdline)
console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
printf("\n\r");
if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
len = min(len, size-1);
strncpy(buf, builtin_cmdline, len);
buf[len] = '\0';
}
else if ((devp = finddevice("/chosen")))
getprop(devp, "bootargs", buf, size);
}
static void set_cmdline(char *buf)
{
void *devp;
if ((devp = finddevice("/chosen")))
setprop(devp, "bootargs", buf, strlen(buf) + 1);
/* Put the command line back into the devtree for the kernel */
setprop_str(chosen, "bootargs", cmdline);
}
struct platform_ops platform_ops;
struct dt_ops dt_ops;
struct console_ops console_ops;
struct loader_info loader_info;
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
void start(void)
{
struct addr_range vmlinux, initrd;
kernel_entry_t kentry;
char cmdline[COMMAND_LINE_SIZE];
unsigned long ft_addr = 0;
void *chosen;
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));
/* Do this first, because malloc() could clobber the loader's
* command line. Only use the loader command line if a
* built-in command line wasn't set by an external tool */
if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
memmove(cmdline, loader_info.cmdline,
min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
if (platform_init(promptr, _dtb_start, _dtb_end))
exit();
if (console_ops.open && (console_ops.open() < 0))
exit();
if (platform_ops.fixups)
platform_ops.fixups();
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
_start, sp);
_start, get_sp());
prep_kernel(a1, a2);
/* Ensure that the device tree has a /chosen node */
chosen = finddevice("/chosen");
if (!chosen)
chosen = create_node(NULL, "chosen");
/* If cmdline came from zimage wrapper or if we can edit the one
* in the dt, print it out and edit it, if possible.
*/
if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
get_cmdline(cmdline, COMMAND_LINE_SIZE);
printf("\n\rLinux/PowerPC load: %s", cmdline);
if (console_ops.edit_cmdline)
console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
printf("\n\r");
set_cmdline(cmdline);
}
vmlinux = prep_kernel();
initrd = prep_initrd(vmlinux, chosen,
loader_info.initrd_addr, loader_info.initrd_size);
prep_cmdline(chosen);
printf("Finalizing device tree...");
if (dt_ops.finalize)
@ -335,7 +203,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
if (ft_addr)
printf(" flat tree at 0x%lx\n\r", ft_addr);
else
printf(" using OF tree (promptr=%p)\n\r", promptr);
printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
if (console_ops.close)
console_ops.close();
@ -344,10 +212,9 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
if (ft_addr)
kentry(ft_addr, 0, NULL);
else
/* XXX initrd addr/size should be passed in properties */
kentry(initrd.addr, initrd.size, promptr);
kentry((unsigned long)initrd.addr, initrd.size,
loader_info.promptr);
/* console closed so printf below may not work */
printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
exit();
/* console closed so printf in fatal below may not work */
fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
}

View File

@ -55,11 +55,16 @@ static u8 ns16550_tstc(void)
int ns16550_console_init(void *devp, struct serial_console_data *scdp)
{
int n;
unsigned long reg_phys;
n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
if (n != sizeof(reg_base))
if (n != sizeof(reg_base)) {
if (!dt_xlate_reg(devp, 0, &reg_phys, NULL))
return -1;
reg_base = (void *)reg_phys;
}
n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
if (n != sizeof(reg_shift))
reg_shift = 0;

View File

@ -173,7 +173,7 @@ static void *claim(unsigned long virt, unsigned long size, unsigned long align)
return (void *) virt;
}
static void *of_try_claim(u32 size)
static void *of_try_claim(unsigned long size)
{
unsigned long addr = 0;
@ -208,6 +208,16 @@ static void of_image_hdr(const void *hdr)
}
}
static void *of_vmlinux_alloc(unsigned long size)
{
void *p = malloc(size);
if (!p)
fatal("Can't allocate memory for kernel image!\n\r");
return p;
}
static void of_exit(void)
{
call_prom("exit", 0, 0);
@ -256,11 +266,12 @@ static void of_console_write(char *buf, int len)
call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
void platform_init(unsigned long a1, unsigned long a2, void *promptr)
{
platform_ops.image_hdr = of_image_hdr;
platform_ops.malloc = of_try_claim;
platform_ops.exit = of_exit;
platform_ops.vmlinux_alloc = of_vmlinux_alloc;
dt_ops.finddevice = of_finddevice;
dt_ops.getprop = of_getprop;
@ -270,5 +281,9 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
console_ops.write = of_console_write;
prom = (int (*)(void *))promptr;
return 0;
loader_info.promptr = promptr;
if (a1 && a2 && a2 != 0xdeadbeef) {
loader_info.initrd_addr = a1;
loader_info.initrd_size = a2;
}
}

View File

@ -11,7 +11,9 @@
#ifndef _PPC_BOOT_OPS_H_
#define _PPC_BOOT_OPS_H_
#include <stddef.h>
#include "types.h"
#include "string.h"
#define COMMAND_LINE_SIZE 512
#define MAX_PATH_LEN 256
@ -21,10 +23,11 @@
struct platform_ops {
void (*fixups)(void);
void (*image_hdr)(const void *);
void * (*malloc)(u32 size);
void * (*malloc)(unsigned long size);
void (*free)(void *ptr);
void * (*realloc)(void *ptr, unsigned long size);
void (*exit)(void);
void * (*vmlinux_alloc)(unsigned long size);
};
extern struct platform_ops platform_ops;
@ -35,6 +38,12 @@ struct dt_ops {
const int buflen);
int (*setprop)(const void *phandle, const char *name,
const void *buf, const int buflen);
void *(*get_parent)(const void *phandle);
/* The node must not already exist. */
void *(*create_node)(const void *parent, const char *name);
void *(*find_node_by_prop_value)(const void *prev,
const char *propname,
const char *propval, int proplen);
unsigned long (*finalize)(void);
};
extern struct dt_ops dt_ops;
@ -58,13 +67,23 @@ struct serial_console_data {
void (*close)(void);
};
int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
struct loader_info {
void *promptr;
unsigned long initrd_addr, initrd_size;
char *cmdline;
int cmdline_len;
};
extern struct loader_info loader_info;
void start(void);
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);
void *simple_alloc_init(char *base, unsigned long heap_size,
unsigned long granularity, unsigned long max_allocs);
extern void flush_cache(void *, unsigned long);
int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
static inline void *finddevice(const char *name)
{
@ -76,12 +95,76 @@ static inline int getprop(void *devp, const char *name, void *buf, int buflen)
return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1;
}
static inline int setprop(void *devp, const char *name, void *buf, int buflen)
static inline int setprop(void *devp, const char *name,
const void *buf, int buflen)
{
return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1;
}
#define setprop_val(devp, name, val) \
do { \
typeof(val) x = (val); \
setprop((devp), (name), &x, sizeof(x)); \
} while (0)
static inline void *malloc(u32 size)
static inline int setprop_str(void *devp, const char *name, const char *buf)
{
if (dt_ops.setprop)
return dt_ops.setprop(devp, name, buf, strlen(buf) + 1);
return -1;
}
static inline void *get_parent(const char *devp)
{
return dt_ops.get_parent ? dt_ops.get_parent(devp) : NULL;
}
static inline void *create_node(const void *parent, const char *name)
{
return dt_ops.create_node ? dt_ops.create_node(parent, name) : NULL;
}
static inline void *find_node_by_prop_value(const void *prev,
const char *propname,
const char *propval, int proplen)
{
if (dt_ops.find_node_by_prop_value)
return dt_ops.find_node_by_prop_value(prev, propname,
propval, proplen);
return NULL;
}
static inline void *find_node_by_prop_value_str(const void *prev,
const char *propname,
const char *propval)
{
return find_node_by_prop_value(prev, propname, propval,
strlen(propval) + 1);
}
static inline void *find_node_by_devtype(const void *prev,
const char *type)
{
return find_node_by_prop_value_str(prev, "device_type", type);
}
void dt_fixup_memory(u64 start, u64 size);
void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq);
void dt_fixup_clock(const char *path, u32 freq);
void __dt_fixup_mac_addresses(u32 startindex, ...);
#define dt_fixup_mac_addresses(...) \
__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
{
return find_node_by_prop_value(NULL, "linux,phandle",
(char *)&linuxphandle, sizeof(u32));
}
static inline void *malloc(unsigned long size)
{
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
}
@ -98,5 +181,11 @@ static inline void exit(void)
platform_ops.exit();
for(;;);
}
#define fatal(args...) { printf(args); exit(); }
#define BSS_STACK(size) \
static char _bss_stack[size]; \
void *_platform_stack_top = _bss_stack + sizeof(_bss_stack);
#endif /* _PPC_BOOT_OPS_H_ */

108
arch/powerpc/boot/ppcboot.h Normal file
View File

@ -0,0 +1,108 @@
/*
* This interface is used for compatibility with old U-boots *ONLY*.
* Please do not imitate or extend this.
*/
/*
* (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* 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
*/
#ifndef __PPCBOOT_H__
#define __PPCBOOT_H__
/*
* Board information passed to kernel from PPCBoot
*
* include/asm-ppc/ppcboot.h
*/
#include "types.h"
typedef struct bd_info {
unsigned long bi_memstart; /* start of DRAM memory */
unsigned long bi_memsize; /* size of DRAM memory in bytes */
unsigned long bi_flashstart; /* start of FLASH memory */
unsigned long bi_flashsize; /* size of FLASH memory */
unsigned long bi_flashoffset; /* reserved area for startup monitor */
unsigned long bi_sramstart; /* start of SRAM memory */
unsigned long bi_sramsize; /* size of SRAM memory */
#if defined(TARGET_8xx) || defined(TARGET_CPM2) || defined(TARGET_85xx) ||\
defined(TARGET_83xx)
unsigned long bi_immr_base; /* base of IMMR register */
#endif
#if defined(TARGET_PPC_MPC52xx)
unsigned long bi_mbar_base; /* base of internal registers */
#endif
unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
unsigned long bi_ip_addr; /* IP Address */
unsigned char bi_enetaddr[6]; /* Ethernet address */
unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
unsigned long bi_intfreq; /* Internal Freq, in MHz */
unsigned long bi_busfreq; /* Bus Freq, in MHz */
#if defined(TARGET_CPM2)
unsigned long bi_cpmfreq; /* CPM_CLK Freq, in MHz */
unsigned long bi_brgfreq; /* BRG_CLK Freq, in MHz */
unsigned long bi_sccfreq; /* SCC_CLK Freq, in MHz */
unsigned long bi_vco; /* VCO Out from PLL, in MHz */
#endif
#if defined(TARGET_PPC_MPC52xx)
unsigned long bi_ipbfreq; /* IPB Bus Freq, in MHz */
unsigned long bi_pcifreq; /* PCI Bus Freq, in MHz */
#endif
unsigned long bi_baudrate; /* Console Baudrate */
#if defined(TARGET_4xx)
unsigned char bi_s_version[4]; /* Version of this structure */
unsigned char bi_r_version[32]; /* Version of the ROM (IBM) */
unsigned int bi_procfreq; /* CPU (Internal) Freq, in Hz */
unsigned int bi_plb_busfreq; /* PLB Bus speed, in Hz */
unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
#endif
#if defined(TARGET_HYMOD)
hymod_conf_t bi_hymod_conf; /* hymod configuration information */
#endif
#if defined(TARGET_EVB64260) || defined(TARGET_405EP) || defined(TARGET_44x) || \
defined(TARGET_85xx) || defined(TARGET_83xx)
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#define HAVE_ENET1ADDR
#endif
#if defined(TARGET_EVB64260) || defined(TARGET_440GX) || defined(TARGET_85xx)
/* third onboard ethernet ports */
unsigned char bi_enet2addr[6];
#define HAVE_ENET2ADDR
#endif
#if defined(TARGET_440GX)
/* fourth onboard ethernet ports */
unsigned char bi_enet3addr[6];
#define HAVE_ENET3ADDR
#endif
#if defined(TARGET_4xx)
unsigned int bi_opbfreq; /* OB clock in Hz */
int bi_iic_fast[2]; /* Use fast i2c mode */
#endif
#if defined(TARGET_440GX)
int bi_phynum[4]; /* phy mapping */
int bi_phymode[4]; /* phy mode */
#endif
} bd_t;
#define bi_tbfreq bi_intfreq
#endif /* __PPCBOOT_H__ */

22
arch/powerpc/boot/reg.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef _PPC_BOOT_REG_H
#define _PPC_BOOT_REG_H
/*
* Copyright 2007 Davud Gibson, IBM Corporation.
*
* 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.
*/
static inline u32 mfpvr(void)
{
u32 pvr;
asm volatile ("mfpvr %0" : "=r"(pvr));
return pvr;
}
register void *__stack_pointer asm("r1");
#define get_sp() (__stack_pointer)
#endif /* _PPC_BOOT_REG_H */

View File

@ -19,24 +19,24 @@
#define ENTRY_IN_USE 0x02
static struct alloc_info {
u32 flags;
u32 base;
u32 size;
unsigned long flags;
unsigned long base;
unsigned long size;
} *alloc_tbl;
static u32 tbl_entries;
static u32 alloc_min;
static u32 next_base;
static u32 space_left;
static unsigned long tbl_entries;
static unsigned long alloc_min;
static unsigned long next_base;
static unsigned long 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)
static void *simple_malloc(unsigned long size)
{
u32 i;
unsigned long i;
struct alloc_info *p = alloc_tbl;
if (size == 0)
@ -67,13 +67,14 @@ err_out:
static struct alloc_info *simple_find_entry(void *ptr)
{
u32 i;
unsigned long 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))
if ((p->flags & ENTRY_IN_USE) &&
(p->base == (unsigned long)ptr))
return p;
}
return NULL;
@ -122,10 +123,10 @@ static void *simple_realloc(void *ptr, unsigned long size)
* 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)
void *simple_alloc_init(char *base, unsigned long heap_size,
unsigned long granularity, unsigned long max_allocs)
{
u32 heap_base, tbl_size;
unsigned long heap_base, tbl_size;
heap_size = _ALIGN_UP(heap_size, granularity);
alloc_min = granularity;
@ -136,7 +137,7 @@ void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
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);
heap_base = _ALIGN_UP((unsigned long)alloc_tbl + tbl_size, alloc_min);
next_base = heap_base;
space_left = heap_size;

View File

@ -7,11 +7,12 @@
#define EINVAL 22 /* Invalid argument */
#define ENOSPC 28 /* No space left on device */
extern int printf(const char *fmt, ...);
extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
#define fprintf(fmt, args...) printf(args)
extern int sprintf(char *buf, const char *fmt, ...);
extern int sprintf(char *buf, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
extern int vsprintf(char *buf, const char *fmt, va_list args);

View File

@ -29,6 +29,7 @@ initrd=
dtb=
dts=
cacheit=
gzip=.gz
# cross-compilation prefix
CROSS=
@ -42,7 +43,7 @@ tmpdir=.
usage() {
echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2
echo ' [-D datadir] [-W workingdir] [vmlinux]' >&2
echo ' [-D datadir] [-W workingdir] [--no-gzip] [vmlinux]' >&2
exit 1
}
@ -91,6 +92,9 @@ while [ "$#" -gt 0 ]; do
[ "$#" -gt 0 ] || usage
tmpdir="$1"
;;
--no-gzip)
gzip=
;;
-?)
usage
;;
@ -137,31 +141,44 @@ miboot|uboot)
ksection=image
isection=initrd
;;
cuboot*)
gzip=
;;
esac
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
if [ -z "$cacheit" -o ! -f "$vmz.gz" -o "$vmz.gz" -ot "$kernel" ]; then
if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then
${CROSS}objcopy $objflags "$kernel" "$vmz.$$"
if [ -n "$gzip" ]; then
gzip -f -9 "$vmz.$$"
fi
if [ -n "$cacheit" ]; then
mv -f "$vmz.$$.gz" "$vmz.gz"
mv -f "$vmz.$$$gzip" "$vmz$gzip"
else
vmz="$vmz.$$"
fi
fi
vmz="$vmz$gzip"
case "$platform" in
uboot)
rm -f "$ofile"
uboot|cuboot*)
version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
cut -d' ' -f3`
if [ -n "$version" ]; then
version="-n Linux-$version"
fi
esac
case "$platform" in
uboot)
rm -f "$ofile"
mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
$version -d "$vmz.gz" "$ofile"
$version -d "$vmz" "$ofile"
if [ -z "$cacheit" ]; then
rm -f $vmz.gz
rm -f "$vmz"
fi
exit 0
;;
@ -173,9 +190,9 @@ addsec() {
--set-section-flags=$3=contents,alloc,load,readonly,data
}
addsec $tmp "$vmz.gz" $ksection $object/empty.o
addsec $tmp "$vmz" $ksection $object/empty.o
if [ -z "$cacheit" ]; then
rm -f "$vmz.gz"
rm -f "$vmz"
fi
if [ -n "$initrd" ]; then
@ -191,7 +208,7 @@ fi
if [ "$platform" != "miboot" ]; then
${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \
$object/crt0.o $platformo $tmp $object/wrapper.a
$platformo $tmp $object/wrapper.a
rm $tmp
fi
@ -201,7 +218,19 @@ pseries|chrp)
$object/addnote "$ofile"
;;
pmaccoff)
${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile"
entry=`objdump -f "$ofile" | grep '^start address ' | \
cut -d' ' -f3`
${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
$object/hack-coff "$ofile"
;;
cuboot*)
base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \
cut -d' ' -f3`
mv "$ofile" "$ofile".elf
${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin
gzip -f -9 "$ofile".bin
mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
$version -d "$ofile".bin.gz "$ofile"
;;
esac

View File

@ -1,5 +1,6 @@
OUTPUT_ARCH(powerpc:common)
ENTRY(_start)
ENTRY(_zimage_start_opd)
EXTERN(_zimage_start_opd)
SECTIONS
{
. = (5*1024*1024);

View File

@ -1,5 +1,6 @@
OUTPUT_ARCH(powerpc:common)
ENTRY(_zimage_start)
EXTERN(_zimage_start)
SECTIONS
{
. = (4*1024*1024);

View File

@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.21-rc3
# Fri Mar 9 23:34:53 2007
# Linux kernel version: 2.6.21-rc6
# Mon Apr 23 20:46:48 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
CONFIG_PPC_CELLEB=y
CONFIG_PPC_PS3=y
#
# PS3 Platform Options
#
# CONFIG_PS3_ADVANCED is not set
CONFIG_PS3_HTAB_SIZE=20
# CONFIG_PS3_DYNAMIC_DMA is not set
CONFIG_PS3_USE_LPAR_ADDR=y
CONFIG_PS3_VUART=y
CONFIG_PS3_PS3AV=y
CONFIG_PS3_SYS_MANAGER=y
CONFIG_PPC_CELL=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
CONFIG_PPC_PS3=y
CONFIG_PPC_CELLEB=y
#
# Cell Broadband Engine options
#
CONFIG_SPU_FS=m
CONFIG_SPU_BASE=y
CONFIG_CBE_RAS=y
CONFIG_CBE_THERM=m
CONFIG_CBE_CPUFREQ=m
CONFIG_PPC_NATIVE=y
CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_PPC_UDBG_BEAT=y
@ -174,26 +194,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_MPIC=y
#
# Cell Broadband Engine options
#
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_ADVANCED is not set
CONFIG_PS3_HTAB_SIZE=20
# CONFIG_PS3_DYNAMIC_DMA is not set
CONFIG_PS3_USE_LPAR_ADDR=y
CONFIG_PS3_VUART=y
CONFIG_PS3_PS3AV=y
CONFIG_PS3_SYS_MANAGER=y
#
# Kernel options
#
@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_AEC62XX=y
# CONFIG_BLK_DEV_ALI15X3 is not set
@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_BLK_DEV_TC86C001 is not set
CONFIG_BLK_DEV_IDE_CELLEB=y
CONFIG_BLK_DEV_CELLEB=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_HVC_DRIVER=y
CONFIG_HVC_RTAS=y
# CONFIG_HVC_BEAT is not set
CONFIG_HVC_BEAT=y
#
# IPMI
@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
# CONFIG_UCC_FAST is not set
#
# Library routines
@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y

View File

@ -143,7 +143,7 @@ CONFIG_PPC_NATIVE=y
CONFIG_U3_DART=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_MPIC_BROKEN_U3=y
CONFIG_MPIC_U3_HT_IRQS=y
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
# CONFIG_PPC_INDIRECT_IO is not set

View File

@ -146,7 +146,7 @@ CONFIG_PPC_RTAS=y
CONFIG_RTAS_PROC=y
# CONFIG_RTAS_FLASH is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_MPIC_BROKEN_U3=y
CONFIG_MPIC_U3_HT_IRQS=y
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
# CONFIG_PPC_INDIRECT_IO is not set

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -152,7 +152,7 @@ CONFIG_RTAS_ERROR_LOGGING=y
CONFIG_RTAS_PROC=y
CONFIG_RTAS_FLASH=m
CONFIG_MMIO_NVRAM=y
CONFIG_MPIC_BROKEN_U3=y
CONFIG_MPIC_U3_HT_IRQS=y
CONFIG_IBMVIO=y
# CONFIG_IBMEBUS is not set
# CONFIG_PPC_MPC106 is not set

View File

@ -25,8 +25,8 @@ obj-$(CONFIG_PPC_970_NAP) += idle_power4.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
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y)
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y)
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_LPARCFG) += lparcfg.o

View File

@ -241,7 +241,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
if (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size))
return -EFAULT;
for (i = 0; i < size / sizeof(long); ++i)
if (__put_user(0, p+i))
if (__put_user_inatomic(0, p+i))
return -EFAULT;
return 1;
}
@ -288,7 +288,8 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
} else {
unsigned long pc = regs->nip ^ (swiz & 4);
if (__get_user(instr, (unsigned int __user *)pc))
if (__get_user_inatomic(instr,
(unsigned int __user *)pc))
return -EFAULT;
if (swiz == 0 && (flags & SW))
instr = cpu_to_le32(instr);
@ -324,26 +325,30 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
((nb0 + 3) / 4) * sizeof(unsigned long));
for (i = 0; i < nb; ++i, ++p)
if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
for (i = 0; i < nb0; ++i, ++p)
if (__get_user(REG_BYTE(rptr, i ^ bswiz),
if (__get_user_inatomic(REG_BYTE(rptr,
i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
}
} else {
for (i = 0; i < nb; ++i, ++p)
if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
for (i = 0; i < nb0; ++i, ++p)
if (__put_user(REG_BYTE(rptr, i ^ bswiz),
if (__put_user_inatomic(REG_BYTE(rptr,
i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
}
@ -398,7 +403,8 @@ int fix_alignment(struct pt_regs *regs)
if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
pc ^= 4;
if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
if (unlikely(__get_user_inatomic(instr,
(unsigned int __user *)pc)))
return -EFAULT;
if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
instr = cpu_to_le32(instr);
@ -474,16 +480,16 @@ int fix_alignment(struct pt_regs *regs)
p = (unsigned long) addr;
switch (nb) {
case 8:
ret |= __get_user(data.v[0], SWIZ_PTR(p++));
ret |= __get_user(data.v[1], SWIZ_PTR(p++));
ret |= __get_user(data.v[2], SWIZ_PTR(p++));
ret |= __get_user(data.v[3], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++));
case 4:
ret |= __get_user(data.v[4], SWIZ_PTR(p++));
ret |= __get_user(data.v[5], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++));
case 2:
ret |= __get_user(data.v[6], SWIZ_PTR(p++));
ret |= __get_user(data.v[7], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++));
ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++));
if (unlikely(ret))
return -EFAULT;
}
@ -551,16 +557,16 @@ int fix_alignment(struct pt_regs *regs)
p = (unsigned long) addr;
switch (nb) {
case 8:
ret |= __put_user(data.v[0], SWIZ_PTR(p++));
ret |= __put_user(data.v[1], SWIZ_PTR(p++));
ret |= __put_user(data.v[2], SWIZ_PTR(p++));
ret |= __put_user(data.v[3], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++));
case 4:
ret |= __put_user(data.v[4], SWIZ_PTR(p++));
ret |= __put_user(data.v[5], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++));
case 2:
ret |= __put_user(data.v[6], SWIZ_PTR(p++));
ret |= __put_user(data.v[7], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++));
ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++));
}
if (unlikely(ret))
return -EFAULT;

View File

@ -77,7 +77,6 @@ int main(void)
DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
#else /* CONFIG_PPC64 */
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
DEFINE(PT_PTRACED, PT_PTRACED);
@ -140,6 +139,7 @@ int main(void)
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
DEFINE(SLBSHADOW_STACKVSID,
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));

View File

@ -161,33 +161,33 @@ int btext_initialize(struct device_node *np)
unsigned long address = 0;
const u32 *prop;
prop = get_property(np, "linux,bootx-width", NULL);
prop = of_get_property(np, "linux,bootx-width", NULL);
if (prop == NULL)
prop = get_property(np, "width", NULL);
prop = of_get_property(np, "width", NULL);
if (prop == NULL)
return -EINVAL;
width = *prop;
prop = get_property(np, "linux,bootx-height", NULL);
prop = of_get_property(np, "linux,bootx-height", NULL);
if (prop == NULL)
prop = get_property(np, "height", NULL);
prop = of_get_property(np, "height", NULL);
if (prop == NULL)
return -EINVAL;
height = *prop;
prop = get_property(np, "linux,bootx-depth", NULL);
prop = of_get_property(np, "linux,bootx-depth", NULL);
if (prop == NULL)
prop = get_property(np, "depth", NULL);
prop = of_get_property(np, "depth", NULL);
if (prop == NULL)
return -EINVAL;
depth = *prop;
pitch = width * ((depth + 7) / 8);
prop = get_property(np, "linux,bootx-linebytes", NULL);
prop = of_get_property(np, "linux,bootx-linebytes", NULL);
if (prop == NULL)
prop = get_property(np, "linebytes", NULL);
prop = of_get_property(np, "linebytes", NULL);
if (prop && *prop != 0xffffffffu)
pitch = *prop;
if (pitch == 1)
pitch = 0x1000;
prop = get_property(np, "address", NULL);
prop = of_get_property(np, "address", NULL);
if (prop)
address = *prop;
@ -219,7 +219,7 @@ int __init btext_find_display(int allow_nonstdout)
struct device_node *np = NULL;
int rc = -ENODEV;
name = get_property(of_chosen, "linux,stdout-path", NULL);
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (name != NULL) {
np = of_find_node_by_path(name);
if (np != NULL) {
@ -236,7 +236,7 @@ int __init btext_find_display(int allow_nonstdout)
return rc;
for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) {
if (of_get_property(np, "linux,opened", NULL)) {
printk("trying %s ...\n", np->full_name);
rc = btext_initialize(np);
printk("result: %d\n", rc);

View File

@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t)
beqlr
mfspr r0,SPRN_HID5
ori r0,r0,0x30
ori r0,r0,0x38
mtspr SPRN_HID5,r0
mfspr r0,SPRN_LPCR

View File

@ -389,6 +389,8 @@ static struct cpu_spec cpu_specs[] = {
.pmc_type = PPC_PMC_PA6T,
.cpu_setup = __setup_cpu_pa6t,
.cpu_restore = __restore_cpu_pa6t,
.oprofile_cpu_type = "ppc64/pa6t",
.oprofile_type = PPC_OPROFILE_PA6T,
.platform = "pa6t",
},
{ /* default match */
@ -558,6 +560,18 @@ static struct cpu_spec cpu_specs[] = {
.cpu_setup = __setup_cpu_750cx,
.platform = "ppc750",
},
{ /* 750CL */
.pvr_mask = 0xfffff0f0,
.pvr_value = 0x00087010,
.cpu_name = "750CL",
.cpu_features = CPU_FTRS_750CL,
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
.platform = "ppc750",
},
{ /* 745/755 */
.pvr_mask = 0xfffff000,
.pvr_value = 0x00083000,

View File

@ -191,7 +191,6 @@ stack_ovf:
0:
_GLOBAL(DoSyscall)
stw r0,THREAD+LAST_SYSCALL(r2)
stw r3,ORIG_GPR3(r1)
li r12,0
stw r12,RESULT(r1)

View File

@ -278,8 +278,12 @@ exception_marker:
beq- 1f; \
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
bge- cr1,bad_stack; /* abort if it is */ \
std r9,_CCR(r1); /* save CR in stackframe */ \
bge- cr1,2f; /* abort if it is */ \
b 3f; \
2: li r1,(n); /* will be reloaded later */ \
sth r1,PACA_TRAP_SAVE(r13); \
b bad_stack; \
3: std r9,_CCR(r1); /* save CR in stackframe */ \
std r11,_NIP(r1); /* save SRR0 in stackframe */ \
std r12,_MSR(r1); /* save SRR1 in stackframe */ \
std r10,0(r1); /* make stack chain pointer */ \
@ -940,6 +944,8 @@ bad_stack:
SAVE_2GPRS(7,r1)
SAVE_10GPRS(12,r1)
SAVE_10GPRS(22,r1)
lhz r12,PACA_TRAP_SAVE(r13)
std r12,_TRAP(r1)
addi r11,r1,INT_FRAME_SIZE
std r11,0(r1)
li r12,0
@ -1555,7 +1561,6 @@ _GLOBAL(generic_secondary_smp_init)
/* turn on 64-bit mode */
bl .enable_64b_mode
isync
/* Set up a paca value for this processor. Since we have the
* physical cpu id in r24, we need to search the pacas to find
@ -1735,10 +1740,6 @@ _STATIC(__boot_from_prom)
/* We never return */
trap
/*
* At this point, r3 contains the physical address we are running at,
* returned by prom_init()
*/
_STATIC(__after_prom_start)
/*
@ -1851,7 +1852,6 @@ __secondary_start_pmac_0:
_GLOBAL(pmac_secondary_start)
/* turn on 64-bit mode */
bl .enable_64b_mode
isync
/* Copy some CPU settings from CPU 0 */
bl .__restore_cpu_ppc970

View File

@ -2,6 +2,7 @@
* IBM PowerPC IBM eBus Infrastructure Support.
*
* Copyright (c) 2005 IBM Corporation
* Joachim Fenkes <fenkes@de.ibm.com>
* Heiko J Schick <schickhj@de.ibm.com>
*
* All rights reserved.
@ -43,12 +44,12 @@
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */
.name = ibmebus_bus_device.ofdev.dev.bus_id,
.ofdev.dev.bus_id = "ibmebus",
.ofdev.dev.bus = &ibmebus_bus_type,
static struct device ibmebus_bus_device = { /* fake "parent" device */
.bus_id = "ibmebus",
};
struct bus_type ibmebus_bus_type;
static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
@ -158,21 +159,12 @@ static void __devinit ibmebus_dev_release(struct device *dev)
kfree(to_ibmebus_dev(dev));
}
static ssize_t ibmebusdev_show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name);
}
static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name,
NULL);
static struct ibmebus_dev* __devinit ibmebus_register_device_common(
static int __devinit ibmebus_register_device_common(
struct ibmebus_dev *dev, const char *name)
{
int err = 0;
dev->name = name;
dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev;
dev->ofdev.dev.parent = &ibmebus_bus_device;
dev->ofdev.dev.bus = &ibmebus_bus_type;
dev->ofdev.dev.release = ibmebus_dev_release;
@ -186,12 +178,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common(
if ((err = of_device_register(&dev->ofdev)) != 0) {
printk(KERN_ERR "%s: failed to register device (%d).\n",
__FUNCTION__, err);
return NULL;
return -ENODEV;
}
device_create_file(&dev->ofdev.dev, &dev_attr_name);
return dev;
return 0;
}
static struct ibmebus_dev* __devinit ibmebus_register_device_node(
@ -201,22 +191,22 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
const char *loc_code;
int length;
loc_code = get_property(dn, "ibm,loc-code", NULL);
loc_code = of_get_property(dn, "ibm,loc-code", NULL);
if (!loc_code) {
printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
__FUNCTION__, dn->name ? dn->name : "<unknown>");
return NULL;
return ERR_PTR(-EINVAL);
}
if (strlen(loc_code) == 0) {
printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n",
__FUNCTION__);
return NULL;
return ERR_PTR(-EINVAL);
}
dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
if (!dev) {
return NULL;
return ERR_PTR(-ENOMEM);
}
dev->ofdev.node = of_node_get(dn);
@ -227,9 +217,9 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
min(length, BUS_ID_SIZE - 1));
/* Register with generic device framework. */
if (ibmebus_register_device_common(dev, dn->name) == NULL) {
if (ibmebus_register_device_common(dev, dn->name) != 0) {
kfree(dev);
return NULL;
return ERR_PTR(-ENODEV);
}
return dev;
@ -240,9 +230,8 @@ static void ibmebus_probe_of_nodes(char* name)
struct device_node *dn = NULL;
while ((dn = of_find_node_by_name(dn, name))) {
if (ibmebus_register_device_node(dn) == NULL) {
if (IS_ERR(ibmebus_register_device_node(dn))) {
of_node_put(dn);
return;
}
}
@ -262,9 +251,14 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt)
return;
}
static int ibmebus_match_helper(struct device *dev, void *data)
static int ibmebus_match_name(struct device *dev, void *data)
{
if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0)
const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
const char *name;
name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
if (name && (strcmp(data, name) == 0))
return 1;
return 0;
@ -272,7 +266,6 @@ static int ibmebus_match_helper(struct device *dev, void *data)
static int ibmebus_unregister_device(struct device *dev)
{
device_remove_file(dev, &dev_attr_name);
of_device_unregister(to_of_device(dev));
return 0;
@ -285,11 +278,10 @@ static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
while (strlen(idt->name) > 0) {
while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
(void*)idt->name,
ibmebus_match_helper))) {
ibmebus_match_name))) {
ibmebus_unregister_device(dev);
}
idt++;
}
return;
@ -307,6 +299,9 @@ int ibmebus_register_driver(struct ibmebus_driver *drv)
if ((err = driver_register(&drv->driver) != 0))
return err;
/* remove all supported devices first, in case someone
* probed them manually before registering the driver */
ibmebus_remove_devices_by_id(drv->id_table);
ibmebus_add_devices_by_id(drv->id_table);
return 0;
@ -361,9 +356,116 @@ static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
const char *name = of_get_property(ebus_dev->ofdev.node, "name", NULL);
return sprintf(buf, "%s\n", name);
}
static struct device_attribute ibmebus_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_NULL
};
static int ibmebus_match_path(struct device *dev, void *data)
{
int rc;
struct device_node *dn =
of_node_get(to_ibmebus_dev(dev)->ofdev.node);
rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
of_node_put(dn);
return rc;
}
static char *ibmebus_chomp(const char *in, size_t count)
{
char *out = (char*)kmalloc(count + 1, GFP_KERNEL);
if (!out)
return NULL;
memcpy(out, in, count);
out[count] = '\0';
if (out[count - 1] == '\n')
out[count - 1] = '\0';
return out;
}
static ssize_t ibmebus_store_probe(struct bus_type *bus,
const char *buf, size_t count)
{
struct device_node *dn = NULL;
struct ibmebus_dev *dev;
char *path;
ssize_t rc;
path = ibmebus_chomp(buf, count);
if (!path)
return -ENOMEM;
if (bus_find_device(&ibmebus_bus_type, NULL, path,
ibmebus_match_path)) {
printk(KERN_WARNING "%s: %s has already been probed\n",
__FUNCTION__, path);
rc = -EINVAL;
goto out;
}
if ((dn = of_find_node_by_path(path))) {
dev = ibmebus_register_device_node(dn);
of_node_put(dn);
rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
} else {
printk(KERN_WARNING "%s: no such device node: %s\n",
__FUNCTION__, path);
rc = -ENODEV;
}
out:
kfree(path);
return rc;
}
static ssize_t ibmebus_store_remove(struct bus_type *bus,
const char *buf, size_t count)
{
struct device *dev;
char *path;
path = ibmebus_chomp(buf, count);
if (!path)
return -ENOMEM;
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
ibmebus_match_path))) {
ibmebus_unregister_device(dev);
kfree(path);
return count;
} else {
printk(KERN_WARNING "%s: %s not on the bus\n",
__FUNCTION__, path);
kfree(path);
return -ENODEV;
}
}
static struct bus_attribute ibmebus_bus_attrs[] = {
__ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
__ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
__ATTR_NULL
};
struct bus_type ibmebus_bus_type = {
.name = "ibmebus",
.match = ibmebus_bus_match,
.dev_attrs = ibmebus_dev_attrs,
.bus_attrs = ibmebus_bus_attrs
};
EXPORT_SYMBOL(ibmebus_bus_type);
@ -380,7 +482,7 @@ static int __init ibmebus_bus_init(void)
return err;
}
err = device_register(&ibmebus_bus_device.ofdev.dev);
err = device_register(&ibmebus_bus_device);
if (err) {
printk(KERN_WARNING "%s: device_register returned %i\n",
__FUNCTION__, err);

View File

@ -47,6 +47,8 @@ static int novmerge = 0;
static int novmerge = 1;
#endif
static int protect4gb = 1;
static inline unsigned long iommu_num_pages(unsigned long vaddr,
unsigned long slen)
{
@ -58,6 +60,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr,
return npages;
}
static int __init setup_protect4gb(char *str)
{
if (strcmp(str, "on") == 0)
protect4gb = 1;
else if (strcmp(str, "off") == 0)
protect4gb = 0;
return 1;
}
static int __init setup_iommu(char *str)
{
if (!strcmp(str, "novmerge"))
@ -67,6 +79,7 @@ static int __init setup_iommu(char *str)
return 1;
}
__setup("protect4gb=", setup_protect4gb);
__setup("iommu=", setup_iommu);
static unsigned long iommu_range_alloc(struct iommu_table *tbl,
@ -429,6 +442,9 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
{
unsigned long sz;
unsigned long start_index, end_index;
unsigned long entries_per_4g;
unsigned long index;
static int welcomed = 0;
struct page *page;
@ -450,7 +466,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
#ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
unsigned long index, tceval;
unsigned long tceval;
unsigned long tcecount = 0;
/*
@ -480,6 +496,23 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
#endif
/*
* DMA cannot cross 4 GB boundary. Mark last entry of each 4
* GB chunk as reserved.
*/
if (protect4gb) {
entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
/* Mark the last bit before a 4GB boundary as used */
start_index = tbl->it_offset | (entries_per_4g - 1);
start_index -= tbl->it_offset;
end_index = tbl->it_size;
for (index = start_index; index < end_index - 1; index += entries_per_4g)
__set_bit(index, tbl->it_map);
}
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");

View File

@ -394,7 +394,7 @@ EXPORT_SYMBOL(do_softirq);
#ifdef CONFIG_PPC_MERGE
static LIST_HEAD(irq_hosts);
static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(irq_big_lock);
static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
static unsigned int irq_radix_writer;
struct irq_map_entry irq_map[NR_IRQS];

View File

@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
}
if (!ret) {
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
memcpy(p->ainsn.insn, p->addr,
MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
flush_icache_range((unsigned long)p->ainsn.insn,
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
}
p->ainsn.boostable = 0;
return ret;
}
@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
return 1;
ss_probe:
if (p->ainsn.boostable >= 0) {
unsigned int insn = *p->ainsn.insn;
/* regs->nip is also adjusted if emulate_step returns 1 */
ret = emulate_step(regs, insn);
if (ret > 0) {
/*
* Once this instruction has been boosted
* successfully, set the boostable flag
*/
if (unlikely(p->ainsn.boostable == 0))
p->ainsn.boostable = 1;
if (p->post_handler)
p->post_handler(p, regs, 0);
kcb->kprobe_status = KPROBE_HIT_SSDONE;
reset_current_kprobe();
preempt_enable_no_resched();
return 1;
} else if (ret < 0) {
/*
* We don't allow kprobes on mtmsr(d)/rfi(d), etc.
* So, we should never get here... but, its still
* good to catch them, just in case...
*/
printk("Can't step on instruction %x\n", insn);
BUG();
} else if (ret == 0)
/* This instruction can't be boosted */
p->ainsn.boostable = -1;
}
prepare_singlestep(p, regs);
kcb->kprobe_status = KPROBE_HIT_SS;
return 1;

View File

@ -44,12 +44,12 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
int index;
/* get clock freq. if present */
clk = get_property(np, "clock-frequency", NULL);
clk = of_get_property(np, "clock-frequency", NULL);
if (clk && *clk)
clock = *clk;
/* get default speed if present */
spd = get_property(np, "current-speed", NULL);
spd = of_get_property(np, "current-speed", NULL);
/* If we have a location index, then try to use it */
if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
@ -121,11 +121,11 @@ static int __init add_legacy_soc_port(struct device_node *np,
/* We only support ports that have a clock frequency properly
* encoded in the device-tree.
*/
if (get_property(np, "clock-frequency", NULL) == NULL)
if (of_get_property(np, "clock-frequency", NULL) == NULL)
return -1;
/* if rtas uses this device, don't try to use it as well */
if (get_property(np, "used-by-rtas", NULL) != NULL)
if (of_get_property(np, "used-by-rtas", NULL) != NULL)
return -1;
/* Get the address */
@ -157,7 +157,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
/* Get the ISA port number */
reg = get_property(np, "reg", NULL);
reg = of_get_property(np, "reg", NULL);
if (reg == NULL)
return -1;
@ -168,7 +168,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
/* Now look for an "ibm,aix-loc" property that gives us ordering
* if any...
*/
typep = get_property(np, "ibm,aix-loc", NULL);
typep = of_get_property(np, "ibm,aix-loc", NULL);
/* If we have a location index, then use it */
if (typep && *typep == 'S')
@ -206,7 +206,7 @@ static int __init add_legacy_pci_port(struct device_node *np,
* compatible UARTs on PCI need all sort of quirks (port offsets
* etc...) that this code doesn't know about
*/
if (get_property(np, "clock-frequency", NULL) == NULL)
if (of_get_property(np, "clock-frequency", NULL) == NULL)
return -1;
/* Get the PCI address. Assume BAR 0 */
@ -232,7 +232,7 @@ static int __init add_legacy_pci_port(struct device_node *np,
* we get to their "reg" property
*/
if (np != pci_dev) {
const u32 *reg = get_property(np, "reg", NULL);
const u32 *reg = of_get_property(np, "reg", NULL);
if (reg && (*reg < 4))
index = lindex = *reg;
}
@ -296,7 +296,7 @@ void __init find_legacy_serial_ports(void)
DBG(" -> find_legacy_serial_port()\n");
/* Now find out if one of these is out firmware console */
path = get_property(of_chosen, "linux,stdout-path", NULL);
path = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (path != NULL) {
stdout = of_find_node_by_path(path);
if (stdout)
@ -529,7 +529,7 @@ static int __init check_legacy_serial_console(void)
}
/* We are getting a weird phandle from OF ... */
/* ... So use the full path instead */
name = get_property(of_chosen, "linux,stdout-path", NULL);
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (name == NULL) {
DBG(" no linux,stdout-path !\n");
return -ENODEV;
@ -541,12 +541,12 @@ static int __init check_legacy_serial_console(void)
}
DBG("stdout is %s\n", prom_stdout->full_name);
name = get_property(prom_stdout, "name", NULL);
name = of_get_property(prom_stdout, "name", NULL);
if (!name) {
DBG(" stdout package has no name !\n");
goto not_found;
}
spd = get_property(prom_stdout, "current-speed", NULL);
spd = of_get_property(prom_stdout, "current-speed", NULL);
if (spd)
speed = *spd;

View File

@ -130,30 +130,31 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v)
/*
* Methods used to fetch LPAR data when running on a pSeries platform.
*/
/* find a better place for this function... */
static void log_plpar_hcall_return(unsigned long rc, char *tag)
{
if (rc == 0) /* success, return */
switch(rc) {
case 0:
return;
/* check for null tag ? */
if (rc == H_HARDWARE)
printk(KERN_INFO
"plpar-hcall (%s) failed with hardware fault\n", tag);
else if (rc == H_FUNCTION)
printk(KERN_INFO
"plpar-hcall (%s) failed; function not allowed\n", tag);
else if (rc == H_AUTHORITY)
printk(KERN_INFO
"plpar-hcall (%s) failed; not authorized to this"
" function\n", tag);
else if (rc == H_PARAMETER)
printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
tag);
else
printk(KERN_INFO
"plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",
tag, rc);
case H_HARDWARE:
printk(KERN_INFO "plpar-hcall (%s) "
"Hardware fault\n", tag);
return;
case H_FUNCTION:
printk(KERN_INFO "plpar-hcall (%s) "
"Function not allowed\n", tag);
return;
case H_AUTHORITY:
printk(KERN_INFO "plpar-hcall (%s) "
"Not authorized to this function\n", tag);
return;
case H_PARAMETER:
printk(KERN_INFO "plpar-hcall (%s) "
"Bad parameter(s)\n",tag);
return;
default:
printk(KERN_INFO "plpar-hcall (%s) "
"Unexpected rc(0x%lx)\n", tag, rc);
}
}
/*
@ -321,15 +322,16 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
struct device_node *rtas_node;
const int *lrdrp = NULL;
rtas_node = find_path_device("/rtas");
rtas_node = of_find_node_by_path("/rtas");
if (rtas_node)
lrdrp = get_property(rtas_node, "ibm,lrdr-capacity", NULL);
lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL);
if (lrdrp == NULL) {
partition_potential_processors = vdso_data->processorCount;
} else {
partition_potential_processors = *(lrdrp + 4);
}
of_node_put(rtas_node);
partition_active_processors = lparcfg_count_active_processors();
@ -537,25 +539,27 @@ static int lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
rootdn = find_path_device("/");
rootdn = of_find_node_by_path("/");
if (rootdn) {
tmp = get_property(rootdn, "model", NULL);
tmp = of_get_property(rootdn, "model", NULL);
if (tmp) {
model = tmp;
/* Skip "IBM," - see platforms/iseries/dt.c */
if (firmware_has_feature(FW_FEATURE_ISERIES))
model += 4;
}
tmp = get_property(rootdn, "system-id", NULL);
tmp = of_get_property(rootdn, "system-id", NULL);
if (tmp) {
system_id = tmp;
/* Skip "IBM," - see platforms/iseries/dt.c */
if (firmware_has_feature(FW_FEATURE_ISERIES))
system_id += 4;
}
lp_index_ptr = get_property(rootdn, "ibm,partition-no", NULL);
lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
NULL);
if (lp_index_ptr)
lp_index = *lp_index_ptr;
of_node_put(rootdn);
}
seq_printf(m, "serial_number=%s\n", system_id);
seq_printf(m, "system_type=%s\n", model);

View File

@ -72,8 +72,8 @@ int default_machine_kexec_prepare(struct kimage *image)
/* We also should not overwrite the tce tables */
for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
node = of_find_node_by_type(node, "pci")) {
basep = get_property(node, "linux,tce-base", NULL);
sizep = get_property(node, "linux,tce-size", NULL);
basep = of_get_property(node, "linux,tce-base", NULL);
sizep = of_get_property(node, "linux,tce-size", NULL);
if (basep == NULL || sizep == NULL)
continue;
@ -294,19 +294,19 @@ static unsigned long htab_base, kernel_end;
static struct property htab_base_prop = {
.name = "linux,htab-base",
.length = sizeof(unsigned long),
.value = (unsigned char *)&htab_base,
.value = &htab_base,
};
static struct property htab_size_prop = {
.name = "linux,htab-size",
.length = sizeof(unsigned long),
.value = (unsigned char *)&htab_size_bytes,
.value = &htab_size_bytes,
};
static struct property kernel_end_prop = {
.name = "linux,kernel-end",
.length = sizeof(unsigned long),
.value = (unsigned char *)&kernel_end,
.value = &kernel_end,
};
static void __init export_htab_values(void)
@ -335,7 +335,7 @@ static void __init export_htab_values(void)
static struct property crashk_base_prop = {
.name = "linux,crashkernel-base",
.length = sizeof(unsigned long),
.value = (unsigned char *)&crashk_res.start,
.value = &crashk_res.start,
};
static unsigned long crashk_size;
@ -343,7 +343,7 @@ static unsigned long crashk_size;
static struct property crashk_size_prop = {
.name = "linux,crashkernel-size",
.length = sizeof(unsigned long),
.value = (unsigned char *)&crashk_size,
.value = &crashk_size,
};
static void __init export_crashk_values(void)

View File

@ -734,10 +734,6 @@ _GLOBAL(abs)
sub r3,r3,r4
blr
_GLOBAL(_get_SP)
mr r3,r1 /* Close enough */
blr
/*
* Create a kernel thread
* kernel_thread(fn, arg, flags)

View File

@ -120,6 +120,117 @@ void of_device_unregister(struct of_device *ofdev)
}
static ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len)
{
const char *compat;
int cplen, i;
ssize_t tsize, csize, repend;
/* Name & Type */
csize = snprintf(str, len, "of:N%sT%s",
ofdev->node->name, ofdev->node->type);
/* Get compatible property if any */
compat = of_get_property(ofdev->node, "compatible", &cplen);
if (!compat)
return csize;
/* Find true end (we tolerate multiple \0 at the end */
for (i=(cplen-1); i>=0 && !compat[i]; i--)
cplen--;
if (!cplen)
return csize;
cplen++;
/* Check space (need cplen+1 chars including final \0) */
tsize = csize + cplen;
repend = tsize;
if (csize>=len) /* @ the limit, all is already filled */
return tsize;
if (tsize>=len) { /* limit compat list */
cplen = len-csize-1;
repend = len;
}
/* Copy and do char replacement */
memcpy(&str[csize+1], compat, cplen);
for (i=csize; i<repend; i++) {
char c = str[i];
if (c=='\0')
str[i] = 'C';
else if (c==' ')
str[i] = '_';
}
return tsize;
}
int of_device_uevent(struct device *dev,
char **envp, int num_envp, char *buffer, int buffer_size)
{
struct of_device *ofdev;
const char *compat;
int i = 0, length = 0, seen = 0, cplen, sl;
if (!dev)
return -ENODEV;
ofdev = to_of_device(dev);
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"OF_NAME=%s", ofdev->node->name))
return -ENOMEM;
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"OF_TYPE=%s", ofdev->node->type))
return -ENOMEM;
/* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */
compat = of_get_property(ofdev->node, "compatible", &cplen);
while (compat && *compat && cplen > 0) {
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"OF_COMPATIBLE_%d=%s", seen, compat))
return -ENOMEM;
sl = strlen (compat) + 1;
compat += sl;
cplen -= sl;
seen++;
}
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"OF_COMPATIBLE_N=%d", seen))
return -ENOMEM;
/* modalias is trickier, we add it in 2 steps */
if (add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MODALIAS="))
return -ENOMEM;
sl = of_device_get_modalias(ofdev, &buffer[length-1],
buffer_size-length);
if (sl >= (buffer_size-length))
return -ENOMEM;
length += sl;
envp[i] = NULL;
return 0;
}
EXPORT_SYMBOL(of_match_node);
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_device_register);
@ -127,3 +238,4 @@ EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_release_dev);
EXPORT_SYMBOL(of_device_uevent);

View File

@ -133,6 +133,7 @@ static int of_platform_device_resume(struct device * dev)
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
.uevent = of_device_uevent,
.probe = of_platform_device_probe,
.remove = of_platform_device_remove,
.suspend = of_platform_device_suspend,
@ -177,7 +178,7 @@ static void of_platform_make_bus_id(struct of_device *dev)
* and 'D' for MMIO DCRs.
*/
#ifdef CONFIG_PPC_DCR
reg = get_property(node, "dcr-reg", NULL);
reg = of_get_property(node, "dcr-reg", NULL);
if (reg) {
#ifdef CONFIG_PPC_DCR_NATIVE
snprintf(name, BUS_ID_SIZE, "d%x.%s",
@ -197,7 +198,7 @@ static void of_platform_make_bus_id(struct of_device *dev)
/*
* For MMIO, get the physical address
*/
reg = get_property(node, "reg", NULL);
reg = of_get_property(node, "reg", NULL);
if (reg) {
addr = of_translate_address(node, reg);
if (addr != OF_BAD_ADDR) {

View File

@ -637,7 +637,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
if (pci_bus >= pci_bus_count)
return;
bus_range = get_property(node, "bus-range", &len);
bus_range = of_get_property(node, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, "
"assuming it starts at 0\n", node->full_name);
@ -649,17 +649,20 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
struct pci_dev* dev;
const unsigned int *class_code, *reg;
class_code = get_property(node, "class-code", NULL);
class_code = of_get_property(node, "class-code", NULL);
if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
continue;
reg = get_property(node, "reg", NULL);
reg = of_get_property(node, "reg", NULL);
if (!reg)
continue;
dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
if (!dev || !dev->subordinate)
dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
if (!dev || !dev->subordinate) {
pci_dev_put(dev);
continue;
}
make_one_node_map(node, dev->subordinate->number);
pci_dev_put(dev);
}
}
@ -669,6 +672,7 @@ pcibios_make_OF_bus_map(void)
int i;
struct pci_controller* hose;
struct property *map_prop;
struct device_node *dn;
pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
if (!pci_to_OF_bus_map) {
@ -690,12 +694,13 @@ pcibios_make_OF_bus_map(void)
continue;
make_one_node_map(node, hose->first_busno);
}
map_prop = of_find_property(find_path_device("/"),
"pci-OF-bus-map", NULL);
dn = of_find_node_by_path("/");
map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
if (map_prop) {
BUG_ON(pci_bus_count > map_prop->length);
memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
}
of_node_put(dn);
#ifdef DEBUG
printk("PCI->OF bus map:\n");
for (i=0; i<pci_bus_count; i++) {
@ -724,7 +729,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
* a fake root for all functions of a multi-function device,
* we go down them as well.
*/
class_code = get_property(node, "class-code", NULL);
class_code = of_get_property(node, "class-code", NULL);
if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
strcmp(node->name, "multifunc-device"))
@ -744,7 +749,7 @@ static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
unsigned int psize;
while ((np = of_get_next_child(parent, np)) != NULL) {
reg = get_property(np, "reg", &psize);
reg = of_get_property(np, "reg", &psize);
if (reg == NULL || psize < 4)
continue;
if (((reg[0] >> 8) & 0xff) == devfn)
@ -859,7 +864,7 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
find_OF_pci_device_filter, (void *)node))
return -ENODEV;
reg = get_property(node, "reg", NULL);
reg = of_get_property(node, "reg", NULL);
if (!reg)
return -ENODEV;
*bus = (reg[0] >> 16) & 0xff;
@ -895,14 +900,14 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
int rlen = 0, orig_rlen;
int memno = 0;
struct resource *res;
int np, na = prom_n_addr_cells(dev);
int np, na = of_n_addr_cells(dev);
np = na + 5;
/* First we try to merge ranges to fix a problem with some pmacs
* that can have more than 3 ranges, fortunately using contiguous
* addresses -- BenH
*/
dt_ranges = get_property(dev, "ranges", &rlen);
dt_ranges = of_get_property(dev, "ranges", &rlen);
if (!dt_ranges)
return;
/* Sanity check, though hopefully that never happens */
@ -1006,14 +1011,19 @@ void __init
pci_create_OF_bus_map(void)
{
struct property* of_prop;
struct device_node *dn;
of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
if (of_prop && find_path_device("/")) {
if (!of_prop)
return;
dn = of_find_node_by_path("/");
if (dn) {
memset(of_prop, -1, sizeof(struct property) + 256);
of_prop->name = "pci-OF-bus-map";
of_prop->length = 256;
of_prop->value = (unsigned char *)&of_prop[1];
prom_add_property(find_path_device("/"), of_prop);
of_prop->value = &of_prop[1];
prom_add_property(dn, of_prop);
of_node_put(dn);
}
}

View File

@ -61,8 +61,7 @@ void iSeries_pcibios_init(void);
LIST_HEAD(hose_list);
struct dma_mapping_ops *pci_dma_ops;
EXPORT_SYMBOL(pci_dma_ops);
static struct dma_mapping_ops *pci_dma_ops;
int global_phb_number; /* Global phb counter */
@ -70,6 +69,17 @@ int global_phb_number; /* Global phb counter */
struct pci_dev *ppc64_isabridge_dev = NULL;
EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
{
pci_dma_ops = dma_ops;
}
struct dma_mapping_ops *get_pci_dma_ops(void)
{
return pci_dma_ops;
}
EXPORT_SYMBOL(get_pci_dma_ops);
static void fixup_broken_pcnet32(struct pci_dev* dev)
{
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@ -258,7 +268,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
const u32 *prop;
int len;
prop = get_property(np, name, &len);
prop = of_get_property(np, name, &len);
if (prop && len >= 4)
return *prop;
return def;
@ -291,7 +301,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
u32 i;
int proplen;
addrs = get_property(node, "assigned-addresses", &proplen);
addrs = of_get_property(node, "assigned-addresses", &proplen);
if (!addrs)
return;
DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
@ -333,7 +343,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev)
return NULL;
type = get_property(node, "device_type", NULL);
type = of_get_property(node, "device_type", NULL);
if (type == NULL)
type = "";
@ -397,7 +407,7 @@ void __devinit of_scan_bus(struct device_node *node,
while ((child = of_get_next_child(node, child)) != NULL) {
DBG(" * %s\n", child->full_name);
reg = get_property(child, "reg", &reglen);
reg = of_get_property(child, "reg", &reglen);
if (reg == NULL || reglen < 20)
continue;
devfn = (reg[0] >> 8) & 0xff;
@ -430,13 +440,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
DBG("of_scan_pci_bridge(%s)\n", node->full_name);
/* parse bus-range property */
busrange = get_property(node, "bus-range", &len);
busrange = of_get_property(node, "bus-range", &len);
if (busrange == NULL || len != 8) {
printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
node->full_name);
return;
}
ranges = get_property(node, "ranges", &len);
ranges = of_get_property(node, "ranges", &len);
if (ranges == NULL) {
printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
node->full_name);
@ -900,7 +910,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
unsigned int size;
int rlen = 0;
range = get_property(isa_node, "ranges", &rlen);
range = of_get_property(isa_node, "ranges", &rlen);
if (range == NULL || (rlen < sizeof(struct isa_range))) {
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
"mapping 64k\n");
@ -947,7 +957,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
int rlen = 0;
int memno = 0;
struct resource *res;
int np, na = prom_n_addr_cells(dev);
int np, na = of_n_addr_cells(dev);
unsigned long pci_addr, cpu_phys_addr;
np = na + 5;
@ -960,7 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
* (size depending on dev->n_addr_cells)
* cells 4+5 or 5+6: the size of the range
*/
ranges = get_property(dev, "ranges", &rlen);
ranges = of_get_property(dev, "ranges", &rlen);
if (ranges == NULL)
return;
hose->io_base_phys = 0;

View File

@ -40,7 +40,8 @@
static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
{
struct pci_controller *phb = data;
const int *type = get_property(dn, "ibm,pci-config-space-type", NULL);
const int *type =
of_get_property(dn, "ibm,pci-config-space-type", NULL);
const u32 *regs;
struct pci_dn *pdn;
@ -54,14 +55,14 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
dn->data = pdn;
pdn->node = dn;
pdn->phb = phb;
regs = get_property(dn, "reg", NULL);
regs = of_get_property(dn, "reg", NULL);
if (regs) {
/* First register entry is addr (00BBSS00) */
pdn->busno = (regs[0] >> 16) & 0xff;
pdn->devfn = (regs[0] >> 8) & 0xff;
}
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
const u32 *busp = get_property(dn, "linux,subbus", NULL);
const u32 *busp = of_get_property(dn, "linux,subbus", NULL);
if (busp)
pdn->bussubno = *busp;
}
@ -100,7 +101,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
u32 class;
nextdn = NULL;
classp = get_property(dn, "class-code", NULL);
classp = of_get_property(dn, "class-code", NULL);
class = classp ? *classp : 0;
if (pre && ((ret = pre(dn, data)) != NULL))

View File

@ -20,7 +20,6 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/ide.h>
#include <asm/atomic.h>
#include <asm/checksum.h>
#include <asm/pgtable.h>

View File

@ -305,9 +305,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
set_dabr(new->thread.dabr);
__get_cpu_var(current_dabr) = new->thread.dabr;
}
flush_tlb_pending();
#endif
#endif /* CONFIG_PPC64 */
new_thread = &new->thread;
old_thread = &current->thread;
@ -402,11 +400,11 @@ static void printbits(unsigned long val, struct regbit *bits)
}
#ifdef CONFIG_PPC64
#define REG "%016lX"
#define REG "%016lx"
#define REGS_PER_LINE 4
#define LAST_VOLATILE 13
#else
#define REG "%08lX"
#define REG "%08lx"
#define REGS_PER_LINE 8
#define LAST_VOLATILE 12
#endif
@ -421,7 +419,7 @@ void show_regs(struct pt_regs * regs)
regs, regs->trap, print_tainted(), init_utsname()->release);
printk("MSR: "REG" ", regs->msr);
printbits(regs->msr, msr_bits);
printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer);
printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
trap = TRAP(regs);
if (trap == 0x300 || trap == 0x600)
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
@ -572,7 +570,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
kregs->nip = *((unsigned long *)ret_from_fork);
#else
kregs->nip = (unsigned long)ret_from_fork;
p->thread.last_syscall = -1;
#endif
return 0;
@ -823,6 +820,35 @@ out:
return error;
}
#ifdef CONFIG_IRQSTACKS
static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
unsigned long stack_page;
unsigned long cpu = task_cpu(p);
/*
* Avoid crashing if the stack has overflowed and corrupted
* task_cpu(p), which is in the thread_info struct.
*/
if (cpu < NR_CPUS && cpu_possible(cpu)) {
stack_page = (unsigned long) hardirq_ctx[cpu];
if (sp >= stack_page + sizeof(struct thread_struct)
&& sp <= stack_page + THREAD_SIZE - nbytes)
return 1;
stack_page = (unsigned long) softirq_ctx[cpu];
if (sp >= stack_page + sizeof(struct thread_struct)
&& sp <= stack_page + THREAD_SIZE - nbytes)
return 1;
}
return 0;
}
#else
#define valid_irq_stack(sp, p, nb) 0
#endif /* CONFIG_IRQSTACKS */
int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
@ -832,19 +858,7 @@ int validate_sp(unsigned long sp, struct task_struct *p,
&& sp <= stack_page + THREAD_SIZE - nbytes)
return 1;
#ifdef CONFIG_IRQSTACKS
stack_page = (unsigned long) hardirq_ctx[task_cpu(p)];
if (sp >= stack_page + sizeof(struct thread_struct)
&& sp <= stack_page + THREAD_SIZE - nbytes)
return 1;
stack_page = (unsigned long) softirq_ctx[task_cpu(p)];
if (sp >= stack_page + sizeof(struct thread_struct)
&& sp <= stack_page + THREAD_SIZE - nbytes)
return 1;
#endif
return 0;
return valid_irq_stack(sp, p, nbytes);
}
#ifdef CONFIG_PPC64

View File

@ -390,18 +390,19 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
if (allnextpp) {
pp->name = "name";
pp->length = sz;
pp->value = (unsigned char *)(pp + 1);
pp->value = pp + 1;
*prev_pp = pp;
prev_pp = &pp->next;
memcpy(pp->value, ps, sz - 1);
((char *)pp->value)[sz - 1] = 0;
DBG("fixed up name for %s -> %s\n", pathp, pp->value);
DBG("fixed up name for %s -> %s\n", pathp,
(char *)pp->value);
}
}
if (allnextpp) {
*prev_pp = NULL;
np->name = get_property(np, "name", NULL);
np->type = get_property(np, "device_type", NULL);
np->name = of_get_property(np, "name", NULL);
np->type = of_get_property(np, "device_type", NULL);
if (!np->name)
np->name = "<NULL>";
@ -719,6 +720,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
const char *uname, int depth, void *data)
{
unsigned long *lprop;
u32 *prop;
unsigned long l;
char *p;
@ -760,6 +762,22 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
crashk_res.end = crashk_res.start + *lprop - 1;
#endif
#ifdef CONFIG_BLK_DEV_INITRD
DBG("Looking for initrd properties... ");
prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
if (prop) {
initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
if (prop) {
initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4));
initrd_below_start_ok = 1;
} else {
initrd_start = 0;
}
}
DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end);
#endif /* CONFIG_BLK_DEV_INITRD */
/* Retreive command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
@ -926,6 +944,12 @@ static void __init early_reserve_mem(void)
self_size = initial_boot_params->totalsize;
lmb_reserve(self_base, self_size);
#ifdef CONFIG_BLK_DEV_INITRD
/* then reserve the initrd, if any */
if (initrd_start && (initrd_end > initrd_start))
lmb_reserve(__pa(initrd_start), initrd_end - initrd_start);
#endif /* CONFIG_BLK_DEV_INITRD */
#ifdef CONFIG_PPC32
/*
* Handle the case where we might be booting from an old kexec
@ -954,9 +978,6 @@ static void __init early_reserve_mem(void)
size = *(reserve_map++);
if (size == 0)
break;
/* skip if the reservation is for the blob */
if (base == self_base && size == self_size)
continue;
DBG("reserving: %llx -> %llx\n", base, size);
lmb_reserve(base, size);
}
@ -1021,102 +1042,46 @@ void __init early_init_devtree(void *params)
#undef printk
int
prom_n_addr_cells(struct device_node* np)
int of_n_addr_cells(struct device_node* np)
{
const int *ip;
do {
if (np->parent)
np = np->parent;
ip = get_property(np, "#address-cells", NULL);
ip = of_get_property(np, "#address-cells", NULL);
if (ip != NULL)
return *ip;
} while (np->parent);
/* No #address-cells property for the root node, default to 1 */
return 1;
}
EXPORT_SYMBOL(prom_n_addr_cells);
EXPORT_SYMBOL(of_n_addr_cells);
int
prom_n_size_cells(struct device_node* np)
int of_n_size_cells(struct device_node* np)
{
const int* ip;
do {
if (np->parent)
np = np->parent;
ip = get_property(np, "#size-cells", NULL);
ip = of_get_property(np, "#size-cells", NULL);
if (ip != NULL)
return *ip;
} while (np->parent);
/* No #size-cells property for the root node, default to 1 */
return 1;
}
EXPORT_SYMBOL(prom_n_size_cells);
/**
* Construct and return a list of the device_nodes with a given name.
*/
struct device_node *find_devices(const char *name)
{
struct device_node *head, **prevp, *np;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
if (np->name != 0 && strcasecmp(np->name, name) == 0) {
*prevp = np;
prevp = &np->next;
}
}
*prevp = NULL;
return head;
}
EXPORT_SYMBOL(find_devices);
/**
* Construct and return a list of the device_nodes with a given type.
*/
struct device_node *find_type_devices(const char *type)
{
struct device_node *head, **prevp, *np;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
if (np->type != 0 && strcasecmp(np->type, type) == 0) {
*prevp = np;
prevp = &np->next;
}
}
*prevp = NULL;
return head;
}
EXPORT_SYMBOL(find_type_devices);
/**
* Returns all nodes linked together
*/
struct device_node *find_all_nodes(void)
{
struct device_node *head, **prevp, *np;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
*prevp = np;
prevp = &np->next;
}
*prevp = NULL;
return head;
}
EXPORT_SYMBOL(find_all_nodes);
EXPORT_SYMBOL(of_n_size_cells);
/** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property
*/
int device_is_compatible(const struct device_node *device, const char *compat)
int of_device_is_compatible(const struct device_node *device,
const char *compat)
{
const char* cp;
int cplen, l;
cp = get_property(device, "compatible", &cplen);
cp = of_get_property(device, "compatible", &cplen);
if (cp == NULL)
return 0;
while (cplen > 0) {
@ -1129,7 +1094,7 @@ int device_is_compatible(const struct device_node *device, const char *compat)
return 0;
}
EXPORT_SYMBOL(device_is_compatible);
EXPORT_SYMBOL(of_device_is_compatible);
/**
@ -1143,51 +1108,13 @@ int machine_is_compatible(const char *compat)
root = of_find_node_by_path("/");
if (root) {
rc = device_is_compatible(root, compat);
rc = of_device_is_compatible(root, compat);
of_node_put(root);
}
return rc;
}
EXPORT_SYMBOL(machine_is_compatible);
/**
* Construct and return a list of the device_nodes with a given type
* and compatible property.
*/
struct device_node *find_compatible_devices(const char *type,
const char *compat)
{
struct device_node *head, **prevp, *np;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
if (type != NULL
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
continue;
if (device_is_compatible(np, compat)) {
*prevp = np;
prevp = &np->next;
}
}
*prevp = NULL;
return head;
}
EXPORT_SYMBOL(find_compatible_devices);
/**
* Find the device_node with a given full_name.
*/
struct device_node *find_path_device(const char *path)
{
struct device_node *np;
for (np = allnodes; np != 0; np = np->allnext)
if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
return np;
return NULL;
}
EXPORT_SYMBOL(find_path_device);
/*******
*
* New implementation of the OF "find" APIs, return a refcounted
@ -1280,7 +1207,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
if (type != NULL
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
continue;
if (device_is_compatible(np, compatible) && of_node_get(np))
if (of_device_is_compatible(np, compatible) && of_node_get(np))
break;
}
of_node_put(from);
@ -1527,8 +1454,8 @@ static int of_finish_dynamic_node(struct device_node *node)
int err = 0;
const phandle *ibm_phandle;
node->name = get_property(node, "name", NULL);
node->type = get_property(node, "device_type", NULL);
node->name = of_get_property(node, "name", NULL);
node->type = of_get_property(node, "device_type", NULL);
if (!parent) {
err = -ENODEV;
@ -1542,7 +1469,7 @@ static int of_finish_dynamic_node(struct device_node *node)
return -ENODEV;
/* fix up new node's linux_phandle field */
if ((ibm_phandle = get_property(node, "ibm,phandle", NULL)))
if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
node->linux_phandle = *ibm_phandle;
out:
@ -1605,13 +1532,13 @@ EXPORT_SYMBOL(of_find_property);
* Find a property with a given name for a given node
* and return the value.
*/
const void *get_property(const struct device_node *np, const char *name,
const void *of_get_property(const struct device_node *np, const char *name,
int *lenp)
{
struct property *pp = of_find_property(np,name,lenp);
return pp ? pp->value : NULL;
}
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL(of_get_property);
/*
* Add a property to a node
@ -1742,10 +1669,10 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
* fallback to "reg" property and assume no threads
*/
intserv = get_property(np, "ibm,ppc-interrupt-server#s",
intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
&plen);
if (intserv == NULL) {
const u32 *reg = get_property(np, "reg", NULL);
const u32 *reg = of_get_property(np, "reg", NULL);
if (reg == NULL)
continue;
if (*reg == hardid) {

View File

@ -2035,39 +2035,50 @@ static void __init fixup_device_tree_maple(void)
#endif
#ifdef CONFIG_PPC_CHRP
/* Pegasos and BriQ lacks the "ranges" property in the isa node */
/*
* Pegasos and BriQ lacks the "ranges" property in the isa node
* Pegasos needs decimal IRQ 14/15, not hexadecimal
*/
static void __init fixup_device_tree_chrp(void)
{
phandle isa;
u32 isa_ranges[6];
phandle ph;
u32 prop[6];
u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
char *name;
int rc;
name = "/pci@80000000/isa@c";
isa = call_prom("finddevice", 1, 1, ADDR(name));
if (!PHANDLE_VALID(isa)) {
ph = call_prom("finddevice", 1, 1, ADDR(name));
if (!PHANDLE_VALID(ph)) {
name = "/pci@ff500000/isa@6";
isa = call_prom("finddevice", 1, 1, ADDR(name));
ph = call_prom("finddevice", 1, 1, ADDR(name));
rloc = 0x01003000; /* IO space; PCI device = 6 */
}
if (!PHANDLE_VALID(isa))
return;
rc = prom_getproplen(isa, "ranges");
if (rc != 0 && rc != PROM_ERROR)
return;
if (PHANDLE_VALID(ph)) {
rc = prom_getproplen(ph, "ranges");
if (rc == 0 || rc == PROM_ERROR) {
prom_printf("Fixing up missing ISA range on Pegasos...\n");
isa_ranges[0] = 0x1;
isa_ranges[1] = 0x0;
isa_ranges[2] = rloc;
isa_ranges[3] = 0x0;
isa_ranges[4] = 0x0;
isa_ranges[5] = 0x00010000;
prom_setprop(isa, name, "ranges",
isa_ranges, sizeof(isa_ranges));
prop[0] = 0x1;
prop[1] = 0x0;
prop[2] = rloc;
prop[3] = 0x0;
prop[4] = 0x0;
prop[5] = 0x00010000;
prom_setprop(ph, name, "ranges", prop, sizeof(prop));
}
}
name = "/pci@80000000/ide@C,1";
ph = call_prom("finddevice", 1, 1, ADDR(name));
if (PHANDLE_VALID(ph)) {
prom_printf("Fixing up IDE interrupt on Pegasos...\n");
prop[0] = 14;
prop[1] = 0x0;
prop[2] = 15;
prop[3] = 0x0;
prom_setprop(ph, name, "interrupts", prop, 4*sizeof(u32));
}
}
#else
#define fixup_device_tree_chrp()

View File

@ -68,9 +68,9 @@ static void of_bus_default_count_cells(struct device_node *dev,
int *addrc, int *sizec)
{
if (addrc)
*addrc = prom_n_addr_cells(dev);
*addrc = of_n_addr_cells(dev);
if (sizec)
*sizec = prom_n_size_cells(dev);
*sizec = of_n_size_cells(dev);
}
static u64 of_bus_default_map(u32 *addr, const u32 *range,
@ -196,7 +196,7 @@ const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
return NULL;
/* Get "reg" or "assigned-addresses" property */
prop = get_property(dev, bus->addresses, &psize);
prop = of_get_property(dev, bus->addresses, &psize);
if (prop == NULL)
return NULL;
psize /= 4;
@ -438,7 +438,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
* to translate addresses that aren't supposed to be translated in
* the first place. --BenH.
*/
ranges = get_property(parent, "ranges", &rlen);
ranges = of_get_property(parent, "ranges", &rlen);
if (ranges == NULL || rlen == 0) {
offset = of_read_number(addr, na);
memset(addr, 0, pna * 4);
@ -578,7 +578,7 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
return NULL;
/* Get "reg" or "assigned-addresses" property */
prop = get_property(dev, bus->addresses, &psize);
prop = of_get_property(dev, bus->addresses, &psize);
if (prop == NULL)
return NULL;
psize /= 4;
@ -650,17 +650,17 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
/* busno is always one cell */
*busno = *(dma_window++);
prop = get_property(dn, "ibm,#dma-address-cells", NULL);
prop = of_get_property(dn, "ibm,#dma-address-cells", NULL);
if (!prop)
prop = get_property(dn, "#address-cells", NULL);
prop = of_get_property(dn, "#address-cells", NULL);
cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn);
cells = prop ? *(u32 *)prop : of_n_addr_cells(dn);
*phys = of_read_number(dma_window, cells);
dma_window += cells;
prop = get_property(dn, "ibm,#dma-size-cells", NULL);
cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
prop = of_get_property(dn, "ibm,#dma-size-cells", NULL);
cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
*size = of_read_number(dma_window, cells);
}
@ -680,7 +680,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
return NULL;
do {
parp = get_property(child, "interrupt-parent", NULL);
parp = of_get_property(child, "interrupt-parent", NULL);
if (parp == NULL)
p = of_get_parent(child);
else {
@ -691,7 +691,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
}
of_node_put(child);
child = p;
} while (p && get_property(p, "#interrupt-cells", NULL) == NULL);
} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
return p;
}
@ -716,7 +716,7 @@ void of_irq_map_init(unsigned int flags)
struct device_node *np;
for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
if (get_property(np, "interrupt-controller", NULL)
if (of_get_property(np, "interrupt-controller", NULL)
== NULL)
continue;
/* Skip /chosen/interrupt-controller */
@ -755,7 +755,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
* is none, we are nice and just walk up the tree
*/
do {
tmp = get_property(ipar, "#interrupt-cells", NULL);
tmp = of_get_property(ipar, "#interrupt-cells", NULL);
if (tmp != NULL) {
intsize = *tmp;
break;
@ -779,7 +779,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
*/
old = of_node_get(ipar);
do {
tmp = get_property(old, "#address-cells", NULL);
tmp = of_get_property(old, "#address-cells", NULL);
tnode = of_get_parent(old);
of_node_put(old);
old = tnode;
@ -795,7 +795,8 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
/* Now check if cursor is an interrupt-controller and if it is
* then we are done
*/
if (get_property(ipar, "interrupt-controller", NULL) != NULL) {
if (of_get_property(ipar, "interrupt-controller", NULL) !=
NULL) {
DBG(" -> got it !\n");
memcpy(out_irq->specifier, intspec,
intsize * sizeof(u32));
@ -806,7 +807,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
}
/* Now look for an interrupt-map */
imap = get_property(ipar, "interrupt-map", &imaplen);
imap = of_get_property(ipar, "interrupt-map", &imaplen);
/* No interrupt map, check for an interrupt parent */
if (imap == NULL) {
DBG(" -> no map, getting parent\n");
@ -816,7 +817,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
imaplen /= sizeof(u32);
/* Look for a mask */
imask = get_property(ipar, "interrupt-map-mask", NULL);
imask = of_get_property(ipar, "interrupt-map-mask", NULL);
/* If we were passed no "reg" property and we attempt to parse
* an interrupt-map, then #address-cells must be 0.
@ -863,15 +864,13 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
/* Get #interrupt-cells and #address-cells of new
* parent
*/
tmp = get_property(newpar, "#interrupt-cells",
NULL);
tmp = of_get_property(newpar, "#interrupt-cells", NULL);
if (tmp == NULL) {
DBG(" -> parent lacks #interrupt-cells !\n");
goto fail;
}
newintsize = *tmp;
tmp = get_property(newpar, "#address-cells",
NULL);
tmp = of_get_property(newpar, "#address-cells", NULL);
newaddrsize = (tmp == NULL) ? 0 : *tmp;
DBG(" -> newintsize=%d, newaddrsize=%d\n",
@ -928,7 +927,7 @@ static int of_irq_map_oldworld(struct device_node *device, int index,
* everything together on these)
*/
while (device) {
ints = get_property(device, "AAPL,interrupts", &intlen);
ints = of_get_property(device, "AAPL,interrupts", &intlen);
if (ints != NULL)
break;
device = device->parent;
@ -970,13 +969,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
return of_irq_map_oldworld(device, index, out_irq);
/* Get the interrupts property */
intspec = get_property(device, "interrupts", &intlen);
intspec = of_get_property(device, "interrupts", &intlen);
if (intspec == NULL)
return -EINVAL;
intlen /= sizeof(u32);
/* Get the reg property (if any) */
addr = get_property(device, "reg", NULL);
addr = of_get_property(device, "reg", NULL);
/* Look for the interrupt parent. */
p = of_irq_find_parent(device);
@ -984,7 +983,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
return -EINVAL;
/* Get size of interrupt specifier */
tmp = get_property(p, "#interrupt-cells", NULL);
tmp = of_get_property(p, "#interrupt-cells", NULL);
if (tmp == NULL) {
of_node_put(p);
return -EINVAL;

View File

@ -450,7 +450,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
int llen, offs;
sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
loc = get_property(rtas_node, rstr, &llen);
loc = of_get_property(rtas_node, rstr, &llen);
/* A sensor may have multiple instances */
for (j = 0, offs = 0; j <= p->quant; j++) {
@ -477,7 +477,7 @@ static int ppc_rtas_find_all_sensors(void)
const unsigned int *utmp;
int len, i;
utmp = get_property(rtas_node, "rtas-sensors", &len);
utmp = of_get_property(rtas_node, "rtas-sensors", &len);
if (utmp == NULL) {
printk (KERN_ERR "error: could not get rtas-sensors\n");
return 1;

View File

@ -192,18 +192,19 @@ void rtas_progress(char *s, unsigned short hex)
if (display_width == 0) {
display_width = 0x10;
if ((root = find_path_device("/rtas"))) {
if ((p = get_property(root,
if ((root = of_find_node_by_path("/rtas"))) {
if ((p = of_get_property(root,
"ibm,display-line-length", NULL)))
display_width = *p;
if ((p = get_property(root,
if ((p = of_get_property(root,
"ibm,form-feed", NULL)))
form_feed = *p;
if ((p = get_property(root,
if ((p = of_get_property(root,
"ibm,display-number-of-lines", NULL)))
display_lines = *p;
row_width = get_property(root,
row_width = of_get_property(root,
"ibm,display-truncation-length", NULL);
of_node_put(root);
}
display_character = rtas_token("display-character");
set_indicator = rtas_token("set-indicator");
@ -298,7 +299,7 @@ int rtas_token(const char *service)
const int *tokp;
if (rtas.dev == NULL)
return RTAS_UNKNOWN_SERVICE;
tokp = get_property(rtas.dev, service, NULL);
tokp = of_get_property(rtas.dev, service, NULL);
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
}
EXPORT_SYMBOL(rtas_token);
@ -832,12 +833,12 @@ void __init rtas_initialize(void)
if (rtas.dev) {
const u32 *basep, *entryp, *sizep;
basep = get_property(rtas.dev, "linux,rtas-base", NULL);
sizep = get_property(rtas.dev, "rtas-size", NULL);
basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
sizep = of_get_property(rtas.dev, "rtas-size", NULL);
if (basep != NULL && sizep != NULL) {
rtas.base = *basep;
rtas.size = *sizep;
entryp = get_property(rtas.dev,
entryp = of_get_property(rtas.dev,
"linux,rtas-entry", NULL);
if (entryp == NULL) /* Ugh */
rtas.entry = rtas.base;

View File

@ -60,7 +60,7 @@ static int of_device_available(struct device_node * dn)
{
const char *status;
status = get_property(dn, "status", NULL);
status = of_get_property(dn, "status", NULL);
if (!status)
return 1;
@ -177,7 +177,7 @@ struct pci_ops rtas_pci_ops = {
int is_python(struct device_node *dev)
{
const char *model = get_property(dev, "model", NULL);
const char *model = of_get_property(dev, "model", NULL);
if (model && strstr(model, "Python"))
return 1;
@ -247,7 +247,7 @@ static int phb_set_bus_ranges(struct device_node *dev,
const int *bus_range;
unsigned int len;
bus_range = get_property(dev, "bus-range", &len);
bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
return 1;
}
@ -274,7 +274,7 @@ int __devinit rtas_setup_phb(struct pci_controller *phb)
return 0;
}
unsigned long __init find_and_init_phbs(void)
void __init find_and_init_phbs(void)
{
struct device_node *node;
struct pci_controller *phb;
@ -309,18 +309,16 @@ unsigned long __init find_and_init_phbs(void)
if (of_chosen) {
const int *prop;
prop = get_property(of_chosen,
prop = of_get_property(of_chosen,
"linux,pci-probe-only", NULL);
if (prop)
pci_probe_only = *prop;
prop = get_property(of_chosen,
prop = of_get_property(of_chosen,
"linux,pci-assign-all-buses", NULL);
if (prop)
pci_assign_all_buses = *prop;
}
return 0;
}
/* RPA-specific bits for removing PHBs */

View File

@ -21,7 +21,6 @@
#include <linux/delay.h>
#include <linux/initrd.h>
#include <linux/platform_device.h>
#include <linux/ide.h>
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/console.h>
@ -304,26 +303,8 @@ struct seq_operations cpuinfo_op = {
void __init check_for_initrd(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
const unsigned int *prop;
int len;
DBG(" -> check_for_initrd()\n");
if (of_chosen) {
prop = get_property(of_chosen, "linux,initrd-start", &len);
if (prop != NULL) {
initrd_start = (unsigned long)
__va(of_read_ulong(prop, len / 4));
prop = get_property(of_chosen,
"linux,initrd-end", &len);
if (prop != NULL) {
initrd_end = (unsigned long)
__va(of_read_ulong(prop, len / 4));
initrd_below_start_ok = 1;
} else
initrd_start = 0;
}
}
DBG(" -> check_for_initrd() initrd_start=0x%lx initrd_end=0x%lx\n",
initrd_start, initrd_end);
/* If we were passed an initrd, set the ROOT_DEV properly if the values
* look sensible. If not, clear initrd reference.
@ -371,11 +352,12 @@ void __init smp_setup_cpu_maps(void)
const int *intserv;
int j, len = sizeof(u32), nthreads = 1;
intserv = get_property(dn, "ibm,ppc-interrupt-server#s", &len);
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
&len);
if (intserv)
nthreads = len / sizeof(int);
else {
intserv = get_property(dn, "reg", NULL);
intserv = of_get_property(dn, "reg", NULL);
if (!intserv)
intserv = &cpu; /* assume logical == phys */
}
@ -398,10 +380,10 @@ void __init smp_setup_cpu_maps(void)
int num_addr_cell, num_size_cell, maxcpus;
const unsigned int *ireg;
num_addr_cell = prom_n_addr_cells(dn);
num_size_cell = prom_n_size_cells(dn);
num_addr_cell = of_n_addr_cells(dn);
num_size_cell = of_n_size_cells(dn);
ireg = get_property(dn, "ibm,lrdr-capacity", NULL);
ireg = of_get_property(dn, "ibm,lrdr-capacity", NULL);
if (!ireg)
goto out;
@ -496,11 +478,39 @@ void probe_machine(void)
printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
}
/* Match a class of boards, not a specific device configuration. */
int check_legacy_ioport(unsigned long base_port)
{
if (ppc_md.check_legacy_ioport == NULL)
return 0;
return ppc_md.check_legacy_ioport(base_port);
struct device_node *parent, *np = NULL;
int ret = -ENODEV;
switch(base_port) {
case I8042_DATA_REG:
np = of_find_node_by_type(NULL, "8042");
break;
case FDC_BASE: /* FDC1 */
np = of_find_node_by_type(NULL, "fdc");
break;
#ifdef CONFIG_PPC_PREP
case _PIDXR:
case _PNPWRP:
case PNPBIOS_BASE:
/* implement me */
#endif
default:
/* ipmi is supposed to fail here */
break;
}
if (!np)
return ret;
parent = of_get_parent(np);
if (parent) {
if (strcmp(parent->type, "isa") == 0)
ret = 0;
of_node_put(parent);
}
of_node_put(np);
return ret;
}
EXPORT_SYMBOL(check_legacy_ioport);

View File

@ -92,7 +92,8 @@ unsigned long __init early_init(unsigned long dt_ptr)
/* First zero the BSS -- use memset_io, some platforms don't have
* caches on yet */
memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start);
memset_io((void __iomem *)PTRRELOC(&__bss_start), 0,
__bss_stop - __bss_start);
/*
* Identify the CPU type and fix up code sections
@ -195,18 +196,22 @@ EXPORT_SYMBOL(nvram_sync);
#endif /* CONFIG_NVRAM */
static struct cpu cpu_devices[NR_CPUS];
static DEFINE_PER_CPU(struct cpu, cpu_devices);
int __init ppc_init(void)
{
int i;
int cpu;
/* clear the progress line */
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
if (ppc_md.progress)
ppc_md.progress(" ", 0xffff);
/* register CPU devices */
for_each_possible_cpu(i)
register_cpu(&cpu_devices[i], i);
for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
c->hotpluggable = 1;
register_cpu(c, cpu);
}
/* call platform init */
if (ppc_md.init != NULL) {

View File

@ -20,7 +20,6 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/initrd.h>
#include <linux/ide.h>
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/console.h>
@ -110,7 +109,7 @@ static void check_smt_enabled(void)
dn = of_find_node_by_path("/options");
if (dn) {
smt_option = get_property(dn, "ibm,smt-enabled", NULL);
smt_option = of_get_property(dn, "ibm,smt-enabled", NULL);
if (smt_option) {
if (!strcmp(smt_option, "on"))
@ -305,10 +304,10 @@ static void __init initialize_cache_info(void)
size = 0;
lsize = cur_cpu_spec->dcache_bsize;
sizep = get_property(np, "d-cache-size", NULL);
sizep = of_get_property(np, "d-cache-size", NULL);
if (sizep != NULL)
size = *sizep;
lsizep = get_property(np, dc, NULL);
lsizep = of_get_property(np, dc, NULL);
if (lsizep != NULL)
lsize = *lsizep;
if (sizep == 0 || lsizep == 0)
@ -322,10 +321,10 @@ static void __init initialize_cache_info(void)
size = 0;
lsize = cur_cpu_spec->icache_bsize;
sizep = get_property(np, "i-cache-size", NULL);
sizep = of_get_property(np, "i-cache-size", NULL);
if (sizep != NULL)
size = *sizep;
lsizep = get_property(np, ic, NULL);
lsizep = of_get_property(np, ic, NULL);
if (lsizep != NULL)
lsize = *lsizep;
if (sizep == 0 || lsizep == 0)

View File

@ -428,10 +428,6 @@ void generic_mach_cpu_die(void)
smp_wmb();
while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
cpu_relax();
#ifdef CONFIG_PPC64
flush_tlb_pending();
#endif
cpu_set(cpu, cpu_online_map);
local_irq_enable();
}

View File

@ -53,10 +53,6 @@
#include <asm/ppc-pci.h>
#include <asm/syscalls.h>
/* readdir & getdents */
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
struct old_linux_dirent32 {
u32 d_ino;
u32 d_offset;

View File

@ -66,16 +66,17 @@ static int __init smt_setup(void)
if (!cpu_has_feature(CPU_FTR_SMT))
return -ENODEV;
options = find_path_device("/options");
options = of_find_node_by_path("/options");
if (!options)
return -ENODEV;
val = get_property(options, "ibm,smt-snooze-delay", NULL);
val = of_get_property(options, "ibm,smt-snooze-delay", NULL);
if (!smt_snooze_cmdline && val) {
for_each_possible_cpu(cpu)
per_cpu(smt_snooze_delay, cpu) = *val;
}
of_node_put(options);
return 0;
}
__initcall(smt_setup);
@ -189,12 +190,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR);
SYSFS_PMCSETUP(spurr, SPRN_SPURR);
SYSFS_PMCSETUP(dscr, SPRN_DSCR);
SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0);
SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1);
SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2);
SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3);
SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4);
SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5);
SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0);
SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1);
SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2);
SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);

View File

@ -834,7 +834,7 @@ static int __init get_freq(char *name, int cells, unsigned long *val)
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu) {
fp = get_property(cpu, name, NULL);
fp = of_get_property(cpu, name, NULL);
if (fp) {
found = 1;
*val = of_read_ulong(fp, cells);

View File

@ -90,21 +90,11 @@ EXPORT_SYMBOL(unregister_die_notifier);
* Trap & Exception support
*/
static DEFINE_SPINLOCK(die_lock);
int die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter;
if (debugger(regs))
return 1;
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
#ifdef CONFIG_PMAC_BACKLIGHT
static void pmac_backlight_unblank(void)
{
mutex_lock(&pmac_backlight_mutex);
if (machine_is(powermac) && pmac_backlight) {
if (pmac_backlight) {
struct backlight_properties *props;
props = &pmac_backlight->props;
@ -113,7 +103,43 @@ int die(const char *str, struct pt_regs *regs, long err)
backlight_update_status(pmac_backlight);
}
mutex_unlock(&pmac_backlight_mutex);
}
#else
static inline void pmac_backlight_unblank(void) { }
#endif
int die(const char *str, struct pt_regs *regs, long err)
{
static struct {
spinlock_t lock;
u32 lock_owner;
int lock_owner_depth;
} die = {
.lock = __SPIN_LOCK_UNLOCKED(die.lock),
.lock_owner = -1,
.lock_owner_depth = 0
};
static int die_counter;
unsigned long flags;
if (debugger(regs))
return 1;
oops_enter();
if (die.lock_owner != raw_smp_processor_id()) {
console_verbose();
spin_lock_irqsave(&die.lock, flags);
die.lock_owner = smp_processor_id();
die.lock_owner_depth = 0;
bust_spinlocks(1);
if (machine_is(powermac))
pmac_backlight_unblank();
} else {
local_save_flags(flags);
}
if (++die.lock_owner_depth < 3) {
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
@ -127,12 +153,17 @@ int die(const char *str, struct pt_regs *regs, long err)
#ifdef CONFIG_NUMA
printk("NUMA ");
#endif
printk("%s\n", ppc_md.name ? "" : ppc_md.name);
printk("%s\n", ppc_md.name ? ppc_md.name : "");
print_modules();
show_regs(regs);
} else {
printk("Recursive die() failure, output suppressed\n");
}
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
die.lock_owner = -1;
spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current) ||
kexec_sr_activated(smp_processor_id()))
@ -145,6 +176,7 @@ int die(const char *str, struct pt_regs *regs, long err)
if (panic_on_oops)
panic("Fatal exception");
oops_exit();
do_exit(err);
return 0;

View File

@ -81,7 +81,7 @@ 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.archdata.of_node,
dma_window = of_get_property(dev->dev.archdata.of_node,
"ibm,my-dma-window", NULL);
if (!dma_window)
return NULL;
@ -226,7 +226,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
return NULL;
}
unit_address = get_property(of_node, "reg", NULL);
unit_address = of_get_property(of_node, "reg", NULL);
if (unit_address == NULL) {
printk(KERN_WARNING "%s: node %s missing 'reg'\n",
__FUNCTION__,
@ -246,7 +246,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
viodev->type = of_node->type;
viodev->unit_address = *unit_address;
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
unit_address = get_property(of_node,
unit_address = of_get_property(of_node,
"linux,unit_address", NULL);
if (unit_address != NULL)
viodev->unit_address = *unit_address;
@ -308,7 +308,7 @@ static int __init vio_bus_init(void)
return err;
}
node_vroot = find_devices("vdevice");
node_vroot = of_find_node_by_name(NULL, "vdevice");
if (node_vroot) {
struct device_node *of_node;
@ -322,6 +322,7 @@ static int __init vio_bus_init(void)
__FUNCTION__, of_node);
vio_register_device_node(of_node);
}
of_node_put(node_vroot);
}
return 0;
@ -377,7 +378,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
dn = dev->archdata.of_node;
if (!dn)
return -ENODEV;
cp = get_property(dn, "compatible", &length);
cp = of_get_property(dn, "compatible", &length);
if (!cp)
return -ENODEV;
@ -406,12 +407,12 @@ struct bus_type vio_bus_type = {
* @which: The property/attribute to be extracted.
* @length: Pointer to length of returned data size (unused if NULL).
*
* Calls prom.c's get_property() to return the value of the
* Calls prom.c's of_get_property() to return the value of the
* attribute specified by @which
*/
const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
{
return get_property(vdev->dev.archdata.of_node, which, length);
return of_get_property(vdev->dev.archdata.of_node, which, length);
}
EXPORT_SYMBOL(vio_get_attribute);
@ -443,7 +444,7 @@ struct vio_dev *vio_find_node(struct device_node *vnode)
char kobj_name[BUS_ID_SIZE];
/* construct the kobject name from the device node */
unit_address = get_property(vnode, "reg", NULL);
unit_address = of_get_property(vnode, "reg", NULL);
if (!unit_address)
return NULL;
snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);

View File

@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user)
dcbt 0,r4
beq .Lcopy_page_4K
andi. r6,r6,7
mtcrf 0x01,r5
PPC_MTOCRF 0x01,r5
blt cr1,.Lshort_copy
bne .Ldst_unaligned
.Ldst_aligned:
@ -135,7 +135,7 @@ _GLOBAL(__copy_tofrom_user)
b .Ldo_tail
.Ldst_unaligned:
mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */
PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */
subf r5,r6,r5
li r7,0
cmpldi r1,r5,16
@ -150,7 +150,7 @@ _GLOBAL(__copy_tofrom_user)
2: bf cr7*4+1,3f
37: lwzx r0,r7,r4
83: stwx r0,r7,r3
3: mtcrf 0x01,r5
3: PPC_MTOCRF 0x01,r5
add r4,r6,r4
add r3,r6,r3
b .Ldst_aligned

View File

@ -43,9 +43,11 @@ void __spin_yield(raw_spinlock_t *lock)
if (firmware_has_feature(FW_FEATURE_ISERIES))
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
((u64)holder_cpu << 32) | yield_count);
#ifdef CONFIG_PPC_SPLPAR
else
plpar_hcall_norets(H_CONFER,
get_hard_smp_processor_id(holder_cpu), yield_count);
#endif
}
/*
@ -72,9 +74,11 @@ void __rw_yield(raw_rwlock_t *rw)
if (firmware_has_feature(FW_FEATURE_ISERIES))
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
((u64)holder_cpu << 32) | yield_count);
#ifdef CONFIG_PPC_SPLPAR
else
plpar_hcall_norets(H_CONFER,
get_hard_smp_processor_id(holder_cpu), yield_count);
#endif
}
#endif

View File

@ -19,7 +19,7 @@ _GLOBAL(memset)
rlwimi r4,r4,16,0,15
cmplw cr1,r5,r0 /* do we get that far? */
rldimi r4,r4,32,0
mtcrf 1,r0
PPC_MTOCRF 1,r0
mr r6,r3
blt cr1,8f
beq+ 3f /* if already 8-byte aligned */
@ -49,7 +49,7 @@ _GLOBAL(memset)
bdnz 4b
5: srwi. r0,r5,3
clrlwi r5,r5,29
mtcrf 1,r0
PPC_MTOCRF 1,r0
beq 8f
bf 29,6f
std r4,0(r6)
@ -65,7 +65,7 @@ _GLOBAL(memset)
std r4,0(r6)
addi r6,r6,8
8: cmpwi r5,0
mtcrf 1,r5
PPC_MTOCRF 1,r5
beqlr+
bf 29,9f
stw r4,0(r6)

View File

@ -12,7 +12,7 @@
.align 7
_GLOBAL(memcpy)
std r3,48(r1) /* save destination pointer for return value */
mtcrf 0x01,r5
PPC_MTOCRF 0x01,r5
cmpldi cr1,r5,16
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
andi. r6,r6,7
@ -128,7 +128,7 @@ _GLOBAL(memcpy)
b .Ldo_tail
.Ldst_unaligned:
mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7
PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7
subf r5,r6,r5
li r7,0
cmpldi r1,r5,16
@ -143,7 +143,7 @@ _GLOBAL(memcpy)
2: bf cr7*4+1,3f
lwzx r0,r7,r4
stwx r0,r7,r3
3: mtcrf 0x01,r5
3: PPC_MTOCRF 0x01,r5
add r4,r6,r4
add r3,r6,r3
b .Ldst_aligned

View File

@ -54,7 +54,7 @@ static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
*/
int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
{
unsigned int opcode, rd;
unsigned int opcode, rs, rb, rd, spr;
unsigned long int imm;
opcode = instr >> 26;
@ -152,6 +152,49 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
regs->nip &= 0xffffffffUL;
return 1;
#endif
case 0x26: /* mfcr */
regs->gpr[rd] = regs->ccr;
regs->gpr[rd] &= 0xffffffffUL;
goto mtspr_out;
case 0x2a6: /* mfspr */
spr = (instr >> 11) & 0x3ff;
switch (spr) {
case 0x20: /* mfxer */
regs->gpr[rd] = regs->xer;
regs->gpr[rd] &= 0xffffffffUL;
goto mtspr_out;
case 0x100: /* mflr */
regs->gpr[rd] = regs->link;
goto mtspr_out;
case 0x120: /* mfctr */
regs->gpr[rd] = regs->ctr;
goto mtspr_out;
}
break;
case 0x378: /* orx */
rs = (instr >> 21) & 0x1f;
rb = (instr >> 11) & 0x1f;
if (rs == rb) { /* mr */
rd = (instr >> 16) & 0x1f;
regs->gpr[rd] = regs->gpr[rs];
goto mtspr_out;
}
break;
case 0x3a6: /* mtspr */
spr = (instr >> 11) & 0x3ff;
switch (spr) {
case 0x20: /* mtxer */
regs->xer = (regs->gpr[rd] & 0xffffffffUL);
goto mtspr_out;
case 0x100: /* mtlr */
regs->link = regs->gpr[rd];
goto mtspr_out;
case 0x120: /* mtctr */
regs->ctr = regs->gpr[rd];
mtspr_out:
regs->nip += 4;
return 1;
}
}
}
return 0;

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