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:
@@ -39,7 +39,7 @@
|
|||||||
and property data. The old style variable
|
and property data. The old style variable
|
||||||
alignment would make it impossible to do
|
alignment would make it impossible to do
|
||||||
"simple" insertion of properties using
|
"simple" insertion of properties using
|
||||||
memove (thanks Milton for
|
memmove (thanks Milton for
|
||||||
noticing). Updated kernel patch as well
|
noticing). Updated kernel patch as well
|
||||||
- Correct a few more alignment constraints
|
- Correct a few more alignment constraints
|
||||||
- Add a chapter about the device-tree
|
- Add a chapter about the device-tree
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
- Add some definitions of interrupt tree (simple/complex)
|
- 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 some common address format examples
|
||||||
- Add definitions for standard properties and "compatible"
|
- Add definitions for standard properties and "compatible"
|
||||||
names for cells that are not already defined by the existing
|
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:
|
forth words isn't required), you can enter the kernel with:
|
||||||
|
|
||||||
r5 : OF callback pointer as defined by IEEE 1275
|
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
|
is currently supported
|
||||||
|
|
||||||
r3, r4 : address & length of an initrd if any or 0
|
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;
|
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
|
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
|
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
|
cannot support both configurations with Book E and configurations
|
||||||
with classic Powerpc architectures.
|
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
|
enable another config option to select the specific board
|
||||||
supported.
|
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
|
point to setup_32.c
|
||||||
|
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ struct boot_param_header {
|
|||||||
u32 off_dt_struct; /* offset to structure */
|
u32 off_dt_struct; /* offset to structure */
|
||||||
u32 off_dt_strings; /* offset to strings */
|
u32 off_dt_strings; /* offset to strings */
|
||||||
u32 off_mem_rsvmap; /* offset to memory reserve map
|
u32 off_mem_rsvmap; /* offset to memory reserve map
|
||||||
*/
|
*/
|
||||||
u32 version; /* format version */
|
u32 version; /* format version */
|
||||||
u32 last_comp_version; /* last compatible version */
|
u32 last_comp_version; /* last compatible version */
|
||||||
|
|
||||||
@@ -265,6 +265,9 @@ struct boot_param_header {
|
|||||||
booting on */
|
booting on */
|
||||||
/* version 3 fields below */
|
/* version 3 fields below */
|
||||||
u32 size_dt_strings; /* size of the strings block */
|
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:
|
Along with the constants:
|
||||||
@@ -273,7 +276,7 @@ struct boot_param_header {
|
|||||||
#define OF_DT_HEADER 0xd00dfeed /* 4: version,
|
#define OF_DT_HEADER 0xd00dfeed /* 4: version,
|
||||||
4: total size */
|
4: total size */
|
||||||
#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name
|
#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name
|
||||||
*/
|
*/
|
||||||
#define OF_DT_END_NODE 0x2 /* End node */
|
#define OF_DT_END_NODE 0x2 /* End node */
|
||||||
#define OF_DT_PROP 0x3 /* Property: name off,
|
#define OF_DT_PROP 0x3 /* Property: name off,
|
||||||
size, content */
|
size, content */
|
||||||
@@ -310,9 +313,8 @@ struct boot_param_header {
|
|||||||
- off_mem_rsvmap
|
- off_mem_rsvmap
|
||||||
|
|
||||||
This is an offset from the beginning of the header to the start
|
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
|
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
|
list is terminated by an entry of size 0. This map provides the
|
||||||
kernel with a list of physical memory areas that are "reserved"
|
kernel with a list of physical memory areas that are "reserved"
|
||||||
and thus not to be used for memory allocations, especially during
|
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
|
contain _at least_ this DT block itself (header,total_size). If
|
||||||
you are passing an initrd to the kernel, you should reserve it as
|
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
|
well. You do not need to reserve the kernel image itself. The map
|
||||||
should be 64 bit aligned.
|
should be 64-bit aligned.
|
||||||
|
|
||||||
- version
|
- version
|
||||||
|
|
||||||
@@ -335,10 +337,13 @@ struct boot_param_header {
|
|||||||
to reallocate it easily at boot and free up the unused flattened
|
to reallocate it easily at boot and free up the unused flattened
|
||||||
structure after expansion. Version 16 introduces a new more
|
structure after expansion. Version 16 introduces a new more
|
||||||
"compact" format for the tree itself that is however not backward
|
"compact" format for the tree itself that is however not backward
|
||||||
compatible. You should always generate a structure of the highest
|
compatible. Version 17 adds an additional field, size_dt_struct,
|
||||||
version defined at the time of your implementation. Currently
|
allowing it to be reallocated or moved more easily (this is
|
||||||
that is version 16, unless you explicitly aim at being backward
|
particularly useful for bootloaders which need to make
|
||||||
compatible.
|
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
|
- last_comp_version
|
||||||
|
|
||||||
@@ -347,7 +352,7 @@ struct boot_param_header {
|
|||||||
is backward compatible with version 1 (that is, a kernel build
|
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
|
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
|
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.
|
using the new unit name format.
|
||||||
|
|
||||||
- boot_cpuid_phys
|
- boot_cpuid_phys
|
||||||
@@ -360,6 +365,17 @@ struct boot_param_header {
|
|||||||
point (see further chapters for more informations on the required
|
point (see further chapters for more informations on the required
|
||||||
device-tree contents)
|
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
|
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
|
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
|
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
|
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
|
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.
|
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
|
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
|
interrupt tree which will be described in a further version of this
|
||||||
document.
|
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
|
identifies a node. You are free to use whatever values or system of
|
||||||
values, internal pointers, or whatever to generate these, the only
|
values, internal pointers, or whatever to generate these, the only
|
||||||
requirement is that every node for which you provide that property has
|
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
|
designates a node followed by the node unit name. Properties are
|
||||||
presented with their name followed by their content. "content"
|
presented with their name followed by their content. "content"
|
||||||
represents an ASCII string (zero terminated) value, while <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
|
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
|
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
|
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]
|
* [align gap to next 4 bytes boundary]
|
||||||
* for each property:
|
* for each property:
|
||||||
* token OF_DT_PROP (that is 0x00000003)
|
* token OF_DT_PROP (that is 0x00000003)
|
||||||
* 32 bit value of property value size in bytes (or 0 of no
|
* 32-bit value of property value size in bytes (or 0 if no
|
||||||
* value)
|
value)
|
||||||
* 32 bit value of offset in string block of property name
|
* 32-bit value of offset in string block of property name
|
||||||
* property value data if any
|
* property value data if any
|
||||||
* [align gap to next 4 bytes boundary]
|
* [align gap to next 4 bytes boundary]
|
||||||
* [child nodes if any]
|
* [child nodes if any]
|
||||||
* token OF_DT_END_NODE (that is 0x00000002)
|
* 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
|
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.
|
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
|
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
|
and there exist an OF bus binding, then you should follow the
|
||||||
specification. However, the kernel does not require every single
|
specification. However, the kernel does not require every single
|
||||||
device or bus to be described by the device tree.
|
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.
|
on the processor bus.
|
||||||
|
|
||||||
Those 2 properties define 'cells' for representing an address and a
|
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
|
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
|
concatenated and expected to be in big endian format). Another example
|
||||||
is the way Apple firmware defines them, with 2 cells for an address
|
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
|
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
|
The "reg" property only defines addresses and sizes (if #size-cells
|
||||||
is non-0) within a given bus. In order to translate addresses upward
|
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
|
addresses), all busses must contain a "ranges" property. If the
|
||||||
"ranges" property is missing at a given level, it's assumed that
|
"ranges" property is missing at a given level, it's assumed that
|
||||||
translation isn't possible. The format of the "ranges" property for a
|
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
|
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.
|
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
|
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
|
1/1 format, unless the processor supports physical addresses greater
|
||||||
than 32-bits, in which case a 2/1 format is recommended.
|
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:
|
Required properties:
|
||||||
|
|
||||||
- device_type : has to be "cpu"
|
- 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
|
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
|
unit name in the full path. For example, with 2 CPUs, you would
|
||||||
have the full path:
|
have the full path:
|
||||||
@@ -785,7 +801,7 @@ address which can extend beyond that limit.
|
|||||||
the kernel timebase/decrementer calibration based on this
|
the kernel timebase/decrementer calibration based on this
|
||||||
value.
|
value.
|
||||||
- clock-frequency : a cell indicating the CPU core clock frequency
|
- 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
|
your frequency is < 4Ghz, one cell is enough. Here as well as
|
||||||
for the above, the common code doesn't use that property, but
|
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
|
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
|
This node is a bit "special". Normally, that's where open firmware
|
||||||
puts some variable environment information, like the arguments, or
|
puts some variable environment information, like the arguments, or
|
||||||
phandle pointers to nodes like the main interrupt controller, or the
|
the default input/output devices.
|
||||||
default input/output devices.
|
|
||||||
|
|
||||||
This specification makes a few of these mandatory, but also defines
|
This specification makes a few of these mandatory, but also defines
|
||||||
some linux-specific properties that would be normally constructed by
|
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
|
that the kernel tries to find out the default console and has
|
||||||
knowledge of various types like 8250 serial ports. You may want
|
knowledge of various types like 8250 serial ports. You may want
|
||||||
to extend this function to add your own.
|
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
|
Note that u-boot creates and fills in the chosen node for platforms
|
||||||
that use it.
|
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
|
f) the /soc<SOCname> node
|
||||||
|
|
||||||
This node is used to represent a system-on-a-chip (SOC) and must be
|
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
|
The SOC node may contain child nodes for each SOC device that the
|
||||||
platform uses. Nodes should not be created for devices which exist
|
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
|
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
|
for more information on how to specify devices that are part of a SOC.
|
||||||
SOC.
|
|
||||||
|
|
||||||
Example SOC node for the MPC8540:
|
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
|
[-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
|
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.
|
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
|
property2 = <1234abcd>; /* define a property containing a
|
||||||
* numerical 32 bits value (hexadecimal)
|
* numerical 32-bit value (hexadecimal)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
property3 = <12345678 12345678 deadbeef>;
|
property3 = <12345678 12345678 deadbeef>;
|
||||||
/* define a property containing 3
|
/* define a property containing 3
|
||||||
* numerical 32 bits values (cells) in
|
* numerical 32-bit values (cells) in
|
||||||
* hexadecimal
|
* hexadecimal
|
||||||
*/
|
*/
|
||||||
property4 = [0a 0b 0c 0d de ea ad be ef];
|
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
|
its usage in early_init_devtree(), and the corresponding various
|
||||||
early_init_dt_scan_*() callbacks. That code can be re-used in a
|
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
|
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.
|
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
|
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
|
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
|
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
|
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.
|
MPC8540.
|
||||||
|
|
||||||
|
|
||||||
2) Specifying interrupt information for SOC devices
|
2) Representing devices without a current OF specification
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
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
|
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
Currently, there are many devices on SOCs that do not have a standard
|
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
|
- phy-handle : The phandle for the PHY connected to this ethernet
|
||||||
controller.
|
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:
|
Example:
|
||||||
|
|
||||||
ethernet@24000 {
|
ethernet@24000 {
|
||||||
@@ -1312,10 +1298,10 @@ platforms are moved over to use the flattened-device-tree model.
|
|||||||
and additions :
|
and additions :
|
||||||
|
|
||||||
Required properties :
|
Required properties :
|
||||||
- compatible : Should be "fsl-usb2-mph" for multi port host usb
|
- compatible : Should be "fsl-usb2-mph" for multi port host USB
|
||||||
controllers, or "fsl-usb2-dr" for dual role usb controllers
|
controllers, or "fsl-usb2-dr" for dual role USB controllers
|
||||||
- phy_type : For multi port host usb controllers, should be one of
|
- phy_type : For multi port host USB controllers, should be one of
|
||||||
"ulpi", or "serial". For dual role usb controllers, should be
|
"ulpi", or "serial". For dual role USB controllers, should be
|
||||||
one of "ulpi", "utmi", "utmi_wide", or "serial".
|
one of "ulpi", "utmi", "utmi_wide", or "serial".
|
||||||
- reg : Offset and length of the register set for the device
|
- reg : Offset and length of the register set for the device
|
||||||
- port0 : boolean; if defined, indicates port0 is connected for
|
- 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
|
- interrupt-parent : the phandle for the interrupt controller that
|
||||||
services interrupts for this device.
|
services interrupts for this device.
|
||||||
|
|
||||||
Example multi port host usb controller device node :
|
Example multi port host USB controller device node :
|
||||||
usb@22000 {
|
usb@22000 {
|
||||||
device_type = "usb";
|
device_type = "usb";
|
||||||
compatible = "fsl-usb2-mph";
|
compatible = "fsl-usb2-mph";
|
||||||
@@ -1353,7 +1339,7 @@ platforms are moved over to use the flattened-device-tree model.
|
|||||||
port1;
|
port1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Example dual role usb controller device node :
|
Example dual role USB controller device node :
|
||||||
usb@23000 {
|
usb@23000 {
|
||||||
device_type = "usb";
|
device_type = "usb";
|
||||||
compatible = "fsl-usb2-dr";
|
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
|
- channel-fifo-len : An integer representing the number of
|
||||||
descriptor pointers each channel fetch fifo can hold.
|
descriptor pointers each channel fetch fifo can hold.
|
||||||
- exec-units-mask : The bitmask representing what execution units
|
- 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
|
should be encoded following the SEC's Descriptor Header Dword
|
||||||
EU_SEL0 field documentation, i.e. as follows:
|
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.
|
bits 8 through 31 are reserved for future SEC EUs.
|
||||||
|
|
||||||
- descriptor-types-mask : The bitmask representing what descriptors
|
- 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
|
information should be encoded following the SEC's Descriptor
|
||||||
Header Dword DESC_TYPE field documentation, i.e. as follows:
|
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:
|
Required properties:
|
||||||
- device_type : should be "spi".
|
- device_type : should be "spi".
|
||||||
- compatible : should be "fsl_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
|
- reg : Offset and length of the register set for the device
|
||||||
- interrupts : <a b> where a is the interrupt number and b is a
|
- interrupts : <a b> where a is the interrupt number and b is a
|
||||||
field that represents an encoding of the sense and level
|
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.
|
- mac-address : list of bytes representing the ethernet address.
|
||||||
- phy-handle : The phandle for the PHY connected to this controller.
|
- 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:
|
Example:
|
||||||
ucc@2000 {
|
ucc@2000 {
|
||||||
device_type = "network";
|
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
|
- 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'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 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
|
- partition-names : The list of concatenated zero terminated strings
|
||||||
representing the partition names.
|
representing the partition names.
|
||||||
- probe-type : The type of probe which should be done for the chip
|
- 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.
|
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
|
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
|
This option selects whether a 32-bit or a 64-bit kernel
|
||||||
will be built.
|
will be built.
|
||||||
|
|
||||||
|
config PPC_PM_NEEDS_RTC_LIB
|
||||||
|
bool
|
||||||
|
select RTC_LIB
|
||||||
|
default y if PM
|
||||||
|
|
||||||
config PPC32
|
config PPC32
|
||||||
bool
|
bool
|
||||||
default y if !PPC64
|
default y if !PPC64
|
||||||
@@ -89,7 +94,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
|
|||||||
|
|
||||||
config ARCH_MAY_HAVE_PC_FDC
|
config ARCH_MAY_HAVE_PC_FDC
|
||||||
bool
|
bool
|
||||||
default y
|
default !PPC_PSERIES || PCI
|
||||||
|
|
||||||
config PPC_OF
|
config PPC_OF
|
||||||
def_bool y
|
def_bool y
|
||||||
@@ -157,17 +162,20 @@ config PPC_83xx
|
|||||||
select FSL_SOC
|
select FSL_SOC
|
||||||
select 83xx
|
select 83xx
|
||||||
select PPC_FPU
|
select PPC_FPU
|
||||||
|
select WANT_DEVICE_TREE
|
||||||
|
|
||||||
config PPC_85xx
|
config PPC_85xx
|
||||||
bool "Freescale 85xx"
|
bool "Freescale 85xx"
|
||||||
select E500
|
select E500
|
||||||
select FSL_SOC
|
select FSL_SOC
|
||||||
select 85xx
|
select 85xx
|
||||||
|
select WANT_DEVICE_TREE
|
||||||
|
|
||||||
config PPC_86xx
|
config PPC_86xx
|
||||||
bool "Freescale 86xx"
|
bool "Freescale 86xx"
|
||||||
select 6xx
|
select 6xx
|
||||||
select FSL_SOC
|
select FSL_SOC
|
||||||
|
select FSL_PCIE
|
||||||
select PPC_FPU
|
select PPC_FPU
|
||||||
select ALTIVEC
|
select ALTIVEC
|
||||||
help
|
help
|
||||||
@@ -186,7 +194,6 @@ config 44x
|
|||||||
bool "AMCC 44x"
|
bool "AMCC 44x"
|
||||||
select PPC_DCR_NATIVE
|
select PPC_DCR_NATIVE
|
||||||
|
|
||||||
|
|
||||||
config E200
|
config E200
|
||||||
bool "Freescale e200"
|
bool "Freescale e200"
|
||||||
|
|
||||||
@@ -367,394 +374,7 @@ endmenu
|
|||||||
|
|
||||||
source "init/Kconfig"
|
source "init/Kconfig"
|
||||||
|
|
||||||
menu "Platform support"
|
source "arch/powerpc/platforms/Kconfig"
|
||||||
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
|
|
||||||
|
|
||||||
menu "Kernel options"
|
menu "Kernel options"
|
||||||
|
|
||||||
@@ -837,15 +457,6 @@ config CRASH_DUMP
|
|||||||
|
|
||||||
Don't change this unless you know what you are doing.
|
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
|
config PPCBUG_NVRAM
|
||||||
bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
|
bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
|
||||||
default y if PPC_PREP
|
default y if PPC_PREP
|
||||||
@@ -859,8 +470,6 @@ config IRQ_ALL_CPUS
|
|||||||
CPU. Generally saying Y is safe, although some problems have been
|
CPU. Generally saying Y is safe, although some problems have been
|
||||||
reported with SMP Power Macintoshes with this option enabled.
|
reported with SMP Power Macintoshes with this option enabled.
|
||||||
|
|
||||||
source "arch/powerpc/platforms/pseries/Kconfig"
|
|
||||||
|
|
||||||
config NUMA
|
config NUMA
|
||||||
bool "NUMA support"
|
bool "NUMA support"
|
||||||
depends on PPC64
|
depends on PPC64
|
||||||
@@ -910,10 +519,10 @@ config PPC_64K_PAGES
|
|||||||
depends on PPC64
|
depends on PPC64
|
||||||
help
|
help
|
||||||
This option changes the kernel logical page size to 64k. On machines
|
This option changes the kernel logical page size to 64k. On machines
|
||||||
without processor support for 64k pages, the kernel will simulate
|
without processor support for 64k pages, the kernel will simulate
|
||||||
them by loading each individual 4k page on demand transparently,
|
them by loading each individual 4k page on demand transparently,
|
||||||
while on hardware with such support, it will be used to map
|
while on hardware with such support, it will be used to map
|
||||||
normal application pages.
|
normal application pages.
|
||||||
|
|
||||||
config SCHED_SMT
|
config SCHED_SMT
|
||||||
bool "SMT (Hyperthreading) scheduler support"
|
bool "SMT (Hyperthreading) scheduler support"
|
||||||
@@ -931,8 +540,6 @@ config PROC_DEVICETREE
|
|||||||
an image of the device tree that the kernel copies from Open
|
an image of the device tree that the kernel copies from Open
|
||||||
Firmware or other boot firmware. If unsure, say Y here.
|
Firmware or other boot firmware. If unsure, say Y here.
|
||||||
|
|
||||||
source "arch/powerpc/platforms/prep/Kconfig"
|
|
||||||
|
|
||||||
config CMDLINE_BOOL
|
config CMDLINE_BOOL
|
||||||
bool "Default bootloader kernel arguments"
|
bool "Default bootloader kernel arguments"
|
||||||
|
|
||||||
@@ -967,6 +574,29 @@ config SECCOMP
|
|||||||
|
|
||||||
If unsure, say Y. Only embedded should say N here.
|
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
|
endmenu
|
||||||
|
|
||||||
config ISA_DMA_API
|
config ISA_DMA_API
|
||||||
@@ -995,24 +625,17 @@ config GENERIC_ISA_DMA
|
|||||||
depends on PPC64 || POWER4 || 6xx && !CPM2
|
depends on PPC64 || POWER4 || 6xx && !CPM2
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config MPIC
|
|
||||||
bool
|
|
||||||
default n
|
|
||||||
|
|
||||||
config MPIC_WEIRD
|
|
||||||
bool
|
|
||||||
default n
|
|
||||||
|
|
||||||
config PPC_I8259
|
|
||||||
bool
|
|
||||||
default n
|
|
||||||
|
|
||||||
config PPC_INDIRECT_PCI
|
config PPC_INDIRECT_PCI
|
||||||
bool
|
bool
|
||||||
depends on PCI
|
depends on PCI
|
||||||
default y if 40x || 44x
|
default y if 40x || 44x
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config PPC_INDIRECT_PCI_BE
|
||||||
|
bool
|
||||||
|
depends PPC_INDIRECT_PCI
|
||||||
|
default n
|
||||||
|
|
||||||
config EISA
|
config EISA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
@@ -1022,13 +645,18 @@ config SBUS
|
|||||||
config FSL_SOC
|
config FSL_SOC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config FSL_PCIE
|
||||||
|
bool
|
||||||
|
depends on PPC_86xx
|
||||||
|
|
||||||
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
|
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
|
||||||
config MCA
|
config MCA
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config PCI
|
config PCI
|
||||||
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|
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 \
|
default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
|
||||||
&& !PPC_85xx && !PPC_86xx
|
&& !PPC_85xx && !PPC_86xx
|
||||||
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
|
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/sysdev/qe_lib/Kconfig"
|
||||||
|
|
||||||
source "arch/powerpc/platforms/iseries/Kconfig"
|
|
||||||
|
|
||||||
source "lib/Kconfig"
|
source "lib/Kconfig"
|
||||||
|
|
||||||
menu "Instrumentation Support"
|
menu "Instrumentation Support"
|
||||||
depends on EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
|
|
||||||
source "arch/powerpc/oprofile/Kconfig"
|
source "arch/powerpc/oprofile/Kconfig"
|
||||||
|
|
||||||
|
@@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE
|
|||||||
|
|
||||||
This option will slow down process creation somewhat.
|
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
|
config HCALL_STATS
|
||||||
bool "Hypervisor call instrumentation"
|
bool "Hypervisor call instrumentation"
|
||||||
depends on PPC_PSERIES && DEBUG_FS
|
depends on PPC_PSERIES && DEBUG_FS
|
||||||
@@ -132,8 +141,7 @@ config BOOTX_TEXT
|
|||||||
|
|
||||||
config SERIAL_TEXT_DEBUG
|
config SERIAL_TEXT_DEBUG
|
||||||
bool "Support for early boot texts over serial port"
|
bool "Support for early boot texts over serial port"
|
||||||
depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
|
depends on 4xx
|
||||||
PPC_GEN550 || PPC_MPC52xx
|
|
||||||
|
|
||||||
config PPC_EARLY_DEBUG
|
config PPC_EARLY_DEBUG
|
||||||
bool "Early debugging (dangerous)"
|
bool "Early debugging (dangerous)"
|
||||||
|
@@ -102,9 +102,9 @@ CFLAGS += $(call cc-option,-mno-altivec)
|
|||||||
# kernel considerably.
|
# kernel considerably.
|
||||||
CFLAGS += $(call cc-option,-funit-at-a-time)
|
CFLAGS += $(call cc-option,-funit-at-a-time)
|
||||||
|
|
||||||
ifndef CONFIG_FSL_BOOKE
|
# Never use string load/store instructions as they are
|
||||||
CFLAGS += -mstring
|
# often slow when they are implemented at all
|
||||||
endif
|
CFLAGS += -mno-string
|
||||||
|
|
||||||
ifeq ($(CONFIG_6xx),y)
|
ifeq ($(CONFIG_6xx),y)
|
||||||
CFLAGS += -mcpu=powerpc
|
CFLAGS += -mcpu=powerpc
|
||||||
@@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE)
|
|||||||
|
|
||||||
CPPFLAGS_vmlinux.lds := -Upowerpc
|
CPPFLAGS_vmlinux.lds := -Upowerpc
|
||||||
|
|
||||||
BOOT_TARGETS = zImage zImage.initrd uImage
|
BOOT_TARGETS = zImage zImage.initrd uImage cuImage
|
||||||
|
|
||||||
PHONY += $(BOOT_TARGETS)
|
PHONY += $(BOOT_TARGETS)
|
||||||
|
|
||||||
@@ -166,6 +166,9 @@ define archhelp
|
|||||||
@echo ' *_defconfig - Select default config from arch/$(ARCH)/configs'
|
@echo ' *_defconfig - Select default config from arch/$(ARCH)/configs'
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
|
||||||
|
|
||||||
archclean:
|
archclean:
|
||||||
$(Q)$(MAKE) $(clean)=$(boot)
|
$(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
|
kernel-vmlinux.strip.gz
|
||||||
mktree
|
mktree
|
||||||
uImage
|
uImage
|
||||||
|
cuImage
|
||||||
|
cuImage.bin.gz
|
||||||
|
cuImage.elf
|
||||||
zImage
|
zImage
|
||||||
zImage.chrp
|
zImage.chrp
|
||||||
zImage.coff
|
zImage.coff
|
||||||
|
@@ -40,10 +40,11 @@ zliblinuxheader := zlib.h zconf.h zutil.h
|
|||||||
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
|
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
|
||||||
$(addprefix $(obj)/,$(zlibheader))
|
$(addprefix $(obj)/,$(zlibheader))
|
||||||
|
|
||||||
src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.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 $(zlib)
|
ns16550.c serial.c simple_alloc.c div64.S util.S \
|
||||||
src-plat := of.c
|
gunzip_util.c elf_util.c $(zlib) devtree.c
|
||||||
src-boot := crt0.S $(src-wlib) $(src-plat) empty.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))
|
src-boot := $(addprefix $(obj)/, $(src-boot))
|
||||||
obj-boot := $(addsuffix .o, $(basename $(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 $< $@
|
@cp $< $@
|
||||||
|
|
||||||
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
|
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 $@
|
quiet_cmd_bootcc = BOOTCC $@
|
||||||
cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
|
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 $@ $<
|
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
quiet_cmd_bootar = BOOTAR $@
|
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)
|
$(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)
|
$(call if_changed_dep,bootas)
|
||||||
|
|
||||||
$(obj)/wrapper.a: $(obj-wlib)
|
$(obj)/wrapper.a: $(obj-wlib) FORCE
|
||||||
$(call cmd,bootar)
|
$(call if_changed,bootar)
|
||||||
|
|
||||||
hostprogs-y := addnote addRamDisk hack-coff mktree
|
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
|
$(obj)/zImage.lds $(obj)/zImage.coff.lds
|
||||||
|
|
||||||
wrapper :=$(srctree)/$(src)/wrapper
|
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
|
# Bits for building various flavours of zImage
|
||||||
@@ -113,50 +116,10 @@ CROSSWRAP := -C "$(CROSS_COMPILE)"
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd
|
||||||
quiet_cmd_wrap = WRAP $@
|
quiet_cmd_wrap = WRAP $@
|
||||||
cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux
|
cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
|
||||||
quiet_cmd_wrap_initrd = WRAP $@
|
$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
|
||||||
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)
|
|
||||||
|
|
||||||
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
|
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
|
||||||
image-$(CONFIG_PPC_MAPLE) += 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_CHRP) += zImage.chrp
|
||||||
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
|
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
|
||||||
image-$(CONFIG_PPC_PMAC) += zImage.pmac
|
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
|
# For 32-bit powermacs, build the COFF and miboot images
|
||||||
# as well as the ELF images.
|
# as well as the ELF images.
|
||||||
@@ -174,16 +137,55 @@ ifeq ($(CONFIG_PPC32),y)
|
|||||||
image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot
|
image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
|
||||||
initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y))
|
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))
|
$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
|
||||||
@rm -f $@; ln $< $@
|
@rm -f $@; ln $< $@
|
||||||
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
|
$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
|
||||||
@rm -f $@; ln $< $@
|
@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)" $<
|
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
|
||||||
|
|
||||||
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz)
|
# anything not in $(targets)
|
||||||
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz)
|
clean-files += $(image-) $(initrd-) zImage zImage.initrd \
|
||||||
clean-files += $(image-)
|
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:
|
_zimage_start_opd:
|
||||||
.long _zimage_start, 0, 0, 0
|
.long _zimage_start, 0, 0, 0
|
||||||
|
|
||||||
|
.weak _zimage_start
|
||||||
.globl _zimage_start
|
.globl _zimage_start
|
||||||
_zimage_start:
|
_zimage_start:
|
||||||
|
.globl _zimage_start_lib
|
||||||
|
_zimage_start_lib:
|
||||||
/* Work out the offset between the address we were linked at
|
/* Work out the offset between the address we were linked at
|
||||||
and the address where we're running. */
|
and the address where we're running. */
|
||||||
bl 1f
|
bl 1f
|
||||||
@@ -44,7 +47,7 @@ _zimage_start:
|
|||||||
addi r9,r9,4
|
addi r9,r9,4
|
||||||
bdnz 2b
|
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
|
3: lis r9,_start@ha
|
||||||
addi r9,r9,_start@l
|
addi r9,r9,_start@l
|
||||||
add r9,r0,r9
|
add r9,r0,r9
|
||||||
@@ -59,6 +62,34 @@ _zimage_start:
|
|||||||
sync
|
sync
|
||||||
isync
|
isync
|
||||||
|
|
||||||
mr r6,r1
|
/* Clear the BSS */
|
||||||
b start
|
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 {
|
cpus {
|
||||||
linux,phandle = <2000>;
|
linux,phandle = <2000>;
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#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-parent = <4400>;
|
||||||
interrupt-map-mask = <f800 0 0 7>;
|
interrupt-map-mask = <f800 0 0 7>;
|
||||||
interrupt-map = <
|
interrupt-map = <
|
||||||
/* IDSEL 0x11 - IRQ0 ETH */
|
/* IDSEL 11 - IRQ0 ETH */
|
||||||
5800 0 0 1 4400 0 1
|
5800 0 0 1 4400 0 1
|
||||||
5800 0 0 2 4400 1 1
|
5800 0 0 2 4400 1 1
|
||||||
5800 0 0 3 4400 2 1
|
5800 0 0 3 4400 2 1
|
||||||
5800 0 0 4 4400 3 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 1 4400 1 1
|
||||||
6000 0 0 2 4400 2 1
|
6000 0 0 2 4400 2 1
|
||||||
6000 0 0 3 4400 3 1
|
6000 0 0 3 4400 3 1
|
||||||
6000 0 0 4 4400 0 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 1 4400 3 1
|
||||||
7000 0 0 2 4400 3 1
|
7000 0 0 2 4400 3 1
|
||||||
7000 0 0 3 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 {
|
cpus {
|
||||||
linux,phandle = <2000>;
|
linux,phandle = <2000>;
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#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-parent = <4400>;
|
||||||
interrupt-map-mask = <f800 0 0 7>;
|
interrupt-map-mask = <f800 0 0 7>;
|
||||||
interrupt-map = <
|
interrupt-map = <
|
||||||
/* IDSEL 0x11 - IRQ0 ETH */
|
/* IDSEL 11 - IRQ0 ETH */
|
||||||
5800 0 0 1 4400 0 1
|
5800 0 0 1 4400 0 1
|
||||||
5800 0 0 2 4400 1 1
|
5800 0 0 2 4400 1 1
|
||||||
5800 0 0 3 4400 2 1
|
5800 0 0 3 4400 2 1
|
||||||
5800 0 0 4 4400 3 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 1 4400 1 1
|
||||||
6000 0 0 2 4400 2 1
|
6000 0 0 2 4400 2 1
|
||||||
6000 0 0 3 4400 3 1
|
6000 0 0 3 4400 3 1
|
||||||
6000 0 0 4 4400 0 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 1 4400 3 1
|
||||||
7000 0 0 2 4400 3 1
|
7000 0 0 2 4400 3 1
|
||||||
7000 0 0 3 4400 3 1
|
7000 0 0 3 4400 3 1
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
linux,phandle = <100>;
|
linux,phandle = <100>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells =<0>;
|
#size-cells =<0>;
|
||||||
linux,phandle = <200>;
|
linux,phandle = <200>;
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
linux,phandle = <100>;
|
linux,phandle = <100>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
linux,phandle = <200>;
|
linux,phandle = <200>;
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#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>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#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>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <2>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#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 {
|
mpic: pic@40000 {
|
||||||
clock-frequency = <0>;
|
clock-frequency = <0>;
|
||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
linux,phandle = <100>;
|
linux,phandle = <100>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
linux,phandle = <200>;
|
linux,phandle = <200>;
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
linux,phandle = <100>;
|
linux,phandle = <100>;
|
||||||
|
|
||||||
cpus {
|
cpus {
|
||||||
#cpus = <1>;
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
linux,phandle = <200>;
|
linux,phandle = <200>;
|
||||||
|
@@ -146,4 +146,12 @@ typedef struct elf64_phdr {
|
|||||||
#define ELFOSABI_NONE 0
|
#define ELFOSABI_NONE 0
|
||||||
#define ELFOSABI_LINUX 3
|
#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_ */
|
#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))
|
#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 */
|
/* 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 */
|
/* 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;
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (i = 1; i < cxt->nodes_used; i++) /* already there? */
|
for (i = 1; i < cxt->nodes_used; i++) /* already there? */
|
||||||
if (cxt->node_tbl[i] == node)
|
if (cxt->node_tbl[i] == node)
|
||||||
return (void *)i;
|
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)
|
if (rgn == FT_STRUCT)
|
||||||
ft_node_update_before(cxt, p, -nextra);
|
ft_node_update_before(cxt, p, -nextra);
|
||||||
}
|
}
|
||||||
*p -= nextra;
|
*pp -= nextra;
|
||||||
cxt->rgn[rgn].start -= nextra;
|
cxt->rgn[rgn].start -= nextra;
|
||||||
cxt->rgn[rgn].size += nextra;
|
cxt->rgn[rgn].size += nextra;
|
||||||
return 1;
|
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;
|
char *str, *next;
|
||||||
enum ft_rgn_id r;
|
enum ft_rgn_id r;
|
||||||
|
|
||||||
if (!cxt->isordered && !ft_reorder(cxt, nextra))
|
if (!cxt->isordered) {
|
||||||
return 0;
|
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))
|
if (ft_shuffle(cxt, pp, rgn, nextra))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -415,7 +429,7 @@ int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
|
|||||||
{
|
{
|
||||||
int off, len;
|
int off, len;
|
||||||
|
|
||||||
off = lookup_string(cxt, name);
|
off = map_string(cxt, name);
|
||||||
if (off == NO_STRING)
|
if (off == NO_STRING)
|
||||||
return -1;
|
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)
|
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)
|
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 */
|
/* require absolute path */
|
||||||
if (srch_path[0] != '/')
|
if (srch_path[0] != '/')
|
||||||
return NULL;
|
return NULL;
|
||||||
node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
|
node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path);
|
||||||
return ft_node_add(cxt, node);
|
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)
|
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;
|
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;
|
int d;
|
||||||
struct ft_atom atom;
|
struct ft_atom atom;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
node = ft_node_ph2node(cxt, phandle);
|
|
||||||
if (node == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (d = 0; cxt->genealogy[d] != NULL; ++d)
|
for (d = 0; cxt->genealogy[d] != NULL; ++d)
|
||||||
if (cxt->genealogy[d] == node)
|
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... */
|
/* have to do it the hard way... */
|
||||||
p = cxt->rgn[FT_STRUCT].start;
|
p = ft_root_node(cxt);
|
||||||
d = 0;
|
d = 0;
|
||||||
while ((p = ft_next(cxt, p, &atom)) != NULL) {
|
while ((p = ft_next(cxt, p, &atom)) != NULL) {
|
||||||
switch (atom.tag) {
|
switch (atom.tag) {
|
||||||
@@ -726,7 +748,7 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
|
|||||||
if (node == atom.data) {
|
if (node == atom.data) {
|
||||||
/* found it */
|
/* found it */
|
||||||
cxt->genealogy[d + 1] = NULL;
|
cxt->genealogy[d + 1] = NULL;
|
||||||
return d > 0 ? cxt->genealogy[d - 1] : node;
|
return d > 0 ? cxt->genealogy[d - 1] : NULL;
|
||||||
}
|
}
|
||||||
++d;
|
++d;
|
||||||
break;
|
break;
|
||||||
@@ -738,41 +760,131 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
|
void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
|
||||||
void *buf, const unsigned int buflen)
|
{
|
||||||
|
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;
|
struct ft_atom atom;
|
||||||
void *node;
|
int depth = 0;
|
||||||
char *p;
|
|
||||||
int depth;
|
|
||||||
unsigned int size;
|
|
||||||
|
|
||||||
node = ft_node_ph2node(cxt, phandle);
|
while ((node = ft_next(cxt, node, &atom)) != NULL) {
|
||||||
if (node == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
depth = 0;
|
|
||||||
p = (char *)node;
|
|
||||||
|
|
||||||
while ((p = ft_next(cxt, p, &atom)) != NULL) {
|
|
||||||
switch (atom.tag) {
|
switch (atom.tag) {
|
||||||
case OF_DT_BEGIN_NODE:
|
case OF_DT_BEGIN_NODE:
|
||||||
++depth;
|
++depth;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OF_DT_PROP:
|
case OF_DT_PROP:
|
||||||
if ((depth != 1) || strcmp(atom.name, propname))
|
if (depth != 1 || strcmp(atom.name, propname))
|
||||||
break;
|
break;
|
||||||
size = min(atom.size, buflen);
|
|
||||||
memcpy(buf, atom.data, size);
|
if (len)
|
||||||
return atom.size;
|
*len = atom.size;
|
||||||
|
|
||||||
|
return atom.data;
|
||||||
|
|
||||||
case OF_DT_END_NODE:
|
case OF_DT_END_NODE:
|
||||||
if (--depth <= 0)
|
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;
|
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,
|
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
|
||||||
const void *buf, const unsigned int buflen)
|
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;
|
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;
|
struct ft_atom atom;
|
||||||
char *p, *next;
|
char *p, *next;
|
||||||
int depth = 0;
|
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) {
|
while ((next = ft_next(cxt, p, &atom)) != NULL) {
|
||||||
switch (atom.tag) {
|
switch (atom.tag) {
|
||||||
case OF_DT_BEGIN_NODE:
|
case OF_DT_BEGIN_NODE:
|
||||||
++depth;
|
++depth;
|
||||||
if (depth == 1 && strcmp(atom.name, path) == 0)
|
if (depth == 1 && strcmp(atom.name, name) == 0)
|
||||||
/* duplicate node path, return error */
|
/* duplicate node name, return error */
|
||||||
return NULL;
|
return NULL;
|
||||||
break;
|
break;
|
||||||
case OF_DT_END_NODE:
|
case OF_DT_END_NODE:
|
||||||
@@ -870,7 +989,7 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
|
|||||||
break;
|
break;
|
||||||
/* end of node, insert here */
|
/* end of node, insert here */
|
||||||
cxt->p = p;
|
cxt->p = p;
|
||||||
ft_begin_node(cxt, path);
|
ft_begin_node(cxt, name);
|
||||||
ft_end_node(cxt);
|
ft_end_node(cxt);
|
||||||
return p;
|
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_dump_blob(const void *bphp);
|
||||||
void ft_merge_blob(struct ft_cxt *cxt, void *blob);
|
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(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);
|
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,
|
int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
|
||||||
void *buf, const unsigned int buflen);
|
void *buf, const unsigned int buflen);
|
||||||
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
|
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
|
||||||
const void *buf, const unsigned int buflen);
|
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 */
|
#endif /* FLATDEVTREE_H */
|
||||||
|
@@ -16,24 +16,43 @@
|
|||||||
|
|
||||||
static struct ft_cxt cxt;
|
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);
|
return ft_find_device(&cxt, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ft_getprop(const void *phandle, const char *propname, void *buf,
|
static int fdtm_getprop(const void *phandle, const char *propname,
|
||||||
const int buflen)
|
void *buf, const int buflen)
|
||||||
{
|
{
|
||||||
return ft_get_prop(&cxt, phandle, propname, buf, buflen);
|
return ft_get_prop(&cxt, phandle, propname, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ft_setprop(const void *phandle, const char *propname,
|
static int fdtm_setprop(const void *phandle, const char *propname,
|
||||||
const void *buf, const int buflen)
|
const void *buf, const int buflen)
|
||||||
{
|
{
|
||||||
return ft_set_prop(&cxt, phandle, propname, buf, 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);
|
ft_end_tree(&cxt);
|
||||||
return (unsigned long)cxt.bph;
|
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)
|
int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
|
||||||
{
|
{
|
||||||
dt_ops.finddevice = ft_finddevice;
|
dt_ops.finddevice = fdtm_finddevice;
|
||||||
dt_ops.getprop = ft_getprop;
|
dt_ops.getprop = fdtm_getprop;
|
||||||
dt_ops.setprop = ft_setprop;
|
dt_ops.setprop = fdtm_setprop;
|
||||||
dt_ops.finalize = ft_finalize;
|
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,
|
return ft_open(&cxt, dt_blob, max_size, max_find_device,
|
||||||
platform_ops.realloc);
|
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 "page.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "zlib.h"
|
|
||||||
#include "ops.h"
|
#include "ops.h"
|
||||||
|
#include "gunzip_util.h"
|
||||||
#include "flatdevtree.h"
|
#include "flatdevtree.h"
|
||||||
|
#include "reg.h"
|
||||||
extern void flush_cache(void *, unsigned long);
|
|
||||||
|
|
||||||
extern char _start[];
|
extern char _start[];
|
||||||
extern char __bss_start[];
|
extern char __bss_start[];
|
||||||
@@ -30,304 +29,173 @@ extern char _initrd_end[];
|
|||||||
extern char _dtb_start[];
|
extern char _dtb_start[];
|
||||||
extern char _dtb_end[];
|
extern char _dtb_end[];
|
||||||
|
|
||||||
|
static struct gunzip_state gzstate;
|
||||||
|
|
||||||
struct addr_range {
|
struct addr_range {
|
||||||
unsigned long addr;
|
void *addr;
|
||||||
unsigned long size;
|
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 *);
|
typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
#define HEAD_CRC 2
|
static struct addr_range prep_kernel(void)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
|
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;
|
int len;
|
||||||
|
|
||||||
vmlinuz.addr = (unsigned long)_vmlinux_start;
|
|
||||||
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
|
|
||||||
|
|
||||||
/* gunzip the ELF header of the kernel */
|
/* gunzip the ELF header of the kernel */
|
||||||
if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
|
gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
|
||||||
len = vmlinuz.size;
|
gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
|
||||||
gunzip(elfheader, sizeof(elfheader),
|
|
||||||
(unsigned char *)vmlinuz.addr, &len);
|
if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
|
||||||
} else
|
fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
|
||||||
memcpy(elfheader, (const void *)vmlinuz.addr,
|
|
||||||
sizeof(elfheader));
|
|
||||||
|
|
||||||
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)
|
if (platform_ops.image_hdr)
|
||||||
platform_ops.image_hdr(elfheader);
|
platform_ops.image_hdr(elfheader);
|
||||||
|
|
||||||
/* We need to alloc the memsize plus the file offset since gzip
|
/* We need to alloc the memsize: gzip will expand the kernel
|
||||||
* will expand the header (file offset), then the kernel, then
|
* text/data, then possible rubbish we don't care about. But
|
||||||
* possible rubbish we don't care about. But the kernel bss must
|
* the kernel bss must be claimed (it will be zero'd by the
|
||||||
* be claimed (it will be zero'd by the kernel itself)
|
* kernel itself)
|
||||||
*/
|
*/
|
||||||
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
|
printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize);
|
||||||
vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
|
|
||||||
if (vmlinux.addr == 0) {
|
if (platform_ops.vmlinux_alloc) {
|
||||||
printf("Can't allocate memory for kernel image !\n\r");
|
addr = platform_ops.vmlinux_alloc(ei.memsize);
|
||||||
exit();
|
} 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
|
* If the initrd is too low it will be clobbered when the
|
||||||
*
|
* kernel relocates to its final location. In this case,
|
||||||
* First see if we have an image attached to us. If so
|
* allocate a safer place and move it.
|
||||||
* allocate memory for it and copy it there.
|
|
||||||
*/
|
*/
|
||||||
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
|
if (initrd_addr < vmlinux.size) {
|
||||||
initrd.memsize = initrd.size;
|
void *old_addr = (void *)initrd_addr;
|
||||||
if (initrd.size > 0) {
|
|
||||||
printf("Allocating 0x%lx bytes for initrd ...\n\r",
|
printf("Allocating 0x%lx bytes for initrd ...\n\r",
|
||||||
initrd.size);
|
initrd_size);
|
||||||
initrd.addr = (unsigned long)malloc((u32)initrd.size);
|
initrd_addr = (unsigned long)malloc(initrd_size);
|
||||||
if (initrd.addr == 0) {
|
if (! initrd_addr)
|
||||||
printf("Can't allocate memory for initial "
|
fatal("Can't allocate memory for initial "
|
||||||
"ramdisk !\n\r");
|
"ramdisk !\n\r");
|
||||||
exit();
|
printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r",
|
||||||
}
|
initrd_addr, old_addr, initrd_size);
|
||||||
printf("initial ramdisk moving 0x%lx <- 0x%lx "
|
memmove((void *)initrd_addr, old_addr, initrd_size);
|
||||||
"(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Eventually gunzip the kernel */
|
printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip over the ELF header */
|
/* Tell the kernel initrd address via device tree */
|
||||||
#ifdef DEBUG
|
setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr));
|
||||||
printf("... skipping 0x%lx bytes of ELF header\n\r",
|
setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size));
|
||||||
elfoffset);
|
|
||||||
#endif
|
|
||||||
vmlinux.addr += elfoffset;
|
|
||||||
|
|
||||||
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
|
/* 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).
|
* 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.
|
* 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")));
|
__attribute__((__section__("__builtin_cmdline")));
|
||||||
|
|
||||||
static void get_cmdline(char *buf, int size)
|
static void prep_cmdline(void *chosen)
|
||||||
{
|
{
|
||||||
void *devp;
|
if (cmdline[0] == '\0')
|
||||||
int len = strlen(builtin_cmdline);
|
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 */
|
/* Put the command line back into the devtree for the kernel */
|
||||||
len = min(len, size-1);
|
setprop_str(chosen, "bootargs", cmdline);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct platform_ops platform_ops;
|
struct platform_ops platform_ops;
|
||||||
struct dt_ops dt_ops;
|
struct dt_ops dt_ops;
|
||||||
struct console_ops console_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;
|
kernel_entry_t kentry;
|
||||||
char cmdline[COMMAND_LINE_SIZE];
|
|
||||||
unsigned long ft_addr = 0;
|
unsigned long ft_addr = 0;
|
||||||
|
void *chosen;
|
||||||
|
|
||||||
memset(__bss_start, 0, _end - __bss_start);
|
/* Do this first, because malloc() could clobber the loader's
|
||||||
memset(&platform_ops, 0, sizeof(platform_ops));
|
* command line. Only use the loader command line if a
|
||||||
memset(&dt_ops, 0, sizeof(dt_ops));
|
* built-in command line wasn't set by an external tool */
|
||||||
memset(&console_ops, 0, sizeof(console_ops));
|
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))
|
if (console_ops.open && (console_ops.open() < 0))
|
||||||
exit();
|
exit();
|
||||||
if (platform_ops.fixups)
|
if (platform_ops.fixups)
|
||||||
platform_ops.fixups();
|
platform_ops.fixups();
|
||||||
|
|
||||||
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
|
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
|
vmlinux = prep_kernel();
|
||||||
* in the dt, print it out and edit it, if possible.
|
initrd = prep_initrd(vmlinux, chosen,
|
||||||
*/
|
loader_info.initrd_addr, loader_info.initrd_size);
|
||||||
if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
|
prep_cmdline(chosen);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Finalizing device tree...");
|
printf("Finalizing device tree...");
|
||||||
if (dt_ops.finalize)
|
if (dt_ops.finalize)
|
||||||
@@ -335,7 +203,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
|||||||
if (ft_addr)
|
if (ft_addr)
|
||||||
printf(" flat tree at 0x%lx\n\r", ft_addr);
|
printf(" flat tree at 0x%lx\n\r", ft_addr);
|
||||||
else
|
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)
|
if (console_ops.close)
|
||||||
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)
|
if (ft_addr)
|
||||||
kentry(ft_addr, 0, NULL);
|
kentry(ft_addr, 0, NULL);
|
||||||
else
|
else
|
||||||
/* XXX initrd addr/size should be passed in properties */
|
kentry((unsigned long)initrd.addr, initrd.size,
|
||||||
kentry(initrd.addr, initrd.size, promptr);
|
loader_info.promptr);
|
||||||
|
|
||||||
/* console closed so printf below may not work */
|
/* console closed so printf in fatal below may not work */
|
||||||
printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
|
fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
@@ -55,10 +55,15 @@ static u8 ns16550_tstc(void)
|
|||||||
int ns16550_console_init(void *devp, struct serial_console_data *scdp)
|
int ns16550_console_init(void *devp, struct serial_console_data *scdp)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
unsigned long reg_phys;
|
||||||
|
|
||||||
n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base));
|
n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base));
|
||||||
if (n != sizeof(reg_base))
|
if (n != sizeof(reg_base)) {
|
||||||
return -1;
|
if (!dt_xlate_reg(devp, 0, ®_phys, NULL))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
reg_base = (void *)reg_phys;
|
||||||
|
}
|
||||||
|
|
||||||
n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
|
n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
|
||||||
if (n != 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;
|
return (void *) virt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *of_try_claim(u32 size)
|
static void *of_try_claim(unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long addr = 0;
|
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)
|
static void of_exit(void)
|
||||||
{
|
{
|
||||||
call_prom("exit", 0, 0);
|
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);
|
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.image_hdr = of_image_hdr;
|
||||||
platform_ops.malloc = of_try_claim;
|
platform_ops.malloc = of_try_claim;
|
||||||
platform_ops.exit = of_exit;
|
platform_ops.exit = of_exit;
|
||||||
|
platform_ops.vmlinux_alloc = of_vmlinux_alloc;
|
||||||
|
|
||||||
dt_ops.finddevice = of_finddevice;
|
dt_ops.finddevice = of_finddevice;
|
||||||
dt_ops.getprop = of_getprop;
|
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;
|
console_ops.write = of_console_write;
|
||||||
|
|
||||||
prom = (int (*)(void *))promptr;
|
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_
|
#ifndef _PPC_BOOT_OPS_H_
|
||||||
#define _PPC_BOOT_OPS_H_
|
#define _PPC_BOOT_OPS_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
#define COMMAND_LINE_SIZE 512
|
#define COMMAND_LINE_SIZE 512
|
||||||
#define MAX_PATH_LEN 256
|
#define MAX_PATH_LEN 256
|
||||||
@@ -21,10 +23,11 @@
|
|||||||
struct platform_ops {
|
struct platform_ops {
|
||||||
void (*fixups)(void);
|
void (*fixups)(void);
|
||||||
void (*image_hdr)(const void *);
|
void (*image_hdr)(const void *);
|
||||||
void * (*malloc)(u32 size);
|
void * (*malloc)(unsigned long size);
|
||||||
void (*free)(void *ptr);
|
void (*free)(void *ptr);
|
||||||
void * (*realloc)(void *ptr, unsigned long size);
|
void * (*realloc)(void *ptr, unsigned long size);
|
||||||
void (*exit)(void);
|
void (*exit)(void);
|
||||||
|
void * (*vmlinux_alloc)(unsigned long size);
|
||||||
};
|
};
|
||||||
extern struct platform_ops platform_ops;
|
extern struct platform_ops platform_ops;
|
||||||
|
|
||||||
@@ -35,6 +38,12 @@ struct dt_ops {
|
|||||||
const int buflen);
|
const int buflen);
|
||||||
int (*setprop)(const void *phandle, const char *name,
|
int (*setprop)(const void *phandle, const char *name,
|
||||||
const void *buf, const int buflen);
|
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);
|
unsigned long (*finalize)(void);
|
||||||
};
|
};
|
||||||
extern struct dt_ops dt_ops;
|
extern struct dt_ops dt_ops;
|
||||||
@@ -58,13 +67,23 @@ struct serial_console_data {
|
|||||||
void (*close)(void);
|
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 ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
|
||||||
int serial_console_init(void);
|
int serial_console_init(void);
|
||||||
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
|
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
|
||||||
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
|
void *simple_alloc_init(char *base, unsigned long heap_size,
|
||||||
u32 max_allocs);
|
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)
|
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;
|
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;
|
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;
|
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
|
||||||
}
|
}
|
||||||
@@ -98,5 +181,11 @@ static inline void exit(void)
|
|||||||
platform_ops.exit();
|
platform_ops.exit();
|
||||||
for(;;);
|
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_ */
|
#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
|
#define ENTRY_IN_USE 0x02
|
||||||
|
|
||||||
static struct alloc_info {
|
static struct alloc_info {
|
||||||
u32 flags;
|
unsigned long flags;
|
||||||
u32 base;
|
unsigned long base;
|
||||||
u32 size;
|
unsigned long size;
|
||||||
} *alloc_tbl;
|
} *alloc_tbl;
|
||||||
|
|
||||||
static u32 tbl_entries;
|
static unsigned long tbl_entries;
|
||||||
static u32 alloc_min;
|
static unsigned long alloc_min;
|
||||||
static u32 next_base;
|
static unsigned long next_base;
|
||||||
static u32 space_left;
|
static unsigned long space_left;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First time an entry is used, its base and size are set.
|
* 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.
|
* An entry can be freed and re-malloc'd but its base & size don't change.
|
||||||
* Should be smart enough for needs of bootwrapper.
|
* 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;
|
struct alloc_info *p = alloc_tbl;
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
@@ -67,13 +67,14 @@ err_out:
|
|||||||
|
|
||||||
static struct alloc_info *simple_find_entry(void *ptr)
|
static struct alloc_info *simple_find_entry(void *ptr)
|
||||||
{
|
{
|
||||||
u32 i;
|
unsigned long i;
|
||||||
struct alloc_info *p = alloc_tbl;
|
struct alloc_info *p = alloc_tbl;
|
||||||
|
|
||||||
for (i=0; i<tbl_entries; i++,p++) {
|
for (i=0; i<tbl_entries; i++,p++) {
|
||||||
if (!(p->flags & ENTRY_BEEN_USED))
|
if (!(p->flags & ENTRY_BEEN_USED))
|
||||||
break;
|
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 p;
|
||||||
}
|
}
|
||||||
return NULL;
|
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
|
* Returns addr of first byte after heap so caller can see if it took
|
||||||
* too much space. If so, change args & try again.
|
* too much space. If so, change args & try again.
|
||||||
*/
|
*/
|
||||||
void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
|
void *simple_alloc_init(char *base, unsigned long heap_size,
|
||||||
u32 max_allocs)
|
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);
|
heap_size = _ALIGN_UP(heap_size, granularity);
|
||||||
alloc_min = 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);
|
alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
|
||||||
memset(alloc_tbl, 0, tbl_size);
|
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;
|
next_base = heap_base;
|
||||||
space_left = heap_size;
|
space_left = heap_size;
|
||||||
|
@@ -7,11 +7,12 @@
|
|||||||
#define EINVAL 22 /* Invalid argument */
|
#define EINVAL 22 /* Invalid argument */
|
||||||
#define ENOSPC 28 /* No space left on device */
|
#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)
|
#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);
|
extern int vsprintf(char *buf, const char *fmt, va_list args);
|
||||||
|
|
||||||
|
@@ -29,6 +29,7 @@ initrd=
|
|||||||
dtb=
|
dtb=
|
||||||
dts=
|
dts=
|
||||||
cacheit=
|
cacheit=
|
||||||
|
gzip=.gz
|
||||||
|
|
||||||
# cross-compilation prefix
|
# cross-compilation prefix
|
||||||
CROSS=
|
CROSS=
|
||||||
@@ -42,7 +43,7 @@ tmpdir=.
|
|||||||
usage() {
|
usage() {
|
||||||
echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
|
echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
|
||||||
echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&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
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +92,9 @@ while [ "$#" -gt 0 ]; do
|
|||||||
[ "$#" -gt 0 ] || usage
|
[ "$#" -gt 0 ] || usage
|
||||||
tmpdir="$1"
|
tmpdir="$1"
|
||||||
;;
|
;;
|
||||||
|
--no-gzip)
|
||||||
|
gzip=
|
||||||
|
;;
|
||||||
-?)
|
-?)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@@ -137,31 +141,44 @@ miboot|uboot)
|
|||||||
ksection=image
|
ksection=image
|
||||||
isection=initrd
|
isection=initrd
|
||||||
;;
|
;;
|
||||||
|
cuboot*)
|
||||||
|
gzip=
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
vmz="$tmpdir/`basename \"$kernel\"`.$ext"
|
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.$$"
|
${CROSS}objcopy $objflags "$kernel" "$vmz.$$"
|
||||||
gzip -f -9 "$vmz.$$"
|
|
||||||
|
if [ -n "$gzip" ]; then
|
||||||
|
gzip -f -9 "$vmz.$$"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$cacheit" ]; then
|
if [ -n "$cacheit" ]; then
|
||||||
mv -f "$vmz.$$.gz" "$vmz.gz"
|
mv -f "$vmz.$$$gzip" "$vmz$gzip"
|
||||||
else
|
else
|
||||||
vmz="$vmz.$$"
|
vmz="$vmz.$$"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
vmz="$vmz$gzip"
|
||||||
|
|
||||||
case "$platform" in
|
case "$platform" in
|
||||||
uboot)
|
uboot|cuboot*)
|
||||||
rm -f "$ofile"
|
|
||||||
version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
|
version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
|
||||||
cut -d' ' -f3`
|
cut -d' ' -f3`
|
||||||
if [ -n "$version" ]; then
|
if [ -n "$version" ]; then
|
||||||
version="-n Linux-$version"
|
version="-n Linux-$version"
|
||||||
fi
|
fi
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$platform" in
|
||||||
|
uboot)
|
||||||
|
rm -f "$ofile"
|
||||||
mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
|
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
|
if [ -z "$cacheit" ]; then
|
||||||
rm -f $vmz.gz
|
rm -f "$vmz"
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
@@ -173,9 +190,9 @@ addsec() {
|
|||||||
--set-section-flags=$3=contents,alloc,load,readonly,data
|
--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
|
if [ -z "$cacheit" ]; then
|
||||||
rm -f "$vmz.gz"
|
rm -f "$vmz"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$initrd" ]; then
|
if [ -n "$initrd" ]; then
|
||||||
@@ -191,7 +208,7 @@ fi
|
|||||||
|
|
||||||
if [ "$platform" != "miboot" ]; then
|
if [ "$platform" != "miboot" ]; then
|
||||||
${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \
|
${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \
|
||||||
$object/crt0.o $platformo $tmp $object/wrapper.a
|
$platformo $tmp $object/wrapper.a
|
||||||
rm $tmp
|
rm $tmp
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -201,7 +218,19 @@ pseries|chrp)
|
|||||||
$object/addnote "$ofile"
|
$object/addnote "$ofile"
|
||||||
;;
|
;;
|
||||||
pmaccoff)
|
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"
|
$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
|
esac
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
OUTPUT_ARCH(powerpc:common)
|
OUTPUT_ARCH(powerpc:common)
|
||||||
ENTRY(_start)
|
ENTRY(_zimage_start_opd)
|
||||||
|
EXTERN(_zimage_start_opd)
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = (5*1024*1024);
|
. = (5*1024*1024);
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
OUTPUT_ARCH(powerpc:common)
|
OUTPUT_ARCH(powerpc:common)
|
||||||
ENTRY(_zimage_start)
|
ENTRY(_zimage_start)
|
||||||
|
EXTERN(_zimage_start)
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = (4*1024*1024);
|
. = (4*1024*1024);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated make config: don't edit
|
# Automatically generated make config: don't edit
|
||||||
# Linux kernel version: 2.6.21-rc3
|
# Linux kernel version: 2.6.21-rc6
|
||||||
# Fri Mar 9 23:34:53 2007
|
# Mon Apr 23 20:46:48 2007
|
||||||
#
|
#
|
||||||
CONFIG_PPC64=y
|
CONFIG_PPC64=y
|
||||||
CONFIG_64BIT=y
|
CONFIG_64BIT=y
|
||||||
@@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y
|
|||||||
# CONFIG_PPC_PMAC is not set
|
# CONFIG_PPC_PMAC is not set
|
||||||
# CONFIG_PPC_MAPLE is not set
|
# CONFIG_PPC_MAPLE is not set
|
||||||
# CONFIG_PPC_PASEMI 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=y
|
||||||
CONFIG_PPC_CELL_NATIVE=y
|
CONFIG_PPC_CELL_NATIVE=y
|
||||||
CONFIG_PPC_IBM_CELL_BLADE=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_PPC_NATIVE=y
|
||||||
CONFIG_UDBG_RTAS_CONSOLE=y
|
CONFIG_UDBG_RTAS_CONSOLE=y
|
||||||
CONFIG_PPC_UDBG_BEAT=y
|
CONFIG_PPC_UDBG_BEAT=y
|
||||||
@@ -174,26 +194,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
|
|||||||
# CONFIG_WANT_EARLY_SERIAL is not set
|
# CONFIG_WANT_EARLY_SERIAL is not set
|
||||||
CONFIG_MPIC=y
|
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
|
# Kernel options
|
||||||
#
|
#
|
||||||
@@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y
|
|||||||
# CONFIG_BLK_DEV_OPTI621 is not set
|
# CONFIG_BLK_DEV_OPTI621 is not set
|
||||||
CONFIG_BLK_DEV_IDEDMA_PCI=y
|
CONFIG_BLK_DEV_IDEDMA_PCI=y
|
||||||
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
|
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
|
||||||
CONFIG_IDEDMA_PCI_AUTO=y
|
|
||||||
# CONFIG_IDEDMA_ONLYDISK is not set
|
# CONFIG_IDEDMA_ONLYDISK is not set
|
||||||
CONFIG_BLK_DEV_AEC62XX=y
|
CONFIG_BLK_DEV_AEC62XX=y
|
||||||
# CONFIG_BLK_DEV_ALI15X3 is not set
|
# 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_TRM290 is not set
|
||||||
# CONFIG_BLK_DEV_VIA82CXXX is not set
|
# CONFIG_BLK_DEV_VIA82CXXX is not set
|
||||||
# CONFIG_BLK_DEV_TC86C001 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_IDE_ARM is not set
|
||||||
CONFIG_BLK_DEV_IDEDMA=y
|
CONFIG_BLK_DEV_IDEDMA=y
|
||||||
# CONFIG_IDEDMA_IVB is not set
|
# CONFIG_IDEDMA_IVB is not set
|
||||||
CONFIG_IDEDMA_AUTO=y
|
|
||||||
# CONFIG_BLK_DEV_HD is not set
|
# CONFIG_BLK_DEV_HD is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y
|
|||||||
# CONFIG_LEGACY_PTYS is not set
|
# CONFIG_LEGACY_PTYS is not set
|
||||||
CONFIG_HVC_DRIVER=y
|
CONFIG_HVC_DRIVER=y
|
||||||
CONFIG_HVC_RTAS=y
|
CONFIG_HVC_RTAS=y
|
||||||
# CONFIG_HVC_BEAT is not set
|
CONFIG_HVC_BEAT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# IPMI
|
# IPMI
|
||||||
@@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m
|
|||||||
# Distributed Lock Manager
|
# Distributed Lock Manager
|
||||||
#
|
#
|
||||||
# CONFIG_DLM is not set
|
# CONFIG_DLM is not set
|
||||||
|
# CONFIG_UCC_SLOW is not set
|
||||||
|
# CONFIG_UCC_FAST is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Library routines
|
# Library routines
|
||||||
@@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
|
|||||||
# CONFIG_FAULT_INJECTION is not set
|
# CONFIG_FAULT_INJECTION is not set
|
||||||
# CONFIG_DEBUG_STACKOVERFLOW is not set
|
# CONFIG_DEBUG_STACKOVERFLOW is not set
|
||||||
# CONFIG_DEBUG_STACK_USAGE is not set
|
# CONFIG_DEBUG_STACK_USAGE is not set
|
||||||
|
# CONFIG_DEBUG_PAGEALLOC is not set
|
||||||
CONFIG_DEBUGGER=y
|
CONFIG_DEBUGGER=y
|
||||||
CONFIG_XMON=y
|
CONFIG_XMON=y
|
||||||
CONFIG_XMON_DEFAULT=y
|
CONFIG_XMON_DEFAULT=y
|
||||||
|
@@ -143,7 +143,7 @@ CONFIG_PPC_NATIVE=y
|
|||||||
CONFIG_U3_DART=y
|
CONFIG_U3_DART=y
|
||||||
# CONFIG_PPC_RTAS is not set
|
# CONFIG_PPC_RTAS is not set
|
||||||
# CONFIG_MMIO_NVRAM 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_MPC106 is not set
|
||||||
CONFIG_PPC_970_NAP=y
|
CONFIG_PPC_970_NAP=y
|
||||||
# CONFIG_PPC_INDIRECT_IO is not set
|
# CONFIG_PPC_INDIRECT_IO is not set
|
||||||
|
@@ -146,7 +146,7 @@ CONFIG_PPC_RTAS=y
|
|||||||
CONFIG_RTAS_PROC=y
|
CONFIG_RTAS_PROC=y
|
||||||
# CONFIG_RTAS_FLASH is not set
|
# CONFIG_RTAS_FLASH is not set
|
||||||
# CONFIG_MMIO_NVRAM 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_MPC106 is not set
|
||||||
CONFIG_PPC_970_NAP=y
|
CONFIG_PPC_970_NAP=y
|
||||||
# CONFIG_PPC_INDIRECT_IO is not set
|
# 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_PROC=y
|
||||||
CONFIG_RTAS_FLASH=m
|
CONFIG_RTAS_FLASH=m
|
||||||
CONFIG_MMIO_NVRAM=y
|
CONFIG_MMIO_NVRAM=y
|
||||||
CONFIG_MPIC_BROKEN_U3=y
|
CONFIG_MPIC_U3_HT_IRQS=y
|
||||||
CONFIG_IBMVIO=y
|
CONFIG_IBMVIO=y
|
||||||
# CONFIG_IBMEBUS is not set
|
# CONFIG_IBMEBUS is not set
|
||||||
# CONFIG_PPC_MPC106 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
|
obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o
|
||||||
procfs-$(CONFIG_PPC64) := proc_ppc64.o
|
procfs-$(CONFIG_PPC64) := proc_ppc64.o
|
||||||
obj-$(CONFIG_PROC_FS) += $(procfs-y)
|
obj-$(CONFIG_PROC_FS) += $(procfs-y)
|
||||||
rtaspci-$(CONFIG_PPC64) := rtas_pci.o
|
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
|
||||||
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y)
|
obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y)
|
||||||
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
|
||||||
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
|
||||||
obj-$(CONFIG_LPARCFG) += lparcfg.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))
|
if (user_mode(regs) && !access_ok(VERIFY_WRITE, p, size))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
for (i = 0; i < size / sizeof(long); ++i)
|
for (i = 0; i < size / sizeof(long); ++i)
|
||||||
if (__put_user(0, p+i))
|
if (__put_user_inatomic(0, p+i))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,8 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
|
|||||||
} else {
|
} else {
|
||||||
unsigned long pc = regs->nip ^ (swiz & 4);
|
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;
|
return -EFAULT;
|
||||||
if (swiz == 0 && (flags & SW))
|
if (swiz == 0 && (flags & SW))
|
||||||
instr = cpu_to_le32(instr);
|
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));
|
((nb0 + 3) / 4) * sizeof(unsigned long));
|
||||||
|
|
||||||
for (i = 0; i < nb; ++i, ++p)
|
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;
|
return -EFAULT;
|
||||||
if (nb0 > 0) {
|
if (nb0 > 0) {
|
||||||
rptr = ®s->gpr[0];
|
rptr = ®s->gpr[0];
|
||||||
addr += nb;
|
addr += nb;
|
||||||
for (i = 0; i < nb0; ++i, ++p)
|
for (i = 0; i < nb0; ++i, ++p)
|
||||||
if (__get_user(REG_BYTE(rptr, i ^ bswiz),
|
if (__get_user_inatomic(REG_BYTE(rptr,
|
||||||
SWIZ_PTR(p)))
|
i ^ bswiz),
|
||||||
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < nb; ++i, ++p)
|
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;
|
return -EFAULT;
|
||||||
if (nb0 > 0) {
|
if (nb0 > 0) {
|
||||||
rptr = ®s->gpr[0];
|
rptr = ®s->gpr[0];
|
||||||
addr += nb;
|
addr += nb;
|
||||||
for (i = 0; i < nb0; ++i, ++p)
|
for (i = 0; i < nb0; ++i, ++p)
|
||||||
if (__put_user(REG_BYTE(rptr, i ^ bswiz),
|
if (__put_user_inatomic(REG_BYTE(rptr,
|
||||||
SWIZ_PTR(p)))
|
i ^ bswiz),
|
||||||
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
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))
|
if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
|
||||||
pc ^= 4;
|
pc ^= 4;
|
||||||
if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
|
if (unlikely(__get_user_inatomic(instr,
|
||||||
|
(unsigned int __user *)pc)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
|
if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
|
||||||
instr = cpu_to_le32(instr);
|
instr = cpu_to_le32(instr);
|
||||||
@@ -474,16 +480,16 @@ int fix_alignment(struct pt_regs *regs)
|
|||||||
p = (unsigned long) addr;
|
p = (unsigned long) addr;
|
||||||
switch (nb) {
|
switch (nb) {
|
||||||
case 8:
|
case 8:
|
||||||
ret |= __get_user(data.v[0], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++));
|
||||||
ret |= __get_user(data.v[1], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++));
|
||||||
ret |= __get_user(data.v[2], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++));
|
||||||
ret |= __get_user(data.v[3], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++));
|
||||||
case 4:
|
case 4:
|
||||||
ret |= __get_user(data.v[4], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++));
|
||||||
ret |= __get_user(data.v[5], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++));
|
||||||
case 2:
|
case 2:
|
||||||
ret |= __get_user(data.v[6], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++));
|
||||||
ret |= __get_user(data.v[7], SWIZ_PTR(p++));
|
ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++));
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
@@ -551,16 +557,16 @@ int fix_alignment(struct pt_regs *regs)
|
|||||||
p = (unsigned long) addr;
|
p = (unsigned long) addr;
|
||||||
switch (nb) {
|
switch (nb) {
|
||||||
case 8:
|
case 8:
|
||||||
ret |= __put_user(data.v[0], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++));
|
||||||
ret |= __put_user(data.v[1], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++));
|
||||||
ret |= __put_user(data.v[2], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++));
|
||||||
ret |= __put_user(data.v[3], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++));
|
||||||
case 4:
|
case 4:
|
||||||
ret |= __put_user(data.v[4], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++));
|
||||||
ret |= __put_user(data.v[5], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++));
|
||||||
case 2:
|
case 2:
|
||||||
ret |= __put_user(data.v[6], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++));
|
||||||
ret |= __put_user(data.v[7], SWIZ_PTR(p++));
|
ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++));
|
||||||
}
|
}
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@@ -77,7 +77,6 @@ int main(void)
|
|||||||
DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
|
DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
|
||||||
#else /* CONFIG_PPC64 */
|
#else /* CONFIG_PPC64 */
|
||||||
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
|
DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
|
||||||
DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
|
|
||||||
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
|
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
|
||||||
DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
|
DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
|
||||||
DEFINE(PT_PTRACED, PT_PTRACED);
|
DEFINE(PT_PTRACED, PT_PTRACED);
|
||||||
@@ -140,6 +139,7 @@ int main(void)
|
|||||||
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
||||||
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
|
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
|
||||||
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
|
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
|
||||||
|
DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
|
||||||
|
|
||||||
DEFINE(SLBSHADOW_STACKVSID,
|
DEFINE(SLBSHADOW_STACKVSID,
|
||||||
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
|
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;
|
unsigned long address = 0;
|
||||||
const u32 *prop;
|
const u32 *prop;
|
||||||
|
|
||||||
prop = get_property(np, "linux,bootx-width", NULL);
|
prop = of_get_property(np, "linux,bootx-width", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
prop = get_property(np, "width", NULL);
|
prop = of_get_property(np, "width", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
width = *prop;
|
width = *prop;
|
||||||
prop = get_property(np, "linux,bootx-height", NULL);
|
prop = of_get_property(np, "linux,bootx-height", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
prop = get_property(np, "height", NULL);
|
prop = of_get_property(np, "height", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
height = *prop;
|
height = *prop;
|
||||||
prop = get_property(np, "linux,bootx-depth", NULL);
|
prop = of_get_property(np, "linux,bootx-depth", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
prop = get_property(np, "depth", NULL);
|
prop = of_get_property(np, "depth", NULL);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
depth = *prop;
|
depth = *prop;
|
||||||
pitch = width * ((depth + 7) / 8);
|
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)
|
if (prop == NULL)
|
||||||
prop = get_property(np, "linebytes", NULL);
|
prop = of_get_property(np, "linebytes", NULL);
|
||||||
if (prop && *prop != 0xffffffffu)
|
if (prop && *prop != 0xffffffffu)
|
||||||
pitch = *prop;
|
pitch = *prop;
|
||||||
if (pitch == 1)
|
if (pitch == 1)
|
||||||
pitch = 0x1000;
|
pitch = 0x1000;
|
||||||
prop = get_property(np, "address", NULL);
|
prop = of_get_property(np, "address", NULL);
|
||||||
if (prop)
|
if (prop)
|
||||||
address = *prop;
|
address = *prop;
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ int __init btext_find_display(int allow_nonstdout)
|
|||||||
struct device_node *np = NULL;
|
struct device_node *np = NULL;
|
||||||
int rc = -ENODEV;
|
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) {
|
if (name != NULL) {
|
||||||
np = of_find_node_by_path(name);
|
np = of_find_node_by_path(name);
|
||||||
if (np != NULL) {
|
if (np != NULL) {
|
||||||
@@ -236,7 +236,7 @@ int __init btext_find_display(int allow_nonstdout)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
|
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);
|
printk("trying %s ...\n", np->full_name);
|
||||||
rc = btext_initialize(np);
|
rc = btext_initialize(np);
|
||||||
printk("result: %d\n", rc);
|
printk("result: %d\n", rc);
|
||||||
|
@@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t)
|
|||||||
beqlr
|
beqlr
|
||||||
|
|
||||||
mfspr r0,SPRN_HID5
|
mfspr r0,SPRN_HID5
|
||||||
ori r0,r0,0x30
|
ori r0,r0,0x38
|
||||||
mtspr SPRN_HID5,r0
|
mtspr SPRN_HID5,r0
|
||||||
|
|
||||||
mfspr r0,SPRN_LPCR
|
mfspr r0,SPRN_LPCR
|
||||||
|
@@ -389,6 +389,8 @@ static struct cpu_spec cpu_specs[] = {
|
|||||||
.pmc_type = PPC_PMC_PA6T,
|
.pmc_type = PPC_PMC_PA6T,
|
||||||
.cpu_setup = __setup_cpu_pa6t,
|
.cpu_setup = __setup_cpu_pa6t,
|
||||||
.cpu_restore = __restore_cpu_pa6t,
|
.cpu_restore = __restore_cpu_pa6t,
|
||||||
|
.oprofile_cpu_type = "ppc64/pa6t",
|
||||||
|
.oprofile_type = PPC_OPROFILE_PA6T,
|
||||||
.platform = "pa6t",
|
.platform = "pa6t",
|
||||||
},
|
},
|
||||||
{ /* default match */
|
{ /* default match */
|
||||||
@@ -558,6 +560,18 @@ static struct cpu_spec cpu_specs[] = {
|
|||||||
.cpu_setup = __setup_cpu_750cx,
|
.cpu_setup = __setup_cpu_750cx,
|
||||||
.platform = "ppc750",
|
.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 */
|
{ /* 745/755 */
|
||||||
.pvr_mask = 0xfffff000,
|
.pvr_mask = 0xfffff000,
|
||||||
.pvr_value = 0x00083000,
|
.pvr_value = 0x00083000,
|
||||||
|
@@ -191,7 +191,6 @@ stack_ovf:
|
|||||||
0:
|
0:
|
||||||
|
|
||||||
_GLOBAL(DoSyscall)
|
_GLOBAL(DoSyscall)
|
||||||
stw r0,THREAD+LAST_SYSCALL(r2)
|
|
||||||
stw r3,ORIG_GPR3(r1)
|
stw r3,ORIG_GPR3(r1)
|
||||||
li r12,0
|
li r12,0
|
||||||
stw r12,RESULT(r1)
|
stw r12,RESULT(r1)
|
||||||
|
@@ -278,8 +278,12 @@ exception_marker:
|
|||||||
beq- 1f; \
|
beq- 1f; \
|
||||||
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
|
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
|
||||||
1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
|
1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
|
||||||
bge- cr1,bad_stack; /* abort if it is */ \
|
bge- cr1,2f; /* abort if it is */ \
|
||||||
std r9,_CCR(r1); /* save CR in stackframe */ \
|
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 r11,_NIP(r1); /* save SRR0 in stackframe */ \
|
||||||
std r12,_MSR(r1); /* save SRR1 in stackframe */ \
|
std r12,_MSR(r1); /* save SRR1 in stackframe */ \
|
||||||
std r10,0(r1); /* make stack chain pointer */ \
|
std r10,0(r1); /* make stack chain pointer */ \
|
||||||
@@ -940,6 +944,8 @@ bad_stack:
|
|||||||
SAVE_2GPRS(7,r1)
|
SAVE_2GPRS(7,r1)
|
||||||
SAVE_10GPRS(12,r1)
|
SAVE_10GPRS(12,r1)
|
||||||
SAVE_10GPRS(22,r1)
|
SAVE_10GPRS(22,r1)
|
||||||
|
lhz r12,PACA_TRAP_SAVE(r13)
|
||||||
|
std r12,_TRAP(r1)
|
||||||
addi r11,r1,INT_FRAME_SIZE
|
addi r11,r1,INT_FRAME_SIZE
|
||||||
std r11,0(r1)
|
std r11,0(r1)
|
||||||
li r12,0
|
li r12,0
|
||||||
@@ -1555,7 +1561,6 @@ _GLOBAL(generic_secondary_smp_init)
|
|||||||
|
|
||||||
/* turn on 64-bit mode */
|
/* turn on 64-bit mode */
|
||||||
bl .enable_64b_mode
|
bl .enable_64b_mode
|
||||||
isync
|
|
||||||
|
|
||||||
/* Set up a paca value for this processor. Since we have the
|
/* 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
|
* physical cpu id in r24, we need to search the pacas to find
|
||||||
@@ -1735,10 +1740,6 @@ _STATIC(__boot_from_prom)
|
|||||||
/* We never return */
|
/* We never return */
|
||||||
trap
|
trap
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point, r3 contains the physical address we are running at,
|
|
||||||
* returned by prom_init()
|
|
||||||
*/
|
|
||||||
_STATIC(__after_prom_start)
|
_STATIC(__after_prom_start)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1851,7 +1852,6 @@ __secondary_start_pmac_0:
|
|||||||
_GLOBAL(pmac_secondary_start)
|
_GLOBAL(pmac_secondary_start)
|
||||||
/* turn on 64-bit mode */
|
/* turn on 64-bit mode */
|
||||||
bl .enable_64b_mode
|
bl .enable_64b_mode
|
||||||
isync
|
|
||||||
|
|
||||||
/* Copy some CPU settings from CPU 0 */
|
/* Copy some CPU settings from CPU 0 */
|
||||||
bl .__restore_cpu_ppc970
|
bl .__restore_cpu_ppc970
|
||||||
|
@@ -2,36 +2,37 @@
|
|||||||
* IBM PowerPC IBM eBus Infrastructure Support.
|
* IBM PowerPC IBM eBus Infrastructure Support.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005 IBM Corporation
|
* Copyright (c) 2005 IBM Corporation
|
||||||
|
* Joachim Fenkes <fenkes@de.ibm.com>
|
||||||
* Heiko J Schick <schickhj@de.ibm.com>
|
* Heiko J Schick <schickhj@de.ibm.com>
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
|
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
|
||||||
* BSD.
|
* BSD.
|
||||||
*
|
*
|
||||||
* OpenIB BSD License
|
* OpenIB BSD License
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
* list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials
|
* and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* 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
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -43,19 +44,19 @@
|
|||||||
#include <asm/ibmebus.h>
|
#include <asm/ibmebus.h>
|
||||||
#include <asm/abs_addr.h>
|
#include <asm/abs_addr.h>
|
||||||
|
|
||||||
static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */
|
static struct device ibmebus_bus_device = { /* fake "parent" device */
|
||||||
.name = ibmebus_bus_device.ofdev.dev.bus_id,
|
.bus_id = "ibmebus",
|
||||||
.ofdev.dev.bus_id = "ibmebus",
|
|
||||||
.ofdev.dev.bus = &ibmebus_bus_type,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bus_type ibmebus_bus_type;
|
||||||
|
|
||||||
static void *ibmebus_alloc_coherent(struct device *dev,
|
static void *ibmebus_alloc_coherent(struct device *dev,
|
||||||
size_t size,
|
size_t size,
|
||||||
dma_addr_t *dma_handle,
|
dma_addr_t *dma_handle,
|
||||||
gfp_t flag)
|
gfp_t flag)
|
||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
|
|
||||||
mem = kmalloc(size, flag);
|
mem = kmalloc(size, flag);
|
||||||
*dma_handle = (dma_addr_t)mem;
|
*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,
|
static void ibmebus_free_coherent(struct device *dev,
|
||||||
size_t size, void *vaddr,
|
size_t size, void *vaddr,
|
||||||
dma_addr_t dma_handle)
|
dma_addr_t dma_handle)
|
||||||
{
|
{
|
||||||
kfree(vaddr);
|
kfree(vaddr);
|
||||||
@@ -79,7 +80,7 @@ static dma_addr_t ibmebus_map_single(struct device *dev,
|
|||||||
|
|
||||||
static void ibmebus_unmap_single(struct device *dev,
|
static void ibmebus_unmap_single(struct device *dev,
|
||||||
dma_addr_t dma_addr,
|
dma_addr_t dma_addr,
|
||||||
size_t size,
|
size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -90,13 +91,13 @@ static int ibmebus_map_sg(struct device *dev,
|
|||||||
int nents, enum dma_data_direction direction)
|
int nents, enum dma_data_direction direction)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < nents; 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].offset;
|
||||||
sg[i].dma_length = sg[i].length;
|
sg[i].dma_length = sg[i].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nents;
|
return nents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,15 +129,15 @@ static int ibmebus_bus_probe(struct device *dev)
|
|||||||
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
||||||
const struct of_device_id *id;
|
const struct of_device_id *id;
|
||||||
int error = -ENODEV;
|
int error = -ENODEV;
|
||||||
|
|
||||||
if (!ibmebusdrv->probe)
|
if (!ibmebusdrv->probe)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
|
id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
|
||||||
if (id) {
|
if (id) {
|
||||||
error = ibmebusdrv->probe(ibmebusdev, id);
|
error = ibmebusdrv->probe(ibmebusdev, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,11 +145,11 @@ static int ibmebus_bus_remove(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
|
struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
|
||||||
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
|
||||||
|
|
||||||
if (ibmebusdrv->remove) {
|
if (ibmebusdrv->remove) {
|
||||||
return ibmebusdrv->remove(ibmebusdev);
|
return ibmebusdrv->remove(ibmebusdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,21 +159,12 @@ static void __devinit ibmebus_dev_release(struct device *dev)
|
|||||||
kfree(to_ibmebus_dev(dev));
|
kfree(to_ibmebus_dev(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t ibmebusdev_show_name(struct device *dev,
|
static int __devinit ibmebus_register_device_common(
|
||||||
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(
|
|
||||||
struct ibmebus_dev *dev, const char *name)
|
struct ibmebus_dev *dev, const char *name)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
dev->name = name;
|
dev->ofdev.dev.parent = &ibmebus_bus_device;
|
||||||
dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev;
|
|
||||||
dev->ofdev.dev.bus = &ibmebus_bus_type;
|
dev->ofdev.dev.bus = &ibmebus_bus_type;
|
||||||
dev->ofdev.dev.release = ibmebus_dev_release;
|
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);
|
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
|
/* 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) {
|
if ((err = of_device_register(&dev->ofdev)) != 0) {
|
||||||
printk(KERN_ERR "%s: failed to register device (%d).\n",
|
printk(KERN_ERR "%s: failed to register device (%d).\n",
|
||||||
__FUNCTION__, err);
|
__FUNCTION__, err);
|
||||||
return NULL;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_create_file(&dev->ofdev.dev, &dev_attr_name);
|
return 0;
|
||||||
|
|
||||||
return dev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ibmebus_dev* __devinit ibmebus_register_device_node(
|
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;
|
const char *loc_code;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
loc_code = get_property(dn, "ibm,loc-code", NULL);
|
loc_code = of_get_property(dn, "ibm,loc-code", NULL);
|
||||||
if (!loc_code) {
|
if (!loc_code) {
|
||||||
printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
|
printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
|
||||||
__FUNCTION__, dn->name ? dn->name : "<unknown>");
|
__FUNCTION__, dn->name ? dn->name : "<unknown>");
|
||||||
return NULL;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(loc_code) == 0) {
|
if (strlen(loc_code) == 0) {
|
||||||
printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n",
|
printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return NULL;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
return NULL;
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->ofdev.node = of_node_get(dn);
|
dev->ofdev.node = of_node_get(dn);
|
||||||
|
|
||||||
length = strlen(loc_code);
|
length = strlen(loc_code);
|
||||||
memcpy(dev->ofdev.dev.bus_id, loc_code
|
memcpy(dev->ofdev.dev.bus_id, loc_code
|
||||||
+ (length - min(length, BUS_ID_SIZE - 1)),
|
+ (length - min(length, BUS_ID_SIZE - 1)),
|
||||||
min(length, BUS_ID_SIZE - 1));
|
min(length, BUS_ID_SIZE - 1));
|
||||||
|
|
||||||
/* Register with generic device framework. */
|
/* 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);
|
kfree(dev);
|
||||||
return NULL;
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
@@ -238,17 +228,16 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
|
|||||||
static void ibmebus_probe_of_nodes(char* name)
|
static void ibmebus_probe_of_nodes(char* name)
|
||||||
{
|
{
|
||||||
struct device_node *dn = NULL;
|
struct device_node *dn = NULL;
|
||||||
|
|
||||||
while ((dn = of_find_node_by_name(dn, name))) {
|
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);
|
of_node_put(dn);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
of_node_put(dn);
|
of_node_put(dn);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,17 +251,21 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt)
|
|||||||
return;
|
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 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ibmebus_unregister_device(struct device *dev)
|
static int ibmebus_unregister_device(struct device *dev)
|
||||||
{
|
{
|
||||||
device_remove_file(dev, &dev_attr_name);
|
|
||||||
of_device_unregister(to_of_device(dev));
|
of_device_unregister(to_of_device(dev));
|
||||||
|
|
||||||
return 0;
|
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)
|
static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
while (strlen(idt->name) > 0) {
|
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,
|
(void*)idt->name,
|
||||||
ibmebus_match_helper))) {
|
ibmebus_match_name))) {
|
||||||
ibmebus_unregister_device(dev);
|
ibmebus_unregister_device(dev);
|
||||||
}
|
}
|
||||||
idt++;
|
idt++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,30 +299,33 @@ int ibmebus_register_driver(struct ibmebus_driver *drv)
|
|||||||
if ((err = driver_register(&drv->driver) != 0))
|
if ((err = driver_register(&drv->driver) != 0))
|
||||||
return err;
|
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);
|
ibmebus_add_devices_by_id(drv->id_table);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ibmebus_register_driver);
|
EXPORT_SYMBOL(ibmebus_register_driver);
|
||||||
|
|
||||||
void ibmebus_unregister_driver(struct ibmebus_driver *drv)
|
void ibmebus_unregister_driver(struct ibmebus_driver *drv)
|
||||||
{
|
{
|
||||||
driver_unregister(&drv->driver);
|
driver_unregister(&drv->driver);
|
||||||
ibmebus_remove_devices_by_id(drv->id_table);
|
ibmebus_remove_devices_by_id(drv->id_table);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ibmebus_unregister_driver);
|
EXPORT_SYMBOL(ibmebus_unregister_driver);
|
||||||
|
|
||||||
int ibmebus_request_irq(struct ibmebus_dev *dev,
|
int ibmebus_request_irq(struct ibmebus_dev *dev,
|
||||||
u32 ist,
|
u32 ist,
|
||||||
irq_handler_t handler,
|
irq_handler_t handler,
|
||||||
unsigned long irq_flags, const char * devname,
|
unsigned long irq_flags, const char * devname,
|
||||||
void *dev_id)
|
void *dev_id)
|
||||||
{
|
{
|
||||||
unsigned int irq = irq_create_mapping(NULL, ist);
|
unsigned int irq = irq_create_mapping(NULL, ist);
|
||||||
|
|
||||||
if (irq == NO_IRQ)
|
if (irq == NO_IRQ)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return request_irq(irq, handler,
|
return request_irq(irq, handler,
|
||||||
irq_flags, devname, dev_id);
|
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)
|
void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
|
||||||
{
|
{
|
||||||
unsigned int irq = irq_find_mapping(NULL, ist);
|
unsigned int irq = irq_find_mapping(NULL, ist);
|
||||||
|
|
||||||
free_irq(irq, dev_id);
|
free_irq(irq, dev_id);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ibmebus_free_irq);
|
EXPORT_SYMBOL(ibmebus_free_irq);
|
||||||
|
|
||||||
static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
|
static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
{
|
{
|
||||||
const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
|
const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
|
||||||
struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
|
struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
|
||||||
const struct of_device_id *ids = ebus_drv->id_table;
|
const struct of_device_id *ids = ebus_drv->id_table;
|
||||||
const struct of_device_id *found_id;
|
const struct of_device_id *found_id;
|
||||||
|
|
||||||
if (!ids)
|
if (!ids)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
found_id = of_match_device(ids, &ebus_dev->ofdev);
|
found_id = of_match_device(ids, &ebus_dev->ofdev);
|
||||||
if (found_id)
|
if (found_id)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
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 = {
|
struct bus_type ibmebus_bus_type = {
|
||||||
.name = "ibmebus",
|
.name = "ibmebus",
|
||||||
.match = ibmebus_bus_match,
|
.match = ibmebus_bus_match,
|
||||||
|
.dev_attrs = ibmebus_dev_attrs,
|
||||||
|
.bus_attrs = ibmebus_bus_attrs
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(ibmebus_bus_type);
|
EXPORT_SYMBOL(ibmebus_bus_type);
|
||||||
|
|
||||||
static int __init ibmebus_bus_init(void)
|
static int __init ibmebus_bus_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
printk(KERN_INFO "IBM eBus Device Driver\n");
|
printk(KERN_INFO "IBM eBus Device Driver\n");
|
||||||
|
|
||||||
err = bus_register(&ibmebus_bus_type);
|
err = bus_register(&ibmebus_bus_type);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
|
printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = device_register(&ibmebus_bus_device.ofdev.dev);
|
err = device_register(&ibmebus_bus_device);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_WARNING "%s: device_register returned %i\n",
|
printk(KERN_WARNING "%s: device_register returned %i\n",
|
||||||
__FUNCTION__, err);
|
__FUNCTION__, err);
|
||||||
bus_unregister(&ibmebus_bus_type);
|
bus_unregister(&ibmebus_bus_type);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
__initcall(ibmebus_bus_init);
|
__initcall(ibmebus_bus_init);
|
||||||
|
@@ -47,6 +47,8 @@ static int novmerge = 0;
|
|||||||
static int novmerge = 1;
|
static int novmerge = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int protect4gb = 1;
|
||||||
|
|
||||||
static inline unsigned long iommu_num_pages(unsigned long vaddr,
|
static inline unsigned long iommu_num_pages(unsigned long vaddr,
|
||||||
unsigned long slen)
|
unsigned long slen)
|
||||||
{
|
{
|
||||||
@@ -58,6 +60,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr,
|
|||||||
return npages;
|
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)
|
static int __init setup_iommu(char *str)
|
||||||
{
|
{
|
||||||
if (!strcmp(str, "novmerge"))
|
if (!strcmp(str, "novmerge"))
|
||||||
@@ -67,6 +79,7 @@ static int __init setup_iommu(char *str)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__setup("protect4gb=", setup_protect4gb);
|
||||||
__setup("iommu=", setup_iommu);
|
__setup("iommu=", setup_iommu);
|
||||||
|
|
||||||
static unsigned long iommu_range_alloc(struct iommu_table *tbl,
|
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)
|
struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
|
||||||
{
|
{
|
||||||
unsigned long sz;
|
unsigned long sz;
|
||||||
|
unsigned long start_index, end_index;
|
||||||
|
unsigned long entries_per_4g;
|
||||||
|
unsigned long index;
|
||||||
static int welcomed = 0;
|
static int welcomed = 0;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
||||||
@@ -450,7 +466,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
|
|||||||
|
|
||||||
#ifdef CONFIG_CRASH_DUMP
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
if (ppc_md.tce_get) {
|
if (ppc_md.tce_get) {
|
||||||
unsigned long index, tceval;
|
unsigned long tceval;
|
||||||
unsigned long tcecount = 0;
|
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);
|
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
|
||||||
#endif
|
#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) {
|
if (!welcomed) {
|
||||||
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
|
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
|
||||||
novmerge ? "disabled" : "enabled");
|
novmerge ? "disabled" : "enabled");
|
||||||
|
@@ -394,7 +394,7 @@ EXPORT_SYMBOL(do_softirq);
|
|||||||
#ifdef CONFIG_PPC_MERGE
|
#ifdef CONFIG_PPC_MERGE
|
||||||
|
|
||||||
static LIST_HEAD(irq_hosts);
|
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 DEFINE_PER_CPU(unsigned int, irq_radix_reader);
|
||||||
static unsigned int irq_radix_writer;
|
static unsigned int irq_radix_writer;
|
||||||
struct irq_map_entry irq_map[NR_IRQS];
|
struct irq_map_entry irq_map[NR_IRQS];
|
||||||
|
@@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ret) {
|
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;
|
p->opcode = *p->addr;
|
||||||
flush_icache_range((unsigned long)p->ainsn.insn,
|
flush_icache_range((unsigned long)p->ainsn.insn,
|
||||||
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
|
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->ainsn.boostable = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ss_probe:
|
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);
|
prepare_singlestep(p, regs);
|
||||||
kcb->kprobe_status = KPROBE_HIT_SS;
|
kcb->kprobe_status = KPROBE_HIT_SS;
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -44,12 +44,12 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
|
|||||||
int index;
|
int index;
|
||||||
|
|
||||||
/* get clock freq. if present */
|
/* get clock freq. if present */
|
||||||
clk = get_property(np, "clock-frequency", NULL);
|
clk = of_get_property(np, "clock-frequency", NULL);
|
||||||
if (clk && *clk)
|
if (clk && *clk)
|
||||||
clock = *clk;
|
clock = *clk;
|
||||||
|
|
||||||
/* get default speed if present */
|
/* 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 we have a location index, then try to use it */
|
||||||
if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
|
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
|
/* We only support ports that have a clock frequency properly
|
||||||
* encoded in the device-tree.
|
* encoded in the device-tree.
|
||||||
*/
|
*/
|
||||||
if (get_property(np, "clock-frequency", NULL) == NULL)
|
if (of_get_property(np, "clock-frequency", NULL) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* if rtas uses this device, don't try to use it as well */
|
/* 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;
|
return -1;
|
||||||
|
|
||||||
/* Get the address */
|
/* 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);
|
DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
|
||||||
|
|
||||||
/* Get the ISA port number */
|
/* Get the ISA port number */
|
||||||
reg = get_property(np, "reg", NULL);
|
reg = of_get_property(np, "reg", NULL);
|
||||||
if (reg == NULL)
|
if (reg == NULL)
|
||||||
return -1;
|
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
|
/* Now look for an "ibm,aix-loc" property that gives us ordering
|
||||||
* if any...
|
* 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 we have a location index, then use it */
|
||||||
if (typep && *typep == 'S')
|
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
|
* compatible UARTs on PCI need all sort of quirks (port offsets
|
||||||
* etc...) that this code doesn't know about
|
* 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;
|
return -1;
|
||||||
|
|
||||||
/* Get the PCI address. Assume BAR 0 */
|
/* 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
|
* we get to their "reg" property
|
||||||
*/
|
*/
|
||||||
if (np != pci_dev) {
|
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))
|
if (reg && (*reg < 4))
|
||||||
index = lindex = *reg;
|
index = lindex = *reg;
|
||||||
}
|
}
|
||||||
@@ -296,7 +296,7 @@ void __init find_legacy_serial_ports(void)
|
|||||||
DBG(" -> find_legacy_serial_port()\n");
|
DBG(" -> find_legacy_serial_port()\n");
|
||||||
|
|
||||||
/* Now find out if one of these is out firmware console */
|
/* 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) {
|
if (path != NULL) {
|
||||||
stdout = of_find_node_by_path(path);
|
stdout = of_find_node_by_path(path);
|
||||||
if (stdout)
|
if (stdout)
|
||||||
@@ -529,7 +529,7 @@ static int __init check_legacy_serial_console(void)
|
|||||||
}
|
}
|
||||||
/* We are getting a weird phandle from OF ... */
|
/* We are getting a weird phandle from OF ... */
|
||||||
/* ... So use the full path instead */
|
/* ... 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) {
|
if (name == NULL) {
|
||||||
DBG(" no linux,stdout-path !\n");
|
DBG(" no linux,stdout-path !\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -541,12 +541,12 @@ static int __init check_legacy_serial_console(void)
|
|||||||
}
|
}
|
||||||
DBG("stdout is %s\n", prom_stdout->full_name);
|
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) {
|
if (!name) {
|
||||||
DBG(" stdout package has no name !\n");
|
DBG(" stdout package has no name !\n");
|
||||||
goto not_found;
|
goto not_found;
|
||||||
}
|
}
|
||||||
spd = get_property(prom_stdout, "current-speed", NULL);
|
spd = of_get_property(prom_stdout, "current-speed", NULL);
|
||||||
if (spd)
|
if (spd)
|
||||||
speed = *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.
|
* 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)
|
static void log_plpar_hcall_return(unsigned long rc, char *tag)
|
||||||
{
|
{
|
||||||
if (rc == 0) /* success, return */
|
switch(rc) {
|
||||||
|
case 0:
|
||||||
return;
|
return;
|
||||||
/* check for null tag ? */
|
case H_HARDWARE:
|
||||||
if (rc == H_HARDWARE)
|
printk(KERN_INFO "plpar-hcall (%s) "
|
||||||
printk(KERN_INFO
|
"Hardware fault\n", tag);
|
||||||
"plpar-hcall (%s) failed with hardware fault\n", tag);
|
return;
|
||||||
else if (rc == H_FUNCTION)
|
case H_FUNCTION:
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO "plpar-hcall (%s) "
|
||||||
"plpar-hcall (%s) failed; function not allowed\n", tag);
|
"Function not allowed\n", tag);
|
||||||
else if (rc == H_AUTHORITY)
|
return;
|
||||||
printk(KERN_INFO
|
case H_AUTHORITY:
|
||||||
"plpar-hcall (%s) failed; not authorized to this"
|
printk(KERN_INFO "plpar-hcall (%s) "
|
||||||
" function\n", tag);
|
"Not authorized to this function\n", tag);
|
||||||
else if (rc == H_PARAMETER)
|
return;
|
||||||
printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
|
case H_PARAMETER:
|
||||||
tag);
|
printk(KERN_INFO "plpar-hcall (%s) "
|
||||||
else
|
"Bad parameter(s)\n",tag);
|
||||||
printk(KERN_INFO
|
return;
|
||||||
"plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",
|
default:
|
||||||
tag, rc);
|
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;
|
struct device_node *rtas_node;
|
||||||
const int *lrdrp = NULL;
|
const int *lrdrp = NULL;
|
||||||
|
|
||||||
rtas_node = find_path_device("/rtas");
|
rtas_node = of_find_node_by_path("/rtas");
|
||||||
if (rtas_node)
|
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) {
|
if (lrdrp == NULL) {
|
||||||
partition_potential_processors = vdso_data->processorCount;
|
partition_potential_processors = vdso_data->processorCount;
|
||||||
} else {
|
} else {
|
||||||
partition_potential_processors = *(lrdrp + 4);
|
partition_potential_processors = *(lrdrp + 4);
|
||||||
}
|
}
|
||||||
|
of_node_put(rtas_node);
|
||||||
|
|
||||||
partition_active_processors = lparcfg_count_active_processors();
|
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);
|
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
|
||||||
|
|
||||||
rootdn = find_path_device("/");
|
rootdn = of_find_node_by_path("/");
|
||||||
if (rootdn) {
|
if (rootdn) {
|
||||||
tmp = get_property(rootdn, "model", NULL);
|
tmp = of_get_property(rootdn, "model", NULL);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
model = tmp;
|
model = tmp;
|
||||||
/* Skip "IBM," - see platforms/iseries/dt.c */
|
/* Skip "IBM," - see platforms/iseries/dt.c */
|
||||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||||
model += 4;
|
model += 4;
|
||||||
}
|
}
|
||||||
tmp = get_property(rootdn, "system-id", NULL);
|
tmp = of_get_property(rootdn, "system-id", NULL);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
system_id = tmp;
|
system_id = tmp;
|
||||||
/* Skip "IBM," - see platforms/iseries/dt.c */
|
/* Skip "IBM," - see platforms/iseries/dt.c */
|
||||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||||
system_id += 4;
|
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)
|
if (lp_index_ptr)
|
||||||
lp_index = *lp_index_ptr;
|
lp_index = *lp_index_ptr;
|
||||||
|
of_node_put(rootdn);
|
||||||
}
|
}
|
||||||
seq_printf(m, "serial_number=%s\n", system_id);
|
seq_printf(m, "serial_number=%s\n", system_id);
|
||||||
seq_printf(m, "system_type=%s\n", model);
|
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 */
|
/* We also should not overwrite the tce tables */
|
||||||
for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
|
for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
|
||||||
node = of_find_node_by_type(node, "pci")) {
|
node = of_find_node_by_type(node, "pci")) {
|
||||||
basep = get_property(node, "linux,tce-base", NULL);
|
basep = of_get_property(node, "linux,tce-base", NULL);
|
||||||
sizep = get_property(node, "linux,tce-size", NULL);
|
sizep = of_get_property(node, "linux,tce-size", NULL);
|
||||||
if (basep == NULL || sizep == NULL)
|
if (basep == NULL || sizep == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -294,19 +294,19 @@ static unsigned long htab_base, kernel_end;
|
|||||||
static struct property htab_base_prop = {
|
static struct property htab_base_prop = {
|
||||||
.name = "linux,htab-base",
|
.name = "linux,htab-base",
|
||||||
.length = sizeof(unsigned long),
|
.length = sizeof(unsigned long),
|
||||||
.value = (unsigned char *)&htab_base,
|
.value = &htab_base,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct property htab_size_prop = {
|
static struct property htab_size_prop = {
|
||||||
.name = "linux,htab-size",
|
.name = "linux,htab-size",
|
||||||
.length = sizeof(unsigned long),
|
.length = sizeof(unsigned long),
|
||||||
.value = (unsigned char *)&htab_size_bytes,
|
.value = &htab_size_bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct property kernel_end_prop = {
|
static struct property kernel_end_prop = {
|
||||||
.name = "linux,kernel-end",
|
.name = "linux,kernel-end",
|
||||||
.length = sizeof(unsigned long),
|
.length = sizeof(unsigned long),
|
||||||
.value = (unsigned char *)&kernel_end,
|
.value = &kernel_end,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init export_htab_values(void)
|
static void __init export_htab_values(void)
|
||||||
@@ -335,7 +335,7 @@ static void __init export_htab_values(void)
|
|||||||
static struct property crashk_base_prop = {
|
static struct property crashk_base_prop = {
|
||||||
.name = "linux,crashkernel-base",
|
.name = "linux,crashkernel-base",
|
||||||
.length = sizeof(unsigned long),
|
.length = sizeof(unsigned long),
|
||||||
.value = (unsigned char *)&crashk_res.start,
|
.value = &crashk_res.start,
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long crashk_size;
|
static unsigned long crashk_size;
|
||||||
@@ -343,7 +343,7 @@ static unsigned long crashk_size;
|
|||||||
static struct property crashk_size_prop = {
|
static struct property crashk_size_prop = {
|
||||||
.name = "linux,crashkernel-size",
|
.name = "linux,crashkernel-size",
|
||||||
.length = sizeof(unsigned long),
|
.length = sizeof(unsigned long),
|
||||||
.value = (unsigned char *)&crashk_size,
|
.value = &crashk_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init export_crashk_values(void)
|
static void __init export_crashk_values(void)
|
||||||
|
@@ -734,10 +734,6 @@ _GLOBAL(abs)
|
|||||||
sub r3,r3,r4
|
sub r3,r3,r4
|
||||||
blr
|
blr
|
||||||
|
|
||||||
_GLOBAL(_get_SP)
|
|
||||||
mr r3,r1 /* Close enough */
|
|
||||||
blr
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a kernel thread
|
* Create a kernel thread
|
||||||
* kernel_thread(fn, arg, flags)
|
* 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_node);
|
||||||
EXPORT_SYMBOL(of_match_device);
|
EXPORT_SYMBOL(of_match_device);
|
||||||
EXPORT_SYMBOL(of_device_register);
|
EXPORT_SYMBOL(of_device_register);
|
||||||
@@ -127,3 +238,4 @@ EXPORT_SYMBOL(of_device_unregister);
|
|||||||
EXPORT_SYMBOL(of_dev_get);
|
EXPORT_SYMBOL(of_dev_get);
|
||||||
EXPORT_SYMBOL(of_dev_put);
|
EXPORT_SYMBOL(of_dev_put);
|
||||||
EXPORT_SYMBOL(of_release_dev);
|
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 = {
|
struct bus_type of_platform_bus_type = {
|
||||||
.name = "of_platform",
|
.name = "of_platform",
|
||||||
.match = of_platform_bus_match,
|
.match = of_platform_bus_match,
|
||||||
|
.uevent = of_device_uevent,
|
||||||
.probe = of_platform_device_probe,
|
.probe = of_platform_device_probe,
|
||||||
.remove = of_platform_device_remove,
|
.remove = of_platform_device_remove,
|
||||||
.suspend = of_platform_device_suspend,
|
.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.
|
* and 'D' for MMIO DCRs.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_PPC_DCR
|
#ifdef CONFIG_PPC_DCR
|
||||||
reg = get_property(node, "dcr-reg", NULL);
|
reg = of_get_property(node, "dcr-reg", NULL);
|
||||||
if (reg) {
|
if (reg) {
|
||||||
#ifdef CONFIG_PPC_DCR_NATIVE
|
#ifdef CONFIG_PPC_DCR_NATIVE
|
||||||
snprintf(name, BUS_ID_SIZE, "d%x.%s",
|
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
|
* For MMIO, get the physical address
|
||||||
*/
|
*/
|
||||||
reg = get_property(node, "reg", NULL);
|
reg = of_get_property(node, "reg", NULL);
|
||||||
if (reg) {
|
if (reg) {
|
||||||
addr = of_translate_address(node, reg);
|
addr = of_translate_address(node, reg);
|
||||||
if (addr != OF_BAD_ADDR) {
|
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)
|
if (pci_bus >= pci_bus_count)
|
||||||
return;
|
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)) {
|
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||||
printk(KERN_WARNING "Can't get bus-range for %s, "
|
printk(KERN_WARNING "Can't get bus-range for %s, "
|
||||||
"assuming it starts at 0\n", node->full_name);
|
"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;
|
struct pci_dev* dev;
|
||||||
const unsigned int *class_code, *reg;
|
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 &&
|
if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
|
||||||
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
|
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
|
||||||
continue;
|
continue;
|
||||||
reg = get_property(node, "reg", NULL);
|
reg = of_get_property(node, "reg", NULL);
|
||||||
if (!reg)
|
if (!reg)
|
||||||
continue;
|
continue;
|
||||||
dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
|
dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
|
||||||
if (!dev || !dev->subordinate)
|
if (!dev || !dev->subordinate) {
|
||||||
|
pci_dev_put(dev);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
make_one_node_map(node, dev->subordinate->number);
|
make_one_node_map(node, dev->subordinate->number);
|
||||||
|
pci_dev_put(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,6 +672,7 @@ pcibios_make_OF_bus_map(void)
|
|||||||
int i;
|
int i;
|
||||||
struct pci_controller* hose;
|
struct pci_controller* hose;
|
||||||
struct property *map_prop;
|
struct property *map_prop;
|
||||||
|
struct device_node *dn;
|
||||||
|
|
||||||
pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
|
pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
|
||||||
if (!pci_to_OF_bus_map) {
|
if (!pci_to_OF_bus_map) {
|
||||||
@@ -690,12 +694,13 @@ pcibios_make_OF_bus_map(void)
|
|||||||
continue;
|
continue;
|
||||||
make_one_node_map(node, hose->first_busno);
|
make_one_node_map(node, hose->first_busno);
|
||||||
}
|
}
|
||||||
map_prop = of_find_property(find_path_device("/"),
|
dn = of_find_node_by_path("/");
|
||||||
"pci-OF-bus-map", NULL);
|
map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
|
||||||
if (map_prop) {
|
if (map_prop) {
|
||||||
BUG_ON(pci_bus_count > map_prop->length);
|
BUG_ON(pci_bus_count > map_prop->length);
|
||||||
memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
|
memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
|
||||||
}
|
}
|
||||||
|
of_node_put(dn);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printk("PCI->OF bus map:\n");
|
printk("PCI->OF bus map:\n");
|
||||||
for (i=0; i<pci_bus_count; i++) {
|
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,
|
* a fake root for all functions of a multi-function device,
|
||||||
* we go down them as well.
|
* 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 &&
|
if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
|
||||||
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
|
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
|
||||||
strcmp(node->name, "multifunc-device"))
|
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;
|
unsigned int psize;
|
||||||
|
|
||||||
while ((np = of_get_next_child(parent, np)) != NULL) {
|
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)
|
if (reg == NULL || psize < 4)
|
||||||
continue;
|
continue;
|
||||||
if (((reg[0] >> 8) & 0xff) == devfn)
|
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,
|
if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
|
||||||
find_OF_pci_device_filter, (void *)node))
|
find_OF_pci_device_filter, (void *)node))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
reg = get_property(node, "reg", NULL);
|
reg = of_get_property(node, "reg", NULL);
|
||||||
if (!reg)
|
if (!reg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
*bus = (reg[0] >> 16) & 0xff;
|
*bus = (reg[0] >> 16) & 0xff;
|
||||||
@@ -895,14 +900,14 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||||||
int rlen = 0, orig_rlen;
|
int rlen = 0, orig_rlen;
|
||||||
int memno = 0;
|
int memno = 0;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int np, na = prom_n_addr_cells(dev);
|
int np, na = of_n_addr_cells(dev);
|
||||||
np = na + 5;
|
np = na + 5;
|
||||||
|
|
||||||
/* First we try to merge ranges to fix a problem with some pmacs
|
/* First we try to merge ranges to fix a problem with some pmacs
|
||||||
* that can have more than 3 ranges, fortunately using contiguous
|
* that can have more than 3 ranges, fortunately using contiguous
|
||||||
* addresses -- BenH
|
* addresses -- BenH
|
||||||
*/
|
*/
|
||||||
dt_ranges = get_property(dev, "ranges", &rlen);
|
dt_ranges = of_get_property(dev, "ranges", &rlen);
|
||||||
if (!dt_ranges)
|
if (!dt_ranges)
|
||||||
return;
|
return;
|
||||||
/* Sanity check, though hopefully that never happens */
|
/* Sanity check, though hopefully that never happens */
|
||||||
@@ -1006,14 +1011,19 @@ void __init
|
|||||||
pci_create_OF_bus_map(void)
|
pci_create_OF_bus_map(void)
|
||||||
{
|
{
|
||||||
struct property* of_prop;
|
struct property* of_prop;
|
||||||
|
struct device_node *dn;
|
||||||
|
|
||||||
of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
|
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);
|
memset(of_prop, -1, sizeof(struct property) + 256);
|
||||||
of_prop->name = "pci-OF-bus-map";
|
of_prop->name = "pci-OF-bus-map";
|
||||||
of_prop->length = 256;
|
of_prop->length = 256;
|
||||||
of_prop->value = (unsigned char *)&of_prop[1];
|
of_prop->value = &of_prop[1];
|
||||||
prom_add_property(find_path_device("/"), of_prop);
|
prom_add_property(dn, of_prop);
|
||||||
|
of_node_put(dn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -61,8 +61,7 @@ void iSeries_pcibios_init(void);
|
|||||||
|
|
||||||
LIST_HEAD(hose_list);
|
LIST_HEAD(hose_list);
|
||||||
|
|
||||||
struct dma_mapping_ops *pci_dma_ops;
|
static struct dma_mapping_ops *pci_dma_ops;
|
||||||
EXPORT_SYMBOL(pci_dma_ops);
|
|
||||||
|
|
||||||
int global_phb_number; /* Global phb counter */
|
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;
|
struct pci_dev *ppc64_isabridge_dev = NULL;
|
||||||
EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
|
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)
|
static void fixup_broken_pcnet32(struct pci_dev* dev)
|
||||||
{
|
{
|
||||||
if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
|
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;
|
const u32 *prop;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
prop = get_property(np, name, &len);
|
prop = of_get_property(np, name, &len);
|
||||||
if (prop && len >= 4)
|
if (prop && len >= 4)
|
||||||
return *prop;
|
return *prop;
|
||||||
return def;
|
return def;
|
||||||
@@ -291,7 +301,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
|
|||||||
u32 i;
|
u32 i;
|
||||||
int proplen;
|
int proplen;
|
||||||
|
|
||||||
addrs = get_property(node, "assigned-addresses", &proplen);
|
addrs = of_get_property(node, "assigned-addresses", &proplen);
|
||||||
if (!addrs)
|
if (!addrs)
|
||||||
return;
|
return;
|
||||||
DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
|
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);
|
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
type = get_property(node, "device_type", NULL);
|
type = of_get_property(node, "device_type", NULL);
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
type = "";
|
type = "";
|
||||||
|
|
||||||
@@ -397,7 +407,7 @@ void __devinit of_scan_bus(struct device_node *node,
|
|||||||
|
|
||||||
while ((child = of_get_next_child(node, child)) != NULL) {
|
while ((child = of_get_next_child(node, child)) != NULL) {
|
||||||
DBG(" * %s\n", child->full_name);
|
DBG(" * %s\n", child->full_name);
|
||||||
reg = get_property(child, "reg", ®len);
|
reg = of_get_property(child, "reg", ®len);
|
||||||
if (reg == NULL || reglen < 20)
|
if (reg == NULL || reglen < 20)
|
||||||
continue;
|
continue;
|
||||||
devfn = (reg[0] >> 8) & 0xff;
|
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);
|
DBG("of_scan_pci_bridge(%s)\n", node->full_name);
|
||||||
|
|
||||||
/* parse bus-range property */
|
/* parse bus-range property */
|
||||||
busrange = get_property(node, "bus-range", &len);
|
busrange = of_get_property(node, "bus-range", &len);
|
||||||
if (busrange == NULL || len != 8) {
|
if (busrange == NULL || len != 8) {
|
||||||
printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
|
printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
|
||||||
node->full_name);
|
node->full_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ranges = get_property(node, "ranges", &len);
|
ranges = of_get_property(node, "ranges", &len);
|
||||||
if (ranges == NULL) {
|
if (ranges == NULL) {
|
||||||
printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
|
printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
|
||||||
node->full_name);
|
node->full_name);
|
||||||
@@ -900,7 +910,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
|
|||||||
unsigned int size;
|
unsigned int size;
|
||||||
int rlen = 0;
|
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))) {
|
if (range == NULL || (rlen < sizeof(struct isa_range))) {
|
||||||
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
|
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
|
||||||
"mapping 64k\n");
|
"mapping 64k\n");
|
||||||
@@ -947,7 +957,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||||||
int rlen = 0;
|
int rlen = 0;
|
||||||
int memno = 0;
|
int memno = 0;
|
||||||
struct resource *res;
|
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;
|
unsigned long pci_addr, cpu_phys_addr;
|
||||||
|
|
||||||
np = na + 5;
|
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)
|
* (size depending on dev->n_addr_cells)
|
||||||
* cells 4+5 or 5+6: the size of the range
|
* 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)
|
if (ranges == NULL)
|
||||||
return;
|
return;
|
||||||
hose->io_base_phys = 0;
|
hose->io_base_phys = 0;
|
||||||
|
@@ -40,7 +40,8 @@
|
|||||||
static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
|
static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
|
||||||
{
|
{
|
||||||
struct pci_controller *phb = 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;
|
const u32 *regs;
|
||||||
struct pci_dn *pdn;
|
struct pci_dn *pdn;
|
||||||
|
|
||||||
@@ -54,14 +55,14 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
|
|||||||
dn->data = pdn;
|
dn->data = pdn;
|
||||||
pdn->node = dn;
|
pdn->node = dn;
|
||||||
pdn->phb = phb;
|
pdn->phb = phb;
|
||||||
regs = get_property(dn, "reg", NULL);
|
regs = of_get_property(dn, "reg", NULL);
|
||||||
if (regs) {
|
if (regs) {
|
||||||
/* First register entry is addr (00BBSS00) */
|
/* First register entry is addr (00BBSS00) */
|
||||||
pdn->busno = (regs[0] >> 16) & 0xff;
|
pdn->busno = (regs[0] >> 16) & 0xff;
|
||||||
pdn->devfn = (regs[0] >> 8) & 0xff;
|
pdn->devfn = (regs[0] >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
|
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)
|
if (busp)
|
||||||
pdn->bussubno = *busp;
|
pdn->bussubno = *busp;
|
||||||
}
|
}
|
||||||
@@ -100,7 +101,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
|
|||||||
u32 class;
|
u32 class;
|
||||||
|
|
||||||
nextdn = NULL;
|
nextdn = NULL;
|
||||||
classp = get_property(dn, "class-code", NULL);
|
classp = of_get_property(dn, "class-code", NULL);
|
||||||
class = classp ? *classp : 0;
|
class = classp ? *classp : 0;
|
||||||
|
|
||||||
if (pre && ((ret = pre(dn, data)) != NULL))
|
if (pre && ((ret = pre(dn, data)) != NULL))
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/ide.h>
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/checksum.h>
|
#include <asm/checksum.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
|
@@ -305,9 +305,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|||||||
set_dabr(new->thread.dabr);
|
set_dabr(new->thread.dabr);
|
||||||
__get_cpu_var(current_dabr) = new->thread.dabr;
|
__get_cpu_var(current_dabr) = new->thread.dabr;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
flush_tlb_pending();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
new_thread = &new->thread;
|
new_thread = &new->thread;
|
||||||
old_thread = ¤t->thread;
|
old_thread = ¤t->thread;
|
||||||
@@ -402,11 +400,11 @@ static void printbits(unsigned long val, struct regbit *bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
#define REG "%016lX"
|
#define REG "%016lx"
|
||||||
#define REGS_PER_LINE 4
|
#define REGS_PER_LINE 4
|
||||||
#define LAST_VOLATILE 13
|
#define LAST_VOLATILE 13
|
||||||
#else
|
#else
|
||||||
#define REG "%08lX"
|
#define REG "%08lx"
|
||||||
#define REGS_PER_LINE 8
|
#define REGS_PER_LINE 8
|
||||||
#define LAST_VOLATILE 12
|
#define LAST_VOLATILE 12
|
||||||
#endif
|
#endif
|
||||||
@@ -421,7 +419,7 @@ void show_regs(struct pt_regs * regs)
|
|||||||
regs, regs->trap, print_tainted(), init_utsname()->release);
|
regs, regs->trap, print_tainted(), init_utsname()->release);
|
||||||
printk("MSR: "REG" ", regs->msr);
|
printk("MSR: "REG" ", regs->msr);
|
||||||
printbits(regs->msr, msr_bits);
|
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);
|
trap = TRAP(regs);
|
||||||
if (trap == 0x300 || trap == 0x600)
|
if (trap == 0x300 || trap == 0x600)
|
||||||
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
|
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);
|
kregs->nip = *((unsigned long *)ret_from_fork);
|
||||||
#else
|
#else
|
||||||
kregs->nip = (unsigned long)ret_from_fork;
|
kregs->nip = (unsigned long)ret_from_fork;
|
||||||
p->thread.last_syscall = -1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -823,6 +820,35 @@ out:
|
|||||||
return error;
|
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,
|
int validate_sp(unsigned long sp, struct task_struct *p,
|
||||||
unsigned long nbytes)
|
unsigned long nbytes)
|
||||||
{
|
{
|
||||||
@@ -832,19 +858,7 @@ int validate_sp(unsigned long sp, struct task_struct *p,
|
|||||||
&& sp <= stack_page + THREAD_SIZE - nbytes)
|
&& sp <= stack_page + THREAD_SIZE - nbytes)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef CONFIG_IRQSTACKS
|
return valid_irq_stack(sp, p, nbytes);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
|
@@ -390,18 +390,19 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
|
|||||||
if (allnextpp) {
|
if (allnextpp) {
|
||||||
pp->name = "name";
|
pp->name = "name";
|
||||||
pp->length = sz;
|
pp->length = sz;
|
||||||
pp->value = (unsigned char *)(pp + 1);
|
pp->value = pp + 1;
|
||||||
*prev_pp = pp;
|
*prev_pp = pp;
|
||||||
prev_pp = &pp->next;
|
prev_pp = &pp->next;
|
||||||
memcpy(pp->value, ps, sz - 1);
|
memcpy(pp->value, ps, sz - 1);
|
||||||
((char *)pp->value)[sz - 1] = 0;
|
((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) {
|
if (allnextpp) {
|
||||||
*prev_pp = NULL;
|
*prev_pp = NULL;
|
||||||
np->name = get_property(np, "name", NULL);
|
np->name = of_get_property(np, "name", NULL);
|
||||||
np->type = get_property(np, "device_type", NULL);
|
np->type = of_get_property(np, "device_type", NULL);
|
||||||
|
|
||||||
if (!np->name)
|
if (!np->name)
|
||||||
np->name = "<NULL>";
|
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)
|
const char *uname, int depth, void *data)
|
||||||
{
|
{
|
||||||
unsigned long *lprop;
|
unsigned long *lprop;
|
||||||
|
u32 *prop;
|
||||||
unsigned long l;
|
unsigned long l;
|
||||||
char *p;
|
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;
|
crashk_res.end = crashk_res.start + *lprop - 1;
|
||||||
#endif
|
#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 */
|
/* Retreive command line */
|
||||||
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||||
if (p != NULL && l > 0)
|
if (p != NULL && l > 0)
|
||||||
@@ -926,6 +944,12 @@ static void __init early_reserve_mem(void)
|
|||||||
self_size = initial_boot_params->totalsize;
|
self_size = initial_boot_params->totalsize;
|
||||||
lmb_reserve(self_base, self_size);
|
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
|
#ifdef CONFIG_PPC32
|
||||||
/*
|
/*
|
||||||
* Handle the case where we might be booting from an old kexec
|
* 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++);
|
size = *(reserve_map++);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
break;
|
break;
|
||||||
/* skip if the reservation is for the blob */
|
|
||||||
if (base == self_base && size == self_size)
|
|
||||||
continue;
|
|
||||||
DBG("reserving: %llx -> %llx\n", base, size);
|
DBG("reserving: %llx -> %llx\n", base, size);
|
||||||
lmb_reserve(base, size);
|
lmb_reserve(base, size);
|
||||||
}
|
}
|
||||||
@@ -1021,102 +1042,46 @@ void __init early_init_devtree(void *params)
|
|||||||
|
|
||||||
#undef printk
|
#undef printk
|
||||||
|
|
||||||
int
|
int of_n_addr_cells(struct device_node* np)
|
||||||
prom_n_addr_cells(struct device_node* np)
|
|
||||||
{
|
{
|
||||||
const int *ip;
|
const int *ip;
|
||||||
do {
|
do {
|
||||||
if (np->parent)
|
if (np->parent)
|
||||||
np = np->parent;
|
np = np->parent;
|
||||||
ip = get_property(np, "#address-cells", NULL);
|
ip = of_get_property(np, "#address-cells", NULL);
|
||||||
if (ip != NULL)
|
if (ip != NULL)
|
||||||
return *ip;
|
return *ip;
|
||||||
} while (np->parent);
|
} while (np->parent);
|
||||||
/* No #address-cells property for the root node, default to 1 */
|
/* No #address-cells property for the root node, default to 1 */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(prom_n_addr_cells);
|
EXPORT_SYMBOL(of_n_addr_cells);
|
||||||
|
|
||||||
int
|
int of_n_size_cells(struct device_node* np)
|
||||||
prom_n_size_cells(struct device_node* np)
|
|
||||||
{
|
{
|
||||||
const int* ip;
|
const int* ip;
|
||||||
do {
|
do {
|
||||||
if (np->parent)
|
if (np->parent)
|
||||||
np = np->parent;
|
np = np->parent;
|
||||||
ip = get_property(np, "#size-cells", NULL);
|
ip = of_get_property(np, "#size-cells", NULL);
|
||||||
if (ip != NULL)
|
if (ip != NULL)
|
||||||
return *ip;
|
return *ip;
|
||||||
} while (np->parent);
|
} while (np->parent);
|
||||||
/* No #size-cells property for the root node, default to 1 */
|
/* No #size-cells property for the root node, default to 1 */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(prom_n_size_cells);
|
EXPORT_SYMBOL(of_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);
|
|
||||||
|
|
||||||
/** Checks if the given "compat" string matches one of the strings in
|
/** Checks if the given "compat" string matches one of the strings in
|
||||||
* the device's "compatible" property
|
* 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;
|
const char* cp;
|
||||||
int cplen, l;
|
int cplen, l;
|
||||||
|
|
||||||
cp = get_property(device, "compatible", &cplen);
|
cp = of_get_property(device, "compatible", &cplen);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
while (cplen > 0) {
|
while (cplen > 0) {
|
||||||
@@ -1129,7 +1094,7 @@ int device_is_compatible(const struct device_node *device, const char *compat)
|
|||||||
|
|
||||||
return 0;
|
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("/");
|
root = of_find_node_by_path("/");
|
||||||
if (root) {
|
if (root) {
|
||||||
rc = device_is_compatible(root, compat);
|
rc = of_device_is_compatible(root, compat);
|
||||||
of_node_put(root);
|
of_node_put(root);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(machine_is_compatible);
|
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
|
* 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
|
if (type != NULL
|
||||||
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
|
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
|
||||||
continue;
|
continue;
|
||||||
if (device_is_compatible(np, compatible) && of_node_get(np))
|
if (of_device_is_compatible(np, compatible) && of_node_get(np))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
of_node_put(from);
|
of_node_put(from);
|
||||||
@@ -1527,8 +1454,8 @@ static int of_finish_dynamic_node(struct device_node *node)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
const phandle *ibm_phandle;
|
const phandle *ibm_phandle;
|
||||||
|
|
||||||
node->name = get_property(node, "name", NULL);
|
node->name = of_get_property(node, "name", NULL);
|
||||||
node->type = get_property(node, "device_type", NULL);
|
node->type = of_get_property(node, "device_type", NULL);
|
||||||
|
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
@@ -1542,7 +1469,7 @@ static int of_finish_dynamic_node(struct device_node *node)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* fix up new node's linux_phandle field */
|
/* 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;
|
node->linux_phandle = *ibm_phandle;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -1605,13 +1532,13 @@ EXPORT_SYMBOL(of_find_property);
|
|||||||
* Find a property with a given name for a given node
|
* Find a property with a given name for a given node
|
||||||
* and return the value.
|
* 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)
|
int *lenp)
|
||||||
{
|
{
|
||||||
struct property *pp = of_find_property(np,name,lenp);
|
struct property *pp = of_find_property(np,name,lenp);
|
||||||
return pp ? pp->value : NULL;
|
return pp ? pp->value : NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(get_property);
|
EXPORT_SYMBOL(of_get_property);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a property to a node
|
* 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
|
/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
|
||||||
* fallback to "reg" property and assume no threads
|
* 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);
|
&plen);
|
||||||
if (intserv == NULL) {
|
if (intserv == NULL) {
|
||||||
const u32 *reg = get_property(np, "reg", NULL);
|
const u32 *reg = of_get_property(np, "reg", NULL);
|
||||||
if (reg == NULL)
|
if (reg == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (*reg == hardid) {
|
if (*reg == hardid) {
|
||||||
|
@@ -2035,39 +2035,50 @@ static void __init fixup_device_tree_maple(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_CHRP
|
#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)
|
static void __init fixup_device_tree_chrp(void)
|
||||||
{
|
{
|
||||||
phandle isa;
|
phandle ph;
|
||||||
u32 isa_ranges[6];
|
u32 prop[6];
|
||||||
u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
|
u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
|
||||||
char *name;
|
char *name;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
name = "/pci@80000000/isa@c";
|
name = "/pci@80000000/isa@c";
|
||||||
isa = call_prom("finddevice", 1, 1, ADDR(name));
|
ph = call_prom("finddevice", 1, 1, ADDR(name));
|
||||||
if (!PHANDLE_VALID(isa)) {
|
if (!PHANDLE_VALID(ph)) {
|
||||||
name = "/pci@ff500000/isa@6";
|
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 */
|
rloc = 0x01003000; /* IO space; PCI device = 6 */
|
||||||
}
|
}
|
||||||
if (!PHANDLE_VALID(isa))
|
if (PHANDLE_VALID(ph)) {
|
||||||
return;
|
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");
|
prop[0] = 0x1;
|
||||||
if (rc != 0 && rc != PROM_ERROR)
|
prop[1] = 0x0;
|
||||||
return;
|
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");
|
name = "/pci@80000000/ide@C,1";
|
||||||
|
ph = call_prom("finddevice", 1, 1, ADDR(name));
|
||||||
isa_ranges[0] = 0x1;
|
if (PHANDLE_VALID(ph)) {
|
||||||
isa_ranges[1] = 0x0;
|
prom_printf("Fixing up IDE interrupt on Pegasos...\n");
|
||||||
isa_ranges[2] = rloc;
|
prop[0] = 14;
|
||||||
isa_ranges[3] = 0x0;
|
prop[1] = 0x0;
|
||||||
isa_ranges[4] = 0x0;
|
prop[2] = 15;
|
||||||
isa_ranges[5] = 0x00010000;
|
prop[3] = 0x0;
|
||||||
prom_setprop(isa, name, "ranges",
|
prom_setprop(ph, name, "interrupts", prop, 4*sizeof(u32));
|
||||||
isa_ranges, sizeof(isa_ranges));
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define fixup_device_tree_chrp()
|
#define fixup_device_tree_chrp()
|
||||||
|
@@ -68,9 +68,9 @@ static void of_bus_default_count_cells(struct device_node *dev,
|
|||||||
int *addrc, int *sizec)
|
int *addrc, int *sizec)
|
||||||
{
|
{
|
||||||
if (addrc)
|
if (addrc)
|
||||||
*addrc = prom_n_addr_cells(dev);
|
*addrc = of_n_addr_cells(dev);
|
||||||
if (sizec)
|
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,
|
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;
|
return NULL;
|
||||||
|
|
||||||
/* Get "reg" or "assigned-addresses" property */
|
/* Get "reg" or "assigned-addresses" property */
|
||||||
prop = get_property(dev, bus->addresses, &psize);
|
prop = of_get_property(dev, bus->addresses, &psize);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
psize /= 4;
|
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
|
* to translate addresses that aren't supposed to be translated in
|
||||||
* the first place. --BenH.
|
* the first place. --BenH.
|
||||||
*/
|
*/
|
||||||
ranges = get_property(parent, "ranges", &rlen);
|
ranges = of_get_property(parent, "ranges", &rlen);
|
||||||
if (ranges == NULL || rlen == 0) {
|
if (ranges == NULL || rlen == 0) {
|
||||||
offset = of_read_number(addr, na);
|
offset = of_read_number(addr, na);
|
||||||
memset(addr, 0, pna * 4);
|
memset(addr, 0, pna * 4);
|
||||||
@@ -578,7 +578,7 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Get "reg" or "assigned-addresses" property */
|
/* Get "reg" or "assigned-addresses" property */
|
||||||
prop = get_property(dev, bus->addresses, &psize);
|
prop = of_get_property(dev, bus->addresses, &psize);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
psize /= 4;
|
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 is always one cell */
|
||||||
*busno = *(dma_window++);
|
*busno = *(dma_window++);
|
||||||
|
|
||||||
prop = get_property(dn, "ibm,#dma-address-cells", NULL);
|
prop = of_get_property(dn, "ibm,#dma-address-cells", NULL);
|
||||||
if (!prop)
|
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);
|
*phys = of_read_number(dma_window, cells);
|
||||||
|
|
||||||
dma_window += cells;
|
dma_window += cells;
|
||||||
|
|
||||||
prop = get_property(dn, "ibm,#dma-size-cells", NULL);
|
prop = of_get_property(dn, "ibm,#dma-size-cells", NULL);
|
||||||
cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
|
cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
|
||||||
*size = of_read_number(dma_window, cells);
|
*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;
|
return NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
parp = get_property(child, "interrupt-parent", NULL);
|
parp = of_get_property(child, "interrupt-parent", NULL);
|
||||||
if (parp == NULL)
|
if (parp == NULL)
|
||||||
p = of_get_parent(child);
|
p = of_get_parent(child);
|
||||||
else {
|
else {
|
||||||
@@ -691,7 +691,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
|
|||||||
}
|
}
|
||||||
of_node_put(child);
|
of_node_put(child);
|
||||||
child = p;
|
child = p;
|
||||||
} while (p && get_property(p, "#interrupt-cells", NULL) == NULL);
|
} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -716,7 +716,7 @@ void of_irq_map_init(unsigned int flags)
|
|||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
|
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)
|
== NULL)
|
||||||
continue;
|
continue;
|
||||||
/* Skip /chosen/interrupt-controller */
|
/* 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
|
* is none, we are nice and just walk up the tree
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
tmp = get_property(ipar, "#interrupt-cells", NULL);
|
tmp = of_get_property(ipar, "#interrupt-cells", NULL);
|
||||||
if (tmp != NULL) {
|
if (tmp != NULL) {
|
||||||
intsize = *tmp;
|
intsize = *tmp;
|
||||||
break;
|
break;
|
||||||
@@ -779,7 +779,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
|
|||||||
*/
|
*/
|
||||||
old = of_node_get(ipar);
|
old = of_node_get(ipar);
|
||||||
do {
|
do {
|
||||||
tmp = get_property(old, "#address-cells", NULL);
|
tmp = of_get_property(old, "#address-cells", NULL);
|
||||||
tnode = of_get_parent(old);
|
tnode = of_get_parent(old);
|
||||||
of_node_put(old);
|
of_node_put(old);
|
||||||
old = tnode;
|
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
|
/* Now check if cursor is an interrupt-controller and if it is
|
||||||
* then we are done
|
* 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");
|
DBG(" -> got it !\n");
|
||||||
memcpy(out_irq->specifier, intspec,
|
memcpy(out_irq->specifier, intspec,
|
||||||
intsize * sizeof(u32));
|
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 */
|
/* 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 */
|
/* No interrupt map, check for an interrupt parent */
|
||||||
if (imap == NULL) {
|
if (imap == NULL) {
|
||||||
DBG(" -> no map, getting parent\n");
|
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);
|
imaplen /= sizeof(u32);
|
||||||
|
|
||||||
/* Look for a mask */
|
/* 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
|
/* If we were passed no "reg" property and we attempt to parse
|
||||||
* an interrupt-map, then #address-cells must be 0.
|
* 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
|
/* Get #interrupt-cells and #address-cells of new
|
||||||
* parent
|
* parent
|
||||||
*/
|
*/
|
||||||
tmp = get_property(newpar, "#interrupt-cells",
|
tmp = of_get_property(newpar, "#interrupt-cells", NULL);
|
||||||
NULL);
|
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
DBG(" -> parent lacks #interrupt-cells !\n");
|
DBG(" -> parent lacks #interrupt-cells !\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
newintsize = *tmp;
|
newintsize = *tmp;
|
||||||
tmp = get_property(newpar, "#address-cells",
|
tmp = of_get_property(newpar, "#address-cells", NULL);
|
||||||
NULL);
|
|
||||||
newaddrsize = (tmp == NULL) ? 0 : *tmp;
|
newaddrsize = (tmp == NULL) ? 0 : *tmp;
|
||||||
|
|
||||||
DBG(" -> newintsize=%d, newaddrsize=%d\n",
|
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)
|
* everything together on these)
|
||||||
*/
|
*/
|
||||||
while (device) {
|
while (device) {
|
||||||
ints = get_property(device, "AAPL,interrupts", &intlen);
|
ints = of_get_property(device, "AAPL,interrupts", &intlen);
|
||||||
if (ints != NULL)
|
if (ints != NULL)
|
||||||
break;
|
break;
|
||||||
device = device->parent;
|
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);
|
return of_irq_map_oldworld(device, index, out_irq);
|
||||||
|
|
||||||
/* Get the interrupts property */
|
/* Get the interrupts property */
|
||||||
intspec = get_property(device, "interrupts", &intlen);
|
intspec = of_get_property(device, "interrupts", &intlen);
|
||||||
if (intspec == NULL)
|
if (intspec == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
intlen /= sizeof(u32);
|
intlen /= sizeof(u32);
|
||||||
|
|
||||||
/* Get the reg property (if any) */
|
/* Get the reg property (if any) */
|
||||||
addr = get_property(device, "reg", NULL);
|
addr = of_get_property(device, "reg", NULL);
|
||||||
|
|
||||||
/* Look for the interrupt parent. */
|
/* Look for the interrupt parent. */
|
||||||
p = of_irq_find_parent(device);
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Get size of interrupt specifier */
|
/* Get size of interrupt specifier */
|
||||||
tmp = get_property(p, "#interrupt-cells", NULL);
|
tmp = of_get_property(p, "#interrupt-cells", NULL);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
of_node_put(p);
|
of_node_put(p);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@@ -450,7 +450,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
|
|||||||
int llen, offs;
|
int llen, offs;
|
||||||
|
|
||||||
sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
|
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 */
|
/* A sensor may have multiple instances */
|
||||||
for (j = 0, offs = 0; j <= p->quant; j++) {
|
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;
|
const unsigned int *utmp;
|
||||||
int len, i;
|
int len, i;
|
||||||
|
|
||||||
utmp = get_property(rtas_node, "rtas-sensors", &len);
|
utmp = of_get_property(rtas_node, "rtas-sensors", &len);
|
||||||
if (utmp == NULL) {
|
if (utmp == NULL) {
|
||||||
printk (KERN_ERR "error: could not get rtas-sensors\n");
|
printk (KERN_ERR "error: could not get rtas-sensors\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -192,18 +192,19 @@ void rtas_progress(char *s, unsigned short hex)
|
|||||||
|
|
||||||
if (display_width == 0) {
|
if (display_width == 0) {
|
||||||
display_width = 0x10;
|
display_width = 0x10;
|
||||||
if ((root = find_path_device("/rtas"))) {
|
if ((root = of_find_node_by_path("/rtas"))) {
|
||||||
if ((p = get_property(root,
|
if ((p = of_get_property(root,
|
||||||
"ibm,display-line-length", NULL)))
|
"ibm,display-line-length", NULL)))
|
||||||
display_width = *p;
|
display_width = *p;
|
||||||
if ((p = get_property(root,
|
if ((p = of_get_property(root,
|
||||||
"ibm,form-feed", NULL)))
|
"ibm,form-feed", NULL)))
|
||||||
form_feed = *p;
|
form_feed = *p;
|
||||||
if ((p = get_property(root,
|
if ((p = of_get_property(root,
|
||||||
"ibm,display-number-of-lines", NULL)))
|
"ibm,display-number-of-lines", NULL)))
|
||||||
display_lines = *p;
|
display_lines = *p;
|
||||||
row_width = get_property(root,
|
row_width = of_get_property(root,
|
||||||
"ibm,display-truncation-length", NULL);
|
"ibm,display-truncation-length", NULL);
|
||||||
|
of_node_put(root);
|
||||||
}
|
}
|
||||||
display_character = rtas_token("display-character");
|
display_character = rtas_token("display-character");
|
||||||
set_indicator = rtas_token("set-indicator");
|
set_indicator = rtas_token("set-indicator");
|
||||||
@@ -298,7 +299,7 @@ int rtas_token(const char *service)
|
|||||||
const int *tokp;
|
const int *tokp;
|
||||||
if (rtas.dev == NULL)
|
if (rtas.dev == NULL)
|
||||||
return RTAS_UNKNOWN_SERVICE;
|
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;
|
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rtas_token);
|
EXPORT_SYMBOL(rtas_token);
|
||||||
@@ -832,12 +833,12 @@ void __init rtas_initialize(void)
|
|||||||
if (rtas.dev) {
|
if (rtas.dev) {
|
||||||
const u32 *basep, *entryp, *sizep;
|
const u32 *basep, *entryp, *sizep;
|
||||||
|
|
||||||
basep = get_property(rtas.dev, "linux,rtas-base", NULL);
|
basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
|
||||||
sizep = get_property(rtas.dev, "rtas-size", NULL);
|
sizep = of_get_property(rtas.dev, "rtas-size", NULL);
|
||||||
if (basep != NULL && sizep != NULL) {
|
if (basep != NULL && sizep != NULL) {
|
||||||
rtas.base = *basep;
|
rtas.base = *basep;
|
||||||
rtas.size = *sizep;
|
rtas.size = *sizep;
|
||||||
entryp = get_property(rtas.dev,
|
entryp = of_get_property(rtas.dev,
|
||||||
"linux,rtas-entry", NULL);
|
"linux,rtas-entry", NULL);
|
||||||
if (entryp == NULL) /* Ugh */
|
if (entryp == NULL) /* Ugh */
|
||||||
rtas.entry = rtas.base;
|
rtas.entry = rtas.base;
|
||||||
|
@@ -60,7 +60,7 @@ static int of_device_available(struct device_node * dn)
|
|||||||
{
|
{
|
||||||
const char *status;
|
const char *status;
|
||||||
|
|
||||||
status = get_property(dn, "status", NULL);
|
status = of_get_property(dn, "status", NULL);
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -177,7 +177,7 @@ struct pci_ops rtas_pci_ops = {
|
|||||||
|
|
||||||
int is_python(struct device_node *dev)
|
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"))
|
if (model && strstr(model, "Python"))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -247,7 +247,7 @@ static int phb_set_bus_ranges(struct device_node *dev,
|
|||||||
const int *bus_range;
|
const int *bus_range;
|
||||||
unsigned int len;
|
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)) {
|
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ int __devinit rtas_setup_phb(struct pci_controller *phb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long __init find_and_init_phbs(void)
|
void __init find_and_init_phbs(void)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
struct pci_controller *phb;
|
struct pci_controller *phb;
|
||||||
@@ -309,18 +309,16 @@ unsigned long __init find_and_init_phbs(void)
|
|||||||
if (of_chosen) {
|
if (of_chosen) {
|
||||||
const int *prop;
|
const int *prop;
|
||||||
|
|
||||||
prop = get_property(of_chosen,
|
prop = of_get_property(of_chosen,
|
||||||
"linux,pci-probe-only", NULL);
|
"linux,pci-probe-only", NULL);
|
||||||
if (prop)
|
if (prop)
|
||||||
pci_probe_only = *prop;
|
pci_probe_only = *prop;
|
||||||
|
|
||||||
prop = get_property(of_chosen,
|
prop = of_get_property(of_chosen,
|
||||||
"linux,pci-assign-all-buses", NULL);
|
"linux,pci-assign-all-buses", NULL);
|
||||||
if (prop)
|
if (prop)
|
||||||
pci_assign_all_buses = *prop;
|
pci_assign_all_buses = *prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RPA-specific bits for removing PHBs */
|
/* RPA-specific bits for removing PHBs */
|
||||||
|
@@ -21,7 +21,6 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/initrd.h>
|
#include <linux/initrd.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/ide.h>
|
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
@@ -304,26 +303,8 @@ struct seq_operations cpuinfo_op = {
|
|||||||
void __init check_for_initrd(void)
|
void __init check_for_initrd(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
const unsigned int *prop;
|
DBG(" -> check_for_initrd() initrd_start=0x%lx initrd_end=0x%lx\n",
|
||||||
int len;
|
initrd_start, initrd_end);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we were passed an initrd, set the ROOT_DEV properly if the values
|
/* If we were passed an initrd, set the ROOT_DEV properly if the values
|
||||||
* look sensible. If not, clear initrd reference.
|
* look sensible. If not, clear initrd reference.
|
||||||
@@ -371,11 +352,12 @@ void __init smp_setup_cpu_maps(void)
|
|||||||
const int *intserv;
|
const int *intserv;
|
||||||
int j, len = sizeof(u32), nthreads = 1;
|
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)
|
if (intserv)
|
||||||
nthreads = len / sizeof(int);
|
nthreads = len / sizeof(int);
|
||||||
else {
|
else {
|
||||||
intserv = get_property(dn, "reg", NULL);
|
intserv = of_get_property(dn, "reg", NULL);
|
||||||
if (!intserv)
|
if (!intserv)
|
||||||
intserv = &cpu; /* assume logical == phys */
|
intserv = &cpu; /* assume logical == phys */
|
||||||
}
|
}
|
||||||
@@ -398,10 +380,10 @@ void __init smp_setup_cpu_maps(void)
|
|||||||
int num_addr_cell, num_size_cell, maxcpus;
|
int num_addr_cell, num_size_cell, maxcpus;
|
||||||
const unsigned int *ireg;
|
const unsigned int *ireg;
|
||||||
|
|
||||||
num_addr_cell = prom_n_addr_cells(dn);
|
num_addr_cell = of_n_addr_cells(dn);
|
||||||
num_size_cell = prom_n_size_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)
|
if (!ireg)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -496,11 +478,39 @@ void probe_machine(void)
|
|||||||
printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
|
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)
|
int check_legacy_ioport(unsigned long base_port)
|
||||||
{
|
{
|
||||||
if (ppc_md.check_legacy_ioport == NULL)
|
struct device_node *parent, *np = NULL;
|
||||||
return 0;
|
int ret = -ENODEV;
|
||||||
return ppc_md.check_legacy_ioport(base_port);
|
|
||||||
|
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);
|
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
|
/* First zero the BSS -- use memset_io, some platforms don't have
|
||||||
* caches on yet */
|
* 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
|
* Identify the CPU type and fix up code sections
|
||||||
@@ -195,18 +196,22 @@ EXPORT_SYMBOL(nvram_sync);
|
|||||||
|
|
||||||
#endif /* CONFIG_NVRAM */
|
#endif /* CONFIG_NVRAM */
|
||||||
|
|
||||||
static struct cpu cpu_devices[NR_CPUS];
|
static DEFINE_PER_CPU(struct cpu, cpu_devices);
|
||||||
|
|
||||||
int __init ppc_init(void)
|
int __init ppc_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int cpu;
|
||||||
|
|
||||||
/* clear the progress line */
|
/* clear the progress line */
|
||||||
if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
|
if (ppc_md.progress)
|
||||||
|
ppc_md.progress(" ", 0xffff);
|
||||||
|
|
||||||
/* register CPU devices */
|
/* register CPU devices */
|
||||||
for_each_possible_cpu(i)
|
for_each_possible_cpu(cpu) {
|
||||||
register_cpu(&cpu_devices[i], i);
|
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
||||||
|
c->hotpluggable = 1;
|
||||||
|
register_cpu(c, cpu);
|
||||||
|
}
|
||||||
|
|
||||||
/* call platform init */
|
/* call platform init */
|
||||||
if (ppc_md.init != NULL) {
|
if (ppc_md.init != NULL) {
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/initrd.h>
|
#include <linux/initrd.h>
|
||||||
#include <linux/ide.h>
|
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
@@ -110,7 +109,7 @@ static void check_smt_enabled(void)
|
|||||||
dn = of_find_node_by_path("/options");
|
dn = of_find_node_by_path("/options");
|
||||||
|
|
||||||
if (dn) {
|
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 (smt_option) {
|
||||||
if (!strcmp(smt_option, "on"))
|
if (!strcmp(smt_option, "on"))
|
||||||
@@ -305,10 +304,10 @@ static void __init initialize_cache_info(void)
|
|||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
lsize = cur_cpu_spec->dcache_bsize;
|
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)
|
if (sizep != NULL)
|
||||||
size = *sizep;
|
size = *sizep;
|
||||||
lsizep = get_property(np, dc, NULL);
|
lsizep = of_get_property(np, dc, NULL);
|
||||||
if (lsizep != NULL)
|
if (lsizep != NULL)
|
||||||
lsize = *lsizep;
|
lsize = *lsizep;
|
||||||
if (sizep == 0 || lsizep == 0)
|
if (sizep == 0 || lsizep == 0)
|
||||||
@@ -322,10 +321,10 @@ static void __init initialize_cache_info(void)
|
|||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
lsize = cur_cpu_spec->icache_bsize;
|
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)
|
if (sizep != NULL)
|
||||||
size = *sizep;
|
size = *sizep;
|
||||||
lsizep = get_property(np, ic, NULL);
|
lsizep = of_get_property(np, ic, NULL);
|
||||||
if (lsizep != NULL)
|
if (lsizep != NULL)
|
||||||
lsize = *lsizep;
|
lsize = *lsizep;
|
||||||
if (sizep == 0 || lsizep == 0)
|
if (sizep == 0 || lsizep == 0)
|
||||||
|
@@ -428,10 +428,6 @@ void generic_mach_cpu_die(void)
|
|||||||
smp_wmb();
|
smp_wmb();
|
||||||
while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
|
while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
flush_tlb_pending();
|
|
||||||
#endif
|
|
||||||
cpu_set(cpu, cpu_online_map);
|
cpu_set(cpu, cpu_online_map);
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
}
|
}
|
||||||
|
@@ -53,10 +53,6 @@
|
|||||||
#include <asm/ppc-pci.h>
|
#include <asm/ppc-pci.h>
|
||||||
#include <asm/syscalls.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 {
|
struct old_linux_dirent32 {
|
||||||
u32 d_ino;
|
u32 d_ino;
|
||||||
u32 d_offset;
|
u32 d_offset;
|
||||||
|
@@ -66,16 +66,17 @@ static int __init smt_setup(void)
|
|||||||
if (!cpu_has_feature(CPU_FTR_SMT))
|
if (!cpu_has_feature(CPU_FTR_SMT))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
options = find_path_device("/options");
|
options = of_find_node_by_path("/options");
|
||||||
if (!options)
|
if (!options)
|
||||||
return -ENODEV;
|
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) {
|
if (!smt_snooze_cmdline && val) {
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
per_cpu(smt_snooze_delay, cpu) = *val;
|
per_cpu(smt_snooze_delay, cpu) = *val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
of_node_put(options);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
__initcall(smt_setup);
|
__initcall(smt_setup);
|
||||||
@@ -189,12 +190,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR);
|
|||||||
SYSFS_PMCSETUP(spurr, SPRN_SPURR);
|
SYSFS_PMCSETUP(spurr, SPRN_SPURR);
|
||||||
SYSFS_PMCSETUP(dscr, SPRN_DSCR);
|
SYSFS_PMCSETUP(dscr, SPRN_DSCR);
|
||||||
|
|
||||||
SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0);
|
SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0);
|
||||||
SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1);
|
SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1);
|
||||||
SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2);
|
SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2);
|
||||||
SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3);
|
SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
|
||||||
SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4);
|
SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
|
||||||
SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5);
|
SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
|
||||||
|
|
||||||
|
|
||||||
static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
|
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");
|
cpu = of_find_node_by_type(NULL, "cpu");
|
||||||
|
|
||||||
if (cpu) {
|
if (cpu) {
|
||||||
fp = get_property(cpu, name, NULL);
|
fp = of_get_property(cpu, name, NULL);
|
||||||
if (fp) {
|
if (fp) {
|
||||||
found = 1;
|
found = 1;
|
||||||
*val = of_read_ulong(fp, cells);
|
*val = of_read_ulong(fp, cells);
|
||||||
|
@@ -90,21 +90,11 @@ EXPORT_SYMBOL(unregister_die_notifier);
|
|||||||
* Trap & Exception support
|
* 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
|
#ifdef CONFIG_PMAC_BACKLIGHT
|
||||||
|
static void pmac_backlight_unblank(void)
|
||||||
|
{
|
||||||
mutex_lock(&pmac_backlight_mutex);
|
mutex_lock(&pmac_backlight_mutex);
|
||||||
if (machine_is(powermac) && pmac_backlight) {
|
if (pmac_backlight) {
|
||||||
struct backlight_properties *props;
|
struct backlight_properties *props;
|
||||||
|
|
||||||
props = &pmac_backlight->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);
|
backlight_update_status(pmac_backlight);
|
||||||
}
|
}
|
||||||
mutex_unlock(&pmac_backlight_mutex);
|
mutex_unlock(&pmac_backlight_mutex);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void pmac_backlight_unblank(void) { }
|
||||||
#endif
|
#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
|
#ifdef CONFIG_PREEMPT
|
||||||
printk("PREEMPT ");
|
printk("PREEMPT ");
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
printk("SMP NR_CPUS=%d ", NR_CPUS);
|
printk("SMP NR_CPUS=%d ", NR_CPUS);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||||
printk("DEBUG_PAGEALLOC ");
|
printk("DEBUG_PAGEALLOC ");
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
printk("NUMA ");
|
printk("NUMA ");
|
||||||
#endif
|
#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);
|
bust_spinlocks(0);
|
||||||
spin_unlock_irq(&die_lock);
|
die.lock_owner = -1;
|
||||||
|
spin_unlock_irqrestore(&die.lock, flags);
|
||||||
|
|
||||||
if (kexec_should_crash(current) ||
|
if (kexec_should_crash(current) ||
|
||||||
kexec_sr_activated(smp_processor_id()))
|
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)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
|
oops_exit();
|
||||||
do_exit(err);
|
do_exit(err);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -81,7 +81,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
|
|||||||
struct iommu_table *tbl;
|
struct iommu_table *tbl;
|
||||||
unsigned long offset, size;
|
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);
|
"ibm,my-dma-window", NULL);
|
||||||
if (!dma_window)
|
if (!dma_window)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -226,7 +226,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unit_address = get_property(of_node, "reg", NULL);
|
unit_address = of_get_property(of_node, "reg", NULL);
|
||||||
if (unit_address == NULL) {
|
if (unit_address == NULL) {
|
||||||
printk(KERN_WARNING "%s: node %s missing 'reg'\n",
|
printk(KERN_WARNING "%s: node %s missing 'reg'\n",
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
@@ -246,7 +246,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
|
|||||||
viodev->type = of_node->type;
|
viodev->type = of_node->type;
|
||||||
viodev->unit_address = *unit_address;
|
viodev->unit_address = *unit_address;
|
||||||
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
|
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
|
||||||
unit_address = get_property(of_node,
|
unit_address = of_get_property(of_node,
|
||||||
"linux,unit_address", NULL);
|
"linux,unit_address", NULL);
|
||||||
if (unit_address != NULL)
|
if (unit_address != NULL)
|
||||||
viodev->unit_address = *unit_address;
|
viodev->unit_address = *unit_address;
|
||||||
@@ -308,7 +308,7 @@ static int __init vio_bus_init(void)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_vroot = find_devices("vdevice");
|
node_vroot = of_find_node_by_name(NULL, "vdevice");
|
||||||
if (node_vroot) {
|
if (node_vroot) {
|
||||||
struct device_node *of_node;
|
struct device_node *of_node;
|
||||||
|
|
||||||
@@ -322,6 +322,7 @@ static int __init vio_bus_init(void)
|
|||||||
__FUNCTION__, of_node);
|
__FUNCTION__, of_node);
|
||||||
vio_register_device_node(of_node);
|
vio_register_device_node(of_node);
|
||||||
}
|
}
|
||||||
|
of_node_put(node_vroot);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -377,7 +378,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
|||||||
dn = dev->archdata.of_node;
|
dn = dev->archdata.of_node;
|
||||||
if (!dn)
|
if (!dn)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
cp = get_property(dn, "compatible", &length);
|
cp = of_get_property(dn, "compatible", &length);
|
||||||
if (!cp)
|
if (!cp)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@@ -406,12 +407,12 @@ struct bus_type vio_bus_type = {
|
|||||||
* @which: The property/attribute to be extracted.
|
* @which: The property/attribute to be extracted.
|
||||||
* @length: Pointer to length of returned data size (unused if NULL).
|
* @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
|
* attribute specified by @which
|
||||||
*/
|
*/
|
||||||
const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
|
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);
|
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];
|
char kobj_name[BUS_ID_SIZE];
|
||||||
|
|
||||||
/* construct the kobject name from the device node */
|
/* 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)
|
if (!unit_address)
|
||||||
return NULL;
|
return NULL;
|
||||||
snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
|
snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
|
||||||
|
@@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user)
|
|||||||
dcbt 0,r4
|
dcbt 0,r4
|
||||||
beq .Lcopy_page_4K
|
beq .Lcopy_page_4K
|
||||||
andi. r6,r6,7
|
andi. r6,r6,7
|
||||||
mtcrf 0x01,r5
|
PPC_MTOCRF 0x01,r5
|
||||||
blt cr1,.Lshort_copy
|
blt cr1,.Lshort_copy
|
||||||
bne .Ldst_unaligned
|
bne .Ldst_unaligned
|
||||||
.Ldst_aligned:
|
.Ldst_aligned:
|
||||||
@@ -135,7 +135,7 @@ _GLOBAL(__copy_tofrom_user)
|
|||||||
b .Ldo_tail
|
b .Ldo_tail
|
||||||
|
|
||||||
.Ldst_unaligned:
|
.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
|
subf r5,r6,r5
|
||||||
li r7,0
|
li r7,0
|
||||||
cmpldi r1,r5,16
|
cmpldi r1,r5,16
|
||||||
@@ -150,7 +150,7 @@ _GLOBAL(__copy_tofrom_user)
|
|||||||
2: bf cr7*4+1,3f
|
2: bf cr7*4+1,3f
|
||||||
37: lwzx r0,r7,r4
|
37: lwzx r0,r7,r4
|
||||||
83: stwx r0,r7,r3
|
83: stwx r0,r7,r3
|
||||||
3: mtcrf 0x01,r5
|
3: PPC_MTOCRF 0x01,r5
|
||||||
add r4,r6,r4
|
add r4,r6,r4
|
||||||
add r3,r6,r3
|
add r3,r6,r3
|
||||||
b .Ldst_aligned
|
b .Ldst_aligned
|
||||||
|
@@ -43,9 +43,11 @@ void __spin_yield(raw_spinlock_t *lock)
|
|||||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||||
((u64)holder_cpu << 32) | yield_count);
|
((u64)holder_cpu << 32) | yield_count);
|
||||||
|
#ifdef CONFIG_PPC_SPLPAR
|
||||||
else
|
else
|
||||||
plpar_hcall_norets(H_CONFER,
|
plpar_hcall_norets(H_CONFER,
|
||||||
get_hard_smp_processor_id(holder_cpu), yield_count);
|
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))
|
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||||
((u64)holder_cpu << 32) | yield_count);
|
((u64)holder_cpu << 32) | yield_count);
|
||||||
|
#ifdef CONFIG_PPC_SPLPAR
|
||||||
else
|
else
|
||||||
plpar_hcall_norets(H_CONFER,
|
plpar_hcall_norets(H_CONFER,
|
||||||
get_hard_smp_processor_id(holder_cpu), yield_count);
|
get_hard_smp_processor_id(holder_cpu), yield_count);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ _GLOBAL(memset)
|
|||||||
rlwimi r4,r4,16,0,15
|
rlwimi r4,r4,16,0,15
|
||||||
cmplw cr1,r5,r0 /* do we get that far? */
|
cmplw cr1,r5,r0 /* do we get that far? */
|
||||||
rldimi r4,r4,32,0
|
rldimi r4,r4,32,0
|
||||||
mtcrf 1,r0
|
PPC_MTOCRF 1,r0
|
||||||
mr r6,r3
|
mr r6,r3
|
||||||
blt cr1,8f
|
blt cr1,8f
|
||||||
beq+ 3f /* if already 8-byte aligned */
|
beq+ 3f /* if already 8-byte aligned */
|
||||||
@@ -49,7 +49,7 @@ _GLOBAL(memset)
|
|||||||
bdnz 4b
|
bdnz 4b
|
||||||
5: srwi. r0,r5,3
|
5: srwi. r0,r5,3
|
||||||
clrlwi r5,r5,29
|
clrlwi r5,r5,29
|
||||||
mtcrf 1,r0
|
PPC_MTOCRF 1,r0
|
||||||
beq 8f
|
beq 8f
|
||||||
bf 29,6f
|
bf 29,6f
|
||||||
std r4,0(r6)
|
std r4,0(r6)
|
||||||
@@ -65,7 +65,7 @@ _GLOBAL(memset)
|
|||||||
std r4,0(r6)
|
std r4,0(r6)
|
||||||
addi r6,r6,8
|
addi r6,r6,8
|
||||||
8: cmpwi r5,0
|
8: cmpwi r5,0
|
||||||
mtcrf 1,r5
|
PPC_MTOCRF 1,r5
|
||||||
beqlr+
|
beqlr+
|
||||||
bf 29,9f
|
bf 29,9f
|
||||||
stw r4,0(r6)
|
stw r4,0(r6)
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
.align 7
|
.align 7
|
||||||
_GLOBAL(memcpy)
|
_GLOBAL(memcpy)
|
||||||
std r3,48(r1) /* save destination pointer for return value */
|
std r3,48(r1) /* save destination pointer for return value */
|
||||||
mtcrf 0x01,r5
|
PPC_MTOCRF 0x01,r5
|
||||||
cmpldi cr1,r5,16
|
cmpldi cr1,r5,16
|
||||||
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
|
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
|
||||||
andi. r6,r6,7
|
andi. r6,r6,7
|
||||||
@@ -128,7 +128,7 @@ _GLOBAL(memcpy)
|
|||||||
b .Ldo_tail
|
b .Ldo_tail
|
||||||
|
|
||||||
.Ldst_unaligned:
|
.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
|
subf r5,r6,r5
|
||||||
li r7,0
|
li r7,0
|
||||||
cmpldi r1,r5,16
|
cmpldi r1,r5,16
|
||||||
@@ -143,7 +143,7 @@ _GLOBAL(memcpy)
|
|||||||
2: bf cr7*4+1,3f
|
2: bf cr7*4+1,3f
|
||||||
lwzx r0,r7,r4
|
lwzx r0,r7,r4
|
||||||
stwx r0,r7,r3
|
stwx r0,r7,r3
|
||||||
3: mtcrf 0x01,r5
|
3: PPC_MTOCRF 0x01,r5
|
||||||
add r4,r6,r4
|
add r4,r6,r4
|
||||||
add r3,r6,r3
|
add r3,r6,r3
|
||||||
b .Ldst_aligned
|
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)
|
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;
|
unsigned long int imm;
|
||||||
|
|
||||||
opcode = instr >> 26;
|
opcode = instr >> 26;
|
||||||
@@ -152,6 +152,49 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
|
|||||||
regs->nip &= 0xffffffffUL;
|
regs->nip &= 0xffffffffUL;
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#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;
|
return 0;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user