mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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:
commit
24a77daf3d
@ -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
|
||||
|
||||
|
||||
@ -256,7 +256,7 @@ struct boot_param_header {
|
||||
u32 off_dt_struct; /* offset to structure */
|
||||
u32 off_dt_strings; /* offset to strings */
|
||||
u32 off_mem_rsvmap; /* offset to memory reserve map
|
||||
*/
|
||||
*/
|
||||
u32 version; /* format version */
|
||||
u32 last_comp_version; /* last compatible version */
|
||||
|
||||
@ -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:
|
||||
@ -273,7 +276,7 @@ struct boot_param_header {
|
||||
#define OF_DT_HEADER 0xd00dfeed /* 4: version,
|
||||
4: total size */
|
||||
#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name
|
||||
*/
|
||||
*/
|
||||
#define OF_DT_END_NODE 0x2 /* End node */
|
||||
#define OF_DT_PROP 0x3 /* Property: name off,
|
||||
size, content */
|
||||
@ -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
|
||||
========================================
|
||||
|
@ -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
|
||||
@ -910,10 +519,10 @@ config PPC_64K_PAGES
|
||||
depends on PPC64
|
||||
help
|
||||
This option changes the kernel logical page size to 64k. On machines
|
||||
without processor support for 64k pages, the kernel will simulate
|
||||
them by loading each individual 4k page on demand transparently,
|
||||
while on hardware with such support, it will be used to map
|
||||
normal application pages.
|
||||
without processor support for 64k pages, the kernel will simulate
|
||||
them by loading each individual 4k page on demand transparently,
|
||||
while on hardware with such support, it will be used to map
|
||||
normal application pages.
|
||||
|
||||
config SCHED_SMT
|
||||
bool "SMT (Hyperthreading) scheduler support"
|
||||
@ -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,12 +856,10 @@ source "fs/Kconfig"
|
||||
|
||||
source "arch/powerpc/sysdev/qe_lib/Kconfig"
|
||||
|
||||
source "arch/powerpc/platforms/iseries/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
||||
|
||||
menu "Instrumentation Support"
|
||||
depends on EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
|
||||
source "arch/powerpc/oprofile/Kconfig"
|
||||
|
||||
|
@ -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)"
|
||||
|
@ -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)
|
||||
|
||||
|
3
arch/powerpc/boot/.gitignore
vendored
3
arch/powerpc/boot/.gitignore
vendored
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
68
arch/powerpc/boot/cuboot-83xx.c
Normal file
68
arch/powerpc/boot/cuboot-83xx.c
Normal 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;
|
||||
}
|
69
arch/powerpc/boot/cuboot-85xx.c
Normal file
69
arch/powerpc/boot/cuboot-85xx.c
Normal 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
307
arch/powerpc/boot/devtree.c
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -24,7 +24,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells =<0>;
|
||||
linux,phandle = <200>;
|
||||
|
@ -17,7 +17,6 @@
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <200>;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
291
arch/powerpc/boot/dts/mpc832x_rdb.dts
Normal file
291
arch/powerpc/boot/dts/mpc832x_rdb.dts
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
@ -15,7 +15,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
136
arch/powerpc/boot/dts/mpc8544ds.dts
Normal file
136
arch/powerpc/boot/dts/mpc8544ds.dts
Normal 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;
|
||||
};
|
||||
};
|
||||
};
|
@ -17,7 +17,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -18,7 +18,6 @@
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <200>;
|
||||
|
@ -18,7 +18,6 @@
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <200>;
|
||||
|
@ -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_ */
|
||||
|
76
arch/powerpc/boot/elf_util.c
Normal file
76
arch/powerpc/boot/elf_util.c
Normal 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;
|
||||
}
|
@ -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))
|
||||
return 0;
|
||||
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,41 +760,131 @@ 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,
|
||||
const void *buf, const unsigned int buflen)
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
const void *buf, const int buflen)
|
||||
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);
|
||||
|
206
arch/powerpc/boot/gunzip_util.c
Normal file
206
arch/powerpc/boot/gunzip_util.c
Normal 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;
|
||||
}
|
45
arch/powerpc/boot/gunzip_util.h
Normal file
45
arch/powerpc/boot/gunzip_util.h
Normal 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_ */
|
@ -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 "
|
||||
"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);
|
||||
initrd_size);
|
||||
initrd_addr = (unsigned long)malloc(initrd_size);
|
||||
if (! initrd_addr)
|
||||
fatal("Can't allocate memory for initial "
|
||||
"ramdisk !\n\r");
|
||||
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");
|
||||
}
|
||||
|
@ -55,10 +55,15 @@ 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", ®_base, sizeof(reg_base));
|
||||
if (n != sizeof(reg_base))
|
||||
return -1;
|
||||
if (n != sizeof(reg_base)) {
|
||||
if (!dt_xlate_reg(devp, 0, ®_phys, NULL))
|
||||
return -1;
|
||||
|
||||
reg_base = (void *)reg_phys;
|
||||
}
|
||||
|
||||
n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
|
||||
if (n != sizeof(reg_shift))
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
108
arch/powerpc/boot/ppcboot.h
Normal 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
22
arch/powerpc/boot/reg.h
Normal 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 */
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.$$"
|
||||
gzip -f -9 "$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
|
||||
|
@ -1,5 +1,6 @@
|
||||
OUTPUT_ARCH(powerpc:common)
|
||||
ENTRY(_start)
|
||||
ENTRY(_zimage_start_opd)
|
||||
EXTERN(_zimage_start_opd)
|
||||
SECTIONS
|
||||
{
|
||||
. = (5*1024*1024);
|
||||
|
@ -1,5 +1,6 @@
|
||||
OUTPUT_ARCH(powerpc:common)
|
||||
ENTRY(_zimage_start)
|
||||
EXTERN(_zimage_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = (4*1024*1024);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1292
arch/powerpc/configs/mpc832x_rdb_defconfig
Normal file
1292
arch/powerpc/configs/mpc832x_rdb_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1077
arch/powerpc/configs/mpc8544_ds_defconfig
Normal file
1077
arch/powerpc/configs/mpc8544_ds_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,27 +325,31 @@ 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 = ®s->gpr[0];
|
||||
addr += nb;
|
||||
for (i = 0; i < nb0; ++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;
|
||||
}
|
||||
|
||||
} 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 = ®s->gpr[0];
|
||||
addr += nb;
|
||||
for (i = 0; i < nb0; ++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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -2,36 +2,37 @@
|
||||
* 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.
|
||||
*
|
||||
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
|
||||
* BSD.
|
||||
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
|
||||
* BSD.
|
||||
*
|
||||
* OpenIB BSD License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials
|
||||
* provided with the distribution.
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@ -43,19 +44,19 @@
|
||||
#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,
|
||||
gfp_t flag)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
|
||||
mem = kmalloc(size, flag);
|
||||
*dma_handle = (dma_addr_t)mem;
|
||||
|
||||
@ -63,7 +64,7 @@ static void *ibmebus_alloc_coherent(struct device *dev,
|
||||
}
|
||||
|
||||
static void ibmebus_free_coherent(struct device *dev,
|
||||
size_t size, void *vaddr,
|
||||
size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
kfree(vaddr);
|
||||
@ -79,7 +80,7 @@ static dma_addr_t ibmebus_map_single(struct device *dev,
|
||||
|
||||
static void ibmebus_unmap_single(struct device *dev,
|
||||
dma_addr_t dma_addr,
|
||||
size_t size,
|
||||
size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
return;
|
||||
@ -90,13 +91,13 @@ static int ibmebus_map_sg(struct device *dev,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; i < nents; i++) {
|
||||
sg[i].dma_address = (dma_addr_t)page_address(sg[i].page)
|
||||
sg[i].dma_address = (dma_addr_t)page_address(sg[i].page)
|
||||
+ sg[i].offset;
|
||||
sg[i].dma_length = sg[i].length;
|
||||
}
|
||||
|
||||
|
||||
return nents;
|
||||
}
|
||||
|
||||
@ -128,15 +129,15 @@ static int ibmebus_bus_probe(struct device *dev)
|
||||
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
||||
const struct of_device_id *id;
|
||||
int error = -ENODEV;
|
||||
|
||||
|
||||
if (!ibmebusdrv->probe)
|
||||
return error;
|
||||
|
||||
|
||||
id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
|
||||
if (id) {
|
||||
error = ibmebusdrv->probe(ibmebusdev, id);
|
||||
}
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -144,11 +145,11 @@ static int ibmebus_bus_remove(struct device *dev)
|
||||
{
|
||||
struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
|
||||
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
||||
|
||||
|
||||
if (ibmebusdrv->remove) {
|
||||
return ibmebusdrv->remove(ibmebusdev);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -181,17 +173,15 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common(
|
||||
dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
|
||||
|
||||
/* An ibmebusdev is based on a of_device. We have to change the
|
||||
* bus type to use our own DMA mapping operations.
|
||||
*/
|
||||
* bus type to use our own DMA mapping operations.
|
||||
*/
|
||||
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,35 +191,35 @@ 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);
|
||||
|
||||
|
||||
length = strlen(loc_code);
|
||||
memcpy(dev->ofdev.dev.bus_id, loc_code
|
||||
+ (length - min(length, BUS_ID_SIZE - 1)),
|
||||
memcpy(dev->ofdev.dev.bus_id, loc_code
|
||||
+ (length - min(length, BUS_ID_SIZE - 1)),
|
||||
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;
|
||||
@ -238,17 +228,16 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
of_node_put(dn);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -262,17 +251,21 @@ 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;
|
||||
}
|
||||
|
||||
static int ibmebus_unregister_device(struct device *dev)
|
||||
{
|
||||
device_remove_file(dev, &dev_attr_name);
|
||||
of_device_unregister(to_of_device(dev));
|
||||
|
||||
return 0;
|
||||
@ -281,17 +274,16 @@ static int ibmebus_unregister_device(struct device *dev)
|
||||
static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
|
||||
while (strlen(idt->name) > 0) {
|
||||
while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
|
||||
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,30 +299,33 @@ 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;
|
||||
}
|
||||
EXPORT_SYMBOL(ibmebus_register_driver);
|
||||
|
||||
void ibmebus_unregister_driver(struct ibmebus_driver *drv)
|
||||
{
|
||||
{
|
||||
driver_unregister(&drv->driver);
|
||||
ibmebus_remove_devices_by_id(drv->id_table);
|
||||
}
|
||||
EXPORT_SYMBOL(ibmebus_unregister_driver);
|
||||
|
||||
int ibmebus_request_irq(struct ibmebus_dev *dev,
|
||||
u32 ist,
|
||||
u32 ist,
|
||||
irq_handler_t handler,
|
||||
unsigned long irq_flags, const char * devname,
|
||||
void *dev_id)
|
||||
{
|
||||
unsigned int irq = irq_create_mapping(NULL, ist);
|
||||
|
||||
|
||||
if (irq == NO_IRQ)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
return request_irq(irq, handler,
|
||||
irq_flags, devname, dev_id);
|
||||
}
|
||||
@ -339,56 +334,163 @@ EXPORT_SYMBOL(ibmebus_request_irq);
|
||||
void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
|
||||
{
|
||||
unsigned int irq = irq_find_mapping(NULL, ist);
|
||||
|
||||
|
||||
free_irq(irq, dev_id);
|
||||
}
|
||||
EXPORT_SYMBOL(ibmebus_free_irq);
|
||||
|
||||
static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
{
|
||||
const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
|
||||
struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
|
||||
const struct of_device_id *ids = ebus_drv->id_table;
|
||||
const struct of_device_id *found_id;
|
||||
|
||||
|
||||
if (!ids)
|
||||
return 0;
|
||||
|
||||
|
||||
found_id = of_match_device(ids, &ebus_dev->ofdev);
|
||||
if (found_id)
|
||||
return 1;
|
||||
|
||||
|
||||
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,
|
||||
.name = "ibmebus",
|
||||
.match = ibmebus_bus_match,
|
||||
.dev_attrs = ibmebus_dev_attrs,
|
||||
.bus_attrs = ibmebus_bus_attrs
|
||||
};
|
||||
EXPORT_SYMBOL(ibmebus_bus_type);
|
||||
|
||||
static int __init ibmebus_bus_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
printk(KERN_INFO "IBM eBus Device Driver\n");
|
||||
|
||||
|
||||
err = bus_register(&ibmebus_bus_type);
|
||||
if (err) {
|
||||
printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
|
||||
__FUNCTION__);
|
||||
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",
|
||||
printk(KERN_WARNING "%s: device_register returned %i\n",
|
||||
__FUNCTION__, err);
|
||||
bus_unregister(&ibmebus_bus_type);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
__initcall(ibmebus_bus_init);
|
||||
|
@ -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");
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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", ®len);
|
||||
reg = of_get_property(child, "reg", ®len);
|
||||
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;
|
||||
|
@ -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))
|
||||
|
@ -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>
|
||||
|
@ -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 = ¤t->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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
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");
|
||||
|
||||
rc = prom_getproplen(isa, "ranges");
|
||||
if (rc != 0 && rc != PROM_ERROR)
|
||||
return;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
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()
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,26 +103,67 @@ 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
|
||||
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
|
||||
|
||||
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 ");
|
||||
printk("PREEMPT ");
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
printk("SMP NR_CPUS=%d ", NR_CPUS);
|
||||
printk("SMP NR_CPUS=%d ", NR_CPUS);
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
printk("DEBUG_PAGEALLOC ");
|
||||
printk("DEBUG_PAGEALLOC ");
|
||||
#endif
|
||||
#ifdef CONFIG_NUMA
|
||||
printk("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");
|
||||
}
|
||||
|
||||
print_modules();
|
||||
show_regs(regs);
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user